bluetooth: host: HCI support for CS configuration

Adds following HCI support for CS configuration:
- LE CS Create Config command
- LE CS Remove Config command
- LE CS Config Complete event

Two callbacks have been added to notify the application
when a new CS configuration is created or an existing
CS configuration is removed.

Signed-off-by: Burak Gorduk <burak.gorduk@nordicsemi.no>
This commit is contained in:
Burak Gorduk 2024-09-24 10:53:43 +01:00 committed by Carles Cufí
commit 7b82214d29
10 changed files with 749 additions and 96 deletions

View file

@ -413,6 +413,131 @@ struct bt_conn_le_cs_fae_table {
uint8_t *remote_fae_table; uint8_t *remote_fae_table;
}; };
/** Channel sounding main mode */
enum bt_conn_le_cs_main_mode {
/** Mode-1 (RTT) */
BT_CONN_LE_CS_MAIN_MODE_1 = BT_HCI_OP_LE_CS_MAIN_MODE_1,
/** Mode-2 (PBR) */
BT_CONN_LE_CS_MAIN_MODE_2 = BT_HCI_OP_LE_CS_MAIN_MODE_2,
/** Mode-3 (RTT and PBR) */
BT_CONN_LE_CS_MAIN_MODE_3 = BT_HCI_OP_LE_CS_MAIN_MODE_3,
};
/** Channel sounding sub mode */
enum bt_conn_le_cs_sub_mode {
/** Unused */
BT_CONN_LE_CS_SUB_MODE_UNUSED = BT_HCI_OP_LE_CS_SUB_MODE_UNUSED,
/** Mode-1 (RTT) */
BT_CONN_LE_CS_SUB_MODE_1 = BT_HCI_OP_LE_CS_SUB_MODE_1,
/** Mode-2 (PBR) */
BT_CONN_LE_CS_SUB_MODE_2 = BT_HCI_OP_LE_CS_SUB_MODE_2,
/** Mode-3 (RTT and PBR) */
BT_CONN_LE_CS_SUB_MODE_3 = BT_HCI_OP_LE_CS_SUB_MODE_3,
};
/** Channel sounding role */
enum bt_conn_le_cs_role {
/** CS initiator role */
BT_CONN_LE_CS_ROLE_INITIATOR,
/** CS reflector role */
BT_CONN_LE_CS_ROLE_REFLECTOR,
};
/** Channel sounding RTT type */
enum bt_conn_le_cs_rtt_type {
/** RTT AA only */
BT_CONN_LE_CS_RTT_TYPE_AA_ONLY = BT_HCI_OP_LE_CS_RTT_TYPE_AA_ONLY,
/** RTT with 32-bit sounding sequence */
BT_CONN_LE_CS_RTT_TYPE_32_BIT_SOUNDING = BT_HCI_OP_LE_CS_RTT_TYPE_32BIT_SOUND,
/** RTT with 96-bit sounding sequence */
BT_CONN_LE_CS_RTT_TYPE_96_BIT_SOUNDING = BT_HCI_OP_LE_CS_RTT_TYPE_96BIT_SOUND,
/** RTT with 32-bit random sequence */
BT_CONN_LE_CS_RTT_TYPE_32_BIT_RANDOM = BT_HCI_OP_LE_CS_RTT_TYPE_32BIT_RAND,
/** RTT with 64-bit random sequence */
BT_CONN_LE_CS_RTT_TYPE_64_BIT_RANDOM = BT_HCI_OP_LE_CS_RTT_TYPE_64BIT_RAND,
/** RTT with 96-bit random sequence */
BT_CONN_LE_CS_RTT_TYPE_96_BIT_RANDOM = BT_HCI_OP_LE_CS_RTT_TYPE_96BIT_RAND,
/** RTT with 128-bit random sequence */
BT_CONN_LE_CS_RTT_TYPE_128_BIT_RANDOM = BT_HCI_OP_LE_CS_RTT_TYPE_128BIT_RAND,
};
/** Channel sounding PHY used for CS sync */
enum bt_conn_le_cs_sync_phy {
/** LE 1M PHY */
BT_CONN_LE_CS_SYNC_1M_PHY = BT_HCI_OP_LE_CS_CS_SYNC_1M,
/** LE 2M PHY */
BT_CONN_LE_CS_SYNC_2M_PHY = BT_HCI_OP_LE_CS_CS_SYNC_2M,
/** LE 2M 2BT PHY */
BT_CONN_LE_CS_SYNC_2M_2BT_PHY = BT_HCI_OP_LE_CS_CS_SYNC_2M_2BT,
};
/** Channel sounding channel selection type */
enum bt_conn_le_cs_chsel_type {
/** Use Channel Selection Algorithm #3b for non-mode-0 CS steps */
BT_CONN_LE_CS_CHSEL_TYPE_3B = BT_HCI_OP_LE_CS_TEST_CHSEL_TYPE_3B,
/** Use Channel Selection Algorithm #3c for non-mode-0 CS steps */
BT_CONN_LE_CS_CHSEL_TYPE_3C = BT_HCI_OP_LE_CS_TEST_CHSEL_TYPE_3C,
};
/** Channel sounding channel sequence shape */
enum bt_conn_le_cs_ch3c_shape {
/** Use Hat shape for user-specified channel sequence */
BT_CONN_LE_CS_CH3C_SHAPE_HAT = BT_HCI_OP_LE_CS_TEST_CH3C_SHAPE_HAT,
/** Use X shape for user-specified channel sequence */
BT_CONN_LE_CS_CH3C_SHAPE_X = BT_HCI_OP_LE_CS_TEST_CH3C_SHAPE_X,
};
/** Channel sounding configuration */
struct bt_conn_le_cs_config {
/** CS configuration ID */
uint8_t id;
/** Main CS mode type */
enum bt_conn_le_cs_main_mode main_mode_type;
/** Sub CS mode type */
enum bt_conn_le_cs_sub_mode sub_mode_type;
/** Minimum number of CS main mode steps to be executed before a submode step is executed */
uint8_t min_main_mode_steps;
/** Maximum number of CS main mode steps to be executed before a submode step is executed */
uint8_t max_main_mode_steps;
/** Number of main mode steps taken from the end of the last CS subevent to be repeated
* at the beginning of the current CS subevent directly after the last mode-0 step of that
* event
*/
uint8_t main_mode_repetition;
/** Number of CS mode-0 steps to be included at the beginning of each CS subevent */
uint8_t mode_0_steps;
/** CS role */
enum bt_conn_le_cs_role role;
/** RTT type */
enum bt_conn_le_cs_rtt_type rtt_type;
/** CS Sync PHY */
enum bt_conn_le_cs_sync_phy cs_sync_phy;
/** The number of times the Channel_Map field will be cycled through for non-mode-0 steps
* within a CS procedure
*/
uint8_t channel_map_repetition;
/** Channel selection type */
enum bt_conn_le_cs_chsel_type channel_selection_type;
/** User-specified channel sequence shape */
enum bt_conn_le_cs_ch3c_shape ch3c_shape;
/** Number of channels skipped in each rising and falling sequence */
uint8_t ch3c_jump;
/** Interlude time in microseconds between the RTT packets */
uint8_t t_ip1_time_us;
/** Interlude time in microseconds between the CS tones */
uint8_t t_ip2_time_us;
/** Time in microseconds for frequency changes */
uint8_t t_fcs_time_us;
/** Time in microseconds for the phase measurement period of the CS tones */
uint8_t t_pm_time_us;
/** Channel map used for CS procedure
* Channels n = 0, 1, 23, 24, 25, 77, and 78 are not allowed and shall be set to zero.
* Channel 79 is reserved for future use and shall be set to zero.
* At least 15 channels shall be enabled.
*/
uint8_t channel_map[10];
};
/** @brief Increment a connection's reference count. /** @brief Increment a connection's reference count.
* *
* Increment the reference count of a connection object. * Increment the reference count of a connection object.
@ -1532,6 +1657,26 @@ struct bt_conn_cb {
*/ */
void (*remote_cs_fae_table_available)(struct bt_conn *conn, void (*remote_cs_fae_table_available)(struct bt_conn *conn,
struct bt_conn_le_cs_fae_table *params); struct bt_conn_le_cs_fae_table *params);
/** @brief LE CS Config created.
*
* This callback notifies the application that a Channel Sounding
* Configuration procedure has completed and a new CS config is created
*
* @param conn Connection object.
* @param config CS configuration.
*/
void (*le_cs_config_created)(struct bt_conn *conn, struct bt_conn_le_cs_config *config);
/** @brief LE CS Config removed.
*
* This callback notifies the application that a Channel Sounding
* Configuration procedure has completed and a CS config is removed
*
* @param conn Connection object.
* @param config_id ID of the CS configuration that was removed.
*/
void (*le_cs_config_removed)(struct bt_conn *conn, uint8_t config_id);
#endif #endif
/** @internal Internally used field for list handling */ /** @internal Internally used field for list handling */

