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 utility functions
22 *
23 ******************************************************************************/
24
25 #include <netinet/in.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "bt_common.h"
31 #include "bt_types.h"
32
33 #include "hcidefs.h"
34 #include "hcimsgs.h"
35 #include "l2cdefs.h"
36
37 #include "sdp_api.h"
38 #include "sdpint.h"
39
40 #include "btu.h"
41
42 static const uint8_t sdp_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
44 0x5F, 0x9B, 0x34, 0xFB};
45
46 /*******************************************************************************
47 *
48 * Function sdpu_find_ccb_by_cid
49 *
50 * Description This function searches the CCB table for an entry with the
51 * passed CID.
52 *
53 * Returns the CCB address, or NULL if not found.
54 *
55 ******************************************************************************/
sdpu_find_ccb_by_cid(uint16_t cid)56 tCONN_CB* sdpu_find_ccb_by_cid(uint16_t cid) {
57 uint16_t xx;
58 tCONN_CB* p_ccb;
59
60 /* Look through each connection control block */
61 for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
62 if ((p_ccb->con_state != SDP_STATE_IDLE) && (p_ccb->connection_id == cid))
63 return (p_ccb);
64 }
65
66 /* If here, not found */
67 return (NULL);
68 }
69
70 /*******************************************************************************
71 *
72 * Function sdpu_find_ccb_by_db
73 *
74 * Description This function searches the CCB table for an entry with the
75 * passed discovery db.
76 *
77 * Returns the CCB address, or NULL if not found.
78 *
79 ******************************************************************************/
sdpu_find_ccb_by_db(tSDP_DISCOVERY_DB * p_db)80 tCONN_CB* sdpu_find_ccb_by_db(tSDP_DISCOVERY_DB* p_db) {
81 uint16_t xx;
82 tCONN_CB* p_ccb;
83
84 if (p_db) {
85 /* Look through each connection control block */
86 for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
87 if ((p_ccb->con_state != SDP_STATE_IDLE) && (p_ccb->p_db == p_db))
88 return (p_ccb);
89 }
90 }
91 /* If here, not found */
92 return (NULL);
93 }
94
95 /*******************************************************************************
96 *
97 * Function sdpu_allocate_ccb
98 *
99 * Description This function allocates a new CCB.
100 *
101 * Returns CCB address, or NULL if none available.
102 *
103 ******************************************************************************/
sdpu_allocate_ccb(void)104 tCONN_CB* sdpu_allocate_ccb(void) {
105 uint16_t xx;
106 tCONN_CB* p_ccb;
107
108 /* Look through each connection control block for a free one */
109 for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
110 if (p_ccb->con_state == SDP_STATE_IDLE) {
111 memset(p_ccb, 0, sizeof(tCONN_CB));
112 p_ccb->sdp_conn_timer = alarm_new("sdp.sdp_conn_timer");
113 return (p_ccb);
114 }
115 }
116
117 /* If here, no free CCB found */
118 return (NULL);
119 }
120
121 /*******************************************************************************
122 *
123 * Function sdpu_release_ccb
124 *
125 * Description This function releases a CCB.
126 *
127 * Returns void
128 *
129 ******************************************************************************/
sdpu_release_ccb(tCONN_CB * p_ccb)130 void sdpu_release_ccb(tCONN_CB* p_ccb) {
131 /* Ensure timer is stopped */
132 alarm_free(p_ccb->sdp_conn_timer);
133 p_ccb->sdp_conn_timer = NULL;
134
135 /* Drop any response pointer we may be holding */
136 p_ccb->con_state = SDP_STATE_IDLE;
137 p_ccb->is_attr_search = false;
138
139 /* Free the response buffer */
140 if (p_ccb->rsp_list) SDP_TRACE_DEBUG("releasing SDP rsp_list");
141 osi_free_and_reset((void**)&p_ccb->rsp_list);
142 }
143
144 /*******************************************************************************
145 *
146 * Function sdpu_build_attrib_seq
147 *
148 * Description This function builds an attribute sequence from the list of
149 * passed attributes. It is also passed the address of the
150 * output buffer.
151 *
152 * Returns Pointer to next byte in the output buffer.
153 *
154 ******************************************************************************/
sdpu_build_attrib_seq(uint8_t * p_out,uint16_t * p_attr,uint16_t num_attrs)155 uint8_t* sdpu_build_attrib_seq(uint8_t* p_out, uint16_t* p_attr,
156 uint16_t num_attrs) {
157 uint16_t xx;
158
159 /* First thing is the data element header. See if the length fits 1 byte */
160 /* If no attributes, assume a 4-byte wildcard */
161 if (!p_attr)
162 xx = 5;
163 else
164 xx = num_attrs * 3;
165
166 if (xx > 255) {
167 UINT8_TO_BE_STREAM(p_out,
168 (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_WORD);
169 UINT16_TO_BE_STREAM(p_out, xx);
170 } else {
171 UINT8_TO_BE_STREAM(p_out,
172 (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
173 UINT8_TO_BE_STREAM(p_out, xx);
174 }
175
176 /* If there are no attributes specified, assume caller wants wildcard */
177 if (!p_attr) {
178 UINT8_TO_BE_STREAM(p_out, (UINT_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
179 UINT16_TO_BE_STREAM(p_out, 0);
180 UINT16_TO_BE_STREAM(p_out, 0xFFFF);
181 } else {
182 /* Loop through and put in all the attributes(s) */
183 for (xx = 0; xx < num_attrs; xx++, p_attr++) {
184 UINT8_TO_BE_STREAM(p_out, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
185 UINT16_TO_BE_STREAM(p_out, *p_attr);
186 }
187 }
188
189 return (p_out);
190 }
191
192 /*******************************************************************************
193 *
194 * Function sdpu_build_attrib_entry
195 *
196 * Description This function builds an attribute entry from the passed
197 * attribute record. It is also passed the address of the
198 * output buffer.
199 *
200 * Returns Pointer to next byte in the output buffer.
201 *
202 ******************************************************************************/
sdpu_build_attrib_entry(uint8_t * p_out,tSDP_ATTRIBUTE * p_attr)203 uint8_t* sdpu_build_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr) {
204 /* First, store the attribute ID. Goes as a UINT */
205 UINT8_TO_BE_STREAM(p_out, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
206 UINT16_TO_BE_STREAM(p_out, p_attr->id);
207
208 /* the attribute is in the db record.
209 * assuming the attribute len is less than SDP_MAX_ATTR_LEN */
210 switch (p_attr->type) {
211 case TEXT_STR_DESC_TYPE: /* 4 */
212 case DATA_ELE_SEQ_DESC_TYPE: /* 6 */
213 case DATA_ELE_ALT_DESC_TYPE: /* 7 */
214 case URL_DESC_TYPE: /* 8 */
215 #if (SDP_MAX_ATTR_LEN > 0xFFFF)
216 if (p_attr->len > 0xFFFF) {
217 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_LONG);
218 UINT32_TO_BE_STREAM(p_out, p_attr->len);
219 } else
220 #endif /* 0xFFFF - 0xFF */
221 #if (SDP_MAX_ATTR_LEN > 0xFF)
222 if (p_attr->len > 0xFF) {
223 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_WORD);
224 UINT16_TO_BE_STREAM(p_out, p_attr->len);
225 } else
226 #endif /* 0xFF and less*/
227 {
228 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_BYTE);
229 UINT8_TO_BE_STREAM(p_out, p_attr->len);
230 }
231
232 if (p_attr->value_ptr != NULL) {
233 ARRAY_TO_BE_STREAM(p_out, p_attr->value_ptr, (int)p_attr->len);
234 }
235
236 return (p_out);
237 }
238
239 /* Now, store the attribute value */
240 switch (p_attr->len) {
241 case 1:
242 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_ONE_BYTE);
243 break;
244 case 2:
245 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_TWO_BYTES);
246 break;
247 case 4:
248 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_FOUR_BYTES);
249 break;
250 case 8:
251 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_EIGHT_BYTES);
252 break;
253 case 16:
254 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_SIXTEEN_BYTES);
255 break;
256 default:
257 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_BYTE);
258 UINT8_TO_BE_STREAM(p_out, p_attr->len);
259 break;
260 }
261
262 if (p_attr->value_ptr != NULL) {
263 ARRAY_TO_BE_STREAM(p_out, p_attr->value_ptr, (int)p_attr->len);
264 }
265
266 return (p_out);
267 }
268
269 /*******************************************************************************
270 *
271 * Function sdpu_build_n_send_error
272 *
273 * Description This function builds and sends an error packet.
274 *
275 * Returns void
276 *
277 ******************************************************************************/
sdpu_build_n_send_error(tCONN_CB * p_ccb,uint16_t trans_num,uint16_t error_code,char * p_error_text)278 void sdpu_build_n_send_error(tCONN_CB* p_ccb, uint16_t trans_num,
279 uint16_t error_code, char* p_error_text) {
280 uint8_t *p_rsp, *p_rsp_start, *p_rsp_param_len;
281 uint16_t rsp_param_len;
282 BT_HDR* p_buf = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
283
284 SDP_TRACE_WARNING("SDP - sdpu_build_n_send_error code: 0x%x CID: 0x%x",
285 error_code, p_ccb->connection_id);
286
287 /* Send the packet to L2CAP */
288 p_buf->offset = L2CAP_MIN_OFFSET;
289 p_rsp = p_rsp_start = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
290
291 UINT8_TO_BE_STREAM(p_rsp, SDP_PDU_ERROR_RESPONSE);
292 UINT16_TO_BE_STREAM(p_rsp, trans_num);
293
294 /* Skip the parameter length, we need to add it at the end */
295 p_rsp_param_len = p_rsp;
296 p_rsp += 2;
297
298 UINT16_TO_BE_STREAM(p_rsp, error_code);
299
300 /* Unplugfest example traces do not have any error text */
301 if (p_error_text)
302 ARRAY_TO_BE_STREAM(p_rsp, p_error_text, (int)strlen(p_error_text));
303
304 /* Go back and put the parameter length into the buffer */
305 rsp_param_len = p_rsp - p_rsp_param_len - 2;
306 UINT16_TO_BE_STREAM(p_rsp_param_len, rsp_param_len);
307
308 /* Set the length of the SDP data in the buffer */
309 p_buf->len = p_rsp - p_rsp_start;
310
311 /* Send the buffer through L2CAP */
312 L2CA_DataWrite(p_ccb->connection_id, p_buf);
313 }
314
315 /*******************************************************************************
316 *
317 * Function sdpu_extract_uid_seq
318 *
319 * Description This function extracts a UUID sequence from the passed input
320 * buffer, and puts it into the passed output list.
321 *
322 * Returns Pointer to next byte in the input buffer after the sequence.
323 *
324 ******************************************************************************/
sdpu_extract_uid_seq(uint8_t * p,uint16_t param_len,tSDP_UUID_SEQ * p_seq)325 uint8_t* sdpu_extract_uid_seq(uint8_t* p, uint16_t param_len,
326 tSDP_UUID_SEQ* p_seq) {
327 uint8_t* p_seq_end;
328 uint8_t descr, type, size;
329 uint32_t seq_len, uuid_len;
330
331 /* Assume none found */
332 p_seq->num_uids = 0;
333
334 /* A UID sequence is composed of a bunch of UIDs. */
335
336 BE_STREAM_TO_UINT8(descr, p);
337 type = descr >> 3;
338 size = descr & 7;
339
340 if (type != DATA_ELE_SEQ_DESC_TYPE) return (NULL);
341
342 switch (size) {
343 case SIZE_TWO_BYTES:
344 seq_len = 2;
345 break;
346 case SIZE_FOUR_BYTES:
347 seq_len = 4;
348 break;
349 case SIZE_SIXTEEN_BYTES:
350 seq_len = 16;
351 break;
352 case SIZE_IN_NEXT_BYTE:
353 BE_STREAM_TO_UINT8(seq_len, p);
354 break;
355 case SIZE_IN_NEXT_WORD:
356 BE_STREAM_TO_UINT16(seq_len, p);
357 break;
358 case SIZE_IN_NEXT_LONG:
359 BE_STREAM_TO_UINT32(seq_len, p);
360 break;
361 default:
362 return (NULL);
363 }
364
365 if (seq_len >= param_len) return (NULL);
366
367 p_seq_end = p + seq_len;
368
369 /* Loop through, extracting the UIDs */
370 for (; p < p_seq_end;) {
371 BE_STREAM_TO_UINT8(descr, p);
372 type = descr >> 3;
373 size = descr & 7;
374
375 if (type != UUID_DESC_TYPE) return (NULL);
376
377 switch (size) {
378 case SIZE_TWO_BYTES:
379 uuid_len = 2;
380 break;
381 case SIZE_FOUR_BYTES:
382 uuid_len = 4;
383 break;
384 case SIZE_SIXTEEN_BYTES:
385 uuid_len = 16;
386 break;
387 case SIZE_IN_NEXT_BYTE:
388 BE_STREAM_TO_UINT8(uuid_len, p);
389 break;
390 case SIZE_IN_NEXT_WORD:
391 BE_STREAM_TO_UINT16(uuid_len, p);
392 break;
393 case SIZE_IN_NEXT_LONG:
394 BE_STREAM_TO_UINT32(uuid_len, p);
395 break;
396 default:
397 return (NULL);
398 }
399
400 /* If UUID length is valid, copy it across */
401 if ((uuid_len == 2) || (uuid_len == 4) || (uuid_len == 16)) {
402 p_seq->uuid_entry[p_seq->num_uids].len = (uint16_t)uuid_len;
403 BE_STREAM_TO_ARRAY(p, p_seq->uuid_entry[p_seq->num_uids].value,
404 (int)uuid_len);
405 p_seq->num_uids++;
406 } else
407 return (NULL);
408
409 /* We can only do so many */
410 if (p_seq->num_uids >= MAX_UUIDS_PER_SEQ) return (NULL);
411 }
412
413 if (p != p_seq_end) return (NULL);
414
415 return (p);
416 }
417
418 /*******************************************************************************
419 *
420 * Function sdpu_extract_attr_seq
421 *
422 * Description This function extracts an attribute sequence from the passed
423 * input buffer, and puts it into the passed output list.
424 *
425 * Returns Pointer to next byte in the input buffer after the sequence.
426 *
427 ******************************************************************************/
sdpu_extract_attr_seq(uint8_t * p,uint16_t param_len,tSDP_ATTR_SEQ * p_seq)428 uint8_t* sdpu_extract_attr_seq(uint8_t* p, uint16_t param_len,
429 tSDP_ATTR_SEQ* p_seq) {
430 uint8_t* p_end_list;
431 uint8_t descr, type, size;
432 uint32_t list_len, attr_len;
433
434 /* Assume none found */
435 p_seq->num_attr = 0;
436
437 /* Get attribute sequence info */
438 BE_STREAM_TO_UINT8(descr, p);
439 type = descr >> 3;
440 size = descr & 7;
441
442 if (type != DATA_ELE_SEQ_DESC_TYPE) return (p);
443
444 switch (size) {
445 case SIZE_IN_NEXT_BYTE:
446 BE_STREAM_TO_UINT8(list_len, p);
447 break;
448
449 case SIZE_IN_NEXT_WORD:
450 BE_STREAM_TO_UINT16(list_len, p);
451 break;
452
453 case SIZE_IN_NEXT_LONG:
454 BE_STREAM_TO_UINT32(list_len, p);
455 break;
456
457 default:
458 return (p);
459 }
460
461 if (list_len > param_len) return (p);
462
463 p_end_list = p + list_len;
464
465 /* Loop through, extracting the attribute IDs */
466 for (; p < p_end_list;) {
467 BE_STREAM_TO_UINT8(descr, p);
468 type = descr >> 3;
469 size = descr & 7;
470
471 if (type != UINT_DESC_TYPE) return (p);
472
473 switch (size) {
474 case SIZE_TWO_BYTES:
475 attr_len = 2;
476 break;
477 case SIZE_FOUR_BYTES:
478 attr_len = 4;
479 break;
480 case SIZE_IN_NEXT_BYTE:
481 BE_STREAM_TO_UINT8(attr_len, p);
482 break;
483 case SIZE_IN_NEXT_WORD:
484 BE_STREAM_TO_UINT16(attr_len, p);
485 break;
486 case SIZE_IN_NEXT_LONG:
487 BE_STREAM_TO_UINT32(attr_len, p);
488 break;
489 default:
490 return (NULL);
491 break;
492 }
493
494 /* Attribute length must be 2-bytes or 4-bytes for a paired entry. */
495 if (attr_len == 2) {
496 BE_STREAM_TO_UINT16(p_seq->attr_entry[p_seq->num_attr].start, p);
497 p_seq->attr_entry[p_seq->num_attr].end =
498 p_seq->attr_entry[p_seq->num_attr].start;
499 } else if (attr_len == 4) {
500 BE_STREAM_TO_UINT16(p_seq->attr_entry[p_seq->num_attr].start, p);
501 BE_STREAM_TO_UINT16(p_seq->attr_entry[p_seq->num_attr].end, p);
502 } else
503 return (NULL);
504
505 /* We can only do so many */
506 if (++p_seq->num_attr >= MAX_ATTR_PER_SEQ) return (NULL);
507 }
508
509 return (p);
510 }
511
512 /*******************************************************************************
513 *
514 * Function sdpu_get_len_from_type
515 *
516 * Description This function gets the length
517 *
518 * Returns void
519 *
520 ******************************************************************************/
sdpu_get_len_from_type(uint8_t * p,uint8_t type,uint32_t * p_len)521 uint8_t* sdpu_get_len_from_type(uint8_t* p, uint8_t type, uint32_t* p_len) {
522 uint8_t u8;
523 uint16_t u16;
524 uint32_t u32;
525
526 switch (type & 7) {
527 case SIZE_ONE_BYTE:
528 *p_len = 1;
529 break;
530 case SIZE_TWO_BYTES:
531 *p_len = 2;
532 break;
533 case SIZE_FOUR_BYTES:
534 *p_len = 4;
535 break;
536 case SIZE_EIGHT_BYTES:
537 *p_len = 8;
538 break;
539 case SIZE_SIXTEEN_BYTES:
540 *p_len = 16;
541 break;
542 case SIZE_IN_NEXT_BYTE:
543 BE_STREAM_TO_UINT8(u8, p);
544 *p_len = u8;
545 break;
546 case SIZE_IN_NEXT_WORD:
547 BE_STREAM_TO_UINT16(u16, p);
548 *p_len = u16;
549 break;
550 case SIZE_IN_NEXT_LONG:
551 BE_STREAM_TO_UINT32(u32, p);
552 *p_len = (uint16_t)u32;
553 break;
554 }
555
556 return (p);
557 }
558
559 /*******************************************************************************
560 *
561 * Function sdpu_is_base_uuid
562 *
563 * Description This function checks a 128-bit UUID with the base to see if
564 * it matches. Only the last 12 bytes are compared.
565 *
566 * Returns true if matched, else false
567 *
568 ******************************************************************************/
sdpu_is_base_uuid(uint8_t * p_uuid)569 bool sdpu_is_base_uuid(uint8_t* p_uuid) {
570 uint16_t xx;
571
572 for (xx = 4; xx < MAX_UUID_SIZE; xx++)
573 if (p_uuid[xx] != sdp_base_uuid[xx]) return (false);
574
575 /* If here, matched */
576 return (true);
577 }
578
579 /*******************************************************************************
580 *
581 * Function sdpu_compare_uuid_arrays
582 *
583 * Description This function compares 2 BE UUIDs. If needed, they are
584 * expanded to 128-bit UUIDs, then compared.
585 *
586 * NOTE it is assumed that the arrays are in Big Endian format
587 *
588 * Returns true if matched, else false
589 *
590 ******************************************************************************/
sdpu_compare_uuid_arrays(uint8_t * p_uuid1,uint32_t len1,uint8_t * p_uuid2,uint16_t len2)591 bool sdpu_compare_uuid_arrays(uint8_t* p_uuid1, uint32_t len1, uint8_t* p_uuid2,
592 uint16_t len2) {
593 uint8_t nu1[MAX_UUID_SIZE];
594 uint8_t nu2[MAX_UUID_SIZE];
595
596 if (((len1 != 2) && (len1 != 4) && (len1 != 16)) ||
597 ((len2 != 2) && (len2 != 4) && (len2 != 16))) {
598 SDP_TRACE_ERROR("%s: invalid length", __func__);
599 return false;
600 }
601
602 /* If lengths match, do a straight compare */
603 if (len1 == len2) {
604 if (len1 == 2)
605 return ((p_uuid1[0] == p_uuid2[0]) && (p_uuid1[1] == p_uuid2[1]));
606 if (len1 == 4)
607 return ((p_uuid1[0] == p_uuid2[0]) && (p_uuid1[1] == p_uuid2[1]) &&
608 (p_uuid1[2] == p_uuid2[2]) && (p_uuid1[3] == p_uuid2[3]));
609 else
610 return (memcmp(p_uuid1, p_uuid2, (size_t)len1) == 0);
611 } else if (len1 > len2) {
612 /* If the len1 was 4-byte, (so len2 is 2-byte), compare on the fly */
613 if (len1 == 4) {
614 return ((p_uuid1[0] == 0) && (p_uuid1[1] == 0) &&
615 (p_uuid1[2] == p_uuid2[0]) && (p_uuid1[3] == p_uuid2[1]));
616 } else {
617 /* Normalize UUIDs to 16-byte form, then compare. Len1 must be 16 */
618 memcpy(nu1, p_uuid1, MAX_UUID_SIZE);
619 memcpy(nu2, sdp_base_uuid, MAX_UUID_SIZE);
620
621 if (len2 == 4)
622 memcpy(nu2, p_uuid2, len2);
623 else if (len2 == 2)
624 memcpy(nu2 + 2, p_uuid2, len2);
625
626 return (memcmp(nu1, nu2, MAX_UUID_SIZE) == 0);
627 }
628 } else {
629 /* len2 is greater than len1 */
630 /* If the len2 was 4-byte, (so len1 is 2-byte), compare on the fly */
631 if (len2 == 4) {
632 return ((p_uuid2[0] == 0) && (p_uuid2[1] == 0) &&
633 (p_uuid2[2] == p_uuid1[0]) && (p_uuid2[3] == p_uuid1[1]));
634 } else {
635 /* Normalize UUIDs to 16-byte form, then compare. Len1 must be 16 */
636 memcpy(nu2, p_uuid2, MAX_UUID_SIZE);
637 memcpy(nu1, sdp_base_uuid, MAX_UUID_SIZE);
638
639 if (len1 == 4)
640 memcpy(nu1, p_uuid1, (size_t)len1);
641 else if (len1 == 2)
642 memcpy(nu1 + 2, p_uuid1, (size_t)len1);
643
644 return (memcmp(nu1, nu2, MAX_UUID_SIZE) == 0);
645 }
646 }
647 }
648
649 /*******************************************************************************
650 *
651 * Function sdpu_compare_bt_uuids
652 *
653 * Description This function compares 2 BT UUID structures.
654 *
655 * NOTE it is assumed that BT UUID structures are compressed to the
656 * smallest possible UUIDs (by removing the base SDP UUID)
657 *
658 * Returns true if matched, else false
659 *
660 ******************************************************************************/
sdpu_compare_bt_uuids(tBT_UUID * p_uuid1,tBT_UUID * p_uuid2)661 bool sdpu_compare_bt_uuids(tBT_UUID* p_uuid1, tBT_UUID* p_uuid2) {
662 /* Lengths must match for BT UUIDs to match */
663 if (p_uuid1->len == p_uuid2->len) {
664 if (p_uuid1->len == 2)
665 return (p_uuid1->uu.uuid16 == p_uuid2->uu.uuid16);
666 else if (p_uuid1->len == 4)
667 return (p_uuid1->uu.uuid32 == p_uuid2->uu.uuid32);
668 else if (!memcmp(p_uuid1->uu.uuid128, p_uuid2->uu.uuid128, 16))
669 return (true);
670 }
671
672 return (false);
673 }
674
675 /*******************************************************************************
676 *
677 * Function sdpu_compare_uuid_with_attr
678 *
679 * Description This function compares a BT UUID structure with the UUID in
680 * an SDP attribute record. If needed, they are expanded to
681 * 128-bit UUIDs, then compared.
682 *
683 * NOTE - it is assumed that BT UUID structures are compressed to the
684 * smallest possible UUIDs (by removing the base SDP UUID).
685 * - it is also assumed that the discovery atribute is compressed
686 * to the smallest possible
687 *
688 * Returns true if matched, else false
689 *
690 ******************************************************************************/
sdpu_compare_uuid_with_attr(tBT_UUID * p_btuuid,tSDP_DISC_ATTR * p_attr)691 bool sdpu_compare_uuid_with_attr(tBT_UUID* p_btuuid, tSDP_DISC_ATTR* p_attr) {
692 uint16_t attr_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
693
694 /* Since both UUIDs are compressed, lengths must match */
695 if (p_btuuid->len != attr_len) return (false);
696
697 if (p_btuuid->len == 2)
698 return (bool)(p_btuuid->uu.uuid16 == p_attr->attr_value.v.u16);
699 else if (p_btuuid->len == 4)
700 return (bool)(p_btuuid->uu.uuid32 == p_attr->attr_value.v.u32);
701 else if (!memcmp(p_btuuid->uu.uuid128, (void*)p_attr->attr_value.v.array,
702 MAX_UUID_SIZE))
703 return (true);
704
705 return (false);
706 }
707
708 /*******************************************************************************
709 *
710 * Function sdpu_sort_attr_list
711 *
712 * Description sorts a list of attributes in numeric order from lowest to
713 * highest to conform to SDP specification
714 *
715 * Returns void
716 *
717 ******************************************************************************/
sdpu_sort_attr_list(uint16_t num_attr,tSDP_DISCOVERY_DB * p_db)718 void sdpu_sort_attr_list(uint16_t num_attr, tSDP_DISCOVERY_DB* p_db) {
719 uint16_t i;
720 uint16_t x;
721
722 /* Done if no attributes to sort */
723 if (num_attr <= 1) {
724 return;
725 } else if (num_attr > SDP_MAX_ATTR_FILTERS) {
726 num_attr = SDP_MAX_ATTR_FILTERS;
727 }
728
729 num_attr--; /* for the for-loop */
730 for (i = 0; i < num_attr;) {
731 if (p_db->attr_filters[i] > p_db->attr_filters[i + 1]) {
732 /* swap the attribute IDs and start from the beginning */
733 x = p_db->attr_filters[i];
734 p_db->attr_filters[i] = p_db->attr_filters[i + 1];
735 p_db->attr_filters[i + 1] = x;
736
737 i = 0;
738 } else
739 i++;
740 }
741 }
742
743 /*******************************************************************************
744 *
745 * Function sdpu_get_list_len
746 *
747 * Description gets the total list length in the sdp database for a given
748 * uid sequence and attr sequence
749 *
750 * Returns void
751 *
752 ******************************************************************************/
sdpu_get_list_len(tSDP_UUID_SEQ * uid_seq,tSDP_ATTR_SEQ * attr_seq)753 uint16_t sdpu_get_list_len(tSDP_UUID_SEQ* uid_seq, tSDP_ATTR_SEQ* attr_seq) {
754 tSDP_RECORD* p_rec;
755 uint16_t len = 0;
756 uint16_t len1;
757
758 for (p_rec = sdp_db_service_search(NULL, uid_seq); p_rec;
759 p_rec = sdp_db_service_search(p_rec, uid_seq)) {
760 len += 3;
761
762 len1 = sdpu_get_attrib_seq_len(p_rec, attr_seq);
763
764 if (len1 != 0)
765 len += len1;
766 else
767 len -= 3;
768 }
769 return len;
770 }
771
772 /*******************************************************************************
773 *
774 * Function sdpu_get_attrib_seq_len
775 *
776 * Description gets the length of the specific attributes in a given
777 * sdp record
778 *
779 * Returns void
780 *
781 ******************************************************************************/
sdpu_get_attrib_seq_len(tSDP_RECORD * p_rec,tSDP_ATTR_SEQ * attr_seq)782 uint16_t sdpu_get_attrib_seq_len(tSDP_RECORD* p_rec, tSDP_ATTR_SEQ* attr_seq) {
783 tSDP_ATTRIBUTE* p_attr;
784 uint16_t len1 = 0;
785 uint16_t xx;
786 bool is_range = false;
787 uint16_t start_id = 0, end_id = 0;
788
789 for (xx = 0; xx < attr_seq->num_attr; xx++) {
790 if (is_range == false) {
791 start_id = attr_seq->attr_entry[xx].start;
792 end_id = attr_seq->attr_entry[xx].end;
793 }
794 p_attr = sdp_db_find_attr_in_rec(p_rec, start_id, end_id);
795 if (p_attr) {
796 len1 += sdpu_get_attrib_entry_len(p_attr);
797
798 /* If doing a range, stick with this one till no more attributes found */
799 if (start_id != end_id) {
800 /* Update for next time through */
801 start_id = p_attr->id + 1;
802 xx--;
803 is_range = true;
804 } else
805 is_range = false;
806 } else
807 is_range = false;
808 }
809 return len1;
810 }
811
812 /*******************************************************************************
813 *
814 * Function sdpu_get_attrib_entry_len
815 *
816 * Description gets the length of a specific attribute
817 *
818 * Returns void
819 *
820 ******************************************************************************/
sdpu_get_attrib_entry_len(tSDP_ATTRIBUTE * p_attr)821 uint16_t sdpu_get_attrib_entry_len(tSDP_ATTRIBUTE* p_attr) {
822 uint16_t len = 3;
823
824 /* the attribute is in the db record.
825 * assuming the attribute len is less than SDP_MAX_ATTR_LEN */
826 switch (p_attr->type) {
827 case TEXT_STR_DESC_TYPE: /* 4 */
828 case DATA_ELE_SEQ_DESC_TYPE: /* 6 */
829 case DATA_ELE_ALT_DESC_TYPE: /* 7 */
830 case URL_DESC_TYPE: /* 8 */
831 #if (SDP_MAX_ATTR_LEN > 0xFFFF)
832 if (p_attr->len > 0xFFFF) {
833 len += 5;
834 } else
835 #endif /* 0xFFFF - 0xFF */
836 #if (SDP_MAX_ATTR_LEN > 0xFF)
837 if (p_attr->len > 0xFF) {
838 len += 3;
839 } else
840 #endif /* 0xFF and less*/
841 {
842 len += 2;
843 }
844 len += p_attr->len;
845 return len;
846 }
847
848 /* Now, the attribute value */
849 switch (p_attr->len) {
850 case 1:
851 case 2:
852 case 4:
853 case 8:
854 case 16:
855 len += 1;
856 break;
857 default:
858 len += 2;
859 break;
860 }
861
862 len += p_attr->len;
863 return len;
864 }
865
866 /*******************************************************************************
867 *
868 * Function sdpu_build_partial_attrib_entry
869 *
870 * Description This function fills a buffer with partial attribute. It is
871 * assumed that the maximum size of any attribute is 256 bytes.
872 *
873 * p_out: output buffer
874 * p_attr: attribute to be copied partially into p_out
875 * rem_len: num bytes to copy into p_out
876 * offset: current start offset within the attr that needs to
877 * be copied
878 *
879 * Returns Pointer to next byte in the output buffer.
880 * offset is also updated
881 *
882 ******************************************************************************/
sdpu_build_partial_attrib_entry(uint8_t * p_out,tSDP_ATTRIBUTE * p_attr,uint16_t len,uint16_t * offset)883 uint8_t* sdpu_build_partial_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr,
884 uint16_t len, uint16_t* offset) {
885 uint8_t* p_attr_buff =
886 (uint8_t*)osi_malloc(sizeof(uint8_t) * SDP_MAX_ATTR_LEN);
887 sdpu_build_attrib_entry(p_attr_buff, p_attr);
888
889 uint16_t attr_len = sdpu_get_attrib_entry_len(p_attr);
890
891 if (len > SDP_MAX_ATTR_LEN) {
892 SDP_TRACE_ERROR("%s len %d exceeds SDP_MAX_ATTR_LEN", __func__, len);
893 len = SDP_MAX_ATTR_LEN;
894 }
895
896 size_t len_to_copy =
897 ((attr_len - *offset) < len) ? (attr_len - *offset) : len;
898 memcpy(p_out, &p_attr_buff[*offset], len_to_copy);
899
900 p_out = &p_out[len_to_copy];
901 *offset += len_to_copy;
902
903 osi_free(p_attr_buff);
904 return p_out;
905 }
906
907 /*******************************************************************************
908 *
909 * Function sdpu_uuid16_to_uuid128
910 *
911 * Description This function converts UUID-16 to UUID-128 by including the
912 * base UUID
913 *
914 * uuid16: 2-byte UUID
915 * p_uuid128: Expanded 128-bit UUID
916 *
917 * Returns None
918 *
919 ******************************************************************************/
sdpu_uuid16_to_uuid128(uint16_t uuid16,uint8_t * p_uuid128)920 void sdpu_uuid16_to_uuid128(uint16_t uuid16, uint8_t* p_uuid128) {
921 uint16_t uuid16_bo;
922 memset(p_uuid128, 0, 16);
923
924 memcpy(p_uuid128, sdp_base_uuid, MAX_UUID_SIZE);
925 uuid16_bo = ntohs(uuid16);
926 memcpy(p_uuid128 + 2, &uuid16_bo, sizeof(uint16_t));
927 }
928