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