#include <string.h>
#include <stdio.h>
+#include "device/include/controller.h"
+#include "btcore/include/counter.h"
#include "gki.h"
#include "bt_types.h"
#include "hcimsgs.h"
#include "btm_api.h"
#include "btm_int.h"
#include "hcidefs.h"
-#include "bd.h"
#include "bt_utils.h"
+#include "osi/include/allocator.h"
/*******************************************************************************
**
l2cb.num_links_active++;
l2c_link_adjust_allocation();
}
+ p_lcb->link_xmit_data_q = list_new(NULL);
return (p_lcb);
}
}
}
#if (BLE_INCLUDED == TRUE)
- l2cb.is_ble_connecting = FALSE;
+ // Reset BLE connecting flag only if the address matches
+ if (!memcmp(l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN))
+ l2cb.is_ble_connecting = FALSE;
#endif
#if (L2CAP_NUM_FIXED_CHNLS > 0)
- {
- int xx;
-
- for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
- {
- if (p_lcb->p_fixed_ccbs[xx])
- {
- l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
- p_lcb->p_fixed_ccbs[xx] = NULL;
- (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
- }
- else if ( (p_lcb->peer_chnl_mask[0] & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
- && (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) )
- (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
- }
- }
+ l2cu_process_fixed_disc_cback(p_lcb);
#endif
/* Ensure no CCBs left on this LCB */
#else
btm_acl_removed (p_lcb->remote_bd_addr, BT_TRANSPORT_BR_EDR);
#endif
+
/* Release any held buffers */
- while (p_lcb->link_xmit_data_q.p_first)
- GKI_freebuf (GKI_dequeue (&p_lcb->link_xmit_data_q));
+ if (p_lcb->link_xmit_data_q)
+ {
+ while (!list_is_empty(p_lcb->link_xmit_data_q)) {
+ BT_HDR *p_buf = list_front(p_lcb->link_xmit_data_q);
+ list_remove(p_lcb->link_xmit_data_q, p_buf);
+ GKI_freebuf(p_buf);
+ }
+ list_free(p_lcb->link_xmit_data_q);
+ p_lcb->link_xmit_data_q = NULL;
+ }
#if (L2CAP_UCD_INCLUDED == TRUE)
/* clean up any security pending UCD */
*******************************************************************************/
UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb)
{
- UINT8 i;
- for (i = 0; i < BTM_ROLE_DEVICE_NUM; i++) {
- if ((btm_cb.previous_connected_role[i] != BTM_ROLE_UNDEFINED) &&
- (!bdcmp(p_this_lcb->remote_bd_addr, btm_cb.previous_connected_remote_addr[i]))) {
- L2CAP_TRACE_WARNING ("l2cu_get_conn_role %d",
- btm_cb.previous_connected_role[i]);
- return btm_cb.previous_connected_role[i];
- }
- }
return l2cb.desire_role;
}
#if (BLE_INCLUDED == TRUE)
if (p_lcb->transport == BT_TRANSPORT_LE)
{
+ counter_add("l2cap.ble.tx.bytes", p_buf->len);
+ counter_add("l2cap.ble.tx.pkts", 1);
+
UINT16_TO_STREAM (p, L2CAP_BLE_SIGNALLING_CID);
}
else
#endif
{
+ counter_add("l2cap.sig.tx.bytes", p_buf->len);
+ counter_add("l2cap.sig.tx.pkts", 1);
UINT16_TO_STREAM (p, L2CAP_SIGNALLING_CID);
}
*/
if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE)
{
- while (p_ccb->xmit_hold_q.p_first)
+ while (GKI_getfirst(&p_ccb->xmit_hold_q))
{
p_buf2 = (BT_HDR *)GKI_dequeue (&p_ccb->xmit_hold_q);
l2cu_set_acl_hci_header (p_buf2, p_ccb);
return;
}
+ uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
+ uint16_t acl_packet_size = controller_get_interface()->get_acl_packet_size_classic();
/* Don't return data if it does not fit in ACL and L2CAP MTU */
- maxlen = (GKI_get_pool_bufsize(L2CAP_CMD_POOL_ID) > btu_cb.hcit_acl_pkt_size) ?
- btu_cb.hcit_acl_data_size : (UINT16)GKI_get_pool_bufsize(L2CAP_CMD_POOL_ID);
+ maxlen = (GKI_get_pool_bufsize(L2CAP_CMD_POOL_ID) > acl_packet_size) ?
+ acl_data_size : (UINT16)GKI_get_pool_bufsize(L2CAP_CMD_POOL_ID);
maxlen -= (UINT16)(BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
L2CAP_CMD_OVERHEAD + L2CAP_ECHO_RSP_LEN);
p_ccb->p_lcb = p_lcb;
p_ccb->p_rcb = NULL;
+ p_ccb->should_free_rcb = false;
/* Set priority then insert ccb into LCB queue (if we have an LCB) */
p_ccb->ccb_priority = L2CAP_CHNL_PRIORITY_LOW;
btm_sec_clr_service_by_psm(p_rcb->psm);
}
+ if (p_ccb->should_free_rcb)
+ {
+ osi_free(p_rcb);
+ p_ccb->p_rcb = NULL;
+ p_ccb->should_free_rcb = false;
+ }
+
btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
/* Stop the timer */
btu_stop_timer (&p_ccb->timer_entry);
- while (p_ccb->xmit_hold_q.p_first)
+ while (!GKI_queue_is_empty(&p_ccb->xmit_hold_q))
GKI_freebuf (GKI_dequeue (&p_ccb->xmit_hold_q));
l2c_fcr_cleanup (p_ccb);
#endif
}
-#if (TCS_WUG_MEMBER_INCLUDED == TRUE && TCS_INCLUDED == TRUE)
-extern UINT16 tcs_wug_get_clk_offset( BD_ADDR addr ) ;
-#endif
-
/*******************************************************************************
**
** Function l2cu_create_conn
if (transport == BT_TRANSPORT_LE)
{
- if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+ if (!controller_get_interface()->supports_ble())
return FALSE;
p_lcb->ble_addr_type = addr_type;
p_lcb->link_state = LST_CONNECTING;
-
-#if (TCS_WUG_MEMBER_INCLUDED == TRUE && TCS_INCLUDED == TRUE)
- if ( (clock_offset = tcs_wug_get_clk_offset( p_lcb->remote_bd_addr )) != 0 )
+ /* Check with the BT manager if details about remote device are known */
+ if ((p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr)) != NULL)
{
- page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R0;
- page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
+ page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
+ page_scan_mode = p_inq_info->results.page_scan_mode;
+ clock_offset = (UINT16)(p_inq_info->results.clock_offset);
}
else
{
-#endif
-
- /* Check with the BT manager if details about remote device are known */
- if ((p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr)) != NULL)
- {
- page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
- page_scan_mode = p_inq_info->results.page_scan_mode;
- clock_offset = (UINT16)(p_inq_info->results.clock_offset);
- }
- else
- {
- /* No info known. Use default settings */
- page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
- page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
+ /* No info known. Use default settings */
+ page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
+ page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
- clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
- }
-#if (TCS_WUG_MEMBER_INCLUDED == TRUE && TCS_INCLUDED == TRUE)
+ clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
}
-#endif
if (!btsnd_hcic_create_conn (p_lcb->remote_bd_addr,
( HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1
return (FALSE);
}
-#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
btm_acl_update_busy_level (BTM_BLI_PAGE_EVT);
-#endif
btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK,
L2CAP_LINK_CONNECT_TOUT);
*******************************************************************************/
void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb)
{
- int xx;
#if (BLE_INCLUDED == TRUE)
/* always exclude LE fixed channel on BR/EDR fix channel capability */
if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
p_lcb->peer_chnl_mask[0] &= ~(L2CAP_FIXED_CHNL_ATT_BIT| \
L2CAP_FIXED_CHNL_BLE_SIG_BIT| \
L2CAP_FIXED_CHNL_SMP_BIT);
+ else
+ p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
#endif
/* Tell all registered fixed channels about the connection */
- for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
+ for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
{
#if BLE_INCLUDED == TRUE
/* skip sending LE fix channel callbacks on BR/EDR links */
void l2cu_process_fixed_disc_cback (tL2C_LCB *p_lcb)
{
#if (L2CAP_NUM_FIXED_CHNLS > 0)
- int xx;
- for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
+ /* Select peer channels mask to use depending on transport */
+ UINT8 peer_channel_mask = p_lcb->peer_chnl_mask[0];
+
+ // For LE, reset the stored peer channel mask
+ if (p_lcb->transport == BT_TRANSPORT_LE)
+ p_lcb->peer_chnl_mask[0] = 0;
+
+ for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
{
if (p_lcb->p_fixed_ccbs[xx])
{
- l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
- p_lcb->p_fixed_ccbs[xx] = NULL;
+ if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb)
+ {
+ tL2C_CCB *p_l2c_chnl_ctrl_block;
+ p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
+ p_lcb->p_fixed_ccbs[xx] = NULL;
+ l2cu_release_ccb(p_l2c_chnl_ctrl_block);
#if BLE_INCLUDED == TRUE
(*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
#else
(*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
#endif
+ }
}
- else if ( (p_lcb->peer_chnl_mask[0] & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
+ else if ( (peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
&& (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) )
#if BLE_INCLUDED == TRUE
(*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
}
L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d",
- p_ccb->ccb_priority, p_ccb->local_cid, p_ccb->xmit_hold_q.count );
+ p_ccb->ccb_priority, p_ccb->local_cid, GKI_queue_length(&p_ccb->xmit_hold_q));
/* store the next serving channel */
/* this channel is the last channel of its priority group */
if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy)
continue;
- if ( p_ccb->fcrb.retrans_q.count == 0 )
+ if ( GKI_queue_is_empty(&p_ccb->fcrb.retrans_q))
{
- if ( p_ccb->xmit_hold_q.count == 0 )
+ if ( GKI_queue_is_empty(&p_ccb->xmit_hold_q))
continue;
/* If using the common pool, should be at least 10% free. */
}
else
{
- if (p_ccb->xmit_hold_q.count == 0)
+ if (GKI_queue_is_empty(&p_ccb->xmit_hold_q))
continue;
}
continue;
/* No more checks needed if sending from the reatransmit queue */
- if (p_ccb->fcrb.retrans_q.count == 0)
+ if (GKI_queue_is_empty(&p_ccb->fcrb.retrans_q))
{
- if (p_ccb->xmit_hold_q.count == 0)
+ if (GKI_queue_is_empty(&p_ccb->xmit_hold_q))
continue;
/* If using the common pool, should be at least 10% free. */
}
else
{
- if (p_ccb->xmit_hold_q.count != 0)
+ if (!GKI_queue_is_empty(&p_ccb->xmit_hold_q))
{
p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->xmit_hold_q);
if(NULL == p_buf)
{
UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT));
+ uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_ble();
/* The HCI transport will segment the buffers. */
- if (p_buf->len > btu_cb.hcit_ble_acl_data_size)
+ if (p_buf->len > acl_data_size)
{
- UINT16_TO_STREAM (p, btu_cb.hcit_ble_acl_data_size);
+ UINT16_TO_STREAM (p, acl_data_size);
}
else
{
UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
#endif
+ uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
/* The HCI transport will segment the buffers. */
- if (p_buf->len > btu_cb.hcit_acl_data_size)
+ if (p_buf->len > acl_data_size)
{
- UINT16_TO_STREAM (p, btu_cb.hcit_acl_data_size);
+ UINT16_TO_STREAM (p, acl_data_size);
}
else
{
*******************************************************************************/
void l2cu_check_channel_congestion (tL2C_CCB *p_ccb)
{
- UINT16 q_count = p_ccb->xmit_hold_q.count;
+ UINT16 q_count = GKI_queue_length(&p_ccb->xmit_hold_q);
#if (L2CAP_UCD_INCLUDED == TRUE)
if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID )