mediatek: add mtwifi-cfg for configure mt_wifi

This commit is contained in:
hanwckf 2023-11-23 18:50:06 +08:00
parent 95c3efbca9
commit 3951b5a04a
12 changed files with 4020 additions and 0 deletions

View File

@ -0,0 +1,53 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=mtwifi-cfg
PKG_VERSION:=1
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/mtwifi-cfg
SECTION:=MTK Properties
CATEGORY:=MTK Properties
SUBMENU:=Applications
TITLE:=mtwifi configure scripts for mt798x
DEPENDS:=+iwinfo +wifi-dats +lua-cjson +datconf-lua @!PACKAGE_luci-app-mtk @!PACKAGE_wifi-profile
endef
define Package/mtwifi-cfg-luci
SECTION:=MTK Properties
CATEGORY:=MTK Properties
SUBMENU:=Applications
TITLE:=luci files for mtwifi configure scripts
DEPENDS:=+mtwifi-cfg +luci
endef
define Build/Compile
endef
define Package/mtwifi-cfg/install
$(INSTALL_DIR) $(1)/sbin $(1)/usr/lib/lua
$(INSTALL_DIR) $(1)/lib/netifd/wireless/ $(1)/lib/wifi/
$(INSTALL_DIR) $(1)/etc/hotplug.d/net/
$(INSTALL_BIN) ./files/netifd/mtwifi.sh $(1)/lib/netifd/wireless/
$(INSTALL_BIN) ./files/mtwifi.sh $(1)/lib/wifi/
$(INSTALL_BIN) ./files/mtwifi-cfg/mtwifi_cfg $(1)/sbin/
$(INSTALL_BIN) ./files/mtwifi-cfg/inspect.lua $(1)/usr/lib/lua/
$(INSTALL_BIN) ./files/mtwifi-cfg/mtwifi_defs.lua $(1)/usr/lib/lua/
$(INSTALL_BIN) ./files/mtwifi-cfg/mtwifi_utils.lua $(1)/usr/lib/lua/
$(INSTALL_BIN) ./files/l1util/l1util $(1)/sbin/
$(INSTALL_BIN) ./files/l1util/l1dat_parser.lua $(1)/usr/lib/lua/
$(INSTALL_DATA) ./files/hotplug/10-mtwifi-detect $(1)/etc/hotplug.d/net/
endef
define Package/mtwifi-cfg-luci/install
$(INSTALL_DIR) $(1)/etc/uci-defaults/ $(1)/www/luci-static/resources/view/network/
$(INSTALL_DATA) ./files/luci/wireless-mtk.js $(1)/www/luci-static/resources/view/network/wireless-mtk.js
$(INSTALL_DATA) ./files/luci/mtwifi-cfg-luci.default $(1)/etc/uci-defaults/20-mtwifi-cfg-luci.default
endef
$(eval $(call BuildPackage,mtwifi-cfg))
$(eval $(call BuildPackage,mtwifi-cfg-luci))

View File

@ -0,0 +1,9 @@
#!/bin/sh
[ "${ACTION}" = "add" ] && [ "${INTERFACE%%[0-9]}" = "ra" ] && {
if [ ! -f /etc/config/wireless ]; then
need_up=1
fi
/sbin/wifi config
[ "$need_up" = "1" ] && /sbin/wifi up
}

View File

