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