wifi-detect.uc 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #!/usr/bin/env ucode
  2. 'use strict';
  3. import { readfile, writefile, realpath, glob, basename, unlink, open, rename } from "fs";
  4. import { is_equal } from "/usr/share/hostap/common.uc";
  5. let nl = require("nl80211");
  6. let board_file = "/etc/board.json";
  7. let prev_board_data = json(readfile(board_file));
  8. let board_data = json(readfile(board_file));
  9. function phy_idx(name) {
  10. return +rtrim(readfile(`/sys/class/ieee80211/${name}/index`));
  11. }
  12. function phy_path(name) {
  13. let devpath = realpath(`/sys/class/ieee80211/${name}/device`);
  14. devpath = replace(devpath, /^\/sys\/devices\//, "");
  15. if (match(devpath, /^platform\/.*\/pci/))
  16. devpath = replace(devpath, /^platform\//, "");
  17. let dev_phys = map(glob(`/sys/class/ieee80211/${name}/device/ieee80211/*`), basename);
  18. sort(dev_phys, (a, b) => phy_idx(a) - phy_idx(b));
  19. let ofs = index(dev_phys, name);
  20. if (ofs > 0)
  21. devpath += `+${ofs}`;
  22. return devpath;
  23. }
  24. function cleanup() {
  25. let wlan = board_data.wlan;
  26. for (let name in wlan)
  27. if (substr(name, 0, 3) == "phy")
  28. delete wlan[name];
  29. else
  30. delete wlan[name].info;
  31. }
  32. function wiphy_get_entry(phy, path) {
  33. let wlan = board_data.wlan;
  34. for (let name in wlan)
  35. if (wlan[name].path == path)
  36. return wlan[name];
  37. wlan[phy] = {
  38. path: path
  39. };
  40. return wlan[phy];
  41. }
  42. function wiphy_detect() {
  43. let phys = nl.request(nl.const.NL80211_CMD_GET_WIPHY, nl.const.NLM_F_DUMP, { split_wiphy_dump: true });
  44. if (!phys)
  45. return;
  46. for (let phy in phys) {
  47. let name = phy.wiphy_name;
  48. let path = phy_path(name);
  49. let info = {
  50. antenna_rx: phy.wiphy_antenna_avail_rx,
  51. antenna_tx: phy.wiphy_antenna_avail_tx,
  52. bands: {},
  53. };
  54. let bands = info.bands;
  55. for (let band in phy.wiphy_bands) {
  56. if (!band || !band.freqs)
  57. continue;
  58. let freq = band.freqs[0].freq;
  59. let band_info = {};
  60. let band_name;
  61. if (freq > 50000)
  62. band_name = "60G";
  63. else if (freq > 5900)
  64. band_name = "6G";
  65. else if (freq > 4000)
  66. band_name = "5G";
  67. else
  68. band_name = "2G";
  69. bands[band_name] = band_info;
  70. if (band.ht_capa > 0)
  71. band_info.ht = true;
  72. if (band.vht_capa > 0)
  73. band_info.vht = true;
  74. let he_phy_cap = 0;
  75. for (let ift in band.iftype_data) {
  76. if (!ift.he_cap_phy)
  77. continue;
  78. band_info.he = true;
  79. he_phy_cap |= ift.he_cap_phy[0];
  80. /* TODO: EHT */
  81. }
  82. if (band_name != "2G" &&
  83. (he_phy_cap & 0x18) || ((band.vht_capa >> 2) & 0x3))
  84. band_info.max_width = 160;
  85. else if (band_name != "2G" &&
  86. (he_phy_cap & 4) || band.vht_capa > 0)
  87. band_info.max_width = 80;
  88. else if ((band.ht_capa & 0x2) || (he_phy_cap & 0x2))
  89. band_info.max_width = 40;
  90. else
  91. band_info.max_width = 20;
  92. let modes = band_info.modes = [ "NOHT" ];
  93. if (band_info.ht)
  94. push(modes, "HT20");
  95. if (band_info.vht)
  96. push(modes, "VHT20");
  97. if (band_info.he)
  98. push(modes, "HE20");
  99. if (band.ht_capa & 0x2) {
  100. push(modes, "HT40");
  101. if (band_info.vht)
  102. push(modes, "VHT40")
  103. }
  104. if (he_phy_cap & 0x2)
  105. push(modes, "HE40");
  106. if (band_name == "2G")
  107. continue;
  108. if (band_info.vht)
  109. push(modes, "VHT80");
  110. if (he_phy_cap & 4)
  111. push(modes, "HE80");
  112. if ((band.vht_capa >> 2) & 0x3)
  113. push(modes, "VHT160");
  114. if (he_phy_cap & 0x18)
  115. push(modes, "HE160");
  116. }
  117. let entry = wiphy_get_entry(name, path);
  118. entry.info = info;
  119. }
  120. }
  121. cleanup();
  122. wiphy_detect();
  123. if (!is_equal(prev_board_data, board_data)) {
  124. let new_file = board_file + ".new";
  125. unlink(new_file);
  126. let f = open(new_file, "wx");
  127. if (!f)
  128. exit(1);
  129. f.write(sprintf("%.J\n", board_data));
  130. f.close();
  131. rename(new_file, board_file);
  132. }