Skip to content

Commit c51a877

Browse files
committed
bluetooth: host: Add support for extended feature set feature
This commit adds support for the extended feature set feature. This includes: - hci boilerplate - kconfigs, including one for a max supported feature page - linking into the current auto feature exchange procedure Signed-off-by: Sean Madigan <sean.madigan@nordicsemi.no>
1 parent 9e6390c commit c51a877

File tree

11 files changed

+184
-16
lines changed

11 files changed

+184
-16
lines changed

include/zephyr/bluetooth/bluetooth.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,16 @@ extern "C" {
7171
#define BT_ID_DEFAULT 0
7272

7373
/**
74-
* @brief Number of octets for local supported
74+
* @brief Number of octets for local and remote supported features
7575
*
76-
* The value of 8 correspond to page 0 in the LE Controller supported features
76+
* The value of 8 correspond to page 0 in the LE Controller supported features.
77+
* 24 bytes are required for all subsequent supported feature pages.
7778
*/
78-
#define BT_LE_LOCAL_SUPPORTED_FEATURES_SIZE 8
79+
#ifdef CONFIG_BT_LE_MAX_SUPPORTED_FEATURE_PAGE
80+
#define BT_LE_LOCAL_SUPPORTED_FEATURES_SIZE (8 + (CONFIG_BT_LE_MAX_SUPPORTED_FEATURE_PAGE * 24))
81+
#else
82+
#define BT_LE_LOCAL_SUPPORTED_FEATURES_SIZE (8)
83+
#endif
7984

8085
/** Opaque type representing an advertiser. */
8186
struct bt_le_ext_adv;

include/zephyr/bluetooth/hci_types.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,8 @@ struct bt_hci_cmd_hdr {
284284
BT_LE_FEAT_BIT_CHANNEL_SOUNDING)
285285
#define BT_FEAT_LE_CHANNEL_SOUNDING_HOST(feat) BT_LE_FEAT_TEST(feat, \
286286
BT_LE_FEAT_BIT_CHANNEL_SOUNDING_HOST)
287+
#define BT_FEAT_LE_LL_EXTENDED_FEAT_SET(feat) BT_LE_FEAT_TEST(feat, \
288+
BT_LE_FEAT_BIT_LL_EXTENDED_FEAT_SET)
287289

288290
#define BT_FEAT_LE_CIS(feat) (BT_FEAT_LE_CIS_CENTRAL(feat) | \
289291
BT_FEAT_LE_CIS_PERIPHERAL(feat))
@@ -2438,6 +2440,20 @@ struct bt_hci_cp_le_tx_test_v4 {
24382440
uint8_t ant_ids[0];
24392441
} __packed;
24402442

2443+
#define BT_HCI_OP_LE_READ_ALL_LOCAL_SUPPORTED_FEATURES BT_OP(BT_OGF_LE, 0x0087) /* 0x2087 */
2444+
struct bt_hci_rp_le_read_all_local_supported_features {
2445+
uint8_t status;
2446+
uint8_t max_page;
2447+
uint8_t features[248];
2448+
} __packed;
2449+
2450+
2451+
#define BT_HCI_OP_LE_READ_ALL_REMOTE_FEATURES BT_OP(BT_OGF_LE, 0x0088) /* 0x2088 */
2452+
struct bt_hci_cp_le_read_all_remote_features {
2453+
uint16_t handle;
2454+
uint8_t pages_requested;
2455+
} __packed;
2456+
24412457
#define BT_HCI_TX_TEST_POWER_MIN -0x7F
24422458
#define BT_HCI_TX_TEST_POWER_MAX 0x14
24432459

@@ -3552,6 +3568,16 @@ struct bt_hci_evt_le_cis_established_v2 {
35523568
uint8_t framing;
35533569
} __packed;
35543570

3571+
#define BT_HCI_EVT_LE_READ_ALL_REMOTE_FEAT_COMPLETE 0x2b
3572+
3573+
struct bt_hci_evt_le_read_all_remote_feat_complete {
3574+
uint8_t status;
3575+
uint16_t handle;
3576+
uint8_t max_remote_page;
3577+
uint8_t max_valid_page;
3578+
uint8_t features[248];
3579+
} __packed;
3580+
35553581
#define BT_HCI_LE_CS_INITIATOR_ROLE_MASK BIT(0)
35563582
#define BT_HCI_LE_CS_REFLECTOR_ROLE_MASK BIT(1)
35573583

@@ -4024,6 +4050,8 @@ struct bt_hci_evt_le_cs_procedure_enable_complete {
40244050
#define BT_EVT_MASK_LE_ENH_CONN_COMPLETE_V2 BT_EVT_BIT(40)
40254051
#define BT_EVT_MASK_LE_CIS_ESTABLISHED_V2 BT_EVT_BIT(41)
40264052

4053+
#define BT_EVT_MASK_LE_READ_ALL_REMOTE_FEAT_COMPLTETE BT_EVT_BIT(42)
4054+
40274055
#define BT_EVT_MASK_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE BT_EVT_BIT(43)
40284056
#define BT_EVT_MASK_LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE BT_EVT_BIT(44)
40294057
#define BT_EVT_MASK_LE_CS_SECURITY_ENABLE_COMPLETE BT_EVT_BIT(45)

subsys/bluetooth/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,21 @@ config BT_CONN_TX
115115
help
116116
Hidden configuration that is true if ACL or broadcast ISO is enabled
117117

118+
config BT_LE_MAX_SUPPORTED_FEATURE_PAGE
119+
int "Maximum supported feature page"
120+
default 0
121+
range 0 10
122+
help
123+
Maximum supported feature page that can be stored locally and fetched
124+
from the remote connection with the LL Extended Feature Set feature.
125+
126+
config BT_LL_EXTENDED_FEAT_SET
127+
bool "LL Extended Feature Set"
128+
default y if BT_LE_MAX_SUPPORTED_FEATURE_PAGE > 0
129+
depends on !HAS_BT_CTLR || BT_CTLR_LL_EXTENDED_FEAT_SET_SUPPORT
130+
help
131+
Enable support for the LL Extended Feature Set feature.
132+
118133
if BT_CONN
119134
config BT_HCI_ACL_FLOW_CONTROL
120135
bool "Controller to Host ACL flow control support"

subsys/bluetooth/common/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ config BT_BUF_ACL_RX_COUNT
119119

120120
config BT_BUF_EVT_RX_SIZE
121121
int "Maximum supported HCI Event buffer length"
122-
default $(UINT8_MAX) if (BT_EXT_ADV && BT_OBSERVER) || BT_PER_ADV_SYNC || BT_DF_CONNECTION_CTE_RX || BT_CLASSIC || BT_CHANNEL_SOUNDING
122+
default $(UINT8_MAX) if (BT_EXT_ADV && BT_OBSERVER) || BT_PER_ADV_SYNC || BT_DF_CONNECTION_CTE_RX || BT_CLASSIC || BT_CHANNEL_SOUNDING || BT_LL_EXTENDED_FEAT_SET
123123
# LE Read Supported Commands command complete event.
124124
default 68
125125
range 68 $(UINT8_MAX)

subsys/bluetooth/controller/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ config BT_CTLR_SUBRATING_SUPPORT
128128
config BT_CTLR_CHANNEL_SOUNDING_SUPPORT
129129
bool
130130

131+
config BT_CTLR_LL_EXTENDED_FEAT_SET_SUPPORT
132+
bool
133+
131134
# Virtual option that all local LL implementations should select
132135
config HAS_BT_CTLR
133136
bool
@@ -1174,6 +1177,14 @@ config BT_CTLR_CHANNEL_SOUNDING
11741177
Enable support for Bluetooth 6.0 Channel Sounding in the
11751178
Controller.
11761179

1180+
config BT_CTLR_LL_EXTENDED_FEAT_SET
1181+
bool "LL Extended Feature Set support"
1182+
depends on BT_CTLR_LL_EXTENDED_FEAT_SET_SUPPORT
1183+
default y if BT_LL_EXTENDED_FEAT_SET
1184+
help
1185+
Enable support for Bluetooth 6.0 LL Extended Feature Set
1186+
in the Controller.
1187+
11771188
rsource "Kconfig.df"
11781189
rsource "Kconfig.ll_sw_split"
11791190
rsource "Kconfig.dtm"

subsys/bluetooth/host/conn.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,7 +1706,12 @@ static bool can_initiate_feature_exchange(struct bt_conn *conn)
17061706
return true;
17071707
}
17081708

1709-
return BT_FEAT_LE_PER_INIT_FEAT_XCHG(bt_dev.le.features);
1709+
if (IS_ENABLED(CONFIG_HAS_BT_CTLR) && IS_ENABLED(CONFIG_BT_CTLR_LL_EXTENDED_FEAT_SET)) {
1710+
return true;
1711+
}
1712+
1713+
return BT_FEAT_LE_PER_INIT_FEAT_XCHG(bt_dev.le.features) ||
1714+
BT_FEAT_LE_LL_EXTENDED_FEAT_SET(bt_dev.le.features);
17101715
}
17111716

17121717
static void perform_auto_initiated_procedures(struct bt_conn *conn, void *unused)
@@ -1732,9 +1737,18 @@ static void perform_auto_initiated_procedures(struct bt_conn *conn, void *unused
17321737

17331738
if (!atomic_test_bit(conn->flags, BT_CONN_LE_FEATURES_EXCHANGED) &&
17341739
can_initiate_feature_exchange(conn)) {
1735-
err = bt_hci_le_read_remote_features(conn);
1736-
if (err) {
1737-
LOG_ERR("Failed read remote features (%d)", err);
1740+
1741+
if (IS_ENABLED(CONFIG_BT_LL_EXTENDED_FEAT_SET) &&
1742+
BT_FEAT_LE_LL_EXTENDED_FEAT_SET(bt_dev.le.features)) {
1743+
err = bt_hci_le_read_all_remote_features(conn);
1744+
if (err) {
1745+
LOG_ERR("Failed all read remote features (%d)", err);
1746+
}
1747+
} else {
1748+
err = bt_hci_le_read_remote_features(conn);
1749+
if (err) {
1750+
LOG_ERR("Failed read remote features (%d)", err);
1751+
}
17381752
}
17391753
if (conn->state != BT_CONN_CONNECTED) {
17401754
return;

subsys/bluetooth/host/conn_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ struct bt_conn_le {
125125
* Available after `atomic_test_bit(conn->flags, BT_CONN_LE_FEATURES_EXCHANGED)`.
126126
* Signaled by bt_conn_cb.remote_info_available().
127127
*/
128-
uint8_t features[8];
128+
uint8_t features[BT_LE_LOCAL_SUPPORTED_FEATURES_SIZE];
129129

130130
struct bt_keys *keys;
131131

subsys/bluetooth/host/hci_core.c

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,23 @@ int bt_hci_le_read_remote_features(struct bt_conn *conn)
11171117
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_REMOTE_FEATURES, buf, NULL);
11181118
}
11191119

1120+
int bt_hci_le_read_all_remote_features(struct bt_conn *conn)
1121+
{
1122+
struct bt_hci_cp_le_read_all_remote_features *cp;
1123+
struct net_buf *buf;
1124+
1125+
buf = bt_hci_cmd_alloc(K_FOREVER);
1126+
if (!buf) {
1127+
return -ENOBUFS;
1128+
}
1129+
1130+
cp = net_buf_add(buf, sizeof(*cp));
1131+
cp->handle = sys_cpu_to_le16(conn->handle);
1132+
cp->pages_requested = CONFIG_BT_LE_MAX_SUPPORTED_FEATURE_PAGE;
1133+
1134+
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_ALL_REMOTE_FEATURES, buf, NULL);
1135+
}
1136+
11201137
int bt_hci_read_remote_version(struct bt_conn *conn)
11211138
{
11221139
struct bt_hci_cp_read_remote_version_info *cp;
@@ -1784,6 +1801,35 @@ static void le_remote_feat_complete(struct net_buf *buf)
17841801
return;
17851802
}
17861803

1804+
if (!evt->status) {
1805+
memcpy(conn->le.features, evt->features,
1806+
sizeof(evt->features));
1807+
}
1808+
1809+
atomic_set_bit(conn->flags, BT_CONN_LE_FEATURES_EXCHANGED);
1810+
1811+
if (IS_ENABLED(CONFIG_BT_REMOTE_INFO) &&
1812+
(!IS_ENABLED(CONFIG_BT_REMOTE_VERSION) ||
1813+
atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO))) {
1814+
notify_remote_info(conn);
1815+
}
1816+
1817+
bt_conn_unref(conn);
1818+
}
1819+
1820+
#if defined(CONFIG_BT_LL_EXTENDED_FEAT_SET)
1821+
static void le_read_all_remote_feat_complete(struct net_buf *buf)
1822+
{
1823+
struct bt_hci_evt_le_read_all_remote_feat_complete *evt = (void *)buf->data;
1824+
uint16_t handle = sys_le16_to_cpu(evt->handle);
1825+
struct bt_conn *conn;
1826+
1827+
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_LE);
1828+
if (!conn) {
1829+
LOG_ERR("Unable to lookup conn for handle %u", handle);
1830+
return;
1831+
}
1832+
17871833
if (!evt->status) {
17881834
memcpy(conn->le.features, evt->features,
17891835
sizeof(conn->le.features));
@@ -1799,6 +1845,7 @@ static void le_remote_feat_complete(struct net_buf *buf)
17991845

18001846
bt_conn_unref(conn);
18011847
}
1848+
#endif /* CONFIG_BT_LL_EXTENDED_FEAT_SET */
18021849

