1 /******************************************************************************
2 *
3 * Copyright 2024 The Android Open Source Project
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 connection parameter
22 *management.
23 *
24 ******************************************************************************/
25
26 #define LOG_TAG "l2c_ble_conn_params"
27
28 #include <bluetooth/log.h>
29 #include <com_android_bluetooth_flags.h>
30
31 #include "common/le_conn_params.h"
32 #include "hci/controller_interface.h"
33 #include "hci/event_checkers.h"
34 #include "hci/hci_interface.h"
35 #include "hci/hci_packets.h"
36 #include "internal_include/stack_config.h"
37 #include "main/shim/acl_api.h"
38 #include "main/shim/entry.h"
39 #include "osi/include/properties.h"
40 #include "stack/btm/btm_dev.h"
41 #include "stack/include/acl_api.h"
42 #include "stack/include/btm_ble_api_types.h"
43 #include "stack/include/btm_client_interface.h"
44 #include "stack/include/l2cap_hci_link_interface.h"
45 #include "stack/include/l2cap_interface.h"
46 #include "stack/include/main_thread.h"
47 #include "stack/l2cap/l2c_int.h"
48 #include "types/raw_address.h"
49
50 using namespace bluetooth;
51
52 void l2cble_start_conn_update(tL2C_LCB* p_lcb);
53 static void l2cble_start_subrate_change(tL2C_LCB* p_lcb);
54
55 /*******************************************************************************
56 *
57 * Function L2CA_UpdateBleConnParams
58 *
59 * Description Update BLE connection parameters.
60 *
61 * Parameters: BD Address of remote
62 *
63 * Return value: true if update started
64 *
65 ******************************************************************************/
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)66 bool L2CA_UpdateBleConnParams(const RawAddress& rem_bda, uint16_t min_int, uint16_t max_int,
67 uint16_t latency, uint16_t timeout, uint16_t min_ce_len,
68 uint16_t max_ce_len) {
69 /* See if we have a link control block for the remote device */
70 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
71
72 /* If we do not have one, create one and accept the connection. */
73 if (!p_lcb || !get_btm_client_interface().peer.BTM_IsAclConnectionUp(rem_bda, BT_TRANSPORT_LE)) {
74 log::warn("- unknown BD_ADDR {}", rem_bda);
75 return false;
76 }
77
78 if (p_lcb->transport != BT_TRANSPORT_LE) {
79 log::warn("- BD_ADDR {} not LE", rem_bda);
80 return false;
81 }
82
83 log::verbose("BD_ADDR={}, min_int={}, max_int={}, min_ce_len={}, max_ce_len={}", rem_bda, min_int,
84 max_int, min_ce_len, max_ce_len);
85
86 p_lcb->min_interval = min_int;
87 p_lcb->max_interval = max_int;
88 p_lcb->latency = latency;
89 p_lcb->timeout = timeout;
90 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
91 if (com::android::bluetooth::flags::initial_conn_params_p1()) {
92 p_lcb->conn_update_mask &= ~L2C_BLE_AGGRESSIVE_INITIAL_PARAM;
93 }
94
95 p_lcb->min_ce_len = min_ce_len;
96 p_lcb->max_ce_len = max_ce_len;
97
98 l2cble_start_conn_update(p_lcb);
99
100 return true;
101 }
102
103 static bool l2c_enable_update_ble_conn_params(tL2C_LCB* p_lcb, bool enable);
104
105 /* When called with lock=true, LE connection parameters will be locked on
106 * fastest value, and we won't accept request to change it from remote. When
107 * called with lock=false, parameters are relaxed.
108 */
L2CA_LockBleConnParamsForServiceDiscovery(const RawAddress & rem_bda,bool lock)109 void L2CA_LockBleConnParamsForServiceDiscovery(const RawAddress& rem_bda, bool lock) {
110 if (stack_config_get_interface()->get_pts_conn_updates_disabled()) {
111 return;
112 }
113
114 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
115 if (!p_lcb) {
116 log::warn("unknown address {}", rem_bda);
117 return;
118 }
119
120 if (p_lcb->transport != BT_TRANSPORT_LE) {
121 log::warn("{} not LE, link role {}", rem_bda, p_lcb->LinkRole());
122 return;
123 }
124
125 if (lock == p_lcb->conn_update_blocked_by_service_discovery) {
126 log::warn("{} service discovery already locked/unlocked conn params: {}", rem_bda, lock);
127
128 if (!lock && com::android::bluetooth::flags::initial_conn_params_p1() &&
129 (p_lcb->conn_update_mask & L2C_BLE_AGGRESSIVE_INITIAL_PARAM)) {
130 p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
131 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
132 log::info("Service discovery is skipped. Relaxing connection parameters.");
133 } else {
134 return;
135 }
136 }
137
138 p_lcb->conn_update_blocked_by_service_discovery = lock;
139
140 if (p_lcb->conn_update_blocked_by_profile_connection) {
141 log::info("{} conn params stay locked because of audio setup", rem_bda);
142 return;
143 }
144
145 log::info("{} Locking/unlocking conn params for service discovery: {}", rem_bda, lock);
146 l2c_enable_update_ble_conn_params(p_lcb, !lock);
147 }
148
149 /* When called with lock=true, LE connection parameters will be locked on
150 * fastest value, and we won't accept request to change it from remote. When
151 * called with lock=false, parameters are relaxed.
152 */
L2CA_LockBleConnParamsForProfileConnection(const RawAddress & rem_bda,bool lock)153 void L2CA_LockBleConnParamsForProfileConnection(const RawAddress& rem_bda, bool lock) {
154 if (stack_config_get_interface()->get_pts_conn_updates_disabled()) {
155 return;
156 }
157
158 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
159 if (!p_lcb) {
160 log::warn("unknown address {}", rem_bda);
161 return;
162 }
163
164 if (p_lcb->transport != BT_TRANSPORT_LE) {
165 log::warn("{} not LE, link role {}", rem_bda, p_lcb->LinkRole());
166 return;
167 }
168
169 if (lock == p_lcb->conn_update_blocked_by_profile_connection) {
170 log::info("{} audio setup already locked/unlocked conn params: {}", rem_bda, lock);
171 return;
172 }
173
174 p_lcb->conn_update_blocked_by_profile_connection = lock;
175
176 if (p_lcb->conn_update_blocked_by_service_discovery) {
177 log::info("{} conn params stay locked because of service discovery", rem_bda);
178 return;
179 }
180
181 log::info("{} Locking/unlocking conn params for audio setup: {}", rem_bda, lock);
182 l2c_enable_update_ble_conn_params(p_lcb, !lock);
183 }
184
l2c_enable_update_ble_conn_params(tL2C_LCB * p_lcb,bool enable)185 static bool l2c_enable_update_ble_conn_params(tL2C_LCB* p_lcb, bool enable) {
186 log::debug("{} enable {} current upd state 0x{:02x}", p_lcb->remote_bd_addr, enable,
187 p_lcb->conn_update_mask);
188
189 if (enable) {
190 p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
191 p_lcb->subrate_req_mask &= ~L2C_BLE_SUBRATE_REQ_DISABLE;
192 } else {
193 p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE;
194 p_lcb->subrate_req_mask |= L2C_BLE_SUBRATE_REQ_DISABLE;
195 }
196
197 l2cble_start_conn_update(p_lcb);
198
199 return true;
200 }
201
202 /*******************************************************************************
203 *
204 * Function l2cble_start_conn_update
205 *
206 * Description Start the BLE connection parameter update process based on
207 * status.
208 *
209 * Parameters: lcb : l2cap link control block
210 *
211 * Return value: none
212 *
213 ******************************************************************************/
l2cble_start_conn_update(tL2C_LCB * p_lcb)214 void l2cble_start_conn_update(tL2C_LCB* p_lcb) {
215 uint16_t min_conn_int, max_conn_int, peripheral_latency, supervision_tout;
216 if (!BTM_IsAclConnectionUp(p_lcb->remote_bd_addr, BT_TRANSPORT_LE)) {
217 log::error("No known connection ACL for {}", p_lcb->remote_bd_addr);
218 return;
219 }
220
221 // TODO(armansito): The return value of this call wasn't being used but the
222 // logic of this function might be depending on its side effects. We should
223 // verify if this call is needed at all and remove it otherwise.
224 btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
225
226 if ((p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) ||
227 (p_lcb->subrate_req_mask & L2C_BLE_SUBRATE_REQ_PENDING)) {
228 return;
229 }
230
231 if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) {
232 /* application requests to disable parameters update.
233 If parameters are already updated, lets set them
234 up to what has been requested during connection establishement */
235 if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM) {
236 if (com::android::bluetooth::flags::initial_conn_params_p1()) {
237 min_conn_int = LeConnectionParameters::GetMinConnIntervalAggressive();
238 max_conn_int = LeConnectionParameters::GetMaxConnIntervalAggressive();
239 log::info("min_conn_int={}, max_conn_int={}", min_conn_int, max_conn_int);
240
241 if (p_lcb->conn_update_mask & L2C_BLE_AGGRESSIVE_INITIAL_PARAM) {
242 // Usually, we can use the same aggressive connection parameters for service discovery.
243 // However when hearing aid is being used, the connection intervals may need to be
244 // adjusted.
245 uint16_t adjusted_min_conn_int = min_conn_int;
246 uint16_t adjusted_max_conn_int = max_conn_int;
247
248 stack::l2cap::get_interface().L2CA_AdjustConnectionIntervals(
249 &adjusted_min_conn_int, &adjusted_max_conn_int, BTM_BLE_CONN_INT_MIN);
250
251 log::info("adjusted_min_conn_int={}, adjusted_max_conn_int={}", adjusted_min_conn_int,
252 adjusted_max_conn_int);
253
254 if ((adjusted_min_conn_int == min_conn_int) && (adjusted_max_conn_int == max_conn_int)) {
255 log::info("No need to update connection parameters.");
256 p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
257 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
258 return;
259 }
260 }
261 } else {
262 if (p_lcb->min_interval <= BTM_BLE_CONN_INT_MIN) {
263 // Skip updating connection parameters for service discovery if we are already
264 // using default minimum interval.
265 return;
266 }
267 /* use 7.5 ms as fast connection parameter, 0 peripheral latency */
268 min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
269 }
270
271 stack::l2cap::get_interface().L2CA_AdjustConnectionIntervals(&min_conn_int, &max_conn_int,
272 BTM_BLE_CONN_INT_MIN);
273
274 peripheral_latency = BTM_BLE_CONN_PERIPHERAL_LATENCY_DEF;
275 supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;
276
277 /* if both side 4.1, or we are central device, send HCI command */
278 if (p_lcb->IsLinkRoleCentral() ||
279 (bluetooth::shim::GetController()->SupportsBleConnectionParametersRequest() &&
280 acl_peer_supports_ble_connection_parameters_request(p_lcb->remote_bd_addr))) {
281 acl_ble_connection_parameters_request(p_lcb->Handle(), min_conn_int, max_conn_int,
282 peripheral_latency, supervision_tout, 0, 0);
283 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
284 } else {
285 l2cu_send_peer_ble_par_req(p_lcb, min_conn_int, max_conn_int, peripheral_latency,
286 supervision_tout);
287 }
288 p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
289 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
290 }
291 } else {
292 /* application allows to do update, if we were delaying one do it now */
293 if (p_lcb->conn_update_mask & L2C_BLE_NEW_CONN_PARAM) {
294 /* if both side 4.1, or we are central device, send HCI command */
295 if (p_lcb->IsLinkRoleCentral() ||
296 (bluetooth::shim::GetController()->SupportsBleConnectionParametersRequest() &&
297 acl_peer_supports_ble_connection_parameters_request(p_lcb->remote_bd_addr))) {
298 if (com::android::bluetooth::flags::initial_conn_params_p1() &&
299 (p_lcb->conn_update_mask & L2C_BLE_AGGRESSIVE_INITIAL_PARAM)) {
300 log::info("Relaxing aggressive initial connection parameters. addr={}",
301 p_lcb->remote_bd_addr);
302 p_lcb->min_interval = LeConnectionParameters::GetMinConnIntervalRelaxed();
303 p_lcb->max_interval = LeConnectionParameters::GetMaxConnIntervalRelaxed();
304 p_lcb->conn_update_mask &= ~L2C_BLE_AGGRESSIVE_INITIAL_PARAM;
305 }
306
307 acl_ble_connection_parameters_request(p_lcb->Handle(), p_lcb->min_interval,
308 p_lcb->max_interval, p_lcb->latency, p_lcb->timeout,
309 p_lcb->min_ce_len, p_lcb->max_ce_len);
310 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
311 } else {
312 l2cu_send_peer_ble_par_req(p_lcb, p_lcb->min_interval, p_lcb->max_interval, p_lcb->latency,
313 p_lcb->timeout);
314 }
315 p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
316 p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
317 }
318 }
319 }
320
321 /*******************************************************************************
322 *
323 * Function l2cble_process_conn_update_evt
324 *
325 * Description This function enables the connection update request from
326 * remote after a successful connection update response is
327 * received.
328 *
329 * Returns void
330 *
331 ******************************************************************************/
l2cble_process_conn_update_evt(uint16_t handle,uint8_t status,uint16_t interval,uint16_t,uint16_t)332 void l2cble_process_conn_update_evt(uint16_t handle, uint8_t status, uint16_t interval,
333 uint16_t /* latency */, uint16_t /* timeout */) {
334 log::verbose("");
335
336 /* See if we have a link control block for the remote device */
337 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
338 if (!p_lcb) {
339 log::warn("Invalid handle: {}", handle);
340 return;
341 }
342 p_lcb->SetConnInterval(interval);
343 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
344
345 if (status != HCI_SUCCESS) {
346 log::warn("Error status: {}", status);
347 }
348
349 l2cble_start_conn_update(p_lcb);
350
351 l2cble_start_subrate_change(p_lcb);
352
353 log::verbose("conn_update_mask={} , subrate_req_mask={}", p_lcb->conn_update_mask,
354 p_lcb->subrate_req_mask);
355 }
356
357 /*******************************************************************************
358 *
359 * Function l2cble_process_rc_param_request_evt
360 *
361 * Description process LE Remote Connection Parameter Request Event.
362 *
363 * Returns void
364 *
365 ******************************************************************************/
l2cble_process_rc_param_request_evt(uint16_t handle,uint16_t int_min,uint16_t int_max,uint16_t latency,uint16_t timeout)366 void l2cble_process_rc_param_request_evt(uint16_t handle, uint16_t int_min, uint16_t int_max,
367 uint16_t latency, uint16_t timeout) {
368 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
369 if (!p_lcb) {
370 log::warn("No link to update connection parameter");
371 return;
372 }
373
374 p_lcb->min_interval = int_min;
375 p_lcb->max_interval = int_max;
376 p_lcb->latency = latency;
377 p_lcb->timeout = timeout;
378 if (com::android::bluetooth::flags::initial_conn_params_p1()) {
379 p_lcb->conn_update_mask &= ~L2C_BLE_AGGRESSIVE_INITIAL_PARAM;
380 }
381
382 /* if update is enabled, always accept connection parameter update */
383 if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0) {
384 shim::GetHciLayer()->EnqueueCommand(
385 hci::LeRemoteConnectionParameterRequestReplyBuilder::Create(handle, int_min, int_max,
386 latency, timeout, 0, 0),
387 get_main()->BindOnce(
388 hci::check_complete<hci::LeRemoteConnectionParameterRequestReplyCompleteView>));
389 } else {
390 log::verbose("L2CAP - LE - update currently disabled");
391 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
392 shim::GetHciLayer()->EnqueueCommand(
393 hci::LeRemoteConnectionParameterRequestNegativeReplyBuilder::Create(
394 handle, hci::ErrorCode::UNACCEPTABLE_CONNECTION_PARAMETERS),
395 get_main()->BindOnce(
396 hci::check_complete<
397 hci::LeRemoteConnectionParameterRequestNegativeReplyCompleteView>));
398 }
399 }
400
l2cble_use_preferred_conn_params(const RawAddress & bda)401 void l2cble_use_preferred_conn_params(const RawAddress& bda) {
402 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE);
403 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(bda);
404
405 /* If there are any preferred connection parameters, set them now */
406 if ((p_lcb != NULL) && (p_dev_rec != NULL) &&
407 (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN) &&
408 (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX) &&
409 (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN) &&
410 (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX) &&
411 (p_dev_rec->conn_params.peripheral_latency <= BTM_BLE_CONN_LATENCY_MAX) &&
412 (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
413 (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
414 ((p_lcb->min_interval < p_dev_rec->conn_params.min_conn_int &&
415 p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
416 (p_lcb->min_interval > p_dev_rec->conn_params.max_conn_int) ||
417 (p_lcb->latency > p_dev_rec->conn_params.peripheral_latency) ||
418 (p_lcb->timeout > p_dev_rec->conn_params.supervision_tout))) {
419 log::verbose(
420 "HANDLE={} min_conn_int={} max_conn_int={} peripheral_latency={} "
421 "supervision_tout={}",
422 p_lcb->Handle(), p_dev_rec->conn_params.min_conn_int,
423 p_dev_rec->conn_params.max_conn_int, p_dev_rec->conn_params.peripheral_latency,
424 p_dev_rec->conn_params.supervision_tout);
425
426 p_lcb->min_interval = p_dev_rec->conn_params.min_conn_int;
427 p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int;
428 p_lcb->timeout = p_dev_rec->conn_params.supervision_tout;
429 p_lcb->latency = p_dev_rec->conn_params.peripheral_latency;
430 if (com::android::bluetooth::flags::initial_conn_params_p1()) {
431 p_lcb->conn_update_mask &= ~L2C_BLE_AGGRESSIVE_INITIAL_PARAM;
432 }
433
434 if (com::android::bluetooth::flags::prevent_concurrent_conn_param_updates()) {
435 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
436 l2cble_start_conn_update(p_lcb);
437 } else {
438 acl_ble_connection_parameters_request(p_lcb->Handle(), p_dev_rec->conn_params.min_conn_int,
439 p_dev_rec->conn_params.max_conn_int,
440 p_dev_rec->conn_params.peripheral_latency,
441 p_dev_rec->conn_params.supervision_tout, 0, 0);
442 }
443 }
444 }
445
446 /*******************************************************************************
447 *
448 * Function l2cble_start_subrate_change
449 *
450 * Description Start the BLE subrate change process based on
451 * status.
452 *
453 * Parameters: lcb : l2cap link control block
454 *
455 * Return value: none
456 *
457 ******************************************************************************/
l2cble_start_subrate_change(tL2C_LCB * p_lcb)458 static void l2cble_start_subrate_change(tL2C_LCB* p_lcb) {
459 if (!get_btm_client_interface().peer.BTM_IsAclConnectionUp(p_lcb->remote_bd_addr,
460 BT_TRANSPORT_LE)) {
461 log::error("No known connection ACL for {}", p_lcb->remote_bd_addr);
462 return;
463 }
464
465 btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
466
467 log::verbose("subrate_req_mask={} conn_update_mask={}", p_lcb->subrate_req_mask,
468 p_lcb->conn_update_mask);
469
470 if (p_lcb->subrate_req_mask & L2C_BLE_SUBRATE_REQ_PENDING) {
471 log::verbose("returning L2C_BLE_SUBRATE_REQ_PENDING");
472 return;
473 }
474
475 if (p_lcb->subrate_req_mask & L2C_BLE_SUBRATE_REQ_DISABLE) {
476 log::verbose("returning L2C_BLE_SUBRATE_REQ_DISABLE");
477 return;
478 }
479
480 /* application allows to do update, if we were delaying one do it now */
481 if (!(p_lcb->subrate_req_mask & L2C_BLE_NEW_SUBRATE_PARAM) ||
482 (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) ||
483 (p_lcb->conn_update_mask & L2C_BLE_NEW_CONN_PARAM)) {
484 log::verbose("returning L2C_BLE_NEW_SUBRATE_PARAM");
485 return;
486 }
487
488 if (!bluetooth::shim::GetController()->SupportsBleConnectionSubrating() ||
489 !acl_peer_supports_ble_connection_subrating(p_lcb->remote_bd_addr) ||
490 !acl_peer_supports_ble_connection_subrating_host(p_lcb->remote_bd_addr)) {
491 log::verbose(
492 "returning L2C_BLE_NEW_SUBRATE_PARAM local_host_sup={}, "
493 "local_conn_subrarte_sup={}, peer_subrate_sup={}, peer_host_sup={}",
494 bluetooth::shim::GetController()->SupportsBleConnectionSubratingHost(),
495 bluetooth::shim::GetController()->SupportsBleConnectionSubrating(),
496 acl_peer_supports_ble_connection_subrating(p_lcb->remote_bd_addr),
497 acl_peer_supports_ble_connection_subrating_host(p_lcb->remote_bd_addr));
498 return;
499 }
500
501 log::verbose("Sending HCI cmd for subrate req");
502 bluetooth::shim::ACL_LeSubrateRequest(p_lcb->Handle(), p_lcb->subrate_min, p_lcb->subrate_max,
503 p_lcb->max_latency, p_lcb->cont_num,
504 p_lcb->supervision_tout);
505
506 p_lcb->subrate_req_mask |= L2C_BLE_SUBRATE_REQ_PENDING;
507 p_lcb->subrate_req_mask &= ~L2C_BLE_NEW_SUBRATE_PARAM;
508 p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
509 }
510
511 /*******************************************************************************
512 *
513 * Function L2CA_SubrateRequest
514 *
515 * Description BLE Subrate request.
516 *
517 * Parameters: Subrate parameters
518 *
519 * Return value: true if update started
520 *
521 ******************************************************************************/
L2CA_SubrateRequest(const RawAddress & rem_bda,uint16_t subrate_min,uint16_t subrate_max,uint16_t max_latency,uint16_t cont_num,uint16_t timeout)522 bool L2CA_SubrateRequest(const RawAddress& rem_bda, uint16_t subrate_min, uint16_t subrate_max,
523 uint16_t max_latency, uint16_t cont_num, uint16_t timeout) {
524 /* See if we have a link control block for the remote device */
525 tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
526
527 /* If we don't have one, create one and accept the connection. */
528 if (!p_lcb || !get_btm_client_interface().peer.BTM_IsAclConnectionUp(rem_bda, BT_TRANSPORT_LE)) {
529 log::warn("unknown BD_ADDR {}", rem_bda);
530 return false;
531 }
532
533 if (p_lcb->transport != BT_TRANSPORT_LE) {
534 log::warn("BD_ADDR {} not LE", rem_bda);
535 return false;
536 }
537
538 log::verbose(
539 "BD_ADDR={}, subrate_min={}, subrate_max={}, max_latency={}, "
540 "cont_num={}, timeout={}",
541 rem_bda, subrate_min, subrate_max, max_latency, cont_num, timeout);
542
543 p_lcb->subrate_min = subrate_min;
544 p_lcb->subrate_max = subrate_max;
545 p_lcb->max_latency = max_latency;
546 p_lcb->cont_num = cont_num;
547 p_lcb->subrate_req_mask |= L2C_BLE_NEW_SUBRATE_PARAM;
548 p_lcb->supervision_tout = timeout;
549
550 l2cble_start_subrate_change(p_lcb);
551
552 return true;
553 }
554
555 /*******************************************************************************
556 *
557 * Function l2cble_process_subrate_change_evt
558 *
559 * Description This function enables LE subrating
560 * after a successful subrate change process is
561 * done.
562 *
563 * Parameters: LE connection handle
564 * status
565 * subrate factor
566 * peripheral latency
567 * continuation number
568 * supervision timeout
569 *
570 * Returns void
571 *
572 ******************************************************************************/
l2cble_process_subrate_change_evt(uint16_t handle,uint8_t status,uint16_t,uint16_t,uint16_t,uint16_t)573 void l2cble_process_subrate_change_evt(uint16_t handle, uint8_t status,
574 uint16_t /* subrate_factor */,
575 uint16_t /* peripheral_latency */, uint16_t /* cont_num */,
576 uint16_t /* timeout */) {
577 log::verbose("");
578
579 /* See if we have a link control block for the remote device */
580 tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
581 if (!p_lcb) {
582 log::warn("Invalid handle: {}", handle);
583 return;
584 }
585
586 p_lcb->subrate_req_mask &= ~L2C_BLE_SUBRATE_REQ_PENDING;
587
588 if (status != HCI_SUCCESS) {
589 log::warn("Error status: {}", status);
590 }
591
592 l2cble_start_conn_update(p_lcb);
593
594 l2cble_start_subrate_change(p_lcb);
595
596 log::verbose("conn_update_mask={} , subrate_req_mask={}", p_lcb->conn_update_mask,
597 p_lcb->subrate_req_mask);
598 }
599