Home | History | Annotate | Download | only in hf_client
      1 /******************************************************************************
      2  *
      3  *  Copyright (c) 2014 The Android Open Source Project
      4  *  Copyright (C) 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 <string.h>
     28 #include "bta_api.h"
     29 #include "bta_hf_client_int.h"
     30 #include "port_api.h"
     31 #include "bt_utils.h"
     32 
     33 /*******************************************************************************
     34 **
     35 ** Function         bta_hf_client_port_cback
     36 **
     37 ** Description      RFCOMM Port callback
     38 **
     39 **
     40 ** Returns          void
     41 **
     42 *******************************************************************************/
     43 static void bta_hf_client_port_cback(UINT32 code, UINT16 port_handle)
     44 {
     45     BT_HDR      *p_buf;
     46     UNUSED(code);
     47 
     48     /* ignore port events for port handles other than connected handle */
     49     if (port_handle != bta_hf_client_cb.scb.conn_handle)
     50     {
     51         APPL_TRACE_DEBUG("bta_hf_client_port_cback ignoring handle:%d conn_handle = %d",
     52                           port_handle, bta_hf_client_cb.scb.conn_handle);
     53         return;
     54     }
     55 
     56     if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
     57     {
     58         p_buf->event = BTA_HF_CLIENT_RFC_DATA_EVT;
     59         bta_sys_sendmsg(p_buf);
     60     }
     61 }
     62 
     63 /*******************************************************************************
     64 **
     65 ** Function         bta_hf_client_mgmt_cback
     66 **
     67 ** Description      RFCOMM management callback
     68 **
     69 **
     70 ** Returns          void
     71 **
     72 *******************************************************************************/
     73 static void bta_hf_client_mgmt_cback(UINT32 code, UINT16 port_handle)
     74 {
     75     tBTA_HF_CLIENT_RFC     *p_buf;
     76     UINT16                  event;
     77 
     78     APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback : code = %d, port_handle = %d, conn_handle = %d, serv_handle = %d",
     79                         code, port_handle, bta_hf_client_cb.scb.conn_handle, bta_hf_client_cb.scb.serv_handle);
     80 
     81     /* ignore close event for port handles other than connected handle */
     82     if ((code != PORT_SUCCESS) && (port_handle != bta_hf_client_cb.scb.conn_handle))
     83     {
     84         APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback ignoring handle:%d", port_handle);
     85         return;
     86     }
     87 
     88     if (code == PORT_SUCCESS)
     89     {
     90         if ((bta_hf_client_cb.scb.conn_handle && (port_handle == bta_hf_client_cb.scb.conn_handle)) || /* outgoing connection */
     91                 (port_handle == bta_hf_client_cb.scb.serv_handle))                       /* incoming connection */
     92         {
     93             event = BTA_HF_CLIENT_RFC_OPEN_EVT;
     94         }
     95         else
     96         {
     97             APPL_TRACE_ERROR ("bta_hf_client_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle);
     98             return;
     99         }
    100     }
    101     /* distinguish server close events */
    102     else if (port_handle == bta_hf_client_cb.scb.conn_handle)
    103     {
    104         event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
    105     }
    106     else
    107     {
    108         event = BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT;
    109     }
    110 
    111     if ((p_buf = (tBTA_HF_CLIENT_RFC *) GKI_getbuf(sizeof(tBTA_HF_CLIENT_RFC))) != NULL)
    112     {
    113         p_buf->hdr.event = event;
    114         p_buf->port_handle = port_handle;
    115         bta_sys_sendmsg(p_buf);
    116     }
    117 }
    118 
    119 /*******************************************************************************
    120 **
    121 ** Function         bta_hf_client_setup_port
    122 **
    123 ** Description      Setup RFCOMM port for use by HF Client.
    124 **
    125 **
    126 ** Returns          void
    127 **
    128 *******************************************************************************/
    129 void bta_hf_client_setup_port(UINT16 handle)
    130 {
    131     PORT_SetEventMask(handle, PORT_EV_RXCHAR);
    132     PORT_SetEventCallback(handle, bta_hf_client_port_cback);
    133 }
    134 
    135 /*******************************************************************************
    136 **
    137 ** Function         bta_hf_client_start_server
    138 **
    139 ** Description      Setup RFCOMM server for use by HF Client.
    140 **
    141 **
    142 ** Returns          void
    143 **
    144 *******************************************************************************/
    145 void bta_hf_client_start_server(void)
    146 {
    147     int port_status;
    148 
    149     if (bta_hf_client_cb.scb.serv_handle > 0)
    150     {
    151         APPL_TRACE_DEBUG("%s already started, handle: %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle);
    152         return;
    153     }
    154 
    155     BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HF_HANDSFREE, bta_hf_client_cb.scb.serv_sec_mask,
    156         BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scn);
    157 
    158     port_status =  RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scn,
    159         TRUE, BTA_HF_CLIENT_MTU, (UINT8 *) bd_addr_any, &(bta_hf_client_cb.scb.serv_handle),
    160         bta_hf_client_mgmt_cback);
    161 
    162     if (port_status  == PORT_SUCCESS)
    163     {
    164         bta_hf_client_setup_port(bta_hf_client_cb.scb.serv_handle);
    165     }
    166     else
    167     {
    168         /* TODO: can we handle this better? */
    169         APPL_TRACE_DEBUG("bta_hf_client_start_server: RFCOMM_CreateConnection returned error:%d", port_status);
    170     }
    171 
    172     APPL_TRACE_DEBUG("bta_hf_client_start_server handle: %d", bta_hf_client_cb.scb.serv_handle);
    173 }
    174 
    175 /*******************************************************************************
    176 **
    177 ** Function         bta_hf_client_close_server
    178 **
    179 ** Description      Close RFCOMM server port for use by HF Client.
    180 **
    181 **
    182 ** Returns          void
    183 **
    184 *******************************************************************************/
    185 void bta_hf_client_close_server(void)
    186 {
    187     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle);
    188 
    189     if (bta_hf_client_cb.scb.serv_handle == 0)
    190     {
    191         APPL_TRACE_DEBUG("%s already stopped", __FUNCTION__);
    192         return;
    193     }
    194 
    195     RFCOMM_RemoveServer(bta_hf_client_cb.scb.serv_handle);
    196     bta_hf_client_cb.scb.serv_handle = 0;
    197 }
    198 
    199 /*******************************************************************************
    200 **
    201 ** Function         bta_hf_client_rfc_do_open
    202 **
    203 ** Description      Open an RFCOMM connection to the peer device.
    204 **
    205 **
    206 ** Returns          void
    207 **
    208 *******************************************************************************/
    209 void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA *p_data)
    210 {
    211     BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HF_HANDSFREE,
    212                             bta_hf_client_cb.scb.cli_sec_mask, BT_PSM_RFCOMM,
    213                             BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scb.peer_scn);
    214 
    215     if (RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scb.peer_scn,
    216             FALSE, BTA_HF_CLIENT_MTU, bta_hf_client_cb.scb.peer_addr, &(bta_hf_client_cb.scb.conn_handle),
    217             bta_hf_client_mgmt_cback) == PORT_SUCCESS)
    218     {
    219         bta_hf_client_setup_port(bta_hf_client_cb.scb.conn_handle);
    220         APPL_TRACE_DEBUG("bta_hf_client_rfc_do_open : conn_handle = %d", bta_hf_client_cb.scb.conn_handle);
    221     }
    222     /* RFCOMM create connection failed; send ourselves RFCOMM close event */
    223     else
    224     {
    225         bta_hf_client_sm_execute(BTA_HF_CLIENT_RFC_CLOSE_EVT, p_data);
    226     }
    227 }
    228 
    229 /*******************************************************************************
    230 **
    231 ** Function         bta_hf_client_rfc_do_close
    232 **
    233 ** Description      Close RFCOMM connection.
    234 **
    235 **
    236 ** Returns          void
    237 **
    238 *******************************************************************************/
    239 void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA *p_data)
    240 {
    241     tBTA_HF_CLIENT_RFC     *p_buf;
    242     UNUSED(p_data);
    243 
    244     if (bta_hf_client_cb.scb.conn_handle)
    245     {
    246         RFCOMM_RemoveConnection(bta_hf_client_cb.scb.conn_handle);
    247     }
    248     else
    249     {
    250         /* Close API was called while HF Client is in Opening state.        */
    251         /* Need to trigger the state machine to send callback to the app    */
    252         /* and move back to INIT state.                                     */
    253         if ((p_buf = (tBTA_HF_CLIENT_RFC *) GKI_getbuf(sizeof(tBTA_HF_CLIENT_RFC))) != NULL)
    254         {
    255             p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
    256             bta_sys_sendmsg(p_buf);
    257         }
    258 
    259         /* Cancel SDP if it had been started. */
    260         if(bta_hf_client_cb.scb.p_disc_db)
    261         {
    262             (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db);
    263             bta_hf_client_free_db(NULL);
    264         }
    265     }
    266 }
    267