Patchwork wpa_supplicant: Add bandwidth and center freq info to signal_poll

login
register
mail settings
Submitter Ilan Peer
Date May 28, 2013, 1:20 p.m.
Message ID <1369747228-10156-1-git-send-email-ilan.peer@intel.com>
Download mbox | patch
Permalink /patch/246869/
State Superseded
Headers show

Comments

Ilan Peer - May 28, 2013, 1:20 p.m.
From: Andrei Otcheretianski <andrei.otcheretianski@intel.com>

Change-Id: Ia11162e5100f2606bc0f895f4d34f78cce7c5a5d
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Reviewed-on: https://gerrit.rds.intel.com/13914
Tested-by: IWL Jenkins
Reviewed-by: Ilan Peer <ilan.peer@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(-)

Patch

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 4e7f86d..38ffc49 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -9204,6 +9204,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)
 {
@@ -9215,11 +9282,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;