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 <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28
29 #include "bt_target.h"
30 #include "gki.h"
31 #include "l2cdefs.h"
32 #include "hcidefs.h"
33 #include "hcimsgs.h"
34
35 #include "sdp_api.h"
36 #include "sdpint.h"
37 #include "btu.h"
38
39 #include <cutils/log.h>
40 #define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
41 #define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
42 #define error(fmt, ...) LOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__)
43 #define asrt(s) if(!(s)) LOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
44
45
46 /**********************************************************************
47 ** C L I E N T F U N C T I O N P R O T O T Y P E S *
48 ***********************************************************************/
49
50 /*******************************************************************************
51 **
52 ** Function SDP_InitDiscoveryDb
53 **
54 ** Description This function is called to initialize a discovery database.
55 **
56 ** Parameters: p_db - (input) address of an area of memory where the
57 ** discovery database is managed.
58 ** len - (input) size (in bytes) of the memory
59 ** NOTE: This must be larger than sizeof(tSDP_DISCOVERY_DB)
60 ** num_uuid - (input) number of UUID filters applied
61 ** p_uuid_list - (input) list of UUID filters
62 ** num_attr - (input) number of attribute filters applied
63 ** p_attr_list - (input) list of attribute filters
64 **
65 **
66 ** Returns BOOLEAN
67 ** TRUE if successful
68 ** FALSE if one or more parameters are bad
69 **
70 *******************************************************************************/
SDP_InitDiscoveryDb(tSDP_DISCOVERY_DB * p_db,UINT32 len,UINT16 num_uuid,tSDP_UUID * p_uuid_list,UINT16 num_attr,UINT16 * p_attr_list)71 BOOLEAN SDP_InitDiscoveryDb (tSDP_DISCOVERY_DB *p_db, UINT32 len, UINT16 num_uuid,
72 tSDP_UUID *p_uuid_list, UINT16 num_attr, UINT16 *p_attr_list)
73 {
74 #if SDP_CLIENT_ENABLED == TRUE
75 UINT16 xx;
76
77 /* verify the parameters */
78 if (p_db == NULL || (sizeof (tSDP_DISCOVERY_DB) > len) ||
79 num_attr > SDP_MAX_ATTR_FILTERS || num_uuid > SDP_MAX_UUID_FILTERS)
80 {
81 SDP_TRACE_ERROR4("SDP_InitDiscoveryDb Illegal param: p_db 0x%x, len %d, num_uuid %d, num_attr %d",
82 (UINT32)p_db, len, num_uuid, num_attr);
83
84 return(FALSE);
85 }
86
87 memset (p_db, 0, (size_t)len);
88
89 p_db->mem_size = len - sizeof (tSDP_DISCOVERY_DB);
90 p_db->mem_free = p_db->mem_size;
91 p_db->p_first_rec = NULL;
92 p_db->p_free_mem = (UINT8 *)(p_db + 1);
93
94 for (xx = 0; xx < num_uuid; xx++)
95 p_db->uuid_filters[xx] = *p_uuid_list++;
96
97 p_db->num_uuid_filters = num_uuid;
98
99 for (xx = 0; xx < num_attr; xx++)
100 p_db->attr_filters[xx] = *p_attr_list++;
101
102 /* sort attributes */
103 sdpu_sort_attr_list( num_attr, p_db );
104
105 p_db->num_attr_filters = num_attr;
106 #endif
107 return(TRUE);
108 }
109
110
111
112 /*******************************************************************************
113 **
114 ** Function SDP_CancelServiceSearch
115 **
116 ** Description This function cancels an active query to an SDP server.
117 **
118 ** Returns TRUE if discovery cancelled, FALSE if a matching activity is not found.
119 **
120 *******************************************************************************/
SDP_CancelServiceSearch(tSDP_DISCOVERY_DB * p_db)121 BOOLEAN SDP_CancelServiceSearch (tSDP_DISCOVERY_DB *p_db)
122 {
123 #if SDP_CLIENT_ENABLED == TRUE
124 tCONN_CB *p_ccb = sdpu_find_ccb_by_db (p_db);
125 if (!p_ccb)
126 return(FALSE);
127
128 sdp_disconnect (p_ccb, SDP_CANCEL);
129 p_ccb->disc_state = SDP_DISC_WAIT_CANCEL;
130 #endif
131 return(TRUE);
132 }
133
134
135
136 /*******************************************************************************
137 **
138 ** Function SDP_ServiceSearchRequest
139 **
140 ** Description This function queries an SDP server for information.
141 **
142 ** Returns TRUE if discovery started, FALSE if failed.
143 **
144 *******************************************************************************/
SDP_ServiceSearchRequest(UINT8 * p_bd_addr,tSDP_DISCOVERY_DB * p_db,tSDP_DISC_CMPL_CB * p_cb)145 BOOLEAN SDP_ServiceSearchRequest (UINT8 *p_bd_addr, tSDP_DISCOVERY_DB *p_db,
146 tSDP_DISC_CMPL_CB *p_cb)
147 {
148 #if SDP_CLIENT_ENABLED == TRUE
149 tCONN_CB *p_ccb;
150
151 /* Specific BD address */
152 p_ccb = sdp_conn_originate (p_bd_addr);
153
154 if (!p_ccb)
155 return(FALSE);
156
157 p_ccb->disc_state = SDP_DISC_WAIT_CONN;
158 p_ccb->p_db = p_db;
159 p_ccb->p_cb = p_cb;
160
161 return(TRUE);
162 #else
163 return(FALSE);
164 #endif
165 }
166
167
168 /*******************************************************************************
169 **
170 ** Function SDP_ServiceSearchAttributeRequest
171 **
172 ** Description This function queries an SDP server for information.
173 **
174 ** The difference between this API function and the function
175 ** SDP_ServiceSearchRequest is that this one does a
176 ** combined ServiceSearchAttributeRequest SDP function.
177 ** (This is for Unplug Testing)
178 **
179 ** Returns TRUE if discovery started, FALSE if failed.
180 **
181 *******************************************************************************/
SDP_ServiceSearchAttributeRequest(UINT8 * p_bd_addr,tSDP_DISCOVERY_DB * p_db,tSDP_DISC_CMPL_CB * p_cb)182 BOOLEAN SDP_ServiceSearchAttributeRequest (UINT8 *p_bd_addr, tSDP_DISCOVERY_DB *p_db,
183 tSDP_DISC_CMPL_CB *p_cb)
184 {
185 #if SDP_CLIENT_ENABLED == TRUE
186 tCONN_CB *p_ccb;
187
188 /* Specific BD address */
189 p_ccb = sdp_conn_originate (p_bd_addr);
190
191 if (!p_ccb)
192 return(FALSE);
193
194 p_ccb->disc_state = SDP_DISC_WAIT_CONN;
195 p_ccb->p_db = p_db;
196 p_ccb->p_cb = p_cb;
197
198 p_ccb->is_attr_search = TRUE;
199
200 return(TRUE);
201 #else
202 return(FALSE);
203 #endif
204 }
205 /*******************************************************************************
206 **
207 ** Function SDP_ServiceSearchAttributeRequest2
208 **
209 ** Description This function queries an SDP server for information.
210 **
211 ** The difference between this API function and the function
212 ** SDP_ServiceSearchRequest is that this one does a
213 ** combined ServiceSearchAttributeRequest SDP function.
214 ** (This is for Unplug Testing)
215 **
216 ** Returns TRUE if discovery started, FALSE if failed.
217 **
218 *******************************************************************************/
SDP_ServiceSearchAttributeRequest2(UINT8 * p_bd_addr,tSDP_DISCOVERY_DB * p_db,tSDP_DISC_CMPL_CB2 * p_cb2,void * user_data)219 BOOLEAN SDP_ServiceSearchAttributeRequest2 (UINT8 *p_bd_addr, tSDP_DISCOVERY_DB *p_db,
220 tSDP_DISC_CMPL_CB2 *p_cb2, void * user_data)
221 {
222 #if SDP_CLIENT_ENABLED == TRUE
223 tCONN_CB *p_ccb;
224
225 /* Specific BD address */
226 p_ccb = sdp_conn_originate (p_bd_addr);
227
228 if (!p_ccb)
229 return(FALSE);
230
231 p_ccb->disc_state = SDP_DISC_WAIT_CONN;
232 p_ccb->p_db = p_db;
233 p_ccb->p_cb2 = p_cb2;
234
235 p_ccb->is_attr_search = TRUE;
236 p_ccb->user_data = user_data;
237
238 return(TRUE);
239 #else
240 return(FALSE);
241 #endif
242 }
243
244 #if SDP_CLIENT_ENABLED == TRUE
SDP_SetIdleTimeout(BD_ADDR addr,UINT16 timeout)245 void SDP_SetIdleTimeout (BD_ADDR addr, UINT16 timeout)
246 {
247 }
248 #endif
249
250 /*******************************************************************************
251 **
252 ** Function SDP_FindAttributeInDb
253 **
254 ** Description This function queries an SDP database for a specific attribute.
255 ** If the p_start_rec pointer is NULL, it looks from the beginning
256 ** of the database, else it continues from the next record after
257 ** p_start_rec.
258 **
259 ** Returns Pointer to matching record, or NULL
260 **
261 *******************************************************************************/
SDP_FindAttributeInDb(tSDP_DISCOVERY_DB * p_db,UINT16 attr_id,tSDP_DISC_REC * p_start_rec)262 tSDP_DISC_REC *SDP_FindAttributeInDb (tSDP_DISCOVERY_DB *p_db, UINT16 attr_id,
263 tSDP_DISC_REC *p_start_rec)
264 {
265 #if SDP_CLIENT_ENABLED == TRUE
266 tSDP_DISC_REC *p_rec;
267 tSDP_DISC_ATTR *p_attr;
268
269 /* Must have a valid database */
270 if (p_db == NULL)
271 return(NULL);
272
273 if (!p_start_rec)
274 p_rec = p_db->p_first_rec;
275 else
276 p_rec = p_start_rec->p_next_rec;
277
278 while (p_rec)
279 {
280 p_attr = p_rec->p_first_attr;
281 while (p_attr)
282 {
283 if (p_attr->attr_id == attr_id)
284 return(p_rec);
285
286 p_attr = p_attr->p_next_attr;
287 }
288
289 p_rec = p_rec->p_next_rec;
290 }
291 #endif
292 /* If here, no matching attribute found */
293 return(NULL);
294 }
295
296
297 /*******************************************************************************
298 **
299 ** Function SDP_FindAttributeInRec
300 **
301 ** Description This function searches an SDP discovery record for a specific
302 ** attribute.
303 **
304 ** Returns Pointer to matching attribute entry, or NULL
305 **
306 *******************************************************************************/
SDP_FindAttributeInRec(tSDP_DISC_REC * p_rec,UINT16 attr_id)307 tSDP_DISC_ATTR *SDP_FindAttributeInRec (tSDP_DISC_REC *p_rec, UINT16 attr_id)
308 {
309 #if SDP_CLIENT_ENABLED == TRUE
310 tSDP_DISC_ATTR *p_attr;
311
312 p_attr = p_rec->p_first_attr;
313 while (p_attr)
314 {
315 if (p_attr->attr_id == attr_id)
316 return(p_attr);
317
318 p_attr = p_attr->p_next_attr;
319 }
320 #endif
321 /* If here, no matching attribute found */
322 return(NULL);
323 }
324
325 /*******************************************************************************
326 **
327 ** Function SDP_FindServiceUUIDInRec
328 **
329 ** Description This function is called to read the service UUID within a record
330 ** if there is any.
331 **
332 ** Parameters: p_rec - pointer to a SDP record.
333 ** p_uuid - output parameter to save the UUID found.
334 **
335 ** Returns TRUE if found, otherwise FALSE.
336 **
337 *******************************************************************************/
SDP_FindServiceUUIDInRec(tSDP_DISC_REC * p_rec,tBT_UUID * p_uuid)338 BOOLEAN SDP_FindServiceUUIDInRec(tSDP_DISC_REC *p_rec, tBT_UUID * p_uuid)
339 {
340 #if SDP_CLIENT_ENABLED == TRUE
341 tSDP_DISC_ATTR *p_attr, *p_sattr, *p_extra_sattr;
342
343 p_attr = p_rec->p_first_attr;
344
345 while (p_attr)
346 {
347 if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST)
348 && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE))
349 {
350 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
351 {
352 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE)
353 {
354 /* only support 16 bits UUID for now */
355 if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2)
356 {
357 p_uuid->len = 2;
358 p_uuid->uu.uuid16 = p_sattr->attr_value.v.u16;
359 }
360 return(TRUE);
361 }
362
363 /* Checking for Toyota G Block Car Kit:
364 ** This car kit puts an extra data element sequence
365 ** where the UUID is suppose to be!!!
366 */
367 else
368 {
369 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)
370 {
371 /* Look through data element sequence until no more UUIDs */
372 for (p_extra_sattr = p_sattr->attr_value.v.p_sub_attr; p_extra_sattr; p_extra_sattr = p_extra_sattr->p_next_attr)
373 {
374 /* Increment past this to see if the next attribut is UUID */
375 if ((SDP_DISC_ATTR_TYPE(p_extra_sattr->attr_len_type) == UUID_DESC_TYPE)
376 /* only support 16 bits UUID for now */
377 && (SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2))
378 {
379 p_uuid->len = 2;
380 p_uuid->uu.uuid16 = p_extra_sattr->attr_value.v.u16;
381 return(TRUE);
382 }
383 }
384 }
385 }
386 }
387 break;
388 }
389 else if (p_attr->attr_id == ATTR_ID_SERVICE_ID)
390 {
391 if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE)
392 /* only support 16 bits UUID for now */
393 && (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2))
394 {
395 p_uuid->len = 2;
396 p_uuid->uu.uuid16 = p_attr->attr_value.v.u16;
397 return(TRUE);
398 }
399 }
400 p_attr = p_attr->p_next_attr;
401 }
402 return FALSE;
403 #endif
404 }
405
406 /*******************************************************************************
407 **
408 ** Function SDP_FindServiceUUIDInRec_128bit
409 **
410 ** Description This function is called to read the 128-bit service UUID within a record
411 ** if there is any.
412 **
413 ** Parameters: p_rec - pointer to a SDP record.
414 ** p_uuid - output parameter to save the UUID found.
415 **
416 ** Returns TRUE if found, otherwise FALSE.
417 **
418 *******************************************************************************/
SDP_FindServiceUUIDInRec_128bit(tSDP_DISC_REC * p_rec,tBT_UUID * p_uuid)419 BOOLEAN SDP_FindServiceUUIDInRec_128bit(tSDP_DISC_REC *p_rec, tBT_UUID * p_uuid)
420 {
421 #if SDP_CLIENT_ENABLED == TRUE
422 tSDP_DISC_ATTR *p_attr, *p_sattr, *p_extra_sattr;
423
424 p_attr = p_rec->p_first_attr;
425
426 while (p_attr)
427 {
428 if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST)
429 && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE))
430 {
431 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
432 {
433 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE)
434 {
435 /* only support 128 bits UUID for now */
436 if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 16)
437 {
438 p_uuid->len = 16;
439 memcpy(p_uuid->uu.uuid128, p_sattr->attr_value.v.array, MAX_UUID_SIZE);
440 }
441 return(TRUE);
442 }
443 }
444 break;
445 }
446 else if (p_attr->attr_id == ATTR_ID_SERVICE_ID)
447 {
448 if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE)
449 /* only support 128 bits UUID for now */
450 && (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 16))
451 {
452 p_uuid->len = 16;
453 memcpy(p_uuid->uu.uuid128, p_sattr->attr_value.v.array, MAX_UUID_SIZE);
454 return(TRUE);
455 }
456 }
457 p_attr = p_attr->p_next_attr;
458 }
459 return FALSE;
460 #endif
461 }
462
463 /*******************************************************************************
464 **
465 ** Function SDP_FindServiceInDb
466 **
467 ** Description This function queries an SDP database for a specific service.
468 ** If the p_start_rec pointer is NULL, it looks from the beginning
469 ** of the database, else it continues from the next record after
470 ** p_start_rec.
471 **
472 ** Returns Pointer to record containing service class, or NULL
473 **
474 *******************************************************************************/
SDP_FindServiceInDb(tSDP_DISCOVERY_DB * p_db,UINT16 service_uuid,tSDP_DISC_REC * p_start_rec)475 tSDP_DISC_REC *SDP_FindServiceInDb (tSDP_DISCOVERY_DB *p_db, UINT16 service_uuid, tSDP_DISC_REC *p_start_rec)
476 {
477 #if SDP_CLIENT_ENABLED == TRUE
478 tSDP_DISC_REC *p_rec;
479 tSDP_DISC_ATTR *p_attr, *p_sattr, *p_extra_sattr;
480
481 /* Must have a valid database */
482 if (p_db == NULL)
483 return(NULL);
484
485 if (!p_start_rec)
486 p_rec = p_db->p_first_rec;
487 else
488 p_rec = p_start_rec->p_next_rec;
489
490 while (p_rec)
491 {
492 p_attr = p_rec->p_first_attr;
493 while (p_attr)
494 {
495 if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST)
496 && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE))
497 {
498 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
499 {
500
501 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE)
502 && (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2) ) {
503 printf("SDP_FindServiceInDb - p_sattr value = 0x%x serviceuuid = 0x%x\r\n", p_sattr->attr_value.v.u16, service_uuid);
504 if(service_uuid == UUID_SERVCLASS_HDP_PROFILE)
505 {
506 if( (p_sattr->attr_value.v.u16==UUID_SERVCLASS_HDP_SOURCE) || ( p_sattr->attr_value.v.u16==UUID_SERVCLASS_HDP_SOURCE))
507 {
508 printf("SDP_FindServiceInDb found HDP source or sink\n" );
509 return (p_rec);
510 }
511 }
512
513 }
514
515 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE)
516 && (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2)
517 /* for a specific uuid, or any one */
518 && ((p_sattr->attr_value.v.u16 == service_uuid) || service_uuid == 0))
519 {
520 return(p_rec);
521 }
522
523 /* Checking for Toyota G Block Car Kit:
524 ** This car kit puts an extra data element sequence
525 ** where the UUID is suppose to be!!!
526 */
527 else
528 {
529 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)
530 {
531 /* Look through data element sequence until no more UUIDs */
532 for (p_extra_sattr = p_sattr->attr_value.v.p_sub_attr; p_extra_sattr; p_extra_sattr = p_extra_sattr->p_next_attr)
533 {
534 /* Increment past this to see if the next attribut is UUID */
535 if ((SDP_DISC_ATTR_TYPE(p_extra_sattr->attr_len_type) == UUID_DESC_TYPE)
536 && (SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2)
537 /* for a specific uuid, or any one */
538 && ((p_extra_sattr->attr_value.v.u16 == service_uuid) || (service_uuid == 0)))
539 {
540 return(p_rec);
541 }
542 }
543 }
544 }
545 }
546 break;
547 }
548 else if (p_attr->attr_id == ATTR_ID_SERVICE_ID)
549 {
550 if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE)
551 && (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2))
552 {
553 printf("SDP_FindServiceInDb - p_attr value = 0x%x serviceuuid= 0x%x \r\n", p_attr->attr_value.v.u16, service_uuid);
554 }
555
556 if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE)
557 && (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2)
558 /* find a specific UUID or anyone */
559 && ((p_attr->attr_value.v.u16 == service_uuid) || service_uuid == 0))
560 return(p_rec);
561 }
562
563 p_attr = p_attr->p_next_attr;
564 }
565
566 p_rec = p_rec->p_next_rec;
567 }
568 #endif
569 /* If here, no matching UUID found */
570 return(NULL);
571 }
572
573 /*******************************************************************************
574 **
575 ** Function SDP_FindServiceInDb_128bit
576 **
577 ** Description This function queries an SDP database for a specific service.
578 ** If the p_start_rec pointer is NULL, it looks from the beginning
579 ** of the database, else it continues from the next record after
580 ** p_start_rec.
581 **
582 ** This function is kept separate from SDP_FindServiceInDb since
583 ** that API is expected to return only 16-bit UUIDs
584 **
585 ** Returns Pointer to record containing service class, or NULL
586 **
587 *******************************************************************************/
SDP_FindServiceInDb_128bit(tSDP_DISCOVERY_DB * p_db,tSDP_DISC_REC * p_start_rec)588 tSDP_DISC_REC *SDP_FindServiceInDb_128bit(tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_start_rec)
589 {
590 #if SDP_CLIENT_ENABLED == TRUE
591 tSDP_DISC_REC *p_rec;
592 tSDP_DISC_ATTR *p_attr, *p_sattr, *p_extra_sattr;
593
594 /* Must have a valid database */
595 if (p_db == NULL)
596 return(NULL);
597
598 if (!p_start_rec)
599 p_rec = p_db->p_first_rec;
600 else
601 p_rec = p_start_rec->p_next_rec;
602
603 while (p_rec)
604 {
605 p_attr = p_rec->p_first_attr;
606 while (p_attr)
607 {
608 if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST)
609 && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE))
610 {
611 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
612 {
613 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE)
614 && (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 16))
615 {
616 return(p_rec);
617 }
618 }
619 break;
620 }
621 else if (p_attr->attr_id == ATTR_ID_SERVICE_ID)
622 {
623 if ((SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE)
624 && (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 16))
625 return(p_rec);
626 }
627
628 p_attr = p_attr->p_next_attr;
629 }
630
631 p_rec = p_rec->p_next_rec;
632 }
633 #endif
634 /* If here, no matching UUID found */
635 return(NULL);
636 }
637
638
639 /*******************************************************************************
640 **
641 ** Function SDP_FindServiceUUIDInDb
642 **
643 ** Description This function queries an SDP database for a specific service.
644 ** If the p_start_rec pointer is NULL, it looks from the beginning
645 ** of the database, else it continues from the next record after
646 ** p_start_rec.
647 **
648 ** NOTE the only difference between this function and the previous function
649 ** "SDP_FindServiceInDb()" is that this function takes a tBT_UUID input
650 **
651 ** Returns Pointer to record containing service class, or NULL
652 **
653 *******************************************************************************/
SDP_FindServiceUUIDInDb(tSDP_DISCOVERY_DB * p_db,tBT_UUID * p_uuid,tSDP_DISC_REC * p_start_rec)654 tSDP_DISC_REC *SDP_FindServiceUUIDInDb (tSDP_DISCOVERY_DB *p_db, tBT_UUID *p_uuid, tSDP_DISC_REC *p_start_rec)
655 {
656 #if SDP_CLIENT_ENABLED == TRUE
657 tSDP_DISC_REC *p_rec;
658 tSDP_DISC_ATTR *p_attr, *p_sattr;
659
660 /* Must have a valid database */
661 if (p_db == NULL)
662 return(NULL);
663
664 if (!p_start_rec)
665 p_rec = p_db->p_first_rec;
666 else
667 p_rec = p_start_rec->p_next_rec;
668
669 while (p_rec)
670 {
671 p_attr = p_rec->p_first_attr;
672 while (p_attr)
673 {
674 if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST)
675 && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE))
676 {
677 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
678 {
679 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE)
680 {
681
682 printf("uuid len=%d ", p_uuid->len);
683 if (p_uuid->len == 2)
684 {
685 printf("uuid=0x%x \n", p_uuid->uu.uuid16);
686 }
687 else
688 {
689 printf("\n");
690 }
691
692 if (sdpu_compare_uuid_with_attr (p_uuid, p_sattr))
693 return(p_rec);
694 }
695 }
696 break;
697 }
698 else if (p_attr->attr_id == ATTR_ID_SERVICE_ID)
699 {
700 if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE )
701 {
702 if (sdpu_compare_uuid_with_attr (p_uuid, p_attr))
703 return(p_rec);
704 }
705 }
706
707 p_attr = p_attr->p_next_attr;
708 }
709
710 p_rec = p_rec->p_next_rec;
711 }
712 #endif /* CLIENT_ENABLED == TRUE */
713 /* If here, no matching UUID found */
714 return(NULL);
715 }
716
717 #if SDP_CLIENT_ENABLED == TRUE
718 /*******************************************************************************
719 **
720 ** Function sdp_fill_proto_elem
721 **
722 ** Description This function retrieves the protocol element.
723 **
724 ** Returns TRUE if found, FALSE if not
725 ** If found, the passed protocol list element is filled in.
726 **
727 *******************************************************************************/
sdp_fill_proto_elem(tSDP_DISC_ATTR * p_attr,UINT16 layer_uuid,tSDP_PROTOCOL_ELEM * p_elem)728 static BOOLEAN sdp_fill_proto_elem( tSDP_DISC_ATTR *p_attr, UINT16 layer_uuid,
729 tSDP_PROTOCOL_ELEM *p_elem)
730 {
731 tSDP_DISC_ATTR *p_sattr;
732
733 /* Walk through the protocol descriptor list */
734 for (p_attr = p_attr->attr_value.v.p_sub_attr; p_attr; p_attr = p_attr->p_next_attr)
735 {
736 /* Safety check - each entry should itself be a sequence */
737 if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE)
738 return(FALSE);
739
740 /* Now, see if the entry contains the layer we are interested in */
741 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
742 {
743 /* SDP_TRACE_DEBUG3 ("SDP - p_sattr 0x%x, layer_uuid:0x%x, u16:0x%x####",
744 p_sattr, layer_uuid, p_sattr->attr_value.v.u16); */
745
746 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE)
747 && (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2)
748 && (p_sattr->attr_value.v.u16 == layer_uuid))
749 {
750 /* Bingo. Now fill in the passed element */
751 p_elem->protocol_uuid = layer_uuid;
752 p_elem->num_params = 0;
753
754 /* Store the parameters, if any */
755 for (p_sattr = p_sattr->p_next_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
756 {
757 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) != UINT_DESC_TYPE)
758 break;
759
760 if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2)
761 p_elem->params[p_elem->num_params++] = p_sattr->attr_value.v.u16;
762 else
763 p_elem->params[p_elem->num_params++] = p_sattr->attr_value.v.u8;
764
765 if (p_elem->num_params >= SDP_MAX_PROTOCOL_PARAMS)
766 break;
767 }
768 return(TRUE);
769 }
770 }
771 }
772
773 return(FALSE);
774 }
775 #endif /* CLIENT_ENABLED == TRUE */
776
777 /*******************************************************************************
778 **
779 ** Function SDP_FindProtocolListElemInRec
780 **
781 ** Description This function looks at a specific discovery record for a protocol
782 ** list element.
783 **
784 ** Returns TRUE if found, FALSE if not
785 ** If found, the passed protocol list element is filled in.
786 **
787 *******************************************************************************/
SDP_FindProtocolListElemInRec(tSDP_DISC_REC * p_rec,UINT16 layer_uuid,tSDP_PROTOCOL_ELEM * p_elem)788 BOOLEAN SDP_FindProtocolListElemInRec (tSDP_DISC_REC *p_rec, UINT16 layer_uuid, tSDP_PROTOCOL_ELEM *p_elem)
789 {
790 #if SDP_CLIENT_ENABLED == TRUE
791 tSDP_DISC_ATTR *p_attr;
792
793 p_attr = p_rec->p_first_attr;
794 while (p_attr)
795 {
796 /* Find the protocol descriptor list */
797 if ((p_attr->attr_id == ATTR_ID_PROTOCOL_DESC_LIST)
798 && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE))
799 {
800 return sdp_fill_proto_elem(p_attr, layer_uuid, p_elem);
801 }
802 p_attr = p_attr->p_next_attr;
803 }
804 #endif
805 /* If here, no match found */
806 return(FALSE);
807 }
808
809
810 /*******************************************************************************
811 **
812 ** Function SDP_FindAddProtoListsElemInRec
813 **
814 ** Description This function looks at a specific discovery record for a protocol
815 ** list element.
816 **
817 ** Returns TRUE if found, FALSE if not
818 ** If found, the passed protocol list element is filled in.
819 **
820 *******************************************************************************/
SDP_FindAddProtoListsElemInRec(tSDP_DISC_REC * p_rec,UINT16 layer_uuid,tSDP_PROTOCOL_ELEM * p_elem)821 BOOLEAN SDP_FindAddProtoListsElemInRec (tSDP_DISC_REC *p_rec, UINT16 layer_uuid, tSDP_PROTOCOL_ELEM *p_elem)
822 {
823 #if SDP_CLIENT_ENABLED == TRUE
824 tSDP_DISC_ATTR *p_attr, *p_sattr;
825 BOOLEAN ret = FALSE;
826
827 p_attr = p_rec->p_first_attr;
828 while (p_attr)
829 {
830 /* Find the additional protocol descriptor list attribute */
831 if ((p_attr->attr_id == ATTR_ID_ADDITION_PROTO_DESC_LISTS)
832 && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE))
833 {
834 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
835 {
836 /* Safety check - each entry should itself be a sequence */
837 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)
838 {
839 if ( (ret = sdp_fill_proto_elem(p_sattr, layer_uuid, p_elem)) == TRUE)
840 break;
841 }
842 }
843 return ret;
844 }
845 p_attr = p_attr->p_next_attr;
846 }
847 #endif
848 /* If here, no match found */
849 return(FALSE);
850 }
851
852
853 /*******************************************************************************
854 **
855 ** Function SDP_FindProfileVersionInRec
856 **
857 ** Description This function looks at a specific discovery record for the
858 ** Profile list descriptor, and pulls out the version number.
859 ** The version number consists of an 8-bit major version and
860 ** an 8-bit minor version.
861 **
862 ** Returns TRUE if found, FALSE if not
863 ** If found, the major and minor version numbers that were passed
864 ** in are filled in.
865 **
866 *******************************************************************************/
SDP_FindProfileVersionInRec(tSDP_DISC_REC * p_rec,UINT16 profile_uuid,UINT16 * p_version)867 BOOLEAN SDP_FindProfileVersionInRec (tSDP_DISC_REC *p_rec, UINT16 profile_uuid, UINT16 *p_version)
868 {
869 #if SDP_CLIENT_ENABLED == TRUE
870 tSDP_DISC_ATTR *p_attr, *p_sattr;
871
872 p_attr = p_rec->p_first_attr;
873 while (p_attr)
874 {
875 /* Find the profile descriptor list */
876 if ((p_attr->attr_id == ATTR_ID_BT_PROFILE_DESC_LIST)
877 && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE))
878 {
879 /* Walk through the protocol descriptor list */
880 for (p_attr = p_attr->attr_value.v.p_sub_attr; p_attr; p_attr = p_attr->p_next_attr)
881 {
882 /* Safety check - each entry should itself be a sequence */
883 if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE)
884 return(FALSE);
885
886 /* Now, see if the entry contains the profile UUID we are interested in */
887 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
888 {
889 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE)
890 && (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2) /* <- This is bytes, not size code! */
891 && (p_sattr->attr_value.v.u16 == profile_uuid))
892 {
893 /* Now fill in the major and minor numbers */
894 /* if the attribute matches the description for version (type UINT, size 2 bytes) */
895 p_sattr = p_sattr->p_next_attr;
896
897 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UINT_DESC_TYPE) &&
898 (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2))
899 {
900 /* The high order 8 bits is the major number, low order is the minor number (big endian) */
901 *p_version = p_sattr->attr_value.v.u16;
902
903 return(TRUE);
904 }
905 else
906 return(FALSE); /* The type and/or size was not valid for the profile list version */
907 }
908 }
909 }
910
911 return(FALSE);
912 }
913 p_attr = p_attr->p_next_attr;
914 }
915 #endif /* CLIENT_ENABLED == TRUE */
916
917 /* If here, no match found */
918 return(FALSE);
919 }
920
921 /*******************************************************************************
922 ** Device Identification (DI) Client Functions
923 *******************************************************************************/
924
925 /*******************************************************************************
926 **
927 ** Function SDP_DiDiscover
928 **
929 ** Description This function queries a remote device for DI information.
930 **
931 ** Returns SDP_SUCCESS if query started successfully, else error
932 **
933 *******************************************************************************/
SDP_DiDiscover(BD_ADDR remote_device,tSDP_DISCOVERY_DB * p_db,UINT32 len,tSDP_DISC_CMPL_CB * p_cb)934 UINT16 SDP_DiDiscover( BD_ADDR remote_device, tSDP_DISCOVERY_DB *p_db,
935 UINT32 len, tSDP_DISC_CMPL_CB *p_cb )
936 {
937 #if SDP_CLIENT_ENABLED == TRUE
938 UINT16 result = SDP_DI_DISC_FAILED;
939 UINT16 num_uuids = 1;
940 UINT16 di_uuid = UUID_SERVCLASS_PNP_INFORMATION;
941
942 /* build uuid for db init */
943 tSDP_UUID init_uuid;
944 init_uuid.len = 2;
945 init_uuid.uu.uuid16 = di_uuid;
946
947 if ( SDP_InitDiscoveryDb(p_db, len, num_uuids, &init_uuid, 0, NULL) )
948 if ( SDP_ServiceSearchRequest(remote_device, p_db, p_cb) )
949 result = SDP_SUCCESS;
950
951 return result;
952 #else
953 return SDP_DI_DISC_FAILED;
954 #endif
955 }
956
957 /*******************************************************************************
958 **
959 ** Function SDP_GetNumDiRecords
960 **
961 ** Description Searches specified database for DI records
962 **
963 ** Returns number of DI records found
964 **
965 *******************************************************************************/
SDP_GetNumDiRecords(tSDP_DISCOVERY_DB * p_db)966 UINT8 SDP_GetNumDiRecords( tSDP_DISCOVERY_DB *p_db )
967 {
968 #if SDP_CLIENT_ENABLED == TRUE
969 UINT8 num_records = 0;
970 tSDP_DISC_REC *p_curr_record = NULL;
971
972 do
973 {
974 p_curr_record = SDP_FindServiceInDb( p_db, UUID_SERVCLASS_PNP_INFORMATION,
975 p_curr_record );
976 if ( p_curr_record )
977 num_records++;
978 }while ( p_curr_record );
979
980 return num_records;
981 #else
982 return 0;
983 #endif
984 }
985
986 /*******************************************************************************
987 **
988 ** Function SDP_GetDiRecord
989 **
990 ** Description This function retrieves a remote device's DI record from
991 ** the specified database.
992 **
993 ** Returns SDP_SUCCESS if record retrieved, else error
994 **
995 *******************************************************************************/
SDP_GetDiRecord(UINT8 get_record_index,tSDP_DI_GET_RECORD * p_device_info,tSDP_DISCOVERY_DB * p_db)996 UINT16 SDP_GetDiRecord( UINT8 get_record_index, tSDP_DI_GET_RECORD *p_device_info,
997 tSDP_DISCOVERY_DB *p_db )
998 {
999 #if SDP_CLIENT_ENABLED == TRUE
1000 UINT16 result = SDP_NO_DI_RECORD_FOUND;
1001 UINT8 curr_record_index = 1;
1002
1003 tSDP_DISC_REC *p_curr_record = NULL;
1004
1005 /* find the requested SDP record in the discovery database */
1006 do
1007 {
1008 p_curr_record = SDP_FindServiceInDb( p_db, UUID_SERVCLASS_PNP_INFORMATION,
1009 p_curr_record );
1010 if ( p_curr_record )
1011 {
1012 if ( curr_record_index++ == get_record_index )
1013 {
1014 result = SDP_SUCCESS;
1015 break;
1016 }
1017 }
1018 }while ( p_curr_record );
1019
1020 if ( result == SDP_SUCCESS )
1021 {
1022 /* copy the information from the SDP record to the DI record */
1023 tSDP_DISC_ATTR *p_curr_attr = NULL;
1024
1025 /* ClientExecutableURL is optional */
1026 p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_CLIENT_EXE_URL );
1027 if ( p_curr_attr )
1028 BCM_STRNCPY_S( p_device_info->rec.client_executable_url, sizeof(p_device_info->rec.client_executable_url),
1029 (char *)p_curr_attr->attr_value.v.array, SDP_MAX_ATTR_LEN );
1030 else
1031 p_device_info->rec.client_executable_url[0] = '\0';
1032
1033 /* Service Description is optional */
1034 p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_SERVICE_DESCRIPTION );
1035 if ( p_curr_attr )
1036 BCM_STRNCPY_S( p_device_info->rec.service_description, sizeof(p_device_info->rec.service_description),
1037 (char *)p_curr_attr->attr_value.v.array, SDP_MAX_ATTR_LEN );
1038 else
1039 p_device_info->rec.service_description[0] = '\0';
1040
1041 /* DocumentationURL is optional */
1042 p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_DOCUMENTATION_URL );
1043 if ( p_curr_attr )
1044 BCM_STRNCPY_S( p_device_info->rec.documentation_url, sizeof(p_device_info->rec.documentation_url),
1045 (char *)p_curr_attr->attr_value.v.array, SDP_MAX_ATTR_LEN );
1046 else
1047 p_device_info->rec.documentation_url[0] = '\0';
1048
1049 p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_SPECIFICATION_ID );
1050 if ( p_curr_attr )
1051 p_device_info->spec_id = p_curr_attr->attr_value.v.u16;
1052 else
1053 result = SDP_ERR_ATTR_NOT_PRESENT;
1054
1055 p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_VENDOR_ID );
1056 if ( p_curr_attr )
1057 p_device_info->rec.vendor = p_curr_attr->attr_value.v.u16;
1058 else
1059 result = SDP_ERR_ATTR_NOT_PRESENT;
1060
1061 p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_VENDOR_ID_SOURCE );
1062 if ( p_curr_attr )
1063 p_device_info->rec.vendor_id_source = p_curr_attr->attr_value.v.u16;
1064 else
1065 result = SDP_ERR_ATTR_NOT_PRESENT;
1066
1067 p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_PRODUCT_ID );
1068 if ( p_curr_attr )
1069 p_device_info->rec.product = p_curr_attr->attr_value.v.u16;
1070 else
1071 result = SDP_ERR_ATTR_NOT_PRESENT;
1072
1073 p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_PRODUCT_VERSION );
1074 if ( p_curr_attr )
1075 p_device_info->rec.version = p_curr_attr->attr_value.v.u16;
1076 else
1077 result = SDP_ERR_ATTR_NOT_PRESENT;
1078
1079 p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_PRIMARY_RECORD );
1080 if ( p_curr_attr )
1081 p_device_info->rec.primary_record = (BOOLEAN)p_curr_attr->attr_value.v.u8;
1082 else
1083 result = SDP_ERR_ATTR_NOT_PRESENT;
1084 }
1085
1086 return result;
1087 #else /* SDP_CLIENT_ENABLED is FALSE */
1088 return SDP_NO_DI_RECORD_FOUND;
1089 #endif
1090 }
1091
1092 /*******************************************************************************
1093 ** Device Identification (DI) Server Functions
1094 *******************************************************************************/
1095
1096 /*******************************************************************************
1097 **
1098 ** Function SDP_SetLocalDiRecord
1099 **
1100 ** Description This function adds a DI record to the local SDP database.
1101 **
1102 **
1103 **
1104 ** Returns Returns SDP_SUCCESS if record added successfully, else error
1105 **
1106 *******************************************************************************/
SDP_SetLocalDiRecord(tSDP_DI_RECORD * p_device_info,UINT32 * p_handle)1107 UINT16 SDP_SetLocalDiRecord( tSDP_DI_RECORD *p_device_info, UINT32 *p_handle )
1108 {
1109 #if SDP_SERVER_ENABLED == TRUE
1110 UINT16 result = SDP_SUCCESS;
1111 UINT32 handle;
1112 UINT16 di_uuid = UUID_SERVCLASS_PNP_INFORMATION;
1113 UINT16 di_specid = BLUETOOTH_DI_SPECIFICATION;
1114 UINT8 temp_u16[2];
1115 UINT8 *p_temp;
1116 UINT8 u8;
1117
1118 *p_handle = 0;
1119 if ( p_device_info == NULL )
1120 return SDP_ILLEGAL_PARAMETER;
1121
1122 /* if record is to be primary record, get handle to replace old primary */
1123 if ( p_device_info->primary_record == TRUE && sdp_cb.server_db.di_primary_handle )
1124 handle = sdp_cb.server_db.di_primary_handle;
1125 else
1126 {
1127 if ( (handle = SDP_CreateRecord()) == 0 )
1128 return SDP_NO_RESOURCES;
1129 }
1130
1131 *p_handle = handle;
1132
1133 /* build the SDP entry */
1134 /* Add the UUID to the Service Class ID List */
1135 if ((SDP_AddServiceClassIdList(handle, 1, &di_uuid)) == FALSE)
1136 result = SDP_DI_REG_FAILED;
1137
1138 /* mandatory */
1139 if ( result == SDP_SUCCESS)
1140 {
1141 p_temp = temp_u16;
1142 UINT16_TO_BE_STREAM(p_temp, di_specid);
1143 if ( !(SDP_AddAttribute(handle, ATTR_ID_SPECIFICATION_ID,
1144 UINT_DESC_TYPE, sizeof(di_specid),
1145 temp_u16)) )
1146 result = SDP_DI_REG_FAILED;
1147 }
1148
1149 /* optional - if string is null, do not add attribute */
1150 if ( result == SDP_SUCCESS )
1151 {
1152 if ( p_device_info->client_executable_url[0] != '\0' )
1153 {
1154 if ( !((strlen(p_device_info->client_executable_url)+1 <= SDP_MAX_ATTR_LEN) &&
1155 SDP_AddAttribute(handle, ATTR_ID_CLIENT_EXE_URL, URL_DESC_TYPE,
1156 (UINT32)(strlen(p_device_info->client_executable_url)+1),
1157 (UINT8 *)p_device_info->client_executable_url)) )
1158 result = SDP_DI_REG_FAILED;
1159 }
1160 }
1161
1162 /* optional - if string is null, do not add attribute */
1163 if ( result == SDP_SUCCESS )
1164 {
1165 if ( p_device_info->service_description[0] != '\0' )
1166 {
1167 if ( !((strlen(p_device_info->service_description)+1 <= SDP_MAX_ATTR_LEN) &&
1168 SDP_AddAttribute(handle, ATTR_ID_SERVICE_DESCRIPTION,
1169 TEXT_STR_DESC_TYPE,
1170 (UINT32)(strlen(p_device_info->service_description)+1),
1171 (UINT8 *)p_device_info->service_description)) )
1172 result = SDP_DI_REG_FAILED;
1173 }
1174 }
1175
1176 /* optional - if string is null, do not add attribute */
1177 if ( result == SDP_SUCCESS )
1178 {
1179 if ( p_device_info->documentation_url[0] != '\0' )
1180 {
1181 if ( !((strlen(p_device_info->documentation_url)+1 <= SDP_MAX_ATTR_LEN) &&
1182 SDP_AddAttribute(handle, ATTR_ID_DOCUMENTATION_URL, URL_DESC_TYPE,
1183 (UINT32)(strlen(p_device_info->documentation_url)+1),
1184 (UINT8 *)p_device_info->documentation_url)) )
1185 result = SDP_DI_REG_FAILED;
1186 }
1187 }
1188
1189 /* mandatory */
1190 if ( result == SDP_SUCCESS)
1191 {
1192 p_temp = temp_u16;
1193 UINT16_TO_BE_STREAM(p_temp, p_device_info->vendor);
1194 if ( !(SDP_AddAttribute(handle, ATTR_ID_VENDOR_ID, UINT_DESC_TYPE,
1195 sizeof(p_device_info->vendor), temp_u16)) )
1196 result = SDP_DI_REG_FAILED;
1197 }
1198
1199 /* mandatory */
1200 if ( result == SDP_SUCCESS)
1201 {
1202 p_temp = temp_u16;
1203 UINT16_TO_BE_STREAM (p_temp, p_device_info->product);
1204 if ( !(SDP_AddAttribute(handle, ATTR_ID_PRODUCT_ID,
1205 UINT_DESC_TYPE, sizeof(p_device_info->product), temp_u16)) )
1206 result = SDP_DI_REG_FAILED;
1207 }
1208
1209 /* mandatory */
1210 if ( result == SDP_SUCCESS)
1211 {
1212 p_temp = temp_u16;
1213 UINT16_TO_BE_STREAM (p_temp, p_device_info->version);
1214 if ( !(SDP_AddAttribute(handle, ATTR_ID_PRODUCT_VERSION, UINT_DESC_TYPE,
1215 sizeof(p_device_info->version), temp_u16)) )
1216 result = SDP_DI_REG_FAILED;
1217 }
1218
1219 /* mandatory */
1220 if ( result == SDP_SUCCESS)
1221 {
1222 u8 = (UINT8)p_device_info->primary_record;
1223 if ( !(SDP_AddAttribute(handle, ATTR_ID_PRIMARY_RECORD,
1224 BOOLEAN_DESC_TYPE, 1, &u8)) )
1225 result = SDP_DI_REG_FAILED;
1226 }
1227
1228 /* mandatory */
1229 if ( result == SDP_SUCCESS)
1230 {
1231 p_temp = temp_u16;
1232 UINT16_TO_BE_STREAM(p_temp, p_device_info->vendor_id_source);
1233 if ( !(SDP_AddAttribute(handle, ATTR_ID_VENDOR_ID_SOURCE, UINT_DESC_TYPE,
1234 sizeof(p_device_info->vendor_id_source), temp_u16)) )
1235 result = SDP_DI_REG_FAILED;
1236 }
1237
1238 if ( result != SDP_SUCCESS )
1239 SDP_DeleteRecord( handle );
1240 else if (p_device_info->primary_record == TRUE)
1241 sdp_cb.server_db.di_primary_handle = handle;
1242
1243 return result;
1244 #else /* SDP_SERVER_ENABLED is FALSE */
1245 return SDP_DI_REG_FAILED;
1246 #endif /* if SDP_SERVER_ENABLED */
1247 }
1248
1249 /*******************************************************************************
1250 **
1251 ** Function SDP_GetLocalDiRecord
1252 **
1253 ** Description This function adds a DI record to the local SDP database.
1254 **
1255 ** Fills in the device information of the record
1256 ** p_handle - if p_handle == 0, the primary record is returned
1257 **
1258 ** Returns Returns SDP_SUCCESS if record exists, else error
1259 **
1260 *******************************************************************************/
SDP_GetLocalDiRecord(tSDP_DI_GET_RECORD * p_device_info,UINT32 * p_handle)1261 UINT16 SDP_GetLocalDiRecord(tSDP_DI_GET_RECORD *p_device_info, UINT32 *p_handle )
1262 {
1263 UINT16 result = SDP_NO_DI_RECORD_FOUND;
1264
1265 #if SDP_SERVER_ENABLED == TRUE
1266 tSDP_RECORD *p_rec;
1267 tSDP_ATTRIBUTE *p_attr;
1268 UINT8 *p_temp;
1269 INT32 templen;
1270
1271 if (*p_handle == 0)
1272 *p_handle = sdp_cb.server_db.di_primary_handle;
1273
1274 if ((p_rec = sdp_db_find_record(*p_handle)) != NULL)
1275 {
1276 memset(p_device_info, 0, sizeof(tSDP_DI_RECORD));
1277
1278 result = SDP_SUCCESS;
1279
1280 /* Retrieve the Specification ID */
1281 if ((p_attr = sdp_db_find_attr_in_rec(p_rec, ATTR_ID_SPECIFICATION_ID,
1282 ATTR_ID_SPECIFICATION_ID)) != NULL)
1283 {
1284 p_temp = p_attr->value_ptr;
1285 BE_STREAM_TO_UINT16 (p_device_info->spec_id, p_temp);
1286 }
1287
1288 /* Retrieve the Vendor ID */
1289 if ((p_attr = sdp_db_find_attr_in_rec(p_rec, ATTR_ID_VENDOR_ID,
1290 ATTR_ID_VENDOR_ID)) != NULL)
1291 {
1292 p_temp = p_attr->value_ptr;
1293 BE_STREAM_TO_UINT16 (p_device_info->rec.vendor, p_temp);
1294 }
1295
1296 /* Retrieve the Product ID */
1297 if ((p_attr = sdp_db_find_attr_in_rec(p_rec, ATTR_ID_PRODUCT_ID,
1298 ATTR_ID_PRODUCT_ID)) != NULL)
1299 {
1300 p_temp = p_attr->value_ptr;
1301 BE_STREAM_TO_UINT16 (p_device_info->rec.product, p_temp);
1302 }
1303
1304 /* Retrieve the Version ID */
1305 if ((p_attr = sdp_db_find_attr_in_rec(p_rec, ATTR_ID_PRODUCT_VERSION,
1306 ATTR_ID_PRODUCT_VERSION)) != NULL)
1307 {
1308 p_temp = p_attr->value_ptr;
1309 BE_STREAM_TO_UINT16 (p_device_info->rec.version, p_temp);
1310 }
1311
1312 /* Retrieve the Vendor ID Source ID */
1313 if ((p_attr = sdp_db_find_attr_in_rec(p_rec, ATTR_ID_VENDOR_ID_SOURCE,
1314 ATTR_ID_VENDOR_ID_SOURCE)) != NULL)
1315 {
1316 p_temp = p_attr->value_ptr;
1317 BE_STREAM_TO_UINT16 (p_device_info->rec.vendor_id_source, p_temp);
1318 }
1319
1320 /* Retrieve the Primary Record */
1321 if ((p_attr = sdp_db_find_attr_in_rec(p_rec, ATTR_ID_PRIMARY_RECORD,
1322 ATTR_ID_PRIMARY_RECORD)) != NULL)
1323 {
1324 p_device_info->rec.primary_record = *p_attr->value_ptr;
1325 }
1326
1327 /* Retrieve the Client Executable URL */
1328 if ((p_attr = sdp_db_find_attr_in_rec(p_rec, ATTR_ID_CLIENT_EXE_URL,
1329 ATTR_ID_CLIENT_EXE_URL)) != NULL)
1330 {
1331 templen = (INT32)((p_attr->len < SDP_MAX_ATTR_LEN) ? p_attr->len : SDP_MAX_ATTR_LEN);
1332 p_temp = p_attr->value_ptr;
1333 BE_STREAM_TO_ARRAY (p_temp, p_device_info->rec.client_executable_url, templen);
1334 }
1335
1336 /* Retrieve the Service Description */
1337 if ((p_attr = sdp_db_find_attr_in_rec(p_rec, ATTR_ID_SERVICE_DESCRIPTION,
1338 ATTR_ID_SERVICE_DESCRIPTION)) != NULL)
1339 {
1340 templen = (INT32)((p_attr->len < SDP_MAX_ATTR_LEN) ? p_attr->len : SDP_MAX_ATTR_LEN);
1341 p_temp = p_attr->value_ptr;
1342 BE_STREAM_TO_ARRAY (p_temp, p_device_info->rec.service_description, templen);
1343 }
1344
1345 /* Retrieve the Documentation URL */
1346 if ((p_attr = sdp_db_find_attr_in_rec(p_rec, ATTR_ID_DOCUMENTATION_URL,
1347 ATTR_ID_DOCUMENTATION_URL)) != NULL)
1348 {
1349 templen = (INT32)((p_attr->len < SDP_MAX_ATTR_LEN) ? p_attr->len : SDP_MAX_ATTR_LEN);
1350 p_temp = p_attr->value_ptr;
1351 BE_STREAM_TO_ARRAY (p_temp, p_device_info->rec.documentation_url, templen);
1352 }
1353 }
1354 else
1355 *p_handle = 0;
1356 #endif
1357
1358 return result;
1359 }
1360
1361
1362 /*******************************************************************************
1363 **
1364 ** Function SDP_SetTraceLevel
1365 **
1366 ** Description This function sets the trace level for SDP. If called with
1367 ** a value of 0xFF, it simply reads the current trace level.
1368 **
1369 ** Returns the new (current) trace level
1370 **
1371 *******************************************************************************/
SDP_SetTraceLevel(UINT8 new_level)1372 UINT8 SDP_SetTraceLevel (UINT8 new_level)
1373 {
1374 if (new_level != 0xFF)
1375 sdp_cb.trace_level = new_level;
1376
1377 return(sdp_cb.trace_level);
1378 }
1379
1380 #if SDP_FOR_JV_INCLUDED == TRUE
1381 /*******************************************************************************
1382 **
1383 ** Function SDP_ConnOpen
1384 **
1385 ** Description This function creates a connection to the SDP server on the
1386 ** given device.
1387 **
1388 ** Returns 0, if failed to initiate connection. Otherwise, the handle.
1389 **
1390 *******************************************************************************/
SDP_ConnOpen(UINT8 * p_bd_addr,tSDP_DISC_RES_CB * p_rcb,tSDP_DISC_CMPL_CB * p_cb)1391 UINT32 SDP_ConnOpen (UINT8 *p_bd_addr, tSDP_DISC_RES_CB *p_rcb,
1392 tSDP_DISC_CMPL_CB *p_cb)
1393 {
1394 #if SDP_CLIENT_ENABLED == TRUE
1395 tCONN_CB *p_ccb;
1396 UINT32 idx = 0;
1397
1398 if (!p_cb || !p_rcb)
1399 return(idx);
1400
1401 /* Specific BD address */
1402 p_ccb = sdp_conn_originate (p_bd_addr);
1403
1404 if (!p_ccb)
1405 return(idx);
1406
1407 p_ccb->disc_state = SDP_DISC_WAIT_CONN;
1408 p_ccb->p_db = (tSDP_DISCOVERY_DB *)p_rcb;
1409 p_ccb->p_cb = p_cb;
1410
1411 p_ccb->is_attr_search = SDP_IS_PASS_THRU;
1412
1413 idx = (UINT32)(p_ccb - sdp_cb.ccb);
1414 return(UINT32)(idx + 1);
1415 #else
1416 return(0);
1417 #endif
1418 }
1419
1420 /*******************************************************************************
1421 **
1422 ** Function SDP_WriteData
1423 **
1424 ** Description This function sends data to the connected SDP server.
1425 **
1426 ** Returns TRUE if data is sent, FALSE if failed.
1427 **
1428 *******************************************************************************/
SDP_WriteData(UINT32 handle,BT_HDR * p_msg)1429 BOOLEAN SDP_WriteData (UINT32 handle, BT_HDR *p_msg)
1430 {
1431 #if SDP_CLIENT_ENABLED == TRUE
1432 tCONN_CB *p_ccb = NULL;
1433
1434 if (p_msg && (handle > 0) && (handle <= SDP_MAX_CONNECTIONS) )
1435 {
1436 p_ccb = &sdp_cb.ccb[handle - 1];
1437 if ( (p_ccb->con_state == SDP_STATE_CONNECTED) &&
1438 (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) )
1439 {
1440 /* Start inactivity timer */
1441 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT);
1442 L2CA_DataWrite (p_ccb->connection_id, p_msg);
1443 return TRUE;
1444 }
1445 }
1446 #endif
1447 return FALSE;
1448 }
1449
1450 /*******************************************************************************
1451 **
1452 ** Function SDP_ConnClose
1453 **
1454 ** Description This function is called to close a SDP connection.
1455 **
1456 ** Parameters: handle - Handle of the connection returned by SDP_ConnOpen
1457 **
1458 ** Returns TRUE if connection is closed, FALSE if failed to find the handle.
1459 **
1460 *******************************************************************************/
SDP_ConnClose(UINT32 handle)1461 BOOLEAN SDP_ConnClose (UINT32 handle)
1462 {
1463 #if SDP_CLIENT_ENABLED == TRUE
1464 tCONN_CB *p_ccb = NULL;
1465
1466 if (handle > 0 && handle <= SDP_MAX_CONNECTIONS)
1467 {
1468 p_ccb = &sdp_cb.ccb[handle - 1];
1469 sdp_disconnect (p_ccb, SDP_SUCCESS);
1470 return TRUE;
1471 }
1472 #endif
1473 return FALSE;
1474 }
1475 #endif
1476