18031850
#if defined(CONFIG_BT_DATA_LEN_UPDATE)
18041851
static void le_data_len_change(struct net_buf *buf)
@@ -2922,6 +2969,11 @@ static const struct event_handler meta_events[] = {
29222969
EVENT_HANDLER(BT_HCI_EVT_LE_ENH_CONN_COMPLETE_V2, le_enh_conn_complete_v2,
29232970
sizeof(struct bt_hci_evt_le_enh_conn_complete_v2)),
29242971
#endif /* CONFIG_BT_PER_ADV_RSP || CONFIG_BT_PER_ADV_SYNC_RSP */
2972+
#if defined(CONFIG_BT_LL_EXTENDED_FEAT_SET)
2973+
EVENT_HANDLER(BT_HCI_EVT_LE_READ_ALL_REMOTE_FEAT_COMPLETE,
2974+
le_read_all_remote_feat_complete,
2975+
sizeof(struct bt_hci_evt_le_read_all_remote_feat_complete)),
2976+
#endif /* CONFIG_BT_LL_EXTENDED_FEAT_SET */
29252977
#endif /* CONFIG_BT_CONN */
29262978
#if defined(CONFIG_BT_CHANNEL_SOUNDING)
29272979
EVENT_HANDLER(BT_HCI_EVT_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE,
@@ -3158,9 +3210,46 @@ static void read_le_features_complete(struct net_buf *buf)
31583210

31593211
LOG_DBG("status 0x%02x %s", rp->status, bt_hci_err_to_str(rp->status));
31603212

3213+
memcpy(bt_dev.le.features, rp->features, sizeof(rp->features));
3214+
}
3215+
3216+
static void read_le_all_supported_features_complete(struct net_buf *buf)
3217+
{
3218+
struct bt_hci_rp_le_read_all_local_supported_features *rp = (void *)buf->data;
3219+
3220+
LOG_DBG("status 0x%02x %s", rp->status, bt_hci_err_to_str(rp->status));
3221+
31613222
memcpy(bt_dev.le.features, rp->features, sizeof(bt_dev.le.features));
31623223
}
31633224

3225+
static int read_le_local_supported_features(void)
3226+
{
3227+
struct net_buf *rsp;
3228+
int err;
3229+
3230+
/* Read Low Energy Supported Features */
3231+
if (IS_ENABLED(CONFIG_BT_LL_EXTENDED_FEAT_SET)) {
3232+
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_ALL_LOCAL_SUPPORTED_FEATURES, NULL,
3233+
&rsp);
3234+
if (err) {
3235+
return err;
3236+
}
3237+
3238+
read_le_all_supported_features_complete(rsp);
3239+
} else {
3240+
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_LOCAL_FEATURES, NULL,
3241+
&rsp);
3242+
if (err) {
3243+
return err;
3244+
}
3245+
3246+
read_le_features_complete(rsp);
3247+
}
3248+
3249+
net_buf_unref(rsp);
3250+
return 0;
3251+
}
3252+
31643253
#if defined(CONFIG_BT_CONN)
31653254
#if !defined(CONFIG_BT_CLASSIC)
31663255
static void read_buffer_size_complete(struct net_buf *buf)
@@ -3445,6 +3534,11 @@ static int le_set_event_mask(void)
34453534
BT_FEAT_LE_CONN_SUBRATING(bt_dev.le.features)) {
34463535
mask |= BT_EVT_MASK_LE_SUBRATE_CHANGE;
34473536
}
3537+
3538+
if (IS_ENABLED(CONFIG_BT_LL_EXTENDED_FEAT_SET) &&
3539+
BT_FEAT_LE_LL_EXTENDED_FEAT_SET(bt_dev.le.features)) {
3540+
mask |= BT_EVT_MASK_LE_READ_ALL_REMOTE_FEAT_COMPLTETE;
3541+
}
34483542
}
34493543

