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