diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index 7a96b9ba9..a1285ed66 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -2824,7 +2824,7 @@ static int wpa_driver_test_p2p_find(void *priv, unsigned int timeout, int type) wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout); if (!drv->p2p) return -1; - return p2p_find(drv->p2p, timeout, type, 0, NULL, NULL); + return p2p_find(drv->p2p, timeout, type, 0, NULL, NULL, 0); } diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 16196ceec..85d506252 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -920,7 +920,7 @@ static void p2p_free_req_dev_types(struct p2p_data *p2p) int p2p_find(struct p2p_data *p2p, unsigned int timeout, enum p2p_discovery_type type, unsigned int num_req_dev_types, const u8 *req_dev_types, - const u8 *dev_id) + const u8 *dev_id, unsigned int search_delay) { int res; @@ -954,6 +954,8 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, p2p->find_type = type; p2p_device_clear_reported(p2p); p2p_set_state(p2p, P2P_SEARCH); + p2p->search_delay = search_delay; + p2p->in_search_delay = 0; eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); p2p->last_p2p_find_timeout = timeout; if (timeout) @@ -1009,7 +1011,7 @@ int p2p_other_scan_completed(struct p2p_data *p2p) "now that previous scan was completed"); if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type, p2p->num_req_dev_types, p2p->req_dev_types, - p2p->find_dev_id) < 0) + p2p->find_dev_id, p2p->search_delay) < 0) return 0; return 1; } @@ -2940,6 +2942,14 @@ int p2p_listen_end(struct p2p_data *p2p, unsigned int freq) p2p_set_timeout(p2p, 0, 100000); return 1; } + if (p2p->search_delay) { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay " + "search operation by %u ms", + p2p->search_delay); + p2p_set_timeout(p2p, p2p->search_delay / 1000, + (p2p->search_delay % 1000) * 1000); + return 1; + } p2p_search(p2p); return 1; } @@ -3134,6 +3144,16 @@ static void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx) /* Check if we timed out waiting for PD req */ if (p2p->pending_action_state == P2P_PENDING_PD) p2p_timeout_prov_disc_req(p2p); + if (p2p->search_delay && !p2p->in_search_delay) { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay " + "search operation by %u ms", + p2p->search_delay); + p2p->in_search_delay = 1; + p2p_set_timeout(p2p, p2p->search_delay / 1000, + (p2p->search_delay % 1000) * 1000); + break; + } + p2p->in_search_delay = 0; p2p_search(p2p); break; case P2P_CONNECT: diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index d8a3ff176..138f3e760 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -830,12 +830,13 @@ enum p2p_discovery_type { * containing num_req_dev_types * WPS_DEV_TYPE_LEN bytes; %NULL if no * requested device types. * @dev_id: Device ID to search for or %NULL to find all devices + * @search_delay: Extra delay in milliseconds between search iterations * Returns: 0 on success, -1 on failure */ int p2p_find(struct p2p_data *p2p, unsigned int timeout, enum p2p_discovery_type type, unsigned int num_req_dev_types, const u8 *req_dev_types, - const u8 *dev_id); + const u8 *dev_id, unsigned int search_delay); /** * p2p_stop_find - Stop P2P Find (Device Discovery) diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 027cad252..3c505563a 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -427,6 +427,10 @@ struct p2p_data { u8 go_timeout; u8 client_timeout; + + /* Extra delay in milliseconds between search iterations */ + unsigned int search_delay; + int in_search_delay; }; /** diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P index bb4c2adeb..c71fc1cb1 100644 --- a/wpa_supplicant/README-P2P +++ b/wpa_supplicant/README-P2P @@ -71,7 +71,8 @@ over the main control interface. Device Discovery -p2p_find [timeout in seconds] [type=] +p2p_find [timeout in seconds] [type=] \ + [dev_id=] [delay=] The default behavior is to run a single full scan in the beginning and then scan only social channels. type=social will scan only social @@ -81,6 +82,11 @@ progressively one channel at the time in the Search state rounds. This will help in finding new groups or groups missed during the initial full scan. +The optional dev_id option can be used to specify a single P2P peer to +search for. The optional delay parameter can be used to request an extra +delay to be used between search iterations (e.g., to free up radio +resources for concurrent operations). + p2p_listen [timeout in seconds] Start Listen-only state (become discoverable without searching for diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 4fd83b9e9..b15ad1129 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2958,6 +2958,7 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; u8 dev_id[ETH_ALEN], *_dev_id = NULL; char *pos; + unsigned int search_delay = 0; if (os_strstr(cmd, "type=social")) type = P2P_FIND_ONLY_SOCIAL; @@ -2972,7 +2973,14 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) _dev_id = dev_id; } - return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id); + pos = os_strstr(cmd, "delay="); + if (pos) { + pos += 6; + search_delay = atoi(pos); + } + + return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id, + search_delay); } diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c index c05e4601d..aee8b3a59 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c +++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c @@ -127,7 +127,7 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message, } wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types, - NULL); + NULL, 0); os_free(req_dev_types); return reply; diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 27b7e349d..9cd2ff531 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -3950,7 +3950,7 @@ static void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s) int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, enum p2p_discovery_type type, unsigned int num_req_dev_types, const u8 *req_dev_types, - const u8 *dev_id) + const u8 *dev_id, unsigned int search_delay) { wpas_p2p_clear_pending_action_tx(wpa_s); wpa_s->p2p_long_listen = 0; @@ -3965,7 +3965,8 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, wpa_supplicant_cancel_sched_scan(wpa_s); return p2p_find(wpa_s->global->p2p, timeout, type, - num_req_dev_types, req_dev_types, dev_id); + num_req_dev_types, req_dev_types, dev_id, + search_delay); } diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 8ecd24ce7..678dadb56 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -53,7 +53,7 @@ enum p2p_discovery_type; int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, enum p2p_discovery_type type, unsigned int num_req_dev_types, const u8 *req_dev_types, - const u8 *dev_id); + const u8 *dev_id, unsigned int search_delay); void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s); int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout); int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,