From 60a972a68da94de6182b2ca52c9b4184b00afc45 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Aug 2010 16:58:06 +0300 Subject: [PATCH] Add current signal strength into signal quality change events --- src/drivers/driver.h | 1 + src/drivers/driver_nl80211.c | 54 ++++++++++++++++++++++++++++++++++ wpa_supplicant/bgscan.c | 6 ++-- wpa_supplicant/bgscan.h | 8 +++-- wpa_supplicant/bgscan_learn.c | 5 ++-- wpa_supplicant/bgscan_simple.c | 5 ++-- wpa_supplicant/events.c | 3 +- 7 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 85ca0a5be..3c3bf9c9f 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2452,6 +2452,7 @@ union wpa_event_data { */ struct signal_change { int above_threshold; + int current_signal; } signal_change; }; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 3ad8812e5..0590fed96 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -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); } diff --git a/wpa_supplicant/bgscan.c b/wpa_supplicant/bgscan.c index e5fdfc4f7..e76e95453 100644 --- a/wpa_supplicant/bgscan.c +++ b/wpa_supplicant/bgscan.c @@ -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); } diff --git a/wpa_supplicant/bgscan.h b/wpa_supplicant/bgscan.h index e0c9eb01f..9f2ba2f4f 100644 --- a/wpa_supplicant/bgscan.h +++ b/wpa_supplicant/bgscan.h @@ -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) { } diff --git a/wpa_supplicant/bgscan_learn.c b/wpa_supplicant/bgscan_learn.c index 32305a4d5..865347b31 100644 --- a/wpa_supplicant/bgscan_learn.c +++ b/wpa_supplicant/bgscan_learn.c @@ -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"); diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c index aeecc01aa..b58cb76ae 100644 --- a/wpa_supplicant/bgscan_simple.c +++ b/wpa_supplicant/bgscan_simple.c @@ -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"); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 2ca55d855..80a9f858c 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -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");