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
42static 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 ******************************************************************************/
56tCONN_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 ******************************************************************************/
80tCONN_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 ******************************************************************************/
104tCONN_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 ******************************************************************************/
130void 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 ******************************************************************************/
155uint8_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 ******************************************************************************/
203uint8_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 ******************************************************************************/
278void 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 ******************************************************************************/
325uint8_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 ******************************************************************************/
428uint8_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 ******************************************************************************/
521uint8_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 ******************************************************************************/
569bool 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 ******************************************************************************/
591bool 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 ******************************************************************************/
661bool 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 ******************************************************************************/
691bool 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 ******************************************************************************/
718void 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 ******************************************************************************/
753uint16_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 ******************************************************************************/
782uint16_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 ******************************************************************************/
821uint16_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 ******************************************************************************/
883uint8_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 ******************************************************************************/
920void 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