Home | History | Annotate | Download | only in ag
      1 /******************************************************************************
      2  *
      3  *  Copyright 2004-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  This file contains the audio gateway functions controlling the RFCOMM
     22  *  connections.
     23  *
     24  ******************************************************************************/
     25 
     26 #include <cstring>
     27 
     28 #include <base/bind.h>
     29 
     30 #include "bt_common.h"
     31 #include "bta_ag_api.h"
     32 #include "bta_ag_int.h"
     33 #include "btm_api.h"
     34 #include "osi/include/osi.h"
     35 #include "port_api.h"
     36 #include "rfcdefs.h"
     37 #include "utl.h"
     38 
     39 /* Event mask for RfCOMM port callback */
     40 #define BTA_AG_PORT_EV_MASK PORT_EV_RXCHAR
     41 
     42 /* each scb has its own rfcomm callbacks */
     43 void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle);
     44 void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle);
     45 void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle);
     46 void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle);
     47 void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle);
     48 void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle);
     49 void bta_ag_mgmt_cback_1(uint32_t code, uint16_t port_handle);
     50 void bta_ag_mgmt_cback_2(uint32_t code, uint16_t port_handle);
     51 void bta_ag_mgmt_cback_3(uint32_t code, uint16_t port_handle);
     52 void bta_ag_mgmt_cback_4(uint32_t code, uint16_t port_handle);
     53 void bta_ag_mgmt_cback_5(uint32_t code, uint16_t port_handle);
     54 void bta_ag_mgmt_cback_6(uint32_t code, uint16_t port_handle);
     55 
     56 /* rfcomm callback function tables */
     57 typedef tPORT_CALLBACK* tBTA_AG_PORT_CBACK;
     58 const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] = {
     59     bta_ag_port_cback_1, bta_ag_port_cback_2, bta_ag_port_cback_3,
     60     bta_ag_port_cback_4, bta_ag_port_cback_5, bta_ag_port_cback_6};
     61 
     62 const tBTA_AG_PORT_CBACK bta_ag_mgmt_cback_tbl[] = {
     63     bta_ag_mgmt_cback_1, bta_ag_mgmt_cback_2, bta_ag_mgmt_cback_3,
     64     bta_ag_mgmt_cback_4, bta_ag_mgmt_cback_5, bta_ag_mgmt_cback_6};
     65 
     66 /*******************************************************************************
     67  *
     68  * Function         bta_ag_port_cback
     69  *
     70  * Description      RFCOMM Port callback
     71  *
     72  *
     73  * Returns          void
     74  *
     75  ******************************************************************************/
     76 static void bta_ag_port_cback(UNUSED_ATTR uint32_t code, uint16_t port_handle,
     77                               uint16_t handle) {
     78   tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(handle);
     79   if (p_scb != nullptr) {
     80     /* ignore port events for port handles other than connected handle */
     81     if (port_handle != p_scb->conn_handle) {
     82       APPL_TRACE_ERROR(
     83           "ag_port_cback ignoring handle:%d conn_handle = %d other handle = %d",
     84           port_handle, p_scb->conn_handle, handle);
     85       return;
     86     }
     87     if (!bta_ag_scb_open(p_scb)) {
     88       LOG(ERROR) << __func__ << ": rfcomm data on an unopened control block "
     89                  << handle << " peer_addr " << p_scb->peer_addr << " state "
     90                  << std::to_string(p_scb->state);
     91     }
     92     do_in_bta_thread(FROM_HERE,
     93                      base::Bind(&bta_ag_sm_execute_by_handle, handle,
     94                                 BTA_AG_RFC_DATA_EVT, tBTA_AG_DATA::kEmpty));
     95   }
     96 }
     97 
     98 /*******************************************************************************
     99  *
    100  * Function         bta_ag_mgmt_cback
    101  *
    102  * Description      RFCOMM management callback
    103  *
    104  *
    105  * Returns          void
    106  *
    107  ******************************************************************************/
    108 static void bta_ag_mgmt_cback(uint32_t code, uint16_t port_handle,
    109                               uint16_t handle) {
    110   tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(handle);
    111   APPL_TRACE_DEBUG("%s: code=%d, port_handle=%d, scb_handle=%d, p_scb=0x%08x",
    112                    __func__, code, port_handle, handle, p_scb);
    113   if (p_scb == nullptr) {
    114     LOG(WARNING) << __func__ << ": cannot find scb, code=" << code
    115                  << ", port_handle=" << port_handle << ", handle=" << handle;
    116     return;
    117   }
    118   /* ignore close event for port handles other than connected handle */
    119   if ((code != PORT_SUCCESS) && (port_handle != p_scb->conn_handle)) {
    120     LOG(WARNING) << __func__ << ": ignore open failure for unmatched "
    121                  << "port_handle " << port_handle << ", scb_handle=" << handle;
    122     return;
    123   }
    124   uint16_t event;
    125   if (code == PORT_SUCCESS) {
    126     bool found_handle = false;
    127     if (p_scb->conn_handle) {
    128       /* Outgoing connection */
    129       if (port_handle == p_scb->conn_handle) {
    130         found_handle = true;
    131       }
    132     } else {
    133       /* Incoming connection */
    134       for (uint16_t service_port_handle : p_scb->serv_handle) {
    135         if (port_handle == service_port_handle) {
    136           found_handle = true;
    137           break;
    138         }
    139       }
    140     }
    141     if (!found_handle) {
    142       LOG(ERROR) << __func__ << ": port opened successfully, but port_handle "
    143                  << port_handle << " is unknown"
    144                  << ", scb_handle=" << handle;
    145       return;
    146     }
    147     event = BTA_AG_RFC_OPEN_EVT;
    148   } else if (port_handle == p_scb->conn_handle) {
    149     /* distinguish server close events */
    150     event = BTA_AG_RFC_CLOSE_EVT;
    151   } else {
    152     event = BTA_AG_RFC_SRV_CLOSE_EVT;
    153   }
    154 
    155   tBTA_AG_DATA data = {};
    156   data.rfc.port_handle = port_handle;
    157   do_in_bta_thread(
    158       FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle, event, data));
    159 }
    160 
    161 /*******************************************************************************
    162  *
    163  * Function         bta_ag_port_cback_1 to 6
    164  *                  bta_ag_mgmt_cback_1 to 6
    165  *
    166  * Description      RFCOMM callback functions.  This is an easy way to
    167  *                  distinguish scb from the callback.
    168  *
    169  *
    170  * Returns          void
    171  *
    172  ******************************************************************************/
    173 void bta_ag_mgmt_cback_1(uint32_t code, uint16_t port_handle) {
    174   bta_ag_mgmt_cback(code, port_handle, 1);
    175 }
    176 void bta_ag_mgmt_cback_2(uint32_t code, uint16_t port_handle) {
    177   bta_ag_mgmt_cback(code, port_handle, 2);
    178 }
    179 void bta_ag_mgmt_cback_3(uint32_t code, uint16_t port_handle) {
    180   bta_ag_mgmt_cback(code, port_handle, 3);
    181 }
    182 void bta_ag_mgmt_cback_4(uint32_t code, uint16_t port_handle) {
    183   bta_ag_mgmt_cback(code, port_handle, 4);
    184 }
    185 void bta_ag_mgmt_cback_5(uint32_t code, uint16_t port_handle) {
    186   bta_ag_mgmt_cback(code, port_handle, 5);
    187 }
    188 void bta_ag_mgmt_cback_6(uint32_t code, uint16_t port_handle) {
    189   bta_ag_mgmt_cback(code, port_handle, 6);
    190 }
    191 void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle) {
    192   bta_ag_port_cback(code, port_handle, 1);
    193 }
    194 void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle) {
    195   bta_ag_port_cback(code, port_handle, 2);
    196 }
    197 void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle) {
    198   bta_ag_port_cback(code, port_handle, 3);
    199 }
    200 void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle) {
    201   bta_ag_port_cback(code, port_handle, 4);
    202 }
    203 void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle) {
    204   bta_ag_port_cback(code, port_handle, 5);
    205 }
    206 void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle) {
    207   bta_ag_port_cback(code, port_handle, 6);
    208 }
    209 
    210 /*******************************************************************************
    211  *
    212  * Function         bta_ag_setup_port
    213  *
    214  * Description      Setup RFCOMM port for use by AG.
    215  *
    216  *
    217  * Returns          void
    218  *
    219  ******************************************************************************/
    220 void bta_ag_setup_port(tBTA_AG_SCB* p_scb, uint16_t handle) {
    221   int port_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
    222   CHECK_GE(port_callback_index, 0)
    223       << "invalid callback index, handle=" << handle << ", bd_addr"
    224       << p_scb->peer_addr;
    225   CHECK_LT(port_callback_index,
    226            static_cast<int>(sizeof(bta_ag_port_cback_tbl) /
    227                             sizeof(bta_ag_port_cback_tbl[0])))
    228       << "callback index out of bound, handle=" << handle << ", bd_addr"
    229       << p_scb->peer_addr;
    230   PORT_SetEventMask(handle, BTA_AG_PORT_EV_MASK);
    231   PORT_SetEventCallback(handle, bta_ag_port_cback_tbl[port_callback_index]);
    232 }
    233 
    234 /*******************************************************************************
    235  *
    236  * Function         bta_ag_start_servers
    237  *
    238  * Description      Setup RFCOMM servers for use by AG.
    239  *
    240  *
    241  * Returns          void
    242  *
    243  ******************************************************************************/
    244 void bta_ag_start_servers(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK services) {
    245   services >>= BTA_HSP_SERVICE_ID;
    246   for (int i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
    247     /* if service is set in mask */
    248     if (services & 1) {
    249       BTM_SetSecurityLevel(false, "", bta_ag_sec_id[i], p_scb->serv_sec_mask,
    250                            BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM,
    251                            bta_ag_cb.profile[i].scn);
    252       int management_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
    253       CHECK_GE(management_callback_index, 0)
    254           << "invalid callback index, services=" << loghex(services)
    255           << ", bd_addr=" << p_scb->peer_addr;
    256       CHECK_LT(management_callback_index,
    257                static_cast<int>(sizeof(bta_ag_mgmt_cback_tbl) /
    258                                 sizeof(bta_ag_mgmt_cback_tbl[0])))
    259           << "callback index out of bound, services=" << loghex(services)
    260           << ", bd_addr" << p_scb->peer_addr;
    261       int status = RFCOMM_CreateConnection(
    262           bta_ag_uuid[i], bta_ag_cb.profile[i].scn, true, BTA_AG_MTU,
    263           RawAddress::kAny, &(p_scb->serv_handle[i]),
    264           bta_ag_mgmt_cback_tbl[management_callback_index]);
    265       if (status == PORT_SUCCESS) {
    266         bta_ag_setup_port(p_scb, p_scb->serv_handle[i]);
    267       } else {
    268         /* TODO: CR#137125 to handle to error properly */
    269         LOG(ERROR) << __func__ << ": RFCOMM_CreateConnection ERROR " << status
    270                    << ", p_scb=" << p_scb << ", services=" << loghex(services)
    271                    << ", mgmt_cback_index=" << management_callback_index;
    272       }
    273       APPL_TRACE_DEBUG("%s: p_scb=0x%08x, services=0x%04x, mgmt_cback_index=%d",
    274                        __func__, p_scb, services, management_callback_index);
    275     }
    276   }
    277 }
    278 
    279 /*******************************************************************************
    280  *
    281  * Function         bta_ag_close_servers
    282  *
    283  * Description      Close RFCOMM servers port for use by AG.
    284  *
    285  *
    286  * Returns          void
    287  *
    288  ******************************************************************************/
    289 void bta_ag_close_servers(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK services) {
    290   services >>= BTA_HSP_SERVICE_ID;
    291   for (int i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
    292     /* if service is set in mask */
    293     if (services & 1) {
    294       RFCOMM_RemoveServer(p_scb->serv_handle[i]);
    295       p_scb->serv_handle[i] = 0;
    296     }
    297   }
    298 }
    299 
    300 /*******************************************************************************
    301  *
    302  * Function         bta_ag_is_server_closed
    303  *
    304  * Description      Returns true if all servers are closed.
    305  *
    306  *
    307  * Returns          true if all servers are closed, false otherwise
    308  *
    309  ******************************************************************************/
    310 bool bta_ag_is_server_closed(tBTA_AG_SCB* p_scb) {
    311   uint8_t xx;
    312   bool is_closed = true;
    313 
    314   for (xx = 0; xx < BTA_AG_NUM_IDX; xx++) {
    315     if (p_scb->serv_handle[xx] != 0) is_closed = false;
    316   }
    317 
    318   return is_closed;
    319 }
    320 
    321 /*******************************************************************************
    322  *
    323  * Function         bta_ag_rfc_do_open
    324  *
    325  * Description      Open an RFCOMM connection to the peer device.
    326  *
    327  *
    328  * Returns          void
    329  *
    330  ******************************************************************************/
    331 void bta_ag_rfc_do_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
    332   BTM_SetSecurityLevel(true, "", bta_ag_sec_id[p_scb->conn_service],
    333                        p_scb->cli_sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM,
    334                        p_scb->peer_scn);
    335 
    336   int management_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
    337   int status = RFCOMM_CreateConnection(
    338       bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn, false, BTA_AG_MTU,
    339       p_scb->peer_addr, &(p_scb->conn_handle),
    340       bta_ag_mgmt_cback_tbl[management_callback_index]);
    341   APPL_TRACE_DEBUG(
    342       "%s: p_scb=0x%08x, conn_handle=%d, mgmt_cback_index=%d,"
    343       " status=%d",
    344       __func__, p_scb, p_scb->conn_handle, management_callback_index, status);
    345   if (status == PORT_SUCCESS) {
    346     bta_ag_setup_port(p_scb, p_scb->conn_handle);
    347   } else {
    348     /* RFCOMM create connection failed; send ourselves RFCOMM close event */
    349     LOG(ERROR) << __func__ << ": RFCOMM_CreateConnection ERROR " << status
    350                << " for " << p_scb->peer_addr;
    351     bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, data);
    352   }
    353 }
    354 
    355 /*******************************************************************************
    356  *
    357  * Function         bta_ag_rfc_do_close
    358  *
    359  * Description      Close RFCOMM connection.
    360  *
    361  *
    362  * Returns          void
    363  *
    364  ******************************************************************************/
    365 void bta_ag_rfc_do_close(tBTA_AG_SCB* p_scb,
    366                          UNUSED_ATTR const tBTA_AG_DATA& data) {
    367   if (p_scb->conn_handle) {
    368     RFCOMM_RemoveConnection(p_scb->conn_handle);
    369   } else {
    370     /* Close API was called while AG is in Opening state.               */
    371     /* Need to trigger the state machine to send callback to the app    */
    372     /* and move back to INIT state.                                     */
    373     do_in_bta_thread(
    374         FROM_HERE,
    375         base::Bind(&bta_ag_sm_execute_by_handle, bta_ag_scb_to_idx(p_scb),
    376                    BTA_AG_RFC_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
    377 
    378     /* Cancel SDP if it had been started. */
    379     /*
    380     if(p_scb->p_disc_db)
    381     {
    382         (void)SDP_CancelServiceSearch (p_scb->p_disc_db);
    383     }
    384     */
    385   }
    386 }
    387