sdp_utils.c revision a51c9d9d225e41fe36a0133f1c17fd981ea59c1d
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
43static 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*******************************************************************************/
56tCONN_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*******************************************************************************/
83tCONN_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*******************************************************************************/
113tCONN_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*******************************************************************************/
145void 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_DEBUG("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*******************************************************************************/
178UINT8 *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*******************************************************************************/
232UINT8 *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*******************************************************************************/
313void 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_WARNING ("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_ERROR ("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*******************************************************************************/
369UINT8 *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*******************************************************************************/
483UINT8 *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*******************************************************************************/
587UINT8 *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*******************************************************************************/
638BOOLEAN 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*******************************************************************************/
663BOOLEAN 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*******************************************************************************/
739BOOLEAN 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*******************************************************************************/
772BOOLEAN 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*******************************************************************************/
808void 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*******************************************************************************/
851UINT16 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*******************************************************************************/
881UINT16 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*******************************************************************************/
929UINT16 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*******************************************************************************/
1000UINT8 *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_ERROR("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*******************************************************************************/
1040void 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