Home | History | Annotate | Download | only in hf_client
      1 /******************************************************************************
      2  *
      3  *  Copyright (c) 2014 The Android Open Source Project
      4  *  Copyright 2004-2012 Broadcom Corporation
      5  *
      6  *  Licensed under the Apache License, Version 2.0 (the "License");
      7  *  you may not use this file except in compliance with the License.
      8  *  You may obtain a copy of the License at:
      9  *
     10  *  http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  *  Unless required by applicable law or agreed to in writing, software
     13  *  distributed under the License is distributed on an "AS IS" BASIS,
     14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  *  See the License for the specific language governing permissions and
     16  *  limitations under the License.
     17  *
     18  ******************************************************************************/
     19 
     20 /******************************************************************************
     21  *
     22  *  This file contains the audio gateway functions controlling the RFCOMM
     23  *  connections.
     24  *
     25  ******************************************************************************/
     26 
     27 #include <base/logging.h>
     28 #include <string.h>
     29 
     30 #include "bt_utils.h"
     31 #include "bta_api.h"
     32 #include "bta_hf_client_int.h"
     33 #include "osi/include/osi.h"
     34 #include "port_api.h"
     35 
     36 /*******************************************************************************
     37  *
     38  * Function         bta_hf_client_port_cback
     39  *
     40  * Description      RFCOMM Port callback. The handle in this function is
     41  *                  specified by BTA layer via the PORT_SetEventCallback
     42  *                  method
     43  *
     44  * Returns          void
     45  *
     46  ******************************************************************************/
     47 static void bta_hf_client_port_cback(UNUSED_ATTR uint32_t code,
     48                                      uint16_t port_handle) {
     49   /* ignore port events for port handles other than connected handle */
     50   tBTA_HF_CLIENT_CB* client_cb =
     51       bta_hf_client_find_cb_by_rfc_handle(port_handle);
     52   if (client_cb == NULL) {
     53     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__, port_handle);
     54     return;
     55   }
     56 
     57   tBTA_HF_CLIENT_RFC* p_buf =
     58       (tBTA_HF_CLIENT_RFC*)osi_malloc(sizeof(tBTA_HF_CLIENT_RFC));
     59   p_buf->hdr.event = BTA_HF_CLIENT_RFC_DATA_EVT;
     60   p_buf->hdr.layer_specific = client_cb->handle;
     61   bta_sys_sendmsg(p_buf);
     62 }
     63 
     64 /*******************************************************************************
     65  *
     66  * Function         bta_hf_client_mgmt_cback
     67  *
     68  * Description      RFCOMM management callback
     69  *
     70  *
     71  * Returns          void
     72  *
     73  ******************************************************************************/
     74 static void bta_hf_client_mgmt_cback(uint32_t code, uint16_t port_handle) {
     75   tBTA_HF_CLIENT_CB* client_cb =
     76       bta_hf_client_find_cb_by_rfc_handle(port_handle);
     77 
     78   APPL_TRACE_DEBUG("%s: code = %d, port_handle = %d serv = %d", __func__, code,
     79                    port_handle, bta_hf_client_cb_arr.serv_handle);
     80 
     81   /* ignore close event for port handles other than connected handle */
     82   if (code != PORT_SUCCESS && client_cb != NULL &&
     83       port_handle != client_cb->conn_handle) {
     84     APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback ignoring handle:%d",
     85                      port_handle);
     86     return;
     87   }
     88 
     89   tBTA_HF_CLIENT_RFC* p_buf =
     90       (tBTA_HF_CLIENT_RFC*)osi_malloc(sizeof(tBTA_HF_CLIENT_RFC));
     91 
     92   if (code == PORT_SUCCESS) {
     93     if (client_cb && port_handle == client_cb->conn_handle) { /* out conn */
     94       p_buf->hdr.event = BTA_HF_CLIENT_RFC_OPEN_EVT;
     95     } else if (port_handle == bta_hf_client_cb_arr.serv_handle) {
     96       p_buf->hdr.event = BTA_HF_CLIENT_RFC_OPEN_EVT;
     97 
     98       APPL_TRACE_DEBUG("%s: allocating a new CB for incoming connection",
     99                        __func__);
    100       // Find the BDADDR of the peer device
    101       RawAddress peer_addr;
    102       uint16_t lcid;
    103       PORT_CheckConnection(port_handle, peer_addr, &lcid);
    104 
    105       // Since we accepted a remote request we should allocate a handle first.
    106       uint16_t tmp_handle = -1;
    107       bta_hf_client_allocate_handle(peer_addr, &tmp_handle);
    108       client_cb = bta_hf_client_find_cb_by_handle(tmp_handle);
    109 
    110       // If allocation fails then we abort.
    111       if (client_cb == NULL) {
    112         APPL_TRACE_ERROR("%s: error allocating a new handle", __func__);
    113         p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
    114       } else {
    115         // Set the connection fields for this new CB
    116         client_cb->conn_handle = port_handle;
    117 
    118         // Since we have accepted an incoming RFCOMM connection:
    119         // a) Release the current server from it duties
    120         // b) Start a new server for more new incoming connection
    121         bta_hf_client_cb_arr.serv_handle = 0;
    122         bta_hf_client_start_server();
    123       }
    124     } else {
    125       APPL_TRACE_ERROR("%s: PORT_SUCCESS, ignoring handle = %d", __func__,
    126                        port_handle);
    127       return;
    128     }
    129   } else if (client_cb != NULL &&
    130              port_handle == client_cb->conn_handle) { /* code != PORT_SUC */
    131     LOG(ERROR) << __func__ << ": closing port handle " << port_handle << "dev "
    132                << client_cb->peer_addr;
    133 
    134     RFCOMM_RemoveServer(port_handle);
    135     p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
    136   }
    137 
    138   p_buf->hdr.layer_specific = client_cb != NULL ? client_cb->handle : 0;
    139   bta_sys_sendmsg(p_buf);
    140 }
    141 
    142 /*******************************************************************************
    143  *
    144  * Function         bta_hf_client_setup_port
    145  *
    146  * Description      Setup RFCOMM port for use by HF Client.
    147  *
    148  *
    149  * Returns          void
    150  *
    151  ******************************************************************************/
    152 void bta_hf_client_setup_port(uint16_t handle) {
    153   PORT_SetEventMask(handle, PORT_EV_RXCHAR);
    154   PORT_SetEventCallback(handle, bta_hf_client_port_cback);
    155 }
    156 
    157 /*******************************************************************************
    158  *
    159  * Function         bta_hf_client_start_server
    160  *
    161  * Description      Setup RFCOMM server for use by HF Client.
    162  *
    163  *
    164  * Returns          void
    165  *
    166  ******************************************************************************/
    167 void bta_hf_client_start_server() {
    168   int port_status;
    169 
    170   if (bta_hf_client_cb_arr.serv_handle > 0) {
    171     APPL_TRACE_DEBUG("%s: already started, handle: %d", __func__,
    172                      bta_hf_client_cb_arr.serv_handle);
    173     return;
    174   }
    175 
    176   BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_HF_HANDSFREE,
    177                        bta_hf_client_cb_arr.serv_sec_mask, BT_PSM_RFCOMM,
    178                        BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb_arr.scn);
    179 
    180   port_status = RFCOMM_CreateConnection(
    181       UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb_arr.scn, true,
    182       BTA_HF_CLIENT_MTU, RawAddress::kAny, &(bta_hf_client_cb_arr.serv_handle),
    183       bta_hf_client_mgmt_cback);
    184 
    185   APPL_TRACE_DEBUG("%s: started rfcomm server with handle %d", __func__,
    186                    bta_hf_client_cb_arr.serv_handle);
    187 
    188   if (port_status == PORT_SUCCESS) {
    189     bta_hf_client_setup_port(bta_hf_client_cb_arr.serv_handle);
    190   } else {
    191     APPL_TRACE_DEBUG("%s: RFCOMM_CreateConnection returned error:%d", __func__,
    192                      port_status);
    193   }
    194 }
    195 
    196 /*******************************************************************************
    197  *
    198  * Function         bta_hf_client_close_server
    199  *
    200  * Description      Close RFCOMM server port for use by HF Client.
    201  *
    202  *
    203  * Returns          void
    204  *
    205  ******************************************************************************/
    206 void bta_hf_client_close_server() {
    207   APPL_TRACE_DEBUG("%s: %d", __func__, bta_hf_client_cb_arr.serv_handle);
    208 
    209   if (bta_hf_client_cb_arr.serv_handle == 0) {
    210     APPL_TRACE_DEBUG("%s: already stopped", __func__);
    211     return;
    212   }
    213 
    214   RFCOMM_RemoveServer(bta_hf_client_cb_arr.serv_handle);
    215   bta_hf_client_cb_arr.serv_handle = 0;
    216 }
    217 
    218 /*******************************************************************************
    219  *
    220  * Function         bta_hf_client_rfc_do_open
    221  *
    222  * Description      Open an RFCOMM connection to the peer device.
    223  *
    224  *
    225  * Returns          void
    226  *
    227  ******************************************************************************/
    228 void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA* p_data) {
    229   tBTA_HF_CLIENT_CB* client_cb =
    230       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
    231   if (client_cb == NULL) {
    232     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
    233                      p_data->hdr.layer_specific);
    234     return;
    235   }
    236 
    237   BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_HF_HANDSFREE,
    238                        client_cb->cli_sec_mask, BT_PSM_RFCOMM,
    239                        BTM_SEC_PROTO_RFCOMM, client_cb->peer_scn);
    240   if (RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, client_cb->peer_scn,
    241                               false, BTA_HF_CLIENT_MTU, client_cb->peer_addr,
    242                               &(client_cb->conn_handle),
    243                               bta_hf_client_mgmt_cback) == PORT_SUCCESS) {
    244     bta_hf_client_setup_port(client_cb->conn_handle);
    245     APPL_TRACE_DEBUG("bta_hf_client_rfc_do_open : conn_handle = %d",
    246                      client_cb->conn_handle);
    247   }
    248   /* RFCOMM create connection failed; send ourselves RFCOMM close event */
    249   else {
    250     bta_hf_client_sm_execute(BTA_HF_CLIENT_RFC_CLOSE_EVT, p_data);
    251   }
    252 }
    253 
    254 /*******************************************************************************
    255  *
    256  * Function         bta_hf_client_rfc_do_close
    257  *
    258  * Description      Close RFCOMM connection.
    259  *
    260  *
    261  * Returns          void
    262  *
    263  ******************************************************************************/
    264 void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA* p_data) {
    265   tBTA_HF_CLIENT_CB* client_cb =
    266       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
    267   if (client_cb == NULL) {
    268     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
    269                      p_data->hdr.layer_specific);
    270     return;
    271   }
    272 
    273   if (client_cb->conn_handle) {
    274     RFCOMM_RemoveConnection(client_cb->conn_handle);
    275   } else {
    276     /* Close API was called while HF Client is in Opening state.        */
    277     /* Need to trigger the state machine to send callback to the app    */
    278     /* and move back to INIT state.                                     */
    279     tBTA_HF_CLIENT_RFC* p_buf =
    280         (tBTA_HF_CLIENT_RFC*)osi_malloc(sizeof(tBTA_HF_CLIENT_RFC));
    281     p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
    282     bta_sys_sendmsg(p_buf);
    283 
    284     /* Cancel SDP if it had been started. */
    285     if (client_cb->p_disc_db) {
    286       (void)SDP_CancelServiceSearch(client_cb->p_disc_db);
    287       osi_free_and_reset((void**)&client_cb->p_disc_db);
    288     }
    289   }
    290 }
    291