e->channel = nl80211_freq2channel(e->mhz);
e->restricted = (
- freqs[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] ||
- freqs[NL80211_FREQUENCY_ATTR_NO_IBSS] ||
- freqs[NL80211_FREQUENCY_ATTR_RADAR]
+ freqs[NL80211_FREQUENCY_ATTR_NO_IR] &&
+ !freqs[NL80211_FREQUENCY_ATTR_RADAR]
) ? 1 : 0;
e++;
return 0;
}
-static int nl80211_get_hwmodelist_cb(struct nl_msg *msg, void *arg)
+
+struct nl80211_modes
+{
+ bool ok;
+ uint32_t hw;
+ uint32_t ht;
+};
+
+static int nl80211_get_modelist_cb(struct nl_msg *msg, void *arg)
{
- int *modes = arg;
+ struct nl80211_modes *m = arg;
int bands_remain, freqs_remain;
uint16_t caps = 0;
uint32_t vht_caps = 0;
struct nlattr *freqs[NL80211_FREQUENCY_ATTR_MAX + 1];
struct nlattr *band, *freq;
- *modes = 0;
-
if (attr[NL80211_ATTR_WIPHY_BANDS])
{
nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain)
/* Treat any nonzero capability as 11n */
if (caps > 0)
- *modes |= IWINFO_80211_N;
-
- if (bands[NL80211_BAND_ATTR_VHT_CAPA])
- vht_caps = nla_get_u32(bands[NL80211_BAND_ATTR_VHT_CAPA]);
+ {
+ m->hw |= IWINFO_80211_N;
+ m->ht |= IWINFO_HTMODE_HT20;
- /* Treat any nonzero capability as 11ac */
- if (vht_caps > 0)
- *modes |= IWINFO_80211_AC;
+ if (caps & (1 << 1))
+ m->ht |= IWINFO_HTMODE_HT40;
+ }
nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS],
freqs_remain)
if (nla_get_u32(freqs[NL80211_FREQUENCY_ATTR_FREQ]) < 2485)
{
- *modes |= IWINFO_80211_B;
- *modes |= IWINFO_80211_G;
+ m->hw |= IWINFO_80211_B;
+ m->hw |= IWINFO_80211_G;
+ }
+ else if (bands[NL80211_BAND_ATTR_VHT_CAPA])
+ {
+ vht_caps = nla_get_u32(bands[NL80211_BAND_ATTR_VHT_CAPA]);
+
+ /* Treat any nonzero capability as 11ac */
+ if (vht_caps > 0)
+ {
+ m->hw |= IWINFO_80211_AC;
+ m->ht |= IWINFO_HTMODE_VHT20 | IWINFO_HTMODE_VHT40 | IWINFO_HTMODE_VHT80;
+
+ switch ((vht_caps >> 2) & 3)
+ {
+ case 2:
+ m->ht |= IWINFO_HTMODE_VHT80_80;
+ /* fall through */
+
+ case 1:
+ m->ht |= IWINFO_HTMODE_VHT160;
+ }
+ }
}
- else if (!(*modes & IWINFO_80211_AC))
+ else if (!(m->hw & IWINFO_80211_AC))
{
- *modes |= IWINFO_80211_A;
+ m->hw |= IWINFO_80211_A;
}
}
}
+
+ m->ok = 1;
}
return NL_SKIP;
static int nl80211_get_hwmodelist(const char *ifname, int *buf)
{
struct nl80211_msg_conveyor *req;
+ struct nl80211_modes m = { };
req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
if (req)
{
- nl80211_send(req, nl80211_get_hwmodelist_cb, buf);
+ nl80211_send(req, nl80211_get_modelist_cb, &m);
nl80211_free(req);
}
- return *buf ? 0 : -1;
+ if (m.ok)
+ {
+ *buf = m.hw;
+ return 0;
+ }
+
+ return -1;
}
+static int nl80211_get_htmodelist(const char *ifname, int *buf)
+{
+ struct nl80211_msg_conveyor *req;
+ struct nl80211_modes m = { };
+
+ req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
+ if (req)
+ {
+ nl80211_send(req, nl80211_get_modelist_cb, &m);
+ nl80211_free(req);
+ }
+
+ if (m.ok)
+ {
+ *buf = m.ht;
+ return 0;
+ }
+
+ return -1;
+}
+
+
static int nl80211_get_ifcomb_cb(struct nl_msg *msg, void *arg)
{
struct nlattr **attr = nl80211_parse(msg);
[NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
};
- struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
+ struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB+1];
static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
[NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
};
- struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
+ struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT+1];
struct nlattr *limit;
- nla_parse_nested(tb_comb, NL80211_BAND_ATTR_MAX, comb, iface_combination_policy);
+ nla_parse_nested(tb_comb, NUM_NL80211_IFACE_COMB, comb, iface_combination_policy);
if (!tb_comb[NL80211_IFACE_COMB_LIMITS])
continue;
return 0;
}
+static int nl80211_lookup_phyname(const char *section, char *buf)
+{
+ int idx;
+
+ if ((idx = nl80211_phy_idx_from_uci(section)) < 0)
+ return -1;
+
+ sprintf(buf, "phy%d", idx);
+ return 0;
+}
+
const struct iwinfo_ops nl80211_ops = {
.name = "nl80211",
.probe = nl80211_probe,
.quality_max = nl80211_get_quality_max,
.mbssid_support = nl80211_get_mbssid_support,
.hwmodelist = nl80211_get_hwmodelist,
+ .htmodelist = nl80211_get_htmodelist,
.mode = nl80211_get_mode,
.ssid = nl80211_get_ssid,
.bssid = nl80211_get_bssid,
.scanlist = nl80211_get_scanlist,
.freqlist = nl80211_get_freqlist,
.countrylist = nl80211_get_countrylist,
+ .lookup_phy = nl80211_lookup_phyname,
.close = nl80211_close
};