[PATCH 15/24] P2P: add support for using indoor channels
Ilan Peer
ilan.peer
Mon May 19 00:06:12 PDT 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