• 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 #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 && (service_uuid == 0
530                         || (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2
531                             && p_sattr->attr_value.v.u16 == service_uuid)))
532                         /* for a specific uuid, or any one */
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