From 96beff11d152dafc0dac45a42f5d6c5ac51e3bbe Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 30 Oct 2012 15:12:04 +0200 Subject: [PATCH] P2P: Allow discoverable interval for p2p_find to be configured The new P2P_SET parameter disc_int can now be used to configure discoverable interval for p2p_find operations. The format of the command for setting the values is "P2P_SET disc_int ". The first two parameters are given in units of 100 TUs (102.4 ms). The third parameter can be used to further limit the interval into a specific TU amount. If it is set to -1, no such additional limitation is enforced. It should be noted that the P2P specification describes the random Listen state interval to be in units of 100 TUs, so setting the max TU value to anything else than -1 is not compliant with the specification and should not be used in normal cases. The default parameters can be set with "P2P_SET disc_int 1 3 -1". Signed-hostap: Jouni Malinen --- src/p2p/p2p.c | 41 +++++++++++++++++++++++++++++---- src/p2p/p2p.h | 26 +++++++++++++++++++++ src/p2p/p2p_i.h | 5 ++++ wpa_supplicant/ctrl_iface.c | 24 +++++++++++++++++++ wpa_supplicant/p2p_supplicant.c | 2 ++ 5 files changed, 93 insertions(+), 5 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 7d449c689..af2d24afd 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -214,7 +214,7 @@ void p2p_go_neg_failed(struct p2p_data *p2p, struct p2p_device *peer, } -static void p2p_listen_in_find(struct p2p_data *p2p) +static void p2p_listen_in_find(struct p2p_data *p2p, int dev_disc) { unsigned int r, tu; int freq; @@ -235,6 +235,19 @@ static void p2p_listen_in_find(struct p2p_data *p2p) os_get_random((u8 *) &r, sizeof(r)); tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) + p2p->min_disc_int) * 100; + if (p2p->max_disc_tu >= 0 && tu > (unsigned int) p2p->max_disc_tu) + tu = p2p->max_disc_tu; + if (!dev_disc && tu < 100) + tu = 100; /* Need to wait in non-device discovery use cases */ + if (p2p->cfg->max_listen && 1024 * tu / 1000 > p2p->cfg->max_listen) + tu = p2p->cfg->max_listen * 1000 / 1024; + + if (tu == 0) { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip listen state " + "since duration was 0 TU"); + p2p_set_timeout(p2p, 0, 0); + return; + } p2p->pending_listen_freq = freq; p2p->pending_listen_sec = 0; @@ -2327,6 +2340,7 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg) p2p->min_disc_int = 1; p2p->max_disc_int = 3; + p2p->max_disc_tu = -1; os_get_random(&p2p->next_tie_breaker, 1); p2p->next_tie_breaker &= 0x01; @@ -2590,7 +2604,7 @@ void p2p_continue_find(struct p2p_data *p2p) } } - p2p_listen_in_find(p2p); + p2p_listen_in_find(p2p, 1); } @@ -3060,7 +3074,7 @@ static void p2p_timeout_connect(struct p2p_data *p2p) return; } p2p_set_state(p2p, P2P_CONNECT_LISTEN); - p2p_listen_in_find(p2p); + p2p_listen_in_find(p2p, 0); } @@ -3124,7 +3138,7 @@ static void p2p_timeout_wait_peer_idle(struct p2p_data *p2p) "P2P: Go to Listen state while waiting for the peer to become " "ready for GO Negotiation"); p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT); - p2p_listen_in_find(p2p); + p2p_listen_in_find(p2p, 0); } @@ -3192,7 +3206,7 @@ static void p2p_timeout_invite(struct p2p_data *p2p) p2p_set_timeout(p2p, 0, 100000); return; } - p2p_listen_in_find(p2p); + p2p_listen_in_find(p2p, 0); } @@ -4237,3 +4251,20 @@ int p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p, } #endif /* CONFIG_WIFI_DISPLAY */ + + +int p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int, + int max_disc_tu) +{ + if (min_disc_int > max_disc_int || min_disc_int < 0 || max_disc_int < 0) + return -1; + + p2p->min_disc_int = min_disc_int; + p2p->max_disc_int = max_disc_int; + p2p->max_disc_tu = max_disc_tu; + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set discoverable interval: " + "min=%d max=%d max_tu=%d", min_disc_int, max_disc_int, + max_disc_tu); + + return 0; +} diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index e5833f009..4d40a9f79 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -354,6 +354,11 @@ struct p2p_config { */ size_t ssid_postfix_len; + /** + * max_listen - Maximum listen duration in ms + */ + unsigned int max_listen; + /** * msg_ctx - Context to use with wpa_msg() calls */ @@ -1739,4 +1744,25 @@ int p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p, const struct wpabuf *elem); struct wpabuf * wifi_display_encaps(struct wpabuf *subelems); +/** + * p2p_set_disc_int - Set min/max discoverable interval for p2p_find + * @p2p: P2P module context from p2p_init() + * @min_disc_int: minDiscoverableInterval (in units of 100 TU); default 1 + * @max_disc_int: maxDiscoverableInterval (in units of 100 TU); default 3 + * @max_disc_tu: Maximum number of TUs (1.024 ms) for discoverable interval; or + * -1 not to limit + * Returns: 0 on success, or -1 on failure + * + * This function can be used to configure minDiscoverableInterval and + * maxDiscoverableInterval parameters for the Listen state during device + * discovery (p2p_find). A random number of 100 TU units is picked for each + * Listen state iteration from [min_disc_int,max_disc_int] range. + * + * max_disc_tu can be used to futher limit the discoverable duration. However, + * it should be noted that use of this parameter is not recommended since it + * would not be compliant with the P2P specification. + */ +int p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int, + int max_disc_tu); + #endif /* P2P_H */ diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 0f00c5402..c38eb3bde 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -225,6 +225,11 @@ struct p2p_data { */ int max_disc_int; + /** + * max_disc_tu - Maximum number of TUs for discoverable interval + */ + int max_disc_tu; + /** * devices - List of known P2P Device peers */ diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 2f0b38c78..a037cca4c 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -4223,6 +4223,30 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) if (os_strcmp(cmd, "disallow_freq") == 0) return p2p_ctrl_disallow_freq(wpa_s, param); + if (os_strcmp(cmd, "disc_int") == 0) { + int min_disc_int, max_disc_int, max_disc_tu; + char *pos; + + pos = param; + + min_disc_int = atoi(pos); + pos = os_strchr(pos, ' '); + if (pos == NULL) + return -1; + *pos++ = '\0'; + + max_disc_int = atoi(pos); + pos = os_strchr(pos, ' '); + if (pos == NULL) + return -1; + *pos++ = '\0'; + + max_disc_tu = atoi(pos); + + return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int, + max_disc_int, max_disc_tu); + } + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", cmd); diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 800499d14..7dae6ef5c 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -2760,6 +2760,8 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss; + p2p.max_listen = wpa_s->max_remain_on_chan; + global->p2p = p2p_init(&p2p); if (global->p2p == NULL) return -1;