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 "bt_target.h"
27 #include "bt_utils.h"
28 #include "btm_int.h"
29 #include "btu.h"
30 #include "device/include/controller.h"
31 #include "hcimsgs.h"
32 #include "l2c_int.h"
33 #include "l2cdefs.h"
34 #include "osi/include/osi.h"
35 #include "stack_config.h"
36
37 extern fixed_queue_t* btu_general_alarm_queue;
38
39 static void l2cble_start_conn_update(tL2C_LCB* p_lcb);
40
41 /*******************************************************************************
42 *
43 * Function L2CA_CancelBleConnectReq
44 *
45 * Description Cancel a pending connection attempt to a BLE device.
46 *
47 * Parameters: BD Address of remote
48 *
49 * Return value: true if connection was cancelled
50 *
51 ******************************************************************************/
L2CA_CancelBleConnectReq(BD_ADDR rem_bda)52 bool L2CA_CancelBleConnectReq(BD_ADDR rem_bda) {
53 tL2C_LCB* p_lcb;
54
55 /* There can be only one BLE connection request outstanding at a time */
56 if (btm_ble_get_conn_st() == BLE_CONN_IDLE) {
57 L2CAP_TRACE_WARNING("%s - no connection pending", __func__);
58 return (false);
59 }
60
61 if (memcmp(rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN)) {
62 L2CAP_TRACE_WARNING(
63 "%s - different BDA Connecting: %08x%04x Cancel: %08x%04x", __func__,
64 (l2cb.ble_connecting_bda[0] << 24) +
65 (l2cb.ble_connecting_bda[1] << 16) +
66 (l2cb.ble_connecting_bda[2] << 8) + l2cb.ble_connecting_bda[3],
67 (l2cb.ble_connecting_bda[4] << 8) + l2cb.ble_connecting_bda[5],
68 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) +
69 rem_bda[3],
70 (rem_bda[4] << 8) + rem_bda[5]);
71 btm_ble_dequeue_direct_conn_req(rem_bda);
72 return (false);
73 }
74
75 btsnd_hcic_ble_create_conn_cancel();
76
77 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
78 /* Do not remove lcb if an LE link is already up as a peripheral */
79 if (p_lcb != NULL &&
80 !(p_lcb->link_role == HCI_ROLE_SLAVE &&
81 btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE) != NULL)) {
82 p_lcb->disc_reason = L2CAP_CONN_CANCEL;
83 l2cu_release_lcb(p_lcb);
84 }
85 /* update state to be cancel, wait for connection cancel complete */
86 btm_ble_set_conn_st(BLE_CONN_CANCEL);
87
88 return (true);
89 }
90
91 /*******************************************************************************
92 *
93 * Function L2CA_UpdateBleConnParams
94 *
95 * Description Update BLE connection parameters.
96 *
97 * Parameters: BD Address of remote
98 *
99 * Return value: true if update started
100 *
101 ******************************************************************************/
L2CA_UpdateBleConnParams(BD_ADDR rem_bda,uint16_t min_int,uint16_t max_int,uint16_t latency,uint16_t timeout)102 bool L2CA_UpdateBleConnParams(BD_ADDR rem_bda, uint16_t min_int,
103 uint16_t max_int, uint16_t latency,
104 uint16_t timeout) {
105 tL2C_LCB* p_lcb;
106 tACL_CONN* p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
107
108 /* See if we have a link control block for the remote device */
109 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
110
111 /* If we don't have one, create one and accept the connection. */
112 if (!p_lcb || !p_acl_cb) {
113 L2CAP_TRACE_WARNING("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
114 (rem_bda[0] << 24) + (rem_bda[1] << 16) +
115 (rem_bda[2] << 8) + rem_bda[3],
116 (rem_bda[4] << 8) + rem_bda[5]);
117 return (false);
118 }
119
120 if (p_lcb->transport != BT_TRANSPORT_LE) {
121 L2CAP_TRACE_WARNING("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
122 (rem_bda[0] << 24) + (rem_bda[1] << 16) +
123 (rem_bda[2] << 8) + rem_bda[3],
124 (rem_bda[4] << 8) + rem_bda[5]);
125 return (false);
126 }
127
128 p_lcb->min_interval = min_int;
129 p_lcb->max_interval = max_int;
130 p_lcb->latency = latency;
131 p_lcb->timeout = timeout;
132 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
133
134 l2cble_start_conn_update(p_lcb);
135
136 return (true);
137 }
138
139 /*******************************************************************************
140 *
141 * Function L2CA_EnableUpdateBleConnParams
142 *
143 * Description Enable or disable update based on the request from the peer
144 *
145 * Parameters: BD Address of remote
146 *
147 * Return value: true if update started
148 *
149 ******************************************************************************/
L2CA_EnableUpdateBleConnParams(BD_ADDR rem_bda,bool enable)150 bool L2CA_EnableUpdateBleConnParams(BD_ADDR rem_bda, bool enable) {
151 if (stack_config_get_interface()->get_pts_conn_updates_disabled())
152 return false;
153
154 tL2C_LCB* p_lcb;
155
156 /* See if we have a link control block for the remote device */
157 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
158
159 if (!p_lcb) {
160 L2CAP_TRACE_WARNING(
161 "L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x",
162 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) +
163 rem_bda[3],
164 (rem_bda[4] << 8) + rem_bda[5]);
165 return (false);
166 }
167
168 L2CAP_TRACE_API(
169 "%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x", __func__,
170 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
171 (rem_bda[4] << 8) + rem_bda[5], enable, p_lcb->conn_update_mask);
172
173 if (p_lcb->transport != BT_TRANSPORT_LE) {
174 L2CAP_TRACE_WARNING("%s - BD_ADDR %08x%04x not LE (link role %d)", __func__,
175 (rem_bda[0] << 24) + (rem_bda[1] << 16) +
176 (rem_bda[2] << 8) + rem_bda[3],
177 (rem_bda[4] << 8) + rem_bda[5], p_lcb->link_role);
178 return (false);
179 }
180
181 if (enable)
182 p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
183 else
184 p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE;
185
186 l2cble_start_conn_update(p_lcb);
187
188 return (true);
189 }
190
191 /*******************************************************************************
192 *
193 * Function L2CA_GetBleConnRole
194 *
195 * Description This function returns the connection role.
196 *
197 * Returns link role.
198 *
199 ******************************************************************************/
L2CA_GetBleConnRole(BD_ADDR bd_addr)200 uint8_t L2CA_GetBleConnRole(BD_ADDR bd_addr) {
201 uint8_t role = HCI_ROLE_UNKNOWN;
202
203 tL2C_LCB* p_lcb;
204
205 p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
206 if (p_lcb != NULL) role = p_lcb->link_role;
207
208 return role;
209 }
210 /*******************************************************************************
211 *
212 * Function L2CA_GetDisconnectReason
213 *
214 * Description This function returns the disconnect reason code.
215 *
216 * Returns disconnect reason
217 *
218 ******************************************************************************/
L2CA_GetDisconnectReason(BD_ADDR remote_bda,tBT_TRANSPORT transport)219 uint16_t L2CA_GetDisconnectReason(BD_ADDR remote_bda, tBT_TRANSPORT transport) {
220 tL2C_LCB* p_lcb;
221 uint16_t reason = 0;
222
223 p_lcb = l2cu_find_lcb_by_bd_addr(remote_bda, transport);
224 if (p_lcb != NULL) reason = p_lcb->disc_reason;
225
226 L2CAP_TRACE_DEBUG("L2CA_GetDisconnectReason=%d ", reason);
227
228 return reason;
229 }
230
231 /*******************************************************************************
232 *
233 * Function l2cble_notify_le_connection
234 *
235 * Description This function notifiy the l2cap connection to the app layer
236 *
237 * Returns none
238 *
239 ******************************************************************************/
l2cble_notify_le_connection(BD_ADDR bda)240 void l2cble_notify_le_connection(BD_ADDR bda) {
241 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE);
242 tACL_CONN* p_acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE);
243 tL2C_CCB* p_ccb;
244
245 if (p_lcb != NULL && p_acl != NULL && p_lcb->link_state != LST_CONNECTED) {
246 /* update link status */
247 btm_establish_continue(p_acl);
248 /* update l2cap link status and send callback */
249 p_lcb->link_state = LST_CONNECTED;
250 l2cu_process_fixed_chnl_resp(p_lcb);
251 }
252
253 if (p_lcb != NULL) {
254 /* For all channels, send the event through their FSMs */
255 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;
256 p_ccb = p_ccb->p_next_ccb) {
257 if (p_ccb->chnl_state == CST_CLOSED)
258 l2c_csm_execute(p_ccb, L2CEVT_LP_CONNECT_CFM, NULL);
259 }
260 }
261 }
262
263 /*******************************************************************************
264 *
265 * Function l2cble_scanner_conn_comp
266 *
267 * Description This function is called when an HCI Connection Complete
268 * event is received while we are a scanner (so we are master).
269 *
270 * Returns void
271 *
272 ******************************************************************************/
l2cble_scanner_conn_comp(uint16_t handle,BD_ADDR bda,tBLE_ADDR_TYPE type,uint16_t conn_interval,uint16_t conn_latency,uint16_t conn_timeout)273 void l2cble_scanner_conn_comp(uint16_t handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
274 uint16_t conn_interval, uint16_t conn_latency,
275 uint16_t conn_timeout) {
276 tL2C_LCB* p_lcb;
277 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(bda);
278
279 L2CAP_TRACE_DEBUG(
280 "l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d "
281 "slave_latency=%d supervision_tout=%d",
282 handle, type, conn_interval, conn_latency, conn_timeout);
283
284 l2cb.is_ble_connecting = false;
285
286 /* See if we have a link control block for the remote device */
287 p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE);
288
289 /* If we don't have one, create one. this is auto connection complete. */
290 if (!p_lcb) {
291 p_lcb = l2cu_allocate_lcb(bda, false, BT_TRANSPORT_LE);
292 if (!p_lcb) {
293 btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION);
294 L2CAP_TRACE_ERROR("l2cble_scanner_conn_comp - failed to allocate LCB");
295 return;
296 } else {
297 if (!l2cu_initialize_fixed_ccb(
298 p_lcb, L2CAP_ATT_CID,
299 &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL]
300 .fixed_chnl_opts)) {
301 btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION);
302 L2CAP_TRACE_WARNING("l2cble_scanner_conn_comp - LCB but no CCB");
303 return;
304 }
305 }
306 } else if (p_lcb->link_state != LST_CONNECTING) {
307 L2CAP_TRACE_ERROR("L2CAP got BLE scanner conn_comp in bad state: %d",
308 p_lcb->link_state);
309 return;
310 }
311 alarm_cancel(p_lcb->l2c_lcb_timer);
312
313 /* Save the handle */
314 p_lcb->handle = handle;
315
316 /* Connected OK. Change state to connected, we were scanning so we are master
317 */
318 p_lcb->link_role = HCI_ROLE_MASTER;
319 p_lcb->transport = BT_TRANSPORT_LE;
320
321 /* update link parameter, set slave link as non-spec default upon link up */
322 p_lcb->min_interval = p_lcb->max_interval = conn_interval;
323 p_lcb->timeout = conn_timeout;
324 p_lcb->latency = conn_latency;
325 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
326
327 /* Tell BTM Acl management about the link */
328 btm_acl_created(bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role,
329 BT_TRANSPORT_LE);
330
331 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT |
332 L2CAP_FIXED_CHNL_BLE_SIG_BIT |
333 L2CAP_FIXED_CHNL_SMP_BIT;
334
335 btm_ble_set_conn_st(BLE_CONN_IDLE);
336
337 #if (BLE_PRIVACY_SPT == TRUE)
338 btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true);
339 #endif
340 }
341
342 /*******************************************************************************
343 *
344 * Function l2cble_advertiser_conn_comp
345 *
346 * Description This function is called when an HCI Connection Complete
347 * event is received while we are an advertiser (so we are
348 * slave).
349 *
350 * Returns void
351 *
352 ******************************************************************************/
l2cble_advertiser_conn_comp(uint16_t handle,BD_ADDR bda,UNUSED_ATTR tBLE_ADDR_TYPE type,UNUSED_ATTR uint16_t conn_interval,UNUSED_ATTR uint16_t conn_latency,UNUSED_ATTR uint16_t conn_timeout)353 void l2cble_advertiser_conn_comp(uint16_t handle, BD_ADDR bda,
354 UNUSED_ATTR tBLE_ADDR_TYPE type,
355 UNUSED_ATTR uint16_t conn_interval,
356 UNUSED_ATTR uint16_t conn_latency,
357 UNUSED_ATTR uint16_t conn_timeout) {
358 tL2C_LCB* p_lcb;
359 tBTM_SEC_DEV_REC* p_dev_rec;
360
361 /* See if we have a link control block for the remote device */
362 p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE);
363
364 /* If we don't have one, create one and accept the connection. */
365 if (!p_lcb) {
366 p_lcb = l2cu_allocate_lcb(bda, false, BT_TRANSPORT_LE);
367 if (!p_lcb) {
368 btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION);
369 L2CAP_TRACE_ERROR("l2cble_advertiser_conn_comp - failed to allocate LCB");
370 return;
371 } else {
372 if (!l2cu_initialize_fixed_ccb(
373 p_lcb, L2CAP_ATT_CID,
374 &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL]
375 .fixed_chnl_opts)) {
376 btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION);
377 L2CAP_TRACE_WARNING("l2cble_scanner_conn_comp - LCB but no CCB");
378 return;
379 }
380 }
381 }
382
383 /* Save the handle */
384 p_lcb->handle = handle;
385
386 /* Connected OK. Change state to connected, we were advertising, so we are
387 * slave */
388 p_lcb->link_role = HCI_ROLE_SLAVE;
389 p_lcb->transport = BT_TRANSPORT_LE;
390
391 /* update link parameter, set slave link as non-spec default upon link up */
392 p_lcb->min_interval = p_lcb->max_interval = conn_interval;
393 p_lcb->timeout = conn_timeout;
394 p_lcb->latency = conn_latency;
395 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
396
397 /* Tell BTM Acl management about the link */
398 p_dev_rec = btm_find_or_alloc_dev(bda);
399
400 btm_acl_created(bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role,
401 BT_TRANSPORT_LE);
402
403 #if (BLE_PRIVACY_SPT == TRUE)
404 btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, true);
405 #endif
406
407 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT |
408 L2CAP_FIXED_CHNL_BLE_SIG_BIT |
409 L2CAP_FIXED_CHNL_SMP_BIT;
410
411 if (!HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(
412 controller_get_interface()->get_features_ble()->as_array)) {
413 p_lcb->link_state = LST_CONNECTED;
414 l2cu_process_fixed_chnl_resp(p_lcb);
415 }
416
417 /* when adv and initiating are both active, cancel the direct connection */
418 if (l2cb.is_ble_connecting &&
419 memcmp(bda, l2cb.ble_connecting_bda, BD_ADDR_LEN) == 0) {
420 L2CA_CancelBleConnectReq(bda);
421 }
422 }
423
424 /*******************************************************************************
425 *
426 * Function l2cble_conn_comp
427 *
428 * Description This function is called when an HCI Connection Complete
429 * event is received.
430 *
431 * Returns void
432 *
433 ******************************************************************************/
l2cble_conn_comp(uint16_t handle,uint8_t role,BD_ADDR bda,tBLE_ADDR_TYPE type,uint16_t conn_interval,uint16_t conn_latency,uint16_t conn_timeout)434 void l2cble_conn_comp(uint16_t handle, uint8_t role, BD_ADDR bda,
435 tBLE_ADDR_TYPE type, uint16_t conn_interval,
436 uint16_t conn_latency, uint16_t conn_timeout) {
437 btm_ble_update_link_topology_mask(role, true);
438
439 if (role == HCI_ROLE_MASTER) {
440 l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency,
441 conn_timeout);
442 } else {
443 l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency,
444 conn_timeout);
445 }
446 }
447
448 /*******************************************************************************
449 *
450 * Function l2cble_start_conn_update
451 *
452 * Description Start the BLE connection parameter update process based on
453 * status.
454 *
455 * Parameters: lcb : l2cap link control block
456 *
457 * Return value: none
458 *
459 ******************************************************************************/
l2cble_start_conn_update(tL2C_LCB * p_lcb)460 static void l2cble_start_conn_update(tL2C_LCB* p_lcb) {
461 uint16_t min_conn_int, max_conn_int, slave_latency, supervision_tout;
462 tACL_CONN* p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
463
464 // TODO(armansito): The return value of this call wasn't being used but the
465 // logic of this function might be depending on its side effects. We should
466 // verify if this call is needed at all and remove it otherwise.
467 btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
468
469 if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) return;
470
471 if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) {
472 /* application requests to disable parameters update.
473 If parameters are already updated, lets set them
474 up to what has been requested during connection establishement */
475 if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM &&
476 /* current connection interval is greater than default min */
477 p_lcb->min_interval > BTM_BLE_CONN_INT_MIN) {
478 /* use 7.5 ms as fast connection parameter, 0 slave latency */
479 min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
480 slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF;
481 supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;
482
483 /* if both side 4.1, or we are master device, send HCI command */
484 if (p_lcb->link_role == HCI_ROLE_MASTER
485 #if (BLE_LLT_INCLUDED == TRUE)
486 || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(
487 controller_get_interface()->get_features_ble()->as_array) &&
488 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
489 #endif
490 ) {
491 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, min_conn_int,
492 max_conn_int, slave_latency,
493 supervision_tout, 0, 0);
494 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
495 } else {
496 l2cu_send_peer_ble_par_req(p_lcb, min_conn_int, max_conn_int,
497 slave_latency, supervision_tout);
498 }
499 p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
500 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
501 }
502 } else {
503 /* application allows to do update, if we were delaying one do it now */
504 if (p_lcb->conn_update_mask & L2C_BLE_NEW_CONN_PARAM) {
505 /* if both side 4.1, or we are master device, send HCI command */
506 if (p_lcb->link_role == HCI_ROLE_MASTER
507 #if (BLE_LLT_INCLUDED == TRUE)
508 || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(
509 controller_get_interface()->get_features_ble()->as_array) &&
510 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
511 #endif
512 ) {
513 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
514 p_lcb->max_interval, p_lcb->latency,
515 p_lcb->timeout, 0, 0);
516 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
517 } else {
518 l2cu_send_peer_ble_par_req(p_lcb, p_lcb->min_interval,
519 p_lcb->max_interval, p_lcb->latency,
520 p_lcb->timeout);
521 }
522 p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
523 p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
524 }
525 }
526 }
527
528 /*******************************************************************************
529 *
530 * Function l2cble_process_conn_update_evt
531 *
532 * Description This function enables the connection update request from
533 * remote after a successful connection update response is
534 * received.
535 *
536 * Returns void
537 *
538 ******************************************************************************/
l2cble_process_conn_update_evt(uint16_t handle,uint8_t status,uint16_t interval,uint16_t latency,uint16_t timeout)539 void l2cble_process_conn_update_evt(uint16_t handle, uint8_t status,
540 uint16_t interval, uint16_t latency,
541 uint16_t timeout) {
542 L2CAP_TRACE_DEBUG("%s", __func__);
543
544 /* See if we have a link control block for the remote device */
545 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
546 if (!p_lcb) {
547 L2CAP_TRACE_WARNING("%s: Invalid handle: %d", __func__, handle);
548 return;
549 }
550
551 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
552
553 if (status != HCI_SUCCESS) {
554 L2CAP_TRACE_WARNING("%s: Error status: %d", __func__, status);
555 }
556
557 l2cble_start_conn_update(p_lcb);
558
559 L2CAP_TRACE_DEBUG("%s: conn_update_mask=%d", __func__,
560 p_lcb->conn_update_mask);
561 }
562
563 /*******************************************************************************
564 *
565 * Function l2cble_process_sig_cmd
566 *
567 * Description This function is called when a signalling packet is received
568 * on the BLE signalling CID
569 *
570 * Returns void
571 *
572 ******************************************************************************/
l2cble_process_sig_cmd(tL2C_LCB * p_lcb,uint8_t * p,uint16_t pkt_len)573 void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
574 uint8_t* p_pkt_end;
575 uint8_t cmd_code, id;
576 uint16_t cmd_len;
577 uint16_t min_interval, max_interval, latency, timeout;
578 tL2C_CONN_INFO con_info;
579 uint16_t lcid = 0, rcid = 0, mtu = 0, mps = 0, initial_credit = 0;
580 tL2C_CCB *p_ccb = NULL, *temp_p_ccb = NULL;
581 tL2C_RCB* p_rcb;
582 uint16_t credit;
583 p_pkt_end = p + pkt_len;
584
585 STREAM_TO_UINT8(cmd_code, p);
586 STREAM_TO_UINT8(id, p);
587 STREAM_TO_UINT16(cmd_len, p);
588
589 /* Check command length does not exceed packet length */
590 if ((p + cmd_len) > p_pkt_end) {
591 L2CAP_TRACE_WARNING(
592 "L2CAP - LE - format error, pkt_len: %d cmd_len: %d code: %d",
593 pkt_len, cmd_len, cmd_code);
594 return;
595 }
596
597 switch (cmd_code) {
598 case L2CAP_CMD_REJECT:
599 p += 2;
600 break;
601
602 case L2CAP_CMD_ECHO_REQ:
603 case L2CAP_CMD_ECHO_RSP:
604 case L2CAP_CMD_INFO_RSP:
605 case L2CAP_CMD_INFO_REQ:
606 l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
607 break;
608
609 case L2CAP_CMD_BLE_UPDATE_REQ:
610 STREAM_TO_UINT16(min_interval, p); /* 0x0006 - 0x0C80 */
611 STREAM_TO_UINT16(max_interval, p); /* 0x0006 - 0x0C80 */
612 STREAM_TO_UINT16(latency, p); /* 0x0000 - 0x03E8 */
613 STREAM_TO_UINT16(timeout, p); /* 0x000A - 0x0C80 */
614 /* If we are a master, the slave wants to update the parameters */
615 if (p_lcb->link_role == HCI_ROLE_MASTER) {
616 if (min_interval < BTM_BLE_CONN_INT_MIN_LIMIT)
617 min_interval = BTM_BLE_CONN_INT_MIN_LIMIT;
618
619 // While this could result in connection parameters that fall
620 // outside fo the range requested, this will allow the connection
621 // to remain established.
622 // In other words, this is a workaround for certain peripherals.
623 if (max_interval < BTM_BLE_CONN_INT_MIN_LIMIT)
624 max_interval = BTM_BLE_CONN_INT_MIN_LIMIT;
625
626 if (min_interval < BTM_BLE_CONN_INT_MIN ||
627 min_interval > BTM_BLE_CONN_INT_MAX ||
628 max_interval < BTM_BLE_CONN_INT_MIN ||
629 max_interval > BTM_BLE_CONN_INT_MAX ||
630 latency > BTM_BLE_CONN_LATENCY_MAX ||
631 /*(timeout >= max_interval && latency > (timeout * 10/(max_interval
632 * 1.25) - 1)) ||*/
633 timeout < BTM_BLE_CONN_SUP_TOUT_MIN ||
634 timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
635 max_interval < min_interval) {
636 l2cu_send_peer_ble_par_rsp(p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
637 } else {
638 l2cu_send_peer_ble_par_rsp(p_lcb, L2CAP_CFG_OK, id);
639
640 p_lcb->min_interval = min_interval;
641 p_lcb->max_interval = max_interval;
642 p_lcb->latency = latency;
643 p_lcb->timeout = timeout;
644 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
645
646 l2cble_start_conn_update(p_lcb);
647 }
648 } else
649 l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0,
650 0);
651 break;
652
653 case L2CAP_CMD_BLE_UPDATE_RSP:
654 p += 2;
655 break;
656
657 case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ:
658 STREAM_TO_UINT16(con_info.psm, p);
659 STREAM_TO_UINT16(rcid, p);
660 STREAM_TO_UINT16(mtu, p);
661 STREAM_TO_UINT16(mps, p);
662 STREAM_TO_UINT16(initial_credit, p);
663
664 L2CAP_TRACE_DEBUG(
665 "Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ with "
666 "mtu = %d, "
667 "mps = %d, "
668 "initial credit = %d",
669 mtu, mps, initial_credit);
670
671 p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, rcid);
672 if (p_ccb) {
673 L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for duplicated cid: 0x%04x",
674 rcid);
675 l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_SOURCE_CID_ALREADY_ALLOCATED);
676 break;
677 }
678
679 p_rcb = l2cu_find_ble_rcb_by_psm(con_info.psm);
680 if (p_rcb == NULL) {
681 L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for unknown PSM: 0x%04x",
682 con_info.psm);
683 l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_NO_PSM);
684 break;
685 } else {
686 if (!p_rcb->api.pL2CA_ConnectInd_Cb) {
687 L2CAP_TRACE_WARNING(
688 "L2CAP - rcvd conn req for outgoing-only connection PSM: %d",
689 con_info.psm);
690 l2cu_reject_ble_connection(p_lcb, id, L2CAP_CONN_NO_PSM);
691 break;
692 }
693 }
694
695 /* Allocate a ccb for this.*/
696 p_ccb = l2cu_allocate_ccb(p_lcb, 0);
697 if (p_ccb == NULL) {
698 L2CAP_TRACE_ERROR("L2CAP - unable to allocate CCB");
699 l2cu_reject_ble_connection(p_lcb, id, L2CAP_CONN_NO_RESOURCES);
700 break;
701 }
702
703 /* validate the parameters */
704 if (mtu < L2CAP_LE_MIN_MTU || mps < L2CAP_LE_MIN_MPS ||
705 mps > L2CAP_LE_MAX_MPS) {
706 L2CAP_TRACE_ERROR("L2CAP don't like the params");
707 l2cu_reject_ble_connection(p_lcb, id, L2CAP_CONN_NO_RESOURCES);
708 break;
709 }
710
711 p_ccb->remote_id = id;
712 p_ccb->p_rcb = p_rcb;
713 p_ccb->remote_cid = rcid;
714
715 p_ccb->peer_conn_cfg.mtu = mtu;
716 p_ccb->peer_conn_cfg.mps = mps;
717 p_ccb->peer_conn_cfg.credits = initial_credit;
718
719 p_ccb->tx_mps = mps;
720 p_ccb->ble_sdu = NULL;
721 p_ccb->ble_sdu_length = 0;
722 p_ccb->is_first_seg = true;
723 p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
724
725 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info);
726 break;
727
728 case L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES:
729 L2CAP_TRACE_DEBUG("Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES");
730 /* For all channels, see whose identifier matches this id */
731 for (temp_p_ccb = p_lcb->ccb_queue.p_first_ccb; temp_p_ccb;
732 temp_p_ccb = temp_p_ccb->p_next_ccb) {
733 if (temp_p_ccb->local_id == id) {
734 p_ccb = temp_p_ccb;
735 break;
736 }
737 }
738 if (p_ccb) {
739 L2CAP_TRACE_DEBUG("I remember the connection req");
740 STREAM_TO_UINT16(p_ccb->remote_cid, p);
741 STREAM_TO_UINT16(p_ccb->peer_conn_cfg.mtu, p);
742 STREAM_TO_UINT16(p_ccb->peer_conn_cfg.mps, p);
743 STREAM_TO_UINT16(p_ccb->peer_conn_cfg.credits, p);
744 STREAM_TO_UINT16(con_info.l2cap_result, p);
745 con_info.remote_cid = p_ccb->remote_cid;
746
747 L2CAP_TRACE_DEBUG(
748 "remote_cid = %d, "
749 "mtu = %d, "
750 "mps = %d, "
751 "initial_credit = %d, "
752 "con_info.l2cap_result = %d",
753 p_ccb->remote_cid, p_ccb->peer_conn_cfg.mtu,
754 p_ccb->peer_conn_cfg.mps, p_ccb->peer_conn_cfg.credits,
755 con_info.l2cap_result);
756
757 /* validate the parameters */
758 if (p_ccb->peer_conn_cfg.mtu < L2CAP_LE_MIN_MTU ||
759 p_ccb->peer_conn_cfg.mps < L2CAP_LE_MIN_MPS ||
760 p_ccb->peer_conn_cfg.mps > L2CAP_LE_MAX_MPS) {
761 L2CAP_TRACE_ERROR("L2CAP don't like the params");
762 con_info.l2cap_result = L2CAP_LE_NO_RESOURCES;
763 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
764 break;
765 }
766
767 p_ccb->tx_mps = p_ccb->peer_conn_cfg.mps;
768 p_ccb->ble_sdu = NULL;
769 p_ccb->ble_sdu_length = 0;
770 p_ccb->is_first_seg = true;
771 p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
772
773 if (con_info.l2cap_result == L2CAP_LE_CONN_OK)
774 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP, &con_info);
775 else
776 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
777 } else {
778 L2CAP_TRACE_DEBUG("I DO NOT remember the connection req");
779 con_info.l2cap_result = L2CAP_LE_INVALID_SOURCE_CID;
780 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
781 }
782 break;
783
784 case L2CAP_CMD_BLE_FLOW_CTRL_CREDIT:
785 STREAM_TO_UINT16(lcid, p);
786 p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, lcid);
787 if (p_ccb == NULL) {
788 L2CAP_TRACE_DEBUG("%s Credit received for unknown channel id %d",
789 __func__, lcid);
790 break;
791 }
792
793 STREAM_TO_UINT16(credit, p);
794 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT, &credit);
795 L2CAP_TRACE_DEBUG("%s Credit received", __func__);
796 break;
797
798 case L2CAP_CMD_DISC_REQ:
799 STREAM_TO_UINT16(lcid, p);
800 STREAM_TO_UINT16(rcid, p);
801
802 p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
803 if (p_ccb != NULL) {
804 if (p_ccb->remote_cid == rcid) {
805 p_ccb->remote_id = id;
806 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_REQ, NULL);
807 }
808 } else
809 l2cu_send_peer_disc_rsp(p_lcb, id, lcid, rcid);
810
811 break;
812
813 case L2CAP_CMD_DISC_RSP:
814 STREAM_TO_UINT16(rcid, p);
815 STREAM_TO_UINT16(lcid, p);
816
817 p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
818 if (p_ccb != NULL) {
819 if ((p_ccb->remote_cid == rcid) && (p_ccb->local_id == id))
820 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_RSP, NULL);
821 }
822 break;
823
824 default:
825 L2CAP_TRACE_WARNING("L2CAP - LE - unknown cmd code: %d", cmd_code);
826 l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
827 break;
828 }
829 }
830
831 /*******************************************************************************
832 *
833 * Function l2cble_init_direct_conn
834 *
835 * Description This function is to initate a direct connection
836 *
837 * Returns true connection initiated, false otherwise.
838 *
839 ******************************************************************************/
l2cble_init_direct_conn(tL2C_LCB * p_lcb)840 bool l2cble_init_direct_conn(tL2C_LCB* p_lcb) {
841 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
842 tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
843 uint16_t scan_int;
844 uint16_t scan_win;
845 BD_ADDR peer_addr;
846 uint8_t peer_addr_type = BLE_ADDR_PUBLIC;
847 uint8_t own_addr_type = BLE_ADDR_PUBLIC;
848
849 /* There can be only one BLE connection request outstanding at a time */
850 if (p_dev_rec == NULL) {
851 L2CAP_TRACE_WARNING("unknown device, can not initate connection");
852 return (false);
853 }
854
855 scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF)
856 ? BTM_BLE_SCAN_FAST_INT
857 : p_cb->scan_int;
858 scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF)
859 ? BTM_BLE_SCAN_FAST_WIN
860 : p_cb->scan_win;
861
862 peer_addr_type = p_lcb->ble_addr_type;
863 memcpy(peer_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
864
865 #if (BLE_PRIVACY_SPT == TRUE)
866 own_addr_type =
867 btm_cb.ble_ctr_cb.privacy_mode ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC;
868 if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) {
869 if (btm_cb.ble_ctr_cb.privacy_mode >= BTM_PRIVACY_1_2)
870 own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
871
872 btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
873 btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type);
874 } else {
875 btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true);
876
877 // If we have a current RPA, use that instead.
878 if (!bdaddr_is_empty((const bt_bdaddr_t*)p_dev_rec->ble.cur_rand_addr)) {
879 memcpy(peer_addr, p_dev_rec->ble.cur_rand_addr, BD_ADDR_LEN);
880 }
881 }
882 #endif
883
884 if (!btm_ble_topology_check(BTM_BLE_STATE_INIT)) {
885 l2cu_release_lcb(p_lcb);
886 L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
887 return false;
888 }
889
890 btm_send_hci_create_connection(
891 scan_int, /* uint16_t scan_int */
892 scan_win, /* uint16_t scan_win */
893 false, /* uint8_t white_list */
894 peer_addr_type, /* uint8_t addr_type_peer */
895 peer_addr, /* BD_ADDR bda_peer */
896 own_addr_type, /* uint8_t addr_type_own */
897 (uint16_t)(
898 (p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF)
899 ? p_dev_rec->conn_params.min_conn_int
900 : BTM_BLE_CONN_INT_MIN_DEF), /* uint16_t conn_int_min */
901 (uint16_t)(
902 (p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF)
903 ? p_dev_rec->conn_params.max_conn_int
904 : BTM_BLE_CONN_INT_MAX_DEF), /* uint16_t conn_int_max */
905 (uint16_t)(
906 (p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF)
907 ? p_dev_rec->conn_params.slave_latency
908 : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* uint16_t conn_latency */
909 (uint16_t)(
910 (p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF)
911 ? p_dev_rec->conn_params.supervision_tout
912 : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
913 0, /* uint16_t min_len */
914 0, /* uint16_t max_len */
915 p_lcb->initiating_phys);
916
917 p_lcb->link_state = LST_CONNECTING;
918 l2cb.is_ble_connecting = true;
919 memcpy(l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
920 alarm_set_on_queue(p_lcb->l2c_lcb_timer, L2CAP_BLE_LINK_CONNECT_TIMEOUT_MS,
921 l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue);
922 btm_ble_set_conn_st(BLE_DIR_CONN);
923
924 return (true);
925 }
926
927 /*******************************************************************************
928 *
929 * Function l2cble_create_conn
930 *
931 * Description This function initiates an acl connection via HCI
932 *
933 * Returns true if successful, false if connection not started.
934 *
935 ******************************************************************************/
l2cble_create_conn(tL2C_LCB * p_lcb)936 bool l2cble_create_conn(tL2C_LCB* p_lcb) {
937 tBTM_BLE_CONN_ST conn_st = btm_ble_get_conn_st();
938 bool rt = false;
939
940 /* There can be only one BLE connection request outstanding at a time */
941 if (conn_st == BLE_CONN_IDLE) {
942 rt = l2cble_init_direct_conn(p_lcb);
943 } else {
944 L2CAP_TRACE_WARNING(
945 "L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
946
947 btm_ble_enqueue_direct_conn_req(p_lcb);
948
949 if (conn_st == BLE_BG_CONN) btm_ble_suspend_bg_conn();
950
951 rt = true;
952 }
953 return rt;
954 }
955
956 /*******************************************************************************
957 *
958 * Function l2c_link_processs_ble_num_bufs
959 *
960 * Description This function is called when a "controller buffer size"
961 * event is first received from the controller. It updates
962 * the L2CAP values.
963 *
964 * Returns void
965 *
966 ******************************************************************************/
l2c_link_processs_ble_num_bufs(uint16_t num_lm_ble_bufs)967 void l2c_link_processs_ble_num_bufs(uint16_t num_lm_ble_bufs) {
968 if (num_lm_ble_bufs == 0) {
969 num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED;
970 l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED;
971 }
972
973 l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs;
974 }
975
976 /*******************************************************************************
977 *
978 * Function l2c_ble_link_adjust_allocation
979 *
980 * Description This function is called when a link is created or removed
981 * to calculate the amount of packets each link may send to
982 * the HCI without an ack coming back.
983 *
984 * Currently, this is a simple allocation, dividing the
985 * number of Controller Packets by the number of links. In
986 * the future, QOS configuration should be examined.
987 *
988 * Returns void
989 *
990 ******************************************************************************/
l2c_ble_link_adjust_allocation(void)991 void l2c_ble_link_adjust_allocation(void) {
992 uint16_t qq, yy, qq_remainder;
993 tL2C_LCB* p_lcb;
994 uint16_t hi_quota, low_quota;
995 uint16_t num_lowpri_links = 0;
996 uint16_t num_hipri_links = 0;
997 uint16_t controller_xmit_quota = l2cb.num_lm_ble_bufs;
998 uint16_t high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
999
1000 /* If no links active, reset buffer quotas and controller buffers */
1001 if (l2cb.num_ble_links_active == 0) {
1002 l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
1003 l2cb.ble_round_robin_quota = l2cb.ble_round_robin_unacked = 0;
1004 return;
1005 }
1006
1007 /* First, count the links */
1008 for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) {
1009 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) {
1010 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)
1011 num_hipri_links++;
1012 else
1013 num_lowpri_links++;
1014 }
1015 }
1016
1017 /* now adjust high priority link quota */
1018 low_quota = num_lowpri_links ? 1 : 0;
1019 while ((num_hipri_links * high_pri_link_quota + low_quota) >
1020 controller_xmit_quota)
1021 high_pri_link_quota--;
1022
1023 /* Work out the xmit quota and buffer quota high and low priorities */
1024 hi_quota = num_hipri_links * high_pri_link_quota;
1025 low_quota =
1026 (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1;
1027
1028 /* Work out and save the HCI xmit quota for each low priority link */
1029
1030 /* If each low priority link cannot have at least one buffer */
1031 if (num_lowpri_links > low_quota) {
1032 l2cb.ble_round_robin_quota = low_quota;
1033 qq = qq_remainder = 0;
1034 }
1035 /* If each low priority link can have at least one buffer */
1036 else if (num_lowpri_links > 0) {
1037 l2cb.ble_round_robin_quota = 0;
1038 l2cb.ble_round_robin_unacked = 0;
1039 qq = low_quota / num_lowpri_links;
1040 qq_remainder = low_quota % num_lowpri_links;
1041 }
1042 /* If no low priority link */
1043 else {
1044 l2cb.ble_round_robin_quota = 0;
1045 l2cb.ble_round_robin_unacked = 0;
1046 qq = qq_remainder = 0;
1047 }
1048 L2CAP_TRACE_EVENT(
1049 "l2c_ble_link_adjust_allocation num_hipri: %u num_lowpri: %u "
1050 "low_quota: %u round_robin_quota: %u qq: %u",
1051 num_hipri_links, num_lowpri_links, low_quota, l2cb.ble_round_robin_quota,
1052 qq);
1053
1054 /* Now, assign the quotas to each link */
1055 for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) {
1056 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) {
1057 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) {
1058 p_lcb->link_xmit_quota = high_pri_link_quota;
1059 } else {
1060 /* Safety check in case we switched to round-robin with something
1061 * outstanding */
1062 /* if sent_not_acked is added into round_robin_unacked then don't add it
1063 * again */
1064 /* l2cap keeps updating sent_not_acked for exiting from round robin */
1065 if ((p_lcb->link_xmit_quota > 0) && (qq == 0))
1066 l2cb.ble_round_robin_unacked += p_lcb->sent_not_acked;
1067
1068 p_lcb->link_xmit_quota = qq;
1069 if (qq_remainder > 0) {
1070 p_lcb->link_xmit_quota++;
1071 qq_remainder--;
1072 }
1073 }
1074
1075 L2CAP_TRACE_EVENT(
1076 "l2c_ble_link_adjust_allocation LCB %d Priority: %d XmitQuota: %d",
1077 yy, p_lcb->acl_priority, p_lcb->link_xmit_quota);
1078
1079 L2CAP_TRACE_EVENT(" SentNotAcked: %d RRUnacked: %d",
1080 p_lcb->sent_not_acked, l2cb.round_robin_unacked);
1081
1082 /* There is a special case where we have readjusted the link quotas and */
1083 /* this link may have sent anything but some other link sent packets so */
1084 /* so we may need a timer to kick off this link's transmissions. */
1085 if ((p_lcb->link_state == LST_CONNECTED) &&
1086 (!list_is_empty(p_lcb->link_xmit_data_q)) &&
1087 (p_lcb->sent_not_acked < p_lcb->link_xmit_quota)) {
1088 alarm_set_on_queue(
1089 p_lcb->l2c_lcb_timer, L2CAP_LINK_FLOW_CONTROL_TIMEOUT_MS,
1090 l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue);
1091 }
1092 }
1093 }
1094 }
1095
1096 #if (BLE_LLT_INCLUDED == TRUE)
1097 /*******************************************************************************
1098 *
1099 * Function l2cble_process_rc_param_request_evt
1100 *
1101 * Description process LE Remote Connection Parameter Request Event.
1102 *
1103 * Returns void
1104 *
1105 ******************************************************************************/
l2cble_process_rc_param_request_evt(uint16_t handle,uint16_t int_min,uint16_t int_max,uint16_t latency,uint16_t timeout)1106 void l2cble_process_rc_param_request_evt(uint16_t handle, uint16_t int_min,
1107 uint16_t int_max, uint16_t latency,
1108 uint16_t timeout) {
1109 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
1110
1111 if (p_lcb != NULL) {
1112 p_lcb->min_interval = int_min;
1113 p_lcb->max_interval = int_max;
1114 p_lcb->latency = latency;
1115 p_lcb->timeout = timeout;
1116
1117 /* if update is enabled, always accept connection parameter update */
1118 if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0) {
1119 btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency,
1120 timeout, 0, 0);
1121 } else {
1122 L2CAP_TRACE_EVENT("L2CAP - LE - update currently disabled");
1123 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
1124 btsnd_hcic_ble_rc_param_req_neg_reply(handle,
1125 HCI_ERR_UNACCEPT_CONN_INTERVAL);
1126 }
1127
1128 } else {
1129 L2CAP_TRACE_WARNING("No link to update connection parameter")
1130 }
1131 }
1132 #endif
1133
1134 /*******************************************************************************
1135 *
1136 * Function l2cble_update_data_length
1137 *
1138 * Description This function update link tx data length if applicable
1139 *
1140 * Returns void
1141 *
1142 ******************************************************************************/
l2cble_update_data_length(tL2C_LCB * p_lcb)1143 void l2cble_update_data_length(tL2C_LCB* p_lcb) {
1144 uint16_t tx_mtu = 0;
1145 uint16_t i = 0;
1146
1147 L2CAP_TRACE_DEBUG("%s", __func__);
1148
1149 /* See if we have a link control block for the connection */
1150 if (p_lcb == NULL) return;
1151
1152 for (i = 0; i < L2CAP_NUM_FIXED_CHNLS; i++) {
1153 if (i + L2CAP_FIRST_FIXED_CHNL != L2CAP_BLE_SIGNALLING_CID) {
1154 if ((p_lcb->p_fixed_ccbs[i] != NULL) &&
1155 (tx_mtu < (p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD)))
1156 tx_mtu = p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD;
1157 }
1158 }
1159
1160 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX) tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1161
1162 /* update TX data length if changed */
1163 if (p_lcb->tx_data_len != tx_mtu)
1164 BTM_SetBleDataLength(p_lcb->remote_bd_addr, tx_mtu);
1165 }
1166
1167 /*******************************************************************************
1168 *
1169 * Function l2cble_process_data_length_change_evt
1170 *
1171 * Description This function process the data length change event
1172 *
1173 * Returns void
1174 *
1175 ******************************************************************************/
l2cble_process_data_length_change_event(uint16_t handle,uint16_t tx_data_len,uint16_t rx_data_len)1176 void l2cble_process_data_length_change_event(uint16_t handle,
1177 uint16_t tx_data_len,
1178 uint16_t rx_data_len) {
1179 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
1180
1181 L2CAP_TRACE_DEBUG("%s TX data len = %d", __func__, tx_data_len);
1182 if (p_lcb == NULL) return;
1183
1184 if (tx_data_len > 0) p_lcb->tx_data_len = tx_data_len;
1185
1186 /* ignore rx_data len for now */
1187 }
1188
1189 /*******************************************************************************
1190 *
1191 * Function l2cble_set_fixed_channel_tx_data_length
1192 *
1193 * Description This function update max fixed channel tx data length if
1194 * applicable
1195 *
1196 * Returns void
1197 *
1198 ******************************************************************************/
l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda,uint16_t fix_cid,uint16_t tx_mtu)1199 void l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda,
1200 uint16_t fix_cid,
1201 uint16_t tx_mtu) {
1202 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(remote_bda, BT_TRANSPORT_LE);
1203 uint16_t cid = fix_cid - L2CAP_FIRST_FIXED_CHNL;
1204
1205 L2CAP_TRACE_DEBUG("%s TX MTU = %d", __func__, tx_mtu);
1206
1207 if (!controller_get_interface()->supports_ble_packet_extension()) {
1208 L2CAP_TRACE_WARNING("%s, request not supported", __func__);
1209 return;
1210 }
1211
1212 /* See if we have a link control block for the connection */
1213 if (p_lcb == NULL) return;
1214
1215 if (p_lcb->p_fixed_ccbs[cid] != NULL) {
1216 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX) tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1217
1218 p_lcb->p_fixed_ccbs[cid]->tx_data_len = tx_mtu;
1219 }
1220
1221 l2cble_update_data_length(p_lcb);
1222 }
1223
1224 /*******************************************************************************
1225 *
1226 * Function l2cble_credit_based_conn_req
1227 *
1228 * Description This function sends LE Credit Based Connection Request for
1229 * LE connection oriented channels.
1230 *
1231 * Returns void
1232 *
1233 ******************************************************************************/
l2cble_credit_based_conn_req(tL2C_CCB * p_ccb)1234 void l2cble_credit_based_conn_req(tL2C_CCB* p_ccb) {
1235 if (!p_ccb) return;
1236
1237 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1238 L2CAP_TRACE_WARNING("LE link doesn't exist");
1239 return;
1240 }
1241
1242 l2cu_send_peer_ble_credit_based_conn_req(p_ccb);
1243 return;
1244 }
1245
1246 /*******************************************************************************
1247 *
1248 * Function l2cble_credit_based_conn_res
1249 *
1250 * Description This function sends LE Credit Based Connection Response for
1251 * LE connection oriented channels.
1252 *
1253 * Returns void
1254 *
1255 ******************************************************************************/
l2cble_credit_based_conn_res(tL2C_CCB * p_ccb,uint16_t result)1256 void l2cble_credit_based_conn_res(tL2C_CCB* p_ccb, uint16_t result) {
1257 if (!p_ccb) return;
1258
1259 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1260 L2CAP_TRACE_WARNING("LE link doesn't exist");
1261 return;
1262 }
1263
1264 l2cu_send_peer_ble_credit_based_conn_res(p_ccb, result);
1265 return;
1266 }
1267
1268 /*******************************************************************************
1269 *
1270 * Function l2cble_send_flow_control_credit
1271 *
1272 * Description This function sends flow control credits for
1273 * LE connection oriented channels.
1274 *
1275 * Returns void
1276 *
1277 ******************************************************************************/
l2cble_send_flow_control_credit(tL2C_CCB * p_ccb,uint16_t credit_value)1278 void l2cble_send_flow_control_credit(tL2C_CCB* p_ccb, uint16_t credit_value) {
1279 if (!p_ccb) return;
1280
1281 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1282 L2CAP_TRACE_WARNING("LE link doesn't exist");
1283 return;
1284 }
1285
1286 l2cu_send_peer_ble_flow_control_credit(p_ccb, credit_value);
1287 return;
1288 }
1289
1290 /*******************************************************************************
1291 *
1292 * Function l2cble_send_peer_disc_req
1293 *
1294 * Description This function sends disconnect request
1295 * to the peer LE device
1296 *
1297 * Returns void
1298 *
1299 ******************************************************************************/
l2cble_send_peer_disc_req(tL2C_CCB * p_ccb)1300 void l2cble_send_peer_disc_req(tL2C_CCB* p_ccb) {
1301 L2CAP_TRACE_DEBUG("%s", __func__);
1302 if (!p_ccb) return;
1303
1304 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1305 L2CAP_TRACE_WARNING("LE link doesn't exist");
1306 return;
1307 }
1308
1309 l2cu_send_peer_ble_credit_based_disconn_req(p_ccb);
1310 return;
1311 }
1312
1313 /*******************************************************************************
1314 *
1315 * Function l2cble_sec_comp
1316 *
1317 * Description This function is called when security procedure for an LE
1318 * COC link is done
1319 *
1320 * Returns void
1321 *
1322 ******************************************************************************/
l2cble_sec_comp(BD_ADDR p_bda,tBT_TRANSPORT transport,void * p_ref_data,uint8_t status)1323 void l2cble_sec_comp(BD_ADDR p_bda, tBT_TRANSPORT transport, void* p_ref_data,
1324 uint8_t status) {
1325 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, BT_TRANSPORT_LE);
1326 tL2CAP_SEC_DATA* p_buf = NULL;
1327 uint8_t sec_flag;
1328 uint8_t sec_act;
1329
1330 if (!p_lcb) {
1331 L2CAP_TRACE_WARNING("%s security complete for unknown device", __func__);
1332 return;
1333 }
1334
1335 sec_act = p_lcb->sec_act;
1336 p_lcb->sec_act = 0;
1337
1338 if (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) {
1339 p_buf = (tL2CAP_SEC_DATA*)fixed_queue_dequeue(p_lcb->le_sec_pending_q);
1340 if (!p_buf) {
1341 L2CAP_TRACE_WARNING(
1342 "%s Security complete for request not initiated from L2CAP",
1343 __func__);
1344 return;
1345 }
1346
1347 if (status != BTM_SUCCESS) {
1348 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1349 } else {
1350 if (sec_act == BTM_SEC_ENCRYPT_MITM) {
1351 BTM_GetSecurityFlagsByTransport(p_bda, &sec_flag, transport);
1352 if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
1353 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
1354 status);
1355 else {
1356 L2CAP_TRACE_DEBUG("%s MITM Protection Not present", __func__);
1357 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
1358 BTM_FAILED_ON_SECURITY);
1359 }
1360 } else {
1361 L2CAP_TRACE_DEBUG("%s MITM Protection not required sec_act = %d",
1362 __func__, p_lcb->sec_act);
1363
1364 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
1365 status);
1366 }
1367 }
1368 } else {
1369 L2CAP_TRACE_WARNING(
1370 "%s Security complete for request not initiated from L2CAP", __func__);
1371 return;
1372 }
1373 osi_free(p_buf);
1374
1375 while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) {
1376 p_buf = (tL2CAP_SEC_DATA*)fixed_queue_dequeue(p_lcb->le_sec_pending_q);
1377
1378 if (status != BTM_SUCCESS)
1379 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1380 else
1381 l2ble_sec_access_req(p_bda, p_buf->psm, p_buf->is_originator,
1382 p_buf->p_callback, p_buf->p_ref_data);
1383
1384 osi_free(p_buf);
1385 }
1386 }
1387
1388 /*******************************************************************************
1389 *
1390 * Function l2ble_sec_access_req
1391 *
1392 * Description This function is called by LE COC link to meet the
1393 * security requirement for the link
1394 *
1395 * Returns true - security procedures are started
1396 * false - failure
1397 *
1398 ******************************************************************************/
l2ble_sec_access_req(BD_ADDR bd_addr,uint16_t psm,bool is_originator,tL2CAP_SEC_CBACK * p_callback,void * p_ref_data)1399 bool l2ble_sec_access_req(BD_ADDR bd_addr, uint16_t psm, bool is_originator,
1400 tL2CAP_SEC_CBACK* p_callback, void* p_ref_data) {
1401 L2CAP_TRACE_DEBUG("%s", __func__);
1402 bool status;
1403 tL2C_LCB* p_lcb = NULL;
1404
1405 if (!p_callback) {
1406 L2CAP_TRACE_ERROR("%s No callback function", __func__);
1407 return false;
1408 }
1409
1410 p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
1411
1412 if (!p_lcb) {
1413 L2CAP_TRACE_ERROR("%s Security check for unknown device", __func__);
1414 p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_UNKNOWN_ADDR);
1415 return false;
1416 }
1417
1418 tL2CAP_SEC_DATA* p_buf =
1419 (tL2CAP_SEC_DATA*)osi_malloc((uint16_t)sizeof(tL2CAP_SEC_DATA));
1420 if (!p_buf) {
1421 p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_NO_RESOURCES);
1422 return false;
1423 }
1424
1425 p_buf->psm = psm;
1426 p_buf->is_originator = is_originator;
1427 p_buf->p_callback = p_callback;
1428 p_buf->p_ref_data = p_ref_data;
1429 fixed_queue_enqueue(p_lcb->le_sec_pending_q, p_buf);
1430 status = btm_ble_start_sec_check(bd_addr, psm, is_originator,
1431 &l2cble_sec_comp, p_ref_data);
1432
1433 return status;
1434 }
1435