Home | History | Annotate | Download | only in sdp
      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  ******************************************************************************/
     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  ******************************************************************************/
     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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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