blob: 322e27dcf506f41ac55958f26c1b04b12df17961 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
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 functions that handle the database
22 *
23 ******************************************************************************/
24
25#include <stdlib.h>
26#include <string.h>
27#include <stdio.h>
28
29#include "bt_target.h"
30
31#include "gki.h"
32
33#include "l2cdefs.h"
34#include "hcidefs.h"
35#include "hcimsgs.h"
36
37#include "sdp_api.h"
38#include "sdpint.h"
39#include "wbt_api.h"
40
41#if SDP_SERVER_ENABLED == TRUE
42/********************************************************************************/
43/* L O C A L F U N C T I O N P R O T O T Y P E S */
44/********************************************************************************/
45static BOOLEAN find_uuid_in_seq (UINT8 *p , UINT32 seq_len, UINT8 *p_his_uuid,
46 UINT16 his_len, int nest_level);
47
48
49/*******************************************************************************
50**
51** Function sdp_db_service_search
52**
53** Description This function searches for a record that contains the
54** specified UIDs. It is passed either NULL to start at the
55** beginning, or the previous record found.
56**
57** Returns Pointer to the record, or NULL if not found.
58**
59*******************************************************************************/
60tSDP_RECORD *sdp_db_service_search (tSDP_RECORD *p_rec, tSDP_UUID_SEQ *p_seq)
61{
62 UINT16 xx, yy;
63 tSDP_ATTRIBUTE *p_attr;
64 tSDP_RECORD *p_end = &sdp_cb.server_db.record[sdp_cb.server_db.num_records];
65
66 /* If NULL, start at the beginning, else start at the first specified record */
67 if (!p_rec)
68 p_rec = &sdp_cb.server_db.record[0];
69 else
70 p_rec++;
71
72 /* Look through the records. The spec says that a match occurs if */
73 /* the record contains all the passed UUIDs in it. */
74 for ( ; p_rec < p_end; p_rec++)
75 {
76 for (yy = 0; yy < p_seq->num_uids; yy++)
77 {
78 p_attr = &p_rec->attribute[0];
79 for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
80 {
81 if (p_attr->type == UUID_DESC_TYPE)
82 {
83 if (sdpu_compare_uuid_arrays (p_attr->value_ptr, p_attr->len,
84 &p_seq->uuid_entry[yy].value[0],
85 p_seq->uuid_entry[yy].len))
86 break;
87 }
88 else if (p_attr->type == DATA_ELE_SEQ_DESC_TYPE)
89 {
90 if (find_uuid_in_seq (p_attr->value_ptr, p_attr->len,
91 &p_seq->uuid_entry[yy].value[0],
92 p_seq->uuid_entry[yy].len, 0))
93 break;
94 }
95 }
96 /* If any UUID was not found, on to the next record */
97 if (xx == p_rec->num_attributes)
98 break;
99 }
100
101 /* If every UUID was found in the record, return the record */
102 if (yy == p_seq->num_uids)
103 return (p_rec);
104 }
105
106 /* If here, no more records found */
107 return (NULL);
108}
109
110/*******************************************************************************
111**
112** Function find_uuid_in_seq
113**
114** Description This function searches a data element sequenct for a UUID.
115**
116** Returns TRUE if found, else FALSE
117**
118*******************************************************************************/
119static BOOLEAN find_uuid_in_seq (UINT8 *p , UINT32 seq_len, UINT8 *p_uuid,
120 UINT16 uuid_len, int nest_level)
121{
122 UINT8 *p_end = p + seq_len;
123 UINT8 type;
124 UINT32 len;
125
126 /* A little safety check to avoid excessive recursion */
127 if (nest_level > 3)
128 return (FALSE);
129
130 while (p < p_end)
131 {
132 type = *p++;
133 p = sdpu_get_len_from_type (p, type, &len);
134 type = type >> 3;
135 if (type == UUID_DESC_TYPE)
136 {
137 if (sdpu_compare_uuid_arrays (p, len, p_uuid, uuid_len))
138 return (TRUE);
139 }
140 else if (type == DATA_ELE_SEQ_DESC_TYPE)
141 {
142 if (find_uuid_in_seq (p, len, p_uuid, uuid_len, nest_level + 1))
143 return (TRUE);
144 }
145 p = p + len;
146 }
147
148 /* If here, failed to match */
149 return (FALSE);
150}
151
152/*******************************************************************************
153**
154** Function sdp_db_find_record
155**
156** Description This function searches for a record with a specific handle
157** It is passed the handle of the record.
158**
159** Returns Pointer to the record, or NULL if not found.
160**
161*******************************************************************************/
162tSDP_RECORD *sdp_db_find_record (UINT32 handle)
163{
164 tSDP_RECORD *p_rec;
165 tSDP_RECORD *p_end = &sdp_cb.server_db.record[sdp_cb.server_db.num_records];
166
167 /* Look through the records for the caller's handle */
168 for (p_rec = &sdp_cb.server_db.record[0]; p_rec < p_end; p_rec++)
169 {
170 if (p_rec->record_handle == handle)
171 return (p_rec);
172 }
173
174 /* Record with that handle not found. */
175 return (NULL);
176}
177
178/*******************************************************************************
179**
180** Function sdp_db_find_attr_in_rec
181**
182** Description This function searches a record for specific attributes.
183** It is passed a pointer to the record. If the record contains
184** the specified attribute, (the caller may specify be a range
185** of attributes), the attribute is returned.
186**
187** Returns Pointer to the attribute, or NULL if not found.
188**
189*******************************************************************************/
190tSDP_ATTRIBUTE *sdp_db_find_attr_in_rec (tSDP_RECORD *p_rec, UINT16 start_attr,
191 UINT16 end_attr)
192{
193 tSDP_ATTRIBUTE *p_at;
194 UINT16 xx;
195
196 /* Note that the attributes in a record are assumed to be in sorted order */
197 for (xx = 0, p_at = &p_rec->attribute[0]; xx < p_rec->num_attributes;
198 xx++, p_at++)
199 {
200 if ((p_at->id >= start_attr) && (p_at->id <= end_attr))
201 return (p_at);
202 }
203
204 /* No matching attribute found */
205 return (NULL);
206}
207
208
209/*******************************************************************************
210**
211** Function sdp_compose_proto_list
212**
213** Description This function is called to compose a data sequence from
214** protocol element list struct pointer
215**
216** Returns the length of the data sequence
217**
218*******************************************************************************/
219static int sdp_compose_proto_list( UINT8 *p, UINT16 num_elem,
220 tSDP_PROTOCOL_ELEM *p_elem_list)
221{
222 UINT16 xx, yy, len;
223 BOOLEAN is_rfcomm_scn;
224 UINT8 *p_head = p;
225 UINT8 *p_len;
226
227 /* First, build the protocol list. This consists of a set of data element
228 ** sequences, one for each layer. Each layer sequence consists of layer's
229 ** UUID and optional parameters
230 */
231 for (xx = 0; xx < num_elem; xx++, p_elem_list++)
232 {
233 len = 3 + (p_elem_list->num_params * 3);
234 UINT8_TO_BE_STREAM (p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
235
236 p_len = p;
237 *p++ = (UINT8) len;
238
239 UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
240 UINT16_TO_BE_STREAM (p, p_elem_list->protocol_uuid);
241
242 if (p_elem_list->protocol_uuid == UUID_PROTOCOL_RFCOMM)
243 is_rfcomm_scn = TRUE;
244 else
245 is_rfcomm_scn = FALSE;
246
247 for (yy = 0; yy < p_elem_list->num_params; yy++)
248 {
249 if (is_rfcomm_scn)
250 {
251 UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
252 UINT8_TO_BE_STREAM (p, p_elem_list->params[yy]);
253
254 *p_len -= 1;
255 }
256 else
257 {
258 UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
259 UINT16_TO_BE_STREAM (p, p_elem_list->params[yy]);
260 }
261 }
262 }
263 return (p - p_head);
264}
265
266#endif /* SDP_SERVER_ENABLED == TRUE */
267
268/*******************************************************************************
269**
270** Function SDP_CreateRecord
271**
272** Description This function is called to create a record in the database.
273** This would be through the SDP database maintenance API. The
274** record is created empty, teh application should then call
275** "add_attribute" to add the record's attributes.
276**
277** Returns Record handle if OK, else 0.
278**
279*******************************************************************************/
280UINT32 SDP_CreateRecord (void)
281{
282#if SDP_SERVER_ENABLED == TRUE
283 UINT32 handle;
284 UINT8 buf[4];
285 tSDP_DB *p_db = &sdp_cb.server_db;
286
287 /* First, check if there is a free record */
288 if (p_db->num_records < SDP_MAX_RECORDS)
289 {
290 memset (&p_db->record[p_db->num_records], 0,
291 sizeof (tSDP_RECORD));
292
293 /* We will use a handle of the first unreserved handle plus last record
294 ** number + 1 */
295 if (p_db->num_records)
296 handle = p_db->record[p_db->num_records - 1].record_handle + 1;
297 else
298 handle = 0x10000;
299
300 p_db->record[p_db->num_records].record_handle = handle;
301
302 p_db->num_records++;
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700303 SDP_TRACE_DEBUG("SDP_CreateRecord ok, num_records:%d", p_db->num_records);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800304 /* Add the first attribute (the handle) automatically */
305 UINT32_TO_BE_FIELD (buf, handle);
306 SDP_AddAttribute (handle, ATTR_ID_SERVICE_RECORD_HDL, UINT_DESC_TYPE,
307 4, buf);
308
309 return (p_db->record[p_db->num_records - 1].record_handle);
310 }
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700311 else SDP_TRACE_ERROR("SDP_CreateRecord fail, exceed maximum records:%d", SDP_MAX_RECORDS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800312#endif
313 return (0);
314}
315
316
317/*******************************************************************************
318**
319** Function SDP_DeleteRecord
320**
321** Description This function is called to add a record (or all records)
322** from the database. This would be through the SDP database
323** maintenance API.
324**
325** If a record handle of 0 is passed, all records are deleted.
326**
327** Returns TRUE if succeeded, else FALSE
328**
329*******************************************************************************/
330BOOLEAN SDP_DeleteRecord (UINT32 handle)
331{
332#if SDP_SERVER_ENABLED == TRUE
333 UINT16 xx, yy, zz;
334 tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0];
335
336 if (handle == 0 || sdp_cb.server_db.num_records == 0)
337 {
338 /* Delete all records in the database */
339 sdp_cb.server_db.num_records = 0;
340
341 /* require new DI record to be created in SDP_SetLocalDiRecord */
342 sdp_cb.server_db.di_primary_handle = 0;
343 sdp_cb.server_db.brcm_di_registered = 0;
344
345 return (TRUE);
346 }
347 else
348 {
349 /* Find the record in the database */
350 for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++)
351 {
352 if (p_rec->record_handle == handle)
353 {
354 /* Found it. Shift everything up one */
355 for (yy = xx; yy < sdp_cb.server_db.num_records; yy++, p_rec++)
356 {
357 *p_rec = *(p_rec + 1);
358
359 /* Adjust the attribute value pointer for each attribute */
360 for (zz = 0; zz < p_rec->num_attributes; zz++)
361 p_rec->attribute[zz].value_ptr -= sizeof(tSDP_RECORD);
362 }
363
364 sdp_cb.server_db.num_records--;
365
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700366 SDP_TRACE_DEBUG("SDP_DeleteRecord ok, num_records:%d", sdp_cb.server_db.num_records);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800367 /* if we're deleting the primary DI record, clear the */
368 /* value in the control block */
369 if( sdp_cb.server_db.di_primary_handle == handle )
370 {
371 sdp_cb.server_db.di_primary_handle = 0;
372 sdp_cb.server_db.brcm_di_registered = 0;
373 }
374
375 return (TRUE);
376 }
377 }
378 }
379#endif
380 return (FALSE);
381}
382
383
384/*******************************************************************************
385**
386** Function SDP_AddAttribute
387**
388** Description This function is called to add an attribute to a record.
389** This would be through the SDP database maintenance API.
390** If the attribute already exists in the record, it is replaced
391** with the new value.
392**
393** NOTE Attribute values must be passed as a Big Endian stream.
394**
395** Returns TRUE if added OK, else FALSE
396**
397*******************************************************************************/
398BOOLEAN SDP_AddAttribute (UINT32 handle, UINT16 attr_id, UINT8 attr_type,
399 UINT32 attr_len, UINT8 *p_val)
400{
401#if SDP_SERVER_ENABLED == TRUE
402 UINT16 xx, yy, zz;
403 tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0];
404
405#if (BT_TRACE_VERBOSE == TRUE)
406 if (sdp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG)
407 {
408 if ((attr_type == UINT_DESC_TYPE) ||
409 (attr_type == TWO_COMP_INT_DESC_TYPE) ||
410 (attr_type == UUID_DESC_TYPE) ||
411 (attr_type == DATA_ELE_SEQ_DESC_TYPE) ||
412 (attr_type == DATA_ELE_ALT_DESC_TYPE))
413 {
414 UINT8 num_array[400];
415 UINT32 i;
416 UINT32 len = (attr_len > 200) ? 200 : attr_len;
417
418 num_array[0] ='\0';
419 for (i = 0; i < len; i++)
420 {
421 sprintf((char *)&num_array[i*2],"%02X",(UINT8)(p_val[i]));
422 }
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700423 SDP_TRACE_DEBUG("SDP_AddAttribute: handle:%X, id:%04X, type:%d, len:%d, p_val:%p, *p_val:%s",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800424 handle,attr_id,attr_type,attr_len,p_val,num_array);
425 }
426 else if (attr_type == BOOLEAN_DESC_TYPE)
427 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700428 SDP_TRACE_DEBUG("SDP_AddAttribute: handle:%X, id:%04X, type:%d, len:%d, p_val:%p, *p_val:%d",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800429 handle,attr_id,attr_type,attr_len,p_val,*p_val);
430 }
431 else
432 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700433 SDP_TRACE_DEBUG("SDP_AddAttribute: handle:%X, id:%04X, type:%d, len:%d, p_val:%p, *p_val:%s",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800434 handle,attr_id,attr_type,attr_len,p_val,p_val);
435 }
436 }
437#endif
438
439 /* Find the record in the database */
440 for (zz = 0; zz < sdp_cb.server_db.num_records; zz++, p_rec++)
441 {
442 if (p_rec->record_handle == handle)
443 {
444 tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0];
445
446 /* Found the record. Now, see if the attribute already exists */
447 for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
448 {
449 /* The attribute exists. replace it */
450 if (p_attr->id == attr_id)
451 {
452 SDP_DeleteAttribute (handle, attr_id);
453 break;
454 }
455 if (p_attr->id > attr_id)
456 break;
457 }
458
459 if (p_rec->num_attributes == SDP_MAX_REC_ATTR)
460 return (FALSE);
461
462 /* If not found, see if we can allocate a new entry */
463 if (xx == p_rec->num_attributes)
464 p_attr = &p_rec->attribute[p_rec->num_attributes];
465 else
466 {
467 /* Since the attributes are kept in sorted order, insert ours here */
468 for (yy = p_rec->num_attributes; yy > xx; yy--)
469 p_rec->attribute[yy] = p_rec->attribute[yy - 1];
470 }
471
472 p_attr->id = attr_id;
473 p_attr->type = attr_type;
474 p_attr->len = attr_len;
475
476 if (p_rec->free_pad_ptr + attr_len >= SDP_MAX_PAD_LEN)
477 {
478 /* do truncate only for text string type descriptor */
479 if (attr_type == TEXT_STR_DESC_TYPE)
480 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700481 SDP_TRACE_WARNING("SDP_AddAttribute: attr_len:%d too long. truncate to (%d)",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800482 attr_len, SDP_MAX_PAD_LEN - p_rec->free_pad_ptr );
483
484 attr_len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr;
485 p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr] = '\0';
486 p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr+1] = '\0';
487 }
488 else
489 attr_len = 0;
490 }
491
492 if ((attr_len > 0) && (p_val != 0))
493 {
494 p_attr->len = attr_len;
495 memcpy (&p_rec->attr_pad[p_rec->free_pad_ptr], p_val, (size_t)attr_len);
496 p_attr->value_ptr = &p_rec->attr_pad[p_rec->free_pad_ptr];
497 p_rec->free_pad_ptr += attr_len;
498 }
499 else if ((attr_len == 0 && p_attr->len != 0) || /* if truncate to 0 length, simply don't add */
500 p_val == 0)
501 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700502 SDP_TRACE_ERROR("SDP_AddAttribute fail, length exceed maximum: ID %d: attr_len:%d ",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800503 attr_id, attr_len );
504 p_attr->id = p_attr->type = p_attr->len = 0;
505 return (FALSE);
506 }
507 p_rec->num_attributes++;
508
509 /*** Mark DI record as used by Broadcom ***/
510 if (handle == sdp_cb.server_db.di_primary_handle &&
511 attr_id == ATTR_ID_EXT_BRCM_VERSION)
512 sdp_cb.server_db.brcm_di_registered = TRUE;
513
514 return (TRUE);
515 }
516 }
517#endif
518 return (FALSE);
519}
520
521
522/*******************************************************************************
523**
524** Function SDP_AddSequence
525**
526** Description This function is called to add a sequence to a record.
527** This would be through the SDP database maintenance API.
528** If the sequence already exists in the record, it is replaced
529** with the new sequence.
530**
531** NOTE Element values must be passed as a Big Endian stream.
532**
533** Returns TRUE if added OK, else FALSE
534**
535*******************************************************************************/
536BOOLEAN SDP_AddSequence (UINT32 handle, UINT16 attr_id, UINT16 num_elem,
537 UINT8 type[], UINT8 len[], UINT8 *p_val[])
538{
539#if SDP_SERVER_ENABLED == TRUE
540 UINT16 xx;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800541 UINT8 *p_buff;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800542 UINT8 *p;
543 UINT8 *p_head;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800544 BOOLEAN result;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800545
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800546 if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
547 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700548 SDP_TRACE_ERROR("SDP_AddSequence cannot get a buffer!");
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800549 return (FALSE);
550 }
551 p = p_buff;
552
The Android Open Source Project5738f832012-12-12 16:00:35 -0800553 /* First, build the sequence */
554 for (xx = 0; xx < num_elem; xx++)
555 {
556 p_head = p;
557 switch (len[xx])
558 {
559 case 1:
560 UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_ONE_BYTE);
561 break;
562 case 2:
563 UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_TWO_BYTES);
564 break;
565 case 4:
566 UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_FOUR_BYTES);
567 break;
568 case 8:
569 UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_EIGHT_BYTES);
570 break;
571 case 16:
572 UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_SIXTEEN_BYTES);
573 break;
574 default:
575 UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_IN_NEXT_BYTE);
576 UINT8_TO_BE_STREAM (p, len[xx]);
577 break;
578 }
579
580 ARRAY_TO_BE_STREAM (p, p_val[xx], len[xx]);
581
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800582 if (p - p_buff > SDP_MAX_ATTR_LEN)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800583 {
584 /* go back to before we add this element */
585 p = p_head;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800586 if(p_head == p_buff)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800587 {
588 /* the first element exceed the max length */
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700589 SDP_TRACE_ERROR ("SDP_AddSequence - too long(attribute is not added)!!");
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800590 GKI_freebuf(p_buff);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800591 return FALSE;
592 }
593 else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700594 SDP_TRACE_ERROR ("SDP_AddSequence - too long, add %d elements of %d", xx, num_elem);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800595 break;
596 }
597 }
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800598 result = SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,(UINT32) (p - p_buff), p_buff);
599 GKI_freebuf(p_buff);
600 return result;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800601#else /* SDP_SERVER_ENABLED == FALSE */
602 return (FALSE);
603#endif
604}
605
606
607/*******************************************************************************
608**
609** Function SDP_AddUuidSequence
610**
611** Description This function is called to add a UUID sequence to a record.
612** This would be through the SDP database maintenance API.
613** If the sequence already exists in the record, it is replaced
614** with the new sequence.
615**
616** Returns TRUE if added OK, else FALSE
617**
618*******************************************************************************/
619BOOLEAN SDP_AddUuidSequence (UINT32 handle, UINT16 attr_id, UINT16 num_uuids,
620 UINT16 *p_uuids)
621{
622#if SDP_SERVER_ENABLED == TRUE
623 UINT16 xx;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800624 UINT8 *p_buff;
625 UINT8 *p;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800626 INT32 max_len = SDP_MAX_ATTR_LEN -3;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800627 BOOLEAN result;
628
629 if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
630 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700631 SDP_TRACE_ERROR("SDP_AddUuidSequence cannot get a buffer!");
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800632 return (FALSE);
633 }
634 p = p_buff;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800635
636 /* First, build the sequence */
637 for (xx = 0; xx < num_uuids ; xx++, p_uuids++)
638 {
639 UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
640 UINT16_TO_BE_STREAM (p, *p_uuids);
641
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800642 if((p - p_buff) > max_len)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800643 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700644 SDP_TRACE_WARNING ("SDP_AddUuidSequence - too long, add %d uuids of %d", xx, num_uuids);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800645 break;
646 }
647 }
648
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800649 result = SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,(UINT32) (p - p_buff), p_buff);
650 GKI_freebuf(p_buff);
651 return result;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800652#else /* SDP_SERVER_ENABLED == FALSE */
653 return (FALSE);
654#endif
655}
656
657/*******************************************************************************
658**
659** Function SDP_AddProtocolList
660**
661** Description This function is called to add a protocol descriptor list to
662** a record. This would be through the SDP database maintenance API.
663** If the protocol list already exists in the record, it is replaced
664** with the new list.
665**
666** Returns TRUE if added OK, else FALSE
667**
668*******************************************************************************/
669BOOLEAN SDP_AddProtocolList (UINT32 handle, UINT16 num_elem,
670 tSDP_PROTOCOL_ELEM *p_elem_list)
671{
672#if SDP_SERVER_ENABLED == TRUE
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800673 UINT8 *p_buff;
674 int offset;
675 BOOLEAN result;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800676
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800677 if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
678 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700679 SDP_TRACE_ERROR("SDP_AddProtocolList cannot get a buffer!");
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800680 return (FALSE);
681 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800682
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800683 offset = sdp_compose_proto_list(p_buff, num_elem, p_elem_list);
684 result = SDP_AddAttribute (handle, ATTR_ID_PROTOCOL_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) offset, p_buff);
685 GKI_freebuf(p_buff);
686 return result;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800687#else /* SDP_SERVER_ENABLED == FALSE */
688 return (FALSE);
689#endif
690}
691
692
693/*******************************************************************************
694**
695** Function SDP_AddAdditionProtoLists
696**
697** Description This function is called to add a protocol descriptor list to
698** a record. This would be through the SDP database maintenance API.
699** If the protocol list already exists in the record, it is replaced
700** with the new list.
701**
702** Returns TRUE if added OK, else FALSE
703**
704*******************************************************************************/
705BOOLEAN SDP_AddAdditionProtoLists (UINT32 handle, UINT16 num_elem,
706 tSDP_PROTO_LIST_ELEM *p_proto_list)
707{
708#if SDP_SERVER_ENABLED == TRUE
709 UINT16 xx;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800710 UINT8 *p_buff;
711 UINT8 *p;
712 UINT8 *p_len;
713 int offset;
714 BOOLEAN result;
715
716 if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
717 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700718 SDP_TRACE_ERROR("SDP_AddAdditionProtoLists cannot get a buffer!");
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800719 return (FALSE);
720 }
721 p = p_buff;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800722
723 /* for each ProtocolDescriptorList */
724 for (xx = 0; xx < num_elem; xx++, p_proto_list++)
725 {
726 UINT8_TO_BE_STREAM (p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
727 p_len = p++;
728
729 offset = sdp_compose_proto_list(p, p_proto_list->num_elems,
730 p_proto_list->list_elem);
731 p += offset;
732
733 *p_len = (UINT8)(p - p_len - 1);
734 }
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800735 result = SDP_AddAttribute (handle, ATTR_ID_ADDITION_PROTO_DESC_LISTS,DATA_ELE_SEQ_DESC_TYPE,
736 (UINT32) (p - p_buff), p_buff);
737 GKI_freebuf(p_buff);
738 return result;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800739
The Android Open Source Project5738f832012-12-12 16:00:35 -0800740#else /* SDP_SERVER_ENABLED == FALSE */
741 return (FALSE);
742#endif
743}
744
745/*******************************************************************************
746**
747** Function SDP_AddProfileDescriptorList
748**
749** Description This function is called to add a profile descriptor list to
750** a record. This would be through the SDP database maintenance API.
751** If the version already exists in the record, it is replaced
752** with the new one.
753**
754** Returns TRUE if added OK, else FALSE
755**
756*******************************************************************************/
757BOOLEAN SDP_AddProfileDescriptorList (UINT32 handle, UINT16 profile_uuid,
758 UINT16 version)
759{
760#if SDP_SERVER_ENABLED == TRUE
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800761 UINT8 *p_buff;
762 UINT8 *p;
763 BOOLEAN result;
764
765 if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN)) == NULL)
766 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700767 SDP_TRACE_ERROR("SDP_AddProfileDescriptorList cannot get a buffer!");
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800768 return (FALSE);
769 }
770 p = p_buff+2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800771
772 /* First, build the profile descriptor list. This consists of a data element sequence. */
773 /* The sequence consists of profile's UUID and version number */
774 UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
775 UINT16_TO_BE_STREAM (p, profile_uuid);
776
777 UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
778 UINT16_TO_BE_STREAM (p, version);
779
780 /* Add in type and length fields */
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800781 *p_buff = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
782 *(p_buff+1) = (UINT8) (p - (p_buff+2));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800783
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800784 result = SDP_AddAttribute (handle, ATTR_ID_BT_PROFILE_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - p_buff), p_buff);
785 GKI_freebuf(p_buff);
786 return result;
787
The Android Open Source Project5738f832012-12-12 16:00:35 -0800788#else /* SDP_SERVER_ENABLED == FALSE */
789 return (FALSE);
790#endif
791}
792
793
794/*******************************************************************************
795**
796** Function SDP_AddLanguageBaseAttrIDList
797**
798** Description This function is called to add a language base attr list to
799** a record. This would be through the SDP database maintenance API.
800** If the version already exists in the record, it is replaced
801** with the new one.
802**
803** Returns TRUE if added OK, else FALSE
804**
805*******************************************************************************/
806BOOLEAN SDP_AddLanguageBaseAttrIDList (UINT32 handle, UINT16 lang,
807 UINT16 char_enc, UINT16 base_id)
808{
809#if SDP_SERVER_ENABLED == TRUE
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800810 UINT8 *p_buff;
811 UINT8 *p;
812 BOOLEAN result;
813
814 if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN)) == NULL)
815 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700816 SDP_TRACE_ERROR("SDP_AddLanguageBaseAttrIDList cannot get a buffer!");
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800817 return (FALSE);
818 }
819 p = p_buff;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800820
821 /* First, build the language base descriptor list. This consists of a data */
822 /* element sequence. The sequence consists of 9 bytes (3 UINt16 fields) */
823 UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
824 UINT16_TO_BE_STREAM (p, lang);
825
826 UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
827 UINT16_TO_BE_STREAM (p, char_enc);
828
829 UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
830 UINT16_TO_BE_STREAM (p, base_id);
831
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800832 result = SDP_AddAttribute (handle, ATTR_ID_LANGUAGE_BASE_ATTR_ID_LIST,DATA_ELE_SEQ_DESC_TYPE,
833 (UINT32) (p - p_buff), p_buff);
834 GKI_freebuf(p_buff);
835 return result;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800836#else /* SDP_SERVER_ENABLED == FALSE */
837 return (FALSE);
838#endif
839}
840
841
842/*******************************************************************************
843**
844** Function SDP_AddServiceClassIdList
845**
846** Description This function is called to add a service list to a record.
847** This would be through the SDP database maintenance API.
848** If the service list already exists in the record, it is replaced
849** with the new list.
850**
851** Returns TRUE if added OK, else FALSE
852**
853*******************************************************************************/
854BOOLEAN SDP_AddServiceClassIdList (UINT32 handle, UINT16 num_services,
855 UINT16 *p_service_uuids)
856{
857#if SDP_SERVER_ENABLED == TRUE
858 UINT16 xx;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800859 UINT8 *p_buff;
860 UINT8 *p;
861 BOOLEAN result;
862
863 if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
864 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700865 SDP_TRACE_ERROR("SDP_AddServiceClassIdList cannot get a buffer!");
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800866 return (FALSE);
867 }
868 p = p_buff;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800869
870 for (xx = 0; xx < num_services; xx++, p_service_uuids++)
871 {
872 UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
873 UINT16_TO_BE_STREAM (p, *p_service_uuids);
874 }
875
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800876 result = SDP_AddAttribute (handle, ATTR_ID_SERVICE_CLASS_ID_LIST,DATA_ELE_SEQ_DESC_TYPE,
877 (UINT32) (p - p_buff), p_buff);
878 GKI_freebuf(p_buff);
879 return result;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800880#else /* SDP_SERVER_ENABLED == FALSE */
881 return (FALSE);
882#endif
883}
884
885
886/*******************************************************************************
887**
888** Function SDP_DeleteAttribute
889**
890** Description This function is called to delete an attribute from a record.
891** This would be through the SDP database maintenance API.
892**
893** Returns TRUE if deleted OK, else FALSE if not found
894**
895*******************************************************************************/
896BOOLEAN SDP_DeleteAttribute (UINT32 handle, UINT16 attr_id)
897{
898#if SDP_SERVER_ENABLED == TRUE
899 UINT16 xx, yy;
900 tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0];
901 UINT8 *pad_ptr;
902 UINT32 len; /* Number of bytes in the entry */
903
904 /* Find the record in the database */
905 for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++)
906 {
907 if (p_rec->record_handle == handle)
908 {
909 tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0];
910
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700911 SDP_TRACE_API("Deleting attr_id 0x%04x for handle 0x%x", attr_id, handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800912 /* Found it. Now, find the attribute */
913 for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
914 {
915 if (p_attr->id == attr_id)
916 {
917 pad_ptr = p_attr->value_ptr;
918 len = p_attr->len;
919
920 if (len)
921 {
922 for (yy = 0; yy < p_rec->num_attributes; yy++)
923 {
924 if( p_rec->attribute[yy].value_ptr > pad_ptr )
925 p_rec->attribute[yy].value_ptr -= len;
926 }
927 }
928
929 /* Found it. Shift everything up one */
930 p_rec->num_attributes--;
931
932 for (yy = xx; yy < p_rec->num_attributes; yy++, p_attr++)
933 {
934 *p_attr = *(p_attr + 1);
935 }
936
937 /* adjust attribute values if needed */
938 if (len)
939 {
940 xx = (p_rec->free_pad_ptr - ((pad_ptr+len) -
941 &p_rec->attr_pad[0]));
942 for( yy=0; yy<xx; yy++, pad_ptr++)
943 *pad_ptr = *(pad_ptr+len);
944 p_rec->free_pad_ptr -= len;
945 }
946 return (TRUE);
947 }
948 }
949 }
950 }
951#endif
952 /* If here, not found */
953 return (FALSE);
954}
955
956/*******************************************************************************
957**
958** Function SDP_ReadRecord
959**
960** Description This function is called to get the raw data of the record
961** with the given handle from the database.
962**
963** Returns -1, if the record is not found.
964** Otherwise, the offset (0 or 1) to start of data in p_data.
965**
966** The size of data copied into p_data is in *p_data_len.
967**
968*******************************************************************************/
969#if (SDP_RAW_DATA_INCLUDED == TRUE)
970INT32 SDP_ReadRecord(UINT32 handle, UINT8 *p_data, INT32 *p_data_len)
971{
972 INT32 len = 0; /* Number of bytes in the entry */
973 INT32 offset = -1; /* default to not found */
974#if SDP_SERVER_ENABLED == TRUE
975 tSDP_RECORD *p_rec;
976 UINT16 start = 0;
977 UINT16 end = 0xffff;
978 tSDP_ATTRIBUTE *p_attr;
979 UINT16 rem_len;
980 UINT8 *p_rsp;
981
982 /* Find the record in the database */
983 p_rec = sdp_db_find_record(handle);
984 if(p_rec && p_data && p_data_len)
985 {
986 p_rsp = &p_data[3];
987 while ( (p_attr = sdp_db_find_attr_in_rec (p_rec, start, end)) != NULL)
988 {
989 /* Check if attribute fits. Assume 3-byte value type/length */
990 rem_len = *p_data_len - (UINT16) (p_rsp - p_data);
991
992 if (p_attr->len > (UINT32)(rem_len - 6))
993 break;
994
995 p_rsp = sdpu_build_attrib_entry (p_rsp, p_attr);
996
997 /* next attr id */
998 start = p_attr->id + 1;
999 }
1000 len = (INT32) (p_rsp - p_data);
1001
1002 /* Put in the sequence header (2 or 3 bytes) */
1003 if (len > 255)
1004 {
1005 offset = 0;
1006 p_data[0] = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_WORD);
1007 p_data[1] = (UINT8) ((len - 3) >> 8);
1008 p_data[2] = (UINT8) (len - 3);
1009 }
1010 else
1011 {
1012 offset = 1;
1013
1014 p_data[1] = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
1015 p_data[2] = (UINT8) (len - 3);
1016
1017 len--;
1018 }
1019 *p_data_len = len;
1020 }
1021#endif
1022 /* If here, not found */
1023 return (offset);
1024}
1025#endif
1026
1027
1028