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