* @burst_duration: burst duration. If @trigger_based or @non_trigger_based is
* set, this is the burst duration in milliseconds, and zero means the
* device should pick an appropriate value based on @ftms_per_burst.
- * @ftms_per_burst: number of FTMs per burst
+ * @ftms_per_burst: number of FTMs per burst. If set to 0, the firmware or
+ * driver can automatically select an appropriate value.
* @ftmr_retries: number of retries for FTM request
* @request_lci: request LCI information
* @request_civicloc: request civic location information
* @bss_color: the bss color of the responder. Optional. Set to zero to
* indicate the driver should set the BSS color. Only valid if
* @non_trigger_based or @trigger_based is set.
+ * @request_type: ranging request type, one of
+ * &enum nl80211_peer_measurement_ftm_req_type. Defaults to
+ * %NL80211_PMSR_FTM_REQ_TYPE_INFRA if not specified.
+ * @min_time_between_measurements: minimum time between two consecutive range
+ * measurements in units of 100 microseconds, for non-trigger based
+ * ranging. Should be set as short as possible to minimize turnaround
+ * time, since two-way ranging with delayed LMR requires two measurements.
+ * Only valid if @non_trigger_based is set.
+ * @max_time_between_measurements: maximum time between two consecutive range
+ * measurements in units of 10 milliseconds, for non-trigger based
+ * ranging. Acts as a session timeout; if exceeded, the ranging session
+ * should be terminated. Only valid if @non_trigger_based is set.
+ * @availability_window: duration of the availability window (AW) in units of
+ * 1 millisecond (0-255 ms). Only valid if @non_trigger_based is set.
+ * If set to 0, the firmware or driver can automatically select an
+ * appropriate value.
+ * @nominal_time: Nominal duration between adjacent availability windows
+ * in units of milli seconds. Only valid if @non_trigger_based is set.
+ * If set to 0, the firmware or driver can automatically select an
+ * appropriate value.
+ * @num_measurements: number of Availability Windows (AWs) to schedule
+ * for non-trigger-based ranging. Each AW may contain multiple FTM
+ * exchanges as configured by @ftms_per_burst. Only valid if
+ * @non_trigger_based is set. If set to 0, the firmware or driver
+ * can automatically select an appropriate value.
*
* See also nl80211 for the respective attribute documentation.
*/
u8 ftms_per_burst;
u8 ftmr_retries;
u8 bss_color;
+
+ u32 request_type;
+ u32 min_time_between_measurements;
+ u32 max_time_between_measurements;
+ u8 availability_window;
+ u32 nominal_time;
+ u32 num_measurements;
};
/**
NL80211_PMSR_RESP_ATTR_MAX = NUM_NL80211_PMSR_RESP_ATTRS - 1
};
+/**
+ * enum nl80211_peer_measurement_ftm_req_type - FTM ranging request type,
+ * used with %NL80211_PMSR_PEER_ATTR_REQ_TYPE
+ *
+ * @NL80211_PMSR_FTM_REQ_TYPE_INFRA: infrastructure ranging, i.e. STA-to-AP
+ * @NL80211_PMSR_FTM_REQ_TYPE_PD: peer-to-peer ranging as defined in the
+ * Wi-Fi Alliance specification "Proximity Ranging (PR) Implementation
+ * Consideration Draft 1.9 Rev 1"
+ * @NUM_NL80211_PMSR_FTM_REQ_TYPE: internal
+ * @NL80211_PMSR_FTM_REQ_TYPE_MAX: highest request type value
+ */
+enum nl80211_peer_measurement_ftm_req_type {
+ NL80211_PMSR_FTM_REQ_TYPE_INFRA,
+ NL80211_PMSR_FTM_REQ_TYPE_PD,
+
+ /* keep last */
+ NUM_NL80211_PMSR_FTM_REQ_TYPE,
+ NL80211_PMSR_FTM_REQ_TYPE_MAX = NUM_NL80211_PMSR_FTM_REQ_TYPE - 1
+};
+
/**
* enum nl80211_peer_measurement_peer_attrs - peer attributes for measurement
* @__NL80211_PMSR_PEER_ATTR_INVALID: invalid
* @NL80211_PMSR_PEER_ATTR_RESP: This is a nested attribute indexed by
* measurement type, with attributes from the
* &enum nl80211_peer_measurement_resp inside.
+ * @NL80211_PMSR_PEER_ATTR_REQ_TYPE: u32 attribute specifying the ranging
+ * request type, using values from &enum nl80211_peer_measurement_ftm_req_type.
+ * If absent, defaults to %NL80211_PMSR_FTM_REQ_TYPE_INFRA.
*
* @NUM_NL80211_PMSR_PEER_ATTRS: internal
* @NL80211_PMSR_PEER_ATTR_MAX: highest attribute number
NL80211_PMSR_PEER_ATTR_CHAN,
NL80211_PMSR_PEER_ATTR_REQ,
NL80211_PMSR_PEER_ATTR_RESP,
+ NL80211_PMSR_PEER_ATTR_REQ_TYPE,
/* keep last */
NUM_NL80211_PMSR_PEER_ATTRS,
* default 15 i.e. "no preference"). For non-EDCA ranging, this is the
* burst duration in milliseconds (optional with default 0, i.e. let the
* device decide).
- * @NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST: number of successful FTM frames
- * requested per burst
+ * @NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST: (Optional) number of successful
+ * FTM frames requested per burst
* (u8, 0-31, optional with default 0 i.e. "no preference")
+ * If the attribute is absent ("no preference"), the driver or firmware can
+ * choose a suitable value.
* @NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES: number of FTMR frame retries
* (u8, default 3)
* @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI: request LCI data (flag)
* Only valid if %NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK is set (so the
* RSTA will have the measurement results to report back in the FTM
* response).
+ * @NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS: minimum time
+ * between two consecutive range measurements in units of 100 microseconds,
+ * for non-trigger based ranging (u32). Should be set as short as possible
+ * to minimize turnaround time, since two-way ranging with delayed LMR
+ * requires two measurements. Only valid if
+ * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * @NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS: maximum time
+ * between two consecutive range measurements in units of 10 milliseconds,
+ * for non-trigger based ranging (u32). Acts as a session timeout; if
+ * exceeded, the ranging session should be terminated. Only valid if
+ * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * @NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME: The nominal time field shall be
+ * set to the nominal duration between adjacent Availability Windows in
+ * units of milli seconds (u32). Mandatory if
+ * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * @NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION: (Optional) The AW duration field
+ * shall be set to the duration of the AW in units of 1ms (0-255 ms) (u32).
+ * Only valid if %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * If the attribute is absent ("no preference"), the driver or firmware
+ * can choose a suitable value.
+ * @NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS: (Optional) number of
+ * Availability Windows (AWs) to schedule for non-trigger-based ranging.
+ * Each AW may contain multiple FTM exchanges as configured by
+ * %NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST. Only valid if
+ * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * If the attribute is absent ("no preference"), the driver or firmware
+ * can choose a suitable value.
*
* @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal
* @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number
NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK,
NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR,
NL80211_PMSR_FTM_REQ_ATTR_RSTA,
+ NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS,
+ NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS,
+ NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME,
+ NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION,
+ NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS,
/* keep last */
NUM_NL80211_PMSR_FTM_REQ_ATTR,
[NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK] = { .type = NLA_FLAG },
[NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR] = { .type = NLA_U8 },
[NL80211_PMSR_FTM_REQ_ATTR_RSTA] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS] = {
+ .type = NLA_U32
+ },
+ [NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS] = {
+ .type = NLA_U32
+ },
+ [NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION] = NLA_POLICY_MAX(NLA_U32, 255),
+ [NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS] = { .type = NLA_U32 },
};
static const struct nla_policy
[NL80211_PMSR_PEER_ATTR_REQ] =
NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy),
[NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
+ [NL80211_PMSR_PEER_ATTR_REQ_TYPE] =
+ NLA_POLICY_MAX(NLA_U32, NL80211_PMSR_FTM_REQ_TYPE_MAX),
};
static const struct nla_policy
nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST]);
if (capa->ftm.max_ftms_per_burst &&
- (out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst ||
- out->ftm.ftms_per_burst == 0)) {
+ out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst) {
NL_SET_ERR_MSG_ATTR(info->extack,
tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST],
- "FTM: FTMs per burst must be set lower than the device limit but non-zero");
+ "FTM: FTMs per burst must be set lower than the device limit");
return -EINVAL;
}
return -EINVAL;
}
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ out->ftm.trigger_based) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ ftmreq,
+ "FTM: TB ranging is not supported for PD request type");
+ return -EINVAL;
+ }
+
out->ftm.non_trigger_based =
!!tb[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED];
if (out->ftm.non_trigger_based && !capa->ftm.non_trigger_based) {
return -EINVAL;
}
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ out->ftm.non_trigger_based && out->ftm.ftms_per_burst > 4) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST],
+ "FTM: FTMs per burst must not exceed 4 for PD NTB ranging");
+ return -ERANGE;
+ }
+
if (out->ftm.ftms_per_burst > 31 && !out->ftm.non_trigger_based &&
!out->ftm.trigger_based) {
NL_SET_ERR_MSG_ATTR(info->extack,
return -EINVAL;
}
+ if (out->ftm.non_trigger_based) {
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ !tb[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME]) {
+ NL_SET_ERR_MSG(info->extack,
+ "FTM: nominal time is required for PD NTB ranging");
+ return -EINVAL;
+ }
+ out->ftm.nominal_time =
+ nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS])
+ out->ftm.min_time_between_measurements =
+ nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS])
+ out->ftm.max_time_between_measurements =
+ nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION])
+ out->ftm.availability_window =
+ nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS])
+ out->ftm.num_measurements =
+ nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS]);
+ }
+
return 0;
}
memcpy(out->addr, nla_data(tb[NL80211_PMSR_PEER_ATTR_ADDR]), ETH_ALEN);
+ if (tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE])
+ out->ftm.request_type =
+ nla_get_u32(tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE]);
+ else
+ out->ftm.request_type = NL80211_PMSR_FTM_REQ_TYPE_INFRA;
+
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ !rdev->wiphy.pmsr_capa->ftm.type.pd_support) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE],
+ "FTM: PD request type not supported by device");
+ return -EINVAL;
+ }
/* reuse info->attrs */
memset(info->attrs, 0, sizeof(*info->attrs) * (NL80211_ATTR_MAX + 1));
err = nla_parse_nested_deprecated(info->attrs, NL80211_ATTR_MAX,