@ -0,0 +1,263 @@
#!/usr/bin/env lua
--[[
* A lua library to manipulate mtk's wifi driver. used in luci-app-mtk.
*
* Copyright (C) 2016 MTK <support@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
]]
local l1dat_parser = {
L1_DAT_PATH = "/etc/wireless/l1profile.dat",
IF_RINDEX = "ifname_ridx",
DEV_RINDEX = "devname_ridx",
MAX_NUM_APCLI = 1,
MAX_NUM_WDS = 4,
MAX_NUM_MESH = 1,
MAX_NUM_EXTIF = 16,
MAX_NUM_DBDC_BAND = 2,
}
local l1cfg_options = {
ext_ifname="",
apcli_ifname="apcli",
wds_ifname="wds",
mesh_ifname="mesh"
}
function l1dat_parser.__trim(s)
if s then return (s:gsub("^%s*(.-)%s*$", "%1")) end
end
function l1dat_parser.__cfg2list(str)
-- delimeter == ";"
local i = 1
local list = {}
for k in string.gmatch(str, "([^;]+)") do
list[i] = k
i = i + 1
end
return list
end
function l1dat_parser.token_get(str, n, v)
-- n starts from 1
-- v is the backup in case token n is nil
if not str then return v end
local tmp = l1dat_parser.__cfg2list(str)
return tmp[tonumber(n)] or v
end
function l1dat_parser.add_default_value(l1cfg)
for k, v in ipairs(l1cfg) do
for opt, default in pairs(l1cfg_options) do
if ( opt == "ext_ifname" ) then
v[opt] = v[opt] or v["main_ifname"].."_"
else
v[opt] = v[opt] or default..k.."_"
end
end
end
return l1cfg
end
function l1dat_parser.get_value_by_idx(devidx, mainidx, subidx, key)
--print("Enter l1dat_parser.get_value_by_idx("..devidx..","..mainidx..", "..subidx..", "..key..")<br>")
if not devidx or not mainidx or not key then return end
local devs = l1dat_parser.load_l1_profile(l1dat_parser.L1_DAT_PATH)
if not devs then return end
local dev_ridx = l1dat_parser.DEV_RINDEX
local sidx = subidx or 1
local devname1 = devidx.."_"..mainidx
local devname2 = devidx.."_"..mainidx.."_"..sidx
--print("devnam1=", devname1, "devname2=", devname2, "<br>")
return devs[dev_ridx][devname2] and devs[dev_ridx][devname2][key]
or devs[dev_ridx][devname1] and devs[dev_ridx][devname1][key]
end
function l1dat_parser.l1_ifname_to_datpath(ifname)
if not ifname then return end
local devs = l1dat_parser.load_l1_profile(l1dat_parser.L1_DAT_PATH)
if not devs then return end
local ridx = l1dat_parser.IF_RINDEX
return devs[ridx][ifname] and devs[ridx][ifname].profile_path
end
-- input: L1 profile path.
-- output A table, devs, contains
-- 1. devs[%d] = table of each INDEX# in the L1 profile
-- 2. devs.ifname_ridx[ifname]
-- = table of each ifname and point to relevant contain in dev[$d]
-- 3. devs.devname_ridx[devname] similar to devs.ifnameridx, but use devname.
-- devname = INDEX#_value.mainidx(.subidx)
-- Using *_ridx do not need to handle name=k1;k2 case of DBDC card.
function l1dat_parser.load_l1_profile(path)
local devs = setmetatable({}, {__index=
function(tbl, key)
--local util = require("luci.util")
--print("metatable function:", util.serialize_data(tbl), key)
--print("-----------------------------------------------")
if ( string.match(key, "^%d+")) then
tbl[key] = {}
return tbl[key]
end
end
})
local nixio = require("nixio")
local chipset_num = {}
local dir = io.popen("ls /etc/wireless/")
if not dir then return end
local fd = io.open(path, "r")
if not fd then return end
-- convert l1 profile into lua table
for line in fd:lines() do
line = l1dat_parser.__trim(line)
if string.byte(line) ~= string.byte("#") then
local i = string.find(line, "=")
if i then
local k, v, k1, k2
k = l1dat_parser.__trim( string.sub(line, 1, i-1) )
v = l1dat_parser.__trim( string.sub(line, i+1) )
k1, k2 = string.match(k, "INDEX(%d+)_(.+)")
if k1 then
k1 = tonumber(k1) + 1
if devs[k1][k2] then
nixio.syslog("warning", "skip repeated key"..line)
end
devs[k1][k2] = v or ""
else
k1 = string.match(k, "INDEX(%d+)")
k1 = tonumber(k1) + 1
devs[k1]["INDEX"] = v
chipset_num[v] = (not chipset_num[v] and 1) or chipset_num[v] + 1
devs[k1]["mainidx"] = chipset_num[v]
end
--else
-- nixio.syslog("warning", "skip line without '=' "..line)
end
--else
-- nixio.syslog("warning", "skip comment line "..line)
end
end
l1dat_parser.add_default_value(devs)
--local util = require("luci.util")
--local seen2 = {}
-- print("Before setup ridx", util.serialize_data(devs, seen2))
-- Force to setup reverse indice for quick search.
-- Benifit:
-- 1. O(1) search with ifname, devname
-- 2. Seperate DBDC name=k1;k2 format in the L1 profile into each
-- ifname, devname.
local dbdc_if = {}
local ridx = l1dat_parser.IF_RINDEX
local dridx = l1dat_parser.DEV_RINDEX
local band_num = l1dat_parser.MAX_NUM_DBDC_BAND
local k, v, dev, i , j, last
local devname
devs[ridx] = {}
devs[dridx] = {}
for _, dev in ipairs(devs) do
dbdc_if[band_num] = l1dat_parser.token_get(dev.main_ifname, band_num, nil)
if dbdc_if[band_num] then
for i = 1, band_num - 1 do
dbdc_if[i] = l1dat_parser.token_get(dev.main_ifname, i, nil)
end
for i = 1, band_num do
devs[ridx][dbdc_if[i]] = {}
devs[ridx][dbdc_if[i]]["subidx"] = i
for k, v in pairs(dev) do
if k == "INDEX" or k == "EEPROM_offset" or k == "EEPROM_size"
or k == "mainidx" then
devs[ridx][dbdc_if[i]][k] = v
else
devs[ridx][dbdc_if[i]][k] = l1dat_parser.token_get(v, i, "")
end
end
devname = dev.INDEX.."_"..dev.mainidx.."_"..devs[ridx][dbdc_if[i]]["subidx"]
devs[dridx][devname] = devs[ridx][dbdc_if[i]]
end
local apcli_if, wds_if, ext_if, mesh_if = {}, {}, {}, {}
for i = 1, band_num do
ext_if[i] = l1dat_parser.token_get(dev.ext_ifname, i, nil)
apcli_if[i] = l1dat_parser.token_get(dev.apcli_ifname, i, nil)
wds_if[i] = l1dat_parser.token_get(dev.wds_ifname, i, nil)
mesh_if[i] = l1dat_parser.token_get(dev.mesh_ifname, i, nil)
end
for i = 1, l1dat_parser.MAX_NUM_EXTIF - 1 do -- ifname idx is from 0
for j = 1, band_num do
devs[ridx][ext_if[j]..i] = devs[ridx][dbdc_if[j]]
end
end
for i = 0, l1dat_parser.MAX_NUM_APCLI - 1 do
for j = 1, band_num do
devs[ridx][apcli_if[j]..i] = devs[ridx][dbdc_if[j]]
end
end
for i = 0, l1dat_parser.MAX_NUM_WDS - 1 do
for j = 1, band_num do
devs[ridx][wds_if[j]..i] = devs[ridx][dbdc_if[j]]
end
end
for i = 0, l1dat_parser.MAX_NUM_MESH - 1 do
for j = 1, band_num do
if mesh_if[j] then
devs[ridx][mesh_if[j]..i] = devs[ridx][dbdc_if[j]]
end
end
end
else
devs[ridx][dev.main_ifname] = dev
devname = dev.INDEX.."_"..dev.mainidx
devs[dridx][devname] = dev
for i = 1, l1dat_parser.MAX_NUM_EXTIF - 1 do -- ifname idx is from 0
devs[ridx][dev.ext_ifname..i] = dev
end
for i = 0, l1dat_parser.MAX_NUM_APCLI - 1 do -- ifname idx is from 0
devs[ridx][dev.apcli_ifname..i] = dev
end
for i = 0, l1dat_parser.MAX_NUM_WDS - 1 do -- ifname idx is from 0
devs[ridx][dev.wds_ifname..i] = dev
end
for i = 0, l1dat_parser.MAX_NUM_MESH - 1 do -- ifname idx is from 0
devs[ridx][dev.mesh_ifname..i] = dev
end
end
end
fd:close()
return devs
end
return l1dat_parser

View File

@ -0,0 +1,56 @@
#!/usr/bin/lua
--[[
*
* Copyright (C) 2023 hanwckf <hanwckf@vip.qq.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* The Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
]]
local l1parser = require("l1dat_parser")
local l1dat = l1parser.load_l1_profile(l1parser.L1_DAT_PATH)
if not l1dat then
return
end
function show_devs()
local ret = ""
for k, _ in pairs(l1dat.devname_ridx) do
if #ret > 0 then
ret = ret .. " " .. k
else
ret = k
end
end
print(ret)
end
function get_dev_prop(dev, prop)
if l1dat.devname_ridx[dev] then
print(l1dat.devname_ridx[dev][prop])
end
end
local action = {
["list"] = function()
show_devs()
end,
["get"] = function(dev, prop)
get_dev_prop(dev, prop)
end
}
if #arg == 1 then
action[arg[1]]()
elseif #arg == 3 then
action[arg[1]](arg[2], arg[3])
end

