Bluetooth: controller: split: Handle zero length L2CAP start frame
Added a fix to handle L2CAP start frame with payload length of zero which otherwise sent zero length data start PDU on air. Relates to #17046. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
a081e001b0
commit
da431f2a7d
2 changed files with 43 additions and 0 deletions
|
@ -46,6 +46,11 @@ static int init_reset(void);
|
||||||
static void ticker_update_conn_op_cb(u32_t status, void *param);
|
static void ticker_update_conn_op_cb(u32_t status, void *param);
|
||||||
static inline void disable(u16_t handle);
|
static inline void disable(u16_t handle);
|
||||||
static void conn_cleanup(struct ll_conn *conn);
|
static void conn_cleanup(struct ll_conn *conn);
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_LLID_DATA_START_EMPTY)
|
||||||
|
static int empty_data_start_release(struct ll_conn *conn, struct node_tx *tx);
|
||||||
|
#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
|
||||||
|
|
||||||
static void ctrl_tx_enqueue(struct ll_conn *conn, struct node_tx *tx);
|
static void ctrl_tx_enqueue(struct ll_conn *conn, struct node_tx *tx);
|
||||||
static inline void event_fex_prep(struct ll_conn *conn);
|
static inline void event_fex_prep(struct ll_conn *conn);
|
||||||
static inline void event_vex_prep(struct ll_conn *conn);
|
static inline void event_vex_prep(struct ll_conn *conn);
|
||||||
|
@ -1153,6 +1158,12 @@ void ull_conn_tx_demux(u8_t count)
|
||||||
if (conn) {
|
if (conn) {
|
||||||
struct node_tx *tx = lll_tx->node;
|
struct node_tx *tx = lll_tx->node;
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_LLID_DATA_START_EMPTY)
|
||||||
|
if (empty_data_start_release(conn, tx)) {
|
||||||
|
goto ull_conn_tx_demux_release;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
|
||||||
|
|
||||||
tx->next = NULL;
|
tx->next = NULL;
|
||||||
if (!conn->tx_data) {
|
if (!conn->tx_data) {
|
||||||
conn->tx_data = tx;
|
conn->tx_data = tx;
|
||||||
|
@ -1175,6 +1186,10 @@ void ull_conn_tx_demux(u8_t count)
|
||||||
ll_tx_ack_put(0xFFFF, tx);
|
ll_tx_ack_put(0xFFFF, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_LLID_DATA_START_EMPTY)
|
||||||
|
ull_conn_tx_demux_release:
|
||||||
|
#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
|
||||||
|
|
||||||
MFIFO_DEQUEUE(conn_tx);
|
MFIFO_DEQUEUE(conn_tx);
|
||||||
} while (--count);
|
} while (--count);
|
||||||
}
|
}
|
||||||
|
@ -1501,6 +1516,29 @@ static void conn_cleanup(struct ll_conn *conn)
|
||||||
lll->handle = 0xFFFF;
|
lll->handle = 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_LLID_DATA_START_EMPTY)
|
||||||
|
static int empty_data_start_release(struct ll_conn *conn, struct node_tx *tx)
|
||||||
|
{
|
||||||
|
struct pdu_data *p = (void *)tx->pdu;
|
||||||
|
|
||||||
|
if ((p->ll_id == PDU_DATA_LLID_DATA_START) && !p->len) {
|
||||||
|
conn->start_empty = 1U;
|
||||||
|
|
||||||
|
ll_tx_ack_put(conn->lll.handle, tx);
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
} else if (p->len && conn->start_empty) {
|
||||||
|
conn->start_empty = 0U;
|
||||||
|
|
||||||
|
if (p->ll_id == PDU_DATA_LLID_DATA_CONTINUE) {
|
||||||
|
p->ll_id = PDU_DATA_LLID_DATA_START;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
|
||||||
|
|
||||||
static void ctrl_tx_last_enqueue(struct ll_conn *conn,
|
static void ctrl_tx_last_enqueue(struct ll_conn *conn,
|
||||||
struct node_tx *tx)
|
struct node_tx *tx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -202,6 +202,11 @@ struct ll_conn {
|
||||||
u8_t phy_pref_rx:3;
|
u8_t phy_pref_rx:3;
|
||||||
#endif /* CONFIG_BT_CTLR_PHY */
|
#endif /* CONFIG_BT_CTLR_PHY */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_LLID_DATA_START_EMPTY)
|
||||||
|
/* Detect empty L2CAP start frame */
|
||||||
|
u8_t start_empty:1;
|
||||||
|
#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
|
||||||
|
|
||||||
struct node_tx *tx_head;
|
struct node_tx *tx_head;
|
||||||
struct node_tx *tx_ctrl;
|
struct node_tx *tx_ctrl;
|
||||||
struct node_tx *tx_ctrl_last;
|
struct node_tx *tx_ctrl_last;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue