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