driver: Function to directly poll signal quality
authorPaul Stewart <pstew@google.com>
Thu, 31 Mar 2011 14:56:48 +0000 (17:56 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 31 Mar 2011 14:56:48 +0000 (17:56 +0300)
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 <pstew@google.com>
src/drivers/driver.h
src/drivers/driver_ndis.c
src/drivers/driver_nl80211.c
wpa_supplicant/driver_i.h

index 3627f7d..2836224 100644 (file)
@@ -707,6 +707,17 @@ enum tdls_oper {
 };
 
 /**
+ * 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
  *
  * This structure defines the API that each driver interface needs to implement
@@ -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
index 762931e..aeb7304 100644 (file)
@@ -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 */
 };
index 20440f1..59d44a1 100644 (file)
@@ -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,
index 2f57af4..693491b 100644 (file)
@@ -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,