[NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD] = { .type = NLA_U64 },
[NL80211_PMSR_FTM_RESP_ATTR_LCI] = { .type = NLA_STRING },
[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_STRING },
+ [NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS] = { .type = NLA_U8 },
+ [NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS] = { .type = NLA_U8 },
+ [NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR] = { .type = NLA_FLAG },
};
static const struct nla_policy
[NL80211_PMSR_ATTR_PEERS] = NLA_POLICY_NESTED_ARRAY(hwsim_pmsr_peer_result_policy),
};
+static const struct nla_policy
+hwsim_ftm_role_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = {
+ [NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA] = { .type = NLA_FLAG },
+};
+
+static const struct nla_policy
+hwsim_ftm_type_capa_policy[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX + 1] = {
+ [NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INFRA_SUPPORT] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT] = { .type = NLA_FLAG },
+};
+
static const struct nla_policy
hwsim_ftm_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_CAPA_ATTR_ASAP] = { .type = NLA_FLAG },
[NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST] = NLA_POLICY_MAX(NLA_U8, 31),
[NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG },
[NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS] = { .type = NLA_U8 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS] = { .type = NLA_U8 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS] =
+ NLA_POLICY_NESTED(hwsim_ftm_role_capa_policy),
+ [NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS] =
+ NLA_POLICY_NESTED(hwsim_ftm_role_capa_policy),
+ [NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS] =
+ NLA_POLICY_NESTED(hwsim_ftm_type_capa_policy),
+ [NL80211_PMSR_FTM_CAPA_ATTR_CONCURRENT_ISTA_RSTA_SUPPORT] = { .type = NLA_FLAG },
};
static const struct nla_policy
if (nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR, request->bss_color))
return -ENOBUFS;
+ if (request->min_time_between_measurements &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS,
+ request->min_time_between_measurements))
+ return -ENOBUFS;
+
+ if (request->max_time_between_measurements &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS,
+ request->max_time_between_measurements))
+ return -ENOBUFS;
+
+ if (request->availability_window &&
+ nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION,
+ request->availability_window))
+ return -ENOBUFS;
+
+ if (request->nominal_time &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME,
+ request->nominal_time))
+ return -ENOBUFS;
+
+ if (request->num_measurements &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS,
+ request->num_measurements))
+ return -ENOBUFS;
+
+ if (request->ingress_distance &&
+ nla_put_u64_64bit(msg, NL80211_PMSR_FTM_REQ_ATTR_INGRESS,
+ request->ingress_distance,
+ NL80211_PMSR_FTM_REQ_ATTR_PAD))
+ return -ENOBUFS;
+
+ if (request->egress_distance &&
+ nla_put_u64_64bit(msg, NL80211_PMSR_FTM_REQ_ATTR_EGRESS,
+ request->egress_distance,
+ NL80211_PMSR_FTM_REQ_ATTR_PAD))
+ return -ENOBUFS;
+
+ if (request->pd_suppress_range_results &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_REQ_ATTR_PD_SUPPRESS_RESULTS))
+ return -ENOBUFS;
+
nla_nest_end(msg, ftm);
return 0;
result->civicloc_len = nla_len(tb[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]);
}
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT]) {
+ result->tx_ltf_repetition_count_valid = 1;
+ result->tx_ltf_repetition_count =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT]) {
+ result->rx_ltf_repetition_count_valid = 1;
+ result->rx_ltf_repetition_count =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]) {
+ result->max_time_between_measurements_valid = 1;
+ result->max_time_between_measurements =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]) {
+ result->min_time_between_measurements_valid = 1;
+ result->min_time_between_measurements =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS]) {
+ result->num_tx_spatial_streams_valid = 1;
+ result->num_tx_spatial_streams =
+ nla_get_u8(tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS]) {
+ result->num_rx_spatial_streams_valid = 1;
+ result->num_rx_spatial_streams =
+ nla_get_u8(tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME]) {
+ result->nominal_time_valid = 1;
+ result->nominal_time =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW]) {
+ result->availability_window_valid = 1;
+ result->availability_window =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH]) {
+ result->chan_width_valid = 1;
+ result->chan_width =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE]) {
+ result->preamble_valid = 1;
+ result->preamble =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE]);
+ }
+
+ result->is_delayed_lmr =
+ nla_get_flag(tb[NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR]);
+
return 0;
}
out->ftm.trigger_based = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED];
out->ftm.non_trigger_based = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED];
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS])
+ out->ftm.max_no_of_tx_antennas =
+ nla_get_u8(tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS])
+ out->ftm.max_no_of_rx_antennas =
+ nla_get_u8(tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA])
+ out->ftm.min_allowed_ranging_interval_edca =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB])
+ out->ftm.min_allowed_ranging_interval_ntb =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES])
+ out->ftm.pd_preambles =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS])
+ out->ftm.pd_bandwidths =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS]) {
+ struct nlattr *ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1];
+
+ if (!nla_parse_nested(ista_tb, NL80211_PMSR_FTM_CAPA_ATTR_MAX,
+ tb[NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS],
+ hwsim_ftm_role_capa_policy, NULL)) {
+ out->ftm.ista.support_ntb =
+ !!ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB];
+ out->ftm.ista.support_tb =
+ !!ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB];
+ out->ftm.ista.support_edca =
+ !!ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA];
+ if (ista_tb[NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE])
+ out->ftm.ista.max_peers =
+ nla_get_u32(ista_tb[NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE]);
+ }
+ }
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS]) {
+ struct nlattr *rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1];
+
+ if (!nla_parse_nested(rsta_tb, NL80211_PMSR_FTM_CAPA_ATTR_MAX,
+ tb[NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS],
+ hwsim_ftm_role_capa_policy, NULL)) {
+ out->ftm.rsta.support_ntb =
+ !!rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB];
+ out->ftm.rsta.support_tb =
+ !!rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB];
+ out->ftm.rsta.support_edca =
+ !!rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA];
+ if (rsta_tb[NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE])
+ out->ftm.rsta.max_peers =
+ nla_get_u32(rsta_tb[NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE]);
+ }
+ }
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS]) {
+ struct nlattr *type_tb[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX + 1];
+
+ if (!nla_parse_nested(type_tb, NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX,
+ tb[NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS],
+ hwsim_ftm_type_capa_policy, NULL)) {
+ out->ftm.type.infra_support =
+ !!type_tb[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INFRA_SUPPORT];
+ out->ftm.type.pd_support =
+ !!type_tb[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT];
+ }
+ }
+
+ out->ftm.concurrent_ista_rsta_support =
+ !!tb[NL80211_PMSR_FTM_CAPA_ATTR_CONCURRENT_ISTA_RSTA_SUPPORT];
+
return 0;
}