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