Verify that driver supports configured HT capabilities
authorJouni Malinen <jouni.malinen@atheros.com>
Wed, 4 Feb 2009 10:49:23 +0000 (12:49 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 4 Feb 2009 10:49:23 +0000 (12:49 +0200)
hostapd/driver_nl80211.c
hostapd/hw_features.c
hostapd/hw_features.h

index f6c4fc6..3502be7 100644 (file)
@@ -1378,6 +1378,11 @@ static int phy_info_handler(struct nl_msg *msg, void *arg)
                nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
                          nla_len(nl_band), NULL);
 
+               if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) {
+                       mode->ht_capab = nla_get_u16(
+                               tb_band[NL80211_BAND_ATTR_HT_CAPA]);
+               }
+
                nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
                        nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
                                  nla_len(nl_freq), freq_policy);
index 23febdf..3e6f7f2 100644 (file)
@@ -234,6 +234,107 @@ static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
 
        return 1;
 }
+
+
+static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
+{
+       u16 hw = iface->current_mode->ht_capab;
+       u16 conf = iface->conf->ht_capab;
+
+       if (!iface->conf->ieee80211n)
+               return 1;
+
+       if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) &&
+           !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [LDPC]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
+           !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [HT40*]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) &&
+           (conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [SMPS-*]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
+           !(hw & HT_CAP_INFO_GREEN_FIELD)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [GF]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) &&
+           !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [SHORT-GI-20]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) &&
+           !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [SHORT-GI-40]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [TX-STBC]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_RX_STBC_MASK) >
+           (hw & HT_CAP_INFO_RX_STBC_MASK)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [RX-STBC*]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_DELAYED_BA) &&
+           !(hw & HT_CAP_INFO_DELAYED_BA)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [DELAYED-BA]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) &&
+           !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [MAX-AMSDU-7935]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) &&
+           !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [DSSS_CCK-40]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_PSMP_SUPP) && !(hw & HT_CAP_INFO_PSMP_SUPP)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [PSMP]");
+               return 0;
+       }
+
+       if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) &&
+           !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) {
+               wpa_printf(MSG_ERROR, "Driver does not support configured "
+                          "HT capability [LSIG-TXOP-PROT]");
+               return 0;
+       }
+
+       return 1;
+}
 #endif /* CONFIG_IEEE80211N */
 
 
@@ -303,6 +404,8 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
 #ifdef CONFIG_IEEE80211N
        if (!ieee80211n_allowed_ht40_channel_pair(iface))
                return -1;
+       if (!ieee80211n_supported_ht_capab(iface))
+               return -1;
 #endif /* CONFIG_IEEE80211N */
 
        if (hostapd_prepare_rates(iface->bss[0], iface->current_mode)) {
index 15cd3ae..6dd9f9b 100644 (file)
@@ -47,6 +47,7 @@ struct hostapd_hw_modes {
        struct hostapd_channel_data *channels;
        int num_rates;
        struct hostapd_rate_data *rates;
+       u16 ht_capab;
 };