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