devices: add device id for MediaTek MT7996e
[project/iwinfo.git] / iwinfo_nl80211.c
index 5bc2f51df20f12c511369c259283462365eceaef..c352c9f454c777f4718d218de98cc1a427594492 100644 (file)
@@ -825,13 +825,15 @@ static char * nl80211_phy2ifname(const char *ifname)
 
        memset(nif, 0, sizeof(nif));
 
-       snprintf(buffer, sizeof(buffer),
-                "/sys/class/ieee80211/phy%d/device/net", phyidx);
-
-       if ((d = opendir(buffer)) != NULL)
+       if ((d = opendir("/sys/class/net")) != NULL)
        {
                while ((e = readdir(d)) != NULL)
                {
+                       snprintf(buffer, sizeof(buffer),
+                                "/sys/class/net/%s/phy80211/index", e->d_name);
+                       if (nl80211_readint(buffer) != phyidx)
+                               continue;
+
                        snprintf(buffer, sizeof(buffer),
                                 "/sys/class/net/%s/ifindex", e->d_name);
                        cifidx = nl80211_readint(buffer);
@@ -1247,7 +1249,7 @@ static int nl80211_get_ssid_bssid_cb(struct nl_msg *msg, void *arg)
        struct nlattr **tb = nl80211_parse(msg);
        struct nlattr *bss[NL80211_BSS_MAX + 1];
 
-       static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
+       static const struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
                [NL80211_BSS_INFORMATION_ELEMENTS] = { 0 },
                [NL80211_BSS_STATUS]               = { .type = NLA_U32 },
        };
@@ -1371,7 +1373,7 @@ static int nl80211_get_frequency_scan_cb(struct nl_msg *msg, void *arg)
        struct nlattr **attr = nl80211_parse(msg);
        struct nlattr *binfo[NL80211_BSS_MAX + 1];
 
-       static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
+       static const struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
                [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
                [NL80211_BSS_STATUS]    = { .type = NLA_U32 },
        };
@@ -1548,10 +1550,12 @@ static int nl80211_fill_signal_cb(struct nl_msg *msg, void *arg)
        struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
        struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
 
-       static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
+       static const struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
                [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32    },
                [NL80211_STA_INFO_RX_BYTES]      = { .type = NLA_U32    },
                [NL80211_STA_INFO_TX_BYTES]      = { .type = NLA_U32    },
+               [NL80211_STA_INFO_RX_BYTES64]    = { .type = NLA_U64    },
+               [NL80211_STA_INFO_TX_BYTES64]    = { .type = NLA_U64    },
                [NL80211_STA_INFO_RX_PACKETS]    = { .type = NLA_U32    },
                [NL80211_STA_INFO_TX_PACKETS]    = { .type = NLA_U32    },
                [NL80211_STA_INFO_SIGNAL]        = { .type = NLA_U8     },
@@ -1561,7 +1565,7 @@ static int nl80211_fill_signal_cb(struct nl_msg *msg, void *arg)
                [NL80211_STA_INFO_PLINK_STATE]   = { .type = NLA_U8     },
        };
 
