[PATCH 15/24] P2P: add support for using indoor channels

Ilan Peer ilan.peer at intel.com
Mon May 19 03:06:12 EDT 2014


Generally, indoor channels cannot be used for P2P operation as
currently there is no way to determine that the device is
operating in an indoor environment.

Add a relaxation to allow using indoor channels, iff the peer
device is going to be the GO and in addition it is identified
as a non-mobile/indoor device based on its WPS device category.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 src/p2p/p2p.c                   |   53 ++++++++++++++++++++++++++++++---------
 src/p2p/p2p.h                   |   18 ++++++++++++-
 src/p2p/p2p_utils.c             |    2 ++
 wpa_supplicant/config.c         |    2 ++
 wpa_supplicant/config.h         |    2 ++
 wpa_supplicant/config_file.c    |    3 +++
 wpa_supplicant/p2p_supplicant.c |   46 +++++++++++++++++++++++++--------
 7 files changed, 103 insertions(+), 23 deletions(-)

diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 3ca5bc5..ba9b752 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1130,7 +1130,9 @@ void p2p_stop_find(struct p2p_data *p2p)
 
 static int p2p_prepare_channel_pref(struct p2p_data *p2p,
 				    unsigned int force_freq,
-				    unsigned int pref_freq, int go)
+				    unsigned int pref_freq,
+				    int go,
+				    unsigned int allow_indoor)
 {
 	u8 op_class, op_channel;
 	unsigned int freq = force_freq ? force_freq : pref_freq;
@@ -1142,12 +1144,18 @@ static int p2p_prepare_channel_pref(struct p2p_data *p2p,
 		return -1;
 	}
 
-	if (!p2p_channels_includes(&p2p->cfg->channels, op_class, op_channel) &&
-	    (go || !p2p_channels_includes(&p2p->cfg->cli_channels, op_class,
-					  op_channel))) {
-		p2p_dbg(p2p, "Frequency %u MHz (oper_class %u channel %u) not allowed for P2P",
-			freq, op_class, op_channel);
-		return -1;
+	if (!p2p_channels_includes(&p2p->cfg->channels, op_class, op_channel)) {
+		if (go)
+			goto not_allowed;
+
+		if (!p2p_channels_includes(&p2p->cfg->cli_channels, op_class,
+					   op_channel)) {
+			if (!allow_indoor ||
+			    !p2p_channels_includes(&p2p->cfg->indoor_channels,
+						   op_class,
+						   op_channel))
+				goto not_allowed;
+		}
 	}
 
 	p2p->op_reg_class = op_class;
@@ -1164,6 +1172,13 @@ static int p2p_prepare_channel_pref(struct p2p_data *p2p,
 	}
 
 	return 0;
+
+not_allowed:
+
+	p2p_dbg(p2p, "Frequency %u MHz (oper_class %u channel %u) not allowed for P2P",
+		freq, op_class, op_channel);
+	return -1;
+
 }
 
 
@@ -1262,22 +1277,31 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
 int p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev,
 			unsigned int force_freq, unsigned int pref_freq, int go)
 {
+	unsigned int indoor = p2p_is_indoor_device(&dev->info);
+
 	p2p_dbg(p2p, "Prepare channel - force_freq=%u pref_freq=%u go=%d",
 		force_freq, pref_freq, go);
 	if (force_freq || pref_freq) {
-		if (p2p_prepare_channel_pref(p2p, force_freq, pref_freq, go) <
-		    0)
+		if (p2p_prepare_channel_pref(p2p, force_freq, pref_freq, go,
+					     indoor) < 0)
 			return -1;
 	} else {
 		p2p_prepare_channel_best(p2p);
 	}
+
 	p2p_channels_dump(p2p, "prepared channels", &p2p->channels);
 	if (go)
 		p2p_channels_remove_freqs(&p2p->channels, &p2p->no_go_freq);
-	else if (!force_freq)
+	else if (!force_freq) {
 		p2p_channels_union(&p2p->channels, &p2p->cfg->cli_channels,
 				   &p2p->channels);
-	p2p_channels_dump(p2p, "after go/cli filter/add", &p2p->channels);
+		if (indoor)
+			p2p_channels_union(&p2p->channels,
+					   &p2p->cfg->indoor_channels,
+					   &p2p->channels);
+	}
+	p2p_channels_dump(p2p, "after go/cli/indoor filter/add",
+			  &p2p->channels);
 
 	p2p_dbg(p2p, "Own preference for operation channel: Operating Class %u Channel %u%s",
 		p2p->op_reg_class, p2p->op_channel,
@@ -2414,6 +2438,7 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg)
 	p2p_dbg(p2p, "initialized");
 	p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
 	p2p_channels_dump(p2p, "cli_channels", &p2p->cfg->cli_channels);
+	p2p_channels_dump(p2p, "indoor_channels", &p2p->cfg->indoor_channels);
 
 	return p2p;
 }
@@ -4143,7 +4168,8 @@ void p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
 
 void p2p_update_channel_list(struct p2p_data *p2p,
 			     const struct p2p_channels *chan,
-			     const struct p2p_channels *cli_chan)
+			     const struct p2p_channels *cli_chan,
+			     const struct p2p_channels *indoor_chan)
 {
 	p2p_dbg(p2p, "Update channel list");
 	os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
@@ -4151,6 +4177,9 @@ void p2p_update_channel_list(struct p2p_data *p2p,
 	os_memcpy(&p2p->cfg->cli_channels, cli_chan,
 		  sizeof(struct p2p_channels));
 	p2p_channels_dump(p2p, "cli_channels", &p2p->cfg->cli_channels);
+	os_memcpy(&p2p->cfg->indoor_channels, indoor_chan,
+		  sizeof(struct p2p_channels));
+	p2p_channels_dump(p2p, "indoor_channels", &p2p->cfg->indoor_channels);
 }
 
 
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 832b083..6e84302 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -311,6 +311,21 @@ struct p2p_config {
 	struct p2p_channels cli_channels;
 
 	/**
+	 * indoor_channels - Additional client channels
+	 *
+	 * This list of channels (if any) will be used when advertising local
+	 * channels during GO Negotiation or Invitation for the cases where the
+	 * local end may become the client and the peer is identified as a non
+	 * mobile device.
+	 * This may allow the peer to become a GO on additional channels if it
+	 * supports these options and is a non mobile device.
+	 * The uses cases for these channels are similar to that of the
+	 * cli_channels, with the exception that they can be used only if
+	 * we identified the peer as a non mobile device.
+	 */
+	struct p2p_channels indoor_channels;
+
+	/**
 	 * num_pref_chan - Number of pref_chan entries
 	 */
 	unsigned int num_pref_chan;
@@ -1745,7 +1760,8 @@ unsigned int p2p_get_pref_freq(struct p2p_data *p2p,
 
 void p2p_update_channel_list(struct p2p_data *p2p,
 			     const struct p2p_channels *chan,
-			     const struct p2p_channels *cli_chan);
+			     const struct p2p_channels *cli_chan,
+			     const struct p2p_channels *indoor_chan);
 
 /**
  * p2p_set_best_channels - Update best channel information
diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c
index f8981c0..9e26215 100644
--- a/src/p2p/p2p_utils.c
+++ b/src/p2p/p2p_utils.c
@@ -307,6 +307,8 @@ int p2p_supported_freq_cli(struct p2p_data *p2p, unsigned int freq)
 	return p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
 				     op_channel) ||
 		p2p_channels_includes(&p2p->cfg->cli_channels, op_reg_class,
+				      op_channel) ||
+		p2p_channels_includes(&p2p->cfg->indoor_channels, op_reg_class,
 				      op_channel);
 }
 
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 8532b7d..daa06de 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3257,6 +3257,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
 	config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
 	config->p2p_go_freq_change_policy = DEFAULT_P2P_GO_FREQ_MOVE;
 	config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY;
+	config->p2p_add_cli_chan_indoor = DEFAULT_P2P_ADD_CLI_CHAN_INDOOR;
 	config->p2p_optimize_listen_chan = DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN;
 	config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
 	config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
@@ -3840,6 +3841,7 @@ static const struct global_parse_data global_fields[] = {
 	{ FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN },
 	{ FUNC(p2p_no_go_freq), CFG_CHANGED_P2P_PREF_CHAN },
 	{ INT_RANGE(p2p_add_cli_chan, 0, 1), 0 },
+	{ INT_RANGE(p2p_add_cli_chan_indoor, 0, 1), 0 },
 	{ INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 },
 	{ INT(p2p_go_ht40), 0 },
 	{ INT(p2p_go_vht), 0 },
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 9688a32..ed07cca 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -20,6 +20,7 @@
 #define DEFAULT_P2P_INTRA_BSS 1
 #define DEFAULT_P2P_GO_MAX_INACTIVITY (5 * 60)
 #define DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN 0
+#define DEFAULT_P2P_ADD_CLI_CHAN_INDOOR 0
 #define DEFAULT_BSS_MAX_COUNT 200
 #define DEFAULT_BSS_EXPIRATION_AGE 180
 #define DEFAULT_BSS_EXPIRATION_SCAN_COUNT 2
@@ -685,6 +686,7 @@ struct wpa_config {
 	struct p2p_channel *p2p_pref_chan;
 	struct wpa_freq_range_list p2p_no_go_freq;
 	int p2p_add_cli_chan;
+	int p2p_add_cli_chan_indoor;
 	int p2p_ignore_shared_freq;
 	int p2p_optimize_listen_chan;
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 61c8a2a..ad18197 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1034,6 +1034,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
 	}
 	if (config->p2p_add_cli_chan)
 		fprintf(f, "p2p_add_cli_chan=%d\n", config->p2p_add_cli_chan);
+	if (config->p2p_add_cli_chan_indoor != DEFAULT_P2P_ADD_CLI_CHAN_INDOOR)
+		fprintf(f, "p2p_add_cli_chan_indoor=%d\n",
+			config->p2p_add_cli_chan_indoor);
 	if (config->p2p_optimize_listen_chan !=
 	    DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN)
 		fprintf(f, "p2p_optimize_listen_chan=%d\n",
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 2726aba..d26556b 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -3435,11 +3435,13 @@ static void wpas_p2p_add_chan(struct p2p_reg_class *reg, u8 chan)
 
 static int wpas_p2p_default_channels(struct wpa_supplicant *wpa_s,
 				     struct p2p_channels *chan,
-				     struct p2p_channels *cli_chan)
+				     struct p2p_channels *cli_chan,
+				     struct p2p_channels *ind_chan)
 {
 	int i, cla = 0;
 
 	os_memset(cli_chan, 0, sizeof(*cli_chan));
+	os_memset(ind_chan, 0, sizeof(*ind_chan));
 
 	wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for 2.4 GHz "
 		   "band");
@@ -3733,7 +3735,7 @@ static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
 		return NOT_ALLOWED;
 
 	if (res == INDOOR_ONLY || res2 == INDOOR_ONLY)
-		return NOT_ALLOWED;
+		return INDOOR_ONLY;
 
 	if (res == NO_IR || res2 == NO_IR)
 		return NO_IR;
@@ -3743,10 +3745,11 @@ static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
 
 static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
 				   struct p2p_channels *chan,
-				   struct p2p_channels *cli_chan)
+				   struct p2p_channels *cli_chan,
+				   struct p2p_channels *ind_chan)
 {
 	struct hostapd_hw_modes *mode;
-	int cla, op, cli_cla;
+	int cla, op, cli_cla, ind_cla;
 	struct wpa_used_freq_data *freqs;
 	unsigned int num = wpa_s->num_multichan_concurrent;
 
@@ -3754,19 +3757,21 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
 		wpa_printf(MSG_DEBUG, "P2P: Driver did not support fetching "
 			   "of all supported channels; assume dualband "
 			   "support");
-		return wpas_p2p_default_channels(wpa_s, chan, cli_chan);
+		return wpas_p2p_default_channels(wpa_s, chan, cli_chan,
+						 ind_chan);
 	}
 
 	/* Note: the flow can still be handled even if the allocation fails */
 	freqs = os_calloc(num, sizeof(struct wpa_used_freq_data));
 	num = get_shared_radio_freqs_data(wpa_s, freqs, num);
 
-	cla = cli_cla = 0;
+	cla = cli_cla = ind_cla = 0;
 
 	for (op = 0; op_class[op].op_class; op++) {
 		struct p2p_oper_class_map *o = &op_class[op];
 		u8 ch;
 		struct p2p_reg_class *reg = NULL, *cli_reg = NULL;
+		struct p2p_reg_class *indoor_reg = NULL;
 
 		mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode);
 		if (mode == NULL)
@@ -3796,6 +3801,19 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
 				}
 				cli_reg->channel[cli_reg->channels] = ch;
 				cli_reg->channels++;
+			} else if (res == INDOOR_ONLY &&
+				   wpa_s->conf->p2p_add_cli_chan_indoor) {
+				if (indoor_reg == NULL) {
+					wpa_printf(MSG_DEBUG,
+						   "P2P: Add operating class %u (indoor)",
+						   o->op_class);
+					indoor_reg =
+						&ind_chan->reg_class[ind_cla];
+					ind_cla++;
+					indoor_reg->reg_class = o->op_class;
+				}
+				indoor_reg->channel[indoor_reg->channels] = ch;
+				indoor_reg->channels++;
 			}
 		}
 		if (reg) {
@@ -3806,10 +3824,15 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
 			wpa_hexdump(MSG_DEBUG, "P2P: Channels (client only)",
 				    cli_reg->channel, cli_reg->channels);
 		}
+		if (indoor_reg) {
+			wpa_hexdump(MSG_DEBUG, "P2P: Channels (indoor)",
+				    indoor_reg->channel, indoor_reg->channels);
+		}
 	}
 
 	chan->reg_classes = cla;
 	cli_chan->reg_classes = cli_cla;
+	ind_chan->reg_classes = ind_cla;
 
 	os_free(freqs);
 	return 0;
@@ -4120,7 +4143,8 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
 	} else
 		os_memcpy(p2p.country, "XX\x04", 3);
 
-	if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels)) {
+	if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels,
+				    &p2p.indoor_channels)) {
 		wpa_printf(MSG_ERROR, "P2P: Failed to configure supported "
 			   "channel list");
 		return -1;
@@ -6734,7 +6758,7 @@ void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx)
 
 void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s)
 {
-	struct p2p_channels chan, cli_chan;
+	struct p2p_channels chan, cli_chan, ind_chan;
 	struct wpa_supplicant *ifs;
 
 	if (wpa_s->global == NULL || wpa_s->global->p2p == NULL)
@@ -6742,13 +6766,15 @@ void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s)
 
 	os_memset(&chan, 0, sizeof(chan));
 	os_memset(&cli_chan, 0, sizeof(cli_chan));
-	if (wpas_p2p_setup_channels(wpa_s, &chan, &cli_chan)) {
+	os_memset(&ind_chan, 0, sizeof(ind_chan));
+	if (wpas_p2p_setup_channels(wpa_s, &chan, &cli_chan, &ind_chan)) {
 		wpa_printf(MSG_ERROR, "P2P: Failed to update supported "
 			   "channel list");
 		return;
 	}
 
-	p2p_update_channel_list(wpa_s->global->p2p, &chan, &cli_chan);
+	p2p_update_channel_list(wpa_s->global->p2p, &chan, &cli_chan,
+				&ind_chan);
 
 	for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
 		int freq;
-- 
1.7.10.4



More information about the HostAP mailing list