aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorAnil Gathala Sudha <Anil.Sudha@Atheros.com>2010-11-10 11:33:47 (GMT)
committerJouni Malinen <j@w1.fi>2010-11-10 11:33:47 (GMT)
commit7cfc4ac31960948afdf8f3ca959b9d8744b4524d (patch)
tree251503ea17cde28c0f767296e1ec2a204fbda0a4 /wpa_supplicant
parentbacc31286cd17ee2bb3840d625a11d30972a0167 (diff)
downloadhostap-7cfc4ac31960948afdf8f3ca959b9d8744b4524d.zip
hostap-7cfc4ac31960948afdf8f3ca959b9d8744b4524d.tar.gz
hostap-7cfc4ac31960948afdf8f3ca959b9d8744b4524d.tar.bz2
P2P: Add support for automatic channel selection at GO
The driver wrapper may now indicate the preferred channel (e.g., based on scan results) on both 2.4 GHz and 5 GHz bands (and an overall best frequency). When setting up a GO, this preference information is used to select the operating channel if configuration does not include hardcoded channel. Similarly, this information can be used during GO Negotiation to indicate preference for a specific channel based on current channel conditions. p2p_group_add command can now use special values (freq=2 and freq=5) to indicate that the GO is to be started on the specified band.
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/events.c13
-rw-r--r--wpa_supplicant/p2p_supplicant.c113
-rw-r--r--wpa_supplicant/p2p_supplicant.h2
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h5
4 files changed, 120 insertions, 13 deletions
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index b4e8a0d..39ac33b 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1876,6 +1876,19 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpas_p2p_interface_unavailable(wpa_s);
#endif /* CONFIG_P2P */
break;
+ case EVENT_BEST_CHANNEL:
+ wpa_printf(MSG_DEBUG, "Best channel event received (%d %d %d)",
+ data->best_chan.freq_24, data->best_chan.freq_5,
+ data->best_chan.freq_overall);
+ wpa_s->best_24_freq = data->best_chan.freq_24;
+ wpa_s->best_5_freq = data->best_chan.freq_5;
+ wpa_s->best_overall_freq = data->best_chan.freq_overall;
+#ifdef CONFIG_P2P
+ wpas_p2p_update_best_channels(wpa_s, data->best_chan.freq_24,
+ data->best_chan.freq_5,
+ data->best_chan.freq_overall);
+#endif /* CONFIG_P2P */
+ break;
default:
wpa_printf(MSG_INFO, "Unknown event %d", event);
break;
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index eb4b238..2f6ae89 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -2203,23 +2203,28 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
os_get_random((u8 *) &r, sizeof(r));
p2p.channel = 1 + (r % 3) * 5;
}
+ wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d", p2p.channel);
if (wpa_s->conf->p2p_oper_reg_class &&
wpa_s->conf->p2p_oper_channel) {
p2p.op_reg_class = wpa_s->conf->p2p_oper_reg_class;
p2p.op_channel = wpa_s->conf->p2p_oper_channel;
+ p2p.cfg_op_channel = 1;
+ wpa_printf(MSG_DEBUG, "P2P: Configured operating channel: "
+ "%d:%d", p2p.op_reg_class, p2p.op_channel);
+
} else {
p2p.op_reg_class = 81;
/*
- * For initial tests, pick the operation channel randomly.
- * TODO: Use scan results (etc.) to select the best channel.
+ * Use random operation channel from (1, 6, 11) if no other
+ * preference is indicated.
*/
os_get_random((u8 *) &r, sizeof(r));
- p2p.op_channel = 1 + r % 11;
+ p2p.op_channel = 1 + (r % 3) * 5;
+ p2p.cfg_op_channel = 0;
+ wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "
+ "%d:%d", p2p.op_reg_class, p2p.op_channel);
}
- wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d "
- "Own preferred operation channel: %d",
- p2p.channel, p2p.op_channel);
if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
os_memcpy(p2p.country, wpa_s->conf->country, 2);
p2p.country[2] = 0x04;
@@ -2865,16 +2870,48 @@ static void wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
os_memset(params, 0, sizeof(*params));
params->role_go = 1;
- params->freq = 2412;
- if (freq)
+ if (freq) {
+ wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on forced "
+ "frequency %d MHz", freq);
params->freq = freq;
- else if (wpa_s->conf->p2p_oper_reg_class == 81 &&
- wpa_s->conf->p2p_oper_channel >= 1 &&
- wpa_s->conf->p2p_oper_channel <= 11)
+ } else if (wpa_s->conf->p2p_oper_reg_class == 81 &&
+ wpa_s->conf->p2p_oper_channel >= 1 &&
+ wpa_s->conf->p2p_oper_channel <= 11) {
params->freq = 2407 + 5 * wpa_s->conf->p2p_oper_channel;
- else if (wpa_s->conf->p2p_oper_reg_class == 115 ||
- wpa_s->conf->p2p_oper_reg_class == 118)
+ wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
+ "frequency %d MHz", params->freq);
+ } else if (wpa_s->conf->p2p_oper_reg_class == 115 ||
+ wpa_s->conf->p2p_oper_reg_class == 118) {
params->freq = 5000 + 5 * wpa_s->conf->p2p_oper_channel;
+ wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
+ "frequency %d MHz", params->freq);
+ } else if (wpa_s->conf->p2p_oper_channel == 0 &&
+ wpa_s->best_overall_freq > 0 &&
+ p2p_supported_freq(wpa_s->global->p2p,
+ wpa_s->best_overall_freq)) {
+ params->freq = wpa_s->best_overall_freq;
+ wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best overall "
+ "channel %d MHz", params->freq);
+ } else if (wpa_s->conf->p2p_oper_channel == 0 &&
+ wpa_s->best_24_freq > 0 &&
+ p2p_supported_freq(wpa_s->global->p2p,
+ wpa_s->best_24_freq)) {
+ params->freq = wpa_s->best_24_freq;
+ wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 2.4 GHz "
+ "channel %d MHz", params->freq);
+ } else if (wpa_s->conf->p2p_oper_channel == 0 &&
+ wpa_s->best_5_freq > 0 &&
+ p2p_supported_freq(wpa_s->global->p2p,
+ wpa_s->best_5_freq)) {
+ params->freq = wpa_s->best_5_freq;
+ wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 5 GHz "
+ "channel %d MHz", params->freq);
+ } else {
+ params->freq = 2412;
+ wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference "
+ "known)", params->freq);
+ }
+
if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
wpa_s->assoc_freq && !freq) {
wpa_printf(MSG_DEBUG, "P2P: Force GO on the channel we are "
@@ -2927,6 +2964,46 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq)
{
struct p2p_go_neg_results params;
+ unsigned int r;
+
+ if (freq == 2) {
+ wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 2.4 GHz "
+ "band");
+ if (wpa_s->best_24_freq > 0 &&
+ p2p_supported_freq(wpa_s->global->p2p,
+ wpa_s->best_24_freq)) {
+ freq = wpa_s->best_24_freq;
+ wpa_printf(MSG_DEBUG, "P2P: Use best 2.4 GHz band "
+ "channel: %d MHz", freq);
+ } else {
+ os_get_random((u8 *) &r, sizeof(r));
+ freq = 2412 + (r % 3) * 25;
+ wpa_printf(MSG_DEBUG, "P2P: Use random 2.4 GHz band "
+ "channel: %d MHz", freq);
+ }
+ }
+
+ if (freq == 5) {
+ wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 5 GHz "
+ "band");
+ if (wpa_s->best_5_freq > 0 &&
+ p2p_supported_freq(wpa_s->global->p2p,
+ wpa_s->best_5_freq)) {
+ freq = wpa_s->best_5_freq;
+ wpa_printf(MSG_DEBUG, "P2P: Use best 5 GHz band "
+ "channel: %d MHz", freq);
+ } else {
+ os_get_random((u8 *) &r, sizeof(r));
+ freq = 5180 + (r % 4) * 20;
+ if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
+ wpa_printf(MSG_DEBUG, "P2P: Could not select "
+ "5 GHz channel for P2P group");
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "P2P: Use random 5 GHz band "
+ "channel: %d MHz", freq);
+ }
+ }
if (freq > 0 && !p2p_supported_freq(wpa_s->global->p2p, freq)) {
wpa_printf(MSG_DEBUG, "P2P: The forced channel for GO "
@@ -3790,3 +3867,13 @@ void wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s)
wpa_s->removal_reason = P2P_GROUP_REMOVAL_UNAVAILABLE;
wpas_p2p_group_delete(wpa_s);
}
+
+
+void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s,
+ int freq_24, int freq_5, int freq_overall)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+ if (p2p == NULL || (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT))
+ return;
+ p2p_set_best_channels(p2p, freq_24, freq_5, freq_overall);
+}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index a411c9a..d0221f2 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -118,5 +118,7 @@ int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s);
void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s);
int wpas_p2p_cancel(struct wpa_supplicant *wpa_s);
void wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s);
+void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s,
+ int freq_24, int freq_5, int freq_overall);
#endif /* P2P_SUPPLICANT_H */
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 5d8e4d6..13abea6 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -534,6 +534,11 @@ struct wpa_supplicant {
unsigned int wps_freq;
int wps_fragment_size;
int auto_reconnect_disabled;
+
+ /* Channel preferences for AP/P2P GO use */
+ int best_24_freq;
+ int best_5_freq;
+ int best_overall_freq;
};