From 1c5c7273f55d7ce867bd29558dcd0ebef9264ea1 Mon Sep 17 00:00:00 2001 From: Paul Stewart Date: Thu, 31 Mar 2011 17:56:48 +0300 Subject: [PATCH] driver: Function to directly poll signal quality This provides a means for the supplicant to directly request signal quality metrics from the driver. This is useful, for example for background scan algorithms that might ask desire this information out-of-band with CQM events. Signed-off-by: Paul Stewart --- src/drivers/driver.h | 28 ++++++++++++++++++++-------- src/drivers/driver_ndis.c | 3 ++- src/drivers/driver_nl80211.c | 26 +++++++++++++++++++++----- wpa_supplicant/driver_i.h | 8 ++++++++ 4 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 3627f7d00..2836224a3 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -706,6 +706,17 @@ enum tdls_oper { TDLS_DISABLE }; +/** + * struct wpa_signal_info - Information about channel signal quality + */ +struct wpa_signal_info { + u32 frequency; + int above_threshold; + int current_signal; + int current_noise; + int current_txrate; +}; + /** * struct wpa_driver_ops - Driver interface API definition * @@ -2221,6 +2232,13 @@ struct wpa_driver_ops { const u8 *buf, size_t len); int (*tdls_oper)(void *priv, enum tdls_oper oper, const u8 *peer); + + /** + * signal_poll - Get current connection information + * @priv: Private driver interface data + * @signal_info: Connection info structure + */ + int (*signal_poll)(void *priv, struct wpa_signal_info *signal_info); }; @@ -3051,15 +3069,9 @@ union wpa_event_data { } eapol_rx; /** - * struct signal_change - Data for EVENT_SIGNAL_CHANGE events + * signal_change - Data for EVENT_SIGNAL_CHANGE events */ - struct signal_change { - u32 frequency; - int above_threshold; - int current_signal; - int current_noise; - int current_txrate; - } signal_change; + struct wpa_signal_info signal_change; /** * struct best_channel - Data for EVENT_BEST_CHANNEL events diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c index 762931ec8..aeb730413 100644 --- a/src/drivers/driver_ndis.c +++ b/src/drivers/driver_ndis.c @@ -3326,5 +3326,6 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = { NULL /* p2p_reject */, NULL /* p2p_invite */, NULL /* send_tdls_mgmt */, - NULL /* tdls_oper */ + NULL /* tdls_oper */, + NULL /* signal_poll */ }; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 20440f103..59d44a1da 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -1082,7 +1082,7 @@ static int get_link_signal(struct nl_msg *msg, void *arg) [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG }, [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG }, }; - struct signal_change *sig_change = arg; + struct wpa_signal_info *sig_change = arg; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); @@ -1115,7 +1115,7 @@ static int get_link_signal(struct nl_msg *msg, void *arg) static int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv, - struct signal_change *sig) + struct wpa_signal_info *sig) { struct nl_msg *msg; @@ -1147,7 +1147,7 @@ static int get_link_noise(struct nl_msg *msg, void *arg) [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 }, [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 }, }; - struct signal_change *sig_change = arg; + struct wpa_signal_info *sig_change = arg; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); @@ -1183,7 +1183,7 @@ static int get_link_noise(struct nl_msg *msg, void *arg) static int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv, - struct signal_change *sig_change) + struct wpa_signal_info *sig_change) { struct nl_msg *msg; @@ -1217,7 +1217,7 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1]; enum nl80211_cqm_rssi_threshold_event event; union wpa_event_data ed; - struct signal_change sig; + struct wpa_signal_info sig; int res; if (tb[NL80211_ATTR_CQM] == NULL || @@ -6370,6 +6370,21 @@ nla_put_failure: } +static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + int res; + + os_memset(si, 0, sizeof(*si)); + res = nl80211_get_link_signal(drv, si); + if (res != 0) + return res; + + return nl80211_get_link_noise(drv, si); +} + + static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len, int encrypt) { @@ -6520,6 +6535,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .resume = wpa_driver_nl80211_resume, .send_ft_action = nl80211_send_ft_action, .signal_monitor = nl80211_signal_monitor, + .signal_poll = nl80211_signal_poll, .send_frame = nl80211_send_frame, .set_intra_bss = nl80211_set_intra_bss, .set_param = nl80211_set_param, diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 2f57af44a..693491b97 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -504,6 +504,14 @@ static inline int wpa_drv_signal_monitor(struct wpa_supplicant *wpa_s, return -1; } +static inline int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s, + struct wpa_signal_info *si) +{ + if (wpa_s->driver->signal_poll) + return wpa_s->driver->signal_poll(wpa_s->drv_priv, si); + return -1; +} + static inline int wpa_drv_set_ap_wps_ie(struct wpa_supplicant *wpa_s, const struct wpabuf *beacon, const struct wpabuf *proberesp,