diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 90a73f719..760170c63 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -1550,6 +1550,33 @@ static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv, } +static int calculate_chan_offset(int width, int freq, int cf1, int cf2) +{ + int freq1 = 0; + + switch (convert2width(width)) { + case CHAN_WIDTH_20_NOHT: + case CHAN_WIDTH_20: + return 0; + case CHAN_WIDTH_40: + freq1 = cf1 - 10; + break; + case CHAN_WIDTH_80: + freq1 = cf1 - 30; + break; + case CHAN_WIDTH_160: + freq1 = cf1 - 70; + break; + case CHAN_WIDTH_UNKNOWN: + case CHAN_WIDTH_80P80: + /* FIXME: implement this */ + return 0; + } + + return (abs(freq - freq1) / 20) % 2 == 0 ? 1 : -1; +} + + static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, struct nlattr *ifindex, struct nlattr *freq, struct nlattr *type, struct nlattr *bw, @@ -1591,6 +1618,14 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, chan_offset = -1; break; } + } else if (bw && cf1) { + /* This can happen for example with VHT80 ch switch */ + chan_offset = calculate_chan_offset(nla_get_u32(bw), + nla_get_u32(freq), + nla_get_u32(cf1), + cf2 ? nla_get_u32(cf2) : 0); + } else { + wpa_printf(MSG_WARNING, "nl80211: Unknown secondary channel information - following channel definition calculations may fail"); } os_memset(&data, 0, sizeof(data));