1 /******************************************************************************
3 * Copyright (C) 1999-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
21 * This file contains L2CAP utility functions
23 ******************************************************************************/
28 #include "osi/allocator.h"
29 #include "device/controller.h"
30 #include "stack/bt_types.h"
31 #include "stack/hcimsgs.h"
32 #include "stack/l2cdefs.h"
34 #include "stack/hcidefs.h"
35 #include "stack/btu.h"
36 #include "stack/btm_api.h"
38 #include "stack/hcidefs.h"
39 #include "osi/allocator.h"
41 /*******************************************************************************
43 ** Function l2cu_allocate_lcb
45 ** Description Look for an unused LCB
47 ** Returns LCB address or NULL if none found
49 *******************************************************************************/
50 tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPORT transport)
53 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
55 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
57 btu_free_timer(&p_lcb->timer_entry);
58 btu_free_timer(&p_lcb->info_timer_entry);
59 btu_free_timer(&p_lcb->upda_con_timer);
61 memset (p_lcb, 0, sizeof (tL2C_LCB));
62 memcpy (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN);
65 p_lcb->link_state = LST_DISCONNECTED;
66 p_lcb->handle = HCI_INVALID_HANDLE;
67 p_lcb->link_flush_tout = 0xFFFF;
68 p_lcb->timer_entry.param = (TIMER_PARAM_TYPE)p_lcb;
69 p_lcb->info_timer_entry.param = (TIMER_PARAM_TYPE)p_lcb;
70 p_lcb->upda_con_timer.param = (TIMER_PARAM_TYPE)p_lcb;
71 p_lcb->idle_timeout = l2cb.idle_timeout;
72 p_lcb->id = 1; /* spec does not allow '0' */
73 p_lcb->is_bonding = is_bonding;
74 #if (BLE_INCLUDED == TRUE)
75 p_lcb->transport = transport;
76 p_lcb->tx_data_len = controller_get_interface()->get_ble_default_data_packet_length();
77 p_lcb->le_sec_pending_q = fixed_queue_new(SIZE_MAX);
79 if (transport == BT_TRANSPORT_LE) {
80 l2cb.num_ble_links_active++;
81 l2c_ble_link_adjust_allocation();
85 l2cb.num_links_active++;
86 l2c_link_adjust_allocation();
88 p_lcb->link_xmit_data_q = list_new(NULL);
89 #if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
90 p_lcb->completed_packets = 0;
91 #endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
96 /* If here, no free LCB found */
100 /*******************************************************************************
102 ** Function l2cu_update_lcb_4_bonding
104 ** Description Mark the lcb for bonding. Used when bonding takes place on
105 ** an existing ACL connection. (Pre-Lisbon devices)
109 *******************************************************************************/
110 void l2cu_update_lcb_4_bonding (BD_ADDR p_bd_addr, BOOLEAN is_bonding)
112 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr, BT_TRANSPORT_BR_EDR);
115 p_lcb->is_bonding = is_bonding;
119 /*******************************************************************************
121 ** Function l2cu_release_lcb
123 ** Description Release an LCB. All timers will be stopped, channels
124 ** dropped, buffers returned etc.
128 *******************************************************************************/
129 void l2cu_release_lcb (tL2C_LCB *p_lcb)
133 p_lcb->in_use = FALSE;
134 p_lcb->is_bonding = FALSE;
136 /* Stop and release timers */
137 btu_free_timer (&p_lcb->timer_entry);
138 memset(&p_lcb->timer_entry, 0, sizeof(TIMER_LIST_ENT));
139 btu_free_timer (&p_lcb->info_timer_entry);
140 memset(&p_lcb->info_timer_entry, 0, sizeof(TIMER_LIST_ENT));
141 btu_free_timer(&p_lcb->upda_con_timer);
142 memset(&p_lcb->upda_con_timer, 0, sizeof(TIMER_LIST_ENT));
144 /* Release any unfinished L2CAP packet on this link */
145 if (p_lcb->p_hcit_rcv_acl) {
146 osi_free(p_lcb->p_hcit_rcv_acl);
147 p_lcb->p_hcit_rcv_acl = NULL;
150 #if BTM_SCO_INCLUDED == TRUE
151 #if (BLE_INCLUDED == TRUE)
152 if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
154 /* Release all SCO links */
155 btm_remove_sco_links(p_lcb->remote_bd_addr);
158 if (p_lcb->sent_not_acked > 0) {
159 #if (BLE_INCLUDED == TRUE)
160 if (p_lcb->transport == BT_TRANSPORT_LE) {
161 l2cb.controller_le_xmit_window += p_lcb->sent_not_acked;
162 if (l2cb.controller_le_xmit_window > l2cb.num_lm_ble_bufs) {
163 l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
168 l2cb.controller_xmit_window += p_lcb->sent_not_acked;
169 if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs) {
170 l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
175 #if (BLE_INCLUDED == TRUE)
176 // Reset BLE connecting flag only if the address matches
177 if (!memcmp(l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN)) {
178 l2cb.is_ble_connecting = FALSE;
182 #if (L2CAP_NUM_FIXED_CHNLS > 0)
183 l2cu_process_fixed_disc_cback(p_lcb);
186 /* Ensure no CCBs left on this LCB */
187 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_lcb->ccb_queue.p_first_ccb) {
188 l2cu_release_ccb (p_ccb);
191 /* Tell BTM Acl management the link was removed */
192 if ((p_lcb->link_state == LST_CONNECTED) || (p_lcb->link_state == LST_DISCONNECTING))
193 #if (BLE_INCLUDED == TRUE)
194 btm_acl_removed (p_lcb->remote_bd_addr, p_lcb->transport);
196 btm_acl_removed (p_lcb->remote_bd_addr, BT_TRANSPORT_BR_EDR);
199 /* Release any held buffers */
200 if (p_lcb->link_xmit_data_q) {
201 while (!list_is_empty(p_lcb->link_xmit_data_q)) {
202 BT_HDR *p_buf = list_front(p_lcb->link_xmit_data_q);
203 list_remove(p_lcb->link_xmit_data_q, p_buf);
206 list_free(p_lcb->link_xmit_data_q);
207 p_lcb->link_xmit_data_q = NULL;
210 #if (L2CAP_UCD_INCLUDED == TRUE)
211 /* clean up any security pending UCD */
212 l2c_ucd_delete_sec_pending_q(p_lcb);
215 #if BLE_INCLUDED == TRUE
216 /* Re-adjust flow control windows make sure it does not go negative */
217 if (p_lcb->transport == BT_TRANSPORT_LE) {
218 if (l2cb.num_ble_links_active >= 1) {
219 l2cb.num_ble_links_active--;
222 l2c_ble_link_adjust_allocation();
226 if (l2cb.num_links_active >= 1) {
227 l2cb.num_links_active--;
230 l2c_link_adjust_allocation();
233 /* Check for ping outstanding */
234 if (p_lcb->p_echo_rsp_cb) {
235 tL2CA_ECHO_RSP_CB *p_cb = p_lcb->p_echo_rsp_cb;
237 /* Zero out the callback in case app immediately calls us again */
238 p_lcb->p_echo_rsp_cb = NULL;
240 (*p_cb) (L2CAP_PING_RESULT_NO_LINK);
243 /* Check and release all the LE COC connections waiting for security */
244 if (p_lcb->le_sec_pending_q)
246 while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
248 tL2CAP_SEC_DATA *p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q);
249 if (p_buf->p_callback)
250 p_buf->p_callback(p_lcb->remote_bd_addr, p_lcb->transport, p_buf->p_ref_data, BTM_DEV_RESET);
253 fixed_queue_free(p_lcb->le_sec_pending_q, NULL);
254 p_lcb->le_sec_pending_q = NULL;
257 #if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
258 p_lcb->completed_packets = 0;
259 #endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
264 /*******************************************************************************
266 ** Function l2cu_find_lcb_by_bd_addr
268 ** Description Look through all active LCBs for a match based on the
269 ** remote BD address.
271 ** Returns pointer to matched LCB, or NULL if no match
273 *******************************************************************************/
274 tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr, tBT_TRANSPORT transport)
277 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
279 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
280 if ((p_lcb->in_use) &&
281 #if BLE_INCLUDED == TRUE
282 p_lcb->transport == transport &&
284 (!memcmp (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN))) {
289 /* If here, no match found */
293 /*******************************************************************************
295 ** Function l2cu_get_conn_role
297 ** Description Determine the desired role (master or slave) of a link.
298 ** If already got a slave link, this one must be a master. If
299 ** already got at least 1 link where we are the master, make this
302 ** Returns HCI_ROLE_MASTER or HCI_ROLE_SLAVE
304 *******************************************************************************/
305 UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb)
307 return l2cb.desire_role;
310 /*******************************************************************************
312 ** Function l2c_is_cmd_rejected
314 ** Description Checks if cmd_code is command or response
315 ** If a command it will be rejected per spec.
316 ** This function is used when a illegal packet length is detected
318 ** Returns BOOLEAN - TRUE if cmd_code is a command and it is rejected,
319 ** FALSE if response code. (command not rejected)
321 *******************************************************************************/
322 BOOLEAN l2c_is_cmd_rejected (UINT8 cmd_code, UINT8 id, tL2C_LCB *p_lcb)
325 case L2CAP_CMD_CONN_REQ:
326 case L2CAP_CMD_CONFIG_REQ:
327 case L2CAP_CMD_DISC_REQ:
328 case L2CAP_CMD_ECHO_REQ:
329 case L2CAP_CMD_INFO_REQ:
330 case L2CAP_CMD_AMP_CONN_REQ:
331 case L2CAP_CMD_AMP_MOVE_REQ:
332 case L2CAP_CMD_BLE_UPDATE_REQ:
333 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, id, L2CAP_DEFAULT_MTU, 0);
334 L2CAP_TRACE_WARNING ("Dumping first Command (%d)", cmd_code);
337 default: /* Otherwise a response */
342 /*******************************************************************************
344 ** Function l2cu_build_header
346 ** Description Builds the L2CAP command packet header
348 ** Returns Pointer to allocated packet or NULL if no resources
350 *******************************************************************************/
351 BT_HDR *l2cu_build_header (tL2C_LCB *p_lcb, UINT16 len, UINT8 cmd, UINT8 id)
353 BT_HDR *p_buf = (BT_HDR *)osi_malloc(L2CAP_CMD_BUF_SIZE);
360 p_buf->offset = L2CAP_SEND_CMD_OFFSET;
361 p_buf->len = len + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
362 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
364 /* Put in HCI header - handle + pkt boundary */
365 #if (BLE_INCLUDED == TRUE)
366 if (p_lcb->transport == BT_TRANSPORT_LE) {
367 UINT16_TO_STREAM (p, (p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT)));
371 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
372 UINT16_TO_STREAM (p, p_lcb->handle | l2cb.non_flushable_pbf);
374 UINT16_TO_STREAM (p, (p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
378 UINT16_TO_STREAM (p, len + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD);
379 UINT16_TO_STREAM (p, len + L2CAP_CMD_OVERHEAD);
381 #if (BLE_INCLUDED == TRUE)
382 if (p_lcb->transport == BT_TRANSPORT_LE) {
383 //counter_add("l2cap.ble.tx.bytes", p_buf->len);
384 //counter_add("l2cap.ble.tx.pkts", 1);
386 UINT16_TO_STREAM (p, L2CAP_BLE_SIGNALLING_CID);
390 //counter_add("l2cap.sig.tx.bytes", p_buf->len);
391 //counter_add("l2cap.sig.tx.pkts", 1);
392 UINT16_TO_STREAM (p, L2CAP_SIGNALLING_CID);
395 /* Put in L2CAP command header */
396 UINT8_TO_STREAM (p, cmd);
397 UINT8_TO_STREAM (p, id);
398 UINT16_TO_STREAM (p, len);
403 /*******************************************************************************
405 ** Function l2cu_adj_id
407 ** Description Checks for valid ID based on specified mask
408 ** and adjusts the id if invalid.
412 *******************************************************************************/
413 void l2cu_adj_id (tL2C_LCB *p_lcb, UINT8 adj_mask)
415 if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id) {
420 /*******************************************************************************
422 ** Function l2cu_send_peer_cmd_reject
424 ** Description Build and send an L2CAP "command reject" message
429 *******************************************************************************/
430 void l2cu_send_peer_cmd_reject (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id,
431 UINT16 p1, UINT16 p2)
437 /* Put in L2CAP packet header */
438 if (reason == L2CAP_CMD_REJ_MTU_EXCEEDED) {
440 } else if (reason == L2CAP_CMD_REJ_INVALID_CID) {
446 if ((p_buf = l2cu_build_header (p_lcb, (UINT16) (L2CAP_CMD_REJECT_LEN + param_len), L2CAP_CMD_REJECT, rem_id)) == NULL ) {
447 L2CAP_TRACE_WARNING ("L2CAP - no buffer cmd_rej");
451 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
452 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
454 UINT16_TO_STREAM (p, reason);
456 if (param_len >= 2) {
457 UINT16_TO_STREAM (p, p1);
460 if (param_len >= 4) {
461 UINT16_TO_STREAM (p, p2);
464 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
468 /*******************************************************************************
470 ** Function l2cu_send_peer_connect_req
472 ** Description Build and send an L2CAP "connection request" message
477 *******************************************************************************/
478 void l2cu_send_peer_connect_req (tL2C_CCB *p_ccb)
483 /* Create an identifier for this packet */
485 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
487 p_ccb->local_id = p_ccb->p_lcb->id;
489 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, L2CAP_CONN_REQ_LEN, L2CAP_CMD_CONN_REQ,
490 p_ccb->local_id)) == NULL) {
491 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
495 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
496 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
498 UINT16_TO_STREAM (p, p_ccb->p_rcb->real_psm);
499 UINT16_TO_STREAM (p, p_ccb->local_cid);
501 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
505 /*******************************************************************************
507 ** Function l2cu_send_peer_connect_rsp
509 ** Description Build and send an L2CAP "connection response" message
514 *******************************************************************************/
515 void l2cu_send_peer_connect_rsp (tL2C_CCB *p_ccb, UINT16 result, UINT16 status)
520 if (result == L2CAP_CONN_PENDING) {
521 /* if we already sent pending response */
522 if (p_ccb->flags & CCB_FLAG_SENT_PENDING) {
525 p_ccb->flags |= CCB_FLAG_SENT_PENDING;
529 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, p_ccb->remote_id)) == NULL) {
530 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_rsp");
534 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
535 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
537 UINT16_TO_STREAM (p, p_ccb->local_cid);
538 UINT16_TO_STREAM (p, p_ccb->remote_cid);
539 UINT16_TO_STREAM (p, result);
540 UINT16_TO_STREAM (p, status);
542 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
546 /*******************************************************************************
548 ** Function l2cu_reject_connection
550 ** Description Build and send an L2CAP "connection response neg" message
551 ** to the peer. This function is called when there is no peer
552 ** CCB (non-existant PSM or no resources).
556 *******************************************************************************/
557 void l2cu_reject_connection (tL2C_LCB *p_lcb, UINT16 remote_cid, UINT8 rem_id, UINT16 result)
562 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, rem_id)) == NULL ) {
563 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
567 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
569 UINT16_TO_STREAM (p, 0); /* Local CID of 0 */
570 UINT16_TO_STREAM (p, remote_cid);
571 UINT16_TO_STREAM (p, result);
572 UINT16_TO_STREAM (p, 0); /* Status of 0 */
574 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
577 /*******************************************************************************
579 ** Function l2cu_send_peer_config_req
581 ** Description Build and send an L2CAP "configuration request" message
586 *******************************************************************************/
587 void l2cu_send_peer_config_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
593 /* Create an identifier for this packet */
595 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
597 p_ccb->local_id = p_ccb->p_lcb->id;
599 if (p_cfg->mtu_present) {
600 cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
602 if (p_cfg->flush_to_present) {
603 cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
605 if (p_cfg->qos_present) {
606 cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
608 if (p_cfg->fcr_present) {
609 cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
611 if (p_cfg->fcs_present) {
612 cfg_len += L2CAP_CFG_FCS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
614 if (p_cfg->ext_flow_spec_present) {
615 cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
618 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, (UINT16) (L2CAP_CONFIG_REQ_LEN + cfg_len),
619 L2CAP_CMD_CONFIG_REQ, p_ccb->local_id)) == NULL ) {
620 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
624 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
625 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
627 UINT16_TO_STREAM (p, p_ccb->remote_cid);
628 UINT16_TO_STREAM (p, p_cfg->flags); /* Flags (continuation) */
630 /* Now, put the options */
631 if (p_cfg->mtu_present) {
632 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_MTU);
633 UINT8_TO_STREAM (p, L2CAP_CFG_MTU_OPTION_LEN);
634 UINT16_TO_STREAM (p, p_cfg->mtu);
636 if (p_cfg->flush_to_present) {
637 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FLUSH_TOUT);
638 UINT8_TO_STREAM (p, L2CAP_CFG_FLUSH_OPTION_LEN);
639 UINT16_TO_STREAM (p, p_cfg->flush_to);
641 if (p_cfg->qos_present) {
642 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_QOS);
643 UINT8_TO_STREAM (p, L2CAP_CFG_QOS_OPTION_LEN);
644 UINT8_TO_STREAM (p, p_cfg->qos.qos_flags);
645 UINT8_TO_STREAM (p, p_cfg->qos.service_type);
646 UINT32_TO_STREAM (p, p_cfg->qos.token_rate);
647 UINT32_TO_STREAM (p, p_cfg->qos.token_bucket_size);
648 UINT32_TO_STREAM (p, p_cfg->qos.peak_bandwidth);
649 UINT32_TO_STREAM (p, p_cfg->qos.latency);
650 UINT32_TO_STREAM (p, p_cfg->qos.delay_variation);
652 if (p_cfg->fcr_present) {
653 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCR);
654 UINT8_TO_STREAM (p, L2CAP_CFG_FCR_OPTION_LEN);
655 UINT8_TO_STREAM (p, p_cfg->fcr.mode);
656 UINT8_TO_STREAM (p, p_cfg->fcr.tx_win_sz);
657 UINT8_TO_STREAM (p, p_cfg->fcr.max_transmit);
658 UINT16_TO_STREAM (p, p_cfg->fcr.rtrans_tout);
659 UINT16_TO_STREAM (p, p_cfg->fcr.mon_tout);
660 UINT16_TO_STREAM (p, p_cfg->fcr.mps);
663 if (p_cfg->fcs_present) {
664 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCS);
665 UINT8_TO_STREAM (p, L2CAP_CFG_FCS_OPTION_LEN);
666 UINT8_TO_STREAM (p, p_cfg->fcs);
669 if (p_cfg->ext_flow_spec_present) {
670 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_EXT_FLOW);
671 UINT8_TO_STREAM (p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
672 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.id);
673 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.stype);
674 UINT16_TO_STREAM (p, p_cfg->ext_flow_spec.max_sdu_size);
675 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.sdu_inter_time);
676 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.access_latency);
677 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.flush_timeout);
680 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
683 /*******************************************************************************
685 ** Function l2cu_send_peer_config_rsp
687 ** Description Build and send an L2CAP "configuration response" message
692 *******************************************************************************/
693 void l2cu_send_peer_config_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
699 /* Create an identifier for this packet */
700 if (p_cfg->mtu_present) {
701 cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
703 if (p_cfg->flush_to_present) {
704 cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
706 if (p_cfg->qos_present) {
707 cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
709 if (p_cfg->fcr_present) {
710 cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
712 if (p_cfg->ext_flow_spec_present) {
713 cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
716 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, (UINT16)(L2CAP_CONFIG_RSP_LEN + cfg_len),
717 L2CAP_CMD_CONFIG_RSP, p_ccb->remote_id)) == NULL ) {
718 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
722 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
724 UINT16_TO_STREAM (p, p_ccb->remote_cid);
725 UINT16_TO_STREAM (p, p_cfg->flags); /* Flags (continuation) Must match request */
726 UINT16_TO_STREAM (p, p_cfg->result);
728 /* Now, put the options */
729 if (p_cfg->mtu_present) {
730 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_MTU);
731 UINT8_TO_STREAM (p, L2CAP_CFG_MTU_OPTION_LEN);
732 UINT16_TO_STREAM (p, p_cfg->mtu);
734 if (p_cfg->flush_to_present) {
735 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FLUSH_TOUT);
736 UINT8_TO_STREAM (p, L2CAP_CFG_FLUSH_OPTION_LEN);
737 UINT16_TO_STREAM (p, p_cfg->flush_to);
739 if (p_cfg->qos_present) {
740 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_QOS);
741 UINT8_TO_STREAM (p, L2CAP_CFG_QOS_OPTION_LEN);
742 UINT8_TO_STREAM (p, p_cfg->qos.qos_flags);
743 UINT8_TO_STREAM (p, p_cfg->qos.service_type);
744 UINT32_TO_STREAM (p, p_cfg->qos.token_rate);
745 UINT32_TO_STREAM (p, p_cfg->qos.token_bucket_size);
746 UINT32_TO_STREAM (p, p_cfg->qos.peak_bandwidth);
747 UINT32_TO_STREAM (p, p_cfg->qos.latency);
748 UINT32_TO_STREAM (p, p_cfg->qos.delay_variation);
750 if (p_cfg->fcr_present) {
751 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCR);
752 UINT8_TO_STREAM (p, L2CAP_CFG_FCR_OPTION_LEN);
753 UINT8_TO_STREAM (p, p_cfg->fcr.mode);
754 UINT8_TO_STREAM (p, p_cfg->fcr.tx_win_sz);
755 UINT8_TO_STREAM (p, p_cfg->fcr.max_transmit);
756 UINT16_TO_STREAM (p, p_ccb->our_cfg.fcr.rtrans_tout);
757 UINT16_TO_STREAM (p, p_ccb->our_cfg.fcr.mon_tout);
758 UINT16_TO_STREAM (p, p_cfg->fcr.mps);
761 if (p_cfg->ext_flow_spec_present) {
762 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_EXT_FLOW);
763 UINT8_TO_STREAM (p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
764 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.id);
765 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.stype);
766 UINT16_TO_STREAM (p, p_cfg->ext_flow_spec.max_sdu_size);
767 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.sdu_inter_time);
768 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.access_latency);
769 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.flush_timeout);
772 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
775 /*******************************************************************************
777 ** Function l2cu_send_peer_config_rej
779 ** Description Build and send an L2CAP "configuration reject" message
784 *******************************************************************************/
785 void l2cu_send_peer_config_rej (tL2C_CCB *p_ccb, UINT8 *p_data, UINT16 data_len, UINT16 rej_len)
788 UINT16 len, cfg_len, buf_space, len1;
789 UINT8 *p, *p_hci_len, *p_data_end;
792 L2CAP_TRACE_DEBUG("l2cu_send_peer_config_rej: data_len=%d, rej_len=%d", data_len, rej_len);
795 len = BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN;
797 if (rej_len > len1) {
798 L2CAP_TRACE_ERROR ("L2CAP - cfg_rej pkt size exceeds buffer design max limit.");
802 p_buf = (BT_HDR *)osi_malloc (len + rej_len);
805 L2CAP_TRACE_ERROR ("L2CAP - no buffer for cfg_rej");
809 p_buf->offset = L2CAP_SEND_CMD_OFFSET;
810 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
812 /* Put in HCI header - handle + pkt boundary */
813 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
814 if (HCI_NON_FLUSHABLE_PB_SUPPORTED(BTM_ReadLocalFeatures ())) {
815 UINT16_TO_STREAM (p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT)));
819 UINT16_TO_STREAM (p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
822 /* Remember the HCI header length position, and save space for it */
826 /* Put in L2CAP packet header */
827 UINT16_TO_STREAM (p, L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len);
828 UINT16_TO_STREAM (p, L2CAP_SIGNALLING_CID);
830 /* Put in L2CAP command header */
831 UINT8_TO_STREAM (p, L2CAP_CMD_CONFIG_RSP);
832 UINT8_TO_STREAM (p, p_ccb->remote_id);
834 UINT16_TO_STREAM (p, L2CAP_CONFIG_RSP_LEN + rej_len);
836 UINT16_TO_STREAM (p, p_ccb->remote_cid);
837 UINT16_TO_STREAM (p, 0); /* Flags = 0 (no continuation) */
838 UINT16_TO_STREAM (p, L2CAP_CFG_UNKNOWN_OPTIONS);
842 /* Now, put the rejected options */
843 p_data_end = p_data + data_len;
844 while (p_data < p_data_end) {
846 cfg_len = *(p_data + 1);
848 switch (cfg_code & 0x7F) {
849 /* skip known options */
850 case L2CAP_CFG_TYPE_MTU:
851 case L2CAP_CFG_TYPE_FLUSH_TOUT:
852 case L2CAP_CFG_TYPE_QOS:
853 p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
856 /* unknown options; copy into rsp if not hints */
858 /* sanity check option length */
859 if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= data_len) {
860 if ((cfg_code & 0x80) == 0) {
861 if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD)) {
862 memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
863 p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
864 buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
866 L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer");
867 p_data = p_data_end; /* force loop exit */
871 p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
873 /* bad length; force loop exit */
881 len = (UINT16) (p - p_hci_len - 2);
882 UINT16_TO_STREAM (p_hci_len, len);
884 p_buf->len = len + 4;
886 L2CAP_TRACE_DEBUG ("L2CAP - cfg_rej pkt hci_len=%d, l2cap_len=%d",
887 len, (L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len));
889 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
892 /*******************************************************************************
894 ** Function l2cu_send_peer_disc_req
896 ** Description Build and send an L2CAP "disconnect request" message
901 *******************************************************************************/
902 void l2cu_send_peer_disc_req (tL2C_CCB *p_ccb)
904 BT_HDR *p_buf, *p_buf2;
907 /* Create an identifier for this packet */
909 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
911 p_ccb->local_id = p_ccb->p_lcb->id;
913 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_DISC_REQ_LEN, L2CAP_CMD_DISC_REQ, p_ccb->local_id)) == NULL) {
914 L2CAP_TRACE_WARNING ("L2CAP - no buffer for disc_req");
918 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
920 UINT16_TO_STREAM (p, p_ccb->remote_cid);
921 UINT16_TO_STREAM (p, p_ccb->local_cid);
923 /* Move all queued data packets to the LCB. In FCR mode, assume the higher
924 layer checks that all buffers are sent before disconnecting.
926 if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
927 while ((p_buf2 = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q)) != NULL) {
928 l2cu_set_acl_hci_header (p_buf2, p_ccb);
929 l2c_link_check_send_pkts (p_ccb->p_lcb, p_ccb, p_buf2);
933 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
937 /*******************************************************************************
939 ** Function l2cu_send_peer_disc_rsp
941 ** Description Build and send an L2CAP "disconnect response" message
944 ** This function is passed the parameters for the disconnect
945 ** response instead of the CCB address, as it may be called
946 ** to send a disconnect response when there is no CCB.
950 *******************************************************************************/
951 void l2cu_send_peer_disc_rsp (tL2C_LCB *p_lcb, UINT8 remote_id, UINT16 local_cid,
958 L2CAP_TRACE_WARNING("lcb already released\n");
962 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_RSP_LEN, L2CAP_CMD_DISC_RSP, remote_id)) == NULL) {
963 L2CAP_TRACE_WARNING ("L2CAP - no buffer for disc_rsp");
967 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
969 UINT16_TO_STREAM (p, local_cid);
970 UINT16_TO_STREAM (p, remote_cid);
972 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
976 /*******************************************************************************
978 ** Function l2cu_send_peer_echo_req
980 ** Description Build and send an L2CAP "echo request" message
981 ** to the peer. Note that we do not currently allow
982 ** data in the echo request.
986 *******************************************************************************/
987 void l2cu_send_peer_echo_req (tL2C_LCB *p_lcb, UINT8 *p_data, UINT16 data_len)
993 l2cu_adj_id(p_lcb, L2CAP_ADJ_ZERO_ID); /* check for wrap to '0' */
995 if ((p_buf = l2cu_build_header(p_lcb, (UINT16) (L2CAP_ECHO_REQ_LEN + data_len), L2CAP_CMD_ECHO_REQ, p_lcb->id)) == NULL) {
996 L2CAP_TRACE_WARNING ("L2CAP - no buffer for echo_req");
1000 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1003 ARRAY_TO_STREAM (p, p_data, data_len);
1006 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1010 /*******************************************************************************
1012 ** Function l2cu_send_peer_echo_rsp
1014 ** Description Build and send an L2CAP "echo response" message
1019 *******************************************************************************/
1020 void l2cu_send_peer_echo_rsp (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len)
1025 /* Filter out duplicate IDs or if available buffers are low (intruder checking) */
1026 if (!id || id == p_lcb->cur_echo_id) {
1027 /* Dump this request since it is illegal */
1028 L2CAP_TRACE_WARNING ("L2CAP ignoring duplicate echo request (%d)", id);
1031 p_lcb->cur_echo_id = id;
1034 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
1035 uint16_t acl_packet_size = controller_get_interface()->get_acl_packet_size_classic();
1036 /* Don't return data if it does not fit in ACL and L2CAP MTU */
1037 maxlen = (L2CAP_CMD_BUF_SIZE > acl_packet_size) ?
1038 acl_data_size : (UINT16)L2CAP_CMD_BUF_SIZE;
1039 maxlen -= (UINT16)(BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
1040 L2CAP_CMD_OVERHEAD + L2CAP_ECHO_RSP_LEN);
1042 if (data_len > maxlen) {
1046 if ((p_buf = l2cu_build_header (p_lcb, (UINT16)(L2CAP_ECHO_RSP_LEN + data_len), L2CAP_CMD_ECHO_RSP, id)) == NULL) {
1047 L2CAP_TRACE_WARNING ("L2CAP - no buffer for echo_rsp");
1051 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1052 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1055 ARRAY_TO_STREAM (p, p_data, data_len);
1058 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1061 /*******************************************************************************
1063 ** Function l2cu_send_peer_info_req
1065 ** Description Build and send an L2CAP "info request" message
1069 *******************************************************************************/
1070 void l2cu_send_peer_info_req (tL2C_LCB *p_lcb, UINT16 info_type)
1075 /* check for wrap and/or BRCM ID */
1077 l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
1079 if ((p_buf = l2cu_build_header(p_lcb, 2, L2CAP_CMD_INFO_REQ, p_lcb->id)) == NULL) {
1080 L2CAP_TRACE_WARNING ("L2CAP - no buffer for info_req");
1084 L2CAP_TRACE_EVENT ("l2cu_send_peer_info_req: type 0x%04x", info_type);
1086 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1087 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1089 UINT16_TO_STREAM (p, info_type);
1091 p_lcb->w4_info_rsp = TRUE;
1092 btu_start_timer (&p_lcb->info_timer_entry, BTU_TTYPE_L2CAP_INFO, L2CAP_WAIT_INFO_RSP_TOUT);
1094 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1098 /*******************************************************************************
1100 ** Function l2cu_send_peer_info_rsp
1102 ** Description Build and send an L2CAP "info response" message
1107 *******************************************************************************/
1108 void l2cu_send_peer_info_rsp (tL2C_LCB *p_lcb, UINT8 remote_id, UINT16 info_type)
1112 UINT16 len = L2CAP_INFO_RSP_LEN;
1114 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1115 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1116 && (l2cb.test_info_resp & (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1117 L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_EXT_FLOW_SPEC |
1118 L2CAP_EXTFEA_FIXED_CHNLS | L2CAP_EXTFEA_EXT_WINDOW |
1119 L2CAP_EXTFEA_UCD_RECEPTION )) )
1121 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1122 && (L2CAP_EXTFEA_SUPPORTED_MASK & (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1123 L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS |
1124 L2CAP_EXTFEA_UCD_RECEPTION )) )
1127 len += L2CAP_EXTENDED_FEATURES_ARRAY_SIZE;
1128 } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1129 len += L2CAP_FIXED_CHNL_ARRAY_SIZE;
1130 } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1131 len += L2CAP_CONNLESS_MTU_INFO_SIZE;
1134 if ((p_buf = l2cu_build_header(p_lcb, len, L2CAP_CMD_INFO_RSP, remote_id)) == NULL) {
1135 L2CAP_TRACE_WARNING ("L2CAP - no buffer for info_rsp");
1139 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1140 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1142 UINT16_TO_STREAM (p, info_type);
1144 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1145 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1146 && (l2cb.test_info_resp & ( L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE
1147 | L2CAP_EXTFEA_UCD_RECEPTION )) )
1149 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1150 && (L2CAP_EXTFEA_SUPPORTED_MASK & ( L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE
1151 | L2CAP_EXTFEA_UCD_RECEPTION )) )
1154 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1155 #if (BLE_INCLUDED == TRUE)
1156 if (p_lcb->transport == BT_TRANSPORT_LE) {
1157 /* optional data are not added for now */
1158 UINT32_TO_STREAM (p, L2CAP_BLE_EXTFEA_MASK);
1162 #if L2CAP_CONFORMANCE_TESTING == TRUE
1163 UINT32_TO_STREAM (p, l2cb.test_info_resp);
1165 #if (L2CAP_NUM_FIXED_CHNLS > 0)
1166 UINT32_TO_STREAM (p, L2CAP_EXTFEA_SUPPORTED_MASK | L2CAP_EXTFEA_FIXED_CHNLS);
1168 UINT32_TO_STREAM (p, L2CAP_EXTFEA_SUPPORTED_MASK);
1172 } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1173 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1174 memset (p, 0, L2CAP_FIXED_CHNL_ARRAY_SIZE);
1176 p[0] = L2CAP_FIXED_CHNL_SIG_BIT;
1178 if ( L2CAP_EXTFEA_SUPPORTED_MASK & L2CAP_EXTFEA_UCD_RECEPTION ) {
1179 p[0] |= L2CAP_FIXED_CHNL_CNCTLESS_BIT;
1182 #if (L2CAP_NUM_FIXED_CHNLS > 0)
1186 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
1187 if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
1188 p[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] |= 1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8);
1192 } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1193 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1194 UINT16_TO_STREAM (p, L2CAP_UCD_MTU);
1196 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_NOT_SUPPORTED); /* 'not supported' */
1199 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1202 /******************************************************************************
1204 ** Function l2cu_enqueue_ccb
1206 ** Description queue CCB by priority. The first CCB is highest priority and
1207 ** is served at first. The CCB is queued to an LLCB or an LCB.
1211 *******************************************************************************/
1212 void l2cu_enqueue_ccb (tL2C_CCB *p_ccb)
1215 tL2C_CCB_Q *p_q = NULL;
1217 /* Find out which queue the channel is on
1219 if (p_ccb->p_lcb != NULL) {
1220 p_q = &p_ccb->p_lcb->ccb_queue;
1223 if ( (!p_ccb->in_use) || (p_q == NULL) ) {
1224 L2CAP_TRACE_ERROR ("l2cu_enqueue_ccb CID: 0x%04x ERROR in_use: %u p_lcb: %p",
1225 p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb);
1229 L2CAP_TRACE_DEBUG ("l2cu_enqueue_ccb CID: 0x%04x priority: %d",
1230 p_ccb->local_cid, p_ccb->ccb_priority);
1232 /* If the queue is empty, we go at the front */
1233 if (!p_q->p_first_ccb) {
1234 p_q->p_first_ccb = p_q->p_last_ccb = p_ccb;
1235 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1237 p_ccb1 = p_q->p_first_ccb;
1239 while (p_ccb1 != NULL) {
1240 /* Insert new ccb at the end of the same priority. Lower number, higher priority */
1241 if (p_ccb->ccb_priority < p_ccb1->ccb_priority) {
1242 /* Are we at the head of the queue ? */
1243 if (p_ccb1 == p_q->p_first_ccb) {
1244 p_q->p_first_ccb = p_ccb;
1246 p_ccb1->p_prev_ccb->p_next_ccb = p_ccb;
1249 p_ccb->p_next_ccb = p_ccb1;
1250 p_ccb->p_prev_ccb = p_ccb1->p_prev_ccb;
1251 p_ccb1->p_prev_ccb = p_ccb;
1255 p_ccb1 = p_ccb1->p_next_ccb;
1258 /* If we are lower then anyone in the list, we go at the end */
1260 /* add new ccb at the end of the list */
1261 p_q->p_last_ccb->p_next_ccb = p_ccb;
1263 p_ccb->p_next_ccb = NULL;
1264 p_ccb->p_prev_ccb = p_q->p_last_ccb;
1265 p_q->p_last_ccb = p_ccb;
1269 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1270 /* Adding CCB into round robin service table of its LCB */
1271 if (p_ccb->p_lcb != NULL) {
1272 /* if this is the first channel in this priority group */
1273 if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0 ) {
1274 /* Set the first channel to this CCB */
1275 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1276 /* Set the next serving channel in this group to this CCB */
1277 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1278 /* Initialize quota of this priority group based on its priority */
1279 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota = L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1281 /* increase number of channels in this group */
1282 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb++;
1288 /******************************************************************************
1290 ** Function l2cu_dequeue_ccb
1292 ** Description dequeue CCB from a queue
1296 *******************************************************************************/
1297 void l2cu_dequeue_ccb (tL2C_CCB *p_ccb)
1299 tL2C_CCB_Q *p_q = NULL;
1301 L2CAP_TRACE_DEBUG ("l2cu_dequeue_ccb CID: 0x%04x", p_ccb->local_cid);
1303 /* Find out which queue the channel is on
1305 if (p_ccb->p_lcb != NULL) {
1306 p_q = &p_ccb->p_lcb->ccb_queue;
1309 if ( (!p_ccb->in_use) || (p_q == NULL) || (p_q->p_first_ccb == NULL) ) {
1310 L2CAP_TRACE_ERROR ("l2cu_dequeue_ccb CID: 0x%04x ERROR in_use: %u p_lcb: %p p_q: %p p_q->p_first_ccb: %p",
1311 p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb, p_q, p_q ? p_q->p_first_ccb : 0);
1315 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1316 /* Removing CCB from round robin service table of its LCB */
1317 if (p_ccb->p_lcb != NULL) {
1318 /* decrease number of channels in this priority group */
1319 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb--;
1321 /* if it was the last channel in the priority group */
1322 if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0 ) {
1323 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1324 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1326 /* if it is the first channel of this group */
1327 if ( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb == p_ccb ) {
1328 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb->p_next_ccb;
1330 /* if it is the next serving channel of this group */
1331 if ( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb == p_ccb ) {
1332 /* simply, start serving from the first channel */
1333 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb
1334 = p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb;
1340 if (p_ccb == p_q->p_first_ccb) {
1341 /* We are removing the first in a queue */
1342 p_q->p_first_ccb = p_ccb->p_next_ccb;
1344 if (p_q->p_first_ccb) {
1345 p_q->p_first_ccb->p_prev_ccb = NULL;
1347 p_q->p_last_ccb = NULL;
1349 } else if (p_ccb == p_q->p_last_ccb) {
1350 /* We are removing the last in a queue */
1351 p_q->p_last_ccb = p_ccb->p_prev_ccb;
1352 p_q->p_last_ccb->p_next_ccb = NULL;
1354 /* In the middle of a chain. */
1355 p_ccb->p_prev_ccb->p_next_ccb = p_ccb->p_next_ccb;
1356 p_ccb->p_next_ccb->p_prev_ccb = p_ccb->p_prev_ccb;
1359 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1362 /******************************************************************************
1364 ** Function l2cu_change_pri_ccb
1370 *******************************************************************************/
1371 void l2cu_change_pri_ccb (tL2C_CCB *p_ccb, tL2CAP_CHNL_PRIORITY priority)
1373 if (p_ccb->ccb_priority != priority) {
1374 /* If CCB is not the only guy on the queue */
1375 if ( (p_ccb->p_next_ccb != NULL) || (p_ccb->p_prev_ccb != NULL) ) {
1376 L2CAP_TRACE_DEBUG ("Update CCB list in logical link");
1378 /* Remove CCB from queue and re-queue it at new priority */
1379 l2cu_dequeue_ccb (p_ccb);
1381 p_ccb->ccb_priority = priority;
1382 l2cu_enqueue_ccb (p_ccb);
1384 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1386 /* If CCB is the only guy on the queue, no need to re-enqueue */
1387 /* update only round robin service data */
1388 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 0;
1389 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1390 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1392 p_ccb->ccb_priority = priority;
1394 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1395 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1396 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota = L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1397 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 1;
1403 /*******************************************************************************
1405 ** Function l2cu_allocate_ccb
1407 ** Description This function allocates a Channel Control Block and
1408 ** attaches it to a link control block. The local CID
1409 ** is also assigned.
1411 ** Returns pointer to CCB, or NULL if none
1413 *******************************************************************************/
1414 tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
1419 L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x", cid);
1421 if (!l2cb.p_free_ccb_first) {
1425 /* If a CID was passed in, use that, else take the first free one */
1427 p_ccb = l2cb.p_free_ccb_first;
1428 l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1432 p_ccb = &l2cb.ccb_pool[cid - L2CAP_BASE_APPL_CID];
1434 if (p_ccb == l2cb.p_free_ccb_first) {
1435 l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1437 for (p_prev = l2cb.p_free_ccb_first; p_prev != NULL; p_prev = p_prev->p_next_ccb) {
1438 if (p_prev->p_next_ccb == p_ccb) {
1439 p_prev->p_next_ccb = p_ccb->p_next_ccb;
1441 if (p_ccb == l2cb.p_free_ccb_last) {
1442 l2cb.p_free_ccb_last = p_prev;
1448 if (p_prev == NULL) {
1449 L2CAP_TRACE_ERROR ("l2cu_allocate_ccb: could not find CCB for CID 0x%04x in the free list", cid);
1455 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1457 p_ccb->in_use = TRUE;
1459 /* Get a CID for the connection */
1460 p_ccb->local_cid = L2CAP_BASE_APPL_CID + (UINT16)(p_ccb - l2cb.ccb_pool);
1462 p_ccb->p_lcb = p_lcb;
1463 p_ccb->p_rcb = NULL;
1464 p_ccb->should_free_rcb = false;
1466 /* Set priority then insert ccb into LCB queue (if we have an LCB) */
1467 p_ccb->ccb_priority = L2CAP_CHNL_PRIORITY_LOW;
1470 l2cu_enqueue_ccb (p_ccb);
1473 /* clear what peer wants to configure */
1474 p_ccb->peer_cfg_bits = 0;
1476 /* Put in default values for configuration */
1477 memset (&p_ccb->our_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1478 memset (&p_ccb->peer_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1480 /* Put in default values for local/peer configurations */
1481 p_ccb->our_cfg.flush_to = p_ccb->peer_cfg.flush_to = L2CAP_DEFAULT_FLUSH_TO;
1482 p_ccb->our_cfg.mtu = p_ccb->peer_cfg.mtu = L2CAP_DEFAULT_MTU;
1483 p_ccb->our_cfg.qos.service_type = p_ccb->peer_cfg.qos.service_type = L2CAP_DEFAULT_SERV_TYPE;
1484 p_ccb->our_cfg.qos.token_rate = p_ccb->peer_cfg.qos.token_rate = L2CAP_DEFAULT_TOKEN_RATE;
1485 p_ccb->our_cfg.qos.token_bucket_size = p_ccb->peer_cfg.qos.token_bucket_size = L2CAP_DEFAULT_BUCKET_SIZE;
1486 p_ccb->our_cfg.qos.peak_bandwidth = p_ccb->peer_cfg.qos.peak_bandwidth = L2CAP_DEFAULT_PEAK_BANDWIDTH;
1487 p_ccb->our_cfg.qos.latency = p_ccb->peer_cfg.qos.latency = L2CAP_DEFAULT_LATENCY;
1488 p_ccb->our_cfg.qos.delay_variation = p_ccb->peer_cfg.qos.delay_variation = L2CAP_DEFAULT_DELAY;
1490 p_ccb->bypass_fcs = 0;
1491 memset (&p_ccb->ertm_info, 0, sizeof(tL2CAP_ERTM_INFO));
1492 p_ccb->peer_cfg_already_rejected = FALSE;
1493 p_ccb->fcr_cfg_tries = L2CAP_MAX_FCR_CFG_TRIES;
1495 /* stop and release timers */
1496 btu_free_quick_timer(&p_ccb->fcrb.ack_timer);
1497 memset(&p_ccb->fcrb.ack_timer, 0, sizeof(TIMER_LIST_ENT));
1498 p_ccb->fcrb.ack_timer.param = (TIMER_PARAM_TYPE)p_ccb;
1500 btu_free_quick_timer(&p_ccb->fcrb.mon_retrans_timer);
1501 memset(&p_ccb->fcrb.mon_retrans_timer, 0, sizeof(TIMER_LIST_ENT));
1502 p_ccb->fcrb.mon_retrans_timer.param = (TIMER_PARAM_TYPE)p_ccb;
1505 /* CSP408639 Fix: When L2CAP send amp move channel request or receive
1506 * L2CEVT_AMP_MOVE_REQ do following sequence. Send channel move
1507 * request -> Stop retrans/monitor timer -> Change channel state to CST_AMP_MOVING. */
1510 #if (CLASSIC_BT_INCLUDED == TRUE)
1511 l2c_fcr_free_timer (p_ccb);
1512 #endif ///CLASSIC_BT_INCLUDED == TRUE
1513 p_ccb->ertm_info.preferred_mode = L2CAP_FCR_BASIC_MODE; /* Default mode for channel is basic mode */
1514 p_ccb->ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_BASIC; /* Default mode for channel is basic mode */
1515 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
1516 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
1517 p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
1518 p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
1519 p_ccb->max_rx_mtu = L2CAP_MTU_SIZE;
1520 p_ccb->tx_mps = L2CAP_FCR_TX_BUF_SIZE - 32;
1522 p_ccb->xmit_hold_q = fixed_queue_new(SIZE_MAX);
1523 #if (CLASSIC_BT_INCLUDED == TRUE)
1524 p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX);
1525 p_ccb->fcrb.retrans_q = fixed_queue_new(SIZE_MAX);
1526 p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(SIZE_MAX);
1527 #endif ///CLASSIC_BT_INCLUDED == TRUE
1529 p_ccb->cong_sent = FALSE;
1530 p_ccb->buff_quota = 2; /* This gets set after config */
1532 /* If CCB was reserved Config_Done can already have some value */
1534 p_ccb->config_done = 0;
1536 L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x config_done:0x%x", cid, p_ccb->config_done);
1539 p_ccb->chnl_state = CST_CLOSED;
1541 p_ccb->tx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1542 p_ccb->rx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1544 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
1545 p_ccb->is_flushable = FALSE;
1548 btu_free_timer(&p_ccb->timer_entry);
1549 memset(&p_ccb->timer_entry, 0, sizeof(TIMER_LIST_ENT));
1550 p_ccb->timer_entry.param = (TIMER_PARAM_TYPE)p_ccb;
1551 p_ccb->timer_entry.in_use = 0;
1553 l2c_link_adjust_chnl_allocation ();
1558 /*******************************************************************************
1560 ** Function l2cu_start_post_bond_timer
1562 ** Description This function starts the ACL Link inactivity timer after
1563 ** dedicated bonding
1564 ** This timer can be longer than the normal link inactivity
1565 ** timer for some platforms.
1567 ** Returns BOOLEAN - TRUE if idle timer started or disconnect initiated
1568 ** FALSE if there's one or more pending CCB's exist
1570 *******************************************************************************/
1571 BOOLEAN l2cu_start_post_bond_timer (UINT16 handle)
1574 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
1580 p_lcb->is_bonding = FALSE;
1582 /* Only start timer if no control blocks allocated */
1583 if (p_lcb->ccb_queue.p_first_ccb != NULL) {
1587 /* If no channels on the connection, start idle timeout */
1588 if ( (p_lcb->link_state == LST_CONNECTED) || (p_lcb->link_state == LST_CONNECTING) || (p_lcb->link_state == LST_DISCONNECTING) ) {
1589 if (p_lcb->idle_timeout == 0) {
1590 if (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) {
1591 p_lcb->link_state = LST_DISCONNECTING;
1592 timeout = L2CAP_LINK_DISCONNECT_TOUT;
1594 timeout = BT_1SEC_TIMEOUT;
1597 timeout = L2CAP_BONDING_TIMEOUT;
1600 if (timeout != 0xFFFF) {
1601 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, timeout);
1610 /*******************************************************************************
1612 ** Function l2cu_release_ccb
1614 ** Description This function releases a Channel Control Block. The timer
1615 ** is stopped, any attached buffers freed, and the CCB is removed
1616 ** from the link control block.
1620 *******************************************************************************/
1621 void l2cu_release_ccb (tL2C_CCB *p_ccb)
1623 tL2C_LCB *p_lcb = p_ccb->p_lcb;
1624 tL2C_RCB *p_rcb = p_ccb->p_rcb;
1626 L2CAP_TRACE_DEBUG ("l2cu_release_ccb: cid 0x%04x in_use: %u", p_ccb->local_cid, p_ccb->in_use);
1628 /* If already released, could be race condition */
1629 if (!p_ccb->in_use) {
1632 #if (SDP_INCLUDED == TRUE)
1633 if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
1634 btm_sec_clr_service_by_psm(p_rcb->psm);
1636 #endif ///SMP_INCLUDED == TRUE
1637 if (p_ccb->should_free_rcb) {
1639 p_ccb->p_rcb = NULL;
1640 p_ccb->should_free_rcb = false;
1644 btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
1647 /* Stop and free the timer */
1648 btu_free_timer (&p_ccb->timer_entry);
1650 fixed_queue_free(p_ccb->xmit_hold_q, osi_free_func);
1651 p_ccb->xmit_hold_q = NULL;
1652 #if (CLASSIC_BT_INCLUDED == TRUE)
1653 fixed_queue_free(p_ccb->fcrb.srej_rcv_hold_q, osi_free_func);
1654 fixed_queue_free(p_ccb->fcrb.retrans_q, osi_free_func);
1655 fixed_queue_free(p_ccb->fcrb.waiting_for_ack_q, osi_free_func);
1656 p_ccb->fcrb.srej_rcv_hold_q = NULL;
1657 p_ccb->fcrb.retrans_q = NULL;
1658 p_ccb->fcrb.waiting_for_ack_q = NULL;
1659 #endif ///CLASSIC_BT_INCLUDED == TRUE
1662 #if (CLASSIC_BT_INCLUDED == TRUE)
1663 l2c_fcr_cleanup (p_ccb);
1664 #endif ///CLASSIC_BT_INCLUDED == TRUE
1665 /* Channel may not be assigned to any LCB if it was just pre-reserved */
1667 ( (p_ccb->local_cid >= L2CAP_BASE_APPL_CID)
1668 #if (L2CAP_UCD_INCLUDED == TRUE)
1669 || (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)
1673 l2cu_dequeue_ccb (p_ccb);
1675 /* Delink the CCB from the LCB */
1676 p_ccb->p_lcb = NULL;
1679 /* Put the CCB back on the free pool */
1680 if (!l2cb.p_free_ccb_first) {
1681 l2cb.p_free_ccb_first = p_ccb;
1682 l2cb.p_free_ccb_last = p_ccb;
1683 p_ccb->p_next_ccb = NULL;
1684 p_ccb->p_prev_ccb = NULL;
1686 p_ccb->p_next_ccb = NULL;
1687 p_ccb->p_prev_ccb = l2cb.p_free_ccb_last;
1688 l2cb.p_free_ccb_last->p_next_ccb = p_ccb;
1689 l2cb.p_free_ccb_last = p_ccb;
1692 /* Flag as not in use */
1693 p_ccb->in_use = FALSE;
1695 /* If no channels on the connection, start idle timeout */
1696 if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED)) {
1697 if (!p_lcb->ccb_queue.p_first_ccb) {
1698 l2cu_no_dynamic_ccbs (p_lcb);
1700 /* Link is still active, adjust channel quotas. */
1701 l2c_link_adjust_chnl_allocation ();
1706 /*******************************************************************************
1708 ** Function l2cu_find_ccb_by_remote_cid
1710 ** Description Look through all active CCBs on a link for a match based
1711 ** on the remote CID.
1713 ** Returns pointer to matched CCB, or NULL if no match
1715 *******************************************************************************/
1716 tL2C_CCB *l2cu_find_ccb_by_remote_cid (tL2C_LCB *p_lcb, UINT16 remote_cid)
1720 /* If LCB is NULL, look through all active links */
1724 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
1725 if ((p_ccb->in_use) && (p_ccb->remote_cid == remote_cid)) {
1730 /* If here, no match found */
1734 /*******************************************************************************
1736 ** Function l2cu_allocate_rcb
1738 ** Description Look through the Registration Control Blocks for a free
1741 ** Returns Pointer to the RCB or NULL if not found
1743 *******************************************************************************/
1744 tL2C_RCB *l2cu_allocate_rcb (UINT16 psm)
1746 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
1749 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1750 if (!p_rcb->in_use) {
1751 p_rcb->in_use = TRUE;
1753 #if (L2CAP_UCD_INCLUDED == TRUE)
1754 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
1760 /* If here, no free RCB found */
1764 /*******************************************************************************
1766 ** Function l2cu_allocate_ble_rcb
1768 ** Description Look through the BLE Registration Control Blocks for a free
1771 ** Returns Pointer to the BLE RCB or NULL if not found
1773 *******************************************************************************/
1774 tL2C_RCB *l2cu_allocate_ble_rcb (UINT16 psm)
1776 tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
1779 for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
1783 p_rcb->in_use = TRUE;
1785 #if (L2CAP_UCD_INCLUDED == TRUE)
1786 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
1792 /* If here, no free RCB found */
1796 /*******************************************************************************
1798 ** Function l2cu_release_rcb
1800 ** Description Mark an RCB as no longet in use
1804 *******************************************************************************/
1805 void l2cu_release_rcb (tL2C_RCB *p_rcb)
1807 p_rcb->in_use = FALSE;
1812 /*******************************************************************************
1814 ** Function l2cu_disconnect_chnl
1816 ** Description Disconnect a channel. Typically, this is due to either
1817 ** receiving a bad configuration, bad packet or max_retries expiring.
1819 *******************************************************************************/
1820 void l2cu_disconnect_chnl (tL2C_CCB *p_ccb)
1822 UINT16 local_cid = p_ccb->local_cid;
1824 if (local_cid >= L2CAP_BASE_APPL_CID) {
1825 tL2CA_DISCONNECT_IND_CB *p_disc_cb = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
1827 L2CAP_TRACE_WARNING ("L2CAP - disconnect_chnl CID: 0x%04x", local_cid);
1829 l2cu_send_peer_disc_req (p_ccb);
1831 l2cu_release_ccb (p_ccb);
1833 (*p_disc_cb)(local_cid, FALSE);
1835 /* failure on the AMP channel, probably need to disconnect ACL */
1836 L2CAP_TRACE_ERROR ("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid);
1841 /*******************************************************************************
1843 ** Function l2cu_find_rcb_by_psm
1845 ** Description Look through the Registration Control Blocks to see if
1846 ** anyone registered to handle the PSM in question
1848 ** Returns Pointer to the RCB or NULL if not found
1850 *******************************************************************************/
1851 tL2C_RCB *l2cu_find_rcb_by_psm (UINT16 psm)
1853 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
1856 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1857 if ((p_rcb->in_use) && (p_rcb->psm == psm)) {
1862 /* If here, no match found */
1866 /*******************************************************************************
1868 ** Function l2cu_find_ble_rcb_by_psm
1870 ** Description Look through the BLE Registration Control Blocks to see if
1871 ** anyone registered to handle the PSM in question
1873 ** Returns Pointer to the BLE RCB or NULL if not found
1875 *******************************************************************************/
1876 tL2C_RCB *l2cu_find_ble_rcb_by_psm (UINT16 psm)
1878 tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
1881 for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
1883 if ((p_rcb->in_use) && (p_rcb->psm == psm))
1887 /* If here, no match found */
1893 /*******************************************************************************
1895 ** Function l2cu_process_peer_cfg_req
1897 ** Description This function is called when the peer sends us a "config request"
1898 ** message. It extracts the configuration of interest and saves
1901 ** Note: Negotiation of the FCR channel type is handled internally,
1902 ** all others are passed to the upper layer.
1904 ** Returns UINT8 - L2CAP_PEER_CFG_OK if passed to upper layer,
1905 ** L2CAP_PEER_CFG_UNACCEPTABLE if automatically responded to
1906 ** because parameters are unnacceptable from a specification
1908 ** L2CAP_PEER_CFG_DISCONNECT if no compatible channel modes
1909 ** between the two devices, and shall be closed.
1911 *******************************************************************************/
1912 UINT8 l2cu_process_peer_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
1914 BOOLEAN mtu_ok = TRUE;
1915 BOOLEAN qos_type_ok = TRUE;
1916 BOOLEAN flush_to_ok = TRUE;
1917 BOOLEAN fcr_ok = TRUE;
1918 #if (CLASSIC_BT_INCLUDED == TRUE)
1920 #endif ///CLASSIC_BT_INCLUDED == TRUE
1921 /* Ignore FCR parameters for basic mode */
1922 if (!p_cfg->fcr_present) {
1923 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
1926 /* Save the MTU that our peer can receive */
1927 if (p_cfg->mtu_present) {
1928 /* Make sure MTU is at least the minimum */
1929 if (p_cfg->mtu >= L2CAP_MIN_MTU) {
1930 /* In basic mode, limit the MTU to our buffer size */
1931 if ( (p_cfg->fcr_present == FALSE) && (p_cfg->mtu > L2CAP_MTU_SIZE) ) {
1932 p_cfg->mtu = L2CAP_MTU_SIZE;
1935 /* Save the accepted value in case of renegotiation */
1936 p_ccb->peer_cfg.mtu = p_cfg->mtu;
1937 p_ccb->peer_cfg.mtu_present = TRUE;
1938 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_MTU;
1939 } else { /* Illegal MTU value */
1940 p_cfg->mtu = L2CAP_MIN_MTU;
1944 /* Reload mtu from a previously accepted config request */
1945 else if (p_ccb->peer_cfg.mtu_present) {
1946 p_cfg->mtu_present = TRUE;
1947 p_cfg->mtu = p_ccb->peer_cfg.mtu;
1950 /* Verify that the flush timeout is a valid value (0 is illegal) */
1951 if (p_cfg->flush_to_present) {
1952 if (!p_cfg->flush_to) {
1953 p_cfg->flush_to = 0xFFFF; /* Infinite retransmissions (spec default) */
1954 flush_to_ok = FALSE;
1955 } else { /* Save the accepted value in case of renegotiation */
1956 p_ccb->peer_cfg.flush_to_present = TRUE;
1957 p_ccb->peer_cfg.flush_to = p_cfg->flush_to;
1958 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FLUSH_TO;
1961 /* Reload flush_to from a previously accepted config request */
1962 else if (p_ccb->peer_cfg.flush_to_present) {
1963 p_cfg->flush_to_present = TRUE;
1964 p_cfg->flush_to = p_ccb->peer_cfg.flush_to;
1967 /* Save the QOS settings the the peer is using */
1968 if (p_cfg->qos_present) {
1969 /* Make sure service type is not a reserved value; otherwise let upper
1970 layer decide if acceptable
1972 if (p_cfg->qos.service_type <= GUARANTEED) {
1973 p_ccb->peer_cfg.qos = p_cfg->qos;
1974 p_ccb->peer_cfg.qos_present = TRUE;
1975 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_QOS;
1976 } else { /* Illegal service type value */
1977 p_cfg->qos.service_type = BEST_EFFORT;
1978 qos_type_ok = FALSE;
1981 /* Reload QOS from a previously accepted config request */
1982 else if (p_ccb->peer_cfg.qos_present) {
1983 p_cfg->qos_present = TRUE;
1984 p_cfg->qos = p_ccb->peer_cfg.qos;
1986 #if (CLASSIC_BT_INCLUDED == TRUE)
1987 if ((fcr_status = l2c_fcr_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_DISCONNECT) {
1988 /* Notify caller to disconnect the channel (incompatible modes) */
1989 p_cfg->result = L2CAP_CFG_FAILED_NO_REASON;
1990 p_cfg->mtu_present = p_cfg->qos_present = p_cfg->flush_to_present = 0;
1992 return (L2CAP_PEER_CFG_DISCONNECT);
1995 fcr_ok = (fcr_status == L2CAP_PEER_CFG_OK);
1996 #endif ///CLASSIC_BT_INCLUDED == TRUE
1998 /* Return any unacceptable parameters */
1999 if (mtu_ok && flush_to_ok && qos_type_ok && fcr_ok) {
2000 l2cu_adjust_out_mps (p_ccb);
2001 return (L2CAP_PEER_CFG_OK);
2003 p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
2006 p_cfg->mtu_present = FALSE;
2009 p_cfg->flush_to_present = FALSE;
2012 p_cfg->qos_present = FALSE;
2015 p_cfg->fcr_present = FALSE;
2018 return (L2CAP_PEER_CFG_UNACCEPTABLE);
2023 /*******************************************************************************
2025 ** Function l2cu_process_peer_cfg_rsp
2027 ** Description This function is called when the peer sends us a "config response"
2028 ** message. It extracts the configuration of interest and saves
2033 *******************************************************************************/
2034 void l2cu_process_peer_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2036 /* If we wanted QoS and the peer sends us a positive response with QoS, use his values */
2037 if ( (p_cfg->qos_present) && (p_ccb->our_cfg.qos_present) ) {
2038 p_ccb->our_cfg.qos = p_cfg->qos;
2041 if (p_cfg->fcr_present) {
2042 /* Save the retransmission and monitor timeout values */
2043 if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE) {
2044 p_ccb->peer_cfg.fcr.rtrans_tout = p_cfg->fcr.rtrans_tout;
2045 p_ccb->peer_cfg.fcr.mon_tout = p_cfg->fcr.mon_tout;
2048 /* Calculate the max number of packets for which we can delay sending an ack */
2049 if (p_cfg->fcr.tx_win_sz < p_ccb->our_cfg.fcr.tx_win_sz) {
2050 p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2052 p_ccb->fcrb.max_held_acks = p_ccb->our_cfg.fcr.tx_win_sz / 3;
2055 L2CAP_TRACE_DEBUG ("l2cu_process_peer_cfg_rsp(): peer tx_win_sz: %d, our tx_win_sz: %d, max_held_acks: %d",
2056 p_cfg->fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz, p_ccb->fcrb.max_held_acks);
2060 /*******************************************************************************
2062 ** Function l2cu_process_our_cfg_req
2064 ** Description This function is called when we send a "config request"
2065 ** message. It extracts the configuration of interest and saves
2070 *******************************************************************************/
2071 void l2cu_process_our_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2074 UINT16 hci_flush_to;
2076 /* Save the QOS settings we are using for transmit */
2077 if (p_cfg->qos_present) {
2078 p_ccb->our_cfg.qos_present = TRUE;
2079 p_ccb->our_cfg.qos = p_cfg->qos;
2082 if (p_cfg->fcr_present) {
2083 /* Override FCR options if attempting streaming or basic */
2084 if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE) {
2085 memset(&p_cfg->fcr, 0, sizeof(tL2CAP_FCR_OPTS));
2087 /* On BR/EDR, timer values are zero in config request */
2088 /* On class 2 AMP, timer value in config request shall be non-0 processing time */
2089 /* timer value in config response shall be greater than received processing time */
2090 p_cfg->fcr.mon_tout = p_cfg->fcr.rtrans_tout = 0;
2092 if (p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE) {
2093 p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0;
2097 /* Set the threshold to send acks (may be updated in the cfg response) */
2098 p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2100 /* Include FCS option only if peer can handle it */
2101 if (p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_NO_CRC) {
2102 /* FCS check can be bypassed if peer also desires to bypass */
2103 if (p_cfg->fcs_present && p_cfg->fcs == L2CAP_CFG_FCS_BYPASS) {
2104 p_ccb->bypass_fcs |= L2CAP_CFG_FCS_OUR;
2107 p_cfg->fcs_present = FALSE;
2110 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
2113 p_ccb->our_cfg.fcr.mode = p_cfg->fcr.mode;
2114 p_ccb->our_cfg.fcr_present = p_cfg->fcr_present;
2116 /* Check the flush timeout. If it is lower than the current one used */
2117 /* then we need to adjust the flush timeout sent to the controller */
2118 if (p_cfg->flush_to_present) {
2119 if ((p_cfg->flush_to == 0) || (p_cfg->flush_to == L2CAP_NO_AUTOMATIC_FLUSH)) {
2120 /* don't send invalid flush timeout */
2121 /* SPEC: The sender of the Request shall specify its flush timeout value */
2122 /* if it differs from the default value of 0xFFFF */
2123 p_cfg->flush_to_present = FALSE;
2125 p_ccb->our_cfg.flush_to = p_cfg->flush_to;
2126 p_lcb = p_ccb->p_lcb;
2128 if (p_cfg->flush_to < p_lcb->link_flush_tout) {
2129 p_lcb->link_flush_tout = p_cfg->flush_to;
2131 /* If the timeout is within range of HCI, set the flush timeout */
2132 if (p_cfg->flush_to <= ((HCI_MAX_AUTO_FLUSH_TOUT * 5) / 8)) {
2133 /* Convert flush timeout to 0.625 ms units, with round */
2134 hci_flush_to = ((p_cfg->flush_to * 8) + 3) / 5;
2135 btsnd_hcic_write_auto_flush_tout (p_lcb->handle, hci_flush_to);
2143 /*******************************************************************************
2145 ** Function l2cu_process_our_cfg_rsp
2147 ** Description This function is called when we send the peer a "config response"
2148 ** message. It extracts the configuration of interest and saves
2153 *******************************************************************************/
2154 #if (CLASSIC_BT_INCLUDED == TRUE)
2155 void l2cu_process_our_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2157 /* If peer wants QoS, we are allowed to change the values in a positive response */
2158 if ( (p_cfg->qos_present) && (p_ccb->peer_cfg.qos_present) ) {
2159 p_ccb->peer_cfg.qos = p_cfg->qos;
2161 p_cfg->qos_present = FALSE;
2164 l2c_fcr_adj_our_rsp_options (p_ccb, p_cfg);
2166 #endif ///CLASSIC_BT_INCLUDED == TRUE
2169 /*******************************************************************************
2171 ** Function l2cu_device_reset
2173 ** Description This function is called when reset of the device is
2174 ** completed. For all active connection simulate HCI_DISC
2178 *******************************************************************************/
2179 void l2cu_device_reset (void)
2182 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
2184 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2185 if ((p_lcb->in_use) && (p_lcb->handle != HCI_INVALID_HANDLE)) {
2186 l2c_link_hci_disc_comp (p_lcb->handle, (UINT8) - 1);
2189 #if (BLE_INCLUDED == TRUE)
2190 l2cb.is_ble_connecting = FALSE;
2194 /*******************************************************************************
2196 ** Function l2cu_create_conn
2198 ** Description This function initiates an acl connection via HCI
2200 ** Returns TRUE if successful, FALSE if gki get buffer fails.
2202 *******************************************************************************/
2203 BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
2206 tL2C_LCB *p_lcb_cur = &l2cb.lcb_pool[0];
2207 #if BTM_SCO_INCLUDED == TRUE
2208 BOOLEAN is_sco_active;
2211 #if (BLE_INCLUDED == TRUE)
2212 tBT_DEVICE_TYPE dev_type;
2213 tBLE_ADDR_TYPE addr_type = p_lcb->open_addr_type;
2214 BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
2216 if (transport == BT_TRANSPORT_LE) {
2217 if (!controller_get_interface()->supports_ble()) {
2221 p_lcb->ble_addr_type = addr_type;
2222 p_lcb->transport = BT_TRANSPORT_LE;
2224 return (l2cble_create_conn(p_lcb));
2228 /* If there is a connection where we perform as a slave, try to switch roles
2229 for this connection */
2230 for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb_cur++) {
2231 if (p_lcb_cur == p_lcb) {
2235 if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) {
2237 #if BTM_SCO_INCLUDED == TRUE
2238 /* The LMP_switch_req shall be sent only if the ACL logical transport
2239 is in active mode, when encryption is disabled, and all synchronous
2240 logical transports on the same physical link are disabled." */
2242 /* Check if there is any SCO Active on this BD Address */
2243 is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr);
2245 L2CAP_TRACE_API ("l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s", \
2246 (is_sco_active == TRUE) ? "TRUE" : "FALSE");
2248 if (is_sco_active == TRUE) {
2249 continue; /* No Master Slave switch not allowed when SCO Active */
2252 /*4_1_TODO check if btm_cb.devcb.local_features to be used instead */
2253 if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) {
2254 /* mark this lcb waiting for switch to be completed and
2255 start switch on the other one */
2256 p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
2257 p_lcb->link_role = HCI_ROLE_MASTER;
2259 if (BTM_SwitchRole (p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) == BTM_CMD_STARTED) {
2260 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_LINK_ROLE_SWITCH_TOUT);
2267 p_lcb->link_state = LST_CONNECTING;
2269 return (l2cu_create_conn_after_switch (p_lcb));
2272 /*******************************************************************************
2274 ** Function l2cu_get_num_hi_priority
2276 ** Description Gets the number of high priority channels.
2280 *******************************************************************************/
2281 UINT8 l2cu_get_num_hi_priority (void)
2285 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
2287 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2288 if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2296 /*******************************************************************************
2298 ** Function l2cu_create_conn_after_switch
2300 ** Description This function initiates an acl connection via HCI
2301 ** If switch required to create connection it is already done.
2303 ** Returns TRUE if successful, FALSE if gki get buffer fails.
2305 *******************************************************************************/
2307 BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb)
2309 UINT8 allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2310 tBTM_INQ_INFO *p_inq_info;
2311 UINT8 page_scan_rep_mode;
2312 UINT8 page_scan_mode;
2313 UINT16 clock_offset;
2315 UINT16 num_acl = BTM_GetNumAclLinks();
2316 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_lcb->remote_bd_addr);
2317 UINT8 no_hi_prio_chs = l2cu_get_num_hi_priority();
2319 p_features = BTM_ReadLocalFeatures();
2321 L2CAP_TRACE_DEBUG ("l2cu_create_conn_after_switch :%d num_acl:%d no_hi: %d is_bonding:%d",
2322 l2cb.disallow_switch, num_acl, no_hi_prio_chs, p_lcb->is_bonding);
2323 /* FW team says that we can participant in 4 piconets
2324 * typically 3 piconet + 1 for scanning.
2325 * We can enhance the code to count the number of piconets later. */
2326 if ( ((!l2cb.disallow_switch && (num_acl < 3)) || (p_lcb->is_bonding && (no_hi_prio_chs == 0)))
2327 && HCI_SWITCH_SUPPORTED(p_features)) {
2328 allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2330 allow_switch = HCI_CR_CONN_NOT_ALLOW_SWITCH;
2333 p_lcb->link_state = LST_CONNECTING;
2335 /* Check with the BT manager if details about remote device are known */
2336 if ((p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr)) != NULL) {
2337 page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
2338 page_scan_mode = p_inq_info->results.page_scan_mode;
2339 clock_offset = (UINT16)(p_inq_info->results.clock_offset);
2341 /* No info known. Use default settings */
2342 page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
2343 page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
2345 clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
2348 if (!btsnd_hcic_create_conn (p_lcb->remote_bd_addr,
2349 ( HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1
2350 | HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3
2351 | HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5 ),
2358 L2CAP_TRACE_ERROR ("L2CAP - no buffer for l2cu_create_conn");
2359 l2cu_release_lcb (p_lcb);
2363 btm_acl_update_busy_level (BTM_BLI_PAGE_EVT);
2365 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK,
2366 L2CAP_LINK_CONNECT_TOUT);
2372 /*******************************************************************************
2374 ** Function l2cu_find_lcb_by_state
2376 ** Description Look through all active LCBs for a match based on the
2379 ** Returns pointer to first matched LCB, or NULL if no match
2381 *******************************************************************************/
2382 tL2C_LCB *l2cu_find_lcb_by_state (tL2C_LINK_STATE state)
2385 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
2387 for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2388 if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
2393 /* If here, no match found */
2398 /*******************************************************************************
2400 ** Function l2cu_lcb_disconnecting
2402 ** Description On each active lcb, check if the lcb is in disconnecting
2403 ** state, or if there are no ccb's on the lcb (implying
2404 idle timeout is running), or if last ccb on the link
2405 is in disconnecting state.
2407 ** Returns TRUE if any of above conditions met, FALSE otherwise
2409 *******************************************************************************/
2410 BOOLEAN l2cu_lcb_disconnecting (void)
2415 BOOLEAN status = FALSE;
2417 p_lcb = &l2cb.lcb_pool[0];
2419 for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2420 if (p_lcb->in_use) {
2421 /* no ccbs on lcb, or lcb is in disconnecting state */
2422 if ((!p_lcb->ccb_queue.p_first_ccb) || (p_lcb->link_state == LST_DISCONNECTING)) {
2426 /* only one ccb left on lcb */
2427 else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) {
2428 p_ccb = p_lcb->ccb_queue.p_first_ccb;
2430 if ((p_ccb->in_use) &&
2431 ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
2432 (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
2443 /*******************************************************************************
2445 ** Function l2cu_set_acl_priority
2447 ** Description Sets the transmission priority for a channel.
2448 ** (For initial implementation only two values are valid.
2449 ** L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
2451 ** Returns TRUE if a valid channel, else FALSE
2453 *******************************************************************************/
2455 BOOLEAN l2cu_set_acl_priority (BD_ADDR bd_addr, UINT8 priority, BOOLEAN reset_after_rs)
2459 UINT8 command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2462 //APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority);
2464 /* Find the link control block for the acl channel */
2465 if ((p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR)) == NULL) {
2466 L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_SetAclPriority");
2470 if (BTM_IS_BRCM_CONTROLLER()) {
2471 /* Called from above L2CAP through API; send VSC if changed */
2472 if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||
2473 /* Called because of a master/slave role switch; if high resend VSC */
2474 ( reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2477 vs_param = (priority == L2CAP_PRIORITY_HIGH) ? HCI_BRCM_ACL_PRIORITY_HIGH : HCI_BRCM_ACL_PRIORITY_LOW;
2479 UINT16_TO_STREAM (pp, p_lcb->handle);
2480 UINT8_TO_STREAM (pp, vs_param);
2482 BTM_VendorSpecificCommand (HCI_BRCM_SET_ACL_PRIORITY, HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command, NULL);
2484 /* Adjust lmp buffer allocation for this channel if priority changed */
2485 if (p_lcb->acl_priority != priority) {
2486 p_lcb->acl_priority = priority;
2487 l2c_link_adjust_allocation();
2494 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
2495 /******************************************************************************
2497 ** Function l2cu_set_non_flushable_pbf
2499 ** Description set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts
2503 *******************************************************************************/
2504 void l2cu_set_non_flushable_pbf (BOOLEAN is_supported)
2507 l2cb.non_flushable_pbf = (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT);
2509 l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT);
2514 /*******************************************************************************
2516 ** Function l2cu_resubmit_pending_sec_req
2518 ** Description This function is called when required security procedures
2519 ** are completed and any pending requests can be re-submitted.
2523 *******************************************************************************/
2524 #if (CLASSIC_BT_INCLUDED == TRUE)
2525 void l2cu_resubmit_pending_sec_req (BD_ADDR p_bda)
2529 tL2C_CCB *p_next_ccb;
2531 L2CAP_TRACE_DEBUG ("l2cu_resubmit_pending_sec_req p_bda: %p", p_bda);
2533 /* If we are called with a BDA, only resubmit for that BDA */
2535 p_lcb = l2cu_find_lcb_by_bd_addr (p_bda, BT_TRANSPORT_BR_EDR);
2536 /* If we don't have one, this is an error */
2538 /* For all channels, send the event through their FSMs */
2539 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2540 p_next_ccb = p_ccb->p_next_ccb;
2541 l2c_csm_execute (p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2544 L2CAP_TRACE_WARNING ("l2cu_resubmit_pending_sec_req - unknown BD_ADDR");
2547 /* No BDA pasesed in, so check all links */
2548 for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2549 if (p_lcb->in_use) {
2550 /* For all channels, send the event through their FSMs */
2551 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2552 p_next_ccb = p_ccb->p_next_ccb;
2553 l2c_csm_execute (p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2559 #endif ///CLASSIC_BT_INCLUDED == TRUE
2561 #if L2CAP_CONFORMANCE_TESTING == TRUE
2562 /*******************************************************************************
2564 ** Function l2cu_set_info_rsp_mask
2566 ** Description This function allows the script wrapper to change the
2567 ** info resp mask for conformance testing.
2569 ** Returns pointer to CCB, or NULL if none
2571 *******************************************************************************/
2572 void l2cu_set_info_rsp_mask (UINT32 mask)
2574 l2cb.test_info_resp = mask;
2576 #endif /* L2CAP_CONFORMANCE_TESTING */
2578 /*******************************************************************************
2580 ** Function l2cu_adjust_out_mps
2582 ** Description Sets our MPS based on current controller capabilities
2586 *******************************************************************************/
2587 void l2cu_adjust_out_mps (tL2C_CCB *p_ccb)
2591 /* on the tx side MTU is selected based on packet size of the controller */
2592 packet_size = btm_get_max_packet_size (p_ccb->p_lcb->remote_bd_addr);
2594 if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) {
2595 /* something is very wrong */
2596 L2CAP_TRACE_DEBUG ("l2cu_adjust_out_mps bad packet size: %u will use MPS: %u", packet_size, p_ccb->peer_cfg.fcr.mps);
2597 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2599 packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN);
2601 /* We try to negotiate MTU that each packet can be split into whole
2602 number of max packets. For example if link is 1.2 max packet size is 339 bytes.
2603 At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4 overhead.
2604 1695, that will be 5 Dh5 packets. Now maximum L2CAP packet is
2605 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.
2607 For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1 3DH5 packet
2608 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. */
2609 if (p_ccb->peer_cfg.fcr.mps >= packet_size) {
2610 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size;
2612 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2615 L2CAP_TRACE_DEBUG ("l2cu_adjust_out_mps use %d Based on peer_cfg.fcr.mps: %u packet_size: %u",
2616 p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size);
2621 /*******************************************************************************
2623 ** Function l2cu_initialize_fixed_ccb
2625 ** Description Initialize a fixed channel's CCB
2627 ** Returns TRUE or FALSE
2629 *******************************************************************************/
2630 BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 fixed_cid, tL2CAP_FCR_OPTS *p_fcr)
2632 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2634 /* If we already have a CCB, then simply return */
2635 if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] != NULL) {
2639 if ((p_ccb = l2cu_allocate_ccb (NULL, 0)) == NULL) {
2643 btu_stop_timer(&p_lcb->timer_entry);
2645 /* Set CID for the connection */
2646 p_ccb->local_cid = fixed_cid;
2647 p_ccb->remote_cid = fixed_cid;
2649 p_ccb->is_flushable = FALSE;
2651 p_ccb->timer_entry.param = (TIMER_PARAM_TYPE)p_ccb;
2655 /* Set the FCR parameters. For now, we will use default pools */
2656 p_ccb->our_cfg.fcr = p_ccb->peer_cfg.fcr = *p_fcr;
2658 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
2659 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
2660 p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
2661 p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
2663 p_ccb->fcrb.max_held_acks = p_fcr->tx_win_sz / 3;
2666 /* Link ccb to lcb and lcb to ccb */
2667 p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb;
2668 p_ccb->p_lcb = p_lcb;
2670 /* There is no configuration, so if the link is up, the channel is up */
2671 if (p_lcb->link_state == LST_CONNECTED) {
2672 p_ccb->chnl_state = CST_OPEN;
2675 /* Set the default idle timeout value to use */
2676 p_ccb->fixed_chnl_idle_tout = l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout;
2681 /*******************************************************************************
2683 ** Function l2cu_no_dynamic_ccbs
2685 ** Description Handles the case when there are no more dynamic CCBs. If there
2686 ** are any fixed CCBs, start the longest of the fixed CCB timeouts,
2687 ** otherwise start the default link idle timeout or disconnect.
2691 *******************************************************************************/
2692 void l2cu_no_dynamic_ccbs (tL2C_LCB *p_lcb)
2694 #if (SMP_INCLUDED == TRUE)
2696 #endif ///SMP_INCLUDED == TRUE
2697 UINT16 timeout = p_lcb->idle_timeout;
2699 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2702 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2703 if ( (p_lcb->p_fixed_ccbs[xx] != NULL) && (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout > timeout) ) {
2704 timeout = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout;
2709 /* If the link is pairing, do not mess with the timeouts */
2710 if (p_lcb->is_bonding) {
2715 L2CAP_TRACE_DEBUG ("l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link");
2716 #if (SMP_INCLUDED == TRUE)
2717 rc = btm_sec_disconnect (p_lcb->handle, HCI_ERR_PEER_USER);
2718 if (rc == BTM_CMD_STARTED) {
2719 l2cu_process_fixed_disc_cback(p_lcb);
2720 p_lcb->link_state = LST_DISCONNECTING;
2721 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2722 } else if (rc == BTM_SUCCESS) {
2723 l2cu_process_fixed_disc_cback(p_lcb);
2724 /* BTM SEC will make sure that link is release (probably after pairing is done) */
2725 p_lcb->link_state = LST_DISCONNECTING;
2727 } else if ( (p_lcb->is_bonding)
2728 && (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) ) {
2729 l2cu_process_fixed_disc_cback(p_lcb);
2730 p_lcb->link_state = LST_DISCONNECTING;
2731 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2733 /* probably no buffer to send disconnect */
2734 timeout = BT_1SEC_TIMEOUT;
2737 if (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) {
2738 l2cu_process_fixed_disc_cback(p_lcb);
2739 p_lcb->link_state = LST_DISCONNECTING;
2740 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2742 timeout = BT_1SEC_TIMEOUT;
2744 #endif ///SMP_INCLUDED == TRUE
2748 if (timeout != 0xFFFF) {
2749 L2CAP_TRACE_DEBUG ("l2cu_no_dynamic_ccbs() starting IDLE timeout: %d", timeout);
2750 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, timeout);
2752 btu_stop_timer(&p_lcb->timer_entry);
2756 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2757 /*******************************************************************************
2759 ** Function l2cu_process_fixed_chnl_resp
2761 ** Description handle a fixed channel response (or lack thereof)
2762 ** if the link failed, or a fixed channel response was
2763 ** not received, the bitfield is all zeros.
2765 *******************************************************************************/
2766 void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb)
2768 L2CAP_TRACE_DEBUG("%s",__func__);
2769 #if (BLE_INCLUDED == TRUE)
2770 if (p_lcb->transport == BT_TRANSPORT_BR_EDR) {
2771 /* ignore all not assigned BR/EDR channels */
2772 p_lcb->peer_chnl_mask[0] &= (L2CAP_FIXED_CHNL_SIG_BIT | \
2773 L2CAP_FIXED_CHNL_CNCTLESS_BIT | \
2774 L2CAP_FIXED_CHNL_SMP_BR_BIT);
2776 p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
2780 /* Tell all registered fixed channels about the connection */
2781 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2782 #if BLE_INCLUDED == TRUE
2783 /* skip sending LE fix channel callbacks on BR/EDR links */
2784 if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
2785 xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID &&
2786 xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID) {
2790 if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
2791 if (p_lcb->peer_chnl_mask[(xx + L2CAP_FIRST_FIXED_CHNL) / 8]
2792 & (1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8))) {
2793 if (p_lcb->p_fixed_ccbs[xx]) {
2794 p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
2796 #if BLE_INCLUDED == TRUE
2797 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2798 p_lcb->remote_bd_addr, TRUE, 0, p_lcb->transport);
2800 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2801 p_lcb->remote_bd_addr, TRUE, 0, BT_TRANSPORT_BR_EDR);
2804 #if BLE_INCLUDED == TRUE
2805 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2806 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2808 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2809 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2812 if (p_lcb->p_fixed_ccbs[xx]) {
2813 l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
2814 p_lcb->p_fixed_ccbs[xx] = NULL;
2823 /*******************************************************************************
2825 ** Function l2cu_process_fixed_disc_cback
2827 ** Description send l2cap fixed channel disconnection callback to application
2832 *******************************************************************************/
2833 void l2cu_process_fixed_disc_cback (tL2C_LCB *p_lcb)
2835 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2837 /* Select peer channels mask to use depending on transport */
2838 UINT8 peer_channel_mask = p_lcb->peer_chnl_mask[0];
2840 // For LE, reset the stored peer channel mask
2841 if (p_lcb->transport == BT_TRANSPORT_LE) {
2842 p_lcb->peer_chnl_mask[0] = 0;
2845 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2846 if (p_lcb->p_fixed_ccbs[xx]) {
2847 if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) {
2848 tL2C_CCB *p_l2c_chnl_ctrl_block;
2849 p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
2850 p_lcb->p_fixed_ccbs[xx] = NULL;
2851 l2cu_release_ccb(p_l2c_chnl_ctrl_block);
2852 #if BLE_INCLUDED == TRUE
2853 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2854 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2856 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2857 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2860 } else if ( (peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
2861 && (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) )
2862 #if BLE_INCLUDED == TRUE
2863 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2864 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2866 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2867 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2873 #if (BLE_INCLUDED == TRUE)
2874 /*******************************************************************************
2876 ** Function l2cu_send_peer_ble_par_req
2878 ** Description Build and send a BLE parameter update request message
2883 *******************************************************************************/
2884 void l2cu_send_peer_ble_par_req (tL2C_LCB *p_lcb, UINT16 min_int, UINT16 max_int,
2885 UINT16 latency, UINT16 timeout)
2890 /* Create an identifier for this packet */
2892 l2cu_adj_id (p_lcb, L2CAP_ADJ_ID);
2894 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN,
2895 L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->id)) == NULL ) {
2896 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_par_req - no buffer");
2900 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2901 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2903 UINT16_TO_STREAM (p, min_int);
2904 UINT16_TO_STREAM (p, max_int);
2905 UINT16_TO_STREAM (p, latency);
2906 UINT16_TO_STREAM (p, timeout);
2908 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2911 /*******************************************************************************
2913 ** Function l2cu_send_peer_ble_par_rsp
2915 ** Description Build and send a BLE parameter update response message
2920 *******************************************************************************/
2921 void l2cu_send_peer_ble_par_rsp (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id)
2926 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN,
2927 L2CAP_CMD_BLE_UPDATE_RSP, rem_id)) == NULL ) {
2928 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_par_rsp - no buffer");
2932 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2933 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2935 UINT16_TO_STREAM (p, reason);
2937 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2940 /*******************************************************************************
2942 ** Function l2cu_send_peer_ble_credit_based_conn_req
2944 ** Description Build and send a BLE packet to establish LE connection oriented
2949 *******************************************************************************/
2950 void l2cu_send_peer_ble_credit_based_conn_req (tL2C_CCB *p_ccb)
2954 tL2C_LCB *p_lcb = NULL;
2957 UINT16 initial_credit;
2961 p_lcb = p_ccb->p_lcb;
2963 /* Create an identifier for this packet */
2965 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
2967 p_ccb->local_id = p_ccb->p_lcb->id;
2969 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
2970 L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id)) == NULL )
2972 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2976 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2977 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2979 mtu = p_ccb->local_conn_cfg.mtu;
2980 mps = p_ccb->local_conn_cfg.mps;
2981 initial_credit = p_ccb->local_conn_cfg.credits;
2983 L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
2984 mtu:%d mps:%d initial_credit:%d", p_ccb->p_rcb->real_psm,\
2985 p_ccb->local_cid, mtu, mps, initial_credit);
2987 UINT16_TO_STREAM (p, p_ccb->p_rcb->real_psm);
2988 UINT16_TO_STREAM (p, p_ccb->local_cid);
2989 UINT16_TO_STREAM (p, mtu);
2990 UINT16_TO_STREAM (p, mps);
2991 UINT16_TO_STREAM (p, initial_credit);
2993 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2996 /*******************************************************************************
2998 ** Function l2cu_reject_ble_connection
3000 ** Description Build and send an L2CAP "Credit based connection res" message
3001 ** to the peer. This function is called for non-success cases.
3005 *******************************************************************************/
3006 void l2cu_reject_ble_connection (tL2C_LCB *p_lcb, UINT8 rem_id, UINT16 result)
3011 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3012 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id)) == NULL )
3014 L2CAP_TRACE_WARNING ("l2cu_reject_ble_connection - no buffer");
3018 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3019 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3021 UINT16_TO_STREAM (p, 0); /* Local CID of 0 */
3022 UINT16_TO_STREAM (p, 0); /* MTU */
3023 UINT16_TO_STREAM (p, 0); /* MPS */
3024 UINT16_TO_STREAM (p, 0); /* initial credit */
3025 UINT16_TO_STREAM (p, result);
3027 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3030 /*******************************************************************************
3032 ** Function l2cu_send_peer_ble_credit_based_conn_res
3034 ** Description Build and send an L2CAP "Credit based connection res" message
3035 ** to the peer. This function is called in case of success.
3039 *******************************************************************************/
3040 void l2cu_send_peer_ble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
3045 L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_res");
3046 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3047 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id)) == NULL )
3049 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
3053 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3054 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3056 UINT16_TO_STREAM (p, p_ccb->local_cid); /* Local CID */
3057 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mtu); /* MTU */
3058 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mps); /* MPS */
3059 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.credits); /* initial credit */
3060 UINT16_TO_STREAM (p, result);
3062 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
3065 /*******************************************************************************
3067 ** Function l2cu_send_peer_ble_flow_control_credit
3069 ** Description Build and send a BLE packet to give credits to peer device
3070 ** for LE connection oriented L2CAP channel.
3074 *******************************************************************************/
3075 void l2cu_send_peer_ble_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
3079 tL2C_LCB *p_lcb = NULL;
3083 p_lcb = p_ccb->p_lcb;
3085 /* Create an identifier for this packet */
3087 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3089 p_ccb->local_id = p_ccb->p_lcb->id;
3091 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
3092 L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id)) == NULL )
3094 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
3098 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3099 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3101 UINT16_TO_STREAM (p, p_ccb->local_cid);
3102 UINT16_TO_STREAM (p, credit_value);
3104 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3107 /*******************************************************************************
3109 ** Function l2cu_send_peer_ble_credit_based_conn_req
3111 ** Description Build and send a BLE packet to disconnect LE connection oriented
3116 *******************************************************************************/
3117 void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb)
3121 tL2C_LCB *p_lcb = NULL;
3122 L2CAP_TRACE_DEBUG ("%s",__func__);
3126 p_lcb = p_ccb->p_lcb;
3128 /* Create an identifier for this packet */
3130 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3132 p_ccb->local_id = p_ccb->p_lcb->id;
3133 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_DISC_REQ_LEN,
3134 L2CAP_CMD_DISC_REQ, p_lcb->id)) == NULL )
3136 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
3140 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3141 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3143 UINT16_TO_STREAM (p, p_ccb->remote_cid);
3144 UINT16_TO_STREAM (p,p_ccb->local_cid);
3146 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3149 #endif /* BLE_INCLUDED == TRUE */
3151 #if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
3152 /*******************************************************************************
3154 ** Function l2cu_find_completed_packets
3156 ** Description Find the completed packets,
3157 ** Then set it to zero
3159 ** Returns The num of handles
3161 *******************************************************************************/
3162 UINT8 l2cu_find_completed_packets(UINT16 *handles, UINT16 *num_packets)
3166 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
3168 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
3169 if ((p_lcb->in_use) && (p_lcb->completed_packets > 0)) {
3170 *(handles++) = p_lcb->handle;
3171 *(num_packets++) = p_lcb->completed_packets;
3173 p_lcb->completed_packets = 0;
3179 #endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
3181 /*******************************************************************************
3182 ** Functions used by both Full and Light Stack
3183 ********************************************************************************/
3185 /*******************************************************************************
3187 ** Function l2cu_find_lcb_by_handle
3189 ** Description Look through all active LCBs for a match based on the
3192 ** Returns pointer to matched LCB, or NULL if no match
3194 *******************************************************************************/
3195 tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle)
3198 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
3200 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
3201 if ((p_lcb->in_use) && (p_lcb->handle == handle)) {
3206 /* If here, no match found */
3210 /*******************************************************************************
3212 ** Function l2cu_find_ccb_by_cid
3214 ** Description Look through all active CCBs on a link for a match based
3215 ** on the local CID. If passed the link pointer is NULL, all
3216 ** active links are searched.
3218 ** Returns pointer to matched CCB, or NULL if no match
3220 *******************************************************************************/
3221 tL2C_CCB *l2cu_find_ccb_by_cid (tL2C_LCB *p_lcb, UINT16 local_cid)
3223 tL2C_CCB *p_ccb = NULL;
3224 #if (L2CAP_UCD_INCLUDED == TRUE)
3228 if (local_cid >= L2CAP_BASE_APPL_CID) {
3229 /* find the associated CCB by "index" */
3230 local_cid -= L2CAP_BASE_APPL_CID;
3232 if (local_cid >= MAX_L2CAP_CHANNELS) {
3236 p_ccb = l2cb.ccb_pool + local_cid;
3238 /* make sure the CCB is in use */
3239 if (!p_ccb->in_use) {
3242 /* make sure it's for the same LCB */
3243 else if (p_lcb && p_lcb != p_ccb->p_lcb) {
3247 #if (L2CAP_UCD_INCLUDED == TRUE)
3249 /* searching fixed channel */
3250 p_ccb = l2cb.ccb_pool;
3251 for ( xx = 0; xx < MAX_L2CAP_CHANNELS; xx++ ) {
3252 if ((p_ccb->local_cid == local_cid)
3254 && (p_lcb == p_ccb->p_lcb)) {
3260 if ( xx >= MAX_L2CAP_CHANNELS ) {
3269 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE && CLASSIC_BT_INCLUDED == TRUE)
3271 /******************************************************************************
3273 ** Function l2cu_get_next_channel_in_rr
3275 ** Description get the next channel to send on a link. It also adjusts the
3276 ** CCB queue to do a basic priority and round-robin scheduling.
3278 ** Returns pointer to CCB or NULL
3280 *******************************************************************************/
3281 static tL2C_CCB *l2cu_get_next_channel_in_rr(tL2C_LCB *p_lcb)
3283 tL2C_CCB *p_serve_ccb = NULL;
3288 /* scan all of priority until finding a channel to serve */
3289 for ( i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++ ) {
3290 /* scan all channel within serving priority group until finding a channel to serve */
3291 for ( j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb); j++) {
3292 /* scaning from next serving channel */
3293 p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb;
3296 L2CAP_TRACE_ERROR("p_serve_ccb is NULL, rr_pri=%d", p_lcb->rr_pri);
3300 L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d",
3301 p_ccb->ccb_priority, p_ccb->local_cid,
3302 fixed_queue_length(p_ccb->xmit_hold_q));
3304 /* store the next serving channel */
3305 /* this channel is the last channel of its priority group */
3306 if (( p_ccb->p_next_ccb == NULL )
3307 || ( p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority )) {
3308 /* next serving channel is set to the first channel in the group */
3309 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_first_ccb;
3311 /* next serving channel is set to the next channel in the group */
3312 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_ccb->p_next_ccb;
3315 if (p_ccb->chnl_state != CST_OPEN) {
3319 /* eL2CAP option in use */
3320 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3321 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3325 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3326 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3331 #if (CLASSIC_BT_INCLUDED == TRUE)
3332 /* If in eRTM mode, check for window closure */
3333 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3336 #endif ///CLASSIC_BT_INCLUDED == TRUE
3339 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3344 /* found a channel to serve */
3345 p_serve_ccb = p_ccb;
3346 /* decrease quota of its priority group */
3347 p_lcb->rr_serv[p_lcb->rr_pri].quota--;
3350 /* if there is no more quota of the priority group or no channel to have data to send */
3351 if ((p_lcb->rr_serv[p_lcb->rr_pri].quota == 0) || (!p_serve_ccb)) {
3352 /* serve next priority group */
3353 p_lcb->rr_pri = (p_lcb->rr_pri + 1) % L2CAP_NUM_CHNL_PRIORITY;
3354 /* initialize its quota */
3355 p_lcb->rr_serv[p_lcb->rr_pri].quota = L2CAP_GET_PRIORITY_QUOTA(p_lcb->rr_pri);
3360 L2CAP_TRACE_DEBUG("RR service pri=%d, quota=%d, lcid=0x%04x",
3361 p_serve_ccb->ccb_priority,
3362 p_lcb->rr_serv[p_serve_ccb->ccb_priority].quota,
3363 p_serve_ccb->local_cid );
3369 #else /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3371 /******************************************************************************
3373 ** Function l2cu_get_next_channel
3375 ** Description get the next channel to send on a link bassed on priority
3378 ** Returns pointer to CCB or NULL
3380 *******************************************************************************/
3381 #if (CLASSIC_BT_INCLUDED == TRUE)
3382 static tL2C_CCB *l2cu_get_next_channel(tL2C_LCB *p_lcb)
3386 /* Get the first CCB with data to send.
3388 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
3389 if (p_ccb->chnl_state != CST_OPEN) {
3393 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3397 if (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q))
3401 if (fixed_queue_is_empty(p_ccb->xmit_hold_q))
3405 /* If in eRTM mode, check for window closure */
3406 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3410 /* If here, we found someone */
3416 #endif ///CLASSIC_BT_INCLUDED == TRUE
3418 #endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3420 /******************************************************************************
3422 ** Function l2cu_get_next_buffer_to_send
3424 ** Description get the next buffer to send on a link. It also adjusts the
3425 ** CCB queue to do a basic priority and round-robin scheduling.
3427 ** Returns pointer to buffer or NULL
3429 *******************************************************************************/
3430 BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
3433 BT_HDR *p_buf = NULL;
3435 /* Highest priority are fixed channels */
3436 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3439 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3440 if ((p_ccb = p_lcb->p_fixed_ccbs[xx]) == NULL) {
3444 /* eL2CAP option in use */
3445 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3446 #if (CLASSIC_BT_INCLUDED == TRUE)
3447 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3451 /* No more checks needed if sending from the reatransmit queue */
3452 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q))
3454 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3457 /* If in eRTM mode, check for window closure */
3458 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3462 if ((p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0)) != NULL) {
3463 l2cu_check_channel_congestion (p_ccb);
3464 l2cu_set_acl_hci_header (p_buf, p_ccb);
3469 #endif ///CLASSIC_BT_INCLUDED == TRUE
3472 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3473 p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3474 if (NULL == p_buf) {
3475 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
3478 /* send tx complete */
3479 if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb) {
3480 (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
3483 l2cu_check_channel_congestion (p_ccb);
3484 l2cu_set_acl_hci_header (p_buf, p_ccb);
3490 #if (CLASSIC_BT_INCLUDED == TRUE)
3491 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
3492 /* get next serving channel in round-robin */
3493 p_ccb = l2cu_get_next_channel_in_rr( p_lcb );
3495 p_ccb = l2cu_get_next_channel( p_lcb );
3498 /* Return if no buffer */
3499 if (p_ccb == NULL) {
3503 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3505 if ((p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0)) == NULL) {
3510 p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3511 if (NULL == p_buf) {
3512 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
3517 if ( p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb && (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE) ) {
3518 (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);
3522 l2cu_check_channel_congestion (p_ccb);
3524 l2cu_set_acl_hci_header (p_buf, p_ccb);
3525 #endif ///CLASSIC_BT_INCLUDED == TRUE
3530 /******************************************************************************
3532 ** Function l2cu_set_acl_hci_header
3534 ** Description Set HCI handle for ACL packet
3538 *******************************************************************************/
3539 void l2cu_set_acl_hci_header (BT_HDR *p_buf, tL2C_CCB *p_ccb)
3543 /* Set the pointer to the beginning of the data minus 4 bytes for the packet header */
3544 p = (UINT8 *)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE;
3546 #if (BLE_INCLUDED == TRUE)
3547 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3548 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT));
3550 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_ble();
3551 /* The HCI transport will segment the buffers. */
3552 if (p_buf->len > acl_data_size) {
3553 UINT16_TO_STREAM (p, acl_data_size);
3555 UINT16_TO_STREAM (p, p_buf->len);
3557 } /* (BLE_INCLUDED == TRUE) */
3561 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
3562 if ( (((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == L2CAP_FLUSHABLE_CH_BASED) && (p_ccb->is_flushable))
3563 || ((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == L2CAP_FLUSHABLE_PKT) ) {
3564 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3566 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | l2cb.non_flushable_pbf);
3569 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3572 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
3573 /* The HCI transport will segment the buffers. */
3574 if (p_buf->len > acl_data_size) {
3575 UINT16_TO_STREAM (p, acl_data_size);
3577 UINT16_TO_STREAM (p, p_buf->len);
3580 p_buf->offset -= HCI_DATA_PREAMBLE_SIZE;
3581 p_buf->len += HCI_DATA_PREAMBLE_SIZE;
3584 /******************************************************************************
3586 ** Function l2cu_check_channel_congestion
3588 ** Description check if any change in congestion status
3592 *******************************************************************************/
3593 void l2cu_check_channel_congestion (tL2C_CCB *p_ccb)
3595 size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
3597 #if (L2CAP_UCD_INCLUDED == TRUE)
3598 if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3599 q_count += fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q);
3602 /* If the CCB queue limit is subject to a quota, check for congestion */
3603 /* if this channel has outgoing traffic */
3604 if (p_ccb->buff_quota != 0) {
3605 /* If this channel was congested */
3606 if ( p_ccb->cong_sent ) {
3607 /* If the channel is not congested now, tell the app */
3608 if (q_count <= (p_ccb->buff_quota / 2)) {
3609 p_ccb->cong_sent = FALSE;
3610 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3611 L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (FALSE), CID: 0x%04x xmit_hold_q.count: %u buff_quota: %u",
3612 p_ccb->local_cid, q_count, p_ccb->buff_quota);
3614 /* Prevent recursive calling */
3615 l2cb.is_cong_cback_context = TRUE;
3616 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, FALSE);
3617 l2cb.is_cong_cback_context = FALSE;
3619 #if (L2CAP_UCD_INCLUDED == TRUE)
3620 else if ( p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3621 if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
3622 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCD CongestionStatus_Cb (FALSE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
3623 fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3624 fixed_queue_length(p_ccb->xmit_hold_q),
3626 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, FALSE );
3630 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3633 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx ++) {
3634 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3635 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) {
3636 (* l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr, FALSE);
3645 /* If this channel was not congested but it is congested now, tell the app */
3646 if (q_count > p_ccb->buff_quota) {
3647 p_ccb->cong_sent = TRUE;
3648 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3649 L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (TRUE),CID:0x%04x,XmitQ:%u,Quota:%u",
3650 p_ccb->local_cid, q_count, p_ccb->buff_quota);
3652 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, TRUE);
3654 #if (L2CAP_UCD_INCLUDED == TRUE)
3655 else if ( p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3656 if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
3657 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCD CongestionStatus_Cb (TRUE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
3658 fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3659 fixed_queue_length(p_ccb->xmit_hold_q),
3661 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, TRUE );
3665 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3668 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx ++) {
3669 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3670 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) {
3671 (* l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr, TRUE);