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 "allocator.h"
29 #include "controller.h"
39 #include "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 memset (p_lcb, 0, sizeof (tL2C_LCB));
59 memcpy (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN);
62 p_lcb->link_state = LST_DISCONNECTED;
63 p_lcb->handle = HCI_INVALID_HANDLE;
64 p_lcb->link_flush_tout = 0xFFFF;
65 p_lcb->timer_entry.param = (TIMER_PARAM_TYPE)p_lcb;
66 p_lcb->info_timer_entry.param = (TIMER_PARAM_TYPE)p_lcb;
67 p_lcb->upda_con_timer.param = (TIMER_PARAM_TYPE)p_lcb;
68 p_lcb->idle_timeout = l2cb.idle_timeout;
69 p_lcb->id = 1; /* spec does not allow '0' */
70 p_lcb->is_bonding = is_bonding;
71 #if (BLE_INCLUDED == TRUE)
72 p_lcb->transport = transport;
73 p_lcb->tx_data_len = controller_get_interface()->get_ble_default_data_packet_length();
74 p_lcb->le_sec_pending_q = fixed_queue_new(SIZE_MAX);
76 if (transport == BT_TRANSPORT_LE) {
77 l2cb.num_ble_links_active++;
78 l2c_ble_link_adjust_allocation();
82 l2cb.num_links_active++;
83 l2c_link_adjust_allocation();
85 p_lcb->link_xmit_data_q = list_new(NULL);
90 /* If here, no free LCB found */
94 /*******************************************************************************
96 ** Function l2cu_update_lcb_4_bonding
98 ** Description Mark the lcb for bonding. Used when bonding takes place on
99 ** an existing ACL connection. (Pre-Lisbon devices)
103 *******************************************************************************/
104 void l2cu_update_lcb_4_bonding (BD_ADDR p_bd_addr, BOOLEAN is_bonding)
106 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr, BT_TRANSPORT_BR_EDR);
109 p_lcb->is_bonding = is_bonding;
113 /*******************************************************************************
115 ** Function l2cu_release_lcb
117 ** Description Release an LCB. All timers will be stopped, channels
118 ** dropped, buffers returned etc.
122 *******************************************************************************/
123 void l2cu_release_lcb (tL2C_LCB *p_lcb)
127 p_lcb->in_use = FALSE;
128 p_lcb->is_bonding = FALSE;
131 btu_stop_timer (&p_lcb->timer_entry);
132 btu_stop_timer (&p_lcb->info_timer_entry);
134 /* Release any unfinished L2CAP packet on this link */
135 if (p_lcb->p_hcit_rcv_acl) {
136 osi_free(p_lcb->p_hcit_rcv_acl);
137 p_lcb->p_hcit_rcv_acl = NULL;
140 #if BTM_SCO_INCLUDED == TRUE
141 #if (BLE_INCLUDED == TRUE)
142 if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
144 /* Release all SCO links */
145 btm_remove_sco_links(p_lcb->remote_bd_addr);
148 if (p_lcb->sent_not_acked > 0) {
149 #if (BLE_INCLUDED == TRUE)
150 if (p_lcb->transport == BT_TRANSPORT_LE) {
151 l2cb.controller_le_xmit_window += p_lcb->sent_not_acked;
152 if (l2cb.controller_le_xmit_window > l2cb.num_lm_ble_bufs) {
153 l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
158 l2cb.controller_xmit_window += p_lcb->sent_not_acked;
159 if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs) {
160 l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
165 #if (BLE_INCLUDED == TRUE)
166 // Reset BLE connecting flag only if the address matches
167 if (!memcmp(l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN)) {
168 l2cb.is_ble_connecting = FALSE;
172 #if (L2CAP_NUM_FIXED_CHNLS > 0)
173 l2cu_process_fixed_disc_cback(p_lcb);
176 /* Ensure no CCBs left on this LCB */
177 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_lcb->ccb_queue.p_first_ccb) {
178 l2cu_release_ccb (p_ccb);
181 /* Tell BTM Acl management the link was removed */
182 if ((p_lcb->link_state == LST_CONNECTED) || (p_lcb->link_state == LST_DISCONNECTING))
183 #if (BLE_INCLUDED == TRUE)
184 btm_acl_removed (p_lcb->remote_bd_addr, p_lcb->transport);
186 btm_acl_removed (p_lcb->remote_bd_addr, BT_TRANSPORT_BR_EDR);
189 /* Release any held buffers */
190 if (p_lcb->link_xmit_data_q) {
191 while (!list_is_empty(p_lcb->link_xmit_data_q)) {
192 BT_HDR *p_buf = list_front(p_lcb->link_xmit_data_q);
193 list_remove(p_lcb->link_xmit_data_q, p_buf);
196 list_free(p_lcb->link_xmit_data_q);
197 p_lcb->link_xmit_data_q = NULL;
200 #if (L2CAP_UCD_INCLUDED == TRUE)
201 /* clean up any security pending UCD */
202 l2c_ucd_delete_sec_pending_q(p_lcb);
205 #if BLE_INCLUDED == TRUE
206 /* Re-adjust flow control windows make sure it does not go negative */
207 if (p_lcb->transport == BT_TRANSPORT_LE) {
208 if (l2cb.num_ble_links_active >= 1) {
209 l2cb.num_ble_links_active--;
212 l2c_ble_link_adjust_allocation();
216 if (l2cb.num_links_active >= 1) {
217 l2cb.num_links_active--;
220 l2c_link_adjust_allocation();
223 /* Check for ping outstanding */
224 if (p_lcb->p_echo_rsp_cb) {
225 tL2CA_ECHO_RSP_CB *p_cb = p_lcb->p_echo_rsp_cb;
227 /* Zero out the callback in case app immediately calls us again */
228 p_lcb->p_echo_rsp_cb = NULL;
230 (*p_cb) (L2CAP_PING_RESULT_NO_LINK);
233 /* Check and release all the LE COC connections waiting for security */
234 if (p_lcb->le_sec_pending_q)
236 while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
238 tL2CAP_SEC_DATA *p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q);
239 if (p_buf->p_callback)
240 p_buf->p_callback(p_lcb->remote_bd_addr, p_lcb->transport, p_buf->p_ref_data, BTM_DEV_RESET);
243 fixed_queue_free(p_lcb->le_sec_pending_q, NULL);
244 p_lcb->le_sec_pending_q = NULL;
249 /*******************************************************************************
251 ** Function l2cu_find_lcb_by_bd_addr
253 ** Description Look through all active LCBs for a match based on the
254 ** remote BD address.
256 ** Returns pointer to matched LCB, or NULL if no match
258 *******************************************************************************/
259 tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr, tBT_TRANSPORT transport)
262 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
264 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
265 if ((p_lcb->in_use) &&
266 #if BLE_INCLUDED == TRUE
267 p_lcb->transport == transport &&
269 (!memcmp (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN))) {
274 /* If here, no match found */
278 /*******************************************************************************
280 ** Function l2cu_get_conn_role
282 ** Description Determine the desired role (master or slave) of a link.
283 ** If already got a slave link, this one must be a master. If
284 ** already got at least 1 link where we are the master, make this
287 ** Returns HCI_ROLE_MASTER or HCI_ROLE_SLAVE
289 *******************************************************************************/
290 UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb)
292 return l2cb.desire_role;
295 /*******************************************************************************
297 ** Function l2c_is_cmd_rejected
299 ** Description Checks if cmd_code is command or response
300 ** If a command it will be rejected per spec.
301 ** This function is used when a illegal packet length is detected
303 ** Returns BOOLEAN - TRUE if cmd_code is a command and it is rejected,
304 ** FALSE if response code. (command not rejected)
306 *******************************************************************************/
307 BOOLEAN l2c_is_cmd_rejected (UINT8 cmd_code, UINT8 id, tL2C_LCB *p_lcb)
310 case L2CAP_CMD_CONN_REQ:
311 case L2CAP_CMD_CONFIG_REQ:
312 case L2CAP_CMD_DISC_REQ:
313 case L2CAP_CMD_ECHO_REQ:
314 case L2CAP_CMD_INFO_REQ:
315 case L2CAP_CMD_AMP_CONN_REQ:
316 case L2CAP_CMD_AMP_MOVE_REQ:
317 case L2CAP_CMD_BLE_UPDATE_REQ:
318 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, id, L2CAP_DEFAULT_MTU, 0);
319 L2CAP_TRACE_WARNING ("Dumping first Command (%d)", cmd_code);
322 default: /* Otherwise a response */
327 /*******************************************************************************
329 ** Function l2cu_build_header
331 ** Description Builds the L2CAP command packet header
333 ** Returns Pointer to allocated packet or NULL if no resources
335 *******************************************************************************/
336 BT_HDR *l2cu_build_header (tL2C_LCB *p_lcb, UINT16 len, UINT8 cmd, UINT8 id)
338 BT_HDR *p_buf = (BT_HDR *)osi_malloc(L2CAP_CMD_BUF_SIZE);
345 p_buf->offset = L2CAP_SEND_CMD_OFFSET;
346 p_buf->len = len + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
347 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
349 /* Put in HCI header - handle + pkt boundary */
350 #if (BLE_INCLUDED == TRUE)
351 if (p_lcb->transport == BT_TRANSPORT_LE) {
352 UINT16_TO_STREAM (p, (p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT)));
356 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
357 UINT16_TO_STREAM (p, p_lcb->handle | l2cb.non_flushable_pbf);
359 UINT16_TO_STREAM (p, (p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
363 UINT16_TO_STREAM (p, len + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD);
364 UINT16_TO_STREAM (p, len + L2CAP_CMD_OVERHEAD);
366 #if (BLE_INCLUDED == TRUE)
367 if (p_lcb->transport == BT_TRANSPORT_LE) {
368 //counter_add("l2cap.ble.tx.bytes", p_buf->len);
369 //counter_add("l2cap.ble.tx.pkts", 1);
371 UINT16_TO_STREAM (p, L2CAP_BLE_SIGNALLING_CID);
375 //counter_add("l2cap.sig.tx.bytes", p_buf->len);
376 //counter_add("l2cap.sig.tx.pkts", 1);
377 UINT16_TO_STREAM (p, L2CAP_SIGNALLING_CID);
380 /* Put in L2CAP command header */
381 UINT8_TO_STREAM (p, cmd);
382 UINT8_TO_STREAM (p, id);
383 UINT16_TO_STREAM (p, len);
388 /*******************************************************************************
390 ** Function l2cu_adj_id
392 ** Description Checks for valid ID based on specified mask
393 ** and adjusts the id if invalid.
397 *******************************************************************************/
398 void l2cu_adj_id (tL2C_LCB *p_lcb, UINT8 adj_mask)
400 if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id) {
405 /*******************************************************************************
407 ** Function l2cu_send_peer_cmd_reject
409 ** Description Build and send an L2CAP "command reject" message
414 *******************************************************************************/
415 void l2cu_send_peer_cmd_reject (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id,
416 UINT16 p1, UINT16 p2)
422 /* Put in L2CAP packet header */
423 if (reason == L2CAP_CMD_REJ_MTU_EXCEEDED) {
425 } else if (reason == L2CAP_CMD_REJ_INVALID_CID) {
431 if ((p_buf = l2cu_build_header (p_lcb, (UINT16) (L2CAP_CMD_REJECT_LEN + param_len), L2CAP_CMD_REJECT, rem_id)) == NULL ) {
432 L2CAP_TRACE_WARNING ("L2CAP - no buffer cmd_rej");
436 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
437 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
439 UINT16_TO_STREAM (p, reason);
441 if (param_len >= 2) {
442 UINT16_TO_STREAM (p, p1);
445 if (param_len >= 4) {
446 UINT16_TO_STREAM (p, p2);
449 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
453 /*******************************************************************************
455 ** Function l2cu_send_peer_connect_req
457 ** Description Build and send an L2CAP "connection request" message
462 *******************************************************************************/
463 void l2cu_send_peer_connect_req (tL2C_CCB *p_ccb)
468 /* Create an identifier for this packet */
470 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
472 p_ccb->local_id = p_ccb->p_lcb->id;
474 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, L2CAP_CONN_REQ_LEN, L2CAP_CMD_CONN_REQ,
475 p_ccb->local_id)) == NULL) {
476 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
480 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
481 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
483 UINT16_TO_STREAM (p, p_ccb->p_rcb->real_psm);
484 UINT16_TO_STREAM (p, p_ccb->local_cid);
486 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
490 /*******************************************************************************
492 ** Function l2cu_send_peer_connect_rsp
494 ** Description Build and send an L2CAP "connection response" message
499 *******************************************************************************/
500 void l2cu_send_peer_connect_rsp (tL2C_CCB *p_ccb, UINT16 result, UINT16 status)
505 if (result == L2CAP_CONN_PENDING) {
506 /* if we already sent pending response */
507 if (p_ccb->flags & CCB_FLAG_SENT_PENDING) {
510 p_ccb->flags |= CCB_FLAG_SENT_PENDING;
514 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, p_ccb->remote_id)) == NULL) {
515 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_rsp");
519 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
520 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
522 UINT16_TO_STREAM (p, p_ccb->local_cid);
523 UINT16_TO_STREAM (p, p_ccb->remote_cid);
524 UINT16_TO_STREAM (p, result);
525 UINT16_TO_STREAM (p, status);
527 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
531 /*******************************************************************************
533 ** Function l2cu_reject_connection
535 ** Description Build and send an L2CAP "connection response neg" message
536 ** to the peer. This function is called when there is no peer
537 ** CCB (non-existant PSM or no resources).
541 *******************************************************************************/
542 void l2cu_reject_connection (tL2C_LCB *p_lcb, UINT16 remote_cid, UINT8 rem_id, UINT16 result)
547 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, rem_id)) == NULL ) {
548 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
552 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
554 UINT16_TO_STREAM (p, 0); /* Local CID of 0 */
555 UINT16_TO_STREAM (p, remote_cid);
556 UINT16_TO_STREAM (p, result);
557 UINT16_TO_STREAM (p, 0); /* Status of 0 */
559 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
562 /*******************************************************************************
564 ** Function l2cu_send_peer_config_req
566 ** Description Build and send an L2CAP "configuration request" message
571 *******************************************************************************/
572 void l2cu_send_peer_config_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
578 /* Create an identifier for this packet */
580 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
582 p_ccb->local_id = p_ccb->p_lcb->id;
584 if (p_cfg->mtu_present) {
585 cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
587 if (p_cfg->flush_to_present) {
588 cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
590 if (p_cfg->qos_present) {
591 cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
593 if (p_cfg->fcr_present) {
594 cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
596 if (p_cfg->fcs_present) {
597 cfg_len += L2CAP_CFG_FCS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
599 if (p_cfg->ext_flow_spec_present) {
600 cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
603 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, (UINT16) (L2CAP_CONFIG_REQ_LEN + cfg_len),
604 L2CAP_CMD_CONFIG_REQ, p_ccb->local_id)) == NULL ) {
605 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
609 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
610 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
612 UINT16_TO_STREAM (p, p_ccb->remote_cid);
613 UINT16_TO_STREAM (p, p_cfg->flags); /* Flags (continuation) */
615 /* Now, put the options */
616 if (p_cfg->mtu_present) {
617 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_MTU);
618 UINT8_TO_STREAM (p, L2CAP_CFG_MTU_OPTION_LEN);
619 UINT16_TO_STREAM (p, p_cfg->mtu);
621 if (p_cfg->flush_to_present) {
622 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FLUSH_TOUT);
623 UINT8_TO_STREAM (p, L2CAP_CFG_FLUSH_OPTION_LEN);
624 UINT16_TO_STREAM (p, p_cfg->flush_to);
626 if (p_cfg->qos_present) {
627 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_QOS);
628 UINT8_TO_STREAM (p, L2CAP_CFG_QOS_OPTION_LEN);
629 UINT8_TO_STREAM (p, p_cfg->qos.qos_flags);
630 UINT8_TO_STREAM (p, p_cfg->qos.service_type);
631 UINT32_TO_STREAM (p, p_cfg->qos.token_rate);
632 UINT32_TO_STREAM (p, p_cfg->qos.token_bucket_size);
633 UINT32_TO_STREAM (p, p_cfg->qos.peak_bandwidth);
634 UINT32_TO_STREAM (p, p_cfg->qos.latency);
635 UINT32_TO_STREAM (p, p_cfg->qos.delay_variation);
637 if (p_cfg->fcr_present) {
638 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCR);
639 UINT8_TO_STREAM (p, L2CAP_CFG_FCR_OPTION_LEN);
640 UINT8_TO_STREAM (p, p_cfg->fcr.mode);
641 UINT8_TO_STREAM (p, p_cfg->fcr.tx_win_sz);
642 UINT8_TO_STREAM (p, p_cfg->fcr.max_transmit);
643 UINT16_TO_STREAM (p, p_cfg->fcr.rtrans_tout);
644 UINT16_TO_STREAM (p, p_cfg->fcr.mon_tout);
645 UINT16_TO_STREAM (p, p_cfg->fcr.mps);
648 if (p_cfg->fcs_present) {
649 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCS);
650 UINT8_TO_STREAM (p, L2CAP_CFG_FCS_OPTION_LEN);
651 UINT8_TO_STREAM (p, p_cfg->fcs);
654 if (p_cfg->ext_flow_spec_present) {
655 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_EXT_FLOW);
656 UINT8_TO_STREAM (p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
657 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.id);
658 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.stype);
659 UINT16_TO_STREAM (p, p_cfg->ext_flow_spec.max_sdu_size);
660 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.sdu_inter_time);
661 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.access_latency);
662 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.flush_timeout);
665 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
668 /*******************************************************************************
670 ** Function l2cu_send_peer_config_rsp
672 ** Description Build and send an L2CAP "configuration response" message
677 *******************************************************************************/
678 void l2cu_send_peer_config_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
684 /* Create an identifier for this packet */
685 if (p_cfg->mtu_present) {
686 cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
688 if (p_cfg->flush_to_present) {
689 cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
691 if (p_cfg->qos_present) {
692 cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
694 if (p_cfg->fcr_present) {
695 cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
697 if (p_cfg->ext_flow_spec_present) {
698 cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
701 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, (UINT16)(L2CAP_CONFIG_RSP_LEN + cfg_len),
702 L2CAP_CMD_CONFIG_RSP, p_ccb->remote_id)) == NULL ) {
703 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
707 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
709 UINT16_TO_STREAM (p, p_ccb->remote_cid);
710 UINT16_TO_STREAM (p, p_cfg->flags); /* Flags (continuation) Must match request */
711 UINT16_TO_STREAM (p, p_cfg->result);
713 /* Now, put the options */
714 if (p_cfg->mtu_present) {
715 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_MTU);
716 UINT8_TO_STREAM (p, L2CAP_CFG_MTU_OPTION_LEN);
717 UINT16_TO_STREAM (p, p_cfg->mtu);
719 if (p_cfg->flush_to_present) {
720 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FLUSH_TOUT);
721 UINT8_TO_STREAM (p, L2CAP_CFG_FLUSH_OPTION_LEN);
722 UINT16_TO_STREAM (p, p_cfg->flush_to);
724 if (p_cfg->qos_present) {
725 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_QOS);
726 UINT8_TO_STREAM (p, L2CAP_CFG_QOS_OPTION_LEN);
727 UINT8_TO_STREAM (p, p_cfg->qos.qos_flags);
728 UINT8_TO_STREAM (p, p_cfg->qos.service_type);
729 UINT32_TO_STREAM (p, p_cfg->qos.token_rate);
730 UINT32_TO_STREAM (p, p_cfg->qos.token_bucket_size);
731 UINT32_TO_STREAM (p, p_cfg->qos.peak_bandwidth);
732 UINT32_TO_STREAM (p, p_cfg->qos.latency);
733 UINT32_TO_STREAM (p, p_cfg->qos.delay_variation);
735 if (p_cfg->fcr_present) {
736 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCR);
737 UINT8_TO_STREAM (p, L2CAP_CFG_FCR_OPTION_LEN);
738 UINT8_TO_STREAM (p, p_cfg->fcr.mode);
739 UINT8_TO_STREAM (p, p_cfg->fcr.tx_win_sz);
740 UINT8_TO_STREAM (p, p_cfg->fcr.max_transmit);
741 UINT16_TO_STREAM (p, p_ccb->our_cfg.fcr.rtrans_tout);
742 UINT16_TO_STREAM (p, p_ccb->our_cfg.fcr.mon_tout);
743 UINT16_TO_STREAM (p, p_cfg->fcr.mps);
746 if (p_cfg->ext_flow_spec_present) {
747 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_EXT_FLOW);
748 UINT8_TO_STREAM (p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
749 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.id);
750 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.stype);
751 UINT16_TO_STREAM (p, p_cfg->ext_flow_spec.max_sdu_size);
752 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.sdu_inter_time);
753 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.access_latency);
754 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.flush_timeout);
757 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
760 /*******************************************************************************
762 ** Function l2cu_send_peer_config_rej
764 ** Description Build and send an L2CAP "configuration reject" message
769 *******************************************************************************/
770 void l2cu_send_peer_config_rej (tL2C_CCB *p_ccb, UINT8 *p_data, UINT16 data_len, UINT16 rej_len)
773 UINT16 len, cfg_len, buf_space, len1;
774 UINT8 *p, *p_hci_len, *p_data_end;
777 L2CAP_TRACE_DEBUG("l2cu_send_peer_config_rej: data_len=%d, rej_len=%d", data_len, rej_len);
780 len = BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN;
782 if (rej_len > len1) {
783 L2CAP_TRACE_ERROR ("L2CAP - cfg_rej pkt size exceeds buffer design max limit.");
787 p_buf = (BT_HDR *)osi_malloc (len + rej_len);
790 L2CAP_TRACE_ERROR ("L2CAP - no buffer for cfg_rej");
794 p_buf->offset = L2CAP_SEND_CMD_OFFSET;
795 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
797 /* Put in HCI header - handle + pkt boundary */
798 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
799 if (HCI_NON_FLUSHABLE_PB_SUPPORTED(BTM_ReadLocalFeatures ())) {
800 UINT16_TO_STREAM (p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT)));
804 UINT16_TO_STREAM (p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
807 /* Remember the HCI header length position, and save space for it */
811 /* Put in L2CAP packet header */
812 UINT16_TO_STREAM (p, L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len);
813 UINT16_TO_STREAM (p, L2CAP_SIGNALLING_CID);
815 /* Put in L2CAP command header */
816 UINT8_TO_STREAM (p, L2CAP_CMD_CONFIG_RSP);
817 UINT8_TO_STREAM (p, p_ccb->remote_id);
819 UINT16_TO_STREAM (p, L2CAP_CONFIG_RSP_LEN + rej_len);
821 UINT16_TO_STREAM (p, p_ccb->remote_cid);
822 UINT16_TO_STREAM (p, 0); /* Flags = 0 (no continuation) */
823 UINT16_TO_STREAM (p, L2CAP_CFG_UNKNOWN_OPTIONS);
827 /* Now, put the rejected options */
828 p_data_end = p_data + data_len;
829 while (p_data < p_data_end) {
831 cfg_len = *(p_data + 1);
833 switch (cfg_code & 0x7F) {
834 /* skip known options */
835 case L2CAP_CFG_TYPE_MTU:
836 case L2CAP_CFG_TYPE_FLUSH_TOUT:
837 case L2CAP_CFG_TYPE_QOS:
838 p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
841 /* unknown options; copy into rsp if not hints */
843 /* sanity check option length */
844 if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= data_len) {
845 if ((cfg_code & 0x80) == 0) {
846 if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD)) {
847 memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
848 p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
849 buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
851 L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer");
852 p_data = p_data_end; /* force loop exit */
856 p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
858 /* bad length; force loop exit */
866 len = (UINT16) (p - p_hci_len - 2);
867 UINT16_TO_STREAM (p_hci_len, len);
869 p_buf->len = len + 4;
871 L2CAP_TRACE_DEBUG ("L2CAP - cfg_rej pkt hci_len=%d, l2cap_len=%d",
872 len, (L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len));
874 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
877 /*******************************************************************************
879 ** Function l2cu_send_peer_disc_req
881 ** Description Build and send an L2CAP "disconnect request" message
886 *******************************************************************************/
887 void l2cu_send_peer_disc_req (tL2C_CCB *p_ccb)
889 BT_HDR *p_buf, *p_buf2;
892 /* Create an identifier for this packet */
894 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
896 p_ccb->local_id = p_ccb->p_lcb->id;
898 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_DISC_REQ_LEN, L2CAP_CMD_DISC_REQ, p_ccb->local_id)) == NULL) {
899 L2CAP_TRACE_WARNING ("L2CAP - no buffer for disc_req");
903 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
905 UINT16_TO_STREAM (p, p_ccb->remote_cid);
906 UINT16_TO_STREAM (p, p_ccb->local_cid);
908 /* Move all queued data packets to the LCB. In FCR mode, assume the higher
909 layer checks that all buffers are sent before disconnecting.
911 if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
912 while ((p_buf2 = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q)) != NULL) {
913 l2cu_set_acl_hci_header (p_buf2, p_ccb);
914 l2c_link_check_send_pkts (p_ccb->p_lcb, p_ccb, p_buf2);
918 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
922 /*******************************************************************************
924 ** Function l2cu_send_peer_disc_rsp
926 ** Description Build and send an L2CAP "disconnect response" message
929 ** This function is passed the parameters for the disconnect
930 ** response instead of the CCB address, as it may be called
931 ** to send a disconnect response when there is no CCB.
935 *******************************************************************************/
936 void l2cu_send_peer_disc_rsp (tL2C_LCB *p_lcb, UINT8 remote_id, UINT16 local_cid,
943 L2CAP_TRACE_WARNING("lcb already released\n");
947 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_RSP_LEN, L2CAP_CMD_DISC_RSP, remote_id)) == NULL) {
948 L2CAP_TRACE_WARNING ("L2CAP - no buffer for disc_rsp");
952 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
954 UINT16_TO_STREAM (p, local_cid);
955 UINT16_TO_STREAM (p, remote_cid);
957 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
961 /*******************************************************************************
963 ** Function l2cu_send_peer_echo_req
965 ** Description Build and send an L2CAP "echo request" message
966 ** to the peer. Note that we do not currently allow
967 ** data in the echo request.
971 *******************************************************************************/
972 void l2cu_send_peer_echo_req (tL2C_LCB *p_lcb, UINT8 *p_data, UINT16 data_len)
978 l2cu_adj_id(p_lcb, L2CAP_ADJ_ZERO_ID); /* check for wrap to '0' */
980 if ((p_buf = l2cu_build_header(p_lcb, (UINT16) (L2CAP_ECHO_REQ_LEN + data_len), L2CAP_CMD_ECHO_REQ, p_lcb->id)) == NULL) {
981 L2CAP_TRACE_WARNING ("L2CAP - no buffer for echo_req");
985 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
988 ARRAY_TO_STREAM (p, p_data, data_len);
991 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
995 /*******************************************************************************
997 ** Function l2cu_send_peer_echo_rsp
999 ** Description Build and send an L2CAP "echo response" message
1004 *******************************************************************************/
1005 void l2cu_send_peer_echo_rsp (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len)
1010 /* Filter out duplicate IDs or if available buffers are low (intruder checking) */
1011 if (!id || id == p_lcb->cur_echo_id) {
1012 /* Dump this request since it is illegal */
1013 L2CAP_TRACE_WARNING ("L2CAP ignoring duplicate echo request (%d)", id);
1016 p_lcb->cur_echo_id = id;
1019 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
1020 uint16_t acl_packet_size = controller_get_interface()->get_acl_packet_size_classic();
1021 /* Don't return data if it does not fit in ACL and L2CAP MTU */
1022 maxlen = (L2CAP_CMD_BUF_SIZE > acl_packet_size) ?
1023 acl_data_size : (UINT16)L2CAP_CMD_BUF_SIZE;
1024 maxlen -= (UINT16)(BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
1025 L2CAP_CMD_OVERHEAD + L2CAP_ECHO_RSP_LEN);
1027 if (data_len > maxlen) {
1031 if ((p_buf = l2cu_build_header (p_lcb, (UINT16)(L2CAP_ECHO_RSP_LEN + data_len), L2CAP_CMD_ECHO_RSP, id)) == NULL) {
1032 L2CAP_TRACE_WARNING ("L2CAP - no buffer for echo_rsp");
1036 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1037 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1040 ARRAY_TO_STREAM (p, p_data, data_len);
1043 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1046 /*******************************************************************************
1048 ** Function l2cu_send_peer_info_req
1050 ** Description Build and send an L2CAP "info request" message
1054 *******************************************************************************/
1055 void l2cu_send_peer_info_req (tL2C_LCB *p_lcb, UINT16 info_type)
1060 /* check for wrap and/or BRCM ID */
1062 l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
1064 if ((p_buf = l2cu_build_header(p_lcb, 2, L2CAP_CMD_INFO_REQ, p_lcb->id)) == NULL) {
1065 L2CAP_TRACE_WARNING ("L2CAP - no buffer for info_req");
1069 L2CAP_TRACE_EVENT ("l2cu_send_peer_info_req: type 0x%04x", info_type);
1071 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1072 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1074 UINT16_TO_STREAM (p, info_type);
1076 p_lcb->w4_info_rsp = TRUE;
1077 btu_start_timer (&p_lcb->info_timer_entry, BTU_TTYPE_L2CAP_INFO, L2CAP_WAIT_INFO_RSP_TOUT);
1079 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1083 /*******************************************************************************
1085 ** Function l2cu_send_peer_info_rsp
1087 ** Description Build and send an L2CAP "info response" message
1092 *******************************************************************************/
1093 void l2cu_send_peer_info_rsp (tL2C_LCB *p_lcb, UINT8 remote_id, UINT16 info_type)
1097 UINT16 len = L2CAP_INFO_RSP_LEN;
1099 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1100 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1101 && (l2cb.test_info_resp & (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1102 L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_EXT_FLOW_SPEC |
1103 L2CAP_EXTFEA_FIXED_CHNLS | L2CAP_EXTFEA_EXT_WINDOW |
1104 L2CAP_EXTFEA_UCD_RECEPTION )) )
1106 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1107 && (L2CAP_EXTFEA_SUPPORTED_MASK & (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1108 L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS |
1109 L2CAP_EXTFEA_UCD_RECEPTION )) )
1112 len += L2CAP_EXTENDED_FEATURES_ARRAY_SIZE;
1113 } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1114 len += L2CAP_FIXED_CHNL_ARRAY_SIZE;
1115 } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1116 len += L2CAP_CONNLESS_MTU_INFO_SIZE;
1119 if ((p_buf = l2cu_build_header(p_lcb, len, L2CAP_CMD_INFO_RSP, remote_id)) == NULL) {
1120 L2CAP_TRACE_WARNING ("L2CAP - no buffer for info_rsp");
1124 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1125 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1127 UINT16_TO_STREAM (p, info_type);
1129 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1130 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1131 && (l2cb.test_info_resp & ( L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE
1132 | L2CAP_EXTFEA_UCD_RECEPTION )) )
1134 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1135 && (L2CAP_EXTFEA_SUPPORTED_MASK & ( L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE
1136 | L2CAP_EXTFEA_UCD_RECEPTION )) )
1139 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1140 #if (BLE_INCLUDED == TRUE)
1141 if (p_lcb->transport == BT_TRANSPORT_LE) {
1142 /* optional data are not added for now */
1143 UINT32_TO_STREAM (p, L2CAP_BLE_EXTFEA_MASK);
1147 #if L2CAP_CONFORMANCE_TESTING == TRUE
1148 UINT32_TO_STREAM (p, l2cb.test_info_resp);
1150 #if (L2CAP_NUM_FIXED_CHNLS > 0)
1151 UINT32_TO_STREAM (p, L2CAP_EXTFEA_SUPPORTED_MASK | L2CAP_EXTFEA_FIXED_CHNLS);
1153 UINT32_TO_STREAM (p, L2CAP_EXTFEA_SUPPORTED_MASK);
1157 } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1158 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1159 memset (p, 0, L2CAP_FIXED_CHNL_ARRAY_SIZE);
1161 p[0] = L2CAP_FIXED_CHNL_SIG_BIT;
1163 if ( L2CAP_EXTFEA_SUPPORTED_MASK & L2CAP_EXTFEA_UCD_RECEPTION ) {
1164 p[0] |= L2CAP_FIXED_CHNL_CNCTLESS_BIT;
1167 #if (L2CAP_NUM_FIXED_CHNLS > 0)
1171 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
1172 if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
1173 p[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] |= 1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8);
1177 } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1178 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1179 UINT16_TO_STREAM (p, L2CAP_UCD_MTU);
1181 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_NOT_SUPPORTED); /* 'not supported' */
1184 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1187 /******************************************************************************
1189 ** Function l2cu_enqueue_ccb
1191 ** Description queue CCB by priority. The first CCB is highest priority and
1192 ** is served at first. The CCB is queued to an LLCB or an LCB.
1196 *******************************************************************************/
1197 void l2cu_enqueue_ccb (tL2C_CCB *p_ccb)
1200 tL2C_CCB_Q *p_q = NULL;
1202 /* Find out which queue the channel is on
1204 if (p_ccb->p_lcb != NULL) {
1205 p_q = &p_ccb->p_lcb->ccb_queue;
1208 if ( (!p_ccb->in_use) || (p_q == NULL) ) {
1209 L2CAP_TRACE_ERROR ("l2cu_enqueue_ccb CID: 0x%04x ERROR in_use: %u p_lcb: %p",
1210 p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb);
1214 L2CAP_TRACE_DEBUG ("l2cu_enqueue_ccb CID: 0x%04x priority: %d",
1215 p_ccb->local_cid, p_ccb->ccb_priority);
1217 /* If the queue is empty, we go at the front */
1218 if (!p_q->p_first_ccb) {
1219 p_q->p_first_ccb = p_q->p_last_ccb = p_ccb;
1220 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1222 p_ccb1 = p_q->p_first_ccb;
1224 while (p_ccb1 != NULL) {
1225 /* Insert new ccb at the end of the same priority. Lower number, higher priority */
1226 if (p_ccb->ccb_priority < p_ccb1->ccb_priority) {
1227 /* Are we at the head of the queue ? */
1228 if (p_ccb1 == p_q->p_first_ccb) {
1229 p_q->p_first_ccb = p_ccb;
1231 p_ccb1->p_prev_ccb->p_next_ccb = p_ccb;
1234 p_ccb->p_next_ccb = p_ccb1;
1235 p_ccb->p_prev_ccb = p_ccb1->p_prev_ccb;
1236 p_ccb1->p_prev_ccb = p_ccb;
1240 p_ccb1 = p_ccb1->p_next_ccb;
1243 /* If we are lower then anyone in the list, we go at the end */
1245 /* add new ccb at the end of the list */
1246 p_q->p_last_ccb->p_next_ccb = p_ccb;
1248 p_ccb->p_next_ccb = NULL;
1249 p_ccb->p_prev_ccb = p_q->p_last_ccb;
1250 p_q->p_last_ccb = p_ccb;
1254 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1255 /* Adding CCB into round robin service table of its LCB */
1256 if (p_ccb->p_lcb != NULL) {
1257 /* if this is the first channel in this priority group */
1258 if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0 ) {
1259 /* Set the first channel to this CCB */
1260 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1261 /* Set the next serving channel in this group to this CCB */
1262 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1263 /* Initialize quota of this priority group based on its priority */
1264 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota = L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1266 /* increase number of channels in this group */
1267 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb++;
1273 /******************************************************************************
1275 ** Function l2cu_dequeue_ccb
1277 ** Description dequeue CCB from a queue
1281 *******************************************************************************/
1282 void l2cu_dequeue_ccb (tL2C_CCB *p_ccb)
1284 tL2C_CCB_Q *p_q = NULL;
1286 L2CAP_TRACE_DEBUG ("l2cu_dequeue_ccb CID: 0x%04x", p_ccb->local_cid);
1288 /* Find out which queue the channel is on
1290 if (p_ccb->p_lcb != NULL) {
1291 p_q = &p_ccb->p_lcb->ccb_queue;
1294 if ( (!p_ccb->in_use) || (p_q == NULL) || (p_q->p_first_ccb == NULL) ) {
1295 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",
1296 p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb, p_q, p_q ? p_q->p_first_ccb : 0);
1300 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1301 /* Removing CCB from round robin service table of its LCB */
1302 if (p_ccb->p_lcb != NULL) {
1303 /* decrease number of channels in this priority group */
1304 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb--;
1306 /* if it was the last channel in the priority group */
1307 if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0 ) {
1308 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1309 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1311 /* if it is the first channel of this group */
1312 if ( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb == p_ccb ) {
1313 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb->p_next_ccb;
1315 /* if it is the next serving channel of this group */
1316 if ( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb == p_ccb ) {
1317 /* simply, start serving from the first channel */
1318 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb
1319 = p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb;
1325 if (p_ccb == p_q->p_first_ccb) {
1326 /* We are removing the first in a queue */
1327 p_q->p_first_ccb = p_ccb->p_next_ccb;
1329 if (p_q->p_first_ccb) {
1330 p_q->p_first_ccb->p_prev_ccb = NULL;
1332 p_q->p_last_ccb = NULL;
1334 } else if (p_ccb == p_q->p_last_ccb) {
1335 /* We are removing the last in a queue */
1336 p_q->p_last_ccb = p_ccb->p_prev_ccb;
1337 p_q->p_last_ccb->p_next_ccb = NULL;
1339 /* In the middle of a chain. */
1340 p_ccb->p_prev_ccb->p_next_ccb = p_ccb->p_next_ccb;
1341 p_ccb->p_next_ccb->p_prev_ccb = p_ccb->p_prev_ccb;
1344 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1347 /******************************************************************************
1349 ** Function l2cu_change_pri_ccb
1355 *******************************************************************************/
1356 void l2cu_change_pri_ccb (tL2C_CCB *p_ccb, tL2CAP_CHNL_PRIORITY priority)
1358 if (p_ccb->ccb_priority != priority) {
1359 /* If CCB is not the only guy on the queue */
1360 if ( (p_ccb->p_next_ccb != NULL) || (p_ccb->p_prev_ccb != NULL) ) {
1361 L2CAP_TRACE_DEBUG ("Update CCB list in logical link");
1363 /* Remove CCB from queue and re-queue it at new priority */
1364 l2cu_dequeue_ccb (p_ccb);
1366 p_ccb->ccb_priority = priority;
1367 l2cu_enqueue_ccb (p_ccb);
1369 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1371 /* If CCB is the only guy on the queue, no need to re-enqueue */
1372 /* update only round robin service data */
1373 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 0;
1374 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1375 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1377 p_ccb->ccb_priority = priority;
1379 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1380 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1381 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota = L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1382 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 1;
1388 /*******************************************************************************
1390 ** Function l2cu_allocate_ccb
1392 ** Description This function allocates a Channel Control Block and
1393 ** attaches it to a link control block. The local CID
1394 ** is also assigned.
1396 ** Returns pointer to CCB, or NULL if none
1398 *******************************************************************************/
1399 tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
1404 L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x", cid);
1406 if (!l2cb.p_free_ccb_first) {
1410 /* If a CID was passed in, use that, else take the first free one */
1412 p_ccb = l2cb.p_free_ccb_first;
1413 l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1417 p_ccb = &l2cb.ccb_pool[cid - L2CAP_BASE_APPL_CID];
1419 if (p_ccb == l2cb.p_free_ccb_first) {
1420 l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1422 for (p_prev = l2cb.p_free_ccb_first; p_prev != NULL; p_prev = p_prev->p_next_ccb) {
1423 if (p_prev->p_next_ccb == p_ccb) {
1424 p_prev->p_next_ccb = p_ccb->p_next_ccb;
1426 if (p_ccb == l2cb.p_free_ccb_last) {
1427 l2cb.p_free_ccb_last = p_prev;
1433 if (p_prev == NULL) {
1434 L2CAP_TRACE_ERROR ("l2cu_allocate_ccb: could not find CCB for CID 0x%04x in the free list", cid);
1440 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1442 p_ccb->in_use = TRUE;
1444 /* Get a CID for the connection */
1445 p_ccb->local_cid = L2CAP_BASE_APPL_CID + (UINT16)(p_ccb - l2cb.ccb_pool);
1447 p_ccb->p_lcb = p_lcb;
1448 p_ccb->p_rcb = NULL;
1449 p_ccb->should_free_rcb = false;
1451 /* Set priority then insert ccb into LCB queue (if we have an LCB) */
1452 p_ccb->ccb_priority = L2CAP_CHNL_PRIORITY_LOW;
1455 l2cu_enqueue_ccb (p_ccb);
1458 /* clear what peer wants to configure */
1459 p_ccb->peer_cfg_bits = 0;
1461 /* Put in default values for configuration */
1462 memset (&p_ccb->our_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1463 memset (&p_ccb->peer_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1465 /* Put in default values for local/peer configurations */
1466 p_ccb->our_cfg.flush_to = p_ccb->peer_cfg.flush_to = L2CAP_DEFAULT_FLUSH_TO;
1467 p_ccb->our_cfg.mtu = p_ccb->peer_cfg.mtu = L2CAP_DEFAULT_MTU;
1468 p_ccb->our_cfg.qos.service_type = p_ccb->peer_cfg.qos.service_type = L2CAP_DEFAULT_SERV_TYPE;
1469 p_ccb->our_cfg.qos.token_rate = p_ccb->peer_cfg.qos.token_rate = L2CAP_DEFAULT_TOKEN_RATE;
1470 p_ccb->our_cfg.qos.token_bucket_size = p_ccb->peer_cfg.qos.token_bucket_size = L2CAP_DEFAULT_BUCKET_SIZE;
1471 p_ccb->our_cfg.qos.peak_bandwidth = p_ccb->peer_cfg.qos.peak_bandwidth = L2CAP_DEFAULT_PEAK_BANDWIDTH;
1472 p_ccb->our_cfg.qos.latency = p_ccb->peer_cfg.qos.latency = L2CAP_DEFAULT_LATENCY;
1473 p_ccb->our_cfg.qos.delay_variation = p_ccb->peer_cfg.qos.delay_variation = L2CAP_DEFAULT_DELAY;
1475 p_ccb->bypass_fcs = 0;
1476 memset (&p_ccb->ertm_info, 0, sizeof(tL2CAP_ERTM_INFO));
1477 p_ccb->peer_cfg_already_rejected = FALSE;
1478 p_ccb->fcr_cfg_tries = L2CAP_MAX_FCR_CFG_TRIES;
1479 p_ccb->fcrb.ack_timer.param = (TIMER_PARAM_TYPE)p_ccb;
1481 /* if timer is running, remove it from timer list */
1482 if (p_ccb->fcrb.ack_timer.in_use) {
1483 btu_stop_quick_timer (&p_ccb->fcrb.ack_timer);
1486 p_ccb->fcrb.mon_retrans_timer.param = (TIMER_PARAM_TYPE)p_ccb;
1489 /* CSP408639 Fix: When L2CAP send amp move channel request or receive
1490 * L2CEVT_AMP_MOVE_REQ do following sequence. Send channel move
1491 * request -> Stop retrans/monitor timer -> Change channel state to CST_AMP_MOVING. */
1492 if (p_ccb->fcrb.mon_retrans_timer.in_use) {
1493 btu_stop_quick_timer (&p_ccb->fcrb.mon_retrans_timer);
1496 #if (CLASSIC_BT_INCLUDED == TRUE)
1497 l2c_fcr_stop_timer (p_ccb);
1498 #endif ///CLASSIC_BT_INCLUDED == TRUE
1499 p_ccb->ertm_info.preferred_mode = L2CAP_FCR_BASIC_MODE; /* Default mode for channel is basic mode */
1500 p_ccb->ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_BASIC; /* Default mode for channel is basic mode */
1501 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
1502 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
1503 p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
1504 p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
1505 p_ccb->max_rx_mtu = L2CAP_MTU_SIZE;
1506 p_ccb->tx_mps = L2CAP_FCR_TX_BUF_SIZE - 32;
1508 p_ccb->xmit_hold_q = fixed_queue_new(SIZE_MAX);
1509 #if (CLASSIC_BT_INCLUDED == TRUE)
1510 p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX);
1511 p_ccb->fcrb.retrans_q = fixed_queue_new(SIZE_MAX);
1512 p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(SIZE_MAX);
1513 #endif ///CLASSIC_BT_INCLUDED == TRUE
1515 p_ccb->cong_sent = FALSE;
1516 p_ccb->buff_quota = 2; /* This gets set after config */
1518 /* If CCB was reserved Config_Done can already have some value */
1520 p_ccb->config_done = 0;
1522 L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x config_done:0x%x", cid, p_ccb->config_done);
1525 p_ccb->chnl_state = CST_CLOSED;
1527 p_ccb->tx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1528 p_ccb->rx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1530 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
1531 p_ccb->is_flushable = FALSE;
1534 p_ccb->timer_entry.param = (TIMER_PARAM_TYPE)p_ccb;
1535 p_ccb->timer_entry.in_use = 0;
1537 l2c_link_adjust_chnl_allocation ();
1542 /*******************************************************************************
1544 ** Function l2cu_start_post_bond_timer
1546 ** Description This function starts the ACL Link inactivity timer after
1547 ** dedicated bonding
1548 ** This timer can be longer than the normal link inactivity
1549 ** timer for some platforms.
1551 ** Returns BOOLEAN - TRUE if idle timer started or disconnect initiated
1552 ** FALSE if there's one or more pending CCB's exist
1554 *******************************************************************************/
1555 BOOLEAN l2cu_start_post_bond_timer (UINT16 handle)
1558 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
1564 p_lcb->is_bonding = FALSE;
1566 /* Only start timer if no control blocks allocated */
1567 if (p_lcb->ccb_queue.p_first_ccb != NULL) {
1571 /* If no channels on the connection, start idle timeout */
1572 if ( (p_lcb->link_state == LST_CONNECTED) || (p_lcb->link_state == LST_CONNECTING) || (p_lcb->link_state == LST_DISCONNECTING) ) {
1573 if (p_lcb->idle_timeout == 0) {
1574 if (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) {
1575 p_lcb->link_state = LST_DISCONNECTING;
1576 timeout = L2CAP_LINK_DISCONNECT_TOUT;
1578 timeout = BT_1SEC_TIMEOUT;
1581 timeout = L2CAP_BONDING_TIMEOUT;
1584 if (timeout != 0xFFFF) {
1585 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, timeout);
1594 /*******************************************************************************
1596 ** Function l2cu_release_ccb
1598 ** Description This function releases a Channel Control Block. The timer
1599 ** is stopped, any attached buffers freed, and the CCB is removed
1600 ** from the link control block.
1604 *******************************************************************************/
1605 void l2cu_release_ccb (tL2C_CCB *p_ccb)
1607 tL2C_LCB *p_lcb = p_ccb->p_lcb;
1608 tL2C_RCB *p_rcb = p_ccb->p_rcb;
1610 L2CAP_TRACE_DEBUG ("l2cu_release_ccb: cid 0x%04x in_use: %u", p_ccb->local_cid, p_ccb->in_use);
1612 /* If already released, could be race condition */
1613 if (!p_ccb->in_use) {
1616 #if (SDP_INCLUDED == TRUE)
1617 if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
1618 btm_sec_clr_service_by_psm(p_rcb->psm);
1620 #endif ///SMP_INCLUDED == TRUE
1621 if (p_ccb->should_free_rcb) {
1623 p_ccb->p_rcb = NULL;
1624 p_ccb->should_free_rcb = false;
1628 btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
1631 /* Stop the timer */
1632 btu_stop_timer (&p_ccb->timer_entry);
1635 fixed_queue_free(p_ccb->xmit_hold_q, osi_free_func);
1636 p_ccb->xmit_hold_q = NULL;
1637 #if (CLASSIC_BT_INCLUDED == TRUE)
1638 fixed_queue_free(p_ccb->fcrb.srej_rcv_hold_q, osi_free_func);
1639 fixed_queue_free(p_ccb->fcrb.retrans_q, osi_free_func);
1640 fixed_queue_free(p_ccb->fcrb.waiting_for_ack_q, osi_free_func);
1641 p_ccb->fcrb.srej_rcv_hold_q = NULL;
1642 p_ccb->fcrb.retrans_q = NULL;
1643 p_ccb->fcrb.waiting_for_ack_q = NULL;
1644 #endif ///CLASSIC_BT_INCLUDED == TRUE
1647 #if (CLASSIC_BT_INCLUDED == TRUE)
1648 l2c_fcr_cleanup (p_ccb);
1649 #endif ///CLASSIC_BT_INCLUDED == TRUE
1650 /* Channel may not be assigned to any LCB if it was just pre-reserved */
1652 ( (p_ccb->local_cid >= L2CAP_BASE_APPL_CID)
1653 #if (L2CAP_UCD_INCLUDED == TRUE)
1654 || (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)
1658 l2cu_dequeue_ccb (p_ccb);
1660 /* Delink the CCB from the LCB */
1661 p_ccb->p_lcb = NULL;
1664 /* Put the CCB back on the free pool */
1665 if (!l2cb.p_free_ccb_first) {
1666 l2cb.p_free_ccb_first = p_ccb;
1667 l2cb.p_free_ccb_last = p_ccb;
1668 p_ccb->p_next_ccb = NULL;
1669 p_ccb->p_prev_ccb = NULL;
1671 p_ccb->p_next_ccb = NULL;
1672 p_ccb->p_prev_ccb = l2cb.p_free_ccb_last;
1673 l2cb.p_free_ccb_last->p_next_ccb = p_ccb;
1674 l2cb.p_free_ccb_last = p_ccb;
1677 /* Flag as not in use */
1678 p_ccb->in_use = FALSE;
1680 /* If no channels on the connection, start idle timeout */
1681 if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED)) {
1682 if (!p_lcb->ccb_queue.p_first_ccb) {
1683 l2cu_no_dynamic_ccbs (p_lcb);
1685 /* Link is still active, adjust channel quotas. */
1686 l2c_link_adjust_chnl_allocation ();
1691 /*******************************************************************************
1693 ** Function l2cu_find_ccb_by_remote_cid
1695 ** Description Look through all active CCBs on a link for a match based
1696 ** on the remote CID.
1698 ** Returns pointer to matched CCB, or NULL if no match
1700 *******************************************************************************/
1701 tL2C_CCB *l2cu_find_ccb_by_remote_cid (tL2C_LCB *p_lcb, UINT16 remote_cid)
1705 /* If LCB is NULL, look through all active links */
1709 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
1710 if ((p_ccb->in_use) && (p_ccb->remote_cid == remote_cid)) {
1715 /* If here, no match found */
1719 /*******************************************************************************
1721 ** Function l2cu_allocate_rcb
1723 ** Description Look through the Registration Control Blocks for a free
1726 ** Returns Pointer to the RCB or NULL if not found
1728 *******************************************************************************/
1729 tL2C_RCB *l2cu_allocate_rcb (UINT16 psm)
1731 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
1734 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1735 if (!p_rcb->in_use) {
1736 p_rcb->in_use = TRUE;
1738 #if (L2CAP_UCD_INCLUDED == TRUE)
1739 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
1745 /* If here, no free RCB found */
1749 /*******************************************************************************
1751 ** Function l2cu_allocate_ble_rcb
1753 ** Description Look through the BLE Registration Control Blocks for a free
1756 ** Returns Pointer to the BLE RCB or NULL if not found
1758 *******************************************************************************/
1759 tL2C_RCB *l2cu_allocate_ble_rcb (UINT16 psm)
1761 tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
1764 for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
1768 p_rcb->in_use = TRUE;
1770 #if (L2CAP_UCD_INCLUDED == TRUE)
1771 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
1777 /* If here, no free RCB found */
1781 /*******************************************************************************
1783 ** Function l2cu_release_rcb
1785 ** Description Mark an RCB as no longet in use
1789 *******************************************************************************/
1790 void l2cu_release_rcb (tL2C_RCB *p_rcb)
1792 p_rcb->in_use = FALSE;
1797 /*******************************************************************************
1799 ** Function l2cu_disconnect_chnl
1801 ** Description Disconnect a channel. Typically, this is due to either
1802 ** receiving a bad configuration, bad packet or max_retries expiring.
1804 *******************************************************************************/
1805 void l2cu_disconnect_chnl (tL2C_CCB *p_ccb)
1807 UINT16 local_cid = p_ccb->local_cid;
1809 if (local_cid >= L2CAP_BASE_APPL_CID) {
1810 tL2CA_DISCONNECT_IND_CB *p_disc_cb = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
1812 L2CAP_TRACE_WARNING ("L2CAP - disconnect_chnl CID: 0x%04x", local_cid);
1814 l2cu_send_peer_disc_req (p_ccb);
1816 l2cu_release_ccb (p_ccb);
1818 (*p_disc_cb)(local_cid, FALSE);
1820 /* failure on the AMP channel, probably need to disconnect ACL */
1821 L2CAP_TRACE_ERROR ("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid);
1826 /*******************************************************************************
1828 ** Function l2cu_find_rcb_by_psm
1830 ** Description Look through the Registration Control Blocks to see if
1831 ** anyone registered to handle the PSM in question
1833 ** Returns Pointer to the RCB or NULL if not found
1835 *******************************************************************************/
1836 tL2C_RCB *l2cu_find_rcb_by_psm (UINT16 psm)
1838 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
1841 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1842 if ((p_rcb->in_use) && (p_rcb->psm == psm)) {
1847 /* If here, no match found */
1851 /*******************************************************************************
1853 ** Function l2cu_find_ble_rcb_by_psm
1855 ** Description Look through the BLE Registration Control Blocks to see if
1856 ** anyone registered to handle the PSM in question
1858 ** Returns Pointer to the BLE RCB or NULL if not found
1860 *******************************************************************************/
1861 tL2C_RCB *l2cu_find_ble_rcb_by_psm (UINT16 psm)
1863 tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
1866 for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
1868 if ((p_rcb->in_use) && (p_rcb->psm == psm))
1872 /* If here, no match found */
1878 /*******************************************************************************
1880 ** Function l2cu_process_peer_cfg_req
1882 ** Description This function is called when the peer sends us a "config request"
1883 ** message. It extracts the configuration of interest and saves
1886 ** Note: Negotiation of the FCR channel type is handled internally,
1887 ** all others are passed to the upper layer.
1889 ** Returns UINT8 - L2CAP_PEER_CFG_OK if passed to upper layer,
1890 ** L2CAP_PEER_CFG_UNACCEPTABLE if automatically responded to
1891 ** because parameters are unnacceptable from a specification
1893 ** L2CAP_PEER_CFG_DISCONNECT if no compatible channel modes
1894 ** between the two devices, and shall be closed.
1896 *******************************************************************************/
1897 UINT8 l2cu_process_peer_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
1899 BOOLEAN mtu_ok = TRUE;
1900 BOOLEAN qos_type_ok = TRUE;
1901 BOOLEAN flush_to_ok = TRUE;
1902 BOOLEAN fcr_ok = TRUE;
1903 #if (CLASSIC_BT_INCLUDED == TRUE)
1905 #endif ///CLASSIC_BT_INCLUDED == TRUE
1906 /* Ignore FCR parameters for basic mode */
1907 if (!p_cfg->fcr_present) {
1908 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
1911 /* Save the MTU that our peer can receive */
1912 if (p_cfg->mtu_present) {
1913 /* Make sure MTU is at least the minimum */
1914 if (p_cfg->mtu >= L2CAP_MIN_MTU) {
1915 /* In basic mode, limit the MTU to our buffer size */
1916 if ( (p_cfg->fcr_present == FALSE) && (p_cfg->mtu > L2CAP_MTU_SIZE) ) {
1917 p_cfg->mtu = L2CAP_MTU_SIZE;
1920 /* Save the accepted value in case of renegotiation */
1921 p_ccb->peer_cfg.mtu = p_cfg->mtu;
1922 p_ccb->peer_cfg.mtu_present = TRUE;
1923 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_MTU;
1924 } else { /* Illegal MTU value */
1925 p_cfg->mtu = L2CAP_MIN_MTU;
1929 /* Reload mtu from a previously accepted config request */
1930 else if (p_ccb->peer_cfg.mtu_present) {
1931 p_cfg->mtu_present = TRUE;
1932 p_cfg->mtu = p_ccb->peer_cfg.mtu;
1935 /* Verify that the flush timeout is a valid value (0 is illegal) */
1936 if (p_cfg->flush_to_present) {
1937 if (!p_cfg->flush_to) {
1938 p_cfg->flush_to = 0xFFFF; /* Infinite retransmissions (spec default) */
1939 flush_to_ok = FALSE;
1940 } else { /* Save the accepted value in case of renegotiation */
1941 p_ccb->peer_cfg.flush_to_present = TRUE;
1942 p_ccb->peer_cfg.flush_to = p_cfg->flush_to;
1943 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FLUSH_TO;
1946 /* Reload flush_to from a previously accepted config request */
1947 else if (p_ccb->peer_cfg.flush_to_present) {
1948 p_cfg->flush_to_present = TRUE;
1949 p_cfg->flush_to = p_ccb->peer_cfg.flush_to;
1952 /* Save the QOS settings the the peer is using */
1953 if (p_cfg->qos_present) {
1954 /* Make sure service type is not a reserved value; otherwise let upper
1955 layer decide if acceptable
1957 if (p_cfg->qos.service_type <= GUARANTEED) {
1958 p_ccb->peer_cfg.qos = p_cfg->qos;
1959 p_ccb->peer_cfg.qos_present = TRUE;
1960 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_QOS;
1961 } else { /* Illegal service type value */
1962 p_cfg->qos.service_type = BEST_EFFORT;
1963 qos_type_ok = FALSE;
1966 /* Reload QOS from a previously accepted config request */
1967 else if (p_ccb->peer_cfg.qos_present) {
1968 p_cfg->qos_present = TRUE;
1969 p_cfg->qos = p_ccb->peer_cfg.qos;
1971 #if (CLASSIC_BT_INCLUDED == TRUE)
1972 if ((fcr_status = l2c_fcr_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_DISCONNECT) {
1973 /* Notify caller to disconnect the channel (incompatible modes) */
1974 p_cfg->result = L2CAP_CFG_FAILED_NO_REASON;
1975 p_cfg->mtu_present = p_cfg->qos_present = p_cfg->flush_to_present = 0;
1977 return (L2CAP_PEER_CFG_DISCONNECT);
1980 fcr_ok = (fcr_status == L2CAP_PEER_CFG_OK);
1981 #endif ///CLASSIC_BT_INCLUDED == TRUE
1983 /* Return any unacceptable parameters */
1984 if (mtu_ok && flush_to_ok && qos_type_ok && fcr_ok) {
1985 l2cu_adjust_out_mps (p_ccb);
1986 return (L2CAP_PEER_CFG_OK);
1988 p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
1991 p_cfg->mtu_present = FALSE;
1994 p_cfg->flush_to_present = FALSE;
1997 p_cfg->qos_present = FALSE;
2000 p_cfg->fcr_present = FALSE;
2003 return (L2CAP_PEER_CFG_UNACCEPTABLE);
2008 /*******************************************************************************
2010 ** Function l2cu_process_peer_cfg_rsp
2012 ** Description This function is called when the peer sends us a "config response"
2013 ** message. It extracts the configuration of interest and saves
2018 *******************************************************************************/
2019 void l2cu_process_peer_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2021 /* If we wanted QoS and the peer sends us a positive response with QoS, use his values */
2022 if ( (p_cfg->qos_present) && (p_ccb->our_cfg.qos_present) ) {
2023 p_ccb->our_cfg.qos = p_cfg->qos;
2026 if (p_cfg->fcr_present) {
2027 /* Save the retransmission and monitor timeout values */
2028 if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE) {
2029 p_ccb->peer_cfg.fcr.rtrans_tout = p_cfg->fcr.rtrans_tout;
2030 p_ccb->peer_cfg.fcr.mon_tout = p_cfg->fcr.mon_tout;
2033 /* Calculate the max number of packets for which we can delay sending an ack */
2034 if (p_cfg->fcr.tx_win_sz < p_ccb->our_cfg.fcr.tx_win_sz) {
2035 p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2037 p_ccb->fcrb.max_held_acks = p_ccb->our_cfg.fcr.tx_win_sz / 3;
2040 L2CAP_TRACE_DEBUG ("l2cu_process_peer_cfg_rsp(): peer tx_win_sz: %d, our tx_win_sz: %d, max_held_acks: %d",
2041 p_cfg->fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz, p_ccb->fcrb.max_held_acks);
2045 /*******************************************************************************
2047 ** Function l2cu_process_our_cfg_req
2049 ** Description This function is called when we send a "config request"
2050 ** message. It extracts the configuration of interest and saves
2055 *******************************************************************************/
2056 void l2cu_process_our_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2059 UINT16 hci_flush_to;
2061 /* Save the QOS settings we are using for transmit */
2062 if (p_cfg->qos_present) {
2063 p_ccb->our_cfg.qos_present = TRUE;
2064 p_ccb->our_cfg.qos = p_cfg->qos;
2067 if (p_cfg->fcr_present) {
2068 /* Override FCR options if attempting streaming or basic */
2069 if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE) {
2070 memset(&p_cfg->fcr, 0, sizeof(tL2CAP_FCR_OPTS));
2072 /* On BR/EDR, timer values are zero in config request */
2073 /* On class 2 AMP, timer value in config request shall be non-0 processing time */
2074 /* timer value in config response shall be greater than received processing time */
2075 p_cfg->fcr.mon_tout = p_cfg->fcr.rtrans_tout = 0;
2077 if (p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE) {
2078 p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0;
2082 /* Set the threshold to send acks (may be updated in the cfg response) */
2083 p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2085 /* Include FCS option only if peer can handle it */
2086 if (p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_NO_CRC) {
2087 /* FCS check can be bypassed if peer also desires to bypass */
2088 if (p_cfg->fcs_present && p_cfg->fcs == L2CAP_CFG_FCS_BYPASS) {
2089 p_ccb->bypass_fcs |= L2CAP_CFG_FCS_OUR;
2092 p_cfg->fcs_present = FALSE;
2095 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
2098 p_ccb->our_cfg.fcr.mode = p_cfg->fcr.mode;
2099 p_ccb->our_cfg.fcr_present = p_cfg->fcr_present;
2101 /* Check the flush timeout. If it is lower than the current one used */
2102 /* then we need to adjust the flush timeout sent to the controller */
2103 if (p_cfg->flush_to_present) {
2104 if ((p_cfg->flush_to == 0) || (p_cfg->flush_to == L2CAP_NO_AUTOMATIC_FLUSH)) {
2105 /* don't send invalid flush timeout */
2106 /* SPEC: The sender of the Request shall specify its flush timeout value */
2107 /* if it differs from the default value of 0xFFFF */
2108 p_cfg->flush_to_present = FALSE;
2110 p_ccb->our_cfg.flush_to = p_cfg->flush_to;
2111 p_lcb = p_ccb->p_lcb;
2113 if (p_cfg->flush_to < p_lcb->link_flush_tout) {
2114 p_lcb->link_flush_tout = p_cfg->flush_to;
2116 /* If the timeout is within range of HCI, set the flush timeout */
2117 if (p_cfg->flush_to <= ((HCI_MAX_AUTO_FLUSH_TOUT * 5) / 8)) {
2118 /* Convert flush timeout to 0.625 ms units, with round */
2119 hci_flush_to = ((p_cfg->flush_to * 8) + 3) / 5;
2120 btsnd_hcic_write_auto_flush_tout (p_lcb->handle, hci_flush_to);
2128 /*******************************************************************************
2130 ** Function l2cu_process_our_cfg_rsp
2132 ** Description This function is called when we send the peer a "config response"
2133 ** message. It extracts the configuration of interest and saves
2138 *******************************************************************************/
2139 #if (CLASSIC_BT_INCLUDED == TRUE)
2140 void l2cu_process_our_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2142 /* If peer wants QoS, we are allowed to change the values in a positive response */
2143 if ( (p_cfg->qos_present) && (p_ccb->peer_cfg.qos_present) ) {
2144 p_ccb->peer_cfg.qos = p_cfg->qos;
2146 p_cfg->qos_present = FALSE;
2149 l2c_fcr_adj_our_rsp_options (p_ccb, p_cfg);
2151 #endif ///CLASSIC_BT_INCLUDED == TRUE
2154 /*******************************************************************************
2156 ** Function l2cu_device_reset
2158 ** Description This function is called when reset of the device is
2159 ** completed. For all active connection simulate HCI_DISC
2163 *******************************************************************************/
2164 void l2cu_device_reset (void)
2167 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
2169 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2170 if ((p_lcb->in_use) && (p_lcb->handle != HCI_INVALID_HANDLE)) {
2171 l2c_link_hci_disc_comp (p_lcb->handle, (UINT8) - 1);
2174 #if (BLE_INCLUDED == TRUE)
2175 l2cb.is_ble_connecting = FALSE;
2179 /*******************************************************************************
2181 ** Function l2cu_create_conn
2183 ** Description This function initiates an acl connection via HCI
2185 ** Returns TRUE if successful, FALSE if gki get buffer fails.
2187 *******************************************************************************/
2188 BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
2191 tL2C_LCB *p_lcb_cur = &l2cb.lcb_pool[0];
2192 #if BTM_SCO_INCLUDED == TRUE
2193 BOOLEAN is_sco_active;
2196 #if (BLE_INCLUDED == TRUE)
2197 tBT_DEVICE_TYPE dev_type;
2198 tBLE_ADDR_TYPE addr_type;
2201 BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
2203 if (transport == BT_TRANSPORT_LE) {
2204 if (!controller_get_interface()->supports_ble()) {
2208 p_lcb->ble_addr_type = addr_type;
2209 p_lcb->transport = BT_TRANSPORT_LE;
2211 return (l2cble_create_conn(p_lcb));
2215 /* If there is a connection where we perform as a slave, try to switch roles
2216 for this connection */
2217 for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb_cur++) {
2218 if (p_lcb_cur == p_lcb) {
2222 if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) {
2224 #if BTM_SCO_INCLUDED == TRUE
2225 /* The LMP_switch_req shall be sent only if the ACL logical transport
2226 is in active mode, when encryption is disabled, and all synchronous
2227 logical transports on the same physical link are disabled." */
2229 /* Check if there is any SCO Active on this BD Address */
2230 is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr);
2232 L2CAP_TRACE_API ("l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s", \
2233 (is_sco_active == TRUE) ? "TRUE" : "FALSE");
2235 if (is_sco_active == TRUE) {
2236 continue; /* No Master Slave switch not allowed when SCO Active */
2239 /*4_1_TODO check if btm_cb.devcb.local_features to be used instead */
2240 if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) {
2241 /* mark this lcb waiting for switch to be completed and
2242 start switch on the other one */
2243 p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
2244 p_lcb->link_role = HCI_ROLE_MASTER;
2246 if (BTM_SwitchRole (p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) == BTM_CMD_STARTED) {
2247 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_LINK_ROLE_SWITCH_TOUT);
2254 p_lcb->link_state = LST_CONNECTING;
2256 return (l2cu_create_conn_after_switch (p_lcb));
2259 /*******************************************************************************
2261 ** Function l2cu_get_num_hi_priority
2263 ** Description Gets the number of high priority channels.
2267 *******************************************************************************/
2268 UINT8 l2cu_get_num_hi_priority (void)
2272 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
2274 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2275 if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2283 /*******************************************************************************
2285 ** Function l2cu_create_conn_after_switch
2287 ** Description This function initiates an acl connection via HCI
2288 ** If switch required to create connection it is already done.
2290 ** Returns TRUE if successful, FALSE if gki get buffer fails.
2292 *******************************************************************************/
2294 BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb)
2296 UINT8 allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2297 tBTM_INQ_INFO *p_inq_info;
2298 UINT8 page_scan_rep_mode;
2299 UINT8 page_scan_mode;
2300 UINT16 clock_offset;
2302 UINT16 num_acl = BTM_GetNumAclLinks();
2303 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_lcb->remote_bd_addr);
2304 UINT8 no_hi_prio_chs = l2cu_get_num_hi_priority();
2306 p_features = BTM_ReadLocalFeatures();
2308 L2CAP_TRACE_DEBUG ("l2cu_create_conn_after_switch :%d num_acl:%d no_hi: %d is_bonding:%d",
2309 l2cb.disallow_switch, num_acl, no_hi_prio_chs, p_lcb->is_bonding);
2310 /* FW team says that we can participant in 4 piconets
2311 * typically 3 piconet + 1 for scanning.
2312 * We can enhance the code to count the number of piconets later. */
2313 if ( ((!l2cb.disallow_switch && (num_acl < 3)) || (p_lcb->is_bonding && (no_hi_prio_chs == 0)))
2314 && HCI_SWITCH_SUPPORTED(p_features)) {
2315 allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2317 allow_switch = HCI_CR_CONN_NOT_ALLOW_SWITCH;
2320 p_lcb->link_state = LST_CONNECTING;
2322 /* Check with the BT manager if details about remote device are known */
2323 if ((p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr)) != NULL) {
2324 page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
2325 page_scan_mode = p_inq_info->results.page_scan_mode;
2326 clock_offset = (UINT16)(p_inq_info->results.clock_offset);
2328 /* No info known. Use default settings */
2329 page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
2330 page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
2332 clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
2335 if (!btsnd_hcic_create_conn (p_lcb->remote_bd_addr,
2336 ( HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1
2337 | HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3
2338 | HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5 ),
2345 L2CAP_TRACE_ERROR ("L2CAP - no buffer for l2cu_create_conn");
2346 l2cu_release_lcb (p_lcb);
2350 btm_acl_update_busy_level (BTM_BLI_PAGE_EVT);
2352 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK,
2353 L2CAP_LINK_CONNECT_TOUT);
2359 /*******************************************************************************
2361 ** Function l2cu_find_lcb_by_state
2363 ** Description Look through all active LCBs for a match based on the
2366 ** Returns pointer to first matched LCB, or NULL if no match
2368 *******************************************************************************/
2369 tL2C_LCB *l2cu_find_lcb_by_state (tL2C_LINK_STATE state)
2372 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
2374 for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2375 if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
2380 /* If here, no match found */
2385 /*******************************************************************************
2387 ** Function l2cu_lcb_disconnecting
2389 ** Description On each active lcb, check if the lcb is in disconnecting
2390 ** state, or if there are no ccb's on the lcb (implying
2391 idle timeout is running), or if last ccb on the link
2392 is in disconnecting state.
2394 ** Returns TRUE if any of above conditions met, FALSE otherwise
2396 *******************************************************************************/
2397 BOOLEAN l2cu_lcb_disconnecting (void)
2402 BOOLEAN status = FALSE;
2404 p_lcb = &l2cb.lcb_pool[0];
2406 for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2407 if (p_lcb->in_use) {
2408 /* no ccbs on lcb, or lcb is in disconnecting state */
2409 if ((!p_lcb->ccb_queue.p_first_ccb) || (p_lcb->link_state == LST_DISCONNECTING)) {
2413 /* only one ccb left on lcb */
2414 else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) {
2415 p_ccb = p_lcb->ccb_queue.p_first_ccb;
2417 if ((p_ccb->in_use) &&
2418 ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
2419 (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
2430 /*******************************************************************************
2432 ** Function l2cu_set_acl_priority
2434 ** Description Sets the transmission priority for a channel.
2435 ** (For initial implementation only two values are valid.
2436 ** L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
2438 ** Returns TRUE if a valid channel, else FALSE
2440 *******************************************************************************/
2442 BOOLEAN l2cu_set_acl_priority (BD_ADDR bd_addr, UINT8 priority, BOOLEAN reset_after_rs)
2446 UINT8 command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2449 //APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority);
2451 /* Find the link control block for the acl channel */
2452 if ((p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR)) == NULL) {
2453 L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_SetAclPriority");
2457 if (BTM_IS_BRCM_CONTROLLER()) {
2458 /* Called from above L2CAP through API; send VSC if changed */
2459 if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||
2460 /* Called because of a master/slave role switch; if high resend VSC */
2461 ( reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2464 vs_param = (priority == L2CAP_PRIORITY_HIGH) ? HCI_BRCM_ACL_PRIORITY_HIGH : HCI_BRCM_ACL_PRIORITY_LOW;
2466 UINT16_TO_STREAM (pp, p_lcb->handle);
2467 UINT8_TO_STREAM (pp, vs_param);
2469 BTM_VendorSpecificCommand (HCI_BRCM_SET_ACL_PRIORITY, HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command, NULL);
2471 /* Adjust lmp buffer allocation for this channel if priority changed */
2472 if (p_lcb->acl_priority != priority) {
2473 p_lcb->acl_priority = priority;
2474 l2c_link_adjust_allocation();
2481 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
2482 /******************************************************************************
2484 ** Function l2cu_set_non_flushable_pbf
2486 ** Description set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts
2490 *******************************************************************************/
2491 void l2cu_set_non_flushable_pbf (BOOLEAN is_supported)
2494 l2cb.non_flushable_pbf = (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT);
2496 l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT);
2501 /*******************************************************************************
2503 ** Function l2cu_resubmit_pending_sec_req
2505 ** Description This function is called when required security procedures
2506 ** are completed and any pending requests can be re-submitted.
2510 *******************************************************************************/
2511 #if (CLASSIC_BT_INCLUDED == TRUE)
2512 void l2cu_resubmit_pending_sec_req (BD_ADDR p_bda)
2516 tL2C_CCB *p_next_ccb;
2518 L2CAP_TRACE_DEBUG ("l2cu_resubmit_pending_sec_req p_bda: %p", p_bda);
2520 /* If we are called with a BDA, only resubmit for that BDA */
2522 p_lcb = l2cu_find_lcb_by_bd_addr (p_bda, BT_TRANSPORT_BR_EDR);
2523 /* If we don't have one, this is an error */
2525 /* For all channels, send the event through their FSMs */
2526 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2527 p_next_ccb = p_ccb->p_next_ccb;
2528 l2c_csm_execute (p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2531 L2CAP_TRACE_WARNING ("l2cu_resubmit_pending_sec_req - unknown BD_ADDR");
2534 /* No BDA pasesed in, so check all links */
2535 for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2536 if (p_lcb->in_use) {
2537 /* For all channels, send the event through their FSMs */
2538 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2539 p_next_ccb = p_ccb->p_next_ccb;
2540 l2c_csm_execute (p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2546 #endif ///CLASSIC_BT_INCLUDED == TRUE
2548 #if L2CAP_CONFORMANCE_TESTING == TRUE
2549 /*******************************************************************************
2551 ** Function l2cu_set_info_rsp_mask
2553 ** Description This function allows the script wrapper to change the
2554 ** info resp mask for conformance testing.
2556 ** Returns pointer to CCB, or NULL if none
2558 *******************************************************************************/
2559 void l2cu_set_info_rsp_mask (UINT32 mask)
2561 l2cb.test_info_resp = mask;
2563 #endif /* L2CAP_CONFORMANCE_TESTING */
2565 /*******************************************************************************
2567 ** Function l2cu_adjust_out_mps
2569 ** Description Sets our MPS based on current controller capabilities
2573 *******************************************************************************/
2574 void l2cu_adjust_out_mps (tL2C_CCB *p_ccb)
2578 /* on the tx side MTU is selected based on packet size of the controller */
2579 packet_size = btm_get_max_packet_size (p_ccb->p_lcb->remote_bd_addr);
2581 if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) {
2582 /* something is very wrong */
2583 L2CAP_TRACE_ERROR ("l2cu_adjust_out_mps bad packet size: %u will use MPS: %u", packet_size, p_ccb->peer_cfg.fcr.mps);
2584 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2586 packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN);
2588 /* We try to negotiate MTU that each packet can be split into whole
2589 number of max packets. For example if link is 1.2 max packet size is 339 bytes.
2590 At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4 overhead.
2591 1695, that will be 5 Dh5 packets. Now maximum L2CAP packet is
2592 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.
2594 For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1 3DH5 packet
2595 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. */
2596 if (p_ccb->peer_cfg.fcr.mps >= packet_size) {
2597 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size;
2599 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2602 L2CAP_TRACE_DEBUG ("l2cu_adjust_out_mps use %d Based on peer_cfg.fcr.mps: %u packet_size: %u",
2603 p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size);
2608 /*******************************************************************************
2610 ** Function l2cu_initialize_fixed_ccb
2612 ** Description Initialize a fixed channel's CCB
2614 ** Returns TRUE or FALSE
2616 *******************************************************************************/
2617 BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 fixed_cid, tL2CAP_FCR_OPTS *p_fcr)
2619 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2621 /* If we already have a CCB, then simply return */
2622 if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] != NULL) {
2626 if ((p_ccb = l2cu_allocate_ccb (NULL, 0)) == NULL) {
2630 btu_stop_timer(&p_lcb->timer_entry);
2632 /* Set CID for the connection */
2633 p_ccb->local_cid = fixed_cid;
2634 p_ccb->remote_cid = fixed_cid;
2636 p_ccb->is_flushable = FALSE;
2638 p_ccb->timer_entry.param = (TIMER_PARAM_TYPE)p_ccb;
2642 /* Set the FCR parameters. For now, we will use default pools */
2643 p_ccb->our_cfg.fcr = p_ccb->peer_cfg.fcr = *p_fcr;
2645 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
2646 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
2647 p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
2648 p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
2650 p_ccb->fcrb.max_held_acks = p_fcr->tx_win_sz / 3;
2653 /* Link ccb to lcb and lcb to ccb */
2654 p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb;
2655 p_ccb->p_lcb = p_lcb;
2657 /* There is no configuration, so if the link is up, the channel is up */
2658 if (p_lcb->link_state == LST_CONNECTED) {
2659 p_ccb->chnl_state = CST_OPEN;
2662 /* Set the default idle timeout value to use */
2663 p_ccb->fixed_chnl_idle_tout = l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout;
2668 /*******************************************************************************
2670 ** Function l2cu_no_dynamic_ccbs
2672 ** Description Handles the case when there are no more dynamic CCBs. If there
2673 ** are any fixed CCBs, start the longest of the fixed CCB timeouts,
2674 ** otherwise start the default link idle timeout or disconnect.
2678 *******************************************************************************/
2679 void l2cu_no_dynamic_ccbs (tL2C_LCB *p_lcb)
2681 #if (SMP_INCLUDED == TRUE)
2683 #endif ///SMP_INCLUDED == TRUE
2684 UINT16 timeout = p_lcb->idle_timeout;
2686 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2689 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2690 if ( (p_lcb->p_fixed_ccbs[xx] != NULL) && (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout > timeout) ) {
2691 timeout = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout;
2696 /* If the link is pairing, do not mess with the timeouts */
2697 if (p_lcb->is_bonding) {
2702 L2CAP_TRACE_DEBUG ("l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link");
2703 #if (SMP_INCLUDED == TRUE)
2704 rc = btm_sec_disconnect (p_lcb->handle, HCI_ERR_PEER_USER);
2705 if (rc == BTM_CMD_STARTED) {
2706 l2cu_process_fixed_disc_cback(p_lcb);
2707 p_lcb->link_state = LST_DISCONNECTING;
2708 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2709 } else if (rc == BTM_SUCCESS) {
2710 l2cu_process_fixed_disc_cback(p_lcb);
2711 /* BTM SEC will make sure that link is release (probably after pairing is done) */
2712 p_lcb->link_state = LST_DISCONNECTING;
2714 } else if ( (p_lcb->is_bonding)
2715 && (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) ) {
2716 l2cu_process_fixed_disc_cback(p_lcb);
2717 p_lcb->link_state = LST_DISCONNECTING;
2718 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2720 /* probably no buffer to send disconnect */
2721 timeout = BT_1SEC_TIMEOUT;
2724 if (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) {
2725 l2cu_process_fixed_disc_cback(p_lcb);
2726 p_lcb->link_state = LST_DISCONNECTING;
2727 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2729 timeout = BT_1SEC_TIMEOUT;
2731 #endif ///SMP_INCLUDED == TRUE
2735 if (timeout != 0xFFFF) {
2736 L2CAP_TRACE_DEBUG ("l2cu_no_dynamic_ccbs() starting IDLE timeout: %d", timeout);
2737 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, timeout);
2739 btu_stop_timer(&p_lcb->timer_entry);
2743 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2744 /*******************************************************************************
2746 ** Function l2cu_process_fixed_chnl_resp
2748 ** Description handle a fixed channel response (or lack thereof)
2749 ** if the link failed, or a fixed channel response was
2750 ** not received, the bitfield is all zeros.
2752 *******************************************************************************/
2753 void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb)
2755 L2CAP_TRACE_DEBUG("%s",__func__);
2756 #if (BLE_INCLUDED == TRUE)
2757 if (p_lcb->transport == BT_TRANSPORT_BR_EDR) {
2758 /* ignore all not assigned BR/EDR channels */
2759 p_lcb->peer_chnl_mask[0] &= (L2CAP_FIXED_CHNL_SIG_BIT | \
2760 L2CAP_FIXED_CHNL_CNCTLESS_BIT | \
2761 L2CAP_FIXED_CHNL_SMP_BR_BIT);
2763 p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
2767 /* Tell all registered fixed channels about the connection */
2768 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2769 #if BLE_INCLUDED == TRUE
2770 /* skip sending LE fix channel callbacks on BR/EDR links */
2771 if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
2772 xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID &&
2773 xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID) {
2777 if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
2778 if (p_lcb->peer_chnl_mask[(xx + L2CAP_FIRST_FIXED_CHNL) / 8]
2779 & (1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8))) {
2780 if (p_lcb->p_fixed_ccbs[xx]) {
2781 p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
2783 #if BLE_INCLUDED == TRUE
2784 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2785 p_lcb->remote_bd_addr, TRUE, 0, p_lcb->transport);
2787 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2788 p_lcb->remote_bd_addr, TRUE, 0, BT_TRANSPORT_BR_EDR);
2791 #if BLE_INCLUDED == TRUE
2792 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2793 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2795 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2796 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2799 if (p_lcb->p_fixed_ccbs[xx]) {
2800 l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
2801 p_lcb->p_fixed_ccbs[xx] = NULL;
2810 /*******************************************************************************
2812 ** Function l2cu_process_fixed_disc_cback
2814 ** Description send l2cap fixed channel disconnection callback to application
2819 *******************************************************************************/
2820 void l2cu_process_fixed_disc_cback (tL2C_LCB *p_lcb)
2822 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2824 /* Select peer channels mask to use depending on transport */
2825 UINT8 peer_channel_mask = p_lcb->peer_chnl_mask[0];
2827 // For LE, reset the stored peer channel mask
2828 if (p_lcb->transport == BT_TRANSPORT_LE) {
2829 p_lcb->peer_chnl_mask[0] = 0;
2832 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2833 if (p_lcb->p_fixed_ccbs[xx]) {
2834 if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) {
2835 tL2C_CCB *p_l2c_chnl_ctrl_block;
2836 p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
2837 p_lcb->p_fixed_ccbs[xx] = NULL;
2838 l2cu_release_ccb(p_l2c_chnl_ctrl_block);
2839 #if BLE_INCLUDED == TRUE
2840 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2841 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2843 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2844 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2847 } else if ( (peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
2848 && (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) )
2849 #if BLE_INCLUDED == TRUE
2850 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2851 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2853 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2854 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2860 #if (BLE_INCLUDED == TRUE)
2861 /*******************************************************************************
2863 ** Function l2cu_send_peer_ble_par_req
2865 ** Description Build and send a BLE parameter update request message
2870 *******************************************************************************/
2871 void l2cu_send_peer_ble_par_req (tL2C_LCB *p_lcb, UINT16 min_int, UINT16 max_int,
2872 UINT16 latency, UINT16 timeout)
2877 /* Create an identifier for this packet */
2879 l2cu_adj_id (p_lcb, L2CAP_ADJ_ID);
2881 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN,
2882 L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->id)) == NULL ) {
2883 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_par_req - no buffer");
2887 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2888 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2890 UINT16_TO_STREAM (p, min_int);
2891 UINT16_TO_STREAM (p, max_int);
2892 UINT16_TO_STREAM (p, latency);
2893 UINT16_TO_STREAM (p, timeout);
2895 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2898 /*******************************************************************************
2900 ** Function l2cu_send_peer_ble_par_rsp
2902 ** Description Build and send a BLE parameter update response message
2907 *******************************************************************************/
2908 void l2cu_send_peer_ble_par_rsp (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id)
2913 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN,
2914 L2CAP_CMD_BLE_UPDATE_RSP, rem_id)) == NULL ) {
2915 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_par_rsp - no buffer");
2919 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2920 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2922 UINT16_TO_STREAM (p, reason);
2924 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2927 /*******************************************************************************
2929 ** Function l2cu_send_peer_ble_credit_based_conn_req
2931 ** Description Build and send a BLE packet to establish LE connection oriented
2936 *******************************************************************************/
2937 void l2cu_send_peer_ble_credit_based_conn_req (tL2C_CCB *p_ccb)
2941 tL2C_LCB *p_lcb = NULL;
2944 UINT16 initial_credit;
2948 p_lcb = p_ccb->p_lcb;
2950 /* Create an identifier for this packet */
2952 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
2954 p_ccb->local_id = p_ccb->p_lcb->id;
2956 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
2957 L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id)) == NULL )
2959 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2963 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2964 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2966 mtu = p_ccb->local_conn_cfg.mtu;
2967 mps = p_ccb->local_conn_cfg.mps;
2968 initial_credit = p_ccb->local_conn_cfg.credits;
2970 L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
2971 mtu:%d mps:%d initial_credit:%d", p_ccb->p_rcb->real_psm,\
2972 p_ccb->local_cid, mtu, mps, initial_credit);
2974 UINT16_TO_STREAM (p, p_ccb->p_rcb->real_psm);
2975 UINT16_TO_STREAM (p, p_ccb->local_cid);
2976 UINT16_TO_STREAM (p, mtu);
2977 UINT16_TO_STREAM (p, mps);
2978 UINT16_TO_STREAM (p, initial_credit);
2980 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2983 /*******************************************************************************
2985 ** Function l2cu_reject_ble_connection
2987 ** Description Build and send an L2CAP "Credit based connection res" message
2988 ** to the peer. This function is called for non-success cases.
2992 *******************************************************************************/
2993 void l2cu_reject_ble_connection (tL2C_LCB *p_lcb, UINT8 rem_id, UINT16 result)
2998 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
2999 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id)) == NULL )
3001 L2CAP_TRACE_WARNING ("l2cu_reject_ble_connection - no buffer");
3005 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3006 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3008 UINT16_TO_STREAM (p, 0); /* Local CID of 0 */
3009 UINT16_TO_STREAM (p, 0); /* MTU */
3010 UINT16_TO_STREAM (p, 0); /* MPS */
3011 UINT16_TO_STREAM (p, 0); /* initial credit */
3012 UINT16_TO_STREAM (p, result);
3014 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3017 /*******************************************************************************
3019 ** Function l2cu_send_peer_ble_credit_based_conn_res
3021 ** Description Build and send an L2CAP "Credit based connection res" message
3022 ** to the peer. This function is called in case of success.
3026 *******************************************************************************/
3027 void l2cu_send_peer_ble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
3032 L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_res");
3033 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3034 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id)) == NULL )
3036 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
3040 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3041 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3043 UINT16_TO_STREAM (p, p_ccb->local_cid); /* Local CID */
3044 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mtu); /* MTU */
3045 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mps); /* MPS */
3046 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.credits); /* initial credit */
3047 UINT16_TO_STREAM (p, result);
3049 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
3052 /*******************************************************************************
3054 ** Function l2cu_send_peer_ble_flow_control_credit
3056 ** Description Build and send a BLE packet to give credits to peer device
3057 ** for LE connection oriented L2CAP channel.
3061 *******************************************************************************/
3062 void l2cu_send_peer_ble_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
3066 tL2C_LCB *p_lcb = NULL;
3070 p_lcb = p_ccb->p_lcb;
3072 /* Create an identifier for this packet */
3074 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3076 p_ccb->local_id = p_ccb->p_lcb->id;
3078 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
3079 L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id)) == NULL )
3081 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
3085 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3086 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3088 UINT16_TO_STREAM (p, p_ccb->local_cid);
3089 UINT16_TO_STREAM (p, credit_value);
3091 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3094 /*******************************************************************************
3096 ** Function l2cu_send_peer_ble_credit_based_conn_req
3098 ** Description Build and send a BLE packet to disconnect LE connection oriented
3103 *******************************************************************************/
3104 void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb)
3108 tL2C_LCB *p_lcb = NULL;
3109 L2CAP_TRACE_DEBUG ("%s",__func__);
3113 p_lcb = p_ccb->p_lcb;
3115 /* Create an identifier for this packet */
3117 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3119 p_ccb->local_id = p_ccb->p_lcb->id;
3120 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_DISC_REQ_LEN,
3121 L2CAP_CMD_DISC_REQ, p_lcb->id)) == NULL )
3123 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
3127 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3128 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3130 UINT16_TO_STREAM (p, p_ccb->remote_cid);
3131 UINT16_TO_STREAM (p,p_ccb->local_cid);
3133 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3136 #endif /* BLE_INCLUDED == TRUE */
3139 /*******************************************************************************
3140 ** Functions used by both Full and Light Stack
3141 ********************************************************************************/
3143 /*******************************************************************************
3145 ** Function l2cu_find_lcb_by_handle
3147 ** Description Look through all active LCBs for a match based on the
3150 ** Returns pointer to matched LCB, or NULL if no match
3152 *******************************************************************************/
3153 tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle)
3156 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
3158 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
3159 if ((p_lcb->in_use) && (p_lcb->handle == handle)) {
3164 /* If here, no match found */
3168 /*******************************************************************************
3170 ** Function l2cu_find_ccb_by_cid
3172 ** Description Look through all active CCBs on a link for a match based
3173 ** on the local CID. If passed the link pointer is NULL, all
3174 ** active links are searched.
3176 ** Returns pointer to matched CCB, or NULL if no match
3178 *******************************************************************************/
3179 tL2C_CCB *l2cu_find_ccb_by_cid (tL2C_LCB *p_lcb, UINT16 local_cid)
3181 tL2C_CCB *p_ccb = NULL;
3182 #if (L2CAP_UCD_INCLUDED == TRUE)
3186 if (local_cid >= L2CAP_BASE_APPL_CID) {
3187 /* find the associated CCB by "index" */
3188 local_cid -= L2CAP_BASE_APPL_CID;
3190 if (local_cid >= MAX_L2CAP_CHANNELS) {
3194 p_ccb = l2cb.ccb_pool + local_cid;
3196 /* make sure the CCB is in use */
3197 if (!p_ccb->in_use) {
3200 /* make sure it's for the same LCB */
3201 else if (p_lcb && p_lcb != p_ccb->p_lcb) {
3205 #if (L2CAP_UCD_INCLUDED == TRUE)
3207 /* searching fixed channel */
3208 p_ccb = l2cb.ccb_pool;
3209 for ( xx = 0; xx < MAX_L2CAP_CHANNELS; xx++ ) {
3210 if ((p_ccb->local_cid == local_cid)
3212 && (p_lcb == p_ccb->p_lcb)) {
3218 if ( xx >= MAX_L2CAP_CHANNELS ) {
3227 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE && CLASSIC_BT_INCLUDED == TRUE)
3229 /******************************************************************************
3231 ** Function l2cu_get_next_channel_in_rr
3233 ** Description get the next channel to send on a link. It also adjusts the
3234 ** CCB queue to do a basic priority and round-robin scheduling.
3236 ** Returns pointer to CCB or NULL
3238 *******************************************************************************/
3239 static tL2C_CCB *l2cu_get_next_channel_in_rr(tL2C_LCB *p_lcb)
3241 tL2C_CCB *p_serve_ccb = NULL;
3246 /* scan all of priority until finding a channel to serve */
3247 for ( i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++ ) {
3248 /* scan all channel within serving priority group until finding a channel to serve */
3249 for ( j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb); j++) {
3250 /* scaning from next serving channel */
3251 p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb;
3254 L2CAP_TRACE_ERROR("p_serve_ccb is NULL, rr_pri=%d", p_lcb->rr_pri);
3258 L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d",
3259 p_ccb->ccb_priority, p_ccb->local_cid,
3260 fixed_queue_length(p_ccb->xmit_hold_q));
3262 /* store the next serving channel */
3263 /* this channel is the last channel of its priority group */
3264 if (( p_ccb->p_next_ccb == NULL )
3265 || ( p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority )) {
3266 /* next serving channel is set to the first channel in the group */
3267 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_first_ccb;
3269 /* next serving channel is set to the next channel in the group */
3270 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_ccb->p_next_ccb;
3273 if (p_ccb->chnl_state != CST_OPEN) {
3277 /* eL2CAP option in use */
3278 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3279 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3283 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3284 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3289 #if (CLASSIC_BT_INCLUDED == TRUE)
3290 /* If in eRTM mode, check for window closure */
3291 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3294 #endif ///CLASSIC_BT_INCLUDED == TRUE
3297 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3302 /* found a channel to serve */
3303 p_serve_ccb = p_ccb;
3304 /* decrease quota of its priority group */
3305 p_lcb->rr_serv[p_lcb->rr_pri].quota--;
3308 /* if there is no more quota of the priority group or no channel to have data to send */
3309 if ((p_lcb->rr_serv[p_lcb->rr_pri].quota == 0) || (!p_serve_ccb)) {
3310 /* serve next priority group */
3311 p_lcb->rr_pri = (p_lcb->rr_pri + 1) % L2CAP_NUM_CHNL_PRIORITY;
3312 /* initialize its quota */
3313 p_lcb->rr_serv[p_lcb->rr_pri].quota = L2CAP_GET_PRIORITY_QUOTA(p_lcb->rr_pri);
3318 L2CAP_TRACE_DEBUG("RR service pri=%d, quota=%d, lcid=0x%04x",
3319 p_serve_ccb->ccb_priority,
3320 p_lcb->rr_serv[p_serve_ccb->ccb_priority].quota,
3321 p_serve_ccb->local_cid );
3327 #else /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3329 /******************************************************************************
3331 ** Function l2cu_get_next_channel
3333 ** Description get the next channel to send on a link bassed on priority
3336 ** Returns pointer to CCB or NULL
3338 *******************************************************************************/
3339 #if (CLASSIC_BT_INCLUDED == TRUE)
3340 static tL2C_CCB *l2cu_get_next_channel(tL2C_LCB *p_lcb)
3344 /* Get the first CCB with data to send.
3346 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
3347 if (p_ccb->chnl_state != CST_OPEN) {
3351 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3355 if (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q))
3359 if (fixed_queue_is_empty(p_ccb->xmit_hold_q))
3363 /* If in eRTM mode, check for window closure */
3364 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3368 /* If here, we found someone */
3374 #endif ///CLASSIC_BT_INCLUDED == TRUE
3376 #endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3378 /******************************************************************************
3380 ** Function l2cu_get_next_buffer_to_send
3382 ** Description get the next buffer to send on a link. It also adjusts the
3383 ** CCB queue to do a basic priority and round-robin scheduling.
3385 ** Returns pointer to buffer or NULL
3387 *******************************************************************************/
3388 BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
3391 BT_HDR *p_buf = NULL;
3393 /* Highest priority are fixed channels */
3394 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3397 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3398 if ((p_ccb = p_lcb->p_fixed_ccbs[xx]) == NULL) {
3402 /* eL2CAP option in use */
3403 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3404 #if (CLASSIC_BT_INCLUDED == TRUE)
3405 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3409 /* No more checks needed if sending from the reatransmit queue */
3410 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q))
3412 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3415 /* If in eRTM mode, check for window closure */
3416 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3420 if ((p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0)) != NULL) {
3421 l2cu_check_channel_congestion (p_ccb);
3422 l2cu_set_acl_hci_header (p_buf, p_ccb);
3427 #endif ///CLASSIC_BT_INCLUDED == TRUE
3430 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3431 p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3432 if (NULL == p_buf) {
3433 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
3436 /* send tx complete */
3437 if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb) {
3438 (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
3441 l2cu_check_channel_congestion (p_ccb);
3442 l2cu_set_acl_hci_header (p_buf, p_ccb);
3448 #if (CLASSIC_BT_INCLUDED == TRUE)
3449 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
3450 /* get next serving channel in round-robin */
3451 p_ccb = l2cu_get_next_channel_in_rr( p_lcb );
3453 p_ccb = l2cu_get_next_channel( p_lcb );
3456 /* Return if no buffer */
3457 if (p_ccb == NULL) {
3461 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3463 if ((p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0)) == NULL) {
3468 p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3469 if (NULL == p_buf) {
3470 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
3475 if ( p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb && (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE) ) {
3476 (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);
3480 l2cu_check_channel_congestion (p_ccb);
3482 l2cu_set_acl_hci_header (p_buf, p_ccb);
3483 #endif ///CLASSIC_BT_INCLUDED == TRUE
3488 /******************************************************************************
3490 ** Function l2cu_set_acl_hci_header
3492 ** Description Set HCI handle for ACL packet
3496 *******************************************************************************/
3497 void l2cu_set_acl_hci_header (BT_HDR *p_buf, tL2C_CCB *p_ccb)
3501 /* Set the pointer to the beginning of the data minus 4 bytes for the packet header */
3502 p = (UINT8 *)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE;
3504 #if (BLE_INCLUDED == TRUE)
3505 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3506 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT));
3508 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_ble();
3509 /* The HCI transport will segment the buffers. */
3510 if (p_buf->len > acl_data_size) {
3511 UINT16_TO_STREAM (p, acl_data_size);
3513 UINT16_TO_STREAM (p, p_buf->len);
3515 } /* (BLE_INCLUDED == TRUE) */
3519 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
3520 if ( (((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == L2CAP_FLUSHABLE_CH_BASED) && (p_ccb->is_flushable))
3521 || ((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == L2CAP_FLUSHABLE_PKT) ) {
3522 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3524 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | l2cb.non_flushable_pbf);
3527 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3530 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
3531 /* The HCI transport will segment the buffers. */
3532 if (p_buf->len > acl_data_size) {
3533 UINT16_TO_STREAM (p, acl_data_size);
3535 UINT16_TO_STREAM (p, p_buf->len);
3538 p_buf->offset -= HCI_DATA_PREAMBLE_SIZE;
3539 p_buf->len += HCI_DATA_PREAMBLE_SIZE;
3542 /******************************************************************************
3544 ** Function l2cu_check_channel_congestion
3546 ** Description check if any change in congestion status
3550 *******************************************************************************/
3551 void l2cu_check_channel_congestion (tL2C_CCB *p_ccb)
3553 size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
3555 #if (L2CAP_UCD_INCLUDED == TRUE)
3556 if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3557 q_count += fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q);
3560 /* If the CCB queue limit is subject to a quota, check for congestion */
3561 /* if this channel has outgoing traffic */
3562 if (p_ccb->buff_quota != 0) {
3563 /* If this channel was congested */
3564 if ( p_ccb->cong_sent ) {
3565 /* If the channel is not congested now, tell the app */
3566 if (q_count <= (p_ccb->buff_quota / 2)) {
3567 p_ccb->cong_sent = FALSE;
3568 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3569 L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (FALSE), CID: 0x%04x xmit_hold_q.count: %u buff_quota: %u",
3570 p_ccb->local_cid, q_count, p_ccb->buff_quota);
3572 /* Prevent recursive calling */
3573 l2cb.is_cong_cback_context = TRUE;
3574 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, FALSE);
3575 l2cb.is_cong_cback_context = FALSE;
3577 #if (L2CAP_UCD_INCLUDED == TRUE)
3578 else if ( p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3579 if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
3580 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCD CongestionStatus_Cb (FALSE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
3581 fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3582 fixed_queue_length(p_ccb->xmit_hold_q),
3584 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, FALSE );
3588 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3591 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx ++) {
3592 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3593 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) {
3594 (* l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr, FALSE);
3603 /* If this channel was not congested but it is congested now, tell the app */
3604 if (q_count > p_ccb->buff_quota) {
3605 p_ccb->cong_sent = TRUE;
3606 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3607 L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (TRUE),CID:0x%04x,XmitQ:%u,Quota:%u",
3608 p_ccb->local_cid, q_count, p_ccb->buff_quota);
3610 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, TRUE);
3612 #if (L2CAP_UCD_INCLUDED == TRUE)
3613 else if ( p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3614 if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
3615 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCD CongestionStatus_Cb (TRUE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
3616 fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3617 fixed_queue_length(p_ccb->xmit_hold_q),
3619 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, TRUE );
3623 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3626 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx ++) {
3627 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3628 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) {
3629 (* l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr, TRUE);