]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Bluetooth: hci_sync: Add LE Channel Sounding HCI Command/event structures
authorNaga Bhavani Akella <naga.akella@oss.qualcomm.com>
Wed, 17 Dec 2025 11:25:23 +0000 (16:55 +0530)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thu, 29 Jan 2026 18:24:48 +0000 (13:24 -0500)
1. Implement LE Event Mask to include events required for
   LE Channel Sounding
2. Enable Channel Sounding feature bit in the
   LE Host Supported Features command
3. Define HCI command and event structures necessary for
   LE Channel Sounding functionality

Signed-off-by: Naga Bhavani Akella <naga.akella@oss.qualcomm.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_sync.c

index a27cd3626b87262b6664acc21929492c8b70bb1a..4a731e1bec53b4957bf3d71b41b6d54409a90170 100644 (file)
@@ -654,6 +654,8 @@ enum {
 #define HCI_LE_ISO_BROADCASTER         0x40
 #define HCI_LE_ISO_SYNC_RECEIVER       0x80
 #define HCI_LE_LL_EXT_FEATURE          0x80
+#define HCI_LE_CS                      0x40
+#define HCI_LE_CS_HOST                 0x80
 
 /* Connection modes */
 #define HCI_CM_ACTIVE  0x0000
@@ -2269,6 +2271,204 @@ struct hci_cp_le_read_all_remote_features {
        __u8     pages;
 } __packed;
 
+/* Channel Sounding Commands */
+#define HCI_OP_LE_CS_RD_LOCAL_SUPP_CAP 0x2089
+struct hci_rp_le_cs_rd_local_supp_cap {
+       __u8    status;
+       __u8    num_config_supported;
+       __le16  max_consecutive_procedures_supported;
+       __u8    num_antennas_supported;
+       __u8    max_antenna_paths_supported;
+       __u8    roles_supported;
+       __u8    modes_supported;
+       __u8    rtt_capability;
+       __u8    rtt_aa_only_n;
+       __u8    rtt_sounding_n;
+       __u8    rtt_random_payload_n;
+       __le16  nadm_sounding_capability;
+       __le16  nadm_random_capability;
+       __u8    cs_sync_phys_supported;
+       __le16  subfeatures_supported;
+       __le16  t_ip1_times_supported;
+       __le16  t_ip2_times_supported;
+       __le16  t_fcs_times_supported;
+       __le16  t_pm_times_supported;
+       __u8    t_sw_time_supported;
+       __u8    tx_snr_capability;
+} __packed;
+
+#define HCI_OP_LE_CS_RD_RMT_SUPP_CAP           0x208A
+struct hci_cp_le_cs_rd_local_supp_cap {
+       __le16  handle;
+} __packed;
+
+#define HCI_OP_LE_CS_WR_CACHED_RMT_SUPP_CAP    0x208B
+struct hci_cp_le_cs_wr_cached_rmt_supp_cap {
+       __le16  handle;
+       __u8    num_config_supported;
+       __le16  max_consecutive_procedures_supported;
+       __u8    num_antennas_supported;
+       __u8    max_antenna_paths_supported;
+       __u8    roles_supported;
+       __u8    modes_supported;
+       __u8    rtt_capability;
+       __u8    rtt_aa_only_n;
+       __u8    rtt_sounding_n;
+       __u8    rtt_random_payload_n;
+       __le16  nadm_sounding_capability;
+       __le16  nadm_random_capability;
+       __u8    cs_sync_phys_supported;
+       __le16  subfeatures_supported;
+       __le16  t_ip1_times_supported;
+       __le16  t_ip2_times_supported;
+       __le16  t_fcs_times_supported;
+       __le16  t_pm_times_supported;
+       __u8    t_sw_time_supported;
+       __u8    tx_snr_capability;
+} __packed;
+
+struct hci_rp_le_cs_wr_cached_rmt_supp_cap {
+       __u8    status;
+       __le16  handle;
+} __packed;
+
+#define HCI_OP_LE_CS_SEC_ENABLE                        0x208C
+struct hci_cp_le_cs_sec_enable {
+       __le16  handle;
+} __packed;
+
+#define HCI_OP_LE_CS_SET_DEFAULT_SETTINGS      0x208D
+struct hci_cp_le_cs_set_default_settings {
+       __le16  handle;
+       __u8    role_enable;
+       __u8    cs_sync_ant_sel;
+       __s8    max_tx_power;
+} __packed;
+
+struct hci_rp_le_cs_set_default_settings {
+       __u8    status;
+       __le16  handle;
+} __packed;
+
+#define HCI_OP_LE_CS_RD_RMT_FAE_TABLE          0x208E
+struct hci_cp_le_cs_rd_rmt_fae_table {
+       __le16  handle;
+} __packed;
+
+#define HCI_OP_LE_CS_WR_CACHED_RMT_FAE_TABLE   0x208F
+struct hci_cp_le_cs_wr_rmt_cached_fae_table {
+       __le16  handle;
+       __u8    remote_fae_table[72];
+} __packed;
+
+struct hci_rp_le_cs_wr_rmt_cached_fae_table {
+       __u8    status;
+       __le16  handle;
+} __packed;
+
+#define HCI_OP_LE_CS_CREATE_CONFIG             0x2090
+struct hci_cp_le_cs_create_config {
+       __le16  handle;
+       __u8    config_id;
+       __u8    create_context;
+       __u8    main_mode_type;
+       __u8    sub_mode_type;
+       __u8    min_main_mode_steps;
+       __u8    max_main_mode_steps;
+       __u8    main_mode_repetition;
+       __u8    mode_0_steps;
+       __u8    role;
+       __u8    rtt_type;
+       __u8    cs_sync_phy;
+       __u8    channel_map[10];
+       __u8    channel_map_repetition;
+       __u8    channel_selection_type;
+       __u8    ch3c_shape;
+       __u8    ch3c_jump;
+       __u8    reserved;
+} __packed;
+
+#define HCI_OP_LE_CS_REMOVE_CONFIG             0x2091
+struct hci_cp_le_cs_remove_config {
+       __le16  handle;
+       __u8    config_id;
+} __packed;
+
+#define HCI_OP_LE_CS_SET_CH_CLASSIFICATION     0x2092
+struct hci_cp_le_cs_set_ch_classification {
+       __u8    ch_classification[10];
+} __packed;
+
+struct hci_rp_le_cs_set_ch_classification {
+       __u8    status;
+} __packed;
+
+#define HCI_OP_LE_CS_SET_PROC_PARAM            0x2093
+struct hci_cp_le_cs_set_proc_param {
+       __le16  handle;
+       __u8    config_id;
+       __le16  max_procedure_len;
+       __le16  min_procedure_interval;
+       __le16  max_procedure_interval;
+       __le16  max_procedure_count;
+       __u8    min_subevent_len[3];
+       __u8    max_subevent_len[3];
+       __u8    tone_antenna_config_selection;
+       __u8    phy;
+       __u8    tx_power_delta;
+       __u8    preferred_peer_antenna;
+       __u8    snr_control_initiator;
+       __u8    snr_control_reflector;
+} __packed;
+
+struct hci_rp_le_cs_set_proc_param {
+       __u8    status;
+       __le16  handle;
+} __packed;
+
+#define HCI_OP_LE_CS_SET_PROC_ENABLE           0x2094
+struct hci_cp_le_cs_set_proc_enable {
+       __le16  handle;
+       __u8    config_id;
+       __u8    enable;
+} __packed;
+
+#define HCI_OP_LE_CS_TEST                      0x2095
+struct hci_cp_le_cs_test {
+       __u8    main_mode_type;
+       __u8    sub_mode_type;
+       __u8    main_mode_repetition;
+       __u8    mode_0_steps;
+       __u8    role;
+       __u8    rtt_type;
+       __u8    cs_sync_phy;
+       __u8    cs_sync_antenna_selection;
+       __u8    subevent_len[3];
+       __le16  subevent_interval;
+       __u8    max_num_subevents;
+       __u8    transmit_power_level;
+       __u8    t_ip1_time;
+       __u8    t_ip2_time;
+       __u8    t_fcs_time;
+       __u8    t_pm_time;
+       __u8    t_sw_time;
+       __u8    tone_antenna_config_selection;
+       __u8    reserved;
+       __u8    snr_control_initiator;
+       __u8    snr_control_reflector;
+       __le16  drbg_nonce;
+       __u8    channel_map_repetition;
+       __le16  override_config;
+       __u8    override_parameters_length;
+       __u8    override_parameters_data[];
+} __packed;
+
+struct hci_rp_le_cs_test {
+       __u8    status;
+} __packed;
+
+#define HCI_OP_LE_CS_TEST_END                  0x2096
+
 /* ---- HCI Events ---- */
 struct hci_ev_status {
        __u8    status;
@@ -2960,6 +3160,129 @@ struct hci_evt_le_read_all_remote_features_complete {
        __u8    features[248];
 } __packed;
 
+/* Channel Sounding Events */
+#define HCI_EVT_LE_CS_READ_RMT_SUPP_CAP_COMPLETE       0x2C
+struct hci_evt_le_cs_read_rmt_supp_cap_complete {
+       __u8    status;
+       __le16  handle;
+       __u8    num_configs_supp;
+       __le16  max_consec_proc_supp;
+       __u8    num_ant_supp;
+       __u8    max_ant_path_supp;
+       __u8    roles_supp;
+       __u8    modes_supp;
+       __u8    rtt_cap;
+       __u8    rtt_aa_only_n;
+       __u8    rtt_sounding_n;
+       __u8    rtt_rand_payload_n;
+       __le16  nadm_sounding_cap;
+       __le16  nadm_rand_cap;
+       __u8    cs_sync_phys_supp;
+       __le16  sub_feat_supp;
+       __le16  t_ip1_times_supp;
+       __le16  t_ip2_times_supp;
+       __le16  t_fcs_times_supp;
+       __le16  t_pm_times_supp;
+       __u8    t_sw_times_supp;
+       __u8    tx_snr_cap;
+} __packed;
+
+#define HCI_EVT_LE_CS_READ_RMT_FAE_TABLE_COMPLETE      0x2D
+struct hci_evt_le_cs_read_rmt_fae_table_complete {
+       __u8    status;
+       __le16  handle;
+       __u8    remote_fae_table[72];
+} __packed;
+
+#define HCI_EVT_LE_CS_SECURITY_ENABLE_COMPLETE         0x2E
+struct hci_evt_le_cs_security_enable_complete {
+       __u8    status;
+       __le16  handle;
+} __packed;
+
+#define HCI_EVT_LE_CS_CONFIG_COMPLETE                  0x2F
+struct hci_evt_le_cs_config_complete {
+       __u8    status;
+       __le16  handle;
+       __u8    config_id;
+       __u8    action;
+       __u8    main_mode_type;
+       __u8    sub_mode_type;
+       __u8    min_main_mode_steps;
+       __u8    max_main_mode_steps;
+       __u8    main_mode_rep;
+       __u8    mode_0_steps;
+       __u8    role;
+       __u8    rtt_type;
+       __u8    cs_sync_phy;
+       __u8    channel_map[10];
+       __u8    channel_map_rep;
+       __u8    channel_sel_type;
+       __u8    ch3c_shape;
+       __u8    ch3c_jump;
+       __u8    reserved;
+       __u8    t_ip1_time;
+       __u8    t_ip2_time;
+       __u8    t_fcs_time;
+       __u8    t_pm_time;
+} __packed;
+
+#define HCI_EVT_LE_CS_PROCEDURE_ENABLE_COMPLETE                0x30
+struct hci_evt_le_cs_procedure_enable_complete {
+       __u8    status;
+       __le16  handle;
+       __u8    config_id;
+       __u8    state;
+       __u8    tone_ant_config_sel;
+       __s8    sel_tx_pwr;
+       __u8    sub_evt_len[3];
+       __u8    sub_evts_per_evt;
+       __le16  sub_evt_intrvl;
+       __le16  evt_intrvl;
+       __le16  proc_intrvl;
+       __le16  proc_counter;
+       __le16  max_proc_len;
+} __packed;
+
+#define HCI_EVT_LE_CS_SUBEVENT_RESULT                  0x31
+struct hci_evt_le_cs_subevent_result {
+       __le16  handle;
+       __u8    config_id;
+       __le16  start_acl_conn_evt_counter;
+       __le16  proc_counter;
+       __le16  freq_comp;
+       __u8    ref_pwr_lvl;
+       __u8    proc_done_status;
+       __u8    subevt_done_status;
+       __u8    abort_reason;
+       __u8    num_ant_paths;
+       __u8    num_steps_reported;
+       __u8    step_mode[0]; /* depends on num_steps_reported */
+       __u8    step_channel[0]; /* depends on num_steps_reported */
+       __u8    step_data_length[0]; /* depends on num_steps_reported */
+       __u8    step_data[0]; /* depends on num_steps_reported */
+} __packed;
+
+#define HCI_EVT_LE_CS_SUBEVENT_RESULT_CONTINUE         0x32
+struct hci_evt_le_cs_subevent_result_continue {
+       __le16  handle;
+       __u8    config_id;
+       __u8    proc_done_status;
+       __u8    subevt_done_status;
+       __u8    abort_reason;
+       __u8    num_ant_paths;
+       __u8    num_steps_reported;
+       __u8    step_mode[0]; /* depends on num_steps_reported */
+       __u8    step_channel[0]; /* depends on num_steps_reported */
+       __u8    step_data_length[0]; /* depends on num_steps_reported */
+       __u8    step_data[0]; /* depends on num_steps_reported */
+} __packed;
+
+#define HCI_EVT_LE_CS_TEST_END_COMPLETE                        0x33
+struct hci_evt_le_cs_test_end_complete {
+       __u8    status;
+} __packed;
+
 #define HCI_EV_VENDOR                  0xff
 
 /* Internal events generated by Bluetooth stack */
index 8aadf4cdead2bdac76a5a83cfbb2982797b27b44..a7d5beb01b695cf8e835fa6beadb8415f494e48b 100644 (file)
@@ -2073,6 +2073,12 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define ll_ext_feature_capable(dev) \
        ((dev)->le_features[7] & HCI_LE_LL_EXT_FEATURE)
 
+/* Channel sounding support */
+#define le_cs_capable(dev) \
+       ((dev)->le_features[5] & HCI_LE_CS)
+#define le_cs_host_capable(dev) \
+       ((dev)->le_features[5] & HCI_LE_CS_HOST)
+
 #define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \
        (!hci_test_quirk((dev), HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG)))
 
index 334eb4376a266673dc9f568171851ab763ba81d6..4163d9b16e1a4d6ea79e618387e1508b2d155482 100644 (file)
@@ -4428,6 +4428,17 @@ static int hci_le_set_event_mask_sync(struct hci_dev *hdev)
                events[4] |= 0x02;      /* LE BIG Info Advertising Report */
        }
 
