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