34503544
if (IS_ENABLED(CONFIG_BT_SMP) &&
@@ -3583,16 +3677,11 @@ static int le_init(void)
35833677
return -ENODEV;
35843678
}
35853679

3586-
/* Read Low Energy Supported Features */
3587-
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_LOCAL_FEATURES, NULL,
3588-
&rsp);
3680+
err = read_le_local_supported_features();
35893681
if (err) {
35903682
return err;
35913683
}
35923684

3593-
read_le_features_complete(rsp);
3594-
net_buf_unref(rsp);
3595-
35963685
if (IS_ENABLED(CONFIG_BT_ISO) &&
35973686
BT_FEAT_LE_ISO(bt_dev.le.features)) {
35983687
err = le_init_iso();

subsys/bluetooth/host/hci_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ void bt_hci_le_per_adv_response_report(struct net_buf *buf);
577577

578578
int bt_hci_read_remote_version(struct bt_conn *conn);
579579
int bt_hci_le_read_remote_features(struct bt_conn *conn);
580+
int bt_hci_le_read_all_remote_features(struct bt_conn *conn);
580581
int bt_hci_le_read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time);
581582

582583
bool bt_drv_quirk_no_auto_dle(void);

subsys/bluetooth/host/shell/bt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,7 @@ static void remote_info_available(struct bt_conn *conn,
934934
}
935935

936936
if (info.type == BT_CONN_TYPE_LE) {
937-
uint8_t features[8];
937+
uint8_t features[BT_LE_LOCAL_SUPPORTED_FEATURES_SIZE];
938938
char features_str[2 * sizeof(features) + 1];
939939

940940
sys_memcpy_swap(features, remote_info->le.features,

0 commit comments

Comments
 (0)