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