• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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