View file

@ -27,6 +27,26 @@
extern "C" { extern "C" {
#endif #endif
/**
* @brief Macro for getting a specific channel bit in CS channel map
*
* @param[in] chmap Channel map array
* @param[in] bit Bit number to be accessed
*
* @return Bit value, either 1 or 0
*/
#define BT_LE_CS_CHANNEL_BIT_GET(chmap, bit) (((chmap)[(bit) / 8] >> ((bit) % 8)) & 1)
/**
* @brief Macro for setting a specific channel bit value in CS channel map
*
* @param[in] chmap Channel map array
* @param[in] bit Bit number to be accessed
* @param[in] val Bit value to be set, either 1 or 0
*/
#define BT_LE_CS_CHANNEL_BIT_SET_VAL(chmap, bit, val) \
((chmap)[(bit) / 8] = ((chmap)[(bit) / 8] & ~BIT((bit) % 8)) | ((val) << ((bit) % 8)))
enum bt_cs_sync_antenna_selection_opt { enum bt_cs_sync_antenna_selection_opt {
/** Use antenna identifier 1 for CS_SYNC packets. */ /** Use antenna identifier 1 for CS_SYNC packets. */
BT_CS_ANTENNA_SELECTION_OPT_ONE = BT_HCI_OP_LE_CS_ANTENNA_SEL_ONE, BT_CS_ANTENNA_SELECTION_OPT_ONE = BT_HCI_OP_LE_CS_ANTENNA_SEL_ONE,
@ -60,59 +80,6 @@ struct bt_cs_set_default_settings_param {
int8_t max_tx_power; int8_t max_tx_power;
}; };
/** CS Test Main Mode */
enum bt_cs_test_main_mode {
/** CS Test Mode-1 */
BT_CS_TEST_MAIN_MODE_1 = BT_HCI_OP_LE_CS_MAIN_MODE_1,
/** CS Test Mode-2 */
BT_CS_TEST_MAIN_MODE_2 = BT_HCI_OP_LE_CS_MAIN_MODE_2,
/** CS Test Mode-3 */
BT_CS_TEST_MAIN_MODE_3 = BT_HCI_OP_LE_CS_MAIN_MODE_3,
};
/** CS Test Sub-Mode */
enum bt_cs_test_sub_mode {
/** CS Test sub-mode-1 */
BT_CS_TEST_SUB_MODE_1 = BT_HCI_OP_LE_CS_SUB_MODE_1,
/** CS Test sub-mode-2 */
BT_CS_TEST_SUB_MODE_2 = BT_HCI_OP_LE_CS_SUB_MODE_2,
/** CS Test sub-mode-3 */
BT_CS_TEST_SUB_MODE_3 = BT_HCI_OP_LE_CS_SUB_MODE_3,
/** No CS Test sub-mode. */
BT_CS_TEST_SUB_MODE_UNUSED = BT_HCI_OP_LE_CS_SUB_MODE_UNUSED,
};
/** CS Test Role */
enum bt_cs_test_role {
BT_CS_TEST_ROLE_INITIATOR = BT_HCI_OP_LE_CS_INITIATOR_ROLE,
BT_CS_TEST_ROLE_REFLECTOR = BT_HCI_OP_LE_CS_REFLECTOR_ROLE,
};
/** CS Test RTT type */
enum bt_cs_test_rtt_type {
/** RTT AA Only */
BT_CS_TEST_RTT_AA_ONLY = BT_HCI_OP_LE_CS_RTT_TYPE_AA_ONLY,
/** RTT with 32-bit sounding sequence */
BT_CS_TEST_RTT_32_BIT_SOUNDING = BT_HCI_OP_LE_CS_RTT_TYPE_32BIT_SOUND,
/** RTT with 96-bit sounding sequence */
BT_CS_TEST_RTT_96_BIT_SOUNDING = BT_HCI_OP_LE_CS_RTT_TYPE_96BIT_SOUND,
/** RTT with 32-bit random sequence */
BT_CS_TEST_RTT_32_BIT_RANDOM = BT_HCI_OP_LE_CS_RTT_TYPE_32BIT_RAND,
/** RTT with 64-bit random sequence */
BT_CS_TEST_RTT_64_BIT_RANDOM = BT_HCI_OP_LE_CS_RTT_TYPE_64BIT_RAND,
/** RTT with 96-bit random sequence */
BT_CS_TEST_RTT_96_BIT_RANDOM = BT_HCI_OP_LE_CS_RTT_TYPE_96BIT_RAND,
/** RTT with 128-bit random sequence */
BT_CS_TEST_RTT_128_BIT_RANDOM = BT_HCI_OP_LE_CS_RTT_TYPE_128BIT_RAND,
};
/** CS Test CS_SYNC PHY */
enum bt_cs_test_cs_sync_phy {
BT_CS_TEST_CS_SYNC_LE_1M_PHY = BT_HCI_OP_LE_CS_CS_SYNC_1M,
BT_CS_TEST_CS_SYNC_LE_2M_PHY = BT_HCI_OP_LE_CS_CS_SYNC_2M,
BT_CS_TEST_CS_SYNC_LE_2M_2BT_PHY = BT_HCI_OP_LE_CS_CS_SYNC_2M_2BT,
};
/** CS Test CS_SYNC Antenna Identifier */ /** CS Test CS_SYNC Antenna Identifier */
enum bt_cs_test_cs_sync_antenna_selection { enum bt_cs_test_cs_sync_antenna_selection {
BT_CS_TEST_CS_SYNC_ANTENNA_SELECTION_ONE = BT_HCI_OP_LE_CS_ANTENNA_SEL_ONE, BT_CS_TEST_CS_SYNC_ANTENNA_SELECTION_ONE = BT_HCI_OP_LE_CS_ANTENNA_SEL_ONE,
@ -179,18 +146,6 @@ enum bt_cs_test_reflector_snr_control {
BT_CS_TEST_REFLECTOR_SNR_CONTROL_NOT_USED = BT_HCI_OP_LE_CS_TEST_REFLECTOR_SNR_NOT_USED, BT_CS_TEST_REFLECTOR_SNR_CONTROL_NOT_USED = BT_HCI_OP_LE_CS_TEST_REFLECTOR_SNR_NOT_USED,
}; };
/** CS Test Override 0 channel selection algorithm selection */
enum bt_cs_test_override_0_chsel_alg {
BT_CS_TEST_OVERRIDE_0_CHSEL_ALG_3B = BT_HCI_OP_LE_CS_TEST_CHSEL_TYPE_3B,
BT_CS_TEST_OVERRIDE_0_CHSEL_ALG_3C = BT_HCI_OP_LE_CS_TEST_CHSEL_TYPE_3C,
};
/** CS Test Override 0 chsel #3c shape */
enum bt_cs_test_override_0_ch3c_shape {
BT_CS_TEST_OVERRIDE_0_CHSEL_ALG_3C_HAT_SHAPE = BT_HCI_OP_LE_CS_TEST_CH3C_SHAPE_HAT,
BT_CS_TEST_OVERRIDE_0_CHSEL_ALG_3C_X_SHAPE = BT_HCI_OP_LE_CS_TEST_CH3C_SHAPE_X,
};
/** CS Test Override 3 T_PM Tone Extension */ /** CS Test Override 3 T_PM Tone Extension */
enum bt_cs_test_override_3_pm_tone_ext { enum bt_cs_test_override_3_pm_tone_ext {
/** Initiator and reflector tones sent without tone extension */ /** Initiator and reflector tones sent without tone extension */
@ -336,9 +291,9 @@ enum bt_cs_test_override_8_cs_sync_payload_pattern {
/** CS Test parameters */ /** CS Test parameters */
struct bt_cs_test_param { struct bt_cs_test_param {
/** CS mode to be used during the CS procedure. */ /** CS mode to be used during the CS procedure. */
enum bt_cs_test_main_mode main_mode; enum bt_conn_le_cs_main_mode main_mode;
/** CS sub-mode to be used during the CS procedure. */ /** CS sub-mode to be used during the CS procedure. */
enum bt_cs_test_sub_mode sub_mode; enum bt_conn_le_cs_sub_mode sub_mode;
/** Number of main mode steps taken from the end of the last CS subevent /** Number of main mode steps taken from the end of the last CS subevent
* to be repeated at the beginning of the current CS subevent directly * to be repeated at the beginning of the current CS subevent directly
* after the last mode-0 step of that event. * after the last mode-0 step of that event.
@ -347,11 +302,11 @@ struct bt_cs_test_param {
/** Number of CS mode-0 steps at the beginning of the test CS subevent. */ /** Number of CS mode-0 steps at the beginning of the test CS subevent. */
uint8_t mode_0_steps; uint8_t mode_0_steps;
/** CS Test role */ /** CS Test role */
enum bt_cs_test_role role; enum bt_conn_le_cs_role role;
/** RTT variant */ /** RTT variant */
enum bt_cs_test_rtt_type rtt_type; enum bt_conn_le_cs_rtt_type rtt_type;
/** CS_SYNC PHY */ /** CS_SYNC PHY */
enum bt_cs_test_cs_sync_phy cs_sync_phy; enum bt_conn_le_cs_sync_phy cs_sync_phy;
/** Antenna identifier to be used for CS_SYNC packets. */ /** Antenna identifier to be used for CS_SYNC packets. */
enum bt_cs_test_cs_sync_antenna_selection cs_sync_antenna_selection; enum bt_cs_test_cs_sync_antenna_selection cs_sync_antenna_selection;
/** CS subevent length in microseconds. /** CS subevent length in microseconds.
@ -436,8 +391,8 @@ struct bt_cs_test_param {
} set; } set;
struct { struct {
uint8_t channel_map[10]; uint8_t channel_map[10];
enum bt_cs_test_override_0_chsel_alg channel_selection_type; enum bt_conn_le_cs_chsel_type channel_selection_type;
enum bt_cs_test_override_0_ch3c_shape ch3c_shape; enum bt_conn_le_cs_ch3c_shape ch3c_shape;
uint8_t ch3c_jump; uint8_t ch3c_jump;
} not_set; } not_set;
}; };
@ -470,12 +425,13 @@ struct bt_cs_test_param {
struct { struct {
/** Bit number where the first marker in the channel sounding sequence starts. /** Bit number where the first marker in the channel sounding sequence starts.
* *
* Must be between 0 and 28 when using @ref BT_CS_TEST_RTT_32_BIT_SOUNDING. * Must be between 0 and 28 when using @ref BT_CONN_LE_CS_RTT_TYPE_32_BIT_SOUNDING.
*/ */
uint8_t ss_marker1_position; uint8_t ss_marker1_position;
/** Bit number where the second marker in the channel sounding sequence starts. /** Bit number where the second marker in the channel sounding sequence starts.
* *
* Must be between 67 and 92 when using @ref BT_CS_TEST_RTT_96_BIT_SOUNDING. * Must be between 67 and 92 when using @ref
* BT_CONN_LE_CS_RTT_TYPE_96_BIT_SOUNDING.
* *
* A value of @ref BT_HCI_OP_LE_CS_TEST_SS_MARKER_2_POSITION_NOT_PRESENT * A value of @ref BT_HCI_OP_LE_CS_TEST_SS_MARKER_2_POSITION_NOT_PRESENT
* indicates that this sounding sequence or marker is not present. * indicates that this sounding sequence or marker is not present.
@ -506,6 +462,68 @@ struct bt_cs_test_param {
} override_config_8; } override_config_8;
}; };
/** CS config creation context */
enum bt_le_cs_create_config_context {
/** Write CS configuration in local Controller only */
BT_LE_CS_CREATE_CONFIG_CONTEXT_LOCAL_ONLY,
/** Write CS configuration in both local and remote Controller using Channel Sounding
* Configuration procedure
*/
BT_LE_CS_CREATE_CONFIG_CONTEXT_LOCAL_AND_REMOTE
};
/** CS Create Config params */
struct bt_le_cs_create_config_params {
/** CS configuration ID */
uint8_t id;
/** Main CS mode type */
enum bt_conn_le_cs_main_mode main_mode_type;
/** Sub CS mode type */
enum bt_conn_le_cs_sub_mode sub_mode_type;
/** Minimum number of CS main mode steps to be executed before a submode step is executed */
uint8_t min_main_mode_steps;
/** Maximum number of CS main mode steps to be executed before a submode step is executed */
uint8_t max_main_mode_steps;
/** Number of main mode steps taken from the end of the last CS subevent to be repeated
* at the beginning of the current CS subevent directly after the last mode-0 step of that
* event
*/
uint8_t main_mode_repetition;
/** Number of CS mode-0 steps to be included at the beginning of each CS subevent */
uint8_t mode_0_steps;
/** CS role */
enum bt_conn_le_cs_role role;
/** RTT type */
enum bt_conn_le_cs_rtt_type rtt_type;
/** CS Sync PHY */
enum bt_conn_le_cs_sync_phy cs_sync_phy;
/** The number of times the Channel_Map field will be cycled through for non-mode-0 steps
* within a CS procedure
*/
uint8_t channel_map_repetition;
/** Channel selection type */
enum bt_conn_le_cs_chsel_type channel_selection_type;
/** User-specified channel sequence shape */
enum bt_conn_le_cs_ch3c_shape ch3c_shape;
/** Number of channels skipped in each rising and falling sequence */
uint8_t ch3c_jump;
/** Channel map used for CS procedure
* Channels n = 0, 1, 23, 24, 25, 77, and 78 are not allowed and shall be set to zero.
* Channel 79 is reserved for future use and shall be set to zero.
* At least 15 channels shall be enabled.
*/
uint8_t channel_map[10];
};
/** @brief Set all valid channel map bits
*
* This command is used to enable all valid channels in a
* given CS channel map
*
* @param channel_map Chanel map
*/
void bt_le_cs_set_valid_chmap_bits(uint8_t channel_map[10]);
/** @brief Read Remote Supported Capabilities /** @brief Read Remote Supported Capabilities
* *
* This command is used to query the CS capabilities that are supported * This command is used to query the CS capabilities that are supported
@ -569,6 +587,37 @@ int bt_cs_read_remote_fae_table(struct bt_conn *conn);
*/ */
int bt_cs_start_test(const struct bt_cs_test_param *params); int bt_cs_start_test(const struct bt_cs_test_param *params);
/** @brief Create CS configuration
*
* This command is used to create a new CS configuration or update an
* existing one with the config id specified.
*
* @note To use this API @kconfig{CONFIG_BT_CHANNEL_SOUNDING} must be set.
*
* @param conn Connection Object.
* @param params CS Create Config parameters
* @param context Controls whether the configuration is written to the local controller or
* both the local and the remote controller
*
* @return Zero on success or (negative) error code on failure.
*/
int bt_le_cs_create_config(struct bt_conn *conn, struct bt_le_cs_create_config_params *params,
enum bt_le_cs_create_config_context context);
/** @brief Create CS configuration
*
* This command is used to remove a CS configuration from the local controller
* identified by the config_id
*
* @note To use this API @kconfig{CONFIG_BT_CHANNEL_SOUNDING} must be set.
*
* @param conn Connection Object.
* @param config_id CS Config ID
*
* @return Zero on success or (negative) error code on failure.
*/
int bt_le_cs_remove_config(struct bt_conn *conn, uint8_t config_id);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -2582,6 +2582,36 @@ struct bt_hci_op_le_cs_test {
uint8_t override_parameters_data[]; uint8_t override_parameters_data[];
} __packed; } __packed;
#define BT_HCI_OP_LE_CS_CREATE_CONFIG BT_OP(BT_OGF_LE, 0x0090) /* 0x2090 */
struct bt_hci_cp_le_cs_create_config {
uint16_t handle;
uint8_t config_id;
uint8_t create_context;
uint8_t main_mode_type;
uint8_t sub_mode_type;
uint8_t min_main_mode_steps;
uint8_t max_main_mode_steps;
uint8_t main_mode_repetition;
uint8_t mode_0_steps;
uint8_t role;
uint8_t rtt_type;
uint8_t cs_sync_phy;
uint8_t channel_map[10];
uint8_t channel_map_repetition;
uint8_t channel_selection_type;
uint8_t ch3c_shape;
uint8_t ch3c_jump;
uint8_t reserved;
} __packed;
#define BT_HCI_OP_LE_CS_REMOVE_CONFIG BT_OP(BT_OGF_LE, 0x0091) /* 0x2091 */
struct bt_hci_cp_le_cs_remove_config {
uint16_t handle;
uint8_t config_id;
} __packed;
/* Event definitions */ /* Event definitions */
#define BT_HCI_EVT_UNKNOWN 0x00 #define BT_HCI_EVT_UNKNOWN 0x00
@ -3403,6 +3433,36 @@ struct bt_hci_evt_le_cs_read_remote_fae_table_complete {
uint8_t remote_fae_table[72]; uint8_t remote_fae_table[72];
} __packed; } __packed;
#define BT_HCI_LE_CS_CONFIG_ACTION_REMOVED 0x00
#define BT_HCI_LE_CS_CONFIG_ACTION_CREATED 0x01
#define BT_HCI_EVT_LE_CS_CONFIG_COMPLETE 0x2F
struct bt_hci_evt_le_cs_config_complete {
uint8_t status;
uint16_t handle;
uint8_t config_id;
uint8_t action;
uint8_t main_mode_type;
uint8_t sub_mode_type;
uint8_t min_main_mode_steps;
uint8_t max_main_mode_steps;
uint8_t main_mode_repetition;
uint8_t mode_0_steps;
uint8_t role;
uint8_t rtt_type;
uint8_t cs_sync_phy;
uint8_t channel_map[10];
uint8_t channel_map_repetition;
uint8_t channel_selection_type;
uint8_t ch3c_shape;
uint8_t ch3c_jump;
uint8_t reserved;
uint8_t t_ip1_time;
uint8_t t_ip2_time;
uint8_t t_fcs_time;
uint8_t t_pm_time;
} __packed;
/* Event mask bits */ /* Event mask bits */
#define BT_EVT_BIT(n) (1ULL << (n)) #define BT_EVT_BIT(n) (1ULL << (n))
@ -3494,6 +3554,7 @@ struct bt_hci_evt_le_cs_read_remote_fae_table_complete {
#define BT_EVT_MASK_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE BT_EVT_BIT(43) #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_READ_REMOTE_FAE_TABLE_COMPLETE BT_EVT_BIT(44)
#define BT_EVT_MASK_LE_CS_CONFIG_COMPLETE BT_EVT_BIT(46)
/** HCI Error Codes, BT Core Spec v5.4 [Vol 1, Part F]. */ /** HCI Error Codes, BT Core Spec v5.4 [Vol 1, Part F]. */
#define BT_HCI_ERR_SUCCESS 0x00 #define BT_HCI_ERR_SUCCESS 0x00

View file

@ -3354,6 +3354,40 @@ void notify_remote_cs_fae_table(struct bt_conn *conn, struct bt_conn_le_cs_fae_t
} }
} }
} }
void notify_cs_config_created(struct bt_conn *conn, struct bt_conn_le_cs_config *params)
{
struct bt_conn_cb *callback;
SYS_SLIST_FOR_EACH_CONTAINER(&conn_cbs, callback, _node) {
if (callback->le_cs_config_created) {
callback->le_cs_config_created(conn, params);
}
}
STRUCT_SECTION_FOREACH(bt_conn_cb, cb) {
if (cb->le_cs_config_created) {
cb->le_cs_config_created(conn, params);
}
}
}
void notify_cs_config_removed(struct bt_conn *conn, uint8_t config_id)
{
struct bt_conn_cb *callback;
SYS_SLIST_FOR_EACH_CONTAINER(&conn_cbs, callback, _node) {
if (callback->le_cs_config_removed) {
callback->le_cs_config_removed(conn, config_id);
}
}
STRUCT_SECTION_FOREACH(bt_conn_cb, cb) {
if (cb->le_cs_config_removed) {
cb->le_cs_config_removed(conn, config_id);
}
}
}
#endif /* CONFIG_BT_CHANNEL_SOUNDING */ #endif /* CONFIG_BT_CHANNEL_SOUNDING */
int bt_conn_le_param_update(struct bt_conn *conn, int bt_conn_le_param_update(struct bt_conn *conn,

View file

@ -498,6 +498,10 @@ void notify_remote_cs_capabilities(struct bt_conn *conn,
void notify_remote_cs_fae_table(struct bt_conn *conn, void notify_remote_cs_fae_table(struct bt_conn *conn,
struct bt_conn_le_cs_fae_table params); struct bt_conn_le_cs_fae_table params);
void notify_cs_config_created(struct bt_conn *conn, struct bt_conn_le_cs_config *params);
void notify_cs_config_removed(struct bt_conn *conn, uint8_t config_id);
#if defined(CONFIG_BT_SMP) #if defined(CONFIG_BT_SMP)
/* If role specific LTK is present */ /* If role specific LTK is present */
bool bt_conn_ltk_present(const struct bt_conn *conn); bool bt_conn_ltk_present(const struct bt_conn *conn);

View file

@ -18,6 +18,24 @@
LOG_MODULE_REGISTER(bt_cs); LOG_MODULE_REGISTER(bt_cs);
#if defined(CONFIG_BT_CHANNEL_SOUNDING) #if defined(CONFIG_BT_CHANNEL_SOUNDING)
void bt_le_cs_set_valid_chmap_bits(uint8_t channel_map[10])
{
memset(channel_map, 0xFF, 10);
/** Channels n = 0, 1, 23, 24, 25, 77, and 78 are not allowed and shall be set to zero.
* Channel 79 is reserved for future use and shall be set to zero.
*/
BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 0, 0);
BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 1, 0);
BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 23, 0);
BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 24, 0);
BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 25, 0);
BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 77, 0);
BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 78, 0);
BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 79, 0);
}
int bt_cs_read_remote_supported_capabilities(struct bt_conn *conn) int bt_cs_read_remote_supported_capabilities(struct bt_conn *conn)
{ {
struct bt_hci_cp_le_read_remote_supported_capabilities *cp; struct bt_hci_cp_le_read_remote_supported_capabilities *cp;
@ -326,4 +344,107 @@ int bt_cs_start_test(const struct bt_cs_test_param *params)
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_TEST, buf, NULL); return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_TEST, buf, NULL);
} }
void bt_hci_le_cs_config_complete_event(struct net_buf *buf)
{
struct bt_hci_evt_le_cs_config_complete *evt;
struct bt_conn_le_cs_config config;
struct bt_conn *conn;
if (buf->len < sizeof(*evt)) {
LOG_ERR("Unexpected end of buffer");
return;
}
evt = net_buf_pull_mem(buf, sizeof(*evt));
if (evt->status) {
LOG_INF("CS Config failed (status 0x%02X)", evt->status);
return;
}
conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->handle), BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Could not lookup connection handle when reading CS configuration");
return;
}
if (evt->action == BT_HCI_LE_CS_CONFIG_ACTION_REMOVED) {
notify_cs_config_removed(conn, evt->config_id);
bt_conn_unref(conn);
return;
}
config.id = evt->config_id;
config.main_mode_type = evt->main_mode_type;
config.sub_mode_type = evt->sub_mode_type;
config.min_main_mode_steps = evt->min_main_mode_steps;
config.max_main_mode_steps = evt->max_main_mode_steps;
config.main_mode_repetition = evt->main_mode_repetition;
config.mode_0_steps = evt->mode_0_steps;
config.role = evt->role;
config.rtt_type = evt->rtt_type;
config.cs_sync_phy = evt->cs_sync_phy;
config.channel_map_repetition = evt->channel_map_repetition;
config.channel_selection_type = evt->channel_selection_type;
config.ch3c_shape = evt->ch3c_shape;
config.ch3c_jump = evt->ch3c_jump;
config.t_ip1_time_us = evt->t_ip1_time;
config.t_ip2_time_us = evt->t_ip2_time;
config.t_fcs_time_us = evt->t_fcs_time;
config.t_pm_time_us = evt->t_pm_time;
memcpy(config.channel_map, evt->channel_map, ARRAY_SIZE(config.channel_map));
notify_cs_config_created(conn, &config);
bt_conn_unref(conn);
}
int bt_le_cs_create_config(struct bt_conn *conn, struct bt_le_cs_create_config_params *params,
enum bt_le_cs_create_config_context context)
{
struct bt_hci_cp_le_cs_create_config *cp;
struct net_buf *buf;
buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_CREATE_CONFIG, sizeof(*cp));
if (!buf) {
return -ENOBUFS;
}
cp = net_buf_add(buf, sizeof(*cp));
cp->handle = sys_cpu_to_le16(conn->handle);
cp->config_id = params->id;
cp->create_context = context;
cp->main_mode_type = params->main_mode_type;
cp->sub_mode_type = params->sub_mode_type;
cp->min_main_mode_steps = params->min_main_mode_steps;
cp->max_main_mode_steps = params->max_main_mode_steps;
cp->main_mode_repetition = params->main_mode_repetition;
cp->mode_0_steps = params->mode_0_steps;
cp->role = params->role;
cp->rtt_type = params->rtt_type;
cp->cs_sync_phy = params->cs_sync_phy;
cp->channel_map_repetition = params->channel_map_repetition;
cp->channel_selection_type = params->channel_selection_type;
cp->ch3c_shape = params->ch3c_shape;
cp->ch3c_jump = params->ch3c_jump;
cp->reserved = 0;
memcpy(cp->channel_map, params->channel_map, ARRAY_SIZE(cp->channel_map));
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_CREATE_CONFIG, buf, NULL);
}
int bt_le_cs_remove_config(struct bt_conn *conn, uint8_t config_id)
{
struct bt_hci_cp_le_cs_remove_config *cp;
struct net_buf *buf;
buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_REMOVE_CONFIG, sizeof(*cp));
if (!buf) {
return -ENOBUFS;
}
cp = net_buf_add(buf, sizeof(*cp));
cp->handle = sys_cpu_to_le16(conn->handle);
cp->config_id = config_id;
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_REMOVE_CONFIG, buf, NULL);
}
#endif /* CONFIG_BT_CHANNEL_SOUNDING */ #endif /* CONFIG_BT_CHANNEL_SOUNDING */

