summaryrefslogtreecommitdiffstats
path: root/freebsd/contrib/wpa/src/common/hw_features_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/contrib/wpa/src/common/hw_features_common.c')
-rw-r--r--freebsd/contrib/wpa/src/common/hw_features_common.c116
1 files changed, 93 insertions, 23 deletions
diff --git a/freebsd/contrib/wpa/src/common/hw_features_common.c b/freebsd/contrib/wpa/src/common/hw_features_common.c
index 61287bc4..b9e0ada3 100644
--- a/freebsd/contrib/wpa/src/common/hw_features_common.c
+++ b/freebsd/contrib/wpa/src/common/hw_features_common.c
@@ -89,13 +89,29 @@ int hw_get_chan(struct hostapd_hw_modes *mode, int freq)
int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan,
int sec_chan)
{
- int ok, j, first;
+ int ok, first;
int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
149, 157, 165, 184, 192 };
size_t k;
+ struct hostapd_channel_data *p_chan, *s_chan;
+ const int ht40_plus = pri_chan < sec_chan;
- if (pri_chan == sec_chan || !sec_chan)
- return 1; /* HT40 not used */
+ p_chan = hw_get_channel_chan(mode, pri_chan, NULL);
+ if (!p_chan)
+ return 0;
+
+ if (pri_chan == sec_chan || !sec_chan) {
+ if (chan_pri_allowed(p_chan))
+ return 1; /* HT40 not used */
+
+ wpa_printf(MSG_ERROR, "Channel %d is not allowed as primary",
+ pri_chan);
+ return 0;
+ }
+
+ s_chan = hw_get_channel_chan(mode, sec_chan, NULL);
+ if (!s_chan)
+ return 0;
wpa_printf(MSG_DEBUG,
"HT40: control channel: %d secondary channel: %d",
@@ -103,16 +119,9 @@ int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan,
/* Verify that HT40 secondary channel is an allowed 20 MHz
* channel */
- ok = 0;
- for (j = 0; j < mode->num_channels; j++) {
- struct hostapd_channel_data *chan = &mode->channels[j];
- if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
- chan->chan == sec_chan) {
- ok = 1;
- break;
- }
- }
- if (!ok) {
+ if ((s_chan->flag & HOSTAPD_CHAN_DISABLED) ||
+ (ht40_plus && !(p_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) ||
+ (!ht40_plus && !(p_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M))) {
wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed",
sec_chan);
return 0;
@@ -354,30 +363,35 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
int hostapd_set_freq_params(struct hostapd_freq_params *data,
enum hostapd_hw_mode mode,
int freq, int channel, int ht_enabled,
- int vht_enabled, int sec_channel_offset,
- int vht_oper_chwidth, int center_segment0,
- int center_segment1, u32 vht_caps)
+ int vht_enabled, int he_enabled,
+ int sec_channel_offset,
+ int oper_chwidth, int center_segment0,
+ int center_segment1, u32 vht_caps,
+ struct he_capabilities *he_cap)
{
+ if (!he_cap)
+ he_enabled = 0;
os_memset(data, 0, sizeof(*data));
data->mode = mode;
data->freq = freq;
data->channel = channel;
data->ht_enabled = ht_enabled;
data->vht_enabled = vht_enabled;
+ data->he_enabled = he_enabled;
data->sec_channel_offset = sec_channel_offset;
data->center_freq1 = freq + sec_channel_offset * 10;
data->center_freq2 = 0;
data->bandwidth = sec_channel_offset ? 40 : 20;
- if (data->vht_enabled) switch (vht_oper_chwidth) {
- case VHT_CHANWIDTH_USE_HT:
+ if (data->vht_enabled) switch (oper_chwidth) {
+ case CHANWIDTH_USE_HT:
if (center_segment1 ||
(center_segment0 != 0 &&
5000 + center_segment0 * 5 != data->center_freq1 &&
2407 + center_segment0 * 5 != data->center_freq1))
return -1;
break;
- case VHT_CHANWIDTH_80P80MHZ:
+ case CHANWIDTH_80P80MHZ:
if (!(vht_caps & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) {
wpa_printf(MSG_ERROR,
"80+80 channel width is not supported!");
@@ -388,11 +402,11 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
return -1;
data->center_freq2 = 5000 + center_segment1 * 5;
/* fall through */
- case VHT_CHANWIDTH_80MHZ:
+ case CHANWIDTH_80MHZ:
data->bandwidth = 80;
- if ((vht_oper_chwidth == VHT_CHANWIDTH_80MHZ &&
+ if ((oper_chwidth == CHANWIDTH_80MHZ &&
center_segment1) ||
- (vht_oper_chwidth == VHT_CHANWIDTH_80P80MHZ &&
+ (oper_chwidth == CHANWIDTH_80P80MHZ &&
!center_segment1) ||
!sec_channel_offset)
return -1;
@@ -425,7 +439,7 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
return -1;
}
break;
- case VHT_CHANWIDTH_160MHZ:
+ case CHANWIDTH_160MHZ:
data->bandwidth = 160;
if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) {
@@ -555,3 +569,59 @@ int ieee80211ac_cap_check(u32 hw, u32 conf)
}
#endif /* CONFIG_IEEE80211AC */
+
+
+u32 num_chan_to_bw(int num_chans)
+{
+ switch (num_chans) {
+ case 2:
+ case 4:
+ case 8:
+ return num_chans * 20;
+ default:
+ return 20;
+ }
+}
+
+
+/* check if BW is applicable for channel */
+int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw,
+ int ht40_plus, int pri)
+{
+ u32 bw_mask;
+
+ switch (bw) {
+ case 20:
+ bw_mask = HOSTAPD_CHAN_WIDTH_20;
+ break;
+ case 40:
+ /* HT 40 MHz support declared only for primary channel,
+ * just skip 40 MHz secondary checking */
+ if (pri && ht40_plus)
+ bw_mask = HOSTAPD_CHAN_WIDTH_40P;
+ else if (pri && !ht40_plus)
+ bw_mask = HOSTAPD_CHAN_WIDTH_40M;
+ else
+ bw_mask = 0;
+ break;
+ case 80:
+ bw_mask = HOSTAPD_CHAN_WIDTH_80;
+ break;
+ case 160:
+ bw_mask = HOSTAPD_CHAN_WIDTH_160;
+ break;
+ default:
+ bw_mask = 0;
+ break;
+ }
+
+ return (chan->allowed_bw & bw_mask) == bw_mask;
+}
+
+
+/* check if channel is allowed to be used as primary */
+int chan_pri_allowed(const struct hostapd_channel_data *chan)
+{
+ return !(chan->flag & HOSTAPD_CHAN_DISABLED) &&
+ (chan->allowed_bw & HOSTAPD_CHAN_WIDTH_20);
+}