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