2 = 160 MHz
3 = 80+80 MHz */
extern const uint16_t vht_chan_width[4];
+/* 0 = 20 MHz
+ 1 = 40 MHz
+ 2 = 80 MHz
+ 3 = 80+80 or 160 MHz
+ 4 = 160+160 or 320 MHz */
+extern const uint16_t eht_chan_width[5];
struct iwinfo_scanlist_entry {
uint8_t mac[6];
struct iwinfo_crypto_entry crypto;
struct iwinfo_scanlist_ht_chan_entry ht_chan_info;
struct iwinfo_scanlist_vht_chan_entry vht_chan_info;
+ struct iwinfo_scanlist_vht_chan_entry he_chan_info;
+ struct iwinfo_scanlist_vht_chan_entry eht_chan_info;
};
struct iwinfo_country_entry {
return "unknown";
}
+static const char* format_6ghz_chan_width(uint8_t width)
+{
+ if (width < ARRAY_SIZE(eht_chan_width))
+ switch (eht_chan_width[width]) {
+ case 20: return "20 MHz";
+ case 40: return "40 MHz";
+ case 80: return "80 MHz";
+ case 160: return "160 MHz";
+ case 320: return "320 MHz";
+ }
+
+ return "unknown";
+}
static const char * print_type(const struct iwinfo_ops *iw, const char *ifname)
{
format_chan_width(true, e->vht_chan_info.chan_width));
}
+ if (e->he_chan_info.center_chan_1) {
+ printf(" HE Operation:\n");
+ printf(" Center Frequency 1: %d\n",
+ e->he_chan_info.center_chan_1);
+ printf(" Center Frequency 2: %d\n",
+ e->he_chan_info.center_chan_2);
+ printf(" Channel Width: %s\n",
+ format_6ghz_chan_width(e->he_chan_info.chan_width));
+ }
+
+ if (e->eht_chan_info.center_chan_1) {
+ printf(" EHT Operation:\n");
+ printf(" Center Frequency 1: %d\n",
+ e->eht_chan_info.center_chan_1);
+ printf(" Center Frequency 2: %d\n",
+ e->eht_chan_info.center_chan_2);
+ printf(" Channel Width: %s\n",
+ format_6ghz_chan_width(e->eht_chan_info.chan_width));
+ }
+
printf("\n");
}
}
8080, /* 80+80 MHz */
};
+const uint16_t eht_chan_width[5] = {
+ 20, /* 20 MHz */
+ 40, /* 40 MHz */
+ 80, /* 80 MHz */
+ 160, /* 80+80 or 160 MHz */
+ 320, /* 160+160 or 320 MHz */
+};
+
/*
* ISO3166 country labels
*/
};
+static void nl80211_get_scanlist_he_operation(unsigned char len,
+ unsigned char *ie, struct iwinfo_scanlist_entry *e)
+{
+ uint8_t offset = 6;
+
+ /* 6 GHz Operation Info not present */
+ if (!(ie[2] & 0x02))
+ return;
+
+ /* VHT Operation Info present */
+ if (ie[1] & 0x40)
+ offset += 3;
+
+ /* Co Hosted BSS present */
+ if (ie[1] & 0x80)
+ offset += 1;
+
+ if (len - offset < 5)
+ return;
+
+ e->he_chan_info.chan_width = ie[offset + 1] & 0x03;
+ e->he_chan_info.center_chan_1 = ie[offset + 2];
+ e->he_chan_info.center_chan_2 = ie[offset + 3];
+}
+
+
+static void nl80211_get_scanlist_eht_operation(unsigned char len,
+ unsigned char *ie, struct iwinfo_scanlist_entry *e)
+{
+ /* EHT Operation Info not present */
+ if (!(ie[0] & 0x01))
+ return;
+
+ if (len < 8)
+ return;
+
+ e->eht_chan_info.chan_width = ie[5] & 0x07;
+ e->eht_chan_info.center_chan_1 = ie[6];
+ e->eht_chan_info.center_chan_2 = ie[7];
+}
+
+
+static void nl80211_get_scanlist_extension(unsigned char len,
+ unsigned char *ie, struct iwinfo_scanlist_entry *e)
+{
+ if (len < 1)
+ return;
+
+ switch (ie[0])
+ {
+ case 36: /* HE Operation */
+ nl80211_get_scanlist_he_operation(len - 1, ie + 1, e);
+ break;
+ case 106: /* EHT Operation */
+ nl80211_get_scanlist_eht_operation(len - 1, ie + 1, e);
+ break;
+ }
+}
+
+
static void nl80211_get_scanlist_ie(struct nlattr **bss,
struct iwinfo_scanlist_entry *e)
{
e->vht_chan_info.center_chan_2 = ie[4];
}
break;
+ case 255: /* Extension Tag*/
+ nl80211_get_scanlist_extension(ie[1], ie + 2, e);
+ break;
}
ielen -= ie[1] + 2;