From 55096d55f029297c02f816451777e7ee0afc8df0 Mon Sep 17 00:00:00 2001
From: David Bauer <mail@david-bauer.net>
Date: Mon, 5 Sep 2022 21:15:45 +0200
Subject: [PATCH] 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 <mail@david-bauer.net>
---
 .../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 000000000..ab6bdfba0
--- /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 ef616aef7..7b6c56274 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 4934f86b8..1d4a41b0b 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
-- 
GitLab