From b9329c5dfeed7d5c55d2117d8dfe326fc40c8fb1 Mon Sep 17 00:00:00 2001
From: Antonio Quartulli <ordex@autistici.org>
Date: Tue, 3 Jul 2012 00:36:24 +0200
Subject: [PATCH] wpa_s: support htmode param

possible values are HT20, HT40-, HT40+ and NOHT

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 src/drivers/driver.h            |    2 ++
 src/drivers/driver_nl80211.c    |   16 ++++++++++
 wpa_supplicant/config.c         |   66 +++++++++++++++++++++++++++++++++++++++
 wpa_supplicant/config_ssid.h    |    2 ++
 wpa_supplicant/wpa_supplicant.c |    2 ++
 5 files changed, 88 insertions(+)

--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -356,6 +356,8 @@ struct wpa_driver_associate_params {
 	int fixed_freq;
 	unsigned char rates[NL80211_MAX_SUPP_RATES];
 	int mcast_rate;
+	int ht_set;
+	unsigned int htmode;
 
 	/**
 	 * bg_scan_period - Background scan period in seconds, 0 to disable
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -6651,6 +6651,22 @@ retry:
 		NLA_PUT_U32(msg, NL80211_ATTR_MCAST_RATE, params->mcast_rate);
 	}
 
+	if (params->ht_set) {
+		switch(params->htmode) {
+			case NL80211_CHAN_HT20:
+				wpa_printf(MSG_DEBUG, "  * ht=HT20");
+				break;
+			case NL80211_CHAN_HT40PLUS:
+				wpa_printf(MSG_DEBUG, "  * ht=HT40+");
+				break;
+			case NL80211_CHAN_HT40MINUS:
+				wpa_printf(MSG_DEBUG, "  * ht=HT40-");
+				break;
+		}
+		NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+			    params->htmode);
+	}
+
 	ret = nl80211_set_conn_keys(params, msg);
 	if (ret)
 		goto nla_put_failure;
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1495,6 +1495,71 @@ static char * wpa_config_write_mcast_rat
 }
 #endif /* NO_CONFIG_WRITE */
 
+static int wpa_config_parse_htmode(const struct parse_data *data,
+				   struct wpa_ssid *ssid, int line,
+				   const char *value)
+{
+	int i;
+	static const struct {
+		const char *name;
+		unsigned int val;
+	} htmap[] = {
+		{ .name = "HT20", .val = NL80211_CHAN_HT20, },
+		{ .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
+		{ .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
+		{ .name = "NOHT", .val = NL80211_CHAN_NO_HT, },
+	};
+	ssid->ht_set = 0;;
+	for (i = 0; i < 4; i++) {
+		if (strcasecmp(htmap[i].name, value) == 0) {
+			ssid->htmode = htmap[i].val;
+			ssid->ht_set = 1;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_htmode(const struct parse_data *data,
+				      struct wpa_ssid *ssid)
+{
+	char *value;
+	int res;
+
+	value = os_malloc(6); /* longest: HT40+ */
+	if (value == NULL)
+		return NULL;
+
+	switch(ssid->htmode) {
+		case NL80211_CHAN_HT20:
+			res = os_snprintf(value, 4, "HT20");
+			break;
+		case NL80211_CHAN_HT40PLUS:
+			res = os_snprintf(value, 5, "HT40+");
+			break;
+		case NL80211_CHAN_HT40MINUS:
+			res = os_snprintf(value, 5, "HT40-");
+			break;
+		case NL80211_CHAN_NO_HT:
+			res = os_snprintf(value, 4, "NOHT");
+			break;
+		default:
+			os_free(value);
+			return NULL;
+	}
+
+	if (res < 0) {
+		os_free(value);
+		return NULL;
+	}
+
+	return value;
+}
+#endif /* NO_CONFIG_WRITE */
+
+
 static int wpa_config_parse_rates(const struct parse_data *data,
 				  struct wpa_ssid *ssid, int line,
 				  const char *value)
@@ -1734,6 +1799,7 @@ static const struct parse_data ssid_fiel
 	{ INT_RANGE(beacon_interval, 0, 1000) },
 	{ FUNC(rates) },
 	{ FUNC(mcast_rate) },
+	{ FUNC(htmode) },
 };
 
 #undef OFFSET
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -535,6 +535,8 @@ struct wpa_ssid {
 	int beacon_interval;
 	unsigned char rates[NL80211_MAX_SUPP_RATES];
 	double mcast_rate;
+	int ht_set;
+	unsigned int htmode;
 };
 
 #endif /* CONFIG_SSID_H */
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1577,6 +1577,8 @@ void wpa_supplicant_associate(struct wpa
 			i++;
 		}
 		params.mcast_rate = ssid->mcast_rate;
+		params.ht_set = ssid->ht_set;
+		params.htmode = ssid->htmode;
 	}
 
 	params.wpa_ie = wpa_ie;