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