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 * p_end,uint8_t type,uint32_t * p_len)546 uint8_t* sdpu_get_len_from_type(uint8_t* p, uint8_t* p_end, uint8_t type,
547 uint32_t* p_len) {
548 uint8_t u8;
549 uint16_t u16;
550 uint32_t u32;
551
552 switch (type & 7) {
553 case SIZE_ONE_BYTE:
554 *p_len = 1;
555 break;
556 case SIZE_TWO_BYTES:
557 *p_len = 2;
558 break;
559 case SIZE_FOUR_BYTES:
560 *p_len = 4;
561 break;
562 case SIZE_EIGHT_BYTES:
563 *p_len = 8;
564 break;
565 case SIZE_SIXTEEN_BYTES:
566 *p_len = 16;
567 break;
568 case SIZE_IN_NEXT_BYTE:
569 if (p + 1 > p_end) {
570 *p_len = 0;
571 return NULL;
572 }
573 BE_STREAM_TO_UINT8(u8, p);
574 *p_len = u8;
575 break;
576 case SIZE_IN_NEXT_WORD:
577 if (p + 2 > p_end) {
578 *p_len = 0;
579 return NULL;
580 }
581 BE_STREAM_TO_UINT16(u16, p);
582 *p_len = u16;
583 break;
584 case SIZE_IN_NEXT_LONG:
585 if (p + 4 > p_end) {
586 *p_len = 0;
587 return NULL;
588 }
589 BE_STREAM_TO_UINT32(u32, p);
590 *p_len = (uint16_t)u32;
591 break;
592 }
593
594 return (p);
595 }
596
597 /*******************************************************************************
598 *
599 * Function sdpu_is_base_uuid
600 *
601 * Description This function checks a 128-bit UUID with the base to see if
602 * it matches. Only the last 12 bytes are compared.
603 *
604 * Returns true if matched, else false
605 *
606 ******************************************************************************/
sdpu_is_base_uuid(uint8_t * p_uuid)607 bool sdpu_is_base_uuid(uint8_t* p_uuid) {
608 uint16_t xx;
609
610 for (xx = 4; xx < Uuid::kNumBytes128; xx++)
611 if (p_uuid[xx] != sdp_base_uuid[xx]) return (false);
612
613 /* If here, matched */
614 return (true);
615 }
616
617 /*******************************************************************************
618 *
619 * Function sdpu_compare_uuid_arrays
620 *
621 * Description This function compares 2 BE UUIDs. If needed, they are
622 * expanded to 128-bit UUIDs, then compared.
623 *
624 * NOTE it is assumed that the arrays are in Big Endian format
625 *
626 * Returns true if matched, else false
627 *
628 ******************************************************************************/
sdpu_compare_uuid_arrays(uint8_t * p_uuid1,uint32_t len1,uint8_t * p_uuid2,uint16_t len2)629 bool sdpu_compare_uuid_arrays(uint8_t* p_uuid1, uint32_t len1, uint8_t* p_uuid2,
630 uint16_t len2) {
631 uint8_t nu1[Uuid::kNumBytes128];
632 uint8_t nu2[Uuid::kNumBytes128];
633
634 if (((len1 != 2) && (len1 != 4) && (len1 != 16)) ||
635 ((len2 != 2) && (len2 != 4) && (len2 != 16))) {
636 SDP_TRACE_ERROR("%s: invalid length", __func__);
637 return false;
638 }
639
640 /* If lengths match, do a straight compare */
641 if (len1 == len2) {
642 if (len1 == 2)
643 return ((p_uuid1[0] == p_uuid2[0]) && (p_uuid1[1] == p_uuid2[1]));
644 if (len1 == 4)
645 return ((p_uuid1[0] == p_uuid2[0]) && (p_uuid1[1] == p_uuid2[1]) &&
646 (p_uuid1[2] == p_uuid2[2]) && (p_uuid1[3] == p_uuid2[3]));
647 else
648 return (memcmp(p_uuid1, p_uuid2, (size_t)len1) == 0);
649 } else if (len1 > len2) {
650 /* If the len1 was 4-byte, (so len2 is 2-byte), compare on the fly */
651 if (len1 == 4) {
652 return ((p_uuid1[0] == 0) && (p_uuid1[1] == 0) &&
653 (p_uuid1[2] == p_uuid2[0]) && (p_uuid1[3] == p_uuid2[1]));
654 } else {
655 /* Normalize UUIDs to 16-byte form, then compare. Len1 must be 16 */
656 memcpy(nu1, p_uuid1, Uuid::kNumBytes128);
657 memcpy(nu2, sdp_base_uuid, Uuid::kNumBytes128);
658
659 if (len2 == 4)
660 memcpy(nu2, p_uuid2, len2);
661 else if (len2 == 2)
662 memcpy(nu2 + 2, p_uuid2, len2);
663
664 return (memcmp(nu1, nu2, Uuid::kNumBytes128) == 0);
665 }
666 } else {
667 /* len2 is greater than len1 */
668 /* If the len2 was 4-byte, (so len1 is 2-byte), compare on the fly */
669 if (len2 == 4) {
670 return ((p_uuid2[0] == 0) && (p_uuid2[1] == 0) &&
671 (p_uuid2[2] == p_uuid1[0]) && (p_uuid2[3] == p_uuid1[1]));
672 } else {
673 /* Normalize UUIDs to 16-byte form, then compare. Len1 must be 16 */
674 memcpy(nu2, p_uuid2, Uuid::kNumBytes128);
675 memcpy(nu1, sdp_base_uuid, Uuid::kNumBytes128);
676
677 if (len1 == 4)
678 memcpy(nu1, p_uuid1, (size_t)len1);
679 else if (len1 == 2)
680 memcpy(nu1 + 2, p_uuid1, (size_t)len1);
681
682 return (memcmp(nu1, nu2, Uuid::kNumBytes128) == 0);
683 }
684 }
685 }
686
687 /*******************************************************************************
688 *
689 * Function sdpu_compare_uuid_with_attr
690 *
691 * Description This function compares a BT UUID structure with the UUID in
692 * an SDP attribute record. If needed, they are expanded to
693 * 128-bit UUIDs, then compared.
694 *
695 * NOTE - it is assumed that BT UUID structures are compressed to the
696 * smallest possible UUIDs (by removing the base SDP UUID).
697 * - it is also assumed that the discovery atribute is compressed
698 * to the smallest possible
699 *
700 * Returns true if matched, else false
701 *
702 ******************************************************************************/
sdpu_compare_uuid_with_attr(const Uuid & uuid,tSDP_DISC_ATTR * p_attr)703 bool sdpu_compare_uuid_with_attr(const Uuid& uuid, tSDP_DISC_ATTR* p_attr) {
704 int len = uuid.GetShortestRepresentationSize();
705 if (len == 2) return uuid.As16Bit() == p_attr->attr_value.v.u16;
706 if (len == 4) return uuid.As32Bit() == p_attr->attr_value.v.u32;
707 if (memcmp(uuid.To128BitBE().data(), (void*)p_attr->attr_value.v.array,
708 Uuid::kNumBytes128) == 0)
709 return (true);
710
711 return (false);
712 }
713
714 /*******************************************************************************
715 *
716 * Function sdpu_sort_attr_list
717 *
718 * Description sorts a list of attributes in numeric order from lowest to
719 * highest to conform to SDP specification
720 *
721 * Returns void
722 *
723 ******************************************************************************/
sdpu_sort_attr_list(uint16_t num_attr,tSDP_DISCOVERY_DB * p_db)724 void sdpu_sort_attr_list(uint16_t num_attr, tSDP_DISCOVERY_DB* p_db) {
725 uint16_t i;
726 uint16_t x;
727
728 /* Done if no attributes to sort */
729 if (num_attr <= 1) {
730 return;
731 } else if (num_attr > SDP_MAX_ATTR_FILTERS) {
732 num_attr = SDP_MAX_ATTR_FILTERS;
733 }
734
735 num_attr--; /* for the for-loop */
736 for (i = 0; i < num_attr;) {
737 if (p_db->attr_filters[i] > p_db->attr_filters[i + 1]) {
738 /* swap the attribute IDs and start from the beginning */
739 x = p_db->attr_filters[i];
740 p_db->attr_filters[i] = p_db->attr_filters[i + 1];
741 p_db->attr_filters[i + 1] = x;
742
743 i = 0;
744 } else
745 i++;
746 }
747 }
748
749 /*******************************************************************************
750 *
751 * Function sdpu_get_list_len
752 *
753 * Description gets the total list length in the sdp database for a given
754 * uid sequence and attr sequence
755 *
756 * Returns void
757 *
758 ******************************************************************************/
sdpu_get_list_len(tSDP_UUID_SEQ * uid_seq,tSDP_ATTR_SEQ * attr_seq)759 uint16_t sdpu_get_list_len(tSDP_UUID_SEQ* uid_seq, tSDP_ATTR_SEQ* attr_seq) {
760 tSDP_RECORD* p_rec;
761 uint16_t len = 0;
762 uint16_t len1;
763
764 for (p_rec = sdp_db_service_search(NULL, uid_seq); p_rec;
765 p_rec = sdp_db_service_search(p_rec, uid_seq)) {
766 len += 3;
767
768 len1 = sdpu_get_attrib_seq_len(p_rec, attr_seq);
769
770 if (len1 != 0)
771 len += len1;
772 else
773 len -= 3;
774 }
775 return len;
776 }
777
778 /*******************************************************************************
779 *
780 * Function sdpu_get_attrib_seq_len
781 *
782 * Description gets the length of the specific attributes in a given
783 * sdp record
784 *
785 * Returns void
786 *
787 ******************************************************************************/
sdpu_get_attrib_seq_len(tSDP_RECORD * p_rec,tSDP_ATTR_SEQ * attr_seq)788 uint16_t sdpu_get_attrib_seq_len(tSDP_RECORD* p_rec, tSDP_ATTR_SEQ* attr_seq) {
789 tSDP_ATTRIBUTE* p_attr;
790 uint16_t len1 = 0;
791 uint16_t xx;
792 bool is_range = false;
793 uint16_t start_id = 0, end_id = 0;
794
795 for (xx = 0; xx < attr_seq->num_attr; xx++) {
796 if (!is_range) {
797 start_id = attr_seq->attr_entry[xx].start;
798 end_id = attr_seq->attr_entry[xx].end;
799 }
800 p_attr = sdp_db_find_attr_in_rec(p_rec, start_id, end_id);
801 if (p_attr) {
802 len1 += sdpu_get_attrib_entry_len(p_attr);
803
804 /* If doing a range, stick with this one till no more attributes found */
805 if (start_id != end_id) {
806 /* Update for next time through */
807 start_id = p_attr->id + 1;
808 xx--;
809 is_range = true;
810 } else
811 is_range = false;
812 } else
813 is_range = false;
814 }
815 return len1;
816 }
817
818 /*******************************************************************************
819 *
820 * Function sdpu_get_attrib_entry_len
821 *
822 * Description gets the length of a specific attribute
823 *
824 * Returns void
825 *
826 ******************************************************************************/
sdpu_get_attrib_entry_len(tSDP_ATTRIBUTE * p_attr)827 uint16_t sdpu_get_attrib_entry_len(tSDP_ATTRIBUTE* p_attr) {
828 uint16_t len = 3;
829
830 /* the attribute is in the db record.
831 * assuming the attribute len is less than SDP_MAX_ATTR_LEN */
832 switch (p_attr->type) {
833 case TEXT_STR_DESC_TYPE: /* 4 */
834 case DATA_ELE_SEQ_DESC_TYPE: /* 6 */
835 case DATA_ELE_ALT_DESC_TYPE: /* 7 */
836 case URL_DESC_TYPE: /* 8 */
837 #if (SDP_MAX_ATTR_LEN > 0xFFFF)
838 if (p_attr->len > 0xFFFF) {
839 len += 5;
840 } else
841 #endif /* 0xFFFF - 0xFF */
842 #if (SDP_MAX_ATTR_LEN > 0xFF)
843 if (p_attr->len > 0xFF) {
844 len += 3;
845 } else
846 #endif /* 0xFF and less*/
847 {
848 len += 2;
849 }
850 len += p_attr->len;
851 return len;
852 }
853
854 /* Now, the attribute value */
855 switch (p_attr->len) {
856 case 1:
857 case 2:
858 case 4:
859 case 8:
860 case 16:
861 len += 1;
862 break;
863 default:
864 len += 2;
865 break;
866 }
867
868 len += p_attr->len;
869 return len;
870 }
871
872 /*******************************************************************************
873 *
874 * Function sdpu_build_partial_attrib_entry
875 *
876 * Description This function fills a buffer with partial attribute. It is
877 * assumed that the maximum size of any attribute is 256 bytes.
878 *
879 * p_out: output buffer
880 * p_attr: attribute to be copied partially into p_out
881 * rem_len: num bytes to copy into p_out
882 * offset: current start offset within the attr that needs to
883 * be copied
884 *
885 * Returns Pointer to next byte in the output buffer.
886 * offset is also updated
887 *
888 ******************************************************************************/
sdpu_build_partial_attrib_entry(uint8_t * p_out,tSDP_ATTRIBUTE * p_attr,uint16_t len,uint16_t * offset)889 uint8_t* sdpu_build_partial_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr,
890 uint16_t len, uint16_t* offset) {
891 uint8_t* p_attr_buff =
892 (uint8_t*)osi_malloc(sizeof(uint8_t) * SDP_MAX_ATTR_LEN);
893 sdpu_build_attrib_entry(p_attr_buff, p_attr);
894
895 uint16_t attr_len = sdpu_get_attrib_entry_len(p_attr);
896
897 if (len > SDP_MAX_ATTR_LEN) {
898 SDP_TRACE_ERROR("%s len %d exceeds SDP_MAX_ATTR_LEN", __func__, len);
899 len = SDP_MAX_ATTR_LEN;
900 }
901
902 size_t len_to_copy =
903 ((attr_len - *offset) < len) ? (attr_len - *offset) : len;
904 memcpy(p_out, &p_attr_buff[*offset], len_to_copy);
905
906 p_out = &p_out[len_to_copy];
907 *offset += len_to_copy;
908
909 osi_free(p_attr_buff);
910 return p_out;
911 }
912