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