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