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