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 inline void disable(u16_t handle);
|
||||
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 inline void event_fex_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) {
|
||||
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;
|
||||
if (!conn->tx_data) {
|
||||
conn->tx_data = tx;
|
||||
|
@ -1175,6 +1186,10 @@ void ull_conn_tx_demux(u8_t count)
|
|||
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);
|
||||
} while (--count);
|
||||
}
|
||||
|
@ -1501,6 +1516,29 @@ static void conn_cleanup(struct ll_conn *conn)
|
|||
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,
|
||||
struct node_tx *tx)
|
||||
{
|
||||
|
|
|
@ -202,6 +202,11 @@ struct ll_conn {
|
|||
u8_t phy_pref_rx:3;
|
||||
#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_ctrl;
|
||||
struct node_tx *tx_ctrl_last;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue