Bluetooth: controller: Add support for ISO feature bits
Add support for ISO feature bits. This includes extending fields that hold features to 64 bits to be able to handle the host-controlled "Isochronous Channels" feature. Signed-off-by: Wolfgang Puffitsch <wopu@demant.com>
This commit is contained in:
parent
45bdff1509
commit
ef1f8c34f1
4 changed files with 60 additions and 26 deletions
|
@ -1137,7 +1137,7 @@ static void le_read_local_features(struct net_buf *buf, struct net_buf **evt)
|
||||||
rp->status = 0x00;
|
rp->status = 0x00;
|
||||||
|
|
||||||
(void)memset(&rp->features[0], 0x00, sizeof(rp->features));
|
(void)memset(&rp->features[0], 0x00, sizeof(rp->features));
|
||||||
sys_put_le24(LL_FEAT, rp->features);
|
sys_put_le64(LL_FEAT, rp->features);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void le_set_random_address(struct net_buf *buf, struct net_buf **evt)
|
static void le_set_random_address(struct net_buf *buf, struct net_buf **evt)
|
||||||
|
|
|
@ -125,9 +125,40 @@
|
||||||
#define LL_FEAT_BIT_ANT_SWITCH_TX_AOD 0
|
#define LL_FEAT_BIT_ANT_SWITCH_TX_AOD 0
|
||||||
#endif /* !CONFIG_BT_CTLR_DF && !CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */
|
#endif /* !CONFIG_BT_CTLR_DF && !CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */
|
||||||
|
|
||||||
#define LL_FEAT_BIT_MASK 0x1FFFF
|
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
|
||||||
#define LL_FEAT_BIT_MASK_VALID 0x1CF2F
|
#define LL_FEAT_BIT_CIS_CENTRAL BIT64(BT_LE_FEAT_BIT_CIS_MASTER)
|
||||||
#define LL_FEAT_FILTER_OCTET0 0x1FF00
|
#else /* !CONFIG_BT_CTLR_CENTRAL_ISO */
|
||||||
|
#define LL_FEAT_BIT_CIS_CENTRAL 0
|
||||||
|
#endif /* !CONFIG_BT_CTLR_CENTRAL_ISO */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
|
||||||
|
#define LL_FEAT_BIT_CIS_PERIPHERAL BIT64(BT_LE_FEAT_BIT_CIS_SLAVE)
|
||||||
|
#else /* !CONFIG_BT_CTLR_PERIPHERAL_ISO */
|
||||||
|
#define LL_FEAT_BIT_CIS_PERIPHERAL 0
|
||||||
|
#endif /* !CONFIG_BT_CTLR_PERIPHERAL_ISO */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_ADV_ISO)
|
||||||
|
#define LL_FEAT_BIT_ISO_BROADCASTER BIT64(BT_LE_FEAT_BIT_ISO_BROADCASTER)
|
||||||
|
#else /* !CONFIG_BT_CTLR_ADV_ISO */
|
||||||
|
#define LL_FEAT_BIT_ISO_BROADCASTER 0
|
||||||
|
#endif /* !CONFIG_BT_CTLR_ADV_ISO */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
|
||||||
|
#define LL_FEAT_BIT_SYNC_RECEIVER BIT64(BT_LE_FEAT_BIT_SYNC_RECEIVER)
|
||||||
|
#else /* !CONFIG_BT_CTLR_SYNC_ISO */
|
||||||
|
#define LL_FEAT_BIT_SYNC_RECEIVER 0
|
||||||
|
#endif /* !CONFIG_BT_CTLR_SYNC_ISO */
|
||||||
|
|
||||||
|
/* All defined feature bits */
|
||||||
|
#define LL_FEAT_BIT_MASK 0xFFFFFFFFFULL
|
||||||
|
|
||||||
|
/* Feature bits that are valid from controller to controller */
|
||||||
|
#define LL_FEAT_BIT_MASK_VALID 0xFF787CF2FULL
|
||||||
|
|
||||||
|
/* Mask to filter away octet 0 for feature exchange */
|
||||||
|
#define LL_FEAT_FILTER_OCTET0 (LL_FEAT_BIT_MASK & ~0xFFULL)
|
||||||
|
|
||||||
|
/* Feature bits of this controller */
|
||||||
#define LL_FEAT (LL_FEAT_BIT_ENC | \
|
#define LL_FEAT (LL_FEAT_BIT_ENC | \
|
||||||
LL_FEAT_BIT_CONN_PARAM_REQ | \
|
LL_FEAT_BIT_CONN_PARAM_REQ | \
|
||||||
LL_FEAT_BIT_EXT_REJ_IND | \
|
LL_FEAT_BIT_EXT_REJ_IND | \
|
||||||
|
@ -145,4 +176,8 @@
|
||||||
LL_FEAT_BIT_CONNECTIONLESS_CTE_TX | \
|
LL_FEAT_BIT_CONNECTIONLESS_CTE_TX | \
|
||||||
LL_FEAT_BIT_ANT_SWITCH_TX_AOD | \
|
LL_FEAT_BIT_ANT_SWITCH_TX_AOD | \
|
||||||
LL_FEAT_BIT_CHAN_SEL_2 | \
|
LL_FEAT_BIT_CHAN_SEL_2 | \
|
||||||
LL_FEAT_BIT_MIN_USED_CHAN)
|
LL_FEAT_BIT_MIN_USED_CHAN | \
|
||||||
|
LL_FEAT_BIT_CIS_CENTRAL | \
|
||||||
|
LL_FEAT_BIT_CIS_PERIPHERAL | \
|
||||||
|
LL_FEAT_BIT_ISO_BROADCASTER | \
|
||||||
|
LL_FEAT_BIT_SYNC_RECEIVER)
|
||||||
|
|
|
@ -333,7 +333,7 @@ uint8_t ll_conn_update(uint16_t handle, uint8_t cmd, uint8_t status, uint16_t in
|
||||||
if (!conn->llcp_conn_param.disabled &&
|
if (!conn->llcp_conn_param.disabled &&
|
||||||
(!conn->common.fex_valid ||
|
(!conn->common.fex_valid ||
|
||||||
(conn->llcp_feature.features_conn &
|
(conn->llcp_feature.features_conn &
|
||||||
BIT(BT_LE_FEAT_BIT_CONN_PARAM_REQ)))) {
|
BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ)))) {
|
||||||
cmd++;
|
cmd++;
|
||||||
} else if (conn->lll.role) {
|
} else if (conn->lll.role) {
|
||||||
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||||
|
@ -523,7 +523,7 @@ uint32_t ll_length_req_send(uint16_t handle, uint16_t tx_octets, uint16_t tx_tim
|
||||||
|
|
||||||
if (conn->llcp_length.disabled ||
|
if (conn->llcp_length.disabled ||
|
||||||
(conn->common.fex_valid &&
|
(conn->common.fex_valid &&
|
||||||
!(conn->llcp_feature.features_conn & BIT(BT_LE_FEAT_BIT_DLE)))) {
|
!(conn->llcp_feature.features_conn & BIT64(BT_LE_FEAT_BIT_DLE)))) {
|
||||||
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,9 +634,9 @@ uint8_t ll_phy_req_send(uint16_t handle, uint8_t tx, uint8_t flags, uint8_t rx)
|
||||||
|
|
||||||
if (conn->llcp_phy.disabled ||
|
if (conn->llcp_phy.disabled ||
|
||||||
(conn->common.fex_valid &&
|
(conn->common.fex_valid &&
|
||||||
!(conn->llcp_feature.features_conn & BIT(BT_LE_FEAT_BIT_PHY_2M)) &&
|
!(conn->llcp_feature.features_conn & BIT64(BT_LE_FEAT_BIT_PHY_2M)) &&
|
||||||
!(conn->llcp_feature.features_conn &
|
!(conn->llcp_feature.features_conn &
|
||||||
BIT(BT_LE_FEAT_BIT_PHY_CODED)))) {
|
BIT64(BT_LE_FEAT_BIT_PHY_CODED)))) {
|
||||||
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2709,7 +2709,7 @@ static inline void event_enc_reject_prep(struct ll_conn *conn,
|
||||||
|
|
||||||
if (conn->common.fex_valid &&
|
if (conn->common.fex_valid &&
|
||||||
(conn->llcp_feature.features_conn &
|
(conn->llcp_feature.features_conn &
|
||||||
BIT(BT_LE_FEAT_BIT_EXT_REJ_IND))) {
|
BIT64(BT_LE_FEAT_BIT_EXT_REJ_IND))) {
|
||||||
struct pdu_data_llctrl_reject_ext_ind *p;
|
struct pdu_data_llctrl_reject_ext_ind *p;
|
||||||
|
|
||||||
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND;
|
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND;
|
||||||
|
@ -2937,7 +2937,7 @@ static inline void event_fex_prep(struct ll_conn *conn)
|
||||||
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_FEATURE_RSP;
|
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_FEATURE_RSP;
|
||||||
(void)memset(&pdu->llctrl.feature_rsp.features[0], 0x00,
|
(void)memset(&pdu->llctrl.feature_rsp.features[0], 0x00,
|
||||||
sizeof(pdu->llctrl.feature_rsp.features));
|
sizeof(pdu->llctrl.feature_rsp.features));
|
||||||
sys_put_le24(conn->llcp_feature.features_peer,
|
sys_put_le64(conn->llcp_feature.features_peer,
|
||||||
pdu->llctrl.feature_req.features);
|
pdu->llctrl.feature_req.features);
|
||||||
|
|
||||||
/* enqueue feature rsp structure into rx queue */
|
/* enqueue feature rsp structure into rx queue */
|
||||||
|
@ -2967,7 +2967,7 @@ static inline void event_fex_prep(struct ll_conn *conn)
|
||||||
(void)memset(&pdu->llctrl.feature_req.features[0],
|
(void)memset(&pdu->llctrl.feature_req.features[0],
|
||||||
0x00,
|
0x00,
|
||||||
sizeof(pdu->llctrl.feature_req.features));
|
sizeof(pdu->llctrl.feature_req.features));
|
||||||
sys_put_le24(conn->llcp_feature.features_conn,
|
sys_put_le64(conn->llcp_feature.features_conn,
|
||||||
pdu->llctrl.feature_req.features);
|
pdu->llctrl.feature_req.features);
|
||||||
|
|
||||||
ctrl_tx_enqueue(conn, tx);
|
ctrl_tx_enqueue(conn, tx);
|
||||||
|
@ -3395,22 +3395,22 @@ static inline void event_ping_prep(struct ll_conn *conn)
|
||||||
static inline void dle_max_time_get(const struct ll_conn *conn,
|
static inline void dle_max_time_get(const struct ll_conn *conn,
|
||||||
uint16_t *max_rx_time, uint16_t *max_tx_time)
|
uint16_t *max_rx_time, uint16_t *max_tx_time)
|
||||||
{
|
{
|
||||||
uint32_t feature_coded_phy = 0;
|
uint64_t feature_coded_phy = 0;
|
||||||
uint32_t feature_phy_2m = 0;
|
uint64_t feature_phy_2m = 0;
|
||||||
uint16_t rx_time = 0;
|
uint16_t rx_time = 0;
|
||||||
uint16_t tx_time = 0;
|
uint16_t tx_time = 0;
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_PHY)
|
#if defined(CONFIG_BT_CTLR_PHY)
|
||||||
#if defined(CONFIG_BT_CTLR_PHY_CODED)
|
#if defined(CONFIG_BT_CTLR_PHY_CODED)
|
||||||
feature_coded_phy = (conn->llcp_feature.features_conn &
|
feature_coded_phy = (conn->llcp_feature.features_conn &
|
||||||
BIT(BT_LE_FEAT_BIT_PHY_CODED));
|
BIT64(BT_LE_FEAT_BIT_PHY_CODED));
|
||||||
#else
|
#else
|
||||||
feature_coded_phy = 0;
|
feature_coded_phy = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_PHY_2M)
|
#if defined(CONFIG_BT_CTLR_PHY_2M)
|
||||||
feature_phy_2m = (conn->llcp_feature.features_conn &
|
feature_phy_2m = (conn->llcp_feature.features_conn &
|
||||||
BIT(BT_LE_FEAT_BIT_PHY_2M));
|
BIT64(BT_LE_FEAT_BIT_PHY_2M));
|
||||||
#else
|
#else
|
||||||
feature_phy_2m = 0;
|
feature_phy_2m = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -4252,12 +4252,11 @@ static int unknown_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t feat_get(uint8_t *features)
|
static inline uint64_t feat_get(uint8_t *features)
|
||||||
{
|
{
|
||||||
uint32_t feat;
|
uint64_t feat;
|
||||||
|
|
||||||
feat = ~LL_FEAT_BIT_MASK_VALID | features[0] |
|
feat = ~LL_FEAT_BIT_MASK_VALID | sys_get_le64(features);
|
||||||
(features[1] << 8) | (features[2] << 16);
|
|
||||||
feat &= LL_FEAT_BIT_MASK;
|
feat &= LL_FEAT_BIT_MASK;
|
||||||
|
|
||||||
return feat;
|
return feat;
|
||||||
|
@ -4267,9 +4266,9 @@ static inline uint32_t feat_get(uint8_t *features)
|
||||||
* Perform a logical and on octet0 and keep the remaining bits of the
|
* Perform a logical and on octet0 and keep the remaining bits of the
|
||||||
* first input parameter
|
* first input parameter
|
||||||
*/
|
*/
|
||||||
static inline uint32_t feat_land_octet0(uint32_t feat_to_keep, uint32_t feat_octet0)
|
static inline uint64_t feat_land_octet0(uint64_t feat_to_keep, uint64_t feat_octet0)
|
||||||
{
|
{
|
||||||
uint32_t feat_result;
|
uint64_t feat_result;
|
||||||
|
|
||||||
feat_result = feat_to_keep & feat_octet0;
|
feat_result = feat_to_keep & feat_octet0;
|
||||||
feat_result &= 0xFF;
|
feat_result &= 0xFF;
|
||||||
|
@ -4284,7 +4283,7 @@ static int feature_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx,
|
||||||
struct pdu_data_llctrl_feature_req *req;
|
struct pdu_data_llctrl_feature_req *req;
|
||||||
struct node_tx *tx;
|
struct node_tx *tx;
|
||||||
struct pdu_data *pdu_tx;
|
struct pdu_data *pdu_tx;
|
||||||
uint32_t feat;
|
uint64_t feat;
|
||||||
|
|
||||||
/* acquire tx mem */
|
/* acquire tx mem */
|
||||||
tx = mem_acquire(&mem_conn_tx_ctrl.free);
|
tx = mem_acquire(&mem_conn_tx_ctrl.free);
|
||||||
|
@ -4319,7 +4318,7 @@ static int feature_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx,
|
||||||
* See BTCore V5.2 VOl 6 Part B, chapter 5.1.4
|
* See BTCore V5.2 VOl 6 Part B, chapter 5.1.4
|
||||||
*/
|
*/
|
||||||
feat = feat_land_octet0(LL_FEAT, conn->llcp_feature.features_conn);
|
feat = feat_land_octet0(LL_FEAT, conn->llcp_feature.features_conn);
|
||||||
sys_put_le24(feat, pdu_tx->llctrl.feature_rsp.features);
|
sys_put_le64(feat, pdu_tx->llctrl.feature_rsp.features);
|
||||||
|
|
||||||
ctrl_tx_sec_enqueue(conn, tx);
|
ctrl_tx_sec_enqueue(conn, tx);
|
||||||
|
|
||||||
|
|
|
@ -162,8 +162,8 @@ struct ll_conn {
|
||||||
struct {
|
struct {
|
||||||
uint8_t req;
|
uint8_t req;
|
||||||
uint8_t ack;
|
uint8_t ack;
|
||||||
uint32_t features_conn;
|
uint64_t features_conn;
|
||||||
uint32_t features_peer;
|
uint64_t features_peer;
|
||||||
} llcp_feature;
|
} llcp_feature;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue