[RFC PATCH 21/23] wpa_supplicant: Implement FTM peer measurement result handling
Peddolla Harshavardhan Reddy
peddolla.reddy at oss.qualcomm.com
Tue Mar 31 22:27:11 PDT 2026
There is no mechanism to receive and process Fine Timing Measurement
(FTM) peer measurement results from the nl80211 driver in the proximity
ranging subsystem.
Add a new nl80211 event handler for NL80211_CMD_PEER_MEASUREMENT_RESULT
that parses the incoming netlink message and populates a new
peer_measurement_result structure, including all FTM-specific attributes.
Wire this up through the driver event interface and handle it in
wpa_supplicant by introducing wpas_pr_measurement_result(). Define two
new control interface events, PR_EVENT_PEER_MEASUREMENT for intermediate
per-burst results and PR_EVENT_PEER_MEASUREMENT_COMPLETE for the final
session result, carrying the peer address, status, and key FTM metrics
such as RTT and distance averages.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy at oss.qualcomm.com>
---
src/common/wpa_ctrl.h | 6 +
src/drivers/driver.h | 64 ++++++++
src/drivers/driver_common.c | 1 +
src/drivers/driver_nl80211_event.c | 254 +++++++++++++++++++++++++++++
wpa_supplicant/events.c | 7 +
wpa_supplicant/pr_supplicant.c | 58 +++++++
wpa_supplicant/pr_supplicant.h | 8 +
7 files changed, 398 insertions(+)
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 963d30421..c7c61e6d1 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -480,6 +480,12 @@ extern "C" {
/* Proximity Ranging parameters to use in ranging */
#define PR_RANGING_PARAMS "PR-RANGING-PARAMS "
+/* Proximity Ranging measurement result */
+#define PR_EVENT_PEER_MEASUREMENT "PR-PEER-MEASUREMENT "
+
+/* Proximity Ranging measurement complete */
+#define PR_EVENT_PEER_MEASUREMENT_COMPLETE "PR-PEER-MEASUREMENT-COMPLETE "
+
/* BSS command information masks */
#define WPA_BSS_MASK_ALL 0xFFFDFFFF
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index c250bdaa9..8ccc0d6f0 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -6381,6 +6381,14 @@ enum wpa_event_type {
*/
EVENT_SETUP_LINK_RECONFIG,
+ /**
+ * EVENT_PEER_MEASUREMENT_RESULT - Ranging measurement result
+ *
+ * The driver uses this event to indicate completion of a ranging
+ * measurement.
+ */
+ EVENT_PEER_MEASUREMENT_RESULT,
+
/**
* EVENT_NAN_CLUSTER_JOIN - Notification of a new cluster having been
* joined or started.
@@ -7432,6 +7440,62 @@ union wpa_event_data {
u32 chan_bw_interference_bitmap;
int link_id;
} incumbt_sig_intf_event;
+
+ /**
+ * struct peer_measurement_result - Ranging measurement result
+ */
+ struct peer_measurement_result {
+ u8 addr[ETH_ALEN];
+ u32 status;
+ u64 host_time;
+ u64 ap_tsf;
+ u8 final;
+ u64 cookie;
+
+ /**
+ * struct peer_measurement_ftm_result -
+ * FTM-specific measurement results
+ */
+ struct peer_measurement_ftm_result {
+ u8 fail;
+ u32 burst_index;
+ u32 num_ftmr_attempts;
+ u32 num_ftmr_successes;
+ u32 busy_retry_time;
+ u32 num_bursts_exp;
+ u32 burst_duration;
+ u32 ftms_per_burst;
+ s32 rssi_avg;
+ s32 rssi_spread;
+ s64 rtt_avg;
+ u64 rtt_variance;
+ u64 rtt_spread;
+ s64 dist_avg;
+ u64 dist_variance;
+ u64 dist_spread;
+ const u8 *lci;
+ size_t lci_len;
+ const u8 *civicloc;
+ size_t civicloc_len;
+ /* Additional FTM parameters */
+ u32 burst_period;
+ u32 tx_ltf_repetition_count;
+ u32 rx_ltf_repetition_count;
+ u32 max_time_between_measurements;
+ u32 min_time_between_measurements;
+ u32 num_tx_spatial_streams;
+ u32 num_rx_spatial_streams;
+ u16 nominal_time;
+ u8 availability_window;
+ u8 measurements_per_aw;
+ u32 band_width;
+ u32 preamble;
+ u8 is_delayed_lmr;
+ /* Flag indicating if FTM data is present */
+ u8 has_data;
+ } ftm;
+
+ } peer_measurement_result;
};
/**
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index 50a0b682d..f41d6fad3 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -102,6 +102,7 @@ const char * event_to_string(enum wpa_event_type event)
E2S(LINK_RECONFIG);
E2S(MLD_INTERFACE_FREED);
E2S(SETUP_LINK_RECONFIG);
+ E2S(PEER_MEASUREMENT_RESULT);
E2S(NAN_CLUSTER_JOIN);
E2S(NAN_NEXT_DW);
E2S(INCUMBT_SIG_INTF_DETECTED);
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index d71b06d5f..bed4b57a8 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -4083,6 +4083,255 @@ static void nl80211_assoc_comeback(struct wpa_driver_nl80211_data *drv,
MAC2STR((u8 *) nla_data(mac)), nla_get_u32(timeout));
}
+#ifdef CONFIG_PR
+
+static void
+nl80211_parse_peer_ftm_result(struct peer_measurement_ftm_result *ftm,
+ struct nlattr *ftm_data)
+{
+ struct nlattr *ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_MAX + 1];
+
+ if (nla_parse_nested(ftm_tb, NL80211_PMSR_FTM_RESP_ATTR_MAX,
+ ftm_data, NULL))
+ return;
+
+ ftm->has_data = 1;
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON]) {
+ ftm->fail = 1;
+ wpa_printf(MSG_ERROR,
+ "nl80211: Ranging has failed with status %u",
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON]));
+ return;
+ }
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX])
+ ftm->burst_index =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS])
+ ftm->num_ftmr_attempts =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES])
+ ftm->num_ftmr_successes =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME])
+ ftm->busy_retry_time =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP])
+ ftm->num_bursts_exp =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION])
+ ftm->burst_duration =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST])
+ ftm->ftms_per_burst =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG])
+ ftm->rssi_avg =
+ nla_get_s32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD])
+ ftm->rssi_spread =
+ nla_get_s32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG])
+ ftm->rtt_avg =
+ nla_get_s64(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE])
+ ftm->rtt_variance =
+ nla_get_u64(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD])
+ ftm->rtt_spread =
+ nla_get_u64(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG])
+ ftm->dist_avg =
+ nla_get_s64(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE])
+ ftm->dist_variance =
+ nla_get_u64(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD])
+ ftm->dist_spread =
+ nla_get_u64(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_LCI]) {
+ ftm->lci = nla_data(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_LCI]);
+ ftm->lci_len = nla_len(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_LCI]);
+ }
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]) {
+ ftm->civicloc =
+ nla_data(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]);
+ ftm->civicloc_len =
+ nla_len(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]);
+ }
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_BURST_PERIOD])
+ ftm->burst_period =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_BURST_PERIOD]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT])
+ ftm->tx_ltf_repetition_count =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT])
+ ftm->rx_ltf_repetition_count =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS])
+ ftm->max_time_between_measurements =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS])
+ ftm->min_time_between_measurements =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS])
+ ftm->num_tx_spatial_streams =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS])
+ ftm->num_rx_spatial_streams =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME])
+ ftm->nominal_time =
+ nla_get_u16(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW])
+ ftm->availability_window =
+ nla_get_u8(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_MEASUREMENTS_PER_AW])
+ ftm->measurements_per_aw =
+ nla_get_u8(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_MEASUREMENTS_PER_AW]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH])
+ ftm->band_width =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE])
+ ftm->preamble =
+ nla_get_u32(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE]);
+
+ if (ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR])
+ ftm->is_delayed_lmr =
+ nla_get_flag(ftm_tb[NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR]);
+}
+
+
+static void nl80211_peer_measurement_result_event(struct i802_bss *bss,
+ struct nlattr **tb)
+{
+ union wpa_event_data data;
+ struct nlattr *pmsr[NL80211_PMSR_ATTR_MAX + 1];
+ struct nlattr *peer;
+ u64 cookie = 0;
+ int rem;
+ static struct nla_policy pmsr_policy[NL80211_PMSR_ATTR_MAX + 1] = {
+ [NL80211_PMSR_ATTR_PEERS] = { .type = NLA_NESTED },
+ };
+ static struct nla_policy peer_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
+ [NL80211_PMSR_PEER_ATTR_ADDR] = {
+ .minlen = ETH_ALEN,
+ .maxlen = ETH_ALEN,
+ },
+ [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_NESTED },
+ };
+ static struct nla_policy resp_policy[NL80211_PMSR_RESP_ATTR_MAX + 1] = {
+ [NL80211_PMSR_RESP_ATTR_DATA] = { .type = NLA_NESTED },
+ [NL80211_PMSR_RESP_ATTR_STATUS] = { .type = NLA_U32 },
+ [NL80211_PMSR_RESP_ATTR_HOST_TIME] = { .type = NLA_U64 },
+ [NL80211_PMSR_RESP_ATTR_AP_TSF] = { .type = NLA_U64 },
+ [NL80211_PMSR_RESP_ATTR_FINAL] = { .type = NLA_FLAG },
+ };
+
+ os_memset(&data, 0, sizeof(data));
+ if (tb[NL80211_ATTR_COOKIE]) {
+ cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
+ data.peer_measurement_result.cookie = cookie;
+ wpa_printf(MSG_DEBUG,
+ "nl80211: PR: Peer measurement cookie: %llu",
+ (unsigned long long) cookie);
+ }
+
+ if (!tb[NL80211_ATTR_PEER_MEASUREMENTS] ||
+ nla_parse_nested(pmsr, NL80211_PMSR_ATTR_MAX,
+ tb[NL80211_ATTR_PEER_MEASUREMENTS], pmsr_policy))
+ return;
+
+ if (!pmsr[NL80211_PMSR_ATTR_PEERS])
+ return;
+
+ nla_for_each_nested(peer, pmsr[NL80211_PMSR_ATTR_PEERS], rem) {
+ struct nlattr *peer_tb[NL80211_PMSR_PEER_ATTR_MAX + 1];
+ struct nlattr *resp_tb[NL80211_PMSR_RESP_ATTR_MAX + 1];
+
+ if (nla_parse_nested(peer_tb, NL80211_PMSR_PEER_ATTR_MAX,
+ peer, peer_policy))
+ continue;
+
+ if (!peer_tb[NL80211_PMSR_PEER_ATTR_ADDR] ||
+ !peer_tb[NL80211_PMSR_PEER_ATTR_RESP])
+ continue;
+
+ os_memcpy(data.peer_measurement_result.addr,
+ nla_data(peer_tb[NL80211_PMSR_PEER_ATTR_ADDR]),
+ ETH_ALEN);
+
+ if (nla_parse_nested(resp_tb, NL80211_PMSR_RESP_ATTR_MAX,
+ peer_tb[NL80211_PMSR_PEER_ATTR_RESP],
+ resp_policy))
+ continue;
+
+ if (resp_tb[NL80211_PMSR_RESP_ATTR_STATUS])
+ data.peer_measurement_result.status =
+ nla_get_u32(resp_tb[NL80211_PMSR_RESP_ATTR_STATUS]);
+
+ if (resp_tb[NL80211_PMSR_RESP_ATTR_HOST_TIME])
+ data.peer_measurement_result.host_time =
+ nla_get_u64(resp_tb[NL80211_PMSR_RESP_ATTR_HOST_TIME]);
+
+ if (resp_tb[NL80211_PMSR_RESP_ATTR_AP_TSF])
+ data.peer_measurement_result.ap_tsf =
+ nla_get_u64(resp_tb[NL80211_PMSR_RESP_ATTR_AP_TSF]);
+
+ if (resp_tb[NL80211_PMSR_RESP_ATTR_FINAL])
+ data.peer_measurement_result.final = 1;
+
+ if (resp_tb[NL80211_PMSR_RESP_ATTR_DATA]) {
+ struct nlattr *data_type_tb[NL80211_PMSR_TYPE_MAX + 1];
+
+ if (nla_parse_nested(data_type_tb, NL80211_PMSR_TYPE_MAX,
+ resp_tb[NL80211_PMSR_RESP_ATTR_DATA],
+ NULL))
+ continue;
+
+ if (data_type_tb[NL80211_PMSR_TYPE_FTM])
+ nl80211_parse_peer_ftm_result(&data.peer_measurement_result.ftm,
+ data_type_tb[NL80211_PMSR_TYPE_FTM]);
+ }
+
+ wpa_supplicant_event(bss->ctx, EVENT_PEER_MEASUREMENT_RESULT, &data);
+ os_memset(&data.peer_measurement_result, 0,
+ sizeof(data.peer_measurement_result));
+ if (cookie)
+ data.peer_measurement_result.cookie = cookie;
+ }
+}
+
+#endif /* CONFIG_PR */
#ifdef CONFIG_IEEE80211AX
@@ -4562,6 +4811,11 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
case NL80211_CMD_INCUMBENT_SIGNAL_DETECT:
nl80211_incumbt_sig_intf_event(bss, tb);
break;
+#ifdef CONFIG_PR
+ case NL80211_CMD_PEER_MEASUREMENT_RESULT:
+ nl80211_peer_measurement_result_event(bss, tb);
+ break;
+#endif /* CONFIG_PR */
default:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
"(cmd=%d)", cmd);
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 3d05df2e3..aa2d17890 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -7610,6 +7610,13 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
if (data)
wpas_setup_link_reconfig(wpa_s, &data->reconfig_info);
break;
+ case EVENT_PEER_MEASUREMENT_RESULT:
+#ifdef CONFIG_PR
+ if (data)
+ wpas_pr_measurement_result(wpa_s,
+ &data->peer_measurement_result);
+#endif /* CONFIG_PR */
+ break;
#ifdef CONFIG_NAN
case EVENT_NAN_CLUSTER_JOIN:
wpas_nan_cluster_join(wpa_s, data->nan_cluster_join_info.bssid,
diff --git a/wpa_supplicant/pr_supplicant.c b/wpa_supplicant/pr_supplicant.c
index bc52c8389..4ac092835 100644
--- a/wpa_supplicant/pr_supplicant.c
+++ b/wpa_supplicant/pr_supplicant.c
@@ -779,6 +779,64 @@ void wpas_pr_set_dev_ik(struct wpa_supplicant *wpa_s, const u8 *dik,
}
+void wpas_pr_measurement_result(struct wpa_supplicant *wpa_s,
+ struct peer_measurement_result *result)
+{
+ struct pr_data *pr = wpa_s->global->pr;
+ char buf[200];
+ int len;
+
+ if (!result) {
+ wpa_printf(MSG_ERROR, "PR: Invalid measurement result");
+ return;
+ }
+
+ /* Validate cookie if we have a pending ranging request */
+ if (pr && pr->pr_pasn_params && result->cookie != 0) {
+ if (pr->pr_pasn_params->cookie != result->cookie) {
+ wpa_printf(MSG_WARNING,
+ "PR: Cookie mismatch - expected %llu, got %llu. Ignoring result.",
+ (unsigned long long) pr->pr_pasn_params->cookie,
+ (unsigned long long) result->cookie);
+ return;
+ }
+ }
+
+ if (result->final) {
+ wpa_msg(wpa_s, MSG_INFO, PR_EVENT_PEER_MEASUREMENT_COMPLETE
+ "addr=" MACSTR " status=%u",
+ MAC2STR(result->addr), result->status);
+ if (pr) {
+ os_free(pr->pr_pasn_params);
+ pr->pr_pasn_params = NULL;
+ }
+ return;
+ }
+
+ /* Per-burst intermediate result */
+ len = os_snprintf(buf, sizeof(buf),
+ PR_EVENT_PEER_MEASUREMENT "addr=" MACSTR
+ " status=%u burst_index=%u",
+ MAC2STR(result->addr), result->status,
+ result->ftm.burst_index);
+
+ if (result->ftm.fail) {
+ os_snprintf(buf + len, sizeof(buf) - len, " fail=1");
+ } else {
+ if (result->ftm.rtt_avg)
+ len += os_snprintf(buf + len, sizeof(buf) - len,
+ " rtt_avg=%lld",
+ (long long) result->ftm.rtt_avg);
+ if (result->ftm.dist_avg)
+ os_snprintf(buf + len, sizeof(buf) - len,
+ " dist_avg=%lld",
+ (long long) result->ftm.dist_avg);
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, "%s", buf);
+}
+
+
#ifdef CONFIG_PASN
static int wpas_pr_start_pd(struct wpa_supplicant *wpa_s, const u8 *src_addr)
diff --git a/wpa_supplicant/pr_supplicant.h b/wpa_supplicant/pr_supplicant.h
index 6972ecacb..bf8daf7a3 100644
--- a/wpa_supplicant/pr_supplicant.h
+++ b/wpa_supplicant/pr_supplicant.h
@@ -42,6 +42,8 @@ void wpas_pr_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
unsigned int freq);
void wpas_pr_pasn_trigger(struct wpa_supplicant *wpa_s,
struct pr_pasn_ranging_params *pr_pasn_params);
+void wpas_pr_measurement_result(struct wpa_supplicant *wpa_s,
+ struct peer_measurement_result *result);
#else /* CONFIG_PR */
@@ -115,6 +117,12 @@ static inline void wpas_pr_pasn_trigger(struct wpa_supplicant *wpa_s,
{
}
+static inline void
+wpas_pr_measurement_result(struct wpa_supplicant *wpa_s,
+ struct peer_measurement_result *result)
+{
+}
+
#endif /* CONFIG_PR */
#endif /* PR_SUPPLICANT_H */
--
2.34.1
More information about the Hostap
mailing list