* Returns: 0 on success, -1 on failure
*
* If the scan result is for a GO, the clients in the group will also be added
- * to the peer table.
+ * to the peer table. This function can also be used with some other frames
+ * like Provision Discovery Request that contains P2P Capability and P2P Device
+ * Info attributes.
*/
-static int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
- int level, const u8 *ies, size_t ies_len)
+int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level,
+ const u8 *ies, size_t ies_len)
{
struct p2p_device *dev;
struct p2p_message msg;
msg.ds_params ? *msg.ds_params : -1);
}
dev->listen_freq = freq;
+ if (msg.group_info)
+ dev->oper_freq = freq;
dev->level = level;
if (msg.pri_dev_type)
}
-int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
- enum p2p_wps_method wps_method,
- int go_intent, const u8 *own_interface_addr,
- unsigned int force_freq, int persistent_group)
+static int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq)
{
- struct p2p_device *dev;
-
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Request to start group negotiation - peer=" MACSTR
- " GO Intent=%d Intended Interface Address=" MACSTR
- " wps_method=%d persistent_group=%d",
- MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
- wps_method, persistent_group);
-
if (force_freq) {
+ u8 op_reg_class, op_channel;
if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
- &p2p->op_reg_class, &p2p->op_channel) <
- 0) {
+ &op_reg_class, &op_channel) < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Unsupported frequency %u MHz",
force_freq);
return -1;
}
+ if (!p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
+ op_channel)) {
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+ "P2P: Frequency %u MHz (oper_class %u "
+ "channel %u) not allowed for P2P",
+ force_freq, op_reg_class, op_channel);
+ return -1;
+ }
+ p2p->op_reg_class = op_reg_class;
+ p2p->op_channel = op_channel;
p2p->channels.reg_classes = 1;
p2p->channels.reg_class[0].channels = 1;
p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
p2p->op_reg_class, p2p->op_channel,
force_freq ? " (forced)" : "");
+ return 0;
+}
+
+
+int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
+ enum p2p_wps_method wps_method,
+ int go_intent, const u8 *own_interface_addr,
+ unsigned int force_freq, int persistent_group)
+{
+ struct p2p_device *dev;
+
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+ "P2P: Request to start group negotiation - peer=" MACSTR
+ " GO Intent=%d Intended Interface Address=" MACSTR
+ " wps_method=%d persistent_group=%d",
+ MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
+ wps_method, persistent_group);
+
+ if (p2p_prepare_channel(p2p, force_freq) < 0)
+ return -1;
+
dev = p2p_get_device(p2p, peer_addr);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
wps_method, persistent_group);
- if (force_freq) {
- if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
- &p2p->op_reg_class, &p2p->op_channel) <
- 0) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Unsupported frequency %u MHz",
- force_freq);
- return -1;
- }
- p2p->channels.reg_classes = 1;
- p2p->channels.reg_class[0].channels = 1;
- p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
- p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
- } else {
- p2p->op_reg_class = p2p->cfg->op_reg_class;
- p2p->op_channel = p2p->cfg->op_channel;
- os_memcpy(&p2p->channels, &p2p->cfg->channels,
- sizeof(struct p2p_channels));
- }
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
- "P2P: Own preference for operation channel: "
- "Regulatory Class %u Channel %u%s",
- p2p->op_reg_class, p2p->op_channel,
- force_freq ? " (forced)" : "");
+ if (p2p_prepare_channel(p2p, force_freq) < 0)
+ return -1;
dev = p2p_get_device(p2p, peer_addr);
if (dev == NULL) {
os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
res.ssid_len = p2p->ssid_len;
p2p_random(res.passphrase, 8);
- } else
+ } else {
res.freq = peer->oper_freq;
+ if (p2p->ssid_len) {
+ os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
+ res.ssid_len = p2p->ssid_len;
+ }
+ }
p2p_channels_intersect(&p2p->channels, &peer->channels,
&intersection);
}
}
+ res.peer_config_timeout = go ? peer->client_timeout : peer->go_timeout;
+
p2p_clear_timeout(p2p);
peer->go_neg_req_sent = 0;
peer->wps_method = WPS_NOT_READY;
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"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,
+ p2p->go_neg_peer->status);
+ }
}
p2p->cross_connect = enabled;
/* TODO: may need to tear down any action group where we are GO(?) */
}
+
+
+int p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr)
+{
+ struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
+ if (dev == NULL)
+ return -1;
+ if (dev->oper_freq <= 0)
+ return -1;
+ return dev->oper_freq;
+}
+
+
+void p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
+{
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Intra BSS distribution %s",
+ enabled ? "enabled" : "disabled");
+ p2p->cfg->p2p_intra_bss = enabled;
+}