[PATCH] P2P: Enable 40MHz support for p2p group addition

Rajkumar Manoharan rmanohar
Tue Jul 10 03:08:57 PDT 2012


Add optional "ht40" argument for p2p_group_add command to enable 40MHz
in 5GHz band. This could configure secondary channel, when 11n support
was enabled and if the HW supports 40MHz channel width.

Signed-hostap: Rajkumar Manoharan <rmanohar at qca.qualcomm.com>
---
 wpa_supplicant/ap.c                         | 64 +++++++++++++++++++++++++++++
 wpa_supplicant/config.h                     |  1 +
 wpa_supplicant/ctrl_iface.c                 | 19 +++++----
 wpa_supplicant/dbus/dbus_new_handlers_p2p.c |  2 +-
 wpa_supplicant/p2p_supplicant.c             | 16 ++++----
 wpa_supplicant/p2p_supplicant.h             |  4 +-
 wpa_supplicant/wpa_cli.c                    | 19 ++++-----
 7 files changed, 97 insertions(+), 28 deletions(-)

diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index f9e0045..394784a 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -40,6 +40,57 @@
 static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
 #endif /* CONFIG_WPS */
 
+#ifdef CONFIG_IEEE80211N
+static int wpas_choose_ht40_sec_chan(struct hostapd_hw_modes *mode,
+				     struct hostapd_config *conf,
+				     int secondary_channel)
+{
+	int sec_chan, ok, j, first;
+	int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
+			  184, 192 };
+	size_t k;
+
+	sec_chan = conf->channel + secondary_channel * 4;
+
+	/* Verify that HT40 secondary channel is an allowed 20 MHz
+	 * channel */
+	ok = 0;
+	for (j = 0; j < mode->num_channels; j++) {
+		struct hostapd_channel_data *chan = &mode->channels[j];
+		if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
+		    chan->chan == sec_chan) {
+			ok = 1;
+			break;
+		}
+	}
+	if (!ok) {
+		wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed",
+			   sec_chan);
+		return 0;
+	}
+
+	if (secondary_channel > 0)
+		first = conf->channel;
+	else
+		first = sec_chan;
+
+	ok = 0;
+	for (k = 0; k < sizeof(allowed) / sizeof(allowed[0]); k++) {
+		if (first == allowed[k]) {
+			ok = 1;
+			break;
+		}
+	}
+	if (!ok) {
+		wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed",
+			   conf->channel,
+			   conf->secondary_channel);
+		return 0;
+	}
+
+	return secondary_channel;
+}
+#endif
 
 static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
 				  struct wpa_ssid *ssid,
