From 56eee370528e520b67f0c49626289748ce3cf7d5 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 6 Feb 2025 08:22:36 +0100 Subject: [PATCH] iwinfo: move ucode based version into a feed Signed-off-by: John Crispin --- feeds/qca/iwinfo/Makefile | 127 ++ feeds/qca/iwinfo/files-iwinfo/usr/bin/iwinfo | 156 ++ .../files-iwinfo/usr/share/iso3166.json | 249 +++ .../files-iwinfo/usr/share/ucode/iwinfo.uc | 606 ++++++++ .../files-iwinfo/usr/share/wifi_devices.json | 258 ++++ feeds/qca/iwinfo/patches/100-6g.patch | 13 + ...o-add-ucode-based-version-for-wifi-7.patch | 1337 ----------------- 7 files changed, 1409 insertions(+), 1337 deletions(-) create mode 100644 feeds/qca/iwinfo/Makefile create mode 100755 feeds/qca/iwinfo/files-iwinfo/usr/bin/iwinfo create mode 100644 feeds/qca/iwinfo/files-iwinfo/usr/share/iso3166.json create mode 100644 feeds/qca/iwinfo/files-iwinfo/usr/share/ucode/iwinfo.uc create mode 100644 feeds/qca/iwinfo/files-iwinfo/usr/share/wifi_devices.json create mode 100644 feeds/qca/iwinfo/patches/100-6g.patch delete mode 100644 patches/0084-iwinfo-add-ucode-based-version-for-wifi-7.patch diff --git a/feeds/qca/iwinfo/Makefile b/feeds/qca/iwinfo/Makefile new file mode 100644 index 000000000..ba453f1b4 --- /dev/null +++ b/feeds/qca/iwinfo/Makefile @@ -0,0 +1,127 @@ +# +# Copyright (C) 2010-2016 Jo-Philipp Wich +# +# This is free software, licensed under the GPL 2 license. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=libiwinfo +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL=$(PROJECT_GIT)/project/iwinfo.git +PKG_SOURCE_DATE:=2023-07-01 +PKG_SOURCE_VERSION:=ca79f64154b107f192ec3c1ba631816cb8b07922 +PKG_MIRROR_HASH:=5eddf584a1c3ed5637162d6bfc573ed1ce3691fcb38bdd55bf9f1e11e82ccc46 +PKG_MAINTAINER:=Jo-Philipp Wich +PKG_LICENSE:=GPL-2.0 + +IWINFO_ABI_VERSION:=20230701 + +include $(INCLUDE_DIR)/package.mk + + +define Package/libiwinfo + SECTION:=libs + CATEGORY:=Libraries + TITLE:=Generalized Wireless Information Library (iwinfo) + DEPENDS:=+libnl-tiny +libuci +libubus +libiwinfo-data + ABI_VERSION:=$(IWINFO_ABI_VERSION) +endef + +define Package/libiwinfo/description + Wireless information library with simplified API for nl80211 + and wext driver interfaces. +endef + + +define Package/libiwinfo-lua + SUBMENU:=Lua + SECTION:=lang + CATEGORY:=Languages + TITLE:=libiwinfo Lua binding + DEPENDS:=+libiwinfo +liblua +endef + +define Package/libiwinfo-lua/description + This is the Lua binding for the iwinfo library. It provides access to all enabled + backends. +endef + + +define Package/libiwinfo-data + TITLE:=libiwinfo Lua binding + HIDDEN:=1 +endef + + +define Package/iwinfo + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Generalized Wireless Information utility + DEPENDS:=+libiwinfo +endef + +define Package/iwinfo/description + Command line frontend for the wireless information library. +endef + + +define Build/Configure +endef + +TARGET_CFLAGS += \ + -I$(STAGING_DIR)/usr/include/libnl-tiny \ + -I$(STAGING_DIR)/usr/include \ + -D_GNU_SOURCE + +MAKE_FLAGS += \ + FPIC="$(FPIC)" \ + CFLAGS="$(TARGET_CFLAGS)" \ + LDFLAGS="$(TARGET_LDFLAGS)" \ + BACKENDS="nl80211" \ + SOVERSION="$(IWINFO_ABI_VERSION)" + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/iwinfo + $(CP) $(PKG_BUILD_DIR)/include/iwinfo.h $(1)/usr/include/ + $(CP) $(PKG_BUILD_DIR)/include/iwinfo/* $(1)/usr/include/iwinfo/ + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libiwinfo.so* $(1)/usr/lib/ + $(INSTALL_DIR) $(1)/usr/lib/lua + $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo.so $(1)/usr/lib/lua/iwinfo.so +endef + +define Package/libiwinfo/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/libiwinfo.so.$(IWINFO_ABI_VERSION) $(1)/usr/lib/libiwinfo.so.$(IWINFO_ABI_VERSION) +endef + +define Package/libiwinfo-lua/install + $(INSTALL_DIR) $(1)/usr/lib/lua + $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo.so $(1)/usr/lib/lua/iwinfo.so +endef + +define Package/libiwinfo-data/install + $(INSTALL_DIR) $(1)/usr/share/libiwinfo + $(INSTALL_DATA) $(PKG_BUILD_DIR)/devices.txt $(1)/usr/share/libiwinfo/devices.txt +endef + +ifeq ($(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y) +define Package/iwinfo/install + $(CP) ./files-iwinfo/* $(1) + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo $(1)/usr/share/iwinfo +endef +else +define Package/iwinfo/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo $(1)/usr/bin/iwinfo +endef +endif + +$(eval $(call BuildPackage,libiwinfo)) +$(eval $(call BuildPackage,libiwinfo-lua)) +$(eval $(call BuildPackage,libiwinfo-data)) +$(eval $(call BuildPackage,iwinfo)) diff --git a/feeds/qca/iwinfo/files-iwinfo/usr/bin/iwinfo b/feeds/qca/iwinfo/files-iwinfo/usr/bin/iwinfo new file mode 100755 index 000000000..01285eb38 --- /dev/null +++ b/feeds/qca/iwinfo/files-iwinfo/usr/bin/iwinfo @@ -0,0 +1,156 @@ +#!/usr/bin/ucode + +'use strict'; + +import * as iwinfo from 'iwinfo'; + +function print_assoclist(stations) { + for (let mac, station in stations) { + printf(`${station.mac} ${station.signal} dBm / ${station.noise} dBm (SNR ${station.snr}) ${station.inactive_time} ms ago\n`); + for (let k in [ 'rx', 'tx' ]) { + let bitrate = station[k]; + let flags = join(', ', bitrate.flags); + + printf(`\t${uc(k)}: ${bitrate.bitrate} MBit/s`); + if (length(bitrate.flags)) + printf(', %s', flags); + printf('%10d Pkts.\n', bitrate.packets); + } + printf(`\texpected throughput: ${station.expected_throughput}\n\n`); + } +} + +function print_countrylist(list) { + for (let k, v in list.countries) + printf(`${k == list.active ? '*' : ' '} ${k} "${v}"\n`); +} + +function print_freqlist(channels) { + for (let channel in channels) { + printf(`${channel.active ? '*' : ' '} ${channel.freq} GHz (Band: ${channel.band} GHz, Channel ${channel.channel})`); + if (length(channel.flags)) + printf(` [${join(', ', channel.flags)}]`); + printf('\n'); + } +} + +function print_htmodelist(htmode) { + printf('%s\n', join(' ', htmode)); +} + +function print_info(list) { + let padding = ' '; + + for (let bss in list) { + printf(`${bss.iface} ESSID: "${bss.ssid}"\n`); + printf(`${padding}Access Point: ${bss.mac}\n`); + printf(`${padding}Mode: ${bss.mode} Channel: ${bss.channel} (${bss.freq} GHz) HT Mode: ${bss.htmode}\n`); + printf(`${padding}Center Channel 1: ${bss.center_freq1} 2: ${bss.center_freq2}\n`); + printf(`${padding}Tx-Power: ${bss.txpower} dBm Link Quality: ${bss.quality}/70\n`); + printf(`${padding}Signal: ${bss.signal} Noise: ${bss.noise}\n`); + printf(`${padding}Bit Rate: ${bss.bitrate ?? 'unknown'} MBit/s\n`); + printf(`${padding}Encryption: ${bss.encryption}\n`); + printf(`${padding}Type: nl80211 HW Mode(s): 802.11${bss.hwmode}\n`); + printf(`${padding}Hardware: ${bss.hw_type} [${bss.hw_id}]\n`); + printf(`${padding}TX power offset: ${bss.power_offset}\n`); + printf(`${padding}Channel offset: ${bss.channel_offset}\n`); + printf(`${padding}Supports VAPs: ${bss.vaps} PHY name: ${bss.phy}\n`); + if (bss.owe_transition_ifname) + printf(`${padding}OWE partner: ${bss.owe_transition_ifname}\n`); + printf('\n'); + } + return 0; +} + +function print_scan(cells) { + let idx = 1; + + for (let cell in cells) { + printf('Cell %02d - Address: %s\n', idx++, cell.bssid); + printf('\t Mode: %s Frequency: %s GHz Band: %s GHz Channel: %d\n', cell.mode, cell.frequency, cell.band, cell.channel); + printf('\t Signal: %d dBm Quality: %2d/70\n', cell.dbm, cell.quality); + + if (!length(cell.crypto.key_mgmt)) + printf('\t Encryption: NONE\n'); + else + printf('\t Encryption: %s (%s)\n', join(' / ', cell.crypto.key_mgmt), join(' / ', cell.crypto.pair)); + + if (cell.ht) { + printf('\t HT Operation:\n'); + printf('\t\tPrimary Channel: %d\n', cell.ht.primary_channel); + printf('\t\tSecondary Channel Offset: %s\n', cell.ht.secondary_chan_off); + printf('\t\tChannel Width: %s\n', cell.ht.chan_width); + } + + if (cell.vht) { + printf('\t VHT Operation:\n'); + printf('\t\tCenter Frequency 1: %d\n', cell.vht.center_chan_1); + printf('\t\tCenter Frequency 2: %s\n', cell.vht.center_chan_2); + printf('\t\tChannel Width: %s\n', cell.vht.chan_width); + } + + printf('\n'); + } +} + +function print_txpowerlist(list) { + for (let power in list) + printf('%s %2d dbm (%4d mW)\n', power.active ? '*' : ' ', power.dbm, power.mw); +} + +let pretty = true; +if (ARGV[0] == '-j') { + pretty = false; + shift(ARGV); +} + +if (!length(ARGV)) { + let info = iwinfo.info(); + if (pretty) + print_info(info); + else + printf('%.J\n', info); + return 0; +} + +const commands = { + assoclist: [ iwinfo.assoclist, print_assoclist ], + countrylist: [ iwinfo.countrylist, print_countrylist ], + freqlist: [ iwinfo.freqlist, print_freqlist ], + htmodelist: [ iwinfo.htmodelist, print_htmodelist ], + info: [ iwinfo.info, print_info ], + scan: [ iwinfo.scan, print_scan ], + txpowerlist: [ iwinfo.txpowerlist, print_txpowerlist ], +}; + +if (length(ARGV) == 2 && iwinfo.ifaces[ARGV[0]]) + for (let cmd, cb in commands) + if (substr(cmd, 0, length(ARGV[1])) == ARGV[1]) { + let ret = cb[0](ARGV[0]); + + if (pretty) + cb[1](ret); + else + printf('%.J\n', ret); + return 0; + } + +switch(ARGV[0]) { +case 'phy': + printf('%.J\n', iwinfo.phys); + return 0; + +case 'iface': + printf('%.J\n', iwinfo.ifaces); + return 0; +} + +printf('Usage:\n' + + '\tiwinfo info\n' + + '\tiwinfo scan\n' + + '\tiwinfo txpowerlist\n' + + '\tiwinfo freqlist\n' + + '\tiwinfo assoclist\n' + + '\tiwinfo countrylist\n' + + '\tiwinfo htmodelist\n' + + '\tiwinfo phyname
\n'); diff --git a/feeds/qca/iwinfo/files-iwinfo/usr/share/iso3166.json b/feeds/qca/iwinfo/files-iwinfo/usr/share/iso3166.json new file mode 100644 index 000000000..ecd0b6538 --- /dev/null +++ b/feeds/qca/iwinfo/files-iwinfo/usr/share/iso3166.json @@ -0,0 +1,249 @@ +{ + "00": "World", + "AD": "Andorra", + "AE": "United Arab Emirates", + "AF": "Afghanistan", + "AG": "Antigua and Barbuda", + "AI": "Anguilla", + "AL": "Albania", + "AM": "Armenia", + "AN": "Netherlands Antilles", + "AO": "Angola", + "AQ": "Antarctica", + "AR": "Argentina", + "AS": "American Samoa", + "AT": "Austria", + "AU": "Australia", + "AW": "Aruba", + "AX": "Aland Islands", + "AZ": "Azerbaijan", + "BA": "Bosnia and Herzegovina", + "BB": "Barbados", + "BD": "Bangladesh", + "BE": "Belgium", + "BF": "Burkina Faso", + "BG": "Bulgaria", + "BH": "Bahrain", + "BI": "Burundi", + "BJ": "Benin", + "BL": "Saint Barthelemy", + "BM": "Bermuda", + "BN": "Brunei Darussalam", + "BO": "Bolivia", + "BR": "Brazil", + "BS": "Bahamas", + "BT": "Bhutan", + "BV": "Bouvet Island", + "BW": "Botswana", + "BY": "Belarus", + "BZ": "Belize", + "CA": "Canada", + "CC": "Cocos (Keeling) Islands", + "CD": "Congo", + "CF": "Central African Republic", + "CG": "Congo", + "CH": "Switzerland", + "CI": "Cote d'Ivoire", + "CK": "Cook Islands", + "CL": "Chile", + "CM": "Cameroon", + "CN": "China", + "CO": "Colombia", + "CR": "Costa Rica", + "CU": "Cuba", + "CV": "Cape Verde", + "CX": "Christmas Island", + "CY": "Cyprus", + "CZ": "Czech Republic", + "DE": "Germany", + "DJ": "Djibouti", + "DK": "Denmark", + "DM": "Dominica", + "DO": "Dominican Republic", + "DZ": "Algeria", + "EC": "Ecuador", + "EE": "Estonia", + "EG": "Egypt", + "EH": "Western Sahara", + "ER": "Eritrea", + "ES": "Spain", + "ET": "Ethiopia", + "FI": "Finland", + "FJ": "Fiji", + "FK": "Falkland Islands", + "FM": "Micronesia", + "FO": "Faroe Islands", + "FR": "France", + "GA": "Gabon", + "GB": "United Kingdom", + "GD": "Grenada", + "GE": "Georgia", + "GF": "French Guiana", + "GG": "Guernsey", + "GH": "Ghana", + "GI": "Gibraltar", + "GL": "Greenland", + "GM": "Gambia", + "GN": "Guinea", + "GP": "Guadeloupe", + "GQ": "Equatorial Guinea", + "GR": "Greece", + "GS": "South Georgia", + "GT": "Guatemala", + "GU": "Guam", + "GW": "Guinea-Bissau", + "GY": "Guyana", + "HK": "Hong Kong", + "HM": "Heard and McDonald Islands", + "HN": "Honduras", + "HR": "Croatia", + "HT": "Haiti", + "HU": "Hungary", + "ID": "Indonesia", + "IE": "Ireland", + "IL": "Israel", + "IM": "Isle of Man", + "IN": "India", + "IO": "Chagos Islands", + "IQ": "Iraq", + "IR": "Iran", + "IS": "Iceland", + "IT": "Italy", + "JE": "Jersey", + "JM": "Jamaica", + "JO": "Jordan", + "JP": "Japan", + "KE": "Kenya", + "KG": "Kyrgyzstan", + "KH": "Cambodia", + "KI": "Kiribati", + "KM": "Comoros", + "KN": "Saint Kitts and Nevis", + "KP": "North Korea", + "KR": "South Korea", + "KW": "Kuwait", + "KY": "Cayman Islands", + "KZ": "Kazakhstan", + "LA": "Laos", + "LB": "Lebanon", + "LC": "Saint Lucia", + "LI": "Liechtenstein", + "LK": "Sri Lanka", + "LR": "Liberia", + "LS": "Lesotho", + "LT": "Lithuania", + "LU": "Luxembourg", + "LV": "Latvia", + "LY": "Libyan Arab Jamahiriya", + "MA": "Morocco", + "MC": "Monaco", + "MD": "Moldova", + "ME": "Montenegro", + "MF": "Saint Martin (French part)", + "MG": "Madagascar", + "MH": "Marshall Islands", + "MK": "Macedonia", + "ML": "Mali", + "MM": "Myanmar", + "MN": "Mongolia", + "MO": "Macao", + "MP": "Northern Mariana Islands", + "MQ": "Martinique", + "MR": "Mauritania", + "MS": "Montserrat", + "MT": "Malta", + "MU": "Mauritius", + "MV": "Maldives", + "MW": "Malawi", + "MX": "Mexico", + "MY": "Malaysia", + "MZ": "Mozambique", + "NA": "Namibia", + "NC": "New Caledonia", + "NE": "Niger", + "NF": "Norfolk Island", + "NG": "Nigeria", + "NI": "Nicaragua", + "NL": "Netherlands", + "NO": "Norway", + "NP": "Nepal", + "NR": "Nauru", + "NU": "Niue", + "NZ": "New Zealand", + "OM": "Oman", + "PA": "Panama", + "PE": "Peru", + "PF": "French Polynesia", + "PG": "Papua New Guinea", + "PH": "Philippines", + "PK": "Pakistan", + "PL": "Poland", + "PM": "Saint Pierre and Miquelon", + "PN": "Pitcairn", + "PR": "Puerto Rico", + "PS": "Palestinian Territory", + "PT": "Portugal", + "PW": "Palau", + "PY": "Paraguay", + "QA": "Qatar", + "RE": "Reunion", + "RO": "Romania", + "RS": "Serbia", + "RU": "Russian Federation", + "RW": "Rwanda", + "SA": "Saudi Arabia", + "SB": "Solomon Islands", + "SC": "Seychelles", + "SD": "Sudan", + "SE": "Sweden", + "SG": "Singapore", + "SH": "St. Helena and Dependencies", + "SI": "Slovenia", + "SJ": "Svalbard and Jan Mayen", + "SK": "Slovakia", + "SL": "Sierra Leone", + "SM": "San Marino", + "SN": "Senegal", + "SO": "Somalia", + "SR": "Suriname", + "ST": "Sao Tome and Principe", + "SV": "El Salvador", + "SY": "Syrian Arab Republic", + "SZ": "Swaziland", + "TC": "Turks and Caicos Islands", + "TD": "Chad", + "TF": "French Southern Territories", + "TG": "Togo", + "TH": "Thailand", + "TJ": "Tajikistan", + "TK": "Tokelau", + "TL": "Timor-Leste", + "TM": "Turkmenistan", + "TN": "Tunisia", + "TO": "Tonga", + "TR": "Turkey", + "TT": "Trinidad and Tobago", + "TV": "Tuvalu", + "TW": "Taiwan", + "TZ": "Tanzania", + "UA": "Ukraine", + "UG": "Uganda", + "UM": "U.S. Minor Outlying Islands", + "US": "United States", + "UY": "Uruguay", + "UZ": "Uzbekistan", + "VA": "Vatican City State", + "VC": "St. Vincent and Grenadines", + "VE": "Venezuela", + "VG": "Virgin Islands, British", + "VI": "Virgin Islands, U.S.", + "VN": "Viet Nam", + "VU": "Vanuatu", + "WF": "Wallis and Futuna", + "WS": "Samoa", + "YE": "Yemen", + "YT": "Mayotte", + "ZA": "South Africa", + "ZM": "Zambia", + "ZW": "Zimbabwe" +} diff --git a/feeds/qca/iwinfo/files-iwinfo/usr/share/ucode/iwinfo.uc b/feeds/qca/iwinfo/files-iwinfo/usr/share/ucode/iwinfo.uc new file mode 100644 index 000000000..84615adb5 --- /dev/null +++ b/feeds/qca/iwinfo/files-iwinfo/usr/share/ucode/iwinfo.uc @@ -0,0 +1,606 @@ +'use strict'; + +import * as nl80211 from 'nl80211'; +import * as libubus from 'ubus'; +import { readfile, stat } from "fs"; + +let wifi_devices = json(readfile('/usr/share/wifi_devices.json')); +let countries = json(readfile('/usr/share/iso3166.json')); +let board_data = json(readfile('/etc/board.json')); + +export let phys = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, nl80211.const.NLM_F_DUMP, { split_wiphy_dump: true }); +let interfaces = nl80211.request(nl80211.const.NL80211_CMD_GET_INTERFACE, nl80211.const.NLM_F_DUMP); + +let ubus = libubus.connect(); +let wireless_status = ubus.call('network.wireless', 'status'); + +function find_phy(wiphy) { + for (let k, phy in phys) + if (phy.wiphy == wiphy) + return phy; + return null; +} + +function get_noise(iface) { + for (let phy in phys) { + let channels = nl80211.request(nl80211.const.NL80211_CMD_GET_SURVEY, nl80211.const.NLM_F_DUMP, { dev: iface.ifname }); + for (let k, channel in channels) + if (channel.survey_info.frequency == iface.wiphy_freq) + return channel.survey_info.noise; + } + + return -100; +} + +function get_country(iface) { + let reg = nl80211.request(nl80211.const.NL80211_CMD_GET_REG, 0, { dev: iface.ifname }); + + return reg.reg_alpha2 ?? ''; +} + +function get_max_power(iface) { + let phy = find_phy(iface.wiphy); + + for (let k, band in phy.wiphy_bands) + if (band) + for (let freq in band.freqs) + if (freq.freq == iface.wiphy_freq) + return freq.max_tx_power;; + return 0; +} + +function get_hardware_id(iface) { + let hw = { + type: 'nl80211', + id: 'Generic MAC80211', + power_offset: 0, + channel_offset: 0, + }; + + let path = `/sys/class/ieee80211/phy${iface.wiphy}/device/`; + if (stat(path) + 'vendor') { + let data = []; + for (let lookup in [ 'vendor', 'device', 'subsystem_vendor', 'subsystem_device' ]) + push(data, trim(readfile(path + lookup), '\n')); + + for (let device in wifi_devices.pci) { + let match = 0; + for (let i = 0; i < 4; i++) + if (lc(data[i]) == lc(device[i])) + match++; + if (match == 4) { + hw.type = `${data[0]}:${data[1]} ${data[2]}:${data[3]}`; + hw.power_offset = device[4]; + hw.channel_offset = device[5]; + hw.id = `${device[6]} ${device[7]}`; + } + } + } + + let compatible = trim(readfile(`/sys/class/net/${iface.ifname}/device/of_node/compatible`), '\n'); + if (compatible && wifi_devices.compatible[compatible]) { + hw.id = wifi_devices.compatible[compatible][0] + ' ' + wifi_devices.compatible[compatible][1]; + hw.compatible = compatible; + hw.type = 'embedded'; + } + + return hw; +} + +const iftypes = [ + 'Unknown', 'Ad-Hoc', 'Client', 'Master', 'Master (VLAN)', + 'WDS', 'Monitor', 'Mesh Point', 'P2P Client', 'P2P Go', +]; + +export let ifaces = {}; +for (let k, v in interfaces) { + let iface = ifaces[v.ifname] = v; + + iface.mode = iftypes[iface.iftype] ?? 'unknonw', + iface.noise = get_noise(iface); + iface.country = get_country(iface); + iface.max_power = get_max_power(iface); + iface.assoclist = nl80211.request(nl80211.const.NL80211_CMD_GET_STATION, nl80211.const.NLM_F_DUMP, { dev: v.ifname }) ?? []; + iface.hardware = get_hardware_id(iface); + + iface.bss_info = ubus.call('hostapd', 'bss_info', { iface: v.ifname }); + if (!iface.bss_info) + iface.bss_info = ubus.call('wpa_supplicant', 'bss_info', { iface: v.ifname }); +} + +for (let radio, data in wireless_status) + for (let k, v in data.interfaces) { + if (!v.ifname || !ifaces[v.ifname]) + continue; + + ifaces[v.ifname].ssid = v.config.ssid; + ifaces[v.ifname].radio = data.config; + + let bss_info = ifaces[v.ifname].bss_info; + let owe_transition_ifname = bss_info?.owe_transition_ifname; + + if (v.config.owe_transition && ifaces[owe_transition_ifname]) { + ifaces[v.ifname].owe_transition_ifname = owe_transition_ifname; + ifaces[owe_transition_ifname].ssid = v.config.ssid; + ifaces[owe_transition_ifname].radio = data.config; + ifaces[owe_transition_ifname].owe_transition_ifname = v.ifname + } + } + +function format_channel(freq) { + if (freq < 1000) + return 0; + if (freq == 2484) + return 14; + if (freq == 5935) + return 2; + if (freq < 2484) + return (freq - 2407) / 5; + if (freq >= 4910 && freq <= 4980) + return (freq - 4000) / 5; + if (freq < 5950) + return (freq - 5000) / 5; + if (freq <= 45000) + return (freq - 5950) / 5; + if (freq >= 58320 && freq <= 70200) + return (freq - 56160) / 2160; + + return 'unknown'; +} + +function format_band(freq) { + if (freq == 5935) + return '6'; + if (freq < 2484) + return '2.4'; + if (freq < 5950) + return '5'; + if (freq <= 45000) + return '6'; + + return '60'; +} + +function format_frequency(freq) { + if (!freq) + return 'unknown'; + freq = '' + freq; + return substr(freq, 0, 1) + '.' + substr(freq, 1); +} + +function format_rate(rate) { + if (!rate) + return 'unknown'; + return '' + (rate / 10) + '.' + (rate % 10); +} + +function format_mgmt_key(key) { + switch(+key) { + case 1: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + return '802.1x'; + + case 2: + return 'WPA PSK'; + + case 4: + return 'FT PSK'; + + case 6: + return 'WPA PSK2'; + + case 8: + return 'SAE'; + + case 18: + return 'OWE'; + } + + return null; +} + +function assoc_flags(data) { + const assoc_mhz = { + width_40: 40, + width_80: 80, + width_80p80: '80+80', + width_160: 160, + width_320: 320, + width_10: 10, + width_5: 5 + }; + + let mhz = 'unknown'; + for (let k, v in assoc_mhz) + if (data[k]) + mhz = v; + + const assoc_flags = { + mcs: { + mcs: 'MCS', + }, + vht_mcs: { + vht_mcs: 'VHT-MCS', + vht_nss: 'VHT-NSS', + }, + he_mcs: { + he_mcs: 'HE-MCS', + he_nss: 'HE-NSS', + he_gi: 'HE-GI', + he_dcm: 'HE-DCM', + }, + eht_mcs: { + eht_mcs: 'EHT-MCS', + eht_nss: 'EHT-NSS', + eht_gi: 'EHT-GI', + }, + }; + + let flags = []; + for (let k, v in assoc_flags) { + if (!data[k]) + continue; + + let first = 0; + for (let name, flag in v) { + if (data[name] == null) + continue; + push(flags, `${flag} ${data[name]}`); + if (!first++) + push(flags, `${mhz}MHz`); + } + } + + return flags; +} + +function dbm2mw(dbm) { + const LOG10_MAGIC = 1.25892541179; + let res = 1.0; + let ip = dbm / 10; + let fp = dbm % 10; + + for (let k = 0; k < ip; k++) + res *= 10; + for (let k = 0; k < fp; k++) + res *= 1.25892541179; + + return int(res); +} + +function dbm2quality(dbm) { + let quality = dbm; + + if (quality < -110) + quality = -110; + else if (quality > -40) + quality = -40; + quality += 110; + + return quality; +} + +function hwmodelist(name) { + const mode = { 'HT*': 'n', 'VHT*': 'ac', 'HE*': 'ax' }; + let iface = ifaces[name]; + let phy = board_data.wlan?.['phy' + iface.wiphy]; + if (!phy) + return ''; + let htmodes = phy.info.bands[uc(iface.radio.band)].modes; + let list = []; + if (iface.radio.band == '2g' && 'NOHT' in htmodes) + push(list, 'g/b'); + for (let k, v in mode) + for (let htmode in htmodes) + if (wildcard(htmode, k)) + push(list, v); + + return join('/', reverse(uniq(list))); +} + +export function assoclist(dev) { + let stations = ifaces[dev].assoclist; + let ret = {}; + + for (let station in stations) { + let sta = { + mac: uc(station.mac), + signal: station.sta_info.signal_avg, + noise: ifaces[dev].noise, + snr: station.sta_info.signal_avg - ifaces[dev].noise, + inactive_time: station.sta_info.inactive_time, + rx: { + bitrate: format_rate(station.sta_info.rx_bitrate.bitrate), + bitrate_raw: station.sta_info.rx_bitrate.bitrate, + packets: station.sta_info.rx_packets, + flags: assoc_flags(station.sta_info.rx_bitrate), + }, + tx: { + bitrate: format_rate(station.sta_info.tx_bitrate.bitrate), + bitrate_raw: station.sta_info.tx_bitrate.bitrate, + packets: station.sta_info.tx_packets, + flags: assoc_flags(station.sta_info.tx_bitrate), + }, + expected_throughput: station.sta_info.expected_throughput ?? 'unknown', + }; + ret[sta.mac] = sta; + } + + return ret; +}; + +export function freqlist(name) { + const freq_flags = { + no_10mhz: 'NO_10MHZ', + no_20mhz: 'NO_20MHZ', + no_ht40_minus: 'NO_HT40-', + no_ht40_plus: 'NO_HT40+', + no_80mhz: 'NO_80MHZ', + no_160mhz: 'NO_160MHZ', + indoor_only: 'INDOOR_ONLY', + no_ir: 'NO_IR', + no_he: 'NO_HE', + }; + + let iface = ifaces[name]; + let phy = find_phy(iface.wiphy); + let channels = []; + + for (let k, band in phy.wiphy_bands) { + if (!band) + continue; + + let band_name = format_band(band.freqs[0].freq); + for (let freq in band.freqs) { + if (freq.disabled) + continue; + + let channel = { + freq: format_frequency(freq.freq), + band: band_name, + channel: format_channel(freq.freq), + flags: [], + active: iface.wiphy_freq == freq.freq, + }; + + for (let k, v in freq_flags) + if (freq[k]) + push(channel.flags, v); + + push(channels, channel); + } + } + + return channels; +}; + +export function info(name) { + let order = []; + for (let iface, data in ifaces) + push(order, iface); + + let list = []; + for (let iface in sort(order)) { + if (name && iface != name) + continue; + let data = ifaces[iface]; + let dev = { + iface, + ssid: data.ssid, + mac: data.mac, + mode: data.mode, + channel: format_channel(data.wiphy_freq), + freq: format_frequency(data.wiphy_freq), + htmode: data.radio.htmode, + center_freq1: format_channel(data.center_freq1) || 'unknown', + center_freq2: format_channel(data.center_freq2) || 'unknown', + txpower: data.wiphy_tx_power_level / 100, + noise: data.noise, + signal: 0, + bitrate: 0, + encryption: 'unknown', + hwmode: hwmodelist(iface), + phy: 'phy' + data.wiphy, + vaps: 'no', + hw_type: data.hardware.type, + hw_id: data.hardware.id, + power_offset: data.hardware.power_offset || 'none', + channel_offset: data.hardware.channel_offset || 'none', + }; + + let phy = find_phy(data.wiphy); + for (let limit in phy.interface_combinations[0]?.limits) + if (limit.types?.ap && limit.max > 1) + dev.vaps = 'yes'; + + if (data.bss_info) { + if (data.bss_info.wpa_key_mgmt && data.bss_info.wpa_pairwise) + dev.encryption = `${replace(data.bss_info.wpa_key_mgmt, ' ', ' / ')} (${data.bss_info.wpa_pairwise})`; + else if (data.owe_transition_ifname) + dev.encryption = 'none (OWE transition)'; + else + dev.encryption = 'none'; + } + + let stations = assoclist(iface); + for (let k, station in stations) { + dev.signal += station.signal; + dev.bitrate += station.tx.bitrate_raw; + } + dev.signal /= length(data.assoclist) || 1; + dev.bitrate /= length(data.assoclist) || 1; + dev.bitrate = format_rate(dev.bitrate); + dev.quality = dbm2quality(dev.signal); + + if (data.owe_transition_ifname) + dev.owe_transition_ifname = data.owe_transition_ifname; + + push(list, dev); + } + + return list; +}; + +export function htmodelist(name) { + let iface = ifaces[name]; + let phy = board_data.wlan?.['phy' + iface.wiphy]; + if (!phy) + return []; + + return filter(phy.info.bands[uc(iface.radio.band)].modes, (v) => v != 'NOHT'); +}; + +export function txpowerlist(name) { + let iface = ifaces[name]; + let max_power = iface.max_power / 100; + let match = iface.wiphy_tx_power_level / 100; + let list = []; + + for (let power = 0; power <= max_power; power++) { + let txpower = { + dbm: power, + mw: dbm2mw(power), + active: power == match, + }; + push(list, txpower); + } + + return list; +}; + +export function countrylist(dev) { + let iface = ifaces[dev]; + + let list = { + active: iface.country, + countries, + }; + + return list; +}; + +export function scan(dev) { + const rsn_cipher = [ 'NONE', 'WEP-40', 'TKIP', 'WRAP', 'CCMP', 'WEP-104', 'AES-OCB', 'CKIP', 'GCMP', 'GCMP-256', 'CCMP-256' ]; + const ht_chan_offset = [ 'no secondary', 'above', '[reserved]', 'below' ]; + const vht_chan_width = [ '20 or 40 MHz', '80 MHz', '80+80 MHz', '160 MHz' ]; + const ht_chan_width = [ '20 MHz', '40 MHz or higher' ]; + const SCAN_FLAG_AP = (1<<2); + + let params = { + dev, + scan_flags: SCAN_FLAG_AP, + scan_ssids: [ '' ], + }; + + let res = nl80211.request(nl80211.const.NL80211_CMD_TRIGGER_SCAN, 0, params); + if (res === false) { + printf("Unable to trigger scan: " + nl80211.error() + "\n"); + exit(1); + } + + res = nl80211.waitfor([ + nl80211.const.NL80211_CMD_NEW_SCAN_RESULTS, + nl80211.const.NL80211_CMD_SCAN_ABORTED + ], 5000); + + if (!res) { + printf("Netlink error while awaiting scan results: " + nl80211.error() + "\n"); + exit(1); + } else if (res.cmd == nl80211.const.NL80211_CMD_SCAN_ABORTED) { + printf("Scan aborted by kernel\n"); + exit(1); + } + + let scan = nl80211.request(nl80211.const.NL80211_CMD_GET_SCAN, nl80211.const.NLM_F_DUMP, { dev }); + + let cells = []; + for (let k, bss in scan) { + bss = bss.bss; + let cell = { + bssid: uc(bss.bssid), + frequency: format_frequency(bss.frequency), + band: format_band(bss.frequency), + channel: format_channel(bss.frequency), + dbm: bss.signal_mbm / 100, + + }; + + if (bss.capability & (1 << 1)) + cell.mode = 'Ad-Hoc'; + else if (bss.capability & (1 << 0)) + cell.mode = 'Master'; + else + cell.mode = 'Mesh Point'; + + cell.quality = dbm2quality(cell.dbm); + + for (let ie in bss.information_elements) + switch(ie.type) { + case 0: + case 114: + cell.ssid = ie.data; + break; + + case 7: + cell.country = substr(ie.data, 0, 2); + break; + + case 48: + cell.crypto = { + group: rsn_cipher[+ord(ie.data, 5)] ?? '', + pair: [], + key_mgmt: [], + }; + + let offset = 6; + let count = +ord(ie.data, offset); + offset += 2; + + for (let i = 0; i < count; i++) { + let key = rsn_cipher[+ord(ie.data, offset + 3)]; + if (key) + push(cell.crypto.pair, key); + offset += 4; + } + + count = +ord(ie.data, offset); + offset += 2; + + for (let i = 0; i < count; i++) { + let key = format_mgmt_key(ord(ie.data, offset + 3)); + if (key) + push(cell.crypto.key_mgmt, key); + offset += 4; + } + break; + + case 61: + cell.ht = { + primary_channel: ord(ie.data, 0), + secondary_chan_off: ht_chan_offset[ord(ie.data, 1) & 0x3], + chan_width: ht_chan_width[(ord(ie.data, 1) & 0x4) >> 2], + }; + break; + + case 192: + cell.vht = { + chan_width: vht_chan_width[ord(ie.data, 0)], + center_chan_1: ord(ie.data, 1), + center_chan_2: ord(ie.data, 2), + }; + break; + }; + + + + push(cells, cell); + } + + return cells; +}; diff --git a/feeds/qca/iwinfo/files-iwinfo/usr/share/wifi_devices.json b/feeds/qca/iwinfo/files-iwinfo/usr/share/wifi_devices.json new file mode 100644 index 000000000..7e9c63751 --- /dev/null +++ b/feeds/qca/iwinfo/files-iwinfo/usr/share/wifi_devices.json @@ -0,0 +1,258 @@ +{ + "pci": [ + [ "0x0777", "0x11ac", "0x0777", "0xe7f9", 0, 0, "Ubiquiti", "LiteBeam, 5AC" ], + [ "0xffff", "0xffff", "0xffff", "0xb102", 0, 0, "Ubiquiti", "PowerStation2, (18V)" ], + [ "0xffff", "0xffff", "0xffff", "0xb202", 0, 0, "Ubiquiti", "PowerStation2, (16D)" ], + [ "0xffff", "0xffff", "0xffff", "0xb302", 0, 0, "Ubiquiti", "PowerStation2, (EXT)" ], + [ "0xffff", "0xffff", "0xffff", "0xb105", 0, 0, "Ubiquiti", "PowerStation5, (22V)" ], + [ "0xffff", "0xffff", "0xffff", "0xb305", 0, 0, "Ubiquiti", "PowerStation5, (EXT)" ], + [ "0xffff", "0xffff", "0xffff", "0xc302", 0, 0, "Ubiquiti", "PicoStation2" ], + [ "0xffff", "0xffff", "0xffff", "0xc3a2", 10, 0, "Ubiquiti", "PicoStation2, HP" ], + [ "0xffff", "0xffff", "0xffff", "0xa105", 0, 0, "Ubiquiti", "WispStation5" ], + [ "0xffff", "0xffff", "0xffff", "0xa002", 10, 0, "Ubiquiti", "LiteStation2" ], + [ "0xffff", "0xffff", "0xffff", "0xa005", 5, 0, "Ubiquiti", "LiteStation5" ], + [ "0xffff", "0xffff", "0xffff", "0xc002", 10, 0, "Ubiquiti", "NanoStation2" ], + [ "0xffff", "0xffff", "0xffff", "0xc005", 5, 0, "Ubiquiti", "NanoStation5" ], + [ "0xffff", "0xffff", "0xffff", "0xc102", 10, 0, "Ubiquiti", "NanoStation, Loco2" ], + [ "0xffff", "0xffff", "0xffff", "0xc105", 5, 0, "Ubiquiti", "NanoStation, Loco5" ], + [ "0xffff", "0xffff", "0xffff", "0xc202", 10, 0, "Ubiquiti", "Bullet2" ], + [ "0xffff", "0xffff", "0xffff", "0xc205", 5, 0, "Ubiquiti", "Bullet5" ], + [ "0x168c", "0xffff", "0x0777", "0xe002", 6, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe003", 3, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe005", 5, 0, "Ubiquiti", "NanoStation, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe006", 5, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe009", 6, 0, "Ubiquiti", "NanoStation, Loco, M9" ], + [ "0x168c", "0xffff", "0x0777", "0xe012", 10, 0, "Ubiquiti", "NanoStation, M2" ], + [ "0x168c", "0xffff", "0x0777", "0xe035", 3, 0, "Ubiquiti", "NanoStation, M3" ], + [ "0x168c", "0xffff", "0x0777", "0xe0a2", 2, 0, "Ubiquiti", "NanoStation, Loco, M2" ], + [ "0x168c", "0xffff", "0x0777", "0xe0a5", 1, 0, "Ubiquiti", "NanoStation, Loco, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe102", 6, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe105", 5, 0, "Ubiquiti", "Rocket, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe112", 10, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe115", 3, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe1a3", 3, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe1a5", 5, 0, "Ubiquiti", "PowerBridge, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe1b2", 10, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe1b3", 3, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe1b5", 5, 0, "Ubiquiti", "Rocket, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe1b6", 5, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe1b9", 6, 0, "Ubiquiti", "Rocket, M9" ], + [ "0x168c", "0xffff", "0x0777", "0xe1c2", 10, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe1c3", 3, 0, "Ubiquiti", "Rocket, M3" ], + [ "0x168c", "0xffff", "0x0777", "0xe1c5", 5, 0, "Ubiquiti", "Rocket, M5, GPS" ], + [ "0x168c", "0xffff", "0x0777", "0xe1c5", 5, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe1d2", 10, 0, "Ubiquiti", "Rocket, M2, Titanium" ], + [ "0x168c", "0xffff", "0x0777", "0xe1d3", 3, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe1d5", 5, 0, "Ubiquiti", "airOS, XM/XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe1d9", 6, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe1e3", 3, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe1e5", 5, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe202", 12, 0, "Ubiquiti", "Bullet, M2" ], + [ "0x168c", "0xffff", "0x0777", "0xe205", 6, 0, "Ubiquiti", "Bullet, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe212", 1, 0, "Ubiquiti", "AirGrid, M2" ], + [ "0x168c", "0xffff", "0x0777", "0xe215", 1, 0, "Ubiquiti", "AirGrid, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe232", 2, 0, "Ubiquiti", "NanoBridge, M2" ], + [ "0x168c", "0xffff", "0x0777", "0xe233", 3, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe235", 1, 0, "Ubiquiti", "NanoBridge, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe239", 6, 0, "Ubiquiti", "NanoBridge, M9" ], + [ "0x168c", "0xffff", "0x0777", "0xe242", 9, 0, "Ubiquiti", "AirGrid, M2, HP" ], + [ "0x168c", "0xffff", "0x0777", "0xe243", 3, 0, "Ubiquiti", "NanoBridge, M3" ], + [ "0x168c", "0xffff", "0x0777", "0xe245", 6, 0, "Ubiquiti", "AirGrid, M5, HP" ], + [ "0x168c", "0xffff", "0x0777", "0xe252", 9, 0, "Ubiquiti", "AirGrid, M2, HP" ], + [ "0x168c", "0xffff", "0x0777", "0xe255", 6, 0, "Ubiquiti", "AirGrid, M5, HP" ], + [ "0x168c", "0xffff", "0x0777", "0xe2a3", 3, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe2a5", 5, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe2b2", 10, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe2b5", 1, 0, "Ubiquiti", "NanoBridge, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe2b9", 6, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe2c2", 10, 0, "Ubiquiti", "NanoBeam, M2, Int" ], + [ "0x168c", "0xffff", "0x0777", "0xe2c3", 6, 0, "Ubiquiti", "Bullet, M2, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe2c4", 6, 0, "Ubiquiti", "airOS, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe2d2", 12, 0, "Ubiquiti", "Bullet, M2, Titanium, HP" ], + [ "0x168c", "0xffff", "0x0777", "0xe2d4", 6, 0, "Ubiquiti", "airOS, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe2d5", 6, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe2e5", 4, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe302", 12, 0, "Ubiquiti", "PicoStation, M2"], + [ "0x168c", "0xffff", "0x0777", "0xe305", 6, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe345", 6, 0, "Ubiquiti", "WispStation, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe3a5", 5, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe3b5", 6, 0, "Ubiquiti", "airOS, XM/XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe3e5", 4, 0, "Ubiquiti", "PowerBeam, M5, 300" ], + [ "0x168c", "0xffff", "0x0777", "0xe402", 10, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe405", 1, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe4a2", 1, 0, "Ubiquiti", "AirRouter" ], + [ "0x168c", "0xffff", "0x0777", "0xe4a5", 1, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe4b2", 9, 0, "Ubiquiti", "AirRouter, HP" ], + [ "0x168c", "0xffff", "0x0777", "0xe4d5", 5, 0, "Ubiquiti", "Rocket, M5, Titanium" ], + [ "0x168c", "0xffff", "0x0777", "0xe4e5", 4, 0, "Ubiquiti", "PowerBeam, M5, 400" ], + [ "0x168c", "0xffff", "0x0777", "0xe5e5", 4, 0, "Ubiquiti", "airOS, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe6a2", 1, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe6b2", 1, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe6b5", 5, 0, "Ubiquiti", "Rocket, M5, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe6c2", 6, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe6e5", 4, 0, "Ubiquiti", "PowerBeam, M5, 400, ISO" ], + [ "0x168c", "0xffff", "0x0777", "0xe7f8", 2, 0, "Ubiquiti", "airOS, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe805", 5, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0xffff", "0x0777", "0xe812", 6, 0, "Ubiquiti", "NanoBeam, M2, 13" ], + [ "0x168c", "0xffff", "0x0777", "0xe815", 4, 0, "Ubiquiti", "NanoBeam, M5, 16" ], + [ "0x168c", "0xffff", "0x0777", "0xe825", 4, 0, "Ubiquiti", "NanoBeam, M5, 19" ], + [ "0x168c", "0xffff", "0x0777", "0xe835", 6, 0, "Ubiquiti", "AirGrid, M5, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe845", 1, 0, "Ubiquiti", "NanoStation, Loco, M5, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe855", 5, 0, "Ubiquiti", "NanoStation, M5, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe865", 6, 0, "Ubiquiti", "LiteBeam, M5" ], + [ "0x168c", "0xffff", "0x0777", "0xe866", 6, 0, "Ubiquiti", "NanoStation, M2, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe867", 2, 0, "Ubiquiti", "NanoStation, Loco, M2, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe868", 7, 0, "Ubiquiti", "Rocket, M2, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe869", 2, 0, "Ubiquiti", "airOS, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe875", 4, 0, "Ubiquiti", "airOS, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe879", 2, 0, "Ubiquiti", "airOS, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe885", 4, 0, "Ubiquiti", "PowerBeam, M5, 620, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe895", 4, 0, "Ubiquiti", "airOS, XW" ], + [ "0x168c", "0xffff", "0x0777", "0xe8a5", 1, 0, "Ubiquiti", "NanoStation, Loco, M5"], + [ "0x168c", "0xffff", "0x0777", "0xe8b5", 5, 0, "Ubiquiti", "airOS, XM" ], + [ "0x168c", "0x001b", "0x0777", "0x3002", 10, 0, "Ubiquiti", "XR2" ], + [ "0x168c", "0x001b", "0x7777", "0x3002", 10, 0, "Ubiquiti", "XR2" ], + [ "0x168c", "0x001b", "0x0777", "0x3b02", 10, 0, "Ubiquiti", "XR2.3" ], + [ "0x168c", "0x001b", "0x0777", "0x3c02", 10, 0, "Ubiquiti", "XR2.6" ], + [ "0x168c", "0x001b", "0x0777", "0x3b03", 10, 0, "Ubiquiti", "XR3-2.8" ], + [ "0x168c", "0x001b", "0x0777", "0x3c03", 10, 0, "Ubiquiti", "XR3-3.6" ], + [ "0x168c", "0x001b", "0x0777", "0x3003", 10, 0, "Ubiquiti", "XR3" ], + [ "0x168c", "0x001b", "0x0777", "0x3004", 10, 0, "Ubiquiti", "XR4" ], + [ "0x168c", "0x001b", "0x0777", "0x3005", 10, 0, "Ubiquiti", "XR5" ], + [ "0x168c", "0x001b", "0x7777", "0x3005", 10, 0, "Ubiquiti", "XR5" ], + [ "0x168c", "0x001b", "0x0777", "0x3007", 10, 0, "Ubiquiti", "XR7" ], + [ "0x168c", "0x001b", "0x0777", "0x3009", 10, -1520, "Ubiquiti", "XR9" ], + [ "0x168c", "0x001b", "0x168c", "0x2063", 0, 0, "Atheros", "AR5413" ], + [ "0x168c", "0x0013", "0x168c", "0x1042", 1, 0, "Ubiquiti", "SRC" ], + [ "0x168c", "0x0013", "0x0777", "0x2041", 10, 0, "Ubiquiti", "SR2" ], + [ "0x168c", "0x0013", "0x0777", "0x2004", 6, 0, "Ubiquiti", "SR4" ], + [ "0x168c", "0x0013", "0x7777", "0x2004", 6, 0, "Ubiquiti", "SR4" ], + [ "0x168c", "0x0013", "0x0777", "0x1004", 6, 0, "Ubiquiti", "SR4C" ], + [ "0x168c", "0x0013", "0x7777", "0x1004", 6, 0, "Ubiquiti", "SR4C" ], + [ "0x168c", "0x0013", "0x168c", "0x2042", 7, 0, "Ubiquiti", "SR5" ], + [ "0x168c", "0x0013", "0x7777", "0x2009", 12, -1500, "Ubiquiti", "SR9" ], + [ "0x168c", "0x0027", "0x168c", "0x2082", 7, 0, "Ubiquiti", "SR71A" ], + [ "0x168c", "0x0027", "0x0777", "0x4082", 7, 0, "Ubiquiti", "SR71" ], + [ "0x168c", "0x0029", "0x0777", "0x4005", 7, 0, "Ubiquiti", "SR71-15" ], + [ "0x168c", "0x002a", "0x0777", "0xe302", 12, 0, "Ubiquiti", "PicoStation, M2" ], + [ "0x168c", "0x002a", "0x0777", "0xe012", 12, 0, "Ubiquiti", "NanoStation, M2" ], + [ "0x168c", "0x002a", "0x0777", "0xe005", 5, 0, "Ubiquiti", "NanoStation, M5" ], + [ "0x168c", "0x002a", "0x0777", "0xe202", 12, 0, "Ubiquiti", "Bullet, M2" ], + [ "0x168c", "0x002a", "0x0777", "0xe805", 5, 0, "Ubiquiti", "Bullet, M5" ], + [ "0x168c", "0x002a", "0x0777", "0xe345", 0, 0, "Ubiquiti", "WispStation, M5" ], + [ "0x168c", "0x0029", "0x168c", "0xa094", 0, 0, "Atheros", "AR9220" ], + [ "0x168c", "0x0029", "0x168c", "0xa095", 0, 0, "Atheros", "AR9223" ], + [ "0x168c", "0x002a", "0x168c", "0xa093", 0, 0, "Atheros", "AR9280" ], + [ "0x168c", "0x002b", "0x168c", "0xa091", 0, 0, "Atheros", "AR9285" ], + [ "0x168c", "0x002d", "0x168c", "0x209a", 0, 0, "Atheros", "AR9287" ], + [ "0x168c", "0x002e", "0x1a3b", "0x1121", 0, 0, "Atheros", "AR9287" ], + [ "0x168c", "0x002e", "0x0777", "0xe0a2", 8, 0, "Ubiquiti", "NanoStation, Loco, M2, (XM)" ], + [ "0x168c", "0x002e", "0x168c", "0x30a4", 0, 0, "Atheros", "AR9287" ], + [ "0x168c", "0x002e", "0x168c", "0xa199", 0, 0, "Atheros", "AR9287" ], + [ "0x168c", "0x0030", "0x168c", "0x3112", 0, 0, "Atheros", "AR9380" ], + [ "0x168c", "0x0030", "0x168c", "0x3114", 0, 0, "Atheros", "AR9390" ], + [ "0x168c", "0x0033", "0x168c", "0xa120", 0, 0, "Atheros", "AR9580" ], + [ "0x168c", "0x0033", "0x168c", "0xa136", 0, 0, "Atheros", "AR9580" ], + [ "0x168c", "0x0033", "0x168c", "0x3123", 0, 0, "Atheros", "AR9590" ], + [ "0x168c", "0x0033", "0x19b6", "0xd014", 0, 0, "MikroTik", "R11e-5HnD" ], + [ "0x168c", "0x0033", "0x19b6", "0xd057", 0, 0, "MikroTik", "R11e-5HnDr2" ], + [ "0x168c", "0x0033", "0x19b6", "0xd016", 0, 0, "MikroTik", "R11e-2HPnD" ], + [ "0x168c", "0x0034", "0x17aa", "0x3214", 0, 0, "Atheros", "AR9462" ], + [ "0x168c", "0x003c", "0x0000", "0x0000", 0, 0, "Qualcomm, Atheros", "QCA9880" ], + [ "0x168c", "0x003c", "0x168c", "0x3223", 0, 0, "Qualcomm, Atheros", "QCA9880" ], + [ "0x168c", "0x003c", "0x1a56", "0x1420", 0, 0, "Qualcomm, Atheros", "QCA9862" ], + [ "0x168c", "0x003c", "0x19b6", "0xd03c", 0, 0, "Mikrotik", "R11e-5HacT" ], + [ "0x168c", "0x003c", "0x19b6", "0xd075", 0, 0, "Mikrotik", "R11e-5HacD" ], + [ "0x168c", "0x003e", "0x168c", "0x3361", 0, 0, "Qualcomm, Atheros", "QCA6174" ], + [ "0x168c", "0x0040", "0x168c", "0x0002", 0, 0, "Qualcomm, Atheros", "QCA9990" ], + [ "0x168c", "0x0046", "0x168c", "0xcafe", 0, 0, "Qualcomm, Atheros", "QCA9984" ], + [ "0x168c", "0x0050", "0x0000", "0x0000", 0, 0, "Qualcomm, Atheros", "QCA9887" ], + [ "0x168c", "0x0056", "0x0000", "0x0000", 0, 0, "Qualcomm, Atheros", "QCA9886" ], + [ "0x17cb", "0x1104", "0x17cb", "0x1104", 0, 0, "Qualcomm, Atheros", "QCN6024/9024/9074" ], + [ "0x1814", "0x3051", "0x1814", "0x0007", 0, 0, "Ralink", "Rt3051" ], + [ "0x1814", "0x3052", "0x1814", "0x0008", 0, 0, "Ralink", "Rt3052" ], + [ "0x1814", "0x3350", "0x1814", "0x000b", 0, 0, "Ralink", "Rt3350" ], + [ "0x1814", "0x3662", "0x1814", "0x000d", 0, 0, "Ralink", "Rt3662" ], + [ "0x11ab", "0x2a55", "0x11ab", "0x0000", 0, 0, "Marvell", "88W8864" ], + [ "0x02df", "0x9135", "0x0000", "0x0000", 0, 0, "Marvell", "88W8887" ], + [ "0x11ab", "0x2b40", "0x11ab", "0x0000", 0, 0, "Marvell", "88W8964" ], + [ "0x02df", "0x9141", "0x0000", "0x0000", 0, 0, "Marvell", "88W8997" ], + [ "0x14c3", "0x0608", "0x14c3", "0x0608", 0, 0, "AMD", "RZ608" ], + [ "0x14c3", "0x7603", "0x14c3", "0x7603", 0, 0, "MediaTek", "MT7603E" ], + [ "0x14c3", "0x7610", "0x14c3", "0x7610", 0, 0, "MediaTek", "MT7610E" ], + [ "0x14c3", "0x7612", "0x14c3", "0x7612", 0, 0, "MediaTek", "MT7612E" ], + [ "0x14c3", "0x7663", "0x14c3", "0x7663", 0, 0, "MediaTek", "MT7613BE" ], + [ "0x14c3", "0x7615", "0x7615", "0x14c3", 0, 0, "MediaTek", "MT7615E" ], + [ "0x14c3", "0x7628", "0x14c3", "0x0004", 0, 0, "MediaTek", "MT76x8" ], + [ "0x14c3", "0x7650", "0x14c3", "0x7650", 0, 0, "MediaTek", "MT7610E" ], + [ "0x14c3", "0x7662", "0x14c3", "0x7662", 0, 0, "MediaTek", "MT76x2E" ], + [ "0x14c3", "0x7915", "0x14c3", "0x7915", 0, 0, "MediaTek", "MT7915E" ], + [ "0x14c3", "0x7906", "0x14c3", "0x7906", 0, 0, "MediaTek", "MT7916AN" ], + [ "0x14c3", "0x7990", "0x14C3", "0x6639", 0, 0, "MediaTek", "MT7996E" ], + [ "0x14e4", "0xaa52", "0x14e4", "0xaa52", 0, 0, "Broadcom", "BCM43602" ], + [ "0x02d0", "0xa9a6", "0x0000", "0x0000", 0, 0, "Cypress", "CYW43455" ], + [ "0x02d0", "0x4345", "0x0000", "0x0000", 0, 0, "Cypress", "CYW43455" ], + [ "0x1ae9", "0x0310", "0x1ae9", "0x0000", 0, 0, "Wilocity", "Wil6210" ], + [ "0x0000", "0x0000", "0x148f", "0x7601", 0, 0, "MediaTek", "MT7601U" ], + [ "0x0000", "0x0000", "0x0e8d", "0x7961", 0, 0, "MediaTek", "MT7921AU" ], + [ "0x0000", "0x0000", "0x0b05", "0x1833", 0, 0, "ASUS", "USB-AC54" ], + [ "0x0000", "0x0000", "0x0b05", "0x17eb", 0, 0, "ASUS", "USB-AC55" ], + [ "0x0000", "0x0000", "0x0b05", "0x180b", 0, 0, "ASUS", "USB-N53, B1" ], + [ "0x0000", "0x0000", "0x0e8d", "0x7612", 0, 0, "Aukey", "USBAC1200" ], + [ "0x0000", "0x0000", "0x057c", "0x8503", 0, 0, "AVM", "FRITZ!WLAN, AC860" ], + [ "0x0000", "0x0000", "0x7392", "0xb711", 0, 0, "Edimax", "EW-7722UAC" ], + [ "0x0000", "0x0000", "0x0e8d", "0x7632", 0, 0, "High, Cloud", "HC-M7662BU1" ], + [ "0x0000", "0x0000", "0x2c4e", "0x0103", 0, 0, "Mercury", "UD13" ], + [ "0x0000", "0x0000", "0x0846", "0x9053", 0, 0, "Netgear", "A6210" ], + [ "0x0000", "0x0000", "0x045e", "0x02e6", 0, 0, "Microsoft", "XBox, One, Wireless, Adapter" ], + [ "0x0000", "0x0000", "0x045e", "0x02fe", 0, 0, "Microsoft", "XBox, One, Wireless, Adapter" ], + [ "0x0000", "0x0000", "0x148f", "0x7610", 0, 0, "MediaTek", "MT7610U" ], + [ "0x0000", "0x0000", "0x13b1", "0x003e", 0, 0, "Linksys", "AE6000" ], + [ "0x0000", "0x0000", "0x0e8d", "0x7610", 0, 0, "Sabrent", "NTWLAC" ], + [ "0x0000", "0x0000", "0x7392", "0xa711", 0, 0, "Edimax", "7711MAC" ], + [ "0x0000", "0x0000", "0x148f", "0x761a", 0, 0, "TP-Link", "TL-WDN5200" ], + [ "0x0000", "0x0000", "0x0b05", "0x17d1", 0, 0, "ASUS", "USB-AC51" ], + [ "0x0000", "0x0000", "0x0b05", "0x17db", 0, 0, "ASUS", "USB-AC50" ], + [ "0x0000", "0x0000", "0x0df6", "0x0075", 0, 0, "Sitecom", "WLA-3100" ], + [ "0x0000", "0x0000", "0x2019", "0xab31", 0, 0, "Planex", "GW-450D" ], + [ "0x0000", "0x0000", "0x2001", "0x3d02", 0, 0, "D-Link", "DWA-171, rev, B1" ], + [ "0x0000", "0x0000", "0x0586", "0x3425", 0, 0, "Zyxel", "NWD6505" ], + [ "0x0000", "0x0000", "0x07b8", "0x7610", 0, 0, "AboCom", "AU7212" ], + [ "0x0000", "0x0000", "0x04bb", "0x0951", 0, 0, "I-O, DATA", "WN-AC433UK" ], + [ "0x0000", "0x0000", "0x057c", "0x8502", 0, 0, "AVM", "FRITZ!WLAN, AC430" ], + [ "0x0000", "0x0000", "0x293c", "0x5702", 0, 0, "Comcast", "Xfinity, KXW02AAA" ], + [ "0x0000", "0x0000", "0x20f4", "0x806b", 0, 0, "TRENDnet", "TEW-806UBH" ], + [ "0x0000", "0x0000", "0x7392", "0xc711", 0, 0, "Devolo", "WiFi, Stick, ac" ], + [ "0x0000", "0x0000", "0x0df6", "0x0079", 0, 0, "Sitecom", "WL-356" ], + [ "0x0000", "0x0000", "0x2357", "0x0123", 0, 0, "TP-Link", "T2UHP, US, v1" ], + [ "0x0000", "0x0000", "0x2357", "0x010b", 0, 0, "TP-Link", "T2UHP, UN, v1" ], + [ "0x0000", "0x0000", "0x2357", "0x0105", 0, 0, "TP-Link", "Archer, T1U" ], + [ "0x0000", "0x0000", "0x0e8d", "0x7630", 0, 0, "MediaTek", "MT7630U" ], + [ "0x0000", "0x0000", "0x0e8d", "0x7650", 0, 0, "MediaTek", "MT7650U" ], + [ "0x0000", "0x0000", "0x0e8d", "0x7663", 0, 0, "MediaTek", "MT7663U" ], + [ "0x0000", "0x0000", "0x043e", "0x310c", 0, 0, "LG", "LGSBWAC02" ], + [ "0x0000", "0x0000", "0x0bda", "0x8176", 0, 0, "Realtek", "RTL8188CU" ], + [ "0x0000", "0x0000", "0x0bda", "0xf179", 0, 0, "Realtek", "RTL8188FTV" ] + ], + "compatible": { + "qca,ar9130-wmac": [ "Atheros", "AR9130" ], + "qca,ar9330-wmac": [ "Atheros", "AR9330" ], + "qca,ar9340-wmac": [ "Atheros", "AR9340" ], + "qca,qca9530-wmac": [ "Qualcomm Atheros", "QCA9530" ], + "qca,qca9550-wmac": [ "Qualcomm Atheros", "QCA9550" ], + "qca,qca9560-wmac": [ "Qualcomm Atheros", "QCA9560" ], + "qcom,ipq4019-wifi": [ "Qualcomm Atheros", "IPQ4019" ], + "qcom,ipq6018-wifi": [ "Qualcomm Atheros", "IPQ6018" ], + "qcom,ipq8074-wifi": [ "Qualcomm Atheros", "IPQ8074" ], + "mediatek,mt7622-wmac": [ "MediaTek", "MT7622" ], + "mediatek,mt7628-wmac": [ "MediaTek", "MT7628" ], + "mediatek,mt7981-wmac": [ "MediaTek", "MT7981" ], + "mediatek,mt7986-wmac": [ "MediaTek", "MT7986" ], + "ralink,rt2880-wmac": [ "Ralink", "Rt2880" ], + "ralink,rt3050-wmac": [ "Ralink", "Rt3050" ], + "ralink,rt3352-wmac": [ "Ralink", "Rt3352" ], + "ralink,rt3883-wmac": [ "Ralink", "Rt3883" ], + "ralink,rt5350-wmac": [ "Ralink", "Rt5350" ], + "ralink,rt7620-wmac": [ "MediaTek", "MT7620" ] + } +} diff --git a/feeds/qca/iwinfo/patches/100-6g.patch b/feeds/qca/iwinfo/patches/100-6g.patch new file mode 100644 index 000000000..45472e8cc --- /dev/null +++ b/feeds/qca/iwinfo/patches/100-6g.patch @@ -0,0 +1,13 @@ +Index: libiwinfo-2021-06-09-c0414642/iwinfo_nl80211.c +=================================================================== +--- libiwinfo-2021-06-09-c0414642.orig/iwinfo_nl80211.c ++++ libiwinfo-2021-06-09-c0414642/iwinfo_nl80211.c +@@ -642,6 +642,8 @@ static int nl80211_freq2channel(int freq + return (freq - 4000) / 5; + else if(freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) + return (freq - 56160) / 2160; ++ else if (freq >= 5955 && freq <= 7115) ++ return (freq - 5950) / 5; + else + return (freq - 5000) / 5; + } diff --git a/patches/0084-iwinfo-add-ucode-based-version-for-wifi-7.patch b/patches/0084-iwinfo-add-ucode-based-version-for-wifi-7.patch deleted file mode 100644 index 94becc420..000000000 --- a/patches/0084-iwinfo-add-ucode-based-version-for-wifi-7.patch +++ /dev/null @@ -1,1337 +0,0 @@ -From 1c37b09f50c96890335d56ce9b0837284fd2736c Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 10 Jan 2025 09:44:47 +0100 -Subject: [PATCH] iwinfo: add ucode based version for wifi-7 - -Signed-off-by: John Crispin ---- - package/network/utils/iwinfo/Makefile | 8 + - .../utils/iwinfo/files-iwinfo/usr/bin/iwinfo | 156 +++++ - .../files-iwinfo/usr/share/iso3166.json | 249 +++++++ - .../files-iwinfo/usr/share/ucode/iwinfo.uc | 606 ++++++++++++++++++ - .../files-iwinfo/usr/share/wifi_devices.json | 258 ++++++++ - 5 files changed, 1277 insertions(+) - create mode 100755 package/network/utils/iwinfo/files-iwinfo/usr/bin/iwinfo - create mode 100644 package/network/utils/iwinfo/files-iwinfo/usr/share/iso3166.json - create mode 100644 package/network/utils/iwinfo/files-iwinfo/usr/share/ucode/iwinfo.uc - create mode 100644 package/network/utils/iwinfo/files-iwinfo/usr/share/wifi_devices.json - -diff --git a/package/network/utils/iwinfo/Makefile b/package/network/utils/iwinfo/Makefile -index e5add395ff..ba453f1b42 100644 ---- a/package/network/utils/iwinfo/Makefile -+++ b/package/network/utils/iwinfo/Makefile -@@ -108,10 +108,18 @@ define Package/libiwinfo-data/install - $(INSTALL_DATA) $(PKG_BUILD_DIR)/devices.txt $(1)/usr/share/libiwinfo/devices.txt - endef - -+ifeq ($(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y) -+define Package/iwinfo/install -+ $(CP) ./files-iwinfo/* $(1) -+ $(INSTALL_DIR) $(1)/usr/bin -+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo $(1)/usr/share/iwinfo -+endef -+else - define Package/iwinfo/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo $(1)/usr/bin/iwinfo - endef -+endif - - $(eval $(call BuildPackage,libiwinfo)) - $(eval $(call BuildPackage,libiwinfo-lua)) -diff --git a/package/network/utils/iwinfo/files-iwinfo/usr/bin/iwinfo b/package/network/utils/iwinfo/files-iwinfo/usr/bin/iwinfo -new file mode 100755 -index 0000000000..01285eb385 ---- /dev/null -+++ b/package/network/utils/iwinfo/files-iwinfo/usr/bin/iwinfo -@@ -0,0 +1,156 @@ -+#!/usr/bin/ucode -+ -+'use strict'; -+ -+import * as iwinfo from 'iwinfo'; -+ -+function print_assoclist(stations) { -+ for (let mac, station in stations) { -+ printf(`${station.mac} ${station.signal} dBm / ${station.noise} dBm (SNR ${station.snr}) ${station.inactive_time} ms ago\n`); -+ for (let k in [ 'rx', 'tx' ]) { -+ let bitrate = station[k]; -+ let flags = join(', ', bitrate.flags); -+ -+ printf(`\t${uc(k)}: ${bitrate.bitrate} MBit/s`); -+ if (length(bitrate.flags)) -+ printf(', %s', flags); -+ printf('%10d Pkts.\n', bitrate.packets); -+ } -+ printf(`\texpected throughput: ${station.expected_throughput}\n\n`); -+ } -+} -+ -+function print_countrylist(list) { -+ for (let k, v in list.countries) -+ printf(`${k == list.active ? '*' : ' '} ${k} "${v}"\n`); -+} -+ -+function print_freqlist(channels) { -+ for (let channel in channels) { -+ printf(`${channel.active ? '*' : ' '} ${channel.freq} GHz (Band: ${channel.band} GHz, Channel ${channel.channel})`); -+ if (length(channel.flags)) -+ printf(` [${join(', ', channel.flags)}]`); -+ printf('\n'); -+ } -+} -+ -+function print_htmodelist(htmode) { -+ printf('%s\n', join(' ', htmode)); -+} -+ -+function print_info(list) { -+ let padding = ' '; -+ -+ for (let bss in list) { -+ printf(`${bss.iface} ESSID: "${bss.ssid}"\n`); -+ printf(`${padding}Access Point: ${bss.mac}\n`); -+ printf(`${padding}Mode: ${bss.mode} Channel: ${bss.channel} (${bss.freq} GHz) HT Mode: ${bss.htmode}\n`); -+ printf(`${padding}Center Channel 1: ${bss.center_freq1} 2: ${bss.center_freq2}\n`); -+ printf(`${padding}Tx-Power: ${bss.txpower} dBm Link Quality: ${bss.quality}/70\n`); -+ printf(`${padding}Signal: ${bss.signal} Noise: ${bss.noise}\n`); -+ printf(`${padding}Bit Rate: ${bss.bitrate ?? 'unknown'} MBit/s\n`); -+ printf(`${padding}Encryption: ${bss.encryption}\n`); -+ printf(`${padding}Type: nl80211 HW Mode(s): 802.11${bss.hwmode}\n`); -+ printf(`${padding}Hardware: ${bss.hw_type} [${bss.hw_id}]\n`); -+ printf(`${padding}TX power offset: ${bss.power_offset}\n`); -+ printf(`${padding}Channel offset: ${bss.channel_offset}\n`); -+ printf(`${padding}Supports VAPs: ${bss.vaps} PHY name: ${bss.phy}\n`); -+ if (bss.owe_transition_ifname) -+ printf(`${padding}OWE partner: ${bss.owe_transition_ifname}\n`); -+ printf('\n'); -+ } -+ return 0; -+} -+ -+function print_scan(cells) { -+ let idx = 1; -+ -+ for (let cell in cells) { -+ printf('Cell %02d - Address: %s\n', idx++, cell.bssid); -+ printf('\t Mode: %s Frequency: %s GHz Band: %s GHz Channel: %d\n', cell.mode, cell.frequency, cell.band, cell.channel); -+ printf('\t Signal: %d dBm Quality: %2d/70\n', cell.dbm, cell.quality); -+ -+ if (!length(cell.crypto.key_mgmt)) -+ printf('\t Encryption: NONE\n'); -+ else -+ printf('\t Encryption: %s (%s)\n', join(' / ', cell.crypto.key_mgmt), join(' / ', cell.crypto.pair)); -+ -+ if (cell.ht) { -+ printf('\t HT Operation:\n'); -+ printf('\t\tPrimary Channel: %d\n', cell.ht.primary_channel); -+ printf('\t\tSecondary Channel Offset: %s\n', cell.ht.secondary_chan_off); -+ printf('\t\tChannel Width: %s\n', cell.ht.chan_width); -+ } -+ -+ if (cell.vht) { -+ printf('\t VHT Operation:\n'); -+ printf('\t\tCenter Frequency 1: %d\n', cell.vht.center_chan_1); -+ printf('\t\tCenter Frequency 2: %s\n', cell.vht.center_chan_2); -+ printf('\t\tChannel Width: %s\n', cell.vht.chan_width); -+ } -+ -+ printf('\n'); -+ } -+} -+ -+function print_txpowerlist(list) { -+ for (let power in list) -+ printf('%s %2d dbm (%4d mW)\n', power.active ? '*' : ' ', power.dbm, power.mw); -+} -+ -+let pretty = true; -+if (ARGV[0] == '-j') { -+ pretty = false; -+ shift(ARGV); -+} -+ -+if (!length(ARGV)) { -+ let info = iwinfo.info(); -+ if (pretty) -+ print_info(info); -+ else -+ printf('%.J\n', info); -+ return 0; -+} -+ -+const commands = { -+ assoclist: [ iwinfo.assoclist, print_assoclist ], -+ countrylist: [ iwinfo.countrylist, print_countrylist ], -+ freqlist: [ iwinfo.freqlist, print_freqlist ], -+ htmodelist: [ iwinfo.htmodelist, print_htmodelist ], -+ info: [ iwinfo.info, print_info ], -+ scan: [ iwinfo.scan, print_scan ], -+ txpowerlist: [ iwinfo.txpowerlist, print_txpowerlist ], -+}; -+ -+if (length(ARGV) == 2 && iwinfo.ifaces[ARGV[0]]) -+ for (let cmd, cb in commands) -+ if (substr(cmd, 0, length(ARGV[1])) == ARGV[1]) { -+ let ret = cb[0](ARGV[0]); -+ -+ if (pretty) -+ cb[1](ret); -+ else -+ printf('%.J\n', ret); -+ return 0; -+ } -+ -+switch(ARGV[0]) { -+case 'phy': -+ printf('%.J\n', iwinfo.phys); -+ return 0; -+ -+case 'iface': -+ printf('%.J\n', iwinfo.ifaces); -+ return 0; -+} -+ -+printf('Usage:\n' + -+ '\tiwinfo info\n' + -+ '\tiwinfo scan\n' + -+ '\tiwinfo txpowerlist\n' + -+ '\tiwinfo freqlist\n' + -+ '\tiwinfo assoclist\n' + -+ '\tiwinfo countrylist\n' + -+ '\tiwinfo htmodelist\n' + -+ '\tiwinfo phyname
\n'); -diff --git a/package/network/utils/iwinfo/files-iwinfo/usr/share/iso3166.json b/package/network/utils/iwinfo/files-iwinfo/usr/share/iso3166.json -new file mode 100644 -index 0000000000..ecd0b65383 ---- /dev/null -+++ b/package/network/utils/iwinfo/files-iwinfo/usr/share/iso3166.json -@@ -0,0 +1,249 @@ -+{ -+ "00": "World", -+ "AD": "Andorra", -+ "AE": "United Arab Emirates", -+ "AF": "Afghanistan", -+ "AG": "Antigua and Barbuda", -+ "AI": "Anguilla", -+ "AL": "Albania", -+ "AM": "Armenia", -+ "AN": "Netherlands Antilles", -+ "AO": "Angola", -+ "AQ": "Antarctica", -+ "AR": "Argentina", -+ "AS": "American Samoa", -+ "AT": "Austria", -+ "AU": "Australia", -+ "AW": "Aruba", -+ "AX": "Aland Islands", -+ "AZ": "Azerbaijan", -+ "BA": "Bosnia and Herzegovina", -+ "BB": "Barbados", -+ "BD": "Bangladesh", -+ "BE": "Belgium", -+ "BF": "Burkina Faso", -+ "BG": "Bulgaria", -+ "BH": "Bahrain", -+ "BI": "Burundi", -+ "BJ": "Benin", -+ "BL": "Saint Barthelemy", -+ "BM": "Bermuda", -+ "BN": "Brunei Darussalam", -+ "BO": "Bolivia", -+ "BR": "Brazil", -+ "BS": "Bahamas", -+ "BT": "Bhutan", -+ "BV": "Bouvet Island", -+ "BW": "Botswana", -+ "BY": "Belarus", -+ "BZ": "Belize", -+ "CA": "Canada", -+ "CC": "Cocos (Keeling) Islands", -+ "CD": "Congo", -+ "CF": "Central African Republic", -+ "CG": "Congo", -+ "CH": "Switzerland", -+ "CI": "Cote d'Ivoire", -+ "CK": "Cook Islands", -+ "CL": "Chile", -+ "CM": "Cameroon", -+ "CN": "China", -+ "CO": "Colombia", -+ "CR": "Costa Rica", -+ "CU": "Cuba", -+ "CV": "Cape Verde", -+ "CX": "Christmas Island", -+ "CY": "Cyprus", -+ "CZ": "Czech Republic", -+ "DE": "Germany", -+ "DJ": "Djibouti", -+ "DK": "Denmark", -+ "DM": "Dominica", -+ "DO": "Dominican Republic", -+ "DZ": "Algeria", -+ "EC": "Ecuador", -+ "EE": "Estonia", -+ "EG": "Egypt", -+ "EH": "Western Sahara", -+ "ER": "Eritrea", -+ "ES": "Spain", -+ "ET": "Ethiopia", -+ "FI": "Finland", -+ "FJ": "Fiji", -+ "FK": "Falkland Islands", -+ "FM": "Micronesia", -+ "FO": "Faroe Islands", -+ "FR": "France", -+ "GA": "Gabon", -+ "GB": "United Kingdom", -+ "GD": "Grenada", -+ "GE": "Georgia", -+ "GF": "French Guiana", -+ "GG": "Guernsey", -+ "GH": "Ghana", -+ "GI": "Gibraltar", -+ "GL": "Greenland", -+ "GM": "Gambia", -+ "GN": "Guinea", -+ "GP": "Guadeloupe", -+ "GQ": "Equatorial Guinea", -+ "GR": "Greece", -+ "GS": "South Georgia", -+ "GT": "Guatemala", -+ "GU": "Guam", -+ "GW": "Guinea-Bissau", -+ "GY": "Guyana", -+ "HK": "Hong Kong", -+ "HM": "Heard and McDonald Islands", -+ "HN": "Honduras", -+ "HR": "Croatia", -+ "HT": "Haiti", -+ "HU": "Hungary", -+ "ID": "Indonesia", -+ "IE": "Ireland", -+ "IL": "Israel", -+ "IM": "Isle of Man", -+ "IN": "India", -+ "IO": "Chagos Islands", -+ "IQ": "Iraq", -+ "IR": "Iran", -+ "IS": "Iceland", -+ "IT": "Italy", -+ "JE": "Jersey", -+ "JM": "Jamaica", -+ "JO": "Jordan", -+ "JP": "Japan", -+ "KE": "Kenya", -+ "KG": "Kyrgyzstan", -+ "KH": "Cambodia", -+ "KI": "Kiribati", -+ "KM": "Comoros", -+ "KN": "Saint Kitts and Nevis", -+ "KP": "North Korea", -+ "KR": "South Korea", -+ "KW": "Kuwait", -+ "KY": "Cayman Islands", -+ "KZ": "Kazakhstan", -+ "LA": "Laos", -+ "LB": "Lebanon", -+ "LC": "Saint Lucia", -+ "LI": "Liechtenstein", -+ "LK": "Sri Lanka", -+ "LR": "Liberia", -+ "LS": "Lesotho", -+ "LT": "Lithuania", -+ "LU": "Luxembourg", -+ "LV": "Latvia", -+ "LY": "Libyan Arab Jamahiriya", -+ "MA": "Morocco", -+ "MC": "Monaco", -+ "MD": "Moldova", -+ "ME": "Montenegro", -+ "MF": "Saint Martin (French part)", -+ "MG": "Madagascar", -+ "MH": "Marshall Islands", -+ "MK": "Macedonia", -+ "ML": "Mali", -+ "MM": "Myanmar", -+ "MN": "Mongolia", -+ "MO": "Macao", -+ "MP": "Northern Mariana Islands", -+ "MQ": "Martinique", -+ "MR": "Mauritania", -+ "MS": "Montserrat", -+ "MT": "Malta", -+ "MU": "Mauritius", -+ "MV": "Maldives", -+ "MW": "Malawi", -+ "MX": "Mexico", -+ "MY": "Malaysia", -+ "MZ": "Mozambique", -+ "NA": "Namibia", -+ "NC": "New Caledonia", -+ "NE": "Niger", -+ "NF": "Norfolk Island", -+ "NG": "Nigeria", -+ "NI": "Nicaragua", -+ "NL": "Netherlands", -+ "NO": "Norway", -+ "NP": "Nepal", -+ "NR": "Nauru", -+ "NU": "Niue", -+ "NZ": "New Zealand", -+ "OM": "Oman", -+ "PA": "Panama", -+ "PE": "Peru", -+ "PF": "French Polynesia", -+ "PG": "Papua New Guinea", -+ "PH": "Philippines", -+ "PK": "Pakistan", -+ "PL": "Poland", -+ "PM": "Saint Pierre and Miquelon", -+ "PN": "Pitcairn", -+ "PR": "Puerto Rico", -+ "PS": "Palestinian Territory", -+ "PT": "Portugal", -+ "PW": "Palau", -+ "PY": "Paraguay", -+ "QA": "Qatar", -+ "RE": "Reunion", -+ "RO": "Romania", -+ "RS": "Serbia", -+ "RU": "Russian Federation", -+ "RW": "Rwanda", -+ "SA": "Saudi Arabia", -+ "SB": "Solomon Islands", -+ "SC": "Seychelles", -+ "SD": "Sudan", -+ "SE": "Sweden", -+ "SG": "Singapore", -+ "SH": "St. Helena and Dependencies", -+ "SI": "Slovenia", -+ "SJ": "Svalbard and Jan Mayen", -+ "SK": "Slovakia", -+ "SL": "Sierra Leone", -+ "SM": "San Marino", -+ "SN": "Senegal", -+ "SO": "Somalia", -+ "SR": "Suriname", -+ "ST": "Sao Tome and Principe", -+ "SV": "El Salvador", -+ "SY": "Syrian Arab Republic", -+ "SZ": "Swaziland", -+ "TC": "Turks and Caicos Islands", -+ "TD": "Chad", -+ "TF": "French Southern Territories", -+ "TG": "Togo", -+ "TH": "Thailand", -+ "TJ": "Tajikistan", -+ "TK": "Tokelau", -+ "TL": "Timor-Leste", -+ "TM": "Turkmenistan", -+ "TN": "Tunisia", -+ "TO": "Tonga", -+ "TR": "Turkey", -+ "TT": "Trinidad and Tobago", -+ "TV": "Tuvalu", -+ "TW": "Taiwan", -+ "TZ": "Tanzania", -+ "UA": "Ukraine", -+ "UG": "Uganda", -+ "UM": "U.S. Minor Outlying Islands", -+ "US": "United States", -+ "UY": "Uruguay", -+ "UZ": "Uzbekistan", -+ "VA": "Vatican City State", -+ "VC": "St. Vincent and Grenadines", -+ "VE": "Venezuela", -+ "VG": "Virgin Islands, British", -+ "VI": "Virgin Islands, U.S.", -+ "VN": "Viet Nam", -+ "VU": "Vanuatu", -+ "WF": "Wallis and Futuna", -+ "WS": "Samoa", -+ "YE": "Yemen", -+ "YT": "Mayotte", -+ "ZA": "South Africa", -+ "ZM": "Zambia", -+ "ZW": "Zimbabwe" -+} -diff --git a/package/network/utils/iwinfo/files-iwinfo/usr/share/ucode/iwinfo.uc b/package/network/utils/iwinfo/files-iwinfo/usr/share/ucode/iwinfo.uc -new file mode 100644 -index 0000000000..84615adb5c ---- /dev/null -+++ b/package/network/utils/iwinfo/files-iwinfo/usr/share/ucode/iwinfo.uc -@@ -0,0 +1,606 @@ -+'use strict'; -+ -+import * as nl80211 from 'nl80211'; -+import * as libubus from 'ubus'; -+import { readfile, stat } from "fs"; -+ -+let wifi_devices = json(readfile('/usr/share/wifi_devices.json')); -+let countries = json(readfile('/usr/share/iso3166.json')); -+let board_data = json(readfile('/etc/board.json')); -+ -+export let phys = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, nl80211.const.NLM_F_DUMP, { split_wiphy_dump: true }); -+let interfaces = nl80211.request(nl80211.const.NL80211_CMD_GET_INTERFACE, nl80211.const.NLM_F_DUMP); -+ -+let ubus = libubus.connect(); -+let wireless_status = ubus.call('network.wireless', 'status'); -+ -+function find_phy(wiphy) { -+ for (let k, phy in phys) -+ if (phy.wiphy == wiphy) -+ return phy; -+ return null; -+} -+ -+function get_noise(iface) { -+ for (let phy in phys) { -+ let channels = nl80211.request(nl80211.const.NL80211_CMD_GET_SURVEY, nl80211.const.NLM_F_DUMP, { dev: iface.ifname }); -+ for (let k, channel in channels) -+ if (channel.survey_info.frequency == iface.wiphy_freq) -+ return channel.survey_info.noise; -+ } -+ -+ return -100; -+} -+ -+function get_country(iface) { -+ let reg = nl80211.request(nl80211.const.NL80211_CMD_GET_REG, 0, { dev: iface.ifname }); -+ -+ return reg.reg_alpha2 ?? ''; -+} -+ -+function get_max_power(iface) { -+ let phy = find_phy(iface.wiphy); -+ -+ for (let k, band in phy.wiphy_bands) -+ if (band) -+ for (let freq in band.freqs) -+ if (freq.freq == iface.wiphy_freq) -+ return freq.max_tx_power;; -+ return 0; -+} -+ -+function get_hardware_id(iface) { -+ let hw = { -+ type: 'nl80211', -+ id: 'Generic MAC80211', -+ power_offset: 0, -+ channel_offset: 0, -+ }; -+ -+ let path = `/sys/class/ieee80211/phy${iface.wiphy}/device/`; -+ if (stat(path) + 'vendor') { -+ let data = []; -+ for (let lookup in [ 'vendor', 'device', 'subsystem_vendor', 'subsystem_device' ]) -+ push(data, trim(readfile(path + lookup), '\n')); -+ -+ for (let device in wifi_devices.pci) { -+ let match = 0; -+ for (let i = 0; i < 4; i++) -+ if (lc(data[i]) == lc(device[i])) -+ match++; -+ if (match == 4) { -+ hw.type = `${data[0]}:${data[1]} ${data[2]}:${data[3]}`; -+ hw.power_offset = device[4]; -+ hw.channel_offset = device[5]; -+ hw.id = `${device[6]} ${device[7]}`; -+ } -+ } -+ } -+ -+ let compatible = trim(readfile(`/sys/class/net/${iface.ifname}/device/of_node/compatible`), '\n'); -+ if (compatible && wifi_devices.compatible[compatible]) { -+ hw.id = wifi_devices.compatible[compatible][0] + ' ' + wifi_devices.compatible[compatible][1]; -+ hw.compatible = compatible; -+ hw.type = 'embedded'; -+ } -+ -+ return hw; -+} -+ -+const iftypes = [ -+ 'Unknown', 'Ad-Hoc', 'Client', 'Master', 'Master (VLAN)', -+ 'WDS', 'Monitor', 'Mesh Point', 'P2P Client', 'P2P Go', -+]; -+ -+export let ifaces = {}; -+for (let k, v in interfaces) { -+ let iface = ifaces[v.ifname] = v; -+ -+ iface.mode = iftypes[iface.iftype] ?? 'unknonw', -+ iface.noise = get_noise(iface); -+ iface.country = get_country(iface); -+ iface.max_power = get_max_power(iface); -+ iface.assoclist = nl80211.request(nl80211.const.NL80211_CMD_GET_STATION, nl80211.const.NLM_F_DUMP, { dev: v.ifname }) ?? []; -+ iface.hardware = get_hardware_id(iface); -+ -+ iface.bss_info = ubus.call('hostapd', 'bss_info', { iface: v.ifname }); -+ if (!iface.bss_info) -+ iface.bss_info = ubus.call('wpa_supplicant', 'bss_info', { iface: v.ifname }); -+} -+ -+for (let radio, data in wireless_status) -+ for (let k, v in data.interfaces) { -+ if (!v.ifname || !ifaces[v.ifname]) -+ continue; -+ -+ ifaces[v.ifname].ssid = v.config.ssid; -+ ifaces[v.ifname].radio = data.config; -+ -+ let bss_info = ifaces[v.ifname].bss_info; -+ let owe_transition_ifname = bss_info?.owe_transition_ifname; -+ -+ if (v.config.owe_transition && ifaces[owe_transition_ifname]) { -+ ifaces[v.ifname].owe_transition_ifname = owe_transition_ifname; -+ ifaces[owe_transition_ifname].ssid = v.config.ssid; -+ ifaces[owe_transition_ifname].radio = data.config; -+ ifaces[owe_transition_ifname].owe_transition_ifname = v.ifname -+ } -+ } -+ -+function format_channel(freq) { -+ if (freq < 1000) -+ return 0; -+ if (freq == 2484) -+ return 14; -+ if (freq == 5935) -+ return 2; -+ if (freq < 2484) -+ return (freq - 2407) / 5; -+ if (freq >= 4910 && freq <= 4980) -+ return (freq - 4000) / 5; -+ if (freq < 5950) -+ return (freq - 5000) / 5; -+ if (freq <= 45000) -+ return (freq - 5950) / 5; -+ if (freq >= 58320 && freq <= 70200) -+ return (freq - 56160) / 2160; -+ -+ return 'unknown'; -+} -+ -+function format_band(freq) { -+ if (freq == 5935) -+ return '6'; -+ if (freq < 2484) -+ return '2.4'; -+ if (freq < 5950) -+ return '5'; -+ if (freq <= 45000) -+ return '6'; -+ -+ return '60'; -+} -+ -+function format_frequency(freq) { -+ if (!freq) -+ return 'unknown'; -+ freq = '' + freq; -+ return substr(freq, 0, 1) + '.' + substr(freq, 1); -+} -+ -+function format_rate(rate) { -+ if (!rate) -+ return 'unknown'; -+ return '' + (rate / 10) + '.' + (rate % 10); -+} -+ -+function format_mgmt_key(key) { -+ switch(+key) { -+ case 1: -+ case 11: -+ case 12: -+ case 13: -+ case 14: -+ case 15: -+ case 16: -+ case 17: -+ return '802.1x'; -+ -+ case 2: -+ return 'WPA PSK'; -+ -+ case 4: -+ return 'FT PSK'; -+ -+ case 6: -+ return 'WPA PSK2'; -+ -+ case 8: -+ return 'SAE'; -+ -+ case 18: -+ return 'OWE'; -+ } -+ -+ return null; -+} -+ -+function assoc_flags(data) { -+ const assoc_mhz = { -+ width_40: 40, -+ width_80: 80, -+ width_80p80: '80+80', -+ width_160: 160, -+ width_320: 320, -+ width_10: 10, -+ width_5: 5 -+ }; -+ -+ let mhz = 'unknown'; -+ for (let k, v in assoc_mhz) -+ if (data[k]) -+ mhz = v; -+ -+ const assoc_flags = { -+ mcs: { -+ mcs: 'MCS', -+ }, -+ vht_mcs: { -+ vht_mcs: 'VHT-MCS', -+ vht_nss: 'VHT-NSS', -+ }, -+ he_mcs: { -+ he_mcs: 'HE-MCS', -+ he_nss: 'HE-NSS', -+ he_gi: 'HE-GI', -+ he_dcm: 'HE-DCM', -+ }, -+ eht_mcs: { -+ eht_mcs: 'EHT-MCS', -+ eht_nss: 'EHT-NSS', -+ eht_gi: 'EHT-GI', -+ }, -+ }; -+ -+ let flags = []; -+ for (let k, v in assoc_flags) { -+ if (!data[k]) -+ continue; -+ -+ let first = 0; -+ for (let name, flag in v) { -+ if (data[name] == null) -+ continue; -+ push(flags, `${flag} ${data[name]}`); -+ if (!first++) -+ push(flags, `${mhz}MHz`); -+ } -+ } -+ -+ return flags; -+} -+ -+function dbm2mw(dbm) { -+ const LOG10_MAGIC = 1.25892541179; -+ let res = 1.0; -+ let ip = dbm / 10; -+ let fp = dbm % 10; -+ -+ for (let k = 0; k < ip; k++) -+ res *= 10; -+ for (let k = 0; k < fp; k++) -+ res *= 1.25892541179; -+ -+ return int(res); -+} -+ -+function dbm2quality(dbm) { -+ let quality = dbm; -+ -+ if (quality < -110) -+ quality = -110; -+ else if (quality > -40) -+ quality = -40; -+ quality += 110; -+ -+ return quality; -+} -+ -+function hwmodelist(name) { -+ const mode = { 'HT*': 'n', 'VHT*': 'ac', 'HE*': 'ax' }; -+ let iface = ifaces[name]; -+ let phy = board_data.wlan?.['phy' + iface.wiphy]; -+ if (!phy) -+ return ''; -+ let htmodes = phy.info.bands[uc(iface.radio.band)].modes; -+ let list = []; -+ if (iface.radio.band == '2g' && 'NOHT' in htmodes) -+ push(list, 'g/b'); -+ for (let k, v in mode) -+ for (let htmode in htmodes) -+ if (wildcard(htmode, k)) -+ push(list, v); -+ -+ return join('/', reverse(uniq(list))); -+} -+ -+export function assoclist(dev) { -+ let stations = ifaces[dev].assoclist; -+ let ret = {}; -+ -+ for (let station in stations) { -+ let sta = { -+ mac: uc(station.mac), -+ signal: station.sta_info.signal_avg, -+ noise: ifaces[dev].noise, -+ snr: station.sta_info.signal_avg - ifaces[dev].noise, -+ inactive_time: station.sta_info.inactive_time, -+ rx: { -+ bitrate: format_rate(station.sta_info.rx_bitrate.bitrate), -+ bitrate_raw: station.sta_info.rx_bitrate.bitrate, -+ packets: station.sta_info.rx_packets, -+ flags: assoc_flags(station.sta_info.rx_bitrate), -+ }, -+ tx: { -+ bitrate: format_rate(station.sta_info.tx_bitrate.bitrate), -+ bitrate_raw: station.sta_info.tx_bitrate.bitrate, -+ packets: station.sta_info.tx_packets, -+ flags: assoc_flags(station.sta_info.tx_bitrate), -+ }, -+ expected_throughput: station.sta_info.expected_throughput ?? 'unknown', -+ }; -+ ret[sta.mac] = sta; -+ } -+ -+ return ret; -+}; -+ -+export function freqlist(name) { -+ const freq_flags = { -+ no_10mhz: 'NO_10MHZ', -+ no_20mhz: 'NO_20MHZ', -+ no_ht40_minus: 'NO_HT40-', -+ no_ht40_plus: 'NO_HT40+', -+ no_80mhz: 'NO_80MHZ', -+ no_160mhz: 'NO_160MHZ', -+ indoor_only: 'INDOOR_ONLY', -+ no_ir: 'NO_IR', -+ no_he: 'NO_HE', -+ }; -+ -+ let iface = ifaces[name]; -+ let phy = find_phy(iface.wiphy); -+ let channels = []; -+ -+ for (let k, band in phy.wiphy_bands) { -+ if (!band) -+ continue; -+ -+ let band_name = format_band(band.freqs[0].freq); -+ for (let freq in band.freqs) { -+ if (freq.disabled) -+ continue; -+ -+ let channel = { -+ freq: format_frequency(freq.freq), -+ band: band_name, -+ channel: format_channel(freq.freq), -+ flags: [], -+ active: iface.wiphy_freq == freq.freq, -+ }; -+ -+ for (let k, v in freq_flags) -+ if (freq[k]) -+ push(channel.flags, v); -+ -+ push(channels, channel); -+ } -+ } -+ -+ return channels; -+}; -+ -+export function info(name) { -+ let order = []; -+ for (let iface, data in ifaces) -+ push(order, iface); -+ -+ let list = []; -+ for (let iface in sort(order)) { -+ if (name && iface != name) -+ continue; -+ let data = ifaces[iface]; -+ let dev = { -+ iface, -+ ssid: data.ssid, -+ mac: data.mac, -+ mode: data.mode, -+ channel: format_channel(data.wiphy_freq), -+ freq: format_frequency(data.wiphy_freq), -+ htmode: data.radio.htmode, -+ center_freq1: format_channel(data.center_freq1) || 'unknown', -+ center_freq2: format_channel(data.center_freq2) || 'unknown', -+ txpower: data.wiphy_tx_power_level / 100, -+ noise: data.noise, -+ signal: 0, -+ bitrate: 0, -+ encryption: 'unknown', -+ hwmode: hwmodelist(iface), -+ phy: 'phy' + data.wiphy, -+ vaps: 'no', -+ hw_type: data.hardware.type, -+ hw_id: data.hardware.id, -+ power_offset: data.hardware.power_offset || 'none', -+ channel_offset: data.hardware.channel_offset || 'none', -+ }; -+ -+ let phy = find_phy(data.wiphy); -+ for (let limit in phy.interface_combinations[0]?.limits) -+ if (limit.types?.ap && limit.max > 1) -+ dev.vaps = 'yes'; -+ -+ if (data.bss_info) { -+ if (data.bss_info.wpa_key_mgmt && data.bss_info.wpa_pairwise) -+ dev.encryption = `${replace(data.bss_info.wpa_key_mgmt, ' ', ' / ')} (${data.bss_info.wpa_pairwise})`; -+ else if (data.owe_transition_ifname) -+ dev.encryption = 'none (OWE transition)'; -+ else -+ dev.encryption = 'none'; -+ } -+ -+ let stations = assoclist(iface); -+ for (let k, station in stations) { -+ dev.signal += station.signal; -+ dev.bitrate += station.tx.bitrate_raw; -+ } -+ dev.signal /= length(data.assoclist) || 1; -+ dev.bitrate /= length(data.assoclist) || 1; -+ dev.bitrate = format_rate(dev.bitrate); -+ dev.quality = dbm2quality(dev.signal); -+ -+ if (data.owe_transition_ifname) -+ dev.owe_transition_ifname = data.owe_transition_ifname; -+ -+ push(list, dev); -+ } -+ -+ return list; -+}; -+ -+export function htmodelist(name) { -+ let iface = ifaces[name]; -+ let phy = board_data.wlan?.['phy' + iface.wiphy]; -+ if (!phy) -+ return []; -+ -+ return filter(phy.info.bands[uc(iface.radio.band)].modes, (v) => v != 'NOHT'); -+}; -+ -+export function txpowerlist(name) { -+ let iface = ifaces[name]; -+ let max_power = iface.max_power / 100; -+ let match = iface.wiphy_tx_power_level / 100; -+ let list = []; -+ -+ for (let power = 0; power <= max_power; power++) { -+ let txpower = { -+ dbm: power, -+ mw: dbm2mw(power), -+ active: power == match, -+ }; -+ push(list, txpower); -+ } -+ -+ return list; -+}; -+ -+export function countrylist(dev) { -+ let iface = ifaces[dev]; -+ -+ let list = { -+ active: iface.country, -+ countries, -+ }; -+ -+ return list; -+}; -+ -+export function scan(dev) { -+ const rsn_cipher = [ 'NONE', 'WEP-40', 'TKIP', 'WRAP', 'CCMP', 'WEP-104', 'AES-OCB', 'CKIP', 'GCMP', 'GCMP-256', 'CCMP-256' ]; -+ const ht_chan_offset = [ 'no secondary', 'above', '[reserved]', 'below' ]; -+ const vht_chan_width = [ '20 or 40 MHz', '80 MHz', '80+80 MHz', '160 MHz' ]; -+ const ht_chan_width = [ '20 MHz', '40 MHz or higher' ]; -+ const SCAN_FLAG_AP = (1<<2); -+ -+ let params = { -+ dev, -+ scan_flags: SCAN_FLAG_AP, -+ scan_ssids: [ '' ], -+ }; -+ -+ let res = nl80211.request(nl80211.const.NL80211_CMD_TRIGGER_SCAN, 0, params); -+ if (res === false) { -+ printf("Unable to trigger scan: " + nl80211.error() + "\n"); -+ exit(1); -+ } -+ -+ res = nl80211.waitfor([ -+ nl80211.const.NL80211_CMD_NEW_SCAN_RESULTS, -+ nl80211.const.NL80211_CMD_SCAN_ABORTED -+ ], 5000); -+ -+ if (!res) { -+ printf("Netlink error while awaiting scan results: " + nl80211.error() + "\n"); -+ exit(1); -+ } else if (res.cmd == nl80211.const.NL80211_CMD_SCAN_ABORTED) { -+ printf("Scan aborted by kernel\n"); -+ exit(1); -+ } -+ -+ let scan = nl80211.request(nl80211.const.NL80211_CMD_GET_SCAN, nl80211.const.NLM_F_DUMP, { dev }); -+ -+ let cells = []; -+ for (let k, bss in scan) { -+ bss = bss.bss; -+ let cell = { -+ bssid: uc(bss.bssid), -+ frequency: format_frequency(bss.frequency), -+ band: format_band(bss.frequency), -+ channel: format_channel(bss.frequency), -+ dbm: bss.signal_mbm / 100, -+ -+ }; -+ -+ if (bss.capability & (1 << 1)) -+ cell.mode = 'Ad-Hoc'; -+ else if (bss.capability & (1 << 0)) -+ cell.mode = 'Master'; -+ else -+ cell.mode = 'Mesh Point'; -+ -+ cell.quality = dbm2quality(cell.dbm); -+ -+ for (let ie in bss.information_elements) -+ switch(ie.type) { -+ case 0: -+ case 114: -+ cell.ssid = ie.data; -+ break; -+ -+ case 7: -+ cell.country = substr(ie.data, 0, 2); -+ break; -+ -+ case 48: -+ cell.crypto = { -+ group: rsn_cipher[+ord(ie.data, 5)] ?? '', -+ pair: [], -+ key_mgmt: [], -+ }; -+ -+ let offset = 6; -+ let count = +ord(ie.data, offset); -+ offset += 2; -+ -+ for (let i = 0; i < count; i++) { -+ let key = rsn_cipher[+ord(ie.data, offset + 3)]; -+ if (key) -+ push(cell.crypto.pair, key); -+ offset += 4; -+ } -+ -+ count = +ord(ie.data, offset); -+ offset += 2; -+ -+ for (let i = 0; i < count; i++) { -+ let key = format_mgmt_key(ord(ie.data, offset + 3)); -+ if (key) -+ push(cell.crypto.key_mgmt, key); -+ offset += 4; -+ } -+ break; -+ -+ case 61: -+ cell.ht = { -+ primary_channel: ord(ie.data, 0), -+ secondary_chan_off: ht_chan_offset[ord(ie.data, 1) & 0x3], -+ chan_width: ht_chan_width[(ord(ie.data, 1) & 0x4) >> 2], -+ }; -+ break; -+ -+ case 192: -+ cell.vht = { -+ chan_width: vht_chan_width[ord(ie.data, 0)], -+ center_chan_1: ord(ie.data, 1), -+ center_chan_2: ord(ie.data, 2), -+ }; -+ break; -+ }; -+ -+ -+ -+ push(cells, cell); -+ } -+ -+ return cells; -+}; -diff --git a/package/network/utils/iwinfo/files-iwinfo/usr/share/wifi_devices.json b/package/network/utils/iwinfo/files-iwinfo/usr/share/wifi_devices.json -new file mode 100644 -index 0000000000..7e9c63751b ---- /dev/null -+++ b/package/network/utils/iwinfo/files-iwinfo/usr/share/wifi_devices.json -@@ -0,0 +1,258 @@ -+{ -+ "pci": [ -+ [ "0x0777", "0x11ac", "0x0777", "0xe7f9", 0, 0, "Ubiquiti", "LiteBeam, 5AC" ], -+ [ "0xffff", "0xffff", "0xffff", "0xb102", 0, 0, "Ubiquiti", "PowerStation2, (18V)" ], -+ [ "0xffff", "0xffff", "0xffff", "0xb202", 0, 0, "Ubiquiti", "PowerStation2, (16D)" ], -+ [ "0xffff", "0xffff", "0xffff", "0xb302", 0, 0, "Ubiquiti", "PowerStation2, (EXT)" ], -+ [ "0xffff", "0xffff", "0xffff", "0xb105", 0, 0, "Ubiquiti", "PowerStation5, (22V)" ], -+ [ "0xffff", "0xffff", "0xffff", "0xb305", 0, 0, "Ubiquiti", "PowerStation5, (EXT)" ], -+ [ "0xffff", "0xffff", "0xffff", "0xc302", 0, 0, "Ubiquiti", "PicoStation2" ], -+ [ "0xffff", "0xffff", "0xffff", "0xc3a2", 10, 0, "Ubiquiti", "PicoStation2, HP" ], -+ [ "0xffff", "0xffff", "0xffff", "0xa105", 0, 0, "Ubiquiti", "WispStation5" ], -+ [ "0xffff", "0xffff", "0xffff", "0xa002", 10, 0, "Ubiquiti", "LiteStation2" ], -+ [ "0xffff", "0xffff", "0xffff", "0xa005", 5, 0, "Ubiquiti", "LiteStation5" ], -+ [ "0xffff", "0xffff", "0xffff", "0xc002", 10, 0, "Ubiquiti", "NanoStation2" ], -+ [ "0xffff", "0xffff", "0xffff", "0xc005", 5, 0, "Ubiquiti", "NanoStation5" ], -+ [ "0xffff", "0xffff", "0xffff", "0xc102", 10, 0, "Ubiquiti", "NanoStation, Loco2" ], -+ [ "0xffff", "0xffff", "0xffff", "0xc105", 5, 0, "Ubiquiti", "NanoStation, Loco5" ], -+ [ "0xffff", "0xffff", "0xffff", "0xc202", 10, 0, "Ubiquiti", "Bullet2" ], -+ [ "0xffff", "0xffff", "0xffff", "0xc205", 5, 0, "Ubiquiti", "Bullet5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe002", 6, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe003", 3, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe005", 5, 0, "Ubiquiti", "NanoStation, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe006", 5, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe009", 6, 0, "Ubiquiti", "NanoStation, Loco, M9" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe012", 10, 0, "Ubiquiti", "NanoStation, M2" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe035", 3, 0, "Ubiquiti", "NanoStation, M3" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe0a2", 2, 0, "Ubiquiti", "NanoStation, Loco, M2" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe0a5", 1, 0, "Ubiquiti", "NanoStation, Loco, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe102", 6, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe105", 5, 0, "Ubiquiti", "Rocket, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe112", 10, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe115", 3, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1a3", 3, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1a5", 5, 0, "Ubiquiti", "PowerBridge, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1b2", 10, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1b3", 3, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1b5", 5, 0, "Ubiquiti", "Rocket, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1b6", 5, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1b9", 6, 0, "Ubiquiti", "Rocket, M9" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1c2", 10, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1c3", 3, 0, "Ubiquiti", "Rocket, M3" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1c5", 5, 0, "Ubiquiti", "Rocket, M5, GPS" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1c5", 5, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1d2", 10, 0, "Ubiquiti", "Rocket, M2, Titanium" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1d3", 3, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1d5", 5, 0, "Ubiquiti", "airOS, XM/XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1d9", 6, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1e3", 3, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe1e5", 5, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe202", 12, 0, "Ubiquiti", "Bullet, M2" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe205", 6, 0, "Ubiquiti", "Bullet, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe212", 1, 0, "Ubiquiti", "AirGrid, M2" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe215", 1, 0, "Ubiquiti", "AirGrid, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe232", 2, 0, "Ubiquiti", "NanoBridge, M2" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe233", 3, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe235", 1, 0, "Ubiquiti", "NanoBridge, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe239", 6, 0, "Ubiquiti", "NanoBridge, M9" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe242", 9, 0, "Ubiquiti", "AirGrid, M2, HP" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe243", 3, 0, "Ubiquiti", "NanoBridge, M3" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe245", 6, 0, "Ubiquiti", "AirGrid, M5, HP" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe252", 9, 0, "Ubiquiti", "AirGrid, M2, HP" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe255", 6, 0, "Ubiquiti", "AirGrid, M5, HP" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2a3", 3, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2a5", 5, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2b2", 10, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2b5", 1, 0, "Ubiquiti", "NanoBridge, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2b9", 6, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2c2", 10, 0, "Ubiquiti", "NanoBeam, M2, Int" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2c3", 6, 0, "Ubiquiti", "Bullet, M2, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2c4", 6, 0, "Ubiquiti", "airOS, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2d2", 12, 0, "Ubiquiti", "Bullet, M2, Titanium, HP" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2d4", 6, 0, "Ubiquiti", "airOS, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2d5", 6, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe2e5", 4, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe302", 12, 0, "Ubiquiti", "PicoStation, M2"], -+ [ "0x168c", "0xffff", "0x0777", "0xe305", 6, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe345", 6, 0, "Ubiquiti", "WispStation, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe3a5", 5, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe3b5", 6, 0, "Ubiquiti", "airOS, XM/XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe3e5", 4, 0, "Ubiquiti", "PowerBeam, M5, 300" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe402", 10, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe405", 1, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe4a2", 1, 0, "Ubiquiti", "AirRouter" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe4a5", 1, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe4b2", 9, 0, "Ubiquiti", "AirRouter, HP" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe4d5", 5, 0, "Ubiquiti", "Rocket, M5, Titanium" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe4e5", 4, 0, "Ubiquiti", "PowerBeam, M5, 400" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe5e5", 4, 0, "Ubiquiti", "airOS, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe6a2", 1, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe6b2", 1, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe6b5", 5, 0, "Ubiquiti", "Rocket, M5, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe6c2", 6, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe6e5", 4, 0, "Ubiquiti", "PowerBeam, M5, 400, ISO" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe7f8", 2, 0, "Ubiquiti", "airOS, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe805", 5, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe812", 6, 0, "Ubiquiti", "NanoBeam, M2, 13" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe815", 4, 0, "Ubiquiti", "NanoBeam, M5, 16" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe825", 4, 0, "Ubiquiti", "NanoBeam, M5, 19" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe835", 6, 0, "Ubiquiti", "AirGrid, M5, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe845", 1, 0, "Ubiquiti", "NanoStation, Loco, M5, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe855", 5, 0, "Ubiquiti", "NanoStation, M5, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe865", 6, 0, "Ubiquiti", "LiteBeam, M5" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe866", 6, 0, "Ubiquiti", "NanoStation, M2, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe867", 2, 0, "Ubiquiti", "NanoStation, Loco, M2, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe868", 7, 0, "Ubiquiti", "Rocket, M2, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe869", 2, 0, "Ubiquiti", "airOS, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe875", 4, 0, "Ubiquiti", "airOS, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe879", 2, 0, "Ubiquiti", "airOS, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe885", 4, 0, "Ubiquiti", "PowerBeam, M5, 620, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe895", 4, 0, "Ubiquiti", "airOS, XW" ], -+ [ "0x168c", "0xffff", "0x0777", "0xe8a5", 1, 0, "Ubiquiti", "NanoStation, Loco, M5"], -+ [ "0x168c", "0xffff", "0x0777", "0xe8b5", 5, 0, "Ubiquiti", "airOS, XM" ], -+ [ "0x168c", "0x001b", "0x0777", "0x3002", 10, 0, "Ubiquiti", "XR2" ], -+ [ "0x168c", "0x001b", "0x7777", "0x3002", 10, 0, "Ubiquiti", "XR2" ], -+ [ "0x168c", "0x001b", "0x0777", "0x3b02", 10, 0, "Ubiquiti", "XR2.3" ], -+ [ "0x168c", "0x001b", "0x0777", "0x3c02", 10, 0, "Ubiquiti", "XR2.6" ], -+ [ "0x168c", "0x001b", "0x0777", "0x3b03", 10, 0, "Ubiquiti", "XR3-2.8" ], -+ [ "0x168c", "0x001b", "0x0777", "0x3c03", 10, 0, "Ubiquiti", "XR3-3.6" ], -+ [ "0x168c", "0x001b", "0x0777", "0x3003", 10, 0, "Ubiquiti", "XR3" ], -+ [ "0x168c", "0x001b", "0x0777", "0x3004", 10, 0, "Ubiquiti", "XR4" ], -+ [ "0x168c", "0x001b", "0x0777", "0x3005", 10, 0, "Ubiquiti", "XR5" ], -+ [ "0x168c", "0x001b", "0x7777", "0x3005", 10, 0, "Ubiquiti", "XR5" ], -+ [ "0x168c", "0x001b", "0x0777", "0x3007", 10, 0, "Ubiquiti", "XR7" ], -+ [ "0x168c", "0x001b", "0x0777", "0x3009", 10, -1520, "Ubiquiti", "XR9" ], -+ [ "0x168c", "0x001b", "0x168c", "0x2063", 0, 0, "Atheros", "AR5413" ], -+ [ "0x168c", "0x0013", "0x168c", "0x1042", 1, 0, "Ubiquiti", "SRC" ], -+ [ "0x168c", "0x0013", "0x0777", "0x2041", 10, 0, "Ubiquiti", "SR2" ], -+ [ "0x168c", "0x0013", "0x0777", "0x2004", 6, 0, "Ubiquiti", "SR4" ], -+ [ "0x168c", "0x0013", "0x7777", "0x2004", 6, 0, "Ubiquiti", "SR4" ], -+ [ "0x168c", "0x0013", "0x0777", "0x1004", 6, 0, "Ubiquiti", "SR4C" ], -+ [ "0x168c", "0x0013", "0x7777", "0x1004", 6, 0, "Ubiquiti", "SR4C" ], -+ [ "0x168c", "0x0013", "0x168c", "0x2042", 7, 0, "Ubiquiti", "SR5" ], -+ [ "0x168c", "0x0013", "0x7777", "0x2009", 12, -1500, "Ubiquiti", "SR9" ], -+ [ "0x168c", "0x0027", "0x168c", "0x2082", 7, 0, "Ubiquiti", "SR71A" ], -+ [ "0x168c", "0x0027", "0x0777", "0x4082", 7, 0, "Ubiquiti", "SR71" ], -+ [ "0x168c", "0x0029", "0x0777", "0x4005", 7, 0, "Ubiquiti", "SR71-15" ], -+ [ "0x168c", "0x002a", "0x0777", "0xe302", 12, 0, "Ubiquiti", "PicoStation, M2" ], -+ [ "0x168c", "0x002a", "0x0777", "0xe012", 12, 0, "Ubiquiti", "NanoStation, M2" ], -+ [ "0x168c", "0x002a", "0x0777", "0xe005", 5, 0, "Ubiquiti", "NanoStation, M5" ], -+ [ "0x168c", "0x002a", "0x0777", "0xe202", 12, 0, "Ubiquiti", "Bullet, M2" ], -+ [ "0x168c", "0x002a", "0x0777", "0xe805", 5, 0, "Ubiquiti", "Bullet, M5" ], -+ [ "0x168c", "0x002a", "0x0777", "0xe345", 0, 0, "Ubiquiti", "WispStation, M5" ], -+ [ "0x168c", "0x0029", "0x168c", "0xa094", 0, 0, "Atheros", "AR9220" ], -+ [ "0x168c", "0x0029", "0x168c", "0xa095", 0, 0, "Atheros", "AR9223" ], -+ [ "0x168c", "0x002a", "0x168c", "0xa093", 0, 0, "Atheros", "AR9280" ], -+ [ "0x168c", "0x002b", "0x168c", "0xa091", 0, 0, "Atheros", "AR9285" ], -+ [ "0x168c", "0x002d", "0x168c", "0x209a", 0, 0, "Atheros", "AR9287" ], -+ [ "0x168c", "0x002e", "0x1a3b", "0x1121", 0, 0, "Atheros", "AR9287" ], -+ [ "0x168c", "0x002e", "0x0777", "0xe0a2", 8, 0, "Ubiquiti", "NanoStation, Loco, M2, (XM)" ], -+ [ "0x168c", "0x002e", "0x168c", "0x30a4", 0, 0, "Atheros", "AR9287" ], -+ [ "0x168c", "0x002e", "0x168c", "0xa199", 0, 0, "Atheros", "AR9287" ], -+ [ "0x168c", "0x0030", "0x168c", "0x3112", 0, 0, "Atheros", "AR9380" ], -+ [ "0x168c", "0x0030", "0x168c", "0x3114", 0, 0, "Atheros", "AR9390" ], -+ [ "0x168c", "0x0033", "0x168c", "0xa120", 0, 0, "Atheros", "AR9580" ], -+ [ "0x168c", "0x0033", "0x168c", "0xa136", 0, 0, "Atheros", "AR9580" ], -+ [ "0x168c", "0x0033", "0x168c", "0x3123", 0, 0, "Atheros", "AR9590" ], -+ [ "0x168c", "0x0033", "0x19b6", "0xd014", 0, 0, "MikroTik", "R11e-5HnD" ], -+ [ "0x168c", "0x0033", "0x19b6", "0xd057", 0, 0, "MikroTik", "R11e-5HnDr2" ], -+ [ "0x168c", "0x0033", "0x19b6", "0xd016", 0, 0, "MikroTik", "R11e-2HPnD" ], -+ [ "0x168c", "0x0034", "0x17aa", "0x3214", 0, 0, "Atheros", "AR9462" ], -+ [ "0x168c", "0x003c", "0x0000", "0x0000", 0, 0, "Qualcomm, Atheros", "QCA9880" ], -+ [ "0x168c", "0x003c", "0x168c", "0x3223", 0, 0, "Qualcomm, Atheros", "QCA9880" ], -+ [ "0x168c", "0x003c", "0x1a56", "0x1420", 0, 0, "Qualcomm, Atheros", "QCA9862" ], -+ [ "0x168c", "0x003c", "0x19b6", "0xd03c", 0, 0, "Mikrotik", "R11e-5HacT" ], -+ [ "0x168c", "0x003c", "0x19b6", "0xd075", 0, 0, "Mikrotik", "R11e-5HacD" ], -+ [ "0x168c", "0x003e", "0x168c", "0x3361", 0, 0, "Qualcomm, Atheros", "QCA6174" ], -+ [ "0x168c", "0x0040", "0x168c", "0x0002", 0, 0, "Qualcomm, Atheros", "QCA9990" ], -+ [ "0x168c", "0x0046", "0x168c", "0xcafe", 0, 0, "Qualcomm, Atheros", "QCA9984" ], -+ [ "0x168c", "0x0050", "0x0000", "0x0000", 0, 0, "Qualcomm, Atheros", "QCA9887" ], -+ [ "0x168c", "0x0056", "0x0000", "0x0000", 0, 0, "Qualcomm, Atheros", "QCA9886" ], -+ [ "0x17cb", "0x1104", "0x17cb", "0x1104", 0, 0, "Qualcomm, Atheros", "QCN6024/9024/9074" ], -+ [ "0x1814", "0x3051", "0x1814", "0x0007", 0, 0, "Ralink", "Rt3051" ], -+ [ "0x1814", "0x3052", "0x1814", "0x0008", 0, 0, "Ralink", "Rt3052" ], -+ [ "0x1814", "0x3350", "0x1814", "0x000b", 0, 0, "Ralink", "Rt3350" ], -+ [ "0x1814", "0x3662", "0x1814", "0x000d", 0, 0, "Ralink", "Rt3662" ], -+ [ "0x11ab", "0x2a55", "0x11ab", "0x0000", 0, 0, "Marvell", "88W8864" ], -+ [ "0x02df", "0x9135", "0x0000", "0x0000", 0, 0, "Marvell", "88W8887" ], -+ [ "0x11ab", "0x2b40", "0x11ab", "0x0000", 0, 0, "Marvell", "88W8964" ], -+ [ "0x02df", "0x9141", "0x0000", "0x0000", 0, 0, "Marvell", "88W8997" ], -+ [ "0x14c3", "0x0608", "0x14c3", "0x0608", 0, 0, "AMD", "RZ608" ], -+ [ "0x14c3", "0x7603", "0x14c3", "0x7603", 0, 0, "MediaTek", "MT7603E" ], -+ [ "0x14c3", "0x7610", "0x14c3", "0x7610", 0, 0, "MediaTek", "MT7610E" ], -+ [ "0x14c3", "0x7612", "0x14c3", "0x7612", 0, 0, "MediaTek", "MT7612E" ], -+ [ "0x14c3", "0x7663", "0x14c3", "0x7663", 0, 0, "MediaTek", "MT7613BE" ], -+ [ "0x14c3", "0x7615", "0x7615", "0x14c3", 0, 0, "MediaTek", "MT7615E" ], -+ [ "0x14c3", "0x7628", "0x14c3", "0x0004", 0, 0, "MediaTek", "MT76x8" ], -+ [ "0x14c3", "0x7650", "0x14c3", "0x7650", 0, 0, "MediaTek", "MT7610E" ], -+ [ "0x14c3", "0x7662", "0x14c3", "0x7662", 0, 0, "MediaTek", "MT76x2E" ], -+ [ "0x14c3", "0x7915", "0x14c3", "0x7915", 0, 0, "MediaTek", "MT7915E" ], -+ [ "0x14c3", "0x7906", "0x14c3", "0x7906", 0, 0, "MediaTek", "MT7916AN" ], -+ [ "0x14c3", "0x7990", "0x14C3", "0x6639", 0, 0, "MediaTek", "MT7996E" ], -+ [ "0x14e4", "0xaa52", "0x14e4", "0xaa52", 0, 0, "Broadcom", "BCM43602" ], -+ [ "0x02d0", "0xa9a6", "0x0000", "0x0000", 0, 0, "Cypress", "CYW43455" ], -+ [ "0x02d0", "0x4345", "0x0000", "0x0000", 0, 0, "Cypress", "CYW43455" ], -+ [ "0x1ae9", "0x0310", "0x1ae9", "0x0000", 0, 0, "Wilocity", "Wil6210" ], -+ [ "0x0000", "0x0000", "0x148f", "0x7601", 0, 0, "MediaTek", "MT7601U" ], -+ [ "0x0000", "0x0000", "0x0e8d", "0x7961", 0, 0, "MediaTek", "MT7921AU" ], -+ [ "0x0000", "0x0000", "0x0b05", "0x1833", 0, 0, "ASUS", "USB-AC54" ], -+ [ "0x0000", "0x0000", "0x0b05", "0x17eb", 0, 0, "ASUS", "USB-AC55" ], -+ [ "0x0000", "0x0000", "0x0b05", "0x180b", 0, 0, "ASUS", "USB-N53, B1" ], -+ [ "0x0000", "0x0000", "0x0e8d", "0x7612", 0, 0, "Aukey", "USBAC1200" ], -+ [ "0x0000", "0x0000", "0x057c", "0x8503", 0, 0, "AVM", "FRITZ!WLAN, AC860" ], -+ [ "0x0000", "0x0000", "0x7392", "0xb711", 0, 0, "Edimax", "EW-7722UAC" ], -+ [ "0x0000", "0x0000", "0x0e8d", "0x7632", 0, 0, "High, Cloud", "HC-M7662BU1" ], -+ [ "0x0000", "0x0000", "0x2c4e", "0x0103", 0, 0, "Mercury", "UD13" ], -+ [ "0x0000", "0x0000", "0x0846", "0x9053", 0, 0, "Netgear", "A6210" ], -+ [ "0x0000", "0x0000", "0x045e", "0x02e6", 0, 0, "Microsoft", "XBox, One, Wireless, Adapter" ], -+ [ "0x0000", "0x0000", "0x045e", "0x02fe", 0, 0, "Microsoft", "XBox, One, Wireless, Adapter" ], -+ [ "0x0000", "0x0000", "0x148f", "0x7610", 0, 0, "MediaTek", "MT7610U" ], -+ [ "0x0000", "0x0000", "0x13b1", "0x003e", 0, 0, "Linksys", "AE6000" ], -+ [ "0x0000", "0x0000", "0x0e8d", "0x7610", 0, 0, "Sabrent", "NTWLAC" ], -+ [ "0x0000", "0x0000", "0x7392", "0xa711", 0, 0, "Edimax", "7711MAC" ], -+ [ "0x0000", "0x0000", "0x148f", "0x761a", 0, 0, "TP-Link", "TL-WDN5200" ], -+ [ "0x0000", "0x0000", "0x0b05", "0x17d1", 0, 0, "ASUS", "USB-AC51" ], -+ [ "0x0000", "0x0000", "0x0b05", "0x17db", 0, 0, "ASUS", "USB-AC50" ], -+ [ "0x0000", "0x0000", "0x0df6", "0x0075", 0, 0, "Sitecom", "WLA-3100" ], -+ [ "0x0000", "0x0000", "0x2019", "0xab31", 0, 0, "Planex", "GW-450D" ], -+ [ "0x0000", "0x0000", "0x2001", "0x3d02", 0, 0, "D-Link", "DWA-171, rev, B1" ], -+ [ "0x0000", "0x0000", "0x0586", "0x3425", 0, 0, "Zyxel", "NWD6505" ], -+ [ "0x0000", "0x0000", "0x07b8", "0x7610", 0, 0, "AboCom", "AU7212" ], -+ [ "0x0000", "0x0000", "0x04bb", "0x0951", 0, 0, "I-O, DATA", "WN-AC433UK" ], -+ [ "0x0000", "0x0000", "0x057c", "0x8502", 0, 0, "AVM", "FRITZ!WLAN, AC430" ], -+ [ "0x0000", "0x0000", "0x293c", "0x5702", 0, 0, "Comcast", "Xfinity, KXW02AAA" ], -+ [ "0x0000", "0x0000", "0x20f4", "0x806b", 0, 0, "TRENDnet", "TEW-806UBH" ], -+ [ "0x0000", "0x0000", "0x7392", "0xc711", 0, 0, "Devolo", "WiFi, Stick, ac" ], -+ [ "0x0000", "0x0000", "0x0df6", "0x0079", 0, 0, "Sitecom", "WL-356" ], -+ [ "0x0000", "0x0000", "0x2357", "0x0123", 0, 0, "TP-Link", "T2UHP, US, v1" ], -+ [ "0x0000", "0x0000", "0x2357", "0x010b", 0, 0, "TP-Link", "T2UHP, UN, v1" ], -+ [ "0x0000", "0x0000", "0x2357", "0x0105", 0, 0, "TP-Link", "Archer, T1U" ], -+ [ "0x0000", "0x0000", "0x0e8d", "0x7630", 0, 0, "MediaTek", "MT7630U" ], -+ [ "0x0000", "0x0000", "0x0e8d", "0x7650", 0, 0, "MediaTek", "MT7650U" ], -+ [ "0x0000", "0x0000", "0x0e8d", "0x7663", 0, 0, "MediaTek", "MT7663U" ], -+ [ "0x0000", "0x0000", "0x043e", "0x310c", 0, 0, "LG", "LGSBWAC02" ], -+ [ "0x0000", "0x0000", "0x0bda", "0x8176", 0, 0, "Realtek", "RTL8188CU" ], -+ [ "0x0000", "0x0000", "0x0bda", "0xf179", 0, 0, "Realtek", "RTL8188FTV" ] -+ ], -+ "compatible": { -+ "qca,ar9130-wmac": [ "Atheros", "AR9130" ], -+ "qca,ar9330-wmac": [ "Atheros", "AR9330" ], -+ "qca,ar9340-wmac": [ "Atheros", "AR9340" ], -+ "qca,qca9530-wmac": [ "Qualcomm Atheros", "QCA9530" ], -+ "qca,qca9550-wmac": [ "Qualcomm Atheros", "QCA9550" ], -+ "qca,qca9560-wmac": [ "Qualcomm Atheros", "QCA9560" ], -+ "qcom,ipq4019-wifi": [ "Qualcomm Atheros", "IPQ4019" ], -+ "qcom,ipq6018-wifi": [ "Qualcomm Atheros", "IPQ6018" ], -+ "qcom,ipq8074-wifi": [ "Qualcomm Atheros", "IPQ8074" ], -+ "mediatek,mt7622-wmac": [ "MediaTek", "MT7622" ], -+ "mediatek,mt7628-wmac": [ "MediaTek", "MT7628" ], -+ "mediatek,mt7981-wmac": [ "MediaTek", "MT7981" ], -+ "mediatek,mt7986-wmac": [ "MediaTek", "MT7986" ], -+ "ralink,rt2880-wmac": [ "Ralink", "Rt2880" ], -+ "ralink,rt3050-wmac": [ "Ralink", "Rt3050" ], -+ "ralink,rt3352-wmac": [ "Ralink", "Rt3352" ], -+ "ralink,rt3883-wmac": [ "Ralink", "Rt3883" ], -+ "ralink,rt5350-wmac": [ "Ralink", "Rt5350" ], -+ "ralink,rt7620-wmac": [ "MediaTek", "MT7620" ] -+ } -+} --- -2.34.1 -