+       if (le_cs_capable(hdev)) {
+               /* Channel Sounding events */
+               events[5] |= 0x08;      /* LE CS Read Remote Supported Cap Complete event */
+               events[5] |= 0x10;      /* LE CS Read Remote FAE Table Complete event */
+               events[5] |= 0x20;      /* LE CS Security Enable Complete event */
+               events[5] |= 0x40;      /* LE CS Config Complete event */
+               events[5] |= 0x80;      /* LE CS Procedure Enable Complete event */
+               events[6] |= 0x01;      /* LE CS Subevent Result event */
+               events[6] |= 0x02;      /* LE CS Subevent Result Continue event */
+               events[6] |= 0x04;      /* LE CS Test End Complete event */
+       }
        return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EVENT_MASK,
                                     sizeof(events), events, HCI_CMD_TIMEOUT);
 }
@@ -4560,23 +4571,43 @@ static int hci_set_le_support_sync(struct hci_dev *hdev)
 }
 
 /* LE Set Host Feature */
-static int hci_le_set_host_feature_sync(struct hci_dev *hdev)
+static int hci_le_set_host_feature_sync(struct hci_dev *hdev, u8 bit, u8 value)
 {
        struct hci_cp_le_set_host_feature cp;
 
-       if (!iso_capable(hdev))
-               return 0;
-
        memset(&cp, 0, sizeof(cp));
 
        /* Connected Isochronous Channels (Host Support) */
-       cp.bit_number = 32;
-       cp.bit_value = iso_enabled(hdev) ? 0x01 : 0x00;
+       cp.bit_number = bit;
+       cp.bit_value = value;
 
        return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_HOST_FEATURE,
                                     sizeof(cp), &cp, HCI_CMD_TIMEOUT);
 }
 
