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