diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index 7c6859e4ecb..d89e70aa541 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -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; } diff --git a/subsys/bluetooth/controller/ll_sw/ctrl_internal.h b/subsys/bluetooth/controller/ll_sw/ctrl_internal.h index ba6f76701c5..5d058115d6f 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ctrl_internal.h @@ -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 */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index 17850d11967..a28431fccd6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -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(); diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index e55f7683ad6..a816e6da9ac 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -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; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index decf8ada6bd..0ed7b46c842 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -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; diff --git a/subsys/bluetooth/controller/ll_sw/ull_master.c b/subsys/bluetooth/controller/ll_sw/ull_master.c index a315dad91ca..b47e8da84c7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_master.c +++ b/subsys/bluetooth/controller/ll_sw/ull_master.c @@ -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();