Skip to content

bluetooth: host: Add extended feature set support #92856

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions include/zephyr/bluetooth/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/addr.h>
#include <zephyr/bluetooth/crypto.h>
#include <zephyr/bluetooth/hci_types.h>
#include <zephyr/bluetooth/classic/classic.h>
#include <zephyr/net_buf.h>
#include <zephyr/sys/slist.h>
Expand Down Expand Up @@ -71,11 +72,16 @@ extern "C" {
#define BT_ID_DEFAULT 0

/**
* @brief Number of octets for local supported
* @brief Number of octets for local supported features
*
* The value of 8 correspond to page 0 in the LE Controller supported features
* The value of 8 correspond to page 0 in the LE Controller supported features.
* 24 bytes are required for all subsequent supported feature pages.
*/
#define BT_LE_LOCAL_SUPPORTED_FEATURES_SIZE 8
#define BT_LE_LOCAL_SUPPORTED_FEATURES_SIZE \
(BT_HCI_LE_BYTES_PAGE_0_FEATURE_PAGE + \
COND_CODE_1(CONFIG_BT_LE_MAX_LOCAL_SUPPORTED_FEATURE_PAGE, \
CONFIG_BT_LE_MAX_LOCAL_SUPPORTED_FEATURE_PAGE * BT_HCI_LE_BYTES_PER_FEATURE_PAGE, \
(0U)))

/** Opaque type representing an advertiser. */
struct bt_le_ext_adv;
Expand Down
58 changes: 58 additions & 0 deletions include/zephyr/bluetooth/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,27 @@ struct bt_conn_le_subrate_changed {
uint16_t supervision_timeout;
};

/** Read all remote features complete callback params */
struct bt_conn_le_read_all_remote_feat_complete {
/** @brief HCI Status from LE Read All Remote Features Complete event.
*
* The remaining parameters will be unchanged if status is not @ref BT_HCI_ERR_SUCCESS.
*/
uint8_t status;
/** Number of pages supported by remote device. */
uint8_t max_remote_page;
/** Number of pages fetched from remote device. */
uint8_t max_valid_page;
/** @brief Pointer to array of size 248, with feature bits of remote supported features.
*
* Page 0 being 8 bytes, with the following 10 pages of 24 bytes.
* Refer to BT_LE_FEAT_BIT_* for values.
* Refer to the BT_FEAT_LE_* macros for value comparison.
* See Bluetooth Core Specification, Vol 6, Part B, Section 4.6.
*/
const uint8_t *features;
};

/** Connection Type */
enum __packed bt_conn_type {
/** LE Connection Type */
Expand Down Expand Up @@ -1186,6 +1207,24 @@ int bt_conn_le_subrate_set_defaults(const struct bt_conn_le_subrate_param *param
int bt_conn_le_subrate_request(struct bt_conn *conn,
const struct bt_conn_le_subrate_param *params);

/** @brief Read remote feature pages.
*
* Request remote feature pages, from 0 up to pages_requested or the number
* of pages supported by the peer. There is a maximum of 10 pages.
* This function will trigger the read_all_remote_feat_complete callback
* when the procedure is completed.
*
* @kconfig_dep{CONFIG_BT_LE_EXTENDED_FEAT_SET}
*
* @param conn @ref BT_CONN_TYPE_LE connection object.
* @param pages_requested Number of feature pages to be requested from peer.
* There is a maximum of 10 pages.
*
* @return Zero on success or (negative) error code on failure.
* @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection.
*/
int bt_conn_le_read_all_remote_features(struct bt_conn *conn, uint8_t pages_requested);

/** @brief Update the connection parameters.
*
* If the local device is in the peripheral role then updating the connection
Expand Down Expand Up @@ -1877,6 +1916,25 @@ struct bt_conn_cb {
const struct bt_conn_le_subrate_changed *params);
#endif /* CONFIG_BT_SUBRATING */

#if defined(CONFIG_BT_LE_EXTENDED_FEAT_SET)
/** @brief Read all remote features complete event.
*
* This callback notifies the application that a 'read all remote
* features' procedure of the connection is completed. The other params
* will not be populated if status is not @ref BT_HCI_ERR_SUCCESS.
*
* This callback can be triggered by calling @ref
* bt_conn_le_read_all_remote_features or by the procedure running
* autonomously in the controller.
*
* @param conn Connection object.
* @param params Remote features.
*/
void (*read_all_remote_feat_complete)(
struct bt_conn *conn,
const struct bt_conn_le_read_all_remote_feat_complete *params);
#endif /* CONFIG_BT_LE_EXTENDED_FEAT_SET */

#if defined(CONFIG_BT_CHANNEL_SOUNDING)
/** @brief LE CS Read Remote Supported Capabilities Complete event.
*
Expand Down
36 changes: 35 additions & 1 deletion include/zephyr/bluetooth/hci_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ struct bt_hci_cmd_hdr {
#define BT_LE_FEAT_BIT_CHANNEL_SOUNDING 46
#define BT_LE_FEAT_BIT_CHANNEL_SOUNDING_HOST 47
#define BT_LE_FEAT_BIT_CHANNEL_SOUNDING_TONE_QUAL_IND 48
#define BT_LE_FEAT_BIT_LL_EXTENDED_FEAT_SET 63
#define BT_LE_FEAT_BIT_EXTENDED_FEAT_SET 63

#define BT_LE_FEAT_TEST(feat, n) (feat[(n) >> 3] & \
BIT((n) & 7))
Expand Down Expand Up @@ -284,6 +284,8 @@ struct bt_hci_cmd_hdr {
BT_LE_FEAT_BIT_CHANNEL_SOUNDING)
#define BT_FEAT_LE_CHANNEL_SOUNDING_HOST(feat) BT_LE_FEAT_TEST(feat, \
BT_LE_FEAT_BIT_CHANNEL_SOUNDING_HOST)
#define BT_FEAT_LE_EXTENDED_FEAT_SET(feat) BT_LE_FEAT_TEST(feat, \
BT_LE_FEAT_BIT_EXTENDED_FEAT_SET)

#define BT_FEAT_LE_CIS(feat) (BT_FEAT_LE_CIS_CENTRAL(feat) | \
BT_FEAT_LE_CIS_PERIPHERAL(feat))
Expand Down Expand Up @@ -2438,6 +2440,22 @@ struct bt_hci_cp_le_tx_test_v4 {
uint8_t ant_ids[0];
} __packed;

#define BT_HCI_OP_LE_READ_ALL_LOCAL_SUPPORTED_FEATURES BT_OP(BT_OGF_LE, 0x0087) /* 0x2087 */
struct bt_hci_rp_le_read_all_local_supported_features {
uint8_t status;
uint8_t max_page;
uint8_t features[248];
} __packed;

#define BT_READ_ALL_LOCAL_FEATURES_SUPPORTED(supported_commands) \
BT_CMD_TEST(supported_commands, 47, 2)

#define BT_HCI_OP_LE_READ_ALL_REMOTE_FEATURES BT_OP(BT_OGF_LE, 0x0088) /* 0x2088 */
struct bt_hci_cp_le_read_all_remote_features {
uint16_t handle;
uint8_t pages_requested;
} __packed;

#define BT_HCI_TX_TEST_POWER_MIN -0x7F
#define BT_HCI_TX_TEST_POWER_MAX 0x14

Expand Down Expand Up @@ -3552,6 +3570,20 @@ struct bt_hci_evt_le_cis_established_v2 {
uint8_t framing;
} __packed;

#define BT_HCI_EVT_LE_READ_ALL_REMOTE_FEAT_COMPLETE 0x2b

#define BT_HCI_LE_FEATURE_PAGE_MAX 10
#define BT_HCI_LE_BYTES_PER_FEATURE_PAGE 24
#define BT_HCI_LE_BYTES_PAGE_0_FEATURE_PAGE 8

struct bt_hci_evt_le_read_all_remote_feat_complete {
uint8_t status;
uint16_t handle;
uint8_t max_remote_page;
uint8_t max_valid_page;
uint8_t features[248];
} __packed;

#define BT_HCI_LE_CS_INITIATOR_ROLE_MASK BIT(0)
#define BT_HCI_LE_CS_REFLECTOR_ROLE_MASK BIT(1)

Expand Down Expand Up @@ -4024,6 +4056,8 @@ struct bt_hci_evt_le_cs_procedure_enable_complete {
#define BT_EVT_MASK_LE_ENH_CONN_COMPLETE_V2 BT_EVT_BIT(40)
#define BT_EVT_MASK_LE_CIS_ESTABLISHED_V2 BT_EVT_BIT(41)

#define BT_EVT_MASK_LE_READ_ALL_REMOTE_FEAT_COMPLETE BT_EVT_BIT(42)

#define BT_EVT_MASK_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE BT_EVT_BIT(43)
#define BT_EVT_MASK_LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE BT_EVT_BIT(44)
#define BT_EVT_MASK_LE_CS_SECURITY_ENABLE_COMPLETE BT_EVT_BIT(45)
Expand Down
15 changes: 15 additions & 0 deletions subsys/bluetooth/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@ config BT_CONN_TX
help
Hidden configuration that is true if ACL or broadcast ISO is enabled

config BT_LE_MAX_LOCAL_SUPPORTED_FEATURE_PAGE
int "Maximum supported feature page"
default 0
range 0 10
depends on BT_LE_EXTENDED_FEAT_SET
help
Maximum supported feature page that can be stored locally and fetched
from the remote connection with the LL Extended Feature Set feature.

config BT_LE_EXTENDED_FEAT_SET
bool "LL Extended Feature Set"
depends on !HAS_BT_CTLR || BT_CTLR_EXTENDED_FEAT_SET_SUPPORT
help
Enable support for the LL Extended Feature Set feature.

if BT_CONN
config BT_HCI_ACL_FLOW_CONTROL
bool "Controller to Host ACL flow control support"
Expand Down
2 changes: 1 addition & 1 deletion subsys/bluetooth/common/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ config BT_BUF_ACL_RX_COUNT

config BT_BUF_EVT_RX_SIZE
int "Maximum supported HCI Event buffer length"
default $(UINT8_MAX) if (BT_EXT_ADV && BT_OBSERVER) || BT_PER_ADV_SYNC || BT_DF_CONNECTION_CTE_RX || BT_CLASSIC || BT_CHANNEL_SOUNDING
default $(UINT8_MAX) if (BT_EXT_ADV && BT_OBSERVER) || BT_PER_ADV_SYNC || BT_DF_CONNECTION_CTE_RX || BT_CLASSIC || BT_CHANNEL_SOUNDING || BT_LE_EXTENDED_FEAT_SET
# LE Read Supported Commands command complete event.
default 68
range 68 $(UINT8_MAX)
Expand Down
11 changes: 11 additions & 0 deletions subsys/bluetooth/controller/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ config BT_CTLR_SUBRATING_SUPPORT
config BT_CTLR_CHANNEL_SOUNDING_SUPPORT
bool

config BT_CTLR_EXTENDED_FEAT_SET_SUPPORT
bool

# Virtual option that all local LL implementations should select
config HAS_BT_CTLR
bool
Expand Down Expand Up @@ -1174,6 +1177,14 @@ config BT_CTLR_CHANNEL_SOUNDING
Enable support for Bluetooth 6.0 Channel Sounding in the
Controller.

config BT_CTLR_EXTENDED_FEAT_SET
bool "LL Extended Feature Set support"
depends on BT_CTLR_EXTENDED_FEAT_SET_SUPPORT
default y if BT_LE_EXTENDED_FEAT_SET
help
Enable support for Bluetooth 6.0 LL Extended Feature Set
in the Controller.

rsource "Kconfig.df"
rsource "Kconfig.ll_sw_split"
rsource "Kconfig.dtm"
Expand Down
47 changes: 47 additions & 0 deletions subsys/bluetooth/host/conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -3289,6 +3289,53 @@ int bt_conn_le_subrate_request(struct bt_conn *conn,
}
#endif /* CONFIG_BT_SUBRATING */

#if defined(CONFIG_BT_LE_EXTENDED_FEAT_SET)
void notify_read_all_remote_feat_complete(struct bt_conn *conn,
struct bt_conn_le_read_all_remote_feat_complete *params)
{
struct bt_conn_cb *callback;

SYS_SLIST_FOR_EACH_CONTAINER(&conn_cbs, callback, _node) {
if (callback->read_all_remote_feat_complete != NULL) {
callback->read_all_remote_feat_complete(conn, params);
}
}

STRUCT_SECTION_FOREACH(bt_conn_cb, cb)
{
if (cb->read_all_remote_feat_complete != NULL) {
cb->read_all_remote_feat_complete(conn, params);
}
}
}

int bt_conn_le_read_all_remote_features(struct bt_conn *conn, uint8_t pages_requested)
{
struct bt_hci_cp_le_read_all_remote_features *cp;
struct net_buf *buf;

if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) {
LOG_DBG("Invalid connection type: %u for %p", conn->type, conn);
return -EINVAL;
}

if (pages_requested > BT_HCI_LE_FEATURE_PAGE_MAX) {
return -EINVAL;
}

buf = bt_hci_cmd_alloc(K_FOREVER);
if (buf == NULL) {
return -ENOBUFS;
}

cp = net_buf_add(buf, sizeof(*cp));
cp->handle = sys_cpu_to_le16(conn->handle);
cp->pages_requested = pages_requested;

return bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_ALL_REMOTE_FEATURES, buf, NULL);
}
#endif /* CONFIG_BT_LE_EXTENDED_FEAT_SET */

#if defined(CONFIG_BT_CHANNEL_SOUNDING)
void notify_remote_cs_capabilities(struct bt_conn *conn, uint8_t status,
struct bt_conn_le_cs_capabilities *params)
Expand Down
3 changes: 3 additions & 0 deletions subsys/bluetooth/host/conn_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,9 @@ void notify_path_loss_threshold_report(struct bt_conn *conn,
void notify_subrate_change(struct bt_conn *conn,
struct bt_conn_le_subrate_changed params);

void notify_read_all_remote_feat_complete(struct bt_conn *conn,
struct bt_conn_le_read_all_remote_feat_complete *params);

void notify_remote_cs_capabilities(struct bt_conn *conn,
uint8_t status,
struct bt_conn_le_cs_capabilities *params);
Expand Down
Loading