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