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