1 /******************************************************************************
2 *
3 * Copyright (C) 2009-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 functions relating to BLE management.
22 *
23 ******************************************************************************/
24
25 #include <string.h>
26 #include "common/bt_target.h"
27 //#include "bt_utils.h"
28 #include "stack/l2cdefs.h"
29 #include "l2c_int.h"
30 #include "stack/btu.h"
31 #include "btm_int.h"
32 #include "stack/hcimsgs.h"
33 #include "device/controller.h"
34
35 #if (BLE_INCLUDED == TRUE)
36
37 #if (BLE_50_FEATURE_SUPPORT == TRUE)
38 #define EXT_CONN_INT_DEF_1M MAX(((MAX_ACL_CONNECTIONS + 1) * 4), 12)
39 #define EXT_CONN_INT_DEF_2M MAX(((MAX_ACL_CONNECTIONS + 1) * 2), 12)
40 #define EXT_CONN_INT_DEF_CODED (320) // 306-> 362Kbps
41
42 const static tHCI_ExtConnParams ext_conn_params_1m_phy = {
43 .scan_interval = 0x40,
44 .scan_window = 0x40,
45 .conn_interval_min = EXT_CONN_INT_DEF_1M,
46 .conn_interval_max = EXT_CONN_INT_DEF_1M,
47 .conn_latency = 0,
48 .sup_timeout = 600,
49 .min_ce_len = 0,
50 .max_ce_len = 0,
51 };
52 const static tHCI_ExtConnParams ext_conn_params_2m_phy = {
53 .scan_interval = 0x40,
54 .scan_window = 0x40,
55 .conn_interval_min = EXT_CONN_INT_DEF_2M,
56 .conn_interval_max = EXT_CONN_INT_DEF_2M,
57 .conn_latency = 0,
58 .sup_timeout = 600,
59 .min_ce_len = 0,
60 .max_ce_len = 0,
61 };
62 const static tHCI_ExtConnParams ext_conn_params_coded_phy = {
63 .scan_interval = 0x40,
64 .scan_window = 0x40,
65 .conn_interval_min = EXT_CONN_INT_DEF_CODED,
66 .conn_interval_max = EXT_CONN_INT_DEF_CODED,
67 .conn_latency = 0,
68 .sup_timeout = 600,
69 .min_ce_len = 0,
70 .max_ce_len = 0,
71 };
72 #define BLE_PHY_NO_PREF 0
73 #define BLE_PHY_PREF_MASK ((1 << 2) | (1 << 1) | (1 << 0))
74
75 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
76
77 static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb);
78 extern int64_t esp_system_get_time(void);
79
80 /*******************************************************************************
81 **
82 ** Function L2CA_CancelBleConnectReq
83 **
84 ** Description Cancel a pending connection attempt to a BLE device.
85 **
86 ** Parameters: BD Address of remote
87 **
88 ** Return value: TRUE if connection was cancelled
89 **
90 *******************************************************************************/
L2CA_CancelBleConnectReq(BD_ADDR rem_bda)91 BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
92 {
93 tL2C_LCB *p_lcb;
94
95 /* There can be only one BLE connection request outstanding at a time */
96 if (btm_ble_get_conn_st() == BLE_CONN_IDLE) {
97 L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - no connection pending");
98 return (FALSE);
99 }
100
101 if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN)) {
102 L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different BDA Connecting: %08x%04x Cancel: %08x%04x",
103 (l2cb.ble_connecting_bda[0] << 24) + (l2cb.ble_connecting_bda[1] << 16) + (l2cb.ble_connecting_bda[2] << 8) + l2cb.ble_connecting_bda[3],
104 (l2cb.ble_connecting_bda[4] << 8) + l2cb.ble_connecting_bda[5],
105 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], (rem_bda[4] << 8) + rem_bda[5]);
106
107 return (FALSE);
108 }
109
110 if (btsnd_hcic_ble_create_conn_cancel()) {
111 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
112 /* Do not remove lcb if an LE link is already up as a peripheral */
113 if (p_lcb != NULL &&
114 !(p_lcb->link_role == HCI_ROLE_SLAVE && BTM_ACL_IS_CONNECTED(rem_bda))) {
115 p_lcb->disc_reason = L2CAP_CONN_CANCEL;
116 l2cu_release_lcb (p_lcb);
117 }
118 /* update state to be cancel, wait for connection cancel complete */
119 btm_ble_set_conn_st (BLE_CONN_CANCEL);
120
121 return (TRUE);
122 } else {
123 return (FALSE);
124 }
125 }
126
127 /*******************************************************************************
128 **
129 ** Function L2CA_UpdateBleConnParams
130 **
131 ** Description Update BLE connection parameters.
132 **
133 ** Parameters: BD Address of remote
134 **
135 ** Return value: TRUE if update started
136 **
137 *******************************************************************************/
L2CA_UpdateBleConnParams(BD_ADDR rem_bda,UINT16 min_int,UINT16 max_int,UINT16 latency,UINT16 timeout)138 BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int,
139 UINT16 latency, UINT16 timeout)
140 {
141 tL2C_LCB *p_lcb;
142 tACL_CONN *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
143 UINT8 status = HCI_SUCCESS;
144 BOOLEAN need_cb = false;
145
146 /* See if we have a link control block for the remote device */
147 p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
148
149 /* If we don't have one, create one and accept the connection. */
150 if (!p_lcb || !p_acl_cb) {
151 L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
152 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
153 (rem_bda[4] << 8) + rem_bda[5]);
154 return (FALSE);
155 }
156
157 if (p_lcb->transport != BT_TRANSPORT_LE) {
158 L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
159 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
160 (rem_bda[4] << 8) + rem_bda[5]);
161 return (FALSE);
162 }
163
164 /* Check whether the request conn params is already set */
165 if ((max_int == p_lcb->current_used_conn_interval) && (latency == p_lcb->current_used_conn_latency) &&
166 (timeout == p_lcb->current_used_conn_timeout)) {
167 status = HCI_SUCCESS;
168 need_cb = true;
169 L2CAP_TRACE_WARNING("%s connection parameter already set", __func__);
170 }
171
172 if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PARAM_FULL){
173 status = HCI_ERR_ILLEGAL_COMMAND;
174 need_cb = true;
175 L2CAP_TRACE_ERROR("There are two connection parameter requests that are being updated, please try later ");
176 }
177
178 if ((need_cb == TRUE) && (conn_param_update_cb.update_conn_param_cb != NULL)) {
179 tBTM_LE_UPDATE_CONN_PRAMS update_param;
180 update_param.max_conn_int = max_int;
181 update_param.min_conn_int = min_int;
182 update_param.conn_int = p_lcb->current_used_conn_interval;
183 update_param.slave_latency = p_lcb->current_used_conn_latency;
184 update_param.supervision_tout = p_lcb->current_used_conn_timeout;
185 (conn_param_update_cb.update_conn_param_cb)(status, p_lcb->remote_bd_addr, &update_param);
186 return (status == HCI_SUCCESS);
187 }
188
189 p_lcb->waiting_update_conn_min_interval = min_int;
190 p_lcb->waiting_update_conn_max_interval = max_int;
191 p_lcb->waiting_update_conn_latency = latency;
192 p_lcb->waiting_update_conn_timeout = timeout;
193
194 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
195
196 if(l2cble_start_conn_update(p_lcb) == TRUE) {
197 UINT32 time = CalConnectParamTimeout(p_lcb);
198 btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time);
199 }
200
201 return (TRUE);
202 }
203
204
205 /*******************************************************************************
206 **
207 ** Function L2CA_EnableUpdateBleConnParams
208 **
209 ** Description Enable or disable update based on the request from the peer
210 **
211 ** Parameters: BD Address of remote
212 **
213 ** Return value: TRUE if update started
214 **
215 *******************************************************************************/
L2CA_EnableUpdateBleConnParams(BD_ADDR rem_bda,BOOLEAN enable)216 BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
217 {
218 tL2C_LCB *p_lcb;
219
220 /* See if we have a link control block for the remote device */
221 p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
222
223 if (!p_lcb) {
224 L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x",
225 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
226 (rem_bda[4] << 8) + rem_bda[5]);
227 return (FALSE);
228 }
229
230 L2CAP_TRACE_API ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x", __FUNCTION__,
231 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
232 (rem_bda[4] << 8) + rem_bda[5], enable, p_lcb->conn_update_mask);
233
234 if (p_lcb->transport != BT_TRANSPORT_LE) {
235 L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE (link role %d)", __FUNCTION__,
236 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
237 (rem_bda[4] << 8) + rem_bda[5], p_lcb->link_role);
238 return (FALSE);
239 }
240
241 if (p_lcb->current_used_conn_interval <= BTM_BLE_CONN_INT_MAX_DEF && (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0){
242 return (FALSE);
243 }
244 bool is_disable = (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE);
245 if(l2cu_plcb_active_count() >1 && !(enable && is_disable)) {
246 return FALSE;
247 }
248
249 if (enable) {
250 p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
251 } else {
252 p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE;
253 }
254
255 if (l2cble_start_conn_update(p_lcb) == TRUE) {
256 UINT32 time = CalConnectParamTimeout(p_lcb);
257 btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time);
258 }
259
260 return (TRUE);
261 }
262
263
264 /*******************************************************************************
265 **
266 ** Function L2CA_GetBleConnRole
267 **
268 ** Description This function returns the connection role.
269 **
270 ** Returns link role.
271 **
272 *******************************************************************************/
L2CA_GetBleConnRole(BD_ADDR bd_addr)273 UINT8 L2CA_GetBleConnRole (BD_ADDR bd_addr)
274 {
275 UINT8 role = HCI_ROLE_UNKNOWN;
276
277 tL2C_LCB *p_lcb;
278
279 if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_LE)) != NULL) {
280 role = p_lcb->link_role;
281 }
282
283 return role;
284 }
285
286 /*******************************************************************************
287 **
288 ** Function l2cble_notify_le_connection
289 **
290 ** Description This function notifiy the l2cap connection to the app layer
291 **
292 ** Returns none
293 **
294 *******************************************************************************/
l2cble_notify_le_connection(BD_ADDR bda)295 void l2cble_notify_le_connection (BD_ADDR bda)
296 {
297 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
298 tACL_CONN *p_acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE) ;
299
300 if (p_lcb != NULL && p_acl != NULL && p_lcb->link_state != LST_CONNECTED) {
301
302 if(p_acl->link_role == HCI_ROLE_SLAVE) {
303 //clear p_cb->state, controller will stop adv when ble connected.
304 tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
305 if(p_cb) {
306 p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
307 p_cb->state &= ~BTM_BLE_ADVERTISING;
308 }
309 }
310 /* update link status */
311 btm_establish_continue(p_acl);
312 /* update l2cap link status and send callback */
313 p_lcb->link_state = LST_CONNECTED;
314 l2cu_process_fixed_chnl_resp (p_lcb);
315 }
316 }
317
318 /*******************************************************************************
319 **
320 ** Function l2cble_scanner_conn_comp
321 **
322 ** Description This function is called when an HCI Connection Complete
323 ** event is received while we are a scanner (so we are master).
324 **
325 ** Returns void
326 **
327 *******************************************************************************/
l2cble_scanner_conn_comp(UINT16 handle,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)328 void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
329 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
330 {
331 tL2C_LCB *p_lcb;
332 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda);
333
334 L2CAP_TRACE_DEBUG ("l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d slave_latency=%d supervision_tout=%d",
335 handle, type, conn_interval, conn_latency, conn_timeout);
336
337 l2cb.is_ble_connecting = FALSE;
338
339 /* See if we have a link control block for the remote device */
340 p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
341
342 /* If we don't have one, create one. this is auto connection complete. */
343 if (!p_lcb) {
344 p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
345 if (!p_lcb) {
346 #if (SMP_INCLUDED == TRUE)
347 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
348 L2CAP_TRACE_ERROR ("l2cble_scanner_conn_comp - failed to allocate LCB");
349 #endif ///SMP_INCLUDED == TRUE
350 return;
351 } else {
352 if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) {
353 #if (SMP_INCLUDED == TRUE)
354 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
355 L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
356 #endif ///SMP_INCLUDED == TRUE
357 return ;
358 }
359 }
360 } else if (p_lcb->link_state != LST_CONNECTING) {
361 L2CAP_TRACE_ERROR ("L2CAP got BLE scanner conn_comp in bad state: %d", p_lcb->link_state);
362 return;
363 }
364 btu_stop_timer(&p_lcb->timer_entry);
365
366 /* Save the handle */
367 p_lcb->handle = handle;
368
369 /* Connected OK. Change state to connected, we were scanning so we are master */
370 p_lcb->link_role = HCI_ROLE_MASTER;
371 p_lcb->transport = BT_TRANSPORT_LE;
372
373 /* update link parameter, set slave link as non-spec default upon link up */
374 p_lcb->waiting_update_conn_min_interval = p_lcb->waiting_update_conn_max_interval = p_lcb->current_used_conn_interval = conn_interval;
375 p_lcb->waiting_update_conn_timeout = p_lcb->current_used_conn_timeout = conn_timeout;
376 p_lcb->waiting_update_conn_latency = p_lcb->current_used_conn_latency = conn_latency;
377 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
378 p_lcb->updating_param_flag = false;
379
380 /* If there are any preferred connection parameters, set them now */
381 if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
382 (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX ) &&
383 (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
384 (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX ) &&
385 (p_dev_rec->conn_params.slave_latency <= BTM_BLE_CONN_LATENCY_MAX ) &&
386 (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
387 (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
388 ((conn_interval < p_dev_rec->conn_params.min_conn_int &&
389 p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
390 (conn_interval > p_dev_rec->conn_params.max_conn_int) ||
391 (conn_latency > p_dev_rec->conn_params.slave_latency) ||
392 (conn_timeout > p_dev_rec->conn_params.supervision_tout))) {
393 L2CAP_TRACE_ERROR ("upd_ll_conn_params: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d",
394 handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int,
395 p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout);
396
397 p_lcb->waiting_update_conn_min_interval = p_dev_rec->conn_params.min_conn_int;
398 p_lcb->waiting_update_conn_max_interval = p_dev_rec->conn_params.max_conn_int;
399 p_lcb->waiting_update_conn_timeout = p_dev_rec->conn_params.supervision_tout;
400 p_lcb->waiting_update_conn_latency = p_dev_rec->conn_params.slave_latency;
401
402 btsnd_hcic_ble_upd_ll_conn_params (handle,
403 p_dev_rec->conn_params.min_conn_int,
404 p_dev_rec->conn_params.max_conn_int,
405 p_dev_rec->conn_params.slave_latency,
406 p_dev_rec->conn_params.supervision_tout,
407 BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
408 }
409
410 /* Tell BTM Acl management about the link */
411 btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
412
413 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
414
415 btm_ble_set_conn_st(BLE_CONN_IDLE);
416
417 #if BLE_PRIVACY_SPT == TRUE
418 btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
419 #endif
420 }
421
422
423 /*******************************************************************************
424 **
425 ** Function l2cble_advertiser_conn_comp
426 **
427 ** Description This function is called when an HCI Connection Complete
428 ** event is received while we are an advertiser (so we are slave).
429 **
430 ** Returns void
431 **
432 *******************************************************************************/
l2cble_advertiser_conn_comp(UINT16 handle,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)433 void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
434 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
435 {
436 tL2C_LCB *p_lcb;
437 tBTM_SEC_DEV_REC *p_dev_rec;
438 UNUSED(type);
439 UNUSED(conn_interval);
440 UNUSED(conn_latency);
441 UNUSED(conn_timeout);
442
443 /* See if we have a link control block for the remote device */
444 p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
445
446 /* If we don't have one, create one and accept the connection. */
447 if (!p_lcb) {
448 p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
449 if (!p_lcb) {
450 #if (SMP_INCLUDED == TRUE)
451 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
452 #endif ///SMP_INCLUDED == TRUE
453 L2CAP_TRACE_ERROR ("l2cble_advertiser_conn_comp - failed to allocate LCB");
454 return;
455 } else {
456 if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) {
457 #if (SMP_INCLUDED == TRUE)
458 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
459 #endif ///SMP_INCLUDED == TRUE
460 L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
461 return ;
462 }
463 }
464 }
465
466 /* Save the handle */
467 p_lcb->handle = handle;
468
469 /* Connected OK. Change state to connected, we were advertising, so we are slave */
470 p_lcb->link_role = HCI_ROLE_SLAVE;
471 p_lcb->transport = BT_TRANSPORT_LE;
472
473 /* update link parameter, set slave link as non-spec default upon link up */
474 p_lcb->waiting_update_conn_min_interval = p_lcb->waiting_update_conn_max_interval = p_lcb->current_used_conn_interval = conn_interval;
475 p_lcb->waiting_update_conn_timeout = p_lcb->current_used_conn_timeout = conn_timeout;
476 p_lcb->waiting_update_conn_latency = p_lcb->current_used_conn_latency = conn_latency;
477 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
478 p_lcb->updating_param_flag = false;
479
480 /* Tell BTM Acl management about the link */
481 p_dev_rec = btm_find_or_alloc_dev (bda);
482
483 btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
484
485 #if BLE_PRIVACY_SPT == TRUE
486 btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, TRUE);
487 #endif
488
489 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
490
491 if (!HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(controller_get_interface()->get_features_ble()->as_array)) {
492 p_lcb->link_state = LST_CONNECTED;
493 l2cu_process_fixed_chnl_resp (p_lcb);
494 }
495
496 /* when adv and initiating are both active, cancel the direct connection */
497 if (l2cb.is_ble_connecting && memcmp(bda, l2cb.ble_connecting_bda, BD_ADDR_LEN) == 0) {
498 L2CA_CancelBleConnectReq(bda);
499 }
500 }
501
502 /*******************************************************************************
503 **
504 ** Function l2cble_conn_comp
505 **
506 ** Description This function is called when an HCI Connection Complete
507 ** event is received.
508 **
509 ** Returns void
510 **
511 *******************************************************************************/
l2cble_conn_comp(UINT16 handle,UINT8 role,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)512 void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
513 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
514 {
515 btm_ble_update_link_topology_mask(role, TRUE);
516
517 if (role == HCI_ROLE_MASTER) {
518 l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
519 } else {
520 l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
521 }
522 }
523
524 /*******************************************************************************
525 **
526 ** Function l2cble_start_conn_update
527 **
528 ** Description start BLE connection parameter update process based on status
529 **
530 ** Parameters: lcb : l2cap link control block
531 **
532 ** Return value: true if successfully sending the request to peer device, else false.
533 **
534 *******************************************************************************/
l2cble_start_conn_update(tL2C_LCB * p_lcb)535 static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb)
536 {
537 UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
538 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) && (BLE_SLAVE_UPD_CONN_PARAMS == TRUE)
539 tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
540 #endif /* defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) && (BLE_SLAVE_UPD_CONN_PARAMS == TRUE */
541
542 if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) {
543 L2CAP_TRACE_WARNING("%s, the last connection update command still pending.", __func__);
544 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PARAM_FULL;
545 return FALSE;
546 }
547
548 if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) {
549 /* application requests to disable parameters update.
550 If parameters are already updated, lets set them
551 up to what has been requested during connection establishement */
552 if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM &&
553 /* current connection interval is greater than default min */
554 p_lcb->current_used_conn_interval > BTM_BLE_CONN_INT_MAX_DEF) {
555 /* use 6 * 1.25 = 7.5 ms as fast connection parameter, 0 slave latency */
556 min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
557 slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF;
558 supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;
559
560 /* if both side 4.1, or we are master device, send HCI command */
561 if (p_lcb->link_role == HCI_ROLE_MASTER
562 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) && (BLE_SLAVE_UPD_CONN_PARAMS == TRUE)
563 || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) &&
564 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
565 #endif
566 ) {
567 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, min_conn_int, max_conn_int,
568 slave_latency, supervision_tout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
569 } else {
570 l2cu_send_peer_ble_par_req (p_lcb, min_conn_int, max_conn_int, slave_latency, supervision_tout);
571 }
572
573 //cache save
574 p_lcb->updating_conn_min_interval = min_conn_int;
575 p_lcb->updating_conn_max_interval = max_conn_int;
576 p_lcb->updating_param_flag = true;
577
578 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
579 p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
580 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
581 return TRUE;
582 }else {
583 return FALSE;
584 }
585 } else {
586 /* application allows to do update, if we were delaying one do it now */
587 if (p_lcb->conn_update_mask & L2C_BLE_NEW_CONN_PARAM) {
588 /* if both side 4.1, or we are master device, send HCI command */
589 if (p_lcb->link_role == HCI_ROLE_MASTER
590 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) && (BLE_SLAVE_UPD_CONN_PARAMS == TRUE)
591 || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) &&
592 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
593 #endif
594 ) {
595 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->waiting_update_conn_min_interval,
596 p_lcb->waiting_update_conn_max_interval, p_lcb->waiting_update_conn_latency, p_lcb->waiting_update_conn_timeout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
597 } else {
598 l2cu_send_peer_ble_par_req (p_lcb, p_lcb->waiting_update_conn_min_interval, p_lcb->waiting_update_conn_max_interval,
599 p_lcb->waiting_update_conn_latency, p_lcb->waiting_update_conn_timeout);
600 }
601
602 //cache save
603 p_lcb->updating_conn_min_interval = p_lcb->waiting_update_conn_min_interval;
604 p_lcb->updating_conn_max_interval = p_lcb->waiting_update_conn_max_interval;
605 p_lcb->updating_param_flag = true;
606
607 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
608 p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
609 p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
610 return TRUE;
611 } else {
612 return FALSE;
613 }
614 }
615 }
616
617 /*******************************************************************************
618 **
619 ** Function l2cble_process_conn_update_evt
620 **
621 ** Description This function enables the connection update request from remote
622 ** after a successful connection update response is received.
623 **
624 ** Returns void
625 **
626 *******************************************************************************/
l2cble_process_conn_update_evt(UINT16 handle,UINT8 status,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)627 void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_interval,
628 UINT16 conn_latency, UINT16 conn_timeout)
629 {
630 tL2C_LCB *p_lcb;
631
632 /* See if we have a link control block for the remote device */
633 p_lcb = l2cu_find_lcb_by_handle(handle);
634 if (!p_lcb) {
635 L2CAP_TRACE_WARNING("le con upd: inv hdl=%d", handle);
636 return;
637 }
638 if (status == HCI_SUCCESS){
639 p_lcb->current_used_conn_interval = conn_interval;
640 p_lcb->current_used_conn_latency = conn_latency;
641 p_lcb->current_used_conn_timeout = conn_timeout;
642 }else{
643 L2CAP_TRACE_WARNING("le con upd: err_stat=0x%x", status);
644 }
645
646 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
647 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL;
648 btu_stop_timer(&p_lcb->upda_con_timer);
649
650 if (conn_param_update_cb.update_conn_param_cb != NULL) {
651 l2c_send_update_conn_params_cb(p_lcb, status);
652 }
653
654 if (l2cble_start_conn_update(p_lcb) == TRUE) {
655 UINT32 time = CalConnectParamTimeout(p_lcb);
656 btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time);
657 }
658
659 btu_stop_timer (&p_lcb->timer_entry);
660
661 L2CAP_TRACE_DEBUG("le con upd: conn_update_mask=%d", p_lcb->conn_update_mask);
662 }
663
664 /*******************************************************************************
665 **
666 ** Function l2cble_get_conn_param_format_err_from_contoller
667 **
668 ** Description This function is called when host get illegal connection paramrters
669 ** format status from controller
670 **
671 ** Returns void
672 **
673 *******************************************************************************/
l2cble_get_conn_param_format_err_from_contoller(UINT8 status,UINT16 handle)674 void l2cble_get_conn_param_format_err_from_contoller (UINT8 status, UINT16 handle)
675 {
676 tL2C_LCB *p_lcb;
677
678 /* See if we have a link control block for the remote device */
679 p_lcb = l2cu_find_lcb_by_handle(handle);
680 if (!p_lcb) {
681 L2CAP_TRACE_ERROR("%s: Invalid handle: %d", __FUNCTION__, handle);
682 return;
683 }
684
685 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
686
687 btu_stop_timer (&p_lcb->upda_con_timer);
688
689 if (conn_param_update_cb.update_conn_param_cb != NULL) {
690 l2c_send_update_conn_params_cb(p_lcb, status);
691 }
692 if ((p_lcb->conn_update_mask & L2C_BLE_UPDATE_PARAM_FULL) != 0){
693 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL;
694 if (l2cble_start_conn_update(p_lcb) == TRUE) {
695 UINT32 time = CalConnectParamTimeout(p_lcb);
696 btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time);
697 }
698 }
699
700 }
701
702 /*******************************************************************************
703 **
704 ** Function l2cble_process_sig_cmd
705 **
706 ** Description This function is called when a signalling packet is received
707 ** on the BLE signalling CID
708 **
709 ** Returns void
710 **
711 *******************************************************************************/
l2cble_process_sig_cmd(tL2C_LCB * p_lcb,UINT8 * p,UINT16 pkt_len)712 void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
713 {
714 UINT8 *p_pkt_end;
715 UINT8 cmd_code, id;
716 UINT16 cmd_len;
717 UINT16 min_interval, max_interval, latency, timeout;
718
719 p_pkt_end = p + pkt_len;
720
721 STREAM_TO_UINT8 (cmd_code, p);
722 STREAM_TO_UINT8 (id, p);
723 STREAM_TO_UINT16 (cmd_len, p);
724
725 /* Check command length does not exceed packet length */
726 if ((p + cmd_len) > p_pkt_end) {
727 L2CAP_TRACE_WARNING ("L2CAP - LE - format error, pkt_len: %d cmd_len: %d code: %d", pkt_len, cmd_len, cmd_code);
728 return;
729 }
730
731 switch (cmd_code) {
732 case L2CAP_CMD_REJECT:
733 case L2CAP_CMD_ECHO_RSP:
734 case L2CAP_CMD_INFO_RSP:
735 p += 2;
736 break;
737 case L2CAP_CMD_ECHO_REQ:
738 case L2CAP_CMD_INFO_REQ:
739 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
740 break;
741
742 case L2CAP_CMD_BLE_UPDATE_REQ:
743 STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */
744 STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */
745 STREAM_TO_UINT16 (latency, p); /* 0x0000 - 0x03E8 */
746 STREAM_TO_UINT16 (timeout, p); /* 0x000A - 0x0C80 */
747 /* If we are a master, the slave wants to update the parameters */
748 if (p_lcb->link_role == HCI_ROLE_MASTER) {
749 if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
750 max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
751 latency > BTM_BLE_CONN_LATENCY_MAX ||
752 timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
753 /* The supervision_timeout parameter defines the link supervision timeout for the connection.
754 The supervision_timeout in milliseconds shall be large than (1 + latency) * max_interval * 2,
755 where max_interval is given in milliseconds. (See [Vol 6] Part B, Section 4.5.2).
756 supervision_timeout (mult of 10ms); conn_interval (mult of 1.25ms)
757 (max_interval * 1.25 * 2) replaced by ((max_interval * 5) >> 1).
758 */
759 ((timeout * 10) < ((1 + latency) *((max_interval * 5) >> 1))) ||
760 max_interval < min_interval) {
761 l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
762
763 L2CAP_TRACE_ERROR("slave connection parameters update failed, the parameters are out of range");
764
765 } else {
766
767 l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_OK, id);
768 p_lcb->waiting_update_conn_min_interval = min_interval;
769 p_lcb->waiting_update_conn_max_interval = max_interval;
770 p_lcb->waiting_update_conn_latency = latency;
771 p_lcb->waiting_update_conn_timeout = timeout;
772 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
773
774 if (l2cble_start_conn_update(p_lcb) == TRUE) {
775 UINT32 time = CalConnectParamTimeout(p_lcb);
776 btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time);
777 }
778 }
779 } else {
780 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
781 }
782 break;
783
784 case L2CAP_CMD_BLE_UPDATE_RSP: {
785 UINT16 result = 0;
786 STREAM_TO_UINT16(result, p); //result = 0 connection param accepted, result = 1 connection param rejected.
787 UINT8 status = (result == 0) ? HCI_SUCCESS : HCI_ERR_PARAM_OUT_OF_RANGE;
788 if (status != HCI_SUCCESS) {
789 btu_stop_timer(&p_lcb->upda_con_timer);
790 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
791 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL;
792 l2c_send_update_conn_params_cb(p_lcb, status);
793 }
794 break;
795 }
796 case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ: {
797 tL2C_CCB *p_ccb = NULL;
798 tL2C_RCB *p_rcb = NULL;
799 UINT16 spsm;
800 UINT16 scid;
801 UINT16 mtu;
802 UINT16 mps;
803 UINT16 credits;
804 STREAM_TO_UINT16(spsm, p);
805 STREAM_TO_UINT16(scid, p);
806 STREAM_TO_UINT16(mtu, p);
807 STREAM_TO_UINT16(mps, p);
808 STREAM_TO_UINT16(credits, p);
809 L2CAP_TRACE_DEBUG("%s spsm %x, scid %x", __func__, spsm, scid);
810
811 p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, scid);
812 if (p_ccb) {
813 l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED);
814 break;
815 }
816
817 #if 0
818 p_rcb = l2cu_find_ble_rcb_by_psm(spsm);
819 if (p_rcb == NULL) {
820 break;
821 }
822 #endif
823
824 p_ccb = l2cu_allocate_ccb(p_lcb, 0);
825 if (p_ccb == NULL) {
826 l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_RESULT_NO_RESOURCES);
827 break;
828 }
829
830 p_ccb->remote_id = id;
831 p_ccb->p_rcb = p_rcb;
832 p_ccb->remote_cid = scid;
833 p_ccb->local_conn_cfg.mtu = mtu;
834 p_ccb->local_conn_cfg.mps = controller_get_interface()->get_acl_data_size_ble();
835 p_ccb->local_conn_cfg.credits = credits;
836 p_ccb->peer_conn_cfg.mtu = mtu;
837 p_ccb->peer_conn_cfg.mps = mps;
838 p_ccb->peer_conn_cfg.credits = credits;
839
840 l2cu_send_peer_ble_credit_based_conn_res(p_ccb, L2CAP_LE_RESULT_CONN_OK);
841 break;
842 }
843 case L2CAP_CMD_DISC_REQ: {
844 tL2C_CCB *p_ccb = NULL;
845 UINT16 lcid;
846 UINT16 rcid;
847 STREAM_TO_UINT16(lcid, p);
848 STREAM_TO_UINT16(rcid, p);
849
850 p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
851 if (p_ccb) {
852 p_ccb->remote_id = id;
853 // TODO
854 }
855
856 l2cu_send_peer_disc_rsp(p_lcb, id, lcid, rcid);
857 break;
858 }
859 default:
860 L2CAP_TRACE_WARNING ("L2CAP - LE - unknown cmd code: %d", cmd_code);
861 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
862 return;
863 }
864 }
865
866 /*******************************************************************************
867 **
868 ** Function l2cble_init_direct_conn
869 **
870 ** Description This function is to initate a direct connection
871 **
872 ** Returns TRUE connection initiated, FALSE otherwise.
873 **
874 *******************************************************************************/
l2cble_init_direct_conn(tL2C_LCB * p_lcb)875 BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
876 {
877 #if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE) && (!CONTROLLER_RPA_LIST_ENABLE))
878 //check for security device information in the cache
879 bool dev_rec_exist = true;
880 tBTM_SEC_DEV_REC *find_dev_rec = btm_find_dev (p_lcb->remote_bd_addr);
881 if(find_dev_rec == NULL) {
882 dev_rec_exist = false;
883 }
884
885 #endif // ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE) && (!CONTROLLER_RPA_LIST_ENABLE))
886 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
887 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
888 UINT16 scan_int;
889 UINT16 scan_win;
890 BD_ADDR peer_addr;
891 UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
892 UINT8 own_addr_type = BLE_ADDR_PUBLIC;
893
894 /* There can be only one BLE connection request outstanding at a time */
895 if (p_dev_rec == NULL) {
896 L2CAP_TRACE_WARNING ("unknown device, can not initate connection");
897 return (FALSE);
898 }
899
900 scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
901 scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
902
903 peer_addr_type = p_lcb->ble_addr_type;
904 memcpy(peer_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
905
906 #if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE))
907 own_addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
908 #if (!CONTROLLER_RPA_LIST_ENABLE)
909 if(dev_rec_exist) {
910 // if the current address information is valid, get the real address information
911 if(p_dev_rec->ble.current_addr_valid) {
912 peer_addr_type = p_dev_rec->ble.current_addr_type;
913 memcpy(peer_addr, p_dev_rec->ble.current_addr, 6);
914 } else {
915 /* find security device information but not find the real address information
916 * This state may be directly open without scanning. In this case, you must
917 * use the current adv address of the device to open*/
918 }
919 } else {
920 //not find security device information, We think this is a new device, connect directly
921 }
922
923 /* It will cause that scanner doesn't send scan request to advertiser
924 * which has sent IRK to us and we have stored the IRK in controller.
925 * It is a hardware limitation. The preliminary solution is not to
926 * send key to the controller, but to resolve the random address in host.
927 * so we need send the real address information to controller. */
928
929 #endif // (!CONTROLLER_RPA_LIST_ENABLE)
930
931 #if (CONTROLLER_RPA_LIST_ENABLE)
932
933 if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) {
934 if (btm_cb.ble_ctr_cb.privacy_mode >= BTM_PRIVACY_1_2) {
935 own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
936 }
937
938 //btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
939 btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type);
940 } else {
941 btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
942 }
943
944 #endif // CONTROLLER_RPA_LIST_ENABLE
945 #endif // (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE)
946
947 if (!btm_ble_topology_check(BTM_BLE_STATE_INIT)) {
948 l2cu_release_lcb (p_lcb);
949 L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
950 return FALSE;
951 }
952 uint32_t link_timeout = L2CAP_BLE_LINK_CONNECT_TOUT;
953 if(GATTC_CONNECT_RETRY_COUNT) {
954 if(!p_lcb->retry_create_con) {
955 p_lcb->start_time_s = (esp_system_get_time()/1000);
956 }
957 uint32_t current_time = (esp_system_get_time()/1000);
958 link_timeout = (L2CAP_BLE_LINK_CONNECT_TOUT*1000 - (current_time - p_lcb->start_time_s))/1000;
959
960 if(link_timeout == 0 || link_timeout > L2CAP_BLE_LINK_CONNECT_TOUT) {
961 link_timeout = L2CAP_BLE_LINK_CONNECT_TOUT;
962 }
963 }
964
965 if (!p_lcb->is_aux) {
966 if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */
967 scan_win, /* UINT16 scan_win */
968 FALSE, /* UINT8 white_list */
969 peer_addr_type, /* UINT8 addr_type_peer */
970 peer_addr, /* BD_ADDR bda_peer */
971 own_addr_type, /* UINT8 addr_type_own */
972 (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
973 p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF), /* UINT16 conn_int_min */
974 (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
975 p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF), /* UINT16 conn_int_max */
976 (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
977 p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency */
978 (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
979 p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
980 BLE_CE_LEN_MIN, /* UINT16 min_len */
981 BLE_CE_LEN_MIN)) { /* UINT16 max_len */
982 l2cu_release_lcb (p_lcb);
983 L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
984 return (FALSE);
985 } else {
986 p_lcb->link_state = LST_CONNECTING;
987 l2cb.is_ble_connecting = TRUE;
988 memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
989 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, link_timeout);
990 btm_ble_set_conn_st (BLE_DIR_CONN);
991
992 return (TRUE);
993 }
994 } else {
995 #if (BLE_50_FEATURE_SUPPORT == TRUE)
996
997 /*
998 * 0x00 Public Device Address
999 * 0x01 Random Device Address
1000 * 0x02 Public Identity Address (corresponds to Resolved Private Address)
1001 * 0x03 Random (static) Identity Address (corresponds to Resolved Private Address)
1002 * 0xFF No address provided (anonymous advertisement)
1003 */
1004
1005 if ((peer_addr_type & BLE_ADDR_RANDOM) == BLE_ADDR_RANDOM) {
1006 peer_addr_type = BLE_ADDR_RANDOM;
1007 } else {
1008 peer_addr_type = BLE_ADDR_PUBLIC;
1009 }
1010
1011 tHCI_CreatExtConn aux_conn = {0};
1012 aux_conn.filter_policy = FALSE;
1013 aux_conn.own_addr_type = own_addr_type;
1014 aux_conn.peer_addr_type = peer_addr_type;
1015 memcpy(aux_conn.peer_addr, peer_addr, sizeof(BD_ADDR));
1016 if (p_dev_rec->ext_conn_params.phy_mask == BLE_PHY_NO_PREF) {
1017 L2CAP_TRACE_WARNING("No extend connection parameters set, use default parameters");
1018 aux_conn.init_phy_mask = BLE_PHY_PREF_MASK;
1019 memcpy(&aux_conn.params[0], &ext_conn_params_1m_phy, sizeof(tHCI_ExtConnParams));
1020 memcpy(&aux_conn.params[1], &ext_conn_params_2m_phy, sizeof(tHCI_ExtConnParams));
1021 memcpy(&aux_conn.params[2], &ext_conn_params_coded_phy, sizeof(tHCI_ExtConnParams));
1022 } else {
1023 aux_conn.init_phy_mask = p_dev_rec->ext_conn_params.phy_mask;
1024 memcpy(&aux_conn.params[0], &p_dev_rec->ext_conn_params.phy_1m_conn_params, sizeof(tHCI_ExtConnParams));
1025 memcpy(&aux_conn.params[1], &p_dev_rec->ext_conn_params.phy_2m_conn_params, sizeof(tHCI_ExtConnParams));
1026 memcpy(&aux_conn.params[2], &p_dev_rec->ext_conn_params.phy_coded_conn_params, sizeof(tHCI_ExtConnParams));
1027 }
1028 p_lcb->link_state = LST_CONNECTING;
1029 l2cb.is_ble_connecting = TRUE;
1030 memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
1031 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, link_timeout);
1032 btm_ble_set_conn_st (BLE_DIR_CONN);
1033 if(!btsnd_hcic_ble_create_ext_conn(&aux_conn)) {
1034 l2cu_release_lcb (p_lcb);
1035 L2CAP_TRACE_ERROR("initate Aux connection failed, no resources");
1036 }
1037 #else
1038 L2CAP_TRACE_ERROR("BLE 5.0 not support!\n");
1039 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
1040 return (TRUE);
1041 }
1042 }
1043
1044 /*******************************************************************************
1045 **
1046 ** Function l2cble_create_conn
1047 **
1048 ** Description This function initiates an acl connection via HCI
1049 **
1050 ** Returns TRUE if successful, FALSE if connection not started.
1051 **
1052 *******************************************************************************/
l2cble_create_conn(tL2C_LCB * p_lcb)1053 BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
1054 {
1055 tBTM_BLE_CONN_ST conn_st = btm_ble_get_conn_st();
1056 BOOLEAN rt = FALSE;
1057
1058 /* There can be only one BLE connection request outstanding at a time */
1059 if (conn_st == BLE_CONN_IDLE) {
1060 rt = l2cble_init_direct_conn(p_lcb);
1061 } else {
1062 L2CAP_TRACE_WARNING ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
1063
1064 btm_ble_enqueue_direct_conn_req(p_lcb);
1065
1066 if (conn_st == BLE_BG_CONN) {
1067 btm_ble_suspend_bg_conn();
1068 }
1069
1070 rt = TRUE;
1071 }
1072 return rt;
1073 }
1074
1075 /*******************************************************************************
1076 **
1077 ** Function l2c_link_processs_ble_num_bufs
1078 **
1079 ** Description This function is called when a "controller buffer size"
1080 ** event is first received from the controller. It updates
1081 ** the L2CAP values.
1082 **
1083 ** Returns void
1084 **
1085 *******************************************************************************/
l2c_link_processs_ble_num_bufs(UINT16 num_lm_ble_bufs)1086 void l2c_link_processs_ble_num_bufs (UINT16 num_lm_ble_bufs)
1087 {
1088 if (num_lm_ble_bufs == 0) {
1089 num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED;
1090 l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED;
1091 }
1092 L2CAP_TRACE_DEBUG("num_lm_ble_bufs = %d",num_lm_ble_bufs);
1093 l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs;
1094 }
1095
1096 /*******************************************************************************
1097 **
1098 ** Function l2c_ble_link_adjust_allocation
1099 **
1100 ** Description This function is called when a link is created or removed
1101 ** to calculate the amount of packets each link may send to
1102 ** the HCI without an ack coming back.
1103 **
1104 ** Currently, this is a simple allocation, dividing the
1105 ** number of Controller Packets by the number of links. In
1106 ** the future, QOS configuration should be examined.
1107 **
1108 ** Returns void
1109 **
1110 *******************************************************************************/
l2c_ble_link_adjust_allocation(void)1111 void l2c_ble_link_adjust_allocation (void)
1112 {
1113 UINT16 qq, qq_remainder;
1114 tL2C_LCB *p_lcb;
1115 UINT16 hi_quota, low_quota;
1116 UINT16 num_lowpri_links = 0;
1117 UINT16 num_hipri_links = 0;
1118 UINT16 controller_xmit_quota = l2cb.num_lm_ble_bufs;
1119 UINT16 high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
1120 list_node_t *p_node = NULL;
1121
1122 /* If no links active, reset buffer quotas and controller buffers */
1123 if (l2cb.num_ble_links_active == 0) {
1124 l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
1125 l2cb.ble_round_robin_quota = l2cb.ble_round_robin_unacked = 0;
1126 return;
1127 }
1128
1129 /* First, count the links */
1130 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
1131 p_lcb = list_node(p_node);
1132 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) {
1133 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) {
1134 num_hipri_links++;
1135 } else {
1136 num_lowpri_links++;
1137 }
1138 }
1139 }
1140
1141 /* now adjust high priority link quota */
1142 low_quota = num_lowpri_links ? 1 : 0;
1143 while ( (num_hipri_links * high_pri_link_quota + low_quota) > controller_xmit_quota ) {
1144 high_pri_link_quota--;
1145 }
1146
1147
1148 /* Work out the xmit quota and buffer quota high and low priorities */
1149 hi_quota = num_hipri_links * high_pri_link_quota;
1150 low_quota = (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1;
1151
1152 /* Work out and save the HCI xmit quota for each low priority link */
1153
1154 /* If each low priority link cannot have at least one buffer */
1155 if (num_lowpri_links > low_quota) {
1156 l2cb.ble_round_robin_quota = low_quota;
1157 qq = qq_remainder = 0;
1158 }
1159 /* If each low priority link can have at least one buffer */
1160 else if (num_lowpri_links > 0) {
1161 l2cb.ble_round_robin_quota = 0;
1162 l2cb.ble_round_robin_unacked = 0;
1163 qq = low_quota / num_lowpri_links;
1164 qq_remainder = low_quota % num_lowpri_links;
1165 }
1166 /* If no low priority link */
1167 else {
1168 l2cb.ble_round_robin_quota = 0;
1169 l2cb.ble_round_robin_unacked = 0;
1170 qq = qq_remainder = 0;
1171 }
1172 L2CAP_TRACE_EVENT ("l2c_ble_link_adjust_allocation num_hipri: %u num_lowpri: %u low_quota: %u round_robin_quota: %u qq: %u",
1173 num_hipri_links, num_lowpri_links, low_quota,
1174 l2cb.ble_round_robin_quota, qq);
1175
1176 /* Now, assign the quotas to each link */
1177 p_node = NULL;
1178 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
1179 p_lcb = list_node(p_node);
1180 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) {
1181 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) {
1182 p_lcb->link_xmit_quota = high_pri_link_quota;
1183 } else {
1184 /* Safety check in case we switched to round-robin with something outstanding */
1185 /* if sent_not_acked is added into round_robin_unacked then don't add it again */
1186 /* l2cap keeps updating sent_not_acked for exiting from round robin */
1187 if (( p_lcb->link_xmit_quota > 0 ) && ( qq == 0 )) {
1188 l2cb.ble_round_robin_unacked += p_lcb->sent_not_acked;
1189 }
1190
1191 p_lcb->link_xmit_quota = qq;
1192 if (qq_remainder > 0) {
1193 p_lcb->link_xmit_quota++;
1194 qq_remainder--;
1195 }
1196 }
1197
1198 L2CAP_TRACE_EVENT("l2c_ble_link_adjust_allocation Priority: %d XmitQuota: %d",
1199 p_lcb->acl_priority, p_lcb->link_xmit_quota);
1200
1201 L2CAP_TRACE_EVENT(" SentNotAcked: %d RRUnacked: %d",
1202 p_lcb->sent_not_acked, l2cb.round_robin_unacked);
1203
1204 /* There is a special case where we have readjusted the link quotas and */
1205 /* this link may have sent anything but some other link sent packets so */
1206 /* so we may need a timer to kick off this link's transmissions. */
1207 if ( (p_lcb->link_state == LST_CONNECTED)
1208 && (!list_is_empty(p_lcb->link_xmit_data_q))
1209 && (p_lcb->sent_not_acked < p_lcb->link_xmit_quota) ) {
1210 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_LINK_FLOW_CONTROL_TOUT);
1211 }
1212 }
1213 }
1214 }
1215
1216 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
1217 /*******************************************************************************
1218 **
1219 ** Function l2cble_process_rc_param_request_evt
1220 **
1221 ** Description process LE Remote Connection Parameter Request Event.
1222 **
1223 ** Returns void
1224 **
1225 *******************************************************************************/
l2cble_process_rc_param_request_evt(UINT16 handle,UINT16 int_min,UINT16 int_max,UINT16 latency,UINT16 timeout)1226 void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
1227 UINT16 latency, UINT16 timeout)
1228 {
1229 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle (handle);
1230
1231 if (p_lcb != NULL) {
1232
1233 /* if update is enabled, always accept connection parameter update */
1234 if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0) {
1235 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
1236 btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
1237 }else {
1238 /* always accept connection parameters request which is sent by itself */
1239 if (int_max == BTM_BLE_CONN_INT_MIN) {
1240 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
1241 btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
1242 }else {
1243 L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled");
1244 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
1245 btsnd_hcic_ble_rc_param_req_neg_reply (handle, HCI_ERR_UNACCEPT_CONN_INTERVAL);
1246 }
1247 }
1248
1249 } else {
1250 L2CAP_TRACE_WARNING("No link to update connection parameter")
1251 }
1252 }
1253 #endif
1254
1255 /*******************************************************************************
1256 **
1257 ** Function l2cble_update_data_length
1258 **
1259 ** Description This function update link tx data length if applicable
1260 **
1261 ** Returns void
1262 **
1263 *******************************************************************************/
l2cble_update_data_length(tL2C_LCB * p_lcb)1264 void l2cble_update_data_length(tL2C_LCB *p_lcb)
1265 {
1266 UINT16 tx_mtu = 0;
1267 UINT16 i = 0;
1268
1269 L2CAP_TRACE_DEBUG("%s", __FUNCTION__);
1270
1271 /* See if we have a link control block for the connection */
1272 if (p_lcb == NULL) {
1273 return;
1274 }
1275
1276 for (i = 0; i < L2CAP_NUM_FIXED_CHNLS; i++) {
1277 if (i + L2CAP_FIRST_FIXED_CHNL != L2CAP_BLE_SIGNALLING_CID) {
1278 if ((p_lcb->p_fixed_ccbs[i] != NULL) &&
1279 (tx_mtu < (p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD))) {
1280 tx_mtu = p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD;
1281 }
1282 }
1283 }
1284
1285 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX) {
1286 tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1287 }
1288
1289 /* update TX data length if changed */
1290 if (p_lcb->tx_data_len != tx_mtu) {
1291 BTM_SetBleDataLength(p_lcb->remote_bd_addr, tx_mtu);
1292 }
1293
1294 }
1295
1296 /*******************************************************************************
1297 **
1298 ** Function l2cble_process_data_length_change_evt
1299 **
1300 ** Description This function process the data length change event
1301 **
1302 ** Returns void
1303 **
1304 *******************************************************************************/
l2cble_process_data_length_change_event(UINT16 handle,UINT16 tx_data_len,UINT16 rx_data_len)1305 void l2cble_process_data_length_change_event(UINT16 handle, UINT16 tx_data_len, UINT16 rx_data_len)
1306 {
1307 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
1308 tACL_CONN *p_acl = btm_handle_to_acl(handle);
1309 tBTM_LE_SET_PKT_DATA_LENGTH_PARAMS data_length_params;
1310
1311 L2CAP_TRACE_DEBUG("%s TX data len = %d", __FUNCTION__, tx_data_len);
1312 if (p_lcb == NULL) {
1313 return;
1314 }
1315
1316 if (tx_data_len > 0) {
1317 p_lcb->tx_data_len = tx_data_len;
1318 }
1319
1320 data_length_params.rx_len = rx_data_len;
1321 data_length_params.tx_len = tx_data_len;
1322
1323 if(p_acl) {
1324 p_acl->data_length_params = data_length_params;
1325 if (p_acl->p_set_pkt_data_cback) {
1326 (*p_acl->p_set_pkt_data_cback)(BTM_SUCCESS, &data_length_params);
1327 }
1328
1329 p_acl->data_len_updating = false;
1330 if(p_acl->data_len_waiting) {
1331 p_acl->data_len_waiting = false;
1332 p_acl->p_set_pkt_data_cback = p_acl->p_set_data_len_cback_waiting;
1333 p_acl->p_set_data_len_cback_waiting = NULL;
1334 // if value is same, triger callback directly
1335 if(p_acl->tx_len_waiting == p_acl->data_length_params.tx_len) {
1336 if(p_acl->p_set_pkt_data_cback) {
1337 (*p_acl->p_set_pkt_data_cback)(BTM_SUCCESS, &p_acl->data_length_params);
1338 }
1339 return;
1340 }
1341 p_acl->data_len_updating = true;
1342 /* always set the TxTime to be max, as controller does not care for now */
1343 btsnd_hcic_ble_set_data_length(handle, p_acl->tx_len_waiting,
1344 BTM_BLE_DATA_TX_TIME_MAX);
1345 }
1346 }
1347 }
1348
1349 /*******************************************************************************
1350 **
1351 ** Function l2cble_set_fixed_channel_tx_data_length
1352 **
1353 ** Description This function update max fixed channel tx data length if applicable
1354 **
1355 ** Returns void
1356 **
1357 *******************************************************************************/
l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda,UINT16 fix_cid,UINT16 tx_mtu)1358 void l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda, UINT16 fix_cid, UINT16 tx_mtu)
1359 {
1360 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(remote_bda, BT_TRANSPORT_LE);
1361 UINT16 cid = fix_cid - L2CAP_FIRST_FIXED_CHNL;
1362
1363 L2CAP_TRACE_DEBUG("%s TX MTU = %d", __FUNCTION__, tx_mtu);
1364
1365 if (!controller_get_interface()->supports_ble_packet_extension()) {
1366 L2CAP_TRACE_WARNING("%s, request not supported", __FUNCTION__);
1367 return;
1368 }
1369
1370 /* See if we have a link control block for the connection */
1371 if (p_lcb == NULL) {
1372 return;
1373 }
1374
1375 if (p_lcb->p_fixed_ccbs[cid] != NULL) {
1376 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX) {
1377 tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1378 }
1379
1380 p_lcb->p_fixed_ccbs[cid]->tx_data_len = tx_mtu;
1381 }
1382
1383 l2cble_update_data_length(p_lcb);
1384 }
1385
1386
1387 /*******************************************************************************
1388 **
1389 ** Function l2c_send_update_conn_params_cb
1390 **
1391 ** Description This function send the update connection parameter callback to the uplayer.
1392 **
1393 ** Returns void
1394 **
1395 *******************************************************************************/
l2c_send_update_conn_params_cb(tL2C_LCB * p_lcb,UINT8 status)1396 void l2c_send_update_conn_params_cb(tL2C_LCB *p_lcb, UINT8 status)
1397 {
1398 if(conn_param_update_cb.update_conn_param_cb != NULL){
1399 tBTM_LE_UPDATE_CONN_PRAMS update_param;
1400 //if myself update the connection parameters
1401 if (p_lcb->updating_param_flag){
1402 update_param.max_conn_int = p_lcb->updating_conn_max_interval;
1403 update_param.min_conn_int = p_lcb->updating_conn_min_interval;
1404 p_lcb->updating_param_flag = false;
1405 }else{
1406 // remote device update the connection parameters
1407 update_param.max_conn_int = update_param.min_conn_int = 0;
1408 }
1409 // current connection parameters
1410 update_param.conn_int = p_lcb->current_used_conn_interval;
1411 update_param.slave_latency = p_lcb->current_used_conn_latency;
1412 update_param.supervision_tout = p_lcb->current_used_conn_timeout;
1413
1414 (conn_param_update_cb.update_conn_param_cb)(status, p_lcb->remote_bd_addr, &update_param);
1415 }
1416 }
1417
1418 /*******************************************************************************
1419 **
1420 ** Function CalConnectParamTimeout
1421 **
1422 ** Description This function is called to calculate the connection parameter timeout.
1423 **
1424 ** Returns timeout
1425 **
1426 *******************************************************************************/
CalConnectParamTimeout(tL2C_LCB * p_lcb)1427 UINT32 CalConnectParamTimeout(tL2C_LCB *p_lcb)
1428 {
1429 UINT32 timeout = 6;
1430 if (p_lcb != NULL){
1431 //1.25 * conn_int *(1+ latency) *32
1432 timeout = (40 * ( 1 + p_lcb->current_used_conn_latency) * p_lcb->current_used_conn_interval + 1000) / 1000;
1433 if (timeout < 1){
1434 timeout = 1;
1435 }else if (timeout > 120){
1436 timeout = 120;
1437 }
1438 }
1439 return timeout;
1440 }
1441
1442 /*******************************************************************************
1443 **
1444 ** Function l2cble_credit_based_conn_req
1445 **
1446 ** Description This function sends LE Credit Based Connection Request for
1447 ** LE connection oriented channels.
1448 **
1449 ** Returns void
1450 **
1451 *******************************************************************************/
l2cble_credit_based_conn_req(tL2C_CCB * p_ccb)1452 void l2cble_credit_based_conn_req (tL2C_CCB *p_ccb)
1453 {
1454 if (!p_ccb) {
1455 return;
1456 }
1457
1458 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1459 {
1460 L2CAP_TRACE_WARNING ("LE link doesn't exist");
1461 return;
1462 }
1463
1464 l2cu_send_peer_ble_credit_based_conn_req (p_ccb);
1465 return;
1466 }
1467
1468 /*******************************************************************************
1469 **
1470 ** Function l2cble_credit_based_conn_res
1471 **
1472 ** Description This function sends LE Credit Based Connection Response for
1473 ** LE connection oriented channels.
1474 **
1475 ** Returns void
1476 **
1477 *******************************************************************************/
l2cble_credit_based_conn_res(tL2C_CCB * p_ccb,UINT16 result)1478 void l2cble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
1479 {
1480 if (!p_ccb) {
1481 return;
1482 }
1483
1484 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1485 {
1486 L2CAP_TRACE_WARNING ("LE link doesn't exist");
1487 return;
1488 }
1489
1490 l2cu_send_peer_ble_credit_based_conn_res (p_ccb, result);
1491 return;
1492 }
1493
1494 /*******************************************************************************
1495 **
1496 ** Function l2cble_send_flow_control_credit
1497 **
1498 ** Description This function sends flow control credits for
1499 ** LE connection oriented channels.
1500 **
1501 ** Returns void
1502 **
1503 *******************************************************************************/
l2cble_send_flow_control_credit(tL2C_CCB * p_ccb,UINT16 credit_value)1504 void l2cble_send_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
1505 {
1506 if (!p_ccb) {
1507 return;
1508 }
1509
1510 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1511 {
1512 L2CAP_TRACE_WARNING ("LE link doesn't exist");
1513 return;
1514 }
1515
1516 l2cu_send_peer_ble_flow_control_credit(p_ccb, credit_value);
1517 return;
1518
1519 }
1520
1521 /*******************************************************************************
1522 **
1523 ** Function l2cble_send_peer_disc_req
1524 **
1525 ** Description This function sends disconnect request
1526 ** to the peer LE device
1527 **
1528 ** Returns void
1529 **
1530 *******************************************************************************/
l2cble_send_peer_disc_req(tL2C_CCB * p_ccb)1531 void l2cble_send_peer_disc_req(tL2C_CCB *p_ccb)
1532 {
1533 L2CAP_TRACE_DEBUG ("%s",__func__);
1534 if (!p_ccb) {
1535 return;
1536 }
1537
1538 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1539 {
1540 L2CAP_TRACE_WARNING ("LE link doesn't exist");
1541 return;
1542 }
1543
1544 l2cu_send_peer_ble_credit_based_disconn_req(p_ccb);
1545 return;
1546 }
1547
1548 #if (SMP_INCLUDED == TRUE)
1549 /*******************************************************************************
1550 **
1551 ** Function l2cble_sec_comp
1552 **
1553 ** Description This function is called when security procedure for an LE COC
1554 ** link is done
1555 **
1556 ** Returns void
1557 **
1558 *******************************************************************************/
l2cble_sec_comp(BD_ADDR p_bda,tBT_TRANSPORT transport,void * p_ref_data,UINT8 status)1559 void l2cble_sec_comp(BD_ADDR p_bda, tBT_TRANSPORT transport, void *p_ref_data, UINT8 status)
1560 {
1561 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, BT_TRANSPORT_LE);
1562 tL2CAP_SEC_DATA *p_buf = NULL;
1563 UINT8 sec_flag;
1564 UINT8 sec_act;
1565
1566 if (!p_lcb)
1567 {
1568 L2CAP_TRACE_WARNING ("%s security complete for unknown device", __func__);
1569 return;
1570 }
1571
1572 sec_act = p_lcb->sec_act;
1573 p_lcb->sec_act = 0;
1574
1575 if (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
1576 {
1577 p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q, FIXED_QUEUE_MAX_TIMEOUT);
1578 if (!p_buf)
1579 {
1580 L2CAP_TRACE_WARNING ("%s Security complete for request not initiated from L2CAP",
1581 __func__);
1582 return;
1583 }
1584
1585 if (status != BTM_SUCCESS)
1586 {
1587 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1588 }
1589 else
1590 {
1591 if (sec_act == BTM_SEC_ENCRYPT_MITM)
1592 {
1593 BTM_GetSecurityFlagsByTransport(p_bda, &sec_flag, transport);
1594 if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) {
1595 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1596 }
1597 else
1598 {
1599 L2CAP_TRACE_DEBUG ("%s MITM Protection Not present", __func__);
1600 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
1601 BTM_FAILED_ON_SECURITY);
1602 }
1603 }
1604 else
1605 {
1606 L2CAP_TRACE_DEBUG ("%s MITM Protection not required sec_act = %d",
1607 __func__, p_lcb->sec_act);
1608
1609 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1610 }
1611 }
1612 }
1613 else
1614 {
1615 L2CAP_TRACE_WARNING ("%s Security complete for request not initiated from L2CAP", __func__);
1616 return;
1617 }
1618 osi_free(p_buf);
1619
1620 while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
1621 {
1622 p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q, FIXED_QUEUE_MAX_TIMEOUT);
1623
1624 if (status != BTM_SUCCESS) {
1625 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1626 } else {
1627 l2ble_sec_access_req(p_bda, p_buf->psm, p_buf->is_originator,
1628 p_buf->p_callback, p_buf->p_ref_data);
1629 }
1630
1631 osi_free(p_buf);
1632 }
1633 }
1634
1635 /*******************************************************************************
1636 **
1637 ** Function l2ble_sec_access_req
1638 **
1639 ** Description This function is called by LE COC link to meet the
1640 ** security requirement for the link
1641 **
1642 ** Returns TRUE - security procedures are started
1643 ** FALSE - failure
1644 **
1645 *******************************************************************************/
l2ble_sec_access_req(BD_ADDR bd_addr,UINT16 psm,BOOLEAN is_originator,tL2CAP_SEC_CBACK * p_callback,void * p_ref_data)1646 BOOLEAN l2ble_sec_access_req(BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator, tL2CAP_SEC_CBACK *p_callback, void *p_ref_data)
1647 {
1648 L2CAP_TRACE_DEBUG ("%s", __func__);
1649 BOOLEAN status;
1650 tL2C_LCB *p_lcb = NULL;
1651
1652 if (!p_callback)
1653 {
1654 L2CAP_TRACE_ERROR("%s No callback function", __func__);
1655 return FALSE;
1656 }
1657
1658 p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
1659
1660 if (!p_lcb)
1661 {
1662 L2CAP_TRACE_ERROR ("%s Security check for unknown device", __func__);
1663 p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_UNKNOWN_ADDR);
1664 return FALSE;
1665 }
1666
1667 tL2CAP_SEC_DATA *p_buf = (tL2CAP_SEC_DATA*) osi_malloc((UINT16)sizeof(tL2CAP_SEC_DATA));
1668 if (!p_buf)
1669 {
1670 p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_NO_RESOURCES);
1671 return FALSE;
1672 }
1673
1674 p_buf->psm = psm;
1675 p_buf->is_originator = is_originator;
1676 p_buf->p_callback = p_callback;
1677 p_buf->p_ref_data = p_ref_data;
1678 fixed_queue_enqueue(p_lcb->le_sec_pending_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
1679 status = btm_ble_start_sec_check(bd_addr, psm, is_originator, &l2cble_sec_comp, p_ref_data);
1680
1681 return status;
1682 }
1683 #endif /* #if (SMP_INCLUDED == TRUE) */
1684 #endif /* (BLE_INCLUDED == TRUE) */
1685 /*******************************************************************************
1686 **
1687 ** Function L2CA_GetDisconnectReason
1688 **
1689 ** Description This function returns the disconnect reason code.
1690 **
1691 ** Returns disconnect reason
1692 **
1693 *******************************************************************************/
L2CA_GetDisconnectReason(BD_ADDR remote_bda,tBT_TRANSPORT transport)1694 UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport)
1695 {
1696 tL2C_LCB *p_lcb;
1697 UINT16 reason = 0;
1698
1699 if ((p_lcb = l2cu_find_lcb_by_bd_addr (remote_bda, transport)) != NULL) {
1700 reason = p_lcb->disc_reason;
1701 }
1702
1703 L2CAP_TRACE_DEBUG ("L2CA_GetDisconnectReason=%d ", reason);
1704
1705 return reason;
1706 }
1707