1/******************************************************************************
2 *
3 *  Copyright (C) 2009-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 GATT utility functions
22 *
23 ******************************************************************************/
24#include "bt_target.h"
25
26#if BLE_INCLUDED == TRUE
27    #include <string.h>
28    #include "stdio.h"
29    #include "gki.h"
30
31    #include "l2cdefs.h"
32    #include "gatt_int.h"
33    #include "gatt_api.h"
34    #include "gattdefs.h"
35    #include "sdp_api.h"
36    #include "btm_int.h"
37/* check if [x, y] and [a, b] have overlapping range */
38    #define GATT_VALIDATE_HANDLE_RANGE(x, y, a, b)   (y >= a && x <= b)
39
40    #define GATT_GET_NEXT_VALID_HANDLE(x)    (((x)/10 + 1) * 10)
41
42const char * const op_code_name[] =
43{
44    "UNKNOWN",
45    "ATT_RSP_ERROR",
46    "ATT_REQ_MTU",
47    "ATT_RSP_MTU",
48    "ATT_REQ_READ_INFO",
49    "ATT_RSP_READ_INFO",
50    "ATT_REQ_FIND_TYPE_VALUE",
51    "ATT_RSP_FIND_TYPE_VALUE",
52    "ATT_REQ_READ_BY_TYPE",
53    "ATT_RSP_READ_BY_TYPE",
54    "ATT_REQ_READ",
55    "ATT_RSP_READ",
56    "ATT_REQ_READ_BLOB",
57    "ATT_RSP_READ_BLOB",
58    "GATT_REQ_READ_MULTI",
59    "GATT_RSP_READ_MULTI",
60    "GATT_REQ_READ_BY_GRP_TYPE",
61    "GATT_RSP_READ_BY_GRP_TYPE",
62    "ATT_REQ_WRITE",
63    "ATT_RSP_WRITE",
64    "ATT_CMD_WRITE",
65    "ATT_SIGN_CMD_WRITE",
66    "ATT_REQ_PREPARE_WRITE",
67    "ATT_RSP_PREPARE_WRITE",
68    "ATT_REQ_EXEC_WRITE",
69    "ATT_RSP_EXEC_WRITE",
70    "Reserved",
71    "ATT_HANDLE_VALUE_NOTIF",
72    "Reserved",
73    "ATT_HANDLE_VALUE_IND",
74    "ATT_HANDLE_VALUE_CONF",
75    "ATT_OP_CODE_MAX"
76};
77
78static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
79    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
80
81
82/*******************************************************************************
83**
84** Function         gatt_free_pending_ind
85**
86** Description    Free all pending indications
87**
88** Returns       None
89**
90*******************************************************************************/
91void gatt_free_pending_ind(tGATT_TCB *p_tcb)
92{
93    GATT_TRACE_DEBUG0("gatt_free_pending_ind");
94    /* release all queued indications */
95    while (p_tcb->pending_ind_q.p_first)
96        GKI_freebuf (GKI_dequeue (&p_tcb->pending_ind_q));
97}
98
99/*******************************************************************************
100**
101** Function         gatt_delete_dev_from_srv_chg_clt_list
102**
103** Description    Delete a device from the service changed client lit
104**
105** Returns       None
106**
107*******************************************************************************/
108void gatt_delete_dev_from_srv_chg_clt_list(BD_ADDR bd_addr)
109{
110    tGATTS_SRV_CHG     *p_buf;
111    tGATTS_SRV_CHG_REQ  req;
112
113    GATT_TRACE_DEBUG0 ("gatt_delete_dev_from_srv_chg_clt_list");
114    if ((p_buf = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr)) != NULL)
115    {
116        if (gatt_cb.cb_info.p_srv_chg_callback)
117        {
118            /* delete from NV */
119            memcpy(req.srv_chg.bda, bd_addr, BD_ADDR_LEN);
120            (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_REMOVE_CLIENT,&req, NULL);
121        }
122        GKI_freebuf (GKI_remove_from_queue (&gatt_cb.srv_chg_clt_q, p_buf));
123    }
124
125}
126
127/*******************************************************************************
128**
129** Function         gatt_set_srv_chg
130**
131** Description      Set the service changed flag to TRUE
132**
133** Returns        None
134**
135*******************************************************************************/
136void gatt_set_srv_chg(void)
137{
138    tGATTS_SRV_CHG *p_buf = (tGATTS_SRV_CHG *)GKI_getfirst(&gatt_cb.srv_chg_clt_q);
139    tGATTS_SRV_CHG_REQ req;
140
141    GATT_TRACE_DEBUG0 ("gatt_set_srv_chg");
142    while (p_buf)
143    {
144        GATT_TRACE_DEBUG0 ("found a srv_chg clt");
145        if (!p_buf->srv_changed)
146        {
147            GATT_TRACE_DEBUG0 ("set srv_changed to TRUE");
148            p_buf->srv_changed= TRUE;
149            memcpy(&req.srv_chg, p_buf, sizeof(tGATTS_SRV_CHG));
150            if (gatt_cb.cb_info.p_srv_chg_callback)
151                (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_UPDATE_CLIENT,&req, NULL);
152        }
153        p_buf = (tGATTS_SRV_CHG *)GKI_getnext(p_buf);
154    }
155}
156
157/*******************************************************************************
158**
159** Function         gatt_sr_is_new_srv_chg
160**
161** Description     Find the app id in on the new service changed list
162**
163** Returns     Pointer to the found new service changed item othwerwise NULL
164**
165*******************************************************************************/
166tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst)
167{
168    tGATTS_HNDL_RANGE *p;
169    tGATTS_PENDING_NEW_SRV_START *p_buf = (tGATTS_PENDING_NEW_SRV_START *)GKI_getfirst(&gatt_cb.pending_new_srv_start_q);
170
171    while (p_buf != NULL)
172    {
173        p = p_buf->p_new_srv_start;
174        if (  gatt_uuid_compare (*p_app_uuid128, p->app_uuid128)
175              &&  gatt_uuid_compare (*p_svc_uuid, p->svc_uuid)
176              &&  (svc_inst == p->svc_inst) )
177        {
178            GATT_TRACE_DEBUG0 ("gatt_sr_is_new_srv_chg: Yes");
179            break;
180        }
181        p_buf = (tGATTS_PENDING_NEW_SRV_START *)GKI_getnext(p_buf);
182    }
183
184    return p_buf;
185}
186
187
188/*******************************************************************************
189**
190** Function     gatt_add_pending_ind
191**
192** Description  Add a pending indication
193**
194** Returns    Pointer to the current pending indication buffer, NULL no buffer available
195**
196*******************************************************************************/
197tGATT_VALUE *gatt_add_pending_ind(tGATT_TCB  *p_tcb, tGATT_VALUE *p_ind)
198{
199    tGATT_VALUE   *p_buf;
200    GATT_TRACE_DEBUG0 ("gatt_add_pending_ind");
201    if ((p_buf = (tGATT_VALUE *)GKI_getbuf((UINT16)sizeof(tGATT_VALUE))) != NULL)
202    {
203        GATT_TRACE_DEBUG0 ("enqueue a pending indication");
204        memcpy(p_buf, p_ind, sizeof(tGATT_VALUE));
205        GKI_enqueue (&p_tcb->pending_ind_q, p_buf);
206    }
207    return p_buf;
208}
209
210
211/*******************************************************************************
212**
213** Function     gatt_add_pending_new_srv_start
214**
215** Description  Add a pending new srv start to the new service start queue
216**
217** Returns    Pointer to the new service start buffer, NULL no buffer available
218**
219*******************************************************************************/
220tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start(tGATTS_HNDL_RANGE *p_new_srv_start)
221{
222    tGATTS_PENDING_NEW_SRV_START   *p_buf;
223
224    GATT_TRACE_DEBUG0 ("gatt_add_pending_new_srv_start");
225    if ((p_buf = (tGATTS_PENDING_NEW_SRV_START *)GKI_getbuf((UINT16)sizeof(tGATTS_PENDING_NEW_SRV_START))) != NULL)
226    {
227        GATT_TRACE_DEBUG0 ("enqueue a new pending new srv start");
228        p_buf->p_new_srv_start = p_new_srv_start;
229        GKI_enqueue (&gatt_cb.pending_new_srv_start_q, p_buf);
230    }
231    return p_buf;
232}
233
234
235/*******************************************************************************
236**
237** Function     gatt_add_srv_chg_clt
238**
239** Description  Add a service chnage client to the service change client queue
240**
241** Returns    Pointer to the service change client buffer; Null no buffer available
242**
243*******************************************************************************/
244tGATTS_SRV_CHG *gatt_add_srv_chg_clt(tGATTS_SRV_CHG *p_srv_chg)
245{
246    tGATTS_SRV_CHG *p_buf;
247    GATT_TRACE_DEBUG0 ("gatt_add_srv_chg_clt");
248    if ((p_buf = (tGATTS_SRV_CHG *)GKI_getbuf((UINT16)sizeof(tGATTS_SRV_CHG))) != NULL)
249    {
250        GATT_TRACE_DEBUG0 ("enqueue a srv chg client");
251        memcpy(p_buf, p_srv_chg, sizeof(tGATTS_SRV_CHG));
252        GKI_enqueue (&gatt_cb.srv_chg_clt_q, p_buf);
253    }
254
255    return p_buf;
256}
257
258
259/*******************************************************************************
260**
261** Function     gatt_alloc_hdl_buffer
262**
263** Description  Allocate a handle buufer
264**
265** Returns    Pointer to the allocated buffer, NULL no buffer available
266**
267*******************************************************************************/
268tGATT_HDL_LIST_ELEM *gatt_alloc_hdl_buffer(void)
269{
270    UINT8 i;
271    tGATT_CB    *p_cb = &gatt_cb;
272    tGATT_HDL_LIST_ELEM * p_elem= &p_cb->hdl_list[0];
273
274    for (i = 0; i < GATT_MAX_SR_PROFILES; i++, p_elem ++)
275    {
276        if (!p_cb->hdl_list[i].in_use)
277        {
278            memset(p_elem, 0, sizeof(tGATT_HDL_LIST_ELEM));
279            p_elem->in_use = TRUE;
280            return p_elem;
281        }
282    }
283
284    return NULL;
285}
286
287/*******************************************************************************
288**
289** Function     gatt_find_hdl_buffer_by_handle
290**
291** Description  Find handle range buffer by service handle.
292**
293** Returns    Pointer to the buffer, NULL no buffer available
294**
295*******************************************************************************/
296tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_handle(UINT16 handle)
297{
298    tGATT_HDL_LIST_INFO *p_list_info= &gatt_cb.hdl_list_info;
299    tGATT_HDL_LIST_ELEM      *p_list = NULL;
300
301    p_list = p_list_info->p_first;
302
303    while (p_list != NULL)
304    {
305        if (p_list->in_use && p_list->asgn_range.s_handle == handle)
306        {
307            return(p_list);
308        }
309        p_list = p_list->p_next;
310    }
311    return NULL;
312}
313/*******************************************************************************
314**
315** Function     gatt_find_hdl_buffer_by_app_id
316**
317** Description  Find handle range buffer by app ID, service and service instance ID.
318**
319** Returns    Pointer to the buffer, NULL no buffer available
320**
321*******************************************************************************/
322tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128,
323                                                     tBT_UUID *p_svc_uuid,
324                                                     UINT16 svc_inst)
325{
326    tGATT_HDL_LIST_INFO *p_list_info= &gatt_cb.hdl_list_info;
327    tGATT_HDL_LIST_ELEM      *p_list = NULL;
328
329    p_list = p_list_info->p_first;
330
331    while (p_list != NULL)
332    {
333        if ( gatt_uuid_compare (*p_app_uuid128, p_list->asgn_range.app_uuid128)
334             &&  gatt_uuid_compare (*p_svc_uuid,    p_list->asgn_range.svc_uuid)
335             &&  (svc_inst == p_list->asgn_range.svc_inst) )
336        {
337            GATT_TRACE_DEBUG0 ("Already allocated handles for this service before!!");
338            return(p_list);
339        }
340        p_list = p_list->p_next;
341    }
342    return NULL;
343}
344/*******************************************************************************
345**
346** Function         gatt_free_hdl_buffer
347**
348** Description     free a handle buffer
349**
350** Returns       None
351**
352*******************************************************************************/
353void gatt_free_hdl_buffer(tGATT_HDL_LIST_ELEM *p)
354{
355
356    if (p)
357    {
358        while (p->svc_db.svc_buffer.p_first)
359            GKI_freebuf (GKI_dequeue (&p->svc_db.svc_buffer));
360        memset(p, 0, sizeof(tGATT_HDL_LIST_ELEM));
361    }
362}
363/*******************************************************************************
364**
365** Function         gatt_free_srvc_db_buffer_app_id
366**
367** Description      free the service attribute database buffers by the owner of the
368**                  service app ID.
369**
370** Returns       None
371**
372*******************************************************************************/
373void gatt_free_srvc_db_buffer_app_id(tBT_UUID *p_app_id)
374{
375    tGATT_HDL_LIST_ELEM *p_elem =  &gatt_cb.hdl_list[0];
376    UINT8   i;
377
378    for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_elem ++)
379    {
380        if (memcmp(p_app_id, &p_elem->asgn_range.app_uuid128, sizeof(tBT_UUID)) == 0)
381        {
382            while (p_elem->svc_db.svc_buffer.p_first)
383                GKI_freebuf (GKI_dequeue (&p_elem->svc_db.svc_buffer));
384
385            p_elem->svc_db.mem_free = 0;
386            p_elem->svc_db.p_attr_list = p_elem->svc_db.p_free_mem = NULL;
387        }
388    }
389}
390/*******************************************************************************
391**
392** Function         gatt_is_last_attribute
393**
394** Description     Check this is the last attribute of the specified value or not
395**
396** Returns       TRUE - yes this is the last attribute
397**
398*******************************************************************************/
399BOOLEAN gatt_is_last_attribute(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_start, tBT_UUID value)
400{
401    tGATT_SRV_LIST_ELEM *p_srv= p_start->p_next;
402    BOOLEAN              is_last_attribute = TRUE;
403    tGATT_SR_REG        *p_rcb = NULL;
404    tBT_UUID            *p_svc_uuid;
405
406    p_list->p_last_primary = NULL;
407
408    while (p_srv)
409    {
410        p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
411
412        p_svc_uuid = gatts_get_service_uuid (p_rcb->p_db);
413
414        if (gatt_uuid_compare(value, *p_svc_uuid))
415        {
416            is_last_attribute = FALSE;
417            break;
418
419        }
420        p_srv = p_srv->p_next;
421    }
422
423    return is_last_attribute;
424
425}
426
427/*******************************************************************************
428**
429** Function         gatt_update_last_pri_srv_info
430**
431** Description     Update the the last primary info for the service list info
432**
433** Returns       None
434**
435*******************************************************************************/
436void gatt_update_last_pri_srv_info(tGATT_SRV_LIST_INFO *p_list)
437{
438    tGATT_SRV_LIST_ELEM *p_srv= p_list->p_first;
439
440    p_list->p_last_primary = NULL;
441
442    while (p_srv)
443    {
444        if (p_srv->is_primary)
445        {
446            p_list->p_last_primary = p_srv;
447        }
448        p_srv = p_srv->p_next;
449    }
450
451}
452/*******************************************************************************
453**
454** Function         gatts_update_srv_list_elem
455**
456** Description      update an element in the service list.
457**
458** Returns          None.
459**
460*******************************************************************************/
461void gatts_update_srv_list_elem(UINT8 i_sreg, UINT16 handle, BOOLEAN is_primary)
462{
463    gatt_cb.srv_list[i_sreg].in_use         = TRUE;
464    gatt_cb.srv_list[i_sreg].i_sreg    = i_sreg;
465    gatt_cb.srv_list[i_sreg].s_hdl          = gatt_cb.sr_reg[i_sreg].s_hdl;
466    gatt_cb.srv_list[i_sreg].is_primary     = is_primary;
467
468    return;
469}
470/*******************************************************************************
471**
472** Function  gatt_add_a_srv_to_list
473**
474** Description  add an service to the list in ascending
475**              order of the start handle
476**
477** Returns   BOOLEAN TRUE-if add is successful
478**
479*******************************************************************************/
480BOOLEAN gatt_add_a_srv_to_list(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_new)
481{
482    tGATT_SRV_LIST_ELEM *p_old;
483
484    if (!p_new)
485    {
486        GATT_TRACE_DEBUG0("p_new==NULL");
487        return FALSE;
488    }
489
490    if (!p_list->p_first)
491    {
492        /* this is an empty list */
493        p_list->p_first =
494        p_list->p_last  = p_new;
495        p_new->p_next   =
496        p_new->p_prev   = NULL;
497    }
498    else
499    {
500        p_old = p_list->p_first;
501        while (1)
502        {
503            if (p_old == NULL)
504            {
505                p_list->p_last->p_next      = p_new;
506                p_new->p_prev               = p_list->p_last;
507                p_new->p_next               = NULL;
508                p_list->p_last              = p_new;
509                break;
510            }
511            else
512            {
513                if (p_new->s_hdl <  p_old->s_hdl)
514                {
515                    /* if not the first in list */
516                    if (p_old->p_prev != NULL)
517                        p_old->p_prev->p_next   = p_new;
518                    else
519                        p_list->p_first = p_new;
520
521                    p_new->p_prev           = p_old->p_prev;
522                    p_new->p_next           = p_old;
523                    p_old->p_prev           = p_new;
524                    break;
525                }
526            }
527            p_old = p_old->p_next;
528        }
529    }
530    p_list->count++;
531
532    gatt_update_last_pri_srv_info(p_list);
533    return TRUE;
534
535}
536
537/*******************************************************************************
538**
539** Function  gatt_remove_a_srv_from_list
540**
541** Description  Remove a service from the list
542**
543** Returns   BOOLEAN TRUE-if remove is successful
544**
545*******************************************************************************/
546BOOLEAN gatt_remove_a_srv_from_list(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_remove)
547{
548    if (!p_remove || !p_list->p_first)
549    {
550        GATT_TRACE_DEBUG0("p_remove==NULL || p_list->p_first==NULL");
551        return FALSE;
552    }
553
554    if (p_remove->p_prev == NULL)
555    {
556        p_list->p_first             = p_remove->p_next;
557        if (p_remove->p_next)
558            p_remove->p_next->p_prev    = NULL;
559    }
560    else if (p_remove->p_next == NULL)
561    {
562        p_list->p_last              = p_remove->p_prev;
563        p_remove->p_prev->p_next    = NULL;
564    }
565    else
566    {
567        p_remove->p_next->p_prev = p_remove->p_prev;
568        p_remove->p_prev->p_next = p_remove->p_next;
569    }
570    p_list->count--;
571    gatt_update_last_pri_srv_info(p_list);
572    return TRUE;
573
574}
575
576/*******************************************************************************
577**
578** Function  gatt_add_an_item_to_list
579**
580** Description  add an service handle range to the list in decending
581**              order of the start handle
582**
583** Returns   BOOLEAN TRUE-if add is successful
584**
585*******************************************************************************/
586BOOLEAN gatt_add_an_item_to_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_LIST_ELEM *p_new)
587{
588    tGATT_HDL_LIST_ELEM *p_old;
589    if (!p_new)
590    {
591        GATT_TRACE_DEBUG0("p_new==NULL");
592        return FALSE;
593    }
594
595    if (!p_list->p_first)
596    {
597        /* this is an empty list */
598        p_list->p_first =
599        p_list->p_last  = p_new;
600        p_new->p_next   =
601        p_new->p_prev   = NULL;
602    }
603    else
604    {
605        p_old = p_list->p_first;
606        while (1)
607        {
608            if (p_old == NULL)
609            {
610                p_list->p_last->p_next      = p_new;
611                p_new->p_prev               = p_list->p_last;
612                p_new->p_next               = NULL;
613                p_list->p_last              = p_new;
614
615                break;
616
617            }
618            else
619            {
620                if (p_new->asgn_range.s_handle >  p_old->asgn_range.s_handle)
621                {
622                    if (p_old == p_list->p_first)
623                        p_list->p_first = p_new;
624
625                    p_new->p_prev    = p_old->p_prev;
626                    p_new->p_next    = p_old;
627
628
629                    p_old->p_prev    = p_new;
630                    break;
631                }
632            }
633            p_old = p_old->p_next;
634        }
635    }
636    p_list->count++;
637    return TRUE;
638
639}
640
641/*******************************************************************************
642**
643** Function  gatt_remove_an_item_from_list
644**
645** Description  Remove an service handle range from the list
646**
647** Returns   BOOLEAN TRUE-if remove is successful
648**
649*******************************************************************************/
650BOOLEAN gatt_remove_an_item_from_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_LIST_ELEM *p_remove)
651{
652    if (!p_remove || !p_list->p_first)
653    {
654        GATT_TRACE_DEBUG0("p_remove==NULL || p_list->p_first==NULL");
655        return FALSE;
656    }
657
658    if (p_remove->p_prev == NULL)
659    {
660        p_list->p_first             = p_remove->p_next;
661        if (p_remove->p_next)
662            p_remove->p_next->p_prev    = NULL;
663    }
664    else if (p_remove->p_next == NULL)
665    {
666        p_list->p_last              = p_remove->p_prev;
667        p_remove->p_prev->p_next    = NULL;
668    }
669    else
670    {
671        p_remove->p_next->p_prev = p_remove->p_prev;
672        p_remove->p_prev->p_next = p_remove->p_next;
673    }
674    p_list->count--;
675    return TRUE;
676
677}
678
679/*******************************************************************************
680**
681** Function         gatt_find_the_connected_bda
682**
683** Description      This function find the connected bda
684**
685** Returns           TRUE if found
686**
687*******************************************************************************/
688BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found_idx)
689{
690    UINT8 i;
691    BOOLEAN found = FALSE;
692    GATT_TRACE_DEBUG1("gatt_find_the_connected_bda start_idx=%d",start_idx);
693
694    for (i = start_idx ; i < GATT_MAX_PHY_CHANNEL; i ++)
695    {
696        if (gatt_cb.tcb[i].in_use)
697        {
698            memcpy( bda, gatt_cb.tcb[i].peer_bda, BD_ADDR_LEN);
699            *p_found_idx = i;
700            found = TRUE;
701            GATT_TRACE_DEBUG6("gatt_find_the_connected_bda bda :%02x-%02x-%02x-%02x-%02x-%02x",
702                              bda[0],  bda[1], bda[2],  bda[3], bda[4],  bda[5]);
703            break;
704        }
705    }
706    GATT_TRACE_DEBUG2("gatt_find_the_connected_bda found=%d found_idx=%d", found, i);
707    return found;
708}
709
710
711
712/*******************************************************************************
713**
714** Function         gatt_is_srv_chg_ind_pending
715**
716** Description      Check whether a service chnaged is in the indication pending queue
717**                  or waiting for an Ack already
718**
719** Returns         BOOLEAN
720**
721*******************************************************************************/
722BOOLEAN gatt_is_srv_chg_ind_pending (tGATT_TCB *p_tcb)
723{
724    tGATT_VALUE *p_buf = (tGATT_VALUE *)GKI_getfirst(&p_tcb->pending_ind_q);
725    BOOLEAN srv_chg_ind_pending = FALSE;
726
727    GATT_TRACE_DEBUG1("gatt_is_srv_chg_ind_pending is_queue_empty=%d", GKI_queue_is_empty(&p_tcb->pending_ind_q) );
728
729    if (p_tcb->indicate_handle == gatt_cb.handle_of_h_r)
730    {
731        srv_chg_ind_pending = TRUE;
732    }
733    else
734    {
735        while (p_buf)
736        {
737            if (p_buf->handle == gatt_cb.handle_of_h_r)
738            {
739                srv_chg_ind_pending = TRUE;
740                break;
741            }
742            p_buf = (tGATT_VALUE *)GKI_getnext(p_buf);
743        }
744    }
745
746    GATT_TRACE_DEBUG1("srv_chg_ind_pending = %d", srv_chg_ind_pending);
747    return srv_chg_ind_pending;
748}
749
750
751/*******************************************************************************
752**
753** Function         gatt_is_bda_in_the_srv_chg_clt_list
754**
755** Description      This function check the specified bda is in the srv chg clinet list or not
756**
757** Returns         pointer to the found elemenet otherwise NULL
758**
759*******************************************************************************/
760tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda)
761{
762    tGATTS_SRV_CHG *p_buf = (tGATTS_SRV_CHG *)GKI_getfirst(&gatt_cb.srv_chg_clt_q);
763
764    GATT_TRACE_DEBUG6("gatt_is_bda_in_the_srv_chg_clt_list :%02x-%02x-%02x-%02x-%02x-%02x",
765                      bda[0],  bda[1], bda[2],  bda[3], bda[4],  bda[5]);
766
767    while (p_buf != NULL)
768    {
769        if (!memcmp( bda, p_buf->bda, BD_ADDR_LEN))
770        {
771            GATT_TRACE_DEBUG0("bda is in the srv chg clt list");
772            break;
773        }
774        p_buf = (tGATTS_SRV_CHG *)GKI_getnext(p_buf);
775    }
776
777    return p_buf;
778}
779
780
781/*******************************************************************************
782**
783** Function         gatt_is_bda_connected
784**
785** Description
786**
787** Returns           GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
788**
789*******************************************************************************/
790BOOLEAN gatt_is_bda_connected(BD_ADDR bda)
791{
792    UINT8 i = 0;
793    BOOLEAN connected=FALSE;
794
795    for ( i=0; i < GATT_MAX_PHY_CHANNEL; i ++)
796    {
797        if (gatt_cb.tcb[i].in_use &&
798            !memcmp(gatt_cb.tcb[i].peer_bda, bda, BD_ADDR_LEN))
799        {
800            connected = TRUE;
801            break;
802        }
803    }
804    return connected;
805}
806
807/*******************************************************************************
808**
809** Function         gatt_find_i_tcb_by_addr
810**
811** Description      The function searches for an empty tcb entry, and return the index.
812**
813** Returns           GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
814**
815*******************************************************************************/
816UINT8 gatt_find_i_tcb_by_addr(BD_ADDR bda)
817{
818    UINT8 i = 0, j = GATT_INDEX_INVALID;
819
820    for ( ; i < GATT_MAX_PHY_CHANNEL; i ++)
821    {
822        if (!memcmp(gatt_cb.tcb[i].peer_bda, bda, BD_ADDR_LEN))
823        {
824            j = i;
825            break;
826        }
827    }
828    return j;
829}
830
831
832/*******************************************************************************
833**
834** Function         gatt_get_tcb_by_idx
835**
836** Description      The function get TCB using the TCB index
837**
838** Returns           NULL if not found. Otherwise index to the tcb.
839**
840*******************************************************************************/
841tGATT_TCB * gatt_get_tcb_by_idx(UINT8 tcb_idx)
842{
843    tGATT_TCB   *p_tcb = NULL;
844
845    if ( (tcb_idx < GATT_MAX_PHY_CHANNEL) && gatt_cb.tcb[tcb_idx].in_use)
846        p_tcb = &gatt_cb.tcb[tcb_idx];
847
848    return p_tcb;
849}
850
851/*******************************************************************************
852**
853** Function         gatt_find_tcb_by_addr
854**
855** Description      The function searches for an empty tcb entry, and return pointer.
856**
857** Returns           NULL if not found. Otherwise index to the tcb.
858**
859*******************************************************************************/
860tGATT_TCB * gatt_find_tcb_by_addr(BD_ADDR bda)
861{
862    tGATT_TCB   *p_tcb = NULL;
863    UINT8 i = 0;
864
865    if ((i = gatt_find_i_tcb_by_addr(bda)) != GATT_INDEX_INVALID)
866        p_tcb = &gatt_cb.tcb[i];
867
868    return p_tcb;
869}
870/*******************************************************************************
871**
872** Function         gatt_find_i_tcb_free
873**
874** Description      The function searches for an empty tcb entry, and return the index.
875**
876** Returns           GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
877**
878*******************************************************************************/
879UINT8 gatt_find_i_tcb_free(void)
880{
881    UINT8 i = 0, j = GATT_INDEX_INVALID;
882
883    for (i = 0; i < GATT_MAX_PHY_CHANNEL; i ++)
884    {
885        if (!gatt_cb.tcb[i].in_use)
886        {
887            j = i;
888            break;
889        }
890    }
891    return j;
892}
893/*******************************************************************************
894**
895** Function         gatt_allocate_tcb_by_bdaddr
896**
897** Description      The function locate or allocate new tcb entry for matching bda.
898**
899** Returns           GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
900**
901*******************************************************************************/
902tGATT_TCB * gatt_allocate_tcb_by_bdaddr(BD_ADDR bda)
903{
904    UINT8 i = 0;
905    BOOLEAN allocated = FALSE;
906    tGATT_TCB    *p_tcb = NULL;
907
908    /* search for existing tcb with matching bda    */
909    i = gatt_find_i_tcb_by_addr(bda);
910    /* find free tcb */
911    if (i == GATT_INDEX_INVALID)
912    {
913        i = gatt_find_i_tcb_free();
914        allocated = TRUE;
915    }
916    if (i != GATT_INDEX_INVALID)
917    {
918        p_tcb = &gatt_cb.tcb[i];
919
920        if (allocated)
921        {
922            memset(p_tcb, 0, sizeof(tGATT_TCB));
923            p_tcb->in_use = TRUE;
924            p_tcb->tcb_idx = i;
925        }
926        memcpy(p_tcb->peer_bda, bda, BD_ADDR_LEN);
927    }
928    return p_tcb;
929}
930
931/*******************************************************************************
932**
933** Function         gatt_convert_uuid16_to_uuid128
934**
935** Description      Convert a 16 bits UUID to be an standard 128 bits one.
936**
937** Returns          TRUE if two uuid match; FALSE otherwise.
938**
939*******************************************************************************/
940void gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
941{
942    UINT8   *p = &uuid_128[LEN_UUID_128 - 4];
943
944    memcpy (uuid_128, base_uuid, LEN_UUID_128);
945
946    UINT16_TO_STREAM(p, uuid_16);
947}
948
949/*******************************************************************************
950**
951** Function         gatt_uuid_compare
952**
953** Description      Compare two UUID to see if they are the same.
954**
955** Returns          TRUE if two uuid match; FALSE otherwise.
956**
957*******************************************************************************/
958BOOLEAN gatt_uuid_compare (tBT_UUID src, tBT_UUID tar)
959{
960    UINT8  su[LEN_UUID_128], tu[LEN_UUID_128];
961    UINT8  *ps, *pt;
962
963    /* any of the UUID is unspecified */
964    if (src.len == 0 || tar.len == 0)
965    {
966        return TRUE;
967    }
968
969    /* If both are 16-bit, we can do a simple compare */
970    if (src.len == 2 && tar.len == 2)
971    {
972        return src.uu.uuid16 == tar.uu.uuid16;
973    }
974
975    /* One or both of the UUIDs is 128-bit */
976    if (src.len == LEN_UUID_16)
977    {
978        /* convert a 16 bits UUID to 128 bits value */
979        gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
980        ps = su;
981    }
982    else
983        ps = src.uu.uuid128;
984
985    if (tar.len == LEN_UUID_16)
986    {
987        /* convert a 16 bits UUID to 128 bits value */
988        gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
989        pt = tu;
990    }
991    else
992        pt = tar.uu.uuid128;
993
994    return(memcmp(ps, pt, LEN_UUID_128) == 0);
995}
996
997/*******************************************************************************
998**
999** Function         gatt_build_uuid_to_stream
1000**
1001** Description      Add UUID into stream.
1002**
1003** Returns          UUID length.
1004**
1005*******************************************************************************/
1006UINT8 gatt_build_uuid_to_stream(UINT8 **p_dst, tBT_UUID uuid)
1007{
1008    UINT8   *p = *p_dst;
1009    UINT8   len = 0;
1010
1011    if (uuid.len == LEN_UUID_16)
1012    {
1013        UINT16_TO_STREAM (p, uuid.uu.uuid16);
1014        len = LEN_UUID_16;
1015    }
1016    else if (uuid.len == LEN_UUID_128)
1017    {
1018        ARRAY_TO_STREAM (p, uuid.uu.uuid128, LEN_UUID_128);
1019        len = LEN_UUID_128;
1020    }
1021
1022    *p_dst = p;
1023    return len;
1024}
1025
1026/*******************************************************************************
1027**
1028** Function         gatt_parse_uuid_from_cmd
1029**
1030** Description      Convert a 128 bits UUID into a 16 bits UUID.
1031**
1032** Returns          TRUE if command sent, otherwise FALSE.
1033**
1034*******************************************************************************/
1035BOOLEAN gatt_parse_uuid_from_cmd(tBT_UUID *p_uuid_rec, UINT16 uuid_size, UINT8 **p_data)
1036{
1037    BOOLEAN is_base_uuid, ret = TRUE;
1038    UINT8  xx;
1039    UINT8 *p_uuid = *p_data;
1040
1041    memset(p_uuid_rec, 0, sizeof(tBT_UUID));
1042
1043    switch (uuid_size)
1044    {
1045        case LEN_UUID_16:
1046            p_uuid_rec->len = uuid_size;
1047            STREAM_TO_UINT16 (p_uuid_rec->uu.uuid16, p_uuid);
1048            *p_data += LEN_UUID_16;
1049            break;
1050
1051        case LEN_UUID_128:
1052            /* See if we can compress his UUID down to 16 or 32bit UUIDs */
1053            is_base_uuid = TRUE;
1054            for (xx = 0; xx < LEN_UUID_128 - 4; xx++)
1055            {
1056                if (p_uuid[xx] != base_uuid[xx])
1057                {
1058                    is_base_uuid = FALSE;
1059                    break;
1060                }
1061            }
1062            if (is_base_uuid)
1063            {
1064                if ((p_uuid[LEN_UUID_128 - 1] == 0) && (p_uuid[LEN_UUID_128 - 2] == 0))
1065                {
1066                    p_uuid += (LEN_UUID_128 - 4);
1067                    p_uuid_rec->len = LEN_UUID_16;
1068                    STREAM_TO_UINT16(p_uuid_rec->uu.uuid16, p_uuid);
1069                }
1070                else
1071                    is_base_uuid = FALSE;
1072            }
1073            if (!is_base_uuid)
1074            {
1075                p_uuid_rec->len = LEN_UUID_128;
1076                memcpy(p_uuid_rec->uu.uuid128, p_uuid, LEN_UUID_128);
1077            }
1078            *p_data += LEN_UUID_128;
1079            break;
1080
1081        case 0:
1082        default:
1083            if (uuid_size != 0) ret = FALSE;
1084            GATT_TRACE_WARNING0("gatt_parse_uuid_from_cmd invalid uuid size");
1085            break;
1086    }
1087
1088    return( ret);
1089}
1090
1091/*******************************************************************************
1092**
1093** Function         gatt_start_rsp_timer
1094**
1095** Description      Start a wait_for_response timer.
1096**
1097** Returns          TRUE if command sent, otherwise FALSE.
1098**
1099*******************************************************************************/
1100void gatt_start_rsp_timer(tGATT_TCB    *p_tcb)
1101{
1102    p_tcb->rsp_timer_ent.param  = (TIMER_PARAM_TYPE)p_tcb;
1103    btu_start_timer (&p_tcb->rsp_timer_ent, BTU_TTYPE_ATT_WAIT_FOR_RSP,
1104                     GATT_WAIT_FOR_RSP_TOUT);
1105}
1106/*******************************************************************************
1107**
1108** Function         gatt_start_conf_timer
1109**
1110** Description      Start a wait_for_confirmation timer.
1111**
1112** Returns          TRUE if command sent, otherwise FALSE.
1113**
1114*******************************************************************************/
1115void gatt_start_conf_timer(tGATT_TCB    *p_tcb)
1116{
1117    p_tcb->conf_timer_ent.param  = (TIMER_PARAM_TYPE)p_tcb;
1118    btu_start_timer (&p_tcb->conf_timer_ent, BTU_TTYPE_ATT_WAIT_FOR_RSP,
1119                     GATT_WAIT_FOR_RSP_TOUT);
1120}
1121/*******************************************************************************
1122**
1123** Function         gatt_start_ind_ack_timer
1124**
1125** Description      start the application ack timer
1126**
1127** Returns          void
1128**
1129*******************************************************************************/
1130void gatt_start_ind_ack_timer(tGATT_TCB *p_tcb)
1131{
1132    p_tcb->ind_ack_timer_ent.param  = (TIMER_PARAM_TYPE)p_tcb;
1133    /* start notification cache timer */
1134    btu_start_timer (&p_tcb->ind_ack_timer_ent, BTU_TTYPE_ATT_WAIT_FOR_IND_ACK,
1135                     GATT_WAIT_FOR_RSP_TOUT);
1136
1137}
1138/*******************************************************************************
1139**
1140** Function         gatt_rsp_timeout
1141**
1142** Description      Called when GATT wait for ATT command response timer expires
1143**
1144** Returns          void
1145**
1146*******************************************************************************/
1147void gatt_rsp_timeout(TIMER_LIST_ENT *p_tle)
1148{
1149    GATT_TRACE_WARNING0("gatt_rsp_timeout disconnecting...");
1150    gatt_disconnect (((tGATT_TCB *)p_tle->param)->peer_bda);
1151}
1152
1153/*******************************************************************************
1154**
1155** Function         gatt_ind_ack_timeout
1156**
1157** Description      Called when GATT wait for ATT handle confirmation timeout
1158**
1159** Returns          void
1160**
1161*******************************************************************************/
1162void gatt_ind_ack_timeout(TIMER_LIST_ENT *p_tle)
1163{
1164    tGATT_TCB * p_tcb = (tGATT_TCB *)p_tle->param;
1165
1166    GATT_TRACE_WARNING0("gatt_ind_ack_timeout send ack now");
1167
1168    if (p_tcb != NULL)
1169        p_tcb->ind_count = 0;
1170
1171    attp_send_cl_msg(((tGATT_TCB *)p_tle->param), 0, GATT_HANDLE_VALUE_CONF, NULL);
1172}
1173/*******************************************************************************
1174**
1175** Function         gatt_sr_find_i_rcb_by_handle
1176**
1177** Description      The function searches for a service that owns a specific handle.
1178**
1179** Returns          GATT_MAX_SR_PROFILES if not found. Otherwise index of th eservice.
1180**
1181*******************************************************************************/
1182UINT8 gatt_sr_find_i_rcb_by_handle(UINT16 handle)
1183{
1184    UINT8  i_rcb = 0;
1185
1186    for ( ; i_rcb < GATT_MAX_SR_PROFILES; i_rcb++)
1187    {
1188        if (gatt_cb.sr_reg[i_rcb].in_use &&
1189            gatt_cb.sr_reg[i_rcb].s_hdl <= handle &&
1190            gatt_cb.sr_reg[i_rcb].e_hdl >= handle )
1191        {
1192            break;
1193        }
1194    }
1195    return i_rcb;
1196}
1197
1198/*******************************************************************************
1199**
1200** Function         gatt_sr_find_i_rcb_by_handle
1201**
1202** Description      The function searches for a service that owns a specific handle.
1203**
1204** Returns          0 if not found. Otherwise index of th eservice.
1205**
1206*******************************************************************************/
1207UINT8 gatt_sr_find_i_rcb_by_app_id(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst)
1208{
1209    UINT8           i_rcb = 0;
1210    tGATT_SR_REG    *p_sreg;
1211    tBT_UUID        *p_this_uuid;
1212
1213    for (i_rcb = 0, p_sreg = gatt_cb.sr_reg; i_rcb < GATT_MAX_SR_PROFILES; i_rcb++, p_sreg++)
1214    {
1215        if ( p_sreg->in_use )
1216        {
1217            p_this_uuid = gatts_get_service_uuid (p_sreg->p_db);
1218
1219            if (p_this_uuid &&
1220                gatt_uuid_compare (*p_app_uuid128, p_sreg->app_uuid ) &&
1221                gatt_uuid_compare (*p_svc_uuid, *p_this_uuid) &&
1222                (svc_inst == p_sreg->service_instance))
1223            {
1224                GATT_TRACE_ERROR0 ("Active Service Found ");
1225                gatt_dbg_display_uuid(*p_svc_uuid);
1226
1227                break;
1228            }
1229        }
1230    }
1231    return i_rcb;
1232}
1233/*******************************************************************************
1234**
1235** Function         gatt_sr_find_i_rcb_by_handle
1236**
1237** Description      The function searches for a service that owns a specific handle.
1238**
1239** Returns          0 if not found. Otherwise index of th eservice.
1240**
1241*******************************************************************************/
1242UINT8 gatt_sr_alloc_rcb(tGATT_HDL_LIST_ELEM *p_list )
1243{
1244    UINT8   ii = 0;
1245    tGATT_SR_REG    *p_sreg = NULL;
1246
1247    /*this is a new application servoce start */
1248    for (ii = 0, p_sreg = gatt_cb.sr_reg; ii < GATT_MAX_SR_PROFILES; ii++, p_sreg++)
1249    {
1250        if (!p_sreg->in_use)
1251        {
1252            memset (p_sreg, 0, sizeof(tGATT_SR_REG));
1253
1254            p_sreg->in_use = TRUE;
1255            memcpy (&p_sreg->app_uuid, &p_list->asgn_range.app_uuid128, sizeof(tBT_UUID));
1256
1257            p_sreg->service_instance    = p_list->asgn_range.svc_inst;
1258            p_sreg->type                = p_list->asgn_range.is_primary ? GATT_UUID_PRI_SERVICE: GATT_UUID_SEC_SERVICE;
1259            p_sreg->s_hdl               = p_list->asgn_range.s_handle;
1260            p_sreg->e_hdl               = p_list->asgn_range.e_handle;
1261            //p_sreg->sr_cb               = *p_cback;
1262            p_sreg->p_db                = &p_list->svc_db;
1263
1264            GATT_TRACE_DEBUG1 ("total GKI buffer in db [%d]",p_sreg->p_db->svc_buffer.count);
1265            break;
1266        }
1267    }
1268
1269    return ii;
1270}
1271/*******************************************************************************
1272**
1273** Function         gatt_sr_get_sec_info
1274**
1275** Description      Get the security flag and key size information for the peer
1276**                  device.
1277**
1278** Returns          void
1279**
1280*******************************************************************************/
1281void gatt_sr_get_sec_info(BD_ADDR rem_bda, BOOLEAN le_conn, UINT8 *p_sec_flag, UINT8 *p_key_size)
1282{
1283    UINT8           sec_flag = 0;
1284
1285    BTM_GetSecurityFlags(rem_bda, &sec_flag);
1286
1287    sec_flag &= (GATT_SEC_FLAG_LKEY_UNAUTHED | GATT_SEC_FLAG_LKEY_AUTHED | GATT_SEC_FLAG_ENCRYPTED);
1288
1289    *p_key_size = btm_ble_read_sec_key_size(rem_bda);
1290    *p_sec_flag = sec_flag;
1291}
1292/*******************************************************************************
1293**
1294** Function         gatt_sr_send_req_callback
1295**
1296** Description
1297**
1298**
1299** Returns          void
1300**
1301*******************************************************************************/
1302void gatt_sr_send_req_callback(UINT16 conn_id,
1303                               UINT32 trans_id,
1304                               tGATTS_REQ_TYPE type, tGATTS_DATA *p_data)
1305{
1306    tGATT_IF        gatt_if = GATT_GET_GATT_IF(conn_id);
1307    tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
1308
1309    if (!p_reg )
1310    {
1311        GATT_TRACE_ERROR0 ("p_reg not found discard request");
1312        return;
1313    }
1314
1315    if ( p_reg->in_use &&
1316         p_reg->app_cb.p_req_cb)
1317    {
1318        (*p_reg->app_cb.p_req_cb)(conn_id, trans_id, type, p_data);
1319    }
1320    else
1321    {
1322        GATT_TRACE_WARNING1("Call back not found for application conn_id=%d", conn_id);
1323    }
1324
1325}
1326
1327/*******************************************************************************
1328**
1329** Function         gatt_send_error_rsp
1330**
1331** Description      This function sends an error response.
1332**
1333** Returns          void
1334**
1335*******************************************************************************/
1336tGATT_STATUS gatt_send_error_rsp (tGATT_TCB *p_tcb, UINT8 err_code, UINT8 op_code,
1337                                  UINT16 handle, BOOLEAN deq)
1338{
1339    tGATT_ERROR      error;
1340    tGATT_STATUS     status;
1341    BT_HDR           *p_buf;
1342
1343    error.cmd_code = op_code;
1344    error.reason = err_code;
1345    error.handle =handle;
1346
1347    if ((p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_ERROR, (tGATT_SR_MSG *)&error)) != NULL)
1348    {
1349        status = attp_send_sr_msg (p_tcb, p_buf);
1350    }
1351    else
1352        status = GATT_INSUF_RESOURCE;
1353
1354    if (deq)
1355        gatt_dequeue_sr_cmd(p_tcb);
1356
1357    return status;
1358}
1359
1360
1361/*******************************************************************************
1362**
1363** Function         gatt_add_sdp_record
1364**
1365** Description      This function add a SDP record for a GATT primary service
1366**
1367** Returns          0 if error else sdp handle for the record.
1368**
1369*******************************************************************************/
1370UINT32 gatt_add_sdp_record (tBT_UUID *p_uuid, UINT16 start_hdl, UINT16 end_hdl)
1371{
1372    tSDP_PROTOCOL_ELEM  proto_elem_list[2];
1373    UINT32              sdp_handle;
1374    UINT16              list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
1375    UINT8               buff[60];
1376    UINT8               *p = buff;
1377
1378    GATT_TRACE_DEBUG2("gatt_add_sdp_record s_hdl=0x%x  s_hdl=0x%x",start_hdl, end_hdl);
1379
1380    if ((sdp_handle = SDP_CreateRecord()) == 0)
1381        return 0;
1382
1383    switch (p_uuid->len)
1384    {
1385        case LEN_UUID_16:
1386            SDP_AddServiceClassIdList(sdp_handle, 1, &p_uuid->uu.uuid16);
1387            break;
1388        case LEN_UUID_128:
1389            UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
1390            ARRAY_TO_BE_STREAM (p, p_uuid->uu.uuid128, LEN_UUID_128);
1391            SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_CLASS_ID_LIST, DATA_ELE_SEQ_DESC_TYPE,
1392                              (UINT32) (p - buff), buff);
1393            break;
1394
1395        default:
1396            GATT_TRACE_ERROR1("inavlid UUID len=%d", p_uuid->len);
1397            SDP_DeleteRecord(sdp_handle);
1398            return 0;
1399            break;
1400    }
1401
1402    /*** Fill out the protocol element sequence for SDP ***/
1403    proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
1404    proto_elem_list[0].num_params    = 1;
1405    proto_elem_list[0].params[0]     = BT_PSM_ATT;
1406    proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_ATT;
1407    proto_elem_list[1].num_params    = 2;
1408    proto_elem_list[1].params[0]     = start_hdl;
1409    proto_elem_list[1].params[1]     = end_hdl;
1410
1411    SDP_AddProtocolList(sdp_handle, 2, proto_elem_list);
1412
1413    /* Make the service browseable */
1414    SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list);
1415
1416    return(sdp_handle);
1417}
1418
1419
1420    #if GATT_CONFORMANCE_TESTING == TRUE
1421/*******************************************************************************
1422**
1423** Function         gatt_set_err_rsp
1424**
1425** Description      This function is called to set the test confirm value
1426**
1427** Returns          void
1428**
1429*******************************************************************************/
1430void gatt_set_err_rsp(BOOLEAN enable, UINT8 req_op_code, UINT8 err_status)
1431{
1432    GATT_TRACE_DEBUG3("gatt_set_err_rsp enable=%d op_code=%d, err_status=%d", enable, req_op_code, err_status);
1433    gatt_cb.enable_err_rsp  = enable;
1434    gatt_cb.req_op_code     = req_op_code;
1435    gatt_cb.err_status      = err_status;
1436}
1437    #endif
1438
1439
1440
1441/*******************************************************************************
1442**
1443** Function         gatt_get_regcb
1444**
1445** Description      The function returns the registration control block.
1446**
1447** Returns          pointer to the registration control block or NULL
1448**
1449*******************************************************************************/
1450tGATT_REG *gatt_get_regcb (tGATT_IF gatt_if)
1451{
1452    UINT8           ii = (UINT8)gatt_if;
1453    tGATT_REG       *p_reg = NULL;
1454
1455    if (ii)
1456    {
1457        ii--; /* convert from one based to zero based */
1458        p_reg = &gatt_cb.cl_rcb[ii];
1459        if ( (ii < GATT_MAX_APPS)  && (p_reg->in_use) )
1460            return(p_reg);
1461    }
1462
1463    return NULL;
1464}
1465
1466
1467/*******************************************************************************
1468**
1469** Function         gatt_is_clcb_allocated
1470**
1471** Description      The function check clcb for conn_id is allocated or not
1472**
1473** Returns           True already allocated
1474**
1475*******************************************************************************/
1476
1477BOOLEAN gatt_is_clcb_allocated (UINT16 conn_id)
1478{
1479    UINT8         i = 0;
1480    BOOLEAN       is_allocated= FALSE;
1481
1482    for (i = 0; i < GATT_CL_MAX_LCB; i++)
1483    {
1484        if (gatt_cb.clcb[i].in_use && (gatt_cb.clcb[i].conn_id == conn_id))
1485        {
1486            is_allocated = TRUE;
1487            break;
1488        }
1489    }
1490
1491    return is_allocated;
1492}
1493
1494/*******************************************************************************
1495**
1496** Function         gatt_clcb_alloc
1497**
1498** Description      The function allocates a GATT  connection link control block
1499**
1500** Returns           NULL if not found. Otherwise pointer to the connection link block.
1501**
1502*******************************************************************************/
1503tGATT_CLCB *gatt_clcb_alloc (UINT16 conn_id)
1504{
1505    UINT8           i = 0;
1506    tGATT_CLCB      *p_clcb = NULL;
1507    tGATT_IF        gatt_if=GATT_GET_GATT_IF(conn_id);
1508    UINT8           tcb_idx = GATT_GET_TCB_IDX(conn_id);
1509    tGATT_TCB       *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1510    tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
1511
1512    for (i = 0; i < GATT_CL_MAX_LCB; i++)
1513    {
1514        if (!gatt_cb.clcb[i].in_use)
1515        {
1516            p_clcb = &gatt_cb.clcb[i];
1517
1518            p_clcb->in_use      = TRUE;
1519            p_clcb->conn_id     = conn_id;
1520            p_clcb->clcb_idx    = i;
1521            p_clcb->p_reg       = p_reg;
1522            p_clcb->p_tcb       = p_tcb;
1523            break;
1524        }
1525    }
1526    return p_clcb;
1527}
1528
1529/*******************************************************************************
1530**
1531** Function         gatt_clcb_dealloc
1532**
1533** Description      The function de allocates a GATT  connection link control block
1534**
1535** Returns         None
1536**
1537*******************************************************************************/
1538void gatt_clcb_dealloc (tGATT_CLCB *p_clcb)
1539{
1540    if (p_clcb && p_clcb->in_use)
1541    {
1542        memset(p_clcb, 0, sizeof(tGATT_CLCB));
1543    }
1544}
1545
1546
1547
1548/*******************************************************************************
1549**
1550** Function         gatt_find_tcb_by_cid
1551**
1552** Description      The function searches for an empty entry
1553**                   in registration info table for GATT client
1554**
1555** Returns           NULL if not found. Otherwise pointer to the rcb.
1556**
1557*******************************************************************************/
1558tGATT_TCB * gatt_find_tcb_by_cid (UINT16 lcid)
1559{
1560    UINT16       xx = 0;
1561    tGATT_TCB    *p_tcb = NULL;
1562
1563    for (xx = 0; xx < GATT_MAX_PHY_CHANNEL; xx++)
1564    {
1565        if (gatt_cb.tcb[xx].in_use && gatt_cb.tcb[xx].att_lcid == lcid)
1566        {
1567            p_tcb = &gatt_cb.tcb[xx];
1568            break;
1569        }
1570    }
1571    return p_tcb;
1572}
1573
1574
1575/*******************************************************************************
1576**
1577** Function         gatt_num_apps_hold_link
1578**
1579** Description      The function find the number of applcaitions is holding the link
1580**
1581** Returns          total number of applications holding this acl link.
1582**
1583*******************************************************************************/
1584UINT8 gatt_num_apps_hold_link(tGATT_TCB *p_tcb)
1585{
1586    UINT8 i, num = 0;
1587
1588    for (i = 0; i < GATT_MAX_APPS; i ++)
1589    {
1590        if (p_tcb->app_hold_link[i])
1591            num ++;
1592    }
1593
1594    GATT_TRACE_DEBUG1("gatt_num_apps_hold_link   num=%d",  num);
1595    return num;
1596}
1597
1598
1599/*******************************************************************************
1600**
1601** Function         gatt_num_clcb_by_bd_addr
1602**
1603** Description      The function searches all LCB with macthing bd address
1604**
1605** Returns          total number of clcb found.
1606**
1607*******************************************************************************/
1608UINT8 gatt_num_clcb_by_bd_addr(BD_ADDR bda)
1609{
1610    UINT8 i, num = 0;
1611
1612    for (i = 0; i < GATT_CL_MAX_LCB; i ++)
1613    {
1614        if (gatt_cb.clcb[i].in_use && memcmp(gatt_cb.clcb[i].p_tcb->peer_bda, bda, BD_ADDR_LEN) == 0)
1615            num ++;
1616    }
1617    return num;
1618}
1619
1620/*******************************************************************************
1621**
1622** Function         gatt_sr_update_cback_cnt
1623**
1624** Description      The function searches all LCB with macthing bd address
1625**
1626** Returns          total number of clcb found.
1627**
1628*******************************************************************************/
1629void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB *p_tcb )
1630{
1631    UINT8 i;
1632
1633    if (p_tcb)
1634    {
1635        for (i = 0; i < GATT_MAX_APPS; i ++)
1636        {
1637            if (p_tcb->prep_cnt[i])
1638            {
1639                p_tcb->sr_cmd.cback_cnt[i]=1;
1640            }
1641        }
1642    }
1643
1644}
1645
1646/*******************************************************************************
1647**
1648** Function         gatt_sr_is_cback_cnt_zero
1649**
1650** Description      The function searches all LCB with macthing bd address
1651**
1652** Returns          True if thetotal application callback count is zero
1653**
1654*******************************************************************************/
1655BOOLEAN gatt_sr_is_cback_cnt_zero(tGATT_TCB *p_tcb )
1656{
1657    BOOLEAN status = TRUE;
1658    UINT8   i;
1659
1660    if (p_tcb)
1661    {
1662        for (i = 0; i < GATT_MAX_APPS; i ++)
1663        {
1664            if (p_tcb->sr_cmd.cback_cnt[i])
1665            {
1666                status = FALSE;
1667                break;
1668            }
1669        }
1670    }
1671    else
1672    {
1673        status = FALSE;
1674    }
1675    return status;
1676}
1677
1678/*******************************************************************************
1679**
1680** Function         gatt_sr_is_prep_cnt_zero
1681**
1682** Description      Check the prepare write request count is zero or not
1683**
1684** Returns          True no prepare write request
1685**
1686*******************************************************************************/
1687BOOLEAN gatt_sr_is_prep_cnt_zero(tGATT_TCB *p_tcb)
1688{
1689    BOOLEAN status = TRUE;
1690    UINT8   i;
1691
1692    if (p_tcb)
1693    {
1694        for (i = 0; i < GATT_MAX_APPS; i ++)
1695        {
1696            if (p_tcb->prep_cnt[i])
1697            {
1698                status = FALSE;
1699                break;
1700            }
1701        }
1702    }
1703    else
1704    {
1705        status = FALSE;
1706    }
1707    return status;
1708}
1709
1710
1711/*******************************************************************************
1712**
1713** Function         gatt_sr_reset_cback_cnt
1714**
1715** Description      Reset the application callback count to zero
1716**
1717** Returns         None
1718**
1719*******************************************************************************/
1720void gatt_sr_reset_cback_cnt(tGATT_TCB *p_tcb )
1721{
1722    UINT8 i;
1723
1724    if (p_tcb)
1725    {
1726        for (i = 0; i < GATT_MAX_APPS; i ++)
1727        {
1728            p_tcb->sr_cmd.cback_cnt[i]=0;
1729        }
1730    }
1731}
1732
1733/*******************************************************************************
1734**
1735** Function         gatt_sr_reset_prep_cnt
1736**
1737** Description     Reset the prep write count to zero
1738**
1739** Returns        None
1740**
1741*******************************************************************************/
1742void gatt_sr_reset_prep_cnt(tGATT_TCB *p_tcb )
1743{
1744    UINT8 i;
1745    if (p_tcb)
1746    {
1747        for (i = 0; i < GATT_MAX_APPS; i ++)
1748        {
1749            p_tcb->prep_cnt[i]=0;
1750        }
1751    }
1752}
1753
1754
1755/*******************************************************************************
1756**
1757** Function         gatt_sr_update_cback_cnt
1758**
1759** Description    Update the teh applicaiton callback count
1760**
1761** Returns           None
1762**
1763*******************************************************************************/
1764void gatt_sr_update_cback_cnt(tGATT_TCB *p_tcb, tGATT_IF gatt_if, BOOLEAN is_inc, BOOLEAN is_reset_first)
1765{
1766
1767    UINT8 idx = ((UINT8) gatt_if) - 1 ;
1768
1769    if (p_tcb)
1770    {
1771        if (is_reset_first)
1772        {
1773            gatt_sr_reset_cback_cnt(p_tcb);
1774        }
1775        if (is_inc)
1776        {
1777            p_tcb->sr_cmd.cback_cnt[idx]++;
1778        }
1779        else
1780        {
1781            if ( p_tcb->sr_cmd.cback_cnt[idx])
1782            {
1783                p_tcb->sr_cmd.cback_cnt[idx]--;
1784            }
1785        }
1786    }
1787}
1788
1789
1790/*******************************************************************************
1791**
1792** Function         gatt_sr_update_prep_cnt
1793**
1794** Description    Update the teh prepare write request count
1795**
1796** Returns           None
1797**
1798*******************************************************************************/
1799void gatt_sr_update_prep_cnt(tGATT_TCB *p_tcb, tGATT_IF gatt_if, BOOLEAN is_inc, BOOLEAN is_reset_first)
1800{
1801    UINT8 idx = ((UINT8) gatt_if) - 1 ;
1802
1803    GATT_TRACE_DEBUG4("gatt_sr_update_prep_cnt tcb idx=%d gatt_if=%d is_inc=%d is_reset_first=%d",
1804                      p_tcb->tcb_idx, gatt_if, is_inc, is_reset_first);
1805
1806    if (p_tcb)
1807    {
1808        if (is_reset_first)
1809        {
1810            gatt_sr_reset_prep_cnt(p_tcb);
1811        }
1812        if (is_inc)
1813        {
1814            p_tcb->prep_cnt[idx]++;
1815        }
1816        else
1817        {
1818            if (p_tcb->prep_cnt[idx])
1819            {
1820                p_tcb->prep_cnt[idx]--;
1821            }
1822        }
1823    }
1824}
1825/*******************************************************************************
1826**
1827** Function         gatt_cancel_open
1828**
1829** Description      Cancel open request
1830**
1831** Returns         Boolean
1832**
1833*******************************************************************************/
1834BOOLEAN gatt_cancel_open(tGATT_IF gatt_if, BD_ADDR bda)
1835{
1836    tGATT_TCB *p_tcb=NULL;
1837    BOOLEAN status= TRUE;
1838
1839    p_tcb = gatt_find_tcb_by_addr(bda);
1840    if (p_tcb)
1841    {
1842        if (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)
1843        {
1844            GATT_TRACE_ERROR0("GATT_CancelConnect - link connected Too late to cancel");
1845            status = FALSE;
1846        }
1847        else
1848        {
1849            gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
1850            if (!gatt_num_apps_hold_link(p_tcb))
1851            {
1852                gatt_disconnect(p_tcb->peer_bda);
1853            }
1854        }
1855    }
1856
1857    return status;
1858}
1859
1860/*******************************************************************************
1861**
1862** Function         gatt_find_app_hold_link
1863**
1864** Description      find the applicaiton that is holding the specified link
1865**
1866** Returns         Boolean
1867**
1868*******************************************************************************/
1869BOOLEAN gatt_find_app_hold_link(tGATT_TCB *p_tcb, UINT8 start_idx, UINT8 *p_found_idx, tGATT_IF *p_gatt_if)
1870{
1871    UINT8 i;
1872    BOOLEAN found= FALSE;
1873
1874    for (i = start_idx; i < GATT_MAX_APPS; i ++)
1875    {
1876        if (p_tcb->app_hold_link[i])
1877        {
1878            *p_gatt_if = gatt_cb.clcb[i].p_reg->gatt_if;
1879            *p_found_idx = i;
1880            found = TRUE;
1881            break;
1882        }
1883    }
1884    return found;
1885}
1886
1887/*******************************************************************************
1888**
1889** Function         gatt_cmd_enq
1890**
1891** Description      Enqueue this command.
1892**
1893** Returns          None.
1894**
1895*******************************************************************************/
1896BOOLEAN gatt_cmd_enq(tGATT_TCB *p_tcb, UINT16 clcb_idx, BOOLEAN to_send, UINT8 op_code, BT_HDR *p_buf)
1897{
1898    tGATT_CMD_Q  *p_cmd = &p_tcb->cl_cmd_q[p_tcb->next_slot_inq];
1899
1900    p_cmd->to_send = to_send; /* waiting to be sent */
1901    p_cmd->op_code  = op_code;
1902    p_cmd->p_cmd    = p_buf;
1903    p_cmd->clcb_idx = clcb_idx;
1904
1905    if (!to_send)
1906    {
1907        p_tcb->pending_cl_req = p_tcb->next_slot_inq;
1908    }
1909
1910    p_tcb->next_slot_inq ++;
1911    p_tcb->next_slot_inq %= GATT_CL_MAX_LCB;
1912
1913    return TRUE;
1914}
1915
1916/*******************************************************************************
1917**
1918** Function         gatt_cmd_dequeue
1919**
1920** Description      dequeue the command in the client CCB command queue.
1921**
1922** Returns          total number of clcb found.
1923**
1924*******************************************************************************/
1925tGATT_CLCB * gatt_cmd_dequeue(tGATT_TCB *p_tcb, UINT8 *p_op_code)
1926{
1927    tGATT_CMD_Q  *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1928    tGATT_CLCB *p_clcb = NULL;
1929
1930    if (p_tcb->pending_cl_req != p_tcb->next_slot_inq)
1931    {
1932        p_clcb = &gatt_cb.clcb[p_cmd->clcb_idx];
1933
1934        *p_op_code = p_cmd->op_code;
1935
1936        p_tcb->pending_cl_req ++;
1937        p_tcb->pending_cl_req %= GATT_CL_MAX_LCB;
1938    }
1939
1940    return p_clcb;
1941}
1942
1943/*******************************************************************************
1944**
1945** Function         gatt_send_write_msg
1946**
1947** Description      This real function send out the ATT message for write.
1948**
1949** Returns          status code
1950**
1951*******************************************************************************/
1952UINT8 gatt_send_write_msg (tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 op_code,
1953                           UINT16 handle, UINT16 len,
1954                           UINT16 offset, UINT8 *p_data)
1955{
1956    tGATT_CL_MSG     msg;
1957
1958    msg.attr_value.handle = handle;
1959    msg.attr_value.len = len;
1960    msg.attr_value.offset = offset;
1961
1962    memcpy (msg.attr_value.value, p_data, len);
1963
1964    /* write by handle */
1965    return attp_send_cl_msg(p_tcb, clcb_idx, op_code, &msg);
1966}
1967
1968/*******************************************************************************
1969**
1970** Function         gatt_act_send_browse
1971**
1972** Description      This function ends a browse command request, including read
1973**                  information request and read by type request.
1974**
1975** Returns          status code
1976**
1977*******************************************************************************/
1978UINT8 gatt_act_send_browse(tGATT_TCB *p_tcb, UINT16 index, UINT8 op, UINT16 s_handle,
1979                           UINT16 e_handle, tBT_UUID uuid)
1980{
1981    tGATT_CL_MSG     msg;
1982
1983    msg.browse.s_handle = s_handle;
1984    msg.browse.e_handle   = e_handle;
1985    memcpy(&msg.browse.uuid, &uuid, sizeof(tBT_UUID));
1986
1987    /* write by handle */
1988    return attp_send_cl_msg(p_tcb, index, op, &msg);
1989}
1990
1991/*******************************************************************************
1992**
1993** Function         gatt_end_operation
1994**
1995** Description      This function ends a discovery, send callback and finalize
1996**                  some control value.
1997**
1998** Returns          16 bits uuid.
1999**
2000*******************************************************************************/
2001void gatt_end_operation(tGATT_CLCB *p_clcb, tGATT_STATUS status, void *p_data)
2002{
2003    tGATT_CL_COMPLETE   cb_data;
2004    tGATT_CMPL_CBACK    *p_cmpl_cb = (p_clcb->p_reg) ? p_clcb->p_reg->app_cb.p_cmpl_cb : NULL;
2005    UINT8               op = p_clcb->operation, disc_type=GATT_DISC_MAX;
2006    tGATT_DISC_CMPL_CB  *p_disc_cmpl_cb = (p_clcb->p_reg) ? p_clcb->p_reg->app_cb.p_disc_cmpl_cb : NULL;
2007    UINT16              conn_id;
2008    UINT8               operation;
2009
2010    GATT_TRACE_DEBUG3 ("gatt_end_operation status=%d op=%d subtype=%d",
2011                       status, p_clcb->operation, p_clcb->op_subtype);
2012
2013    if (p_cmpl_cb != NULL && p_clcb->operation != 0)
2014    {
2015        if (p_clcb->operation == GATTC_OPTYPE_READ)
2016        {
2017            memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
2018            cb_data.att_value.handle   = p_clcb->s_handle;
2019            cb_data.att_value.len      = p_clcb->counter;
2020            if (p_data)
2021                memcpy (cb_data.att_value.value, p_data, cb_data.att_value.len);
2022        }
2023
2024        if (p_clcb->operation == GATTC_OPTYPE_WRITE)
2025        {
2026            memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
2027            cb_data.handle           =
2028            cb_data.att_value.handle = p_clcb->s_handle;
2029            if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
2030            {
2031                if (p_data)
2032                {
2033                    cb_data.att_value = *((tGATT_VALUE *) p_data);
2034                }
2035                else
2036                {
2037                    GATT_TRACE_DEBUG0("Rcv Prepare write rsp but no data");
2038                }
2039            }
2040        }
2041
2042        if (p_clcb->operation == GATTC_OPTYPE_CONFIG)
2043            cb_data.mtu = p_clcb->p_tcb->payload_size;
2044
2045        if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
2046        {
2047            disc_type = p_clcb->op_subtype;
2048        }
2049    }
2050
2051    if (p_clcb->p_attr_buf)
2052    {
2053        GKI_freebuf(p_clcb->p_attr_buf);
2054    }
2055
2056    operation =  p_clcb->operation;
2057    conn_id = p_clcb->conn_id;
2058
2059    gatt_clcb_dealloc(p_clcb);
2060
2061    if (p_disc_cmpl_cb && (op == GATTC_OPTYPE_DISCOVERY))
2062        (*p_disc_cmpl_cb)(conn_id, disc_type, status);
2063    else if (p_cmpl_cb && op)
2064        (*p_cmpl_cb)(conn_id, op, status, &cb_data);
2065    else
2066        GATT_TRACE_WARNING3 ("gatt_end_operation not sent out op=%d p_disc_cmpl_cb:%p p_cmpl_cb:%p",
2067                             operation, p_disc_cmpl_cb, p_cmpl_cb);
2068}
2069
2070/*******************************************************************************
2071**
2072** Function         gatt_cleanup_upon_disc
2073**
2074** Description      This function cleans up the control blocks when L2CAP channel
2075**                  disconnect.
2076**
2077** Returns          16 bits uuid.
2078**
2079*******************************************************************************/
2080void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason)
2081{
2082    tGATT_TCB       *p_tcb = NULL;
2083    tGATT_CLCB      *p_clcb;
2084    UINT8           i;
2085    UINT16          conn_id;
2086    tGATT_REG        *p_reg=NULL;
2087
2088
2089    GATT_TRACE_DEBUG0 ("gatt_cleanup_upon_disc ");
2090
2091    if ((p_tcb = gatt_find_tcb_by_addr(bda)) != NULL)
2092    {
2093        GATT_TRACE_DEBUG0 ("found p_tcb ");
2094        for (i = 0; i < GATT_CL_MAX_LCB; i ++)
2095        {
2096            p_clcb = &gatt_cb.clcb[i];
2097            if (p_clcb->in_use && p_clcb->p_tcb == p_tcb)
2098            {
2099                GATT_TRACE_DEBUG2 ("found p_clcb conn_id=%d clcb_idx=%d", p_clcb->conn_id, p_clcb->clcb_idx);
2100                if (p_clcb->operation != GATTC_OPTYPE_NONE)
2101                    gatt_end_operation(p_clcb, GATT_ERROR, NULL);
2102
2103                gatt_clcb_dealloc(p_clcb);
2104
2105            }
2106        }
2107
2108        btu_stop_timer (&p_tcb->rsp_timer_ent);
2109        btu_stop_timer (&p_tcb->ind_ack_timer_ent);
2110        btu_stop_timer (&p_tcb->conf_timer_ent);
2111        gatt_free_pending_ind(p_tcb);
2112
2113        for (i = 0; i < GATT_MAX_APPS; i ++)
2114        {
2115            p_reg = &gatt_cb.cl_rcb[i];
2116            if (p_reg->in_use && p_reg->app_cb.p_conn_cb)
2117            {
2118                conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
2119                GATT_TRACE_DEBUG3 ("found p_reg tcb_idx=%d gatt_if=%d  conn_id=0x%x", p_tcb->tcb_idx, p_reg->gatt_if, conn_id);
2120                (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if,  bda, conn_id, FALSE, reason);
2121            }
2122        }
2123        memset(p_tcb, 0, sizeof(tGATT_TCB));
2124
2125    }
2126    GATT_TRACE_DEBUG0 ("exit gatt_cleanup_upon_disc ");
2127}
2128/*******************************************************************************
2129**
2130** Function         gatt_dbg_req_op_name
2131**
2132** Description      Get op code description name, for debug information.
2133**
2134** Returns          UINT8 *: name of the operation.
2135**
2136*******************************************************************************/
2137UINT8 * gatt_dbg_op_name(UINT8 op_code)
2138{
2139    UINT8 pseduo_op_code_idx = op_code & (~GATT_WRITE_CMD_MASK);
2140
2141    if (op_code == GATT_CMD_WRITE )
2142    {
2143        pseduo_op_code_idx = 0x14; /* just an index to op_code_name */
2144
2145    }
2146
2147    if (op_code == GATT_SIGN_CMD_WRITE)
2148    {
2149        pseduo_op_code_idx = 0x15; /* just an index to op_code_name */
2150    }
2151
2152    if (pseduo_op_code_idx <= GATT_OP_CODE_MAX)
2153        return(UINT8*) op_code_name[pseduo_op_code_idx];
2154    else
2155        return(UINT8 *)"Op Code Exceed Max";
2156}
2157
2158/*******************************************************************************
2159**
2160** Function         gatt_dbg_display_uuid
2161**
2162** Description      Disaplay the UUID
2163**
2164** Returns          None
2165**
2166*******************************************************************************/
2167void gatt_dbg_display_uuid(tBT_UUID bt_uuid)
2168{
2169    char str_buf[50];
2170    int x = 0;
2171
2172    if (bt_uuid.len == LEN_UUID_16)
2173    {
2174        sprintf(str_buf, "0x%04x", bt_uuid.uu.uuid16);
2175    }
2176    else if (bt_uuid.len == LEN_UUID_128)
2177    {
2178        x += sprintf(&str_buf[x], "0x%02x%02x%02x%02x%02x%02x%02x%02x",
2179                     bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14],
2180                     bt_uuid.uu.uuid128[13], bt_uuid.uu.uuid128[12],
2181                     bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10],
2182                     bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]);
2183        sprintf(&str_buf[x], "%02x%02x%02x%02x%02x%02x%02x%02x",
2184                bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6],
2185                bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[4],
2186                bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2],
2187                bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]);
2188    }
2189    else
2190        BCM_STRNCPY_S(str_buf, sizeof(str_buf), "Unknown UUID 0", 15);
2191
2192    GATT_TRACE_DEBUG1 ("UUID=[%s]", str_buf);
2193
2194}
2195
2196
2197/*******************************************************************************
2198**
2199** Function         gatt_is_bg_dev_for_app
2200**
2201** Description      find is this one of the background devices for the application
2202**
2203** Returns          TRUE this is one of the background devices for the  application
2204**
2205*******************************************************************************/
2206BOOLEAN gatt_is_bg_dev_for_app(tGATT_BG_CONN_DEV *p_dev, tGATT_IF gatt_if)
2207{
2208    UINT8   i;
2209
2210    for (i = 0; i < GATT_MAX_APPS; i ++ )
2211    {
2212        if (p_dev->in_use && (p_dev->gatt_if[i] == gatt_if))
2213        {
2214            return TRUE;
2215        }
2216    }
2217    return FALSE;
2218}
2219/*******************************************************************************
2220**
2221** Function         gatt_find_bg_dev
2222**
2223** Description      find background connection device from the list.
2224**
2225** Returns          pointer to the device record
2226**
2227*******************************************************************************/
2228tGATT_BG_CONN_DEV * gatt_find_bg_dev(BD_ADDR remote_bda)
2229{
2230    tGATT_BG_CONN_DEV    *p_dev_list = &gatt_cb.bgconn_dev[0];
2231    UINT8   i;
2232
2233    for (i = 0; i < GATT_MAX_BG_CONN_DEV; i ++, p_dev_list ++)
2234    {
2235        if (p_dev_list->in_use && !memcmp(p_dev_list->remote_bda, remote_bda, BD_ADDR_LEN))
2236        {
2237            return p_dev_list;
2238        }
2239    }
2240    return NULL;
2241}
2242/*******************************************************************************
2243**
2244** Function         gatt_alloc_bg_dev
2245**
2246** Description      allocate a background connection device record
2247**
2248** Returns          pointer to the device record
2249**
2250*******************************************************************************/
2251tGATT_BG_CONN_DEV * gatt_alloc_bg_dev(BD_ADDR remote_bda)
2252{
2253    tGATT_BG_CONN_DEV    *p_dev_list = &gatt_cb.bgconn_dev[0];
2254    UINT8   i;
2255
2256    for (i = 0; i < GATT_MAX_BG_CONN_DEV; i ++, p_dev_list ++)
2257    {
2258        if (!p_dev_list->in_use)
2259        {
2260            p_dev_list->in_use = TRUE;
2261            memcpy(p_dev_list->remote_bda, remote_bda, BD_ADDR_LEN);
2262
2263            return p_dev_list;
2264        }
2265    }
2266    return NULL;
2267}
2268
2269/*******************************************************************************
2270**
2271** Function         gatt_add_bg_dev_list
2272**
2273** Description      add/remove device from the back ground connection device list
2274**
2275** Returns          pointer to the device record
2276**
2277*******************************************************************************/
2278BOOLEAN gatt_add_bg_dev_list(tGATT_IF gatt_if, BD_ADDR bd_addr)
2279{
2280    tGATT_BG_CONN_DEV   *p_dev = NULL;
2281    UINT8   i;
2282
2283    if ((p_dev = gatt_find_bg_dev(bd_addr)) == NULL)
2284    {
2285        p_dev = gatt_alloc_bg_dev(bd_addr);
2286    }
2287
2288    if (p_dev)
2289    {
2290        for (i = 0; i < GATT_MAX_APPS; i ++)
2291        {
2292            if (p_dev->gatt_if[i] == gatt_if)
2293            {
2294                GATT_TRACE_ERROR0("device already in list");
2295                return FALSE;
2296            }
2297            else if (p_dev->gatt_if[i] == 0)
2298            {
2299                GATT_TRACE_DEBUG0("add device into list");
2300                p_dev->gatt_if[i] = gatt_if;
2301                return TRUE;
2302            }
2303        }
2304    }
2305
2306    GATT_TRACE_ERROR0("no device record available");
2307
2308    return FALSE;
2309}
2310
2311
2312/*******************************************************************************
2313**
2314** Function         gatt_remove_bg_dev_for_app
2315**
2316** Description      Remove the application interface for the specified background device
2317**
2318** Returns          Boolean
2319**
2320*******************************************************************************/
2321BOOLEAN gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, BD_ADDR bd_addr)
2322{
2323    tGATT_TCB    *p_tcb = gatt_find_tcb_by_addr(bd_addr);
2324    BOOLEAN       status;
2325
2326    if (p_tcb)
2327        gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
2328    status = gatt_update_auto_connect_dev(gatt_if, FALSE, bd_addr);
2329    return status;
2330}
2331
2332
2333/*******************************************************************************
2334**
2335** Function         gatt_get_num_apps_for_bg_dev
2336**
2337** Description      Gte the number of applciations for the specified background device
2338**
2339** Returns          UINT8 total number fo applications
2340**
2341*******************************************************************************/
2342UINT8 gatt_get_num_apps_for_bg_dev(BD_ADDR bd_addr)
2343{
2344    tGATT_BG_CONN_DEV   *p_dev = NULL;
2345    UINT8   i;
2346    UINT8   cnt = 0;
2347
2348    if ((p_dev = gatt_find_bg_dev(bd_addr)) != NULL)
2349    {
2350        for (i = 0; i < GATT_MAX_APPS; i ++)
2351        {
2352            if (p_dev->gatt_if[i])
2353                cnt++;
2354        }
2355    }
2356    return cnt;
2357}
2358
2359/*******************************************************************************
2360**
2361** Function         gatt_find_app_for_bg_dev
2362**
2363** Description      find the application interface for the specified background device
2364**
2365** Returns          Boolean
2366**
2367*******************************************************************************/
2368BOOLEAN gatt_find_app_for_bg_dev(BD_ADDR bd_addr, tGATT_IF *p_gatt_if)
2369{
2370    tGATT_BG_CONN_DEV   *p_dev = NULL;
2371    UINT8   i;
2372    BOOLEAN ret = FALSE;
2373
2374    if ((p_dev = gatt_find_bg_dev(bd_addr)) == NULL)
2375    {
2376        return ret;
2377    }
2378
2379    for (i = 0; i < GATT_MAX_APPS; i ++)
2380    {
2381        if (p_dev->gatt_if[i] != 0 )
2382        {
2383            *p_gatt_if = p_dev->gatt_if[i];
2384            ret = TRUE;
2385            break;
2386        }
2387    }
2388    return ret;
2389}
2390
2391
2392/*******************************************************************************
2393**
2394** Function         gatt_remove_bg_dev_from_list
2395**
2396** Description      add/remove device from the back ground connection device list
2397**
2398** Returns          pointer to the device record
2399**
2400*******************************************************************************/
2401BOOLEAN gatt_remove_bg_dev_from_list(tGATT_IF gatt_if, BD_ADDR bd_addr)
2402{
2403    tGATT_BG_CONN_DEV   *p_dev = NULL;
2404    UINT8   i, j;
2405    BOOLEAN ret = FALSE;
2406
2407    if ((p_dev = gatt_find_bg_dev(bd_addr)) == NULL)
2408    {
2409        return ret;
2410    }
2411
2412    for (i = 0; i < GATT_MAX_APPS && p_dev->gatt_if[i] > 0; i ++)
2413    {
2414        if (p_dev->gatt_if[i] == gatt_if)
2415        {
2416            p_dev->gatt_if[i] = 0;
2417
2418            for (j = i + 1; j < GATT_MAX_APPS; j ++)
2419                p_dev->gatt_if[j - 1] = p_dev->gatt_if[j];
2420
2421            if (p_dev->gatt_if[0] == 0)
2422            {
2423                ret = BTM_BleUpdateBgConnDev(FALSE, p_dev->remote_bda);
2424                memset(p_dev, 0, sizeof(tGATT_BG_CONN_DEV));
2425            }
2426            else
2427                ret = TRUE;
2428
2429            break;
2430        }
2431    }
2432
2433    return ret;
2434}
2435/*******************************************************************************
2436**
2437** Function         gatt_deregister_bgdev_list
2438**
2439** Description      deregister all related back ground connetion device.
2440**
2441** Returns          pointer to the device record
2442**
2443*******************************************************************************/
2444void gatt_deregister_bgdev_list(tGATT_IF gatt_if)
2445{
2446    tGATT_BG_CONN_DEV    *p_dev_list = &gatt_cb.bgconn_dev[0];
2447    UINT8 i , j, k;
2448
2449    for (i = 0 ; i <GATT_MAX_BG_CONN_DEV; i ++, p_dev_list ++ )
2450    {
2451        if (p_dev_list->in_use)
2452        {
2453            for (j = 0; j < GATT_MAX_APPS; j ++)
2454            {
2455                if (p_dev_list->gatt_if[j] == 0)
2456                    break;
2457                else if (p_dev_list->gatt_if[j] == gatt_if)
2458                {
2459                    for (k = j + 1; k < GATT_MAX_APPS; k ++)
2460                        p_dev_list->gatt_if[k - 1] = p_dev_list->gatt_if[k];
2461
2462                    if (p_dev_list->gatt_if[0] == 0)
2463                    {
2464                        BTM_BleUpdateBgConnDev(FALSE, p_dev_list->remote_bda);
2465                        memset(p_dev_list, 0, sizeof(tGATT_BG_CONN_DEV));
2466                        break;
2467                    }
2468                }
2469            }
2470        }
2471    }
2472}
2473
2474
2475/*******************************************************************************
2476**
2477** Function         gatt_reset_bgdev_list
2478**
2479** Description      reset bg device list
2480**
2481** Returns          pointer to the device record
2482**
2483*******************************************************************************/
2484void gatt_reset_bgdev_list(void)
2485{
2486    memset(&gatt_cb.bgconn_dev, 0 , sizeof(tGATT_BG_CONN_DEV)*GATT_MAX_BG_CONN_DEV);
2487
2488}
2489/*******************************************************************************
2490**
2491** Function         gatt_update_auto_connect_dev
2492**
2493** Description      This function add or remove a device for background connection
2494**                  procedure.
2495**
2496** Parameters       gatt_if: Application ID.
2497**                  add: add peer device
2498**                  bd_addr: peer device address.
2499**
2500** Returns          TRUE if connection started; FALSE if connection start failure.
2501**
2502*******************************************************************************/
2503BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr)
2504{
2505    BOOLEAN         ret = FALSE, exist_dev = FALSE;
2506    tGATT_REG        *p_reg;
2507    tGATT_TCB       *p_tcb = gatt_find_tcb_by_addr(bd_addr);
2508
2509    GATT_TRACE_API0 ("gatt_update_auto_connect_dev ");
2510    /* Make sure app is registered */
2511    if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
2512    {
2513        GATT_TRACE_ERROR1("gatt_update_auto_connect_dev - gatt_if is not registered", gatt_if);
2514        return(FALSE);
2515    }
2516
2517    if (add)
2518    {
2519        /* new device */
2520        if (gatt_find_bg_dev(bd_addr))
2521            exist_dev = TRUE;
2522
2523        if (gatt_add_bg_dev_list(gatt_if, bd_addr))
2524        {
2525            if (!exist_dev)
2526            {
2527                ret = BTM_BleUpdateBgConnDev(TRUE, bd_addr);
2528            }
2529            else
2530                ret = TRUE;
2531
2532            /* if a connected device, update the link holding number */
2533            if (p_tcb != NULL)
2534                gatt_update_app_use_link_flag(gatt_if, p_tcb, TRUE, TRUE);
2535        }
2536    }
2537    else
2538    {
2539        ret = gatt_remove_bg_dev_from_list(gatt_if, bd_addr);
2540    }
2541    return ret;
2542}
2543
2544
2545
2546/*******************************************************************************
2547**
2548** Function         gatt_get_conn_id
2549**
2550** Description      This function returns a connecttion handle to a ATT server
2551**                  if the server is already connected
2552**
2553** Parameters       gatt_if: client interface.
2554**                  bd_addr: peer device address.
2555**
2556** Returns          Connection handle or invalid handle value
2557**
2558*******************************************************************************/
2559UINT16 gatt_get_conn_id (tGATT_IF gatt_if, BD_ADDR bd_addr)
2560{
2561    tGATT_REG       *p_reg;
2562    tGATT_CLCB      *p_clcb;
2563    tGATT_TCB       *p_tcb;
2564    UINT8           i;
2565
2566    GATT_TRACE_API1 ("GATTC_GetConnIfConnected gatt_if=%d", gatt_if);
2567    /* Do we have a transport to the peer ? If not, we are not connected */
2568    if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) == NULL)
2569    {
2570        GATT_TRACE_EVENT0 ("GATTC_GetConnIfConnected - no TCB found");
2571        return(GATT_INVALID_CONN_ID);
2572    }
2573
2574    /* Make sure app is registered */
2575    if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
2576    {
2577        GATT_TRACE_ERROR1("GATTC_GetConnIfConnected - gatt_if is not registered", gatt_if);
2578        return(GATT_INVALID_CONN_ID);
2579    }
2580
2581    /* Now see if the app already has a client control block to that peer */
2582    for (i = 0, p_clcb = gatt_cb.clcb; i < GATT_CL_MAX_LCB; i++, p_clcb++)
2583    {
2584        if ( p_clcb->in_use && (p_clcb->p_reg == p_reg) && (p_clcb->p_tcb == p_tcb) )
2585        {
2586            return(p_clcb->conn_id);
2587        }
2588    }
2589
2590    /* If here, failed to allocate a client control block */
2591    GATT_TRACE_ERROR1 ("gatt_get_conn_id: not connected- gatt_if: %u", gatt_if);
2592    return(GATT_INVALID_CONN_ID);
2593}
2594
2595
2596
2597
2598#endif
2599
2600
2601