[PATCH V2] wpa_supplicant: Add bandwidth and center freq info to signal_poll
Ilan Peer
ilan.peer
Wed Jun 5 23:11:42 PDT 2013
From: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
Change-Id: I35a0dd5711951b180e4c84626a77a2967057b13d
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
Signed-hostap: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
Reviewed-by: Ilan Peer <ilan.peer at intel.com>
---
src/drivers/driver.h | 14 ++++++++
src/drivers/driver_nl80211.c | 72 ++++++++++++++++++++++++++++++++++++++++--
wpa_supplicant/ctrl_iface.c | 27 ++++++++++++++--
3 files changed, 109 insertions(+), 4 deletions(-)
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 03fc2b3..07cc1d2 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1090,6 +1090,17 @@ enum wnm_oper {
WNM_SLEEP_TFS_IE_DEL /* AP delete the TFS IE */
};
+/* enum chan_width - channel width definitions */
+enum chan_width {
+ CHAN_WIDTH_20_NOHT,
+ CHAN_WIDTH_20,
+ CHAN_WIDTH_40,
+ CHAN_WIDTH_80,
+ CHAN_WIDTH_80P80,
+ CHAN_WIDTH_160,
+ CHAN_WIDTH_UNKNOWN
+};
+
/**
* struct wpa_signal_info - Information about channel signal quality
*/
@@ -1099,6 +1110,9 @@ struct wpa_signal_info {
int current_signal;
int current_noise;
int current_txrate;
+ enum chan_width chanwidth;
+ int center_frq1;
+ int center_frq2;
};
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index e1e27ea..5484d87 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -9207,6 +9207,73 @@ nla_put_failure:
return ret;
}
+/* Converts nl80211_chan_width to a common format */
+static enum chan_width convert2width(int width)
+{
+ switch (width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ return CHAN_WIDTH_20_NOHT;
+ case NL80211_CHAN_WIDTH_20:
+ return CHAN_WIDTH_20;
+ case NL80211_CHAN_WIDTH_40:
+ return CHAN_WIDTH_40;
+ case NL80211_CHAN_WIDTH_80:
+ return CHAN_WIDTH_80;
+ case NL80211_CHAN_WIDTH_80P80:
+ return CHAN_WIDTH_80P80;
+ case NL80211_CHAN_WIDTH_160:
+ return CHAN_WIDTH_160;
+ }
+ return CHAN_WIDTH_UNKNOWN;
+}
+
+static int get_channel_width(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct wpa_signal_info *sig_change = arg;
+
+ wpa_printf(MSG_DEBUG, "nl80211: parse channel width data");
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ sig_change->center_frq1 = -1;
+ sig_change->center_frq2 = -1;
+ sig_change->chanwidth = -1;
+
+ if (tb[NL80211_ATTR_CHANNEL_WIDTH]) {
+ sig_change->chanwidth = convert2width(
+ nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH]));
+ if (tb[NL80211_ATTR_CENTER_FREQ1])
+ sig_change->center_frq1 =
+ nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
+ if (tb[NL80211_ATTR_CENTER_FREQ2])
+ sig_change->center_frq2 =
+ nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
+ }
+ return NL_SKIP;
+}
+
+static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv,
+ struct wpa_signal_info *sig)
+{
+ struct nl_msg *msg;
+
+ wpa_printf(MSG_DEBUG, "nl80211: getting channel width");
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_INTERFACE);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+ return send_and_recv_msgs(drv, msg, get_channel_width, sig);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
{
@@ -9218,11 +9285,12 @@ static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
res = nl80211_get_link_signal(drv, si);
if (res != 0)
return res;
-
+ res = nl80211_get_channel_width(drv, si);
+ if (res != 0)
+ return res;
return nl80211_get_link_noise(drv, si);
}
-
static int wpa_driver_nl80211_shared_freq(void *priv)
{
struct i802_bss *bss = priv;
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 49157bf..7b26493 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -4998,6 +4998,26 @@ static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd
#endif /* CONFIG_WNM */
+/* get string representation of channel width */
+static char *channel_width_name(enum chan_width width)
+{
+ switch (width) {
+ case CHAN_WIDTH_20_NOHT:
+ return "20 MHz (no HT)";
+ case CHAN_WIDTH_20:
+ return "20 MHz";
+ case CHAN_WIDTH_40:
+ return "40 MHz";
+ case CHAN_WIDTH_80:
+ return "80 MHz";
+ case CHAN_WIDTH_80P80:
+ return "80+80 MHz";
+ case CHAN_WIDTH_160:
+ return "160 MHz";
+ default:
+ return "unknown";
+ }
+}
static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
size_t buflen)
@@ -5010,9 +5030,12 @@ static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
return -1;
ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n"
- "NOISE=%d\nFREQUENCY=%u\n",
+ "NOISE=%d\nFREQUENCY=%u\nWIDTH=%s\n"
+ "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
si.current_signal, si.current_txrate / 1000,
- si.current_noise, si.frequency);
+ si.current_noise, si.frequency,
+ channel_width_name(si.chanwidth),
+ si.center_frq1, si.center_frq2);
if (ret < 0 || (unsigned int) ret > buflen)
return -1;
return ret;
--
1.7.10.4
More information about the Hostap
mailing list