}
+void p2p_set_intended_addr(struct p2p_data *p2p, const u8 *intended_addr)
+{
+ if (p2p && intended_addr)
+ os_memcpy(p2p->intended_addr, intended_addr, ETH_ALEN);
+}
+
+
u16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr)
{
struct p2p_device *dev = NULL;
if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
os_memcpy(dev->interface_addr, addr, ETH_ALEN);
if (msg.ssid &&
+ msg.ssid[1] <= sizeof(dev->oper_ssid) &&
(msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
!= 0)) {
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
const u8 *dev_id, unsigned int search_delay,
- u8 seek_count, const char **seek)
+ u8 seek_count, const char **seek, int freq)
{
int res;
p2p, NULL);
switch (type) {
case P2P_FIND_START_WITH_FULL:
+ if (freq > 0) {
+ /*
+ * Start with the specified channel and then move to
+ * social channels only scans.
+ */
+ res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx,
+ P2P_SCAN_SPECIFIC, freq,
+ p2p->num_req_dev_types,
+ p2p->req_dev_types, dev_id,
+ DEV_PW_DEFAULT);
+ break;
+ }
+ /* fall through */
case P2P_FIND_PROGRESSIVE:
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
p2p->num_req_dev_types,
p2p_dbg(p2p, "Stopping find");
eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
p2p_clear_timeout(p2p);
- if (p2p->state == P2P_SEARCH)
+ if (p2p->state == P2P_SEARCH || p2p->state == P2P_SD_DURING_FIND)
p2p->cfg->find_stopped(p2p->cfg->cb_ctx);
p2p->p2ps_seek_count = 0;
p2p->sd_peer = NULL;
p2p->invite_peer = NULL;
p2p_stop_listen_for_freq(p2p, freq);
+ p2p->send_action_in_progress = 0;
}
size_t tmplen;
int res;
u8 group_capab;
+ struct p2p_message msg;
if (p2p_ie == NULL)
return 0; /* WLAN AP is not a P2P manager */
+ os_memset(&msg, 0, sizeof(msg));
+ if (p2p_parse_p2p_ie(p2p_ie, &msg) < 0)
+ return 0;
+
+ p2p_dbg(p2p, "BSS P2P manageability %s",
+ msg.manageability ? "enabled" : "disabled");
+
+ if (!msg.manageability)
+ return 0;
+
/*
* (Re)Association Request - P2P IE
* P2P Capability attribute (shall be present)
}
+void p2p_service_flush_asp(struct p2p_data *p2p)
+{
+ struct p2ps_advertisement *adv, *prev;
+
+ if (!p2p)
+ return;
+
+ adv = p2p->p2ps_adv_list;
+ while (adv) {
+ prev = adv;
+ adv = adv->next;
+ os_free(prev);
+ }
+
+ p2p->p2ps_adv_list = NULL;
+ p2p_dbg(p2p, "All ASP advertisements flushed");
+}
+
+
int p2p_parse_dev_addr_in_p2p_ie(struct wpabuf *p2p_ie, u8 *dev_addr)
{
struct p2p_message msg;
void p2p_deinit(struct p2p_data *p2p)
{
- struct p2ps_advertisement *adv, *prev;
-
#ifdef CONFIG_WIFI_DISPLAY
wpabuf_free(p2p->wfd_ie_beacon);
wpabuf_free(p2p->wfd_ie_probe_req);
os_free(p2p->after_scan_tx);
p2p_remove_wps_vendor_extensions(p2p);
os_free(p2p->no_go_freq.range);
-
- adv = p2p->p2ps_adv_list;
- while (adv) {
- prev = adv;
- adv = adv->next;
- os_free(prev);
- }
+ p2p_service_flush_asp(p2p);
os_free(p2p);
}
if (p2p->sd_peer)
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
p2p->sd_peer = NULL;
- p2p_continue_find(p2p);
+ if (p2p->state != P2P_IDLE)
+ p2p_continue_find(p2p);
return;
}
if (p2p->sd_peer == NULL) {
p2p_dbg(p2p, "No SD peer entry known");
- p2p_continue_find(p2p);
+ if (p2p->state != P2P_IDLE)
+ p2p_continue_find(p2p);
return;
}
{
struct p2p_device *dev;
- if (p2p->state != P2P_IDLE)
- return;
-
/*
* Retry the prov disc req attempt only for the peer that the user had
* requested.
}
+static int p2p_check_after_scan_tx_continuation(struct p2p_data *p2p)
+{
+ if (p2p->after_scan_tx_in_progress) {
+ p2p->after_scan_tx_in_progress = 0;
+ if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
+ p2p_run_after_scan(p2p))
+ return 1;
+ if (p2p->state == P2P_SEARCH) {
+ p2p_dbg(p2p, "Continue find after after_scan_tx completion");
+ p2p_continue_find(p2p);
+ }
+ }
+
+ return 0;
+}
+
+
+static void p2p_prov_disc_resp_cb(struct p2p_data *p2p, int success)
+{
+ p2p_dbg(p2p, "Provision Discovery Response TX callback: success=%d",
+ success);
+
+ if (p2p->send_action_in_progress) {
+ p2p->send_action_in_progress = 0;
+ p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
+ }
+
+ p2p->pending_action_state = P2P_NO_PENDING_ACTION;
+
+ if (!success)
+ goto continue_search;
+
+ if (!p2p->cfg->prov_disc_resp_cb ||
+ p2p->cfg->prov_disc_resp_cb(p2p->cfg->cb_ctx) < 1)
+ goto continue_search;
+
+ p2p_dbg(p2p,
+ "Post-Provision Discovery operations started - do not try to continue other P2P operations");
+ return;
+
+continue_search:
+ p2p_check_after_scan_tx_continuation(p2p);
+}
+
+
int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
struct os_reltime *rx_time, int level, const u8 *ies,
size_t ies_len)
p2p_dbg(p2p, "GO Negotiation Response (failure) TX callback: success=%d", success);
if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
p2p_go_neg_failed(p2p, p2p->go_neg_peer->status);
- } else if (success) {
+ return;
+ }
+
+ if (success) {
struct p2p_device *dev;
dev = p2p_get_device(p2p, addr);
if (dev &&
dev->status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE;
}
+
+ if (p2p->state == P2P_SEARCH || p2p->state == P2P_SD_DURING_FIND)
+ p2p_continue_find(p2p);
}
p2p->send_action_in_progress = 0;
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
}
- if (p2p->after_scan_tx_in_progress) {
- p2p->after_scan_tx_in_progress = 0;
- if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
- p2p_run_after_scan(p2p))
- break;
- if (p2p->state == P2P_SEARCH) {
- p2p_dbg(p2p, "Continue find after after_scan_tx completion");
- p2p_continue_find(p2p);
- }
- }
+ p2p_check_after_scan_tx_continuation(p2p);
break;
case P2P_PENDING_GO_NEG_REQUEST:
p2p_go_neg_req_cb(p2p, success);
case P2P_PENDING_PD:
p2p_prov_disc_cb(p2p, success);
break;
+ case P2P_PENDING_PD_RESPONSE:
+ p2p_prov_disc_resp_cb(p2p, success);
+ break;
case P2P_PENDING_INVITATION_REQUEST:
p2p_invitation_req_cb(p2p, success);
break;
static void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
{
+ u32 adv_id = 0;
+ u8 *adv_mac = NULL;
+
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
/*
for_join = 1;
}
+ if (p2p->p2ps_prov) {
+ adv_id = p2p->p2ps_prov->adv_id;
+ adv_mac = p2p->p2ps_prov->adv_mac;
+ }
+
if (p2p->cfg->prov_disc_fail)
p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
p2p->pending_pd_devaddr,
for_join ?
P2P_PROV_DISC_TIMEOUT_JOIN :
- P2P_PROV_DISC_TIMEOUT);
+ P2P_PROV_DISC_TIMEOUT,
+ adv_id, adv_mac, NULL);
p2p_reset_pending_pd(p2p);
}
}
"country=%c%c\n"
"oper_freq=%d\n"
"req_config_methods=0x%x\n"
- "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
+ "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
"status=%d\n"
"invitation_reqs=%u\n",
(int) (now.sec - dev->last_seen.sec),
"[PD_PEER_DISPLAY]" : "",
dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
"[PD_PEER_KEYPAD]" : "",
+ dev->flags & P2P_DEV_PD_PEER_P2PS ?
+ "[PD_PEER_P2PS]" : "",
dev->flags & P2P_DEV_USER_REJECTED ?
"[USER_REJECTED]" : "",
dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ?
if (p2p_channel_to_freq(reg_class, channel) < 0)
return -1;
- p2p_dbg(p2p, "Set Listen channel: reg_class %u channel %u",
- reg_class, channel);
-
/*
* Listen channel was set in configuration or set by control interface;
* cannot override it.
*/
- if (p2p->cfg->channel_forced && forced == 0)
+ if (p2p->cfg->channel_forced && forced == 0) {
+ p2p_dbg(p2p,
+ "Listen channel was previously configured - do not override based on optimization");
return -1;
+ }
+
+ p2p_dbg(p2p, "Set Listen channel: reg_class %u channel %u",
+ reg_class, channel);
if (p2p->state == P2P_IDLE) {
p2p->cfg->reg_class = reg_class;