aboutsummaryrefslogtreecommitdiffstats
path: root/src/p2p
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2012-03-29 21:28:34 +0300
committerJouni Malinen <j@w1.fi>2012-03-29 21:28:34 +0300
commit21d996f775a2131bb0c73d6e18ca9b382f017057 (patch)
treed32352d0ef626b3cae1b56faa6063daf8160db79 /src/p2p
parent564865e1d48ffa057cef1ecaf2eec59ae98e0be1 (diff)
downloadexternal_wpa_supplicant_8_ti-21d996f775a2131bb0c73d6e18ca9b382f017057.zip
external_wpa_supplicant_8_ti-21d996f775a2131bb0c73d6e18ca9b382f017057.tar.gz
external_wpa_supplicant_8_ti-21d996f775a2131bb0c73d6e18ca9b382f017057.tar.bz2
P2P: Add support for preferred channel list
p2p_pref_chan configuration parameter can now be used to set the list of preferred channel for P2P GO Negotiation. This will be used in the priority order if the peer does not support the channel we are trying to use as the GO (configured operating channel or the best 2.4 GHz/5 GHz channel) for the case where a forced channel is not used. p2p_pref_chan=<op class:channel>,... For example: p2p_pref_chan=81:1,81:2,81:3,81:4,81:5,81:6 This would configure 2.4 GHz channels 1-6 as the preferred ones with channel 1 the most preferred option. These configuration parameters can be set in wpa_supplicant.conf and dynamically updated with "wpa_cli set <param> <value>". Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
Diffstat (limited to 'src/p2p')
-rw-r--r--src/p2p/p2p.c33
-rw-r--r--src/p2p/p2p.h25
-rw-r--r--src/p2p/p2p_go_neg.c16
3 files changed, 74 insertions, 0 deletions
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 6bbc950..5bdf473 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -2212,6 +2212,16 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg)
p2p->cfg->model_number = os_strdup(cfg->model_number);
if (cfg->serial_number)
p2p->cfg->serial_number = os_strdup(cfg->serial_number);
+ if (cfg->pref_chan) {
+ p2p->cfg->pref_chan = os_malloc(cfg->num_pref_chan *
+ sizeof(struct p2p_channel));
+ if (p2p->cfg->pref_chan) {
+ os_memcpy(p2p->cfg->pref_chan, cfg->pref_chan,
+ cfg->num_pref_chan *
+ sizeof(struct p2p_channel));
+ } else
+ p2p->cfg->num_pref_chan = 0;
+ }
p2p->min_disc_int = 1;
p2p->max_disc_int = 3;
@@ -2246,6 +2256,7 @@ void p2p_deinit(struct p2p_data *p2p)
os_free(p2p->cfg->model_name);
os_free(p2p->cfg->model_number);
os_free(p2p->cfg->serial_number);
+ os_free(p2p->cfg->pref_chan);
os_free(p2p->groups);
wpabuf_free(p2p->sd_resp);
os_free(p2p->after_scan_tx);
@@ -3701,6 +3712,28 @@ int p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
}
+int p2p_set_pref_chan(struct p2p_data *p2p, unsigned int num_pref_chan,
+ const struct p2p_channel *pref_chan)
+{
+ struct p2p_channel *n;
+
+ if (pref_chan) {
+ n = os_malloc(num_pref_chan * sizeof(struct p2p_channel));
+ if (n == NULL)
+ return -1;
+ os_memcpy(n, pref_chan,
+ num_pref_chan * sizeof(struct p2p_channel));
+ } else
+ n = NULL;
+
+ os_free(p2p->cfg->pref_chan);
+ p2p->cfg->pref_chan = n;
+ p2p->cfg->num_pref_chan = num_pref_chan;
+
+ return 0;
+}
+
+
int p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
u8 *iface_addr)
{
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index f8fa061..31d5cd1 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -218,6 +218,11 @@ enum p2p_prov_disc_status {
P2P_PROV_DISC_REJECTED,
};
+struct p2p_channel {
+ u8 op_class;
+ u8 chan;
+};
+
/**
* struct p2p_config - P2P configuration
*
@@ -265,6 +270,16 @@ struct p2p_config {
struct p2p_channels channels;
/**
+ * num_pref_chan - Number of pref_chan entries
+ */
+ unsigned int num_pref_chan;
+
+ /**
+ * pref_chan - Preferred channels for GO Negotiation
+ */
+ struct p2p_channel *pref_chan;
+
+ /**
* pri_dev_type - Primary Device Type (see WPS)
*/
u8 pri_dev_type[8];
@@ -1609,6 +1624,16 @@ int p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
int cfg_op_channel);
/**
+ * p2p_set_pref_chan - Set P2P preferred channel list
+ * @p2p: P2P module context from p2p_init()
+ * @num_pref_chan: Number of entries in pref_chan list
+ * @pref_chan: Preferred channels or %NULL to remove preferences
+ * Returns: 0 on success, -1 on failure
+ */
+int p2p_set_pref_chan(struct p2p_data *p2p, unsigned int num_pref_chan,
+ const struct p2p_channel *pref_chan);
+
+/**
* p2p_in_progress - Check whether a P2P operation is progress
* @p2p: P2P module context from p2p_init()
* Returns: 0 if P2P module is idle or 1 if an operation is in progress
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index 5216212..230948d 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -296,6 +296,7 @@ static void p2p_reselect_channel(struct p2p_data *p2p,
struct p2p_reg_class *cl;
int freq;
u8 op_reg_class, op_channel;
+ unsigned int i;
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating "
"channel (reg_class %u channel %u) not acceptable to the "
@@ -328,6 +329,21 @@ static void p2p_reselect_channel(struct p2p_data *p2p,
return;
}
+ /* Select channel with highest preference if the peer supports it */
+ for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) {
+ if (p2p_channels_includes(intersection,
+ p2p->cfg->pref_chan[i].op_class,
+ p2p->cfg->pref_chan[i].chan)) {
+ p2p->op_reg_class = p2p->cfg->pref_chan[i].op_class;
+ p2p->op_channel = p2p->cfg->pref_chan[i].chan;
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick "
+ "highest preferred chnnel (op_class %u "
+ "channel %u) from intersection",
+ p2p->op_reg_class, p2p->op_channel);
+ return;
+ }
+ }
+
/*
* Fall back to whatever is included in the channel intersection since
* no better options seems to be available.