View file

@ -2828,6 +2828,8 @@ static const struct event_handler meta_events[] = {
EVENT_HANDLER(BT_HCI_EVT_LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE, EVENT_HANDLER(BT_HCI_EVT_LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE,
bt_hci_le_cs_read_remote_fae_table_complete, bt_hci_le_cs_read_remote_fae_table_complete,
sizeof(struct bt_hci_evt_le_cs_read_remote_fae_table_complete)), sizeof(struct bt_hci_evt_le_cs_read_remote_fae_table_complete)),
EVENT_HANDLER(BT_HCI_EVT_LE_CS_CONFIG_COMPLETE, bt_hci_le_cs_config_complete_event,
sizeof(struct bt_hci_evt_le_cs_config_complete)),
#endif /* CONFIG_BT_CHANNEL_SOUNDING */ #endif /* CONFIG_BT_CHANNEL_SOUNDING */
}; };
@ -3404,6 +3406,7 @@ static int le_set_event_mask(void)
BT_FEAT_LE_CHANNEL_SOUNDING(bt_dev.le.features)) { BT_FEAT_LE_CHANNEL_SOUNDING(bt_dev.le.features)) {
mask |= BT_EVT_MASK_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE; mask |= BT_EVT_MASK_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE;
mask |= BT_EVT_MASK_LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE; mask |= BT_EVT_MASK_LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE;
mask |= BT_EVT_MASK_LE_CS_CONFIG_COMPLETE;
} }
sys_put_le64(mask, cp_mask->events); sys_put_le64(mask, cp_mask->events);

