• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 1999-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 L2CAP utility functions
22  *
23  ******************************************************************************/
24 #define LOG_TAG "l2c_utils"
25 
26 #include <base/logging.h>
27 #include <stdio.h>
28 #include <string.h>
29 
30 #include "device/include/controller.h"
31 #include "gd/hal/snoop_logger.h"
32 #include "main/shim/l2c_api.h"
33 #include "main/shim/shim.h"
34 #include "osi/include/allocator.h"
35 #include "osi/include/log.h"
36 #include "stack/btm/btm_sec.h"
37 #include "stack/include/acl_api.h"
38 #include "stack/include/bt_hdr.h"
39 #include "stack/include/btm_api.h"
40 #include "stack/include/hci_error_code.h"
41 #include "stack/include/hcidefs.h"
42 #include "stack/include/l2c_api.h"
43 #include "stack/include/l2cdefs.h"
44 #include "stack/l2cap/l2c_int.h"
45 #include "types/raw_address.h"
46 
47 tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb); // TODO Move
48 
49 /*******************************************************************************
50  *
51  * Function         l2cu_allocate_lcb
52  *
53  * Description      Look for an unused LCB
54  *
55  * Returns          LCB address or NULL if none found
56  *
57  ******************************************************************************/
l2cu_allocate_lcb(const RawAddress & p_bd_addr,bool is_bonding,tBT_TRANSPORT transport)58 tL2C_LCB* l2cu_allocate_lcb(const RawAddress& p_bd_addr, bool is_bonding,
59                             tBT_TRANSPORT transport) {
60   int xx;
61   tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
62 
63   for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
64     if (!p_lcb->in_use) {
65       alarm_free(p_lcb->l2c_lcb_timer);
66       alarm_free(p_lcb->info_resp_timer);
67       memset(p_lcb, 0, sizeof(tL2C_LCB));
68 
69       p_lcb->remote_bd_addr = p_bd_addr;
70 
71       p_lcb->in_use = true;
72       p_lcb->with_active_local_clients = false;
73       p_lcb->link_state = LST_DISCONNECTED;
74       p_lcb->InvalidateHandle();
75       p_lcb->l2c_lcb_timer = alarm_new("l2c_lcb.l2c_lcb_timer");
76       p_lcb->info_resp_timer = alarm_new("l2c_lcb.info_resp_timer");
77       p_lcb->idle_timeout = l2cb.idle_timeout;
78       p_lcb->signal_id = 1; /* spec does not allow '0' */
79       if (is_bonding) {
80         p_lcb->SetBonding();
81       } else {
82         p_lcb->ResetBonding();
83       }
84       p_lcb->transport = transport;
85       p_lcb->tx_data_len =
86           controller_get_interface()->get_ble_default_data_packet_length();
87       p_lcb->le_sec_pending_q = fixed_queue_new(SIZE_MAX);
88 
89       if (transport == BT_TRANSPORT_LE) {
90         l2cb.num_ble_links_active++;
91         l2c_ble_link_adjust_allocation();
92       } else {
93         l2cb.num_used_lcbs++;
94         l2c_link_adjust_allocation();
95       }
96       p_lcb->link_xmit_data_q = list_new(NULL);
97       return (p_lcb);
98     }
99   }
100 
101   /* If here, no free LCB found */
102   return (NULL);
103 }
104 
l2cu_set_lcb_handle(struct t_l2c_linkcb & p_lcb,uint16_t handle)105 void l2cu_set_lcb_handle(struct t_l2c_linkcb& p_lcb, uint16_t handle) {
106   if (p_lcb.Handle() != HCI_INVALID_HANDLE) {
107     LOG_WARN("Should not replace active handle:%hu with new handle:%hu",
108              p_lcb.Handle(), handle);
109   }
110   p_lcb.SetHandle(handle);
111 }
112 
113 /*******************************************************************************
114  *
115  * Function         l2cu_update_lcb_4_bonding
116  *
117  * Description      Mark the lcb for bonding. Used when bonding takes place on
118  *                  an existing ACL connection.  (Pre-Lisbon devices)
119  *
120  * Returns          Nothing
121  *
122  ******************************************************************************/
l2cu_update_lcb_4_bonding(const RawAddress & p_bd_addr,bool is_bonding)123 void l2cu_update_lcb_4_bonding(const RawAddress& p_bd_addr, bool is_bonding) {
124   if (bluetooth::shim::is_gd_l2cap_enabled()) {
125     bluetooth::shim::L2CA_SetBondingState(p_bd_addr, is_bonding);
126     return;
127   }
128 
129   tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR);
130 
131   if (p_lcb) {
132     VLOG(1) << __func__ << " BDA: " << ADDRESS_TO_LOGGABLE_STR(p_bd_addr)
133             << " is_bonding: " << is_bonding;
134     if (is_bonding) {
135       p_lcb->SetBonding();
136     } else {
137       p_lcb->ResetBonding();
138     }
139   }
140 }
141 
142 /*******************************************************************************
143  *
144  * Function         l2cu_release_lcb
145  *
146  * Description      Release an LCB. All timers will be stopped and freed,
147  *                  channels dropped, buffers returned etc.
148  *
149  * Returns          void
150  *
151  ******************************************************************************/
l2cu_release_lcb(tL2C_LCB * p_lcb)152 void l2cu_release_lcb(tL2C_LCB* p_lcb) {
153   tL2C_CCB* p_ccb;
154 
155   p_lcb->in_use = false;
156   p_lcb->ResetBonding();
157 
158   /* Stop and free timers */
159   alarm_free(p_lcb->l2c_lcb_timer);
160   p_lcb->l2c_lcb_timer = NULL;
161   alarm_free(p_lcb->info_resp_timer);
162   p_lcb->info_resp_timer = NULL;
163 
164   if (p_lcb->transport == BT_TRANSPORT_BR_EDR) /* Release all SCO links */
165     BTM_RemoveSco(p_lcb->remote_bd_addr);
166 
167   if (p_lcb->sent_not_acked > 0) {
168     if (p_lcb->transport == BT_TRANSPORT_LE) {
169       l2cb.controller_le_xmit_window += p_lcb->sent_not_acked;
170       if (l2cb.controller_le_xmit_window > l2cb.num_lm_ble_bufs) {
171         l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
172       }
173     } else {
174       l2cb.controller_xmit_window += p_lcb->sent_not_acked;
175       if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs) {
176         l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
177       }
178     }
179   }
180 
181   l2cu_process_fixed_disc_cback(p_lcb);
182 
183   /* Ensure no CCBs left on this LCB */
184   for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;
185        p_ccb = p_lcb->ccb_queue.p_first_ccb) {
186     l2cu_release_ccb(p_ccb);
187   }
188 
189   /* Tell BTM Acl management the link was removed */
190   if ((p_lcb->link_state == LST_CONNECTED) ||
191       (p_lcb->link_state == LST_DISCONNECTING))
192     btm_acl_removed(p_lcb->Handle());
193 
194   /* Release any held buffers */
195   if (p_lcb->link_xmit_data_q) {
196     while (!list_is_empty(p_lcb->link_xmit_data_q)) {
197       BT_HDR* p_buf = static_cast<BT_HDR*>(list_front(p_lcb->link_xmit_data_q));
198       list_remove(p_lcb->link_xmit_data_q, p_buf);
199       osi_free(p_buf);
200     }
201     list_free(p_lcb->link_xmit_data_q);
202     p_lcb->link_xmit_data_q = NULL;
203   }
204 
205   /* Re-adjust flow control windows make sure it does not go negative */
206   if (p_lcb->transport == BT_TRANSPORT_LE) {
207     if (l2cb.num_ble_links_active >= 1) l2cb.num_ble_links_active--;
208 
209     l2c_ble_link_adjust_allocation();
210   } else {
211     if (l2cb.num_used_lcbs >= 1) l2cb.num_used_lcbs--;
212 
213     l2c_link_adjust_allocation();
214   }
215 
216   /* Check and release all the LE COC connections waiting for security */
217   if (p_lcb->le_sec_pending_q) {
218     while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) {
219       tL2CAP_SEC_DATA* p_buf =
220           (tL2CAP_SEC_DATA*)fixed_queue_try_dequeue(p_lcb->le_sec_pending_q);
221       if (p_buf->p_callback)
222         p_buf->p_callback(p_lcb->remote_bd_addr, p_lcb->transport,
223                           p_buf->p_ref_data, BTM_DEV_RESET);
224       osi_free(p_buf);
225     }
226     fixed_queue_free(p_lcb->le_sec_pending_q, NULL);
227     p_lcb->le_sec_pending_q = NULL;
228   }
229 }
230 
231 /*******************************************************************************
232  *
233  * Function         l2cu_find_lcb_by_bd_addr
234  *
235  * Description      Look through all active LCBs for a match based on the
236  *                  remote BD address.
237  *
238  * Returns          pointer to matched LCB, or NULL if no match
239  *
240  ******************************************************************************/
l2cu_find_lcb_by_bd_addr(const RawAddress & p_bd_addr,tBT_TRANSPORT transport)241 tL2C_LCB* l2cu_find_lcb_by_bd_addr(const RawAddress& p_bd_addr,
242                                    tBT_TRANSPORT transport) {
243   int xx;
244   tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
245 
246   for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
247     if ((p_lcb->in_use) && p_lcb->transport == transport &&
248         (p_lcb->remote_bd_addr == p_bd_addr)) {
249       return (p_lcb);
250     }
251   }
252 
253   /* If here, no match found */
254   return (NULL);
255 }
256 
257 /*******************************************************************************
258  *
259  * Function         l2c_is_cmd_rejected
260  *
261  * Description      Checks if cmd_code is command or response
262  *                  If a command it will be rejected per spec.
263  *                  This function is used when a illegal packet length is
264  *                  detected.
265  *
266  * Returns          bool    - true if cmd_code is a command and it is rejected,
267  *                            false if response code. (command not rejected)
268  *
269  ******************************************************************************/
l2c_is_cmd_rejected(uint8_t cmd_code,uint8_t signal_id,tL2C_LCB * p_lcb)270 bool l2c_is_cmd_rejected(uint8_t cmd_code, uint8_t signal_id, tL2C_LCB* p_lcb) {
271   switch (cmd_code) {
272     case L2CAP_CMD_CONN_REQ:
273     case L2CAP_CMD_CONFIG_REQ:
274     case L2CAP_CMD_DISC_REQ:
275     case L2CAP_CMD_ECHO_REQ:
276     case L2CAP_CMD_INFO_REQ:
277     case L2CAP_CMD_AMP_CONN_REQ:
278     case L2CAP_CMD_AMP_MOVE_REQ:
279     case L2CAP_CMD_BLE_UPDATE_REQ:
280       l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, signal_id,
281                                 L2CAP_DEFAULT_MTU, 0);
282       L2CAP_TRACE_WARNING("Dumping first Command (%d)", cmd_code);
283       return true;
284 
285     default: /* Otherwise a response */
286       return false;
287   }
288 }
289 
290 /*******************************************************************************
291  *
292  * Function         l2cu_build_header
293  *
294  * Description      Builds the L2CAP command packet header
295  *
296  * Returns          Pointer to allocated packet or NULL if no resources
297  *
298  ******************************************************************************/
l2cu_build_header(tL2C_LCB * p_lcb,uint16_t len,uint8_t cmd,uint8_t signal_id)299 BT_HDR* l2cu_build_header(tL2C_LCB* p_lcb, uint16_t len, uint8_t cmd,
300                           uint8_t signal_id) {
301   BT_HDR* p_buf = (BT_HDR*)osi_malloc(L2CAP_CMD_BUF_SIZE);
302   uint8_t* p;
303 
304   p_buf->offset = L2CAP_SEND_CMD_OFFSET;
305   p_buf->len =
306       len + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
307   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
308 
309   /* Put in HCI header - handle + pkt boundary */
310   if (p_lcb->transport == BT_TRANSPORT_LE) {
311     UINT16_TO_STREAM(p, (p_lcb->Handle() | (L2CAP_PKT_START_NON_FLUSHABLE
312                                             << L2CAP_PKT_TYPE_SHIFT)));
313   } else {
314     UINT16_TO_STREAM(p, p_lcb->Handle() | l2cb.non_flushable_pbf);
315   }
316 
317   UINT16_TO_STREAM(p, len + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD);
318   UINT16_TO_STREAM(p, len + L2CAP_CMD_OVERHEAD);
319 
320   if (p_lcb->transport == BT_TRANSPORT_LE) {
321     UINT16_TO_STREAM(p, L2CAP_BLE_SIGNALLING_CID);
322   } else {
323     UINT16_TO_STREAM(p, L2CAP_SIGNALLING_CID);
324   }
325 
326   /* Put in L2CAP command header */
327   UINT8_TO_STREAM(p, cmd);
328   UINT8_TO_STREAM(p, signal_id);
329   UINT16_TO_STREAM(p, len);
330 
331   return (p_buf);
332 }
333 
334 /*******************************************************************************
335  *
336  * Function         l2cu_adj_id
337  *
338  * Description      Checks for valid ID based on specified mask
339  *                  and adjusts the id if invalid.
340  *
341  * Returns          void
342  *
343  ******************************************************************************/
l2cu_adj_id(tL2C_LCB * p_lcb)344 void l2cu_adj_id(tL2C_LCB* p_lcb) {
345   if (p_lcb->signal_id == 0) {
346     p_lcb->signal_id++;
347   }
348 }
349 
350 /*******************************************************************************
351  *
352  * Function         l2cu_send_peer_cmd_reject
353  *
354  * Description      Build and send an L2CAP "command reject" message
355  *                  to the peer.
356  *
357  * Returns          void
358  *
359  ******************************************************************************/
l2cu_send_peer_cmd_reject(tL2C_LCB * p_lcb,uint16_t reason,uint8_t rem_id,uint16_t p1,uint16_t p2)360 void l2cu_send_peer_cmd_reject(tL2C_LCB* p_lcb, uint16_t reason, uint8_t rem_id,
361                                uint16_t p1, uint16_t p2) {
362   uint16_t param_len;
363   BT_HDR* p_buf;
364   uint8_t* p;
365 
366   /* Put in L2CAP packet header */
367   if (reason == L2CAP_CMD_REJ_MTU_EXCEEDED)
368     param_len = 2;
369   else if (reason == L2CAP_CMD_REJ_INVALID_CID)
370     param_len = 4;
371   else
372     param_len = 0;
373 
374   p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_CMD_REJECT_LEN + param_len),
375                             L2CAP_CMD_REJECT, rem_id);
376   if (p_buf == NULL) {
377     L2CAP_TRACE_WARNING("L2CAP - no buffer cmd_rej");
378     return;
379   }
380 
381   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
382       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
383 
384   UINT16_TO_STREAM(p, reason);
385 
386   if (param_len >= 2) UINT16_TO_STREAM(p, p1);
387 
388   if (param_len >= 4) UINT16_TO_STREAM(p, p2);
389 
390   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
391 }
392 
393 /*******************************************************************************
394  *
395  * Function         l2cu_send_peer_connect_req
396  *
397  * Description      Build and send an L2CAP "connection request" message
398  *                  to the peer.
399  *
400  * Returns          void
401  *
402  ******************************************************************************/
l2cu_send_peer_connect_req(tL2C_CCB * p_ccb)403 void l2cu_send_peer_connect_req(tL2C_CCB* p_ccb) {
404   BT_HDR* p_buf;
405   uint8_t* p;
406 
407   /* Create an identifier for this packet */
408   p_ccb->p_lcb->signal_id++;
409   l2cu_adj_id(p_ccb->p_lcb);
410 
411   p_ccb->local_id = p_ccb->p_lcb->signal_id;
412 
413   p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_REQ_LEN,
414                             L2CAP_CMD_CONN_REQ, p_ccb->local_id);
415   if (p_buf == NULL) {
416     L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
417     return;
418   }
419 
420   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
421       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
422 
423   UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm);
424   UINT16_TO_STREAM(p, p_ccb->local_cid);
425 
426   l2c_link_check_send_pkts(p_ccb->p_lcb, 0, p_buf);
427 }
428 
429 /*******************************************************************************
430  *
431  * Function         l2cu_send_peer_connect_rsp
432  *
433  * Description      Build and send an L2CAP "connection response" message
434  *                  to the peer.
435  *
436  * Returns          void
437  *
438  ******************************************************************************/
l2cu_send_peer_connect_rsp(tL2C_CCB * p_ccb,uint16_t result,uint16_t status)439 void l2cu_send_peer_connect_rsp(tL2C_CCB* p_ccb, uint16_t result,
440                                 uint16_t status) {
441   if (result == L2CAP_CONN_PENDING) {
442     /* if we already sent pending response */
443     if (p_ccb->flags & CCB_FLAG_SENT_PENDING) {
444       LOG_DEBUG("Already sent connection pending, not sending again");
445       return;
446     } else {
447       p_ccb->flags |= CCB_FLAG_SENT_PENDING;
448     }
449   }
450 
451   BT_HDR* p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_RSP_LEN,
452                                     L2CAP_CMD_CONN_RSP, p_ccb->remote_id);
453   if (p_buf == nullptr) {
454     LOG_WARN("no buffer for conn_rsp");
455     return;
456   }
457 
458   uint8_t* p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET +
459                HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
460 
461   UINT16_TO_STREAM(p, p_ccb->local_cid);
462   UINT16_TO_STREAM(p, p_ccb->remote_cid);
463   UINT16_TO_STREAM(p, result);
464   UINT16_TO_STREAM(p, status);
465 
466   l2c_link_check_send_pkts(p_ccb->p_lcb, 0, p_buf);
467 }
468 
469 /*******************************************************************************
470  *
471  * Function         l2cu_reject_connection
472  *
473  * Description      Build and send an L2CAP "connection response neg" message
474  *                  to the peer. This function is called when there is no peer
475  *                  CCB (non-existant PSM or no resources).
476  *
477  * Returns          void
478  *
479  ******************************************************************************/
l2cu_reject_connection(tL2C_LCB * p_lcb,uint16_t remote_cid,uint8_t rem_id,uint16_t result)480 void l2cu_reject_connection(tL2C_LCB* p_lcb, uint16_t remote_cid,
481                             uint8_t rem_id, uint16_t result) {
482   BT_HDR* p_buf;
483   uint8_t* p;
484 
485   p_buf =
486       l2cu_build_header(p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, rem_id);
487   if (p_buf == NULL) {
488     L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
489     return;
490   }
491 
492   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
493       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
494 
495   UINT16_TO_STREAM(p, 0); /* Local CID of 0   */
496   UINT16_TO_STREAM(p, remote_cid);
497   UINT16_TO_STREAM(p, result);
498   UINT16_TO_STREAM(p, 0); /* Status of 0      */
499 
500   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
501 }
502 
503 /*******************************************************************************
504  *
505  * Function         l2cu_send_credit_based_reconfig_req
506  *
507  * Description      Build and send an L2CAP "recoonfiguration request" message
508  *                  to the peer.
509  *
510  * Returns          void
511  *
512  ******************************************************************************/
l2cu_send_credit_based_reconfig_req(tL2C_CCB * p_ccb,tL2CAP_LE_CFG_INFO * p_cfg)513 void l2cu_send_credit_based_reconfig_req(tL2C_CCB* p_ccb,
514                                          tL2CAP_LE_CFG_INFO* p_cfg) {
515   BT_HDR* p_buf;
516   uint16_t cmd_len;
517   uint8_t* p;
518   tL2C_LCB* p_lcb = p_ccb->p_lcb;
519   tL2C_CCB* p_ccb_temp;
520 
521   cmd_len = L2CAP_CMD_CREDIT_BASED_RECONFIG_REQ_MIN_LEN +
522             sizeof(uint16_t) * p_lcb->pending_ecoc_reconfig_cnt;
523 
524   /* Create an identifier for this packet */
525   p_lcb->signal_id++;
526   l2cu_adj_id(p_lcb);
527 
528   p_ccb->local_id = p_lcb->signal_id;
529 
530   p_buf = l2cu_build_header(p_lcb, cmd_len, L2CAP_CMD_CREDIT_BASED_RECONFIG_REQ,
531                             p_lcb->signal_id);
532   if (p_buf == NULL) {
533     L2CAP_TRACE_WARNING("l2cu_send_reconfig_req - no buffer");
534     return;
535   }
536 
537   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
538       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
539 
540   L2CAP_TRACE_DEBUG("l2cu_send_reconfig_req number of cids: %d mtu:%d mps:%d",
541                     p_lcb->pending_ecoc_reconfig_cnt, p_cfg->mtu, p_cfg->mps);
542 
543   UINT16_TO_STREAM(p, p_cfg->mtu);
544   UINT16_TO_STREAM(p, p_cfg->mps);
545 
546   for (p_ccb_temp = p_lcb->ccb_queue.p_first_ccb; p_ccb_temp;
547        p_ccb_temp = p_ccb_temp->p_next_ccb) {
548     if ((p_ccb_temp->in_use) && (p_ccb_temp->ecoc) &&
549         (p_ccb_temp->reconfig_started))
550       UINT16_TO_STREAM(p, p_ccb_temp->local_cid);
551   }
552 
553   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
554 }
555 
556 /*******************************************************************************
557  *
558  * Function         l2cu_send_peer_config_req
559  *
560  * Description      Build and send an L2CAP "configuration request" message
561  *                  to the peer.
562  *
563  * Returns          void
564  *
565  ******************************************************************************/
l2cu_send_peer_config_req(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)566 void l2cu_send_peer_config_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
567   BT_HDR* p_buf;
568   uint16_t cfg_len = 0;
569   uint8_t* p;
570 
571   /* Create an identifier for this packet */
572   p_ccb->p_lcb->signal_id++;
573   l2cu_adj_id(p_ccb->p_lcb);
574 
575   p_ccb->local_id = p_ccb->p_lcb->signal_id;
576 
577   if (p_cfg->mtu_present)
578     cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
579   if (p_cfg->flush_to_present)
580     cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
581   if (p_cfg->qos_present)
582     cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
583   if (p_cfg->fcr_present)
584     cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
585   if (p_cfg->fcs_present)
586     cfg_len += L2CAP_CFG_FCS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
587   if (p_cfg->ext_flow_spec_present)
588     cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
589 
590   p_buf = l2cu_build_header(p_ccb->p_lcb,
591                             (uint16_t)(L2CAP_CONFIG_REQ_LEN + cfg_len),
592                             L2CAP_CMD_CONFIG_REQ, p_ccb->local_id);
593   if (p_buf == NULL) {
594     L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
595     return;
596   }
597 
598   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
599       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
600 
601   UINT16_TO_STREAM(p, p_ccb->remote_cid);
602   UINT16_TO_STREAM(p, p_cfg->flags); /* Flags (continuation) */
603 
604   /* Now, put the options */
605   if (p_cfg->mtu_present) {
606     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_MTU);
607     UINT8_TO_STREAM(p, L2CAP_CFG_MTU_OPTION_LEN);
608     UINT16_TO_STREAM(p, p_cfg->mtu);
609   }
610   if (p_cfg->flush_to_present) {
611     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FLUSH_TOUT);
612     UINT8_TO_STREAM(p, L2CAP_CFG_FLUSH_OPTION_LEN);
613     UINT16_TO_STREAM(p, p_cfg->flush_to);
614   }
615   if (p_cfg->qos_present) {
616     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_QOS);
617     UINT8_TO_STREAM(p, L2CAP_CFG_QOS_OPTION_LEN);
618     UINT8_TO_STREAM(p, p_cfg->qos.qos_flags);
619     UINT8_TO_STREAM(p, p_cfg->qos.service_type);
620     UINT32_TO_STREAM(p, p_cfg->qos.token_rate);
621     UINT32_TO_STREAM(p, p_cfg->qos.token_bucket_size);
622     UINT32_TO_STREAM(p, p_cfg->qos.peak_bandwidth);
623     UINT32_TO_STREAM(p, p_cfg->qos.latency);
624     UINT32_TO_STREAM(p, p_cfg->qos.delay_variation);
625   }
626   if (p_cfg->fcr_present) {
627     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCR);
628     UINT8_TO_STREAM(p, L2CAP_CFG_FCR_OPTION_LEN);
629     UINT8_TO_STREAM(p, p_cfg->fcr.mode);
630     UINT8_TO_STREAM(p, p_cfg->fcr.tx_win_sz);
631     UINT8_TO_STREAM(p, p_cfg->fcr.max_transmit);
632     UINT16_TO_STREAM(p, p_cfg->fcr.rtrans_tout);
633     UINT16_TO_STREAM(p, p_cfg->fcr.mon_tout);
634     UINT16_TO_STREAM(p, p_cfg->fcr.mps);
635   }
636 
637   if (p_cfg->fcs_present) {
638     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCS);
639     UINT8_TO_STREAM(p, L2CAP_CFG_FCS_OPTION_LEN);
640     UINT8_TO_STREAM(p, p_cfg->fcs);
641   }
642 
643   if (p_cfg->ext_flow_spec_present) {
644     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_EXT_FLOW);
645     UINT8_TO_STREAM(p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
646     UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.id);
647     UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.stype);
648     UINT16_TO_STREAM(p, p_cfg->ext_flow_spec.max_sdu_size);
649     UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.sdu_inter_time);
650     UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.access_latency);
651     UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.flush_timeout);
652   }
653 
654   l2c_link_check_send_pkts(p_ccb->p_lcb, 0, p_buf);
655 }
656 
657 /*******************************************************************************
658  *
659  * Function         l2cu_send_peer_config_rsp
660  *
661  * Description      Build and send an L2CAP "configuration response" message
662  *                  to the peer.
663  *
664  * Returns          void
665  *
666  ******************************************************************************/
l2cu_send_peer_config_rsp(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)667 void l2cu_send_peer_config_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
668   BT_HDR* p_buf;
669   uint16_t cfg_len = 0;
670   uint8_t* p;
671 
672   /* Create an identifier for this packet */
673   if (p_cfg->mtu_present)
674     cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
675   if (p_cfg->flush_to_present)
676     cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
677   if (p_cfg->qos_present)
678     cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
679   if (p_cfg->fcr_present)
680     cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
681   if (p_cfg->ext_flow_spec_present)
682     cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
683 
684   p_buf = l2cu_build_header(p_ccb->p_lcb,
685                             (uint16_t)(L2CAP_CONFIG_RSP_LEN + cfg_len),
686                             L2CAP_CMD_CONFIG_RSP, p_ccb->remote_id);
687   if (p_buf == NULL) {
688     L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
689     return;
690   }
691 
692   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
693       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
694 
695   UINT16_TO_STREAM(p, p_ccb->remote_cid);
696   UINT16_TO_STREAM(p,
697                    p_cfg->flags); /* Flags (continuation) Must match request */
698   UINT16_TO_STREAM(p, p_cfg->result);
699 
700   /* Now, put the options */
701   if (p_cfg->mtu_present) {
702     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_MTU);
703     UINT8_TO_STREAM(p, L2CAP_CFG_MTU_OPTION_LEN);
704     UINT16_TO_STREAM(p, p_cfg->mtu);
705   }
706   if (p_cfg->flush_to_present) {
707     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FLUSH_TOUT);
708     UINT8_TO_STREAM(p, L2CAP_CFG_FLUSH_OPTION_LEN);
709     UINT16_TO_STREAM(p, p_cfg->flush_to);
710   }
711   if (p_cfg->qos_present) {
712     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_QOS);
713     UINT8_TO_STREAM(p, L2CAP_CFG_QOS_OPTION_LEN);
714     UINT8_TO_STREAM(p, p_cfg->qos.qos_flags);
715     UINT8_TO_STREAM(p, p_cfg->qos.service_type);
716     UINT32_TO_STREAM(p, p_cfg->qos.token_rate);
717     UINT32_TO_STREAM(p, p_cfg->qos.token_bucket_size);
718     UINT32_TO_STREAM(p, p_cfg->qos.peak_bandwidth);
719     UINT32_TO_STREAM(p, p_cfg->qos.latency);
720     UINT32_TO_STREAM(p, p_cfg->qos.delay_variation);
721   }
722   if (p_cfg->fcr_present) {
723     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCR);
724     UINT8_TO_STREAM(p, L2CAP_CFG_FCR_OPTION_LEN);
725     UINT8_TO_STREAM(p, p_cfg->fcr.mode);
726     UINT8_TO_STREAM(p, p_cfg->fcr.tx_win_sz);
727     UINT8_TO_STREAM(p, p_cfg->fcr.max_transmit);
728     UINT16_TO_STREAM(p, p_ccb->our_cfg.fcr.rtrans_tout);
729     UINT16_TO_STREAM(p, p_ccb->our_cfg.fcr.mon_tout);
730     UINT16_TO_STREAM(p, p_cfg->fcr.mps);
731   }
732 
733   if (p_cfg->ext_flow_spec_present) {
734     UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_EXT_FLOW);
735     UINT8_TO_STREAM(p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
736     UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.id);
737     UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.stype);
738     UINT16_TO_STREAM(p, p_cfg->ext_flow_spec.max_sdu_size);
739     UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.sdu_inter_time);
740     UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.access_latency);
741     UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.flush_timeout);
742   }
743 
744   l2c_link_check_send_pkts(p_ccb->p_lcb, 0, p_buf);
745 }
746 
747 /*******************************************************************************
748  *
749  * Function         l2cu_send_peer_config_rej
750  *
751  * Description      Build and send an L2CAP "configuration reject" message
752  *                  to the peer.
753  *
754  * Returns          void
755  *
756  ******************************************************************************/
l2cu_send_peer_config_rej(tL2C_CCB * p_ccb,uint8_t * p_data,uint16_t data_len,uint16_t rej_len)757 void l2cu_send_peer_config_rej(tL2C_CCB* p_ccb, uint8_t* p_data,
758                                uint16_t data_len, uint16_t rej_len) {
759   uint16_t len, cfg_len, buf_space, len1;
760   uint8_t *p, *p_hci_len, *p_data_end;
761   uint8_t cfg_code;
762 
763   L2CAP_TRACE_DEBUG("l2cu_send_peer_config_rej: data_len=%d, rej_len=%d",
764                     data_len, rej_len);
765 
766   len = BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
767         L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN;
768   len1 = 0xFFFF - len;
769   if (rej_len > len1) {
770     L2CAP_TRACE_ERROR(
771         "L2CAP - cfg_rej pkt size exceeds buffer design max limit.");
772     return;
773   }
774 
775   BT_HDR* p_buf = (BT_HDR*)osi_malloc(len + rej_len);
776   p_buf->offset = L2CAP_SEND_CMD_OFFSET;
777   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
778 
779   const controller_t* controller = controller_get_interface();
780 
781 /* Put in HCI header - handle + pkt boundary */
782   if (controller->supports_non_flushable_pb()) {
783     UINT16_TO_STREAM(p, (p_ccb->p_lcb->Handle() | (L2CAP_PKT_START_NON_FLUSHABLE
784                                                    << L2CAP_PKT_TYPE_SHIFT)));
785   } else
786   {
787     UINT16_TO_STREAM(p, (p_ccb->p_lcb->Handle() |
788                          (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
789   }
790 
791   /* Remember the HCI header length position, and save space for it */
792   p_hci_len = p;
793   p += 2;
794 
795   /* Put in L2CAP packet header */
796   UINT16_TO_STREAM(p, L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len);
797   UINT16_TO_STREAM(p, L2CAP_SIGNALLING_CID);
798 
799   /* Put in L2CAP command header */
800   UINT8_TO_STREAM(p, L2CAP_CMD_CONFIG_RSP);
801   UINT8_TO_STREAM(p, p_ccb->remote_id);
802 
803   UINT16_TO_STREAM(p, L2CAP_CONFIG_RSP_LEN + rej_len);
804 
805   UINT16_TO_STREAM(p, p_ccb->remote_cid);
806   UINT16_TO_STREAM(p, 0); /* Flags = 0 (no continuation) */
807   UINT16_TO_STREAM(p, L2CAP_CFG_UNKNOWN_OPTIONS);
808 
809   buf_space = rej_len;
810 
811   /* Now, put the rejected options */
812   p_data_end = p_data + data_len;
813   while (p_data < p_data_end) {
814     cfg_code = *p_data;
815     cfg_len = *(p_data + 1);
816 
817     switch (cfg_code & 0x7F) {
818       /* skip known options */
819       case L2CAP_CFG_TYPE_MTU:
820       case L2CAP_CFG_TYPE_FLUSH_TOUT:
821       case L2CAP_CFG_TYPE_QOS:
822       case L2CAP_CFG_TYPE_FCR:
823       case L2CAP_CFG_TYPE_FCS:
824       case L2CAP_CFG_TYPE_EXT_FLOW:
825         p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
826         break;
827 
828       /* unknown options; copy into rsp if not hints */
829       default:
830         /* sanity check option length */
831         if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= data_len) {
832           if ((cfg_code & 0x80) == 0) {
833             if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD)) {
834               memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
835               p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
836               buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
837             } else {
838               L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer");
839               p_data = p_data_end; /* force loop exit */
840               break;
841             }
842           }
843           p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
844         }
845         /* bad length; force loop exit */
846         else {
847           p_data = p_data_end;
848         }
849         break;
850     }
851   }
852 
853   len = (uint16_t)(p - p_hci_len - 2);
854   UINT16_TO_STREAM(p_hci_len, len);
855 
856   p_buf->len = len + 4;
857 
858   L2CAP_TRACE_DEBUG("L2CAP - cfg_rej pkt hci_len=%d, l2cap_len=%d", len,
859                     (L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len));
860 
861   l2c_link_check_send_pkts(p_ccb->p_lcb, 0, p_buf);
862 }
863 
864 /*******************************************************************************
865  *
866  * Function         l2cu_send_peer_disc_req
867  *
868  * Description      Build and send an L2CAP "disconnect request" message
869  *                  to the peer.
870  *
871  * Returns          void
872  *
873  ******************************************************************************/
l2cu_send_peer_disc_req(tL2C_CCB * p_ccb)874 void l2cu_send_peer_disc_req(tL2C_CCB* p_ccb) {
875   BT_HDR *p_buf, *p_buf2;
876   uint8_t* p;
877 
878   if ((!p_ccb) || (p_ccb->p_lcb == NULL)) {
879     L2CAP_TRACE_ERROR("%s L2CAP - ccb or lcb invalid", __func__);
880     return;
881   }
882 
883   /* Create an identifier for this packet */
884   p_ccb->p_lcb->signal_id++;
885   l2cu_adj_id(p_ccb->p_lcb);
886 
887   p_ccb->local_id = p_ccb->p_lcb->signal_id;
888 
889   p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_DISC_REQ_LEN,
890                             L2CAP_CMD_DISC_REQ, p_ccb->local_id);
891   if (p_buf == NULL) {
892     L2CAP_TRACE_WARNING("L2CAP - no buffer for disc_req");
893     return;
894   }
895 
896   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
897       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
898 
899   UINT16_TO_STREAM(p, p_ccb->remote_cid);
900   UINT16_TO_STREAM(p, p_ccb->local_cid);
901 
902   /* Move all queued data packets to the LCB. In FCR mode, assume the higher
903      layer checks that all buffers are sent before disconnecting.
904   */
905   if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
906     while ((p_buf2 = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q)) !=
907            NULL) {
908       l2cu_set_acl_hci_header(p_buf2, p_ccb);
909       l2c_link_check_send_pkts(p_ccb->p_lcb, p_ccb->local_cid, p_buf2);
910     }
911   }
912 
913   l2c_link_check_send_pkts(p_ccb->p_lcb, 0, p_buf);
914 }
915 
916 /*******************************************************************************
917  *
918  * Function         l2cu_send_peer_disc_rsp
919  *
920  * Description      Build and send an L2CAP "disconnect response" message
921  *                  to the peer.
922  *
923  *                  This function is passed the parameters for the disconnect
924  *                  response instead of the CCB address, as it may be called
925  *                  to send a disconnect response when there is no CCB.
926  *
927  * Returns          void
928  *
929  ******************************************************************************/
l2cu_send_peer_disc_rsp(tL2C_LCB * p_lcb,uint8_t remote_id,uint16_t local_cid,uint16_t remote_cid)930 void l2cu_send_peer_disc_rsp(tL2C_LCB* p_lcb, uint8_t remote_id,
931                              uint16_t local_cid, uint16_t remote_cid) {
932   BT_HDR* p_buf;
933   uint8_t* p;
934 
935   p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_RSP_LEN, L2CAP_CMD_DISC_RSP,
936                             remote_id);
937   if (p_buf == NULL) {
938     L2CAP_TRACE_WARNING("L2CAP - no buffer for disc_rsp");
939     return;
940   }
941 
942   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
943       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
944 
945   UINT16_TO_STREAM(p, local_cid);
946   UINT16_TO_STREAM(p, remote_cid);
947 
948   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
949 }
950 
951 /*******************************************************************************
952  *
953  * Function         l2cu_send_peer_echo_rsp
954  *
955  * Description      Build and send an L2CAP "echo response" message
956  *                  to the peer.
957  *
958  * Returns          void
959  *
960  ******************************************************************************/
l2cu_send_peer_echo_rsp(tL2C_LCB * p_lcb,uint8_t signal_id,uint8_t * p_data,uint16_t data_len)961 void l2cu_send_peer_echo_rsp(tL2C_LCB* p_lcb, uint8_t signal_id,
962                              uint8_t* p_data, uint16_t data_len) {
963   BT_HDR* p_buf;
964   uint8_t* p;
965   uint16_t maxlen;
966   /* Filter out duplicate IDs or if available buffers are low (intruder
967    * checking) */
968   if (!signal_id || signal_id == p_lcb->cur_echo_id) {
969     /* Dump this request since it is illegal */
970     L2CAP_TRACE_WARNING("L2CAP ignoring duplicate echo request (%d)",
971                         signal_id);
972     return;
973   } else
974     p_lcb->cur_echo_id = signal_id;
975 
976   uint16_t acl_data_size =
977       controller_get_interface()->get_acl_data_size_classic();
978   uint16_t acl_packet_size =
979       controller_get_interface()->get_acl_packet_size_classic();
980   /* Don't return data if it does not fit in ACL and L2CAP MTU */
981   maxlen = (L2CAP_CMD_BUF_SIZE > acl_packet_size)
982                ? acl_data_size
983                : (uint16_t)L2CAP_CMD_BUF_SIZE;
984   maxlen -=
985       (uint16_t)(BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
986                  L2CAP_CMD_OVERHEAD + L2CAP_ECHO_RSP_LEN);
987 
988   if (data_len > maxlen) data_len = 0;
989 
990   p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_RSP_LEN + data_len),
991                             L2CAP_CMD_ECHO_RSP, signal_id);
992   if (p_buf == NULL) {
993     L2CAP_TRACE_WARNING("L2CAP - no buffer for echo_rsp");
994     return;
995   }
996 
997   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
998       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
999 
1000   if (data_len) {
1001     ARRAY_TO_STREAM(p, p_data, data_len);
1002   }
1003 
1004   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
1005 }
1006 
1007 /*******************************************************************************
1008  *
1009  * Function         l2cu_send_peer_info_req
1010  *
1011  * Description      Build and send an L2CAP "info request" message
1012  *                  to the peer.
1013  * Returns          void
1014  *
1015  ******************************************************************************/
l2cu_send_peer_info_req(tL2C_LCB * p_lcb,uint16_t info_type)1016 void l2cu_send_peer_info_req(tL2C_LCB* p_lcb, uint16_t info_type) {
1017   BT_HDR* p_buf;
1018   uint8_t* p;
1019 
1020   /* Create an identifier for this packet */
1021   p_lcb->signal_id++;
1022   l2cu_adj_id(p_lcb);
1023 
1024   p_buf = l2cu_build_header(p_lcb, 2, L2CAP_CMD_INFO_REQ, p_lcb->signal_id);
1025   if (p_buf == NULL) {
1026     L2CAP_TRACE_WARNING("L2CAP - no buffer for info_req");
1027     return;
1028   }
1029 
1030   L2CAP_TRACE_EVENT("l2cu_send_peer_info_req: type 0x%04x", info_type);
1031 
1032   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1033       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1034 
1035   UINT16_TO_STREAM(p, info_type);
1036 
1037   p_lcb->w4_info_rsp = true;
1038   alarm_set_on_mloop(p_lcb->info_resp_timer, L2CAP_WAIT_INFO_RSP_TIMEOUT_MS,
1039                      l2c_info_resp_timer_timeout, p_lcb);
1040 
1041   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
1042 }
1043 
1044 /*******************************************************************************
1045  *
1046  * Function         l2cu_send_peer_info_rsp
1047  *
1048  * Description      Build and send an L2CAP "info response" message
1049  *                  to the peer.
1050  *
1051  * Returns          void
1052  *
1053  ******************************************************************************/
l2cu_send_peer_info_rsp(tL2C_LCB * p_lcb,uint8_t remote_id,uint16_t info_type)1054 void l2cu_send_peer_info_rsp(tL2C_LCB* p_lcb, uint8_t remote_id,
1055                              uint16_t info_type) {
1056   BT_HDR* p_buf;
1057   uint8_t* p;
1058   uint16_t len = L2CAP_INFO_RSP_LEN;
1059 
1060 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1061   if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1062       (l2cb.test_info_resp &
1063        (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1064         L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_EXT_FLOW_SPEC |
1065         L2CAP_EXTFEA_FIXED_CHNLS | L2CAP_EXTFEA_EXT_WINDOW |
1066         L2CAP_EXTFEA_UCD_RECEPTION)))
1067 #else
1068   if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1069       (L2CAP_EXTFEA_SUPPORTED_MASK &
1070        (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1071         L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS |
1072         L2CAP_EXTFEA_UCD_RECEPTION)) != 0)
1073 #endif
1074   {
1075     len += L2CAP_EXTENDED_FEATURES_ARRAY_SIZE;
1076   } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1077     len += L2CAP_FIXED_CHNL_ARRAY_SIZE;
1078   } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1079     len += L2CAP_CONNLESS_MTU_INFO_SIZE;
1080   }
1081 
1082   p_buf = l2cu_build_header(p_lcb, len, L2CAP_CMD_INFO_RSP, remote_id);
1083   if (p_buf == NULL) {
1084     L2CAP_TRACE_WARNING("L2CAP - no buffer for info_rsp");
1085     return;
1086   }
1087 
1088   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1089       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1090 
1091   UINT16_TO_STREAM(p, info_type);
1092 
1093 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1094   if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1095       (l2cb.test_info_resp &
1096        (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1097         L2CAP_EXTFEA_UCD_RECEPTION)))
1098 #else
1099   if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1100       (L2CAP_EXTFEA_SUPPORTED_MASK &
1101        (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1102         L2CAP_EXTFEA_UCD_RECEPTION)) != 0)
1103 #endif
1104   {
1105     UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1106     if (p_lcb->transport == BT_TRANSPORT_LE) {
1107       /* optional data are not added for now */
1108       UINT32_TO_STREAM(p, L2CAP_BLE_EXTFEA_MASK);
1109     } else {
1110 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1111       UINT32_TO_STREAM(p, l2cb.test_info_resp);
1112 #else
1113       UINT32_TO_STREAM(p,
1114                        L2CAP_EXTFEA_SUPPORTED_MASK | L2CAP_EXTFEA_FIXED_CHNLS);
1115 #endif
1116     }
1117   } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1118     UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1119     memset(p, 0, L2CAP_FIXED_CHNL_ARRAY_SIZE);
1120 
1121     p[0] = L2CAP_FIXED_CHNL_SIG_BIT;
1122 
1123     if (L2CAP_EXTFEA_SUPPORTED_MASK & L2CAP_EXTFEA_UCD_RECEPTION)
1124       p[0] |= L2CAP_FIXED_CHNL_CNCTLESS_BIT;
1125 
1126     {
1127       int xx;
1128 
1129       for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
1130         /* Skip fixed channels not used on BR/EDR-ACL link */
1131         if ((xx >= L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL) &&
1132             (xx <= L2CAP_SMP_CID - L2CAP_FIRST_FIXED_CHNL))
1133           continue;
1134 
1135         if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL)
1136           p[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] |=
1137               1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8);
1138       }
1139     }
1140   } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1141     UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1142     UINT16_TO_STREAM(p, L2CAP_MTU_SIZE);
1143   } else {
1144     UINT16_TO_STREAM(
1145         p, L2CAP_INFO_RESP_RESULT_NOT_SUPPORTED); /* 'not supported' */
1146   }
1147 
1148   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
1149 }
1150 
1151 /******************************************************************************
1152  *
1153  * Function         l2cu_enqueue_ccb
1154  *
1155  * Description      queue CCB by priority. The first CCB is highest priority and
1156  *                  is served at first. The CCB is queued to an LLCB or an LCB.
1157  *
1158  * Returns          None
1159  *
1160  ******************************************************************************/
l2cu_enqueue_ccb(tL2C_CCB * p_ccb)1161 void l2cu_enqueue_ccb(tL2C_CCB* p_ccb) {
1162   tL2C_CCB* p_ccb1;
1163   tL2C_CCB_Q* p_q = NULL;
1164 
1165   /* Find out which queue the channel is on
1166   */
1167   if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue;
1168 
1169   if ((!p_ccb->in_use) || (p_q == NULL)) {
1170     L2CAP_TRACE_ERROR("%s: CID: 0x%04x ERROR in_use: %u  p_lcb: %p", __func__,
1171                       p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb);
1172     return;
1173   }
1174 
1175   L2CAP_TRACE_DEBUG("l2cu_enqueue_ccb CID: 0x%04x  priority: %d",
1176                     p_ccb->local_cid, p_ccb->ccb_priority);
1177 
1178   /* If the queue is empty, we go at the front */
1179   if (!p_q->p_first_ccb) {
1180     p_q->p_first_ccb = p_q->p_last_ccb = p_ccb;
1181     p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1182   } else {
1183     p_ccb1 = p_q->p_first_ccb;
1184 
1185     while (p_ccb1 != NULL) {
1186       /* Insert new ccb at the end of the same priority. Lower number, higher
1187        * priority */
1188       if (p_ccb->ccb_priority < p_ccb1->ccb_priority) {
1189         /* Are we at the head of the queue ? */
1190         if (p_ccb1 == p_q->p_first_ccb)
1191           p_q->p_first_ccb = p_ccb;
1192         else
1193           p_ccb1->p_prev_ccb->p_next_ccb = p_ccb;
1194 
1195         p_ccb->p_next_ccb = p_ccb1;
1196         p_ccb->p_prev_ccb = p_ccb1->p_prev_ccb;
1197         p_ccb1->p_prev_ccb = p_ccb;
1198         break;
1199       }
1200 
1201       p_ccb1 = p_ccb1->p_next_ccb;
1202     }
1203 
1204     /* If we are lower then anyone in the list, we go at the end */
1205     if (!p_ccb1) {
1206       /* add new ccb at the end of the list */
1207       p_q->p_last_ccb->p_next_ccb = p_ccb;
1208 
1209       p_ccb->p_next_ccb = NULL;
1210       p_ccb->p_prev_ccb = p_q->p_last_ccb;
1211       p_q->p_last_ccb = p_ccb;
1212     }
1213   }
1214 
1215   /* Adding CCB into round robin service table of its LCB */
1216   if (p_ccb->p_lcb != NULL) {
1217     /* if this is the first channel in this priority group */
1218     if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0) {
1219       /* Set the first channel to this CCB */
1220       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1221       /* Set the next serving channel in this group to this CCB */
1222       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1223       /* Initialize quota of this priority group based on its priority */
1224       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota =
1225           L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1226     }
1227     /* increase number of channels in this group */
1228     p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb++;
1229   }
1230 }
1231 
1232 /******************************************************************************
1233  *
1234  * Function         l2cu_dequeue_ccb
1235  *
1236  * Description      dequeue CCB from a queue
1237  *
1238  * Returns          -
1239  *
1240  ******************************************************************************/
l2cu_dequeue_ccb(tL2C_CCB * p_ccb)1241 void l2cu_dequeue_ccb(tL2C_CCB* p_ccb) {
1242   tL2C_CCB_Q* p_q = NULL;
1243 
1244   L2CAP_TRACE_DEBUG("l2cu_dequeue_ccb  CID: 0x%04x", p_ccb->local_cid);
1245 
1246   /* Find out which queue the channel is on
1247   */
1248   if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue;
1249 
1250   if ((!p_ccb->in_use) || (p_q == NULL) || (p_q->p_first_ccb == NULL)) {
1251     L2CAP_TRACE_ERROR(
1252         "l2cu_dequeue_ccb  CID: 0x%04x ERROR in_use: %u  p_lcb: 0x%08x  p_q: "
1253         "0x%08x  p_q->p_first_ccb: 0x%08x",
1254         p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb, p_q,
1255         p_q ? p_q->p_first_ccb : 0);
1256     return;
1257   }
1258 
1259   /* Removing CCB from round robin service table of its LCB */
1260   if (p_ccb->p_lcb != NULL) {
1261     /* decrease number of channels in this priority group */
1262     p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb--;
1263 
1264     /* if it was the last channel in the priority group */
1265     if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0) {
1266       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1267       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1268     } else {
1269       /* if it is the first channel of this group */
1270       if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb == p_ccb) {
1271         p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb =
1272             p_ccb->p_next_ccb;
1273       }
1274       /* if it is the next serving channel of this group */
1275       if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb == p_ccb) {
1276         /* simply, start serving from the first channel */
1277         p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb =
1278             p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb;
1279       }
1280     }
1281   }
1282 
1283   if (p_ccb == p_q->p_first_ccb) {
1284     /* We are removing the first in a queue */
1285     p_q->p_first_ccb = p_ccb->p_next_ccb;
1286 
1287     if (p_q->p_first_ccb)
1288       p_q->p_first_ccb->p_prev_ccb = NULL;
1289     else
1290       p_q->p_last_ccb = NULL;
1291   } else if (p_ccb == p_q->p_last_ccb) {
1292     /* We are removing the last in a queue */
1293     p_q->p_last_ccb = p_ccb->p_prev_ccb;
1294     p_q->p_last_ccb->p_next_ccb = NULL;
1295   } else {
1296     /* In the middle of a chain. */
1297     p_ccb->p_prev_ccb->p_next_ccb = p_ccb->p_next_ccb;
1298     p_ccb->p_next_ccb->p_prev_ccb = p_ccb->p_prev_ccb;
1299   }
1300 
1301   p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1302 }
1303 
1304 /******************************************************************************
1305  *
1306  * Function         l2cu_change_pri_ccb
1307  *
1308  * Description
1309  *
1310  * Returns          -
1311  *
1312  ******************************************************************************/
l2cu_change_pri_ccb(tL2C_CCB * p_ccb,tL2CAP_CHNL_PRIORITY priority)1313 void l2cu_change_pri_ccb(tL2C_CCB* p_ccb, tL2CAP_CHNL_PRIORITY priority) {
1314   if (p_ccb->ccb_priority != priority) {
1315     /* If CCB is not the only guy on the queue */
1316     if ((p_ccb->p_next_ccb != NULL) || (p_ccb->p_prev_ccb != NULL)) {
1317       L2CAP_TRACE_DEBUG("Update CCB list in logical link");
1318 
1319       /* Remove CCB from queue and re-queue it at new priority */
1320       l2cu_dequeue_ccb(p_ccb);
1321 
1322       p_ccb->ccb_priority = priority;
1323       l2cu_enqueue_ccb(p_ccb);
1324     }
1325     else {
1326       /* If CCB is the only guy on the queue, no need to re-enqueue */
1327       /* update only round robin service data */
1328       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 0;
1329       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1330       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1331 
1332       p_ccb->ccb_priority = priority;
1333 
1334       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1335       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1336       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota =
1337           L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1338       p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 1;
1339     }
1340   }
1341 }
1342 
1343 /*******************************************************************************
1344  *
1345  * Function         l2cu_allocate_ccb
1346  *
1347  * Description      This function allocates a Channel Control Block and
1348  *                  attaches it to a link control block. The local CID
1349  *                  is also assigned.
1350  *
1351  * Returns          pointer to CCB, or NULL if none
1352  *
1353  ******************************************************************************/
l2cu_allocate_ccb(tL2C_LCB * p_lcb,uint16_t cid)1354 tL2C_CCB* l2cu_allocate_ccb(tL2C_LCB* p_lcb, uint16_t cid) {
1355   LOG_DEBUG("is_dynamic = %d, cid 0x%04x", p_lcb != nullptr, cid);
1356   if (!l2cb.p_free_ccb_first) {
1357     LOG_ERROR("First free ccb is null for cid 0x%04x", cid);
1358     return nullptr;
1359   }
1360   tL2C_CCB* p_ccb;
1361   /* If a CID was passed in, use that, else take the first free one */
1362   if (cid == 0) {
1363     p_ccb = l2cb.p_free_ccb_first;
1364     l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1365   } else {
1366     tL2C_CCB* p_prev = nullptr;
1367 
1368     p_ccb = &l2cb.ccb_pool[cid - L2CAP_BASE_APPL_CID];
1369 
1370     if (p_ccb == l2cb.p_free_ccb_first) {
1371       l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1372     } else {
1373       for (p_prev = l2cb.p_free_ccb_first; p_prev != nullptr;
1374            p_prev = p_prev->p_next_ccb) {
1375         if (p_prev->p_next_ccb == p_ccb) {
1376           p_prev->p_next_ccb = p_ccb->p_next_ccb;
1377 
1378           if (p_ccb == l2cb.p_free_ccb_last) {
1379             l2cb.p_free_ccb_last = p_prev;
1380           }
1381 
1382           break;
1383         }
1384       }
1385       if (p_prev == nullptr) {
1386         LOG_ERROR("Could not find CCB for CID 0x%04x in the free list", cid);
1387         return nullptr;
1388       }
1389     }
1390   }
1391 
1392   p_ccb->p_next_ccb = p_ccb->p_prev_ccb = nullptr;
1393 
1394   p_ccb->in_use = true;
1395 
1396   /* Get a CID for the connection */
1397   p_ccb->local_cid = L2CAP_BASE_APPL_CID + (uint16_t)(p_ccb - l2cb.ccb_pool);
1398 
1399   p_ccb->p_lcb = p_lcb;
1400   p_ccb->p_rcb = nullptr;
1401 
1402   /* Set priority then insert ccb into LCB queue (if we have an LCB) */
1403   p_ccb->ccb_priority = L2CAP_CHNL_PRIORITY_LOW;
1404 
1405   if (p_lcb) l2cu_enqueue_ccb(p_ccb);
1406 
1407   /* Put in default values for configuration */
1408   memset(&p_ccb->our_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1409   memset(&p_ccb->peer_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1410 
1411   /* Put in default values for local/peer configurations */
1412   p_ccb->our_cfg.flush_to = p_ccb->peer_cfg.flush_to = L2CAP_NO_AUTOMATIC_FLUSH;
1413   p_ccb->our_cfg.mtu = p_ccb->peer_cfg.mtu = L2CAP_DEFAULT_MTU;
1414   p_ccb->our_cfg.qos.service_type = p_ccb->peer_cfg.qos.service_type =
1415       L2CAP_DEFAULT_SERV_TYPE;
1416   p_ccb->our_cfg.qos.token_rate = p_ccb->peer_cfg.qos.token_rate =
1417       L2CAP_DEFAULT_TOKEN_RATE;
1418   p_ccb->our_cfg.qos.token_bucket_size = p_ccb->peer_cfg.qos.token_bucket_size =
1419       L2CAP_DEFAULT_BUCKET_SIZE;
1420   p_ccb->our_cfg.qos.peak_bandwidth = p_ccb->peer_cfg.qos.peak_bandwidth =
1421       L2CAP_DEFAULT_PEAK_BANDWIDTH;
1422   p_ccb->our_cfg.qos.latency = p_ccb->peer_cfg.qos.latency =
1423       L2CAP_DEFAULT_LATENCY;
1424   p_ccb->our_cfg.qos.delay_variation = p_ccb->peer_cfg.qos.delay_variation =
1425       L2CAP_DEFAULT_DELAY;
1426 
1427   p_ccb->peer_cfg_already_rejected = false;
1428   p_ccb->fcr_cfg_tries = L2CAP_MAX_FCR_CFG_TRIES;
1429 
1430   alarm_free(p_ccb->fcrb.ack_timer);
1431   p_ccb->fcrb.ack_timer = alarm_new("l2c_fcrb.ack_timer");
1432 
1433   /*  CSP408639 Fix: When L2CAP send amp move channel request or receive
1434     * L2CEVT_AMP_MOVE_REQ do following sequence. Send channel move
1435     * request -> Stop retrans/monitor timer -> Change channel state to
1436    * CST_AMP_MOVING. */
1437   alarm_free(p_ccb->fcrb.mon_retrans_timer);
1438   p_ccb->fcrb.mon_retrans_timer = alarm_new("l2c_fcrb.mon_retrans_timer");
1439 
1440   p_ccb->max_rx_mtu = BT_DEFAULT_BUFFER_SIZE -
1441                       (L2CAP_MIN_OFFSET + L2CAP_SDU_LEN_OFFSET + L2CAP_FCS_LEN);
1442   p_ccb->tx_mps = BT_DEFAULT_BUFFER_SIZE - 32;
1443 
1444   p_ccb->xmit_hold_q = fixed_queue_new(SIZE_MAX);
1445   p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX);
1446   p_ccb->fcrb.retrans_q = fixed_queue_new(SIZE_MAX);
1447   p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(SIZE_MAX);
1448 
1449   p_ccb->cong_sent = false;
1450   p_ccb->buff_quota = 2; /* This gets set after config */
1451 
1452   /* If CCB was reserved Config_Done can already have some value */
1453   if (cid == 0) {
1454     p_ccb->config_done = 0;
1455   } else {
1456     LOG_DEBUG("cid 0x%04x config_done:0x%x", cid, p_ccb->config_done);
1457   }
1458 
1459   p_ccb->chnl_state = CST_CLOSED;
1460   p_ccb->flags = 0;
1461   p_ccb->tx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1462   p_ccb->rx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1463 
1464   p_ccb->is_flushable = false;
1465   p_ccb->ecoc = false;
1466 
1467   alarm_free(p_ccb->l2c_ccb_timer);
1468   p_ccb->l2c_ccb_timer = alarm_new("l2c.l2c_ccb_timer");
1469 
1470   l2c_link_adjust_chnl_allocation();
1471 
1472   if (p_lcb != NULL) {
1473     // once a dynamic channel is opened, timeouts become active
1474     p_lcb->with_active_local_clients = true;
1475   }
1476 
1477   return p_ccb;
1478 }
1479 
1480 /*******************************************************************************
1481  *
1482  * Function         l2cu_start_post_bond_timer
1483  *
1484  * Description      This function starts the ACL Link inactivity timer after
1485  *                  dedicated bonding
1486  *                  This timer can be longer than the normal link inactivity
1487  *                  timer for some platforms.
1488  *
1489  * Returns          bool  - true if idle timer started or disconnect initiated
1490  *                          false if there's one or more pending CCB's exist
1491  *
1492  ******************************************************************************/
l2cu_start_post_bond_timer(uint16_t handle)1493 bool l2cu_start_post_bond_timer(uint16_t handle) {
1494   if (bluetooth::shim::is_gd_l2cap_enabled()) {
1495     return true;
1496   }
1497 
1498   tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
1499   if (p_lcb == nullptr) {
1500     LOG_WARN("Unable to find link control block for handle:0x%04x", handle);
1501     return true;
1502   }
1503   p_lcb->ResetBonding();
1504 
1505   /* Only start timer if no control blocks allocated */
1506   if (p_lcb->ccb_queue.p_first_ccb != nullptr) {
1507     LOG_DEBUG("Unable to start post bond timer with existing dynamic channels");
1508     return false;
1509   }
1510 
1511   switch (p_lcb->link_state) {
1512     case LST_CONNECTED:
1513     case LST_CONNECTING:
1514     case LST_DISCONNECTING: {
1515       /* If no channels on the connection, start idle timeout */
1516       uint64_t timeout_ms = L2CAP_BONDING_TIMEOUT * 1000;
1517 
1518       if (p_lcb->idle_timeout == 0) {
1519         acl_disconnect_from_handle(
1520             p_lcb->Handle(), HCI_ERR_PEER_USER,
1521             "stack::l2cap::l2c_utils::l2cu_start_post_bond_timer Idle timeout");
1522         p_lcb->link_state = LST_DISCONNECTING;
1523         timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
1524       }
1525       alarm_set_on_mloop(p_lcb->l2c_lcb_timer, timeout_ms,
1526                          l2c_lcb_timer_timeout, p_lcb);
1527       LOG_DEBUG("Started link IDLE timeout_ms:%lu", (unsigned long)timeout_ms);
1528       return true;
1529     } break;
1530 
1531     default:
1532       LOG_DEBUG("Will not start post bond timer with link state:%s",
1533                 link_state_text(p_lcb->link_state).c_str());
1534       break;
1535   }
1536   return false;
1537 }
1538 
1539 /*******************************************************************************
1540  *
1541  * Function         l2cu_release_ccb
1542  *
1543  * Description      This function releases a Channel Control Block. The timer
1544  *                  is stopped, any attached buffers freed, and the CCB is
1545  *                  removed from the link control block.
1546  *
1547  * Returns          void
1548  *
1549  ******************************************************************************/
l2cu_release_ccb(tL2C_CCB * p_ccb)1550 void l2cu_release_ccb(tL2C_CCB* p_ccb) {
1551   tL2C_LCB* p_lcb = p_ccb->p_lcb;
1552   tL2C_RCB* p_rcb = p_ccb->p_rcb;
1553 
1554   L2CAP_TRACE_DEBUG("l2cu_release_ccb: cid 0x%04x  in_use: %u",
1555                     p_ccb->local_cid, p_ccb->in_use);
1556 
1557   /* If already released, could be race condition */
1558   if (!p_ccb->in_use) return;
1559 
1560   if (p_rcb && p_lcb && p_ccb->chnl_state >= CST_OPEN) {
1561     bluetooth::shim::GetSnoopLogger()->SetL2capChannelClose(
1562         p_ccb->p_lcb->Handle(), p_ccb->local_cid, p_ccb->remote_cid);
1563   }
1564 
1565   if (p_lcb) {
1566     bluetooth::shim::GetSnoopLogger()->ClearL2capAcceptlist(
1567         p_lcb->Handle(), p_ccb->local_cid, p_ccb->remote_cid);
1568   }
1569 
1570   if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
1571     BTM_SecClrServiceByPsm(p_rcb->psm);
1572   }
1573 
1574   /* Free the timer */
1575   alarm_free(p_ccb->l2c_ccb_timer);
1576   p_ccb->l2c_ccb_timer = NULL;
1577 
1578   fixed_queue_free(p_ccb->xmit_hold_q, osi_free);
1579   p_ccb->xmit_hold_q = NULL;
1580 
1581   l2c_fcr_cleanup(p_ccb);
1582 
1583   /* Channel may not be assigned to any LCB if it was just pre-reserved */
1584   if ((p_lcb) && ((p_ccb->local_cid >= L2CAP_BASE_APPL_CID))) {
1585     l2cu_dequeue_ccb(p_ccb);
1586 
1587     /* Delink the CCB from the LCB */
1588     p_ccb->p_lcb = NULL;
1589   }
1590 
1591   /* Put the CCB back on the free pool */
1592   if (!l2cb.p_free_ccb_first) {
1593     l2cb.p_free_ccb_first = p_ccb;
1594     l2cb.p_free_ccb_last = p_ccb;
1595     p_ccb->p_next_ccb = NULL;
1596     p_ccb->p_prev_ccb = NULL;
1597   } else {
1598     p_ccb->p_next_ccb = NULL;
1599     p_ccb->p_prev_ccb = l2cb.p_free_ccb_last;
1600     l2cb.p_free_ccb_last->p_next_ccb = p_ccb;
1601     l2cb.p_free_ccb_last = p_ccb;
1602   }
1603 
1604   /* Flag as not in use */
1605   p_ccb->in_use = false;
1606   // Clear Remote CID and Local Id
1607   p_ccb->remote_cid = 0;
1608   p_ccb->local_id = 0;
1609 
1610   /* If no channels on the connection, start idle timeout */
1611   if ((p_lcb) && p_lcb->in_use) {
1612     if (p_lcb->link_state == LST_CONNECTED) {
1613       if (!p_lcb->ccb_queue.p_first_ccb) {
1614         // Closing a security channel on LE device should not start connection
1615         // timeout
1616         if (p_lcb->transport == BT_TRANSPORT_LE &&
1617             p_ccb->local_cid == L2CAP_SMP_CID)
1618           return;
1619 
1620         l2cu_no_dynamic_ccbs(p_lcb);
1621       } else {
1622         /* Link is still active, adjust channel quotas. */
1623         l2c_link_adjust_chnl_allocation();
1624       }
1625     } else if (p_lcb->link_state == LST_CONNECTING) {
1626       if (!p_lcb->ccb_queue.p_first_ccb) {
1627         if (p_lcb->transport == BT_TRANSPORT_LE &&
1628             p_ccb->local_cid == L2CAP_ATT_CID) {
1629           L2CAP_TRACE_WARNING("%s - disconnecting the LE link", __func__);
1630           l2cu_no_dynamic_ccbs(p_lcb);
1631         }
1632       }
1633     }
1634   }
1635 }
1636 
1637 /*******************************************************************************
1638  *
1639  * Function         l2cu_find_ccb_by_remote_cid
1640  *
1641  * Description      Look through all active CCBs on a link for a match based
1642  *                  on the remote CID.
1643  *
1644  * Returns          pointer to matched CCB, or NULL if no match
1645  *
1646  ******************************************************************************/
l2cu_find_ccb_by_remote_cid(tL2C_LCB * p_lcb,uint16_t remote_cid)1647 tL2C_CCB* l2cu_find_ccb_by_remote_cid(tL2C_LCB* p_lcb, uint16_t remote_cid) {
1648   tL2C_CCB* p_ccb;
1649 
1650   /* If LCB is NULL, look through all active links */
1651   if (!p_lcb) {
1652     return NULL;
1653   } else {
1654     for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
1655       if ((p_ccb->in_use) && (p_ccb->remote_cid == remote_cid)) return (p_ccb);
1656   }
1657 
1658   /* If here, no match found */
1659   return (NULL);
1660 }
1661 
1662 /*******************************************************************************
1663  *
1664  * Function         l2cu_allocate_rcb
1665  *
1666  * Description      Look through the Registration Control Blocks for a free
1667  *                  one.
1668  *
1669  * Returns          Pointer to the RCB or NULL if not found
1670  *
1671  ******************************************************************************/
l2cu_allocate_rcb(uint16_t psm)1672 tL2C_RCB* l2cu_allocate_rcb(uint16_t psm) {
1673   tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
1674   uint16_t xx;
1675 
1676   for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1677     if (!p_rcb->in_use) {
1678       p_rcb->in_use = true;
1679       p_rcb->psm = psm;
1680       return (p_rcb);
1681     }
1682   }
1683 
1684   /* If here, no free RCB found */
1685   return (NULL);
1686 }
1687 
1688 /*******************************************************************************
1689  *
1690  * Function         l2cu_allocate_ble_rcb
1691  *
1692  * Description      Look through the BLE Registration Control Blocks for a free
1693  *                  one.
1694  *
1695  * Returns          Pointer to the BLE RCB or NULL if not found
1696  *
1697  ******************************************************************************/
l2cu_allocate_ble_rcb(uint16_t psm)1698 tL2C_RCB* l2cu_allocate_ble_rcb(uint16_t psm) {
1699   tL2C_RCB* p_rcb = &l2cb.ble_rcb_pool[0];
1700   uint16_t xx;
1701 
1702   for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1703     if (!p_rcb->in_use) {
1704       p_rcb->in_use = true;
1705       p_rcb->psm = psm;
1706       return (p_rcb);
1707     }
1708   }
1709 
1710   /* If here, no free RCB found */
1711   return (NULL);
1712 }
1713 
1714 /*******************************************************************************
1715  *
1716  * Function         l2cu_release_rcb
1717  *
1718  * Description      Mark an RCB as no longet in use
1719  *
1720  * Returns          void
1721  *
1722  ******************************************************************************/
l2cu_release_rcb(tL2C_RCB * p_rcb)1723 void l2cu_release_rcb(tL2C_RCB* p_rcb) {
1724   p_rcb->in_use = false;
1725   p_rcb->psm = 0;
1726 }
1727 
1728 /*******************************************************************************
1729  *
1730  * Function         l2cu_release_ble_rcb
1731  *
1732  * Description      Mark an LE RCB as no longer in use
1733  *
1734  * Returns          void
1735  *
1736  ******************************************************************************/
l2cu_release_ble_rcb(tL2C_RCB * p_rcb)1737 void l2cu_release_ble_rcb(tL2C_RCB* p_rcb) {
1738   L2CA_FreeLePSM(p_rcb->psm);
1739   p_rcb->in_use = false;
1740   p_rcb->psm = 0;
1741 }
1742 
1743 /*******************************************************************************
1744  *
1745  * Function         l2cu_disconnect_chnl
1746  *
1747  * Description      Disconnect a channel. Typically, this is due to either
1748  *                  receiving a bad configuration,  bad packet or max_retries
1749  *                  expiring.
1750  *
1751  ******************************************************************************/
l2cu_disconnect_chnl(tL2C_CCB * p_ccb)1752 void l2cu_disconnect_chnl(tL2C_CCB* p_ccb) {
1753   uint16_t local_cid = p_ccb->local_cid;
1754 
1755   if (local_cid >= L2CAP_BASE_APPL_CID) {
1756     tL2CA_DISCONNECT_IND_CB* p_disc_cb =
1757         p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
1758 
1759     L2CAP_TRACE_WARNING("L2CAP - disconnect_chnl CID: 0x%04x", local_cid);
1760 
1761     l2cu_send_peer_disc_req(p_ccb);
1762 
1763     l2cu_release_ccb(p_ccb);
1764 
1765     (*p_disc_cb)(local_cid, false);
1766   } else {
1767     /* failure on the AMP channel, probably need to disconnect ACL */
1768     L2CAP_TRACE_ERROR("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid);
1769   }
1770 }
1771 
1772 /*******************************************************************************
1773  *
1774  * Function         l2cu_find_rcb_by_psm
1775  *
1776  * Description      Look through the Registration Control Blocks to see if
1777  *                  anyone registered to handle the PSM in question
1778  *
1779  * Returns          Pointer to the RCB or NULL if not found
1780  *
1781  ******************************************************************************/
l2cu_find_rcb_by_psm(uint16_t psm)1782 tL2C_RCB* l2cu_find_rcb_by_psm(uint16_t psm) {
1783   tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
1784   uint16_t xx;
1785 
1786   for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1787     if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb);
1788   }
1789 
1790   /* If here, no match found */
1791   return (NULL);
1792 }
1793 
1794 /*******************************************************************************
1795  *
1796  * Function         l2cu_find_ble_rcb_by_psm
1797  *
1798  * Description      Look through the BLE Registration Control Blocks to see if
1799  *                  anyone registered to handle the PSM in question
1800  *
1801  * Returns          Pointer to the BLE RCB or NULL if not found
1802  *
1803  ******************************************************************************/
l2cu_find_ble_rcb_by_psm(uint16_t psm)1804 tL2C_RCB* l2cu_find_ble_rcb_by_psm(uint16_t psm) {
1805   tL2C_RCB* p_rcb = &l2cb.ble_rcb_pool[0];
1806   uint16_t xx;
1807 
1808   for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1809     if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb);
1810   }
1811 
1812   /* If here, no match found */
1813   return (NULL);
1814 }
1815 
1816 /*******************************************************************************
1817  *
1818  * Function         l2cu_process_peer_cfg_req
1819  *
1820  * Description      This function is called when the peer sends us a "config
1821  *                  request" message. It extracts the configuration of interest
1822  *                  and saves it in the CCB.
1823  *
1824  *                  Note:  Negotiation of the FCR channel type is handled
1825  *                         internally, all others are passed to the upper layer.
1826  *
1827  * Returns          uint8_t - L2CAP_PEER_CFG_OK if passed to upper layer,
1828  *                            L2CAP_PEER_CFG_UNACCEPTABLE if automatically
1829  *                                      responded to because parameters are
1830  *                                      unnacceptable from a specification point
1831  *                                      of view.
1832  *                            L2CAP_PEER_CFG_DISCONNECT if no compatible channel
1833  *                                      modes between the two devices, and shall
1834  *                                      be closed.
1835  *
1836  ******************************************************************************/
l2cu_process_peer_cfg_req(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)1837 uint8_t l2cu_process_peer_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1838   bool mtu_ok = true;
1839   bool qos_type_ok = true;
1840   bool flush_to_ok = true;
1841   bool fcr_ok = true;
1842   uint8_t fcr_status;
1843   uint16_t required_remote_mtu =
1844       std::max<uint16_t>(L2CAP_MIN_MTU, p_ccb->p_rcb->required_remote_mtu);
1845 
1846   /* Ignore FCR parameters for basic mode */
1847   if (!p_cfg->fcr_present) p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
1848 
1849   if (!p_cfg->mtu_present && required_remote_mtu > L2CAP_DEFAULT_MTU) {
1850     // We reject if we have a MTU requirement higher than default MTU
1851     p_cfg->mtu = required_remote_mtu;
1852     mtu_ok = false;
1853   } else if (p_cfg->mtu_present) {
1854     /* Make sure MTU is at least the minimum */
1855     if (p_cfg->mtu >= required_remote_mtu) {
1856       /* In basic mode, limit the MTU to our buffer size */
1857       if ((!p_cfg->fcr_present) && (p_cfg->mtu > L2CAP_MTU_SIZE))
1858         p_cfg->mtu = L2CAP_MTU_SIZE;
1859 
1860       /* Save the accepted value in case of renegotiation */
1861       p_ccb->peer_cfg.mtu = p_cfg->mtu;
1862       p_ccb->peer_cfg.mtu_present = true;
1863     } else /* Illegal MTU value */
1864     {
1865       p_cfg->mtu = required_remote_mtu;
1866       mtu_ok = false;
1867     }
1868   }
1869   /* Reload mtu from a previously accepted config request */
1870   else if (p_ccb->peer_cfg.mtu_present && !(p_ccb->config_done & IB_CFG_DONE)) {
1871     p_cfg->mtu_present = true;
1872     p_cfg->mtu = p_ccb->peer_cfg.mtu;
1873   }
1874 
1875   /* Verify that the flush timeout is a valid value (0 is illegal) */
1876   if (p_cfg->flush_to_present) {
1877     if (!p_cfg->flush_to) {
1878       p_cfg->flush_to = 0xFFFF; /* Infinite retransmissions (spec default) */
1879       flush_to_ok = false;
1880     } else /* Save the accepted value in case of renegotiation */
1881     {
1882       p_ccb->peer_cfg.flush_to_present = true;
1883       p_ccb->peer_cfg.flush_to = p_cfg->flush_to;
1884     }
1885   }
1886   /* Reload flush_to from a previously accepted config request */
1887   else if (p_ccb->peer_cfg.flush_to_present &&
1888            !(p_ccb->config_done & IB_CFG_DONE)) {
1889     p_cfg->flush_to_present = true;
1890     p_cfg->flush_to = p_ccb->peer_cfg.flush_to;
1891   }
1892 
1893   /* Save the QOS settings the the peer is using */
1894   if (p_cfg->qos_present) {
1895     /* Make sure service type is not a reserved value; otherwise let upper
1896        layer decide if acceptable
1897     */
1898     if (p_cfg->qos.service_type <= SVC_TYPE_GUARANTEED) {
1899       p_ccb->peer_cfg.qos = p_cfg->qos;
1900       p_ccb->peer_cfg.qos_present = true;
1901     } else /* Illegal service type value */
1902     {
1903       p_cfg->qos.service_type = SVC_TYPE_BEST_EFFORT;
1904       qos_type_ok = false;
1905     }
1906   }
1907   /* Reload QOS from a previously accepted config request */
1908   else if (p_ccb->peer_cfg.qos_present && !(p_ccb->config_done & IB_CFG_DONE)) {
1909     p_cfg->qos_present = true;
1910     p_cfg->qos = p_ccb->peer_cfg.qos;
1911   }
1912 
1913   fcr_status = l2c_fcr_process_peer_cfg_req(p_ccb, p_cfg);
1914   if (fcr_status == L2CAP_PEER_CFG_DISCONNECT) {
1915     /* Notify caller to disconnect the channel (incompatible modes) */
1916     p_cfg->result = L2CAP_CFG_FAILED_NO_REASON;
1917     p_cfg->mtu_present = p_cfg->qos_present = p_cfg->flush_to_present = 0;
1918 
1919     return (L2CAP_PEER_CFG_DISCONNECT);
1920   }
1921 
1922   fcr_ok = (fcr_status == L2CAP_PEER_CFG_OK);
1923 
1924   /* Return any unacceptable parameters */
1925   if (mtu_ok && flush_to_ok && qos_type_ok && fcr_ok) {
1926     l2cu_adjust_out_mps(p_ccb);
1927     return (L2CAP_PEER_CFG_OK);
1928   } else {
1929     p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
1930 
1931     if (mtu_ok) p_cfg->mtu_present = false;
1932     if (flush_to_ok) p_cfg->flush_to_present = false;
1933     if (qos_type_ok) p_cfg->qos_present = false;
1934     if (fcr_ok) p_cfg->fcr_present = false;
1935 
1936     return (L2CAP_PEER_CFG_UNACCEPTABLE);
1937   }
1938 }
1939 
1940 /*******************************************************************************
1941  *
1942  * Function         l2cu_process_peer_cfg_rsp
1943  *
1944  * Description      This function is called when the peer sends us a "config
1945  *                  response" message. It extracts the configuration of interest
1946  *                  and saves it in the CCB.
1947  *
1948  * Returns          void
1949  *
1950  ******************************************************************************/
l2cu_process_peer_cfg_rsp(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)1951 void l2cu_process_peer_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1952   /* If we wanted QoS and the peer sends us a positive response with QoS, use
1953    * his values */
1954   if ((p_cfg->qos_present) && (p_ccb->our_cfg.qos_present))
1955     p_ccb->our_cfg.qos = p_cfg->qos;
1956 
1957   if (p_cfg->fcr_present) {
1958     /* Save the retransmission and monitor timeout values */
1959     if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE) {
1960       p_ccb->peer_cfg.fcr.rtrans_tout = p_cfg->fcr.rtrans_tout;
1961       p_ccb->peer_cfg.fcr.mon_tout = p_cfg->fcr.mon_tout;
1962     }
1963 
1964     /* Calculate the max number of packets for which we can delay sending an ack
1965      */
1966     if (p_cfg->fcr.tx_win_sz < p_ccb->our_cfg.fcr.tx_win_sz)
1967       p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
1968     else
1969       p_ccb->fcrb.max_held_acks = p_ccb->our_cfg.fcr.tx_win_sz / 3;
1970 
1971     L2CAP_TRACE_DEBUG(
1972         "l2cu_process_peer_cfg_rsp(): peer tx_win_sz: %d, our tx_win_sz: %d, "
1973         "max_held_acks: %d",
1974         p_cfg->fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz,
1975         p_ccb->fcrb.max_held_acks);
1976   }
1977 }
1978 
1979 /*******************************************************************************
1980  *
1981  * Function         l2cu_process_our_cfg_req
1982  *
1983  * Description      This function is called when we send a "config request"
1984  *                  message. It extracts the configuration of interest and saves
1985  *                  it in the CCB.
1986  *
1987  * Returns          void
1988  *
1989  ******************************************************************************/
l2cu_process_our_cfg_req(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)1990 void l2cu_process_our_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1991   /* Save the QOS settings we are using for transmit */
1992   if (p_cfg->qos_present) {
1993     p_ccb->our_cfg.qos_present = true;
1994     p_ccb->our_cfg.qos = p_cfg->qos;
1995   }
1996 
1997   if (p_cfg->fcr_present) {
1998     /* Override FCR options if attempting streaming or basic */
1999     if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE)
2000       memset(&p_cfg->fcr, 0, sizeof(tL2CAP_FCR_OPTS));
2001     else {
2002       /* On BR/EDR, timer values are zero in config request */
2003       /* On class 2 AMP, timer value in config request shall be non-0 processing
2004        * time */
2005       /*                 timer value in config response shall be greater than
2006        * received processing time */
2007       p_cfg->fcr.mon_tout = p_cfg->fcr.rtrans_tout = 0;
2008     }
2009 
2010     /* Set the threshold to send acks (may be updated in the cfg response) */
2011     p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2012 
2013     /* Include FCS option only if peer can handle it */
2014     if ((p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_NO_CRC) == 0) {
2015       p_cfg->fcs_present = false;
2016     }
2017   } else {
2018     p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
2019   }
2020 
2021   p_ccb->our_cfg.fcr.mode = p_cfg->fcr.mode;
2022   p_ccb->our_cfg.fcr_present = p_cfg->fcr_present;
2023 }
2024 
2025 /*******************************************************************************
2026  *
2027  * Function         l2cu_process_our_cfg_rsp
2028  *
2029  * Description      This function is called when we send the peer a "config
2030  *                  response" message. It extracts the configuration of interest
2031  *                  and saves it in the CCB.
2032  *
2033  * Returns          void
2034  *
2035  ******************************************************************************/
l2cu_process_our_cfg_rsp(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)2036 void l2cu_process_our_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
2037   /* If peer wants QoS, we are allowed to change the values in a positive
2038    * response */
2039   if ((p_cfg->qos_present) && (p_ccb->peer_cfg.qos_present))
2040     p_ccb->peer_cfg.qos = p_cfg->qos;
2041   else
2042     p_cfg->qos_present = false;
2043 
2044   l2c_fcr_adj_our_rsp_options(p_ccb, p_cfg);
2045 }
2046 
2047 /*******************************************************************************
2048  *
2049  * Function         l2cu_device_reset
2050  *
2051  * Description      This function is called when reset of the device is
2052  *                  completed.  For all active connection simulate HCI_DISC
2053  *
2054  * Returns          void
2055  *
2056  ******************************************************************************/
l2cu_device_reset(void)2057 void l2cu_device_reset(void) {
2058   if (bluetooth::shim::is_gd_l2cap_enabled()) {
2059     return;
2060   }
2061 
2062   int xx;
2063   tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
2064 
2065   for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2066     if ((p_lcb->in_use) && (p_lcb->Handle() != HCI_INVALID_HANDLE)) {
2067       l2c_link_hci_disc_comp(p_lcb->Handle(), HCI_ERR_UNDEFINED);
2068     }
2069   }
2070 }
2071 
2072 /* This function initiates an acl connection to a LE device.
2073  * Returns true if request started successfully, false otherwise. */
l2cu_create_conn_le(tL2C_LCB * p_lcb)2074 bool l2cu_create_conn_le(tL2C_LCB* p_lcb) {
2075   if (!controller_get_interface()->supports_ble()) return false;
2076   p_lcb->transport = BT_TRANSPORT_LE;
2077   return (l2cble_create_conn(p_lcb));
2078 }
2079 
2080 /* This function initiates an acl connection to a Classic device via HCI. */
l2cu_create_conn_br_edr(tL2C_LCB * p_lcb)2081 void l2cu_create_conn_br_edr(tL2C_LCB* p_lcb) {
2082   const bool controller_supports_role_switch =
2083       controller_get_interface()->supports_role_switch();
2084 
2085   /* While creating a new classic connection, check check all the other
2086    * active connections where we are not SCO nor central.
2087    * If our controller supports role switching, try switching
2088    * roles back to CENTRAL on those connections.
2089    */
2090   tL2C_LCB* p_lcb_cur = &l2cb.lcb_pool[0];
2091   for (uint8_t xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb_cur++) {
2092     if (p_lcb_cur == p_lcb) continue;
2093     if (!p_lcb_cur->in_use) continue;
2094     if (BTM_IsScoActiveByBdaddr(p_lcb_cur->remote_bd_addr)) {
2095       L2CAP_TRACE_DEBUG(
2096           "%s Central peripheral switch not allowed when SCO active", __func__);
2097       continue;
2098     }
2099     if (p_lcb->IsLinkRoleCentral()) continue;
2100     /* The LMP_switch_req shall be sent only if the ACL logical transport
2101        is in active mode, when encryption is disabled, and all synchronous
2102        logical transports on the same physical link are disabled." */
2103 
2104     /*4_1_TODO check  if btm_cb.devcb.local_features to be used instead */
2105     if (controller_supports_role_switch) {
2106       /* mark this lcb waiting for switch to be completed and
2107          start switch on the other one */
2108       p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
2109       p_lcb->SetLinkRoleAsCentral();
2110 
2111       if (BTM_SwitchRoleToCentral(p_lcb_cur->remote_bd_addr) ==
2112           BTM_CMD_STARTED) {
2113         alarm_set_on_mloop(p_lcb->l2c_lcb_timer,
2114                            L2CAP_LINK_ROLE_SWITCH_TIMEOUT_MS,
2115                            l2c_lcb_timer_timeout, p_lcb);
2116         return;
2117       }
2118     }
2119   }
2120   p_lcb->link_state = LST_CONNECTING;
2121   l2cu_create_conn_after_switch(p_lcb);
2122 }
2123 
2124 /*******************************************************************************
2125  *
2126  * Function         l2cu_get_num_hi_priority
2127  *
2128  * Description      Gets the number of high priority channels.
2129  *
2130  * Returns
2131  *
2132  ******************************************************************************/
l2cu_get_num_hi_priority(void)2133 uint8_t l2cu_get_num_hi_priority(void) {
2134   uint8_t no_hi = 0;
2135   int xx;
2136   tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
2137 
2138   for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2139     if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2140       no_hi++;
2141     }
2142   }
2143   return no_hi;
2144 }
2145 
2146 /*******************************************************************************
2147  *
2148  * Function         l2cu_create_conn_after_switch
2149  *
2150  * Description      This continues a connection creation possibly after
2151  *                  a role switch.
2152  *
2153  ******************************************************************************/
l2cu_create_conn_after_switch(tL2C_LCB * p_lcb)2154 void l2cu_create_conn_after_switch(tL2C_LCB* p_lcb) {
2155   const bool there_are_high_priority_channels =
2156       (l2cu_get_num_hi_priority() > 0);
2157 
2158   acl_create_classic_connection(p_lcb->remote_bd_addr,
2159                                 there_are_high_priority_channels,
2160                                 p_lcb->IsBonding());
2161 
2162   alarm_set_on_mloop(p_lcb->l2c_lcb_timer, L2CAP_LINK_CONNECT_TIMEOUT_MS,
2163                      l2c_lcb_timer_timeout, p_lcb);
2164 }
2165 
2166 /*******************************************************************************
2167  *
2168  * Function         l2cu_find_lcb_by_state
2169  *
2170  * Description      Look through all active LCBs for a match based on the
2171  *                  LCB state.
2172  *
2173  * Returns          pointer to first matched LCB, or NULL if no match
2174  *
2175  ******************************************************************************/
l2cu_find_lcb_by_state(tL2C_LINK_STATE state)2176 tL2C_LCB* l2cu_find_lcb_by_state(tL2C_LINK_STATE state) {
2177   uint16_t i;
2178   tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
2179 
2180   for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2181     if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
2182       return (p_lcb);
2183     }
2184   }
2185 
2186   /* If here, no match found */
2187   return (NULL);
2188 }
2189 
2190 /*******************************************************************************
2191  *
2192  * Function         l2cu_lcb_disconnecting
2193  *
2194  * Description      On each active lcb, check if the lcb is in disconnecting
2195  *                  state, or if there are no ccb's on the lcb (implying
2196                     idle timeout is running), or if last ccb on the link
2197                     is in disconnecting state.
2198  *
2199  * Returns          true if any of above conditions met, false otherwise
2200  *
2201  ******************************************************************************/
l2cu_lcb_disconnecting(void)2202 bool l2cu_lcb_disconnecting(void) {
2203   tL2C_LCB* p_lcb;
2204   tL2C_CCB* p_ccb;
2205   uint16_t i;
2206   bool status = false;
2207 
2208   p_lcb = &l2cb.lcb_pool[0];
2209 
2210   for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2211     if (p_lcb->in_use) {
2212       /* no ccbs on lcb, or lcb is in disconnecting state */
2213       if ((!p_lcb->ccb_queue.p_first_ccb) ||
2214           (p_lcb->link_state == LST_DISCONNECTING)) {
2215         status = true;
2216         break;
2217       }
2218       /* only one ccb left on lcb */
2219       else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) {
2220         p_ccb = p_lcb->ccb_queue.p_first_ccb;
2221 
2222         if ((p_ccb->in_use) &&
2223             ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
2224              (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
2225           status = true;
2226           break;
2227         }
2228       }
2229     }
2230   }
2231   return status;
2232 }
2233 
2234 /*******************************************************************************
2235  *
2236  * Function         l2cu_set_acl_priority_latency_brcm
2237  *
2238  * Description      Sends a VSC to set the ACL priority and recorded latency on
2239  *                  Broadcom chip.
2240  *
2241  * Returns          void
2242  *
2243  ******************************************************************************/
2244 
l2cu_set_acl_priority_latency_brcm(tL2C_LCB * p_lcb,tL2CAP_PRIORITY priority)2245 static void l2cu_set_acl_priority_latency_brcm(tL2C_LCB* p_lcb,
2246                                                tL2CAP_PRIORITY priority) {
2247   uint8_t vs_param;
2248   if (priority == L2CAP_PRIORITY_HIGH) {
2249     // priority to high, if using latency mode check preset latency
2250     if (p_lcb->use_latency_mode &&
2251         p_lcb->preset_acl_latency == L2CAP_LATENCY_LOW) {
2252       LOG_INFO("Set ACL priority: High Priority and Low Latency Mode");
2253       vs_param = HCI_BRCM_ACL_HIGH_PRIORITY_LOW_LATENCY;
2254       p_lcb->set_latency(L2CAP_LATENCY_LOW);
2255     } else {
2256       LOG_INFO("Set ACL priority: High Priority Mode");
2257       vs_param = HCI_BRCM_ACL_HIGH_PRIORITY;
2258     }
2259   } else {
2260     // priority to normal
2261     LOG_INFO("Set ACL priority: Normal Mode");
2262     vs_param = HCI_BRCM_ACL_NORMAL_PRIORITY;
2263     p_lcb->set_latency(L2CAP_LATENCY_NORMAL);
2264   }
2265 
2266   uint8_t command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2267   uint8_t* pp = command;
2268   UINT16_TO_STREAM(pp, p_lcb->Handle());
2269   UINT8_TO_STREAM(pp, vs_param);
2270 
2271   BTM_VendorSpecificCommand(HCI_BRCM_SET_ACL_PRIORITY,
2272                             HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command, NULL);
2273 }
2274 
2275 /*******************************************************************************
2276  *
2277  * Function         l2cu_set_acl_priority_latency_syna
2278  *
2279  * Description      Sends a VSC to set the ACL priority and recorded latency on
2280  *                  Synaptics chip.
2281  *
2282  * Returns          void
2283  *
2284  ******************************************************************************/
2285 
l2cu_set_acl_priority_latency_syna(tL2C_LCB * p_lcb,tL2CAP_PRIORITY priority)2286 static void l2cu_set_acl_priority_latency_syna(tL2C_LCB* p_lcb,
2287                                                tL2CAP_PRIORITY priority) {
2288   uint8_t vs_param;
2289   if (priority == L2CAP_PRIORITY_HIGH) {
2290     // priority to high, if using latency mode check preset latency
2291     if (p_lcb->use_latency_mode &&
2292         p_lcb->preset_acl_latency == L2CAP_LATENCY_LOW) {
2293       LOG_INFO("Set ACL priority: High Priority and Low Latency Mode");
2294       vs_param = HCI_SYNA_ACL_HIGH_PRIORITY_LOW_LATENCY;
2295       p_lcb->set_latency(L2CAP_LATENCY_LOW);
2296     } else {
2297       LOG_INFO("Set ACL priority: High Priority Mode");
2298       vs_param = HCI_SYNA_ACL_HIGH_PRIORITY;
2299     }
2300   } else {
2301     // priority to normal
2302     LOG_INFO("Set ACL priority: Normal Mode");
2303     vs_param = HCI_SYNA_ACL_NORMAL_PRIORITY;
2304     p_lcb->set_latency(L2CAP_LATENCY_NORMAL);
2305   }
2306 
2307   uint8_t command[HCI_SYNA_ACL_PRIORITY_PARAM_SIZE];
2308   uint8_t* pp = command;
2309   UINT16_TO_STREAM(pp, p_lcb->Handle());
2310   UINT8_TO_STREAM(pp, vs_param);
2311 
2312   BTM_VendorSpecificCommand(HCI_SYNA_SET_ACL_PRIORITY,
2313                             HCI_SYNA_ACL_PRIORITY_PARAM_SIZE, command, NULL);
2314 }
2315 
2316 /*******************************************************************************
2317  *
2318  * Function         l2cu_set_acl_priority_unisoc
2319  *
2320  * Description      Sends a VSC to set the ACL priority on Unisoc chip.
2321  *
2322  * Returns          void
2323  *
2324  ******************************************************************************/
2325 
l2cu_set_acl_priority_unisoc(tL2C_LCB * p_lcb,tL2CAP_PRIORITY priority)2326 static void l2cu_set_acl_priority_unisoc(tL2C_LCB* p_lcb,
2327                                                tL2CAP_PRIORITY priority) {
2328   uint8_t vs_param;
2329   if (priority == L2CAP_PRIORITY_HIGH) {
2330     // priority to high
2331     LOG_INFO("Set ACL priority: High Priority Mode");
2332     vs_param = HCI_UNISOC_ACL_HIGH_PRIORITY;
2333   } else {
2334     // priority to normal
2335     LOG_INFO("Set ACL priority: Normal Mode");
2336     vs_param = HCI_UNISOC_ACL_NORMAL_PRIORITY;
2337   }
2338 
2339   uint8_t command[HCI_UNISOC_ACL_PRIORITY_PARAM_SIZE];
2340   uint8_t* pp = command;
2341   UINT16_TO_STREAM(pp, p_lcb->Handle());
2342   UINT8_TO_STREAM(pp, vs_param);
2343 
2344   BTM_VendorSpecificCommand(HCI_UNISOC_SET_ACL_PRIORITY,
2345                             HCI_UNISOC_ACL_PRIORITY_PARAM_SIZE, command, NULL);
2346 }
2347 
2348 /*******************************************************************************
2349  *
2350  * Function         l2cu_set_acl_priority
2351  *
2352  * Description      Sets the transmission priority for a channel.
2353  *                  (For initial implementation only two values are valid.
2354  *                  L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
2355  *
2356  * Returns          true if a valid channel, else false
2357  *
2358  ******************************************************************************/
2359 
l2cu_set_acl_priority(const RawAddress & bd_addr,tL2CAP_PRIORITY priority,bool reset_after_rs)2360 bool l2cu_set_acl_priority(const RawAddress& bd_addr, tL2CAP_PRIORITY priority,
2361                            bool reset_after_rs) {
2362   tL2C_LCB* p_lcb;
2363 
2364   APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority);
2365 
2366   /* Find the link control block for the acl channel */
2367   p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR);
2368   if (p_lcb == NULL) {
2369     L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_SetAclPriority");
2370     return (false);
2371   }
2372 
2373   /* Link priority is set if:
2374    * 1. Change in priority requested from above L2CAP through API, Or
2375    * 2. High priority requested because of central/peripheral role switch */
2376   if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||
2377       (reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2378     /* Use vendor specific commands to set the link priority */
2379     switch (controller_get_interface()->get_bt_version()->manufacturer) {
2380       case LMP_COMPID_BROADCOM:
2381         l2cu_set_acl_priority_latency_brcm(p_lcb, priority);
2382         break;
2383 
2384       case LMP_COMPID_SYNAPTICS:
2385         l2cu_set_acl_priority_latency_syna(p_lcb, priority);
2386         break;
2387 
2388       case LMP_COMPID_UNISOC:
2389         l2cu_set_acl_priority_unisoc(p_lcb, priority);
2390         break;
2391 
2392       default:
2393         /* Not supported/required for other vendors */
2394         break;
2395     }
2396   }
2397 
2398   /* Adjust lmp buffer allocation for this channel if priority changed */
2399   if (p_lcb->acl_priority != priority) {
2400     p_lcb->acl_priority = priority;
2401     l2c_link_adjust_allocation();
2402   }
2403   return (true);
2404 }
2405 
2406 /*******************************************************************************
2407  *
2408  * Function         l2cu_set_acl_latency_brcm
2409  *
2410  * Description      Sends a VSC to set the ACL latency on Broadcom chip.
2411  *
2412  * Returns          void
2413  *
2414  ******************************************************************************/
2415 
l2cu_set_acl_latency_brcm(tL2C_LCB * p_lcb,tL2CAP_LATENCY latency)2416 static void l2cu_set_acl_latency_brcm(tL2C_LCB* p_lcb, tL2CAP_LATENCY latency) {
2417   LOG_INFO("Set ACL latency: %s",
2418            latency == L2CAP_LATENCY_LOW ? "Low Latancy" : "Normal Latency");
2419 
2420   uint8_t command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2421   uint8_t* pp = command;
2422   uint8_t vs_param = latency == L2CAP_LATENCY_LOW
2423                          ? HCI_BRCM_ACL_HIGH_PRIORITY_LOW_LATENCY
2424                          : HCI_BRCM_ACL_HIGH_PRIORITY;
2425   UINT16_TO_STREAM(pp, p_lcb->Handle());
2426   UINT8_TO_STREAM(pp, vs_param);
2427 
2428   BTM_VendorSpecificCommand(HCI_BRCM_SET_ACL_PRIORITY,
2429                             HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command, NULL);
2430 }
2431 
2432 /*******************************************************************************
2433  *
2434  * Function         l2cu_set_acl_latency_syna
2435  *
2436  * Description      Sends a VSC to set the ACL latency on Synatics chip.
2437  *
2438  * Returns          void
2439  *
2440  ******************************************************************************/
2441 
l2cu_set_acl_latency_syna(tL2C_LCB * p_lcb,tL2CAP_LATENCY latency)2442 static void l2cu_set_acl_latency_syna(tL2C_LCB* p_lcb, tL2CAP_LATENCY latency) {
2443   LOG_INFO("Set ACL latency: %s",
2444            latency == L2CAP_LATENCY_LOW ? "Low Latancy" : "Normal Latency");
2445 
2446   uint8_t command[HCI_SYNA_ACL_PRIORITY_PARAM_SIZE];
2447   uint8_t* pp = command;
2448   uint8_t vs_param = latency == L2CAP_LATENCY_LOW
2449                          ? HCI_SYNA_ACL_HIGH_PRIORITY_LOW_LATENCY
2450                          : HCI_SYNA_ACL_HIGH_PRIORITY;
2451   UINT16_TO_STREAM(pp, p_lcb->Handle());
2452   UINT8_TO_STREAM(pp, vs_param);
2453 
2454   BTM_VendorSpecificCommand(HCI_SYNA_SET_ACL_PRIORITY,
2455                             HCI_SYNA_ACL_PRIORITY_PARAM_SIZE, command, NULL);
2456 }
2457 
2458 /*******************************************************************************
2459  *
2460  * Function         l2cu_set_acl_latency
2461  *
2462  * Description      Sets the transmission latency for a channel.
2463  *
2464  * Returns          true if a valid channel, else false
2465  *
2466  ******************************************************************************/
2467 
l2cu_set_acl_latency(const RawAddress & bd_addr,tL2CAP_LATENCY latency)2468 bool l2cu_set_acl_latency(const RawAddress& bd_addr, tL2CAP_LATENCY latency) {
2469   LOG_INFO("Set ACL low latency: %d", latency);
2470 
2471   /* Find the link control block for the acl channel */
2472   tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR);
2473 
2474   if (p_lcb == nullptr) {
2475     LOG_WARN("Set latency failed: LCB is null");
2476     return false;
2477   }
2478   /* only change controller's latency when stream using latency mode */
2479   if (p_lcb->use_latency_mode && p_lcb->is_high_priority() &&
2480       latency != p_lcb->acl_latency) {
2481     switch (controller_get_interface()->get_bt_version()->manufacturer) {
2482       case LMP_COMPID_BROADCOM:
2483         l2cu_set_acl_latency_brcm(p_lcb, latency);
2484         break;
2485 
2486       case LMP_COMPID_SYNAPTICS:
2487         l2cu_set_acl_latency_syna(p_lcb, latency);
2488         break;
2489 
2490       default:
2491         /* Not supported/required for other vendors */
2492         break;
2493     }
2494     p_lcb->set_latency(latency);
2495   }
2496   /* save the latency mode even if acl does not use latency mode or start*/
2497   p_lcb->preset_acl_latency = latency;
2498 
2499   return true;
2500 }
2501 
2502 /******************************************************************************
2503  *
2504  * Function         l2cu_set_non_flushable_pbf
2505  *
2506  * Description      set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts
2507  *
2508  * Returns          void
2509  *
2510  ******************************************************************************/
l2cu_set_non_flushable_pbf(bool is_supported)2511 void l2cu_set_non_flushable_pbf(bool is_supported) {
2512   if (bluetooth::shim::is_gd_l2cap_enabled()) {
2513     return;
2514   }
2515 
2516   if (is_supported)
2517     l2cb.non_flushable_pbf =
2518         (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT);
2519   else
2520     l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT);
2521 }
2522 
2523 /*******************************************************************************
2524  *
2525  * Function         l2cu_resubmit_pending_sec_req
2526  *
2527  * Description      This function is called when required security procedures
2528  *                  are completed and any pending requests can be re-submitted.
2529  *
2530  * Returns          void
2531  *
2532  ******************************************************************************/
l2cu_resubmit_pending_sec_req(const RawAddress * p_bda)2533 void l2cu_resubmit_pending_sec_req(const RawAddress* p_bda) {
2534   if (bluetooth::shim::is_gd_l2cap_enabled()) {
2535     // GD L2cap will enforce security when condition changed
2536     return;
2537   }
2538 
2539   tL2C_LCB* p_lcb;
2540   tL2C_CCB* p_ccb;
2541   tL2C_CCB* p_next_ccb;
2542   int xx;
2543 
2544   L2CAP_TRACE_DEBUG("l2cu_resubmit_pending_sec_req  p_bda: 0x%08x", p_bda);
2545 
2546   /* If we are called with a BDA, only resubmit for that BDA */
2547   if (p_bda) {
2548     p_lcb = l2cu_find_lcb_by_bd_addr(*p_bda, BT_TRANSPORT_BR_EDR);
2549 
2550     /* If we don't have one, this is an error */
2551     if (p_lcb) {
2552       /* For all channels, send the event through their FSMs */
2553       for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2554         p_next_ccb = p_ccb->p_next_ccb;
2555         l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2556       }
2557     } else {
2558       L2CAP_TRACE_WARNING("l2cu_resubmit_pending_sec_req - unknown BD_ADDR");
2559     }
2560   } else {
2561     /* No BDA pasesed in, so check all links */
2562     for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS;
2563          xx++, p_lcb++) {
2564       if (p_lcb->in_use) {
2565         /* For all channels, send the event through their FSMs */
2566         for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2567           p_next_ccb = p_ccb->p_next_ccb;
2568           l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2569         }
2570       }
2571     }
2572   }
2573 }
2574 
2575 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
2576 /*******************************************************************************
2577  *
2578  * Function         l2cu_set_info_rsp_mask
2579  *
2580  * Description      This function allows the script wrapper to change the
2581  *                  info resp mask for conformance testing.
2582  *
2583  * Returns          pointer to CCB, or NULL if none
2584  *
2585  ******************************************************************************/
l2cu_set_info_rsp_mask(uint32_t mask)2586 void l2cu_set_info_rsp_mask(uint32_t mask) { l2cb.test_info_resp = mask; }
2587 #endif /* L2CAP_CONFORMANCE_TESTING */
2588 
2589 /*******************************************************************************
2590  *
2591  * Function         l2cu_adjust_out_mps
2592  *
2593  * Description      Sets our MPS based on current controller capabilities
2594  *
2595  * Returns          void
2596  *
2597  ******************************************************************************/
l2cu_adjust_out_mps(tL2C_CCB * p_ccb)2598 void l2cu_adjust_out_mps(tL2C_CCB* p_ccb) {
2599   uint16_t packet_size;
2600 
2601   /* on the tx side MTU is selected based on packet size of the controller */
2602   packet_size = BTM_GetMaxPacketSize(p_ccb->p_lcb->remote_bd_addr);
2603 
2604   if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD +
2605                       L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) {
2606     /* something is very wrong */
2607     L2CAP_TRACE_ERROR(
2608         "l2cu_adjust_out_mps bad packet size: %u  will use MPS: %u",
2609         packet_size, p_ccb->peer_cfg.fcr.mps);
2610     p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2611   } else {
2612     packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD +
2613                     L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN);
2614 
2615     /* We try to negotiate MTU that each packet can be split into whole
2616     number of max packets.  For example if link is 1.2 max packet size is 339
2617     bytes.
2618     At first calculate how many whole packets it is.  MAX L2CAP is 1691 + 4
2619     overhead.
2620     1695, that will be 5 Dh5 packets.  Now maximum L2CAP packet is
2621     5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.
2622 
2623     For EDR 2.0 packet size is 1027.  So we better send RFCOMM packet as 1 3DH5
2624     packet
2625     1 * 1027 = 1027.  Minus 4 bytes L2CAP header 1023.  */
2626     if (p_ccb->peer_cfg.fcr.mps >= packet_size)
2627       p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size;
2628     else
2629       p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2630 
2631     L2CAP_TRACE_DEBUG(
2632         "l2cu_adjust_out_mps use %d   Based on peer_cfg.fcr.mps: %u  "
2633         "packet_size: %u",
2634         p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size);
2635   }
2636 }
2637 
2638 /*******************************************************************************
2639  *
2640  * Function         l2cu_initialize_fixed_ccb
2641  *
2642  * Description      Initialize a fixed channel's CCB
2643  *
2644  * Returns          true or false
2645  *
2646  ******************************************************************************/
l2cu_initialize_fixed_ccb(tL2C_LCB * p_lcb,uint16_t fixed_cid)2647 bool l2cu_initialize_fixed_ccb(tL2C_LCB* p_lcb, uint16_t fixed_cid) {
2648   tL2C_CCB* p_ccb;
2649 
2650   /* If we already have a CCB, then simply return */
2651   p_ccb = p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL];
2652   if ((p_ccb != NULL) && p_ccb->in_use) {
2653     /*
2654      * NOTE: The "in_use" check is needed to ignore leftover entries
2655      * that have been already released by l2cu_release_ccb().
2656      */
2657     return (true);
2658   }
2659 
2660   p_ccb = l2cu_allocate_ccb(NULL, 0);
2661   if (p_ccb == NULL) return (false);
2662 
2663   alarm_cancel(p_lcb->l2c_lcb_timer);
2664 
2665   /* Set CID for the connection */
2666   p_ccb->local_cid = fixed_cid;
2667   p_ccb->remote_cid = fixed_cid;
2668 
2669   p_ccb->is_flushable = false;
2670 
2671   /* Link ccb to lcb and lcb to ccb */
2672   p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb;
2673   p_ccb->p_lcb = p_lcb;
2674 
2675   /* There is no configuration, so if the link is up, the channel is up */
2676   if (p_lcb->link_state == LST_CONNECTED) p_ccb->chnl_state = CST_OPEN;
2677 
2678   /* Set the default idle timeout value to use */
2679   p_ccb->fixed_chnl_idle_tout =
2680       l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout;
2681   return (true);
2682 }
2683 
2684 /*******************************************************************************
2685  *
2686  * Function         l2cu_no_dynamic_ccbs
2687  *
2688  * Description      Handles the case when there are no more dynamic CCBs. If
2689  *                  there are any fixed CCBs, start the longest of the fixed CCB
2690  *                  timeouts, otherwise start the default link idle timeout or
2691  *                  disconnect.
2692  *
2693  * Returns          void
2694  *
2695  ******************************************************************************/
l2cu_no_dynamic_ccbs(tL2C_LCB * p_lcb)2696 void l2cu_no_dynamic_ccbs(tL2C_LCB* p_lcb) {
2697   tBTM_STATUS rc;
2698   uint64_t timeout_ms = p_lcb->idle_timeout * 1000;
2699   bool start_timeout = true;
2700 
2701   int xx;
2702 
2703   for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2704     if ((p_lcb->p_fixed_ccbs[xx] != NULL) &&
2705         (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000 > timeout_ms)) {
2706       if (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout ==
2707           L2CAP_NO_IDLE_TIMEOUT) {
2708         L2CAP_TRACE_DEBUG("%s NO IDLE timeout set for fixed cid 0x%04x",
2709                           __func__, p_lcb->p_fixed_ccbs[xx]->local_cid);
2710         start_timeout = false;
2711       }
2712       timeout_ms = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000;
2713     }
2714   }
2715 
2716   /* If the link is pairing, do not mess with the timeouts */
2717   if (p_lcb->IsBonding()) return;
2718 
2719   L2CAP_TRACE_DEBUG("l2cu_no_dynamic_ccbs() with_active_local_clients=%d",
2720                     p_lcb->with_active_local_clients);
2721   // Inactive connections should not timeout, since the ATT channel might still
2722   // be in use even without a GATT client. We only timeout if either a dynamic
2723   // channel or a GATT client was used, since then we expect the client to
2724   // manage the lifecycle of the connection.
2725   if (bluetooth::common::init_flags::finite_att_timeout_is_enabled() &&
2726       !p_lcb->with_active_local_clients) {
2727     return;
2728   }
2729 
2730   if (timeout_ms == 0) {
2731     L2CAP_TRACE_DEBUG(
2732         "l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link");
2733 
2734     rc = btm_sec_disconnect(
2735         p_lcb->Handle(), HCI_ERR_PEER_USER,
2736         "stack::l2cap::l2c_utils::l2cu_no_dynamic_ccbs Idle timer popped");
2737     if (rc == BTM_CMD_STARTED) {
2738       l2cu_process_fixed_disc_cback(p_lcb);
2739       p_lcb->link_state = LST_DISCONNECTING;
2740       timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
2741     } else if (rc == BTM_SUCCESS) {
2742       l2cu_process_fixed_disc_cback(p_lcb);
2743       /* BTM SEC will make sure that link is release (probably after pairing is
2744        * done) */
2745       p_lcb->link_state = LST_DISCONNECTING;
2746       start_timeout = false;
2747     } else if (p_lcb->IsBonding()) {
2748       acl_disconnect_from_handle(
2749           p_lcb->Handle(), HCI_ERR_PEER_USER,
2750           "stack::l2cap::l2c_utils::l2cu_no_dynamic_ccbs Bonding no traffic");
2751       l2cu_process_fixed_disc_cback(p_lcb);
2752       p_lcb->link_state = LST_DISCONNECTING;
2753       timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
2754     } else {
2755       /* probably no buffer to send disconnect */
2756       timeout_ms = BT_1SEC_TIMEOUT_MS;
2757     }
2758   }
2759 
2760   if (start_timeout) {
2761     alarm_set_on_mloop(p_lcb->l2c_lcb_timer, timeout_ms, l2c_lcb_timer_timeout,
2762                        p_lcb);
2763     LOG_DEBUG("Started link IDLE timeout_ms:%lu", (unsigned long)timeout_ms);
2764   } else {
2765     alarm_cancel(p_lcb->l2c_lcb_timer);
2766   }
2767 }
2768 
2769 /*******************************************************************************
2770  *
2771  * Function         l2cu_process_fixed_chnl_resp
2772  *
2773  * Description      handle a fixed channel response (or lack thereof)
2774  *                  if the link failed, or a fixed channel response was
2775  *                  not received, the bitfield is all zeros.
2776  *
2777  ******************************************************************************/
l2cu_process_fixed_chnl_resp(tL2C_LCB * p_lcb)2778 void l2cu_process_fixed_chnl_resp(tL2C_LCB* p_lcb) {
2779   if (p_lcb->transport == BT_TRANSPORT_BR_EDR) {
2780     /* ignore all not assigned BR/EDR channels */
2781     p_lcb->peer_chnl_mask[0] &=
2782         (L2CAP_FIXED_CHNL_SIG_BIT | L2CAP_FIXED_CHNL_CNCTLESS_BIT |
2783          L2CAP_FIXED_CHNL_SMP_BR_BIT);
2784   } else
2785     p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
2786 
2787   /* Tell all registered fixed channels about the connection */
2788   for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2789     uint16_t channel_id = xx + L2CAP_FIRST_FIXED_CHNL;
2790 
2791     /* See BT Spec Ver 5.0 | Vol 3, Part A 2.1 table 2.1 and 2.2 */
2792 
2793     /* skip sending LE fix channel callbacks on BR/EDR links */
2794     if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
2795         channel_id >= L2CAP_ATT_CID && channel_id <= L2CAP_SMP_CID)
2796       continue;
2797 
2798     /* skip sending BR fix channel callbacks on LE links */
2799     if (p_lcb->transport == BT_TRANSPORT_LE && channel_id == L2CAP_SMP_BR_CID)
2800       continue;
2801 
2802     if (!l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb) continue;
2803 
2804     if (p_lcb->peer_chnl_mask[(channel_id) / 8] & (1 << ((channel_id) % 8))) {
2805       if (p_lcb->p_fixed_ccbs[xx])
2806         p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
2807       (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2808           channel_id, p_lcb->remote_bd_addr, true, 0, p_lcb->transport);
2809     } else {
2810       (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2811           channel_id, p_lcb->remote_bd_addr, false, p_lcb->DisconnectReason(),
2812           p_lcb->transport);
2813 
2814       if (p_lcb->p_fixed_ccbs[xx]) {
2815         l2cu_release_ccb(p_lcb->p_fixed_ccbs[xx]);
2816         p_lcb->p_fixed_ccbs[xx] = NULL;
2817       }
2818     }
2819   }
2820 }
2821 
2822 /*******************************************************************************
2823  *
2824  * Function         l2cu_process_fixed_disc_cback
2825  *
2826  * Description      send l2cap fixed channel disconnection callback to the
2827  *                  application
2828  *
2829  * Returns          void
2830  *
2831  ******************************************************************************/
l2cu_process_fixed_disc_cback(tL2C_LCB * p_lcb)2832 void l2cu_process_fixed_disc_cback(tL2C_LCB* p_lcb) {
2833 
2834   /* Select peer channels mask to use depending on transport */
2835   uint8_t peer_channel_mask = p_lcb->peer_chnl_mask[0];
2836 
2837   // For LE, reset the stored peer channel mask
2838   if (p_lcb->transport == BT_TRANSPORT_LE) p_lcb->peer_chnl_mask[0] = 0;
2839 
2840   for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2841     if (p_lcb->p_fixed_ccbs[xx]) {
2842       if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) {
2843         tL2C_CCB* p_l2c_chnl_ctrl_block;
2844         p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
2845         p_lcb->p_fixed_ccbs[xx] = NULL;
2846         l2cu_release_ccb(p_l2c_chnl_ctrl_block);
2847         (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2848             xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2849             p_lcb->DisconnectReason(), p_lcb->transport);
2850       }
2851     } else if ((peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL))) &&
2852                (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL))
2853       (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2854           xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2855           p_lcb->DisconnectReason(), p_lcb->transport);
2856   }
2857 }
2858 
2859 /*******************************************************************************
2860  *
2861  * Function         l2cu_send_peer_ble_par_req
2862  *
2863  * Description      Build and send a BLE parameter update request message
2864  *                  to the peer.
2865  *
2866  * Returns          void
2867  *
2868  ******************************************************************************/
l2cu_send_peer_ble_par_req(tL2C_LCB * p_lcb,uint16_t min_int,uint16_t max_int,uint16_t latency,uint16_t timeout)2869 void l2cu_send_peer_ble_par_req(tL2C_LCB* p_lcb, uint16_t min_int,
2870                                 uint16_t max_int, uint16_t latency,
2871                                 uint16_t timeout) {
2872   BT_HDR* p_buf;
2873   uint8_t* p;
2874 
2875   /* Create an identifier for this packet */
2876   p_lcb->signal_id++;
2877   l2cu_adj_id(p_lcb);
2878 
2879   p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN,
2880                             L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->signal_id);
2881   if (p_buf == NULL) {
2882     L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_req - no buffer");
2883     return;
2884   }
2885 
2886   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2887       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2888 
2889   UINT16_TO_STREAM(p, min_int);
2890   UINT16_TO_STREAM(p, max_int);
2891   UINT16_TO_STREAM(p, latency);
2892   UINT16_TO_STREAM(p, timeout);
2893 
2894   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
2895 }
2896 
2897 /*******************************************************************************
2898  *
2899  * Function         l2cu_send_peer_ble_par_rsp
2900  *
2901  * Description      Build and send a BLE parameter update response message
2902  *                  to the peer.
2903  *
2904  * Returns          void
2905  *
2906  ******************************************************************************/
l2cu_send_peer_ble_par_rsp(tL2C_LCB * p_lcb,uint16_t reason,uint8_t rem_id)2907 void l2cu_send_peer_ble_par_rsp(tL2C_LCB* p_lcb, uint16_t reason,
2908                                 uint8_t rem_id) {
2909   BT_HDR* p_buf;
2910   uint8_t* p;
2911 
2912   p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN,
2913                             L2CAP_CMD_BLE_UPDATE_RSP, rem_id);
2914   if (p_buf == NULL) {
2915     L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_rsp - no buffer");
2916     return;
2917   }
2918 
2919   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2920       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2921 
2922   UINT16_TO_STREAM(p, reason);
2923 
2924   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
2925 }
2926 
2927 /*******************************************************************************
2928  *
2929  * Function         l2cu_send_peer_ble_credit_based_conn_req
2930  *
2931  * Description      Build and send a BLE packet to establish LE connection
2932  *                  oriented L2CAP channel.
2933  *
2934  * Returns          void
2935  *
2936  ******************************************************************************/
l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB * p_ccb)2937 void l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB* p_ccb) {
2938   BT_HDR* p_buf;
2939   uint8_t* p;
2940   tL2C_LCB* p_lcb = NULL;
2941   uint16_t mtu;
2942   uint16_t mps;
2943   uint16_t initial_credit;
2944 
2945   if (!p_ccb) return;
2946   p_lcb = p_ccb->p_lcb;
2947 
2948   /* Create an identifier for this packet */
2949   p_ccb->p_lcb->signal_id++;
2950   l2cu_adj_id(p_ccb->p_lcb);
2951 
2952   p_ccb->local_id = p_ccb->p_lcb->signal_id;
2953 
2954   p_buf =
2955       l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
2956                         L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->signal_id);
2957   if (p_buf == NULL) {
2958     L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2959     return;
2960   }
2961 
2962   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2963       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2964 
2965   mtu = p_ccb->local_conn_cfg.mtu;
2966   mps = p_ccb->local_conn_cfg.mps;
2967   initial_credit = p_ccb->local_conn_cfg.credits;
2968 
2969   L2CAP_TRACE_DEBUG(
2970       "l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
2971                 mtu:%d mps:%d initial_credit:%d",
2972       p_ccb->p_rcb->real_psm, p_ccb->local_cid, mtu, mps, initial_credit);
2973 
2974   UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm);
2975   UINT16_TO_STREAM(p, p_ccb->local_cid);
2976   UINT16_TO_STREAM(p, mtu);
2977   UINT16_TO_STREAM(p, mps);
2978   UINT16_TO_STREAM(p, initial_credit);
2979 
2980   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
2981 }
2982 
2983 /*******************************************************************************
2984  *
2985  * Function         l2cu_send_peer_credit_based_conn_req
2986  *
2987  * Description      Build and send a BLE packet to establish enhanced connection
2988  *                  oriented L2CAP channel.
2989  *
2990  * Returns          void
2991  *
2992  ******************************************************************************/
l2cu_send_peer_credit_based_conn_req(tL2C_CCB * p_ccb)2993 void l2cu_send_peer_credit_based_conn_req(tL2C_CCB* p_ccb) {
2994   BT_HDR* p_buf;
2995   uint8_t* p;
2996   tL2C_LCB* p_lcb = NULL;
2997   uint16_t mtu;
2998   uint16_t mps;
2999   uint16_t initial_credit;
3000 
3001   if (!p_ccb) return;
3002 
3003   p_lcb = p_ccb->p_lcb;
3004 
3005   /* Create an identifier for this packet */
3006   p_ccb->p_lcb->signal_id++;
3007   l2cu_adj_id(p_ccb->p_lcb);
3008 
3009   p_ccb->local_id = p_lcb->signal_id;
3010 
3011   p_buf = l2cu_build_header(p_lcb,
3012                             L2CAP_CMD_CREDIT_BASED_CONN_REQ_MIN_LEN +
3013                                 2 * p_lcb->pending_ecoc_conn_cnt,
3014                             L2CAP_CMD_CREDIT_BASED_CONN_REQ, p_ccb->local_id);
3015   if (p_buf == NULL) {
3016     L2CAP_TRACE_WARNING("%s - no buffer", __func__);
3017     return;
3018   }
3019 
3020   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3021       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3022 
3023   mtu = p_ccb->local_conn_cfg.mtu;
3024   mps = p_ccb->local_conn_cfg.mps;
3025   initial_credit = p_ccb->local_conn_cfg.credits;
3026 
3027   L2CAP_TRACE_DEBUG(
3028       "%s PSM:0x%04x mtu:%d mps:%d initial_credit:%d, cids_cnt %d", __func__,
3029       p_ccb->p_rcb->real_psm, mtu, mps, initial_credit,
3030       p_lcb->pending_ecoc_conn_cnt);
3031 
3032   UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm);
3033   UINT16_TO_STREAM(p, mtu);
3034   UINT16_TO_STREAM(p, mps);
3035   UINT16_TO_STREAM(p, initial_credit);
3036 
3037   for (int i = 0; i < p_lcb->pending_ecoc_conn_cnt; i++) {
3038     uint16_t cid = p_lcb->pending_ecoc_connection_cids[i];
3039     L2CAP_TRACE_DEBUG("\n\t cid: ", cid);
3040     UINT16_TO_STREAM(p, cid);
3041   }
3042 
3043   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
3044 }
3045 
3046 /*******************************************************************************
3047  *
3048  * Function         l2cu_reject_ble_coc_connection
3049  *
3050  * Description      Build and send an L2CAP "Credit based connection res"
3051  *                  message to the peer. This function is called for non-success
3052  *                  cases.
3053  *
3054  * Returns          void
3055  *
3056  ******************************************************************************/
l2cu_reject_ble_coc_connection(tL2C_LCB * p_lcb,uint8_t rem_id,uint16_t result)3057 void l2cu_reject_ble_coc_connection(tL2C_LCB* p_lcb, uint8_t rem_id,
3058                                     uint16_t result) {
3059   BT_HDR* p_buf;
3060   uint8_t* p;
3061 
3062   p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3063                             L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id);
3064   if (p_buf == NULL) {
3065     L2CAP_TRACE_WARNING("l2cu_reject_ble_coc_connection - no buffer");
3066     return;
3067   }
3068 
3069   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3070       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3071 
3072   UINT16_TO_STREAM(p, 0); /* Local CID of 0   */
3073   UINT16_TO_STREAM(p, 0); /* MTU */
3074   UINT16_TO_STREAM(p, 0); /* MPS */
3075   UINT16_TO_STREAM(p, 0); /* initial credit */
3076   UINT16_TO_STREAM(p, result);
3077 
3078   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
3079 }
3080 
3081 /*******************************************************************************
3082  *
3083  * Function         l2cu_reject_credit_based_connection_req
3084  *
3085  * Description      Build and send an L2CAP "credit based connection
3086  *res" message to the peer. This function is called for non-success cases.
3087  *
3088  * Returns          void
3089  *
3090  ******************************************************************************/
l2cu_reject_credit_based_conn_req(tL2C_LCB * p_lcb,uint8_t rem_id,uint8_t num_of_channels,uint16_t result)3091 void l2cu_reject_credit_based_conn_req(tL2C_LCB* p_lcb, uint8_t rem_id,
3092                                        uint8_t num_of_channels,
3093                                        uint16_t result) {
3094   BT_HDR* p_buf;
3095   uint8_t* p;
3096   uint8_t rsp_len = L2CAP_CMD_CREDIT_BASED_CONN_RES_MIN_LEN +
3097                     sizeof(uint16_t) * num_of_channels;
3098 
3099   p_buf = l2cu_build_header(p_lcb, rsp_len, L2CAP_CMD_CREDIT_BASED_CONN_RES,
3100                             rem_id);
3101   if (p_buf == NULL) {
3102     L2CAP_TRACE_WARNING("l2cu_reject_credit_based_conn_req - no buffer");
3103     return;
3104   }
3105 
3106   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3107       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3108 
3109   memset(p, 0, rsp_len);
3110   UINT16_TO_STREAM(p, L2CAP_CREDIT_BASED_MIN_MTU); /* dummy MTU to satisy PTS */
3111   UINT16_TO_STREAM(p, L2CAP_CREDIT_BASED_MIN_MPS); /* dummy MPS to satisy PTS*/
3112   UINT16_TO_STREAM(p, 1); /* dummy initial credit to satisy PTS */
3113   UINT16_TO_STREAM(p, result);
3114 
3115   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
3116 }
3117 
3118 /*******************************************************************************
3119  *
3120  * Function         l2cu_send_peer_credit_based_conn_res
3121  *
3122  * Description      Build and send an L2CAP "Credit based connection res"
3123  *                  message to the peer. This function is called in case of
3124  *                  success.
3125  *
3126  * Returns          void
3127  *
3128  ******************************************************************************/
l2cu_send_peer_credit_based_conn_res(tL2C_CCB * p_ccb,std::vector<uint16_t> & accepted_cids,uint16_t result)3129 void l2cu_send_peer_credit_based_conn_res(tL2C_CCB* p_ccb,
3130                                           std::vector<uint16_t>& accepted_cids,
3131                                           uint16_t result) {
3132   BT_HDR* p_buf;
3133   uint8_t* p;
3134 
3135   L2CAP_TRACE_DEBUG("%s", __func__);
3136   uint8_t rsp_len = L2CAP_CMD_CREDIT_BASED_CONN_RES_MIN_LEN +
3137                     p_ccb->p_lcb->pending_ecoc_conn_cnt * sizeof(uint16_t);
3138 
3139   p_buf = l2cu_build_header(p_ccb->p_lcb, rsp_len,
3140                             L2CAP_CMD_CREDIT_BASED_CONN_RES, p_ccb->remote_id);
3141   if (p_buf == NULL) {
3142     L2CAP_TRACE_WARNING("%s - no buffer", __func__);
3143     return;
3144   }
3145 
3146   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3147       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3148 
3149   memset(p, 0, rsp_len);
3150   UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mtu);     /* MTU */
3151   UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mps);     /* MPS */
3152   UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.credits); /* initial credit */
3153 
3154   if (result == L2CAP_CONN_OK) {
3155     /* In case of success, we need to check if stack
3156      * did not have previous result stored e.g. when there was no
3157      * resources for allocation all the requrested channels,
3158      * before user indication.
3159      */
3160     result = p_ccb->p_lcb->pending_l2cap_result;
3161   }
3162 
3163   UINT16_TO_STREAM(p, result);
3164 
3165   /* We need to keep order from the request.
3166    * if this vector contais 0 it means channel has been rejected by
3167    * the stack.
3168    * If there is valid cid, we need to verify if it is accepted by upper layer.
3169    */
3170   for (int i = 0; i < p_ccb->p_lcb->pending_ecoc_conn_cnt; i++) {
3171     uint16_t cid = p_ccb->p_lcb->pending_ecoc_connection_cids[i];
3172     if (cid == 0) {
3173       UINT16_TO_STREAM(p, 0);
3174       continue;
3175     }
3176     auto it = std::find(accepted_cids.begin(), accepted_cids.end(), cid);
3177     if (it != accepted_cids.end()) {
3178       UINT16_TO_STREAM(p, cid);
3179     } else {
3180       UINT16_TO_STREAM(p, 0);
3181     }
3182   }
3183 
3184   l2c_link_check_send_pkts(p_ccb->p_lcb, 0, p_buf);
3185 }
3186 
3187 /*******************************************************************************
3188  *
3189  * Function         l2cu_reject_ble_connection
3190  *
3191  * Description      Build and send an L2CAP "Credit based connection res"
3192  *                  message to the peer. This function is called for non-success
3193  *                  cases.
3194  *
3195  * Returns          void
3196  *
3197  ******************************************************************************/
l2cu_reject_ble_connection(tL2C_CCB * p_ccb,uint8_t rem_id,uint16_t result)3198 void l2cu_reject_ble_connection(tL2C_CCB* p_ccb, uint8_t rem_id,
3199                                 uint16_t result) {
3200   if (p_ccb->ecoc)
3201     l2cu_reject_credit_based_conn_req(
3202         p_ccb->p_lcb, rem_id, p_ccb->p_lcb->pending_ecoc_conn_cnt, result);
3203   else
3204     l2cu_reject_ble_coc_connection(p_ccb->p_lcb, rem_id, result);
3205 }
3206 
3207 /*******************************************************************************
3208  *
3209  * Function         l2cu_send_ble_reconfig_rsp
3210  *
3211  * Description      Build and send an L2CAP "Credit based reconfig res"
3212  *                  message to the peer. This function is called for non-success
3213  *                  cases.
3214  *
3215  * Returns          void
3216  *
3217  ******************************************************************************/
3218 
l2cu_send_ble_reconfig_rsp(tL2C_LCB * p_lcb,uint8_t rem_id,uint16_t result)3219 void l2cu_send_ble_reconfig_rsp(tL2C_LCB* p_lcb, uint8_t rem_id,
3220                                 uint16_t result) {
3221   BT_HDR* p_buf;
3222   uint8_t* p;
3223 
3224   L2CAP_TRACE_DEBUG("l2cu_send_ble_reconfig_rsp result 0x04%x", result);
3225 
3226   p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_CREDIT_BASED_RECONFIG_RES_LEN,
3227                             L2CAP_CMD_CREDIT_BASED_RECONFIG_RES, rem_id);
3228   if (p_buf == NULL) {
3229     L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
3230     return;
3231   }
3232 
3233   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3234       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3235 
3236   memset(p, 0, L2CAP_CMD_CREDIT_BASED_RECONFIG_RES_LEN);
3237   UINT16_TO_STREAM(p, result);
3238 
3239   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
3240 }
3241 
3242 /*******************************************************************************
3243  *
3244  * Function         l2cu_send_peer_ble_credit_based_conn_res
3245  *
3246  * Description      Build and send an L2CAP "Credit based connection res"
3247  *                  message to the peer. This function is called in case of
3248  *                  success.
3249  *
3250  * Returns          void
3251  *
3252  ******************************************************************************/
l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB * p_ccb,uint16_t result)3253 void l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB* p_ccb,
3254                                               uint16_t result) {
3255   BT_HDR* p_buf;
3256   uint8_t* p;
3257 
3258   L2CAP_TRACE_DEBUG("l2cu_send_peer_ble_credit_based_conn_res");
3259   p_buf =
3260       l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3261                         L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id);
3262   if (p_buf == NULL) {
3263     L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
3264     return;
3265   }
3266 
3267   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3268       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3269 
3270   UINT16_TO_STREAM(p, p_ccb->local_cid);              /* Local CID */
3271   UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mtu);     /* MTU */
3272   UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mps);     /* MPS */
3273   UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.credits); /* initial credit */
3274   UINT16_TO_STREAM(p, result);
3275 
3276   l2c_link_check_send_pkts(p_ccb->p_lcb, 0, p_buf);
3277 }
3278 
3279 /*******************************************************************************
3280  *
3281  * Function         l2cu_send_peer_ble_flow_control_credit
3282  *
3283  * Description      Build and send a BLE packet to give credits to peer device
3284  *                  for LE connection oriented L2CAP channel.
3285  *
3286  * Returns          void
3287  *
3288  ******************************************************************************/
l2cu_send_peer_ble_flow_control_credit(tL2C_CCB * p_ccb,uint16_t credit_value)3289 void l2cu_send_peer_ble_flow_control_credit(tL2C_CCB* p_ccb,
3290                                             uint16_t credit_value) {
3291   BT_HDR* p_buf;
3292   uint8_t* p;
3293   tL2C_LCB* p_lcb = NULL;
3294 
3295   if (!p_ccb) return;
3296   p_lcb = p_ccb->p_lcb;
3297 
3298   /* Create an identifier for this packet */
3299   p_ccb->p_lcb->signal_id++;
3300   l2cu_adj_id(p_ccb->p_lcb);
3301 
3302   p_ccb->local_id = p_ccb->p_lcb->signal_id;
3303 
3304   p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
3305                             L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->signal_id);
3306   if (p_buf == NULL) {
3307     L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
3308     return;
3309   }
3310 
3311   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3312       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3313 
3314   UINT16_TO_STREAM(p, p_ccb->local_cid);
3315   UINT16_TO_STREAM(p, credit_value);
3316 
3317   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
3318 }
3319 
3320 /*******************************************************************************
3321  *
3322  * Function         l2cu_send_peer_ble_credit_based_conn_req
3323  *
3324  * Description      Build and send a BLE packet to disconnect LE connection
3325  *                  oriented L2CAP channel.
3326  *
3327  * Returns          void
3328  *
3329  ******************************************************************************/
l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB * p_ccb)3330 void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB* p_ccb) {
3331   BT_HDR* p_buf;
3332   uint8_t* p;
3333   tL2C_LCB* p_lcb = NULL;
3334   L2CAP_TRACE_DEBUG("%s", __func__);
3335 
3336   if (!p_ccb) return;
3337   p_lcb = p_ccb->p_lcb;
3338 
3339   /* Create an identifier for this packet */
3340   p_ccb->p_lcb->signal_id++;
3341   l2cu_adj_id(p_ccb->p_lcb);
3342 
3343   p_ccb->local_id = p_ccb->p_lcb->signal_id;
3344   p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_REQ_LEN, L2CAP_CMD_DISC_REQ,
3345                             p_lcb->signal_id);
3346   if (p_buf == NULL) {
3347     L2CAP_TRACE_WARNING(
3348         "l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
3349     return;
3350   }
3351 
3352   p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3353       L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3354 
3355   UINT16_TO_STREAM(p, p_ccb->remote_cid);
3356   UINT16_TO_STREAM(p, p_ccb->local_cid);
3357 
3358   l2c_link_check_send_pkts(p_lcb, 0, p_buf);
3359 }
3360 
3361 /*******************************************************************************
3362  * Functions used by both Full and Light Stack
3363  ******************************************************************************/
3364 
3365 /*******************************************************************************
3366  *
3367  * Function         l2cu_find_lcb_by_handle
3368  *
3369  * Description      Look through all active LCBs for a match based on the
3370  *                  HCI handle.
3371  *
3372  * Returns          pointer to matched LCB, or NULL if no match
3373  *
3374  ******************************************************************************/
l2cu_find_lcb_by_handle(uint16_t handle)3375 tL2C_LCB* l2cu_find_lcb_by_handle(uint16_t handle) {
3376   int xx;
3377   tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
3378 
3379   for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
3380     if ((p_lcb->in_use) && (p_lcb->Handle() == handle)) {
3381       return (p_lcb);
3382     }
3383   }
3384 
3385   /* If here, no match found */
3386   return (NULL);
3387 }
3388 
3389 /*******************************************************************************
3390  *
3391  * Function         l2cu_find_ccb_by_cid
3392  *
3393  * Description      Look through all active CCBs on a link for a match based
3394  *                  on the local CID. If passed the link pointer is NULL, all
3395  *                  active links are searched.
3396  *
3397  * Returns          pointer to matched CCB, or NULL if no match
3398  *
3399  ******************************************************************************/
l2cu_find_ccb_by_cid(tL2C_LCB * p_lcb,uint16_t local_cid)3400 tL2C_CCB* l2cu_find_ccb_by_cid(tL2C_LCB* p_lcb, uint16_t local_cid) {
3401   tL2C_CCB* p_ccb = NULL;
3402   if (local_cid >= L2CAP_BASE_APPL_CID) {
3403     /* find the associated CCB by "index" */
3404     local_cid -= L2CAP_BASE_APPL_CID;
3405 
3406     if (local_cid >= MAX_L2CAP_CHANNELS) return NULL;
3407 
3408     p_ccb = l2cb.ccb_pool + local_cid;
3409 
3410     /* make sure the CCB is in use */
3411     if (!p_ccb->in_use) {
3412       p_ccb = NULL;
3413     }
3414     /* make sure it's for the same LCB */
3415     else if (p_lcb && p_lcb != p_ccb->p_lcb) {
3416       p_ccb = NULL;
3417     }
3418   }
3419   return (p_ccb);
3420 }
3421 
3422 /******************************************************************************
3423  *
3424  * Function         l2cu_set_acl_hci_header
3425  *
3426  * Description      Set HCI handle for ACL packet
3427  *
3428  * Returns          None
3429  *
3430  ******************************************************************************/
l2cu_set_acl_hci_header(BT_HDR * p_buf,tL2C_CCB * p_ccb)3431 void l2cu_set_acl_hci_header(BT_HDR* p_buf, tL2C_CCB* p_ccb) {
3432   uint8_t* p;
3433 
3434   /* Set the pointer to the beginning of the data minus 4 bytes for the packet
3435    * header */
3436   p = (uint8_t*)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE;
3437 
3438   if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3439     UINT16_TO_STREAM(p, p_ccb->p_lcb->Handle() | (L2CAP_PKT_START_NON_FLUSHABLE
3440                                                   << L2CAP_PKT_TYPE_SHIFT));
3441 
3442     uint16_t acl_data_size =
3443         controller_get_interface()->get_acl_data_size_ble();
3444     /* The HCI transport will segment the buffers. */
3445     if (p_buf->len > acl_data_size) {
3446       UINT16_TO_STREAM(p, acl_data_size);
3447     } else {
3448       UINT16_TO_STREAM(p, p_buf->len);
3449     }
3450   } else {
3451     if (((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) ==
3452          L2CAP_FLUSHABLE_CH_BASED) &&
3453         (p_ccb->is_flushable)) {
3454       UINT16_TO_STREAM(p, p_ccb->p_lcb->Handle() |
3455                               (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3456     } else {
3457       UINT16_TO_STREAM(p, p_ccb->p_lcb->Handle() | l2cb.non_flushable_pbf);
3458     }
3459 
3460     uint16_t acl_data_size =
3461         controller_get_interface()->get_acl_data_size_classic();
3462     /* The HCI transport will segment the buffers. */
3463     if (p_buf->len > acl_data_size) {
3464       UINT16_TO_STREAM(p, acl_data_size);
3465     } else {
3466       UINT16_TO_STREAM(p, p_buf->len);
3467     }
3468   }
3469   p_buf->offset -= HCI_DATA_PREAMBLE_SIZE;
3470   p_buf->len += HCI_DATA_PREAMBLE_SIZE;
3471 }
3472 
send_congestion_status_to_all_clients(tL2C_CCB * p_ccb,bool status)3473 static void send_congestion_status_to_all_clients(tL2C_CCB* p_ccb,
3474                                                   bool status) {
3475   p_ccb->cong_sent = status;
3476 
3477   if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3478     L2CAP_TRACE_DEBUG(
3479         "L2CAP - Calling CongestionStatus_Cb (%d), CID: 0x%04x "
3480         "xmit_hold_q.count: %u  buff_quota: %u",
3481         status, p_ccb->local_cid, fixed_queue_length(p_ccb->xmit_hold_q),
3482         p_ccb->buff_quota);
3483 
3484     /* Prevent recursive calling */
3485     if (status == false) l2cb.is_cong_cback_context = true;
3486 
3487     (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, status);
3488 
3489     if (status == false) l2cb.is_cong_cback_context = false;
3490   }
3491   else {
3492     for (uint8_t xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3493       if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3494         if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
3495           (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr,
3496                                                    status);
3497         break;
3498       }
3499     }
3500   }
3501 }
3502 
3503 /* check if any change in congestion status */
l2cu_check_channel_congestion(tL2C_CCB * p_ccb)3504 void l2cu_check_channel_congestion(tL2C_CCB* p_ccb) {
3505   /* If the CCB queue limit is subject to a quota, check for congestion if this
3506    * channel has outgoing traffic */
3507   if (p_ccb->buff_quota == 0) return;
3508 
3509   size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
3510 
3511   if (p_ccb->cong_sent) {
3512     /* if channel was congested, but is not congested now, tell the app */
3513     if (q_count <= (p_ccb->buff_quota / 2))
3514       send_congestion_status_to_all_clients(p_ccb, false);
3515   } else {
3516     /* if channel was not congested, but is congested now, tell the app */
3517     if (q_count > p_ccb->buff_quota)
3518       send_congestion_status_to_all_clients(p_ccb, true);
3519   }
3520 }
3521 
3522 /*******************************************************************************
3523  *
3524  * Function         l2cu_is_ccb_active
3525  *
3526  * Description      Check if Channel Control Block is in use or released
3527  *
3528  * Returns          bool    - true if Channel Control Block is in use
3529  *                            false if p_ccb is null or is released.
3530  *
3531  ******************************************************************************/
l2cu_is_ccb_active(tL2C_CCB * p_ccb)3532 bool l2cu_is_ccb_active(tL2C_CCB* p_ccb) { return (p_ccb && p_ccb->in_use); }
3533 
3534 /*******************************************************************************
3535  *
3536  * Function         le_result_to_l2c_conn
3537  *
3538  * Description      Connvert an LE result code to L2C connection code.
3539  *
3540  * Returns          The converted L2C connection code.
3541  *
3542  ******************************************************************************/
le_result_to_l2c_conn(uint16_t result)3543 uint16_t le_result_to_l2c_conn(uint16_t result) {
3544   tL2CAP_LE_RESULT_CODE code = (tL2CAP_LE_RESULT_CODE)result;
3545   switch (code) {
3546     case L2CAP_LE_RESULT_CONN_OK:
3547     case L2CAP_LE_RESULT_NO_PSM:
3548     case L2CAP_LE_RESULT_NO_RESOURCES:
3549       return code;
3550     case L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION:
3551     case L2CAP_LE_RESULT_INSUFFICIENT_AUTHORIZATION:
3552     case L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP_KEY_SIZE:
3553     case L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP:
3554     case L2CAP_LE_RESULT_INVALID_SOURCE_CID:
3555     case L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED:
3556     case L2CAP_LE_RESULT_UNACCEPTABLE_PARAMETERS:
3557     case L2CAP_LE_RESULT_INVALID_PARAMETERS:
3558       return L2CAP_CONN_LE_MASK | code;
3559     default:
3560       if (result < L2CAP_CONN_LE_MASK) {
3561         return L2CAP_CONN_LE_MASK | code;
3562       }
3563       return L2CAP_CONN_OTHER_ERROR;
3564   }
3565 }
3566