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