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 <= SVC_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 = SVC_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 (p_inq_info->results.inq_result_type & BTM_INQ_RESULT_BR)) {
2249 page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
2250 page_scan_mode = p_inq_info->results.page_scan_mode;
2251 clock_offset = (uint16_t)(p_inq_info->results.clock_offset);
2252 } else {
2253 /* No info known. Use default settings */
2254 page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
2255 page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
2256
2257 clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
2258 }
2259
2260 btsnd_hcic_create_conn(
2261 p_lcb->remote_bd_addr, (HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1 |
2262 HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3 |
2263 HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5),
2264 page_scan_rep_mode, page_scan_mode, clock_offset, allow_switch);
2265
2266 btm_acl_update_busy_level(BTM_BLI_PAGE_EVT);
2267
2268 alarm_set_on_mloop(p_lcb->l2c_lcb_timer, L2CAP_LINK_CONNECT_TIMEOUT_MS,
2269 l2c_lcb_timer_timeout, p_lcb);
2270
2271 return (true);
2272 }
2273
2274 /*******************************************************************************
2275 *
2276 * Function l2cu_find_lcb_by_state
2277 *
2278 * Description Look through all active LCBs for a match based on the
2279 * LCB state.
2280 *
2281 * Returns pointer to first matched LCB, or NULL if no match
2282 *
2283 ******************************************************************************/
l2cu_find_lcb_by_state(tL2C_LINK_STATE state)2284 tL2C_LCB* l2cu_find_lcb_by_state(tL2C_LINK_STATE state) {
2285 uint16_t i;
2286 tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
2287
2288 for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2289 if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
2290 return (p_lcb);
2291 }
2292 }
2293
2294 /* If here, no match found */
2295 return (NULL);
2296 }
2297
2298 /*******************************************************************************
2299 *
2300 * Function l2cu_lcb_disconnecting
2301 *
2302 * Description On each active lcb, check if the lcb is in disconnecting
2303 * state, or if there are no ccb's on the lcb (implying
2304 idle timeout is running), or if last ccb on the link
2305 is in disconnecting state.
2306 *
2307 * Returns true if any of above conditions met, false otherwise
2308 *
2309 ******************************************************************************/
l2cu_lcb_disconnecting(void)2310 bool l2cu_lcb_disconnecting(void) {
2311 tL2C_LCB* p_lcb;
2312 tL2C_CCB* p_ccb;
2313 uint16_t i;
2314 bool status = false;
2315
2316 p_lcb = &l2cb.lcb_pool[0];
2317
2318 for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2319 if (p_lcb->in_use) {
2320 /* no ccbs on lcb, or lcb is in disconnecting state */
2321 if ((!p_lcb->ccb_queue.p_first_ccb) ||
2322 (p_lcb->link_state == LST_DISCONNECTING)) {
2323 status = true;
2324 break;
2325 }
2326 /* only one ccb left on lcb */
2327 else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) {
2328 p_ccb = p_lcb->ccb_queue.p_first_ccb;
2329
2330 if ((p_ccb->in_use) &&
2331 ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
2332 (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
2333 status = true;
2334 break;
2335 }
2336 }
2337 }
2338 }
2339 return status;
2340 }
2341
2342 /*******************************************************************************
2343 *
2344 * Function l2cu_set_acl_priority
2345 *
2346 * Description Sets the transmission priority for a channel.
2347 * (For initial implementation only two values are valid.
2348 * L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
2349 *
2350 * Returns true if a valid channel, else false
2351 *
2352 ******************************************************************************/
2353
l2cu_set_acl_priority(const RawAddress & bd_addr,uint8_t priority,bool reset_after_rs)2354 bool l2cu_set_acl_priority(const RawAddress& bd_addr, uint8_t priority,
2355 bool reset_after_rs) {
2356 tL2C_LCB* p_lcb;
2357 uint8_t* pp;
2358 uint8_t command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2359 uint8_t vs_param;
2360
2361 APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority);
2362
2363 /* Find the link control block for the acl channel */
2364 p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR);
2365 if (p_lcb == NULL) {
2366 L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_SetAclPriority");
2367 return (false);
2368 }
2369
2370 if (BTM_IS_BRCM_CONTROLLER()) {
2371 /* Called from above L2CAP through API; send VSC if changed */
2372 if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||
2373 /* Called because of a master/slave role switch; if high resend VSC */
2374 (reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2375 pp = command;
2376
2377 vs_param = (priority == L2CAP_PRIORITY_HIGH) ? HCI_BRCM_ACL_PRIORITY_HIGH
2378 : HCI_BRCM_ACL_PRIORITY_LOW;
2379
2380 UINT16_TO_STREAM(pp, p_lcb->handle);
2381 UINT8_TO_STREAM(pp, vs_param);
2382
2383 BTM_VendorSpecificCommand(HCI_BRCM_SET_ACL_PRIORITY,
2384 HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command,
2385 NULL);
2386 }
2387 }
2388
2389 /* Adjust lmp buffer allocation for this channel if priority changed */
2390 if (p_lcb->acl_priority != priority) {
2391 p_lcb->acl_priority = priority;
2392 l2c_link_adjust_allocation();
2393 }
2394 return (true);
2395 }
2396
2397 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
2398 /******************************************************************************
2399 *
2400 * Function l2cu_set_non_flushable_pbf
2401 *
2402 * Description set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts
2403 *
2404 * Returns void
2405 *
2406 ******************************************************************************/
l2cu_set_non_flushable_pbf(bool is_supported)2407 void l2cu_set_non_flushable_pbf(bool is_supported) {
2408 if (is_supported)
2409 l2cb.non_flushable_pbf =
2410 (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT);
2411 else
2412 l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT);
2413 }
2414 #endif
2415
2416 /*******************************************************************************
2417 *
2418 * Function l2cu_resubmit_pending_sec_req
2419 *
2420 * Description This function is called when required security procedures
2421 * are completed and any pending requests can be re-submitted.
2422 *
2423 * Returns void
2424 *
2425 ******************************************************************************/
l2cu_resubmit_pending_sec_req(const RawAddress * p_bda)2426 void l2cu_resubmit_pending_sec_req(const RawAddress* p_bda) {
2427 tL2C_LCB* p_lcb;
2428 tL2C_CCB* p_ccb;
2429 tL2C_CCB* p_next_ccb;
2430 int xx;
2431
2432 L2CAP_TRACE_DEBUG("l2cu_resubmit_pending_sec_req p_bda: 0x%08x", p_bda);
2433
2434 /* If we are called with a BDA, only resubmit for that BDA */
2435 if (p_bda) {
2436 p_lcb = l2cu_find_lcb_by_bd_addr(*p_bda, BT_TRANSPORT_BR_EDR);
2437
2438 /* If we don't have one, this is an error */
2439 if (p_lcb) {
2440 /* For all channels, send the event through their FSMs */
2441 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2442 p_next_ccb = p_ccb->p_next_ccb;
2443 l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2444 }
2445 } else {
2446 L2CAP_TRACE_WARNING("l2cu_resubmit_pending_sec_req - unknown BD_ADDR");
2447 }
2448 } else {
2449 /* No BDA pasesed in, so check all links */
2450 for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS;
2451 xx++, p_lcb++) {
2452 if (p_lcb->in_use) {
2453 /* For all channels, send the event through their FSMs */
2454 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2455 p_next_ccb = p_ccb->p_next_ccb;
2456 l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2457 }
2458 }
2459 }
2460 }
2461 }
2462
2463 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
2464 /*******************************************************************************
2465 *
2466 * Function l2cu_set_info_rsp_mask
2467 *
2468 * Description This function allows the script wrapper to change the
2469 * info resp mask for conformance testing.
2470 *
2471 * Returns pointer to CCB, or NULL if none
2472 *
2473 ******************************************************************************/
l2cu_set_info_rsp_mask(uint32_t mask)2474 void l2cu_set_info_rsp_mask(uint32_t mask) { l2cb.test_info_resp = mask; }
2475 #endif /* L2CAP_CONFORMANCE_TESTING */
2476
2477 /*******************************************************************************
2478 *
2479 * Function l2cu_adjust_out_mps
2480 *
2481 * Description Sets our MPS based on current controller capabilities
2482 *
2483 * Returns void
2484 *
2485 ******************************************************************************/
l2cu_adjust_out_mps(tL2C_CCB * p_ccb)2486 void l2cu_adjust_out_mps(tL2C_CCB* p_ccb) {
2487 uint16_t packet_size;
2488
2489 /* on the tx side MTU is selected based on packet size of the controller */
2490 packet_size = btm_get_max_packet_size(p_ccb->p_lcb->remote_bd_addr);
2491
2492 if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD +
2493 L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) {
2494 /* something is very wrong */
2495 L2CAP_TRACE_ERROR(
2496 "l2cu_adjust_out_mps bad packet size: %u will use MPS: %u",
2497 packet_size, p_ccb->peer_cfg.fcr.mps);
2498 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2499 } else {
2500 packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD +
2501 L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN);
2502
2503 /* We try to negotiate MTU that each packet can be split into whole
2504 number of max packets. For example if link is 1.2 max packet size is 339
2505 bytes.
2506 At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4
2507 overhead.
2508 1695, that will be 5 Dh5 packets. Now maximum L2CAP packet is
2509 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.
2510
2511 For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1 3DH5
2512 packet
2513 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. */
2514 if (p_ccb->peer_cfg.fcr.mps >= packet_size)
2515 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size;
2516 else
2517 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2518
2519 L2CAP_TRACE_DEBUG(
2520 "l2cu_adjust_out_mps use %d Based on peer_cfg.fcr.mps: %u "
2521 "packet_size: %u",
2522 p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size);
2523 }
2524 }
2525
2526 /*******************************************************************************
2527 *
2528 * Function l2cu_initialize_fixed_ccb
2529 *
2530 * Description Initialize a fixed channel's CCB
2531 *
2532 * Returns true or false
2533 *
2534 ******************************************************************************/
l2cu_initialize_fixed_ccb(tL2C_LCB * p_lcb,uint16_t fixed_cid,tL2CAP_FCR_OPTS * p_fcr)2535 bool l2cu_initialize_fixed_ccb(tL2C_LCB* p_lcb, uint16_t fixed_cid,
2536 tL2CAP_FCR_OPTS* p_fcr) {
2537 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2538 tL2C_CCB* p_ccb;
2539
2540 /* If we already have a CCB, then simply return */
2541 p_ccb = p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL];
2542 if ((p_ccb != NULL) && p_ccb->in_use) {
2543 /*
2544 * NOTE: The "in_use" check is needed to ignore leftover entries
2545 * that have been already released by l2cu_release_ccb().
2546 */
2547 return (true);
2548 }
2549
2550 p_ccb = l2cu_allocate_ccb(NULL, 0);
2551 if (p_ccb == NULL) return (false);
2552
2553 alarm_cancel(p_lcb->l2c_lcb_timer);
2554
2555 /* Set CID for the connection */
2556 p_ccb->local_cid = fixed_cid;
2557 p_ccb->remote_cid = fixed_cid;
2558
2559 p_ccb->is_flushable = false;
2560
2561 if (p_fcr) {
2562 /* Set the FCR parameters. For now, we will use default pools */
2563 p_ccb->our_cfg.fcr = p_ccb->peer_cfg.fcr = *p_fcr;
2564
2565 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
2566 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
2567 p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
2568 p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
2569
2570 p_ccb->fcrb.max_held_acks = p_fcr->tx_win_sz / 3;
2571 }
2572
2573 /* Link ccb to lcb and lcb to ccb */
2574 p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb;
2575 p_ccb->p_lcb = p_lcb;
2576
2577 /* There is no configuration, so if the link is up, the channel is up */
2578 if (p_lcb->link_state == LST_CONNECTED) p_ccb->chnl_state = CST_OPEN;
2579
2580 /* Set the default idle timeout value to use */
2581 p_ccb->fixed_chnl_idle_tout =
2582 l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout;
2583 #endif
2584 return (true);
2585 }
2586
2587 /*******************************************************************************
2588 *
2589 * Function l2cu_no_dynamic_ccbs
2590 *
2591 * Description Handles the case when there are no more dynamic CCBs. If
2592 * there are any fixed CCBs, start the longest of the fixed CCB
2593 * timeouts, otherwise start the default link idle timeout or
2594 * disconnect.
2595 *
2596 * Returns void
2597 *
2598 ******************************************************************************/
l2cu_no_dynamic_ccbs(tL2C_LCB * p_lcb)2599 void l2cu_no_dynamic_ccbs(tL2C_LCB* p_lcb) {
2600 tBTM_STATUS rc;
2601 uint64_t timeout_ms = p_lcb->idle_timeout * 1000;
2602 bool start_timeout = true;
2603
2604 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2605 int xx;
2606
2607 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2608 if ((p_lcb->p_fixed_ccbs[xx] != NULL) &&
2609 (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000 > timeout_ms)) {
2610
2611 if (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout == L2CAP_NO_IDLE_TIMEOUT) {
2612 L2CAP_TRACE_DEBUG("%s NO IDLE timeout set for fixed cid 0x%04x", __func__,
2613 p_lcb->p_fixed_ccbs[xx]->local_cid);
2614 start_timeout = false;
2615 }
2616 timeout_ms = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000;
2617 }
2618 }
2619 #endif
2620
2621 /* If the link is pairing, do not mess with the timeouts */
2622 if (p_lcb->is_bonding) return;
2623
2624 if (timeout_ms == 0) {
2625 L2CAP_TRACE_DEBUG(
2626 "l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link");
2627
2628 rc = btm_sec_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
2629 if (rc == BTM_CMD_STARTED) {
2630 l2cu_process_fixed_disc_cback(p_lcb);
2631 p_lcb->link_state = LST_DISCONNECTING;
2632 timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
2633 } else if (rc == BTM_SUCCESS) {
2634 l2cu_process_fixed_disc_cback(p_lcb);
2635 /* BTM SEC will make sure that link is release (probably after pairing is
2636 * done) */
2637 p_lcb->link_state = LST_DISCONNECTING;
2638 start_timeout = false;
2639 } else if (p_lcb->is_bonding) {
2640 btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
2641 l2cu_process_fixed_disc_cback(p_lcb);
2642 p_lcb->link_state = LST_DISCONNECTING;
2643 timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
2644 } else {
2645 /* probably no buffer to send disconnect */
2646 timeout_ms = BT_1SEC_TIMEOUT_MS;
2647 }
2648 }
2649
2650 if (start_timeout) {
2651 L2CAP_TRACE_DEBUG("%s starting IDLE timeout: %d ms", __func__, timeout_ms);
2652 alarm_set_on_mloop(p_lcb->l2c_lcb_timer, timeout_ms, l2c_lcb_timer_timeout,
2653 p_lcb);
2654 } else {
2655 alarm_cancel(p_lcb->l2c_lcb_timer);
2656 }
2657 }
2658
2659 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2660 /*******************************************************************************
2661 *
2662 * Function l2cu_process_fixed_chnl_resp
2663 *
2664 * Description handle a fixed channel response (or lack thereof)
2665 * if the link failed, or a fixed channel response was
2666 * not received, the bitfield is all zeros.
2667 *
2668 ******************************************************************************/
l2cu_process_fixed_chnl_resp(tL2C_LCB * p_lcb)2669 void l2cu_process_fixed_chnl_resp(tL2C_LCB* p_lcb) {
2670 if (p_lcb->transport == BT_TRANSPORT_BR_EDR) {
2671 /* ignore all not assigned BR/EDR channels */
2672 p_lcb->peer_chnl_mask[0] &=
2673 (L2CAP_FIXED_CHNL_SIG_BIT | L2CAP_FIXED_CHNL_CNCTLESS_BIT |
2674 L2CAP_FIXED_CHNL_SMP_BR_BIT);
2675 } else
2676 p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
2677
2678 /* Tell all registered fixed channels about the connection */
2679 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2680 uint16_t channel_id = xx + L2CAP_FIRST_FIXED_CHNL;
2681
2682 /* See BT Spec Ver 5.0 | Vol 3, Part A 2.1 table 2.1 and 2.2 */
2683
2684 /* skip sending LE fix channel callbacks on BR/EDR links */
2685 if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
2686 channel_id >= L2CAP_ATT_CID && channel_id <= L2CAP_SMP_CID)
2687 continue;
2688
2689 /* skip sending BR fix channel callbacks on LE links */
2690 if (p_lcb->transport == BT_TRANSPORT_LE && channel_id == L2CAP_SMP_BR_CID)
2691 continue;
2692
2693 if (!l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb) continue;
2694
2695 if (p_lcb->peer_chnl_mask[(channel_id) / 8] & (1 << ((channel_id) % 8))) {
2696 if (p_lcb->p_fixed_ccbs[xx])
2697 p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
2698 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2699 channel_id, p_lcb->remote_bd_addr, true, 0, p_lcb->transport);
2700 } else {
2701 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2702 channel_id, p_lcb->remote_bd_addr, false, p_lcb->disc_reason,
2703 p_lcb->transport);
2704
2705 if (p_lcb->p_fixed_ccbs[xx]) {
2706 l2cu_release_ccb(p_lcb->p_fixed_ccbs[xx]);
2707 p_lcb->p_fixed_ccbs[xx] = NULL;
2708 }
2709 }
2710 }
2711 }
2712 #endif
2713
2714 /*******************************************************************************
2715 *
2716 * Function l2cu_process_fixed_disc_cback
2717 *
2718 * Description send l2cap fixed channel disconnection callback to the
2719 * application
2720 *
2721 * Returns void
2722 *
2723 ******************************************************************************/
l2cu_process_fixed_disc_cback(tL2C_LCB * p_lcb)2724 void l2cu_process_fixed_disc_cback(tL2C_LCB* p_lcb) {
2725 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2726
2727 /* Select peer channels mask to use depending on transport */
2728 uint8_t peer_channel_mask = p_lcb->peer_chnl_mask[0];
2729
2730 // For LE, reset the stored peer channel mask
2731 if (p_lcb->transport == BT_TRANSPORT_LE) p_lcb->peer_chnl_mask[0] = 0;
2732
2733 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2734 if (p_lcb->p_fixed_ccbs[xx]) {
2735 if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) {
2736 tL2C_CCB* p_l2c_chnl_ctrl_block;
2737 p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
2738 p_lcb->p_fixed_ccbs[xx] = NULL;
2739 l2cu_release_ccb(p_l2c_chnl_ctrl_block);
2740 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2741 xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2742 p_lcb->disc_reason, p_lcb->transport);
2743 }
2744 } else if ((peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL))) &&
2745 (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL))
2746 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2747 xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2748 p_lcb->disc_reason, p_lcb->transport);
2749 }
2750 #endif
2751 }
2752
2753 /*******************************************************************************
2754 *
2755 * Function l2cu_send_peer_ble_par_req
2756 *
2757 * Description Build and send a BLE parameter update request message
2758 * to the peer.
2759 *
2760 * Returns void
2761 *
2762 ******************************************************************************/
l2cu_send_peer_ble_par_req(tL2C_LCB * p_lcb,uint16_t min_int,uint16_t max_int,uint16_t latency,uint16_t timeout)2763 void l2cu_send_peer_ble_par_req(tL2C_LCB* p_lcb, uint16_t min_int,
2764 uint16_t max_int, uint16_t latency,
2765 uint16_t timeout) {
2766 BT_HDR* p_buf;
2767 uint8_t* p;
2768
2769 /* Create an identifier for this packet */
2770 p_lcb->id++;
2771 l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
2772
2773 p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN,
2774 L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->id);
2775 if (p_buf == NULL) {
2776 L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_req - no buffer");
2777 return;
2778 }
2779
2780 p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2781 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2782
2783 UINT16_TO_STREAM(p, min_int);
2784 UINT16_TO_STREAM(p, max_int);
2785 UINT16_TO_STREAM(p, latency);
2786 UINT16_TO_STREAM(p, timeout);
2787
2788 l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
2789 }
2790
2791 /*******************************************************************************
2792 *
2793 * Function l2cu_send_peer_ble_par_rsp
2794 *
2795 * Description Build and send a BLE parameter update response message
2796 * to the peer.
2797 *
2798 * Returns void
2799 *
2800 ******************************************************************************/
l2cu_send_peer_ble_par_rsp(tL2C_LCB * p_lcb,uint16_t reason,uint8_t rem_id)2801 void l2cu_send_peer_ble_par_rsp(tL2C_LCB* p_lcb, uint16_t reason,
2802 uint8_t rem_id) {
2803 BT_HDR* p_buf;
2804 uint8_t* p;
2805
2806 p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN,
2807 L2CAP_CMD_BLE_UPDATE_RSP, rem_id);
2808 if (p_buf == NULL) {
2809 L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_rsp - no buffer");
2810 return;
2811 }
2812
2813 p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2814 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2815
2816 UINT16_TO_STREAM(p, reason);
2817
2818 l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
2819 }
2820
2821 /*******************************************************************************
2822 *
2823 * Function l2cu_send_peer_ble_credit_based_conn_req
2824 *
2825 * Description Build and send a BLE packet to establish LE connection
2826 * oriented L2CAP channel.
2827 *
2828 * Returns void
2829 *
2830 ******************************************************************************/
l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB * p_ccb)2831 void l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB* p_ccb) {
2832 BT_HDR* p_buf;
2833 uint8_t* p;
2834 tL2C_LCB* p_lcb = NULL;
2835 uint16_t mtu;
2836 uint16_t mps;
2837 uint16_t initial_credit;
2838
2839 if (!p_ccb) return;
2840 p_lcb = p_ccb->p_lcb;
2841
2842 /* Create an identifier for this packet */
2843 p_ccb->p_lcb->id++;
2844 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
2845
2846 p_ccb->local_id = p_ccb->p_lcb->id;
2847
2848 p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
2849 L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id);
2850 if (p_buf == NULL) {
2851 L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2852 return;
2853 }
2854
2855 p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2856 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2857
2858 mtu = p_ccb->local_conn_cfg.mtu;
2859 mps = p_ccb->local_conn_cfg.mps;
2860 initial_credit = p_ccb->local_conn_cfg.credits;
2861
2862 L2CAP_TRACE_DEBUG(
2863 "l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
2864 mtu:%d mps:%d initial_credit:%d",
2865 p_ccb->p_rcb->real_psm, p_ccb->local_cid, mtu, mps, initial_credit);
2866
2867 UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm);
2868 UINT16_TO_STREAM(p, p_ccb->local_cid);
2869 UINT16_TO_STREAM(p, mtu);
2870 UINT16_TO_STREAM(p, mps);
2871 UINT16_TO_STREAM(p, initial_credit);
2872
2873 l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
2874 }
2875
2876 /*******************************************************************************
2877 *
2878 * Function l2cu_reject_ble_connection
2879 *
2880 * Description Build and send an L2CAP "Credit based connection res"
2881 * message to the peer. This function is called for non-success
2882 * cases.
2883 *
2884 * Returns void
2885 *
2886 ******************************************************************************/
l2cu_reject_ble_connection(tL2C_LCB * p_lcb,uint8_t rem_id,uint16_t result)2887 void l2cu_reject_ble_connection(tL2C_LCB* p_lcb, uint8_t rem_id,
2888 uint16_t result) {
2889 BT_HDR* p_buf;
2890 uint8_t* p;
2891
2892 p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
2893 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id);
2894 if (p_buf == NULL) {
2895 L2CAP_TRACE_WARNING("l2cu_reject_ble_connection - no buffer");
2896 return;
2897 }
2898
2899 p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2900 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2901
2902 UINT16_TO_STREAM(p, 0); /* Local CID of 0 */
2903 UINT16_TO_STREAM(p, 0); /* MTU */
2904 UINT16_TO_STREAM(p, 0); /* MPS */
2905 UINT16_TO_STREAM(p, 0); /* initial credit */
2906 UINT16_TO_STREAM(p, result);
2907
2908 l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
2909 }
2910
2911 /*******************************************************************************
2912 *
2913 * Function l2cu_send_peer_ble_credit_based_conn_res
2914 *
2915 * Description Build and send an L2CAP "Credit based connection res"
2916 * message to the peer. This function is called in case of
2917 * success.
2918 *
2919 * Returns void
2920 *
2921 ******************************************************************************/
l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB * p_ccb,uint16_t result)2922 void l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB* p_ccb,
2923 uint16_t result) {
2924 BT_HDR* p_buf;
2925 uint8_t* p;
2926
2927 L2CAP_TRACE_DEBUG("l2cu_send_peer_ble_credit_based_conn_res");
2928 p_buf =
2929 l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
2930 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id);
2931 if (p_buf == NULL) {
2932 L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
2933 return;
2934 }
2935
2936 p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2937 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2938
2939 UINT16_TO_STREAM(p, p_ccb->local_cid); /* Local CID */
2940 UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mtu); /* MTU */
2941 UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mps); /* MPS */
2942 UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.credits); /* initial credit */
2943 UINT16_TO_STREAM(p, result);
2944
2945 l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
2946 }
2947
2948 /*******************************************************************************
2949 *
2950 * Function l2cu_send_peer_ble_flow_control_credit
2951 *
2952 * Description Build and send a BLE packet to give credits to peer device
2953 * for LE connection oriented L2CAP channel.
2954 *
2955 * Returns void
2956 *
2957 ******************************************************************************/
l2cu_send_peer_ble_flow_control_credit(tL2C_CCB * p_ccb,uint16_t credit_value)2958 void l2cu_send_peer_ble_flow_control_credit(tL2C_CCB* p_ccb,
2959 uint16_t credit_value) {
2960 BT_HDR* p_buf;
2961 uint8_t* p;
2962 tL2C_LCB* p_lcb = NULL;
2963
2964 if (!p_ccb) return;
2965 p_lcb = p_ccb->p_lcb;
2966
2967 /* Create an identifier for this packet */
2968 p_ccb->p_lcb->id++;
2969 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
2970
2971 p_ccb->local_id = p_ccb->p_lcb->id;
2972
2973 p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
2974 L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id);
2975 if (p_buf == NULL) {
2976 L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2977 return;
2978 }
2979
2980 p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2981 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2982
2983 UINT16_TO_STREAM(p, p_ccb->local_cid);
2984 UINT16_TO_STREAM(p, credit_value);
2985
2986 l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
2987 }
2988
2989 /*******************************************************************************
2990 *
2991 * Function l2cu_send_peer_ble_credit_based_conn_req
2992 *
2993 * Description Build and send a BLE packet to disconnect LE connection
2994 * oriented L2CAP channel.
2995 *
2996 * Returns void
2997 *
2998 ******************************************************************************/
l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB * p_ccb)2999 void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB* p_ccb) {
3000 BT_HDR* p_buf;
3001 uint8_t* p;
3002 tL2C_LCB* p_lcb = NULL;
3003 L2CAP_TRACE_DEBUG("%s", __func__);
3004
3005 if (!p_ccb) return;
3006 p_lcb = p_ccb->p_lcb;
3007
3008 /* Create an identifier for this packet */
3009 p_ccb->p_lcb->id++;
3010 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3011
3012 p_ccb->local_id = p_ccb->p_lcb->id;
3013 p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_REQ_LEN, L2CAP_CMD_DISC_REQ,
3014 p_lcb->id);
3015 if (p_buf == NULL) {
3016 L2CAP_TRACE_WARNING(
3017 "l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
3018 return;
3019 }
3020
3021 p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3022 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3023
3024 UINT16_TO_STREAM(p, p_ccb->remote_cid);
3025 UINT16_TO_STREAM(p, p_ccb->local_cid);
3026
3027 l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
3028 }
3029
3030 /*******************************************************************************
3031 * Functions used by both Full and Light Stack
3032 ******************************************************************************/
3033
3034 /*******************************************************************************
3035 *
3036 * Function l2cu_find_lcb_by_handle
3037 *
3038 * Description Look through all active LCBs for a match based on the
3039 * HCI handle.
3040 *
3041 * Returns pointer to matched LCB, or NULL if no match
3042 *
3043 ******************************************************************************/
l2cu_find_lcb_by_handle(uint16_t handle)3044 tL2C_LCB* l2cu_find_lcb_by_handle(uint16_t handle) {
3045 int xx;
3046 tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
3047
3048 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
3049 if ((p_lcb->in_use) && (p_lcb->handle == handle)) {
3050 return (p_lcb);
3051 }
3052 }
3053
3054 /* If here, no match found */
3055 return (NULL);
3056 }
3057
3058 /*******************************************************************************
3059 *
3060 * Function l2cu_find_ccb_by_cid
3061 *
3062 * Description Look through all active CCBs on a link for a match based
3063 * on the local CID. If passed the link pointer is NULL, all
3064 * active links are searched.
3065 *
3066 * Returns pointer to matched CCB, or NULL if no match
3067 *
3068 ******************************************************************************/
l2cu_find_ccb_by_cid(tL2C_LCB * p_lcb,uint16_t local_cid)3069 tL2C_CCB* l2cu_find_ccb_by_cid(tL2C_LCB* p_lcb, uint16_t local_cid) {
3070 tL2C_CCB* p_ccb = NULL;
3071 if (local_cid >= L2CAP_BASE_APPL_CID) {
3072 /* find the associated CCB by "index" */
3073 local_cid -= L2CAP_BASE_APPL_CID;
3074
3075 if (local_cid >= MAX_L2CAP_CHANNELS) return NULL;
3076
3077 p_ccb = l2cb.ccb_pool + local_cid;
3078
3079 /* make sure the CCB is in use */
3080 if (!p_ccb->in_use) {
3081 p_ccb = NULL;
3082 }
3083 /* make sure it's for the same LCB */
3084 else if (p_lcb && p_lcb != p_ccb->p_lcb) {
3085 p_ccb = NULL;
3086 }
3087 }
3088 return (p_ccb);
3089 }
3090
3091 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
3092
3093 /******************************************************************************
3094 *
3095 * Function l2cu_get_next_channel_in_rr
3096 *
3097 * Description get the next channel to send on a link. It also adjusts the
3098 * CCB queue to do a basic priority and round-robin scheduling.
3099 *
3100 * Returns pointer to CCB or NULL
3101 *
3102 ******************************************************************************/
l2cu_get_next_channel_in_rr(tL2C_LCB * p_lcb)3103 static tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb) {
3104 tL2C_CCB* p_serve_ccb = NULL;
3105 tL2C_CCB* p_ccb;
3106
3107 int i, j;
3108
3109 /* scan all of priority until finding a channel to serve */
3110 for (i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++) {
3111 /* scan all channel within serving priority group until finding a channel to
3112 * serve */
3113 for (j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb);
3114 j++) {
3115 /* scaning from next serving channel */
3116 p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb;
3117
3118 if (!p_ccb) {
3119 L2CAP_TRACE_ERROR("p_serve_ccb is NULL, rr_pri=%d", p_lcb->rr_pri);
3120 return NULL;
3121 }
3122
3123 L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d",
3124 p_ccb->ccb_priority, p_ccb->local_cid,
3125 fixed_queue_length(p_ccb->xmit_hold_q));
3126
3127 /* store the next serving channel */
3128 /* this channel is the last channel of its priority group */
3129 if ((p_ccb->p_next_ccb == NULL) ||
3130 (p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority)) {
3131 /* next serving channel is set to the first channel in the group */
3132 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb =
3133 p_lcb->rr_serv[p_lcb->rr_pri].p_first_ccb;
3134 } else {
3135 /* next serving channel is set to the next channel in the group */
3136 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_ccb->p_next_ccb;
3137 }
3138
3139 if (p_ccb->chnl_state != CST_OPEN) continue;
3140
3141 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3142 L2CAP_TRACE_DEBUG("%s : Connection oriented channel", __func__);
3143 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3144
3145 } else {
3146 /* eL2CAP option in use */
3147 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3148 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
3149
3150 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3151 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3152
3153 /* If in eRTM mode, check for window closure */
3154 if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3155 (l2c_fcr_is_flow_controlled(p_ccb)))
3156 continue;
3157 }
3158 } else {
3159 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3160 }
3161 }
3162
3163 /* found a channel to serve */
3164 p_serve_ccb = p_ccb;
3165 /* decrease quota of its priority group */
3166 p_lcb->rr_serv[p_lcb->rr_pri].quota--;
3167 }
3168
3169 /* if there is no more quota of the priority group or no channel to have
3170 * data to send */
3171 if ((p_lcb->rr_serv[p_lcb->rr_pri].quota == 0) || (!p_serve_ccb)) {
3172 /* serve next priority group */
3173 p_lcb->rr_pri = (p_lcb->rr_pri + 1) % L2CAP_NUM_CHNL_PRIORITY;
3174 /* initialize its quota */
3175 p_lcb->rr_serv[p_lcb->rr_pri].quota =
3176 L2CAP_GET_PRIORITY_QUOTA(p_lcb->rr_pri);
3177 }
3178 }
3179
3180 if (p_serve_ccb) {
3181 L2CAP_TRACE_DEBUG("RR service pri=%d, quota=%d, lcid=0x%04x",
3182 p_serve_ccb->ccb_priority,
3183 p_lcb->rr_serv[p_serve_ccb->ccb_priority].quota,
3184 p_serve_ccb->local_cid);
3185 }
3186
3187 return p_serve_ccb;
3188 }
3189
3190 #else /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3191
3192 /******************************************************************************
3193 *
3194 * Function l2cu_get_next_channel
3195 *
3196 * Description get the next channel to send on a link bassed on priority
3197 * scheduling.
3198 *
3199 * Returns pointer to CCB or NULL
3200 *
3201 ******************************************************************************/
l2cu_get_next_channel(tL2C_LCB * p_lcb)3202 static tL2C_CCB* l2cu_get_next_channel(tL2C_LCB* p_lcb) {
3203 tL2C_CCB* p_ccb;
3204
3205 /* Get the first CCB with data to send.
3206 */
3207 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
3208 if (p_ccb->chnl_state != CST_OPEN) continue;
3209
3210 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
3211
3212 if (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) return p_ccb;
3213
3214 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3215
3216 /* If in eRTM mode, check for window closure */
3217 if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3218 (l2c_fcr_is_flow_controlled(p_ccb)))
3219 continue;
3220
3221 /* If here, we found someone */
3222 return p_ccb;
3223 }
3224
3225 return NULL;
3226 }
3227 #endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3228
l2cu_tx_complete(tL2C_TX_COMPLETE_CB_INFO * p_cbi)3229 void l2cu_tx_complete(tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
3230 if (p_cbi->cb != NULL) p_cbi->cb(p_cbi->local_cid, p_cbi->num_sdu);
3231 }
3232
3233 /******************************************************************************
3234 *
3235 * Function l2cu_get_next_buffer_to_send
3236 *
3237 * Description get the next buffer to send on a link. It also adjusts the
3238 * CCB queue to do a basic priority and round-robin scheduling.
3239 *
3240 * Returns pointer to buffer or NULL
3241 *
3242 ******************************************************************************/
l2cu_get_next_buffer_to_send(tL2C_LCB * p_lcb,tL2C_TX_COMPLETE_CB_INFO * p_cbi)3243 BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb,
3244 tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
3245 tL2C_CCB* p_ccb;
3246 BT_HDR* p_buf;
3247
3248 /* Highest priority are fixed channels */
3249 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3250 int xx;
3251
3252 p_cbi->cb = NULL;
3253
3254 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3255 p_ccb = p_lcb->p_fixed_ccbs[xx];
3256 if (p_ccb == NULL) continue;
3257
3258 /* eL2CAP option in use */
3259 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3260 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
3261
3262 /* No more checks needed if sending from the reatransmit queue */
3263 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3264 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3265
3266 /* If in eRTM mode, check for window closure */
3267 if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3268 (l2c_fcr_is_flow_controlled(p_ccb)))
3269 continue;
3270 }
3271
3272 p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
3273 if (p_buf != NULL) {
3274 l2cu_check_channel_congestion(p_ccb);
3275 l2cu_set_acl_hci_header(p_buf, p_ccb);
3276 return (p_buf);
3277 }
3278 } else {
3279 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3280 p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3281 if (NULL == p_buf) {
3282 L2CAP_TRACE_ERROR("%s: No data to be sent", __func__);
3283 return (NULL);
3284 }
3285
3286 /* Prepare callback info for TX completion */
3287 p_cbi->cb = l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb;
3288 p_cbi->local_cid = p_ccb->local_cid;
3289 p_cbi->num_sdu = 1;
3290
3291 l2cu_check_channel_congestion(p_ccb);
3292 l2cu_set_acl_hci_header(p_buf, p_ccb);
3293 return (p_buf);
3294 }
3295 }
3296 }
3297 #endif
3298
3299 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
3300 /* get next serving channel in round-robin */
3301 p_ccb = l2cu_get_next_channel_in_rr(p_lcb);
3302 #else
3303 p_ccb = l2cu_get_next_channel(p_lcb);
3304 #endif
3305
3306 /* Return if no buffer */
3307 if (p_ccb == NULL) return (NULL);
3308
3309 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3310 /* Check credits */
3311 if (p_ccb->peer_conn_cfg.credits == 0) {
3312 L2CAP_TRACE_DEBUG("%s No credits to send packets", __func__);
3313 return NULL;
3314 }
3315
3316 bool last_piece_of_sdu = false;
3317 p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, &last_piece_of_sdu);
3318 p_ccb->peer_conn_cfg.credits--;
3319
3320 if (last_piece_of_sdu) {
3321 // TODO: send callback up the stack. Investigate setting p_cbi->cb to
3322 // notify after controller ack send.
3323 }
3324
3325 } else {
3326 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3327 p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
3328 if (p_buf == NULL) return (NULL);
3329 } else {
3330 p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3331 if (NULL == p_buf) {
3332 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
3333 return (NULL);
3334 }
3335 }
3336 }
3337
3338 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb &&
3339 (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE))
3340 (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);
3341
3342 l2cu_check_channel_congestion(p_ccb);
3343
3344 l2cu_set_acl_hci_header(p_buf, p_ccb);
3345
3346 return (p_buf);
3347 }
3348
3349 /******************************************************************************
3350 *
3351 * Function l2cu_set_acl_hci_header
3352 *
3353 * Description Set HCI handle for ACL packet
3354 *
3355 * Returns None
3356 *
3357 ******************************************************************************/
l2cu_set_acl_hci_header(BT_HDR * p_buf,tL2C_CCB * p_ccb)3358 void l2cu_set_acl_hci_header(BT_HDR* p_buf, tL2C_CCB* p_ccb) {
3359 uint8_t* p;
3360
3361 /* Set the pointer to the beginning of the data minus 4 bytes for the packet
3362 * header */
3363 p = (uint8_t*)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE;
3364
3365 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3366 UINT16_TO_STREAM(p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE
3367 << L2CAP_PKT_TYPE_SHIFT));
3368
3369 uint16_t acl_data_size =
3370 controller_get_interface()->get_acl_data_size_ble();
3371 /* The HCI transport will segment the buffers. */
3372 if (p_buf->len > acl_data_size) {
3373 UINT16_TO_STREAM(p, acl_data_size);
3374 } else {
3375 UINT16_TO_STREAM(p, p_buf->len);
3376 }
3377 } else {
3378 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
3379 if ((((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) ==
3380 L2CAP_FLUSHABLE_CH_BASED) &&
3381 (p_ccb->is_flushable)) ||
3382 ((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) ==
3383 L2CAP_FLUSHABLE_PKT)) {
3384 UINT16_TO_STREAM(
3385 p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3386 } else {
3387 UINT16_TO_STREAM(p, p_ccb->p_lcb->handle | l2cb.non_flushable_pbf);
3388 }
3389 #else
3390 UINT16_TO_STREAM(
3391 p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3392 #endif
3393
3394 uint16_t acl_data_size =
3395 controller_get_interface()->get_acl_data_size_classic();
3396 /* The HCI transport will segment the buffers. */
3397 if (p_buf->len > acl_data_size) {
3398 UINT16_TO_STREAM(p, acl_data_size);
3399 } else {
3400 UINT16_TO_STREAM(p, p_buf->len);
3401 }
3402 }
3403 p_buf->offset -= HCI_DATA_PREAMBLE_SIZE;
3404 p_buf->len += HCI_DATA_PREAMBLE_SIZE;
3405 }
3406
send_congestion_status_to_all_clients(tL2C_CCB * p_ccb,bool status)3407 static void send_congestion_status_to_all_clients(tL2C_CCB* p_ccb,
3408 bool status) {
3409 p_ccb->cong_sent = status;
3410
3411 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3412 L2CAP_TRACE_DEBUG(
3413 "L2CAP - Calling CongestionStatus_Cb (%d), CID: 0x%04x "
3414 "xmit_hold_q.count: %u buff_quota: %u",
3415 status, p_ccb->local_cid, fixed_queue_length(p_ccb->xmit_hold_q),
3416 p_ccb->buff_quota);
3417
3418 /* Prevent recursive calling */
3419 if (status == false) l2cb.is_cong_cback_context = true;
3420
3421 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, status);
3422
3423 if (status == false) l2cb.is_cong_cback_context = false;
3424 }
3425 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3426 else {
3427 for (uint8_t xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3428 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3429 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
3430 (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr,
3431 status);
3432 break;
3433 }
3434 }
3435 }
3436 #endif
3437 }
3438
3439 /* check if any change in congestion status */
l2cu_check_channel_congestion(tL2C_CCB * p_ccb)3440 void l2cu_check_channel_congestion(tL2C_CCB* p_ccb) {
3441 /* If the CCB queue limit is subject to a quota, check for congestion if this
3442 * channel has outgoing traffic */
3443 if (p_ccb->buff_quota == 0) return;
3444
3445 size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
3446
3447 if (p_ccb->cong_sent) {
3448 /* if channel was congested, but is not congested now, tell the app */
3449 if (q_count <= (p_ccb->buff_quota / 2))
3450 send_congestion_status_to_all_clients(p_ccb, false);
3451 } else {
3452 /* if channel was not congested, but is congested now, tell the app */
3453 if (q_count > p_ccb->buff_quota)
3454 send_congestion_status_to_all_clients(p_ccb, true);
3455 }
3456 }
3457
3458 /*******************************************************************************
3459 *
3460 * Function l2cu_is_ccb_active
3461 *
3462 * Description Check if Channel Control Block is in use or released
3463 *
3464 * Returns bool - true if Channel Control Block is in use
3465 * false if p_ccb is null or is released.
3466 *
3467 ******************************************************************************/
l2cu_is_ccb_active(tL2C_CCB * p_ccb)3468 bool l2cu_is_ccb_active(tL2C_CCB* p_ccb) { return (p_ccb && p_ccb->in_use); }
3469