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 btu_free_timer(&p_lcb->timer_entry);
58 btu_free_timer(&p_lcb->info_timer_entry);
59 btu_free_timer(&p_lcb->upda_con_timer);
61 memset (p_lcb, 0, sizeof (tL2C_LCB));
62 memcpy (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN);
65 p_lcb->link_state = LST_DISCONNECTED;
66 p_lcb->handle = HCI_INVALID_HANDLE;
67 p_lcb->link_flush_tout = 0xFFFF;
68 p_lcb->timer_entry.param = (TIMER_PARAM_TYPE)p_lcb;
69 p_lcb->info_timer_entry.param = (TIMER_PARAM_TYPE)p_lcb;
70 p_lcb->upda_con_timer.param = (TIMER_PARAM_TYPE)p_lcb;
71 p_lcb->idle_timeout = l2cb.idle_timeout;
72 p_lcb->id = 1; /* spec does not allow '0' */
73 p_lcb->is_bonding = is_bonding;
74 #if (BLE_INCLUDED == TRUE)
75 p_lcb->transport = transport;
76 p_lcb->tx_data_len = controller_get_interface()->get_ble_default_data_packet_length();
77 p_lcb->le_sec_pending_q = fixed_queue_new(SIZE_MAX);
79 if (transport == BT_TRANSPORT_LE) {
80 l2cb.num_ble_links_active++;
81 l2c_ble_link_adjust_allocation();
85 l2cb.num_links_active++;
86 l2c_link_adjust_allocation();
88 p_lcb->link_xmit_data_q = list_new(NULL);
93 /* If here, no free LCB found */
97 /*******************************************************************************
99 ** Function l2cu_update_lcb_4_bonding
101 ** Description Mark the lcb for bonding. Used when bonding takes place on
102 ** an existing ACL connection. (Pre-Lisbon devices)
106 *******************************************************************************/
107 void l2cu_update_lcb_4_bonding (BD_ADDR p_bd_addr, BOOLEAN is_bonding)
109 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr, BT_TRANSPORT_BR_EDR);
112 p_lcb->is_bonding = is_bonding;
116 /*******************************************************************************
118 ** Function l2cu_release_lcb
120 ** Description Release an LCB. All timers will be stopped, channels
121 ** dropped, buffers returned etc.
125 *******************************************************************************/
126 void l2cu_release_lcb (tL2C_LCB *p_lcb)
130 p_lcb->in_use = FALSE;
131 p_lcb->is_bonding = FALSE;
133 /* Stop and release timers */
134 btu_free_timer (&p_lcb->timer_entry);
135 memset(&p_lcb->timer_entry, 0, sizeof(TIMER_LIST_ENT));
136 btu_free_timer (&p_lcb->info_timer_entry);
137 memset(&p_lcb->info_timer_entry, 0, sizeof(TIMER_LIST_ENT));
138 btu_free_timer(&p_lcb->upda_con_timer);
139 memset(&p_lcb->upda_con_timer, 0, sizeof(TIMER_LIST_ENT));
141 /* Release any unfinished L2CAP packet on this link */
142 if (p_lcb->p_hcit_rcv_acl) {
143 osi_free(p_lcb->p_hcit_rcv_acl);
144 p_lcb->p_hcit_rcv_acl = NULL;
147 #if BTM_SCO_INCLUDED == TRUE
148 #if (BLE_INCLUDED == TRUE)
149 if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
151 /* Release all SCO links */
152 btm_remove_sco_links(p_lcb->remote_bd_addr);
155 if (p_lcb->sent_not_acked > 0) {
156 #if (BLE_INCLUDED == TRUE)
157 if (p_lcb->transport == BT_TRANSPORT_LE) {
158 l2cb.controller_le_xmit_window += p_lcb->sent_not_acked;
159 if (l2cb.controller_le_xmit_window > l2cb.num_lm_ble_bufs) {
160 l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
165 l2cb.controller_xmit_window += p_lcb->sent_not_acked;
166 if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs) {
167 l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
172 #if (BLE_INCLUDED == TRUE)
173 // Reset BLE connecting flag only if the address matches
174 if (!memcmp(l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN)) {
175 l2cb.is_ble_connecting = FALSE;
179 #if (L2CAP_NUM_FIXED_CHNLS > 0)
180 l2cu_process_fixed_disc_cback(p_lcb);
183 /* Ensure no CCBs left on this LCB */
184 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_lcb->ccb_queue.p_first_ccb) {
185 l2cu_release_ccb (p_ccb);
188 /* Tell BTM Acl management the link was removed */
189 if ((p_lcb->link_state == LST_CONNECTED) || (p_lcb->link_state == LST_DISCONNECTING))
190 #if (BLE_INCLUDED == TRUE)
191 btm_acl_removed (p_lcb->remote_bd_addr, p_lcb->transport);
193 btm_acl_removed (p_lcb->remote_bd_addr, BT_TRANSPORT_BR_EDR);
196 /* Release any held buffers */
197 if (p_lcb->link_xmit_data_q) {
198 while (!list_is_empty(p_lcb->link_xmit_data_q)) {
199 BT_HDR *p_buf = list_front(p_lcb->link_xmit_data_q);
200 list_remove(p_lcb->link_xmit_data_q, p_buf);
203 list_free(p_lcb->link_xmit_data_q);
204 p_lcb->link_xmit_data_q = NULL;
207 #if (L2CAP_UCD_INCLUDED == TRUE)
208 /* clean up any security pending UCD */
209 l2c_ucd_delete_sec_pending_q(p_lcb);
212 #if BLE_INCLUDED == TRUE
213 /* Re-adjust flow control windows make sure it does not go negative */
214 if (p_lcb->transport == BT_TRANSPORT_LE) {
215 if (l2cb.num_ble_links_active >= 1) {
216 l2cb.num_ble_links_active--;
219 l2c_ble_link_adjust_allocation();
223 if (l2cb.num_links_active >= 1) {
224 l2cb.num_links_active--;
227 l2c_link_adjust_allocation();
230 /* Check for ping outstanding */
231 if (p_lcb->p_echo_rsp_cb) {
232 tL2CA_ECHO_RSP_CB *p_cb = p_lcb->p_echo_rsp_cb;
234 /* Zero out the callback in case app immediately calls us again */
235 p_lcb->p_echo_rsp_cb = NULL;
237 (*p_cb) (L2CAP_PING_RESULT_NO_LINK);
240 /* Check and release all the LE COC connections waiting for security */
241 if (p_lcb->le_sec_pending_q)
243 while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
245 tL2CAP_SEC_DATA *p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q);
246 if (p_buf->p_callback)
247 p_buf->p_callback(p_lcb->remote_bd_addr, p_lcb->transport, p_buf->p_ref_data, BTM_DEV_RESET);
250 fixed_queue_free(p_lcb->le_sec_pending_q, NULL);
251 p_lcb->le_sec_pending_q = NULL;
256 /*******************************************************************************
258 ** Function l2cu_find_lcb_by_bd_addr
260 ** Description Look through all active LCBs for a match based on the
261 ** remote BD address.
263 ** Returns pointer to matched LCB, or NULL if no match
265 *******************************************************************************/
266 tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr, tBT_TRANSPORT transport)
269 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
271 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
272 if ((p_lcb->in_use) &&
273 #if BLE_INCLUDED == TRUE
274 p_lcb->transport == transport &&
276 (!memcmp (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN))) {
281 /* If here, no match found */
285 /*******************************************************************************
287 ** Function l2cu_get_conn_role
289 ** Description Determine the desired role (master or slave) of a link.
290 ** If already got a slave link, this one must be a master. If
291 ** already got at least 1 link where we are the master, make this
294 ** Returns HCI_ROLE_MASTER or HCI_ROLE_SLAVE
296 *******************************************************************************/
297 UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb)
299 return l2cb.desire_role;
302 /*******************************************************************************
304 ** Function l2c_is_cmd_rejected
306 ** Description Checks if cmd_code is command or response
307 ** If a command it will be rejected per spec.
308 ** This function is used when a illegal packet length is detected
310 ** Returns BOOLEAN - TRUE if cmd_code is a command and it is rejected,
311 ** FALSE if response code. (command not rejected)
313 *******************************************************************************/
314 BOOLEAN l2c_is_cmd_rejected (UINT8 cmd_code, UINT8 id, tL2C_LCB *p_lcb)
317 case L2CAP_CMD_CONN_REQ:
318 case L2CAP_CMD_CONFIG_REQ:
319 case L2CAP_CMD_DISC_REQ:
320 case L2CAP_CMD_ECHO_REQ:
321 case L2CAP_CMD_INFO_REQ:
322 case L2CAP_CMD_AMP_CONN_REQ:
323 case L2CAP_CMD_AMP_MOVE_REQ:
324 case L2CAP_CMD_BLE_UPDATE_REQ:
325 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, id, L2CAP_DEFAULT_MTU, 0);
326 L2CAP_TRACE_WARNING ("Dumping first Command (%d)", cmd_code);
329 default: /* Otherwise a response */
334 /*******************************************************************************
336 ** Function l2cu_build_header
338 ** Description Builds the L2CAP command packet header
340 ** Returns Pointer to allocated packet or NULL if no resources
342 *******************************************************************************/
343 BT_HDR *l2cu_build_header (tL2C_LCB *p_lcb, UINT16 len, UINT8 cmd, UINT8 id)
345 BT_HDR *p_buf = (BT_HDR *)osi_malloc(L2CAP_CMD_BUF_SIZE);
352 p_buf->offset = L2CAP_SEND_CMD_OFFSET;
353 p_buf->len = len + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
354 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
356 /* Put in HCI header - handle + pkt boundary */
357 #if (BLE_INCLUDED == TRUE)
358 if (p_lcb->transport == BT_TRANSPORT_LE) {
359 UINT16_TO_STREAM (p, (p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT)));
363 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
364 UINT16_TO_STREAM (p, p_lcb->handle | l2cb.non_flushable_pbf);
366 UINT16_TO_STREAM (p, (p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
370 UINT16_TO_STREAM (p, len + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD);
371 UINT16_TO_STREAM (p, len + L2CAP_CMD_OVERHEAD);
373 #if (BLE_INCLUDED == TRUE)
374 if (p_lcb->transport == BT_TRANSPORT_LE) {
375 //counter_add("l2cap.ble.tx.bytes", p_buf->len);
376 //counter_add("l2cap.ble.tx.pkts", 1);
378 UINT16_TO_STREAM (p, L2CAP_BLE_SIGNALLING_CID);
382 //counter_add("l2cap.sig.tx.bytes", p_buf->len);
383 //counter_add("l2cap.sig.tx.pkts", 1);
384 UINT16_TO_STREAM (p, L2CAP_SIGNALLING_CID);
387 /* Put in L2CAP command header */
388 UINT8_TO_STREAM (p, cmd);
389 UINT8_TO_STREAM (p, id);
390 UINT16_TO_STREAM (p, len);
395 /*******************************************************************************
397 ** Function l2cu_adj_id
399 ** Description Checks for valid ID based on specified mask
400 ** and adjusts the id if invalid.
404 *******************************************************************************/
405 void l2cu_adj_id (tL2C_LCB *p_lcb, UINT8 adj_mask)
407 if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id) {
412 /*******************************************************************************
414 ** Function l2cu_send_peer_cmd_reject
416 ** Description Build and send an L2CAP "command reject" message
421 *******************************************************************************/
422 void l2cu_send_peer_cmd_reject (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id,
423 UINT16 p1, UINT16 p2)
429 /* Put in L2CAP packet header */
430 if (reason == L2CAP_CMD_REJ_MTU_EXCEEDED) {
432 } else if (reason == L2CAP_CMD_REJ_INVALID_CID) {
438 if ((p_buf = l2cu_build_header (p_lcb, (UINT16) (L2CAP_CMD_REJECT_LEN + param_len), L2CAP_CMD_REJECT, rem_id)) == NULL ) {
439 L2CAP_TRACE_WARNING ("L2CAP - no buffer cmd_rej");
443 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
444 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
446 UINT16_TO_STREAM (p, reason);
448 if (param_len >= 2) {
449 UINT16_TO_STREAM (p, p1);
452 if (param_len >= 4) {
453 UINT16_TO_STREAM (p, p2);
456 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
460 /*******************************************************************************
462 ** Function l2cu_send_peer_connect_req
464 ** Description Build and send an L2CAP "connection request" message
469 *******************************************************************************/
470 void l2cu_send_peer_connect_req (tL2C_CCB *p_ccb)
475 /* Create an identifier for this packet */
477 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
479 p_ccb->local_id = p_ccb->p_lcb->id;
481 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, L2CAP_CONN_REQ_LEN, L2CAP_CMD_CONN_REQ,
482 p_ccb->local_id)) == NULL) {
483 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
487 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
488 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
490 UINT16_TO_STREAM (p, p_ccb->p_rcb->real_psm);
491 UINT16_TO_STREAM (p, p_ccb->local_cid);
493 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
497 /*******************************************************************************
499 ** Function l2cu_send_peer_connect_rsp
501 ** Description Build and send an L2CAP "connection response" message
506 *******************************************************************************/
507 void l2cu_send_peer_connect_rsp (tL2C_CCB *p_ccb, UINT16 result, UINT16 status)
512 if (result == L2CAP_CONN_PENDING) {
513 /* if we already sent pending response */
514 if (p_ccb->flags & CCB_FLAG_SENT_PENDING) {
517 p_ccb->flags |= CCB_FLAG_SENT_PENDING;
521 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, p_ccb->remote_id)) == NULL) {
522 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_rsp");
526 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
527 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
529 UINT16_TO_STREAM (p, p_ccb->local_cid);
530 UINT16_TO_STREAM (p, p_ccb->remote_cid);
531 UINT16_TO_STREAM (p, result);
532 UINT16_TO_STREAM (p, status);
534 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
538 /*******************************************************************************
540 ** Function l2cu_reject_connection
542 ** Description Build and send an L2CAP "connection response neg" message
543 ** to the peer. This function is called when there is no peer
544 ** CCB (non-existant PSM or no resources).
548 *******************************************************************************/
549 void l2cu_reject_connection (tL2C_LCB *p_lcb, UINT16 remote_cid, UINT8 rem_id, UINT16 result)
554 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, rem_id)) == NULL ) {
555 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
559 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
561 UINT16_TO_STREAM (p, 0); /* Local CID of 0 */
562 UINT16_TO_STREAM (p, remote_cid);
563 UINT16_TO_STREAM (p, result);
564 UINT16_TO_STREAM (p, 0); /* Status of 0 */
566 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
569 /*******************************************************************************
571 ** Function l2cu_send_peer_config_req
573 ** Description Build and send an L2CAP "configuration request" message
578 *******************************************************************************/
579 void l2cu_send_peer_config_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
585 /* Create an identifier for this packet */
587 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
589 p_ccb->local_id = p_ccb->p_lcb->id;
591 if (p_cfg->mtu_present) {
592 cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
594 if (p_cfg->flush_to_present) {
595 cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
597 if (p_cfg->qos_present) {
598 cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
600 if (p_cfg->fcr_present) {
601 cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
603 if (p_cfg->fcs_present) {
604 cfg_len += L2CAP_CFG_FCS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
606 if (p_cfg->ext_flow_spec_present) {
607 cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
610 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, (UINT16) (L2CAP_CONFIG_REQ_LEN + cfg_len),
611 L2CAP_CMD_CONFIG_REQ, p_ccb->local_id)) == NULL ) {
612 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
616 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
617 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
619 UINT16_TO_STREAM (p, p_ccb->remote_cid);
620 UINT16_TO_STREAM (p, p_cfg->flags); /* Flags (continuation) */
622 /* Now, put the options */
623 if (p_cfg->mtu_present) {
624 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_MTU);
625 UINT8_TO_STREAM (p, L2CAP_CFG_MTU_OPTION_LEN);
626 UINT16_TO_STREAM (p, p_cfg->mtu);
628 if (p_cfg->flush_to_present) {
629 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FLUSH_TOUT);
630 UINT8_TO_STREAM (p, L2CAP_CFG_FLUSH_OPTION_LEN);
631 UINT16_TO_STREAM (p, p_cfg->flush_to);
633 if (p_cfg->qos_present) {
634 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_QOS);
635 UINT8_TO_STREAM (p, L2CAP_CFG_QOS_OPTION_LEN);
636 UINT8_TO_STREAM (p, p_cfg->qos.qos_flags);
637 UINT8_TO_STREAM (p, p_cfg->qos.service_type);
638 UINT32_TO_STREAM (p, p_cfg->qos.token_rate);
639 UINT32_TO_STREAM (p, p_cfg->qos.token_bucket_size);
640 UINT32_TO_STREAM (p, p_cfg->qos.peak_bandwidth);
641 UINT32_TO_STREAM (p, p_cfg->qos.latency);
642 UINT32_TO_STREAM (p, p_cfg->qos.delay_variation);
644 if (p_cfg->fcr_present) {
645 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCR);
646 UINT8_TO_STREAM (p, L2CAP_CFG_FCR_OPTION_LEN);
647 UINT8_TO_STREAM (p, p_cfg->fcr.mode);
648 UINT8_TO_STREAM (p, p_cfg->fcr.tx_win_sz);
649 UINT8_TO_STREAM (p, p_cfg->fcr.max_transmit);
650 UINT16_TO_STREAM (p, p_cfg->fcr.rtrans_tout);
651 UINT16_TO_STREAM (p, p_cfg->fcr.mon_tout);
652 UINT16_TO_STREAM (p, p_cfg->fcr.mps);
655 if (p_cfg->fcs_present) {
656 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCS);
657 UINT8_TO_STREAM (p, L2CAP_CFG_FCS_OPTION_LEN);
658 UINT8_TO_STREAM (p, p_cfg->fcs);
661 if (p_cfg->ext_flow_spec_present) {
662 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_EXT_FLOW);
663 UINT8_TO_STREAM (p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
664 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.id);
665 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.stype);
666 UINT16_TO_STREAM (p, p_cfg->ext_flow_spec.max_sdu_size);
667 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.sdu_inter_time);
668 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.access_latency);
669 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.flush_timeout);
672 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
675 /*******************************************************************************
677 ** Function l2cu_send_peer_config_rsp
679 ** Description Build and send an L2CAP "configuration response" message
684 *******************************************************************************/
685 void l2cu_send_peer_config_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
691 /* Create an identifier for this packet */
692 if (p_cfg->mtu_present) {
693 cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
695 if (p_cfg->flush_to_present) {
696 cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
698 if (p_cfg->qos_present) {
699 cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
701 if (p_cfg->fcr_present) {
702 cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
704 if (p_cfg->ext_flow_spec_present) {
705 cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
708 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, (UINT16)(L2CAP_CONFIG_RSP_LEN + cfg_len),
709 L2CAP_CMD_CONFIG_RSP, p_ccb->remote_id)) == NULL ) {
710 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
714 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
716 UINT16_TO_STREAM (p, p_ccb->remote_cid);
717 UINT16_TO_STREAM (p, p_cfg->flags); /* Flags (continuation) Must match request */
718 UINT16_TO_STREAM (p, p_cfg->result);
720 /* Now, put the options */
721 if (p_cfg->mtu_present) {
722 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_MTU);
723 UINT8_TO_STREAM (p, L2CAP_CFG_MTU_OPTION_LEN);
724 UINT16_TO_STREAM (p, p_cfg->mtu);
726 if (p_cfg->flush_to_present) {
727 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FLUSH_TOUT);
728 UINT8_TO_STREAM (p, L2CAP_CFG_FLUSH_OPTION_LEN);
729 UINT16_TO_STREAM (p, p_cfg->flush_to);
731 if (p_cfg->qos_present) {
732 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_QOS);
733 UINT8_TO_STREAM (p, L2CAP_CFG_QOS_OPTION_LEN);
734 UINT8_TO_STREAM (p, p_cfg->qos.qos_flags);
735 UINT8_TO_STREAM (p, p_cfg->qos.service_type);
736 UINT32_TO_STREAM (p, p_cfg->qos.token_rate);
737 UINT32_TO_STREAM (p, p_cfg->qos.token_bucket_size);
738 UINT32_TO_STREAM (p, p_cfg->qos.peak_bandwidth);
739 UINT32_TO_STREAM (p, p_cfg->qos.latency);
740 UINT32_TO_STREAM (p, p_cfg->qos.delay_variation);
742 if (p_cfg->fcr_present) {
743 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCR);
744 UINT8_TO_STREAM (p, L2CAP_CFG_FCR_OPTION_LEN);
745 UINT8_TO_STREAM (p, p_cfg->fcr.mode);
746 UINT8_TO_STREAM (p, p_cfg->fcr.tx_win_sz);
747 UINT8_TO_STREAM (p, p_cfg->fcr.max_transmit);
748 UINT16_TO_STREAM (p, p_ccb->our_cfg.fcr.rtrans_tout);
749 UINT16_TO_STREAM (p, p_ccb->our_cfg.fcr.mon_tout);
750 UINT16_TO_STREAM (p, p_cfg->fcr.mps);
753 if (p_cfg->ext_flow_spec_present) {
754 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_EXT_FLOW);
755 UINT8_TO_STREAM (p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
756 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.id);
757 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.stype);
758 UINT16_TO_STREAM (p, p_cfg->ext_flow_spec.max_sdu_size);
759 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.sdu_inter_time);
760 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.access_latency);
761 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.flush_timeout);
764 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
767 /*******************************************************************************
769 ** Function l2cu_send_peer_config_rej
771 ** Description Build and send an L2CAP "configuration reject" message
776 *******************************************************************************/
777 void l2cu_send_peer_config_rej (tL2C_CCB *p_ccb, UINT8 *p_data, UINT16 data_len, UINT16 rej_len)
780 UINT16 len, cfg_len, buf_space, len1;
781 UINT8 *p, *p_hci_len, *p_data_end;
784 L2CAP_TRACE_DEBUG("l2cu_send_peer_config_rej: data_len=%d, rej_len=%d", data_len, rej_len);
787 len = BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN;
789 if (rej_len > len1) {
790 L2CAP_TRACE_ERROR ("L2CAP - cfg_rej pkt size exceeds buffer design max limit.");
794 p_buf = (BT_HDR *)osi_malloc (len + rej_len);
797 L2CAP_TRACE_ERROR ("L2CAP - no buffer for cfg_rej");
801 p_buf->offset = L2CAP_SEND_CMD_OFFSET;
802 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
804 /* Put in HCI header - handle + pkt boundary */
805 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
806 if (HCI_NON_FLUSHABLE_PB_SUPPORTED(BTM_ReadLocalFeatures ())) {
807 UINT16_TO_STREAM (p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT)));
811 UINT16_TO_STREAM (p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
814 /* Remember the HCI header length position, and save space for it */
818 /* Put in L2CAP packet header */
819 UINT16_TO_STREAM (p, L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len);
820 UINT16_TO_STREAM (p, L2CAP_SIGNALLING_CID);
822 /* Put in L2CAP command header */
823 UINT8_TO_STREAM (p, L2CAP_CMD_CONFIG_RSP);
824 UINT8_TO_STREAM (p, p_ccb->remote_id);
826 UINT16_TO_STREAM (p, L2CAP_CONFIG_RSP_LEN + rej_len);
828 UINT16_TO_STREAM (p, p_ccb->remote_cid);
829 UINT16_TO_STREAM (p, 0); /* Flags = 0 (no continuation) */
830 UINT16_TO_STREAM (p, L2CAP_CFG_UNKNOWN_OPTIONS);
834 /* Now, put the rejected options */
835 p_data_end = p_data + data_len;
836 while (p_data < p_data_end) {
838 cfg_len = *(p_data + 1);
840 switch (cfg_code & 0x7F) {
841 /* skip known options */
842 case L2CAP_CFG_TYPE_MTU:
843 case L2CAP_CFG_TYPE_FLUSH_TOUT:
844 case L2CAP_CFG_TYPE_QOS:
845 p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
848 /* unknown options; copy into rsp if not hints */
850 /* sanity check option length */
851 if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= data_len) {
852 if ((cfg_code & 0x80) == 0) {
853 if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD)) {
854 memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
855 p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
856 buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
858 L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer");
859 p_data = p_data_end; /* force loop exit */
863 p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
865 /* bad length; force loop exit */
873 len = (UINT16) (p - p_hci_len - 2);
874 UINT16_TO_STREAM (p_hci_len, len);
876 p_buf->len = len + 4;
878 L2CAP_TRACE_DEBUG ("L2CAP - cfg_rej pkt hci_len=%d, l2cap_len=%d",
879 len, (L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len));
881 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
884 /*******************************************************************************
886 ** Function l2cu_send_peer_disc_req
888 ** Description Build and send an L2CAP "disconnect request" message
893 *******************************************************************************/
894 void l2cu_send_peer_disc_req (tL2C_CCB *p_ccb)
896 BT_HDR *p_buf, *p_buf2;
899 /* Create an identifier for this packet */
901 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
903 p_ccb->local_id = p_ccb->p_lcb->id;
905 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_DISC_REQ_LEN, L2CAP_CMD_DISC_REQ, p_ccb->local_id)) == NULL) {
906 L2CAP_TRACE_WARNING ("L2CAP - no buffer for disc_req");
910 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
912 UINT16_TO_STREAM (p, p_ccb->remote_cid);
913 UINT16_TO_STREAM (p, p_ccb->local_cid);
915 /* Move all queued data packets to the LCB. In FCR mode, assume the higher
916 layer checks that all buffers are sent before disconnecting.
918 if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
919 while ((p_buf2 = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q)) != NULL) {
920 l2cu_set_acl_hci_header (p_buf2, p_ccb);
921 l2c_link_check_send_pkts (p_ccb->p_lcb, p_ccb, p_buf2);
925 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
929 /*******************************************************************************
931 ** Function l2cu_send_peer_disc_rsp
933 ** Description Build and send an L2CAP "disconnect response" message
936 ** This function is passed the parameters for the disconnect
937 ** response instead of the CCB address, as it may be called
938 ** to send a disconnect response when there is no CCB.
942 *******************************************************************************/
943 void l2cu_send_peer_disc_rsp (tL2C_LCB *p_lcb, UINT8 remote_id, UINT16 local_cid,
950 L2CAP_TRACE_WARNING("lcb already released\n");
954 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_RSP_LEN, L2CAP_CMD_DISC_RSP, remote_id)) == NULL) {
955 L2CAP_TRACE_WARNING ("L2CAP - no buffer for disc_rsp");
959 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
961 UINT16_TO_STREAM (p, local_cid);
962 UINT16_TO_STREAM (p, remote_cid);
964 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
968 /*******************************************************************************
970 ** Function l2cu_send_peer_echo_req
972 ** Description Build and send an L2CAP "echo request" message
973 ** to the peer. Note that we do not currently allow
974 ** data in the echo request.
978 *******************************************************************************/
979 void l2cu_send_peer_echo_req (tL2C_LCB *p_lcb, UINT8 *p_data, UINT16 data_len)
985 l2cu_adj_id(p_lcb, L2CAP_ADJ_ZERO_ID); /* check for wrap to '0' */
987 if ((p_buf = l2cu_build_header(p_lcb, (UINT16) (L2CAP_ECHO_REQ_LEN + data_len), L2CAP_CMD_ECHO_REQ, p_lcb->id)) == NULL) {
988 L2CAP_TRACE_WARNING ("L2CAP - no buffer for echo_req");
992 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
995 ARRAY_TO_STREAM (p, p_data, data_len);
998 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1002 /*******************************************************************************
1004 ** Function l2cu_send_peer_echo_rsp
1006 ** Description Build and send an L2CAP "echo response" message
1011 *******************************************************************************/
1012 void l2cu_send_peer_echo_rsp (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len)
1017 /* Filter out duplicate IDs or if available buffers are low (intruder checking) */
1018 if (!id || id == p_lcb->cur_echo_id) {
1019 /* Dump this request since it is illegal */
1020 L2CAP_TRACE_WARNING ("L2CAP ignoring duplicate echo request (%d)", id);
1023 p_lcb->cur_echo_id = id;
1026 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
1027 uint16_t acl_packet_size = controller_get_interface()->get_acl_packet_size_classic();
1028 /* Don't return data if it does not fit in ACL and L2CAP MTU */
1029 maxlen = (L2CAP_CMD_BUF_SIZE > acl_packet_size) ?
1030 acl_data_size : (UINT16)L2CAP_CMD_BUF_SIZE;
1031 maxlen -= (UINT16)(BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
1032 L2CAP_CMD_OVERHEAD + L2CAP_ECHO_RSP_LEN);
1034 if (data_len > maxlen) {
1038 if ((p_buf = l2cu_build_header (p_lcb, (UINT16)(L2CAP_ECHO_RSP_LEN + data_len), L2CAP_CMD_ECHO_RSP, id)) == NULL) {
1039 L2CAP_TRACE_WARNING ("L2CAP - no buffer for echo_rsp");
1043 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1044 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1047 ARRAY_TO_STREAM (p, p_data, data_len);
1050 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1053 /*******************************************************************************
1055 ** Function l2cu_send_peer_info_req
1057 ** Description Build and send an L2CAP "info request" message
1061 *******************************************************************************/
1062 void l2cu_send_peer_info_req (tL2C_LCB *p_lcb, UINT16 info_type)
1067 /* check for wrap and/or BRCM ID */
1069 l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
1071 if ((p_buf = l2cu_build_header(p_lcb, 2, L2CAP_CMD_INFO_REQ, p_lcb->id)) == NULL) {
1072 L2CAP_TRACE_WARNING ("L2CAP - no buffer for info_req");
1076 L2CAP_TRACE_EVENT ("l2cu_send_peer_info_req: type 0x%04x", info_type);
1078 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1079 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1081 UINT16_TO_STREAM (p, info_type);
1083 p_lcb->w4_info_rsp = TRUE;
1084 btu_start_timer (&p_lcb->info_timer_entry, BTU_TTYPE_L2CAP_INFO, L2CAP_WAIT_INFO_RSP_TOUT);
1086 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1090 /*******************************************************************************
1092 ** Function l2cu_send_peer_info_rsp
1094 ** Description Build and send an L2CAP "info response" message
1099 *******************************************************************************/
1100 void l2cu_send_peer_info_rsp (tL2C_LCB *p_lcb, UINT8 remote_id, UINT16 info_type)
1104 UINT16 len = L2CAP_INFO_RSP_LEN;
1106 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1107 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1108 && (l2cb.test_info_resp & (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1109 L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_EXT_FLOW_SPEC |
1110 L2CAP_EXTFEA_FIXED_CHNLS | L2CAP_EXTFEA_EXT_WINDOW |
1111 L2CAP_EXTFEA_UCD_RECEPTION )) )
1113 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1114 && (L2CAP_EXTFEA_SUPPORTED_MASK & (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1115 L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS |
1116 L2CAP_EXTFEA_UCD_RECEPTION )) )
1119 len += L2CAP_EXTENDED_FEATURES_ARRAY_SIZE;
1120 } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1121 len += L2CAP_FIXED_CHNL_ARRAY_SIZE;
1122 } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1123 len += L2CAP_CONNLESS_MTU_INFO_SIZE;
1126 if ((p_buf = l2cu_build_header(p_lcb, len, L2CAP_CMD_INFO_RSP, remote_id)) == NULL) {
1127 L2CAP_TRACE_WARNING ("L2CAP - no buffer for info_rsp");
1131 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1132 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1134 UINT16_TO_STREAM (p, info_type);
1136 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1137 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1138 && (l2cb.test_info_resp & ( L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE
1139 | L2CAP_EXTFEA_UCD_RECEPTION )) )
1141 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1142 && (L2CAP_EXTFEA_SUPPORTED_MASK & ( L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE
1143 | L2CAP_EXTFEA_UCD_RECEPTION )) )
1146 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1147 #if (BLE_INCLUDED == TRUE)
1148 if (p_lcb->transport == BT_TRANSPORT_LE) {
1149 /* optional data are not added for now */
1150 UINT32_TO_STREAM (p, L2CAP_BLE_EXTFEA_MASK);
1154 #if L2CAP_CONFORMANCE_TESTING == TRUE
1155 UINT32_TO_STREAM (p, l2cb.test_info_resp);
1157 #if (L2CAP_NUM_FIXED_CHNLS > 0)
1158 UINT32_TO_STREAM (p, L2CAP_EXTFEA_SUPPORTED_MASK | L2CAP_EXTFEA_FIXED_CHNLS);
1160 UINT32_TO_STREAM (p, L2CAP_EXTFEA_SUPPORTED_MASK);
1164 } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1165 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1166 memset (p, 0, L2CAP_FIXED_CHNL_ARRAY_SIZE);
1168 p[0] = L2CAP_FIXED_CHNL_SIG_BIT;
1170 if ( L2CAP_EXTFEA_SUPPORTED_MASK & L2CAP_EXTFEA_UCD_RECEPTION ) {
1171 p[0] |= L2CAP_FIXED_CHNL_CNCTLESS_BIT;
1174 #if (L2CAP_NUM_FIXED_CHNLS > 0)
1178 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
1179 if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
1180 p[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] |= 1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8);
1184 } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1185 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1186 UINT16_TO_STREAM (p, L2CAP_UCD_MTU);
1188 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_NOT_SUPPORTED); /* 'not supported' */
1191 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1194 /******************************************************************************
1196 ** Function l2cu_enqueue_ccb
1198 ** Description queue CCB by priority. The first CCB is highest priority and
1199 ** is served at first. The CCB is queued to an LLCB or an LCB.
1203 *******************************************************************************/
1204 void l2cu_enqueue_ccb (tL2C_CCB *p_ccb)
1207 tL2C_CCB_Q *p_q = NULL;
1209 /* Find out which queue the channel is on
1211 if (p_ccb->p_lcb != NULL) {
1212 p_q = &p_ccb->p_lcb->ccb_queue;
1215 if ( (!p_ccb->in_use) || (p_q == NULL) ) {
1216 L2CAP_TRACE_ERROR ("l2cu_enqueue_ccb CID: 0x%04x ERROR in_use: %u p_lcb: %p",
1217 p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb);
1221 L2CAP_TRACE_DEBUG ("l2cu_enqueue_ccb CID: 0x%04x priority: %d",
1222 p_ccb->local_cid, p_ccb->ccb_priority);
1224 /* If the queue is empty, we go at the front */
1225 if (!p_q->p_first_ccb) {
1226 p_q->p_first_ccb = p_q->p_last_ccb = p_ccb;
1227 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1229 p_ccb1 = p_q->p_first_ccb;
1231 while (p_ccb1 != NULL) {
1232 /* Insert new ccb at the end of the same priority. Lower number, higher priority */
1233 if (p_ccb->ccb_priority < p_ccb1->ccb_priority) {
1234 /* Are we at the head of the queue ? */
1235 if (p_ccb1 == p_q->p_first_ccb) {
1236 p_q->p_first_ccb = p_ccb;
1238 p_ccb1->p_prev_ccb->p_next_ccb = p_ccb;
1241 p_ccb->p_next_ccb = p_ccb1;
1242 p_ccb->p_prev_ccb = p_ccb1->p_prev_ccb;
1243 p_ccb1->p_prev_ccb = p_ccb;
1247 p_ccb1 = p_ccb1->p_next_ccb;
1250 /* If we are lower then anyone in the list, we go at the end */
1252 /* add new ccb at the end of the list */
1253 p_q->p_last_ccb->p_next_ccb = p_ccb;
1255 p_ccb->p_next_ccb = NULL;
1256 p_ccb->p_prev_ccb = p_q->p_last_ccb;
1257 p_q->p_last_ccb = p_ccb;
1261 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1262 /* Adding CCB into round robin service table of its LCB */
1263 if (p_ccb->p_lcb != NULL) {
1264 /* if this is the first channel in this priority group */
1265 if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0 ) {
1266 /* Set the first channel to this CCB */
1267 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1268 /* Set the next serving channel in this group to this CCB */
1269 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1270 /* Initialize quota of this priority group based on its priority */
1271 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota = L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1273 /* increase number of channels in this group */
1274 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb++;
1280 /******************************************************************************
1282 ** Function l2cu_dequeue_ccb
1284 ** Description dequeue CCB from a queue
1288 *******************************************************************************/
1289 void l2cu_dequeue_ccb (tL2C_CCB *p_ccb)
1291 tL2C_CCB_Q *p_q = NULL;
1293 L2CAP_TRACE_DEBUG ("l2cu_dequeue_ccb CID: 0x%04x", p_ccb->local_cid);
1295 /* Find out which queue the channel is on
1297 if (p_ccb->p_lcb != NULL) {
1298 p_q = &p_ccb->p_lcb->ccb_queue;
1301 if ( (!p_ccb->in_use) || (p_q == NULL) || (p_q->p_first_ccb == NULL) ) {
1302 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",
1303 p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb, p_q, p_q ? p_q->p_first_ccb : 0);
1307 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1308 /* Removing CCB from round robin service table of its LCB */
1309 if (p_ccb->p_lcb != NULL) {
1310 /* decrease number of channels in this priority group */
1311 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb--;
1313 /* if it was the last channel in the priority group */
1314 if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0 ) {
1315 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1316 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1318 /* if it is the first channel of this group */
1319 if ( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb == p_ccb ) {
1320 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb->p_next_ccb;
1322 /* if it is the next serving channel of this group */
1323 if ( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb == p_ccb ) {
1324 /* simply, start serving from the first channel */
1325 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb
1326 = p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb;
1332 if (p_ccb == p_q->p_first_ccb) {
1333 /* We are removing the first in a queue */
1334 p_q->p_first_ccb = p_ccb->p_next_ccb;
1336 if (p_q->p_first_ccb) {
1337 p_q->p_first_ccb->p_prev_ccb = NULL;
1339 p_q->p_last_ccb = NULL;
1341 } else if (p_ccb == p_q->p_last_ccb) {
1342 /* We are removing the last in a queue */
1343 p_q->p_last_ccb = p_ccb->p_prev_ccb;
1344 p_q->p_last_ccb->p_next_ccb = NULL;
1346 /* In the middle of a chain. */
1347 p_ccb->p_prev_ccb->p_next_ccb = p_ccb->p_next_ccb;
1348 p_ccb->p_next_ccb->p_prev_ccb = p_ccb->p_prev_ccb;
1351 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1354 /******************************************************************************
1356 ** Function l2cu_change_pri_ccb
1362 *******************************************************************************/
1363 void l2cu_change_pri_ccb (tL2C_CCB *p_ccb, tL2CAP_CHNL_PRIORITY priority)
1365 if (p_ccb->ccb_priority != priority) {
1366 /* If CCB is not the only guy on the queue */
1367 if ( (p_ccb->p_next_ccb != NULL) || (p_ccb->p_prev_ccb != NULL) ) {
1368 L2CAP_TRACE_DEBUG ("Update CCB list in logical link");
1370 /* Remove CCB from queue and re-queue it at new priority */
1371 l2cu_dequeue_ccb (p_ccb);
1373 p_ccb->ccb_priority = priority;
1374 l2cu_enqueue_ccb (p_ccb);
1376 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1378 /* If CCB is the only guy on the queue, no need to re-enqueue */
1379 /* update only round robin service data */
1380 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 0;
1381 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1382 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1384 p_ccb->ccb_priority = priority;
1386 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1387 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1388 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota = L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1389 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 1;
1395 /*******************************************************************************
1397 ** Function l2cu_allocate_ccb
1399 ** Description This function allocates a Channel Control Block and
1400 ** attaches it to a link control block. The local CID
1401 ** is also assigned.
1403 ** Returns pointer to CCB, or NULL if none
1405 *******************************************************************************/
1406 tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
1411 L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x", cid);
1413 if (!l2cb.p_free_ccb_first) {
1417 /* If a CID was passed in, use that, else take the first free one */
1419 p_ccb = l2cb.p_free_ccb_first;
1420 l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1424 p_ccb = &l2cb.ccb_pool[cid - L2CAP_BASE_APPL_CID];
1426 if (p_ccb == l2cb.p_free_ccb_first) {
1427 l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1429 for (p_prev = l2cb.p_free_ccb_first; p_prev != NULL; p_prev = p_prev->p_next_ccb) {
1430 if (p_prev->p_next_ccb == p_ccb) {
1431 p_prev->p_next_ccb = p_ccb->p_next_ccb;
1433 if (p_ccb == l2cb.p_free_ccb_last) {
1434 l2cb.p_free_ccb_last = p_prev;
1440 if (p_prev == NULL) {
1441 L2CAP_TRACE_ERROR ("l2cu_allocate_ccb: could not find CCB for CID 0x%04x in the free list", cid);
1447 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1449 p_ccb->in_use = TRUE;
1451 /* Get a CID for the connection */
1452 p_ccb->local_cid = L2CAP_BASE_APPL_CID + (UINT16)(p_ccb - l2cb.ccb_pool);
1454 p_ccb->p_lcb = p_lcb;
1455 p_ccb->p_rcb = NULL;
1456 p_ccb->should_free_rcb = false;
1458 /* Set priority then insert ccb into LCB queue (if we have an LCB) */
1459 p_ccb->ccb_priority = L2CAP_CHNL_PRIORITY_LOW;
1462 l2cu_enqueue_ccb (p_ccb);
1465 /* clear what peer wants to configure */
1466 p_ccb->peer_cfg_bits = 0;
1468 /* Put in default values for configuration */
1469 memset (&p_ccb->our_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1470 memset (&p_ccb->peer_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1472 /* Put in default values for local/peer configurations */
1473 p_ccb->our_cfg.flush_to = p_ccb->peer_cfg.flush_to = L2CAP_DEFAULT_FLUSH_TO;
1474 p_ccb->our_cfg.mtu = p_ccb->peer_cfg.mtu = L2CAP_DEFAULT_MTU;
1475 p_ccb->our_cfg.qos.service_type = p_ccb->peer_cfg.qos.service_type = L2CAP_DEFAULT_SERV_TYPE;
1476 p_ccb->our_cfg.qos.token_rate = p_ccb->peer_cfg.qos.token_rate = L2CAP_DEFAULT_TOKEN_RATE;
1477 p_ccb->our_cfg.qos.token_bucket_size = p_ccb->peer_cfg.qos.token_bucket_size = L2CAP_DEFAULT_BUCKET_SIZE;
1478 p_ccb->our_cfg.qos.peak_bandwidth = p_ccb->peer_cfg.qos.peak_bandwidth = L2CAP_DEFAULT_PEAK_BANDWIDTH;
1479 p_ccb->our_cfg.qos.latency = p_ccb->peer_cfg.qos.latency = L2CAP_DEFAULT_LATENCY;
1480 p_ccb->our_cfg.qos.delay_variation = p_ccb->peer_cfg.qos.delay_variation = L2CAP_DEFAULT_DELAY;
1482 p_ccb->bypass_fcs = 0;
1483 memset (&p_ccb->ertm_info, 0, sizeof(tL2CAP_ERTM_INFO));
1484 p_ccb->peer_cfg_already_rejected = FALSE;
1485 p_ccb->fcr_cfg_tries = L2CAP_MAX_FCR_CFG_TRIES;
1487 /* stop and release timers */
1488 btu_free_quick_timer(&p_ccb->fcrb.ack_timer);
1489 memset(&p_ccb->fcrb.ack_timer, 0, sizeof(TIMER_LIST_ENT));
1490 p_ccb->fcrb.ack_timer.param = (TIMER_PARAM_TYPE)p_ccb;
1492 btu_free_quick_timer(&p_ccb->fcrb.mon_retrans_timer);
1493 memset(&p_ccb->fcrb.mon_retrans_timer, 0, sizeof(TIMER_LIST_ENT));
1494 p_ccb->fcrb.mon_retrans_timer.param = (TIMER_PARAM_TYPE)p_ccb;
1497 /* CSP408639 Fix: When L2CAP send amp move channel request or receive
1498 * L2CEVT_AMP_MOVE_REQ do following sequence. Send channel move
1499 * request -> Stop retrans/monitor timer -> Change channel state to CST_AMP_MOVING. */
1502 #if (CLASSIC_BT_INCLUDED == TRUE)
1503 l2c_fcr_free_timer (p_ccb);
1504 #endif ///CLASSIC_BT_INCLUDED == TRUE
1505 p_ccb->ertm_info.preferred_mode = L2CAP_FCR_BASIC_MODE; /* Default mode for channel is basic mode */
1506 p_ccb->ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_BASIC; /* Default mode for channel is basic mode */
1507 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
1508 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
1509 p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
1510 p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
1511 p_ccb->max_rx_mtu = L2CAP_MTU_SIZE;
1512 p_ccb->tx_mps = L2CAP_FCR_TX_BUF_SIZE - 32;
1514 p_ccb->xmit_hold_q = fixed_queue_new(SIZE_MAX);
1515 #if (CLASSIC_BT_INCLUDED == TRUE)
1516 p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX);
1517 p_ccb->fcrb.retrans_q = fixed_queue_new(SIZE_MAX);
1518 p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(SIZE_MAX);
1519 #endif ///CLASSIC_BT_INCLUDED == TRUE
1521 p_ccb->cong_sent = FALSE;
1522 p_ccb->buff_quota = 2; /* This gets set after config */
1524 /* If CCB was reserved Config_Done can already have some value */
1526 p_ccb->config_done = 0;
1528 L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x config_done:0x%x", cid, p_ccb->config_done);
1531 p_ccb->chnl_state = CST_CLOSED;
1533 p_ccb->tx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1534 p_ccb->rx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1536 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
1537 p_ccb->is_flushable = FALSE;
1540 btu_free_timer(&p_ccb->timer_entry);
1541 memset(&p_ccb->timer_entry, 0, sizeof(TIMER_LIST_ENT));
1542 p_ccb->timer_entry.param = (TIMER_PARAM_TYPE)p_ccb;
1543 p_ccb->timer_entry.in_use = 0;
1545 l2c_link_adjust_chnl_allocation ();
1550 /*******************************************************************************
1552 ** Function l2cu_start_post_bond_timer
1554 ** Description This function starts the ACL Link inactivity timer after
1555 ** dedicated bonding
1556 ** This timer can be longer than the normal link inactivity
1557 ** timer for some platforms.
1559 ** Returns BOOLEAN - TRUE if idle timer started or disconnect initiated
1560 ** FALSE if there's one or more pending CCB's exist
1562 *******************************************************************************/
1563 BOOLEAN l2cu_start_post_bond_timer (UINT16 handle)
1566 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
1572 p_lcb->is_bonding = FALSE;
1574 /* Only start timer if no control blocks allocated */
1575 if (p_lcb->ccb_queue.p_first_ccb != NULL) {
1579 /* If no channels on the connection, start idle timeout */
1580 if ( (p_lcb->link_state == LST_CONNECTED) || (p_lcb->link_state == LST_CONNECTING) || (p_lcb->link_state == LST_DISCONNECTING) ) {
1581 if (p_lcb->idle_timeout == 0) {
1582 if (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) {
1583 p_lcb->link_state = LST_DISCONNECTING;
1584 timeout = L2CAP_LINK_DISCONNECT_TOUT;
1586 timeout = BT_1SEC_TIMEOUT;
1589 timeout = L2CAP_BONDING_TIMEOUT;
1592 if (timeout != 0xFFFF) {
1593 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, timeout);
1602 /*******************************************************************************
1604 ** Function l2cu_release_ccb
1606 ** Description This function releases a Channel Control Block. The timer
1607 ** is stopped, any attached buffers freed, and the CCB is removed
1608 ** from the link control block.
1612 *******************************************************************************/
1613 void l2cu_release_ccb (tL2C_CCB *p_ccb)
1615 tL2C_LCB *p_lcb = p_ccb->p_lcb;
1616 tL2C_RCB *p_rcb = p_ccb->p_rcb;
1618 L2CAP_TRACE_DEBUG ("l2cu_release_ccb: cid 0x%04x in_use: %u", p_ccb->local_cid, p_ccb->in_use);
1620 /* If already released, could be race condition */
1621 if (!p_ccb->in_use) {
1624 #if (SDP_INCLUDED == TRUE)
1625 if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
1626 btm_sec_clr_service_by_psm(p_rcb->psm);
1628 #endif ///SMP_INCLUDED == TRUE
1629 if (p_ccb->should_free_rcb) {
1631 p_ccb->p_rcb = NULL;
1632 p_ccb->should_free_rcb = false;
1636 btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
1639 /* Stop and free the timer */
1640 btu_free_timer (&p_ccb->timer_entry);
1642 fixed_queue_free(p_ccb->xmit_hold_q, osi_free_func);
1643 p_ccb->xmit_hold_q = NULL;
1644 #if (CLASSIC_BT_INCLUDED == TRUE)
1645 fixed_queue_free(p_ccb->fcrb.srej_rcv_hold_q, osi_free_func);
1646 fixed_queue_free(p_ccb->fcrb.retrans_q, osi_free_func);
1647 fixed_queue_free(p_ccb->fcrb.waiting_for_ack_q, osi_free_func);
1648 p_ccb->fcrb.srej_rcv_hold_q = NULL;
1649 p_ccb->fcrb.retrans_q = NULL;
1650 p_ccb->fcrb.waiting_for_ack_q = NULL;
1651 #endif ///CLASSIC_BT_INCLUDED == TRUE
1654 #if (CLASSIC_BT_INCLUDED == TRUE)
1655 l2c_fcr_cleanup (p_ccb);
1656 #endif ///CLASSIC_BT_INCLUDED == TRUE
1657 /* Channel may not be assigned to any LCB if it was just pre-reserved */
1659 ( (p_ccb->local_cid >= L2CAP_BASE_APPL_CID)
1660 #if (L2CAP_UCD_INCLUDED == TRUE)
1661 || (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)
1665 l2cu_dequeue_ccb (p_ccb);
1667 /* Delink the CCB from the LCB */
1668 p_ccb->p_lcb = NULL;
1671 /* Put the CCB back on the free pool */
1672 if (!l2cb.p_free_ccb_first) {
1673 l2cb.p_free_ccb_first = p_ccb;
1674 l2cb.p_free_ccb_last = p_ccb;
1675 p_ccb->p_next_ccb = NULL;
1676 p_ccb->p_prev_ccb = NULL;
1678 p_ccb->p_next_ccb = NULL;
1679 p_ccb->p_prev_ccb = l2cb.p_free_ccb_last;
1680 l2cb.p_free_ccb_last->p_next_ccb = p_ccb;
1681 l2cb.p_free_ccb_last = p_ccb;
1684 /* Flag as not in use */
1685 p_ccb->in_use = FALSE;
1687 /* If no channels on the connection, start idle timeout */
1688 if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED)) {
1689 if (!p_lcb->ccb_queue.p_first_ccb) {
1690 l2cu_no_dynamic_ccbs (p_lcb);
1692 /* Link is still active, adjust channel quotas. */
1693 l2c_link_adjust_chnl_allocation ();
1698 /*******************************************************************************
1700 ** Function l2cu_find_ccb_by_remote_cid
1702 ** Description Look through all active CCBs on a link for a match based
1703 ** on the remote CID.
1705 ** Returns pointer to matched CCB, or NULL if no match
1707 *******************************************************************************/
1708 tL2C_CCB *l2cu_find_ccb_by_remote_cid (tL2C_LCB *p_lcb, UINT16 remote_cid)
1712 /* If LCB is NULL, look through all active links */
1716 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
1717 if ((p_ccb->in_use) && (p_ccb->remote_cid == remote_cid)) {
1722 /* If here, no match found */
1726 /*******************************************************************************
1728 ** Function l2cu_allocate_rcb
1730 ** Description Look through the Registration Control Blocks for a free
1733 ** Returns Pointer to the RCB or NULL if not found
1735 *******************************************************************************/
1736 tL2C_RCB *l2cu_allocate_rcb (UINT16 psm)
1738 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
1741 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1742 if (!p_rcb->in_use) {
1743 p_rcb->in_use = TRUE;
1745 #if (L2CAP_UCD_INCLUDED == TRUE)
1746 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
1752 /* If here, no free RCB found */
1756 /*******************************************************************************
1758 ** Function l2cu_allocate_ble_rcb
1760 ** Description Look through the BLE Registration Control Blocks for a free
1763 ** Returns Pointer to the BLE RCB or NULL if not found
1765 *******************************************************************************/
1766 tL2C_RCB *l2cu_allocate_ble_rcb (UINT16 psm)
1768 tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
1771 for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
1775 p_rcb->in_use = TRUE;
1777 #if (L2CAP_UCD_INCLUDED == TRUE)
1778 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
1784 /* If here, no free RCB found */
1788 /*******************************************************************************
1790 ** Function l2cu_release_rcb
1792 ** Description Mark an RCB as no longet in use
1796 *******************************************************************************/
1797 void l2cu_release_rcb (tL2C_RCB *p_rcb)
1799 p_rcb->in_use = FALSE;
1804 /*******************************************************************************
1806 ** Function l2cu_disconnect_chnl
1808 ** Description Disconnect a channel. Typically, this is due to either
1809 ** receiving a bad configuration, bad packet or max_retries expiring.
1811 *******************************************************************************/
1812 void l2cu_disconnect_chnl (tL2C_CCB *p_ccb)
1814 UINT16 local_cid = p_ccb->local_cid;
1816 if (local_cid >= L2CAP_BASE_APPL_CID) {
1817 tL2CA_DISCONNECT_IND_CB *p_disc_cb = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
1819 L2CAP_TRACE_WARNING ("L2CAP - disconnect_chnl CID: 0x%04x", local_cid);
1821 l2cu_send_peer_disc_req (p_ccb);
1823 l2cu_release_ccb (p_ccb);
1825 (*p_disc_cb)(local_cid, FALSE);
1827 /* failure on the AMP channel, probably need to disconnect ACL */
1828 L2CAP_TRACE_ERROR ("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid);
1833 /*******************************************************************************
1835 ** Function l2cu_find_rcb_by_psm
1837 ** Description Look through the Registration Control Blocks to see if
1838 ** anyone registered to handle the PSM in question
1840 ** Returns Pointer to the RCB or NULL if not found
1842 *******************************************************************************/
1843 tL2C_RCB *l2cu_find_rcb_by_psm (UINT16 psm)
1845 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
1848 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1849 if ((p_rcb->in_use) && (p_rcb->psm == psm)) {
1854 /* If here, no match found */
1858 /*******************************************************************************
1860 ** Function l2cu_find_ble_rcb_by_psm
1862 ** Description Look through the BLE Registration Control Blocks to see if
1863 ** anyone registered to handle the PSM in question
1865 ** Returns Pointer to the BLE RCB or NULL if not found
1867 *******************************************************************************/
1868 tL2C_RCB *l2cu_find_ble_rcb_by_psm (UINT16 psm)
1870 tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
1873 for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
1875 if ((p_rcb->in_use) && (p_rcb->psm == psm))
1879 /* If here, no match found */
1885 /*******************************************************************************
1887 ** Function l2cu_process_peer_cfg_req
1889 ** Description This function is called when the peer sends us a "config request"
1890 ** message. It extracts the configuration of interest and saves
1893 ** Note: Negotiation of the FCR channel type is handled internally,
1894 ** all others are passed to the upper layer.
1896 ** Returns UINT8 - L2CAP_PEER_CFG_OK if passed to upper layer,
1897 ** L2CAP_PEER_CFG_UNACCEPTABLE if automatically responded to
1898 ** because parameters are unnacceptable from a specification
1900 ** L2CAP_PEER_CFG_DISCONNECT if no compatible channel modes
1901 ** between the two devices, and shall be closed.
1903 *******************************************************************************/
1904 UINT8 l2cu_process_peer_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
1906 BOOLEAN mtu_ok = TRUE;
1907 BOOLEAN qos_type_ok = TRUE;
1908 BOOLEAN flush_to_ok = TRUE;
1909 BOOLEAN fcr_ok = TRUE;
1910 #if (CLASSIC_BT_INCLUDED == TRUE)
1912 #endif ///CLASSIC_BT_INCLUDED == TRUE
1913 /* Ignore FCR parameters for basic mode */
1914 if (!p_cfg->fcr_present) {
1915 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
1918 /* Save the MTU that our peer can receive */
1919 if (p_cfg->mtu_present) {
1920 /* Make sure MTU is at least the minimum */
1921 if (p_cfg->mtu >= L2CAP_MIN_MTU) {
1922 /* In basic mode, limit the MTU to our buffer size */
1923 if ( (p_cfg->fcr_present == FALSE) && (p_cfg->mtu > L2CAP_MTU_SIZE) ) {
1924 p_cfg->mtu = L2CAP_MTU_SIZE;
1927 /* Save the accepted value in case of renegotiation */
1928 p_ccb->peer_cfg.mtu = p_cfg->mtu;
1929 p_ccb->peer_cfg.mtu_present = TRUE;
1930 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_MTU;
1931 } else { /* Illegal MTU value */
1932 p_cfg->mtu = L2CAP_MIN_MTU;
1936 /* Reload mtu from a previously accepted config request */
1937 else if (p_ccb->peer_cfg.mtu_present) {
1938 p_cfg->mtu_present = TRUE;
1939 p_cfg->mtu = p_ccb->peer_cfg.mtu;
1942 /* Verify that the flush timeout is a valid value (0 is illegal) */
1943 if (p_cfg->flush_to_present) {
1944 if (!p_cfg->flush_to) {
1945 p_cfg->flush_to = 0xFFFF; /* Infinite retransmissions (spec default) */
1946 flush_to_ok = FALSE;
1947 } else { /* Save the accepted value in case of renegotiation */
1948 p_ccb->peer_cfg.flush_to_present = TRUE;
1949 p_ccb->peer_cfg.flush_to = p_cfg->flush_to;
1950 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FLUSH_TO;
1953 /* Reload flush_to from a previously accepted config request */
1954 else if (p_ccb->peer_cfg.flush_to_present) {
1955 p_cfg->flush_to_present = TRUE;
1956 p_cfg->flush_to = p_ccb->peer_cfg.flush_to;
1959 /* Save the QOS settings the the peer is using */
1960 if (p_cfg->qos_present) {
1961 /* Make sure service type is not a reserved value; otherwise let upper
1962 layer decide if acceptable
1964 if (p_cfg->qos.service_type <= GUARANTEED) {
1965 p_ccb->peer_cfg.qos = p_cfg->qos;
1966 p_ccb->peer_cfg.qos_present = TRUE;
1967 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_QOS;
1968 } else { /* Illegal service type value */
1969 p_cfg->qos.service_type = BEST_EFFORT;
1970 qos_type_ok = FALSE;
1973 /* Reload QOS from a previously accepted config request */
1974 else if (p_ccb->peer_cfg.qos_present) {
1975 p_cfg->qos_present = TRUE;
1976 p_cfg->qos = p_ccb->peer_cfg.qos;
1978 #if (CLASSIC_BT_INCLUDED == TRUE)
1979 if ((fcr_status = l2c_fcr_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_DISCONNECT) {
1980 /* Notify caller to disconnect the channel (incompatible modes) */
1981 p_cfg->result = L2CAP_CFG_FAILED_NO_REASON;
1982 p_cfg->mtu_present = p_cfg->qos_present = p_cfg->flush_to_present = 0;
1984 return (L2CAP_PEER_CFG_DISCONNECT);
1987 fcr_ok = (fcr_status == L2CAP_PEER_CFG_OK);
1988 #endif ///CLASSIC_BT_INCLUDED == TRUE
1990 /* Return any unacceptable parameters */
1991 if (mtu_ok && flush_to_ok && qos_type_ok && fcr_ok) {
1992 l2cu_adjust_out_mps (p_ccb);
1993 return (L2CAP_PEER_CFG_OK);
1995 p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
1998 p_cfg->mtu_present = FALSE;
2001 p_cfg->flush_to_present = FALSE;
2004 p_cfg->qos_present = FALSE;
2007 p_cfg->fcr_present = FALSE;
2010 return (L2CAP_PEER_CFG_UNACCEPTABLE);
2015 /*******************************************************************************
2017 ** Function l2cu_process_peer_cfg_rsp
2019 ** Description This function is called when the peer sends us a "config response"
2020 ** message. It extracts the configuration of interest and saves
2025 *******************************************************************************/
2026 void l2cu_process_peer_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2028 /* If we wanted QoS and the peer sends us a positive response with QoS, use his values */
2029 if ( (p_cfg->qos_present) && (p_ccb->our_cfg.qos_present) ) {
2030 p_ccb->our_cfg.qos = p_cfg->qos;
2033 if (p_cfg->fcr_present) {
2034 /* Save the retransmission and monitor timeout values */
2035 if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE) {
2036 p_ccb->peer_cfg.fcr.rtrans_tout = p_cfg->fcr.rtrans_tout;
2037 p_ccb->peer_cfg.fcr.mon_tout = p_cfg->fcr.mon_tout;
2040 /* Calculate the max number of packets for which we can delay sending an ack */
2041 if (p_cfg->fcr.tx_win_sz < p_ccb->our_cfg.fcr.tx_win_sz) {
2042 p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2044 p_ccb->fcrb.max_held_acks = p_ccb->our_cfg.fcr.tx_win_sz / 3;
2047 L2CAP_TRACE_DEBUG ("l2cu_process_peer_cfg_rsp(): peer tx_win_sz: %d, our tx_win_sz: %d, max_held_acks: %d",
2048 p_cfg->fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz, p_ccb->fcrb.max_held_acks);
2052 /*******************************************************************************
2054 ** Function l2cu_process_our_cfg_req
2056 ** Description This function is called when we send a "config request"
2057 ** message. It extracts the configuration of interest and saves
2062 *******************************************************************************/
2063 void l2cu_process_our_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2066 UINT16 hci_flush_to;
2068 /* Save the QOS settings we are using for transmit */
2069 if (p_cfg->qos_present) {
2070 p_ccb->our_cfg.qos_present = TRUE;
2071 p_ccb->our_cfg.qos = p_cfg->qos;
2074 if (p_cfg->fcr_present) {
2075 /* Override FCR options if attempting streaming or basic */
2076 if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE) {
2077 memset(&p_cfg->fcr, 0, sizeof(tL2CAP_FCR_OPTS));
2079 /* On BR/EDR, timer values are zero in config request */
2080 /* On class 2 AMP, timer value in config request shall be non-0 processing time */
2081 /* timer value in config response shall be greater than received processing time */
2082 p_cfg->fcr.mon_tout = p_cfg->fcr.rtrans_tout = 0;
2084 if (p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE) {
2085 p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0;
2089 /* Set the threshold to send acks (may be updated in the cfg response) */
2090 p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2092 /* Include FCS option only if peer can handle it */
2093 if (p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_NO_CRC) {
2094 /* FCS check can be bypassed if peer also desires to bypass */
2095 if (p_cfg->fcs_present && p_cfg->fcs == L2CAP_CFG_FCS_BYPASS) {
2096 p_ccb->bypass_fcs |= L2CAP_CFG_FCS_OUR;
2099 p_cfg->fcs_present = FALSE;
2102 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
2105 p_ccb->our_cfg.fcr.mode = p_cfg->fcr.mode;
2106 p_ccb->our_cfg.fcr_present = p_cfg->fcr_present;
2108 /* Check the flush timeout. If it is lower than the current one used */
2109 /* then we need to adjust the flush timeout sent to the controller */
2110 if (p_cfg->flush_to_present) {
2111 if ((p_cfg->flush_to == 0) || (p_cfg->flush_to == L2CAP_NO_AUTOMATIC_FLUSH)) {
2112 /* don't send invalid flush timeout */
2113 /* SPEC: The sender of the Request shall specify its flush timeout value */
2114 /* if it differs from the default value of 0xFFFF */
2115 p_cfg->flush_to_present = FALSE;
2117 p_ccb->our_cfg.flush_to = p_cfg->flush_to;
2118 p_lcb = p_ccb->p_lcb;
2120 if (p_cfg->flush_to < p_lcb->link_flush_tout) {
2121 p_lcb->link_flush_tout = p_cfg->flush_to;
2123 /* If the timeout is within range of HCI, set the flush timeout */
2124 if (p_cfg->flush_to <= ((HCI_MAX_AUTO_FLUSH_TOUT * 5) / 8)) {
2125 /* Convert flush timeout to 0.625 ms units, with round */
2126 hci_flush_to = ((p_cfg->flush_to * 8) + 3) / 5;
2127 btsnd_hcic_write_auto_flush_tout (p_lcb->handle, hci_flush_to);
2135 /*******************************************************************************
2137 ** Function l2cu_process_our_cfg_rsp
2139 ** Description This function is called when we send the peer a "config response"
2140 ** message. It extracts the configuration of interest and saves
2145 *******************************************************************************/
2146 #if (CLASSIC_BT_INCLUDED == TRUE)
2147 void l2cu_process_our_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2149 /* If peer wants QoS, we are allowed to change the values in a positive response */
2150 if ( (p_cfg->qos_present) && (p_ccb->peer_cfg.qos_present) ) {
2151 p_ccb->peer_cfg.qos = p_cfg->qos;
2153 p_cfg->qos_present = FALSE;
2156 l2c_fcr_adj_our_rsp_options (p_ccb, p_cfg);
2158 #endif ///CLASSIC_BT_INCLUDED == TRUE
2161 /*******************************************************************************
2163 ** Function l2cu_device_reset
2165 ** Description This function is called when reset of the device is
2166 ** completed. For all active connection simulate HCI_DISC
2170 *******************************************************************************/
2171 void l2cu_device_reset (void)
2174 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
2176 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2177 if ((p_lcb->in_use) && (p_lcb->handle != HCI_INVALID_HANDLE)) {
2178 l2c_link_hci_disc_comp (p_lcb->handle, (UINT8) - 1);
2181 #if (BLE_INCLUDED == TRUE)
2182 l2cb.is_ble_connecting = FALSE;
2186 /*******************************************************************************
2188 ** Function l2cu_create_conn
2190 ** Description This function initiates an acl connection via HCI
2192 ** Returns TRUE if successful, FALSE if gki get buffer fails.
2194 *******************************************************************************/
2195 BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
2198 tL2C_LCB *p_lcb_cur = &l2cb.lcb_pool[0];
2199 #if BTM_SCO_INCLUDED == TRUE
2200 BOOLEAN is_sco_active;
2203 #if (BLE_INCLUDED == TRUE)
2204 tBT_DEVICE_TYPE dev_type;
2205 tBLE_ADDR_TYPE addr_type;
2208 BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
2210 if (transport == BT_TRANSPORT_LE) {
2211 if (!controller_get_interface()->supports_ble()) {
2215 p_lcb->ble_addr_type = addr_type;
2216 p_lcb->transport = BT_TRANSPORT_LE;
2218 return (l2cble_create_conn(p_lcb));
2222 /* If there is a connection where we perform as a slave, try to switch roles
2223 for this connection */
2224 for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb_cur++) {
2225 if (p_lcb_cur == p_lcb) {
2229 if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) {
2231 #if BTM_SCO_INCLUDED == TRUE
2232 /* The LMP_switch_req shall be sent only if the ACL logical transport
2233 is in active mode, when encryption is disabled, and all synchronous
2234 logical transports on the same physical link are disabled." */
2236 /* Check if there is any SCO Active on this BD Address */
2237 is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr);
2239 L2CAP_TRACE_API ("l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s", \
2240 (is_sco_active == TRUE) ? "TRUE" : "FALSE");
2242 if (is_sco_active == TRUE) {
2243 continue; /* No Master Slave switch not allowed when SCO Active */
2246 /*4_1_TODO check if btm_cb.devcb.local_features to be used instead */
2247 if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) {
2248 /* mark this lcb waiting for switch to be completed and
2249 start switch on the other one */
2250 p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
2251 p_lcb->link_role = HCI_ROLE_MASTER;
2253 if (BTM_SwitchRole (p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) == BTM_CMD_STARTED) {
2254 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_LINK_ROLE_SWITCH_TOUT);
2261 p_lcb->link_state = LST_CONNECTING;
2263 return (l2cu_create_conn_after_switch (p_lcb));
2266 /*******************************************************************************
2268 ** Function l2cu_get_num_hi_priority
2270 ** Description Gets the number of high priority channels.
2274 *******************************************************************************/
2275 UINT8 l2cu_get_num_hi_priority (void)
2279 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
2281 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2282 if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2290 /*******************************************************************************
2292 ** Function l2cu_create_conn_after_switch
2294 ** Description This function initiates an acl connection via HCI
2295 ** If switch required to create connection it is already done.
2297 ** Returns TRUE if successful, FALSE if gki get buffer fails.
2299 *******************************************************************************/
2301 BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb)
2303 UINT8 allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2304 tBTM_INQ_INFO *p_inq_info;
2305 UINT8 page_scan_rep_mode;
2306 UINT8 page_scan_mode;
2307 UINT16 clock_offset;
2309 UINT16 num_acl = BTM_GetNumAclLinks();
2310 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_lcb->remote_bd_addr);
2311 UINT8 no_hi_prio_chs = l2cu_get_num_hi_priority();
2313 p_features = BTM_ReadLocalFeatures();
2315 L2CAP_TRACE_DEBUG ("l2cu_create_conn_after_switch :%d num_acl:%d no_hi: %d is_bonding:%d",
2316 l2cb.disallow_switch, num_acl, no_hi_prio_chs, p_lcb->is_bonding);
2317 /* FW team says that we can participant in 4 piconets
2318 * typically 3 piconet + 1 for scanning.
2319 * We can enhance the code to count the number of piconets later. */
2320 if ( ((!l2cb.disallow_switch && (num_acl < 3)) || (p_lcb->is_bonding && (no_hi_prio_chs == 0)))
2321 && HCI_SWITCH_SUPPORTED(p_features)) {
2322 allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2324 allow_switch = HCI_CR_CONN_NOT_ALLOW_SWITCH;
2327 p_lcb->link_state = LST_CONNECTING;
2329 /* Check with the BT manager if details about remote device are known */
2330 if ((p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr)) != NULL) {
2331 page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
2332 page_scan_mode = p_inq_info->results.page_scan_mode;
2333 clock_offset = (UINT16)(p_inq_info->results.clock_offset);
2335 /* No info known. Use default settings */
2336 page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
2337 page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
2339 clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
2342 if (!btsnd_hcic_create_conn (p_lcb->remote_bd_addr,
2343 ( HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1
2344 | HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3
2345 | HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5 ),
2352 L2CAP_TRACE_ERROR ("L2CAP - no buffer for l2cu_create_conn");
2353 l2cu_release_lcb (p_lcb);
2357 btm_acl_update_busy_level (BTM_BLI_PAGE_EVT);
2359 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK,
2360 L2CAP_LINK_CONNECT_TOUT);
2366 /*******************************************************************************
2368 ** Function l2cu_find_lcb_by_state
2370 ** Description Look through all active LCBs for a match based on the
2373 ** Returns pointer to first matched LCB, or NULL if no match
2375 *******************************************************************************/
2376 tL2C_LCB *l2cu_find_lcb_by_state (tL2C_LINK_STATE state)
2379 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
2381 for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2382 if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
2387 /* If here, no match found */
2392 /*******************************************************************************
2394 ** Function l2cu_lcb_disconnecting
2396 ** Description On each active lcb, check if the lcb is in disconnecting
2397 ** state, or if there are no ccb's on the lcb (implying
2398 idle timeout is running), or if last ccb on the link
2399 is in disconnecting state.
2401 ** Returns TRUE if any of above conditions met, FALSE otherwise
2403 *******************************************************************************/
2404 BOOLEAN l2cu_lcb_disconnecting (void)
2409 BOOLEAN status = FALSE;
2411 p_lcb = &l2cb.lcb_pool[0];
2413 for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2414 if (p_lcb->in_use) {
2415 /* no ccbs on lcb, or lcb is in disconnecting state */
2416 if ((!p_lcb->ccb_queue.p_first_ccb) || (p_lcb->link_state == LST_DISCONNECTING)) {
2420 /* only one ccb left on lcb */
2421 else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) {
2422 p_ccb = p_lcb->ccb_queue.p_first_ccb;
2424 if ((p_ccb->in_use) &&
2425 ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
2426 (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
2437 /*******************************************************************************
2439 ** Function l2cu_set_acl_priority
2441 ** Description Sets the transmission priority for a channel.
2442 ** (For initial implementation only two values are valid.
2443 ** L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
2445 ** Returns TRUE if a valid channel, else FALSE
2447 *******************************************************************************/
2449 BOOLEAN l2cu_set_acl_priority (BD_ADDR bd_addr, UINT8 priority, BOOLEAN reset_after_rs)
2453 UINT8 command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2456 //APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority);
2458 /* Find the link control block for the acl channel */
2459 if ((p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR)) == NULL) {
2460 L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_SetAclPriority");
2464 if (BTM_IS_BRCM_CONTROLLER()) {
2465 /* Called from above L2CAP through API; send VSC if changed */
2466 if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||
2467 /* Called because of a master/slave role switch; if high resend VSC */
2468 ( reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2471 vs_param = (priority == L2CAP_PRIORITY_HIGH) ? HCI_BRCM_ACL_PRIORITY_HIGH : HCI_BRCM_ACL_PRIORITY_LOW;
2473 UINT16_TO_STREAM (pp, p_lcb->handle);
2474 UINT8_TO_STREAM (pp, vs_param);
2476 BTM_VendorSpecificCommand (HCI_BRCM_SET_ACL_PRIORITY, HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command, NULL);
2478 /* Adjust lmp buffer allocation for this channel if priority changed */
2479 if (p_lcb->acl_priority != priority) {
2480 p_lcb->acl_priority = priority;
2481 l2c_link_adjust_allocation();
2488 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
2489 /******************************************************************************
2491 ** Function l2cu_set_non_flushable_pbf
2493 ** Description set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts
2497 *******************************************************************************/
2498 void l2cu_set_non_flushable_pbf (BOOLEAN is_supported)
2501 l2cb.non_flushable_pbf = (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT);
2503 l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT);
2508 /*******************************************************************************
2510 ** Function l2cu_resubmit_pending_sec_req
2512 ** Description This function is called when required security procedures
2513 ** are completed and any pending requests can be re-submitted.
2517 *******************************************************************************/
2518 #if (CLASSIC_BT_INCLUDED == TRUE)
2519 void l2cu_resubmit_pending_sec_req (BD_ADDR p_bda)
2523 tL2C_CCB *p_next_ccb;
2525 L2CAP_TRACE_DEBUG ("l2cu_resubmit_pending_sec_req p_bda: %p", p_bda);
2527 /* If we are called with a BDA, only resubmit for that BDA */
2529 p_lcb = l2cu_find_lcb_by_bd_addr (p_bda, BT_TRANSPORT_BR_EDR);
2530 /* If we don't have one, this is an error */
2532 /* For all channels, send the event through their FSMs */
2533 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2534 p_next_ccb = p_ccb->p_next_ccb;
2535 l2c_csm_execute (p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2538 L2CAP_TRACE_WARNING ("l2cu_resubmit_pending_sec_req - unknown BD_ADDR");
2541 /* No BDA pasesed in, so check all links */
2542 for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2543 if (p_lcb->in_use) {
2544 /* For all channels, send the event through their FSMs */
2545 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2546 p_next_ccb = p_ccb->p_next_ccb;
2547 l2c_csm_execute (p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2553 #endif ///CLASSIC_BT_INCLUDED == TRUE
2555 #if L2CAP_CONFORMANCE_TESTING == TRUE
2556 /*******************************************************************************
2558 ** Function l2cu_set_info_rsp_mask
2560 ** Description This function allows the script wrapper to change the
2561 ** info resp mask for conformance testing.
2563 ** Returns pointer to CCB, or NULL if none
2565 *******************************************************************************/
2566 void l2cu_set_info_rsp_mask (UINT32 mask)
2568 l2cb.test_info_resp = mask;
2570 #endif /* L2CAP_CONFORMANCE_TESTING */
2572 /*******************************************************************************
2574 ** Function l2cu_adjust_out_mps
2576 ** Description Sets our MPS based on current controller capabilities
2580 *******************************************************************************/
2581 void l2cu_adjust_out_mps (tL2C_CCB *p_ccb)
2585 /* on the tx side MTU is selected based on packet size of the controller */
2586 packet_size = btm_get_max_packet_size (p_ccb->p_lcb->remote_bd_addr);
2588 if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) {
2589 /* something is very wrong */
2590 L2CAP_TRACE_ERROR ("l2cu_adjust_out_mps bad packet size: %u will use MPS: %u", packet_size, p_ccb->peer_cfg.fcr.mps);
2591 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2593 packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN);
2595 /* We try to negotiate MTU that each packet can be split into whole
2596 number of max packets. For example if link is 1.2 max packet size is 339 bytes.
2597 At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4 overhead.
2598 1695, that will be 5 Dh5 packets. Now maximum L2CAP packet is
2599 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.
2601 For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1 3DH5 packet
2602 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. */
2603 if (p_ccb->peer_cfg.fcr.mps >= packet_size) {
2604 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size;
2606 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2609 L2CAP_TRACE_DEBUG ("l2cu_adjust_out_mps use %d Based on peer_cfg.fcr.mps: %u packet_size: %u",
2610 p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size);
2615 /*******************************************************************************
2617 ** Function l2cu_initialize_fixed_ccb
2619 ** Description Initialize a fixed channel's CCB
2621 ** Returns TRUE or FALSE
2623 *******************************************************************************/
2624 BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 fixed_cid, tL2CAP_FCR_OPTS *p_fcr)
2626 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2628 /* If we already have a CCB, then simply return */
2629 if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] != NULL) {
2633 if ((p_ccb = l2cu_allocate_ccb (NULL, 0)) == NULL) {
2637 btu_stop_timer(&p_lcb->timer_entry);
2639 /* Set CID for the connection */
2640 p_ccb->local_cid = fixed_cid;
2641 p_ccb->remote_cid = fixed_cid;
2643 p_ccb->is_flushable = FALSE;
2645 p_ccb->timer_entry.param = (TIMER_PARAM_TYPE)p_ccb;
2649 /* Set the FCR parameters. For now, we will use default pools */
2650 p_ccb->our_cfg.fcr = p_ccb->peer_cfg.fcr = *p_fcr;
2652 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
2653 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
2654 p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
2655 p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
2657 p_ccb->fcrb.max_held_acks = p_fcr->tx_win_sz / 3;
2660 /* Link ccb to lcb and lcb to ccb */
2661 p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb;
2662 p_ccb->p_lcb = p_lcb;
2664 /* There is no configuration, so if the link is up, the channel is up */
2665 if (p_lcb->link_state == LST_CONNECTED) {
2666 p_ccb->chnl_state = CST_OPEN;
2669 /* Set the default idle timeout value to use */
2670 p_ccb->fixed_chnl_idle_tout = l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout;
2675 /*******************************************************************************
2677 ** Function l2cu_no_dynamic_ccbs
2679 ** Description Handles the case when there are no more dynamic CCBs. If there
2680 ** are any fixed CCBs, start the longest of the fixed CCB timeouts,
2681 ** otherwise start the default link idle timeout or disconnect.
2685 *******************************************************************************/
2686 void l2cu_no_dynamic_ccbs (tL2C_LCB *p_lcb)
2688 #if (SMP_INCLUDED == TRUE)
2690 #endif ///SMP_INCLUDED == TRUE
2691 UINT16 timeout = p_lcb->idle_timeout;
2693 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2696 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2697 if ( (p_lcb->p_fixed_ccbs[xx] != NULL) && (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout > timeout) ) {
2698 timeout = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout;
2703 /* If the link is pairing, do not mess with the timeouts */
2704 if (p_lcb->is_bonding) {
2709 L2CAP_TRACE_DEBUG ("l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link");
2710 #if (SMP_INCLUDED == TRUE)
2711 rc = btm_sec_disconnect (p_lcb->handle, HCI_ERR_PEER_USER);
2712 if (rc == BTM_CMD_STARTED) {
2713 l2cu_process_fixed_disc_cback(p_lcb);
2714 p_lcb->link_state = LST_DISCONNECTING;
2715 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2716 } else if (rc == BTM_SUCCESS) {
2717 l2cu_process_fixed_disc_cback(p_lcb);
2718 /* BTM SEC will make sure that link is release (probably after pairing is done) */
2719 p_lcb->link_state = LST_DISCONNECTING;
2721 } else if ( (p_lcb->is_bonding)
2722 && (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) ) {
2723 l2cu_process_fixed_disc_cback(p_lcb);
2724 p_lcb->link_state = LST_DISCONNECTING;
2725 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2727 /* probably no buffer to send disconnect */
2728 timeout = BT_1SEC_TIMEOUT;
2731 if (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) {
2732 l2cu_process_fixed_disc_cback(p_lcb);
2733 p_lcb->link_state = LST_DISCONNECTING;
2734 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2736 timeout = BT_1SEC_TIMEOUT;
2738 #endif ///SMP_INCLUDED == TRUE
2742 if (timeout != 0xFFFF) {
2743 L2CAP_TRACE_DEBUG ("l2cu_no_dynamic_ccbs() starting IDLE timeout: %d", timeout);
2744 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, timeout);
2746 btu_stop_timer(&p_lcb->timer_entry);
2750 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2751 /*******************************************************************************
2753 ** Function l2cu_process_fixed_chnl_resp
2755 ** Description handle a fixed channel response (or lack thereof)
2756 ** if the link failed, or a fixed channel response was
2757 ** not received, the bitfield is all zeros.
2759 *******************************************************************************/
2760 void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb)
2762 L2CAP_TRACE_DEBUG("%s",__func__);
2763 #if (BLE_INCLUDED == TRUE)
2764 if (p_lcb->transport == BT_TRANSPORT_BR_EDR) {
2765 /* ignore all not assigned BR/EDR channels */
2766 p_lcb->peer_chnl_mask[0] &= (L2CAP_FIXED_CHNL_SIG_BIT | \
2767 L2CAP_FIXED_CHNL_CNCTLESS_BIT | \
2768 L2CAP_FIXED_CHNL_SMP_BR_BIT);
2770 p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
2774 /* Tell all registered fixed channels about the connection */
2775 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2776 #if BLE_INCLUDED == TRUE
2777 /* skip sending LE fix channel callbacks on BR/EDR links */
2778 if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
2779 xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID &&
2780 xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID) {
2784 if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
2785 if (p_lcb->peer_chnl_mask[(xx + L2CAP_FIRST_FIXED_CHNL) / 8]
2786 & (1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8))) {
2787 if (p_lcb->p_fixed_ccbs[xx]) {
2788 p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
2790 #if BLE_INCLUDED == TRUE
2791 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2792 p_lcb->remote_bd_addr, TRUE, 0, p_lcb->transport);
2794 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2795 p_lcb->remote_bd_addr, TRUE, 0, BT_TRANSPORT_BR_EDR);
2798 #if BLE_INCLUDED == TRUE
2799 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2800 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2802 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2803 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2806 if (p_lcb->p_fixed_ccbs[xx]) {
2807 l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
2808 p_lcb->p_fixed_ccbs[xx] = NULL;
2817 /*******************************************************************************
2819 ** Function l2cu_process_fixed_disc_cback
2821 ** Description send l2cap fixed channel disconnection callback to application
2826 *******************************************************************************/
2827 void l2cu_process_fixed_disc_cback (tL2C_LCB *p_lcb)
2829 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2831 /* Select peer channels mask to use depending on transport */
2832 UINT8 peer_channel_mask = p_lcb->peer_chnl_mask[0];
2834 // For LE, reset the stored peer channel mask
2835 if (p_lcb->transport == BT_TRANSPORT_LE) {
2836 p_lcb->peer_chnl_mask[0] = 0;
2839 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2840 if (p_lcb->p_fixed_ccbs[xx]) {
2841 if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) {
2842 tL2C_CCB *p_l2c_chnl_ctrl_block;
2843 p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
2844 p_lcb->p_fixed_ccbs[xx] = NULL;
2845 l2cu_release_ccb(p_l2c_chnl_ctrl_block);
2846 #if BLE_INCLUDED == TRUE
2847 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2848 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2850 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2851 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2854 } else if ( (peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
2855 && (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) )
2856 #if BLE_INCLUDED == TRUE
2857 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2858 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2860 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2861 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2867 #if (BLE_INCLUDED == TRUE)
2868 /*******************************************************************************
2870 ** Function l2cu_send_peer_ble_par_req
2872 ** Description Build and send a BLE parameter update request message
2877 *******************************************************************************/
2878 void l2cu_send_peer_ble_par_req (tL2C_LCB *p_lcb, UINT16 min_int, UINT16 max_int,
2879 UINT16 latency, UINT16 timeout)
2884 /* Create an identifier for this packet */
2886 l2cu_adj_id (p_lcb, L2CAP_ADJ_ID);
2888 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN,
2889 L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->id)) == NULL ) {
2890 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_par_req - no buffer");
2894 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2895 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2897 UINT16_TO_STREAM (p, min_int);
2898 UINT16_TO_STREAM (p, max_int);
2899 UINT16_TO_STREAM (p, latency);
2900 UINT16_TO_STREAM (p, timeout);
2902 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2905 /*******************************************************************************
2907 ** Function l2cu_send_peer_ble_par_rsp
2909 ** Description Build and send a BLE parameter update response message
2914 *******************************************************************************/
2915 void l2cu_send_peer_ble_par_rsp (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id)
2920 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN,
2921 L2CAP_CMD_BLE_UPDATE_RSP, rem_id)) == NULL ) {
2922 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_par_rsp - no buffer");
2926 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2927 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2929 UINT16_TO_STREAM (p, reason);
2931 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2934 /*******************************************************************************
2936 ** Function l2cu_send_peer_ble_credit_based_conn_req
2938 ** Description Build and send a BLE packet to establish LE connection oriented
2943 *******************************************************************************/
2944 void l2cu_send_peer_ble_credit_based_conn_req (tL2C_CCB *p_ccb)
2948 tL2C_LCB *p_lcb = NULL;
2951 UINT16 initial_credit;
2955 p_lcb = p_ccb->p_lcb;
2957 /* Create an identifier for this packet */
2959 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
2961 p_ccb->local_id = p_ccb->p_lcb->id;
2963 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
2964 L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id)) == NULL )
2966 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2970 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2971 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2973 mtu = p_ccb->local_conn_cfg.mtu;
2974 mps = p_ccb->local_conn_cfg.mps;
2975 initial_credit = p_ccb->local_conn_cfg.credits;
2977 L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
2978 mtu:%d mps:%d initial_credit:%d", p_ccb->p_rcb->real_psm,\
2979 p_ccb->local_cid, mtu, mps, initial_credit);
2981 UINT16_TO_STREAM (p, p_ccb->p_rcb->real_psm);
2982 UINT16_TO_STREAM (p, p_ccb->local_cid);
2983 UINT16_TO_STREAM (p, mtu);
2984 UINT16_TO_STREAM (p, mps);
2985 UINT16_TO_STREAM (p, initial_credit);
2987 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2990 /*******************************************************************************
2992 ** Function l2cu_reject_ble_connection
2994 ** Description Build and send an L2CAP "Credit based connection res" message
2995 ** to the peer. This function is called for non-success cases.
2999 *******************************************************************************/
3000 void l2cu_reject_ble_connection (tL2C_LCB *p_lcb, UINT8 rem_id, UINT16 result)
3005 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3006 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id)) == NULL )
3008 L2CAP_TRACE_WARNING ("l2cu_reject_ble_connection - no buffer");
3012 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3013 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3015 UINT16_TO_STREAM (p, 0); /* Local CID of 0 */
3016 UINT16_TO_STREAM (p, 0); /* MTU */
3017 UINT16_TO_STREAM (p, 0); /* MPS */
3018 UINT16_TO_STREAM (p, 0); /* initial credit */
3019 UINT16_TO_STREAM (p, result);
3021 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3024 /*******************************************************************************
3026 ** Function l2cu_send_peer_ble_credit_based_conn_res
3028 ** Description Build and send an L2CAP "Credit based connection res" message
3029 ** to the peer. This function is called in case of success.
3033 *******************************************************************************/
3034 void l2cu_send_peer_ble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
3039 L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_res");
3040 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3041 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id)) == NULL )
3043 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
3047 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3048 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3050 UINT16_TO_STREAM (p, p_ccb->local_cid); /* Local CID */
3051 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mtu); /* MTU */
3052 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mps); /* MPS */
3053 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.credits); /* initial credit */
3054 UINT16_TO_STREAM (p, result);
3056 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
3059 /*******************************************************************************
3061 ** Function l2cu_send_peer_ble_flow_control_credit
3063 ** Description Build and send a BLE packet to give credits to peer device
3064 ** for LE connection oriented L2CAP channel.
3068 *******************************************************************************/
3069 void l2cu_send_peer_ble_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
3073 tL2C_LCB *p_lcb = NULL;
3077 p_lcb = p_ccb->p_lcb;
3079 /* Create an identifier for this packet */
3081 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3083 p_ccb->local_id = p_ccb->p_lcb->id;
3085 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
3086 L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id)) == NULL )
3088 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
3092 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3093 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3095 UINT16_TO_STREAM (p, p_ccb->local_cid);
3096 UINT16_TO_STREAM (p, credit_value);
3098 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3101 /*******************************************************************************
3103 ** Function l2cu_send_peer_ble_credit_based_conn_req
3105 ** Description Build and send a BLE packet to disconnect LE connection oriented
3110 *******************************************************************************/
3111 void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb)
3115 tL2C_LCB *p_lcb = NULL;
3116 L2CAP_TRACE_DEBUG ("%s",__func__);
3120 p_lcb = p_ccb->p_lcb;
3122 /* Create an identifier for this packet */
3124 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3126 p_ccb->local_id = p_ccb->p_lcb->id;
3127 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_DISC_REQ_LEN,
3128 L2CAP_CMD_DISC_REQ, p_lcb->id)) == NULL )
3130 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
3134 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3135 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3137 UINT16_TO_STREAM (p, p_ccb->remote_cid);
3138 UINT16_TO_STREAM (p,p_ccb->local_cid);
3140 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3143 #endif /* BLE_INCLUDED == TRUE */
3146 /*******************************************************************************
3147 ** Functions used by both Full and Light Stack
3148 ********************************************************************************/
3150 /*******************************************************************************
3152 ** Function l2cu_find_lcb_by_handle
3154 ** Description Look through all active LCBs for a match based on the
3157 ** Returns pointer to matched LCB, or NULL if no match
3159 *******************************************************************************/
3160 tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle)
3163 tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
3165 for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
3166 if ((p_lcb->in_use) && (p_lcb->handle == handle)) {
3171 /* If here, no match found */
3175 /*******************************************************************************
3177 ** Function l2cu_find_ccb_by_cid
3179 ** Description Look through all active CCBs on a link for a match based
3180 ** on the local CID. If passed the link pointer is NULL, all
3181 ** active links are searched.
3183 ** Returns pointer to matched CCB, or NULL if no match
3185 *******************************************************************************/
3186 tL2C_CCB *l2cu_find_ccb_by_cid (tL2C_LCB *p_lcb, UINT16 local_cid)
3188 tL2C_CCB *p_ccb = NULL;
3189 #if (L2CAP_UCD_INCLUDED == TRUE)
3193 if (local_cid >= L2CAP_BASE_APPL_CID) {
3194 /* find the associated CCB by "index" */
3195 local_cid -= L2CAP_BASE_APPL_CID;
3197 if (local_cid >= MAX_L2CAP_CHANNELS) {
3201 p_ccb = l2cb.ccb_pool + local_cid;
3203 /* make sure the CCB is in use */
3204 if (!p_ccb->in_use) {
3207 /* make sure it's for the same LCB */
3208 else if (p_lcb && p_lcb != p_ccb->p_lcb) {
3212 #if (L2CAP_UCD_INCLUDED == TRUE)
3214 /* searching fixed channel */
3215 p_ccb = l2cb.ccb_pool;
3216 for ( xx = 0; xx < MAX_L2CAP_CHANNELS; xx++ ) {
3217 if ((p_ccb->local_cid == local_cid)
3219 && (p_lcb == p_ccb->p_lcb)) {
3225 if ( xx >= MAX_L2CAP_CHANNELS ) {
3234 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE && CLASSIC_BT_INCLUDED == TRUE)
3236 /******************************************************************************
3238 ** Function l2cu_get_next_channel_in_rr
3240 ** Description get the next channel to send on a link. It also adjusts the
3241 ** CCB queue to do a basic priority and round-robin scheduling.
3243 ** Returns pointer to CCB or NULL
3245 *******************************************************************************/
3246 static tL2C_CCB *l2cu_get_next_channel_in_rr(tL2C_LCB *p_lcb)
3248 tL2C_CCB *p_serve_ccb = NULL;
3253 /* scan all of priority until finding a channel to serve */
3254 for ( i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++ ) {
3255 /* scan all channel within serving priority group until finding a channel to serve */
3256 for ( j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb); j++) {
3257 /* scaning from next serving channel */
3258 p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb;
3261 L2CAP_TRACE_ERROR("p_serve_ccb is NULL, rr_pri=%d", p_lcb->rr_pri);
3265 L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d",
3266 p_ccb->ccb_priority, p_ccb->local_cid,
3267 fixed_queue_length(p_ccb->xmit_hold_q));
3269 /* store the next serving channel */
3270 /* this channel is the last channel of its priority group */
3271 if (( p_ccb->p_next_ccb == NULL )
3272 || ( p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority )) {
3273 /* next serving channel is set to the first channel in the group */
3274 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_first_ccb;
3276 /* next serving channel is set to the next channel in the group */
3277 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_ccb->p_next_ccb;
3280 if (p_ccb->chnl_state != CST_OPEN) {
3284 /* eL2CAP option in use */
3285 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3286 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3290 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3291 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3296 #if (CLASSIC_BT_INCLUDED == TRUE)
3297 /* If in eRTM mode, check for window closure */
3298 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3301 #endif ///CLASSIC_BT_INCLUDED == TRUE
3304 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3309 /* found a channel to serve */
3310 p_serve_ccb = p_ccb;
3311 /* decrease quota of its priority group */
3312 p_lcb->rr_serv[p_lcb->rr_pri].quota--;
3315 /* if there is no more quota of the priority group or no channel to have data to send */
3316 if ((p_lcb->rr_serv[p_lcb->rr_pri].quota == 0) || (!p_serve_ccb)) {
3317 /* serve next priority group */
3318 p_lcb->rr_pri = (p_lcb->rr_pri + 1) % L2CAP_NUM_CHNL_PRIORITY;
3319 /* initialize its quota */
3320 p_lcb->rr_serv[p_lcb->rr_pri].quota = L2CAP_GET_PRIORITY_QUOTA(p_lcb->rr_pri);
3325 L2CAP_TRACE_DEBUG("RR service pri=%d, quota=%d, lcid=0x%04x",
3326 p_serve_ccb->ccb_priority,
3327 p_lcb->rr_serv[p_serve_ccb->ccb_priority].quota,
3328 p_serve_ccb->local_cid );
3334 #else /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3336 /******************************************************************************
3338 ** Function l2cu_get_next_channel
3340 ** Description get the next channel to send on a link bassed on priority
3343 ** Returns pointer to CCB or NULL
3345 *******************************************************************************/
3346 #if (CLASSIC_BT_INCLUDED == TRUE)
3347 static tL2C_CCB *l2cu_get_next_channel(tL2C_LCB *p_lcb)
3351 /* Get the first CCB with data to send.
3353 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
3354 if (p_ccb->chnl_state != CST_OPEN) {
3358 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3362 if (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q))
3366 if (fixed_queue_is_empty(p_ccb->xmit_hold_q))
3370 /* If in eRTM mode, check for window closure */
3371 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3375 /* If here, we found someone */
3381 #endif ///CLASSIC_BT_INCLUDED == TRUE
3383 #endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3385 /******************************************************************************
3387 ** Function l2cu_get_next_buffer_to_send
3389 ** Description get the next buffer to send on a link. It also adjusts the
3390 ** CCB queue to do a basic priority and round-robin scheduling.
3392 ** Returns pointer to buffer or NULL
3394 *******************************************************************************/
3395 BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
3398 BT_HDR *p_buf = NULL;
3400 /* Highest priority are fixed channels */
3401 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3404 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3405 if ((p_ccb = p_lcb->p_fixed_ccbs[xx]) == NULL) {
3409 /* eL2CAP option in use */
3410 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3411 #if (CLASSIC_BT_INCLUDED == TRUE)
3412 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3416 /* No more checks needed if sending from the reatransmit queue */
3417 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q))
3419 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3422 /* If in eRTM mode, check for window closure */
3423 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3427 if ((p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0)) != NULL) {
3428 l2cu_check_channel_congestion (p_ccb);
3429 l2cu_set_acl_hci_header (p_buf, p_ccb);
3434 #endif ///CLASSIC_BT_INCLUDED == TRUE
3437 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3438 p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3439 if (NULL == p_buf) {
3440 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
3443 /* send tx complete */
3444 if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb) {
3445 (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
3448 l2cu_check_channel_congestion (p_ccb);
3449 l2cu_set_acl_hci_header (p_buf, p_ccb);
3455 #if (CLASSIC_BT_INCLUDED == TRUE)
3456 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
3457 /* get next serving channel in round-robin */
3458 p_ccb = l2cu_get_next_channel_in_rr( p_lcb );
3460 p_ccb = l2cu_get_next_channel( p_lcb );
3463 /* Return if no buffer */
3464 if (p_ccb == NULL) {
3468 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3470 if ((p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0)) == NULL) {
3475 p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3476 if (NULL == p_buf) {
3477 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
3482 if ( p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb && (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE) ) {
3483 (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);
3487 l2cu_check_channel_congestion (p_ccb);
3489 l2cu_set_acl_hci_header (p_buf, p_ccb);
3490 #endif ///CLASSIC_BT_INCLUDED == TRUE
3495 /******************************************************************************
3497 ** Function l2cu_set_acl_hci_header
3499 ** Description Set HCI handle for ACL packet
3503 *******************************************************************************/
3504 void l2cu_set_acl_hci_header (BT_HDR *p_buf, tL2C_CCB *p_ccb)
3508 /* Set the pointer to the beginning of the data minus 4 bytes for the packet header */
3509 p = (UINT8 *)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE;
3511 #if (BLE_INCLUDED == TRUE)
3512 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3513 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT));
3515 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_ble();
3516 /* The HCI transport will segment the buffers. */
3517 if (p_buf->len > acl_data_size) {
3518 UINT16_TO_STREAM (p, acl_data_size);
3520 UINT16_TO_STREAM (p, p_buf->len);
3522 } /* (BLE_INCLUDED == TRUE) */
3526 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
3527 if ( (((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == L2CAP_FLUSHABLE_CH_BASED) && (p_ccb->is_flushable))
3528 || ((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == L2CAP_FLUSHABLE_PKT) ) {
3529 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3531 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | l2cb.non_flushable_pbf);
3534 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3537 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
3538 /* The HCI transport will segment the buffers. */
3539 if (p_buf->len > acl_data_size) {
3540 UINT16_TO_STREAM (p, acl_data_size);
3542 UINT16_TO_STREAM (p, p_buf->len);
3545 p_buf->offset -= HCI_DATA_PREAMBLE_SIZE;
3546 p_buf->len += HCI_DATA_PREAMBLE_SIZE;
3549 /******************************************************************************
3551 ** Function l2cu_check_channel_congestion
3553 ** Description check if any change in congestion status
3557 *******************************************************************************/
3558 void l2cu_check_channel_congestion (tL2C_CCB *p_ccb)
3560 size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
3562 #if (L2CAP_UCD_INCLUDED == TRUE)
3563 if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3564 q_count += fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q);
3567 /* If the CCB queue limit is subject to a quota, check for congestion */
3568 /* if this channel has outgoing traffic */
3569 if (p_ccb->buff_quota != 0) {
3570 /* If this channel was congested */
3571 if ( p_ccb->cong_sent ) {
3572 /* If the channel is not congested now, tell the app */
3573 if (q_count <= (p_ccb->buff_quota / 2)) {
3574 p_ccb->cong_sent = FALSE;
3575 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3576 L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (FALSE), CID: 0x%04x xmit_hold_q.count: %u buff_quota: %u",
3577 p_ccb->local_cid, q_count, p_ccb->buff_quota);
3579 /* Prevent recursive calling */
3580 l2cb.is_cong_cback_context = TRUE;
3581 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, FALSE);
3582 l2cb.is_cong_cback_context = FALSE;
3584 #if (L2CAP_UCD_INCLUDED == TRUE)
3585 else if ( p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3586 if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
3587 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCD CongestionStatus_Cb (FALSE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
3588 fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3589 fixed_queue_length(p_ccb->xmit_hold_q),
3591 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, FALSE );
3595 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3598 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx ++) {
3599 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3600 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) {
3601 (* l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr, FALSE);
3610 /* If this channel was not congested but it is congested now, tell the app */
3611 if (q_count > p_ccb->buff_quota) {
3612 p_ccb->cong_sent = TRUE;
3613 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3614 L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (TRUE),CID:0x%04x,XmitQ:%u,Quota:%u",
3615 p_ccb->local_cid, q_count, p_ccb->buff_quota);
3617 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, TRUE);
3619 #if (L2CAP_UCD_INCLUDED == TRUE)
3620 else if ( p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3621 if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
3622 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCD CongestionStatus_Cb (TRUE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
3623 fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3624 fixed_queue_length(p_ccb->xmit_hold_q),
3626 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, TRUE );
3630 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3633 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx ++) {
3634 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3635 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) {
3636 (* l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr, TRUE);