diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 7c1a8a566..b7a5eae35 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -1404,6 +1404,7 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p) const int op_classes_5ghz[] = { 124, 125, 115, 0 }; const int op_classes_ht40[] = { 126, 127, 116, 117, 0 }; const int op_classes_vht[] = { 128, 0 }; + const int op_classes_edmg[] = { 181, 182, 183, 0 }; p2p_dbg(p2p, "Prepare channel best"); @@ -1435,6 +1436,11 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p) p2p_dbg(p2p, "Select first pref_chan entry as operating channel preference"); p2p->op_reg_class = p2p->cfg->pref_chan[0].op_class; p2p->op_channel = p2p->cfg->pref_chan[0].chan; + } else if (p2p_channel_select(&p2p->cfg->channels, op_classes_edmg, + &p2p->op_reg_class, &p2p->op_channel) == + 0) { + p2p_dbg(p2p, "Select possible EDMG channel (op_class %u channel %u) as operating channel preference", + p2p->op_reg_class, p2p->op_channel); } else if (p2p_channel_select(&p2p->cfg->channels, op_classes_vht, &p2p->op_reg_class, &p2p->op_channel) == 0) { diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 425b037be..79de09cef 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -99,6 +99,8 @@ struct p2p_go_neg_results { int vht; + int edmg; + u8 max_oper_chwidth; unsigned int vht_center_freq2; diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index c94bf41a7..113346141 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -390,6 +390,7 @@ void p2p_reselect_channel(struct p2p_data *p2p, const int op_classes_5ghz[] = { 124, 125, 115, 0 }; const int op_classes_ht40[] = { 126, 127, 116, 117, 0 }; const int op_classes_vht[] = { 128, 129, 130, 0 }; + const int op_classes_edmg[] = { 181, 182, 183, 0 }; if (p2p->own_freq_preference > 0 && p2p_freq_to_channel(p2p->own_freq_preference, @@ -454,6 +455,14 @@ void p2p_reselect_channel(struct p2p_data *p2p, } } + /* Try a channel where we might be able to use EDMG */ + if (p2p_channel_select(intersection, op_classes_edmg, + &p2p->op_reg_class, &p2p->op_channel) == 0) { + p2p_dbg(p2p, "Pick possible EDMG channel (op_class %u channel %u) from intersection", + p2p->op_reg_class, p2p->op_channel); + return; + } + /* Try a channel where we might be able to use VHT */ if (p2p_channel_select(intersection, op_classes_vht, &p2p->op_reg_class, &p2p->op_channel) == 0) { diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 59ca15382..e552306d7 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -775,7 +775,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, ssid->frequency = 2462; /* default channel 11 */ params.freq.freq = ssid->frequency; - if (ssid->mode == WPAS_MODE_AP && ssid->enable_edmg) { + if ((ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO) && + ssid->enable_edmg) { u8 primary_channel; if (ieee80211_freq_to_chan(ssid->frequency, &primary_channel) == diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 33b35056b..3b37d152d 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4951,6 +4951,7 @@ static const struct global_parse_data global_fields[] = { { INT(p2p_go_ht40), 0 }, { INT(p2p_go_vht), 0 }, { INT(p2p_go_he), 0 }, + { INT(p2p_go_edmg), 0 }, { INT(p2p_disabled), 0 }, { INT_RANGE(p2p_go_ctwindow, 0, 127), 0 }, { INT(p2p_no_group_iface), 0 }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 326ac6120..b3c779233 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -1089,6 +1089,16 @@ struct wpa_config { */ int p2p_go_vht; + /** + * p2p_go_edmg - Default mode for EDMG enable when operating as GO + * + * This will take effect for p2p_group_add, p2p_connect, and p2p_invite. + * Note that regulatory constraints and driver capabilities are + * consulted anyway, so setting it to 1 can't do real harm. + * By default: 0 (disabled) + */ + int p2p_go_edmg; + /** * p2p_go_he - Default mode for 11ax HE enable when operating as GO * diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 55971fcc6..2a0c7803e 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1287,6 +1287,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) fprintf(f, "p2p_go_vht=%d\n", config->p2p_go_vht); if (config->p2p_go_he) fprintf(f, "p2p_go_he=%d\n", config->p2p_go_he); + if (config->p2p_go_edmg) + fprintf(f, "p2p_go_edmg=%d\n", config->p2p_go_edmg); if (config->p2p_go_ctwindow != DEFAULT_P2P_GO_CTWINDOW) fprintf(f, "p2p_go_ctwindow=%d\n", config->p2p_go_ctwindow); if (config->p2p_disabled) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index f9a1fe1bf..c3eb5ed95 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5673,6 +5673,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, int freq = 0; int pd; int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0; + int edmg; u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL; size_t group_ssid_len = 0; int he; @@ -5688,7 +5689,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, /* <"pbc" | "pin" | PIN> [label|display|keypad|p2ps] * [persistent|persistent=] * [join] [auth] [go_intent=<0..15>] [freq=] [provdisc] - * [ht40] [vht] [he] [auto] [ssid=] */ + * [ht40] [vht] [he] [edmg] [auto] [ssid=] */ if (hwaddr_aton(cmd, addr)) return -1; @@ -5720,6 +5721,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || vht; he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; + edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg; pos2 = os_strstr(pos, " go_intent="); if (pos2) { @@ -5790,7 +5792,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, persistent_group, automatic, join, auth, go_intent, freq, freq2, persistent_id, - pd, ht40, vht, max_oper_chwidth, he, + pd, ht40, vht, max_oper_chwidth, he, edmg, group_ssid, group_ssid_len); if (new_pin == -2) { os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); @@ -6347,6 +6349,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) u8 *_peer = NULL, peer[ETH_ALEN]; int freq = 0, pref_freq = 0; int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0; + int edmg; id = atoi(cmd); pos = os_strstr(cmd, " peer="); @@ -6384,6 +6387,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || vht; he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; + edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg; pos = os_strstr(cmd, "freq2="); if (pos) @@ -6398,7 +6402,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) return -1; return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht, - max_oper_chwidth, pref_freq, he); + max_oper_chwidth, pref_freq, he, edmg); } @@ -6447,7 +6451,7 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, int id, int freq, int vht_center_freq2, int ht40, int vht, int vht_chwidth, - int he) + int he, int edmg) { struct wpa_ssid *ssid; @@ -6461,7 +6465,8 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, vht_center_freq2, 0, ht40, vht, - vht_chwidth, he, NULL, 0, 0); + vht_chwidth, he, edmg, + NULL, 0, 0); } @@ -6471,6 +6476,7 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) int vht = wpa_s->conf->p2p_go_vht; int ht40 = wpa_s->conf->p2p_go_ht40 || vht; int he = wpa_s->conf->p2p_go_he; + int edmg = wpa_s->conf->p2p_go_edmg; int max_oper_chwidth, chwidth = 0, freq2 = 0; char *token, *context = NULL; #ifdef CONFIG_ACS @@ -6495,6 +6501,8 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) ht40 = 1; } else if (os_strcmp(token, "he") == 0) { he = 1; + } else if (os_strcmp(token, "edmg") == 0) { + edmg = 1; } else if (os_strcmp(token, "persistent") == 0) { persistent = 1; } else { @@ -6532,10 +6540,11 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) if (group_id >= 0) return p2p_ctrl_group_add_persistent(wpa_s, group_id, freq, freq2, ht40, vht, - max_oper_chwidth, he); + max_oper_chwidth, he, + edmg); return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht, - max_oper_chwidth, he); + max_oper_chwidth, he, edmg); } diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c index 19715eb4c..7a6567330 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c +++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c @@ -425,14 +425,14 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message, goto inv_args; if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0, - 0, 0, 0, NULL, 0, 0)) { + 0, 0, 0, 0, NULL, 0, 0)) { reply = wpas_dbus_error_unknown_error( message, "Failed to reinvoke a persistent group"); goto out; } } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0, - 0, 0)) + 0, 0, 0)) goto inv_args; out: @@ -652,7 +652,7 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message, new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, persistent_group, 0, join, authorize_only, - go_intent, freq, 0, -1, 0, 0, 0, 0, 0, + go_intent, freq, 0, -1, 0, 0, 0, 0, 0, 0, NULL, 0); if (new_pin >= 0) { @@ -810,7 +810,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message, goto err; if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0, - 0, 0) < 0) { + 0, 0, 0) < 0) { reply = wpas_dbus_error_unknown_error( message, "Failed to reinvoke a persistent group"); diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 55b3b08ef..95bacec19 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -1885,6 +1885,83 @@ static void p2p_go_configured(void *ctx, void *data) } +/** + * wpas_p2p_freq_to_edmg_channel - Convert frequency into EDMG channel + * @freq: Frequency (MHz) to convert + * @op_class: Buffer for returning operating class + * @op_edmg_channel: Buffer for returning channel number + * Returns: 0 on success, -1 on failure + * + * This can be used to find the highest channel bonding which includes the + * specified frequency. + */ +static int wpas_p2p_freq_to_edmg_channel(struct wpa_supplicant *wpa_s, + unsigned int freq, + u8 *op_class, u8 *op_edmg_channel) +{ + struct hostapd_hw_modes *hwmode; + struct ieee80211_edmg_config edmg; + unsigned int i; + enum chan_width chanwidth[] = { + CHAN_WIDTH_8640, + CHAN_WIDTH_6480, + CHAN_WIDTH_4320, + }; + + if (!wpa_s->hw.modes) + return -1; + + hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, + HOSTAPD_MODE_IEEE80211AD); + if (!hwmode) { + wpa_printf(MSG_ERROR, + "Unsupported AP mode: HOSTAPD_MODE_IEEE80211AD"); + return -1; + } + + /* Find the highest EDMG channel bandwidth to start the P2P GO */ + for (i = 0; i < ARRAY_SIZE(chanwidth); i++) { + if (ieee80211_chaninfo_to_channel(freq, chanwidth[i], 0, + op_class, + op_edmg_channel) < 0) + continue; + + hostapd_encode_edmg_chan(1, *op_edmg_channel, 0, &edmg); + if (edmg.channels && + ieee802_edmg_is_allowed(hwmode->edmg, edmg)) { + wpa_printf(MSG_DEBUG, + "Freq %u to EDMG channel %u at opclass %u", + freq, *op_edmg_channel, *op_class); + return 0; + } + } + + return -1; +} + + +int wpas_p2p_try_edmg_channel(struct wpa_supplicant *wpa_s, + struct p2p_go_neg_results *params) +{ + u8 op_channel, op_class; + int freq; + + /* Try social channel as primary channel frequency */ + freq = (!params->freq) ? 58320 + 1 * 2160 : params->freq; + + if (wpas_p2p_freq_to_edmg_channel(wpa_s, freq, &op_class, + &op_channel) == 0) { + wpa_printf(MSG_DEBUG, + "Freq %d will be used to set an EDMG connection (channel=%u opclass=%u)", + freq, op_channel, op_class); + params->freq = freq; + return 0; + } + + return -1; +} + + static void wpas_start_wps_go(struct wpa_supplicant *wpa_s, struct p2p_go_neg_results *params, int group_formation) @@ -1921,6 +1998,20 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s, ssid->max_oper_chwidth = params->max_oper_chwidth; ssid->vht_center_freq2 = params->vht_center_freq2; ssid->he = params->he; + if (params->edmg) { + u8 op_channel, op_class; + + if (!wpas_p2p_freq_to_edmg_channel(wpa_s, params->freq, + &op_class, &op_channel)) { + ssid->edmg_channel = op_channel; + ssid->enable_edmg = params->edmg; + } else { + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Could not match EDMG channel, freq %d, for GO", + params->freq); + } + } + ssid->ssid = os_zalloc(params->ssid_len + 1); if (ssid->ssid) { os_memcpy(ssid->ssid, params->ssid, params->ssid_len); @@ -2270,6 +2361,8 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) res->vht = 1; if (wpa_s->p2p_go_he) res->he = 1; + if (wpa_s->p2p_go_edmg) + res->edmg = 1; res->max_oper_chwidth = wpa_s->p2p_go_max_oper_chwidth; res->vht_center_freq2 = wpa_s->p2p_go_vht_center_freq2; @@ -3089,7 +3182,8 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid, MAC2STR(sa), s->id); } wpas_p2p_group_add_persistent( - wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, 0, NULL, + wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, 0, + 0, NULL, go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 1); } else if (bssid) { @@ -3316,6 +3410,7 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid, wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht, wpa_s->p2p_go_max_oper_chwidth, wpa_s->p2p_go_he, + wpa_s->p2p_go_edmg, channels, ssid->mode == WPAS_MODE_P2P_GO ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : @@ -3560,6 +3655,20 @@ static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s, } +static enum chan_allowed wpas_p2p_verify_edmg(struct wpa_supplicant *wpa_s, + struct hostapd_hw_modes *mode, + u8 channel) +{ + struct ieee80211_edmg_config edmg; + + hostapd_encode_edmg_chan(1, channel, 0, &edmg); + if (edmg.channels && ieee802_edmg_is_allowed(mode->edmg, edmg)) + return ALLOWED; + + return NOT_ALLOWED; +} + + static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s, struct hostapd_hw_modes *mode, u8 channel, u8 bw) @@ -3580,6 +3689,8 @@ static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s, res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw); } else if (bw == BW160) { res2 = wpas_p2p_verify_160mhz(wpa_s, mode, channel, bw); + } else if (bw == BW4320 || bw == BW6480 || bw == BW8640) { + return wpas_p2p_verify_edmg(wpa_s, mode, channel); } if (res == NOT_ALLOWED || res2 == NOT_ALLOWED) @@ -4230,14 +4341,14 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev, if (response_done && persistent_go) { wpas_p2p_group_add_persistent( wpa_s, persistent_go, - 0, 0, freq, 0, 0, 0, 0, 0, NULL, + 0, 0, freq, 0, 0, 0, 0, 0, 0, NULL, persistent_go->mode == WPAS_MODE_P2P_GO ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0); } else if (response_done) { wpas_p2p_group_add(wpa_s, 1, freq, - 0, 0, 0, 0, 0); + 0, 0, 0, 0, 0, 0); } if (passwd_id == DEV_PW_P2PS_DEFAULT) { @@ -4353,11 +4464,12 @@ static int wpas_prov_disc_resp_cb(void *ctx) if (persistent_go) { wpas_p2p_group_add_persistent( - wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, 0, NULL, + wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, 0, 0, + NULL, persistent_go->mode == WPAS_MODE_P2P_GO ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0); } else { - wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0); + wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0); } return 1; @@ -4942,6 +5054,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, wpa_s->p2p_go_vht, wpa_s->p2p_go_max_oper_chwidth, wpa_s->p2p_go_he, + wpa_s->p2p_go_edmg, NULL, 0); return; } @@ -5490,8 +5603,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int persistent_group, int auto_join, int join, int auth, int go_intent, int freq, unsigned int vht_center_freq2, int persistent_id, int pd, int ht40, int vht, - unsigned int vht_chwidth, int he, const u8 *group_ssid, - size_t group_ssid_len) + unsigned int vht_chwidth, int he, int edmg, + const u8 *group_ssid, size_t group_ssid_len) { int force_freq = 0, pref_freq = 0; int ret = 0, res; @@ -5536,6 +5649,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2; wpa_s->p2p_go_max_oper_chwidth = vht_chwidth; wpa_s->p2p_go_he = !!he; + wpa_s->p2p_go_edmg = !!edmg; if (pin) os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin)); @@ -5960,6 +6074,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, struct p2p_go_neg_results *params, int freq, int vht_center_freq2, int ht40, int vht, int max_oper_chwidth, int he, + int edmg, const struct p2p_channels *channels) { struct wpa_used_freq_data *freqs; @@ -5975,6 +6090,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, params->he = he; params->max_oper_chwidth = max_oper_chwidth; params->vht_center_freq2 = vht_center_freq2; + params->edmg = edmg; freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(struct wpa_used_freq_data)); @@ -6005,6 +6121,13 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, } } + /* Try to use EDMG channel */ + if (params->edmg) { + if (wpas_p2p_try_edmg_channel(wpa_s, params) == 0) + goto success; + params->edmg = 0; + } + /* try using the forced freq */ if (freq) { if (wpas_p2p_disallowed_freq(wpa_s->global, freq) || @@ -6322,6 +6445,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated, * @ht40: Start GO with 40 MHz channel width * @vht: Start GO with VHT support * @vht_chwidth: channel bandwidth for GO operating with VHT support + * @edmg: Start GO with EDMG support * Returns: 0 on success, -1 on failure * * This function creates a new P2P group with the local end as the Group Owner, @@ -6329,7 +6453,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated, */ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, int freq, int vht_center_freq2, int ht40, int vht, - int max_oper_chwidth, int he) + int max_oper_chwidth, int he, int edmg) { struct p2p_go_neg_results params; @@ -6350,7 +6474,8 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, } if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, vht_center_freq2, - ht40, vht, max_oper_chwidth, he, NULL)) + ht40, vht, max_oper_chwidth, he, edmg, + NULL)) return -1; p2p_go_params(wpa_s->global->p2p, ¶ms); @@ -6430,6 +6555,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, int force_freq, int neg_freq, int vht_center_freq2, int ht40, int vht, int max_oper_chwidth, int he, + int edmg, const struct p2p_channels *channels, int connection_timeout, int force_scan) { @@ -6505,7 +6631,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, } if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, vht_center_freq2, - ht40, vht, max_oper_chwidth, he, channels)) + ht40, vht, max_oper_chwidth, he, edmg, + channels)) return -1; params.role_go = 1; @@ -7057,7 +7184,7 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr) int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq, int vht_center_freq2, int ht40, int vht, int max_chwidth, - int pref_freq, int he) + int pref_freq, int he, int edmg) { enum p2p_invite_role role; u8 *bssid = NULL; @@ -7078,6 +7205,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, wpa_s->p2p_go_he = !!he; wpa_s->p2p_go_max_oper_chwidth = max_chwidth; wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2; + wpa_s->p2p_go_edmg = !!edmg; if (ssid->mode == WPAS_MODE_P2P_GO) { role = P2P_INVITE_ROLE_GO; if (peer_addr == NULL) { @@ -7155,6 +7283,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, wpa_s->p2p_go_vht = 0; wpa_s->p2p_go_vht_center_freq2 = 0; wpa_s->p2p_go_max_oper_chwidth = 0; + wpa_s->p2p_go_edmg = 0; for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { if (os_strcmp(wpa_s->ifname, ifname) == 0) @@ -8100,7 +8229,9 @@ static int wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s, wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht, wpa_s->p2p_go_max_oper_chwidth, - wpa_s->p2p_go_he, NULL, 0); + wpa_s->p2p_go_he, + wpa_s->p2p_go_edmg, + NULL, 0); return ret; } @@ -8636,7 +8767,7 @@ static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s, WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent, params->go_freq, wpa_s->p2p_go_vht_center_freq2, -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth, - wpa_s->p2p_go_he, + wpa_s->p2p_go_he, wpa_s->p2p_go_edmg, params->go_ssid_len ? params->go_ssid : NULL, params->go_ssid_len); } @@ -8716,7 +8847,8 @@ static int wpas_p2p_nfc_init_go_neg(struct wpa_supplicant *wpa_s, WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent, forced_freq, wpa_s->p2p_go_vht_center_freq2, -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth, - wpa_s->p2p_go_he, NULL, 0); + wpa_s->p2p_go_he, wpa_s->p2p_go_edmg, + NULL, 0); } @@ -8732,7 +8864,8 @@ static int wpas_p2p_nfc_resp_go_neg(struct wpa_supplicant *wpa_s, WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent, forced_freq, wpa_s->p2p_go_vht_center_freq2, -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth, - wpa_s->p2p_go_he, NULL, 0); + wpa_s->p2p_go_he, wpa_s->p2p_go_edmg, + NULL, 0); if (res) return res; @@ -9117,7 +9250,8 @@ static int wpas_p2p_move_go_csa(struct wpa_supplicant *wpa_s) * TODO: This function may not always work correctly. For example, * when we have a running GO and a BSS on a DFS channel. */ - if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, 0, 0, 0, NULL)) { + if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, 0, 0, 0, 0, + NULL)) { wpa_dbg(wpa_s, MSG_DEBUG, "P2P CSA: Failed to select new frequency for GO"); return -1; @@ -9229,7 +9363,8 @@ static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s) wpa_supplicant_ap_deinit(wpa_s); /* Reselect the GO frequency */ - if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, 0, 0, 0, NULL)) { + if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, 0, 0, 0, 0, + NULL)) { wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Failed to reselect freq"); wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL); diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 24ec2cafc..941198e3a 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -37,18 +37,18 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int persistent_group, int auto_join, int join, int auth, int go_intent, int freq, unsigned int vht_center_freq2, int persistent_id, int pd, int ht40, int vht, - unsigned int vht_chwidth, int he, const u8 *group_ssid, - size_t group_ssid_len); + unsigned int vht_chwidth, int he, int edmg, + const u8 *group_ssid, size_t group_ssid_len); int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq, struct wpa_ssid *ssid); int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, int freq, int vht_center_freq2, int ht40, int vht, - int max_oper_chwidth, int he); + int max_oper_chwidth, int he, int edmg); int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int addr_allocated, int force_freq, int neg_freq, - int vht_center_freq2, int ht40, - int vht, int max_oper_chwidth, int he, + int vht_center_freq2, int ht40, int vht, + int max_oper_chwidth, int he, int edmg, const struct p2p_channels *channels, int connection_timeout, int force_scan); struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, @@ -116,8 +116,8 @@ void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic, int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr); int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq, - int vht_center_freq2, int ht40, int vht, - int max_oper_chwidth, int pref_freq, int he); + int vht_center_freq2, int ht40, int vht, int max_chwidth, + int pref_freq, int he, int edmg); int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, const u8 *peer_addr, const u8 *go_dev_addr); int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1, @@ -165,6 +165,8 @@ int wpas_p2p_nfc_report_handover(struct wpa_supplicant *wpa_s, int init, const struct wpabuf *sel, int forced_freq); int wpas_p2p_nfc_tag_enabled(struct wpa_supplicant *wpa_s, int enabled); void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx); +int wpas_p2p_try_edmg_channel(struct wpa_supplicant *wpa_s, + struct p2p_go_neg_results *params); #ifdef CONFIG_P2P diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 47cec0b10..ac271b56b 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -474,7 +474,7 @@ static char ** wpa_cli_complete_set(const char *str, int pos) "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht", "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface", "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask", - "ip_addr_start", "ip_addr_end", + "ip_addr_start", "ip_addr_end", "p2p_go_edmg", #endif /* CONFIG_P2P */ "country", "bss_max_count", "bss_expiration_age", "bss_expiration_scan_count", "filter_ssids", "filter_rssi", @@ -1406,7 +1406,7 @@ static const char *network_fields[] = { "bssid_whitelist", "psk", "proto", "key_mgmt", "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq", "freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1", - "vht_center_freq2", "ht", + "vht_center_freq2", "ht", "edmg", #ifdef IEEE8021X_EAPOL "eap", "identity", "anonymous_identity", "password", "ca_cert", "ca_path", "client_cert", "private_key", "private_key_passwd", diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index db46c02ce..56df23732 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -931,6 +931,7 @@ struct wpa_supplicant { unsigned int p2p_pd_before_go_neg:1; unsigned int p2p_go_ht40:1; unsigned int p2p_go_vht:1; + unsigned int p2p_go_edmg:1; unsigned int p2p_go_he:1; unsigned int user_initiated_pd:1; unsigned int p2p_go_group_formation_completed:1; diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 6b03634c0..05996321e 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -1178,6 +1178,11 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, /* P2P in 60 GHz uses PBSS */ ssid->pbss = 1; } + if (wpa_s->go_params->edmg && + wpas_p2p_try_edmg_channel(wpa_s, + wpa_s->go_params) == 0) + ssid->enable_edmg = 1; + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP " "SSID", ssid->ssid, ssid->ssid_len); } @@ -1261,6 +1266,11 @@ static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s, /* P2P in 60 GHz uses PBSS */ ssid->pbss = 1; } + if (wpa_s->go_params->edmg && + wpas_p2p_try_edmg_channel(wpa_s, + wpa_s->go_params) == 0) + ssid->enable_edmg = 1; + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP " "SSID", ssid->ssid, ssid->ssid_len); }