nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
nla_len(nl_band), NULL);
-#ifdef NL80211_BAND_ATTR_HT_CAPA
if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) {
__u16 cap = nla_get_u16(tb_band[NL80211_BAND_ATTR_HT_CAPA]);
print_ht_capability(cap);
if (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] &&
nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]) == 16)
print_ht_mcs(nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]));
-#endif
+ if (tb_band[NL80211_BAND_ATTR_VHT_CAPA] &&
+ tb_band[NL80211_BAND_ATTR_VHT_MCS_SET])
+ print_vht_info(nla_get_u32(tb_band[NL80211_BAND_ATTR_VHT_CAPA]),
+ nla_data(tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]));
printf("\t\tFrequencies:\n");
printf("\n");
}
+static void print_vht_capa(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+ printf("\n");
+ print_vht_info(data[0] | (data[1] << 8) |
+ (data[2] << 16) | (data[3] << 24),
+ data + 4);
+}
+
struct ie_print {
const char *name;
void (*print)(const uint8_t type, uint8_t len, const uint8_t *data);
[42] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), },
[45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), },
[61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), },
+ [191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), },
[48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), },
[50] = { "Extended supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), },
[114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), },
printf("\t\tHT TX MCS rate indexes are undefined\n");
}
}
+
+void print_vht_info(__u32 capa, const __u8 *mcs)
+{
+ __u16 tmp;
+ int i;
+
+ printf("\t\tVHT Capabilities (0x%.8x):\n", capa);
+
+#define PRINT_VHT_CAPA(_bit, _str) \
+ do { \
+ if (capa & BIT(_bit)) \
+ printf("\t\t\t" _str "\n"); \
+ } while (0)
+
+ printf("\t\t\tMax MPDU length: ");
+ switch (capa & 3) {
+ case 0: printf("3895\n"); break;
+ case 1: printf("7991\n"); break;
+ case 2: printf("11454\n"); break;
+ case 3: printf("(reserved)\n");
+ }
+ printf("\t\t\tSupported Channel Width: ");
+ switch ((capa >> 2) & 3) {
+ case 0: printf("neither 160 nor 80+80\n"); break;
+ case 1: printf("160 MHz\n"); break;
+ case 2: printf("160 MHz, 80+80 MHz\n"); break;
+ case 3: printf("(reserved)\n");
+ }
+ PRINT_VHT_CAPA(4, "RX LDPC");
+ PRINT_VHT_CAPA(5, "short GI (80 MHz)");
+ PRINT_VHT_CAPA(6, "short GI (160/80+80 MHz)");
+ PRINT_VHT_CAPA(7, "TX STBC");
+ /* RX STBC */
+ PRINT_VHT_CAPA(11, "SU Beamformer");
+ PRINT_VHT_CAPA(12, "SU Beamformee");
+ /* compressed steering */
+ /* # of sounding dimensions */
+ PRINT_VHT_CAPA(19, "MU Beamformer");
+ PRINT_VHT_CAPA(20, "MU Beamformee");
+ PRINT_VHT_CAPA(21, "VHT TXOP PS");
+ PRINT_VHT_CAPA(22, "+HTC-VHT");
+ /* max A-MPDU */
+ /* VHT link adaptation */
+ PRINT_VHT_CAPA(29, "RX antenna pattern consistency");
+ PRINT_VHT_CAPA(30, "TX antenna pattern consistency");
+
+ printf("\t\tVHT RX MCS set:\n");
+ tmp = mcs[0] | (mcs[1] << 8);
+ for (i = 1; i <= 8; i++) {
+ printf("\t\t\t%d streams: ", i);
+ switch ((tmp >> ((i-1)*2) ) & 3) {
+ case 0: printf("MCS 0-7\n"); break;
+ case 1: printf("MCS 0-8\n"); break;
+ case 2: printf("MCS 0-9\n"); break;
+ case 3: printf("not supported\n"); break;
+ }
+ }
+ tmp = mcs[2] | (mcs[3] << 8);
+ printf("\t\tVHT RX highest supported: %d Mbps\n", tmp & 0x1fff);
+
+ printf("\t\tVHT TX MCS set:\n");
+ tmp = mcs[4] | (mcs[5] << 8);
+ for (i = 1; i <= 8; i++) {
+ printf("\t\t\t%d streams: ", i);
+ switch ((tmp >> ((i-1)*2) ) & 3) {
+ case 0: printf("MCS 0-7\n"); break;
+ case 1: printf("MCS 0-8\n"); break;
+ case 2: printf("MCS 0-9\n"); break;
+ case 3: printf("not supported\n"); break;
+ }
+ }
+ tmp = mcs[6] | (mcs[7] << 8);
+ printf("\t\tVHT TX highest supported: %d Mbps\n", tmp & 0x1fff);
+}