1 /******************************************************************************
2 *
3 * Copyright 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 #define LOG_TAG "l2c_ble"
26
27 #include <base/logging.h>
28 #include <base/strings/stringprintf.h>
29 #include <log/log.h>
30
31 #include "bt_target.h"
32 #include "bta/include/bta_hearing_aid_api.h"
33 #include "device/include/controller.h"
34 #include "main/shim/l2c_api.h"
35 #include "main/shim/shim.h"
36 #include "osi/include/allocator.h"
37 #include "osi/include/log.h"
38 #include "osi/include/osi.h"
39 #include "stack/btm/btm_dev.h"
40 #include "stack/btm/btm_sec.h"
41 #include "stack/include/acl_api.h"
42 #include "stack/include/l2c_api.h"
43 #include "stack/include/l2cdefs.h"
44 #include "stack/l2cap/l2c_int.h"
45 #include "stack_config.h"
46 #include "types/raw_address.h"
47
48 namespace {
49
50 constexpr char kBtmLogTag[] = "L2CAP";
51
52 }
53
54 tL2CAP_LE_RESULT_CODE btm_ble_start_sec_check(const RawAddress& bd_addr,
55 uint16_t psm, bool is_originator,
56 tBTM_SEC_CALLBACK* p_callback,
57 void* p_ref_data);
58
59 extern tBTM_CB btm_cb;
60
61 using base::StringPrintf;
62
63 static void l2cble_start_conn_update(tL2C_LCB* p_lcb);
64 extern void gatt_notify_conn_update(const RawAddress& remote, uint16_t interval,
65 uint16_t latency, uint16_t timeout,
66 tHCI_STATUS status);
67
68 /*******************************************************************************
69 *
70 * Function L2CA_UpdateBleConnParams
71 *
72 * Description Update BLE connection parameters.
73 *
74 * Parameters: BD Address of remote
75 *
76 * Return value: true if update started
77 *
78 ******************************************************************************/
L2CA_UpdateBleConnParams(const RawAddress & rem_bda,uint16_t min_int,uint16_t max_int,uint16_t latency,uint16_t timeout,uint16_t min_ce_len,uint16_t max_ce_len)79 bool L2CA_UpdateBleConnParams(const RawAddress& rem_bda, uint16_t min_int,
80 uint16_t max_int, uint16_t latency,
81 uint16_t timeout, uint16_t min_ce_len,
82 uint16_t max_ce_len) {
83 if (bluetooth::shim::is_gd_l2cap_enabled()) {
84 bluetooth::shim::L2CA_LeConnectionUpdate(rem_bda, min_int, max_int, latency,
85 timeout, min_ce_len, max_ce_len);
86 return true;
87 }
88
89 tL2C_LCB* p_lcb;
90
91 /* See if we have a link control block for the remote device */
92 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
93
94 /* If we do not have one, create one and accept the connection. */
95 if (!p_lcb || !BTM_IsAclConnectionUp(rem_bda, BT_TRANSPORT_LE)) {
96 LOG(WARNING) << __func__ << " - unknown BD_ADDR " << rem_bda;
97 return (false);
98 }
99
100 if (p_lcb->transport != BT_TRANSPORT_LE) {
101 LOG(WARNING) << __func__ << " - BD_ADDR " << rem_bda << " not LE";
102 return (false);
103 }
104
105 VLOG(2) << __func__ << ": BD_ADDR=" << rem_bda << ", min_int=" << min_int
106 << ", max_int=" << max_int << ", min_ce_len=" << min_ce_len
107 << ", max_ce_len=" << max_ce_len;
108
109 p_lcb->min_interval = min_int;
110 p_lcb->max_interval = max_int;
111 p_lcb->latency = latency;
112 p_lcb->timeout = timeout;
113 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
114 p_lcb->min_ce_len = min_ce_len;
115 p_lcb->max_ce_len = max_ce_len;
116
117 l2cble_start_conn_update(p_lcb);
118
119 return (true);
120 }
121
122 /*******************************************************************************
123 *
124 * Function L2CA_EnableUpdateBleConnParams
125 *
126 * Description Enable or disable update based on the request from the peer
127 *
128 * Parameters: BD Address of remote
129 *
130 * Return value: true if update started
131 *
132 ******************************************************************************/
L2CA_EnableUpdateBleConnParams(const RawAddress & rem_bda,bool enable)133 bool L2CA_EnableUpdateBleConnParams(const RawAddress& rem_bda, bool enable) {
134 if (bluetooth::shim::is_gd_l2cap_enabled()) {
135 return bluetooth::shim::L2CA_EnableUpdateBleConnParams(rem_bda, enable);
136 }
137
138 if (stack_config_get_interface()->get_pts_conn_updates_disabled())
139 return false;
140
141 tL2C_LCB* p_lcb;
142
143 /* See if we have a link control block for the remote device */
144 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
145
146 if (!p_lcb) {
147 LOG(WARNING) << __func__ << " - unknown BD_ADDR " << rem_bda;
148 return false;
149 }
150
151 VLOG(2) << __func__ << " - BD_ADDR " << rem_bda
152 << StringPrintf(" enable %d current upd state 0x%02x", enable,
153 p_lcb->conn_update_mask);
154
155 if (p_lcb->transport != BT_TRANSPORT_LE) {
156 LOG(WARNING) << __func__ << " - BD_ADDR " << rem_bda
157 << " not LE, link role " << p_lcb->LinkRole();
158 return false;
159 }
160
161 if (enable)
162 p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
163 else
164 p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE;
165
166 l2cble_start_conn_update(p_lcb);
167
168 return (true);
169 }
170
L2CA_GetBleConnRole(const RawAddress & bd_addr)171 hci_role_t L2CA_GetBleConnRole(const RawAddress& bd_addr) {
172 if (bluetooth::shim::is_gd_l2cap_enabled()) {
173 return bluetooth::shim::L2CA_GetBleConnRole(bd_addr);
174 }
175
176 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
177 if (p_lcb == nullptr) {
178 return HCI_ROLE_UNKNOWN;
179 }
180 return p_lcb->LinkRole();
181 }
182
183 /*******************************************************************************
184 *
185 * Function l2cble_notify_le_connection
186 *
187 * Description This function notifiy the l2cap connection to the app layer
188 *
189 * Returns none
190 *
191 ******************************************************************************/
l2cble_notify_le_connection(const RawAddress & bda)192 void l2cble_notify_le_connection(const RawAddress& bda) {
193 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE);
194 if (p_lcb == nullptr) {
195 LOG_WARN("Received notification for le connection but no lcb found");
196 return;
197 }
198
199 if (BTM_IsAclConnectionUp(bda, BT_TRANSPORT_LE) &&
200 p_lcb->link_state != LST_CONNECTED) {
201 /* update link status */
202 // TODO Move this back into acl layer
203 btm_establish_continue_from_address(bda, BT_TRANSPORT_LE);
204 /* update l2cap link status and send callback */
205 p_lcb->link_state = LST_CONNECTED;
206 l2cu_process_fixed_chnl_resp(p_lcb);
207 }
208
209 /* For all channels, send the event through their FSMs */
210 for (tL2C_CCB* p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;
211 p_ccb = p_ccb->p_next_ccb) {
212 if (p_ccb->chnl_state == CST_CLOSED)
213 l2c_csm_execute(p_ccb, L2CEVT_LP_CONNECT_CFM, NULL);
214 }
215 }
216
217 /** This function is called when an HCI Connection Complete event is received.
218 */
l2cble_conn_comp(uint16_t handle,uint8_t role,const RawAddress & bda,tBLE_ADDR_TYPE type,uint16_t conn_interval,uint16_t conn_latency,uint16_t conn_timeout)219 bool l2cble_conn_comp(uint16_t handle, uint8_t role, const RawAddress& bda,
220 tBLE_ADDR_TYPE type, uint16_t conn_interval,
221 uint16_t conn_latency, uint16_t conn_timeout) {
222 // role == HCI_ROLE_CENTRAL => scanner completed connection
223 // role == HCI_ROLE_PERIPHERAL => advertiser completed connection
224
225 /* See if we have a link control block for the remote device */
226 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE);
227
228 /* If we do not have one, create one. this is auto connection complete. */
229 if (!p_lcb) {
230 p_lcb = l2cu_allocate_lcb(bda, false, BT_TRANSPORT_LE);
231 if (!p_lcb) {
232 LOG_ERROR("Unable to allocate link resource for le acl connection");
233 return false;
234 } else {
235 if (!l2cu_initialize_fixed_ccb(p_lcb, L2CAP_ATT_CID)) {
236 LOG_ERROR("Unable to allocate channel resource for le acl connection");
237 return false;
238 }
239 }
240 } else if (role == HCI_ROLE_CENTRAL && p_lcb->link_state != LST_CONNECTING) {
241 LOG_ERROR(
242 "Received le acl connection as role central but not in connecting "
243 "state");
244 return false;
245 }
246
247 if (role == HCI_ROLE_CENTRAL) alarm_cancel(p_lcb->l2c_lcb_timer);
248
249 /* Save the handle */
250 l2cu_set_lcb_handle(*p_lcb, handle);
251
252 /* Connected OK. Change state to connected, we were scanning so we are central
253 */
254 if (role == HCI_ROLE_CENTRAL) {
255 p_lcb->SetLinkRoleAsCentral();
256 } else {
257 p_lcb->SetLinkRoleAsPeripheral();
258 }
259
260 p_lcb->transport = BT_TRANSPORT_LE;
261
262 /* update link parameter, set peripheral link as non-spec default upon link up
263 */
264 p_lcb->min_interval = p_lcb->max_interval = conn_interval;
265 p_lcb->timeout = conn_timeout;
266 p_lcb->latency = conn_latency;
267 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
268
269 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT |
270 L2CAP_FIXED_CHNL_BLE_SIG_BIT |
271 L2CAP_FIXED_CHNL_SMP_BIT;
272
273 if (role == HCI_ROLE_PERIPHERAL) {
274 if (!controller_get_interface()
275 ->supports_ble_peripheral_initiated_feature_exchange()) {
276 p_lcb->link_state = LST_CONNECTED;
277 l2cu_process_fixed_chnl_resp(p_lcb);
278 }
279 }
280 return true;
281 }
282
l2cble_conn_comp_from_address_with_type(uint16_t handle,uint8_t role,const tBLE_BD_ADDR & address_with_type,uint16_t conn_interval,uint16_t conn_latency,uint16_t conn_timeout)283 bool l2cble_conn_comp_from_address_with_type(
284 uint16_t handle, uint8_t role, const tBLE_BD_ADDR& address_with_type,
285 uint16_t conn_interval, uint16_t conn_latency, uint16_t conn_timeout) {
286 return l2cble_conn_comp(handle, role, address_with_type.bda,
287 address_with_type.type, conn_interval, conn_latency,
288 conn_timeout);
289 }
290
291 /*******************************************************************************
292 *
293 * Function l2cble_start_conn_update
294 *
295 * Description Start the BLE connection parameter update process based on
296 * status.
297 *
298 * Parameters: lcb : l2cap link control block
299 *
300 * Return value: none
301 *
302 ******************************************************************************/
l2cble_start_conn_update(tL2C_LCB * p_lcb)303 static void l2cble_start_conn_update(tL2C_LCB* p_lcb) {
304 uint16_t min_conn_int, max_conn_int, peripheral_latency, supervision_tout;
305 if (!BTM_IsAclConnectionUp(p_lcb->remote_bd_addr, BT_TRANSPORT_LE)) {
306 LOG(ERROR) << "No known connection ACL for " << p_lcb->remote_bd_addr;
307 return;
308 }
309
310 // TODO(armansito): The return value of this call wasn't being used but the
311 // logic of this function might be depending on its side effects. We should
312 // verify if this call is needed at all and remove it otherwise.
313 btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
314
315 if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) return;
316
317 if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) {
318 /* application requests to disable parameters update.
319 If parameters are already updated, lets set them
320 up to what has been requested during connection establishement */
321 if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM &&
322 /* current connection interval is greater than default min */
323 p_lcb->min_interval > BTM_BLE_CONN_INT_MIN) {
324 /* use 7.5 ms as fast connection parameter, 0 peripheral latency */
325 min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
326
327 L2CA_AdjustConnectionIntervals(&min_conn_int, &max_conn_int,
328 BTM_BLE_CONN_INT_MIN);
329
330 peripheral_latency = BTM_BLE_CONN_PERIPHERAL_LATENCY_DEF;
331 supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;
332
333 /* if both side 4.1, or we are central device, send HCI command */
334 if (p_lcb->IsLinkRoleCentral()
335 || (controller_get_interface()
336 ->supports_ble_connection_parameter_request() &&
337 acl_peer_supports_ble_connection_parameters_request(
338 p_lcb->remote_bd_addr))
339 ) {
340 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->Handle(), min_conn_int,
341 max_conn_int, peripheral_latency,
342 supervision_tout, 0, 0);
343 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
344 } else {
345 l2cu_send_peer_ble_par_req(p_lcb, min_conn_int, max_conn_int,
346 peripheral_latency, supervision_tout);
347 }
348 p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
349 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
350 }
351 } else {
352 /* application allows to do update, if we were delaying one do it now */
353 if (p_lcb->conn_update_mask & L2C_BLE_NEW_CONN_PARAM) {
354 /* if both side 4.1, or we are central device, send HCI command */
355 if (p_lcb->IsLinkRoleCentral()
356 || (controller_get_interface()
357 ->supports_ble_connection_parameter_request() &&
358 acl_peer_supports_ble_connection_parameters_request(
359 p_lcb->remote_bd_addr))
360 ) {
361 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->Handle(), p_lcb->min_interval,
362 p_lcb->max_interval, p_lcb->latency,
363 p_lcb->timeout, p_lcb->min_ce_len,
364 p_lcb->max_ce_len);
365 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
366 } else {
367 l2cu_send_peer_ble_par_req(p_lcb, p_lcb->min_interval,
368 p_lcb->max_interval, p_lcb->latency,
369 p_lcb->timeout);
370 }
371 p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
372 p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
373 }
374 }
375 }
376
377 /*******************************************************************************
378 *
379 * Function l2cble_process_conn_update_evt
380 *
381 * Description This function enables the connection update request from
382 * remote after a successful connection update response is
383 * received.
384 *
385 * Returns void
386 *
387 ******************************************************************************/
l2cble_process_conn_update_evt(uint16_t handle,uint8_t status,uint16_t interval,uint16_t latency,uint16_t timeout)388 void l2cble_process_conn_update_evt(uint16_t handle, uint8_t status,
389 uint16_t interval, uint16_t latency,
390 uint16_t timeout) {
391 L2CAP_TRACE_DEBUG("%s", __func__);
392
393 /* See if we have a link control block for the remote device */
394 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
395 if (!p_lcb) {
396 L2CAP_TRACE_WARNING("%s: Invalid handle: %d", __func__, handle);
397 return;
398 }
399
400 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
401
402 if (status != HCI_SUCCESS) {
403 L2CAP_TRACE_WARNING("%s: Error status: %d", __func__, status);
404 }
405
406 l2cble_start_conn_update(p_lcb);
407
408 L2CAP_TRACE_DEBUG("%s: conn_update_mask=%d", __func__,
409 p_lcb->conn_update_mask);
410 }
411
412 /*******************************************************************************
413 *
414 * Function l2cble_handle_connect_rsp_neg
415 *
416 * Description This function sends error message to all the
417 * outstanding channels
418 *
419 * Returns void
420 *
421 ******************************************************************************/
l2cble_handle_connect_rsp_neg(tL2C_LCB * p_lcb,tL2C_CONN_INFO * con_info)422 static void l2cble_handle_connect_rsp_neg(tL2C_LCB* p_lcb,
423 tL2C_CONN_INFO* con_info) {
424 tL2C_CCB* temp_p_ccb = NULL;
425 for (int i = 0; i < p_lcb->pending_ecoc_conn_cnt; i++) {
426 uint16_t cid = p_lcb->pending_ecoc_connection_cids[i];
427 temp_p_ccb = l2cu_find_ccb_by_cid(p_lcb, cid);
428 l2c_csm_execute(temp_p_ccb, L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP_NEG,
429 con_info);
430 }
431
432 p_lcb->pending_ecoc_conn_cnt = 0;
433 memset(p_lcb->pending_ecoc_connection_cids, 0, L2CAP_CREDIT_BASED_MAX_CIDS);
434 }
435
436 /*******************************************************************************
437 *
438 * Function l2cble_process_sig_cmd
439 *
440 * Description This function is called when a signalling packet is received
441 * on the BLE signalling CID
442 *
443 * Returns void
444 *
445 ******************************************************************************/
l2cble_process_sig_cmd(tL2C_LCB * p_lcb,uint8_t * p,uint16_t pkt_len)446 void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
447 uint8_t* p_pkt_end;
448 uint8_t cmd_code, id;
449 uint16_t cmd_len;
450 uint16_t min_interval, max_interval, latency, timeout;
451 tL2C_CONN_INFO con_info;
452 uint16_t lcid = 0, rcid = 0, mtu = 0, mps = 0, initial_credit = 0;
453 tL2C_CCB *p_ccb = NULL, *temp_p_ccb = NULL;
454 tL2C_RCB* p_rcb;
455 uint16_t credit;
456 uint8_t num_of_channels;
457
458 p_pkt_end = p + pkt_len;
459
460 if (p + 4 > p_pkt_end) {
461 LOG(ERROR) << "invalid read";
462 return;
463 }
464
465 STREAM_TO_UINT8(cmd_code, p);
466 STREAM_TO_UINT8(id, p);
467 STREAM_TO_UINT16(cmd_len, p);
468
469 /* Check command length does not exceed packet length */
470 if ((p + cmd_len) > p_pkt_end) {
471 L2CAP_TRACE_WARNING(
472 "L2CAP - LE - format error, pkt_len: %d cmd_len: %d code: %d",
473 pkt_len, cmd_len, cmd_code);
474 return;
475 }
476
477 switch (cmd_code) {
478 case L2CAP_CMD_REJECT: {
479 uint16_t reason;
480 STREAM_TO_UINT16(reason, p);
481
482 if (reason == L2CAP_CMD_REJ_NOT_UNDERSTOOD &&
483 p_lcb->pending_ecoc_conn_cnt > 0) {
484 con_info.l2cap_result = L2CAP_LE_RESULT_NO_PSM;
485 l2cble_handle_connect_rsp_neg(p_lcb, &con_info);
486 }
487 } break;
488
489 case L2CAP_CMD_ECHO_REQ:
490 case L2CAP_CMD_ECHO_RSP:
491 case L2CAP_CMD_INFO_RSP:
492 case L2CAP_CMD_INFO_REQ:
493 l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
494 break;
495
496 case L2CAP_CMD_BLE_UPDATE_REQ:
497 if (p + 8 > p_pkt_end) {
498 LOG(ERROR) << "invalid read";
499 return;
500 }
501
502 STREAM_TO_UINT16(min_interval, p); /* 0x0006 - 0x0C80 */
503 STREAM_TO_UINT16(max_interval, p); /* 0x0006 - 0x0C80 */
504 STREAM_TO_UINT16(latency, p); /* 0x0000 - 0x03E8 */
505 STREAM_TO_UINT16(timeout, p); /* 0x000A - 0x0C80 */
506 /* If we are a central, the peripheral wants to update the parameters */
507 if (p_lcb->IsLinkRoleCentral()) {
508 L2CA_AdjustConnectionIntervals(&min_interval, &max_interval,
509 BTM_BLE_CONN_INT_MIN_LIMIT);
510
511 if (min_interval < BTM_BLE_CONN_INT_MIN ||
512 min_interval > BTM_BLE_CONN_INT_MAX ||
513 max_interval < BTM_BLE_CONN_INT_MIN ||
514 max_interval > BTM_BLE_CONN_INT_MAX ||
515 latency > BTM_BLE_CONN_LATENCY_MAX ||
516 /*(timeout >= max_interval && latency > (timeout * 10/(max_interval
517 * 1.25) - 1)) ||*/
518 timeout < BTM_BLE_CONN_SUP_TOUT_MIN ||
519 timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
520 max_interval < min_interval) {
521 l2cu_send_peer_ble_par_rsp(p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
522 } else {
523 l2cu_send_peer_ble_par_rsp(p_lcb, L2CAP_CFG_OK, id);
524
525 p_lcb->min_interval = min_interval;
526 p_lcb->max_interval = max_interval;
527 p_lcb->latency = latency;
528 p_lcb->timeout = timeout;
529 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
530
531 l2cble_start_conn_update(p_lcb);
532 }
533 } else
534 l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0,
535 0);
536 break;
537
538 case L2CAP_CMD_BLE_UPDATE_RSP:
539 p += 2;
540 break;
541
542 case L2CAP_CMD_CREDIT_BASED_CONN_REQ: {
543 if (p + 10 > p_pkt_end) {
544 LOG(ERROR) << "invalid L2CAP_CMD_CREDIT_BASED_CONN_REQ len";
545 return;
546 }
547
548 STREAM_TO_UINT16(con_info.psm, p);
549 STREAM_TO_UINT16(mtu, p);
550 STREAM_TO_UINT16(mps, p);
551 STREAM_TO_UINT16(initial_credit, p);
552
553 /* Check how many channels remote side wants. */
554 num_of_channels = (p_pkt_end - p) / sizeof(uint16_t);
555 if (num_of_channels > L2CAP_CREDIT_BASED_MAX_CIDS) {
556 LOG_WARN("L2CAP - invalid number of channels requested: %d",
557 num_of_channels);
558 l2cu_reject_credit_based_conn_req(p_lcb, id,
559 L2CAP_CREDIT_BASED_MAX_CIDS,
560 L2CAP_LE_RESULT_INVALID_PARAMETERS);
561 return;
562 }
563
564 LOG_DEBUG(
565 "Recv L2CAP_CMD_CREDIT_BASED_CONN_REQ with "
566 "mtu = %d, "
567 "mps = %d, "
568 "initial credit = %d"
569 "num_of_channels = %d",
570 mtu, mps, initial_credit, num_of_channels);
571
572 /* Check PSM Support */
573 p_rcb = l2cu_find_ble_rcb_by_psm(con_info.psm);
574 if (p_rcb == NULL) {
575 LOG_WARN("L2CAP - rcvd conn req for unknown PSM: 0x%04x", con_info.psm);
576 l2cu_reject_credit_based_conn_req(p_lcb, id, num_of_channels,
577 L2CAP_LE_RESULT_NO_PSM);
578 return;
579 }
580
581 if (p_lcb->pending_ecoc_conn_cnt > 0) {
582 LOG_WARN("L2CAP - L2CAP_CMD_CREDIT_BASED_CONN_REQ collision:");
583 if (p_rcb->api.pL2CA_CreditBasedCollisionInd_Cb &&
584 con_info.psm == BT_PSM_EATT) {
585 (*p_rcb->api.pL2CA_CreditBasedCollisionInd_Cb)(p_lcb->remote_bd_addr);
586 }
587 l2cu_reject_credit_based_conn_req(p_lcb, id, num_of_channels,
588 L2CAP_LE_RESULT_NO_RESOURCES);
589 return;
590 }
591
592 p_lcb->pending_ecoc_conn_cnt = num_of_channels;
593
594 if (!p_rcb->api.pL2CA_CreditBasedConnectInd_Cb) {
595 LOG_WARN("L2CAP - rcvd conn req for outgoing-only connection PSM: %d",
596 con_info.psm);
597 l2cu_reject_credit_based_conn_req(p_lcb, id, num_of_channels,
598 L2CAP_CONN_NO_PSM);
599 return;
600 }
601
602 /* validate the parameters */
603 if (mtu < L2CAP_CREDIT_BASED_MIN_MTU ||
604 mps < L2CAP_CREDIT_BASED_MIN_MPS || mps > L2CAP_LE_MAX_MPS) {
605 LOG_ERROR("L2CAP don't like the params");
606 l2cu_reject_credit_based_conn_req(p_lcb, id, num_of_channels,
607 L2CAP_LE_RESULT_INVALID_PARAMETERS);
608 return;
609 }
610
611 bool lead_cid_set = false;
612
613 for (int i = 0; i < num_of_channels; i++) {
614 STREAM_TO_UINT16(rcid, p);
615 temp_p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, rcid);
616 if (temp_p_ccb) {
617 LOG_WARN("L2CAP - rcvd conn req for duplicated cid: 0x%04x", rcid);
618 p_lcb->pending_ecoc_connection_cids[i] = 0;
619 p_lcb->pending_l2cap_result =
620 L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED;
621 } else {
622 /* Allocate a ccb for this.*/
623 temp_p_ccb = l2cu_allocate_ccb(p_lcb, 0);
624 if (temp_p_ccb == NULL) {
625 LOG_ERROR("L2CAP - unable to allocate CCB");
626 p_lcb->pending_ecoc_connection_cids[i] = 0;
627 p_lcb->pending_l2cap_result = L2CAP_LE_RESULT_NO_RESOURCES;
628 continue;
629 }
630
631 temp_p_ccb->ecoc = true;
632 temp_p_ccb->remote_id = id;
633 temp_p_ccb->p_rcb = p_rcb;
634 temp_p_ccb->remote_cid = rcid;
635
636 temp_p_ccb->peer_conn_cfg.mtu = mtu;
637 temp_p_ccb->peer_conn_cfg.mps = mps;
638 temp_p_ccb->peer_conn_cfg.credits = initial_credit;
639
640 temp_p_ccb->tx_mps = mps;
641 temp_p_ccb->ble_sdu = NULL;
642 temp_p_ccb->ble_sdu_length = 0;
643 temp_p_ccb->is_first_seg = true;
644 temp_p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
645
646 /* This list will be used to prepare response */
647 p_lcb->pending_ecoc_connection_cids[i] = temp_p_ccb->local_cid;
648
649 /*This is going to be our lead p_ccb for state machine */
650 if (!lead_cid_set) {
651 p_ccb = temp_p_ccb;
652 p_ccb->local_conn_cfg.mtu = L2CAP_SDU_LENGTH_LE_MAX;
653 p_ccb->local_conn_cfg.mps =
654 controller_get_interface()->get_acl_data_size_ble();
655 p_lcb->pending_lead_cid = p_ccb->local_cid;
656 lead_cid_set = true;
657 }
658 }
659 }
660
661 if (!lead_cid_set) {
662 LOG_ERROR("L2CAP - unable to allocate CCB");
663 l2cu_reject_credit_based_conn_req(p_lcb, id, num_of_channels,
664 p_lcb->pending_l2cap_result);
665 return;
666 }
667
668 LOG_DEBUG("L2CAP - processing peer credit based connect request");
669 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CREDIT_BASED_CONNECT_REQ, NULL);
670 break;
671 }
672 case L2CAP_CMD_CREDIT_BASED_CONN_RES:
673 if (p + 2 > p_pkt_end) {
674 LOG(ERROR) << "invalid L2CAP_CMD_CREDIT_BASED_CONN_RES len";
675 return;
676 }
677
678 L2CAP_TRACE_DEBUG("Recv L2CAP_CMD_CREDIT_BASED_CONN_RES");
679 /* For all channels, see whose identifier matches this id */
680 for (temp_p_ccb = p_lcb->ccb_queue.p_first_ccb; temp_p_ccb;
681 temp_p_ccb = temp_p_ccb->p_next_ccb) {
682 if (temp_p_ccb->local_id == id) {
683 p_ccb = temp_p_ccb;
684 break;
685 }
686 }
687
688 if (!p_ccb) {
689 L2CAP_TRACE_DEBUG(" Cannot find matching connection req");
690 con_info.l2cap_result = L2CAP_LE_RESULT_INVALID_SOURCE_CID;
691 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
692 return;
693 }
694
695 STREAM_TO_UINT16(mtu, p);
696 STREAM_TO_UINT16(mps, p);
697 STREAM_TO_UINT16(initial_credit, p);
698 STREAM_TO_UINT16(con_info.l2cap_result, p);
699
700 /* When one of these result is sent back that means,
701 * all the channels has been rejected
702 */
703 if (con_info.l2cap_result == L2CAP_LE_RESULT_NO_PSM ||
704 con_info.l2cap_result ==
705 L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION ||
706 con_info.l2cap_result == L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP ||
707 con_info.l2cap_result == L2CAP_LE_RESULT_INSUFFICIENT_AUTHORIZATION ||
708 con_info.l2cap_result == L2CAP_LE_RESULT_UNACCEPTABLE_PARAMETERS ||
709 con_info.l2cap_result == L2CAP_LE_RESULT_INVALID_PARAMETERS) {
710 L2CAP_TRACE_ERROR("L2CAP - not accepted. Status %d",
711 con_info.l2cap_result);
712 l2cble_handle_connect_rsp_neg(p_lcb, &con_info);
713 return;
714 }
715
716 /* validate the parameters */
717 if (mtu < L2CAP_CREDIT_BASED_MIN_MTU ||
718 mps < L2CAP_CREDIT_BASED_MIN_MPS || mps > L2CAP_LE_MAX_MPS) {
719 L2CAP_TRACE_ERROR("L2CAP - invalid params");
720 con_info.l2cap_result = L2CAP_LE_RESULT_INVALID_PARAMETERS;
721 l2cble_handle_connect_rsp_neg(p_lcb, &con_info);
722 return;
723 }
724
725 /* At least some of the channels has been created and parameters are
726 * good*/
727 num_of_channels = (p_pkt_end - p) / sizeof(uint16_t);
728 if (num_of_channels != p_lcb->pending_ecoc_conn_cnt) {
729 L2CAP_TRACE_ERROR(
730 "Incorrect response."
731 "expected num of channels = %d",
732 "received num of channels = %d", num_of_channels,
733 p_lcb->pending_ecoc_conn_cnt);
734 return;
735 }
736
737 L2CAP_TRACE_DEBUG(
738 "mtu = %d, "
739 "mps = %d, "
740 "initial_credit = %d, "
741 "con_info.l2cap_result = %d"
742 "num_of_channels = %d",
743 mtu, mps, initial_credit, con_info.l2cap_result, num_of_channels);
744
745 con_info.peer_mtu = mtu;
746
747 /* Copy request data and clear it so user can perform another connect if
748 * needed in the callback. */
749 p_lcb->pending_ecoc_conn_cnt = 0;
750 uint16_t cids[L2CAP_CREDIT_BASED_MAX_CIDS];
751 std::copy_n(p_lcb->pending_ecoc_connection_cids,
752 L2CAP_CREDIT_BASED_MAX_CIDS, cids);
753 std::fill_n(p_lcb->pending_ecoc_connection_cids,
754 L2CAP_CREDIT_BASED_MAX_CIDS, 0);
755
756 for (int i = 0; i < num_of_channels; i++) {
757 uint16_t cid = cids[i];
758 STREAM_TO_UINT16(rcid, p);
759
760 if (rcid != 0) {
761 /* If remote cid is duplicated then disconnect original channel
762 * and current channel by sending event to upper layer
763 */
764 temp_p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, rcid);
765 if (temp_p_ccb != nullptr) {
766 L2CAP_TRACE_ERROR(
767 "Already Allocated Destination cid. "
768 "rcid = %d "
769 "send peer_disc_req",
770 rcid);
771
772 l2cu_send_peer_disc_req(temp_p_ccb);
773
774 temp_p_ccb = l2cu_find_ccb_by_cid(p_lcb, cid);
775 con_info.l2cap_result = L2CAP_LE_RESULT_UNACCEPTABLE_PARAMETERS;
776 l2c_csm_execute(temp_p_ccb,
777 L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP_NEG,
778 &con_info);
779 continue;
780 }
781 }
782
783 temp_p_ccb = l2cu_find_ccb_by_cid(p_lcb, cid);
784 temp_p_ccb->remote_cid = rcid;
785
786 L2CAP_TRACE_DEBUG(
787 "local cid = %d "
788 "remote cid = %d",
789 cid, temp_p_ccb->remote_cid);
790
791 /* Check if peer accepted channel, if not release the one not
792 * created
793 */
794 if (temp_p_ccb->remote_cid == 0) {
795 l2c_csm_execute(temp_p_ccb, L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP_NEG,
796 &con_info);
797 } else {
798 temp_p_ccb->tx_mps = mps;
799 temp_p_ccb->ble_sdu = NULL;
800 temp_p_ccb->ble_sdu_length = 0;
801 temp_p_ccb->is_first_seg = true;
802 temp_p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
803 temp_p_ccb->peer_conn_cfg.mtu = mtu;
804 temp_p_ccb->peer_conn_cfg.mps = mps;
805 temp_p_ccb->peer_conn_cfg.credits = initial_credit;
806
807 l2c_csm_execute(temp_p_ccb, L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP,
808 &con_info);
809 }
810 }
811
812 break;
813 case L2CAP_CMD_CREDIT_BASED_RECONFIG_REQ: {
814 if (p + 6 > p_pkt_end) {
815 l2cu_send_ble_reconfig_rsp(p_lcb, id, L2CAP_RECONFIG_UNACCAPTED_PARAM);
816 return;
817 }
818
819 STREAM_TO_UINT16(mtu, p);
820 STREAM_TO_UINT16(mps, p);
821
822 /* validate the parameters */
823 if (mtu < L2CAP_CREDIT_BASED_MIN_MTU ||
824 mps < L2CAP_CREDIT_BASED_MIN_MPS || mps > L2CAP_LE_MAX_MPS) {
825 L2CAP_TRACE_ERROR("L2CAP - invalid params");
826 l2cu_send_ble_reconfig_rsp(p_lcb, id, L2CAP_RECONFIG_UNACCAPTED_PARAM);
827 return;
828 }
829
830 /* Check how many channels remote side wants to reconfigure */
831 num_of_channels = (p_pkt_end - p) / sizeof(uint16_t);
832
833 L2CAP_TRACE_DEBUG(
834 "Recv L2CAP_CMD_CREDIT_BASED_RECONFIG_REQ with "
835 "mtu = %d, "
836 "mps = %d, "
837 "num_of_channels = %d",
838 mtu, mps, num_of_channels);
839
840 uint8_t* p_tmp = p;
841 for (int i = 0; i < num_of_channels; i++) {
842 STREAM_TO_UINT16(rcid, p_tmp);
843 p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, rcid);
844 if (!p_ccb) {
845 L2CAP_TRACE_WARNING(
846 "L2CAP - rcvd config req for non existing cid: 0x%04x", rcid);
847 l2cu_send_ble_reconfig_rsp(p_lcb, id, L2CAP_RECONFIG_INVALID_DCID);
848 return;
849 }
850
851 if (p_ccb->peer_conn_cfg.mtu > mtu) {
852 L2CAP_TRACE_WARNING(
853 "L2CAP - rcvd config req mtu reduction new mtu < mtu (%d < %d)",
854 mtu, p_ccb->peer_conn_cfg.mtu);
855 l2cu_send_ble_reconfig_rsp(p_lcb, id,
856 L2CAP_RECONFIG_REDUCTION_MTU_NO_ALLOWED);
857 return;
858 }
859
860 if (p_ccb->peer_conn_cfg.mps > mps && num_of_channels > 1) {
861 L2CAP_TRACE_WARNING(
862 "L2CAP - rcvd config req mps reduction new mps < mps (%d < %d)",
863 mtu, p_ccb->peer_conn_cfg.mtu);
864 l2cu_send_ble_reconfig_rsp(p_lcb, id,
865 L2CAP_RECONFIG_REDUCTION_MPS_NO_ALLOWED);
866 return;
867 }
868 }
869
870 for (int i = 0; i < num_of_channels; i++) {
871 STREAM_TO_UINT16(rcid, p);
872
873 /* Store new values */
874 p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, rcid);
875 p_ccb->peer_conn_cfg.mtu = mtu;
876 p_ccb->peer_conn_cfg.mps = mps;
877 p_ccb->tx_mps = mps;
878
879 tL2CAP_LE_CFG_INFO le_cfg;
880 le_cfg.mps = mps;
881 le_cfg.mtu = mtu;
882
883 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CREDIT_BASED_RECONFIG_REQ, &le_cfg);
884 }
885
886 l2cu_send_ble_reconfig_rsp(p_lcb, id, L2CAP_RECONFIG_SUCCEED);
887
888 break;
889 }
890
891 case L2CAP_CMD_CREDIT_BASED_RECONFIG_RES: {
892 uint16_t result;
893 if (p + sizeof(uint16_t) > p_pkt_end) {
894 LOG(ERROR) << "invalid read";
895 return;
896 }
897 STREAM_TO_UINT16(result, p);
898
899 L2CAP_TRACE_DEBUG(
900 "Recv L2CAP_CMD_CREDIT_BASED_RECONFIG_RES for "
901 "result = 0x%04x",
902 result);
903
904 p_lcb->pending_ecoc_reconfig_cfg.result = result;
905
906 /* All channels which are in reconfiguration state are marked with
907 * reconfig_started flag. Find it and send response
908 */
909 for (temp_p_ccb = p_lcb->ccb_queue.p_first_ccb; temp_p_ccb;
910 temp_p_ccb = temp_p_ccb->p_next_ccb) {
911 if ((temp_p_ccb->in_use) && (temp_p_ccb->reconfig_started)) {
912 l2c_csm_execute(temp_p_ccb, L2CEVT_L2CAP_CREDIT_BASED_RECONFIG_RSP,
913 &p_lcb->pending_ecoc_reconfig_cfg);
914
915 temp_p_ccb->reconfig_started = false;
916 if (result == L2CAP_CFG_OK) {
917 temp_p_ccb->local_conn_cfg = p_lcb->pending_ecoc_reconfig_cfg;
918 }
919 }
920 }
921
922 break;
923 }
924
925 case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ:
926 if (p + 10 > p_pkt_end) {
927 LOG(ERROR) << "invalid read";
928 return;
929 }
930
931 STREAM_TO_UINT16(con_info.psm, p);
932 STREAM_TO_UINT16(rcid, p);
933 STREAM_TO_UINT16(mtu, p);
934 STREAM_TO_UINT16(mps, p);
935 STREAM_TO_UINT16(initial_credit, p);
936
937 L2CAP_TRACE_DEBUG(
938 "Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ with "
939 "mtu = %d, "
940 "mps = %d, "
941 "initial credit = %d",
942 mtu, mps, initial_credit);
943
944 p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, rcid);
945 if (p_ccb) {
946 L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for duplicated cid: 0x%04x",
947 rcid);
948 l2cu_reject_ble_coc_connection(
949 p_lcb, id, L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED);
950 break;
951 }
952
953 p_rcb = l2cu_find_ble_rcb_by_psm(con_info.psm);
954 if (p_rcb == NULL) {
955 L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for unknown PSM: 0x%04x",
956 con_info.psm);
957 l2cu_reject_ble_coc_connection(p_lcb, id, L2CAP_LE_RESULT_NO_PSM);
958 break;
959 } else {
960 if (!p_rcb->api.pL2CA_ConnectInd_Cb) {
961 L2CAP_TRACE_WARNING(
962 "L2CAP - rcvd conn req for outgoing-only connection PSM: %d",
963 con_info.psm);
964 l2cu_reject_ble_coc_connection(p_lcb, id, L2CAP_CONN_NO_PSM);
965 break;
966 }
967 }
968
969 /* Allocate a ccb for this.*/
970 p_ccb = l2cu_allocate_ccb(p_lcb, 0);
971 if (p_ccb == NULL) {
972 L2CAP_TRACE_ERROR("L2CAP - unable to allocate CCB");
973 l2cu_reject_ble_connection(p_ccb, id, L2CAP_CONN_NO_RESOURCES);
974 break;
975 }
976
977 /* validate the parameters */
978 if (mtu < L2CAP_LE_MIN_MTU || mps < L2CAP_LE_MIN_MPS ||
979 mps > L2CAP_LE_MAX_MPS) {
980 L2CAP_TRACE_ERROR("L2CAP do not like the params");
981 l2cu_reject_ble_connection(p_ccb, id, L2CAP_CONN_NO_RESOURCES);
982 break;
983 }
984
985 p_ccb->remote_id = id;
986 p_ccb->p_rcb = p_rcb;
987 p_ccb->remote_cid = rcid;
988
989 p_ccb->local_conn_cfg.mtu = L2CAP_SDU_LENGTH_LE_MAX;
990 p_ccb->local_conn_cfg.mps =
991 controller_get_interface()->get_acl_data_size_ble();
992 p_ccb->local_conn_cfg.credits = L2CA_LeCreditDefault();
993 p_ccb->remote_credit_count = L2CA_LeCreditDefault();
994
995 p_ccb->peer_conn_cfg.mtu = mtu;
996 p_ccb->peer_conn_cfg.mps = mps;
997 p_ccb->peer_conn_cfg.credits = initial_credit;
998
999 p_ccb->tx_mps = mps;
1000 p_ccb->ble_sdu = NULL;
1001 p_ccb->ble_sdu_length = 0;
1002 p_ccb->is_first_seg = true;
1003 p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
1004
1005 p_ccb->connection_initiator = L2CAP_INITIATOR_REMOTE;
1006
1007 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info);
1008 break;
1009
1010 case L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES:
1011 L2CAP_TRACE_DEBUG("Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES");
1012 /* For all channels, see whose identifier matches this id */
1013 for (temp_p_ccb = p_lcb->ccb_queue.p_first_ccb; temp_p_ccb;
1014 temp_p_ccb = temp_p_ccb->p_next_ccb) {
1015 if (temp_p_ccb->local_id == id) {
1016 p_ccb = temp_p_ccb;
1017 break;
1018 }
1019 }
1020 if (p_ccb) {
1021 L2CAP_TRACE_DEBUG("I remember the connection req");
1022 if (p + 10 > p_pkt_end) {
1023 LOG(ERROR) << "invalid read";
1024 return;
1025 }
1026
1027 STREAM_TO_UINT16(p_ccb->remote_cid, p);
1028 STREAM_TO_UINT16(p_ccb->peer_conn_cfg.mtu, p);
1029 STREAM_TO_UINT16(p_ccb->peer_conn_cfg.mps, p);
1030 STREAM_TO_UINT16(p_ccb->peer_conn_cfg.credits, p);
1031 STREAM_TO_UINT16(con_info.l2cap_result, p);
1032 con_info.remote_cid = p_ccb->remote_cid;
1033
1034 L2CAP_TRACE_DEBUG(
1035 "remote_cid = %d, "
1036 "mtu = %d, "
1037 "mps = %d, "
1038 "initial_credit = %d, "
1039 "con_info.l2cap_result = %d",
1040 p_ccb->remote_cid, p_ccb->peer_conn_cfg.mtu,
1041 p_ccb->peer_conn_cfg.mps, p_ccb->peer_conn_cfg.credits,
1042 con_info.l2cap_result);
1043
1044 /* validate the parameters */
1045 if (p_ccb->peer_conn_cfg.mtu < L2CAP_LE_MIN_MTU ||
1046 p_ccb->peer_conn_cfg.mps < L2CAP_LE_MIN_MPS ||
1047 p_ccb->peer_conn_cfg.mps > L2CAP_LE_MAX_MPS) {
1048 L2CAP_TRACE_ERROR("L2CAP do not like the params");
1049 con_info.l2cap_result = L2CAP_LE_RESULT_NO_RESOURCES;
1050 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
1051 break;
1052 }
1053
1054 p_ccb->tx_mps = p_ccb->peer_conn_cfg.mps;
1055 p_ccb->ble_sdu = NULL;
1056 p_ccb->ble_sdu_length = 0;
1057 p_ccb->is_first_seg = true;
1058 p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
1059
1060 if (con_info.l2cap_result == L2CAP_LE_RESULT_CONN_OK)
1061 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP, &con_info);
1062 else
1063 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
1064 } else {
1065 L2CAP_TRACE_DEBUG("I DO NOT remember the connection req");
1066 con_info.l2cap_result = L2CAP_LE_RESULT_INVALID_SOURCE_CID;
1067 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
1068 }
1069 break;
1070
1071 case L2CAP_CMD_BLE_FLOW_CTRL_CREDIT:
1072 if (p + 4 > p_pkt_end) {
1073 LOG(ERROR) << "invalid read";
1074 return;
1075 }
1076
1077 STREAM_TO_UINT16(lcid, p);
1078 p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, lcid);
1079 if (p_ccb == NULL) {
1080 L2CAP_TRACE_DEBUG("%s Credit received for unknown channel id %d",
1081 __func__, lcid);
1082 break;
1083 }
1084
1085 STREAM_TO_UINT16(credit, p);
1086 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT, &credit);
1087 L2CAP_TRACE_DEBUG("%s Credit received", __func__);
1088 break;
1089
1090 case L2CAP_CMD_DISC_REQ:
1091 if (p + 4 > p_pkt_end) {
1092 return;
1093 }
1094 STREAM_TO_UINT16(lcid, p);
1095 STREAM_TO_UINT16(rcid, p);
1096
1097 p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
1098 if (p_ccb != NULL) {
1099 if (p_ccb->remote_cid == rcid) {
1100 p_ccb->remote_id = id;
1101 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_REQ, NULL);
1102 }
1103 } else
1104 l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_INVALID_CID, id, 0, 0);
1105
1106 break;
1107
1108 case L2CAP_CMD_DISC_RSP:
1109 if (p + 4 > p_pkt_end) {
1110 LOG(ERROR) << "invalid read";
1111 return;
1112 }
1113 STREAM_TO_UINT16(rcid, p);
1114 STREAM_TO_UINT16(lcid, p);
1115
1116 p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
1117 if (p_ccb != NULL) {
1118 if ((p_ccb->remote_cid == rcid) && (p_ccb->local_id == id))
1119 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_RSP, NULL);
1120 }
1121 break;
1122
1123 default:
1124 L2CAP_TRACE_WARNING("L2CAP - LE - unknown cmd code: %d", cmd_code);
1125 l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
1126 break;
1127 }
1128 }
1129
1130 /** This function is to initate a direct connection. Returns true if connection
1131 * initiated, false otherwise. */
l2cble_create_conn(tL2C_LCB * p_lcb)1132 bool l2cble_create_conn(tL2C_LCB* p_lcb) {
1133 if (!acl_create_le_connection(p_lcb->remote_bd_addr)) {
1134 return false;
1135 }
1136
1137 p_lcb->link_state = LST_CONNECTING;
1138
1139 // TODO: we should not need this timer at all, the connection failure should
1140 // be reported from lower layer
1141 alarm_set_on_mloop(p_lcb->l2c_lcb_timer, L2CAP_BLE_LINK_CONNECT_TIMEOUT_MS,
1142 l2c_lcb_timer_timeout, p_lcb);
1143 return true;
1144 }
1145
1146 /*******************************************************************************
1147 *
1148 * Function l2c_link_processs_ble_num_bufs
1149 *
1150 * Description This function is called when a "controller buffer size"
1151 * event is first received from the controller. It updates
1152 * the L2CAP values.
1153 *
1154 * Returns void
1155 *
1156 ******************************************************************************/
l2c_link_processs_ble_num_bufs(uint16_t num_lm_ble_bufs)1157 void l2c_link_processs_ble_num_bufs(uint16_t num_lm_ble_bufs) {
1158 if (bluetooth::shim::is_gd_l2cap_enabled()) {
1159 return;
1160 }
1161
1162 if (num_lm_ble_bufs == 0) {
1163 num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED;
1164 l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED;
1165 }
1166
1167 l2cb.num_lm_ble_bufs = num_lm_ble_bufs;
1168 l2cb.controller_le_xmit_window = num_lm_ble_bufs;
1169 }
1170
1171 /*******************************************************************************
1172 *
1173 * Function l2c_ble_link_adjust_allocation
1174 *
1175 * Description This function is called when a link is created or removed
1176 * to calculate the amount of packets each link may send to
1177 * the HCI without an ack coming back.
1178 *
1179 * Currently, this is a simple allocation, dividing the
1180 * number of Controller Packets by the number of links. In
1181 * the future, QOS configuration should be examined.
1182 *
1183 * Returns void
1184 *
1185 ******************************************************************************/
l2c_ble_link_adjust_allocation(void)1186 void l2c_ble_link_adjust_allocation(void) {
1187 uint16_t qq, yy, qq_remainder;
1188 tL2C_LCB* p_lcb;
1189 uint16_t hi_quota, low_quota;
1190 uint16_t num_lowpri_links = 0;
1191 uint16_t num_hipri_links = 0;
1192 uint16_t controller_xmit_quota = l2cb.num_lm_ble_bufs;
1193 uint16_t high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
1194
1195 /* If no links active, reset buffer quotas and controller buffers */
1196 if (l2cb.num_ble_links_active == 0) {
1197 l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
1198 l2cb.ble_round_robin_quota = l2cb.ble_round_robin_unacked = 0;
1199 return;
1200 }
1201
1202 /* First, count the links */
1203 for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) {
1204 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) {
1205 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)
1206 num_hipri_links++;
1207 else
1208 num_lowpri_links++;
1209 }
1210 }
1211
1212 /* now adjust high priority link quota */
1213 low_quota = num_lowpri_links ? 1 : 0;
1214 while ((num_hipri_links * high_pri_link_quota + low_quota) >
1215 controller_xmit_quota)
1216 high_pri_link_quota--;
1217
1218 /* Work out the xmit quota and buffer quota high and low priorities */
1219 hi_quota = num_hipri_links * high_pri_link_quota;
1220 low_quota =
1221 (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1;
1222
1223 /* Work out and save the HCI xmit quota for each low priority link */
1224
1225 /* If each low priority link cannot have at least one buffer */
1226 if (num_lowpri_links > low_quota) {
1227 l2cb.ble_round_robin_quota = low_quota;
1228 qq = qq_remainder = 0;
1229 }
1230 /* If each low priority link can have at least one buffer */
1231 else if (num_lowpri_links > 0) {
1232 l2cb.ble_round_robin_quota = 0;
1233 l2cb.ble_round_robin_unacked = 0;
1234 qq = low_quota / num_lowpri_links;
1235 qq_remainder = low_quota % num_lowpri_links;
1236 }
1237 /* If no low priority link */
1238 else {
1239 l2cb.ble_round_robin_quota = 0;
1240 l2cb.ble_round_robin_unacked = 0;
1241 qq = qq_remainder = 0;
1242 }
1243 L2CAP_TRACE_EVENT(
1244 "l2c_ble_link_adjust_allocation num_hipri: %u num_lowpri: %u "
1245 "low_quota: %u round_robin_quota: %u qq: %u",
1246 num_hipri_links, num_lowpri_links, low_quota, l2cb.ble_round_robin_quota,
1247 qq);
1248
1249 /* Now, assign the quotas to each link */
1250 for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) {
1251 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) {
1252 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) {
1253 p_lcb->link_xmit_quota = high_pri_link_quota;
1254 } else {
1255 /* Safety check in case we switched to round-robin with something
1256 * outstanding */
1257 /* if sent_not_acked is added into round_robin_unacked then do not add
1258 * it again */
1259 /* l2cap keeps updating sent_not_acked for exiting from round robin */
1260 if ((p_lcb->link_xmit_quota > 0) && (qq == 0))
1261 l2cb.ble_round_robin_unacked += p_lcb->sent_not_acked;
1262
1263 p_lcb->link_xmit_quota = qq;
1264 if (qq_remainder > 0) {
1265 p_lcb->link_xmit_quota++;
1266 qq_remainder--;
1267 }
1268 }
1269
1270 L2CAP_TRACE_EVENT(
1271 "l2c_ble_link_adjust_allocation LCB %d Priority: %d XmitQuota: %d",
1272 yy, p_lcb->acl_priority, p_lcb->link_xmit_quota);
1273
1274 L2CAP_TRACE_EVENT(" SentNotAcked: %d RRUnacked: %d",
1275 p_lcb->sent_not_acked, l2cb.round_robin_unacked);
1276
1277 /* There is a special case where we have readjusted the link quotas and */
1278 /* this link may have sent anything but some other link sent packets so */
1279 /* so we may need a timer to kick off this link's transmissions. */
1280 if ((p_lcb->link_state == LST_CONNECTED) &&
1281 (!list_is_empty(p_lcb->link_xmit_data_q)) &&
1282 (p_lcb->sent_not_acked < p_lcb->link_xmit_quota)) {
1283 alarm_set_on_mloop(p_lcb->l2c_lcb_timer,
1284 L2CAP_LINK_FLOW_CONTROL_TIMEOUT_MS,
1285 l2c_lcb_timer_timeout, p_lcb);
1286 }
1287 }
1288 }
1289 }
1290
1291 /*******************************************************************************
1292 *
1293 * Function l2cble_process_rc_param_request_evt
1294 *
1295 * Description process LE Remote Connection Parameter Request Event.
1296 *
1297 * Returns void
1298 *
1299 ******************************************************************************/
l2cble_process_rc_param_request_evt(uint16_t handle,uint16_t int_min,uint16_t int_max,uint16_t latency,uint16_t timeout)1300 void l2cble_process_rc_param_request_evt(uint16_t handle, uint16_t int_min,
1301 uint16_t int_max, uint16_t latency,
1302 uint16_t timeout) {
1303 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
1304
1305 if (p_lcb != NULL) {
1306 p_lcb->min_interval = int_min;
1307 p_lcb->max_interval = int_max;
1308 p_lcb->latency = latency;
1309 p_lcb->timeout = timeout;
1310
1311 /* if update is enabled, always accept connection parameter update */
1312 if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0) {
1313 btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency,
1314 timeout, 0, 0);
1315 } else {
1316 L2CAP_TRACE_EVENT("L2CAP - LE - update currently disabled");
1317 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
1318 btsnd_hcic_ble_rc_param_req_neg_reply(handle,
1319 HCI_ERR_UNACCEPT_CONN_INTERVAL);
1320 }
1321
1322 } else {
1323 L2CAP_TRACE_WARNING("No link to update connection parameter")
1324 }
1325 }
1326
1327 /*******************************************************************************
1328 *
1329 * Function l2cble_update_data_length
1330 *
1331 * Description This function update link tx data length if applicable
1332 *
1333 * Returns void
1334 *
1335 ******************************************************************************/
l2cble_update_data_length(tL2C_LCB * p_lcb)1336 void l2cble_update_data_length(tL2C_LCB* p_lcb) {
1337 uint16_t tx_mtu = 0;
1338 uint16_t i = 0;
1339
1340 L2CAP_TRACE_DEBUG("%s", __func__);
1341
1342 /* See if we have a link control block for the connection */
1343 if (p_lcb == NULL) return;
1344
1345 for (i = 0; i < L2CAP_NUM_FIXED_CHNLS; i++) {
1346 if (i + L2CAP_FIRST_FIXED_CHNL != L2CAP_BLE_SIGNALLING_CID) {
1347 if ((p_lcb->p_fixed_ccbs[i] != NULL) &&
1348 (tx_mtu < (p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD)))
1349 tx_mtu = p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD;
1350 }
1351 }
1352
1353 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX) tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1354
1355 /* update TX data length if changed */
1356 if (p_lcb->tx_data_len != tx_mtu)
1357 BTM_SetBleDataLength(p_lcb->remote_bd_addr, tx_mtu);
1358 }
1359
1360 /*******************************************************************************
1361 *
1362 * Function l2cble_process_data_length_change_evt
1363 *
1364 * Description This function process the data length change event
1365 *
1366 * Returns void
1367 *
1368 ******************************************************************************/
is_legal_tx_data_len(const uint16_t & tx_data_len)1369 static bool is_legal_tx_data_len(const uint16_t& tx_data_len) {
1370 return (tx_data_len >= 0x001B && tx_data_len <= 0x00FB);
1371 }
1372
l2cble_process_data_length_change_event(uint16_t handle,uint16_t tx_data_len,uint16_t rx_data_len)1373 void l2cble_process_data_length_change_event(uint16_t handle,
1374 uint16_t tx_data_len,
1375 uint16_t rx_data_len) {
1376 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
1377 if (p_lcb == nullptr) {
1378 LOG_WARN("Received data length change event for unknown ACL handle:0x%04x",
1379 handle);
1380 return;
1381 }
1382
1383 if (is_legal_tx_data_len(tx_data_len)) {
1384 LOG_DEBUG("Received data length change event for device:%s tx_data_len:%hu",
1385 PRIVATE_ADDRESS(p_lcb->remote_bd_addr), tx_data_len);
1386 p_lcb->tx_data_len = tx_data_len;
1387 BTM_LogHistory(kBtmLogTag, p_lcb->remote_bd_addr, "LE Data length change",
1388 base::StringPrintf("tx_octets:%hu", tx_data_len));
1389 } else {
1390 LOG_WARN(
1391 "Received illegal data length change event for device:%s "
1392 "tx_data_len:%hu",
1393 PRIVATE_ADDRESS(p_lcb->remote_bd_addr), tx_data_len);
1394 }
1395 /* ignore rx_data len for now */
1396 }
1397
1398 /*******************************************************************************
1399 *
1400 * Function l2cble_credit_based_conn_req
1401 *
1402 * Description This function sends LE Credit Based Connection Request for
1403 * LE connection oriented channels.
1404 *
1405 * Returns void
1406 *
1407 ******************************************************************************/
l2cble_credit_based_conn_req(tL2C_CCB * p_ccb)1408 void l2cble_credit_based_conn_req(tL2C_CCB* p_ccb) {
1409 if (!p_ccb) return;
1410
1411 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1412 L2CAP_TRACE_WARNING("LE link doesn't exist");
1413 return;
1414 }
1415
1416 if (p_ccb->ecoc) {
1417 l2cu_send_peer_credit_based_conn_req(p_ccb);
1418 } else {
1419 l2cu_send_peer_ble_credit_based_conn_req(p_ccb);
1420 }
1421 return;
1422 }
1423
1424 /*******************************************************************************
1425 *
1426 * Function l2cble_credit_based_conn_res
1427 *
1428 * Description This function sends LE Credit Based Connection Response for
1429 * LE connection oriented channels.
1430 *
1431 * Returns void
1432 *
1433 ******************************************************************************/
l2cble_credit_based_conn_res(tL2C_CCB * p_ccb,uint16_t result)1434 void l2cble_credit_based_conn_res(tL2C_CCB* p_ccb, uint16_t result) {
1435 if (!p_ccb) return;
1436
1437 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1438 L2CAP_TRACE_WARNING("LE link doesn't exist");
1439 return;
1440 }
1441
1442 l2cu_send_peer_ble_credit_based_conn_res(p_ccb, result);
1443 return;
1444 }
1445
1446 /*******************************************************************************
1447 *
1448 * Function l2cble_send_flow_control_credit
1449 *
1450 * Description This function sends flow control credits for
1451 * LE connection oriented channels.
1452 *
1453 * Returns void
1454 *
1455 ******************************************************************************/
l2cble_send_flow_control_credit(tL2C_CCB * p_ccb,uint16_t credit_value)1456 void l2cble_send_flow_control_credit(tL2C_CCB* p_ccb, uint16_t credit_value) {
1457 if (!p_ccb) return;
1458
1459 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1460 L2CAP_TRACE_WARNING("LE link doesn't exist");
1461 return;
1462 }
1463
1464 l2cu_send_peer_ble_flow_control_credit(p_ccb, credit_value);
1465 return;
1466 }
1467
1468 /*******************************************************************************
1469 *
1470 * Function l2cble_send_peer_disc_req
1471 *
1472 * Description This function sends disconnect request
1473 * to the peer LE device
1474 *
1475 * Returns void
1476 *
1477 ******************************************************************************/
l2cble_send_peer_disc_req(tL2C_CCB * p_ccb)1478 void l2cble_send_peer_disc_req(tL2C_CCB* p_ccb) {
1479 L2CAP_TRACE_DEBUG("%s", __func__);
1480 if (!p_ccb) return;
1481
1482 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1483 L2CAP_TRACE_WARNING("LE link doesn't exist");
1484 return;
1485 }
1486
1487 l2cu_send_peer_ble_credit_based_disconn_req(p_ccb);
1488 return;
1489 }
1490
1491 /*******************************************************************************
1492 *
1493 * Function l2cble_sec_comp
1494 *
1495 * Description This function is called when security procedure for an LE
1496 * COC link is done
1497 *
1498 * Returns void
1499 *
1500 ******************************************************************************/
l2cble_sec_comp(const RawAddress * bda,tBT_TRANSPORT transport,void * p_ref_data,tBTM_STATUS status)1501 void l2cble_sec_comp(const RawAddress* bda, tBT_TRANSPORT transport,
1502 void* p_ref_data, tBTM_STATUS status) {
1503 const RawAddress& p_bda = *bda;
1504 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, BT_TRANSPORT_LE);
1505 tL2CAP_SEC_DATA* p_buf = NULL;
1506 uint8_t sec_act;
1507
1508 if (!p_lcb) {
1509 L2CAP_TRACE_WARNING("%s: security complete for unknown device. bda=%s",
1510 __func__, bda->ToString().c_str());
1511 return;
1512 }
1513
1514 sec_act = p_lcb->sec_act;
1515 p_lcb->sec_act = 0;
1516
1517 if (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) {
1518 p_buf = (tL2CAP_SEC_DATA*)fixed_queue_dequeue(p_lcb->le_sec_pending_q);
1519 if (!p_buf) {
1520 L2CAP_TRACE_WARNING(
1521 "%s Security complete for request not initiated from L2CAP",
1522 __func__);
1523 return;
1524 }
1525
1526 if (status != BTM_SUCCESS) {
1527 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1528 osi_free(p_buf);
1529 } else {
1530 if (sec_act == BTM_SEC_ENCRYPT_MITM) {
1531 if (BTM_IsLinkKeyAuthed(p_bda, transport))
1532 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
1533 status);
1534 else {
1535 L2CAP_TRACE_DEBUG("%s MITM Protection Not present", __func__);
1536 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
1537 BTM_FAILED_ON_SECURITY);
1538 }
1539 } else {
1540 L2CAP_TRACE_DEBUG("%s MITM Protection not required sec_act = %d",
1541 __func__, p_lcb->sec_act);
1542
1543 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
1544 status);
1545 }
1546 osi_free(p_buf);
1547 }
1548 } else {
1549 L2CAP_TRACE_WARNING(
1550 "%s Security complete for request not initiated from L2CAP", __func__);
1551 return;
1552 }
1553
1554 while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) {
1555 p_buf = (tL2CAP_SEC_DATA*)fixed_queue_dequeue(p_lcb->le_sec_pending_q);
1556
1557 if (status != BTM_SUCCESS) {
1558 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1559 osi_free(p_buf);
1560 }
1561 else {
1562 l2ble_sec_access_req(p_bda, p_buf->psm, p_buf->is_originator,
1563 p_buf->p_callback, p_buf->p_ref_data);
1564
1565 osi_free(p_buf);
1566 break;
1567 }
1568 }
1569 }
1570
1571 /*******************************************************************************
1572 *
1573 * Function l2ble_sec_access_req
1574 *
1575 * Description This function is called by LE COC link to meet the
1576 * security requirement for the link
1577 *
1578 * Returns Returns - L2CAP LE Connection Response Result Code.
1579 *
1580 ******************************************************************************/
l2ble_sec_access_req(const RawAddress & bd_addr,uint16_t psm,bool is_originator,tL2CAP_SEC_CBACK * p_callback,void * p_ref_data)1581 tL2CAP_LE_RESULT_CODE l2ble_sec_access_req(const RawAddress& bd_addr,
1582 uint16_t psm, bool is_originator,
1583 tL2CAP_SEC_CBACK* p_callback,
1584 void* p_ref_data) {
1585 tL2CAP_LE_RESULT_CODE result;
1586 tL2C_LCB* p_lcb = NULL;
1587
1588 if (!p_callback) {
1589 LOG_ERROR("No callback function");
1590 return L2CAP_LE_RESULT_NO_RESOURCES;
1591 }
1592
1593 p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
1594
1595 if (!p_lcb) {
1596 LOG_ERROR("Security check for unknown device");
1597 p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_UNKNOWN_ADDR);
1598 return L2CAP_LE_RESULT_NO_RESOURCES;
1599 }
1600
1601 tL2CAP_SEC_DATA* p_buf =
1602 (tL2CAP_SEC_DATA*)osi_malloc((uint16_t)sizeof(tL2CAP_SEC_DATA));
1603 if (!p_buf) {
1604 LOG_ERROR("No resources for connection");
1605 p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_NO_RESOURCES);
1606 return L2CAP_LE_RESULT_NO_RESOURCES;
1607 }
1608
1609 p_buf->psm = psm;
1610 p_buf->is_originator = is_originator;
1611 p_buf->p_callback = p_callback;
1612 p_buf->p_ref_data = p_ref_data;
1613 fixed_queue_enqueue(p_lcb->le_sec_pending_q, p_buf);
1614 result = btm_ble_start_sec_check(bd_addr, psm, is_originator,
1615 &l2cble_sec_comp, p_ref_data);
1616
1617 return result;
1618 }
1619
1620 /* This function is called to adjust the connection intervals based on various
1621 * constraints. For example, when there is at least one Hearing Aid device
1622 * bonded, the minimum interval is raised. On return, min_interval and
1623 * max_interval are updated. */
L2CA_AdjustConnectionIntervals(uint16_t * min_interval,uint16_t * max_interval,uint16_t floor_interval)1624 void L2CA_AdjustConnectionIntervals(uint16_t* min_interval,
1625 uint16_t* max_interval,
1626 uint16_t floor_interval) {
1627 uint16_t phone_min_interval = floor_interval;
1628
1629 if (HearingAid::GetDeviceCount() > 0) {
1630 // When there are bonded Hearing Aid devices, we will constrained this
1631 // minimum interval.
1632 phone_min_interval = BTM_BLE_CONN_INT_MIN_HEARINGAID;
1633 L2CAP_TRACE_DEBUG("%s: Have Hearing Aids. Min. interval is set to %d",
1634 __func__, phone_min_interval);
1635 }
1636
1637 if (*min_interval < phone_min_interval) {
1638 L2CAP_TRACE_DEBUG("%s: requested min_interval=%d too small. Set to %d",
1639 __func__, *min_interval, phone_min_interval);
1640 *min_interval = phone_min_interval;
1641 }
1642
1643 // While this could result in connection parameters that fall
1644 // outside fo the range requested, this will allow the connection
1645 // to remain established.
1646 // In other words, this is a workaround for certain peripherals.
1647 if (*max_interval < phone_min_interval) {
1648 L2CAP_TRACE_DEBUG("%s: requested max_interval=%d too small. Set to %d",
1649 __func__, *max_interval, phone_min_interval);
1650 *max_interval = phone_min_interval;
1651 }
1652 }
1653
l2cble_use_preferred_conn_params(const RawAddress & bda)1654 void l2cble_use_preferred_conn_params(const RawAddress& bda) {
1655 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE);
1656 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(bda);
1657
1658 /* If there are any preferred connection parameters, set them now */
1659 if ((p_lcb != NULL) && (p_dev_rec != NULL) &&
1660 (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN) &&
1661 (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX) &&
1662 (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN) &&
1663 (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX) &&
1664 (p_dev_rec->conn_params.peripheral_latency <= BTM_BLE_CONN_LATENCY_MAX) &&
1665 (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
1666 (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
1667 ((p_lcb->min_interval < p_dev_rec->conn_params.min_conn_int &&
1668 p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
1669 (p_lcb->min_interval > p_dev_rec->conn_params.max_conn_int) ||
1670 (p_lcb->latency > p_dev_rec->conn_params.peripheral_latency) ||
1671 (p_lcb->timeout > p_dev_rec->conn_params.supervision_tout))) {
1672 BTM_TRACE_DEBUG(
1673 "%s: HANDLE=%d min_conn_int=%d max_conn_int=%d peripheral_latency=%d "
1674 "supervision_tout=%d",
1675 __func__, p_lcb->Handle(), p_dev_rec->conn_params.min_conn_int,
1676 p_dev_rec->conn_params.max_conn_int,
1677 p_dev_rec->conn_params.peripheral_latency,
1678 p_dev_rec->conn_params.supervision_tout);
1679
1680 p_lcb->min_interval = p_dev_rec->conn_params.min_conn_int;
1681 p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int;
1682 p_lcb->timeout = p_dev_rec->conn_params.supervision_tout;
1683 p_lcb->latency = p_dev_rec->conn_params.peripheral_latency;
1684
1685 btsnd_hcic_ble_upd_ll_conn_params(
1686 p_lcb->Handle(), p_dev_rec->conn_params.min_conn_int,
1687 p_dev_rec->conn_params.max_conn_int,
1688 p_dev_rec->conn_params.peripheral_latency,
1689 p_dev_rec->conn_params.supervision_tout, 0, 0);
1690 }
1691 }
1692