|
@@ -113,9 +113,60 @@ void hostapd_get_vht_capab(struct hostapd_data *hapd,
|
|
|
struct ieee80211_vht_capabilities *vht_cap,
|
|
|
struct ieee80211_vht_capabilities *neg_vht_cap)
|
|
|
{
|
|
|
+ u32 cap, own_cap, sym_caps;
|
|
|
+
|
|
|
if (vht_cap == NULL)
|
|
|
return;
|
|
|
os_memcpy(neg_vht_cap, vht_cap, sizeof(*neg_vht_cap));
|
|
|
|
|
|
- /* TODO: mask own capabilities, like get_ht_capab() */
|
|
|
+ cap = le_to_host32(neg_vht_cap->vht_capabilities_info);
|
|
|
+ own_cap = hapd->iconf->vht_capab;
|
|
|
+
|
|
|
+ /* mask out symmetric VHT capabilities we don't support */
|
|
|
+ sym_caps = VHT_CAP_SHORT_GI_80 | VHT_CAP_SHORT_GI_160;
|
|
|
+ cap &= ~sym_caps | (own_cap & sym_caps);
|
|
|
+
|
|
|
+ /* mask out beamformer/beamformee caps if not supported */
|
|
|
+ if (!(own_cap & VHT_CAP_SU_BEAMFORMER_CAPABLE))
|
|
|
+ cap &= ~(VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
|
|
+ VHT_CAP_BEAMFORMEE_STS_MAX);
|
|
|
+
|
|
|
+ if (!(own_cap & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
|
|
|
+ cap &= ~(VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
|
|
+ VHT_CAP_SOUNDING_DIMENSION_MAX);
|
|
|
+
|
|
|
+ if (!(own_cap & VHT_CAP_MU_BEAMFORMER_CAPABLE))
|
|
|
+ cap &= ~VHT_CAP_MU_BEAMFORMEE_CAPABLE;
|
|
|
+
|
|
|
+ if (!(own_cap & VHT_CAP_MU_BEAMFORMEE_CAPABLE))
|
|
|
+ cap &= ~VHT_CAP_MU_BEAMFORMER_CAPABLE;
|
|
|
+
|
|
|
+ /* mask channel widths we don't support */
|
|
|
+ switch (own_cap & VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
|
|
|
+ case VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
|
|
|
+ break;
|
|
|
+ case VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
|
|
|
+ if (cap & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) {
|
|
|
+ cap &= ~VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
|
|
|
+ cap |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ cap &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(cap & VHT_CAP_SUPP_CHAN_WIDTH_MASK))
|
|
|
+ cap &= ~VHT_CAP_SHORT_GI_160;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * if we don't support RX STBC, mask out TX STBC in the STA's HT caps
|
|
|
+ * if we don't support TX STBC, mask out RX STBC in the STA's HT caps
|
|
|
+ */
|
|
|
+ if (!(own_cap & VHT_CAP_RXSTBC_MASK))
|
|
|
+ cap &= ~VHT_CAP_TXSTBC;
|
|
|
+ if (!(own_cap & VHT_CAP_TXSTBC))
|
|
|
+ cap &= ~VHT_CAP_RXSTBC_MASK;
|
|
|
+
|
|
|
+ neg_vht_cap->vht_capabilities_info = host_to_le32(cap);
|
|
|
}
|