1/******************************************************************************
2 *
3 *  Copyright (C) 2003-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 the GATT client utility function.
22 *
23 ******************************************************************************/
24
25#include "bt_target.h"
26
27#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
28
29#include <string.h>
30#include "utl.h"
31#include "gki.h"
32#include "bta_sys.h"
33#include "bta_gattc_int.h"
34#include "bd.h"
35
36/*****************************************************************************
37**  Constants
38*****************************************************************************/
39
40
41static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
42    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
43
44/*******************************************************************************
45**
46** Function         bta_gatt_convert_uuid16_to_uuid128
47**
48** Description      Convert a 16 bits UUID to be an standard 128 bits one.
49**
50** Returns          TRUE if two uuid match; FALSE otherwise.
51**
52*******************************************************************************/
53void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
54{
55    UINT8   *p = &uuid_128[LEN_UUID_128 - 4];
56
57    memcpy (uuid_128, base_uuid, LEN_UUID_128);
58
59    UINT16_TO_STREAM(p, uuid_16);
60}
61/*******************************************************************************
62**
63** Function         bta_gattc_uuid_compare
64**
65** Description      Compare two UUID to see if they are the same.
66**
67** Returns          TRUE if two uuid match; FALSE otherwise.
68**
69*******************************************************************************/
70BOOLEAN bta_gattc_uuid_compare (tBT_UUID src, tBT_UUID tar, BOOLEAN is_precise)
71{
72    UINT8  su[LEN_UUID_128], tu[LEN_UUID_128];
73    UINT8  *ps, *pt;
74
75    /* any of the UUID is unspecified */
76    if (src.len == 0 || tar.len == 0)
77    {
78        if (is_precise)
79            return FALSE;
80        else
81            return TRUE;
82    }
83
84    /* If both are 16-bit, we can do a simple compare */
85    if (src.len == 2 && tar.len == 2)
86    {
87        return src.uu.uuid16 == tar.uu.uuid16;
88    }
89
90    /* One or both of the UUIDs is 128-bit */
91    if (src.len == LEN_UUID_16)
92    {
93        /* convert a 16 bits UUID to 128 bits value */
94        bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
95        ps = su;
96    }
97    else
98        ps = src.uu.uuid128;
99
100    if (tar.len == LEN_UUID_16)
101    {
102        /* convert a 16 bits UUID to 128 bits value */
103        bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
104        pt = tu;
105    }
106    else
107        pt = tar.uu.uuid128;
108
109    return(memcmp(ps, pt, LEN_UUID_128) == 0);
110}
111
112/*******************************************************************************
113**
114** Function         bta_gattc_cl_get_regcb
115**
116** Description      get registration control block by client interface.
117**
118** Returns          pointer to the regcb
119**
120*******************************************************************************/
121tBTA_GATTC_RCB * bta_gattc_cl_get_regcb(UINT8 client_if)
122{
123    UINT8   i = 0;
124    tBTA_GATTC_RCB  *p_clrcb = &bta_gattc_cb.cl_rcb[0];
125
126    for (i = 0; i < BTA_GATTC_CL_MAX; i ++, p_clrcb ++)
127    {
128        if (p_clrcb->in_use &&
129            p_clrcb->client_if == client_if)
130            return p_clrcb;
131    }
132    return NULL;
133}
134/*******************************************************************************
135**
136** Function         bta_gattc_num_reg_app
137**
138** Description      find the number of registered application.
139**
140** Returns          pointer to the regcb
141**
142*******************************************************************************/
143UINT8 bta_gattc_num_reg_app(void)
144{
145    UINT8   i = 0, j = 0;
146
147    for (i = 0; i < BTA_GATTC_CL_MAX; i ++)
148    {
149        if (bta_gattc_cb.cl_rcb[i].in_use)
150            j ++;
151    }
152    return j;
153}
154/*******************************************************************************
155**
156** Function         bta_gattc_find_clcb_by_cif
157**
158** Description      get clcb by client interface and remote bd adddress
159**
160** Returns          pointer to the clcb
161**
162*******************************************************************************/
163tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda)
164{
165    tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
166    UINT8   i;
167
168    for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
169    {
170        if (p_clcb->in_use &&
171            p_clcb->p_rcb->client_if == client_if &&
172            p_clcb->p_srcb &&
173            bdcmp(p_clcb->p_srcb->server_bda, remote_bda) == 0)
174            return p_clcb;
175    }
176    return NULL;
177}
178/*******************************************************************************
179**
180** Function         bta_gattc_find_clcb_by_conn_id
181**
182** Description      get clcb by connection ID
183**
184** Returns          pointer to the clcb
185**
186*******************************************************************************/
187tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_conn_id (UINT16 conn_id)
188{
189    tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
190    UINT8 i;
191
192    for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
193    {
194        if (p_clcb->in_use &&
195            p_clcb->bta_conn_id == conn_id)
196            return p_clcb;
197    }
198    return NULL;
199}
200
201/*******************************************************************************
202**
203** Function         bta_gattc_clcb_alloc
204**
205** Description      allocate CLCB
206**
207** Returns          pointer to the clcb
208**
209*******************************************************************************/
210tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda)
211{
212    UINT8               i_clcb = 0;
213    tBTA_GATTC_CLCB     *p_clcb = NULL;
214
215    for (i_clcb = 0; i_clcb < BTA_GATTC_CLCB_MAX; i_clcb++)
216    {
217        if (!bta_gattc_cb.clcb[i_clcb].in_use)
218        {
219#if BTA_GATT_DEBUG == TRUE
220            APPL_TRACE_DEBUG1("bta_gattc_clcb_alloc: found clcb[%d] available",i_clcb);
221#endif
222            p_clcb                  = &bta_gattc_cb.clcb[i_clcb];
223            p_clcb->in_use          = TRUE;
224            bdcpy(p_clcb->bda, remote_bda);
225
226            p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
227
228            if ((p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL)
229                p_clcb->p_srcb      = bta_gattc_srcb_alloc(remote_bda);
230
231            if (p_clcb->p_rcb != NULL && p_clcb->p_srcb != NULL)
232            {
233                p_clcb->p_srcb->num_clcb ++;
234                p_clcb->p_rcb->num_clcb ++;
235            }
236            else
237            {
238                /* release this clcb if clcb or srcb allocation failed */
239                p_clcb->in_use = FALSE;
240                p_clcb = NULL;
241            }
242            break;
243        }
244    }
245    return p_clcb;
246}
247/*******************************************************************************
248**
249** Function         bta_gattc_find_alloc_clcb
250**
251** Description      find or allocate CLCB if not found.
252**
253** Returns          pointer to the clcb
254**
255*******************************************************************************/
256tBTA_GATTC_CLCB *bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda)
257{
258    tBTA_GATTC_CLCB *p_clcb ;
259
260    if ((p_clcb = bta_gattc_find_clcb_by_cif(client_if, remote_bda)) == NULL)
261    {
262        p_clcb = bta_gattc_clcb_alloc(client_if, remote_bda);
263    }
264    return p_clcb;
265}
266
267/*******************************************************************************
268**
269** Function         bta_gattc_clcb_dealloc
270**
271** Description      Deallocte a clcb
272**
273** Returns          pointer to the clcb
274**
275*******************************************************************************/
276void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
277{
278
279    if (p_clcb)
280    {
281        if (p_clcb->p_srcb->num_clcb)
282            p_clcb->p_srcb->num_clcb --;
283
284        if (p_clcb->p_rcb->num_clcb)
285            p_clcb->p_rcb->num_clcb --;
286
287        utl_freebuf((void **)&p_clcb->p_q_cmd);
288
289        APPL_TRACE_ERROR2("bta_gattc_clcb_dealloc in_use=%d conn_id=%d",p_clcb->in_use, p_clcb->bta_conn_id);
290        memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
291    }
292    else
293    {
294        APPL_TRACE_ERROR0("bta_gattc_clcb_dealloc p_clcb=NULL");
295    }
296}
297
298/*******************************************************************************
299**
300** Function         bta_gattc_find_srcb
301**
302** Description      find server cache by remote bd address
303**
304** Returns          pointer to the server cache.
305**
306*******************************************************************************/
307tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda)
308{
309    tBTA_GATTC_SERV *p_srcb = &bta_gattc_cb.known_server[0];
310    UINT8   i;
311
312    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++)
313    {
314        if (p_srcb->in_use && bdcmp(p_srcb->server_bda, bda) == 0)
315            return p_srcb;
316    }
317    return NULL;
318}
319/*******************************************************************************
320**
321** Function         bta_gattc_find_scb_by_cid
322**
323** Description      find server control block by connection ID
324**
325** Returns          pointer to the server cache.
326**
327*******************************************************************************/
328tBTA_GATTC_SERV * bta_gattc_find_scb_by_cid (UINT16 conn_id)
329{
330    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
331
332    if (p_clcb)
333        return p_clcb->p_srcb;
334    else
335        return NULL;
336}
337/*******************************************************************************
338**
339** Function         bta_gattc_srcb_alloc
340**
341** Description      allocate server cache control block
342**
343** Returns          pointer to the server cache.
344**
345*******************************************************************************/
346tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda)
347{
348    tBTA_GATTC_SERV *p_tcb = &bta_gattc_cb.known_server[0],
349                             *p_recycle = NULL;
350    BOOLEAN         found = FALSE;
351    UINT8           i;
352
353    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_tcb ++)
354    {
355        if (!p_tcb->in_use)
356        {
357            found = TRUE;
358            break;
359        }
360        else if (!p_tcb->connected)
361        {
362            p_recycle = p_tcb;
363        }
364    }
365
366    /* if not found, try to recycle one known device */
367    if (!found && !p_recycle)
368        p_tcb = NULL;
369    else if (p_recycle)
370        p_tcb = p_recycle;
371
372    if (p_tcb != NULL)
373    {
374        while (p_tcb->cache_buffer.p_first)
375            GKI_freebuf (GKI_dequeue (&p_tcb->cache_buffer));
376
377        utl_freebuf((void **)&p_tcb->p_srvc_list);
378        memset(p_tcb, 0 , sizeof(tBTA_GATTC_SERV));
379
380        p_tcb->in_use = TRUE;
381        bdcpy(p_tcb->server_bda, bda);
382    }
383    return p_tcb;
384}
385/*******************************************************************************
386**
387** Function         bta_gattc_enqueue
388**
389** Description      enqueue a client request in clcb.
390**
391** Returns          success or failure.
392**
393*******************************************************************************/
394BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
395{
396    BOOLEAN in_q = FALSE;
397
398    if (p_clcb->p_q_cmd == NULL)
399    {
400        p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(sizeof(tBTA_GATTC_DATA));
401
402        if (p_data)
403            memcpy(p_clcb->p_q_cmd, p_data, sizeof(tBTA_GATTC_DATA));
404
405        in_q = TRUE;
406    }
407    else
408    {
409        APPL_TRACE_ERROR0("already has a pending command!!");
410        /* skip the callback now. ----- need to send callback ? */
411    }
412    return in_q;
413}
414/*******************************************************************************
415**
416** Function         bta_gattc_pack_attr_uuid
417**
418** Description      pack UUID into a stream.
419**
420** Returns
421**
422*******************************************************************************/
423void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR   *p_attr, tBT_UUID *p_uuid)
424{
425    UINT8 *pp = (UINT8 *)p_attr->p_uuid;
426
427    memset(p_uuid, 0, sizeof(tBT_UUID));
428
429    p_uuid->len = p_attr->uuid_len;
430
431    if (p_attr->uuid_len == LEN_UUID_16)
432    {
433        STREAM_TO_UINT16(p_uuid->uu.uuid16, pp);
434    }
435    else
436    {
437        memcpy(p_uuid->uu.uuid128, pp, LEN_UUID_128);
438    }
439
440    return;
441}
442/*******************************************************************************
443**
444** Function         bta_gattc_check_notif_registry
445**
446** Description      check if the service notificaition has been registered.
447**
448** Returns
449**
450*******************************************************************************/
451BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV *p_srcb,
452                                       tBTA_GATTC_NOTIFY  *p_notify)
453{
454    UINT8           i;
455
456    for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
457    {
458        if (p_clreg->notif_reg[i].in_use &&
459            bdcmp(p_clreg->notif_reg[i].remote_bda, p_srcb->server_bda) == 0 &&
460            (bta_gattc_uuid_compare(p_clreg->notif_reg[i].char_id.srvc_id.id.uuid, p_notify->char_id.srvc_id.id.uuid, FALSE) &&
461              p_clreg->notif_reg[i].char_id.srvc_id.id.inst_id == p_notify->char_id.srvc_id.id.inst_id &&
462              p_clreg->notif_reg[i].char_id.srvc_id.is_primary == p_notify->char_id.srvc_id.is_primary  &&
463              bta_gattc_uuid_compare(p_clreg->notif_reg[i].char_id.char_id.uuid, p_notify->char_id.char_id.uuid, FALSE) &&
464              p_clreg->notif_reg[i].char_id.char_id.inst_id == p_notify->char_id.char_id.inst_id)
465           )
466        {
467            APPL_TRACE_DEBUG0("Notification registered!");
468            return TRUE;
469        }
470    }
471    return FALSE;
472
473}
474/*******************************************************************************
475**
476** Function         bta_gattc_clear_notif_registration
477**
478** Description      clear up the notification registration information by BD_ADDR.
479**
480** Returns          None.
481**
482*******************************************************************************/
483void bta_gattc_clear_notif_registration(UINT16 conn_id)
484{
485    BD_ADDR             remote_bda;
486    tBTA_GATTC_IF       gatt_if;
487    tBTA_GATTC_RCB      *p_clrcb ;
488    UINT8       i;
489
490    if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda))
491    {
492        if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL)
493        {
494            for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
495            {
496                if (p_clrcb->notif_reg[i].in_use && !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda))
497                    memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
498            }
499        }
500    }
501    else
502    {
503        APPL_TRACE_ERROR0("can not clear indication/notif registration for unknown app");
504    }
505    return;
506}
507
508/*******************************************************************************
509**
510** Function         bta_gattc_pack_cb_data
511**
512** Description      pack the data from read response into callback data structure.
513**
514** Returns
515**
516*******************************************************************************/
517tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID descr_uuid,
518                                             tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value)
519{
520    UINT8                   i = 0, *pp = p_attr->value;
521    tBT_UUID                uuid = {LEN_UUID_16, {GATT_UUID_CHAR_AGG_FORMAT}};
522    UINT16                  handle;
523    tBTA_GATT_STATUS        status = BTA_GATT_OK;
524
525    /* GATT_UUID_CHAR_AGG_FORMAT */
526    if (bta_gattc_uuid_compare (uuid, descr_uuid, TRUE))
527    {
528        while (p_attr->len >= 2 && i < BTA_GATTC_MULTI_MAX)
529        {
530            STREAM_TO_UINT16(handle, pp);
531
532            if (bta_gattc_handle2id(p_srcb,
533                                    handle,
534                                    &p_value->aggre_value.pre_format[i].char_id.srvc_id,
535                                    &p_value->aggre_value.pre_format[i].char_id.char_id,
536                                    &p_value->aggre_value.pre_format[i].descr_type) == FALSE)
537            {
538                status = BTA_GATT_INTERNAL_ERROR;
539                APPL_TRACE_ERROR1("can not map to GATT ID. handle = 0x%04x", handle);
540                break;
541            }
542            i ++;
543            p_attr->len -= 2;
544        }
545        p_value->aggre_value.num_pres_fmt = i;
546    }
547    else
548    {
549        /* all others, take as raw format */
550        p_value->unformat.len = p_attr->len;
551        p_value->unformat.p_value = p_attr->value;
552    }
553    return status;
554}
555/*******************************************************************************
556**
557** Function         bta_gattc_mark_bg_conn
558**
559** Description      mark background connection status when a bg connection is initiated
560**                  or terminated.
561**
562** Returns          TRUE if success; FALSE otherwise.
563**
564*******************************************************************************/
565BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, BOOLEAN add)
566{
567    tBTA_GATTC_BG_TCK   *p_bg_tck = &bta_gattc_cb.bg_track[0];
568    UINT8   i = 0;
569
570    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
571    {
572        if (p_bg_tck->in_use &&
573            bdcmp(p_bg_tck->remote_bda, remote_bda) == 0)
574        {
575            if (add)
576                /* mask on the cif bit */
577                p_bg_tck->cif_mask |= (1 <<(client_if - 1));
578            else
579                p_bg_tck->cif_mask &= (~(1 <<(client_if - 1)));
580
581            return TRUE;
582        }
583    }
584    if (!add)
585    {
586        APPL_TRACE_ERROR0("Do not find the bg connection mask for the remote device");
587        return FALSE;
588    }
589    else /* adding a new device mask */
590    {
591        for (i = 0, p_bg_tck = &bta_gattc_cb.bg_track[0];
592             i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
593        {
594            if (!p_bg_tck->in_use)
595            {
596                p_bg_tck->in_use = TRUE;
597                bdcpy(p_bg_tck->remote_bda, remote_bda);
598                p_bg_tck->cif_mask = (1 <<(client_if - 1));
599                return TRUE;
600            }
601        }
602        APPL_TRACE_ERROR0("no available space to mark the bg connection status");
603        return FALSE;
604    }
605}
606/*******************************************************************************
607**
608** Function         bta_gattc_check_bg_conn
609**
610** Description      check if this is a background connection background connection.
611**
612** Returns          TRUE if success; FALSE otherwise.
613**
614*******************************************************************************/
615BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda)
616{
617    tBTA_GATTC_BG_TCK   *p_bg_tck = &bta_gattc_cb.bg_track[0];
618    UINT8       i = 0;
619    BOOLEAN     is_bg_conn = FALSE;
620
621    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
622    {
623        if (p_bg_tck->in_use &&
624            bdcmp(p_bg_tck->remote_bda, remote_bda) == 0)
625        {
626            if ((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0)
627                is_bg_conn = TRUE;
628            break;
629        }
630    }
631    return is_bg_conn;
632}
633/*******************************************************************************
634**
635** Function         bta_gattc_send_open_cback
636**
637** Description      send open callback
638**
639** Returns
640**
641*******************************************************************************/
642void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
643                                BD_ADDR remote_bda, UINT16 conn_id)
644{
645    tBTA_GATTC      cb_data;
646
647    if (p_clreg->p_cback)
648    {
649        memset(&cb_data, 0, sizeof(tBTA_GATTC));
650
651        cb_data.open.status = status;
652        cb_data.open.client_if = p_clreg->client_if;
653        cb_data.open.conn_id = conn_id;
654        bdcpy(cb_data.open.remote_bda, remote_bda);
655
656        (*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);
657    }
658}
659
660
661
662
663
664#endif /* BTA_GATT_INCLUDED */
665