-       static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
+       static const struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
                [NL80211_RATE_INFO_BITRATE]      = { .type = NLA_U16  },
                [NL80211_RATE_INFO_MCS]          = { .type = NLA_U8   },
                [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
@@ -1660,7 +1664,7 @@ static int nl80211_get_noise_cb(struct nl_msg *msg, void *arg)
        struct nlattr **tb = nl80211_parse(msg);
        struct nlattr *si[NL80211_SURVEY_INFO_MAX + 1];
 
-       static struct nla_policy sp[NL80211_SURVEY_INFO_MAX + 1] = {
+       static const struct nla_policy sp[NL80211_SURVEY_INFO_MAX + 1] = {
                [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
                [NL80211_SURVEY_INFO_NOISE]     = { .type = NLA_U8  },
        };
@@ -1758,7 +1762,7 @@ static int nl80211_check_wepkey(const char *key)
        return 0;
 }
 
-static struct {
+static const struct {
        const char *match;
        int version;
        int suite;
@@ -1815,7 +1819,7 @@ static void parse_wpa_suites(const char *str, int defversion,
        }
 }
 
-static struct {
+static const struct {
        const char *match;
        int cipher;
 } wpa_cipher_strings[] = {
@@ -2043,7 +2047,17 @@ static void nl80211_parse_rateinfo(struct nlattr **ri,
        else if (ri[NL80211_RATE_INFO_BITRATE])
                re->rate = nla_get_u16(ri[NL80211_RATE_INFO_BITRATE]) * 100;
 
-       if (ri[NL80211_RATE_INFO_HE_MCS])
+       if (ri[NL80211_RATE_INFO_EHT_MCS])
+       {
+               re->is_eht = 1;
+               re->mcs = nla_get_u8(ri[NL80211_RATE_INFO_EHT_MCS]);
+
+               if (ri[NL80211_RATE_INFO_EHT_NSS])
+                       re->nss = nla_get_u8(ri[NL80211_RATE_INFO_EHT_NSS]);
+               if (ri[NL80211_RATE_INFO_EHT_GI])
+                       re->eht_gi = nla_get_u8(ri[NL80211_RATE_INFO_EHT_GI]);
+       }
+       else if (ri[NL80211_RATE_INFO_HE_MCS])
        {
                re->is_he = 1;
                re->mcs = nla_get_u8(ri[NL80211_RATE_INFO_HE_MCS]);
@@ -2080,6 +2094,8 @@ static void nl80211_parse_rateinfo(struct nlattr **ri,
        else if (ri[NL80211_RATE_INFO_80P80_MHZ_WIDTH] ||
                 ri[NL80211_RATE_INFO_160_MHZ_WIDTH])
                re->mhz = 160;
+       else if (ri[NL80211_RATE_INFO_320_MHZ_WIDTH])
+               re->mhz_hi = 320 / 256, re->mhz = 320 % 256;
        else
                re->mhz = 20;
 
@@ -2097,7 +2113,7 @@ static int nl80211_get_survey_cb(struct nl_msg *msg, void *arg)
        struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
        int rc;
 
-       static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
+       static const struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
                [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
                [NL80211_SURVEY_INFO_NOISE]  = { .type = NLA_U8     },
                [NL80211_SURVEY_INFO_TIME] = { .type = NLA_U64   },
@@ -2202,7 +2218,7 @@ static int nl80211_get_assoclist_cb(struct nl_msg *msg, void *arg)
        struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
        struct nl80211_sta_flag_update *sta_flags;
 
-       static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
+       static const struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
                [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32    },
                [NL80211_STA_INFO_RX_PACKETS]    = { .type = NLA_U32    },
                [NL80211_STA_INFO_TX_PACKETS]    = { .type = NLA_U32    },
@@ -2212,6 +2228,8 @@ static int nl80211_get_assoclist_cb(struct nl_msg *msg, void *arg)
                [NL80211_STA_INFO_SIGNAL_AVG]    = { .type = NLA_U8     },
                [NL80211_STA_INFO_RX_BYTES]      = { .type = NLA_U32    },
                [NL80211_STA_INFO_TX_BYTES]      = { .type = NLA_U32    },
+               [NL80211_STA_INFO_RX_BYTES64]    = { .type = NLA_U64    },
+               [NL80211_STA_INFO_TX_BYTES64]    = { .type = NLA_U64    },
                [NL80211_STA_INFO_TX_RETRIES]    = { .type = NLA_U32    },
                [NL80211_STA_INFO_TX_FAILED]     = { .type = NLA_U32    },
                [NL80211_STA_INFO_CONNECTED_TIME]= { .type = NLA_U32    },
@@ -2229,7 +2247,7 @@ static int nl80211_get_assoclist_cb(struct nl_msg *msg, void *arg)
                [NL80211_STA_INFO_NONPEER_PM]    = { .type = NLA_U32    },
        };
 
-       static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
+       static const struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
                [NL80211_RATE_INFO_BITRATE]      = { .type = NLA_U16    },
                [NL80211_RATE_INFO_MCS]          = { .type = NLA_U8     },
                [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG   },
@@ -2275,10 +2293,14 @@ static int nl80211_get_assoclist_cb(struct nl_msg *msg, void *arg)
                                      sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy))
                        nl80211_parse_rateinfo(rinfo, &e->tx_rate);
 
-               if (sinfo[NL80211_STA_INFO_RX_BYTES])
+               if (sinfo[NL80211_STA_INFO_RX_BYTES64])
+                       e->rx_bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
+               else if (sinfo[NL80211_STA_INFO_RX_BYTES])
                        e->rx_bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
 
-               if (sinfo[NL80211_STA_INFO_TX_BYTES])
+               if (sinfo[NL80211_STA_INFO_TX_BYTES64])
+                       e->tx_bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
+               else if (sinfo[NL80211_STA_INFO_TX_BYTES])
                        e->tx_bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
 
                if (sinfo[NL80211_STA_INFO_TX_RETRIES])
@@ -2411,7 +2433,7 @@ static int nl80211_get_txpwrlist_cb(struct nl_msg *msg, void *arg)
        struct nlattr *freqs[NL80211_FREQUENCY_ATTR_MAX + 1];
        struct nlattr *band, *freq;
 
-       static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
+       static const struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
                [NL80211_FREQUENCY_ATTR_FREQ]         = { .type = NLA_U32  },
                [NL80211_FREQUENCY_ATTR_DISABLED]     = { .type = NLA_FLAG },
                [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
@@ -2594,7 +2616,7 @@ static int nl80211_get_scanlist_cb(struct nl_msg *msg, void *arg)
        struct nlattr **tb = nl80211_parse(msg);
        struct nlattr *bss[NL80211_BSS_MAX + 1];
 
-       static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
+       static const struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
                [NL80211_BSS_TSF]                  = { .type = NLA_U64 },
                [NL80211_BSS_FREQUENCY]            = { .type = NLA_U32 },
                [NL80211_BSS_BSSID]                = { 0 },
@@ -3145,6 +3167,7 @@ struct nl80211_modes
        uint16_t nl_ht;
        uint32_t nl_vht;
        uint16_t he_phy_cap[6];
+       uint16_t eht_phy_cap[9];
 };
 
 static void nl80211_eval_modelist(struct nl80211_modes *m)
@@ -3173,6 +3196,22 @@ static void nl80211_eval_modelist(struct nl80211_modes *m)
                        m->ht |= IWINFO_HTMODE_HE160 | IWINFO_HTMODE_HE80_80;
        }
 
+       if (m->eht_phy_cap[0] != 0) {
+               m->hw |= IWINFO_80211_BE;
+               m->ht |= IWINFO_HTMODE_EHT20;
+
+               if (m->he_phy_cap[0] & BIT(9))
+                       m->ht |= IWINFO_HTMODE_EHT40;
+               if (m->he_phy_cap[0] & BIT(10))
+                       m->ht |= IWINFO_HTMODE_EHT40 | IWINFO_HTMODE_EHT80;
+               if (m->he_phy_cap[0] & BIT(11))
+                       m->ht |= IWINFO_HTMODE_EHT160;
+               if (m->he_phy_cap[0] & BIT(12))
+                       m->ht |= IWINFO_HTMODE_EHT160 | IWINFO_HTMODE_EHT80_80;
+               if ((m->eht_phy_cap[0] & BIT(9)) && (m->bands & IWINFO_BAND_6))
+                       m->ht |= IWINFO_HTMODE_EHT320;
+       }
+
        if (m->bands & IWINFO_BAND_24)
        {
                m->hw |= IWINFO_80211_B;
@@ -3242,6 +3281,8 @@ static int nl80211_get_modelist_cb(struct nl_msg *msg, void *arg)
                                nla_for_each_nested(nl_iftype, bands[NL80211_BAND_ATTR_IFTYPE_DATA], rem_band) {
                                        nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX,
                                                  nla_data(nl_iftype), nla_len(nl_iftype), NULL);
+
+                                       // HE
                                        if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) {
                                                len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]);
 
@@ -3251,6 +3292,17 @@ static int nl80211_get_modelist_cb(struct nl_msg *msg, void *arg)
                                                        nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]),
                                                        len);
                                        }
