diff --git a/include/zephyr/bluetooth/conn.h b/include/zephyr/bluetooth/conn.h index 50d68d58ef2..9bef1df7dc0 100644 --- a/include/zephyr/bluetooth/conn.h +++ b/include/zephyr/bluetooth/conn.h @@ -675,6 +675,24 @@ struct bt_conn_le_cs_capabilities { * - Bit 4: 30dB */ uint8_t tx_snr_capability; + /** Supported T_IP2_IPT time durations during CS steps. + * + * - Bit 0: 10 us + * - Bit 1: 20 us + * - Bit 2: 30 us + * - Bit 3: 40 us + * - Bit 4: 50 us + * - Bit 5: 60 us + * - Bit 6: 80 us + */ + uint16_t t_ip2_ipt_times_supported; + /** Supported time in microseconds for the antenna switch period of the + * CS tones during IPT. + * + * 0x00, 0x01, 0x02, 0x04, or 0x0A - Time in microseconds for the + * antenna switch period of the CS tones + */ + uint8_t t_sw_ipt_time_supported; }; /** Remote FAE Table for LE connections supporting CS */ @@ -825,6 +843,11 @@ struct bt_conn_le_cs_config { enum bt_conn_le_cs_ch3c_shape ch3c_shape; /** Number of channels skipped in each rising and falling sequence */ uint8_t ch3c_jump; + /** CS enhancements 1 + * Bit 0 - IPT is enabled in the CS reflector. + * All other bits are reserved and shall be set to 0. + */ + uint8_t cs_enhancements_1; /** Interlude time in microseconds between the RTT packets */ uint8_t t_ip1_time_us; /** Interlude time in microseconds between the CS tones */ diff --git a/include/zephyr/bluetooth/cs.h b/include/zephyr/bluetooth/cs.h index 06450c96201..601d51e1002 100644 --- a/include/zephyr/bluetooth/cs.h +++ b/include/zephyr/bluetooth/cs.h @@ -498,6 +498,12 @@ struct bt_le_cs_create_config_params { enum bt_conn_le_cs_rtt_type rtt_type; /** CS Sync PHY */ enum bt_conn_le_cs_sync_phy cs_sync_phy; + /** 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]; /** The number of times the Channel_Map field will be cycled through for non-mode-0 steps * within a CS procedure */ @@ -508,12 +514,8 @@ struct bt_le_cs_create_config_params { 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]; + /** CS enhancements 1 */ + uint8_t cs_enhancements_1; }; /** Callbacks for CS Test */ @@ -665,7 +667,7 @@ int bt_le_cs_start_test(const struct bt_le_cs_test_param *params); 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 +/** @brief Remove CS configuration * * This command is used to remove a CS configuration from the local controller * identified by the config_id @@ -852,6 +854,19 @@ int bt_le_cs_set_channel_classification(uint8_t channel_classification[10]); */ int bt_le_cs_read_local_supported_capabilities(struct bt_conn_le_cs_capabilities *ret); +/** @brief CS Read Local Supported Capabilities V2 + * + * This command is used to read the CS capabilities that are supported + * by the local Controller. + * + * @note To use this API @kconfig{CONFIG_BT_CHANNEL_SOUNDING} must be set. + * + * @param ret Return values for the CS Procedure Enable command. + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_le_cs_read_local_supported_capabilities_v2(struct bt_conn_le_cs_capabilities *ret); + /** @brief CS Write Cached Remote Supported Capabilities * * This command is used to write the cached copy of the CS capabilities @@ -868,6 +883,22 @@ int bt_le_cs_read_local_supported_capabilities(struct bt_conn_le_cs_capabilities int bt_le_cs_write_cached_remote_supported_capabilities( struct bt_conn *conn, const struct bt_conn_le_cs_capabilities *params); +/** @brief CS Write Cached Remote Supported Capabilities V2 + * + * This command is used to write the cached copy of the CS capabilities + * that are supported by the remote Controller for the connection + * identified. + * + * @note To use this API @kconfig{CONFIG_BT_CHANNEL_SOUNDING} must be set. + * + * @param conn Connection Object. + * @param params Parameters for the CS Write Cached Remote Supported Capabilities command. + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_le_cs_write_cached_remote_supported_capabilities_v2( + struct bt_conn *conn, const struct bt_conn_le_cs_capabilities *params); + /** @brief CS Write Cached Remote FAE Table * * This command is used to write a cached copy of the per-channel mode-0 diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index ce2aa428fa5..4ebd0ad59ad 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -2626,6 +2626,62 @@ struct bt_hci_rp_le_read_local_supported_capabilities { uint8_t tx_snr_capability; } __packed; +/** HCI opcode for LE Read Local Supported Capabilities (v2). */ +#define BT_HCI_OP_LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES_V2 BT_OP(BT_OGF_LE, 0x00A5) /* 0x20A5 */ +/** Test if LE Read Local Supported Capabilities v2 command is supported (octet 49, bit 2). */ +#define BT_LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES_V2_SUPPORTED(cmd) \ + BT_CMD_TEST(cmd, 49, 2) + +/** HCI response parameters for LE Read Local Supported Capabilities command (v2). */ +struct bt_hci_rp_le_read_local_supported_capabilities_v2 { + /** Status. */ + uint8_t status; + /** Number of CS configurations supported. */ + uint8_t num_config_supported; + /** Maximum consecutive procedures supported. */ + uint16_t max_consecutive_procedures_supported; + /** Number of antennas supported. */ + uint8_t num_antennas_supported; + /** Maximum antenna paths supported. */ + uint8_t max_antenna_paths_supported; + /** Roles supported. */ + uint8_t roles_supported; + /** Modes supported. */ + uint8_t modes_supported; + /** RTT capability. */ + uint8_t rtt_capability; + /** RTT AA-only N. */ + uint8_t rtt_aa_only_n; + /** RTT sounding N. */ + uint8_t rtt_sounding_n; + /** RTT random payload N. */ + uint8_t rtt_random_payload_n; + /** NADM sounding capability. */ + uint16_t nadm_sounding_capability; + /** NADM random capability. */ + uint16_t nadm_random_capability; + /** CS sync PHYs supported. */ + uint8_t cs_sync_phys_supported; + /** Subfeatures supported. */ + uint16_t subfeatures_supported; + /** T_IP1 times supported. */ + uint16_t t_ip1_times_supported; + /** T_IP2 times supported. */ + uint16_t t_ip2_times_supported; + /** T_FCS times supported. */ + uint16_t t_fcs_times_supported; + /** T_PM times supported. */ + uint16_t t_pm_times_supported; + /** T_SW time supported. */ + uint8_t t_sw_time_supported; + /** TX SNR capability. */ + uint8_t tx_snr_capability; + /** T_IP2 IPT times supported. */ + uint16_t t_ip2_ipt_times_supported; + /** T_SW IPT time supported. */ + uint8_t t_sw_ipt_time_supported; +} __packed; + #define BT_HCI_OP_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES BT_OP(BT_OGF_LE, 0x008A) /* 0x208A */ struct bt_hci_cp_le_read_remote_supported_capabilities { @@ -2659,6 +2715,60 @@ struct bt_hci_cp_le_write_cached_remote_supported_capabilities { uint8_t tx_snr_capability; } __packed; +/** HCI opcode for LE CS Write Cached Remote Supported Capabilities (v2). */ +#define BT_HCI_OP_LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES_V2 \ + BT_OP(BT_OGF_LE, 0x00A6) /* 0x20A6 */ + +/** HCI command parameters for LE CS Write Cached Remote Supported Capabilities (v2). */ +struct bt_hci_cp_le_write_cached_remote_supported_capabilities_v2 { + /** Connection handle. */ + uint16_t handle; + /** Number of CS configurations supported. */ + uint8_t num_config_supported; + /** Maximum consecutive procedures supported. */ + uint16_t max_consecutive_procedures_supported; + /** Number of antennas supported. */ + uint8_t num_antennas_supported; + /** Maximum antenna paths supported. */ + uint8_t max_antenna_paths_supported; + /** Roles supported. */ + uint8_t roles_supported; + /** Modes supported. */ + uint8_t modes_supported; + /** RTT capability. */ + uint8_t rtt_capability; + /** RTT AA-only N. */ + uint8_t rtt_aa_only_n; + /** RTT sounding N. */ + uint8_t rtt_sounding_n; + /** RTT random payload N. */ + uint8_t rtt_random_payload_n; + /** NADM sounding capability. */ + uint16_t nadm_sounding_capability; + /** NADM random capability. */ + uint16_t nadm_random_capability; + /** CS sync PHYs supported. */ + uint8_t cs_sync_phys_supported; + /** Subfeatures supported. */ + uint16_t subfeatures_supported; + /** T_IP1 times supported. */ + uint16_t t_ip1_times_supported; + /** T_IP2 times supported. */ + uint16_t t_ip2_times_supported; + /** T_FCS times supported. */ + uint16_t t_fcs_times_supported; + /** T_PM times supported. */ + uint16_t t_pm_times_supported; + /** T_SW time supported. */ + uint8_t t_sw_time_supported; + /** TX SNR capability. */ + uint8_t tx_snr_capability; + /** T_IP2 IPT times supported. */ + uint16_t t_ip2_ipt_times_supported; + /** T_SW IPT time supported. */ + uint8_t t_sw_ipt_time_supported; +} __packed; + #define BT_HCI_OP_LE_CS_SECURITY_ENABLE BT_OP(BT_OGF_LE, 0x008C) /* 0x208C */ struct bt_hci_cp_le_security_enable { @@ -2865,7 +2975,8 @@ struct bt_hci_op_le_cs_test { uint8_t t_pm_time; uint8_t t_sw_time; uint8_t tone_antenna_config_selection; - uint8_t reserved; + /** CS enhancements 1. */ + uint8_t cs_enhancements_1; uint8_t snr_control_initiator; uint8_t snr_control_reflector; uint16_t drbg_nonce; @@ -2895,7 +3006,8 @@ struct bt_hci_cp_le_cs_create_config { uint8_t channel_selection_type; uint8_t ch3c_shape; uint8_t ch3c_jump; - uint8_t reserved; + /** CS enhancements 1. */ + uint8_t cs_enhancements_1; } __packed; #define BT_HCI_OP_LE_CS_REMOVE_CONFIG BT_OP(BT_OGF_LE, 0x0091) /* 0x2091 */ @@ -3871,6 +3983,7 @@ struct bt_hci_evt_le_read_all_remote_feat_complete { #define BT_HCI_LE_CS_TX_SNR_CAPABILITY_30DB_MASK BIT(4) #define BT_HCI_EVT_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE 0x2C + struct bt_hci_evt_le_cs_read_remote_supported_capabilities_complete { uint8_t status; uint16_t conn_handle; @@ -3896,6 +4009,61 @@ struct bt_hci_evt_le_cs_read_remote_supported_capabilities_complete { uint8_t tx_snr_capability; } __packed; +/** HCI LE CS Read Remote Supported Capabilities Complete event (v2). */ +#define BT_HCI_EVT_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE_V2 0x38 + +/** HCI event parameters for LE CS Read Remote Supported Capabilities Complete (v2). */ +struct bt_hci_evt_le_cs_read_remote_supported_capabilities_complete_v2 { + /** Status. */ + uint8_t status; + /** Connection handle. */ + uint16_t conn_handle; + /** Number of CS configurations supported. */ + uint8_t num_config_supported; + /** Maximum consecutive procedures supported. */ + uint16_t max_consecutive_procedures_supported; + /** Number of antennas supported. */ + uint8_t num_antennas_supported; + /** Maximum antenna paths supported. */ + uint8_t max_antenna_paths_supported; + /** Roles supported. */ + uint8_t roles_supported; + /** Modes supported. */ + uint8_t modes_supported; + /** RTT capability. */ + uint8_t rtt_capability; + /** RTT AA-only N. */ + uint8_t rtt_aa_only_n; + /** RTT sounding N. */ + uint8_t rtt_sounding_n; + /** RTT random payload N. */ + uint8_t rtt_random_payload_n; + /** NADM sounding capability. */ + uint16_t nadm_sounding_capability; + /** NADM random capability. */ + uint16_t nadm_random_capability; + /** CS sync PHYs supported. */ + uint8_t cs_sync_phys_supported; + /** Subfeatures supported. */ + uint16_t subfeatures_supported; + /** T_IP1 times supported. */ + uint16_t t_ip1_times_supported; + /** T_IP2 times supported. */ + uint16_t t_ip2_times_supported; + /** T_FCS times supported. */ + uint16_t t_fcs_times_supported; + /** T_PM times supported. */ + uint16_t t_pm_times_supported; + /** T_SW time supported. */ + uint8_t t_sw_time_supported; + /** TX SNR capability. */ + uint8_t tx_snr_capability; + /** T_IP2 IPT times supported. */ + uint16_t t_ip2_ipt_times_supported; + /** T_SW IPT time supported. */ + uint8_t t_sw_ipt_time_supported; +} __packed; + #define BT_HCI_EVT_LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE 0x2D struct bt_hci_evt_le_cs_read_remote_fae_table_complete { uint8_t status; @@ -3932,7 +4100,8 @@ struct bt_hci_evt_le_cs_config_complete { uint8_t channel_selection_type; uint8_t ch3c_shape; uint8_t ch3c_jump; - uint8_t reserved; + /** CS enhancements 1. */ + uint8_t cs_enhancements_1; uint8_t t_ip1_time; uint8_t t_ip2_time; uint8_t t_fcs_time; @@ -4323,6 +4492,9 @@ struct bt_hci_evt_le_conn_rate_change { #define BT_EVT_MASK_LE_FRAME_SPACE_UPDATE_COMPLETE BT_EVT_BIT(52) #define BT_EVT_MASK_LE_CONN_RATE_CHANGE BT_EVT_BIT(54) +/** Event mask for LE CS Read Remote Supported Capabilities Complete (v2). */ +#define BT_EVT_MASK_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE_V2 BT_EVT_BIT(55) + /** HCI Error Codes, BT Core Spec v5.4 [Vol 1, Part F]. */ #define BT_HCI_ERR_SUCCESS 0x00 #define BT_HCI_ERR_UNKNOWN_CMD 0x01 diff --git a/subsys/bluetooth/host/cs.c b/subsys/bluetooth/host/cs.c index 1098aba9e8d..c676a9a477f 100644 --- a/subsys/bluetooth/host/cs.c +++ b/subsys/bluetooth/host/cs.c @@ -425,6 +425,9 @@ void bt_hci_le_cs_read_remote_supported_capabilities_complete(struct net_buf *bu remote_cs_capabilities.t_sw_time = evt->t_sw_time_supported; remote_cs_capabilities.tx_snr_capability = evt->tx_snr_capability; + remote_cs_capabilities.t_ip2_ipt_times_supported = 0; + remote_cs_capabilities.t_sw_ipt_time_supported = 0; + bt_conn_notify_remote_cs_capabilities(conn, BT_HCI_ERR_SUCCESS, &remote_cs_capabilities); } else { @@ -434,6 +437,139 @@ void bt_hci_le_cs_read_remote_supported_capabilities_complete(struct net_buf *bu bt_conn_unref(conn); } +void bt_hci_le_cs_read_remote_supported_capabilities_complete_v2(struct net_buf *buf) +{ + struct bt_conn *conn; + struct bt_conn_le_cs_capabilities remote_cs_capabilities; + struct bt_hci_evt_le_cs_read_remote_supported_capabilities_complete_v2 *evt; + + if (buf->len < sizeof(*evt)) { + LOG_ERR("Unexpected end of buffer"); + return; + } + + evt = net_buf_pull_mem(buf, sizeof(*evt)); + if (evt->status) { + LOG_WRN("Read Remote Supported Capabilities failed (status 0x%02X)", evt->status); + } + + conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle), BT_CONN_TYPE_LE); + if (!conn) { + LOG_ERR("Could not lookup connection handle when reading remote CS capabilities"); + return; + } + + if (evt->status != BT_HCI_ERR_SUCCESS) { + bt_conn_notify_remote_cs_capabilities(conn, evt->status, NULL); + goto out; + } + + remote_cs_capabilities.num_config_supported = evt->num_config_supported; + remote_cs_capabilities.max_consecutive_procedures_supported = + sys_le16_to_cpu(evt->max_consecutive_procedures_supported); + remote_cs_capabilities.num_antennas_supported = evt->num_antennas_supported; + remote_cs_capabilities.max_antenna_paths_supported = + evt->max_antenna_paths_supported; + + remote_cs_capabilities.initiator_supported = + evt->roles_supported & BT_HCI_LE_CS_INITIATOR_ROLE_MASK; + remote_cs_capabilities.reflector_supported = + evt->roles_supported & BT_HCI_LE_CS_REFLECTOR_ROLE_MASK; + remote_cs_capabilities.mode_3_supported = + evt->modes_supported & BT_HCI_LE_CS_MODES_SUPPORTED_MODE_3_MASK; + + remote_cs_capabilities.rtt_aa_only_n = evt->rtt_aa_only_n; + remote_cs_capabilities.rtt_sounding_n = evt->rtt_sounding_n; + remote_cs_capabilities.rtt_random_payload_n = evt->rtt_random_payload_n; + + if (evt->rtt_aa_only_n) { + if (evt->rtt_capability & BT_HCI_LE_CS_RTT_AA_ONLY_N_10NS_MASK) { + remote_cs_capabilities.rtt_aa_only_precision = + BT_CONN_LE_CS_RTT_AA_ONLY_10NS; + } else { + remote_cs_capabilities.rtt_aa_only_precision = + BT_CONN_LE_CS_RTT_AA_ONLY_150NS; + } + } else { + remote_cs_capabilities.rtt_aa_only_precision = + BT_CONN_LE_CS_RTT_AA_ONLY_NOT_SUPP; + } + + if (evt->rtt_sounding_n) { + if (evt->rtt_capability & BT_HCI_LE_CS_RTT_SOUNDING_N_10NS_MASK) { + remote_cs_capabilities.rtt_sounding_precision = + BT_CONN_LE_CS_RTT_SOUNDING_10NS; + } else { + remote_cs_capabilities.rtt_sounding_precision = + BT_CONN_LE_CS_RTT_SOUNDING_150NS; + } + } else { + remote_cs_capabilities.rtt_sounding_precision = + BT_CONN_LE_CS_RTT_SOUNDING_NOT_SUPP; + } + + if (evt->rtt_random_payload_n) { + if (evt->rtt_capability & BT_HCI_LE_CS_RTT_RANDOM_PAYLOAD_N_10NS_MASK) { + remote_cs_capabilities.rtt_random_payload_precision = + BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_10NS; + } else { + remote_cs_capabilities.rtt_random_payload_precision = + BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_150NS; + } + } else { + remote_cs_capabilities.rtt_random_payload_precision = + BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_NOT_SUPP; + } + + remote_cs_capabilities.phase_based_nadm_sounding_supported = + sys_le16_to_cpu(evt->nadm_sounding_capability) & + BT_HCI_LE_CS_NADM_SOUNDING_CAPABILITY_PHASE_BASED_MASK; + + remote_cs_capabilities.phase_based_nadm_random_supported = + sys_le16_to_cpu(evt->nadm_random_capability) & + BT_HCI_LE_CS_NADM_RANDOM_CAPABILITY_PHASE_BASED_MASK; + + remote_cs_capabilities.cs_sync_2m_phy_supported = + evt->cs_sync_phys_supported & BT_HCI_LE_CS_SYNC_PHYS_2M_MASK; + + remote_cs_capabilities.cs_sync_2m_2bt_phy_supported = + evt->cs_sync_phys_supported & BT_HCI_LE_CS_SYNC_PHYS_2M_2BT_MASK; + + remote_cs_capabilities.cs_without_fae_supported = + sys_le16_to_cpu(evt->subfeatures_supported) & + BT_HCI_LE_CS_SUBFEATURE_NO_TX_FAE_MASK; + + remote_cs_capabilities.chsel_alg_3c_supported = + sys_le16_to_cpu(evt->subfeatures_supported) & + BT_HCI_LE_CS_SUBFEATURE_CHSEL_ALG_3C_MASK; + + remote_cs_capabilities.pbr_from_rtt_sounding_seq_supported = + sys_le16_to_cpu(evt->subfeatures_supported) & + BT_HCI_LE_CS_SUBFEATURE_PBR_FROM_RTT_SOUNDING_SEQ_MASK; + + remote_cs_capabilities.t_ip1_times_supported = + sys_le16_to_cpu(evt->t_ip1_times_supported); + remote_cs_capabilities.t_ip2_times_supported = + sys_le16_to_cpu(evt->t_ip2_times_supported); + remote_cs_capabilities.t_fcs_times_supported = + sys_le16_to_cpu(evt->t_fcs_times_supported); + remote_cs_capabilities.t_pm_times_supported = + sys_le16_to_cpu(evt->t_pm_times_supported); + + remote_cs_capabilities.t_sw_time = evt->t_sw_time_supported; + remote_cs_capabilities.tx_snr_capability = evt->tx_snr_capability; + + remote_cs_capabilities.t_ip2_ipt_times_supported = + sys_le16_to_cpu(evt->t_ip2_ipt_times_supported); + remote_cs_capabilities.t_sw_ipt_time_supported = evt->t_sw_ipt_time_supported; + + bt_conn_notify_remote_cs_capabilities(conn, BT_HCI_ERR_SUCCESS, + &remote_cs_capabilities); + +out: + bt_conn_unref(conn); +} + int bt_le_cs_set_default_settings(struct bt_conn *conn, const struct bt_le_cs_set_default_settings_param *params) { @@ -556,9 +692,7 @@ int bt_le_cs_start_test(const struct bt_le_cs_test_param *params) cp->t_pm_time = params->t_pm_time; cp->t_sw_time = params->t_sw_time; cp->tone_antenna_config_selection = params->tone_antenna_config_selection; - - cp->reserved = 0; - + cp->cs_enhancements_1 = 0; cp->snr_control_initiator = params->initiator_snr_control; cp->snr_control_reflector = params->reflector_snr_control; cp->drbg_nonce = sys_cpu_to_le16(params->drbg_nonce); @@ -877,6 +1011,7 @@ void bt_hci_le_cs_config_complete_event(struct net_buf *buf) config.channel_selection_type = evt->channel_selection_type; config.ch3c_shape = evt->ch3c_shape; config.ch3c_jump = evt->ch3c_jump; + config.cs_enhancements_1 = evt->cs_enhancements_1; 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; @@ -927,7 +1062,7 @@ int bt_le_cs_create_config(struct bt_conn *conn, struct bt_le_cs_create_config_p cp->channel_selection_type = params->channel_selection_type; cp->ch3c_shape = params->ch3c_shape; cp->ch3c_jump = params->ch3c_jump; - cp->reserved = 0; + cp->cs_enhancements_1 = params->cs_enhancements_1; 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); @@ -1122,12 +1257,113 @@ int bt_le_cs_read_local_supported_capabilities(struct bt_conn_le_cs_capabilities ret->t_sw_time = rp->t_sw_time_supported; ret->tx_snr_capability = rp->tx_snr_capability; + ret->t_ip2_ipt_times_supported = 0; + ret->t_sw_ipt_time_supported = 0; + + net_buf_unref(rsp); + return status; +} + +int bt_le_cs_read_local_supported_capabilities_v2(struct bt_conn_le_cs_capabilities *ret) +{ + struct bt_hci_rp_le_read_local_supported_capabilities_v2 *rp; + struct net_buf *rsp; + + int err = bt_hci_cmd_send_sync( + BT_HCI_OP_LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES_V2, NULL, &rsp); + + if (err) { + return err; + } + + rp = (void *)rsp->data; + + uint8_t status = rp->status; + + ret->num_config_supported = rp->num_config_supported; + ret->max_consecutive_procedures_supported = + sys_le16_to_cpu(rp->max_consecutive_procedures_supported); + ret->num_antennas_supported = rp->num_antennas_supported; + ret->max_antenna_paths_supported = rp->max_antenna_paths_supported; + + ret->initiator_supported = rp->roles_supported & BT_HCI_LE_CS_INITIATOR_ROLE_MASK; + ret->reflector_supported = rp->roles_supported & BT_HCI_LE_CS_REFLECTOR_ROLE_MASK; + ret->mode_3_supported = rp->modes_supported & BT_HCI_LE_CS_MODES_SUPPORTED_MODE_3_MASK; + + ret->rtt_aa_only_n = rp->rtt_aa_only_n; + ret->rtt_sounding_n = rp->rtt_sounding_n; + ret->rtt_random_payload_n = rp->rtt_random_payload_n; + + if (rp->rtt_aa_only_n) { + if (rp->rtt_capability & BT_HCI_LE_CS_RTT_AA_ONLY_N_10NS_MASK) { + ret->rtt_aa_only_precision = BT_CONN_LE_CS_RTT_AA_ONLY_10NS; + } else { + ret->rtt_aa_only_precision = BT_CONN_LE_CS_RTT_AA_ONLY_150NS; + } + } else { + ret->rtt_aa_only_precision = BT_CONN_LE_CS_RTT_AA_ONLY_NOT_SUPP; + } + + if (rp->rtt_sounding_n) { + if (rp->rtt_capability & BT_HCI_LE_CS_RTT_SOUNDING_N_10NS_MASK) { + ret->rtt_sounding_precision = BT_CONN_LE_CS_RTT_SOUNDING_10NS; + } else { + ret->rtt_sounding_precision = BT_CONN_LE_CS_RTT_SOUNDING_150NS; + } + } else { + ret->rtt_sounding_precision = BT_CONN_LE_CS_RTT_SOUNDING_NOT_SUPP; + } + + if (rp->rtt_random_payload_n) { + if (rp->rtt_capability & BT_HCI_LE_CS_RTT_RANDOM_PAYLOAD_N_10NS_MASK) { + ret->rtt_random_payload_precision = BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_10NS; + } else { + ret->rtt_random_payload_precision = BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_150NS; + } + } else { + ret->rtt_random_payload_precision = BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_NOT_SUPP; + } + + ret->phase_based_nadm_sounding_supported = + sys_le16_to_cpu(rp->nadm_sounding_capability) & + BT_HCI_LE_CS_NADM_SOUNDING_CAPABILITY_PHASE_BASED_MASK; + + ret->phase_based_nadm_random_supported = + sys_le16_to_cpu(rp->nadm_random_capability) & + BT_HCI_LE_CS_NADM_RANDOM_CAPABILITY_PHASE_BASED_MASK; + + ret->cs_sync_2m_phy_supported = rp->cs_sync_phys_supported & BT_HCI_LE_CS_SYNC_PHYS_2M_MASK; + + ret->cs_sync_2m_2bt_phy_supported = + rp->cs_sync_phys_supported & BT_HCI_LE_CS_SYNC_PHYS_2M_2BT_MASK; + + ret->cs_without_fae_supported = + sys_le16_to_cpu(rp->subfeatures_supported) & BT_HCI_LE_CS_SUBFEATURE_NO_TX_FAE_MASK; + + ret->chsel_alg_3c_supported = sys_le16_to_cpu(rp->subfeatures_supported) & + BT_HCI_LE_CS_SUBFEATURE_CHSEL_ALG_3C_MASK; + + ret->pbr_from_rtt_sounding_seq_supported = + sys_le16_to_cpu(rp->subfeatures_supported) & + BT_HCI_LE_CS_SUBFEATURE_PBR_FROM_RTT_SOUNDING_SEQ_MASK; + + ret->t_ip1_times_supported = sys_le16_to_cpu(rp->t_ip1_times_supported); + ret->t_ip2_times_supported = sys_le16_to_cpu(rp->t_ip2_times_supported); + ret->t_fcs_times_supported = sys_le16_to_cpu(rp->t_fcs_times_supported); + ret->t_pm_times_supported = sys_le16_to_cpu(rp->t_pm_times_supported); + + ret->t_sw_time = rp->t_sw_time_supported; + ret->tx_snr_capability = rp->tx_snr_capability; + + ret->t_ip2_ipt_times_supported = sys_le16_to_cpu(rp->t_ip2_ipt_times_supported); + ret->t_sw_ipt_time_supported = rp->t_sw_ipt_time_supported; + net_buf_unref(rsp); return status; } -int bt_le_cs_write_cached_remote_supported_capabilities( - struct bt_conn *conn, const struct bt_conn_le_cs_capabilities *params) +int bt_le_cs_write_cached_remote_supported_capabilities(struct bt_conn *conn, + const struct bt_conn_le_cs_capabilities *params) { struct bt_hci_cp_le_write_cached_remote_supported_capabilities *cp; struct net_buf *buf; @@ -1224,6 +1460,108 @@ int bt_le_cs_write_cached_remote_supported_capabilities( NULL); } +int bt_le_cs_write_cached_remote_supported_capabilities_v2(struct bt_conn *conn, + const struct bt_conn_le_cs_capabilities *params) +{ + struct bt_hci_cp_le_write_cached_remote_supported_capabilities_v2 *cp; + struct net_buf *buf; + + buf = bt_hci_cmd_alloc(K_FOREVER); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + + cp->handle = sys_cpu_to_le16(conn->handle); + + cp->num_config_supported = params->num_config_supported; + + cp->max_consecutive_procedures_supported = + sys_cpu_to_le16(params->max_consecutive_procedures_supported); + + cp->num_antennas_supported = params->num_antennas_supported; + cp->max_antenna_paths_supported = params->max_antenna_paths_supported; + + cp->roles_supported = 0; + if (params->initiator_supported) { + cp->roles_supported |= BT_HCI_LE_CS_INITIATOR_ROLE_MASK; + } + if (params->reflector_supported) { + cp->roles_supported |= BT_HCI_LE_CS_REFLECTOR_ROLE_MASK; + } + + cp->modes_supported = 0; + if (params->mode_3_supported) { + cp->modes_supported |= BT_HCI_LE_CS_MODES_SUPPORTED_MODE_3_MASK; + } + + cp->rtt_aa_only_n = params->rtt_aa_only_n; + cp->rtt_sounding_n = params->rtt_sounding_n; + cp->rtt_random_payload_n = params->rtt_random_payload_n; + + cp->rtt_capability = 0; + if (params->rtt_aa_only_precision == BT_CONN_LE_CS_RTT_AA_ONLY_10NS) { + cp->rtt_capability |= BT_HCI_LE_CS_RTT_AA_ONLY_N_10NS_MASK; + } + + if (params->rtt_sounding_precision == BT_CONN_LE_CS_RTT_SOUNDING_10NS) { + cp->rtt_capability |= BT_HCI_LE_CS_RTT_SOUNDING_N_10NS_MASK; + } + + if (params->rtt_random_payload_precision == BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_10NS) { + cp->rtt_capability |= BT_HCI_LE_CS_RTT_RANDOM_PAYLOAD_N_10NS_MASK; + } + + cp->nadm_sounding_capability = 0; + if (params->phase_based_nadm_sounding_supported) { + cp->nadm_sounding_capability |= + sys_cpu_to_le16(BT_HCI_LE_CS_NADM_SOUNDING_CAPABILITY_PHASE_BASED_MASK); + } + + cp->nadm_random_capability = 0; + if (params->phase_based_nadm_random_supported) { + cp->nadm_random_capability |= + sys_cpu_to_le16(BT_HCI_LE_CS_NADM_RANDOM_CAPABILITY_PHASE_BASED_MASK); + } + + cp->cs_sync_phys_supported = 0; + if (params->cs_sync_2m_phy_supported) { + cp->cs_sync_phys_supported |= BT_HCI_LE_CS_SYNC_PHYS_2M_MASK; + } + if (params->cs_sync_2m_2bt_phy_supported) { + cp->cs_sync_phys_supported |= BT_HCI_LE_CS_SYNC_PHYS_2M_2BT_MASK; + } + + cp->subfeatures_supported = 0; + if (params->cs_without_fae_supported) { + cp->subfeatures_supported |= + sys_cpu_to_le16(BT_HCI_LE_CS_SUBFEATURE_NO_TX_FAE_MASK); + } + if (params->chsel_alg_3c_supported) { + cp->subfeatures_supported |= + sys_cpu_to_le16(BT_HCI_LE_CS_SUBFEATURE_CHSEL_ALG_3C_MASK); + } + if (params->pbr_from_rtt_sounding_seq_supported) { + cp->subfeatures_supported |= + sys_cpu_to_le16(BT_HCI_LE_CS_SUBFEATURE_PBR_FROM_RTT_SOUNDING_SEQ_MASK); + } + + cp->t_ip1_times_supported = sys_cpu_to_le16(params->t_ip1_times_supported); + cp->t_ip2_times_supported = sys_cpu_to_le16(params->t_ip2_times_supported); + cp->t_fcs_times_supported = sys_cpu_to_le16(params->t_fcs_times_supported); + cp->t_pm_times_supported = sys_cpu_to_le16(params->t_pm_times_supported); + cp->t_sw_time_supported = params->t_sw_time; + cp->tx_snr_capability = params->tx_snr_capability; + + cp->t_ip2_ipt_times_supported = sys_cpu_to_le16(params->t_ip2_ipt_times_supported); + cp->t_sw_ipt_time_supported = params->t_sw_ipt_time_supported; + + return bt_hci_cmd_send_sync( + BT_HCI_OP_LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES_V2, + buf, NULL); +} + int bt_le_cs_write_cached_remote_fae_table(struct bt_conn *conn, int8_t remote_fae_table[72]) { struct bt_hci_cp_le_write_cached_remote_fae_table *cp; diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 9573f714fa1..454929eecfd 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -3071,17 +3071,21 @@ static const struct event_handler meta_events[] = { EVENT_HANDLER(BT_HCI_EVT_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE, bt_hci_le_cs_read_remote_supported_capabilities_complete, sizeof(struct bt_hci_evt_le_cs_read_remote_supported_capabilities_complete)), + EVENT_HANDLER(BT_HCI_EVT_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE_V2, + bt_hci_le_cs_read_remote_supported_capabilities_complete_v2, + sizeof( + struct bt_hci_evt_le_cs_read_remote_supported_capabilities_complete_v2)), EVENT_HANDLER(BT_HCI_EVT_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)), 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)), EVENT_HANDLER(BT_HCI_EVT_LE_CS_SECURITY_ENABLE_COMPLETE, - bt_hci_le_cs_security_enable_complete, - sizeof(struct bt_hci_evt_le_cs_security_enable_complete)), + bt_hci_le_cs_security_enable_complete, + sizeof(struct bt_hci_evt_le_cs_security_enable_complete)), EVENT_HANDLER(BT_HCI_EVT_LE_CS_PROCEDURE_ENABLE_COMPLETE, - bt_hci_le_cs_procedure_enable_complete, - sizeof(struct bt_hci_evt_le_cs_procedure_enable_complete)), + bt_hci_le_cs_procedure_enable_complete, + sizeof(struct bt_hci_evt_le_cs_procedure_enable_complete)), EVENT_HANDLER(BT_HCI_EVT_LE_CS_SUBEVENT_RESULT, bt_hci_le_cs_subevent_result, sizeof(struct bt_hci_evt_le_cs_subevent_result)), @@ -3724,6 +3728,13 @@ static int le_set_event_mask(void) if (IS_ENABLED(CONFIG_BT_CHANNEL_SOUNDING) && BT_FEAT_LE_CHANNEL_SOUNDING(bt_dev.le.features)) { mask |= BT_EVT_MASK_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE; + /* Only set v2 event mask if controller supports it; v1-only CS controllers + * may reject the Set Event Mask command if an unknown bit is set. + */ + if (BT_LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES_V2_SUPPORTED( + bt_dev.supported_commands)) { + mask |= BT_EVT_MASK_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE_V2; + } mask |= BT_EVT_MASK_LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE; mask |= BT_EVT_MASK_LE_CS_CONFIG_COMPLETE; mask |= BT_EVT_MASK_LE_CS_SECURITY_ENABLE_COMPLETE; diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index dacc51d20fa..1cc40349cfb 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -559,6 +559,7 @@ void bt_hci_le_past_received_v2(struct net_buf *buf); /* 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_v2(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); void bt_hci_le_cs_security_enable_complete(struct net_buf *buf);