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