1 /******************************************************************************
2 *
3 * Copyright (C) 1999-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 SDP interface functions
22 *
23 ******************************************************************************/
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "bt_common.h"
30 #include "bt_target.h"
31 #include "bt_utils.h"
32 #include "hcidefs.h"
33 #include "hcimsgs.h"
34 #include "l2cdefs.h"
35
36 #include "btu.h"
37 #include "sdp_api.h"
38 #include "sdpint.h"
39
40 #include "osi/include/osi.h"
41
42 /**********************************************************************
43 * C L I E N T F U N C T I O N P R O T O T Y P E S *
44 **********************************************************************/
45
46 /*******************************************************************************
47 *
48 * Function SDP_InitDiscoveryDb
49 *
50 * Description This function is called to initialize a discovery database.
51 *
52 * Parameters: p_db - (input) address of an area of memory where the
53 * discovery database is managed.
54 * len - (input) size (in bytes) of the memory
55 * NOTE: This must be larger than
56 * sizeof(tSDP_DISCOVERY_DB)
57 * num_uuid - (input) number of UUID filters applied
58 * p_uuid_list - (input) list of UUID filters
59 * num_attr - (input) number of attribute filters applied
60 * p_attr_list - (input) list of attribute filters
61 *
62 *
63 * Returns bool
64 * true if successful
65 * false if one or more parameters are bad
66 *
67 ******************************************************************************/
SDP_InitDiscoveryDb(tSDP_DISCOVERY_DB * p_db,uint32_t len,uint16_t num_uuid,tSDP_UUID * p_uuid_list,uint16_t num_attr,uint16_t * p_attr_list)68 bool SDP_InitDiscoveryDb(tSDP_DISCOVERY_DB* p_db, uint32_t len,
69 uint16_t num_uuid, tSDP_UUID* p_uuid_list,
70 uint16_t num_attr, uint16_t* p_attr_list) {
71 uint16_t xx;
72
73 /* verify the parameters */
74 if (p_db == NULL || (sizeof(tSDP_DISCOVERY_DB) > len) ||
75 num_attr > SDP_MAX_ATTR_FILTERS || num_uuid > SDP_MAX_UUID_FILTERS) {
76 SDP_TRACE_ERROR(
77 "SDP_InitDiscoveryDb Illegal param: p_db 0x%x, len %d, num_uuid %d, "
78 "num_attr %d",
79 PTR_TO_UINT(p_db), len, num_uuid, num_attr);
80
81 return (false);
82 }
83
84 memset(p_db, 0, (size_t)len);
85
86 p_db->mem_size = len - sizeof(tSDP_DISCOVERY_DB);
87 p_db->mem_free = p_db->mem_size;
88 p_db->p_first_rec = NULL;
89 p_db->p_free_mem = (uint8_t*)(p_db + 1);
90
91 for (xx = 0; xx < num_uuid; xx++) p_db->uuid_filters[xx] = *p_uuid_list++;
92
93 p_db->num_uuid_filters = num_uuid;
94
95 for (xx = 0; xx < num_attr; xx++) p_db->attr_filters[xx] = *p_attr_list++;
96
97 /* sort attributes */
98 sdpu_sort_attr_list(num_attr, p_db);
99
100 p_db->num_attr_filters = num_attr;
101 return (true);
102 }
103
104 /*******************************************************************************
105 *
106 * Function SDP_CancelServiceSearch
107 *
108 * Description This function cancels an active query to an SDP server.
109 *
110 * Returns true if discovery cancelled, false if a matching activity is
111 * not found.
112 *
113 ******************************************************************************/
SDP_CancelServiceSearch(tSDP_DISCOVERY_DB * p_db)114 bool SDP_CancelServiceSearch(tSDP_DISCOVERY_DB* p_db) {
115 tCONN_CB* p_ccb = sdpu_find_ccb_by_db(p_db);
116 if (!p_ccb) return (false);
117
118 sdp_disconnect(p_ccb, SDP_CANCEL);
119 p_ccb->disc_state = SDP_DISC_WAIT_CANCEL;
120 return (true);
121 }
122
123 /*******************************************************************************
124 *
125 * Function SDP_ServiceSearchRequest
126 *
127 * Description This function queries an SDP server for information.
128 *
129 * Returns true if discovery started, false if failed.
130 *
131 ******************************************************************************/
SDP_ServiceSearchRequest(uint8_t * p_bd_addr,tSDP_DISCOVERY_DB * p_db,tSDP_DISC_CMPL_CB * p_cb)132 bool SDP_ServiceSearchRequest(uint8_t* p_bd_addr, tSDP_DISCOVERY_DB* p_db,
133 tSDP_DISC_CMPL_CB* p_cb) {
134 tCONN_CB* p_ccb;
135
136 /* Specific BD address */
137 p_ccb = sdp_conn_originate(p_bd_addr);
138
139 if (!p_ccb) return (false);
140
141 p_ccb->disc_state = SDP_DISC_WAIT_CONN;
142 p_ccb->p_db = p_db;
143 p_ccb->p_cb = p_cb;
144
145 return (true);
146 }
147
148 /*******************************************************************************
149 *
150 * Function SDP_ServiceSearchAttributeRequest
151 *
152 * Description This function queries an SDP server for information.
153 *
154 * The difference between this API function and the function
155 * SDP_ServiceSearchRequest is that this one does a
156 * combined ServiceSearchAttributeRequest SDP function.
157 * (This is for Unplug Testing)
158 *
159 * Returns true if discovery started, false if failed.
160 *
161 ******************************************************************************/
SDP_ServiceSearchAttributeRequest(uint8_t * p_bd_addr,tSDP_DISCOVERY_DB * p_db,tSDP_DISC_CMPL_CB * p_cb)162 bool SDP_ServiceSearchAttributeRequest(uint8_t* p_bd_addr,
163 tSDP_DISCOVERY_DB* p_db,
164 tSDP_DISC_CMPL_CB* p_cb) {
165 tCONN_CB* p_ccb;
166
167 /* Specific BD address */
168 p_ccb = sdp_conn_originate(p_bd_addr);
169
170 if (!p_ccb) return (false);
171
172 p_ccb->disc_state = SDP_DISC_WAIT_CONN;
173 p_ccb->p_db = p_db;
174 p_ccb->p_cb = p_cb;
175
176 p_ccb->is_attr_search = true;
177
178 return (true);
179 }
180 /*******************************************************************************
181 *
182 * Function SDP_ServiceSearchAttributeRequest2
183 *
184 * Description This function queries an SDP server for information.
185 *
186 * The difference between this API function and the function
187 * SDP_ServiceSearchRequest is that this one does a
188 * combined ServiceSearchAttributeRequest SDP function.
189 * (This is for Unplug Testing)
190 *
191 * Returns true if discovery started, false if failed.
192 *
193 ******************************************************************************/
SDP_ServiceSearchAttributeRequest2(uint8_t * p_bd_addr,tSDP_DISCOVERY_DB * p_db,tSDP_DISC_CMPL_CB2 * p_cb2,void * user_data)194 bool SDP_ServiceSearchAttributeRequest2(uint8_t* p_bd_addr,
195 tSDP_DISCOVERY_DB* p_db,
196 tSDP_DISC_CMPL_CB2* p_cb2,
197 void* user_data) {
198 tCONN_CB* p_ccb;
199
200 /* Specific BD address */
201 p_ccb = sdp_conn_originate(p_bd_addr);
202
203 if (!p_ccb) return (false);
204
205 p_ccb->disc_state = SDP_DISC_WAIT_CONN;
206 p_ccb->p_db = p_db;
207 p_ccb->p_cb2 = p_cb2;
208
209 p_ccb->is_attr_search = true;
210 p_ccb->user_data = user_data;
211
212 return (true);
213 }
214
SDP_SetIdleTimeout(UNUSED_ATTR BD_ADDR addr,UNUSED_ATTR uint16_t timeout)215 void SDP_SetIdleTimeout(UNUSED_ATTR BD_ADDR addr,
216 UNUSED_ATTR uint16_t timeout) {}
217
218 /*******************************************************************************
219 *
220 * Function SDP_FindAttributeInDb
221 *
222 * Description This function queries an SDP database for a specific
223 * attribute. If the p_start_rec pointer is NULL, it looks from
224 * the beginning of the database, else it continues from the
225 * next record after p_start_rec.
226 *
227 * Returns Pointer to matching record, or NULL
228 *
229 ******************************************************************************/
SDP_FindAttributeInDb(tSDP_DISCOVERY_DB * p_db,uint16_t attr_id,tSDP_DISC_REC * p_start_rec)230 tSDP_DISC_REC* SDP_FindAttributeInDb(tSDP_DISCOVERY_DB* p_db, uint16_t attr_id,
231 tSDP_DISC_REC* p_start_rec) {
232 tSDP_DISC_REC* p_rec;
233 tSDP_DISC_ATTR* p_attr;
234
235 /* Must have a valid database */
236 if (p_db == NULL) return (NULL);
237
238 if (!p_start_rec)
239 p_rec = p_db->p_first_rec;
240 else
241 p_rec = p_start_rec->p_next_rec;
242
243 while (p_rec) {
244 p_attr = p_rec->p_first_attr;
245 while (p_attr) {
246 if (p_attr->attr_id == attr_id) return (p_rec);
247
248 p_attr = p_attr->p_next_attr;
249 }
250
251 p_rec = p_rec->p_next_rec;
252 }
253 /* If here, no matching attribute found */
254 return (NULL);
255 }
256
257 /*******************************************************************************
258 *
259 * Function SDP_FindAttributeInRec
260 *
261 * Description This function searches an SDP discovery record for a
262 * specific attribute.
263 *
264 * Returns Pointer to matching attribute entry, or NULL
265 *
266 ******************************************************************************/
SDP_FindAttributeInRec(tSDP_DISC_REC * p_rec,uint16_t attr_id)267 tSDP_DISC_ATTR* SDP_FindAttributeInRec(tSDP_DISC_REC* p_rec, uint16_t attr_id) {
268 tSDP_DISC_ATTR* p_attr;
269
270 p_attr = p_rec->p_first_attr;
271 while (p_attr) {
272 if (p_attr->attr_id == attr_id) return (p_attr);
273
274 p_attr = p_attr->p_next_attr;
275 }
276
277 /* If here, no matching attribute found */
278 return (NULL);
279 }
280
281 /*******************************************************************************
282 *
283 * Function SDP_FindServiceUUIDInRec
284 *
285 * Description This function is called to read the service UUID within a
286 * record if there is any.
287 *
288 * Parameters: p_rec - pointer to a SDP record.
289 * p_uuid - output parameter to save the UUID found.
290 *
291 * Returns true if found, otherwise false.
292 *
293 ******************************************************************************/
SDP_FindServiceUUIDInRec(tSDP_DISC_REC * p_rec,tBT_UUID * p_uuid)294 bool SDP_FindServiceUUIDInRec(tSDP_DISC_REC* p_rec, tBT_UUID* p_uuid) {
295 tSDP_DISC_ATTR *p_attr, *p_sattr, *p_extra_sattr;
296
297 p_attr = p_rec->p_first_attr;
298
299 while (p_attr) {
300 if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
301 (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)) {
302 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
303 p_sattr = p_sattr->p_next_attr) {
304 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) {
305 if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == LEN_UUID_16) {
306 p_uuid->len = LEN_UUID_16;
307 p_uuid->uu.uuid16 = p_sattr->attr_value.v.u16;
308 } else if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) ==
309 LEN_UUID_128) {
310 p_uuid->len = LEN_UUID_128;
311 for (uint8_t i = 0; i != LEN_UUID_128; ++i)
312 p_uuid->uu.uuid128[i] =
313 p_sattr->attr_value.v.array[LEN_UUID_128 - i - 1];
314 } else if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == LEN_UUID_32) {
315 p_uuid->len = LEN_UUID_32;
316 p_uuid->uu.uuid32 = p_sattr->attr_value.v.u32;
317 }
318
319 return (true);
320 }
321
322 /* Checking for Toyota G Block Car Kit:
323 ** This car kit puts an extra data element sequence
324 ** where the UUID is suppose to be!!!
325 */
326 else {
327 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) ==
328 DATA_ELE_SEQ_DESC_TYPE) {
329 /* Look through data element sequence until no more UUIDs */
330 for (p_extra_sattr = p_sattr->attr_value.v.p_sub_attr;
331 p_extra_sattr; p_extra_sattr = p_extra_sattr->p_next_attr) {
332 /* Increment past this to see if the next attribut is UUID */
333 if ((SDP_DISC_ATTR_TYPE(p_extra_sattr->attr_len_type) ==
334 UUID_DESC_TYPE)
335 /* only support 16 bits UUID for now */
336 && (SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2)) {
337 p_uuid->len = 2;
338 p_uuid->uu.uuid16 = p_extra_sattr->attr_value.v.u16;
339 return (true);
340 }
341 }
342 }
343 }
344 }
345 break;
346 } else if (p_attr->attr_id == ATTR_ID_SERVICE_ID) {
347 if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE)
348 /* only support 16 bits UUID for now */
349 && (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2)) {
350 p_uuid->len = 2;
351 p_uuid->uu.uuid16 = p_attr->attr_value.v.u16;
352 return (true);
353 }
354 }
355 p_attr = p_attr->p_next_attr;
356 }
357 return false;
358 }
359
360 /*******************************************************************************
361 *
362 * Function SDP_FindServiceUUIDInRec_128bit
363 *
364 * Description This function is called to read the 128-bit service UUID
365 * within a record if there is any.
366 *
367 * Parameters: p_rec - pointer to a SDP record.
368 * p_uuid - output parameter to save the UUID found.
369 *
370 * Returns true if found, otherwise false.
371 *
372 ******************************************************************************/
SDP_FindServiceUUIDInRec_128bit(tSDP_DISC_REC * p_rec,tBT_UUID * p_uuid)373 bool SDP_FindServiceUUIDInRec_128bit(tSDP_DISC_REC* p_rec, tBT_UUID* p_uuid) {
374 tSDP_DISC_ATTR* p_attr = p_rec->p_first_attr;
375 while (p_attr) {
376 if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
377 (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)) {
378 tSDP_DISC_ATTR* p_sattr = p_attr->attr_value.v.p_sub_attr;
379 while (p_sattr) {
380 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) {
381 /* only support 128 bits UUID for now */
382 if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 16) {
383 p_uuid->len = LEN_UUID_128;
384 for (uint8_t i = 0; i != LEN_UUID_128; ++i)
385 p_uuid->uu.uuid128[i] =
386 p_sattr->attr_value.v.array[LEN_UUID_128 - i - 1];
387 }
388 return (true);
389 }
390
391 p_sattr = p_sattr->p_next_attr;
392 }
393 break;
394 } else if (p_attr->attr_id == ATTR_ID_SERVICE_ID) {
395 if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE)
396 /* only support 128 bits UUID for now */
397 && (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 16)) {
398 p_uuid->len = LEN_UUID_128;
399 for (uint8_t i = 0; i != LEN_UUID_128; ++i)
400 p_uuid->uu.uuid128[i] =
401 p_attr->attr_value.v.array[LEN_UUID_128 - i - 1];
402 return (true);
403 }
404 }
405 p_attr = p_attr->p_next_attr;
406 }
407 return false;
408 }
409
410 /*******************************************************************************
411 *
412 * Function SDP_FindServiceInDb
413 *
414 * Description This function queries an SDP database for a specific
415 * service. If the p_start_rec pointer is NULL, it looks from
416 * the beginning of the database, else it continues from the
417 * next record after p_start_rec.
418 *
419 * Returns Pointer to record containing service class, or NULL
420 *
421 ******************************************************************************/
SDP_FindServiceInDb(tSDP_DISCOVERY_DB * p_db,uint16_t service_uuid,tSDP_DISC_REC * p_start_rec)422 tSDP_DISC_REC* SDP_FindServiceInDb(tSDP_DISCOVERY_DB* p_db,
423 uint16_t service_uuid,
424 tSDP_DISC_REC* p_start_rec) {
425 tSDP_DISC_REC* p_rec;
426 tSDP_DISC_ATTR *p_attr, *p_sattr, *p_extra_sattr;
427
428 /* Must have a valid database */
429 if (p_db == NULL) return (NULL);
430
431 if (!p_start_rec)
432 p_rec = p_db->p_first_rec;
433 else
434 p_rec = p_start_rec->p_next_rec;
435
436 while (p_rec) {
437 p_attr = p_rec->p_first_attr;
438 while (p_attr) {
439 if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
440 (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) ==
441 DATA_ELE_SEQ_DESC_TYPE)) {
442 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
443 p_sattr = p_sattr->p_next_attr) {
444 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) &&
445 (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2)) {
446 SDP_TRACE_DEBUG(
447 "SDP_FindServiceInDb - p_sattr value = 0x%x serviceuuid = 0x%x",
448 p_sattr->attr_value.v.u16, service_uuid);
449 if (service_uuid == UUID_SERVCLASS_HDP_PROFILE) {
450 if ((p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SOURCE) ||
451 (p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SINK)) {
452 SDP_TRACE_DEBUG(
453 "SDP_FindServiceInDb found HDP source or sink\n");
454 return (p_rec);
455 }
456 }
457 }
458
459 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE &&
460 (service_uuid == 0 ||
461 (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2 &&
462 p_sattr->attr_value.v.u16 == service_uuid)))
463 /* for a specific uuid, or any one */
464 {
465 return (p_rec);
466 }
467
468 /* Checking for Toyota G Block Car Kit:
469 ** This car kit puts an extra data element sequence
470 ** where the UUID is suppose to be!!!
471 */
472 else {
473 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) ==
474 DATA_ELE_SEQ_DESC_TYPE) {
475 /* Look through data element sequence until no more UUIDs */
476 for (p_extra_sattr = p_sattr->attr_value.v.p_sub_attr;
477 p_extra_sattr; p_extra_sattr = p_extra_sattr->p_next_attr) {
478 /* Increment past this to see if the next attribut is UUID */
479 if ((SDP_DISC_ATTR_TYPE(p_extra_sattr->attr_len_type) ==
480 UUID_DESC_TYPE) &&
481 (SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2)
482 /* for a specific uuid, or any one */
483 && ((p_extra_sattr->attr_value.v.u16 == service_uuid) ||
484 (service_uuid == 0))) {
485 return (p_rec);
486 }
487 }
488 }
489 }
490 }
491 break;
492 } else if (p_attr->attr_id == ATTR_ID_SERVICE_ID) {
493 if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE) &&
494 (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2)
495 /* find a specific UUID or anyone */
496 &&
497 ((p_attr->attr_value.v.u16 == service_uuid) || service_uuid == 0))
498 return (p_rec);
499 }
500
501 p_attr = p_attr->p_next_attr;
502 }
503
504 p_rec = p_rec->p_next_rec;
505 }
506 /* If here, no matching UUID found */
507 return (NULL);
508 }
509
510 /*******************************************************************************
511 *
512 * Function SDP_FindServiceInDb_128bit
513 *
514 * Description Query an SDP database for a specific service. If the
515 * p_start_rec pointer is NULL, it looks from the beginning of
516 * the database, else it continues from the next record after
517 * p_start_rec.
518 *
519 * This function is kept separate from SDP_FindServiceInDb
520 * since that API is expected to return only 16-bit UUIDs
521 *
522 * Returns Pointer to record containing service class, or NULL
523 *
524 ******************************************************************************/
SDP_FindServiceInDb_128bit(tSDP_DISCOVERY_DB * p_db,tSDP_DISC_REC * p_start_rec)525 tSDP_DISC_REC* SDP_FindServiceInDb_128bit(tSDP_DISCOVERY_DB* p_db,
526 tSDP_DISC_REC* p_start_rec) {
527 tSDP_DISC_REC* p_rec;
528 tSDP_DISC_ATTR *p_attr, *p_sattr;
529
530 /* Must have a valid database */
531 if (p_db == NULL) return (NULL);
532
533 if (!p_start_rec)
534 p_rec = p_db->p_first_rec;
535 else
536 p_rec = p_start_rec->p_next_rec;
537
538 while (p_rec) {
539 p_attr = p_rec->p_first_attr;
540 while (p_attr) {
541 if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
542 (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) ==
543 DATA_ELE_SEQ_DESC_TYPE)) {
544 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
545 p_sattr = p_sattr->p_next_attr) {
546 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) &&
547 (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 16)) {
548 return (p_rec);
549 }
550 }
551 break;
552 } else if (p_attr->attr_id == ATTR_ID_SERVICE_ID) {
553 if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE) &&
554 (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 16))
555 return (p_rec);
556 }
557
558 p_attr = p_attr->p_next_attr;
559 }
560
561 p_rec = p_rec->p_next_rec;
562 }
563 /* If here, no matching UUID found */
564 return (NULL);
565 }
566
567 /*******************************************************************************
568 *
569 * Function SDP_FindServiceUUIDInDb
570 *
571 * Description Query an SDP database for a specific service. If the
572 * p_start_rec pointer is NULL, it looks from the beginning of
573 * the database, else it continues from the next record after
574 * p_start_rec.
575 *
576 * NOTE the only difference between this function and the previous
577 * function "SDP_FindServiceInDb()" is that this function takes
578 * a tBT_UUID input
579 *
580 * Returns Pointer to record containing service class, or NULL
581 *
582 ******************************************************************************/
SDP_FindServiceUUIDInDb(tSDP_DISCOVERY_DB * p_db,tBT_UUID * p_uuid,tSDP_DISC_REC * p_start_rec)583 tSDP_DISC_REC* SDP_FindServiceUUIDInDb(tSDP_DISCOVERY_DB* p_db,
584 tBT_UUID* p_uuid,
585 tSDP_DISC_REC* p_start_rec) {
586 tSDP_DISC_REC* p_rec;
587 tSDP_DISC_ATTR *p_attr, *p_sattr;
588
589 /* Must have a valid database */
590 if (p_db == NULL) return (NULL);
591
592 if (!p_start_rec)
593 p_rec = p_db->p_first_rec;
594 else
595 p_rec = p_start_rec->p_next_rec;
596
597 while (p_rec) {
598 p_attr = p_rec->p_first_attr;
599 while (p_attr) {
600 if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
601 (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) ==
602 DATA_ELE_SEQ_DESC_TYPE)) {
603 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
604 p_sattr = p_sattr->p_next_attr) {
605 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) {
606 if (sdpu_compare_uuid_with_attr(p_uuid, p_sattr)) return (p_rec);
607 }
608 }
609 break;
610 } else if (p_attr->attr_id == ATTR_ID_SERVICE_ID) {
611 if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE) {
612 if (sdpu_compare_uuid_with_attr(p_uuid, p_attr)) return (p_rec);
613 }
614 }
615
616 p_attr = p_attr->p_next_attr;
617 }
618
619 p_rec = p_rec->p_next_rec;
620 }
621 /* If here, no matching UUID found */
622 return (NULL);
623 }
624
625 /*******************************************************************************
626 *
627 * Function sdp_fill_proto_elem
628 *
629 * Description This function retrieves the protocol element.
630 *
631 * Returns true if found, false if not
632 * If found, the passed protocol list element is filled in.
633 *
634 ******************************************************************************/
sdp_fill_proto_elem(tSDP_DISC_ATTR * p_attr,uint16_t layer_uuid,tSDP_PROTOCOL_ELEM * p_elem)635 static bool sdp_fill_proto_elem(tSDP_DISC_ATTR* p_attr, uint16_t layer_uuid,
636 tSDP_PROTOCOL_ELEM* p_elem) {
637 tSDP_DISC_ATTR* p_sattr;
638
639 /* Walk through the protocol descriptor list */
640 for (p_attr = p_attr->attr_value.v.p_sub_attr; p_attr;
641 p_attr = p_attr->p_next_attr) {
642 /* Safety check - each entry should itself be a sequence */
643 if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE)
644 return (false);
645
646 /* Now, see if the entry contains the layer we are interested in */
647 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
648 p_sattr = p_sattr->p_next_attr) {
649 /* SDP_TRACE_DEBUG ("SDP - p_sattr 0x%x, layer_uuid:0x%x, u16:0x%x####",
650 p_sattr, layer_uuid, p_sattr->attr_value.v.u16); */
651
652 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) &&
653 (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2) &&
654 (p_sattr->attr_value.v.u16 == layer_uuid)) {
655 /* Bingo. Now fill in the passed element */
656 p_elem->protocol_uuid = layer_uuid;
657 p_elem->num_params = 0;
658
659 /* Store the parameters, if any */
660 for (p_sattr = p_sattr->p_next_attr; p_sattr;
661 p_sattr = p_sattr->p_next_attr) {
662 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) != UINT_DESC_TYPE)
663 break;
664
665 if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2)
666 p_elem->params[p_elem->num_params++] = p_sattr->attr_value.v.u16;
667 else
668 p_elem->params[p_elem->num_params++] = p_sattr->attr_value.v.u8;
669
670 if (p_elem->num_params >= SDP_MAX_PROTOCOL_PARAMS) break;
671 }
672 return (true);
673 }
674 }
675 }
676
677 return (false);
678 }
679
680 /*******************************************************************************
681 *
682 * Function SDP_FindProtocolListElemInRec
683 *
684 * Description This function looks at a specific discovery record for a
685 * protocol list element.
686 *
687 * Returns true if found, false if not
688 * If found, the passed protocol list element is filled in.
689 *
690 ******************************************************************************/
SDP_FindProtocolListElemInRec(tSDP_DISC_REC * p_rec,uint16_t layer_uuid,tSDP_PROTOCOL_ELEM * p_elem)691 bool SDP_FindProtocolListElemInRec(tSDP_DISC_REC* p_rec, uint16_t layer_uuid,
692 tSDP_PROTOCOL_ELEM* p_elem) {
693 tSDP_DISC_ATTR* p_attr;
694
695 p_attr = p_rec->p_first_attr;
696 while (p_attr) {
697 /* Find the protocol descriptor list */
698 if ((p_attr->attr_id == ATTR_ID_PROTOCOL_DESC_LIST) &&
699 (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)) {
700 return sdp_fill_proto_elem(p_attr, layer_uuid, p_elem);
701 }
702 p_attr = p_attr->p_next_attr;
703 }
704 /* If here, no match found */
705 return (false);
706 }
707
708 /*******************************************************************************
709 *
710 * Function SDP_FindAddProtoListsElemInRec
711 *
712 * Description This function looks at a specific discovery record for a
713 * protocol list element.
714 *
715 * Returns true if found, false if not
716 * If found, the passed protocol list element is filled in.
717 *
718 ******************************************************************************/
SDP_FindAddProtoListsElemInRec(tSDP_DISC_REC * p_rec,uint16_t layer_uuid,tSDP_PROTOCOL_ELEM * p_elem)719 bool SDP_FindAddProtoListsElemInRec(tSDP_DISC_REC* p_rec, uint16_t layer_uuid,
720 tSDP_PROTOCOL_ELEM* p_elem) {
721 tSDP_DISC_ATTR *p_attr, *p_sattr;
722 bool ret = false;
723
724 p_attr = p_rec->p_first_attr;
725 while (p_attr) {
726 /* Find the additional protocol descriptor list attribute */
727 if ((p_attr->attr_id == ATTR_ID_ADDITION_PROTO_DESC_LISTS) &&
728 (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)) {
729 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
730 p_sattr = p_sattr->p_next_attr) {
731 /* Safety check - each entry should itself be a sequence */
732 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) ==
733 DATA_ELE_SEQ_DESC_TYPE) {
734 ret = sdp_fill_proto_elem(p_sattr, layer_uuid, p_elem);
735 if (ret == true) break;
736 }
737 }
738 return ret;
739 }
740 p_attr = p_attr->p_next_attr;
741 }
742 /* If here, no match found */
743 return (false);
744 }
745
746 /*******************************************************************************
747 *
748 * Function SDP_FindProfileVersionInRec
749 *
750 * Description This function looks at a specific discovery record for the
751 * Profile list descriptor, and pulls out the version number.
752 * The version number consists of an 8-bit major version and
753 * an 8-bit minor version.
754 *
755 * Returns true if found, false if not
756 * If found, the major and minor version numbers that were
757 * passed in are filled in.
758 *
759 ******************************************************************************/
SDP_FindProfileVersionInRec(tSDP_DISC_REC * p_rec,uint16_t profile_uuid,uint16_t * p_version)760 bool SDP_FindProfileVersionInRec(tSDP_DISC_REC* p_rec, uint16_t profile_uuid,
761 uint16_t* p_version) {
762 tSDP_DISC_ATTR *p_attr, *p_sattr;
763
764 p_attr = p_rec->p_first_attr;
765 while (p_attr) {
766 /* Find the profile descriptor list */
767 if ((p_attr->attr_id == ATTR_ID_BT_PROFILE_DESC_LIST) &&
768 (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)) {
769 /* Walk through the protocol descriptor list */
770 for (p_attr = p_attr->attr_value.v.p_sub_attr; p_attr;
771 p_attr = p_attr->p_next_attr) {
772 /* Safety check - each entry should itself be a sequence */
773 if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE)
774 return (false);
775
776 /* Now, see if the entry contains the profile UUID we are interested in
777 */
778 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
779 p_sattr = p_sattr->p_next_attr) {
780 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) &&
781 (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) ==
782 2) /* <- This is bytes, not size code! */
783 && (p_sattr->attr_value.v.u16 == profile_uuid)) {
784 /* Now fill in the major and minor numbers */
785 /* if the attribute matches the description for version (type UINT,
786 * size 2 bytes) */
787 p_sattr = p_sattr->p_next_attr;
788
789 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) ==
790 UINT_DESC_TYPE) &&
791 (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2)) {
792 /* The high order 8 bits is the major number, low order is the
793 * minor number (big endian) */
794 *p_version = p_sattr->attr_value.v.u16;
795
796 return (true);
797 } else
798 return (false); /* The type and/or size was not valid for the
799 profile list version */
800 }
801 }
802 }
803
804 return (false);
805 }
806 p_attr = p_attr->p_next_attr;
807 }
808
809 /* If here, no match found */
810 return (false);
811 }
812
813 /*******************************************************************************
814 * Device Identification (DI) Client Functions
815 ******************************************************************************/
816
817 /*******************************************************************************
818 *
819 * Function SDP_DiDiscover
820 *
821 * Description This function queries a remote device for DI information.
822 *
823 * Returns SDP_SUCCESS if query started successfully, else error
824 *
825 ******************************************************************************/
SDP_DiDiscover(BD_ADDR remote_device,tSDP_DISCOVERY_DB * p_db,uint32_t len,tSDP_DISC_CMPL_CB * p_cb)826 uint16_t SDP_DiDiscover(BD_ADDR remote_device, tSDP_DISCOVERY_DB* p_db,
827 uint32_t len, tSDP_DISC_CMPL_CB* p_cb) {
828 uint16_t result = SDP_DI_DISC_FAILED;
829 uint16_t num_uuids = 1;
830 uint16_t di_uuid = UUID_SERVCLASS_PNP_INFORMATION;
831
832 /* build uuid for db init */
833 tSDP_UUID init_uuid;
834 init_uuid.len = 2;
835 init_uuid.uu.uuid16 = di_uuid;
836
837 if (SDP_InitDiscoveryDb(p_db, len, num_uuids, &init_uuid, 0, NULL))
838 if (SDP_ServiceSearchRequest(remote_device, p_db, p_cb))
839 result = SDP_SUCCESS;
840
841 return result;
842 }
843
844 /*******************************************************************************
845 *
846 * Function SDP_GetNumDiRecords
847 *
848 * Description Searches specified database for DI records
849 *
850 * Returns number of DI records found
851 *
852 ******************************************************************************/
SDP_GetNumDiRecords(tSDP_DISCOVERY_DB * p_db)853 uint8_t SDP_GetNumDiRecords(tSDP_DISCOVERY_DB* p_db) {
854 uint8_t num_records = 0;
855 tSDP_DISC_REC* p_curr_record = NULL;
856
857 do {
858 p_curr_record = SDP_FindServiceInDb(p_db, UUID_SERVCLASS_PNP_INFORMATION,
859 p_curr_record);
860 if (p_curr_record) num_records++;
861 } while (p_curr_record);
862
863 return num_records;
864 }
865
866 /*******************************************************************************
867 *
868 * Function SDP_AttrStringCopy
869 *
870 * Description This function copy given attribute to specified buffer as a
871 * string
872 *
873 * Returns none
874 *
875 ******************************************************************************/
SDP_AttrStringCopy(char * dst,tSDP_DISC_ATTR * p_attr,uint16_t dst_size)876 static void SDP_AttrStringCopy(char* dst, tSDP_DISC_ATTR* p_attr,
877 uint16_t dst_size) {
878 if (dst == NULL) return;
879 if (p_attr) {
880 uint16_t len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
881 if (len > dst_size - 1) {
882 len = dst_size - 1;
883 }
884 memcpy(dst, (char*)p_attr->attr_value.v.array, len);
885 dst[len] = '\0';
886 } else {
887 dst[0] = '\0';
888 }
889 }
890
891 /*******************************************************************************
892 *
893 * Function SDP_GetDiRecord
894 *
895 * Description This function retrieves a remote device's DI record from
896 * the specified database.
897 *
898 * Returns SDP_SUCCESS if record retrieved, else error
899 *
900 ******************************************************************************/
SDP_GetDiRecord(uint8_t get_record_index,tSDP_DI_GET_RECORD * p_device_info,tSDP_DISCOVERY_DB * p_db)901 uint16_t SDP_GetDiRecord(uint8_t get_record_index,
902 tSDP_DI_GET_RECORD* p_device_info,
903 tSDP_DISCOVERY_DB* p_db) {
904 uint16_t result = SDP_NO_DI_RECORD_FOUND;
905 uint8_t curr_record_index = 1;
906
907 tSDP_DISC_REC* p_curr_record = NULL;
908
909 /* find the requested SDP record in the discovery database */
910 do {
911 p_curr_record = SDP_FindServiceInDb(p_db, UUID_SERVCLASS_PNP_INFORMATION,
912 p_curr_record);
913 if (p_curr_record) {
914 if (curr_record_index++ == get_record_index) {
915 result = SDP_SUCCESS;
916 break;
917 }
918 }
919 } while (p_curr_record);
920
921 if (result == SDP_SUCCESS) {
922 /* copy the information from the SDP record to the DI record */
923 tSDP_DISC_ATTR* p_curr_attr = NULL;
924
925 /* ClientExecutableURL is optional */
926 p_curr_attr = SDP_FindAttributeInRec(p_curr_record, ATTR_ID_CLIENT_EXE_URL);
927 SDP_AttrStringCopy(p_device_info->rec.client_executable_url, p_curr_attr,
928 SDP_MAX_ATTR_LEN);
929
930 /* Service Description is optional */
931 p_curr_attr =
932 SDP_FindAttributeInRec(p_curr_record, ATTR_ID_SERVICE_DESCRIPTION);
933 SDP_AttrStringCopy(p_device_info->rec.service_description, p_curr_attr,
934 SDP_MAX_ATTR_LEN);
935
936 /* DocumentationURL is optional */
937 p_curr_attr =
938 SDP_FindAttributeInRec(p_curr_record, ATTR_ID_DOCUMENTATION_URL);
939 SDP_AttrStringCopy(p_device_info->rec.documentation_url, p_curr_attr,
940 SDP_MAX_ATTR_LEN);
941
942 p_curr_attr =
943 SDP_FindAttributeInRec(p_curr_record, ATTR_ID_SPECIFICATION_ID);
944 if (p_curr_attr)
945 p_device_info->spec_id = p_curr_attr->attr_value.v.u16;
946 else
947 result = SDP_ERR_ATTR_NOT_PRESENT;
948
949 p_curr_attr = SDP_FindAttributeInRec(p_curr_record, ATTR_ID_VENDOR_ID);
950 if (p_curr_attr)
951 p_device_info->rec.vendor = p_curr_attr->attr_value.v.u16;
952 else
953 result = SDP_ERR_ATTR_NOT_PRESENT;
954
955 p_curr_attr =
956 SDP_FindAttributeInRec(p_curr_record, ATTR_ID_VENDOR_ID_SOURCE);
957 if (p_curr_attr)
958 p_device_info->rec.vendor_id_source = p_curr_attr->attr_value.v.u16;
959 else
960 result = SDP_ERR_ATTR_NOT_PRESENT;
961
962 p_curr_attr = SDP_FindAttributeInRec(p_curr_record, ATTR_ID_PRODUCT_ID);
963 if (p_curr_attr)
964 p_device_info->rec.product = p_curr_attr->attr_value.v.u16;
965 else
966 result = SDP_ERR_ATTR_NOT_PRESENT;
967
968 p_curr_attr =
969 SDP_FindAttributeInRec(p_curr_record, ATTR_ID_PRODUCT_VERSION);
970 if (p_curr_attr)
971 p_device_info->rec.version = p_curr_attr->attr_value.v.u16;
972 else
973 result = SDP_ERR_ATTR_NOT_PRESENT;
974
975 p_curr_attr = SDP_FindAttributeInRec(p_curr_record, ATTR_ID_PRIMARY_RECORD);
976 if (p_curr_attr)
977 p_device_info->rec.primary_record = (bool)p_curr_attr->attr_value.v.u8;
978 else
979 result = SDP_ERR_ATTR_NOT_PRESENT;
980 }
981
982 return result;
983 }
984
985 /*******************************************************************************
986 * Device Identification (DI) Server Functions
987 ******************************************************************************/
988
989 /*******************************************************************************
990 *
991 * Function SDP_SetLocalDiRecord
992 *
993 * Description This function adds a DI record to the local SDP database.
994 *
995 *
996 *
997 * Returns Returns SDP_SUCCESS if record added successfully, else error
998 *
999 ******************************************************************************/
SDP_SetLocalDiRecord(tSDP_DI_RECORD * p_device_info,uint32_t * p_handle)1000 uint16_t SDP_SetLocalDiRecord(tSDP_DI_RECORD* p_device_info,
1001 uint32_t* p_handle) {
1002 #if (SDP_SERVER_ENABLED == TRUE)
1003 uint16_t result = SDP_SUCCESS;
1004 uint32_t handle;
1005 uint16_t di_uuid = UUID_SERVCLASS_PNP_INFORMATION;
1006 uint16_t di_specid = BLUETOOTH_DI_SPECIFICATION;
1007 uint8_t temp_u16[2];
1008 uint8_t* p_temp;
1009 uint8_t u8;
1010
1011 *p_handle = 0;
1012 if (p_device_info == NULL) return SDP_ILLEGAL_PARAMETER;
1013
1014 /* if record is to be primary record, get handle to replace old primary */
1015 if (p_device_info->primary_record == true &&
1016 sdp_cb.server_db.di_primary_handle)
1017 handle = sdp_cb.server_db.di_primary_handle;
1018 else {
1019 handle = SDP_CreateRecord();
1020 if (handle == 0) return SDP_NO_RESOURCES;
1021 }
1022
1023 *p_handle = handle;
1024
1025 /* build the SDP entry */
1026 /* Add the UUID to the Service Class ID List */
1027 if ((SDP_AddServiceClassIdList(handle, 1, &di_uuid)) == false)
1028 result = SDP_DI_REG_FAILED;
1029
1030 /* mandatory */
1031 if (result == SDP_SUCCESS) {
1032 p_temp = temp_u16;
1033 UINT16_TO_BE_STREAM(p_temp, di_specid);
1034 if (!(SDP_AddAttribute(handle, ATTR_ID_SPECIFICATION_ID, UINT_DESC_TYPE,
1035 sizeof(di_specid), temp_u16)))
1036 result = SDP_DI_REG_FAILED;
1037 }
1038
1039 /* optional - if string is null, do not add attribute */
1040 if (result == SDP_SUCCESS) {
1041 if (p_device_info->client_executable_url[0] != '\0') {
1042 if (!((strlen(p_device_info->client_executable_url) + 1 <=
1043 SDP_MAX_ATTR_LEN) &&
1044 SDP_AddAttribute(
1045 handle, ATTR_ID_CLIENT_EXE_URL, URL_DESC_TYPE,
1046 (uint32_t)(strlen(p_device_info->client_executable_url) + 1),
1047 (uint8_t*)p_device_info->client_executable_url)))
1048 result = SDP_DI_REG_FAILED;
1049 }
1050 }
1051
1052 /* optional - if string is null, do not add attribute */
1053 if (result == SDP_SUCCESS) {
1054 if (p_device_info->service_description[0] != '\0') {
1055 if (!((strlen(p_device_info->service_description) + 1 <=
1056 SDP_MAX_ATTR_LEN) &&
1057 SDP_AddAttribute(
1058 handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
1059 (uint32_t)(strlen(p_device_info->service_description) + 1),
1060 (uint8_t*)p_device_info->service_description)))
1061 result = SDP_DI_REG_FAILED;
1062 }
1063 }
1064
1065 /* optional - if string is null, do not add attribute */
1066 if (result == SDP_SUCCESS) {
1067 if (p_device_info->documentation_url[0] != '\0') {
1068 if (!((strlen(p_device_info->documentation_url) + 1 <=
1069 SDP_MAX_ATTR_LEN) &&
1070 SDP_AddAttribute(
1071 handle, ATTR_ID_DOCUMENTATION_URL, URL_DESC_TYPE,
1072 (uint32_t)(strlen(p_device_info->documentation_url) + 1),
1073 (uint8_t*)p_device_info->documentation_url)))
1074 result = SDP_DI_REG_FAILED;
1075 }
1076 }
1077
1078 /* mandatory */
1079 if (result == SDP_SUCCESS) {
1080 p_temp = temp_u16;
1081 UINT16_TO_BE_STREAM(p_temp, p_device_info->vendor);
1082 if (!(SDP_AddAttribute(handle, ATTR_ID_VENDOR_ID, UINT_DESC_TYPE,
1083 sizeof(p_device_info->vendor), temp_u16)))
1084 result = SDP_DI_REG_FAILED;
1085 }
1086
1087 /* mandatory */
1088 if (result == SDP_SUCCESS) {
1089 p_temp = temp_u16;
1090 UINT16_TO_BE_STREAM(p_temp, p_device_info->product);
1091 if (!(SDP_AddAttribute(handle, ATTR_ID_PRODUCT_ID, UINT_DESC_TYPE,
1092 sizeof(p_device_info->product), temp_u16)))
1093 result = SDP_DI_REG_FAILED;
1094 }
1095
1096 /* mandatory */
1097 if (result == SDP_SUCCESS) {
1098 p_temp = temp_u16;
1099 UINT16_TO_BE_STREAM(p_temp, p_device_info->version);
1100 if (!(SDP_AddAttribute(handle, ATTR_ID_PRODUCT_VERSION, UINT_DESC_TYPE,
1101 sizeof(p_device_info->version), temp_u16)))
1102 result = SDP_DI_REG_FAILED;
1103 }
1104
1105 /* mandatory */
1106 if (result == SDP_SUCCESS) {
1107 u8 = (uint8_t)p_device_info->primary_record;
1108 if (!(SDP_AddAttribute(handle, ATTR_ID_PRIMARY_RECORD, BOOLEAN_DESC_TYPE, 1,
1109 &u8)))
1110 result = SDP_DI_REG_FAILED;
1111 }
1112
1113 /* mandatory */
1114 if (result == SDP_SUCCESS) {
1115 p_temp = temp_u16;
1116 UINT16_TO_BE_STREAM(p_temp, p_device_info->vendor_id_source);
1117 if (!(SDP_AddAttribute(handle, ATTR_ID_VENDOR_ID_SOURCE, UINT_DESC_TYPE,
1118 sizeof(p_device_info->vendor_id_source), temp_u16)))
1119 result = SDP_DI_REG_FAILED;
1120 }
1121
1122 if (result != SDP_SUCCESS)
1123 SDP_DeleteRecord(handle);
1124 else if (p_device_info->primary_record == true)
1125 sdp_cb.server_db.di_primary_handle = handle;
1126
1127 return result;
1128 #else /* SDP_SERVER_ENABLED is FALSE */
1129 return SDP_DI_REG_FAILED;
1130 #endif /* if SDP_SERVER_ENABLED */
1131 }
1132
1133 /*******************************************************************************
1134 *
1135 * Function SDP_SetTraceLevel
1136 *
1137 * Description This function sets the trace level for SDP. If called with
1138 * a value of 0xFF, it simply reads the current trace level.
1139 *
1140 * Returns the new (current) trace level
1141 *
1142 ******************************************************************************/
SDP_SetTraceLevel(uint8_t new_level)1143 uint8_t SDP_SetTraceLevel(uint8_t new_level) {
1144 if (new_level != 0xFF) sdp_cb.trace_level = new_level;
1145
1146 return (sdp_cb.trace_level);
1147 }
1148