From 55096d55f029297c02f816451777e7ee0afc8df0 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Mon, 5 Sep 2022 21:15:45 +0200 Subject: [PATCH 1/2] gluon-core: add cellular support Add cellular configuration support to Gluon. This implementtaion focuses not on hotpluggable WWAN adapters but instead on embedded LTE modems found in travel-routers or FWA CPEs. Signed-off-by: David Bauer --- .../luasrc/lib/gluon/upgrade/250-cellular | 55 +++++++++++++++++++ .../lib/gluon/upgrade/300-firewall-rules | 11 ++++ .../luasrc/usr/lib/lua/gluon/platform.lua | 14 +++++ 3 files changed, 80 insertions(+) create mode 100755 package/gluon-core/luasrc/lib/gluon/upgrade/250-cellular diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/250-cellular b/package/gluon-core/luasrc/lib/gluon/upgrade/250-cellular new file mode 100755 index 00000000..ab6bdfba --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/250-cellular @@ -0,0 +1,55 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() +local platform = require 'gluon.platform' + +if not platform.is_cellular_device() then + return +end + +local function set_or_delete(package, section, option, val) + if val ~= nil and string.len(val) ~= 0 then + uci:set(package, section, option, val) + else + uci:delete(package, section, option) + end +end + +local function setup_ncm_qmi(devpath, control_type, delay) + local pdptype = uci:get('gluon', 'cellular', 'pdptype') + + local pincode = uci:get('gluon', 'cellular', 'pin') + local username = uci:get('gluon', 'cellular', 'username') + local password = uci:get('gluon', 'cellular', 'password') + + uci:section('network', 'interface', 'cellular', { + proto = control_type, + device = devpath, + disabled = not uci:get_bool('gluon', 'cellular', 'enabled'), + pdptype = pdptype, + apn = uci:get('gluon', 'cellular', 'apn'), + }) + + if pdptype ~= 'IP' then + uci:set('network', 'cellular', 'ipv6', 'auto') + else + uci:delete('network', 'cellular', 'ipv6') + end + + set_or_delete('network', 'cellular', 'pincode', pincode) + set_or_delete('network', 'cellular', 'username', username) + set_or_delete('network', 'cellular', 'password', password) + set_or_delete('network', 'cellular', 'delay', delay) +end + +if platform.match('ath79', 'nand', { + 'zte,mf281', +}) then + setup_ncm_qmi('/dev/ttyACM0', 'ncm', 15) +elseif platform.match('ipq40xx', 'generic', { + 'glinet,gl-ap1300', +}) then + setup_ncm_qmi('/dev/cdc-wdm0', 'qmi', 15) +end + +uci:save('network') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/300-firewall-rules b/package/gluon-core/luasrc/lib/gluon/upgrade/300-firewall-rules index ef616aef..7b6c5627 100755 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/300-firewall-rules +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/300-firewall-rules @@ -1,6 +1,7 @@ #!/usr/bin/lua local uci = require('simple-uci').cursor() +local platform = require 'gluon.platform' local defaults = uci:get_first('firewall', 'defaults') @@ -16,8 +17,18 @@ local function reject_input_on_wan(zone) return true end +local function add_cellular_wan(zone) + if zone.name == 'wan' then + uci:set('firewall', zone['.name'], 'network', {'wan', 'wan6', 'cellular_4', 'cellular_6'}) + end +end + uci:foreach('firewall', 'zone', reject_input_on_wan) +if platform.is_cellular_device() then + uci:foreach('firewall', 'zone', add_cellular_wan) +end + for _, zone in ipairs({'mesh', 'loc_client', 'wired_mesh'}) do -- Other packages assign interfaces to these zones uci:section('firewall', 'zone', zone, { diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua index 4934f86b..1d4a41b0 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua @@ -69,4 +69,18 @@ function M.is_outdoor_device() return false end +function M.is_cellular_device() + if M.match('ath79', 'nand', { + 'zte,mf281', + }) then + return true + elseif M.match('ipq40xx', 'generic', { + 'glinet,gl-ap1300', + }) then + return true + end + + return false +end + return M From c22956ca551739a51e2962daeb982b0d79a2ea50 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Mon, 5 Sep 2022 22:24:13 +0200 Subject: [PATCH 2/2] gluon-web-cellular: add package This adds a new package which allows configuration of Gluons cellular WWAN capabilities using the configuration mode. This way, a user can enter APN information as well as the SIM PIN and enable / disable the functionality. Signed-off-by: David Bauer --- package/gluon-web-cellular/Makefile | 12 +++++ .../i18n/gluon-web-cellular.pot | 37 +++++++++++++ .../config-mode/controller/admin/cellular.lua | 7 +++ .../config-mode/model/admin/cellular.lua | 54 +++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 package/gluon-web-cellular/Makefile create mode 100644 package/gluon-web-cellular/i18n/gluon-web-cellular.pot create mode 100644 package/gluon-web-cellular/luasrc/lib/gluon/config-mode/controller/admin/cellular.lua create mode 100644 package/gluon-web-cellular/luasrc/lib/gluon/config-mode/model/admin/cellular.lua diff --git a/package/gluon-web-cellular/Makefile b/package/gluon-web-cellular/Makefile new file mode 100644 index 00000000..8b88ba98 --- /dev/null +++ b/package/gluon-web-cellular/Makefile @@ -0,0 +1,12 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web-cellular + +include ../gluon.mk + +define Package/gluon-web-cellular + DEPENDS:=+gluon-web-admin + TITLE:=UI for activating cellular WAN +endef + +$(eval $(call BuildPackageGluon,gluon-web-cellular)) diff --git a/package/gluon-web-cellular/i18n/gluon-web-cellular.pot b/package/gluon-web-cellular/i18n/gluon-web-cellular.pot new file mode 100644 index 00000000..5b3b8ae0 --- /dev/null +++ b/package/gluon-web-cellular/i18n/gluon-web-cellular.pot @@ -0,0 +1,37 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +msgid "APN" +msgstr "" + +msgid "Cellular" +msgstr "" + +msgid "Enabled" +msgstr "" + +msgid "IPv4" +msgstr "" + +msgid "IPv4/IPv6" +msgstr "" + +msgid "IPv6" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "SIM PIN" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Username" +msgstr "" + +msgid "" +"You can enable uplink via cellular service. If you decide so, the VPN " +"connection is established using the integrated WWAN modem." +msgstr "" diff --git a/package/gluon-web-cellular/luasrc/lib/gluon/config-mode/controller/admin/cellular.lua b/package/gluon-web-cellular/luasrc/lib/gluon/config-mode/controller/admin/cellular.lua new file mode 100644 index 00000000..06864708 --- /dev/null +++ b/package/gluon-web-cellular/luasrc/lib/gluon/config-mode/controller/admin/cellular.lua @@ -0,0 +1,7 @@ +local platform = require 'gluon.platform' + +package 'gluon-web-cellular' + +if platform.is_cellular_device() then + entry({"admin", "cellular"}, model("admin/cellular"), _("Cellular"), 30) +end diff --git a/package/gluon-web-cellular/luasrc/lib/gluon/config-mode/model/admin/cellular.lua b/package/gluon-web-cellular/luasrc/lib/gluon/config-mode/model/admin/cellular.lua new file mode 100644 index 00000000..38a4dd2c --- /dev/null +++ b/package/gluon-web-cellular/luasrc/lib/gluon/config-mode/model/admin/cellular.lua @@ -0,0 +1,54 @@ +local uci = require("simple-uci").cursor() + +local f = Form(translate("Cellular")) + +local s = f:section(Section, nil, translate( + 'You can enable uplink via cellular service. If you decide so, the VPN connection is established ' + .. 'using the integrated WWAN modem.' +)) + +local enabled = s:option(Flag, "enabled", translate("Enabled")) +enabled.default = uci:get('gluon', 'cellular') and uci:get_bool('gluon', 'cellular', 'enabled') + +local pin = s:option(Value, "pin", translate("SIM PIN")) +pin:depends(enabled, true) +pin.default = uci:get('gluon', 'cellular', 'pin') + +local apn = s:option(Value, "apn", translate("APN")) +apn:depends(enabled, true) +apn.default = uci:get('gluon', 'cellular', 'apn') + +local pdptype = s:option(ListValue, "type", translate("Type")) +pdptype:depends(enabled, true) +pdptype:value("IP", translate("IPv4")) +pdptype:value("IPV6", translate("IPv6")) +pdptype:value("IPV4V6", translate("IPv4/IPv6")) +pdptype.default = uci:get('gluon', 'cellular', 'pdptype') or "IP" + +local username = s:option(Value, "username", translate("Username")) +username:depends(enabled, true) +username.default = uci:get('gluon', 'cellular', 'username') + +local password = s:option(Value, "password", translate("Password")) +password:depends(enabled, true) +password.default = uci:get('gluon', 'cellular', 'password') + +function f:write() + local cellular_enabled = false + if enabled.data then + cellular_enabled = true + end + + uci:section('gluon', 'cellular', 'cellular', { + enabled = cellular_enabled, + apn = apn.data, + pdptype = pdptype.data, + pin = pin.data, + username = username.data, + password = password.data, + }) + + uci:commit('gluon') +end + +return f