+/* Set Host Features, each feature needs to be sent separately since
+ * HCI_OP_LE_SET_HOST_FEATURE doesn't support setting all of them at once.
+ */
+static int hci_le_set_host_features_sync(struct hci_dev *hdev)
+{
+       int err;
+
+       if (iso_capable(hdev)) {
+               /* Connected Isochronous Channels (Host Support) */
+               err = hci_le_set_host_feature_sync(hdev, 32,
+                                                  (iso_enabled(hdev) ? 0x01 :
+                                                   0x00));
+               if (err)
+                       return err;
+       }
+
+       if (le_cs_capable(hdev))
+               /* Channel Sounding (Host Support) */
+               err = hci_le_set_host_feature_sync(hdev, 47, 0x01);
+
+       return err;
+}
+
 /* LE Controller init stage 3 command sequence */
 static const struct hci_init_stage le_init3[] = {
        /* HCI_OP_LE_SET_EVENT_MASK */
@@ -4604,7 +4635,7 @@ static const struct hci_init_stage le_init3[] = {
        /* HCI_OP_WRITE_LE_HOST_SUPPORTED */
        HCI_INIT(hci_set_le_support_sync),
        /* HCI_OP_LE_SET_HOST_FEATURE */
-       HCI_INIT(hci_le_set_host_feature_sync),
+       HCI_INIT(hci_le_set_host_features_sync),
        {}
 };