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