@@ -99,6 +150,19 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
 
 		if (!no_ht && mode && mode->ht_capab) {
 			conf->ieee80211n = 1;
+			if ((conf->hw_mode == HOSTAPD_MODE_IEEE80211A) &&
+			    (mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
+			    wpa_s->conf->p2p_go_ht40) {
+				conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+				if (wpas_choose_ht40_sec_chan(mode, conf, 1))
+					conf->secondary_channel = 1;
+				else if (wpas_choose_ht40_sec_chan(mode, conf, -1))
+					conf->secondary_channel = -1;
+				else {
+					conf->secondary_channel = 0;
+					conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+				}
+			}
 
 			/*
 			 * white-list capabilities that won't cause issues
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 46c4da2..b9317e4 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -510,6 +510,7 @@ struct wpa_config {
 	int p2p_oper_reg_class;
 	int p2p_oper_channel;
 	int p2p_go_intent;
+	int p2p_go_ht40;
 	char *p2p_ssid_postfix;
 	int persistent_reconnect;
 	int p2p_intra_bss;
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index cb3e523..10d4777 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -3429,7 +3429,7 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
 
 
 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
-					 char *cmd, int freq)
+					 char *cmd, int freq, int ht40)
 {
 	int id;
 	struct wpa_ssid *ssid;
@@ -3443,26 +3443,31 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
 		return -1;
 	}
 
-	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq);
+	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40);
 }
 
 
 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
 {
-	int freq = 0;
+	int freq = 0, ht40 = 0;
 	char *pos;
 
 	pos = os_strstr(cmd, "freq=");
 	if (pos)
 		freq = atoi(pos + 5);
 
+	if (os_strncmp(cmd, "ht40", 4) == 0)
+		ht40 = 1;
+
 	if (os_strncmp(cmd, "persistent=", 11) == 0)
-		return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq);
+		return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq, ht40);
 	if (os_strcmp(cmd, "persistent") == 0 ||
 	    os_strncmp(cmd, "persistent ", 11) == 0)
-		return wpas_p2p_group_add(wpa_s, 1, freq);
+		return wpas_p2p_group_add(wpa_s, 1, freq, ht40);
 	if (os_strncmp(cmd, "freq=", 5) == 0)
-		return wpas_p2p_group_add(wpa_s, 0, freq);
+		return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
+	if (ht40)
+		return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
 
 	wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
 		   cmd);
@@ -4257,7 +4262,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 		if (wpas_p2p_group_remove(wpa_s, buf + 17))
 			reply_len = -1;
 	} else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
-		if (wpas_p2p_group_add(wpa_s, 0, 0))
+		if (wpas_p2p_group_add(wpa_s, 0, 0, 0))
 			reply_len = -1;
 	} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
 		if (p2p_ctrl_group_add(wpa_s, buf + 14))
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index f4541f7..f784e85 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -346,7 +346,7 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
 		if (ssid == NULL || ssid->disabled != 2)
 			goto inv_args;
 
-		if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq)) {
+		if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0)) {
 			reply = wpas_dbus_error_unknown_error(
 				message,
 				"Failed to reinvoke a persistent group");
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 218ed2f..f2d7fd2 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -841,6 +841,7 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
 		  sizeof(d->sec_device_type));
 	d->num_sec_device_types = s->num_sec_device_types;
 
+	d->p2p_go_ht40 = s->p2p_go_ht40;
 	d->p2p_group_idle = s->p2p_group_idle;
 	d->p2p_intra_bss = s->p2p_intra_bss;
 	d->persistent_reconnect = s->persistent_reconnect;
@@ -2019,7 +2020,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
 			   MAC2STR(sa), op_freq);
 		if (s) {
 			wpas_p2p_group_add_persistent(
-				wpa_s, s, s->mode == WPAS_MODE_P2P_GO, 0);
+				wpa_s, s, s->mode == WPAS_MODE_P2P_GO, 0, 0);
 		} else if (bssid) {
 			wpas_p2p_join(wpa_s, bssid, go_dev_addr,
 				      wpa_s->p2p_wps_method, 0);
@@ -2086,7 +2087,7 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid)
 	}
 
 	wpas_p2p_group_add_persistent(wpa_s, ssid,
-				      ssid->mode == WPAS_MODE_P2P_GO, 0);
+				      ssid->mode == WPAS_MODE_P2P_GO, 0, 0);
 }
 
 
@@ -3364,13 +3365,14 @@ int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname)
 
 static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
 				   struct p2p_go_neg_results *params,
-				   int freq)
+				   int freq, int ht40)
 {
 	u8 bssid[ETH_ALEN];
 	int res;
 
 	os_memset(params, 0, sizeof(*params));
 	params->role_go = 1;
+	wpa_s->conf->p2p_go_ht40 = ht40;
 	if (freq) {
 		wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on forced "
 			   "frequency %d MHz", freq);
@@ -3482,7 +3484,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
  * i.e., without using Group Owner Negotiation.
  */
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
-		       int freq)
+		       int freq, int ht40)
 {
 	struct p2p_go_neg_results params;
 	unsigned int r;
@@ -3540,7 +3542,7 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 		return -1;
 	}
 
-	if (wpas_p2p_init_go_params(wpa_s, &params, freq))
+	if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40))
 		return -1;
 	if (params.freq &&
 	    !p2p_supported_freq(wpa_s->global->p2p, params.freq)) {
@@ -3607,7 +3609,7 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
 
 int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
 				  struct wpa_ssid *ssid, int addr_allocated,
-				  int freq)
+				  int freq, int ht40)
 {
 	struct p2p_go_neg_results params;
 	int go = 0;
@@ -3633,7 +3635,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
 	if (ssid->mode != WPAS_MODE_P2P_GO)
 		return -1;
 
-	if (wpas_p2p_init_go_params(wpa_s, &params, freq))
+	if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40))
 		return -1;
 
 	params.role_go = 1;
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index e2fe259..23b1503 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -28,10 +28,10 @@ void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
 					  unsigned int freq);
 int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
-		       int freq);
+		       int freq, int ht40);
 int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
 				  struct wpa_ssid *ssid, int addr_allocated,
-				  int freq);
+				  int freq, int ht40);
 struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
 				       struct wpa_ssid *ssid);
 void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index b159ad3..a098976 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -2231,17 +2231,14 @@ static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
 					char *argv[])
 {
 	char cmd[128];
-	int res;
-
-	if (argc == 0)
-		return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD");
+	int res = 0;
 
-	if (argc > 1)
-		res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s %s",
-				  argv[0], argv[1]);
-	else
-		res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s",
-				  argv[0]);
+	res = os_snprintf(cmd + res, sizeof(cmd) - res, "P2P_GROUP_ADD");
+	while (argc) {
+		res += os_snprintf(cmd + res, sizeof(cmd) - res, " %s",
+				   argv[argc - 1]);
+		argc--;
+	}
 	if (res < 0 || (size_t) res >= sizeof(cmd))
 		return -1;
 	cmd[sizeof(cmd) - 1] = '\0';
@@ -3221,7 +3218,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
 	{ "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
 	  "<ifname> = remove P2P group interface (terminate group if GO)" },
 	{ "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
-	  "= add a new P2P group (local end as GO)" },
+	  "[ht40] = add a new P2P group (local end as GO)" },
 	{ "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
 	  "<addr> <method> = request provisioning discovery" },
 	{ "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
-- 
1.7.11.1




More information about the Hostap mailing list