1/******************************************************************************
2 *
3 *  Copyright (C) 2008-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 main ATT functions
22 *
23 ******************************************************************************/
24
25#include "bt_target.h"
26
27#if BLE_INCLUDED == TRUE
28
29#include "gki.h"
30#include "gatt_int.h"
31#include "l2c_api.h"
32#include "btm_int.h"
33#include "btm_ble_int.h"
34
35/* Configuration flags. */
36#define GATT_L2C_CFG_IND_DONE   (1<<0)
37#define GATT_L2C_CFG_CFM_DONE   (1<<1)
38
39/********************************************************************************/
40/*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
41/********************************************************************************/
42static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason);
43static void gatt_le_data_ind (BD_ADDR bd_addr, BT_HDR *p_buf);
44
45static void gatt_l2cif_connect_ind_cback (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
46static void gatt_l2cif_connect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
47static void gatt_l2cif_config_ind_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
48static void gatt_l2cif_config_cfm_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
49static void gatt_l2cif_disconnect_ind_cback (UINT16 l2cap_cid, BOOLEAN ack_needed);
50static void gatt_l2cif_disconnect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
51static void gatt_l2cif_data_ind_cback (UINT16 l2cap_cid, BT_HDR *p_msg);
52static void gatt_send_conn_cback (BOOLEAN is_bg_conn, tGATT_TCB *p_tcb);
53
54static const tL2CAP_APPL_INFO dyn_info =
55{
56    gatt_l2cif_connect_ind_cback,
57    gatt_l2cif_connect_cfm_cback,
58    NULL,
59    gatt_l2cif_config_ind_cback,
60    gatt_l2cif_config_cfm_cback,
61    gatt_l2cif_disconnect_ind_cback,
62    gatt_l2cif_disconnect_cfm_cback,
63    NULL,
64    gatt_l2cif_data_ind_cback,
65    NULL
66} ;
67
68#if GATT_DYNAMIC_MEMORY == FALSE
69tGATT_CB  gatt_cb;
70#endif
71
72/*******************************************************************************
73**
74** Function         gatt_init
75**
76** Description      This function is enable the GATT profile on the device.
77**                  It clears out the control blocks, and registers with L2CAP.
78**
79** Returns          void
80**
81*******************************************************************************/
82void gatt_init (void)
83{
84    tL2CAP_FIXED_CHNL_REG  fixed_reg;
85
86    GATT_TRACE_DEBUG0("gatt_init()");
87
88    memset (&gatt_cb, 0, sizeof(tGATT_CB));
89
90#if defined(GATT_INITIAL_TRACE_LEVEL)
91    gatt_cb.trace_level = GATT_INITIAL_TRACE_LEVEL;
92#else
93    gatt_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
94#endif
95    gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE;
96    GKI_init_q (&gatt_cb.sign_op_queue);
97    /* First, register fixed L2CAP channel for ATT over BLE */
98    fixed_reg.fixed_chnl_opts.mode         = L2CAP_FCR_BASIC_MODE;
99    fixed_reg.fixed_chnl_opts.max_transmit = 0xFF;
100    fixed_reg.fixed_chnl_opts.rtrans_tout  = 2000;
101    fixed_reg.fixed_chnl_opts.mon_tout     = 12000;
102    fixed_reg.fixed_chnl_opts.mps          = 670;
103    fixed_reg.fixed_chnl_opts.tx_win_sz    = 1;
104
105    fixed_reg.pL2CA_FixedConn_Cb = gatt_le_connect_cback;
106    fixed_reg.pL2CA_FixedData_Cb = gatt_le_data_ind;
107    fixed_reg.default_idle_tout  = 0xffff;                  /* 0xffff default idle timeout */
108
109    L2CA_RegisterFixedChannel (L2CAP_ATT_CID, &fixed_reg);
110
111    /* Now, register with L2CAP for ATT PSM over BR/EDR */
112    if (!L2CA_Register (BT_PSM_ATT, (tL2CAP_APPL_INFO *) &dyn_info))
113    {
114        GATT_TRACE_ERROR0 ("ATT Dynamic Registration failed");
115    }
116
117    BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0);
118    BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0);
119
120    gatt_cb.hdl_cfg.gatt_start_hdl = GATT_GATT_START_HANDLE;
121    gatt_cb.hdl_cfg.gap_start_hdl  = GATT_GAP_START_HANDLE;
122    gatt_cb.hdl_cfg.app_start_hdl  = GATT_APP_START_HANDLE;
123    gatt_profile_db_init();
124
125}
126
127
128
129/*******************************************************************************
130**
131** Function         gatt_connect
132**
133** Description      This function is called to initiate a connection to a peer device.
134**
135** Parameter        rem_bda: remote device address to connect to.
136**
137** Returns          TRUE if connection is started, otherwise return FALSE.
138**
139*******************************************************************************/
140BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb)
141{
142    BOOLEAN             gatt_ret = TRUE;
143    tBT_DEVICE_TYPE     dev_type;
144    tBLE_ADDR_TYPE      addr_type;
145
146    BTM_ReadDevInfo(rem_bda, &dev_type, &addr_type);
147
148    gatt_set_ch_state(p_tcb, GATT_CH_CONN);
149
150    if (dev_type == BT_DEVICE_TYPE_BLE)
151    {
152        p_tcb->att_lcid = L2CAP_ATT_CID;
153        gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda);
154    }
155    else
156    {
157        if ((p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda)) == 0)
158            gatt_ret = FALSE;
159    }
160
161    return gatt_ret;
162}
163
164/*******************************************************************************
165**
166** Function         gatt_disconnect
167**
168** Description      This function is called to disconnect to an ATT device.
169**
170** Parameter        rem_bda: remote device address to disconnect from.
171**
172** Returns          TRUE: if connection found and to be disconnected; otherwise
173**                  return FALSE.
174**
175*******************************************************************************/
176BOOLEAN gatt_disconnect (BD_ADDR rem_bda)
177{
178    tGATT_TCB           *p_tcb = gatt_find_tcb_by_addr(rem_bda);
179    BOOLEAN             ret = FALSE;
180    tGATT_CH_STATE      ch_state;
181    GATT_TRACE_DEBUG0 ("gatt_disconnect ");
182
183    if (p_tcb != NULL)
184    {
185        ret = TRUE;
186        if ( (ch_state = gatt_get_ch_state(p_tcb)) != GATT_CH_CLOSING )
187        {
188            if (p_tcb->att_lcid == L2CAP_ATT_CID)
189            {
190                if (ch_state == GATT_CH_OPEN)
191                    /* only LCB exist between remote device and local */
192                    ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, rem_bda);
193                else
194                {
195                    gatt_set_ch_state(p_tcb, GATT_CH_CLOSING);
196                    ret = L2CA_CancelBleConnectReq (rem_bda);
197                }
198            }
199            else
200            {
201                ret = L2CA_DisconnectReq(p_tcb->att_lcid);
202            }
203        }
204        else
205        {
206            GATT_TRACE_DEBUG0 ("gatt_disconnect already in closing state");
207        }
208    }
209
210    return ret;
211}
212
213/*******************************************************************************
214**
215** Function         gatt_update_app_hold_link_status
216**
217** Description      Update the application use link status
218**
219** Returns          void.
220**
221*******************************************************************************/
222void gatt_update_app_hold_link_status (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add)
223{
224    UINT8 i;
225    BOOLEAN found=FALSE;
226
227    if (p_tcb == NULL)
228    {
229        GATT_TRACE_ERROR0("gatt_update_app_hold_link_status p_tcb=NULL");
230        return;
231    }
232
233
234    for (i=0; i<GATT_MAX_APPS; i++)
235    {
236        if (p_tcb->app_hold_link[i] ==  gatt_if)
237        {
238            found = TRUE;
239            if (!is_add)
240            {
241                p_tcb->app_hold_link[i] = 0;
242                break;
243            }
244        }
245    }
246
247    if (!found && is_add)
248    {
249        for (i=0; i<GATT_MAX_APPS; i++)
250        {
251            if (p_tcb->app_hold_link[i] ==  0)
252            {
253                p_tcb->app_hold_link[i] = gatt_if;
254                found = TRUE;
255                break;
256            }
257        }
258    }
259
260    GATT_TRACE_DEBUG4("gatt_update_app_hold_link_status found=%d[1-found] idx=%d gatt_if=%d is_add=%d", found, i, gatt_if, is_add);
261
262}
263
264/*******************************************************************************
265**
266** Function         gatt_update_app_use_link_flag
267**
268** Description      Update the application use link flag and optional to check the acl link
269**                  if the link is up then set the idle time out accordingly
270**
271** Returns          void.
272**
273*******************************************************************************/
274void gatt_update_app_use_link_flag (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link)
275{
276    GATT_TRACE_DEBUG2("gatt_update_app_use_link_flag  is_add=%d chk_link=%d",
277                      is_add, check_acl_link);
278
279    gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add);
280
281    if (check_acl_link &&
282        p_tcb &&
283        (BTM_GetHCIConnHandle(p_tcb->peer_bda) != GATT_INVALID_ACL_HANDLE))
284    {
285        if (is_add)
286        {
287            GATT_TRACE_DEBUG0("GATT disables link idle timer");
288            /* acl link is connected disable the idle timeout */
289            GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT);
290        }
291        else
292        {
293            if (!gatt_num_apps_hold_link(p_tcb))
294            {
295                /* acl link is connected but no application needs to use the link
296                   so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */
297                GATT_TRACE_DEBUG1("GATT starts link idle timer =%d sec", GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
298                GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
299            }
300
301        }
302    }
303}
304
305/*******************************************************************************
306**
307** Function         gatt_act_connect
308**
309** Description      GATT connection initiation.
310**
311** Returns          void.
312**
313*******************************************************************************/
314BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr)
315{
316    BOOLEAN     ret = FALSE;
317    tGATT_TCB   *p_tcb;
318
319    GATT_TRACE_DEBUG0("gatt_act_connect");
320
321    if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
322    {
323        ret = TRUE;
324        if(gatt_get_ch_state(p_tcb) == GATT_CH_CLOSING )
325        {
326            /* need to complete the closing first */
327            ret = FALSE;
328        }
329    }
330    else
331    {
332        if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) != NULL)
333        {
334            if (!gatt_connect(bd_addr,  p_tcb))
335            {
336                GATT_TRACE_ERROR0("gatt_connect failed");
337                memset(p_tcb, 0, sizeof(tGATT_TCB));
338            }
339            else
340                ret = TRUE;
341        }
342        else
343        {
344            ret = 0;
345            GATT_TRACE_ERROR1("Max TCB for gatt_if [%d] reached.", p_reg->gatt_if);
346        }
347    }
348
349    if (ret)
350    {
351        gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE);
352    }
353
354    return ret;
355}
356
357/*******************************************************************************
358**
359** Function         gatt_le_connect_cback
360**
361** Description      This callback function is called by L2CAP to indicate that
362**                  the ATT fixed channel for LE is
363**                      connected (conn = TRUE)/disconnected (conn = FALSE).
364**
365*******************************************************************************/
366static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason)
367{
368
369    tGATT_TCB       *p_tcb = gatt_find_tcb_by_addr(bd_addr);
370
371    BOOLEAN                 check_srv_chg = FALSE;
372    tGATTS_SRV_CHG          *p_srv_chg_clt=NULL;
373    BOOLEAN                 is_bg_conn = FALSE;
374
375
376    GATT_TRACE_DEBUG3 ("GATT   ATT protocol channel with BDA: %08x%04x is %s",
377                       (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
378                       (bd_addr[4]<<8)+bd_addr[5], (connected) ? "connected" : "disconnected");
379
380
381    if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr)) != NULL)
382    {
383        check_srv_chg = TRUE;
384    }
385    else
386    {
387        if (btm_sec_is_a_bonded_dev(bd_addr))
388            gatt_add_a_bonded_dev_for_srv_chg(bd_addr);
389    }
390
391    if (connected)
392    {
393        GATT_TRACE_DEBUG1("connected is TRUE reason=%d",reason );
394        /* BR/EDR lik, ignore this callback */
395        if (reason == 0)
396            return;
397
398        /* do we have a channel initiating a connection? */
399        if (p_tcb)
400        {
401            if (check_srv_chg)
402                gatt_chk_srv_chg (p_srv_chg_clt);
403            /* we are initiating connection */
404            if ( gatt_get_ch_state(p_tcb) == GATT_CH_CONN)
405            {
406                /* send callback */
407                gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
408                p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
409
410                gatt_send_conn_cback(FALSE, p_tcb);
411            }
412            else /* there was an exisiting link, ignore the callback */
413            {
414                GATT_TRACE_ERROR0("connection already up, ignore it");
415                return;
416            }
417        }
418        /* this is incoming connection or background connection callback */
419        else
420        {
421            if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) != NULL)
422            {
423                p_tcb->att_lcid = L2CAP_ATT_CID;
424
425                gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
426
427                p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
428                if (L2CA_GetBleConnRole(p_tcb->peer_bda)== HCI_ROLE_MASTER)
429                {
430                    is_bg_conn = TRUE;
431                }
432                gatt_send_conn_cback (is_bg_conn, p_tcb);
433                if (check_srv_chg)
434                {
435                    gatt_chk_srv_chg (p_srv_chg_clt);
436                }
437            }
438            else
439            {
440                GATT_TRACE_ERROR0("CCB max out, no rsources");
441            }
442        }
443    }
444    else
445    {
446        gatt_cleanup_upon_disc(bd_addr, reason);
447        GATT_TRACE_DEBUG0 ("ATT disconnected");
448    }
449}
450
451/*******************************************************************************
452**
453** Function         gatt_le_data_ind
454**
455** Description      This function is called when data is received from L2CAP.
456**                  if we are the originator of the connection, we are the ATT
457**                  client, and the received message is queued up for the client.
458**
459**                  If we are the destination of the connection, we are the ATT
460**                  server, so the message is passed to the server processing
461**                  function.
462**
463** Returns          void
464**
465*******************************************************************************/
466static void gatt_le_data_ind (BD_ADDR bd_addr, BT_HDR *p_buf)
467{
468    tGATT_TCB    *p_tcb;
469
470    /* Find CCB based on bd addr */
471    if ((p_tcb = gatt_find_tcb_by_addr (bd_addr)) != NULL &&
472        gatt_get_ch_state(p_tcb) >= GATT_CH_OPEN)
473    {
474        gatt_data_process(p_tcb, p_buf);
475    }
476    else
477    {
478        GKI_freebuf (p_buf);
479
480        if (p_tcb != NULL)
481        {
482            GATT_TRACE_WARNING1 ("ATT - Ignored L2CAP data while in state: %d",
483                                 gatt_get_ch_state(p_tcb));
484        }
485    }
486}
487
488/*******************************************************************************
489**
490** Function         gatt_l2cif_connect_ind
491**
492** Description      This function handles an inbound connection indication
493**                  from L2CAP. This is the case where we are acting as a
494**                  server.
495**
496** Returns          void
497**
498*******************************************************************************/
499static void gatt_l2cif_connect_ind_cback (BD_ADDR  bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
500{
501    /* do we already have a control channel for this peer? */
502    UINT8       result = L2CAP_CONN_OK;
503    tL2CAP_CFG_INFO cfg;
504    tGATT_TCB       *p_tcb = gatt_find_tcb_by_addr(bd_addr);
505
506    GATT_TRACE_ERROR1("Connection indication cid = %d", lcid);
507    /* new connection ? */
508    if (p_tcb == NULL)
509    {
510        /* allocate tcb */
511        if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) == NULL)
512        {
513            /* no tcb available, reject L2CAP connection */
514            result = L2CAP_CONN_NO_RESOURCES;
515        }
516        else
517            p_tcb->att_lcid = lcid;
518
519    }
520    else /* existing connection , reject it */
521    {
522        result = L2CAP_CONN_NO_RESOURCES;
523    }
524
525    /* Send L2CAP connect rsp */
526    L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
527
528    /* if result ok, proceed with connection */
529    if (result == L2CAP_CONN_OK)
530    {
531        /* transition to configuration state */
532        gatt_set_ch_state(p_tcb, GATT_CH_CFG);
533
534        /* Send L2CAP config req */
535        memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
536        cfg.mtu_present = TRUE;
537        cfg.mtu = GATT_MAX_MTU_SIZE;
538
539        L2CA_ConfigReq(lcid, &cfg);
540    }
541}
542
543/*******************************************************************************
544**
545** Function         gatt_l2c_connect_cfm_cback
546**
547** Description      This is the L2CAP connect confirm callback function.
548**
549**
550** Returns          void
551**
552*******************************************************************************/
553void gatt_l2cif_connect_cfm_cback(UINT16 lcid, UINT16 result)
554{
555    tGATT_TCB       *p_tcb;
556    tL2CAP_CFG_INFO cfg;
557
558    /* look up clcb for this channel */
559    if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
560    {
561        GATT_TRACE_DEBUG3("gatt_l2c_connect_cfm_cback result: %d ch_state: %d, lcid:0x%x", result, gatt_get_ch_state(p_tcb), p_tcb->att_lcid);
562
563        /* if in correct state */
564        if (gatt_get_ch_state(p_tcb) == GATT_CH_CONN)
565        {
566            /* if result successful */
567            if (result == L2CAP_CONN_OK)
568            {
569                /* set channel state */
570                gatt_set_ch_state(p_tcb, GATT_CH_CFG);
571
572                /* Send L2CAP config req */
573                memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
574                cfg.mtu_present = TRUE;
575                cfg.mtu = GATT_MAX_MTU_SIZE;
576                L2CA_ConfigReq(lcid, &cfg);
577            }
578            /* else initiating connection failure */
579            else
580            {
581                gatt_cleanup_upon_disc(p_tcb->peer_bda, result);
582            }
583        }
584        else /* wrong state, disconnect it */
585        {
586            if (result == L2CAP_CONN_OK)
587            {
588                /* just in case the peer also accepts our connection - Send L2CAP disconnect req */
589                L2CA_DisconnectReq(lcid);
590            }
591        }
592    }
593}
594
595/*******************************************************************************
596**
597** Function         gatt_l2cif_config_cfm_cback
598**
599** Description      This is the L2CAP config confirm callback function.
600**
601**
602** Returns          void
603**
604*******************************************************************************/
605void gatt_l2cif_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
606{
607    tGATT_TCB       *p_tcb;
608    tGATTS_SRV_CHG  *p_srv_chg_clt=NULL;
609
610    /* look up clcb for this channel */
611    if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
612    {
613        /* if in correct state */
614        if ( gatt_get_ch_state(p_tcb) == GATT_CH_CFG)
615        {
616            /* if result successful */
617            if (p_cfg->result == L2CAP_CFG_OK)
618            {
619                /* update flags */
620                p_tcb->ch_flags |= GATT_L2C_CFG_CFM_DONE;
621
622                /* if configuration complete */
623                if (p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE)
624                {
625                    gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
626
627                    if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL)
628                    {
629                        gatt_chk_srv_chg(p_srv_chg_clt);
630                    }
631                    else
632                    {
633                        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
634                            gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
635                    }
636
637                    /* send callback */
638                    gatt_send_conn_cback(FALSE, p_tcb);
639                }
640            }
641            /* else failure */
642            else
643            {
644                /* Send L2CAP disconnect req */
645                L2CA_DisconnectReq(lcid);
646            }
647        }
648    }
649}
650
651/*******************************************************************************
652**
653** Function         gatt_l2cif_config_ind_cback
654**
655** Description      This is the L2CAP config indication callback function.
656**
657**
658** Returns          void
659**
660*******************************************************************************/
661void gatt_l2cif_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
662{
663    tGATT_TCB       *p_tcb;
664    tGATTS_SRV_CHG  *p_srv_chg_clt=NULL;
665    /* look up clcb for this channel */
666    if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
667    {
668        /* GATT uses the smaller of our MTU and peer's MTU  */
669        if ( (p_cfg->mtu_present) && (p_cfg->mtu < L2CAP_DEFAULT_MTU) )
670            p_tcb->payload_size = p_cfg->mtu;
671        else
672            p_tcb->payload_size = L2CAP_DEFAULT_MTU;
673
674        /* send L2CAP configure response */
675        memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
676        p_cfg->result = L2CAP_CFG_OK;
677        L2CA_ConfigRsp(lcid, p_cfg);
678
679        /* if first config ind */
680        if ((p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE) == 0)
681        {
682            /* update flags */
683            p_tcb->ch_flags |= GATT_L2C_CFG_IND_DONE;
684
685            /* if configuration complete */
686            if (p_tcb->ch_flags & GATT_L2C_CFG_CFM_DONE)
687            {
688                gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
689                if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL)
690                {
691                    gatt_chk_srv_chg(p_srv_chg_clt);
692                }
693                else
694                {
695                    if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
696                        gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
697                }
698
699                /* send callback */
700                gatt_send_conn_cback(FALSE, p_tcb);
701            }
702        }
703    }
704}
705
706/*******************************************************************************
707**
708** Function         gatt_l2cif_disconnect_ind_cback
709**
710** Description      This is the L2CAP disconnect indication callback function.
711**
712**
713** Returns          void
714**
715*******************************************************************************/
716void gatt_l2cif_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
717{
718    tGATT_TCB       *p_tcb;
719    UINT16          reason;
720
721    /* look up clcb for this channel */
722    if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
723    {
724        if (ack_needed)
725        {
726            /* send L2CAP disconnect response */
727            L2CA_DisconnectRsp(lcid);
728        }
729        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
730            gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
731        /* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
732        if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda)) == 0)
733            reason = GATT_CONN_TERMINATE_PEER_USER;
734
735        /* send disconnect callback */
736        gatt_cleanup_upon_disc(p_tcb->peer_bda, reason);
737    }
738}
739
740/*******************************************************************************
741**
742** Function         gatt_l2cif_disconnect_cfm_cback
743**
744** Description      This is the L2CAP disconnect confirm callback function.
745**
746**
747** Returns          void
748**
749*******************************************************************************/
750void gatt_l2cif_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
751{
752    tGATT_TCB       *p_tcb;
753    UINT16          reason;
754
755    /* look up clcb for this channel */
756    if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
757    {
758        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
759            gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
760        /* send disconnect callback */
761        /* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
762        if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda)) == 0)
763            reason = GATT_CONN_TERMINATE_LOCAL_HOST;
764
765        gatt_cleanup_upon_disc(p_tcb->peer_bda, reason);
766    }
767}
768
769/*******************************************************************************
770**
771** Function         gatt_l2cif_data_ind_cback
772**
773** Description      This is the L2CAP data indication callback function.
774**
775**
776** Returns          void
777**
778*******************************************************************************/
779void gatt_l2cif_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
780{
781    tGATT_TCB       *p_tcb;
782
783    /* look up clcb for this channel */
784    if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL &&
785        gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)
786    {
787        /* process the data */
788        gatt_data_process(p_tcb, p_buf);
789    }
790    else /* prevent buffer leak */
791        GKI_freebuf(p_buf);
792}
793
794/*******************************************************************************
795**
796** Function         gatt_send_conn_cback
797**
798** Description      Callback used to notify layer above about a connection.
799**
800**
801** Returns          void
802**
803*******************************************************************************/
804static void gatt_send_conn_cback(BOOLEAN is_bg_conn, tGATT_TCB *p_tcb)
805{
806    UINT8               i;
807    tGATT_REG           *p_reg;
808    tGATT_BG_CONN_DEV   *p_bg_dev=NULL;
809    UINT16              conn_id;
810
811    if (is_bg_conn)
812        p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda);
813
814    /* notifying all applications for the connection up event */
815    for (i = 0,  p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++)
816    {
817        if (p_reg->in_use)
818        {
819            if (p_bg_dev && gatt_is_bg_dev_for_app(p_bg_dev, p_reg->gatt_if))
820                gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, TRUE);
821
822            if (p_reg->app_cb.p_conn_cb)
823            {
824                conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
825                (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, TRUE, 0);
826            }
827        }
828    }
829
830
831    if (gatt_num_apps_hold_link(p_tcb))
832    {
833        /* disable idle timeout if one or more clients are holding the link disable the idle timer */
834        GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT);
835    }
836}
837
838/*******************************************************************************
839**
840** Function         gatt_le_data_ind
841**
842** Description      This function is called when data is received from L2CAP.
843**                  if we are the originator of the connection, we are the ATT
844**                  client, and the received message is queued up for the client.
845**
846**                  If we are the destination of the connection, we are the ATT
847**                  server, so the message is passed to the server processing
848**                  function.
849**
850** Returns          void
851**
852*******************************************************************************/
853void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf)
854{
855    UINT8   *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
856    UINT8   op_code, pseudo_op_code;
857    UINT16  msg_len;
858
859
860    if (p_buf->len > 0)
861    {
862        msg_len = p_buf->len - 1;
863        STREAM_TO_UINT8(op_code, p);
864
865        /* remove the two MSBs associated with sign write and write cmd */
866        pseudo_op_code = op_code & (~GATT_WRITE_CMD_MASK);
867
868        if (pseudo_op_code < GATT_OP_CODE_MAX)
869        {
870            if (op_code == GATT_SIGN_CMD_WRITE)
871            {
872                gatt_verify_signature(p_tcb, p_buf);
873                return;
874            }
875            else
876            {
877                /* message from client */
878                if ((op_code % 2) == 0)
879                    gatt_server_handle_client_req (p_tcb, op_code, msg_len, p);
880                else
881                    gatt_client_handle_server_rsp (p_tcb, op_code, msg_len, p);
882            }
883        }
884        else
885        {
886            GATT_TRACE_ERROR1 ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x", op_code);
887        }
888    }
889    else
890    {
891        GATT_TRACE_ERROR0 ("invalid data length, ignore");
892    }
893
894    GKI_freebuf (p_buf);
895}
896
897/*******************************************************************************
898**
899** Function         gatt_add_a_bonded_dev_for_srv_chg
900**
901** Description      Add a bonded dev to the service changed client list
902**
903** Returns          void
904**
905*******************************************************************************/
906void gatt_add_a_bonded_dev_for_srv_chg (BD_ADDR bda)
907{
908    tGATTS_SRV_CHG *p_buf;
909    tGATTS_SRV_CHG_REQ req;
910    tGATTS_SRV_CHG srv_chg_clt;
911
912    memcpy(srv_chg_clt.bda, bda, BD_ADDR_LEN);
913    srv_chg_clt.srv_changed = FALSE;
914    if ((p_buf = gatt_add_srv_chg_clt(&srv_chg_clt)) != NULL)
915    {
916        memcpy(req.srv_chg.bda, bda, BD_ADDR_LEN);
917        req.srv_chg.srv_changed = FALSE;
918        if (gatt_cb.cb_info.p_srv_chg_callback)
919            (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_ADD_CLIENT, &req, NULL);
920    }
921
922}
923
924/*******************************************************************************
925**
926** Function         gatt_send_srv_chg_ind
927**
928** Description      This function is called to send a service chnaged indication to
929**                  the specified bd address
930**
931** Returns          void
932**
933*******************************************************************************/
934void gatt_send_srv_chg_ind (BD_ADDR peer_bda)
935{
936    UINT8   handle_range[GATT_SIZE_OF_SRV_CHG_HNDL_RANGE];
937    UINT8   *p = handle_range;
938    UINT16  conn_id;
939
940    GATT_TRACE_DEBUG0("gatt_send_srv_chg_ind");
941
942    if (gatt_cb.handle_of_h_r)
943    {
944        if ((conn_id = gatt_profile_find_conn_id_by_bd_addr(peer_bda)) != GATT_INVALID_CONN_ID)
945        {
946            UINT16_TO_STREAM (p, 1);
947            UINT16_TO_STREAM (p, 0xFFFF);
948            GATTS_HandleValueIndication (conn_id,
949                                         gatt_cb.handle_of_h_r,
950                                         GATT_SIZE_OF_SRV_CHG_HNDL_RANGE,
951                                         handle_range);
952        }
953        else
954        {
955            GATT_TRACE_ERROR2("Unable to find conn_id for  %08x%04x ",
956                              (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
957                              (peer_bda[4]<<8)+peer_bda[5] );
958        }
959    }
960}
961
962/*******************************************************************************
963**
964** Function         gatt_chk_srv_chg
965**
966** Description      Check sending service chnaged Indication is required or not
967**                  if required then send the Indication
968**
969** Returns          void
970**
971*******************************************************************************/
972void gatt_chk_srv_chg(tGATTS_SRV_CHG *p_srv_chg_clt)
973{
974    GATT_TRACE_DEBUG1("gatt_chk_srv_chg srv_changed=%d", p_srv_chg_clt->srv_changed );
975
976    if (p_srv_chg_clt->srv_changed)
977    {
978        gatt_send_srv_chg_ind(p_srv_chg_clt->bda);
979    }
980    else
981    {
982        GATT_TRACE_DEBUG0("No need to send srv chg ");
983    }
984
985}
986
987/*******************************************************************************
988**
989** Function         gatt_init_srv_chg
990**
991** Description      This function is used to initialize the service changed
992**                  attribute value
993**
994** Returns          void
995**
996*******************************************************************************/
997void gatt_init_srv_chg (void)
998{
999    tGATTS_SRV_CHG_REQ req;
1000    tGATTS_SRV_CHG_RSP rsp;
1001    BOOLEAN status;
1002    UINT8 num_clients,i;
1003    tGATTS_SRV_CHG  srv_chg_clt;
1004
1005    GATT_TRACE_DEBUG0("gatt_init_srv_chg");
1006    if (gatt_cb.cb_info.p_srv_chg_callback)
1007    {
1008        status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_NUM_CLENTS, NULL, &rsp);
1009
1010        if (status && rsp.num_clients)
1011        {
1012            GATT_TRACE_DEBUG1("gatt_init_srv_chg num_srv_chg_clt_clients=%d", rsp.num_clients);
1013            num_clients = rsp.num_clients;
1014            i = 1; /* use one based index */
1015            while ((i <= num_clients) && status)
1016            {
1017                req.client_read_index = i;
1018                if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)))
1019                {
1020                    memcpy(&srv_chg_clt, &rsp.srv_chg ,sizeof(tGATTS_SRV_CHG));
1021                    if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL)
1022                    {
1023                        GATT_TRACE_ERROR0("Unable to add a service change client");
1024                        status = FALSE;
1025                    }
1026                }
1027                i++;
1028            }
1029        }
1030    }
1031    else
1032    {
1033        GATT_TRACE_DEBUG0("gatt_init_srv_chg callback not registered yet");
1034    }
1035}
1036
1037/*******************************************************************************
1038**
1039** Function         gatt_proc_srv_chg
1040**
1041** Description      This function is process the service changed request
1042**
1043** Returns          void
1044**
1045*******************************************************************************/
1046void gatt_proc_srv_chg (void)
1047{
1048    UINT8               start_idx, found_idx;
1049    BD_ADDR             bda;
1050    BOOLEAN             srv_chg_ind_pending=FALSE;
1051    tGATT_TCB           *p_tcb;
1052
1053    GATT_TRACE_DEBUG0 ("gatt_proc_srv_chg");
1054
1055    if (gatt_cb.cb_info.p_srv_chg_callback && gatt_cb.handle_of_h_r)
1056    {
1057        gatt_set_srv_chg();
1058        start_idx =0;
1059        while (gatt_find_the_connected_bda(start_idx, bda, &found_idx))
1060        {
1061            p_tcb = &gatt_cb.tcb[found_idx];;
1062            srv_chg_ind_pending  = gatt_is_srv_chg_ind_pending(p_tcb);
1063
1064            if (!srv_chg_ind_pending)
1065            {
1066                gatt_send_srv_chg_ind(bda);
1067            }
1068            else
1069            {
1070                GATT_TRACE_DEBUG0 ("discard srv chg - already has one in the queue");
1071            }
1072            start_idx = ++found_idx;
1073        }
1074    }
1075}
1076
1077/*******************************************************************************
1078**
1079** Function         gatt_set_ch_state
1080**
1081** Description      This function set the ch_state in tcb
1082**
1083** Returns          none
1084**
1085*******************************************************************************/
1086void gatt_set_ch_state(tGATT_TCB *p_tcb, tGATT_CH_STATE ch_state)
1087{
1088    if (p_tcb)
1089    {
1090        GATT_TRACE_DEBUG2 ("gatt_set_ch_state: old=%d new=%d", p_tcb->ch_state, ch_state);
1091        p_tcb->ch_state = ch_state;
1092    }
1093}
1094
1095/*******************************************************************************
1096**
1097** Function         gatt_get_ch_state
1098**
1099** Description      This function get the ch_state in tcb
1100**
1101** Returns          none
1102**
1103*******************************************************************************/
1104tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB *p_tcb)
1105{
1106    tGATT_CH_STATE ch_state = GATT_CH_CLOSE;
1107    if (p_tcb)
1108    {
1109        GATT_TRACE_DEBUG1 ("gatt_get_ch_state: ch_state=%d", p_tcb->ch_state);
1110        ch_state = p_tcb->ch_state;
1111    }
1112    return ch_state;
1113}
1114
1115#endif /* BLE_INCLUDED */
1116