Home | History | Annotate | Download | only in ag
      1 /******************************************************************************
      2  *
      3  *  Copyright 2003-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 performing SDP
     22  *  operations.
     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 "bta_api.h"
     34 #include "bta_sys.h"
     35 #include "btif_config.h"
     36 #include "btm_api.h"
     37 #include "osi/include/osi.h"
     38 #include "sdp_api.h"
     39 #include "utl.h"
     40 
     41 using bluetooth::Uuid;
     42 
     43 /* Number of protocol elements in protocol element list. */
     44 #define BTA_AG_NUM_PROTO_ELEMS 2
     45 
     46 /* Number of elements in service class id list. */
     47 #define BTA_AG_NUM_SVC_ELEMS 2
     48 
     49 /* size of database for service discovery */
     50 #ifndef BTA_AG_DISC_BUF_SIZE
     51 #define BTA_AG_DISC_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
     52 #endif
     53 
     54 /* declare sdp callback functions */
     55 void bta_ag_sdp_cback_1(uint16_t status);
     56 void bta_ag_sdp_cback_2(uint16_t status);
     57 void bta_ag_sdp_cback_3(uint16_t status);
     58 void bta_ag_sdp_cback_4(uint16_t status);
     59 void bta_ag_sdp_cback_5(uint16_t status);
     60 void bta_ag_sdp_cback_6(uint16_t status);
     61 
     62 /* SDP callback function table */
     63 typedef tSDP_DISC_CMPL_CB* tBTA_AG_SDP_CBACK;
     64 const tBTA_AG_SDP_CBACK bta_ag_sdp_cback_tbl[] = {
     65     bta_ag_sdp_cback_1, bta_ag_sdp_cback_2, bta_ag_sdp_cback_3,
     66     bta_ag_sdp_cback_4, bta_ag_sdp_cback_5, bta_ag_sdp_cback_6};
     67 
     68 /*******************************************************************************
     69  *
     70  * Function         bta_ag_sdp_cback
     71  *
     72  * Description      SDP callback function.
     73  *
     74  *
     75  * Returns          void
     76  *
     77  ******************************************************************************/
     78 static void bta_ag_sdp_cback(uint16_t status, uint8_t idx) {
     79   APPL_TRACE_DEBUG("%s status:0x%x", __func__, status);
     80   tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(idx);
     81   if (p_scb) {
     82     uint16_t event;
     83     /* set event according to int/acp */
     84     if (p_scb->role == BTA_AG_ACP) {
     85       event = BTA_AG_DISC_ACP_RES_EVT;
     86     } else {
     87       event = BTA_AG_DISC_INT_RES_EVT;
     88     }
     89     tBTA_AG_DATA disc_result = {.disc_result.status = status};
     90     do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, idx,
     91                                            event, disc_result));
     92   }
     93 }
     94 
     95 /*******************************************************************************
     96  *
     97  * Function         bta_ag_sdp_cback_1 to 6
     98  *
     99  * Description      SDP callback functions.  Since there is no way to
    100  *                  distinguish scb from the callback we need separate
    101  *                  callbacks for each scb.
    102  *
    103  *
    104  * Returns          void
    105  *
    106  ******************************************************************************/
    107 void bta_ag_sdp_cback_1(uint16_t status) { bta_ag_sdp_cback(status, 1); }
    108 void bta_ag_sdp_cback_2(uint16_t status) { bta_ag_sdp_cback(status, 2); }
    109 void bta_ag_sdp_cback_3(uint16_t status) { bta_ag_sdp_cback(status, 3); }
    110 void bta_ag_sdp_cback_4(uint16_t status) { bta_ag_sdp_cback(status, 4); }
    111 void bta_ag_sdp_cback_5(uint16_t status) { bta_ag_sdp_cback(status, 5); }
    112 void bta_ag_sdp_cback_6(uint16_t status) { bta_ag_sdp_cback(status, 6); }
    113 
    114 /******************************************************************************
    115  *
    116  * Function         bta_ag_add_record
    117  *
    118  * Description      This function is called by a server application to add
    119  *                  HSP or HFP information to an SDP record.  Prior to
    120  *                  calling this function the application must call
    121  *                  SDP_CreateRecord() to create an SDP record.
    122  *
    123  * Returns          true if function execution succeeded,
    124  *                  false if function execution failed.
    125  *
    126  *****************************************************************************/
    127 bool bta_ag_add_record(uint16_t service_uuid, const char* p_service_name,
    128                        uint8_t scn, tBTA_AG_FEAT features,
    129                        uint32_t sdp_handle) {
    130   tSDP_PROTOCOL_ELEM proto_elem_list[BTA_AG_NUM_PROTO_ELEMS];
    131   uint16_t svc_class_id_list[BTA_AG_NUM_SVC_ELEMS];
    132   uint16_t browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
    133   uint16_t version;
    134   uint16_t profile_uuid;
    135   uint8_t network;
    136   bool result = true;
    137   bool codec_supported = false;
    138   uint8_t buf[2];
    139 
    140   APPL_TRACE_DEBUG("%s uuid: %x", __func__, service_uuid);
    141 
    142   for (auto& proto_element : proto_elem_list) {
    143     proto_element = {};
    144   }
    145 
    146   /* add the protocol element sequence */
    147   proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
    148   proto_elem_list[0].num_params = 0;
    149   proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
    150   proto_elem_list[1].num_params = 1;
    151   proto_elem_list[1].params[0] = scn;
    152   result &=
    153       SDP_AddProtocolList(sdp_handle, BTA_AG_NUM_PROTO_ELEMS, proto_elem_list);
    154 
    155   /* add service class id list */
    156   svc_class_id_list[0] = service_uuid;
    157   svc_class_id_list[1] = UUID_SERVCLASS_GENERIC_AUDIO;
    158   result &= SDP_AddServiceClassIdList(sdp_handle, BTA_AG_NUM_SVC_ELEMS,
    159                                       svc_class_id_list);
    160 
    161   /* add profile descriptor list */
    162   if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE) {
    163     profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
    164     version = BTA_HFP_VERSION;
    165   } else {
    166     profile_uuid = UUID_SERVCLASS_HEADSET;
    167     version = HSP_VERSION_1_2;
    168   }
    169   result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version);
    170 
    171   /* add service name */
    172   if (p_service_name != nullptr && p_service_name[0] != 0) {
    173     result &= SDP_AddAttribute(
    174         sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
    175         (uint32_t)(strlen(p_service_name) + 1), (uint8_t*)p_service_name);
    176   }
    177 
    178   /* add features and network */
    179   if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE) {
    180     network = (features & BTA_AG_FEAT_REJECT) ? 1 : 0;
    181     result &= SDP_AddAttribute(sdp_handle, ATTR_ID_DATA_STORES_OR_NETWORK,
    182                                UINT_DESC_TYPE, 1, &network);
    183 
    184     if (features & BTA_AG_FEAT_CODEC) codec_supported = true;
    185 
    186     features &= BTA_AG_SDP_FEAT_SPEC;
    187 
    188     /* Codec bit position is different in SDP and in BRSF */
    189     if (codec_supported) features |= 0x0020;
    190 
    191     UINT16_TO_BE_FIELD(buf, features);
    192     result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES,
    193                                UINT_DESC_TYPE, 2, buf);
    194   }
    195 
    196   /* add browse group list */
    197   result &= SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1,
    198                                 browse_list);
    199 
    200   return result;
    201 }
    202 
    203 /*******************************************************************************
    204  *
    205  * Function         bta_ag_create_records
    206  *
    207  * Description      Create SDP records for registered services.
    208  *
    209  *
    210  * Returns          void
    211  *
    212  ******************************************************************************/
    213 void bta_ag_create_records(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
    214   int i;
    215   tBTA_SERVICE_MASK services;
    216 
    217   services = p_scb->reg_services >> BTA_HSP_SERVICE_ID;
    218   for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
    219     /* if service is set in mask */
    220     if (services & 1) {
    221       /* add sdp record if not already registered */
    222       if (bta_ag_cb.profile[i].sdp_handle == 0) {
    223         bta_ag_cb.profile[i].sdp_handle = SDP_CreateRecord();
    224         bta_ag_cb.profile[i].scn = BTM_AllocateSCN();
    225         bta_ag_add_record(bta_ag_uuid[i], data.api_register.p_name[i],
    226                           bta_ag_cb.profile[i].scn, data.api_register.features,
    227                           bta_ag_cb.profile[i].sdp_handle);
    228         bta_sys_add_uuid(bta_ag_uuid[i]);
    229       }
    230     }
    231   }
    232 }
    233 
    234 /*******************************************************************************
    235  *
    236  * Function         bta_ag_del_records
    237  *
    238  * Description      Delete SDP records for any registered services.
    239  *
    240  *
    241  * Returns          void
    242  *
    243  ******************************************************************************/
    244 void bta_ag_del_records(tBTA_AG_SCB* p_scb) {
    245   tBTA_AG_SCB* p = &bta_ag_cb.scb[0];
    246   tBTA_SERVICE_MASK services;
    247   tBTA_SERVICE_MASK others = 0;
    248   int i;
    249 
    250   /* get services of all other registered servers */
    251   for (i = 0; i < BTA_AG_NUM_IDX; i++, p++) {
    252     if (p_scb == p) {
    253       continue;
    254     }
    255 
    256     if (p->in_use && !p->dealloc) {
    257       others |= p->reg_services;
    258     }
    259   }
    260 
    261   others >>= BTA_HSP_SERVICE_ID;
    262   services = p_scb->reg_services >> BTA_HSP_SERVICE_ID;
    263   for (i = 0; i < BTA_AG_NUM_IDX && services != 0;
    264        i++, services >>= 1, others >>= 1) {
    265     /* if service registered for this scb and not registered for any other scb
    266      */
    267     if (((services & 1) == 1) && ((others & 1) == 0)) {
    268       APPL_TRACE_DEBUG("bta_ag_del_records %d", i);
    269       if (bta_ag_cb.profile[i].sdp_handle != 0) {
    270         SDP_DeleteRecord(bta_ag_cb.profile[i].sdp_handle);
    271         bta_ag_cb.profile[i].sdp_handle = 0;
    272       }
    273       BTM_FreeSCN(bta_ag_cb.profile[i].scn);
    274       BTM_SecClrService(bta_ag_sec_id[i]);
    275       bta_sys_remove_uuid(bta_ag_uuid[i]);
    276     }
    277   }
    278 }
    279 
    280 /*******************************************************************************
    281  *
    282  * Function         bta_ag_sdp_find_attr
    283  *
    284  * Description      Process SDP discovery results to find requested attributes
    285  *                  for requested service.
    286  *
    287  *
    288  * Returns          true if results found, false otherwise.
    289  *
    290  ******************************************************************************/
    291 bool bta_ag_sdp_find_attr(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service) {
    292   tSDP_DISC_REC* p_rec = nullptr;
    293   tSDP_DISC_ATTR* p_attr;
    294   tSDP_PROTOCOL_ELEM pe;
    295   uint16_t uuid;
    296   bool result = false;
    297 
    298   if (service & BTA_HFP_SERVICE_MASK) {
    299     uuid = UUID_SERVCLASS_HF_HANDSFREE;
    300     /* If there is no cached peer version, use default one */
    301     if (p_scb->peer_version == HFP_HSP_VERSION_UNKNOWN) {
    302       p_scb->peer_version = HFP_VERSION_1_1; /* Default version */
    303     }
    304   } else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
    305     uuid = UUID_SERVCLASS_HEADSET_HS;
    306     p_scb->peer_version = HSP_VERSION_1_2; /* Default version */
    307   } else {
    308     uuid = UUID_SERVCLASS_HEADSET_HS;
    309     p_scb->peer_version = HSP_VERSION_1_0;
    310   }
    311 
    312   /* loop through all records we found */
    313   while (true) {
    314     /* get next record; if none found, we're done */
    315     p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec);
    316     if (p_rec == nullptr) {
    317       if (uuid == UUID_SERVCLASS_HEADSET_HS) {
    318         /* Search again in case the peer device uses the old HSP UUID */
    319         uuid = UUID_SERVCLASS_HEADSET;
    320         p_scb->peer_version = HSP_VERSION_1_0;
    321         p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec);
    322         if (p_rec == nullptr) {
    323           break;
    324         }
    325       } else
    326         break;
    327     }
    328 
    329     /* get scn from proto desc list if initiator */
    330     if (p_scb->role == BTA_AG_INT) {
    331       if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
    332         p_scb->peer_scn = (uint8_t)pe.params[0];
    333       } else {
    334         continue;
    335       }
    336     }
    337 
    338     /* get profile version (if failure, version parameter is not updated) */
    339     uint16_t peer_version = HFP_HSP_VERSION_UNKNOWN;
    340     if (!SDP_FindProfileVersionInRec(p_rec, uuid, &peer_version)) {
    341       APPL_TRACE_WARNING("%s: Get peer_version failed, using default 0x%04x",
    342                          __func__, p_scb->peer_version);
    343       peer_version = p_scb->peer_version;
    344     }
    345 
    346     if (service & BTA_HFP_SERVICE_MASK) {
    347       /* Update cached peer version if the new one is different */
    348       if (peer_version != p_scb->peer_version) {
    349         p_scb->peer_version = peer_version;
    350         if (btif_config_set_bin(
    351                 p_scb->peer_addr.ToString(), HFP_VERSION_CONFIG_KEY,
    352                 (const uint8_t*)&peer_version, sizeof(peer_version))) {
    353           btif_config_save();
    354         } else {
    355           APPL_TRACE_WARNING("%s: Failed to store peer HFP version for %s",
    356                              __func__, p_scb->peer_addr.ToString().c_str());
    357         }
    358       }
    359       /* get features if HFP */
    360       p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES);
    361       if (p_attr != nullptr) {
    362         /* Found attribute. Get value. */
    363         /* There might be race condition between SDP and BRSF.  */
    364         /* Do not update if we already received BRSF.           */
    365         uint16_t sdp_features = p_attr->attr_value.v.u16;
    366         bool sdp_wbs_support = sdp_features & BTA_AG_FEAT_WBS_SUPPORT;
    367         if (!p_scb->received_at_bac && sdp_wbs_support) {
    368           // Workaround for misbehaving HFs (e.g. some Hyundai car kit) that:
    369           // 1. Indicate WBS support in SDP and codec negotiation in BRSF
    370           // 2. But do not send required AT+BAC command
    371           // Will assume mSBC is enabled and try codec negotiation by default
    372           p_scb->codec_updated = true;
    373           p_scb->peer_codecs = BTA_AG_CODEC_CVSD & BTA_AG_CODEC_MSBC;
    374           p_scb->sco_codec = UUID_CODEC_MSBC;
    375         }
    376         if (sdp_features != p_scb->peer_sdp_features) {
    377           p_scb->peer_sdp_features = sdp_features;
    378           if (btif_config_set_bin(
    379                   p_scb->peer_addr.ToString(), HFP_SDP_FEATURES_CONFIG_KEY,
    380                   (const uint8_t*)&sdp_features, sizeof(sdp_features))) {
    381             btif_config_save();
    382           } else {
    383             APPL_TRACE_WARNING(
    384                 "%s: Failed to store peer HFP SDP Features for %s", __func__,
    385                 p_scb->peer_addr.ToString().c_str());
    386           }
    387         }
    388         if (p_scb->peer_features == 0) {
    389           p_scb->peer_features = sdp_features & HFP_SDP_BRSF_FEATURES_MASK;
    390         }
    391       }
    392     } else {
    393       /* No peer version caching for HSP, use discovered one directly */
    394       p_scb->peer_version = peer_version;
    395       /* get features if HSP */
    396       p_attr =
    397           SDP_FindAttributeInRec(p_rec, ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL);
    398       if (p_attr != nullptr) {
    399         /* Remote volume control of HSP */
    400         if (p_attr->attr_value.v.u8)
    401           p_scb->peer_features |= BTA_AG_PEER_FEAT_VOL;
    402         else
    403           p_scb->peer_features &= ~BTA_AG_PEER_FEAT_VOL;
    404       }
    405     }
    406 
    407     /* found what we needed */
    408     result = true;
    409     break;
    410   }
    411   return result;
    412 }
    413 
    414 /*******************************************************************************
    415  *
    416  * Function         bta_ag_do_disc
    417  *
    418  * Description      Do service discovery.
    419  *
    420  *
    421  * Returns          void
    422  *
    423  ******************************************************************************/
    424 void bta_ag_do_disc(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service) {
    425   Uuid uuid_list[1];
    426   uint16_t num_uuid = 1;
    427   uint16_t attr_list[4];
    428   uint8_t num_attr;
    429 
    430   /* HFP initiator; get proto list and features */
    431   if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
    432     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
    433     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
    434     attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
    435     attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
    436     num_attr = 4;
    437     uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HF_HANDSFREE);
    438   }
    439   /* HFP acceptor; get features */
    440   else if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_ACP) {
    441     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
    442     attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
    443     attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
    444     num_attr = 3;
    445     uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HF_HANDSFREE);
    446   }
    447   /* HSP initiator; get proto list */
    448   else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
    449     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
    450     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
    451     attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
    452     attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL;
    453     num_attr = 4;
    454     // Although UUID_SERVCLASS_HEADSET_HS (0x1131) is to be used in HSP 1.2,
    455     // some HSP 1.2 implementations, such as PTS, still use
    456     // UUID_SERVCLASS_HEADSET (0x1108) to store its service record. However,
    457     // most of such devices are HSP 1.0 devices.
    458     if (p_scb->hsp_version >= HSP_VERSION_1_2) {
    459       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET_HS);
    460     } else {
    461       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET);
    462     }
    463   } else {
    464     /* HSP acceptor; get features */
    465     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
    466     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
    467     attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
    468     attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL;
    469     num_attr = 4;
    470 
    471     if (p_scb->hsp_version >= HSP_VERSION_1_2) {
    472       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET_HS);
    473       num_uuid = 2;
    474     } else {
    475       /* Legacy from HSP v1.0 */
    476       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET);
    477     }
    478   }
    479 
    480   /* allocate buffer for sdp database */
    481   p_scb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_AG_DISC_BUF_SIZE);
    482   /* set up service discovery database; attr happens to be attr_list len */
    483   if (SDP_InitDiscoveryDb(p_scb->p_disc_db, BTA_AG_DISC_BUF_SIZE, num_uuid,
    484                           uuid_list, num_attr, attr_list)) {
    485     if (SDP_ServiceSearchAttributeRequest(
    486             p_scb->peer_addr, p_scb->p_disc_db,
    487             bta_ag_sdp_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1])) {
    488       return;
    489     } else {
    490       LOG(ERROR) << __func__ << ": failed to start SDP discovery for "
    491                  << p_scb->peer_addr;
    492     }
    493   } else {
    494     LOG(ERROR) << __func__ << ": failed to init SDP discovery database for "
    495                << p_scb->peer_addr;
    496   }
    497   // Failure actions
    498   bta_ag_free_db(p_scb, tBTA_AG_DATA::kEmpty);
    499   bta_ag_sm_execute(p_scb, BTA_AG_DISC_FAIL_EVT, tBTA_AG_DATA::kEmpty);
    500 }
    501 
    502 /*******************************************************************************
    503  *
    504  * Function         bta_ag_free_db
    505  *
    506  * Description      Free discovery database.
    507  *
    508  *
    509  * Returns          void
    510  *
    511  ******************************************************************************/
    512 void bta_ag_free_db(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
    513   osi_free_and_reset((void**)&p_scb->p_disc_db);
    514 }
    515