• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /********************************************************************************/
42 static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason);
43 static void gatt_le_data_ind (BD_ADDR bd_addr, BT_HDR *p_buf);
44 
45 static void gatt_l2cif_connect_ind_cback (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
46 static void gatt_l2cif_connect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
47 static void gatt_l2cif_config_ind_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
48 static void gatt_l2cif_config_cfm_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
49 static void gatt_l2cif_disconnect_ind_cback (UINT16 l2cap_cid, BOOLEAN ack_needed);
50 static void gatt_l2cif_disconnect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
51 static void gatt_l2cif_data_ind_cback (UINT16 l2cap_cid, BT_HDR *p_msg);
52 static void gatt_send_conn_cback (tGATT_TCB *p_tcb);
53 
54 static 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
69 tGATT_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 *******************************************************************************/
gatt_init(void)82 void 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 *******************************************************************************/
gatt_connect(BD_ADDR rem_bda,tGATT_TCB * p_tcb)140 BOOLEAN 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 *******************************************************************************/
gatt_disconnect(BD_ADDR rem_bda)177 BOOLEAN 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 *******************************************************************************/
gatt_update_app_hold_link_status(tGATT_IF gatt_if,tGATT_TCB * p_tcb,BOOLEAN is_add)225 void 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 *******************************************************************************/
gatt_update_app_use_link_flag(tGATT_IF gatt_if,tGATT_TCB * p_tcb,BOOLEAN is_add,BOOLEAN check_acl_link)277 void 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 *******************************************************************************/
gatt_act_connect(tGATT_REG * p_reg,BD_ADDR bd_addr)317 BOOLEAN 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 *******************************************************************************/
gatt_le_connect_cback(BD_ADDR bd_addr,BOOLEAN connected,UINT16 reason)378 static 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 *******************************************************************************/
gatt_le_data_ind(BD_ADDR bd_addr,BT_HDR * p_buf)473 static 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 *******************************************************************************/
gatt_l2cif_connect_ind_cback(BD_ADDR bd_addr,UINT16 lcid,UINT16 psm,UINT8 id)506 static 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 *******************************************************************************/
gatt_l2cif_connect_cfm_cback(UINT16 lcid,UINT16 result)560 void 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 *******************************************************************************/
gatt_l2cif_config_cfm_cback(UINT16 lcid,tL2CAP_CFG_INFO * p_cfg)612 void 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 *******************************************************************************/
gatt_l2cif_config_ind_cback(UINT16 lcid,tL2CAP_CFG_INFO * p_cfg)671 void 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 *******************************************************************************/
gatt_l2cif_disconnect_ind_cback(UINT16 lcid,BOOLEAN ack_needed)729 void 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 *******************************************************************************/
gatt_l2cif_disconnect_cfm_cback(UINT16 lcid,UINT16 result)768 void 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 *******************************************************************************/
gatt_l2cif_data_ind_cback(UINT16 lcid,BT_HDR * p_buf)801 void 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 *******************************************************************************/
gatt_send_conn_cback(tGATT_TCB * p_tcb)826 static 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 *******************************************************************************/
gatt_data_process(tGATT_TCB * p_tcb,BT_HDR * p_buf)874 void 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 *******************************************************************************/
gatt_add_a_bonded_dev_for_srv_chg(BD_ADDR bda)927 void 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 *******************************************************************************/
gatt_send_srv_chg_ind(BD_ADDR peer_bda)955 void 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 *******************************************************************************/
gatt_chk_srv_chg(tGATTS_SRV_CHG * p_srv_chg_clt)993 void 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 *******************************************************************************/
gatt_init_srv_chg(void)1018 void 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 *******************************************************************************/
gatt_proc_srv_chg(void)1067 void 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 *******************************************************************************/
gatt_set_ch_state(tGATT_TCB * p_tcb,tGATT_CH_STATE ch_state)1107 void 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 *******************************************************************************/
gatt_get_ch_state(tGATT_TCB * p_tcb)1125 tGATT_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