View file

@ -541,6 +541,7 @@ void bt_hci_le_past_received_v2(struct net_buf *buf);
/* CS HCI event handlers */ /* CS HCI event handlers */
void bt_hci_le_cs_read_remote_supported_capabilities_complete(struct net_buf *buf); void bt_hci_le_cs_read_remote_supported_capabilities_complete(struct net_buf *buf);
void bt_hci_le_cs_read_remote_fae_table_complete(struct net_buf *buf); void bt_hci_le_cs_read_remote_fae_table_complete(struct net_buf *buf);
void bt_hci_le_cs_config_complete_event(struct net_buf *buf);
/* Adv HCI event handlers */ /* Adv HCI event handlers */
void bt_hci_le_adv_set_terminated(struct net_buf *buf); void bt_hci_le_adv_set_terminated(struct net_buf *buf);

View file

@ -1068,6 +1068,64 @@ void print_remote_cs_fae_table(struct bt_conn *conn, struct bt_conn_le_cs_fae_ta
shell_print(ctx_shell, "Received FAE Table: "); shell_print(ctx_shell, "Received FAE Table: ");
shell_hexdump(ctx_shell, params->remote_fae_table, 72); shell_hexdump(ctx_shell, params->remote_fae_table, 72);
} }
static void le_cs_config_created(struct bt_conn *conn, struct bt_conn_le_cs_config *config)
{
const char *mode_str[5] = {"Unused", "1 (RTT)", "2 (PBR)", "3 (RTT + PBR)", "Invalid"};
const char *role_str[3] = {"Initiator", "Reflector", "Invalid"};
const char *rtt_type_str[8] = {"AA only", "32-bit sounding", "96-bit sounding",
"32-bit random", "64-bit random", "96-bit random",
"128-bit random", "Invalid"};
const char *phy_str[4] = {"Invalid", "LE 1M PHY", "LE 2M PHY", "LE 2M 2BT PHY"};
const char *chsel_type_str[3] = {"Algorithm #3b", "Algorithm #3c", "Invalid"};
const char *ch3c_shape_str[3] = {"Hat shape", "X shape", "Invalid"};
uint8_t main_mode_idx = config->main_mode_type > 0 && config->main_mode_type < 4
? config->main_mode_type
: 4;
uint8_t sub_mode_idx = config->sub_mode_type < 4 ? config->sub_mode_type : 0;
uint8_t role_idx = MIN(config->role, 2);
uint8_t rtt_type_idx = MIN(config->rtt_type, 7);
uint8_t phy_idx =
config->cs_sync_phy > 0 && config->cs_sync_phy < 4 ? config->cs_sync_phy : 0;
uint8_t chsel_type_idx = MIN(config->channel_selection_type, 2);
uint8_t ch3c_shape_idx = MIN(config->ch3c_shape, 2);
shell_print(ctx_shell,
"New CS config created:\n"
"- ID: %d\n"
"- Role: %s\n"
"- Main mode: %s\n"
"- Sub mode: %s\n"
"- RTT type: %s\n"
"- Main mode steps: %d - %d\n"
"- Main mode repetition: %d\n"
"- Mode 0 steps: %d\n"
"- CS sync PHY: %s\n"
"- T_IP1 time: %d\n"
"- T_IP2 time: %d\n"
"- T_FCS time: %d\n"
"- T_PM time: %d\n"
"- Channel map: 0x%08X%08X%04X\n"
"- Channel map repetition: %d\n"
"- Channel selection type: %s\n"
"- Ch3c shape: %s\n"
"- Ch3c jump: %d\n",
config->id, role_str[role_idx], mode_str[main_mode_idx], mode_str[sub_mode_idx],
rtt_type_str[rtt_type_idx], config->min_main_mode_steps,
config->max_main_mode_steps, config->main_mode_repetition, config->mode_0_steps,
phy_str[phy_idx], config->t_ip1_time_us, config->t_ip2_time_us,
config->t_fcs_time_us, config->t_pm_time_us,
sys_get_le32(&config->channel_map[6]), sys_get_le32(&config->channel_map[2]),
sys_get_le16(&config->channel_map[0]), config->channel_map_repetition,
chsel_type_str[chsel_type_idx], ch3c_shape_str[ch3c_shape_idx],
config->ch3c_jump);
}
static void le_cs_config_removed(struct bt_conn *conn, uint8_t config_id)
{
shell_print(ctx_shell, "CS config %d is removed", config_id);
}
#endif #endif
static struct bt_conn_cb conn_callbacks = { static struct bt_conn_cb conn_callbacks = {
@ -1102,6 +1160,8 @@ static struct bt_conn_cb conn_callbacks = {
#if defined(CONFIG_BT_CHANNEL_SOUNDING) #if defined(CONFIG_BT_CHANNEL_SOUNDING)
.remote_cs_capabilities_available = print_remote_cs_capabilities, .remote_cs_capabilities_available = print_remote_cs_capabilities,
.remote_cs_fae_table_available = print_remote_cs_fae_table, .remote_cs_fae_table_available = print_remote_cs_fae_table,
.le_cs_config_created = le_cs_config_created,
.le_cs_config_removed = le_cs_config_removed,
#endif #endif
}; };
#endif /* CONFIG_BT_CONN */ #endif /* CONFIG_BT_CONN */

View file

@ -139,8 +139,8 @@ static int cmd_cs_test_simple(const struct shell *sh, size_t argc, char *argv[])
int err = 0; int err = 0;
struct bt_cs_test_param params; struct bt_cs_test_param params;
params.main_mode = BT_CS_TEST_MAIN_MODE_1; params.main_mode = BT_CONN_LE_CS_MAIN_MODE_1;
params.sub_mode = BT_CS_TEST_SUB_MODE_UNUSED; params.sub_mode = BT_CONN_LE_CS_SUB_MODE_UNUSED;
params.main_mode_repetition = 0; params.main_mode_repetition = 0;
params.mode_0_steps = 0x1; params.mode_0_steps = 0x1;
@ -152,14 +152,15 @@ static int cmd_cs_test_simple(const struct shell *sh, size_t argc, char *argv[])
return SHELL_CMD_HELP_PRINTED; return SHELL_CMD_HELP_PRINTED;
} }
if (params.role != BT_CS_TEST_ROLE_INITIATOR && params.role != BT_CS_TEST_ROLE_REFLECTOR) { if (params.role != BT_CONN_LE_CS_ROLE_INITIATOR &&
params.role != BT_CONN_LE_CS_ROLE_REFLECTOR) {
shell_help(sh); shell_help(sh);
shell_error(sh, "Role selection input invalid"); shell_error(sh, "Role selection input invalid");
return SHELL_CMD_HELP_PRINTED; return SHELL_CMD_HELP_PRINTED;
} }
params.rtt_type = BT_CS_TEST_RTT_AA_ONLY; params.rtt_type = BT_CONN_LE_CS_RTT_TYPE_AA_ONLY;
params.cs_sync_phy = BT_CS_TEST_CS_SYNC_LE_1M_PHY; params.cs_sync_phy = BT_CONN_LE_CS_SYNC_1M_PHY;
params.cs_sync_antenna_selection = BT_CS_TEST_CS_SYNC_ANTENNA_SELECTION_ONE; params.cs_sync_antenna_selection = BT_CS_TEST_CS_SYNC_ANTENNA_SELECTION_ONE;
params.subevent_len = 10000; params.subevent_len = 10000;
params.subevent_interval = 0; params.subevent_interval = 0;
@ -177,12 +178,10 @@ static int cmd_cs_test_simple(const struct shell *sh, size_t argc, char *argv[])
params.override_config = 0; params.override_config = 0;
params.override_config_0.channel_map_repetition = 1; params.override_config_0.channel_map_repetition = 1;
memset(params.override_config_0.not_set.channel_map, 0, memset(params.override_config_0.not_set.channel_map, 0,
sizeof(params.override_config_0.not_set.channel_map)); sizeof(params.override_config_0.not_set.channel_map));
params.override_config_0.not_set.channel_map[1] = 0xFF; params.override_config_0.not_set.channel_map[1] = 0xFF;
params.override_config_0.not_set.channel_selection_type = params.override_config_0.not_set.channel_selection_type = BT_CONN_LE_CS_CHSEL_TYPE_3B;
BT_CS_TEST_OVERRIDE_0_CHSEL_ALG_3B; params.override_config_0.not_set.ch3c_shape = BT_CONN_LE_CS_CH3C_SHAPE_HAT;
params.override_config_0.not_set.ch3c_shape =
BT_CS_TEST_OVERRIDE_0_CHSEL_ALG_3C_HAT_SHAPE;
params.override_config_0.not_set.ch3c_jump = 0x2; params.override_config_0.not_set.ch3c_jump = 0x2;
err = bt_cs_start_test(&params); err = bt_cs_start_test(&params);
@ -194,26 +193,202 @@ static int cmd_cs_test_simple(const struct shell *sh, size_t argc, char *argv[])
return 0; return 0;
} }
static int cmd_remove_config(const struct shell *sh, size_t argc, char *argv[])
{
int err = 0;
if (default_conn == NULL) {
shell_error(sh, "Conn handle error, at least one connection is required.");
return -ENOEXEC;
}
uint8_t config_id = strtoul(argv[1], NULL, 10);
err = bt_le_cs_remove_config(default_conn, config_id);
if (err) {
shell_error(sh, "bt_cs_remove_config returned error %d", err);
return -ENOEXEC;
}
return 0;
}
static int cmd_create_config(const struct shell *sh, size_t argc, char *argv[])
{
int err = 0;
enum bt_le_cs_create_config_context context;
struct bt_le_cs_create_config_params params;
if (default_conn == NULL) {
shell_error(sh, "Conn handle error, at least one connection is required.");
return -ENOEXEC;
}
params.id = strtoul(argv[1], NULL, 10);
if (!strcmp(argv[2], "local-only")) {
context = BT_LE_CS_CREATE_CONFIG_CONTEXT_LOCAL_ONLY;
} else if (!strcmp(argv[2], "local-only")) {
context = BT_LE_CS_CREATE_CONFIG_CONTEXT_LOCAL_AND_REMOTE;
} else {
shell_error(sh, "Invalid context: %s", argv[2]);
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}
if (!strcmp(argv[3], "initiator")) {
params.role = BT_CONN_LE_CS_ROLE_INITIATOR;
} else if (!strcmp(argv[3], "reflector")) {
params.role = BT_CONN_LE_CS_ROLE_REFLECTOR;
} else {
shell_error(sh, "Invalid role: %s", argv[3]);
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}
/* Set the default values */
params.main_mode_type = BT_CONN_LE_CS_MAIN_MODE_2;
params.sub_mode_type = BT_CONN_LE_CS_SUB_MODE_1;
params.min_main_mode_steps = 0x05;
params.max_main_mode_steps = 0x0A;
params.main_mode_repetition = 0;
params.mode_0_steps = 1;
params.rtt_type = BT_CONN_LE_CS_RTT_TYPE_AA_ONLY;
params.cs_sync_phy = BT_CONN_LE_CS_SYNC_2M_PHY;
params.channel_map_repetition = 1;
params.channel_selection_type = BT_CONN_LE_CS_CHSEL_TYPE_3B;
params.ch3c_shape = BT_CONN_LE_CS_CH3C_SHAPE_HAT;
params.ch3c_jump = 2;
bt_le_cs_set_valid_chmap_bits(params.channel_map);
for (int j = 4; j < argc; j++) {
if (!strcmp(argv[j], "rtt-none")) {
params.main_mode_type = BT_CONN_LE_CS_MAIN_MODE_1;
params.sub_mode_type = BT_CONN_LE_CS_SUB_MODE_UNUSED;
} else if (!strcmp(argv[j], "pbr-none")) {
params.main_mode_type = BT_CONN_LE_CS_MAIN_MODE_2;
params.sub_mode_type = BT_CONN_LE_CS_SUB_MODE_UNUSED;
} else if (!strcmp(argv[j], "both-none")) {
params.main_mode_type = BT_CONN_LE_CS_MAIN_MODE_3;
params.sub_mode_type = BT_CONN_LE_CS_SUB_MODE_UNUSED;
} else if (!strcmp(argv[j], "pbr-rtt")) {
params.main_mode_type = BT_CONN_LE_CS_MAIN_MODE_2;
params.sub_mode_type = BT_CONN_LE_CS_SUB_MODE_1;
} else if (!strcmp(argv[j], "pbr-both")) {
params.main_mode_type = BT_CONN_LE_CS_MAIN_MODE_2;
params.sub_mode_type = BT_CONN_LE_CS_SUB_MODE_3;
} else if (!strcmp(argv[j], "both-pbr")) {
params.main_mode_type = BT_CONN_LE_CS_MAIN_MODE_3;
params.sub_mode_type = BT_CONN_LE_CS_SUB_MODE_2;
} else if (!strcmp(argv[j], "steps")) {
if (++j == argc) {
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}
params.min_main_mode_steps = strtoul(argv[j], NULL, 10);
if (++j == argc) {
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}
params.max_main_mode_steps = strtoul(argv[j], NULL, 10);
if (++j == argc) {
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}
params.mode_0_steps = strtoul(argv[j], NULL, 10);
} else if (!strcmp(argv[j], "aa-only")) {
params.rtt_type = BT_CONN_LE_CS_RTT_TYPE_AA_ONLY;
} else if (!strcmp(argv[j], "32b-sound")) {
params.rtt_type = BT_CONN_LE_CS_RTT_TYPE_32_BIT_SOUNDING;
} else if (!strcmp(argv[j], "96b-sound")) {
params.rtt_type = BT_CONN_LE_CS_RTT_TYPE_96_BIT_SOUNDING;
} else if (!strcmp(argv[j], "32b-rand")) {
params.rtt_type = BT_CONN_LE_CS_RTT_TYPE_32_BIT_RANDOM;
} else if (!strcmp(argv[j], "64b-rand")) {
params.rtt_type = BT_CONN_LE_CS_RTT_TYPE_64_BIT_RANDOM;
} else if (!strcmp(argv[j], "96b-rand")) {
params.rtt_type = BT_CONN_LE_CS_RTT_TYPE_96_BIT_RANDOM;
} else if (!strcmp(argv[j], "128b-rand")) {
params.rtt_type = BT_CONN_LE_CS_RTT_TYPE_128_BIT_RANDOM;
} else if (!strcmp(argv[j], "phy-1m")) {
params.cs_sync_phy = BT_CONN_LE_CS_SYNC_1M_PHY;
} else if (!strcmp(argv[j], "phy-2m")) {
params.cs_sync_phy = BT_CONN_LE_CS_SYNC_2M_PHY;
} else if (!strcmp(argv[j], "phy-2m-2b")) {
params.cs_sync_phy = BT_CONN_LE_CS_SYNC_2M_2BT_PHY;
} else if (!strcmp(argv[j], "chmap-rep")) {
if (++j == argc) {
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}
params.channel_map_repetition = strtoul(argv[j], NULL, 10);
} else if (!strcmp(argv[j], "hat-shape")) {
params.ch3c_shape = BT_CONN_LE_CS_CH3C_SHAPE_HAT;
} else if (!strcmp(argv[j], "x-shape")) {
params.ch3c_shape = BT_CONN_LE_CS_CH3C_SHAPE_X;
} else if (!strcmp(argv[j], "chsel-3b")) {
params.channel_selection_type = BT_CONN_LE_CS_CHSEL_TYPE_3B;
} else if (!strcmp(argv[j], "chsel-3c")) {
params.channel_selection_type = BT_CONN_LE_CS_CHSEL_TYPE_3C;
} else if (!strcmp(argv[j], "ch3c-jump")) {
if (++j == argc) {
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}
params.ch3c_jump = strtoul(argv[j], NULL, 10);
} else if (!strcmp(argv[j], "chmap")) {
if (++j == argc) {
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}
if (hex2bin(argv[j], strlen(argv[j]), params.channel_map, 10) == 0) {
shell_error(sh, "Invalid channel map");
return -ENOEXEC;
}
sys_mem_swap(params.channel_map, 10);
} else {
shell_help(sh);
return SHELL_CMD_HELP_PRINTED;
}
}
err = bt_le_cs_create_config(default_conn, &params, context);
if (err) {
shell_error(sh, "bt_cs_create_config returned error %d", err);
return -ENOEXEC;
}
return 0;
}
SHELL_STATIC_SUBCMD_SET_CREATE( SHELL_STATIC_SUBCMD_SET_CREATE(
cs_cmds, cs_cmds,
SHELL_CMD_ARG( SHELL_CMD_ARG(read_remote_supported_capabilities, NULL, "<None>",
read_remote_supported_capabilities, NULL, cmd_read_remote_supported_capabilities, 1, 0),
"<None>",
cmd_read_remote_supported_capabilities, 1, 0),
SHELL_CMD_ARG( SHELL_CMD_ARG(
set_default_settings, NULL, set_default_settings, NULL,
"<Enable initiator role: true, false> <Enable reflector role: true, false> " "<Enable initiator role: true, false> <Enable reflector role: true, false> "
" <CS_SYNC antenna selection: 0x01 - 0x04, 0xFE, 0xFF> <Max TX power: -127 - 20>", " <CS_SYNC antenna selection: 0x01 - 0x04, 0xFE, 0xFF> <Max TX power: -127 - 20>",
cmd_set_default_settings, 5, 0), cmd_set_default_settings, 5, 0),
SHELL_CMD_ARG(read_remote_fae_table, NULL, "<None>", cmd_read_remote_fae_table, 1, 0),
SHELL_CMD_ARG(start_simple_cs_test, NULL, "<Role selection (initiator, reflector): 0, 1>",
cmd_cs_test_simple, 2, 0),
SHELL_CMD_ARG( SHELL_CMD_ARG(
read_remote_fae_table, NULL, create_config, NULL,
"<None>", "<id> <context: local-only, local-remote> <role: initiator, reflector> "
cmd_read_remote_fae_table, 1, 0), "[rtt-none, pbr-none, both-none, pbr-rtt, pbr-both, both-pbr] [steps <min> "
SHELL_CMD_ARG( "<max> <mode-0>] [aa-only, 32b-sound, 96b-sound, 32b-rand, 64b-rand, 96b-rand, "
start_simple_cs_test, NULL, "128b-rand] [phy-1m, phy-2m, phy-2m-2b] [chmap-rep <rep>] [hat-shape, x-shape] "
"<Role selection (initiator, reflector): 0, 1>", "[ch3c-jump <jump>] [chmap <XXXXXXXXXXXXXXXX>] (78-0) [chsel-3b, chsel-3c]",
cmd_cs_test_simple, 2, 0), cmd_create_config, 4, 15),
SHELL_SUBCMD_SET_END); SHELL_CMD_ARG(remove_config, NULL, "<id>", cmd_remove_config, 2, 0), SHELL_SUBCMD_SET_END);
static int cmd_cs(const struct shell *sh, size_t argc, char **argv) static int cmd_cs(const struct shell *sh, size_t argc, char **argv)
{ {