blob: 8fef4f68f9f41aaccdd55182f3256d47b01dff4d [file] [log] [blame]
developer753619c2024-02-22 13:42:45 +08001#!/usr/bin/env ucode
2'use strict';
3import { readfile, writefile, realpath, glob, basename, unlink, open, rename } from "fs";
4import { is_equal } from "/usr/share/hostap/common.uc";
5let nl = require("nl80211");
6
7let board_file = "/etc/board.json";
8let prev_board_data = json(readfile(board_file));
9let board_data = json(readfile(board_file));
10
11function phy_idx(name) {
12 return +rtrim(readfile(`/sys/class/ieee80211/${name}/index`));
13}
14
15function phy_path(name) {
16 let devpath = realpath(`/sys/class/ieee80211/${name}/device`);
17
18 devpath = replace(devpath, /^\/sys\/devices\//, "");
19 if (match(devpath, /^platform\/.*\/pci/))
20 devpath = replace(devpath, /^platform\//, "");
21 let dev_phys = map(glob(`/sys/class/ieee80211/${name}/device/ieee80211/*`), basename);
22 sort(dev_phys, (a, b) => phy_idx(a) - phy_idx(b));
23
24 let ofs = index(dev_phys, name);
25 if (ofs > 0)
26 devpath += `+${ofs}`;
27
28 return devpath;
29}
30
31function cleanup() {
32 let wlan = board_data.wlan;
33
34 for (let name in wlan)
35 if (substr(name, 0, 3) == "phy")
36 delete wlan[name];
37 else
38 delete wlan[name].info;
39}
40
41function wiphy_get_entry(phy, path) {
42 board_data.wlan ??= {};
43
44 let wlan = board_data.wlan;
45 for (let name in wlan)
46 if (wlan[name].path == path)
47 return wlan[name];
48
49 wlan[phy] = {
50 path: path
51 };
52
53 return wlan[phy];
54}
55
developer42c7a432024-07-12 14:39:29 +080056function freq_to_channel(freq) {
57 if (freq < 1000)
58 return 0;
59 if (freq == 2484)
60 return 14;
61 if (freq == 5935)
62 return 2;
63 if (freq < 2484)
64 return (freq - 2407) / 5;
65 if (freq >= 4910 && freq <= 4980)
66 return (freq - 4000) / 5;
67 if (freq < 5950)
68 return (freq - 5000) / 5;
69 if (freq <= 45000)
70 return (freq - 5950) / 5;
71 if (freq >= 58320 && freq <= 70200)
72 return (freq - 56160) / 2160;
73 return 0;
74}
75
developer753619c2024-02-22 13:42:45 +080076function wiphy_detect() {
77 let phys = nl.request(nl.const.NL80211_CMD_GET_WIPHY, nl.const.NLM_F_DUMP, { split_wiphy_dump: true });
78 if (!phys)
79 return;
80
81 for (let phy in phys) {
developerd0c89452024-10-11 16:53:27 +080082 if (!phy)
83 continue;
84
developer753619c2024-02-22 13:42:45 +080085 let name = phy.wiphy_name;
86 let path = phy_path(name);
87 let info = {
88 antenna_rx: phy.wiphy_antenna_avail_rx,
89 antenna_tx: phy.wiphy_antenna_avail_tx,
90 bands: {},
91 };
92
93 let bands = info.bands;
94 for (let band in phy.wiphy_bands) {
95 if (!band || !band.freqs)
96 continue;
97 let freq = band.freqs[0].freq;
98 let band_info = {};
99 let band_name;
100 if (freq > 50000)
101 band_name = "60G";
102 else if (freq > 5900)
103 band_name = "6G";
104 else if (freq > 4000)
105 band_name = "5G";
developer42c7a432024-07-12 14:39:29 +0800106 else if (freq > 2000)
developer753619c2024-02-22 13:42:45 +0800107 band_name = "2G";
developer42c7a432024-07-12 14:39:29 +0800108 else
109 continue;
developer753619c2024-02-22 13:42:45 +0800110 bands[band_name] = band_info;
111 if (band.ht_capa > 0)
112 band_info.ht = true;
113 if (band.vht_capa > 0)
114 band_info.vht = true;
115 let he_phy_cap = 0;
developerd0c89452024-10-11 16:53:27 +0800116 let eht_phy_cap = 0;
developer753619c2024-02-22 13:42:45 +0800117
118 for (let ift in band.iftype_data) {
119 if (!ift.he_cap_phy)
120 continue;
121
122 band_info.he = true;
123 he_phy_cap |= ift.he_cap_phy[0];
developerd0c89452024-10-11 16:53:27 +0800124
125 /* if (!ift.eht_cap_phy) */
126 /* continue; */
127
developer753619c2024-02-22 13:42:45 +0800128 /* TODO: EHT */
developer42c7a432024-07-12 14:39:29 +0800129 /* FIXME: hardcode */
130 band_info.eht = true;
developerd0c89452024-10-11 16:53:27 +0800131 eht_phy_cap = 2;
132 /* eht_phy_cap |= ift.eht_cap_phy[0]; */
developer753619c2024-02-22 13:42:45 +0800133 }
134
developer42c7a432024-07-12 14:39:29 +0800135 if (band_name == "6G" && band_info.eht)
136 band_info.max_width = 320;
137 else if (band_name != "2G" &&
developer753619c2024-02-22 13:42:45 +0800138 (he_phy_cap & 0x18) || ((band.vht_capa >> 2) & 0x3))
139 band_info.max_width = 160;
140 else if (band_name != "2G" &&
141 (he_phy_cap & 4) || band.vht_capa > 0)
142 band_info.max_width = 80;
143 else if ((band.ht_capa & 0x2) || (he_phy_cap & 0x2))
144 band_info.max_width = 40;
145 else
146 band_info.max_width = 20;
147
148 let modes = band_info.modes = [ "NOHT" ];
149 if (band_info.ht)
150 push(modes, "HT20");
151 if (band_info.vht)
152 push(modes, "VHT20");
153 if (band_info.he)
154 push(modes, "HE20");
developer42c7a432024-07-12 14:39:29 +0800155 if (band_info.eht)
156 push(modes, "EHT20");
developer753619c2024-02-22 13:42:45 +0800157 if (band.ht_capa & 0x2) {
158 push(modes, "HT40");
159 if (band_info.vht)
160 push(modes, "VHT40")
161 }
developerd0c89452024-10-11 16:53:27 +0800162 if (he_phy_cap & 2)
developer753619c2024-02-22 13:42:45 +0800163 push(modes, "HE40");
164
developerd0c89452024-10-11 16:53:27 +0800165 if (eht_phy_cap && he_phy_cap & 2)
166 push(modes, "EHT40");
developer42c7a432024-07-12 14:39:29 +0800167
168 for (let freq in band.freqs) {
169 if (freq.disabled)
170 continue;
171 let chan = freq_to_channel(freq.freq);
172 if (!chan)
173 continue;
174 band_info.default_channel = chan;
175 break;
176 }
177
developer753619c2024-02-22 13:42:45 +0800178 if (band_name == "2G")
179 continue;
developerd0c89452024-10-11 16:53:27 +0800180
181 if (he_phy_cap & 4)
182 push(modes, "HE40");
183 if (eht_phy_cap && he_phy_cap & 4)
184 push(modes, "EHT40");
developer753619c2024-02-22 13:42:45 +0800185 if (band_info.vht)
186 push(modes, "VHT80");
developerd0c89452024-10-11 16:53:27 +0800187 if (he_phy_cap & 4)
developer753619c2024-02-22 13:42:45 +0800188 push(modes, "HE80");
developerd0c89452024-10-11 16:53:27 +0800189 if (eht_phy_cap && he_phy_cap & 4)
190 push(modes, "EHT80");
developer753619c2024-02-22 13:42:45 +0800191 if ((band.vht_capa >> 2) & 0x3)
192 push(modes, "VHT160");
developerd0c89452024-10-11 16:53:27 +0800193 if (he_phy_cap & 0x18)
developer753619c2024-02-22 13:42:45 +0800194 push(modes, "HE160");
developerd0c89452024-10-11 16:53:27 +0800195 if (eht_phy_cap && he_phy_cap & 0x18)
196 push(modes, "EHT160");
197
198 if (eht_phy_cap & 2)
developer42c7a432024-07-12 14:39:29 +0800199 push(modes, "EHT320");
developer753619c2024-02-22 13:42:45 +0800200 }
201
202 let entry = wiphy_get_entry(name, path);
203 entry.info = info;
204 }
205}
206
207cleanup();
208wiphy_detect();
209if (!is_equal(prev_board_data, board_data)) {
210 let new_file = board_file + ".new";
211 unlink(new_file);
212 let f = open(new_file, "wx");
213 if (!f)
214 exit(1);
215 f.write(sprintf("%.J\n", board_data));
216 f.close();
217 rename(new_file, board_file);
218}