View File

@ -0,0 +1,3 @@
#!/bin/sh
mv /www/luci-static/resources/view/network/wireless-mtk.js /www/luci-static/resources/view/network/wireless.js

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,337 @@
local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local math = _tl_compat and _tl_compat.math or math; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table
local inspect = {Options = {}, }
inspect._VERSION = 'inspect.lua 3.1.0'
inspect._URL = 'http://github.com/kikito/inspect.lua'
inspect._DESCRIPTION = 'human-readable representations of tables'
inspect._LICENSE = [[
MIT LICENSE
Copyright (c) 2022 Enrique García Cota
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
inspect.KEY = setmetatable({}, { __tostring = function() return 'inspect.KEY' end })
inspect.METATABLE = setmetatable({}, { __tostring = function() return 'inspect.METATABLE' end })
local tostring = tostring
local rep = string.rep
local match = string.match
local char = string.char
local gsub = string.gsub
local fmt = string.format
local function rawpairs(t)
return next, t, nil
end
local function smartQuote(str)
if match(str, '"') and not match(str, "'") then
return "'" .. str .. "'"
end
return '"' .. gsub(str, '"', '\\"') .. '"'
end
local shortControlCharEscapes = {
["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\127"] = "\\127",
}
local longControlCharEscapes = { ["\127"] = "\127" }
for i = 0, 31 do
local ch = char(i)
if not shortControlCharEscapes[ch] then
shortControlCharEscapes[ch] = "\\" .. i
longControlCharEscapes[ch] = fmt("\\%03d", i)
end
end
local function escape(str)
return (gsub(gsub(gsub(str, "\\", "\\\\"),
"(%c)%f[0-9]", longControlCharEscapes),
"%c", shortControlCharEscapes))
end
local function isIdentifier(str)
return type(str) == "string" and not not str:match("^[_%a][_%a%d]*$")
end
local flr = math.floor
local function isSequenceKey(k, sequenceLength)
return type(k) == "number" and
flr(k) == k and
1 <= (k) and
k <= sequenceLength
end
local defaultTypeOrders = {
['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,
['function'] = 5, ['userdata'] = 6, ['thread'] = 7,
}
local function sortKeys(a, b)
local ta, tb = type(a), type(b)
if ta == tb and (ta == 'string' or ta == 'number') then
return (a) < (b)
end
local dta = defaultTypeOrders[ta] or 100
local dtb = defaultTypeOrders[tb] or 100
return dta == dtb and ta < tb or dta < dtb
end
local function getKeys(t)
local seqLen = 1
while rawget(t, seqLen) ~= nil do
seqLen = seqLen + 1
end
seqLen = seqLen - 1
local keys, keysLen = {}, 0
for k in rawpairs(t) do
if not isSequenceKey(k, seqLen) then
keysLen = keysLen + 1
keys[keysLen] = k
end
end
table.sort(keys, sortKeys)
return keys, keysLen, seqLen
end
local function countCycles(x, cycles)
if type(x) == "table" then
if cycles[x] then
cycles[x] = cycles[x] + 1
else
cycles[x] = 1
for k, v in rawpairs(x) do
countCycles(k, cycles)
countCycles(v, cycles)
end
countCycles(getmetatable(x), cycles)
end
end
end
local function makePath(path, a, b)
local newPath = {}
local len = #path
for i = 1, len do newPath[i] = path[i] end
newPath[len + 1] = a
newPath[len + 2] = b
return newPath
end
local function processRecursive(process,
item,
path,
visited)
if item == nil then return nil end
if visited[item] then return visited[item] end
local processed = process(item, path)
if type(processed) == "table" then
local processedCopy = {}
visited[item] = processedCopy
local processedKey
for k, v in rawpairs(processed) do
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
if processedKey ~= nil then
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
end
end
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
if type(mt) ~= 'table' then mt = nil end
setmetatable(processedCopy, mt)
processed = processedCopy
end
return processed
end
local function puts(buf, str)
buf.n = buf.n + 1
buf[buf.n] = str
end
local Inspector = {}
local Inspector_mt = { __index = Inspector }
local function tabify(inspector)
puts(inspector.buf, inspector.newline .. rep(inspector.indent, inspector.level))
end
function Inspector:getId(v)
local id = self.ids[v]
local ids = self.ids
if not id then
local tv = type(v)
id = (ids[tv] or 0) + 1
ids[v], ids[tv] = id, id
end
return tostring(id)
end
function Inspector:putValue(v)
local buf = self.buf
local tv = type(v)
if tv == 'string' then
puts(buf, smartQuote(escape(v)))
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or
tv == 'cdata' or tv == 'ctype' then
puts(buf, tostring(v))
elseif tv == 'table' and not self.ids[v] then
local t = v
if t == inspect.KEY or t == inspect.METATABLE then
puts(buf, tostring(t))
elseif self.level >= self.depth then
puts(buf, '{...}')
else
if self.cycles[t] > 1 then puts(buf, fmt('<%d>', self:getId(t))) end
local keys, keysLen, seqLen = getKeys(t)
puts(buf, '{')
self.level = self.level + 1
for i = 1, seqLen + keysLen do
if i > 1 then puts(buf, ',') end
if i <= seqLen then
puts(buf, ' ')
self:putValue(t[i])
else
local k = keys[i - seqLen]
tabify(self)
if isIdentifier(k) then
puts(buf, k)
else
puts(buf, "[")
self:putValue(k)
puts(buf, "]")
end
puts(buf, ' = ')
self:putValue(t[k])
end
end
local mt = getmetatable(t)
if type(mt) == 'table' then
if seqLen + keysLen > 0 then puts(buf, ',') end
tabify(self)
puts(buf, '<metatable> = ')
self:putValue(mt)
end
self.level = self.level - 1
if keysLen > 0 or type(mt) == 'table' then
tabify(self)
elseif seqLen > 0 then
puts(buf, ' ')
end
puts(buf, '}')
end
else
puts(buf, fmt('<%s %d>', tv, self:getId(v)))
end
end
function inspect.inspect(root, options)
options = options or {}
local depth = options.depth or (math.huge)
local newline = options.newline or '\n'
local indent = options.indent or ' '
local process = options.process
if process then
root = processRecursive(process, root, {}, {})
end
local cycles = {}
countCycles(root, cycles)
local inspector = setmetatable({
buf = { n = 0 },
ids = {},
cycles = cycles,
depth = depth,
level = 0,
newline = newline,
indent = indent,
}, Inspector_mt)
inspector:putValue(root)
return table.concat(inspector.buf)
end
setmetatable(inspect, {
__call = function(_, root, options)
return inspect.inspect(root, options)
end,
})
return inspect

View File

@ -0,0 +1,538 @@
#!/usr/bin/lua
--[[
*
* Copyright (C) 2023 hanwckf <hanwckf@vip.qq.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* The Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
]]
local cjson = require "cjson"
local inspect = require "inspect"
local nixio = require "nixio"
local l1parser = require "l1dat_parser"
local datconf = require "datconf"
local utils = require "mtwifi_utils"
local defs = require "mtwifi_defs"
local l1dat = l1parser.load_l1_profile(l1parser.L1_DAT_PATH)
function string:split(sep)
local sep, fields = sep or ":", {}
local pattern = string.format("([^%s]+)", sep)
self:gsub(pattern, function(c) fields[#fields+1] = c end)
return fields
end
function load_profile(path)
local cfgs = {}
cfgobj = datconf.openfile(path)
if cfgobj then
cfgs = cfgobj:getall()
cfgobj:close()
end
return cfgs
end
function save_profile(cfgs, path)
if not cfgs then
return
end
local datobj = datconf.openfile(path)
datobj:merge(cfgs)
datobj:close(true)
os.execute("sync")
end
function diff_cfg(cfg1, cfg2)
local diff = {}
for k,v in pairs(cfg1) do
if tostring(cfg2[k]) ~= tostring(cfg1[k]) then
diff[k] = {cfg1[k] or "", cfg2[k] or ""}
end
end
for k,v in pairs(cfg2) do
if tostring(cfg2[k]) ~= tostring(cfg1[k]) then
diff[k] = {cfg1[k] or "", cfg2[k] or ""}
end
end
return diff
end
function vif_status(ifname)
local flags = tonumber(utils.read_pipe("cat /sys/class/net/"..ifname.."/flags 2>/dev/null")) or 0
if flags%2 == 1 then
return "up"
end
return "down"
end
function is_dbdc_inited(ifname)
local mac = utils.trim(utils.read_pipe("cat /sys/class/net/"..ifname.."/address 2>/dev/null"))
if mac and mac ~= "00:00:00:00:00:00" then
return true
end
return false
end
function ifup(ifname)
if ifname and #ifname > 0 then
os.execute("ifconfig "..ifname.." up")
end
end
function ifdown(ifname)
if ifname and #ifname > 0 then
os.execute("ifconfig "..ifname.." down")
end
end
function cfg2dat(cfg)
if type(cfg) == type(true) then
if cfg then return 1 else return 0 end
elseif type(cfg) == type(0) or type(cfg) == type("") then
return cfg
end
end
function set_dat(dats, apidx, dat, cfg)
if cfg ~= nil then
dats[dat] = utils.token_set(dats[dat], apidx, cfg2dat(cfg))
end
end
function set_idx_dat(dats, apidx, dat, cfg)
if cfg ~= nil then
dats[dat..tostring(apidx)] = cfg
end
end
function mtwifi_up(devname, cfg, restore_vifs, is_dbdc)
nixio.syslog("info", "mtwifi-cfg: start "..devname)
local dev = l1dat.devname_ridx[devname]
local dbdc_main_ifname = defs.dbdc_init_ifname
if not dev then return end
if is_dbdc then
if not is_dbdc_inited(dbdc_main_ifname) then
nixio.syslog("info", "mtwifi-cfg: dbdc card init...")
ifup(dbdc_main_ifname)
utils.sleep(1)
ifdown(dbdc_main_ifname)
end
if restore_vifs and devname ~= cfg.device then
for _,vif in ipairs(restore_vifs) do
nixio.syslog("info", "mtwifi-cfg: restore vif: "..vif)
ifup(vif)
end
return
end
end
-- start vifs
for _, v in pairs(cfg.interfaces) do
local mode = v.config.mode
if mode and (mode == "ap" or mode == "sta")
and (not v.config.disabled) and v.mtwifi_ifname then
local vif = v.mtwifi_ifname
nixio.syslog("info", "mtwifi-cfg: up vif: "..vif)
ifup(vif)
end
end
end
function mtwifi_down(devname, cfg)
nixio.syslog("info", "mtwifi-cfg: stop "..devname)
local dev = l1dat.devname_ridx[devname]
local reset_vifs = {}
if not dev then return end
for _,vif in ipairs(string.split(utils.read_pipe("ls /sys/class/net"), "\n")) do
if (vif_status(vif) == "up" and (vif == dev.main_ifname
or string.match(vif, utils.esc(dev.ext_ifname).."[0-9]+")
or string.match(vif, utils.esc(dev.apcli_ifname).."[0-9]+")
or string.match(vif, utils.esc(dev.wds_ifname).."[0-9]+")
or string.match(vif, utils.esc(dev.mesh_ifname).."[0-9]+")))
then
nixio.syslog("info", "mtwifi-cfg: down vif: "..vif)
ifdown(vif)
if cfg and devname ~= cfg.device then
reset_vifs[#reset_vifs+1] = vif
end
end
end
return reset_vifs
end
function mtwifi_reinstall()
nixio.syslog("info", "mtwifi-cfg: unload mtwifi module...")
--os.execute("rmmod mt_whnat")
--os.execute("rmmod mtfwd")
os.execute("rmmod mtk_warp_proxy")
os.execute("rmmod mtk_warp")
--os.execute("rmmod mt7915_mt_wifi")
os.execute("rmmod mt_wifi")
utils.sleep(2)
nixio.syslog("info", "mtwifi-cfg: reload mtwifi module...")
os.execute("modprobe mt_wifi")
--os.execute("modprobe mt7915_mt_wifi")
os.execute("modprobe mtk_warp")
os.execute("modprobe mtk_warp_proxy")
--os.execute("modprobe mtfwd")
--os.execute("modprobe mt_whnat")
end
function mtwifi_cfg_setup(argv)
local cfg = cjson.decode(argv)
utils.log2file("input = " .. inspect(cfg))
local devname = cfg.device
local dev = l1dat.devname_ridx[devname]
if not dev then return end
local profile = dev.profile_path
local dats = load_profile(profile)
if not dats then
nixio.syslog("err", "mtwifi-cfg: profile ".. profile .. "open failed")
return
end
local dats_orig = load_profile(profile)
local bssid_num = 0
local vif_num = 0
for k,v in pairs(cfg.interfaces) do
vif_num = vif_num + 1
if v.config.mode == "ap" then
bssid_num = bssid_num + 1
end
end
if vif_num == 0 then
nixio.syslog("err", "mtwifi-cfg: not valid vif found!")
return
elseif vif_num > defs.max_mbssid then
nixio.syslog("err", "mtwifi-cfg: too many vifs!")
return
end
if bssid_num > 0 then
dats.BssidNum = bssid_num
else
dats.BssidNum = 1
end
-- setup apcli
dats.ApCliEnable = 0
dats.ApCliSsid = ""
dats.ApCliBssid = ""
dats.ApCliAuthMode = ""
dats.ApCliEncrypType = ""
dats.ApCliWPAPSK = ""
for _,v in pairs(cfg.interfaces) do
if v.config.mode == "sta" then
if not v.config.disabled then
dats.ApCliEnable = 1
end
dats.ApCliSsid = v.config.ssid
dats.ApCliBssid = v.config.bssid or ""
dats.ApCliAuthMode = defs.enc2dat[v.config.encryption][1]
dats.ApCliEncrypType = defs.enc2dat[v.config.encryption][2]
dats.ApCliWPAPSK = v.config.key or ""
break
end
end
-- setup dev cfgs
if cfg.config.twt then
dats.TWTSupport = 1
else
dats.TWTSupport = 0
end
if type(cfg.config.country) == type("") and #cfg.config.country == 2 then
dats.CountryCode = cfg.config.country
if cfg.config.band == "2g" then
dats.CountryRegion = defs.countryRegions[cfg.config.country][1]
elseif cfg.config.band == "5g" then
dats.CountryRegionABand = defs.countryRegions[cfg.config.country][2]
end
end
if cfg.config.channel == "auto" then
dats.AutoChannelSelect = 3
dats.Channel = 0
else
dats.AutoChannelSelect = 0
dats.Channel = cfg.config.channel
end
if cfg.config.htmode == "HT20" or cfg.config.htmode == "VHT20" or cfg.config.htmode == "HE20" then
dats.HT_BW = 0
dats.VHT_BW = 0
elseif cfg.config.htmode == "HT40" or cfg.config.htmode == "VHT40" or cfg.config.htmode == "HE40" then
dats.HT_BW = 1
dats.VHT_BW = 0
if cfg.config.noscan ~= nil and cfg.config.noscan == "1" then
dats.HT_BSSCoexistence = 0
else
dats.HT_BSSCoexistence = 1
end
elseif cfg.config.htmode == "VHT80" or cfg.config.htmode == "HE80" then
dats.HT_BW = 1
dats.VHT_BW = 1
elseif cfg.config.htmode == "VHT160" or cfg.config.htmode == "HE160" then
dats.HT_BW = 1
dats.VHT_BW = 2
end
if cfg.config.txpower and cfg.config.txpower < 100 then
dats.PERCENTAGEenable = 1
dats.TxPower = cfg.config.txpower
else
dats.PERCENTAGEenable = 0
dats.TxPower = 100
end
if cfg.config.mu_beamformer then
dats.ETxBfEnCond = 1
if dats.ApCliEnable == 1 then
dats.MUTxRxEnable = 3
else
dats.MUTxRxEnable = 1
end
dats.ITxBfEn = 0
else
dats.ETxBfEnCond = 0
dats.MUTxRxEnable = 0
dats.ITxBfEn = 0
end
local WirelessMode
if cfg.config.band == "2g" then
if string.sub(cfg.config.htmode,1,2) == "HE" then
WirelessMode = 16 -- PHY_11AX_24G
else
WirelessMode = 9 -- PHY_11BGN_MIXED
end
elseif cfg.config.band == "5g" then
if string.sub(cfg.config.htmode,1,2) == "HE" then
WirelessMode = 17 -- PHY_11AX_5G
else
WirelessMode = 15 -- PHY_11VHT_N_MIXED
end
end
-- reset vif cfgs to default
for k,v in pairs(defs.vif_cfgs) do
dats[k] = ""
for i = 1, bssid_num do
dats[k] = utils.token_set(dats[k], i, v)
end
end
for k,v in pairs(defs.vif_cfgs_idx) do
for i = 1, defs.max_mbssid do
dats[k..tostring(i)] = ""
end
for i = 1, bssid_num do
dats[k..tostring(i)] = v
end
end
for k,v in pairs(defs.vif_acl) do
for i = 0, defs.max_mbssid-1 do
dats[k..tostring(i)] = ""
end
for i = 0, bssid_num-1 do
dats[k..tostring(i)] = v
end
end
-- setup vif cfgs
local apidx = 1
for idx = 0,vif_num-1 do
v = cfg.interfaces[tostring(idx)]
if v.config.mode == "ap" then
set_idx_dat(dats, apidx, "SSID", v.config.ssid)
set_idx_dat(dats, apidx, "WPAPSK", v.config.key or "")
set_dat(dats, apidx, "NoForwarding", v.config.isolate)
set_dat(dats, apidx, "HideSSID", v.config.hidden)
set_dat(dats, apidx, "WmmCapable", v.config.wmm)
set_dat(dats, apidx, "RRMEnable", v.config.ieee80211k)
set_dat(dats, apidx, "RekeyInterval", v.config.wpa_group_rekey)
set_dat(dats, apidx, "MuMimoDlEnable",v.config.mumimo_dl)
set_dat(dats, apidx, "MuMimoUlEnable",v.config.mumimo_ul)
set_dat(dats, apidx, "MuOfdmaDlEnable",v.config.ofdma_dl)
set_dat(dats, apidx, "MuOfdmaUlEnable",v.config.ofdma_ul)
set_dat(dats, apidx, "HT_AMSDU",v.config.amsdu)
set_dat(dats, apidx, "HT_AutoBA",v.config.autoba)
set_dat(dats, apidx, "APSDCapable",v.config.uapsd)
set_dat(dats, apidx, "RTSThreshold", cfg.config.rts)
set_dat(dats, apidx, "FragThreshold",cfg.config.frag)
set_dat(dats, apidx, "WirelessMode", WirelessMode)
if v.config.macfilter then
if v.config.macfilter == "allow" then
set_idx_dat(dats, apidx-1, "AccessPolicy", 1)
elseif v.config.macfilter == "deny" then
set_idx_dat(dats, apidx-1, "AccessPolicy", 2)
end
end
if v.config.maclist then
local maclist = ""
for _, v in ipairs(v.config.maclist) do
if #maclist > 0 then
maclist = v .. ";" .. maclist
else
maclist = v
end
end
set_idx_dat(dats, apidx-1, "AccessControlList", maclist)
end
local authmode = defs.enc2dat[v.config.encryption][1]
set_dat(dats, apidx, "AuthMode", authmode)
set_dat(dats, apidx, "EncrypType", defs.enc2dat[v.config.encryption][2])
if authmode == "OWE" or authmode == "WPA3PSK" then
set_dat(dats, apidx, "PMFMFPC", 1)
set_dat(dats, apidx, "PMFMFPR", 1)
set_dat(dats, apidx, "PMFSHA256", 0)
elseif authmode == "WPA2PSKWPA3PSK" then
set_dat(dats, apidx, "PMFMFPC", 1)
set_dat(dats, apidx, "PMFMFPR", 0)
set_dat(dats, apidx, "PMFSHA256", 0)
end
if not (authmode == "OPEN" or authmode == "OWE") then
set_dat(dats, apidx, "RekeyMethod", "TIME")
end
apidx = apidx + 1
end
end
local reinstall_wifidrv = false
local cfg_diff = diff_cfg(dats_orig, dats)
utils.log2file("diff = " .. inspect(cfg_diff))
save_profile(dats, profile)
for _,v in pairs(defs.reinstall_cfgs) do
if cfg_diff[v] ~= nil then
if utils.exists("/sys/module/mt_wifi") == false then
nixio.syslog("err", "mtwifi-cfg: mtwifi module is build-in, please reboot the device!")
return
else
reinstall_wifidrv = true
end
end
end
if string.find(profile, "dbdc") then
if reinstall_wifidrv then
for k, _ in pairs(l1dat.devname_ridx) do
mtwifi_down(k)
end
mtwifi_reinstall()
for k, _ in pairs(l1dat.devname_ridx) do
if k == devname then
mtwifi_up(k, cfg, nil, true)
else
os.execute("/sbin/wifi up " .. k)
end
end
else
local restore_vifs = {}
local restart_other_dbdc_dev = false
if next(cfg_diff) ~= nil then
restart_other_dbdc_dev = true
end
if restart_other_dbdc_dev then
for k, _ in pairs(l1dat.devname_ridx) do
local ret = mtwifi_down(k, cfg)
for _, v in ipairs(ret) do
table.insert(restore_vifs, v)
end
end
if #restore_vifs > 0 then
nixio.syslog("info", "mtwifi-cfg: dbdc restore_vifs: "..inspect.inspect(restore_vifs))
end
for k, _ in pairs(l1dat.devname_ridx) do
mtwifi_up(k, cfg, restore_vifs, true)
end
else
mtwifi_down(devname)
mtwifi_up(devname, cfg, nil, true)
end
end
else
mtwifi_down(devname)
if reinstall_wifidrv then
mtwifi_reinstall()
end
mtwifi_up(devname, cfg)
end
end
function mtwifi_cfg_down(devname)
if devname then
mtwifi_down(devname)
else
for k, _ in pairs(l1dat.devname_ridx) do
mtwifi_down(k)
end
end
end
local action = {
["down"] = function(devname)
mtwifi_cfg_down(devname)
end,
["setup"] = function()
local argv = io.read()
if #argv > 0 then
mtwifi_cfg_setup(argv)
end
end
}
if #arg == 1 then
action[arg[1]]()
elseif #arg == 2 then
action[arg[1]](arg[2])
end

View File

@ -0,0 +1,219 @@
#!/usr/bin/lua
--[[
*
* Copyright (C) 2023 hanwckf <hanwckf@vip.qq.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* The Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
]]
local mtwifi_defs = {}
mtwifi_defs.dbdc_init_ifname = "ra0"
mtwifi_defs.max_mbssid = 16
mtwifi_defs.vif_cfgs = {
-- dat cfg = default val
["AuthMode"] = "OPEN",
["EncrypType"] = "NONE",
["PMFMFPC"] = "0",
["PMFMFPR"] = "0",
["PMFSHA256"] = "0",
["RekeyInterval"] = "3600",
["DefaultKeyID"] = "1",
["IEEE8021X"] = "0",
["Key1Type"] = "0",
["Key2Type"] = "0",
["Key3Type"] = "0",
["Key4Type"] = "0",
["PMKCachePeriod"] = "10",
["PreAuth"] = "0",
["RADIUS_Port"] = "1812",
["RADIUS_Server"] = "0",
["RekeyMethod"] = "DISABLE",
["session_timeout_interval"] = "0",
["Wapiifname"] = "",
["HideSSID"] = "0",
["WirelessMode"] = "",
["NoForwarding"] = "0",
["APSDCapable"] = "1",
["WmmCapable"] = "1",
["FragThreshold"] = "2346",
["RTSThreshold"] = "2347",
["HT_AMSDU"] = "1",
["HT_AutoBA"] = "1",
["HT_GI"] = "1",
["HT_LDPC"] = "1",
["HT_OpMode"] = "0",
["HT_PROTECT"] = "1",
["HT_STBC"] = "1",
["IgmpSnEnable"] = "0",
["RRMEnable"] = "1",
["VHT_BW_SIGNAL"] = "0",
["VHT_LDPC"] = "1",
["VHT_SGI"] = "1",
["VHT_STBC"] = "1",
["MuMimoDlEnable"] = "1",
["MuMimoUlEnable"] = "1",
["MuOfdmaDlEnable"] = "1",
["MuOfdmaUlEnable"] = "1",
["DLSCapable"] = "0",
["WdsEnable"] = "0",
["WscConfMode"] = "0",
}
mtwifi_defs.vif_cfgs_idx = {
["WPAPSK"] = "12345678",
["SSID"] = "",
["RADIUS_Key"] = "",
}
mtwifi_defs.vif_acl = {
["AccessPolicy"] = "0",
["AccessControlList"] = "",
}
mtwifi_defs.reinstall_cfgs = {
"BssidNum", "WHNAT", "E2pAccessMode",
"HT_RxStream", "HT_TxStream", "WdsEnable"
}
mtwifi_defs.enc2dat = {
-- enc = AuthMode, EncrypType
["none"] = {"OPEN", "NONE"},
["sae"] = {"WPA3PSK", "AES"},
["sae-mixed"] = {"WPA2PSKWPA3PSK", "AES"},
["psk2+tkip+ccmp"] = {"WPA2PSK", "TKIPAES"},
["psk2+tkip+aes"] = {"WPA2PSK", "TKIPAES"},
["psk2+tkip"] = {"WPA2PSK", "TKIP"},
["psk2+ccmp"] = {"WPA2PSK", "AES"},
["psk2+aes"] = {"WPA2PSK", "AES"},
["psk2"] = {"WPA2PSK", "AES"},
["psk+tkip+ccmp"] = {"WPAPSK", "AES"},
["psk+tkip+aes"] = {"WPAPSK", "AES"},
["psk+tkip"] = {"WPAPSK", "TKIP"},
["psk+ccmp"] = {"WPAPSK", "AES"},
["psk+aes"] = {"WPAPSK", "AES"},
["psk"] = {"WPAPSK", "AES"},
["psk-mixed+tkip+ccmp"] = {"WPAPSKWPA2PSK", "TKIPAES"},
["psk-mixed+tkip+aes"] = {"WPAPSKWPA2PSK", "TKIPAES"},
["psk-mixed+tkip"] = {"WPAPSKWPA2PSK", "TKIP"},
["psk-mixed+ccmp"] = {"WPAPSKWPA2PSK", "AES"},
["psk-mixed+aes"] = {"WPAPSKWPA2PSK", "AES"},
["psk-mixed"] = {"WPAPSKWPA2PSK", "AES"},
["owe"] = {"OWE", "AES"},
}
mtwifi_defs.countryRegions = {
-- CountryCode = 2g region, 5g region
["DB"] = { 5, 13 },
["AE"] = { 1, 0 },
["AL"] = { 1, 0 },
["AR"] = { 1, 3 },
["AT"] = { 1, 1 },
["AM"] = { 1, 2 },
["AU"] = { 1, 0 },
["AZ"] = { 1, 2 },
["BE"] = { 1, 1 },
["BH"] = { 1, 0 },
["BY"] = { 1, 0 },
["BO"] = { 1, 4 },
["BR"] = { 1, 1 },
["BN"] = { 1, 4 },
["BG"] = { 1, 1 },
["BZ"] = { 1, 4 },
["CA"] = { 0, 0 },
["CH"] = { 1, 1 },
["CL"] = { 1, 0 },
["CN"] = { 1, 0 },
["CO"] = { 0, 0 },
["CR"] = { 1, 0 },
["CY"] = { 1, 1 },
["CZ"] = { 1, 2 },
["DE"] = { 1, 1 },
["DK"] = { 1, 1 },
["DO"] = { 0, 0 },
["DZ"] = { 1, 0 },
["EC"] = { 1, 0 },
["EG"] = { 1, 2 },
["EE"] = { 1, 1 },
["ES"] = { 1, 1 },
["FI"] = { 1, 1 },
["FR"] = { 1, 2 },
["GE"] = { 1, 2 },
["GB"] = { 1, 1 },
["GR"] = { 1, 1 },
["GT"] = { 0, 0 },
["HN"] = { 1, 0 },
["HK"] = { 1, 0 },
["HU"] = { 1, 1 },
["HR"] = { 1, 2 },
["IS"] = { 1, 1 },
["IN"] = { 1, 0 },
["ID"] = { 1, 4 },
["IR"] = { 1, 4 },
["IE"] = { 1, 1 },
["IL"] = { 1, 0 },
["IT"] = { 1, 1 },
["JP"] = { 1, 9 },
["JO"] = { 1, 0 },
["KP"] = { 1, 5 },
["KR"] = { 1, 5 },
["KW"] = { 1, 0 },
["KZ"] = { 1, 0 },
["LB"] = { 1, 0 },
["LI"] = { 1, 1 },
["LT"] = { 1, 1 },
["LU"] = { 1, 1 },
["LV"] = { 1, 1 },
["MA"] = { 1, 0 },
["MC"] = { 1, 2 },
["MO"] = { 1, 0 },
["MK"] = { 1, 0 },
["MX"] = { 0, 0 },
["MY"] = { 1, 0 },
["NL"] = { 1, 1 },
["NO"] = { 0, 0 },
["NZ"] = { 1, 0 },
["OM"] = { 1, 0 },
["PA"] = { 0, 0 },
["PE"] = { 1, 4 },
["PH"] = { 1, 4 },
["PL"] = { 1, 1 },
["PK"] = { 1, 0 },
["PT"] = { 1, 1 },
["PR"] = { 0, 0 },
["QA"] = { 1, 0 },
["RO"] = { 1, 0 },
["RU"] = { 1, 0 },
["SA"] = { 1, 0 },
["SG"] = { 1, 0 },
["SK"] = { 1, 1 },
["SI"] = { 1, 1 },
["SV"] = { 1, 0 },
["SE"] = { 1, 1 },
["SY"] = { 1, 0 },
["TH"] = { 1, 0 },
["TN"] = { 1, 2 },
["TR"] = { 1, 2 },
["TT"] = { 1, 2 },
["TW"] = { 0, 3 },
["UA"] = { 1, 0 },
["US"] = { 0, 0 },
["UY"] = { 1, 5 },
["UZ"] = { 0, 1 },
["VE"] = { 1, 5 },
["VN"] = { 1, 0 },
["YE"] = { 1, 0 },
["ZA"] = { 1, 1 },
["ZW"] = { 1, 0 },
}
return mtwifi_defs

View File

@ -0,0 +1,96 @@
#!/usr/bin/lua
local mtwifi_utils = {}
local mtwifi_logfile = "/tmp/mtwifi.log"
function mtwifi_utils.esc(x)
return (x:gsub('%%', '%%%%')
:gsub('^%^', '%%^')
:gsub('%$$', '%%$')
:gsub('%(', '%%(')
:gsub('%)', '%%)')
:gsub('%.', '%%.')
:gsub('%[', '%%[')
:gsub('%]', '%%]')
:gsub('%*', '%%*')
:gsub('%+', '%%+')
:gsub('%-', '%%-')
:gsub('%?', '%%?'))
end
function mtwifi_utils.trim(s)
if s then return (s:gsub("^%s*(.-)%s*$", "%1")) end
end
function mtwifi_utils.exists(path)
local fp = io.open(path, "rb")
if fp then fp:close() end
return fp ~= nil
end
function mtwifi_utils.read_pipe(pipe)
local retry_count = 10
local fp, txt, err
repeat
fp = io.popen(pipe)
txt, err = fp:read("*a")
fp:close()
retry_count = retry_count - 1
until err == nil or retry_count == 0
return txt
end
function mtwifi_utils.__cfg2list(str)
-- delimeter == ";"
local i = 1
local list = {}
for k in string.gmatch(str, "([^;]+)") do
list[i] = k
i = i + 1
end
return list
end
function mtwifi_utils.token_set(str, n, v)
-- n start from 1
-- delimeter == ";"
if not str then return end
if v == nil then return end
local tmp = mtwifi_utils.__cfg2list(str)
if type(v) ~= type("") and type(v) ~= type(0) then
nixio.syslog("err", "invalid value type in token_set, "..type(v))
return
end
if #tmp < tonumber(n) then
for i=#tmp, tonumber(n) do
if not tmp[i] then
tmp[i] = v -- pad holes with v !
end
end
else
tmp[n] = v
end
return table.concat(tmp, ";"):gsub("^;*(.-);*$", "%1"):gsub(";+",";")
end
function mtwifi_utils.token_get(str, n, v)
-- n starts from 1
-- v is the backup in case token n is nil
if not str then return v end
local tmp = mtwifi_utils.__cfg2list(str)
return tmp[tonumber(n)] or v
end
function mtwifi_utils.sleep(s)
local ntime = os.clock() + s
repeat until os.clock() > ntime
end
function mtwifi_utils.log2file(str)
logfile = io.open(mtwifi_logfile, "a")
logfile:write(os.date("%H:%M:%S", os.time()) .. " " .. str .. "\n")
logfile:close()
end
return mtwifi_utils

View File

@ -0,0 +1,55 @@
#!/bin/sh
#
# Copyright (C) 2023, hanwckf <hanwckf@vip.qq.com>
#
append DRIVERS "mtwifi"
detect_mtwifi() {
local idx ifname
local band hwmode htmode htbsscoex ssid
if [ -d "/sys/module/mt_wifi" ]; then
dev_list="$(l1util list)"
for dev in $dev_list; do
config_get type ${dev} type
[ "$type" = "mtwifi" ] || {
ifname="$(l1util get ${dev} main_ifname)"
idx="$(l1util get ${dev} subidx)"
if [ $idx -eq 1 ]; then
band="2g"
hwmode="11g"
htmode="HE40"
htbsscoex="1"
ssid="ImmortalWrt-2.4G"
else
band="5g"
hwmode="11a"
htmode="HE160"
htbsscoex="0"
ssid="ImmortalWrt-5G"
fi
uci -q batch <<-EOF
set wireless.${dev}=wifi-device
set wireless.${dev}.type=mtwifi
set wireless.${dev}.phy=${ifname}
set wireless.${dev}.hwmode=${hwmode}
set wireless.${dev}.band=${band}
set wireless.${dev}.channel=auto
set wireless.${dev}.txpower=100
set wireless.${dev}.htmode=${htmode}
set wireless.${dev}.country=CN
set wireless.${dev}.mu_beamformer=1
set wireless.${dev}.noscan=${htbsscoex}
set wireless.default_${dev}=wifi-iface
set wireless.default_${dev}.device=${dev}
set wireless.default_${dev}.network=lan
set wireless.default_${dev}.mode=ap
set wireless.default_${dev}.ssid=${ssid}
set wireless.default_${dev}.encryption=none
EOF
uci -q commit wireless
}
done
fi
}

View File

@ -0,0 +1,140 @@
#!/bin/sh
#
# Copyright (c) 2023, hanwckf <hanwckf@vip.qq.com>
#
. /lib/netifd/netifd-wireless.sh
init_wireless_driver "$@"
LOCK_FILE="/tmp/mtwifi.lock"
MTWIFI_MAX_AP_IDX=15
MTWIFI_MAX_APCLI_IDX=0
MTWIFI_CFG_IFNAME_KEY="mtwifi_ifname"
drv_mtwifi_init_device_config() {
config_add_int txpower frag rts
config_add_boolean mu_beamformer twt
config_add_string country
}
drv_mtwifi_init_iface_config() {
config_add_string 'ssid:string' macfilter bssid
config_add_boolean wmm hidden isolate ieee80211k
config_add_int wpa_group_rekey
config_add_array 'maclist:list(macaddr)'
config_add_boolean mumimo_dl mumimo_ul ofdma_dl ofdma_ul amsdu autoba uapsd
}
drv_mtwifi_cleanup() {
return
}
mtwifi_vif_ap_config() {
local name="$1"
local ifname=""
local disabled=""
json_select config
json_get_var disabled disabled
json_select ..
[ "$disabled" = "1" ] && return
json_get_var ifname $MTWIFI_CFG_IFNAME_KEY
if [ -n "$ifname" ]; then
logger -t "netifd-mtwifi" "add $ifname to vifidx $name"
wireless_add_vif "$name" "$ifname"
fi
}
mtwifi_vif_sta_config() {
local name="$1"
local ifname=""
local disabled=""
json_select config
json_get_var disabled disabled
json_select ..
[ "$disabled" = "1" ] && return
json_get_var ifname $MTWIFI_CFG_IFNAME_KEY
if [ -n "$ifname" ]; then
logger -t "netifd-mtwifi" "add $ifname to vifidx $name"
# setup apcli autoconnect
iwpriv "$ifname" set ApCliAutoConnect=3
wireless_add_vif "$name" "$ifname"
fi
}
mtwifi_vif_ap_set_data() {
local ifname=""
if [ ! $AP_IDX -gt $MTWIFI_MAX_AP_IDX ]; then
ifname="${MTWIFI_AP_IF_PREFIX}${AP_IDX}"
AP_IDX=$((AP_IDX+1))
fi
json_add_string "$MTWIFI_CFG_IFNAME_KEY" "$ifname"
}
mtwifi_vif_sta_set_data() {
local ifname=""
if [ ! $APCLI_IDX -gt $MTWIFI_MAX_APCLI_IDX ]; then
ifname="${MTWIFI_APCLI_IF_PREFIX}${APCLI_IDX}"
APCLI_IDX=$((APCLI_IDX+1))
fi
json_add_string "$MTWIFI_CFG_IFNAME_KEY" "$ifname"
}
drv_mtwifi_setup() {
ubus -t 120 wait_for network.interface.lan
local dev="$1"
json_add_string device "$dev"
lock $LOCK_FILE
logger -t "netifd-mtwifi" "up: $dev"
MTWIFI_AP_IF_PREFIX="$(l1util get $dev ext_ifname)"
MTWIFI_APCLI_IF_PREFIX="$(l1util get $dev apcli_ifname)"
AP_IDX=0
for_each_interface ap mtwifi_vif_ap_set_data
APCLI_IDX=0
for_each_interface sta mtwifi_vif_sta_set_data
json_dump | /sbin/mtwifi_cfg setup
for_each_interface ap mtwifi_vif_ap_config
for_each_interface sta mtwifi_vif_sta_config
wireless_set_up
lock -u $LOCK_FILE
}
drv_mtwifi_teardown() {
local dev="$1"
lock $LOCK_FILE
logger -t "netifd-mtwifi" "down: $dev"
/sbin/mtwifi_cfg down "$dev"
lock -u $LOCK_FILE
}
add_driver mtwifi