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