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