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