void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
- int offset, int width, int cf1, int cf2)
+ int offset, int width, int cf1, int cf2,
+ int finished)
{
/* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO,
- "driver had channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
+ "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
+ finished ? "had" : "starting",
freq, ht, hapd->iconf->ch_switch_vht_config, offset,
width, channel_width_to_string(width), cf1, cf2);
is_dfs = ieee80211_is_dfs(freq, hapd->iface->hw_features,
hapd->iface->num_hw_features);
+ wpa_msg(hapd->msg_ctx, MSG_INFO,
+ "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d dfs=%d",
+ finished ? WPA_EVENT_CHANNEL_SWITCH :
+ WPA_EVENT_CHANNEL_SWITCH_STARTED,
+ freq, ht, offset, channel_width_to_string(width),
+ cf1, cf2, is_dfs);
+ if (!finished)
+ return;
+
if (hapd->csa_in_progress &&
freq == hapd->cs_freq_params.freq) {
hostapd_cleanup_cs_params(hapd);
case EVENT_AUTH:
hostapd_notif_auth(hapd, &data->auth);
break;
+ case EVENT_CH_SWITCH_STARTED:
case EVENT_CH_SWITCH:
if (!data)
break;
data->ch_switch.ch_offset,
data->ch_switch.ch_width,
data->ch_switch.cf1,
- data->ch_switch.cf2);
+ data->ch_switch.cf2,
+ event == EVENT_CH_SWITCH);
break;
case EVENT_CONNECT_FAILED_REASON:
if (!data)
const u8 *bssid, const u8 *ie, size_t ie_len,
int ssi_signal);
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
- int offset, int width, int cf1, int cf2);
+ int offset, int width, int cf1, int cf2,
+ int finished);
struct survey_results;
void hostapd_event_get_survey(struct hostapd_iface *iface,
struct survey_results *survey_results);
#define WPA_EVENT_BEACON_LOSS "CTRL-EVENT-BEACON-LOSS "
/** Regulatory domain channel */
#define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
+/** Channel switch started (followed by freq=<MHz> and other channel parameters)
+ */
+#define WPA_EVENT_CHANNEL_SWITCH_STARTED "CTRL-EVENT-STARTED-CHANNEL-SWITCH "
/** Channel switch (followed by freq=<MHz> and other channel parameters) */
#define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH "
/** SAE authentication failed due to unknown password identifier */
HIDDEN_SSID_ZERO_CONTENTS
};
+enum ch_switch_state {
+ CH_SW_STARTED,
+ CH_SW_FINISHED
+};
+
struct wowlan_triggers {
u8 any;
u8 disconnect;
* */
EVENT_CH_SWITCH,
+ /**
+ * EVENT_CH_SWITCH_STARTED - AP or GO started to switch channels
+ *
+ * This is a pre-switch event indicating the shortly following switch
+ * of operating channels.
+ *
+ * Described in wpa_event_data.ch_switch
+ */
+ EVENT_CH_SWITCH_STARTED,
/**
* EVENT_WNM - Request WNM operation
*
E2S(DRIVER_CLIENT_POLL_OK);
E2S(EAPOL_TX_STATUS);
E2S(CH_SWITCH);
+ E2S(CH_SWITCH_STARTED);
E2S(WNM);
E2S(CONNECT_FAILED_REASON);
E2S(DFS_RADAR_DETECTED);
static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
struct nlattr *ifindex, struct nlattr *freq,
struct nlattr *type, struct nlattr *bw,
- struct nlattr *cf1, struct nlattr *cf2)
+ struct nlattr *cf1, struct nlattr *cf2,
+ int finished)
{
struct i802_bss *bss;
union wpa_event_data data;
int chan_offset = 0;
int ifidx;
- wpa_printf(MSG_DEBUG, "nl80211: Channel switch event");
+ wpa_printf(MSG_DEBUG, "nl80211: Channel switch%s event",
+ finished ? "" : " started");
if (!freq)
return;
bss->freq = data.ch_switch.freq;
drv->assoc_freq = data.ch_switch.freq;
- wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data);
+ wpa_supplicant_event(bss->ctx, finished ?
+ EVENT_CH_SWITCH : EVENT_CH_SWITCH_STARTED, &data);
}
tb[NL80211_ATTR_PMK],
tb[NL80211_ATTR_PMKID]);
break;
+ case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY:
+ mlme_event_ch_switch(drv,
+ tb[NL80211_ATTR_IFINDEX],
+ tb[NL80211_ATTR_WIPHY_FREQ],
+ tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
+ tb[NL80211_ATTR_CHANNEL_WIDTH],
+ tb[NL80211_ATTR_CENTER_FREQ1],
+ tb[NL80211_ATTR_CENTER_FREQ2],
+ 0);
+ break;
case NL80211_CMD_CH_SWITCH_NOTIFY:
mlme_event_ch_switch(drv,
tb[NL80211_ATTR_IFINDEX],
tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
tb[NL80211_ATTR_CHANNEL_WIDTH],
tb[NL80211_ATTR_CENTER_FREQ1],
- tb[NL80211_ATTR_CENTER_FREQ2]);
+ tb[NL80211_ATTR_CENTER_FREQ2],
+ 1);
break;
case NL80211_CMD_DISCONNECT:
mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
- int offset, int width, int cf1, int cf2)
+ int offset, int width, int cf1, int cf2, int finished)
{
struct hostapd_iface *iface = wpa_s->ap_iface;
if (wpa_s->current_ssid)
wpa_s->current_ssid->frequency = freq;
hostapd_event_ch_switch(iface->bss[0], freq, ht,
- offset, width, cf1, cf2);
+ offset, width, cf1, cf2, finished);
}
struct csa_settings *settings);
int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *txtaddr);
void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
- int offset, int width, int cf1, int cf2);
+ int offset, int width, int cf1, int cf2, int finished);
struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
int ndef);
#ifdef CONFIG_AP
data->rx_from_unknown.wds);
break;
#endif /* CONFIG_AP */
+
+ case EVENT_CH_SWITCH_STARTED:
case EVENT_CH_SWITCH:
if (!data || !wpa_s->current_ssid)
break;
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH
- "freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
+ wpa_msg(wpa_s, MSG_INFO,
+ "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
+ event == EVENT_CH_SWITCH ? WPA_EVENT_CHANNEL_SWITCH :
+ WPA_EVENT_CHANNEL_SWITCH_STARTED,
data->ch_switch.freq,
data->ch_switch.ht_enabled,
data->ch_switch.ch_offset,
channel_width_to_string(data->ch_switch.ch_width),
data->ch_switch.cf1,
data->ch_switch.cf2);
+ if (event == EVENT_CH_SWITCH_STARTED)
+ break;
wpa_s->assoc_freq = data->ch_switch.freq;
wpa_s->current_ssid->frequency = data->ch_switch.freq;
data->ch_switch.ch_offset,
data->ch_switch.ch_width,
data->ch_switch.cf1,
- data->ch_switch.cf2);
+ data->ch_switch.cf2,
+ 1);
}
#endif /* CONFIG_AP */