Bluetooth: controller: Do not use LL procedures not supported by remote
Update LLCP handling during PHY update and Data Length update to not start the LL control procedure if the remote has already indicated that the procedure is not supported. This fulfills the following requirement from the BT Core Specification (Core_v5.2, Vol 6, Part B, Section 4.6): Except where explicitly stated elsewhere in this specification, if the peer Link Layer has indicated either during a feature exchange procedure or by responding with an LL_UNKNOWN_RSP PDU that it does not support a procedure, then the Link Layer shall not use that procedure. Re-use the connection parameter request handling for PHY and data length update procedures. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
parent
e816ac7124
commit
8514794ed3
6 changed files with 48 additions and 0 deletions
|
@ -3454,6 +3454,9 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx,
|
|||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
} else if (_radio.conn_curr->llcp_length.req !=
|
||||
_radio.conn_curr->llcp_length.ack) {
|
||||
/* Mark length update as unsupported */
|
||||
_radio.conn_curr->llcp_length.disabled = 1U;
|
||||
|
||||
/* Procedure complete */
|
||||
_radio.conn_curr->llcp_length.ack =
|
||||
_radio.conn_curr->llcp_length.req;
|
||||
|
@ -3469,6 +3472,9 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx,
|
|||
_radio.conn_curr->llcp_phy.ack) {
|
||||
struct radio_le_phy_upd_cmplt *p;
|
||||
|
||||
/* Mark phy update as unsupported */
|
||||
_radio.conn_curr->llcp_phy.disabled = 1U;
|
||||
|
||||
/* Procedure complete */
|
||||
_radio.conn_curr->llcp_phy.ack =
|
||||
_radio.conn_curr->llcp_phy.req;
|
||||
|
@ -12168,12 +12174,14 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
|
|||
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
conn->llcp_length.disabled = 0U;
|
||||
conn->llcp_length.req = 0U;
|
||||
conn->llcp_length.ack = 0U;
|
||||
conn->llcp_length.cache.tx_octets = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
conn->llcp_phy.disabled = 0U;
|
||||
conn->llcp_phy.req = 0U;
|
||||
conn->llcp_phy.ack = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
@ -12607,6 +12615,12 @@ u32_t ll_length_req_send(u16_t handle, u16_t tx_octets, u16_t tx_time)
|
|||
return BT_HCI_ERR_UNKNOWN_CONN_ID;
|
||||
}
|
||||
|
||||
if (conn->llcp_length.disabled ||
|
||||
(conn->common.fex_valid &&
|
||||
!(conn->llcp_feature.features & BIT(BT_LE_FEAT_BIT_DLE)))) {
|
||||
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||
}
|
||||
|
||||
if (conn->llcp_length.req != conn->llcp_length.ack) {
|
||||
switch (conn->llcp_length.state) {
|
||||
case LLCP_LENGTH_STATE_RSP_ACK_WAIT:
|
||||
|
@ -12702,6 +12716,13 @@ u8_t ll_phy_req_send(u16_t handle, u8_t tx, u8_t flags, u8_t rx)
|
|||
return BT_HCI_ERR_UNKNOWN_CONN_ID;
|
||||
}
|
||||
|
||||
if (conn->llcp_phy.disabled ||
|
||||
(conn->common.fex_valid &&
|
||||
!(conn->llcp_feature.features & BIT(BT_LE_FEAT_BIT_PHY_2M)) &&
|
||||
!(conn->llcp_feature.features & BIT(BT_LE_FEAT_BIT_PHY_CODED)))) {
|
||||
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||
}
|
||||
|
||||
if (conn->llcp_phy.req != conn->llcp_phy.ack) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
|
|
@ -268,6 +268,7 @@ struct connection {
|
|||
#define LLCP_LENGTH_STATE_RESIZE 4
|
||||
#define LLCP_LENGTH_STATE_RESIZE_RSP 5
|
||||
#define LLCP_LENGTH_STATE_RESIZE_RSP_ACK_WAIT 6
|
||||
u8_t disabled:1;
|
||||
u16_t rx_octets;
|
||||
u16_t tx_octets;
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
|
@ -296,6 +297,7 @@ struct connection {
|
|||
u8_t rx:3;
|
||||
u8_t flags:1;
|
||||
u8_t cmd:1;
|
||||
u8_t disabled:1;
|
||||
} llcp_phy;
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
||||
|
|
|
@ -674,6 +674,7 @@ u8_t ll_adv_enable(u8_t enable)
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
conn->llcp_length.req = conn->llcp_length.ack = 0U;
|
||||
conn->llcp_length.disabled = 0U;
|
||||
conn->llcp_length.cache.tx_octets = 0U;
|
||||
conn->default_tx_octets = ull_conn_default_tx_octets_get();
|
||||
|
||||
|
@ -684,6 +685,7 @@ u8_t ll_adv_enable(u8_t enable)
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
conn->llcp_phy.req = conn->llcp_phy.ack = 0;
|
||||
conn->llcp_phy.disabled = 0U;
|
||||
conn->llcp_phy.pause_tx = 0U;
|
||||
conn->phy_pref_tx = ull_conn_default_phy_tx_get();
|
||||
conn->phy_pref_rx = ull_conn_default_phy_rx_get();
|
||||
|
|
|
@ -425,6 +425,12 @@ u32_t ll_length_req_send(u16_t handle, u16_t tx_octets, u16_t tx_time)
|
|||
return BT_HCI_ERR_UNKNOWN_CONN_ID;
|
||||
}
|
||||
|
||||
if (conn->llcp_length.disabled ||
|
||||
(conn->common.fex_valid &&
|
||||
!(conn->llcp_feature.features & BIT(BT_LE_FEAT_BIT_DLE)))) {
|
||||
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||
}
|
||||
|
||||
if (conn->llcp_length.req != conn->llcp_length.ack) {
|
||||
switch (conn->llcp_length.state) {
|
||||
case LLCP_LENGTH_STATE_RSP_ACK_WAIT:
|
||||
|
@ -526,6 +532,13 @@ u8_t ll_phy_req_send(u16_t handle, u8_t tx, u8_t flags, u8_t rx)
|
|||
return BT_HCI_ERR_UNKNOWN_CONN_ID;
|
||||
}
|
||||
|
||||
if (conn->llcp_phy.disabled ||
|
||||
(conn->common.fex_valid &&
|
||||
!(conn->llcp_feature.features & BIT(BT_LE_FEAT_BIT_PHY_2M)) &&
|
||||
!(conn->llcp_feature.features & BIT(BT_LE_FEAT_BIT_PHY_CODED)))) {
|
||||
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||
}
|
||||
|
||||
if ((conn->llcp_req != conn->llcp_ack) ||
|
||||
(conn->llcp_phy.req != conn->llcp_phy.ack)) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
|
@ -5878,6 +5891,9 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
} else if (conn->llcp_length.req != conn->llcp_length.ack) {
|
||||
/* Mark length update as unsupported */
|
||||
conn->llcp_length.disabled = 1U;
|
||||
|
||||
/* Procedure complete */
|
||||
conn->llcp_length.ack = conn->llcp_length.req;
|
||||
|
||||
|
@ -5891,6 +5907,9 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
conn->llcp_phy.ack) {
|
||||
struct lll_conn *lll = &conn->lll;
|
||||
|
||||
/* Mark phy update as unsupported */
|
||||
conn->llcp_phy.disabled = 1U;
|
||||
|
||||
/* Procedure complete */
|
||||
conn->llcp_phy.ack = conn->llcp_phy.req;
|
||||
conn->llcp_phy.pause_tx = 0U;
|
||||
|
|
|
@ -222,6 +222,7 @@ struct ll_conn {
|
|||
#define LLCP_LENGTH_STATE_RESIZE 4
|
||||
#define LLCP_LENGTH_STATE_RESIZE_RSP 5
|
||||
#define LLCP_LENGTH_STATE_RESIZE_RSP_ACK_WAIT 6
|
||||
u8_t disabled:1;
|
||||
u16_t rx_octets;
|
||||
u16_t tx_octets;
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
|
@ -251,6 +252,7 @@ struct ll_conn {
|
|||
u8_t pause_tx:1;
|
||||
u8_t flags:1;
|
||||
u8_t cmd:1;
|
||||
u8_t disabled:1;
|
||||
} llcp_phy;
|
||||
|
||||
u8_t phy_pref_tx:3;
|
||||
|
|
|
@ -221,6 +221,7 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
conn->llcp_length.req = conn->llcp_length.ack = 0U;
|
||||
conn->llcp_length.disabled = 0U;
|
||||
conn->llcp_length.cache.tx_octets = 0U;
|
||||
conn->default_tx_octets = ull_conn_default_tx_octets_get();
|
||||
|
||||
|
@ -231,6 +232,7 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
conn->llcp_phy.req = conn->llcp_phy.ack = 0U;
|
||||
conn->llcp_phy.disabled = 0U;
|
||||
conn->llcp_phy.pause_tx = 0U;
|
||||
conn->phy_pref_tx = ull_conn_default_phy_tx_get();
|
||||
conn->phy_pref_rx = ull_conn_default_phy_rx_get();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue