Add current signal strength into signal quality change events
authorJouni Malinen <j@w1.fi>
Fri, 27 Aug 2010 13:58:06 +0000 (16:58 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 27 Aug 2010 13:58:06 +0000 (16:58 +0300)
src/drivers/driver.h
src/drivers/driver_nl80211.c
wpa_supplicant/bgscan.c
wpa_supplicant/bgscan.h
wpa_supplicant/bgscan_learn.c
wpa_supplicant/bgscan_simple.c
wpa_supplicant/events.c

index 85ca0a5..3c3bf9c 100644 (file)
@@ -2452,6 +2452,7 @@ union wpa_event_data {
         */
        struct signal_change {
                int above_threshold;
+               int current_signal;
        } signal_change;
 };
 
index 3ad8812..0590fed 100644 (file)
@@ -946,6 +946,53 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
 }
 
 
+static int get_link_signal(struct nl_msg *msg, void *arg)
+{
+       struct nlattr *tb[NL80211_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
+       static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {
+               [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+       };
+       int *sig = arg;
+
+       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+       if (!tb[NL80211_ATTR_STA_INFO] ||
+           nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
+                            tb[NL80211_ATTR_STA_INFO], policy))
+               return NL_SKIP;
+       if (!sinfo[NL80211_STA_INFO_SIGNAL])
+               return NL_SKIP;
+
+       *sig = (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
+       return NL_SKIP;
+}
+
+
+static int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
+                                  int *sig)
+{
+       struct nl_msg *msg;
+
+       *sig = -9999;
+
+       msg = nlmsg_alloc();
+       if (!msg)
+               return -ENOMEM;
+
+       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
+                   0, NL80211_CMD_GET_STATION, 0);
+
+       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);
+
+       return send_and_recv_msgs(drv, msg, get_link_signal, sig);
+ nla_put_failure:
+       return -ENOBUFS;
+}
+
+
 static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
                              struct nlattr *tb[])
 {
@@ -957,6 +1004,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;
+       int sig, res;
 
        if (tb[NL80211_ATTR_CQM] == NULL ||
            nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM],
@@ -982,6 +1030,12 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
        } else
                return;
 
+       res = nl80211_get_link_signal(drv, &sig);
+       if (res == 0) {
+               ed.signal_change.current_signal = sig;
+               wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm", sig);
+       }
+
        wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed);
 }
 
index e5fdfc4..e76e954 100644 (file)
@@ -111,8 +111,10 @@ void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s)
 }
 
 
-void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above)
+void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above,
+                                int current_signal)
 {
        if (wpa_s->bgscan && wpa_s->bgscan_priv)
-               wpa_s->bgscan->notify_signal_change(wpa_s->bgscan_priv, above);
+               wpa_s->bgscan->notify_signal_change(wpa_s->bgscan_priv, above,
+                                                   current_signal);
 }
index e0c9eb0..9f2ba2f 100644 (file)
@@ -27,7 +27,8 @@ struct bgscan_ops {
 
        int (*notify_scan)(void *priv, struct wpa_scan_results *scan_res);
        void (*notify_beacon_loss)(void *priv);
-       void (*notify_signal_change)(void *priv, int above);
+       void (*notify_signal_change)(void *priv, int above,
+                                    int current_signal);
 };
 
 #ifdef CONFIG_BGSCAN
@@ -37,7 +38,8 @@ void bgscan_deinit(struct wpa_supplicant *wpa_s);
 int bgscan_notify_scan(struct wpa_supplicant *wpa_s,
                       struct wpa_scan_results *scan_res);
 void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s);
-void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above);
+void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above,
+                                int current_signal);
 
 #else /* CONFIG_BGSCAN */
 
@@ -62,7 +64,7 @@ static inline void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s)
 }
 
 static inline void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s,
-                                              int above)
+                                              int above, int current_signal)
 {
 }
 
index 32305a4..865347b 100644 (file)
@@ -546,7 +546,8 @@ static void bgscan_learn_notify_beacon_loss(void *priv)
 }
 
 
-static void bgscan_learn_notify_signal_change(void *priv, int above)
+static void bgscan_learn_notify_signal_change(void *priv, int above,
+                                             int current_signal)
 {
        struct bgscan_learn_data *data = priv;
 
@@ -555,7 +556,7 @@ static void bgscan_learn_notify_signal_change(void *priv, int above)
                return;
 
        wpa_printf(MSG_DEBUG, "bgscan learn: signal level changed "
-                  "(above=%d)", above);
+                  "(above=%d current_signal=%d)", above, current_signal);
        if (data->scan_interval == data->long_interval && !above) {
                wpa_printf(MSG_DEBUG, "bgscan learn: Trigger immediate scan "
                           "and start using short bgscan interval");
index aeecc01..b58cb76 100644 (file)
@@ -167,7 +167,8 @@ static void bgscan_simple_notify_beacon_loss(void *priv)
 }
 
 
-static void bgscan_simple_notify_signal_change(void *priv, int above)
+static void bgscan_simple_notify_signal_change(void *priv, int above,
+                                              int current_signal)
 {
        struct bgscan_simple_data *data = priv;
 
@@ -176,7 +177,7 @@ static void bgscan_simple_notify_signal_change(void *priv, int above)
                return;
 
        wpa_printf(MSG_DEBUG, "bgscan simple: signal level changed "
-                  "(above=%d)", above);
+                  "(above=%d current_signal=%d)", above, current_signal);
        if (data->scan_interval == data->long_interval && !above) {
                wpa_printf(MSG_DEBUG, "bgscan simple: Trigger immediate scan "
                           "and start using short bgscan interval");
index 2ca55d8..80a9f85 100644 (file)
@@ -1752,7 +1752,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                break;
        case EVENT_SIGNAL_CHANGE:
                bgscan_notify_signal_change(
-                       wpa_s, data->signal_change.above_threshold);
+                       wpa_s, data->signal_change.above_threshold,
+                       data->signal_change.current_signal);
                break;
        case EVENT_INTERFACE_ENABLED:
                wpa_printf(MSG_DEBUG, "Interface was enabled");