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