+
+                                       // EHT
+                                       if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]) {
+                                               len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]);
+
+                                               if (len > sizeof(m->eht_phy_cap) - 1)
+                                                       len = sizeof(m->eht_phy_cap) - 1;
+                                               memcpy(&((uint8_t *)m->eht_phy_cap)[1],
+                                                       nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]),
+                                                       len);
+                                       }
                                }
                        }
                }
@@ -3315,6 +3367,7 @@ static int nl80211_get_htmode(const char *ifname, int *buf)
        char *res, b[2] = { 0 };
        int err;
        bool he = false;
+       bool eht = false;
 
        res = nl80211_phy2ifname(ifname);
        *buf = 0;
@@ -3325,6 +3378,9 @@ static int nl80211_get_htmode(const char *ifname, int *buf)
        if (err)
                return -1;
 
+       if (nl80211_hostapd_query(res ? res : ifname, "ieee80211be", b, sizeof(b)))
+               eht = b[0] == '1';
+
        if (nl80211_hostapd_query(res ? res : ifname, "ieee80211ax", b, sizeof(b)))
                he = b[0] == '1';
        else if (nl80211_wpactl_query(res ? res : ifname, "wifi_generation", b, sizeof(b)))
@@ -3333,7 +3389,7 @@ static int nl80211_get_htmode(const char *ifname, int *buf)
        switch (chn.width) {
        case NL80211_CHAN_WIDTH_20:
                if (he)
-                       *buf = IWINFO_HTMODE_HE20;
+                       *buf = (eht == true) ? IWINFO_HTMODE_EHT20 : IWINFO_HTMODE_HE20;
                else if (chn.mode == -1)
                        *buf = IWINFO_HTMODE_VHT20;
                else
@@ -3341,7 +3397,7 @@ static int nl80211_get_htmode(const char *ifname, int *buf)
                break;
        case NL80211_CHAN_WIDTH_40:
                if (he)
-                       *buf = IWINFO_HTMODE_HE40;
+                       *buf = (eht == true) ? IWINFO_HTMODE_EHT40 : IWINFO_HTMODE_HE40;
                else if (chn.mode == -1)
                        *buf = IWINFO_HTMODE_VHT40;
                else
@@ -3349,22 +3405,25 @@ static int nl80211_get_htmode(const char *ifname, int *buf)
                break;
        case NL80211_CHAN_WIDTH_80:
                if (he)
-                       *buf = IWINFO_HTMODE_HE80;
+                       *buf = (eht == true) ? IWINFO_HTMODE_EHT80 : IWINFO_HTMODE_HE80;
                else
                        *buf = IWINFO_HTMODE_VHT80;
                break;
        case NL80211_CHAN_WIDTH_80P80:
                if (he)
-                       *buf = IWINFO_HTMODE_HE80_80;
+                       *buf = (eht == true) ? IWINFO_HTMODE_EHT80_80 : IWINFO_HTMODE_HE80_80;
                else
                        *buf = IWINFO_HTMODE_VHT80_80;
                break;
        case NL80211_CHAN_WIDTH_160:
                if (he)
-                       *buf = IWINFO_HTMODE_HE160;
+                       *buf = (eht == true) ? IWINFO_HTMODE_EHT160 : IWINFO_HTMODE_HE160;
                else
                        *buf = IWINFO_HTMODE_VHT160;
                break;
+       case NL80211_CHAN_WIDTH_320:
+               *buf = IWINFO_HTMODE_EHT320;
+               break;
        case NL80211_CHAN_WIDTH_5:
        case NL80211_CHAN_WIDTH_10:
        case NL80211_CHAN_WIDTH_20_NOHT:
@@ -3419,12 +3478,12 @@ static int nl80211_get_ifcomb_cb(struct nl_msg *msg, void *arg)
 
        nla_for_each_nested(comb, attr[NL80211_ATTR_INTERFACE_COMBINATIONS], comb_rem)
        {
-               static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
+               static const struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
                        [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
                        [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
                };
                struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB+1];
-               static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
+               static const struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
                        [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
                        [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
                };