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