@@ -202,4 +202,15 @@ static inline int hostapd_drv_set_authmode(struct hostapd_data *hapd,
return hapd->driver->set_authmode(hapd->drv_priv, auth_algs);
}
+static inline int hostapd_drv_remain_on_channel(struct hostapd_data *hapd,
+ unsigned int freq,
+ unsigned int duration)
+{
+ if (hapd->driver == NULL)
+ return -1;
+ if (!hapd->driver->remain_on_channel)
+ return -1;
+ return hapd->driver->remain_on_channel(hapd->drv_priv, freq, duration);
+}
+
#endif /* AP_DRV_OPS */
@@ -487,6 +487,63 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
ieee802_1x_receive(hapd, src, data, data_len);
}
+static int hostapd_roc_channel_check(struct hostapd_iface *iface)
+{
+ struct hostapd_channel_data *chan = NULL, *offchan;
+ unsigned int i;
+ int found = 0;
+
+ offchan = &iface->current_mode->channels[iface->off_channel_freq_idx];
+
+ for (i = 0; i < iface->current_mode->num_channels; i++) {
+ chan = &iface->current_mode->channels[i];
+ if (offchan != chan)
+ continue;
+ found = 1;
+ break;
+ }
+
+ if (!found || !chan) {
+ wpa_printf(MSG_ERROR, "channel requested to go offchannel "
+ "on freq %d MHz disappeared",
+ chan->freq);
+ goto fail;
+ }
+
+ if (chan->flag & HOSTAPD_CHAN_DISABLED) {
+ wpa_printf(MSG_ERROR, "channel requested to go offchannel "
+ "on freq %d MHz became disabled",
+ chan->freq);
+ goto fail;
+ }
+
+
+ return 0;
+fail:
+ return -1;
+}
+
+static void hostapd_event_roc(struct hostapd_data *hapd,
+ unsigned int freq,
+ unsigned int duration)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ int err;
+
+ err = hostapd_roc_channel_check(iface);
+ /* XXX: pass err to listeners, no one yet */
+}
+
+static void hostapd_event_roc_cancel(struct hostapd_data *hapd,
+ unsigned int freq,
+ unsigned int duration)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ int err;
+
+ err = hostapd_roc_channel_check(iface);
+ /* XXX: pass err to listeners, no one yet */
+}
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
@@ -576,8 +633,17 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->rx_action.bssid == NULL)
break;
hostapd_rx_action(hapd, &data->rx_action);
- break;
#endif /* NEED_AP_MLME */
+ case EVENT_REMAIN_ON_CHANNEL:
+ hostapd_event_roc(hapd,
+ data->remain_on_channel.freq,
+ data->remain_on_channel.duration);
+ break;
+ case EVENT_CANCEL_REMAIN_ON_CHANNEL:
+ hostapd_event_roc_cancel(hapd,
+ data->remain_on_channel.freq,
+ data->remain_on_channel.duration);
+ break;
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;
@@ -227,6 +227,10 @@ struct hostapd_iface {
int olbc_ht;
u16 ht_op_mode;
+
+ /* Offchannel operation helper */
+ unsigned int off_channel_freq_idx;
+
void (*scan_cb)(struct hostapd_iface *iface);
int (*ctrl_iface_init)(struct hostapd_data *hapd);
Although unused at the moment, this will be used later by ACS code. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> --- src/ap/ap_drv_ops.h | 11 ++++++++ src/ap/drv_callbacks.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++- src/ap/hostapd.h | 4 +++ 3 files changed, 82 insertions(+), 1 deletions(-)