• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 1998-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 #include <string.h>
20 
21 #include "bt_target.h"
22 #if (HL_INCLUDED == TRUE)
23 
24 #include "bta_hl_int.h"
25 #include "osi/include/osi.h"
26 #include "sdp_api.h"
27 #include "utl.h"
28 
29 /*******************************************************************************
30  *
31  * Function         bta_hl_fill_sup_feature_list
32  *
33  * Description      Fill the supported features from teh SDP record
34  *
35  * Returns          true if found, false if not
36  *                  If found, the passed protocol list element is filled in.
37  *
38  ******************************************************************************/
bta_hl_fill_sup_feature_list(const tSDP_DISC_ATTR * p_attr,tBTA_HL_SUP_FEATURE_LIST_ELEM * p_list)39 bool bta_hl_fill_sup_feature_list(const tSDP_DISC_ATTR* p_attr,
40                                   tBTA_HL_SUP_FEATURE_LIST_ELEM* p_list) {
41   tSDP_DISC_ATTR* p_sattr;
42   uint8_t item_cnt;
43   uint8_t list_cnt = 0;
44   bool status = true;
45 
46   for (p_attr = p_attr->attr_value.v.p_sub_attr; p_attr;
47        p_attr = p_attr->p_next_attr) {
48     /* mdep sequence */
49     if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE) {
50       return (false);
51     }
52 
53     item_cnt = 0;
54 
55     for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr && (item_cnt < 4);
56          p_sattr = p_sattr->p_next_attr) {
57       /* for each mdep list */
58 
59       p_list->list_elem[list_cnt].p_mdep_desp = NULL;
60       switch (item_cnt) {
61         case 0:
62           p_list->list_elem[list_cnt].mdep_id = p_sattr->attr_value.v.u8;
63           break;
64         case 1:
65           p_list->list_elem[list_cnt].data_type = p_sattr->attr_value.v.u16;
66           break;
67         case 2:
68           p_list->list_elem[list_cnt].mdep_role =
69               (tBTA_HL_MDEP_ROLE)p_sattr->attr_value.v.u8;
70           break;
71         case 3:
72           p_list->list_elem[list_cnt].p_mdep_desp =
73               (char*)p_sattr->attr_value.v.array;
74           break;
75       }
76 
77       item_cnt++;
78     }
79     list_cnt++;
80   }
81   p_list->num_elems = list_cnt;
82   return (status);
83 }
84 
85 /*******************************************************************************
86  *
87  * Function         bta_hl_compose_supported_feature_list
88  *
89  * Description      This function is called to compose a data sequence from
90  *                  the supported  feature element list struct pointer
91  *
92  * Returns          the length of the data sequence
93  *
94  ******************************************************************************/
bta_hl_compose_supported_feature_list(uint8_t * p,uint16_t num_elem,const tBTA_HL_SUP_FEATURE_ELEM * p_elem_list)95 int bta_hl_compose_supported_feature_list(
96     uint8_t* p, uint16_t num_elem,
97     const tBTA_HL_SUP_FEATURE_ELEM* p_elem_list) {
98   uint16_t xx, str_len, seq_len;
99   uint8_t* p_head = p;
100 
101   for (xx = 0; xx < num_elem; xx++, p_elem_list++) {
102     UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
103     seq_len = 7;
104     str_len = 0;
105     if (p_elem_list->p_mdep_desp) {
106       str_len = strlen(p_elem_list->p_mdep_desp) + 1;
107       seq_len += str_len + 2; /* todo add a # symbol for 2 */
108     }
109 
110     *p++ = (uint8_t)seq_len;
111 
112     UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
113     UINT8_TO_BE_STREAM(p, p_elem_list->mdep_id);
114     UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
115     UINT16_TO_BE_STREAM(p, p_elem_list->data_type);
116     UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
117     UINT8_TO_BE_STREAM(p, p_elem_list->mdep_role);
118 
119     if (str_len) {
120       UINT8_TO_BE_STREAM(p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
121       UINT8_TO_BE_STREAM(p, str_len);
122       ARRAY_TO_BE_STREAM(p, p_elem_list->p_mdep_desp, str_len);
123     }
124   }
125 
126   return (p - p_head);
127 }
128 
129 /*******************************************************************************
130  *
131  * Function         bta_hl_add_sup_feature_list
132  *
133  * Description      This function is called to add a protocol descriptor list to
134  *                  a record. This would be through the SDP database maintenance
135  *                  API. If the protocol list already exists in the record, it
136  *                  is replaced with the new list.
137  *
138  * Returns          true if added OK, else false
139  *
140  ******************************************************************************/
bta_hl_add_sup_feature_list(uint32_t handle,uint16_t num_elem,const tBTA_HL_SUP_FEATURE_ELEM * p_elem_list)141 bool bta_hl_add_sup_feature_list(uint32_t handle, uint16_t num_elem,
142                                  const tBTA_HL_SUP_FEATURE_ELEM* p_elem_list) {
143   int offset;
144   bool result;
145   uint8_t* p_buf = (uint8_t*)osi_malloc(BTA_HL_SUP_FEATURE_SDP_BUF_SIZE);
146 
147   offset = bta_hl_compose_supported_feature_list(p_buf, num_elem, p_elem_list);
148   result = SDP_AddAttribute(handle, ATTR_ID_HDP_SUP_FEAT_LIST,
149                             DATA_ELE_SEQ_DESC_TYPE, (uint32_t)offset, p_buf);
150   osi_free(p_buf);
151 
152   return result;
153 }
154 
155 /*****************************************************************************
156  *
157  *  Function:    bta_hl_sdp_update
158  *
159  *  Purpose:     Register an HDP application with SDP
160  *
161  *  Parameters:
162  *
163  *  Returns:     void
164  *
165  ****************************************************************************/
bta_hl_sdp_update(UNUSED_ATTR uint8_t app_id)166 tBTA_HL_STATUS bta_hl_sdp_update(UNUSED_ATTR uint8_t app_id) {
167   uint16_t svc_class_id_list[BTA_HL_NUM_SVC_ELEMS];
168   tSDP_PROTOCOL_ELEM proto_elem_list[BTA_HL_NUM_PROTO_ELEMS];
169   tSDP_PROTO_LIST_ELEM add_proto_list;
170   tBTA_HL_SUP_FEATURE_LIST_ELEM sup_feature_list;
171   uint16_t browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
172   uint8_t i, j, cnt, mdep_id, mdep_role;
173   uint8_t data_exchange_spec = BTA_HL_SDP_IEEE_11073_20601;
174   uint8_t mcap_sup_proc = BTA_HL_MCAP_SUP_PROC_MASK;
175   uint16_t profile_uuid = UUID_SERVCLASS_HDP_PROFILE;
176   uint16_t version = BTA_HL_VERSION;
177   uint8_t num_services = 1;
178   tBTA_HL_APP_CB* p_cb = BTA_HL_GET_APP_CB_PTR(0);
179   bool result = true;
180   tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
181 
182   if ((p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE) &&
183       (!p_cb->sup_feature.advertize_source_sdp)) {
184     return BTA_HL_STATUS_OK;
185   }
186 
187   num_services = 1;
188   svc_class_id_list[0] = UUID_SERVCLASS_HDP_SOURCE;
189   if (p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SINK) {
190     svc_class_id_list[0] = UUID_SERVCLASS_HDP_SINK;
191   } else {
192     if (p_cb->sup_feature.app_role_mask != BTA_HL_MDEP_ROLE_MASK_SOURCE) {
193       /* dual role */
194       num_services = 2;
195       svc_class_id_list[1] = UUID_SERVCLASS_HDP_SINK;
196     }
197   }
198   result &= SDP_AddServiceClassIdList(p_cb->sdp_handle, num_services,
199                                       svc_class_id_list);
200 
201   if (result) {
202     /* add the protocol element sequence */
203     proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
204     proto_elem_list[0].num_params = 1;
205     proto_elem_list[0].params[0] = p_cb->ctrl_psm;
206     proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_MCAP_CTRL;
207     proto_elem_list[1].num_params = 1;
208     proto_elem_list[1].params[0] = version;
209     result &= SDP_AddProtocolList(p_cb->sdp_handle, BTA_HL_NUM_PROTO_ELEMS,
210                                   proto_elem_list);
211 
212     result &=
213         SDP_AddProfileDescriptorList(p_cb->sdp_handle, profile_uuid, version);
214   }
215 
216   if (result) {
217     add_proto_list.num_elems = BTA_HL_NUM_ADD_PROTO_ELEMS;
218     add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
219     add_proto_list.list_elem[0].num_params = 1;
220     add_proto_list.list_elem[0].params[0] = p_cb->data_psm;
221     add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_MCAP_DATA;
222     add_proto_list.list_elem[1].num_params = 0;
223     result &=
224         SDP_AddAdditionProtoLists(p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS,
225                                   (tSDP_PROTO_LIST_ELEM*)&add_proto_list);
226   }
227 
228   if (result) {
229     if (p_cb->srv_name[0]) {
230       result &= SDP_AddAttribute(
231           p_cb->sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
232           (uint8_t)TEXT_STR_DESC_TYPE, (uint32_t)(strlen(p_cb->srv_name) + 1),
233           (uint8_t*)p_cb->srv_name);
234     } /* end of setting optional service name */
235   }
236 
237   if (result) {
238     if (p_cb->srv_desp[0]) {
239       result &= SDP_AddAttribute(
240           p_cb->sdp_handle, (uint16_t)ATTR_ID_SERVICE_DESCRIPTION,
241           (uint8_t)TEXT_STR_DESC_TYPE, (uint32_t)(strlen(p_cb->srv_desp) + 1),
242           (uint8_t*)p_cb->srv_desp);
243 
244     } /* end of setting optional service description */
245   }
246 
247   if (result) {
248     if (p_cb->provider_name[0]) {
249       result &=
250           SDP_AddAttribute(p_cb->sdp_handle, (uint16_t)ATTR_ID_PROVIDER_NAME,
251                            (uint8_t)TEXT_STR_DESC_TYPE,
252                            (uint32_t)(strlen(p_cb->provider_name) + 1),
253                            (uint8_t*)p_cb->provider_name);
254     } /* end of setting optional provider name */
255   }
256 
257   /* add supported feture list */
258 
259   if (result) {
260     cnt = 0;
261     for (i = 1; i < BTA_HL_NUM_MDEPS; i++) {
262       if (p_cb->sup_feature.mdep[i].mdep_id) {
263         mdep_id = (uint8_t)p_cb->sup_feature.mdep[i].mdep_id;
264         mdep_role = (uint8_t)p_cb->sup_feature.mdep[i].mdep_cfg.mdep_role;
265 
266         APPL_TRACE_DEBUG(
267             "num_of_mdep_data_types %d ",
268             p_cb->sup_feature.mdep[i].mdep_cfg.num_of_mdep_data_types);
269         for (j = 0;
270              j < p_cb->sup_feature.mdep[i].mdep_cfg.num_of_mdep_data_types;
271              j++) {
272           sup_feature_list.list_elem[cnt].mdep_id = mdep_id;
273           sup_feature_list.list_elem[cnt].mdep_role = mdep_role;
274           sup_feature_list.list_elem[cnt].data_type =
275               p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].data_type;
276           if (p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp[0] != '\0') {
277             sup_feature_list.list_elem[cnt].p_mdep_desp =
278                 p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp;
279           } else {
280             sup_feature_list.list_elem[cnt].p_mdep_desp = NULL;
281           }
282 
283           cnt++;
284           if (cnt == BTA_HL_NUM_SUP_FEATURE_ELEMS) {
285             result = false;
286             break;
287           }
288         }
289       }
290     }
291     sup_feature_list.num_elems = cnt;
292     result &= bta_hl_add_sup_feature_list(p_cb->sdp_handle,
293                                           sup_feature_list.num_elems,
294                                           sup_feature_list.list_elem);
295   }
296   if (result) {
297     result &= SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_DATA_EXCH_SPEC,
298                                UINT_DESC_TYPE, (uint32_t)1,
299                                (uint8_t*)&data_exchange_spec);
300   }
301 
302   if (result) {
303     result &=
304         SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_MCAP_SUP_PROC,
305                          UINT_DESC_TYPE, (uint32_t)1, (uint8_t*)&mcap_sup_proc);
306   }
307 
308   if (result) {
309     result &= SDP_AddUuidSequence(p_cb->sdp_handle, ATTR_ID_BROWSE_GROUP_LIST,
310                                   1, browse_list);
311   }
312 
313   if (result) {
314     for (i = 0; i < num_services; i++) {
315       bta_sys_add_uuid(svc_class_id_list[i]);
316       APPL_TRACE_DEBUG("dbg bta_sys_add_uuid i=%d uuid=0x%x", i,
317                        svc_class_id_list[i]);  // todo
318     }
319   } else {
320     if (p_cb->sdp_handle) {
321       SDP_DeleteRecord(p_cb->sdp_handle);
322       p_cb->sdp_handle = 0;
323     }
324     status = BTA_HL_STATUS_SDP_FAIL;
325   }
326 #if (BTA_HL_DEBUG == TRUE)
327   APPL_TRACE_DEBUG("bta_hl_sdp_update status=%s", bta_hl_status_code(status));
328 #endif
329   return status;
330 }
331 
332 /*****************************************************************************
333  *
334  *  Function:    bta_hl_sdp_register
335  *
336  *  Purpose:     Register an HDP application with SDP
337  *
338  *  Parameters:  p_cb           - Pointer to MA instance control block
339  *               p_service_name - MA server name
340  *               inst_id        - MAS instance ID
341  *               msg_type       - Supported message type(s)
342  *
343  *
344  *  Returns:     void
345  *
346  ****************************************************************************/
bta_hl_sdp_register(uint8_t app_idx)347 tBTA_HL_STATUS bta_hl_sdp_register(uint8_t app_idx) {
348   uint16_t svc_class_id_list[BTA_HL_NUM_SVC_ELEMS];
349   tSDP_PROTOCOL_ELEM proto_elem_list[BTA_HL_NUM_PROTO_ELEMS];
350   tSDP_PROTO_LIST_ELEM add_proto_list;
351   tBTA_HL_SUP_FEATURE_LIST_ELEM sup_feature_list;
352   uint16_t browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
353   uint8_t i, j, cnt, mdep_id, mdep_role;
354   uint8_t data_exchange_spec = BTA_HL_SDP_IEEE_11073_20601;
355   uint8_t mcap_sup_proc = BTA_HL_MCAP_SUP_PROC_MASK;
356   uint16_t profile_uuid = UUID_SERVCLASS_HDP_PROFILE;
357   uint16_t version = BTA_HL_VERSION;
358   uint8_t num_services = 1;
359   tBTA_HL_APP_CB* p_cb = BTA_HL_GET_APP_CB_PTR(app_idx);
360   bool result = true;
361   tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
362 
363 #if (BTA_HL_DEBUG == TRUE)
364   APPL_TRACE_DEBUG("bta_hl_sdp_register app_idx=%d", app_idx);
365 #endif
366 
367   if ((p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE) &&
368       (!p_cb->sup_feature.advertize_source_sdp)) {
369     return BTA_HL_STATUS_OK;
370   }
371 
372   p_cb->sdp_handle = SDP_CreateRecord();
373   if (p_cb->sdp_handle == 0) {
374     return BTA_HL_STATUS_SDP_NO_RESOURCE;
375   }
376 
377   num_services = 1;
378   svc_class_id_list[0] = UUID_SERVCLASS_HDP_SOURCE;
379   if (p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SINK) {
380     svc_class_id_list[0] = UUID_SERVCLASS_HDP_SINK;
381   } else {
382     if (p_cb->sup_feature.app_role_mask != BTA_HL_MDEP_ROLE_MASK_SOURCE) {
383       /* dual role */
384       num_services = 2;
385       svc_class_id_list[1] = UUID_SERVCLASS_HDP_SINK;
386     }
387   }
388   result &= SDP_AddServiceClassIdList(p_cb->sdp_handle, num_services,
389                                       svc_class_id_list);
390 
391   if (result) {
392     /* add the protocol element sequence */
393     proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
394     proto_elem_list[0].num_params = 1;
395     proto_elem_list[0].params[0] = p_cb->ctrl_psm;
396     proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_MCAP_CTRL;
397     proto_elem_list[1].num_params = 1;
398     proto_elem_list[1].params[0] = version;
399     result &= SDP_AddProtocolList(p_cb->sdp_handle, BTA_HL_NUM_PROTO_ELEMS,
400                                   proto_elem_list);
401 
402     result &=
403         SDP_AddProfileDescriptorList(p_cb->sdp_handle, profile_uuid, version);
404   }
405 
406   if (result) {
407     add_proto_list.num_elems = BTA_HL_NUM_ADD_PROTO_ELEMS;
408     add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
409     add_proto_list.list_elem[0].num_params = 1;
410     add_proto_list.list_elem[0].params[0] = p_cb->data_psm;
411     add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_MCAP_DATA;
412     add_proto_list.list_elem[1].num_params = 0;
413     result &=
414         SDP_AddAdditionProtoLists(p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS,
415                                   (tSDP_PROTO_LIST_ELEM*)&add_proto_list);
416   }
417 
418   if (result) {
419     if (p_cb->srv_name[0]) {
420       result &= SDP_AddAttribute(
421           p_cb->sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
422           (uint8_t)TEXT_STR_DESC_TYPE, (uint32_t)(strlen(p_cb->srv_name) + 1),
423           (uint8_t*)p_cb->srv_name);
424     } /* end of setting optional service name */
425   }
426 
427   if (result) {
428     if (p_cb->srv_desp[0]) {
429       result &= SDP_AddAttribute(
430           p_cb->sdp_handle, (uint16_t)ATTR_ID_SERVICE_DESCRIPTION,
431           (uint8_t)TEXT_STR_DESC_TYPE, (uint32_t)(strlen(p_cb->srv_desp) + 1),
432           (uint8_t*)p_cb->srv_desp);
433 
434     } /* end of setting optional service description */
435   }
436 
437   if (result) {
438     if (p_cb->provider_name[0]) {
439       result &=
440           SDP_AddAttribute(p_cb->sdp_handle, (uint16_t)ATTR_ID_PROVIDER_NAME,
441                            (uint8_t)TEXT_STR_DESC_TYPE,
442                            (uint32_t)(strlen(p_cb->provider_name) + 1),
443                            (uint8_t*)p_cb->provider_name);
444     } /* end of setting optional provider name */
445   }
446 
447   /* add supported feture list */
448 
449   if (result) {
450     cnt = 0;
451     for (i = 1; i <= p_cb->sup_feature.num_of_mdeps; i++) {
452       mdep_id = (uint8_t)p_cb->sup_feature.mdep[i].mdep_id;
453       mdep_role = (uint8_t)p_cb->sup_feature.mdep[i].mdep_cfg.mdep_role;
454 
455       for (j = 0; j < p_cb->sup_feature.mdep[i].mdep_cfg.num_of_mdep_data_types;
456            j++) {
457         sup_feature_list.list_elem[cnt].mdep_id = mdep_id;
458         sup_feature_list.list_elem[cnt].mdep_role = mdep_role;
459         sup_feature_list.list_elem[cnt].data_type =
460             p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].data_type;
461         if (p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp[0] != '\0') {
462           sup_feature_list.list_elem[cnt].p_mdep_desp =
463               p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp;
464         } else {
465           sup_feature_list.list_elem[cnt].p_mdep_desp = NULL;
466         }
467 
468         cnt++;
469         if (cnt == BTA_HL_NUM_SUP_FEATURE_ELEMS) {
470           result = false;
471           break;
472         }
473       }
474     }
475     sup_feature_list.num_elems = cnt;
476     result &= bta_hl_add_sup_feature_list(p_cb->sdp_handle,
477                                           sup_feature_list.num_elems,
478                                           sup_feature_list.list_elem);
479   }
480   if (result) {
481     result &= SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_DATA_EXCH_SPEC,
482                                UINT_DESC_TYPE, (uint32_t)1,
483                                (uint8_t*)&data_exchange_spec);
484   }
485 
486   if (result) {
487     result &=
488         SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_MCAP_SUP_PROC,
489                          UINT_DESC_TYPE, (uint32_t)1, (uint8_t*)&mcap_sup_proc);
490   }
491 
492   if (result) {
493     result &= SDP_AddUuidSequence(p_cb->sdp_handle, ATTR_ID_BROWSE_GROUP_LIST,
494                                   1, browse_list);
495   }
496 
497   if (result) {
498     for (i = 0; i < num_services; i++) {
499       bta_sys_add_uuid(svc_class_id_list[i]);
500       APPL_TRACE_DEBUG("dbg bta_sys_add_uuid i=%d uuid=0x%x", i,
501                        svc_class_id_list[i]);  // todo
502     }
503   } else {
504     if (p_cb->sdp_handle) {
505       SDP_DeleteRecord(p_cb->sdp_handle);
506       p_cb->sdp_handle = 0;
507     }
508     status = BTA_HL_STATUS_SDP_FAIL;
509   }
510 #if (BTA_HL_DEBUG == TRUE)
511   APPL_TRACE_DEBUG("bta_hl_sdp_register status=%s", bta_hl_status_code(status));
512 #endif
513   return status;
514 }
515 
516 /*******************************************************************************
517  *
518  * Function         bta_hl_find_sink_or_src_srv_class_in_db
519  *
520  * Description      This function queries an SDP database for either a HDP Sink
521  *                  or Source service class ID.
522  *                  If the p_start_rec pointer is NULL, it looks from the
523  *                  beginning of the database, else it continues from the next
524  *                  record after p_start_rec.
525  *
526  * Returns          Pointer to record containing service class, or NULL
527  *
528  ******************************************************************************/
bta_hl_find_sink_or_src_srv_class_in_db(const tSDP_DISCOVERY_DB * p_db,const tSDP_DISC_REC * p_start_rec)529 tSDP_DISC_REC* bta_hl_find_sink_or_src_srv_class_in_db(
530     const tSDP_DISCOVERY_DB* p_db, const tSDP_DISC_REC* p_start_rec) {
531   tSDP_DISC_REC* p_rec;
532   tSDP_DISC_ATTR *p_attr, *p_sattr;
533 
534   /* Must have a valid database */
535   if (p_db == NULL) return (NULL);
536 
537   if (!p_start_rec) {
538     p_rec = p_db->p_first_rec;
539   } else {
540     p_rec = p_start_rec->p_next_rec;
541   }
542 
543   while (p_rec) {
544     p_attr = p_rec->p_first_attr;
545     while (p_attr) {
546       if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
547           (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) ==
548            DATA_ELE_SEQ_DESC_TYPE)) {
549         for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
550              p_sattr = p_sattr->p_next_attr) {
551           if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) &&
552               (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2) &&
553               ((p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SINK) ||
554                (p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SOURCE))) {
555             return (p_rec);
556           }
557         }
558         break;
559       }
560 
561       p_attr = p_attr->p_next_attr;
562     }
563 
564     p_rec = p_rec->p_next_rec;
565   }
566 /* If here, no matching UUID found */
567 
568 #if (BTA_HL_DEBUG == TRUE)
569   APPL_TRACE_DEBUG("bta_hl_find_sink_or_src_srv_class_in_db failed");
570 #endif
571 
572   return (NULL);
573 }
574 #endif /* HL_INCLUDED */
575