🎨 Sync 2026-06-07 18:17:40

This commit is contained in:
github-actions[bot] committed 2026-06-07 18:17:40 +08:00
1 parent 31e511aff8
commit 71aabc1bca
276 files changed
+1284 -96850

No files matched your search

+11 -7
View File
@@ -1,22 +1,26 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=fibocom-dial PKG_NAME:=fibocom-dial
PKG_RELEASE:=3 PKG_RELEASE:=4
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
define Package/fibocom-dial define Package/fibocom-dial
SECTION:=net SECTION:=utils
CATEGORY:=Network CATEGORY:=Utilities
SUBMENU:=WWAN TITLE:=Fibocom Dial
TITLE:=Dialing tool for Fibocom WWAN modules endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef endef
define Package/fibocom-dial/install define Package/fibocom-dial/install
$(INSTALL_DIR) $(1)/usr/bin $(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/fibocom-dial $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/fibocom-dial $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/fibo_qmimsg_server $(1)/usr/bin/fibocom-qmimsg-server $(INSTALL_BIN) $(PKG_BUILD_DIR)/fibo_qmimsg_server $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/multi-pdn-manager $(1)/usr/bin/fibocom-multi-pdn-manager $(INSTALL_BIN) $(PKG_BUILD_DIR)/multi-pdn-manager $(1)/usr/bin
endef endef
$(eval $(call BuildPackage,fibocom-dial)) $(eval $(call BuildPackage,fibocom-dial))
@@ -1,42 +0,0 @@
--- a/QmiWwanCM.c
+++ b/QmiWwanCM.c
@@ -8,7 +8,7 @@ typedef unsigned short sa_family_t;
#include "QMIThread.h"
#ifdef CONFIG_QMIWWAN
-#define FIBO_QMI_PROXY "fibo_qmimsg_server"
+#define FIBO_QMI_PROXY "fibocom-qmimsg-server"
static int cdc_wdm_fd = -1;
static UCHAR GetQCTLTransactionId(void)
--- a/fibo_qmimsg_server.c
+++ b/fibo_qmimsg_server.c
@@ -984,7 +984,7 @@ qmi_proxy_init_fail:
}
//2021-06-03 willa.liu@fibocom.com changed begin
static void qmi_start_server(void) {
- qmi_proxy_server_fd = create_local_server("fibo_qmimsg_server");
+ qmi_proxy_server_fd = create_local_server("fibocom-qmimsg-server");
printf("%s: qmi_proxy_server_fd = %d\n", __func__, qmi_proxy_server_fd);
if (qmi_proxy_server_fd == -1) {
dprintf("%s Failed to create %s, errno: %d (%s)\n", __func__, "fibocom-qmi-proxy", errno, strerror(errno));
--- a/multi-pdn-manager.c
+++ b/multi-pdn-manager.c
@@ -812,7 +812,7 @@ int main(int argc, char *argv[])
{
dbg_time("The Fibocom multi-pdn-manager is already running! So killall multi-pdn-manager!");
system("killall -9 fibocom-dial");
- system("killall -9 multi-pdn-manager");
+ system("killall -9 fibocom-multi-pdn-manager");
}
}
else
@@ -846,7 +846,7 @@ int main(int argc, char *argv[])
if (is_pcie_dial())
{
dbg_time("start qmi proxy server");
- //system("./fibo_qmimsg_server -d /dev/mhi_QMI0 &");
+ //system("./fibocom-qmimsg-server -d /dev/mhi_QMI0 &");
}
while (1)
{
-22
View File
@@ -1,22 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=fibocom-qmi-wwan
PKG_VERSION:=1.0.5
PKG_RELEASE:=1
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/package.mk
define KernelPackage/usb-net-qmi-wwan-fibocom
SUBMENU:=USB Support
TITLE:=QMI WWAN driver for Fibocom modules
DEPENDS:=+kmod-usb-net +kmod-usb-wdm
FILES:=$(PKG_BUILD_DIR)/qmi_wwan_f.ko
AUTOLOAD:=$(call AutoLoad,82,qmi_wwan_f)
endef
define Build/Compile
+$(KERNEL_MAKE) M="$(PKG_BUILD_DIR)" modules
endef
$(eval $(call KernelPackage,usb-net-qmi-wwan-fibocom))
@@ -1,75 +0,0 @@
--- a/qmi_wwan_f.c
+++ b/qmi_wwan_f.c
@@ -712,7 +712,11 @@ static struct rtnl_link_stats64 *_rmnet_
stats64 = per_cpu_ptr(dev->stats64, cpu);
do {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0)
start = u64_stats_fetch_begin_irq(&stats64->syncp);
+#else
+ start = u64_stats_fetch_begin(&stats64->syncp);
+#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
rx_packets = stats64->rx_packets;
rx_bytes = stats64->rx_bytes;
@@ -724,7 +728,11 @@ static struct rtnl_link_stats64 *_rmnet_
tx_packets = u64_stats_read(&stats64->tx_packets);
tx_bytes = u64_stats_read(&stats64->tx_bytes);
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0)
} while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
+#else
+ } while (u64_stats_fetch_retry(&stats64->syncp, start));
+#endif
stats->rx_packets += rx_packets;
stats->rx_bytes += rx_bytes;
@@ -1187,7 +1195,11 @@ static int qmap_register_device(sQmiWwan
priv->mux_id = FIBOCOM_QMAP_MUX_ID + offset_id;
sprintf(qmap_net->name, "%s.%d", real_dev->name, offset_id + 1);
qmap_net->netdev_ops = &qmap_netdev_ops;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,17,0)
memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN);
+#else
+ __dev_addr_set(qmap_net, real_dev->dev_addr, ETH_ALEN);
+#endif
#ifdef FIBOCOM_BRIDGE_MODE
priv->bridge_mode = !!(pDev->bridge_mode & BIT(offset_id));
@@ -1196,8 +1208,12 @@ static int qmap_register_device(sQmiWwan
priv->agg_skb = NULL;
priv->agg_count = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,18,0)
hrtimer_init(&priv->agg_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
priv->agg_hrtimer.function = rmnet_usb_tx_agg_timer_cb;
+#else
+ hrtimer_setup(&priv->agg_hrtimer, rmnet_usb_tx_agg_timer_cb, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+#endif
INIT_WORK(&priv->agg_wq, rmnet_usb_tx_agg_work);
ktime_get_ts64(&priv->agg_time);
spin_lock_init(&priv->agg_lock);
@@ -1319,7 +1335,7 @@ typedef struct {
unsigned int dl_minimum_padding; //0x1A
} QMAP_SETTING;
-int qma_setting_store(struct device *dev, QMAP_SETTING *qmap_settings, size_t size) {
+static int qma_setting_store(struct device *dev, QMAP_SETTING *qmap_settings, size_t size) {
struct net_device *netdev = to_net_dev(dev);
struct usbnet * usbnetdev = netdev_priv( netdev );
struct qmi_wwan_state *info = (void *)&usbnetdev->data;
@@ -1760,8 +1776,14 @@ static void ql_net_get_drvinfo(struct ne
{
/* Inherit standard device info */
usbnet_get_drvinfo(net, info);
+ /* strlcpy() is deprecated in kernel 6.8.0+, using strscpy instead */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,8,0))
strlcpy(info->driver, driver_name, sizeof(info->driver));
strlcpy(info->version, VERSION_NUMBER, sizeof(info->version));
+#else
+ strscpy(info->driver, driver_name, sizeof(info->driver));
+ strscpy(info->version, VERSION_NUMBER, sizeof(info->version));
+#endif
}
static struct ethtool_ops ql_net_ethtool_ops;
@@ -1,30 +0,0 @@
From 85990e155cb684ec6380bcf70f588255ec41dc69 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=80=AC=E5=90=8D=E7=94=B1=E5=B8=8C?=
<wanglei199909210927@gmail.com>
Date: Wed, 5 Nov 2025 14:16:56 +0800
Subject: [PATCH] qmi_wwan: return correct tx/rx stats in kernel 6.10+ (#130)
---
driver/fibocom_QMI_WWAN/src/qmi_wwan_f.c | 9 ++++++++-
driver/quectel_QMI_WWAN/src/qmi_wwan_q.c | 7 +++++++
2 files changed, 15 insertions(+), 1 deletion(-)
--- a/qmi_wwan_f.c
+++ b/qmi_wwan_f.c
@@ -1910,8 +1910,15 @@ static int qmi_wwan_bind(struct usbnet *
dev_addr_mod(dev->net, 0, &addr, 1);
#endif
}
- if (!_usbnet_get_stats64)
+ if (!_usbnet_get_stats64)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,10,0 ))
_usbnet_get_stats64 = dev->net->netdev_ops->ndo_get_stats64;
+#else
+ /* From kernel 6.10+, usbnet sets pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS (352f5b3282), but removed ndo_get_stats64 (9cb3d523c1) */
+ /* Use dev_get_tstats64 to read per-CPU stats when NETDEV_PCPU_STAT_TSTATS was set */
+ if (dev->net->pcpu_stat_type == NETDEV_PCPU_STAT_TSTATS)
+ _usbnet_get_stats64 = dev_get_tstats64;
+#endif
dev->net->netdev_ops = &qmi_wwan_netdev_ops;
ql_net_ethtool_ops = *dev->net->ethtool_ops;
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=qmi_wwan_f PKG_NAME:=qmi_wwan_f
PKG_VERSION:=1.0 PKG_VERSION:=1.0
PKG_RELEASE:=4 PKG_RELEASE:=5
include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
+23 -5
View File
@@ -712,19 +712,27 @@ static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net,
stats64 = per_cpu_ptr(dev->stats64, cpu); stats64 = per_cpu_ptr(dev->stats64, cpu);
do { do {
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0)
start = u64_stats_fetch_begin_irq(&stats64->syncp); start = u64_stats_fetch_begin_irq(&stats64->syncp);
#else
start = u64_stats_fetch_begin(&stats64->syncp);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
rx_packets = stats64->rx_packets; rx_packets = stats64->rx_packets;
rx_bytes = stats64->rx_bytes; rx_bytes = stats64->rx_bytes;
tx_packets = stats64->tx_packets; tx_packets = stats64->tx_packets;
tx_bytes = stats64->tx_bytes; tx_bytes = stats64->tx_bytes;
#else #else
rx_packets = u64_stats_read(&stats64->rx_packets); rx_packets = u64_stats_read(&stats64->rx_packets);
rx_bytes = u64_stats_read(&stats64->rx_bytes); rx_bytes = u64_stats_read(&stats64->rx_bytes);
tx_packets = u64_stats_read(&stats64->tx_packets); tx_packets = u64_stats_read(&stats64->tx_packets);
tx_bytes = u64_stats_read(&stats64->tx_bytes); tx_bytes = u64_stats_read(&stats64->tx_bytes);
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0)
} while (u64_stats_fetch_retry_irq(&stats64->syncp, start)); } while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
#else
} while (u64_stats_fetch_retry(&stats64->syncp, start));
#endif
stats->rx_packets += rx_packets; stats->rx_packets += rx_packets;
stats->rx_bytes += rx_bytes; stats->rx_bytes += rx_bytes;
@@ -1187,7 +1195,11 @@ static int qmap_register_device(sQmiWwanQmap * pDev, u8 offset_id)
priv->mux_id = FIBOCOM_QMAP_MUX_ID + offset_id; priv->mux_id = FIBOCOM_QMAP_MUX_ID + offset_id;
sprintf(qmap_net->name, "%s.%d", real_dev->name, offset_id + 1); sprintf(qmap_net->name, "%s.%d", real_dev->name, offset_id + 1);
qmap_net->netdev_ops = &qmap_netdev_ops; qmap_net->netdev_ops = &qmap_netdev_ops;
memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN); #if LINUX_VERSION_CODE < KERNEL_VERSION(5,17,0)
memcpy(qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN);
#else
__dev_addr_set(qmap_net, real_dev->dev_addr, ETH_ALEN);
#endif
#ifdef FIBOCOM_BRIDGE_MODE #ifdef FIBOCOM_BRIDGE_MODE
priv->bridge_mode = !!(pDev->bridge_mode & BIT(offset_id)); priv->bridge_mode = !!(pDev->bridge_mode & BIT(offset_id));
@@ -1760,8 +1772,14 @@ static void ql_net_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *i
{ {
/* Inherit standard device info */ /* Inherit standard device info */
usbnet_get_drvinfo(net, info); usbnet_get_drvinfo(net, info);
/* strlcpy() is deprecated in kernel 6.8.0+, using strscpy instead */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,8,0))
strlcpy(info->driver, driver_name, sizeof(info->driver)); strlcpy(info->driver, driver_name, sizeof(info->driver));
strlcpy(info->version, VERSION_NUMBER, sizeof(info->version)); strlcpy(info->version, VERSION_NUMBER, sizeof(info->version));
#else
strscpy(info->driver, driver_name, sizeof(info->driver));
strscpy(info->version, VERSION_NUMBER, sizeof(info->version));
#endif
} }
static struct ethtool_ops ql_net_ethtool_ops; static struct ethtool_ops ql_net_ethtool_ops;
+13 -1
View File
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=gecoosac PKG_NAME:=gecoosac
PKG_VERSION:=2.2.20251015 PKG_VERSION:=2.2.20251015
PKG_RELEASE:=1 PKG_RELEASE:=2
ifeq ($(ARCH),aarch64) ifeq ($(ARCH),aarch64)
PKG_ARCH:=ac_linux_arm64 PKG_ARCH:=ac_linux_arm64
@@ -44,12 +44,24 @@ define Package/$(PKG_NAME)
DEPENDS:=@(aarch64||arm||i386||mips||mipsel||x86_64) DEPENDS:=@(aarch64||arm||i386||mips||mipsel||x86_64)
endef endef
define Package/$(PKG_NAME)/conffiles
/etc/config/gecoosac
/etc/gecoosac/
endef
define Build/Compile define Build/Compile
endef endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin $(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/bin
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/etc/init.d/gecoosac $(1)/etc/init.d/gecoosac
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/etc/config/gecoosac $(1)/etc/config/gecoosac
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/etc/uci-defaults/gecoosac $(1)/etc/uci-defaults/gecoosac
$(INSTALL_DIR) $(1)/etc/gecoosac/tls
endef endef
$(eval $(call BuildPackage,$(PKG_NAME))) $(eval $(call BuildPackage,$(PKG_NAME)))
+15
View File
@@ -0,0 +1,15 @@
config gecoosac 'config'
option enabled '0'
option port '60650'
option isonlyoneprot '0'
option m_port '8080'
option https '0'
option crt_file '/etc/gecoosac/tls/gecoosac.crt'
option key_file '/etc/gecoosac/tls/gecoosac.key'
option upload_dir '/tmp/gecoosac/upload/'
option db_dir '/etc/gecoosac/'
option piddir '/var/run/'
option lang 'zh'
option debug '0'
option showtip '1'
option log '0'
+136
View File
@@ -0,0 +1,136 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2024 ImmortalWrt
. /lib/functions.sh
. /lib/functions/procd.sh
USE_PROCD=1
START=90
STOP=10
PROG=/usr/bin/gecoosac
DEFAULT_DB_DIR=/etc/gecoosac/
DEFAULT_UPLOAD_DIR=/tmp/gecoosac/upload/
DEFAULT_CRT_FILE=/etc/gecoosac/tls/gecoosac.crt
DEFAULT_KEY_FILE=/etc/gecoosac/tls/gecoosac.key
DEFAULT_PID_DIR=/var/run/
DEFAULT_LANG=zh
init_conf() {
config_load "gecoosac"
config_get "db_dir" "config" "db_dir" "$DEFAULT_DB_DIR"
config_get "upload_dir" "config" "upload_dir" "$DEFAULT_UPLOAD_DIR"
config_get "enabled" "config" "enabled" "0"
config_get "port" "config" "port" "60650"
config_get "isonlyoneprot" "config" "isonlyoneprot" "0"
config_get "m_port" "config" "m_port" "8080"
config_get "https" "config" "https" "0"
config_get "crt_file" "config" "crt_file" "$DEFAULT_CRT_FILE"
config_get "key_file" "config" "key_file" "$DEFAULT_KEY_FILE"
config_get "piddir" "config" "piddir" "$DEFAULT_PID_DIR"
config_get "lang" "config" "lang" "$DEFAULT_LANG"
config_get "debug" "config" "debug" "0"
config_get "showtip" "config" "showtip" "1"
config_get "log" "config" "log" "0"
}
is_abs_path() {
case "$1" in
/*) return 0 ;;
*) return 1 ;;
esac
}
is_port() {
case "$1" in
""|*[!0-9]*) return 1 ;;
esac
[ "$1" -ge 1 ] 2>/dev/null && [ "$1" -le 65535 ]
}
normalize_conf() {
is_abs_path "$upload_dir" || upload_dir="$DEFAULT_UPLOAD_DIR"
is_abs_path "$db_dir" || db_dir="$DEFAULT_DB_DIR"
is_abs_path "$crt_file" || crt_file="$DEFAULT_CRT_FILE"
is_abs_path "$key_file" || key_file="$DEFAULT_KEY_FILE"
is_abs_path "$piddir" && [ "$piddir" != "/" ] || piddir="$DEFAULT_PID_DIR"
is_port "$port" || port="60650"
is_port "$m_port" || m_port="8080"
[ "$enabled" = "1" ] || enabled="0"
[ "$isonlyoneprot" = "1" ] || isonlyoneprot="0"
[ "$https" = "1" ] || https="0"
case "$lang" in
zh|en) ;;
*) lang="$DEFAULT_LANG" ;;
esac
[ "$debug" = "1" ] || debug="0"
[ "$showtip" = "0" ] || showtip="1"
[ "$log" = "1" ] || log="0"
}
ensure_dirs() {
mkdir -p "$upload_dir" "$db_dir" "$piddir" /etc/gecoosac/tls
}
start_service() {
init_conf
normalize_conf
[ "$enabled" = "1" ] || return 0
if [ ! -x "$PROG" ]; then
logger -t gecoosac "program not found: $PROG"
return 1
fi
ensure_dirs
if [ "$isonlyoneprot" = "0" ] && [ "$https" = "1" ]; then
if [ ! -r "$crt_file" ] || [ ! -r "$key_file" ]; then
logger -t gecoosac "HTTPS is enabled but certificate or key file is missing"
return 1
fi
fi
procd_open_instance gecoosac
procd_set_param command "$PROG"
procd_append_param command -f "$upload_dir"
procd_append_param command -p "$port"
procd_append_param command -debug "$debug"
procd_append_param command -dbpath "$db_dir"
procd_append_param command -token "1"
procd_append_param command -lang "$lang"
procd_append_param command -piddir "$piddir"
if [ "$isonlyoneprot" = "0" ]; then
procd_append_param command -isonlyoneprot "0"
procd_append_param command -mp "$m_port"
if [ "$https" = "1" ]; then
procd_append_param command -https "1"
procd_append_param command -crt "$crt_file"
procd_append_param command -key "$key_file"
else
procd_append_param command -https "0"
fi
else
procd_append_param command -isonlyoneprot "1"
fi
procd_append_param command -showtip "$showtip"
procd_set_param env GIN_MODE=release
procd_set_param file /etc/config/gecoosac
procd_set_param pidfile "${piddir%/}/gecoosac.pid"
procd_set_param stdout "$log"
procd_set_param stderr "$log"
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
procd_close_instance
}
reload_service() {
stop
start
}
service_triggers() {
procd_add_reload_trigger "gecoosac"
}
+39
View File
@@ -0,0 +1,39 @@
#!/bin/sh
changed=0
ensure_section() {
uci -q get gecoosac.config >/dev/null && return 0
uci -q set gecoosac.config=gecoosac
changed=1
}
set_default() {
local option="$1"
local value="$2"
uci -q get "gecoosac.config.${option}" >/dev/null && return 0
uci -q set "gecoosac.config.${option}=${value}"
changed=1
}
ensure_section
set_default enabled 0
set_default port 60650
set_default isonlyoneprot 0
set_default m_port 8080
set_default https 0
set_default crt_file /etc/gecoosac/tls/gecoosac.crt
set_default key_file /etc/gecoosac/tls/gecoosac.key
set_default upload_dir /tmp/gecoosac/upload/
set_default db_dir /etc/gecoosac/
set_default piddir /var/run/
set_default lang zh
set_default debug 0
# Preserve the previous package behavior for upgraded configs that never had showtip.
set_default showtip 0
set_default log 0
[ "$changed" = "1" ] && uci -q commit gecoosac
exit 0
+1 -5
View File
@@ -7,16 +7,12 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-gecoosac PKG_NAME:=luci-app-gecoosac
PKG_VERSION:=2.2 PKG_VERSION:=2.2
PKG_RELEASE:=1 PKG_RELEASE:=2
LUCI_TITLE:=LuCI Support for gecoosac LUCI_TITLE:=LuCI Support for gecoosac
LUCI_DEPENDS:=+luci-compat +gecoosac LUCI_DEPENDS:=+luci-compat +gecoosac
LUCI_PKGARCH:=all LUCI_PKGARCH:=all
define Package/$(PKG_NAME)/conffiles
/etc/gecoosac
endef
include $(TOPDIR)/feeds/luci/luci.mk include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature # call BuildPackage - OpenWrt buildroot signature
@@ -1,8 +1,11 @@
module("luci.controller.gecoosac", package.seeall) module("luci.controller.gecoosac", package.seeall)
local fs = require "nixio.fs"
local sys = require "luci.sys"
function index() function index()
if not nixio.fs.access("/etc/config/gecoosac") then if not fs.access("/etc/config/gecoosac") then
return return
end end
local page local page
@@ -13,17 +16,9 @@ function index()
end end
function act_status() function act_status()
local e = {} local e = {
local binpath = "/usr/bin/gecoosac" running = sys.call("/etc/init.d/gecoosac status >/dev/null 2>&1") == 0
e = {
running = luci.sys.call("pgrep " .. binpath .. " >/dev/null") == 0
} }
luci.http.prepare_content("application/json") luci.http.prepare_content("application/json")
luci.http.write_json(e) luci.http.write_json(e)
end end
function clear_upload()
local path = "/tmp/gecoosac/upload/"
luci.sys.call("rm -rf " .. path .. "/*")
luci.http.status(200, "OK")
end
+126 -22
View File
@@ -1,11 +1,88 @@
function program_exists(program) local fs = require "nixio.fs"
local handle = io.popen('which ' .. program)
local result = handle:read('*a') local DEFAULT_UPLOAD_DIR = "/tmp/gecoosac/upload/"
handle:close() local DEFAULT_DB_DIR = "/etc/gecoosac/"
return result ~= '' local DEFAULT_CRT_FILE = "/etc/gecoosac/tls/gecoosac.crt"
local DEFAULT_KEY_FILE = "/etc/gecoosac/tls/gecoosac.key"
local DEFAULT_PID_DIR = "/var/run/"
local function trim(value)
return (value or ""):gsub("^%s+", ""):gsub("%s+$", "")
end end
if program_exists("/usr/bin/gecoosac") then local function is_abs_path(value)
return type(value) == "string" and value:match("^/") and not value:find("[%z\r\n]")
end
local function validate_abs_path(self, value)
value = trim(value)
if is_abs_path(value) then
return value
end
return nil, translate("Expecting an absolute path")
end
local function is_upload_path(path)
path = trim(path):gsub("/+$", "")
return path == "/tmp/gecoosac/upload" or path:match("/gecoosac/upload$") ~= nil
end
local function remove_tree(path)
local stat = fs.lstat and fs.lstat(path) or fs.stat(path)
if not stat then
return
end
if stat.type == "dir" then
local iter = fs.dir(path)
if iter then
for entry in iter do
if entry ~= "." and entry ~= ".." then
remove_tree(path .. "/" .. entry)
end
end
end
fs.rmdir(path)
else
fs.unlink(path)
end
end
local function clear_upload_dir(path)
path = trim(path)
if path == "" then
path = DEFAULT_UPLOAD_DIR
end
path = path:gsub("/+$", "")
if not is_abs_path(path) then
return nil, translate("Expecting an absolute path")
end
local real = fs.realpath(path) or path
real = real:gsub("/+$", "")
if not is_upload_path(real) then
return nil, translate("Only Gecoos upload directories can be cleared")
end
if fs.stat(real, "type") ~= "dir" then
return true
end
local iter = fs.dir(real)
if iter then
for entry in iter do
if entry ~= "." and entry ~= ".." then
remove_tree(real .. "/" .. entry)
end
end
end
return true
end
if fs.access("/usr/bin/gecoosac") then
m = Map("gecoosac", translate("Gecoos AC"), translate("Batch management Gecoos AP, Default password: admin") .. "<br>" .. translatef("The current AC version %s, only supports AP 7.6 and above.","2.2")) m = Map("gecoosac", translate("Gecoos AC"), translate("Batch management Gecoos AP, Default password: admin") .. "<br>" .. translatef("The current AC version %s, only supports AP 7.6 and above.","2.2"))
else else
m = Map("gecoosac", translate("Gecoos AC"), translate("Batch management Gecoos AP, Default password: admin") .. "<br>" .. translate("The AC program does not exist, please check.")) m = Map("gecoosac", translate("Gecoos AC"), translate("Batch management Gecoos AP, Default password: admin") .. "<br>" .. translate("The AC program does not exist, please check."))
@@ -27,48 +104,75 @@ o.datatype = "port"
o.rmempty = false o.rmempty = false
o = s:option(Flag, "isonlyoneprot", translate("Single Port Mode"), translate("Do not enable the independent management port, only use one port for management.")) o = s:option(Flag, "isonlyoneprot", translate("Single Port Mode"), translate("Do not enable the independent management port, only use one port for management."))
o.default = 1 o.default = 0
o.rmempty = false o.rmempty = false
o = s:option(Value, "m_port", translate("Set management port")) o = s:option(Value, "m_port", translate("Set management port"))
o.placeholder = 8080 o.placeholder = 8080
o.default = 8080 o.default = 8080
o.datatype = "port" o.datatype = "port"
o:depends("isonlyoneprot", false) o:depends("isonlyoneprot", "0")
o = s:option(Flag, "https", translate("Enable HTTPS service"), translate("A certificate file must be specified, otherwise it will fail to start.")) o = s:option(Flag, "https", translate("Enable HTTPS service"), translate("A certificate file must be specified, otherwise it will fail to start."))
o.default = 0 o.default = 0
o:depends("isonlyoneprot", false) o:depends("isonlyoneprot", "0")
o = s:option(Value, "crt_file", translate("Specify crt certificate file")) o = s:option(Value, "crt_file", translate("Specify crt certificate file"))
o.placeholder = "/etc/gecoosac/tls/1.crt" o.placeholder = DEFAULT_CRT_FILE
o.default = "/etc/gecoosac/tls/1.crt" o.default = DEFAULT_CRT_FILE
o:depends("https", true) o.validate = validate_abs_path
o:depends({isonlyoneprot = "0", https = "1"})
o = s:option(Value, "key_file", translate("Specify key certificate file")) o = s:option(Value, "key_file", translate("Specify key certificate file"))
o.placeholder = "/etc/gecoosac/tls/1.key" o.placeholder = DEFAULT_KEY_FILE
o.default = "/etc/gecoosac/tls/1.key" o.default = DEFAULT_KEY_FILE
o:depends("https", true) o.validate = validate_abs_path
o:depends({isonlyoneprot = "0", https = "1"})
upload_dir = s:option(Value, "upload_dir", translate("Upload dir path"), translate("The path to upload AP upgrade firmware")) upload_dir = s:option(Value, "upload_dir", translate("Upload dir path"), translate("The path to upload AP upgrade firmware"))
upload_dir.placeholder = "/tmp/gecoosac/upload/" upload_dir.placeholder = DEFAULT_UPLOAD_DIR
upload_dir.default = "/tmp/gecoosac/upload/" upload_dir.default = DEFAULT_UPLOAD_DIR
upload_dir.rmempty = false upload_dir.rmempty = false
upload_dir.validate = validate_abs_path
db_dir = s:option(Value, "db_dir", translate("Database dir path"), translate("The path to store the config database")) db_dir = s:option(Value, "db_dir", translate("Database dir path"), translate("The path to store the config database"))
db_dir.placeholder = "/etc/gecoosac/" db_dir.placeholder = DEFAULT_DB_DIR
db_dir.default = "/etc/gecoosac/" db_dir.default = DEFAULT_DB_DIR
db_dir.rmempty = false db_dir.rmempty = false
db_dir.validate = validate_abs_path
o = s:option(Value, "piddir", translate("PID dir path"), translate("The path to store the AC program pid file"))
o.placeholder = DEFAULT_PID_DIR
o.default = DEFAULT_PID_DIR
o.rmempty = false
o.validate = validate_abs_path
o = s:option(ListValue, "lang", translate("Language"))
o:value("zh", translate("Chinese"))
o:value("en", translate("English"))
o.default = "zh"
o.rmempty = false
debug = s:option(Flag, "debug", translate("Debug Mode"))
debug.default = 0
debug.rmempty = false
showtip = s:option(Flag, "showtip", translate("Show IP Tip"), translate("Show the IP 6.7.8.9 setup tip when it is not configured."))
showtip.default = 1
showtip.rmempty = false
log = s:option(Flag, "log", translate("Enable Log")) log = s:option(Flag, "log", translate("Enable Log"))
log.default = 1 log.default = 0
log.rmempty = false log.rmempty = false
clear_upload = s:option(Button, "clear_upload", translate("Clear Upload Directory")) clear_upload = s:option(Button, "clear_upload", translate("Clear Upload Directory"))
clear_upload.inputstyle = "remove" clear_upload.inputstyle = "remove"
clear_upload.write = function(self, section) clear_upload.write = function(self, section)
local path = upload_dir:formvalue(section) or "/tmp/gecoosac/upload/" local path = upload_dir:formvalue(section) or upload_dir:cfgvalue(section) or DEFAULT_UPLOAD_DIR
luci.sys.call("rm -rf " .. path .. "/*") local ok, err = clear_upload_dir(path)
if not ok then
self.map.message = err or translate("Upload directory was not cleared")
end
end end
return m return m
@@ -1,7 +1,8 @@
<% <%
local uci=require"luci.model.uci".cursor() local uci=require"luci.model.uci".cursor()
local json=require"luci.jsonc"
local isonlyoneprot = uci:get("gecoosac", "config", "isonlyoneprot") or "1" local isonlyoneprot = uci:get("gecoosac", "config", "isonlyoneprot") or "0"
local https = uci:get("gecoosac", "config", "https") or "0" local https = uci:get("gecoosac", "config", "https") or "0"
local port = uci:get("gecoosac", "config", "port") or "60650" local port = uci:get("gecoosac", "config", "port") or "60650"
local m_port = uci:get("gecoosac", "config", "m_port") or "8080" local m_port = uci:get("gecoosac", "config", "m_port") or "8080"
@@ -14,8 +15,8 @@ if isonlyoneprot == "0" then
end end
-%> -%>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
var Port = "<%=port%>" var Port = <%=json.stringify(port)%>;
var Http = "<%=http%>" var Http = <%=json.stringify(http)%>;
XHR.poll(3, '<%=url([[admin]], [[services]], [[gecoosac]], [[status]])%>', null, XHR.poll(3, '<%=url([[admin]], [[services]], [[gecoosac]], [[status]])%>', null,
function(x, data) { function(x, data) {
var tb = document.getElementById('gecoosac_status'); var tb = document.getElementById('gecoosac_status');
@@ -30,8 +31,16 @@ XHR.poll(3, '<%=url([[admin]], [[services]], [[gecoosac]], [[status]])%>', null,
} }
); );
function clientHost() {
var host = window.location.hostname;
if (host.indexOf(':') !== -1 && host.charAt(0) !== '[') {
host = '[' + host + ']';
}
return host;
}
function openClient() { function openClient() {
var url = Http + window.location.hostname + ":" + Port; var url = Http + clientHost() + ":" + Port;
window.open(url); window.open(url);
} }
//]]> //]]>
+33
View File
@@ -55,6 +55,30 @@ msgstr "数据库目录"
msgid "The path to store the config database" msgid "The path to store the config database"
msgstr "存放配置数据库的路径" msgstr "存放配置数据库的路径"
msgid "PID dir path"
msgstr "PID 目录"
msgid "The path to store the AC program pid file"
msgstr "存放 AC 程序 PID 文件的路径"
msgid "Language"
msgstr "语言"
msgid "Chinese"
msgstr "中文"
msgid "English"
msgstr "英文"
msgid "Debug Mode"
msgstr "调试模式"
msgid "Show IP Tip"
msgstr "显示 IP 提示"
msgid "Show the IP 6.7.8.9 setup tip when it is not configured."
msgstr "未配置 6.7.8.9 时显示相关提示信息。"
msgid "Enable Log" msgid "Enable Log"
msgstr "启用日志" msgstr "启用日志"
@@ -72,3 +96,12 @@ msgstr "收集数据..."
msgid "Clear Upload Directory" msgid "Clear Upload Directory"
msgstr "清理上传目录" msgstr "清理上传目录"
msgid "Expecting an absolute path"
msgstr "请输入绝对路径"
msgid "Only Gecoos upload directories can be cleared"
msgstr "只能清理集客 AC 上传目录"
msgid "Upload directory was not cleared"
msgstr "上传目录未清理"
@@ -1,8 +0,0 @@
config gecoosac 'config'
option enabled '0'
option port '60650'
option isonlyoneprot '1'
option upload_dir '/tmp/gecoosac/upload/'
option db_dir '/etc/gecoosac/'
option log '0'
@@ -1,45 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDljCCAn6gAwIBAgIIeEgcfPZbDC0wDQYJKoZIhvcNAQELBQAwejELMAkGA1UE
BhMCQ04xFzAVBgNVBAoTDktleU1hbmFnZXIub3JnMTEwLwYDVQQLEyhLZXlNYW5h
Z2VyIFRlc3QgUm9vdCAtIEZvciBUZXN0IFVzZSBPbmx5MR8wHQYDVQQDExZLZXlN
YW5hZ2VyIFRlc3QgUlNBIENBMCAXDTI0MTIxMTA0MDUyNloYDzIxMjQxMjExMDQw
NTI2WjAZMQswCQYDVQQGEwJDTjEKMAgGA1UEAwwBKjCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBALM3K/5+yX6H9Dvq8TrKuk0KtFBqmDDP3lKXMpMkWjDn
4OtKGq4QtaPPJfGBjitYecyHLWbqGZlWU2H8ug/kL/PtAFgtTgiFvObePbP4VUVO
lICitAWCSMo7xsvt/XSGLOF3dV1tCoEcjK9GtJEMOyoqHMOgbuZ986wIR4LkgULz
3A2uC5abXP5Exa6phMCv3MojjaVgOFEIuC4371ZeLU/YXja9ssQ0Bs8PzOIjCP7i
pce94hYYSgAH3Ua1ZcWVZVEbCytoaOGWXkrhNTVZ+nAarlFY4fgN3yCi+YgFipKU
1H9oNr4PgLsxhtM3f19wwu9XNY1RF72cfRPS/mPy86sCAwEAAaN/MH0wDgYDVR0P
AQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4E
FgQUOW6TXeYQEZs1tMI05Vx2aSb9dk0wHwYDVR0jBBgwFoAUfzXMx0QcDHIhuynW
4rB+75TRqw8wDAYDVR0RBAUwA4IBKjANBgkqhkiG9w0BAQsFAAOCAQEAl63ixtfN
azLCIvIKGhjhqk2aU9NZtnsjYO729bNSk8SGtqVvCyXO8FJwdhoybtBlSkxjyvrb
nsR+QbeYGu0ZPsSsJJKuwlsM+ZoTOEGRQrhT7AkkXsNQHSalDCWczPW45xWHkg/s
P9xIGeySWMu4CJ1/eZYczT6bzS0eLd05camVCeU2E5N/M7hAO4SnK0agFZnaUEjp
13KZA3MfFNXZ2Q7na9CRjTbpqDCOpsLteP22fwUq7zutwvkQsQQYnQuVlpiUjSsV
MvY7oxkTi9M5BtowdEtVpWkVO2WOMs5dy2kxfgcIJ5KRZLmU+cPsWgsE76fErIYs
FU2leWlNpSvuMw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIID2jCCAsKgAwIBAgIILz9r/y+4/ZgwDQYJKoZIhvcNAQELBQAwezELMAkGA1UE
BhMCQ04xFzAVBgNVBAoTDktleU1hbmFnZXIub3JnMTEwLwYDVQQLEyhLZXlNYW5h
Z2VyIFRlc3QgUm9vdCAtIEZvciBUZXN0IFVzZSBPbmx5MSAwHgYDVQQDExdLZXlN
YW5hZ2VyIFRlc3QgUm9vdCBDQTAeFw0yNDEyMTEwMzI3MzJaFw0zNDEyMTEwMzI3
MzJaMHoxCzAJBgNVBAYTAkNOMRcwFQYDVQQKEw5LZXlNYW5hZ2VyLm9yZzExMC8G
A1UECxMoS2V5TWFuYWdlciBUZXN0IFJvb3QgLSBGb3IgVGVzdCBVc2UgT25seTEf
MB0GA1UEAxMWS2V5TWFuYWdlciBUZXN0IFJTQSBDQTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAMa7Tdag8tcvEwqRMD+gVEd4G3XeQyYzSYGLAa9DGji4
qUDUcBi0Ml2AndHtNNPcAk4vBUsZ10jjpNtOWtsy+r8VivBIlM5PE38JLhlZWao9
JvT1duxfxss+Q7xdT1oO++CDN/6avPXmDD1dmbTD09/cxcPW8M/3aaHfbI5GWxlr
ZLu8N50yQQxiXLEJad3n7fPjAosGroqa5FcsJ2vDQHuK13mpZG1eBoNZe6/OAzAz
yYkUKyixpS4xc8Agb9BCl7M9Tvkr8VkELGoFPWBMwBsa4BD0OYE7Vc+ZFEqhyzva
mOpicU1xl8mMkNIhiIaSU52fzRgYryZKmxPfYo8JaRUCAwEAAaNjMGEwDgYDVR0P
AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH81zMdEHAxyIbsp
1uKwfu+U0asPMB8GA1UdIwQYMBaAFElv+F66JtNinfmGM1cttCjILv/hMA0GCSqG
SIb3DQEBCwUAA4IBAQDOrqBCHRfVrTC/mfIIXcFn3lB+3kGmAmBVxH5UILljPdl9
ADjW9iiJtaEYxCOjrnFzpcOvuQnWPC7dbb+cy+DntLy/g6x95kBlAPdp02nYoS42
mDHmYUx+rIvnAceSTr72R+Vu9LNVzdbvnULT1o/4kW6uwRnrskisoFkAzeMd/4DT
tY71Dkz9faJt4VIE0wF3/jYXbqVhffyu6xXl+mS9mmCw/u9pFXMys2i/5tF90qIx
hpcVLhqFq4+dTnXaohC2DRpd+sCH4wRHMIRpi7gWI+6nXwLg95VSSwRNd+C+tyyh
GXlSB7/9WOGRGv74M5W9im3VFn5Ot3zMruEtl/WA
-----END CERTIFICATE-----
@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAszcr/n7Jfof0O+rxOsq6TQq0UGqYMM/eUpcykyRaMOfg60oa
rhC1o88l8YGOK1h5zIctZuoZmVZTYfy6D+Qv8+0AWC1OCIW85t49s/hVRU6UgKK0
BYJIyjvGy+39dIYs4Xd1XW0KgRyMr0a0kQw7Kiocw6Bu5n3zrAhHguSBQvPcDa4L
lptc/kTFrqmEwK/cyiONpWA4UQi4LjfvVl4tT9heNr2yxDQGzw/M4iMI/uKlx73i
FhhKAAfdRrVlxZVlURsLK2ho4ZZeSuE1NVn6cBquUVjh+A3fIKL5iAWKkpTUf2g2
vg+AuzGG0zd/X3DC71c1jVEXvZx9E9L+Y/LzqwIDAQABAoIBAELDuAkMdMZFodA8
m3e6lKMk7L3UqDPvDLUaDMZSUaNMjzc4mS3lnbWT81/AUxWE1YNDjL99UOIWDeRA
QZSv/slRrsIqxppYMGKVwsjsJ+A1AQ/XDVfMDJACqvHIDJc/cTLhzQBsIfCtkR+v
KI+szdHMdIDQoOAPZhrdzr5NoHYvQM7B8HYe5G9dyw5GinRnTNqNUIhFM1HW5Gki
dhLAiqUGj2drSsbRoIWIOIzBbM3+hWZK1mO3q+QhdBEPcwzrOgMaj2722Dea57Hb
duCpdpKH43JfSmQ+f0V8OS/zYNUcyQikQg+Euak6dOuMhFN1ma7bNEug3slJMQ0M
JVG55IECgYEAxNgUXU+ORxCVZjMLxq2Uk2qJxbZspRIQ0ElsvsUpVpw0q0KV7V8K
qnxL4c6khOqWZQ9M7PWG4nJgjNXhYW9PpYdTXkmOZzAq+XU8nUYGHR0ZAlDj0oAd
lC9m9hBZPovxRozjMcRpnJinkZRLB0KEuTBECB6ZKZscLqbMIH81kWsCgYEA6RLd
b1Kk6xUjmUcGnq6bZN4a0spEGLayzgFOA2o/Ma1d94c3NsWsz97KGpCISExBOoPd
e/vryCrgvY50U4989z3mOVlcW9IJxaX5jyLmyG1POMkzwpWSST5u1DqnHpZ1xhzo
qjdd+F9E05PG8YM/2JYUDoCgL+BWvSYUsW/bdsECgYA2LZr9S8ZHPQNBy87z8haw
tGQTLPCeRmimS29I2o9ULU45zOvjF4OiBPAFyJBznPWj/yAXIETt0rlMShnsbWyo
jKSfkPNG53UMj/4M85b/MGEPyB/MckKx5JIcK8fEdVQFLQXjTsIavdFxOjWkW+SX
6/btnS5eyzhohrQsRZcC3QKBgEuzauSLbTFFjmhsX0QO5j3evcuVEoUMYgry9Ym6
aogSDSEmc9KAZd6mN/Jk2z7QNadxyPBKJIzBEHnA2RuC0U3kdvBNi+fu0mm1vNa2
uUqD5mVFRGCBACB1/L1Fx53xtJMCNLeEgCr5lns51jX/MS+Bn0YOlPi33rRUuAfh
kuCBAoGAPvxUmDXFnYyt8/3t5dpKt1GEpqDdQfhUDqE6zOPulsv0IkMKCvbyHdKI
iR1EbSvCMP9aVO7BeVRnr9FSrdL10TWNLP4JveSI4Ee1bzy0vvTj5l8CC4MwSdhN
04I8F7UqPhSbdVjsTxw16XrHSkvB5JRZsIAz/K0jVMwZs7fS8Lk=
-----END RSA PRIVATE KEY-----
@@ -1,70 +0,0 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2024 ImmortalWrt
. /lib/functions.sh
. /lib/functions/procd.sh
USE_PROCD=1
START=90
STOP=10
init_conf() {
config_load "gecoosac"
config_get "db_dir" "config" "db_dir" "/etc/gecoosac/"
config_get "upload_dir" "config" "upload_dir" "/tmp/gecoosac/upload/"
config_get "enabled" "config" "enabled" "0"
config_get "port" "config" "port" "60650"
config_get "isonlyoneprot" "config" "isonlyoneprot" "1"
config_get "m_port" "config" "m_port" "8080"
config_get "https" "config" "https" "0"
config_get "crt_file" "config" "crt_file" "/etc/gecoosac/tls/1.crt"
config_get "key_file" "config" "key_file" "/etc/gecoosac/tls/1.key"
config_get "log" "config" "log" "0"
}
start_service() {
init_conf
[ "${enabled}" = "1" ] || return 0
procd_open_instance gecoosac
procd_set_param command "/usr/bin/gecoosac"
procd_append_param command -f "${upload_dir}"
procd_append_param command -p "${port}"
procd_append_param command -debug "0"
procd_append_param command -dbpath "${db_dir}"
procd_append_param command -token "1"
if [ "${isonlyoneprot}" = "0" ]; then
procd_append_param command -isonlyoneprot "0"
procd_append_param command -mp "${m_port}"
if [ "${https}" = "1" ]; then
procd_append_param command -https "1"
procd_append_param command -crt "${crt_file}"
procd_append_param command -key "${key_file}"
else
procd_append_param command -https "0"
fi
else
procd_append_param command -isonlyoneprot "1"
fi
procd_append_param command -showtip "0"
procd_set_param env GIN_MODE=release
procd_set_param pidfile /var/run/gecoosac.pid
procd_set_param stdout $log
procd_set_param stderr $log
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
procd_close_instance
}
stop_service(){
init_conf
}
reload_service()
{
stop
start
}
service_triggers() {
procd_add_reload_trigger "gecoosac"
}
@@ -15,5 +15,6 @@ uci -q batch <<-EOF >/dev/null
commit ucitrack commit ucitrack
EOF EOF
rm -rf /tmp/luci-* rm -f /tmp/luci-indexcache
rm -rf /tmp/luci-modulecache
exit 0 exit 0
+2 -2
View File
@@ -11,8 +11,8 @@ LUCI_DESCRIPTION:=LuCI JS interface for the modemband. The package allows set LT
LUCI_DEPENDS:=+modemband LUCI_DEPENDS:=+modemband
PKG_NAME:=luci-app-modemband PKG_NAME:=luci-app-modemband
PKG_VERSION:=1.0.24 PKG_VERSION:=1.0.25.20240519
PKG_RELEASE:=2 PKG_RELEASE:=3
PKG_MAINTAINER:=Rafał Wabik <4Rafal@gmail.com> PKG_MAINTAINER:=Rafał Wabik <4Rafal@gmail.com>
include $(TOPDIR)/feeds/luci/luci.mk include $(TOPDIR)/feeds/luci/luci.mk
@@ -3,14 +3,14 @@
'require form'; 'require form';
'require network'; 'require network';
var callFileList = rpc.declare({ const callFileList = rpc.declare({
object: 'file', object: 'file',
method: 'list', method: 'list',
params: [ 'path' ], params: [ 'path' ],
expect: { entries: [] }, expect: { entries: [] },
filter: function(list, params) { filter: function(list, params) {
var rv = []; let rv = [];
for (var i = 0; i < list.length; i++) for (let i = 0; i < list.length; i++)
if (list[i].name.match(/^cdc-wdm/)) if (list[i].name.match(/^cdc-wdm/))
rv.push(params.path + list[i].name); rv.push(params.path + list[i].name);
return rv.sort(); return rv.sort();
@@ -31,7 +31,7 @@ return network.registerProtocol('quectel', {
return this._ubus('l3_device') || 'quectel-%s'.format(this.sid); return this._ubus('l3_device') || 'quectel-%s'.format(this.sid);
}, },
getOpkgPackage: function() { getPackageName: function() {
return 'quectel-cm'; return 'quectel-cm';
}, },
@@ -52,14 +52,14 @@ return network.registerProtocol('quectel', {
}, },
renderFormOptions: function(s) { renderFormOptions: function(s) {
var dev = this.getL3Device() || this.getDevice(), o; let dev = this.getL3Device() || this.getDevice(), o;
o = s.taboption('general', form.Value, '_modem_device', _('Modem device')); o = s.taboption('general', form.Value, '_modem_device', _('Modem device'));
o.ucioption = 'device'; o.ucioption = 'device';
o.rmempty = false; o.rmempty = false;
o.load = function(section_id) { o.load = function(section_id) {
return callFileList('/dev/').then(L.bind(function(devices) { return callFileList('/dev/').then(L.bind(function(devices) {
for (var i = 0; i < devices.length; i++) for (let i = 0; i < devices.length; i++)
this.value(devices[i]); this.value(devices[i]);
return form.Value.prototype.load.apply(this, [section_id]); return form.Value.prototype.load.apply(this, [section_id]);
}, this)); }, this));
@@ -99,7 +99,7 @@ return network.registerProtocol('quectel', {
o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'), o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'),
_('Maximum amount of seconds to wait for the modem to become ready')); _('Maximum amount of seconds to wait for the modem to become ready'));
o.placeholder = '20'; o.placeholder = '10';
o.datatype = 'min(1)'; o.datatype = 'min(1)';
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU')); o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
-28
View File
@@ -1,28 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=modemband
PKG_VERSION:=20240616
PKG_RELEASE:=1
PKG_LICENSE:=MIT
PKG_MAINTAINER:=Cezary Jackiewicz <cezary@eko.one.pl>
include $(INCLUDE_DIR)/package.mk
define Package/modemband
SECTION:=net
CATEGORY:=Network
SUBMENU:=WWAN
TITLE:=Setting LTE/5G bands for selected modems
DEPENDS:=+sms-tool
PKGARCH:=all
endef
define Build/Compile
endef
define Package/modemband/install
$(CP) ./files/* $(1)
endef
$(eval $(call BuildPackage,modemband))
-135
View File
@@ -1,135 +0,0 @@
Setting LTE/5G NSA/5G SA bands for selected modems.
Supported devices:
- BroadMobi BM806U
- Dell DW5821e Snapdragon X20 LTE (Foxconn T77W968)
- Fibocom FM350-GL
- Fibocom L850-GL
- Fibocom L850-GL in mbim mode
- Fibocom L860-GL
- Fibocom L860-GL-16
- HP lt4112 (Huawei ME906E)
- HP lt4132 LTE/HSPA+ 4G Module (Huawei ME906s-158)
- HP lt4220 (Foxconn T77W676)
- HP lt4220 (Foxconn T77W676) in mbim mode
- Huawei (various models) in serial mode
- Quectel EC20
- Quectel EC25
- Quectel EG06-E
- Quectel EG18-EA
- Quectel EM12-G
- Quectel EM160R-GL
- Quectel EP06-E
- Quectel RG500Q-EA
- Quectel RG502Q-EA
- Quectel RM500Q-GL
- Quectel RM500U-CNV
- Quectel RM502Q-AE
- Quectel RM502Q-GL
- Quectel RM505Q-AE
- Quectel RM520N-GL
- Sierra Wireless EM7455/MC7455/DW5811e
- SIMCOM SIM8200EA-M2
- Telit LM940
- Telit LN940 (Foxconn T77W676)
- Telit LN940 (Foxconn T77W676) in mbim mode
- Telit LN960 (Foxconn T77W968)
- Telit LN960
- Yuge CLM920 NC_5
- ZTE MF286 (router)
- ZTE MF286A (router)
- ZTE MF286D (router)
- ZTE MF286R (router)
- ZTE MF289R (router)
```
root@MiFi:~# modemband.sh help
Available commands:
/usr/bin/modemband.sh getinfo
/usr/bin/modemband.sh json
/usr/bin/modemband.sh help
for LTE modem
/usr/bin/modemband.sh getsupportedbands
/usr/bin/modemband.sh getsupportedbandsext
/usr/bin/modemband.sh getbands
/usr/bin/modemband.sh getbandsext
/usr/bin/modemband.sh setbands "<band list>"
for 5G NSA modem
/usr/bin/modemband.sh getsupportedbands5gnsa
/usr/bin/modemband.sh getsupportedbandsext5gnsa
/usr/bin/modemband.sh getbands5gnsa
/usr/bin/modemband.sh getbandsext5gnsa
/usr/bin/modemband.sh setbands5gnsa "<band list>"
for 5G SA modem
/usr/bin/modemband.sh getsupportedbands5gsa
/usr/bin/modemband.sh getsupportedbandsext5gsa
/usr/bin/modemband.sh getbands5gsa
/usr/bin/modemband.sh getbandsext5gsa
/usr/bin/modemband.sh setbands5gsa "<band list>"
root@MiFi:~# # modemband.sh
Modem: Quectel EC25
Supported LTE bands: 1 3 5 7 8 20 38 40 41
LTE bands: 1 3 5 7 8 20 38 40 41
1: FDD 2100 MHz
3: FDD 1800 MHz
5: FDD 850 MHz
7: FDD 2600 MHz
8: FDD 900 MHz
20: FDD 800 MHz
38: TDD 2600 MHz
40: TDD 2300 MHz
41: TDD 2500 MHz
root@MiFi:~# modemband.sh json
{ "modem": "Quectel EC25", "supported": [ { "band": 1, "txt": "FDD 2100 MHz" }, { "band": 3, "txt": "FDD 1800 MHz" }, { "band": 5, "txt": "FDD 850 MHz" }, { "band": 7, "txt": "FDD 2600 MHz" }, { "band": 8, "txt": "FDD 900 MHz" }, { "band": 20, "txt": "FDD 800 MHz" }, { "band": 38, "txt": "TDD 2600 MHz" }, { "band": 40, "txt": "TDD 2300 MHz" }, { "band": 41, "txt": "TDD 2500 MHz" } ], "enabled": [ 1, 3, 5, 7, 8, 20, 38, 40, 41 ] }
root@MiFi:~# modemband.sh getinfo
Quectel EC25
root@MiFi:~# modemband.sh getsupportedbands
1 3 5 7 8 20 38 40 41
root@MiFi:~# modemband.sh getsupportedbandsext
1: FDD 2100 MHz
3: FDD 1800 MHz
5: FDD 850 MHz
7: FDD 2600 MHz
8: FDD 900 MHz
20: FDD 800 MHz
38: TDD 2600 MHz
40: TDD 2300 MHz
41: TDD 2500 MHz
root@MiFi:~# modemband.sh getbands
1 3 5 7 8 20 38 40 41
root@MiFi:~# modemband.sh getbandsext
1: FDD 2100 MHz
3: FDD 1800 MHz
5: FDD 850 MHz
7: FDD 2600 MHz
8: FDD 900 MHz
20: FDD 800 MHz
38: TDD 2600 MHz
40: TDD 2300 MHz
41: TDD 2500 MHz
root@MiFi:~# modemband.sh setbands "1 3 5 40"
at+qcfg="band",0,8000000015,0,1
root@MiFi:~# modemband.sh getbands
1 3 5 40
root@MiFi:~# modemband.sh setbands default
at+qcfg="band",0,1a0000800d5,0,1
root@MiFi:~# modemband.sh getbands
1 3 5 7 8 20 38 40 41
```
See also [description in Polish](https://eko.one.pl/?p=openwrt-modemband).
-518
View File
@@ -1,518 +0,0 @@
#!/bin/sh
#
# (c) 2022-2024 Cezary Jackiewicz <cezary@eko.one.pl>
#
# (c) 2022-2024 modified by Rafał Wabik - IceG - From eko.one.pl forum
#
hextobands() {
BANDS=""
HEX="$1"
LEN=${#HEX}
if [ $LEN -gt 18 ]; then
CNT=$((LEN - 16))
HHEX=${HEX:0:CNT}
HEX="0x"${HEX:CNT}
fi
for B in $(seq 0 63); do
POW=$((2 ** $B))
T=$((HEX&$POW))
[ "x$T" = "x$POW" ] && BANDS="${BANDS}$((B + 1)) "
done
if [ -n "$HHEX" ]; then
for B in $(seq 0 63); do
POW=$((2 ** $B))
T=$((HHEX&$POW))
[ "x$T" = "x$POW" ] && BANDS="${BANDS}$((B + 1 + 64)) "
done
fi
echo "$BANDS"
}
bandstohex() {
BANDS="$1"
SUM=0
HSUM=0
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
if [ $BAND -gt 64 ]; then
B=$((BAND - 1 - 64))
POW=$((2 ** $B))
HSUM=$((HSUM + POW))
else
B=$((BAND - 1))
POW=$((2 ** $B))
SUM=$((SUM + POW))
fi
done
if [ $HSUM -eq 0 ]; then
HEX=$(printf '%x' $SUM)
else
HEX=$(printf '%x%016x' $HSUM $SUM)
fi
echo "$HEX"
}
bandtxt() {
BAND=$1
# see https://en.wikipedia.org/wiki/LTE_frequency_bands
case "$BAND" in
"1") echo " $BAND: FDD 2100 MHz";;
"2") echo " $BAND: FDD 1900 MHz";;
"3") echo " $BAND: FDD 1800 MHz";;
"4") echo " $BAND: FDD 1700 MHz";;
"5") echo " $BAND: FDD 850 MHz";;
"7") echo " $BAND: FDD 2600 MHz";;
"8") echo " $BAND: FDD 900 MHz";;
"11") echo "$BAND: FDD 1500 MHz";;
"12") echo "$BAND: FDD 700 MHz";;
"13") echo "$BAND: FDD 700 MHz";;
"14") echo "$BAND: FDD 700 MHz";;
"17") echo "$BAND: FDD 700 MHz";;
"18") echo "$BAND: FDD 850 MHz";;
"19") echo "$BAND: FDD 850 MHz";;
"20") echo "$BAND: FDD 800 MHz";;
"21") echo "$BAND: FDD 1500 MHz";;
"24") echo "$BAND: FDD 1600 MHz";;
"25") echo "$BAND: FDD 1900 MHz";;
"26") echo "$BAND: FDD 850 MHz";;
"28") echo "$BAND: FDD 700 MHz";;
"29") echo "$BAND: SDL 700 MHz";;
"30") echo "$BAND: FDD 2300 MHz";;
"31") echo "$BAND: FDD 450 MHz";;
"32") echo "$BAND: SDL 1500 MHz";;
"34") echo "$BAND: TDD 2000 MHz";;
"37") echo "$BAND: TDD 1900 MHz";;
"38") echo "$BAND: TDD 2600 MHz";;
"39") echo "$BAND: TDD 1900 MHz";;
"40") echo "$BAND: TDD 2300 MHz";;
"41") echo "$BAND: TDD 2500 MHz";;
"42") echo "$BAND: TDD 3500 MHz";;
"43") echo "$BAND: TDD 3700 MHz";;
"46") echo "$BAND: TDD 5200 MHz";;
"47") echo "$BAND: TDD 5900 MHz";;
"48") echo "$BAND: TDD 3500 MHz";;
"50") echo "$BAND: TDD 1500 MHz";;
"51") echo "$BAND: TDD 1500 MHz";;
"53") echo "$BAND: TDD 2400 MHz";;
"54") echo "$BAND: TDD 1600 MHz";;
"65") echo "$BAND: FDD 2100 MHz";;
"66") echo "$BAND: FDD 1700 MHz";;
"67") echo "$BAND: SDL 700 MHz";;
"69") echo "$BAND: SDL 2600 MHz";;
"70") echo "$BAND: FDD 1700 MHz";;
"71") echo "$BAND: FDD 600 MHz";;
"72") echo "$BAND: FDD 450 MHz";;
"73") echo "$BAND: FDD 450 MHz";;
"74") echo "$BAND: FDD 1500 MHz";;
"75") echo "$BAND: SDL 1500 MHz";;
"76") echo "$BAND: SDL 1500 MHz";;
"85") echo "$BAND: FDD 700 MHz";;
"87") echo "$BAND: FDD 410 MHz";;
"88") echo "$BAND: FDD 410 MHz";;
"103") echo "$BAND: FDD 700 MHz";;
"106") echo "$BAND: FDD 900 MHz";;
esac
}
bandtxt5g() {
BAND=$1
# see https://en.wikipedia.org/wiki/5G_NR_frequency_bands
case "$BAND" in
"1") echo " $BAND: FDD 2100 MHz";;
"2") echo " $BAND: FDD 1900 MHz";;
"3") echo " $BAND: FDD 1800 MHz";;
"5") echo " $BAND: FDD 850 MHz";;
"7") echo " $BAND: FDD 2600 MHz";;
"8") echo " $BAND: FDD 900 MHz";;
"12") echo "$BAND: FDD 700 MHz";;
"13") echo "$BAND: FDD 700 MHz";;
"14") echo "$BAND: FDD 700 MHz";;
"18") echo "$BAND: FDD 850 MHz";;
"20") echo "$BAND: FDD 800 MHz";;
"24") echo "$BAND: FDD 1600 MHz";;
"25") echo "$BAND: FDD 1900 MHz";;
"26") echo "$BAND: FDD 850 MHz";;
"28") echo "$BAND: FDD 700 MHz";;
"29") echo "$BAND: SDL 700 MHz";;
"30") echo "$BAND: TDD 2300 MHz";;
"34") echo "$BAND: TDD 2100 MHz";;
"38") echo "$BAND: TDD 2600 MHz";;
"39") echo "$BAND: TDD 1900 MHz";;
"40") echo "$BAND: TDD 2300 MHz";;
"41") echo "$BAND: TDD 2500 MHz";;
"46") echo "$BAND: TDD 5200 MHz";;
"47") echo "$BAND: TDD 5900 MHz";;
"48") echo "$BAND: TDD 3500 MHz";;
"50") echo "$BAND: TDD 1500 MHz";;
"51") echo "$BAND: TDD 1500 MHz";;
"53") echo "$BAND: TDD 2400 MHz";;
"54") echo "$BAND: TDD 1600 MHz";;
"65") echo "$BAND: FDD 2100 MHz";;
"66") echo "$BAND: FDD 1700/2100 MHz";;
"67") echo "$BAND: SDL 700 MHz";;
"70") echo "$BAND: FDD 2000 MHz";;
"71") echo "$BAND: FDD 600 MHz";;
"74") echo "$BAND: FDD 1500 MHz";;
"75") echo "$BAND: SDL 1500 MHz";;
"76") echo "$BAND: SDL 1500 MHz";;
"77") echo "$BAND: TDD 3700 MHz";;
"78") echo "$BAND: TDD 3500 MHz";;
"79") echo "$BAND: TDD 4700 MHz";;
"80") echo "$BAND: SUL 1800 MHz";;
"81") echo "$BAND: SUL 900 MHz";;
"82") echo "$BAND: SUL 800 MHz";;
"83") echo "$BAND: SUL 700 MHz";;
"84") echo "$BAND: SUL 2100 MHz";;
"85") echo "$BAND: FDD 700 MHz";;
"86") echo "$BAND: SUL 1700 MHz";;
"89") echo "$BAND: SUL 850 MHz";;
"90") echo "$BAND: TDD 2500 MHz";;
"91") echo "$BAND: FDD 800/1500 MHz";;
"92") echo "$BAND: FDD 800/1500 MHz";;
"93") echo "$BAND: FDD 900/1500 MHz";;
"94") echo "$BAND: FDD 900/1500 MHz";;
"95") echo "$BAND: SUL 2100 MHz";;
"96") echo "$BAND: TDD 6000 MHz";;
"97") echo "$BAND: SUL 2300 MHz";;
"98") echo "$BAND: SUL 1900 MHz";;
"99") echo "$BAND: SUL 1600 MHz)";;
"100") echo "$BAND: FDD 900 MHz";;
"101") echo "$BAND: TDD 1900 MHz";;
"102") echo "$BAND: TDD 6200 MHz";;
"104") echo "$BAND: TDD 6700 MHz";;
"105") echo "$BAND: FDD 600 MHz";;
"257") echo "$BAND: 28 GHz";;
"258") echo "$BAND: 26 GHz";;
"259") echo "$BAND: 41 GHz";;
"260") echo "$BAND: 39 GHz";;
"261") echo "$BAND: 28 GHz";;
"262") echo "$BAND: 47 GHz";;
"263") echo "$BAND: 60 GHz";;
esac
}
_DEVICE=""
_DEFAULT_LTE_BANDS=""
_DEFAULT_5GNSA_BANDS=""
_DEFAULT_5GSA_BANDS=""
# default templates
# modem name/type
getinfo() {
echo "Unsupported"
}
# get supported band - 4G
getsupportedbands() {
echo "Unsupported"
}
getsupportedbandsext() {
T=$(getsupportedbands)
[ "x$T" = "xUnsupported" ] && return
for BAND in $T; do
bandtxt "$BAND"
done
}
# get current configured bands - 4G
getbands() {
echo "Unsupported"
}
getbandsext() {
T=$(getbands)
[ "x$T" = "xUnsupported" ] && return
for BAND in $T; do
bandtxt "$BAND"
done
}
# set bands - 4G
setbands() {
echo "Unsupported"
}
# get supported band - 5G NSA
getsupportedbands5gnsa() {
echo "Unsupported"
}
getsupportedbandsext5gnsa() {
T=$(getsupportedbands5gnsa)
[ "x$T" = "xUnsupported" ] && return
for BAND in $T; do
bandtxt5g "$BAND"
done
}
# get current configured bands - 5G NSA
getbands5gnsa() {
echo "Unsupported"
}
getbandsext5gnsa() {
T=$(getbands5gnsa)
[ "x$T" = "xUnsupported" ] && return
for BAND in $T; do
bandtxt5g "$BAND"
done
}
# set bands - 5G NSA
setbands5gnsa() {
echo "Unsupported"
}
# get supported band - 5G SA
getsupportedbands5gsa() {
echo "Unsupported"
}
getsupportedbandsext5gsa() {
T=$(getsupportedbands5gsa)
[ "x$T" = "xUnsupported" ] && return
for BAND in $T; do
bandtxt5g "$BAND"
done
}
# get current configured bands - 5G SA
getbands5gsa() {
echo "Unsupported"
}
getbandsext5gsa() {
T=$(getbands5gsa)
[ "x$T" = "xUnsupported" ] && return
for BAND in $T; do
bandtxt5g "$BAND"
done
}
# set bands - 5G SA
setbands5gsa() {
echo "Unsupported"
}
RES="/usr/share/modemband"
_DEVS=$(awk '{gsub("="," ");
if ($0 ~ /Bus.*Lev.*Prnt.*Port.*/) {T=$0}
if ($0 ~ /Vendor.*ProdID/) {idvendor[T]=$3; idproduct[T]=$5}
if ($0 ~ /Product/) {product[T]=$3}}
END {for (idx in idvendor) {printf "%s%s\n%s%s%s\n", idvendor[idx], idproduct[idx], idvendor[idx], idproduct[idx], product[idx]}}' /sys/kernel/debug/usb/devices)
for _DEV in $_DEVS; do
if [ -e "$RES/$_DEV" ]; then
. "$RES/$_DEV"
break
fi
done
if [ -z "$_DEVICE" ]; then
if [ "x$1" = "xjson" ]; then
echo '{"error":"No supported modem was found, quitting..."}'
else
echo "No supported modem was found, quitting..."
fi
exit 0
else
_DEVICE1=$(uci -q get modemband.@modemband[0].set_port)
if [ -n "$_DEVICE1" ]; then
_DEVICE=$_DEVICE1
fi
fi
if [ ! -e "$_DEVICE" ]; then
if [ "x$1" = "xjson" ]; then
echo '{"error":"Port not found, quitting..."}'
else
echo "Port not found, quitting..."
fi
exit 0
fi
case $1 in
"getinfo")
getinfo
;;
"getsupportedbands")
getsupportedbands
;;
"getsupportedbandsext")
getsupportedbandsext
;;
"getbands")
getbands
;;
"getbandsext")
getbandsext
;;
"setbands")
[ -n "$2" ] && setbands "$2"
;;
"getsupportedbands5gnsa")
getsupportedbands5gnsa
;;
"getsupportedbandsext5gnsa")
getsupportedbandsext5gnsa
;;
"getbands5gnsa")
getbands5gnsa
;;
"getbandsext5gnsa")
getbandsext5gnsa
;;
"setbands5gnsa")
[ -n "$2" ] && setbands5gnsa "$2"
;;
"getsupportedbands5gsa")
getsupportedbands5gsa
;;
"getsupportedbandsext5gsa")
getsupportedbandsext5gsa
;;
"getbands5gsa")
getbands5gsa
;;
"getbandsext5gsa")
getbandsext5gsa
;;
"setbands5gsa")
[ -n "$2" ] && setbands5gsa "$2"
;;
"json")
. /usr/share/libubox/jshn.sh
json_init
json_add_string modem "$(getinfo)"
json_add_array supported
T=$(getsupportedbands)
if [ "x$T" != "xUnsupported" ]; then
for BAND in $T; do
json_add_object ""
json_add_int band $BAND
TXT="$(bandtxt $BAND)"
json_add_string txt "${TXT##*: }"
json_close_object
done
fi
json_close_array
json_add_array enabled
T=$(getbands)
if [ "x$T" != "xUnsupported" ]; then
for BAND in $T; do
json_add_int "" $BAND
done
fi
json_close_array
T=$(getsupportedbands5gnsa)
if [ "x$T" != "xUnsupported" ]; then
json_add_array supported5gnsa
for BAND in $T; do
json_add_object ""
json_add_int band $BAND
TXT="$(bandtxt5g $BAND)"
json_add_string txt "${TXT##*: }"
json_close_object
done
json_close_array
json_add_array enabled5gnsa
T=$(getbands5gnsa)
if [ "x$T" != "xUnsupported" ]; then
for BAND in $T; do
json_add_int "" $BAND
done
fi
json_close_array
fi
T=$(getsupportedbands5gsa)
if [ "x$T" != "xUnsupported" ]; then
json_add_array supported5gsa
for BAND in $T; do
json_add_object ""
json_add_int band $BAND
TXT="$(bandtxt5g $BAND)"
json_add_string txt "${TXT##*: }"
json_close_object
done
json_close_array
json_add_array enabled5gsa
T=$(getbands5gsa)
if [ "x$T" != "xUnsupported" ]; then
for BAND in $T; do
json_add_int "" $BAND
done
fi
json_close_array
fi
json_dump
;;
"help")
echo "Available commands:"
echo " $0 getinfo"
echo " $0 json"
echo " $0 help"
echo ""
echo "for LTE modem"
echo " $0 getsupportedbands"
echo " $0 getsupportedbandsext"
echo " $0 getbands"
echo " $0 getbandsext"
echo " $0 setbands \"<band list>\""
echo ""
echo "for 5G NSA modem"
echo " $0 getsupportedbands5gnsa"
echo " $0 getsupportedbandsext5gnsa"
echo " $0 getbands5gnsa"
echo " $0 getbandsext5gnsa"
echo " $0 setbands5gnsa \"<band list>\""
echo ""
echo "for 5G SA modem"
echo " $0 getsupportedbands5gsa"
echo " $0 getsupportedbandsext5gsa"
echo " $0 getbands5gsa"
echo " $0 getbandsext5gsa"
echo " $0 setbands5gsa \"<band list>\""
;;
*)
echo -n "Modem: "
getinfo
echo -n "Supported LTE bands: "
getsupportedbands
echo -n "Enabled LTE bands: "
getbands
echo ""
getsupportedbandsext
T=$(getsupportedbands5gnsa)
if [ "x$T" != "xUnsupported" ]; then
echo -n "Supported 5G NSA bands: "
getsupportedbands5gnsa
echo -n "Enabled 5G NSA bands: "
getbands5gnsa
echo ""
getsupportedbandsext5gnsa
fi
T=$(getsupportedbands5gsa)
if [ "x$T" != "xUnsupported" ]; then
echo -n "Supported 5G SA bands: "
getsupportedbands5gsa
echo -n "Enabled 5G SA bands: "
getbands5gsa
echo ""
getsupportedbandsext5gsa
fi
;;
esac
exit 0
@@ -1,8 +0,0 @@
_DEVICE=/dev/ttyUSB1
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 17 18 19 20 21 25 26 28 29 30 38 39 40 41 66"
getinfo() {
echo "Qualcomm Snapdragon(TM) X12 LTE-A"
}
. $RES/_foxconn_common2
@@ -1,10 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 3 5 7 8 20"
getinfo() {
echo "Quectel EC20"
}
# +QCFG: "band",0xdf,0x800d5,0x3f
. $RES/_quectel_common
@@ -1,36 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 3 5 8 38 39 40 41"
getinfo() {
echo "Yuge CLM920 NC_5"
}
getsupportedbands() {
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
O=$(sms_tool -d $_DEVICE at "as+bandcfg?")
HEXHI=$(echo "$O" | awk -F[,] '/^\+BANDCFG:3,/{print $2}' | xargs)
HEXLO=$(echo "$O" | awk -F[,] '/^\+BANDCFG:3,/{print $3}' | xargs)
hextobands $(printf "0x%x%08x" 0x${HEXHI:-0} 0x${HEXLO:-0})
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
HEX=$(bandstohex "$BANDS")
LEN=${#HEX}
if [ $LEN -gt 8 ]; then
CNT=$((LEN - 8))
HEXHI=${HEX:0:CNT}
HEXLO=${HEX:CNT}
else
HEXLO=$HEX
HEXHI=0
fi
HEXHI=$(printf "%X" 0x$HEXHI)
HEXLO=$(printf "%X" 0x$HEXLO)
[ "$HEX" != "0" ] && sms_tool -d $_DEVICE at "at+bandcfg=$HEXHI,$HEXLO,3"
}
@@ -1,4 +0,0 @@
# +GTUSBMODE: 40
_DEVICE=/dev/ttyUSB2
. $RES/_fibocom_fm350_common
@@ -1,4 +0,0 @@
# +GTUSBMODE: 41
_DEVICE=/dev/ttyUSB4
. $RES/_fibocom_fm350_common
@@ -1,38 +0,0 @@
_DEVICE=/dev/ttyUSB2
getinfo() {
echo "Sierra Wireless EM7455/MC7455/DW5811e"
}
getsupportedbands() {
sms_tool -d $_DEVICE at 'AT!ENTERCND="A710"' >/dev/null 2>&1
O=$(sms_tool -d $_DEVICE at 'AT!BAND=?')
HEX=$(echo "$O" | awk '/^00, All bands/{printf "0x%s\n", $5}')
[ "$HEX" = "0x" ] || hextobands "$HEX"
}
getbands() {
sms_tool -d $_DEVICE at 'AT!ENTERCND="A710"' >/dev/null 2>&1
O=$(sms_tool -d $_DEVICE at 'AT!BAND?')
HEX=$(echo "$O" | awk -F, '/^[0-9a-fA-F][0-9a-fA-F],/{print $3}' | awk '{printf "0x%s\n", $2}')
[ "$HEX" = "0x" ] || hextobands "$HEX"
}
setbands() {
BANDS="$1"
if [ "$BANDS" = "default" ]; then
sms_tool -d $_DEVICE at 'AT!ENTERCND="A710"' >/dev/null 2>&1
sms_tool -d $_DEVICE at 'AT!BAND=00' >/dev/null 2>&1
else
HEXL=$(bandstohex "$BANDS")
if [ "$HEXL" != "0" ]; then
sms_tool -d $_DEVICE at 'AT!ENTERCND="A710"' >/dev/null 2>&1
O=$(sms_tool -d $_DEVICE at 'AT!BAND?')
HEXGW=$(echo "$O" | awk -F, '/^[0-9a-fA-F][0-9a-fA-F],/{print $3}' | awk '{print $1}')
sms_tool -d $_DEVICE at 'AT!BAND=10,"Custom bands",'$HEXGW','$HEXL
sms_tool -d $_DEVICE at 'AT!BAND=10'
sms_tool -d $_DEVICE at 'AT!RESET'
fi
fi
}
@@ -1,47 +0,0 @@
_DEVICE=/dev/ttyUSB2
getinfo() {
echo "Sierra Wireless EM7465"
}
getsupportedbands() {
sms_tool -d $_DEVICE at 'AT!ENTERCND="A710"' >/dev/null 2>&1
O=$(sms_tool -d $_DEVICE at 'AT!BAND=?')
HEX=$(echo "$O" | awk '/^00, All bands/{printf "0x%s%s\n", $6, $5}')
[ "$HEX" = "0x" ] || hextobands "$HEX"
}
getbands() {
sms_tool -d $_DEVICE at 'AT!ENTERCND="A710"' >/dev/null 2>&1
O=$(sms_tool -d $_DEVICE at 'AT!BAND?')
HEX=$(echo "$O" | awk -F, '/^[0-9a-fA-F][0-9a-fA-F],/{print $3}' | awk '{printf "0x%s%s\n", $3, $2}')
[ "$HEX" = "0x" ] || hextobands "$HEX"
}
setbands() {
BANDS="$1"
if [ "$BANDS" = "default" ]; then
sms_tool -d $_DEVICE at 'AT!ENTERCND="A710"' >/dev/null 2>&1
sms_tool -d $_DEVICE at 'AT!BAND=00' >/dev/null 2>&1
else
HEX=$(bandstohex "$BANDS")
if [ "$HEX" != "0" ]; then
sms_tool -d $_DEVICE at 'AT!ENTERCND="A710"' >/dev/null 2>&1
O=$(sms_tool -d $_DEVICE at 'AT!BAND?')
HEXGW=$(echo "$O" | awk -F, '/^[0-9a-fA-F][0-9a-fA-F],/{print $3}' | awk '{print $1}')
LEN=${#HEX}
if [ $LEN -gt 16 ]; then
CNT=$((LEN - 16))
HEXL2=${HEX:0:CNT}
HEXL1=${HEX:CNT}
else
HEXL1=$HEX
HEXL2=0
fi
sms_tool -d $_DEVICE at 'AT!BAND=10,"Custom bands",'$HEXGW','$HEXL1','$HEXL2
sms_tool -d $_DEVICE at 'AT!BAND=10'
sms_tool -d $_DEVICE at 'AT!RESET'
fi
fi
}
@@ -1,60 +0,0 @@
_DEVICE=/dev/ttyUSB1
getinfo() {
O=$(sms_tool -d $_DEVICE at "at+cgmi")
VENDOR=$(echo "$O" | awk '/^[a-zA-Z0-9]/ && !/at\+cgmi/{print $0}' | xargs)
O=$(sms_tool -d $_DEVICE at "at+cgmm")
PRODUCT=$(echo "$O" | awk '/^[a-zA-Z0-9]/ && !/at\+cgmm/{print $0}' | xargs)
echo "$(echo ${VENDOR:0:1} | tr '[a-z]' '[A-Z]')${VENDOR:1} $PRODUCT"
}
getsupportedbands() {
O=$(sms_tool -d $_DEVICE at "at+cgmm")
_NAME=$(echo "$O" | awk '/^[a-zA-Z0-9]/ && !/at\+cgmm/{print tolower($0)}' | xargs)
case "$_NAME" in
"me906e"* | \
"me909u-521")
echo "1 2 3 5 7 8 20"
;;
"me906s"*)
echo "1 2 3 5 7 8 20 28"
;;
"me909s-120")
echo "1 2 3 4 5 7 8 20"
;;
"me909s-821")
echo "1 3 8 38 39 40 41"
;;
"me909s-821a")
echo "1 3 5 8 38 39 40 41"
;;
*)
echo "1 3 7 8 20"
;;
esac
}
getbands() {
O=$(sms_tool -d $_DEVICE at "at^syscfgex?")
HEX="0x"$(echo "$O" | awk -F[:,] '/^\^SYSCFGEX:/{print $6}' | xargs)
if [ "$HEX" = "0x7FFFFFFFFFFFFFFF" ]; then
getsupportedbands
else
[ "$HEX" = "0x" ] || hextobands "$HEX"
fi
}
setbands() {
BANDS="$1"
if [ "$BANDS" = "default" ]; then
HEX="7FFFFFFFFFFFFFFF"
else
HEX=$(bandstohex "$BANDS")
fi
if [ "$HEX" != "0" ]; then
O=$(sms_tool -d $_DEVICE at "at^syscfgex?")
MODE=$(echo "$O" | awk -F[:,] '{print $2}' | xargs)
sms_tool -d $_DEVICE at "at^syscfgex=\"${MODE:-030201}\",3FFFFFFF,2,4,$HEX,,"
fi
}
@@ -1,34 +0,0 @@
_DEVICE=/dev/ttyUSB2
getinfo() {
echo "Huawei E3372h-320"
}
getsupportedbands() {
echo "1 3 7 8 20 28"
}
getbands() {
O=$(sms_tool -d $_DEVICE at "at^syscfgex?")
HEX="0x"$(echo "$O" | awk -F[:,] '/^\^SYSCFGEX:/{print $6}' | xargs)
if [ "$HEX" = "0x7FFFFFFFFFFFFFFF" ]; then
getsupportedbands
else
[ "$HEX" = "0x" ] || hextobands "$HEX"
fi
}
setbands() {
BANDS="$1"
if [ "$BANDS" = "default" ]; then
HEX="7FFFFFFFFFFFFFFF"
else
HEX=$(bandstohex "$BANDS")
fi
if [ "$HEX" != "0" ]; then
O=$(sms_tool -d $_DEVICE at "at^syscfgex?")
MODE=$(echo "$O" | awk -F[:,] '{print $2}' | xargs)
sms_tool -d $_DEVICE at "at^syscfgex=\"${MODE:-030201}\",3FFFFFFF,2,4,$HEX,,"
fi
}
@@ -1,20 +0,0 @@
_DEVICE=/dev/ttyUSB1
_DEFAULT_LTE_BANDS="1 3 7 8 20 28"
_NAME="ZTE MF286"
case $(cat /tmp/sysinfo/board_name) in
"zte,mf286a")
_DEFAULT_LTE_BANDS="1 2 3 5 7 8 20 38"
_NAME="ZTE MF286A"
;;
"zte,mf289f")
_DEFAULT_LTE_BANDS="1 3 7 8 20 28 32 38"
_NAME="ZTE MF289F"
;;
esac
getinfo() {
echo "$_NAME"
}
. $RES/_zte_common
@@ -1,15 +0,0 @@
_DEVICE=/dev/ttyUSB1
_DEFAULT_LTE_BANDS="1 3 7 8 20 28 32 38"
_NAME="ZTE MF286D"
case $(cat /tmp/sysinfo/board_name) in
"zte,mf289f")
_NAME="ZTE MF289F"
;;
esac
getinfo() {
echo "$_NAME"
}
. $RES/_zte_common
@@ -1,8 +0,0 @@
_DEVICE=/dev/ttyACM0
_DEFAULT_LTE_BANDS="1 3 7 8 20 38"
getinfo() {
echo "ZTE MF286R"
}
. $RES/_zte_common
@@ -1,31 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 17 20 25 26 28 29 30 38 40 41"
getinfo() {
echo "Telit LM940"
}
getsupportedbands() {
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
# #BND: 0,11,1A03B0918DF
O=$(sms_tool -d $_DEVICE at "at#bnd?")
HEX="0x"$(echo "$O" | awk -F[:,] '{print $4}' | xargs)
hextobands "$HEX"
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
HEX=$(bandstohex "$BANDS")
if [ "$HEX" != "0" ]; then
O=$(sms_tool -d $_DEVICE at "at#bnd?")
GSM=$(echo "$O" | awk -F[:,] '{print $2}' | xargs)
UMTS=$(echo "$O" | awk -F[:,] '{print $3}' | xargs)
sms_tool -d $_DEVICE at "at#bnd=${GSM},${UMTS},${HEX}"
fi
}
@@ -1,8 +0,0 @@
_DEVICE=/dev/ttyUSB1
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 17 18 19 20 21 25 26 28 29 30 38 39 40 41 66"
getinfo() {
echo "Telit LN940 Mobile Broadband"
}
. $RES/_foxconn_common2
@@ -1,8 +0,0 @@
_DEVICE=/dev/ttyUSB1
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 17 18 19 20 25 26 28 29 30 32 38 39 40 41 42 43 46 66"
getinfo() {
echo "Telit LN960 Mobile Broadband"
}
. $RES/_foxconn_common1
@@ -1,83 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 17 18 19 20 25 26 28 29 30 32 34 38 39 40 41 42 43 48 66 71"
_DEFAULT_5GNSA_BANDS="1 2 3 5 7 8 12 14 20 28 38 40 41 48 66 71 77 78"
_DEFAULT_5GSA_BANDS="1 2 3 5 7 8 12 14 20 28 38 40 41 48 66 71 77 78"
getinfo() {
echo "SIMCOM SIM8200EA-M2"
}
getsupportedbands() {
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
O=$(sms_tool -d $_DEVICE at "AT+CSYSSEL=\"lte_band\"")
echo "$O" | awk -F, '/^\+CSYSSEL: "lte_band",/{gsub(":"," ");print $2}' | xargs
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
T=""
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T}:"
T="${T}${BAND}"
done
[ -n "$T" ] && sms_tool -d $_DEVICE at "AT+CSYSSEL=\"lte_band\",$T"
}
getsupportedbands5gnsa() {
echo "$_DEFAULT_5GNSA_BANDS"
}
getbands5gnsa() {
O=$(sms_tool -d $_DEVICE at "AT+CSYSSEL=\"nsa_nr5g_band\"")
echo "$O" | awk -F, '/^\+CSYSSEL: "nsa_nr5g_band",/{gsub(":"," ");print $2}' | xargs
}
setbands5gnsa() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_5GNSA_BANDS"
T=""
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T}:"
T="${T}${BAND}"
done
[ -n "$T" ] && sms_tool -d $_DEVICE at "AT+CSYSSEL=\"nsa_nr5g_band\",$T"
}
getsupportedbands5gsa() {
echo "$_DEFAULT_5GSA_BANDS"
}
getbands5gsa() {
O=$(sms_tool -d $_DEVICE at "AT+CSYSSEL=\"nr5g_band\"")
echo "$O" | awk -F, '/^\+CSYSSEL: "nr5g_band",/{gsub(":"," ");print $2}' | xargs
}
setbands5gsa() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_5GSA_BANDS"
T=""
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T}:"
T="${T}${BAND}"
done
[ -n "$T" ] && sms_tool -d $_DEVICE at "AT+CSYSSEL=\"nr5g_band\",$T"
}
@@ -1,24 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 5 7 8 12 17 20 38 40"
getinfo() {
echo "BroadMobi BM806U"
}
getsupportedbands() {
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
O=$(sms_tool -d $_DEVICE at "at+bmbandpref?")
HEX=$(echo "$O" | awk -F[:,] '{print $3}' | xargs)
hextobands "$HEX"
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
HEX=$(bandstohex "$BANDS")
[ "$HEX" != "0" ] && sms_tool -d $_DEVICE at "at+bmbandpref=,$HEX,"
}
@@ -1,8 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 3 5 7 8 20 38 40 41"
getinfo() {
echo "Quectel EC25"
}
. $RES/_quectel_common
@@ -1,10 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 3 5 7 8 20 28 32 38 40 41"
getinfo() {
echo "Quectel EG06-E"
}
# +QCFG: "band",0x8df,0x1a0880800d5,0x0
. $RES/_quectel_common
@@ -1,10 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 3 5 7 8 20 28 38 40 41"
getinfo() {
echo "Quectel EP06-E"
}
# +QCFG: "band",0x8d0,0x1a0080800d5,0x1
. $RES/_quectel_common
@@ -1,8 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 3 5 7 8 20 28 38 40 41"
getinfo() {
echo "Quectel EG18-EA"
}
. $RES/_quectel_common
@@ -1,26 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 9 12 13 14 17 18 19 20 21 25 26 28 29 30 32 38 39 40 41 66"
getinfo() {
echo "Quectel EM12-G"
}
getsupportedbands() {
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
# +QCFG: "band",0x5af0,0x42000000003300185a,0x1
O=$(sms_tool -d $_DEVICE at "AT+QCFG=\"band\"")
HEX=$(echo "$O" | awk -F[:,] '{print $4}' | xargs)
hextobands "$HEX"
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
HEX=$(bandstohex "$BANDS")
[ "$HEX" != "0" ] && sms_tool -d $_DEVICE at "AT+QCFG=\"band\",0,$HEX,1"
}
@@ -1,33 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 18 19 20 25 26 28 29 30 32 38 39 40 41 42 46 48 66"
getinfo() {
echo "Quectel EM160R-GL"
}
getsupportedbands() {
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
# +QNWPREFCFG: "lte_band",1:3:7:8:20:28:38
O=$(sms_tool -d $_DEVICE at "at+qnwprefcfg=\"lte_band\"?")
echo "$O" | awk -F, '/^\+QNWPREFCFG:/{gsub(":"," ");print $2}'
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
T=""
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T}:"
T="${T}${BAND}"
done
[ -n "$T" ] && sms_tool -d $_DEVICE at "at+qnwprefcfg=\"lte_band\",$T"
}
@@ -1,12 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 3 5 7 8 18 19 20 26 28 32 34 38 39 40 41 42 43"
_DEFAULT_5GNSA_BANDS="1 3 5 7 8 20 28 38 40 41 77 78 79"
_DEFAULT_5GSA_BANDS="1 3 5 7 8 20 28 38 40 41 77 78 79"
getinfo() {
echo "Quectel RG500Q-EA"
}
# +QNWPREFCFG: "lte_band",1:3:7:8:20:28:38
. $RES/_quectel_common2
@@ -1,12 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 17 18 19 20 25 26 28 29 30 32 34 38 39 40 41 42 43 46 48 66 71"
_DEFAULT_5GNSA_BANDS="1 3 5 7 8 20 28 38 40 41 77 78 79"
_DEFAULT_5GSA_BANDS="1 3 5 7 8 20 28 38 40 41 77 78 79"
getinfo() {
echo "Quectel RG502Q-EA"
}
# +QNWPREFCFG: "lte_band",1:3:7:8:20:28:38
. $RES/_quectel_common2
@@ -1,12 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 17 18 19 20 25 26 28 29 30 32 34 38 39 40 41 42 43 46 48 66 71"
_DEFAULT_5GNSA_BANDS="1 2 3 5 7 8 12 20 25 28 38 40 41 48 66 71 77 78 79"
_DEFAULT_5GSA_BANDS="1 2 3 5 7 8 12 20 25 28 38 40 41 48 66 71 77 78 79"
getinfo() {
echo "Quectel RM500Q-GL"
}
# +QNWPREFCFG: "lte_band",1:3:7:8:20:28:38
. $RES/_quectel_common2
@@ -1,12 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 18 19 20 25 26 28 29 30 32 34 38 39 40 41 42 43 46 48 66 71"
_DEFAULT_5GNSA_BANDS="1 2 3 5 7 8 12 20 25 28 38 40 41 48 66 71 77 78 79"
_DEFAULT_5GSA_BANDS="1 2 3 5 7 8 12 20 25 28 38 40 41 48 66 71 77 78 79"
getinfo() {
echo "Quectel RM502Q-AE"
}
# +QNWPREFCFG: "lte_band",1:3:7:8:20:28:38
. $RES/_quectel_common2
@@ -1,12 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 17 18 19 20 25 26 28 29 30 32 34 38/39 40 41 42 43 48 66 71"
_DEFAULT_5GNSA_BANDS="38 41 77 78"
_DEFAULT_5GSA_BANDS="1 2 3 5 7 8 12 20 25 28 38 40 41 48 66 71 77 78"
getinfo() {
echo "Quectel RM502Q-GL"
}
# +QNWPREFCFG: "lte_band",1:3:7:8:20:28:38
. $RES/_quectel_common2
@@ -1,12 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 4 5 8 12 13 14 17 18 19 20 25 26 28 29 30 32 34 39 40 41 42 43 46 48 66 71"
_DEFAULT_5GNSA_BANDS="1 2 3 5 7 8 12 14 20 25 28 38 40 41 48 66 71 77 78 79"
_DEFAULT_5GSA_BANDS="1 2 3 5 7 8 12 14 20 25 28 38 40 41 48 66 71 77 78 79"
getinfo() {
echo "Quectel RM505Q-AE"
}
# +QNWPREFCFG: "lte_band",1:3:7:8:20:28:38
. $RES/_quectel_common2
@@ -1,15 +0,0 @@
_DEVICE=/dev/ttyUSB3
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 17 18 19 20 25 26 28 29 30 32 34 38 39 40 41 42 43 46 48 66 71"
_DEFAULT_5GNSA_BANDS="1 2 3 5 7 8 12 13 14 18 20 25 26 28 29 30 38 40 41 48 66 70 71 75 76 77 78 79"
_DEFAULT_5GSA_BANDS="1 2 3 5 7 8 12 13 14 18 20 25 26 28 29 30 38 40 41 48 66 70 71 75 76 77 78 79"
getinfo() {
VENDOR=$(sms_tool -d /dev/ttyUSB3 at AT+CGMI | tr -s '\n' | xargs)
DEVICE=$(sms_tool -d /dev/ttyUSB3 at AT+CGMM | tr -s '\n' | xargs)
echo "$VENDOR $DEVICE"
}
# +QNWPREFCFG: "lte_band",1:2:3:4:5:7:8:12:13:14:17:18:19:20:25:26:28:29:30:32:34:38:39:40:41:42:43:46:48:66:71
# +QNWPREFCFG: "nsa_nr5g_band",1:2:3:5:7:8:12:13:14:18:20:25:26:28:29:30:38:40:41:48:66:70:71:75:76:77:78:79
. $RES/_quectel_common2
@@ -1,12 +0,0 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 2 3 5 8 34 38 39 40 41"
_DEFAULT_5GNSA_BANDS="41 78 79"
_DEFAULT_5GSA_BANDS="1 2 3 5 8 28 41 77 78 79"
getinfo() {
echo "Quectel RM500U-CNV"
}
# +QNWPREFCFG: "lte_band",1:3:7:8:20:28:38
. $RES/_quectel_common2
@@ -1,8 +0,0 @@
_DEVICE=/dev/ttyUSB1
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 17 18 19 20 25 26 28 29 30 32 38 39 40 41 42 43 46 66"
getinfo() {
echo "Dell DW5821e Snapdragon X20 LTE"
}
. $RES/_foxconn_common1
@@ -1,57 +0,0 @@
_DEVICE=/dev/ttyACM2
getinfo() {
O=$(sms_tool -d $_DEVICE at "at+gmm")
_NAME="Fibocom $(echo "$O" | awk -F, '{print $2}')"
echo "$_NAME"
}
getsupportedbands() {
O=$(sms_tool -d $_DEVICE at "at+gmm")
if echo "$O" | grep -q "L850"; then
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 11 12 13 17 18 19 20 21 26 28 29 30 38 39 40 41 66"
fi
if echo "$O" | grep -q "L860"; then
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 17 18 19 20 25 26 28 29 30 32 38 39 40 41 42 46 66"
fi
if echo "$O" | grep -q "L860-GL-16"; then
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 17 18 19 20 25 26 28 29 30 32 34 38 39 40 41 42 43 46 48 66 71"
fi
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
# +XACT: 4,2,1,1,2,4,5,8,101,102,103,104,105,107,108,112,113,114,117,118,119,120,125,126,128,129,130,132,138,139,140,141,142,146,166
O=$(sms_tool -d $_DEVICE at "at+xact?")
BANDS=$(echo "$O" | awk -F: '/^\+XACT:/{gsub(","," ");print $2}')
for BAND in $BANDS; do
if [ $BAND -gt 100 ] && [ $BAND -lt 200 ]; then
echo -n "$((BAND - 100)) "
fi
done
echo ""
}
setbands() {
BANDS="$1"
T=""
if [ "$BANDS" = "default" ]; then
T="0"
else
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T},"
T="${T}$((BAND + 100))"
done
fi
if [ -n "$T" ]; then
O=$(sms_tool -d $_DEVICE at "at+xact?")
MODE=$(echo "$O" | awk -F[:,] '{print $2}' | xargs)
sms_tool -d $_DEVICE at "at+xact=$MODE,,,$T"
fi
}
@@ -1,131 +0,0 @@
# Unified for NSA/SA
_DEFAULT_5G_BANDS="1 2 3 5 7 8 20 25 28 30 38 40 41 48 66 71 77 78 79"
getinfo() {
O=$(sms_tool -d $_DEVICE at "AT+CGMM?")
_NAME="Fibocom $(echo "$O" | awk -F[:,] '/^\+CGMM:/{gsub("\"","");print $2}' | xargs)"
echo "$_NAME"
}
getsupportedbands() {
_DEFAULT_LTE_BANDS="1 2 3 4 5 7 8 12 13 14 17 18 19 20 25 26 28 29 30 32 34 38 39 40 41 42 43 46 48 66 71"
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
# +GTACT: 20,6,3,101,102,103,104,105,107,108,112,113,114,117,118,119,120,125,126,128,129,130,132,134,138,139,140,141,142,143,146,148,166,171
O=$(sms_tool -d $_DEVICE at "AT+GTACT?")
BANDS=$(echo "$O" | awk -F: '/^\+GTACT:/{gsub(","," ");print $2}')
for BAND in $BANDS; do
if [ $BAND -gt 100 ] && [ $BAND -lt 200 ]; then
echo -n "$((BAND - 100)) "
fi
done
echo ""
}
setbands() {
BANDS="$1"
T=""
if [ "$BANDS" = "default" ]; then
T="0"
else
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T},"
T="${T}$((BAND + 100))"
done
fi
if [ -n "$T" ]; then
O=$(sms_tool -d $_DEVICE at "AT+GTACT?")
MODE=$(echo "$O" | awk -F[:,] '/\+GTACT:/{print $2","$3","$4}'| xargs)
sms_tool -d $_DEVICE at "AT+GTACT=$MODE,$T"
fi
}
getsupportedbands5gsa() {
echo "$_DEFAULT_5G_BANDS"
}
getsupportedbands5gnsa() {
echo "$_DEFAULT_5G_BANDS"
}
getbands5gsa() {
# +GTACT: 20,6,3,501,502,503,505,507,508,5020,5025,5028,5030,5038,5040,5041,5048,5066,5071,5077,5078,5079
O=$(sms_tool -d $_DEVICE at "AT+GTACT?")
BANDS=$(echo "$O" | awk -F: '/^\+GTACT:/{gsub(","," ");print $2}')
for BAND in $BANDS; do
if [ $BAND -gt 500 ] && [ $BAND -lt 5100 ]; then
echo -n "$(echo "$BAND" | sed 's/^50//g') "
fi
done
echo ""
}
getbands5gnsa() {
# +GTACT: 20,6,3,501,502,503,505,507,508,5020,5025,5028,5030,5038,5040,5041,5048,5066,5071,5077,5078,5079
O=$(sms_tool -d $_DEVICE at "AT+GTACT?")
BANDS=$(echo "$O" | awk -F: '/^\+GTACT:/{gsub(","," ");print $2}')
for BAND in $BANDS; do
if [ $BAND -gt 500 ] && [ $BAND -lt 5100 ]; then
echo -n "$(echo "$BAND" | sed 's/^50//g') "
fi
done
echo ""
}
setbands5gsa() {
BANDS="$1"
T=""
if [ "$BANDS" = "default" ]; then
T="0"
else
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T},"
T="${T}50${BAND}"
done
fi
if [ -n "$T" ]; then
O=$(sms_tool -d $_DEVICE at "AT+GTACT?")
MODE=$(echo "$O" | awk -F[:,] '/\+GTACT:/{print $2","$3","$4}'| xargs)
sms_tool -d $_DEVICE at "AT+GTACT=$MODE,$T"
fi
}
setbands5gnsa() {
BANDS="$1"
T=""
if [ "$BANDS" = "default" ]; then
T="0"
else
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T},"
T="${T}50${BAND}"
done
fi
if [ -n "$T" ]; then
O=$(sms_tool -d $_DEVICE at "AT+GTACT?")
MODE=$(echo "$O" | awk -F[:,] '/\+GTACT:/{print $2","$3","$4}'| xargs)
sms_tool -d $_DEVICE at "AT+GTACT=$MODE,$T"
fi
}
@@ -1,27 +0,0 @@
getsupportedbands() {
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
# ^SLBAND: WCDMA,Enabled,1,2,4,5,6,8,9,19
# ^SLBAND: LTE,Enabled,1,2,3,4,5,7,8,12,13,14,17,18,19,20,25,26,28,29,30,32,38,39,40,41,42,43,46,66
O=$(sms_tool -d $_DEVICE at "at^slband?")
echo "$O" | awk -F: '/LTE/{gsub("LTE,Enabled,","");gsub(","," ");print $2}' | xargs
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
T=""
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T},"
T="${T}${BAND}"
done
[ -n "$T" ] && sms_tool -d $_DEVICE at "at^slband=lte,2,$T"
}
@@ -1,27 +0,0 @@
getsupportedbands() {
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
# ^SLBAND: WCDMA,1,2,4,5,6,8,9,19
# ^SLBAND: LTE,1,2,3,4,5,7,8,12,13,17,18,19,20,21,25,26,28,29,30,38,39,40,41,66
O=$(sms_tool -d $_DEVICE at "at^slband?")
echo "$O" | awk -F: '/^\^SLBAND:.*LTE,/{gsub("LTE,","");gsub(","," ");print $2}' | xargs
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
T=""
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T},"
T="${T}${BAND}"
done
[ -n "$T" ] && sms_tool -d $_DEVICE at "at^slband=lte,$T"
}
@@ -1,17 +0,0 @@
getsupportedbands() {
echo "${_DEFAULT_LTE_BANDS:-Unsupported}"
}
getbands() {
O=$(sms_tool -d $_DEVICE at "at+qcfg=\"band\"")
HEX=$(echo "$O" | awk -F[:,] '{print $4}' | xargs)
hextobands "$HEX"
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
HEX=$(bandstohex "$BANDS")
[ "$HEX" != "0" ] && sms_tool -d $_DEVICE at "at+qcfg=\"band\",0,$HEX,0,1"
}
@@ -1,80 +0,0 @@
getsupportedbands() {
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
# +QNWPREFCFG: "lte_band",1:3:7:8:20:28:38
O=$(sms_tool -d $_DEVICE at "at+qnwprefcfg=\"lte_band\"")
echo "$O" | awk -F, '/^\+QNWPREFCFG:/{gsub(":"," ");print $2}'
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
T=""
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T}:"
T="${T}${BAND}"
done
[ -n "$T" ] && sms_tool -d $_DEVICE at "at+qnwprefcfg=\"lte_band\",$T"
}
getsupportedbands5gnsa() {
echo "$_DEFAULT_5GNSA_BANDS"
}
getbands5gnsa() {
# +QNWPREFCFG: "nsa_nr5g_band",1:2:3:5:7:8:12:20:25:28:38:40:41:48:66:71:77:78:79
O=$(sms_tool -d $_DEVICE at "at+qnwprefcfg=\"nsa_nr5g_band\"")
echo "$O" | awk -F, '/^\+QNWPREFCFG:/{gsub(":"," ");print $2}' | xargs
}
setbands5gnsa() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_5GNSA_BANDS"
T=""
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T}:"
T="${T}${BAND}"
done
[ -n "$T" ] && sms_tool -d $_DEVICE at "at+qnwprefcfg=\"nsa_nr5g_band\",$T"
}
getsupportedbands5gsa() {
echo "$_DEFAULT_5GSA_BANDS"
}
getbands5gsa() {
# +QNWPREFCFG: "nr5g_band",1:2:3:5:7:8:12:20:25:28:38:40:41:48:66:71:77:78:79
O=$(sms_tool -d $_DEVICE at "at+qnwprefcfg=\"nr5g_band\"")
echo "$O" | awk -F, '/^\+QNWPREFCFG:/{gsub(":"," ");print $2}' | xargs
}
setbands5gsa() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_5GSA_BANDS"
T=""
for BAND in $BANDS; do
case $BAND in
''|*[!0-9]*) continue ;;
esac
[ -n "$T" ] && T="${T}:"
T="${T}${BAND}"
done
[ -n "$T" ] && sms_tool -d $_DEVICE at "at+qnwprefcfg=\"nr5g_band\",$T"
}
@@ -1,19 +0,0 @@
getsupportedbands() {
echo "$_DEFAULT_LTE_BANDS"
}
getbands() {
# +ZNLOCKBAND: 80800c5,2000000680380
O=$(sms_tool -d $_DEVICE at "at+znlockband?")
HEX="0x"$(echo "$O" | awk -F[:,] '{print $2}' | xargs)
hextobands "$HEX"
}
setbands() {
BANDS="$1"
[ "$BANDS" = "default" ] && BANDS="$_DEFAULT_LTE_BANDS"
HEX=$(bandstohex "$BANDS")
[ "$HEX" != "0" ] && sms_tool -d $_DEVICE at "at+znlockband=1,0,$HEX,0"
}
+10 -20
View File
@@ -1,36 +1,26 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=quectel-cm PKG_NAME:=quectel-cm
PKG_VERSION:=1.6.8 PKG_VERSION:=1.6.7
PKG_RELEASE:=3 PKG_RELEASE:=4
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/quectel-open-source/Quectel_QConnectManager_Linux
PKG_SOURCE_VERSION:=170ed7177cc3beb831bc85571aad956492ff7e7e
PKG_MIRROR_HASH:=skip
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/quectel-cm define Package/quectel-cm
SECTION:=net SECTION:=net
CATEGORY:=Network CATEGORY:=Network
SUBMENU:=WWAN TITLE:=Quectel dial program
TITLE:=Qconnector Manager for Quectel WWAN modules DEPENDS:=+libpthread
DEPENDS:= \
+kmod-usb-net-cdc-mbim \
+kmod-usb-net-qmi-wwan \
+kmod-usb-net-qmi-wwan-fibocom \
+kmod-usb-net-qmi-wwan-quectel \
+kmod-usb-serial-option
endef endef
define Package/quectel-cm/install define Package/quectel-cm/install
$(INSTALL_DIR) $(1)/usr/bin $(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/quectel-CM $(1)/usr/bin/quectel-cm $(INSTALL_BIN) $(PKG_BUILD_DIR)/quectel-CM $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/quectel-{mbim,qmi}-proxy $(1)/usr/bin/
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/quectel.sh $(1)/lib/netifd/proto/
$(INSTALL_DIR) $(1)/etc/hotplug.d/net
$(INSTALL_BIN) ./files/smp-affinity-mhi-pcie.sh $(1)/etc/hotplug.d/net/21-smp-affinity-mhi-pcie
$(INSTALL_BIN) ./files/smp-affinity-qmi-usb.sh $(1)/etc/hotplug.d/net/22-smp-affinity-qmi-usb
endef endef
$(eval $(call BuildPackage,quectel-cm)) $(eval $(call BuildPackage,quectel-cm))
-138
View File
@@ -1,138 +0,0 @@
#!/bin/sh
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. ../netifd-proto.sh
init_proto "$@"
}
proto_quectel_init_config() {
available=1
no_device=1
proto_config_add_string "device:device"
proto_config_add_string "apn"
proto_config_add_string "auth"
proto_config_add_string "username"
proto_config_add_string "password"
proto_config_add_string "pincode"
proto_config_add_int "delay"
proto_config_add_string "pdptype"
proto_config_add_boolean "dhcp"
proto_config_add_boolean "dhcpv6"
proto_config_add_boolean "sourcefilter"
proto_config_add_boolean "delegate"
proto_config_add_int "mtu"
proto_config_add_defaults
}
proto_quectel_setup() {
local interface="$1"
local device apn auth username password pincode delay pdptype
local dhcp dhcpv6 sourcefilter delegate mtu $PROTO_DEFAULT_OPTIONS
local ip4table ip6table
local pid zone
json_get_vars device apn auth username password pincode delay
json_get_vars pdptype dhcp dhcpv6 sourcefilter delegate ip4table
json_get_vars ip6table mtu $PROTO_DEFAULT_OPTIONS
[ -n "$delay" ] && sleep "$delay"
[ -n "$metric" ] || metric="0"
[ -z "$ctl_device" ] || device="$ctl_device"
[ -n "$device" ] || {
echo "No control device specified"
proto_notify_error "$interface" NO_DEVICE
proto_set_available "$interface" 0
return 1
}
device="$(readlink -f "$device")"
[ -c "$device" ] || {
echo "The specified control device does not exist"
proto_notify_error "$interface" NO_DEVICE
proto_set_available "$interface" 0
return 1
}
devname="$(basename "$device")"
devpath="$(readlink -f "/sys/class/usbmisc/$devname/device/")"
ifname="$(ls "$devpath/net" 2>"/dev/null")"
[ -n "$ifname" ] || {
echo "The interface could not be found."
proto_notify_error "$interface" NO_IFACE
proto_set_available "$interface" 0
return 1
}
[ "$pdptype" = "ipv4" -o "$pdptype" = "ipv4v6" ] && ipv4opt="-4"
[ "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && ipv6opt="-6"
[ -n "$auth" ] || auth="none"
eval "proto_run_command '$interface' /usr/bin/quectel-cm -i '$ifname' $ipv4opt $ipv6opt ${pincode:+-p $pincode} -s '$apn' '$username' '$password' '$auth'"
sleep 5
ifconfig "$ifname" up
ifconfig "${ifname}_1" &>"/dev/null" && ifname="${ifname}_1"
if [ -n "$mtu" ]; then
echo "Setting MTU to $mtu"
/sbin/ip link set dev "$ifname" mtu "$mtu"
fi
echo "Setting up $ifname"
proto_init_update "$ifname" 1
proto_set_keep 1
proto_send_update "$interface"
zone="$(fw3 -q network "$interface" 2>/dev/null)"
if [ "$pdptype" = "ipv6" ] || [ "$pdptype" = "ipv4v6" ]; then
json_init
json_add_string name "${interface}_6"
json_add_string ifname "@$interface"
[ "$pdptype" = "ipv4v6" ] && json_add_string iface_464xlat "0"
json_add_string proto "dhcpv6"
proto_add_dynamic_defaults
[ -z "$ip6table" ] || json_add_string ip6table "$ip6table"
# RFC 7278: Extend an IPv6 /64 Prefix to LAN
json_add_string extendprefix 1
[ "$delegate" = "0" ] && json_add_boolean delegate "0"
[ "$sourcefilter" = "0" ] && json_add_boolean sourcefilter "0"
[ -z "$zone" ] || json_add_string zone "$zone"
json_close_object
ubus call network add_dynamic "$(json_dump)"
fi
if [ "$pdptype" = "ipv4" ] || [ "$pdptype" = "ipv4v6" ]; then
json_init
json_add_string name "${interface}_4"
json_add_string ifname "@$interface"
json_add_string proto "dhcp"
[ -z "$ip4table" ] || json_add_string ip4table "$ip4table"
proto_add_dynamic_defaults
[ -z "$zone" ] || json_add_string zone "$zone"
json_close_object
ubus call network add_dynamic "$(json_dump)"
fi
}
proto_quectel_teardown() {
local interface="$1"
local device
json_get_vars device
[ -z "$ctl_device" ] || device="$ctl_device"
echo "Stopping network $interface"
proto_kill_command "$interface"
proto_init_update "*" 0
proto_send_update "$interface"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol quectel
}
-24
View File
@@ -1,24 +0,0 @@
#!/bin/sh
[ "$ACTION" = add ] || exit
echo "$INTERFACE" | grep -q "rmnet_mhi" || exit
core_count="$(grep -c "processor" "/proc/cpuinfo")"
irq_path="/sys/class/net/$INTERFACE/queues"
devnum="$(echo "${INTERFACE%.*}" | grep -Eo "[0-9]+")"
core="$(( devnum % (core_count - 1) + 1))"
if [ "$INTERFACE" != "${INTERFACE%.*}" ]; then
if [ "$core" -lt "$(( core_count - 1 ))" ]; then
let core++
else
core="1"
fi
fi
irq="$(printf "%x" "$((1 << core))")"
echo "$irq" > "$irq_path/rx-0/rps_cpus"
echo "4096" > "$irq_path/rx-0/rps_flow_cnt"
echo "2000" > "/proc/sys/net/core/netdev_max_backlog"
exit 0
-24
View File
@@ -1,24 +0,0 @@
#!/bin/sh
[ "$ACTION" = add ] || exit
echo "$INTERFACE" | grep -q "wwan" || exit
core_count="$(grep -c "processor" "/proc/cpuinfo")"
irq_path="/sys/class/net/$INTERFACE/queues"
devnum="$(echo "${INTERFACE%_*}" | grep -Eo "[0-9]+")"
core="$(( devnum % (core_count - 1) + 1))"
if [ "$INTERFACE" != "${INTERFACE%_*}" ]; then
if [ "$core" -lt "$(( core_count - 1 ))" ]; then
let core++
else
core="1"
fi
fi
irq="$(printf "%x" "$((1 << core))")"
echo "$irq" > "$irq_path/rx-0/rps_cpus"
echo "4096" > "$irq_path/rx-0/rps_flow_cnt"
echo "2000" > "/proc/sys/net/core/netdev_max_backlog"
exit 0
-29
View File
@@ -1,29 +0,0 @@
--- a/quectel-qrtr-proxy.c
+++ b/quectel-qrtr-proxy.c
@@ -555,7 +555,7 @@ static int recv_qmi_from_client(PQCQMIMS
}
else if (le16toh(pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType) == QMICTL_GET_CLIENT_ID_REQ) {
uint8_t QMIType = pQMI->CTLMsg.GetClientIdReq.QMIType;
- PQCQMIMSG pRsp = (PQCQMIMSG)malloc(256);
+ PQCQMIMSG pRsp = (PQCQMIMSG)malloc(sizeof(*pRsp));
if (pRsp) {
uint8_t ClientId = 0;
@@ -589,7 +589,7 @@ static int recv_qmi_from_client(PQCQMIMS
}
}
else if (le16toh(pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType) == QMICTL_RELEASE_CLIENT_ID_REQ) {
- PQCQMIMSG pRsp = (PQCQMIMSG)malloc(256);
+ PQCQMIMSG pRsp = (PQCQMIMSG)malloc(sizeof(*pRsp));
release_qrtr_client_id(qrtr_con, pQMI->CTLMsg.ReleaseClientIdReq.QMIType, pQMI->CTLMsg.ReleaseClientIdReq.ClientId);
if (pRsp) {
@@ -618,7 +618,7 @@ static int recv_qmi_from_client(PQCQMIMS
}
}
else if (le16toh(pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType) == QMICTL_GET_VERSION_REQ) {
- PQCQMIMSG pRsp = (PQCQMIMSG)malloc(256);
+ PQCQMIMSG pRsp = (PQCQMIMSG)malloc(sizeof(*pRsp));
if (pRsp) {
pRsp->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI;
-8
View File
@@ -1,8 +0,0 @@
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 3.10)
project(quectel-CM)
add_definitions(-Wall -Wextra -Werror -O1)
@@ -1,15 +0,0 @@
--- a/device.c
+++ b/device.c
@@ -342,10 +342,12 @@ BOOL qmidevice_detect(char *qmichannel,
switch (profile->usb_dev.idProduct) { //EC200U
case 0x0901: //EC200U
case 0x0902: //EC200D
+ case 0x0904: //EC200G
case 0x8101: //RG801H
atIntf = 2;
break;
case 0x0900: //RG500U
+ case 0x0903: //EC600
atIntf = 4;
break;
case 0x6026: //EC200T
-36
View File
@@ -1,36 +0,0 @@
cmake_minimum_required(VERSION 2.4)
project(quectel-CM)
add_definitions(-Wall -Wextra -Werror -O1)
option(USE_QRTR "Enable QRTR" OFF)
set( QL_CM_SRC
QmiWwanCM.c GobiNetCM.c main.c QCQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c
atc.c atchannel.c at_tok.c
udhcpc.c
)
if(USE_QRTR)
add_definitions(-DCONFIG_QRTR)
set( QRTR_SRC qrtr.c rmnetctl.c)
endif()
add_executable(quectel-CM ${QL_CM_SRC} ${QRTR_SRC})
target_link_libraries(quectel-CM PUBLIC pthread)
install (TARGETS quectel-CM DESTINATION bin)
add_executable(quectel-qmi-proxy quectel-qmi-proxy.c)
target_link_libraries(quectel-qmi-proxy PUBLIC pthread)
install (TARGETS quectel-qmi-proxy DESTINATION bin)
add_executable(quectel-mbim-proxy quectel-mbim-proxy.c)
target_link_libraries(quectel-mbim-proxy PUBLIC pthread)
install (TARGETS quectel-mbim-proxy DESTINATION bin)
add_executable(quectel-atc-proxy quectel-atc-proxy.c atchannel.c at_tok.c util.c)
target_link_libraries(quectel-atc-proxy PUBLIC pthread)
install (TARGETS quectel-atc-proxy DESTINATION bin)
add_executable(quectel-qrtr-proxy quectel-qrtr-proxy.c)
target_link_libraries(quectel-qrtr-proxy PUBLIC pthread)
install (TARGETS quectel-qrtr-proxy DESTINATION bin)
-242
View File
@@ -1,242 +0,0 @@
/*
Copyright 2025 Quectel Wireless Solutions Co.,Ltd
Quectel hereby grants customers of Quectel a license to use, modify,
distribute and publish the Software in binary form provided that
customers shall have no right to reverse engineer, reverse assemble,
decompile or reduce to source code form any portion of the Software.
Under no circumstances may customers modify, demonstrate, use, deliver
or disclose any portion of the Software in source code form.
*/
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <stdio.h>
#include <ctype.h>
#include "QMIThread.h"
#ifdef CONFIG_GOBINET
static int qmiclientId[QMUX_TYPE_ALL];
// IOCTL to generate a client ID for this service type
#define IOCTL_QMI_GET_SERVICE_FILE 0x8BE0 + 1
// IOCTL to get the VIDPID of the device
#define IOCTL_QMI_GET_DEVICE_VIDPID 0x8BE0 + 2
// IOCTL to get the MEID of the device
#define IOCTL_QMI_GET_DEVICE_MEID 0x8BE0 + 3
static int GobiNetSendQMI(PQCQMIMSG pRequest) {
int ret, fd;
fd = qmiclientId[pRequest->QMIHdr.QMIType];
pRequest->QMIHdr.ClientId = (fd&0xFF) ? fd&0xFF : pRequest->QMIHdr.QMIType;
if (fd <= 0) {
dbg_time("%s QMIType: %d has no clientID", __func__, pRequest->QMIHdr.QMIType);
return -ENODEV;
}
// Always ready to write
if (1 == 1) {
ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR);
ret = write(fd, &pRequest->MUXMsg, nwrites);
if (ret == nwrites) {
ret = 0;
} else {
dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno));
}
} else {
dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno));
}
return ret;
}
static int GobiNetGetClientID(const char *qcqmi, UCHAR QMIType) {
int ClientId;
ClientId = cm_open_dev(qcqmi);
if (ClientId == -1) {
dbg_time("failed to open %s, errno: %d (%s)", qcqmi, errno, strerror(errno));
return 0;
}
if (ioctl(ClientId, IOCTL_QMI_GET_SERVICE_FILE, QMIType) != 0) {
dbg_time("failed to get ClientID for 0x%02x errno: %d (%s)", QMIType, errno, strerror(errno));
close(ClientId);
ClientId = 0;
}
switch (QMIType) {
case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break;
case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break;
case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break;
case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break;
case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break;
case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break;
case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break;
case QMUX_TYPE_COEX: dbg_time("Get clientCOEX = %d", ClientId); break;
case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId);
break;
default: break;
}
return ClientId;
}
static int GobiNetDeInit(void) {
unsigned int i;
for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++)
{
if (qmiclientId[i] != 0)
{
close(qmiclientId[i]);
qmiclientId[i] = 0;
}
}
return 0;
}
static void * GobiNetThread(void *pData) {
PROFILE_T *profile = (PROFILE_T *)pData;
const char *qcqmi = (const char *)profile->qmichannel;
int wait_for_request_quit = 0;
qmiclientId[QMUX_TYPE_WDS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS);
if (profile->enable_ipv6)
qmiclientId[QMUX_TYPE_WDS_IPV6] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS);
qmiclientId[QMUX_TYPE_DMS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_DMS);
qmiclientId[QMUX_TYPE_NAS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_NAS);
qmiclientId[QMUX_TYPE_UIM] = GobiNetGetClientID(qcqmi, QMUX_TYPE_UIM);
#ifdef CONFIG_COEX_WWAN_STATE
qmiclientId[QMUX_TYPE_COEX] = GobiNetGetClientID(qcqmi, QMUX_TYPE_COEX);
#endif
if (profile->qmap_mode == 0 || profile->loopback_state) {//when QMAP enabled, set data format in GobiNet Driver
qmiclientId[QMUX_TYPE_WDS_ADMIN] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS_ADMIN);
profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN];
}
//donot check clientWDA, there is only one client for WDA, if quectel-CM is killed by SIGKILL, i cannot get client ID for WDA again!
if (qmiclientId[QMUX_TYPE_WDS] == 0) /*|| (clientWDA == -1)*/ {
GobiNetDeInit();
dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, qcqmi, errno, strerror(errno));
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
pthread_exit(NULL);
return NULL;
}
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED);
while (1) {
struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}};
int ne, ret, nevents = 1;
unsigned int i;
for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++)
{
if (qmiclientId[i] != 0)
{
pollfds[nevents].fd = qmiclientId[i];
pollfds[nevents].events = POLLIN;
pollfds[nevents].revents = 0;
nevents++;
}
}
do {
ret = poll(pollfds, nevents, wait_for_request_quit ? 1000: -1);
} while ((ret < 0) && (errno == EINTR));
if (ret == 0 && wait_for_request_quit) {
QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI()
continue;
}
if (ret <= 0) {
dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno));
break;
}
for (ne = 0; ne < nevents; ne++) {
int fd = pollfds[ne].fd;
short revents = pollfds[ne].revents;
if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
dbg_time("%s poll err/hup/inval", __func__);
dbg_time("epoll fd = %d, events = 0x%04x", fd, revents);
if (fd == qmidevice_control_fd[1]) {
} else {
}
if (revents & (POLLERR | POLLHUP | POLLNVAL))
goto __GobiNetThread_quit;
}
if ((revents & POLLIN) == 0)
continue;
if (fd == qmidevice_control_fd[1]) {
int triger_event;
if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) {
//DBG("triger_event = 0x%x", triger_event);
switch (triger_event) {
case RIL_REQUEST_QUIT:
goto __GobiNetThread_quit;
break;
case SIG_EVENT_STOP:
wait_for_request_quit = 1;
break;
default:
break;
}
}
continue;
}
{
ssize_t nreads;
PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf;
nreads = read(fd, &pResponse->MUXMsg, sizeof(cm_recv_buf) - sizeof(QCQMI_HDR));
if (nreads <= 0)
{
dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno));
break;
}
for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++)
{
if (qmiclientId[i] == fd)
{
pResponse->QMIHdr.QMIType = i;
}
}
pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI;
pResponse->QMIHdr.Length = cpu_to_le16(nreads + sizeof(QCQMI_HDR) - 1);
pResponse->QMIHdr.CtlFlags = 0x00;
pResponse->QMIHdr.ClientId = (fd&0xFF) ? fd&0xFF : pResponse->QMIHdr.QMIType;;
QmiThreadRecvQMI(pResponse);
}
}
}
__GobiNetThread_quit:
GobiNetDeInit();
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI()
dbg_time("%s exit", __func__);
pthread_exit(NULL);
return NULL;
}
const struct qmi_device_ops gobi_qmidev_ops = {
.deinit = GobiNetDeInit,
.send = GobiNetSendQMI,
.read = GobiNetThread,
};
#endif
-46
View File
@@ -1,46 +0,0 @@
ifneq ($(CROSS_COMPILE),)
CROSS-COMPILE:=$(CROSS_COMPILE)
endif
#CROSS-COMPILE:=/workspace/buildroot/buildroot-qemu_mips_malta_defconfig/output/host/usr/bin/mips-buildroot-linux-uclibc-
#CROSS-COMPILE:=/workspace/buildroot/buildroot-qemu_arm_vexpress_defconfig/output/host/usr/bin/arm-buildroot-linux-uclibcgnueabi-
#CROSS-COMPILE:=/workspace/buildroot-git/qemu_mips64_malta/output/host/usr/bin/mips-gnu-linux-
ifeq ($(CC),cc)
CC:=$(CROSS-COMPILE)gcc
endif
LD:=$(CROSS-COMPILE)ld
QL_CM_SRC=QmiWwanCM.c GobiNetCM.c main.c QCQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c
QL_CM_SRC+=atc.c atchannel.c at_tok.c
#QL_CM_SRC+=qrtr.c rmnetctl.c
ifeq (1,1)
QL_CM_DHCP=udhcpc.c
else
LIBMNL=libmnl/ifutils.c libmnl/attr.c libmnl/callback.c libmnl/nlmsg.c libmnl/socket.c
DHCP=libmnl/dhcp/dhcpclient.c libmnl/dhcp/dhcpmsg.c libmnl/dhcp/packet.c
QL_CM_DHCP=udhcpc_netlink.c
QL_CM_DHCP+=${LIBMNL}
endif
CFLAGS += -Wall -Wextra -Werror -O1 #-s
LDFLAGS += -lpthread -ldl -lrt
release: clean qmi-proxy mbim-proxy atc-proxy #qrtr-proxy
$(CC) ${CFLAGS} ${QL_CM_SRC} ${QL_CM_DHCP} -o quectel-CM ${LDFLAGS}
debug: clean
$(CC) ${CFLAGS} -g -DCM_DEBUG ${QL_CM_SRC} ${QL_CM_DHCP} -o quectel-CM -lpthread -ldl -lrt
qmi-proxy:
$(CC) ${CFLAGS} quectel-qmi-proxy.c -o quectel-qmi-proxy ${LDFLAGS}
mbim-proxy:
$(CC) ${CFLAGS} quectel-mbim-proxy.c -o quectel-mbim-proxy ${LDFLAGS}
qrtr-proxy:
$(CC) ${CFLAGS} quectel-qrtr-proxy.c -o quectel-qrtr-proxy ${LDFLAGS}
atc-proxy:
$(CC) ${CFLAGS} quectel-atc-proxy.c atchannel.c at_tok.c util.c -o quectel-atc-proxy ${LDFLAGS}
clean:
rm -rf *.o libmnl/*.o quectel-CM quectel-qmi-proxy quectel-mbim-proxy quectel-atc-proxy
-22
View File
@@ -1,22 +0,0 @@
bin_PROGRAMS = quectel-CM
QL_CM_SRC=QmiWwanCM.c GobiNetCM.c main.c QCQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c
QL_CM_SRC+=atc.c atchannel.c at_tok.c
#QL_CM_SRC+=qrtr.c rmnetctl.c
QL_CM_DHCP=udhcpc.c
if USE_QRTR
quectel_CM_CFLAGS = -DCONFIG_QRTR
QL_CM_SRC += qrtr.c rmnetctl.c
if USE_MSM_IPC
quectel_CM_CFLAGS += -DUSE_LINUX_MSM_IPC
endif
endif
quectel_CM_SOURCES = ${QL_CM_SRC} ${QL_CM_DHCP}
bin_PROGRAMS += quectel-qmi-proxy
quectel_qmi_proxy_SOURCES = quectel-qmi-proxy.c
bin_PROGRAMS += quectel-mbim-proxy
quectel_mbim_proxy_SOURCES = quectel-mbim-proxy.c
LIBS = -l pthread
CFLAGS = -Wall -Wextra -Werror -O1
-7
View File
@@ -1,7 +0,0 @@
This program is totally open souce code, and public domain software for customers of Quectel company.
The APIs of QMI WWAMN interfaces are defined by Qualcomm. And this program complies with Qualcomm QMI WWAN interfaces specification.
Customers are free to modify the source codes and redistribute them.
For those who is not Quectel's customer, all rights are closed, and any copying and commercial development over this progrma is not allowed.
-389
View File
@@ -1,389 +0,0 @@
/*
Copyright 2025 Quectel Wireless Solutions Co.,Ltd
Quectel hereby grants customers of Quectel a license to use, modify,
distribute and publish the Software in binary form provided that
customers shall have no right to reverse engineer, reverse assemble,
decompile or reduce to source code form any portion of the Software.
Under no circumstances may customers modify, demonstrate, use, deliver
or disclose any portion of the Software in source code form.
*/
#ifndef QCQCTL_H
#define QCQCTL_H
#include "QCQMI.h"
#pragma pack(push, 1)
// ================= QMICTL ==================
// QMICTL Control Flags
#define QMICTL_CTL_FLAG_CMD 0x00
#define QMICTL_CTL_FLAG_RSP 0x01
#define QMICTL_CTL_FLAG_IND 0x02
#if 0
typedef struct _QMICTL_TRANSACTION_ITEM
{
LIST_ENTRY List;
UCHAR TransactionId; // QMICTL transaction id
PVOID Context; // Adapter or IocDev
PIRP Irp;
} QMICTL_TRANSACTION_ITEM, *PQMICTL_TRANSACTION_ITEM;
#endif
typedef struct _QCQMICTL_MSG_HDR
{
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
UCHAR TransactionId;
USHORT QMICTLType;
USHORT Length;
} __attribute__ ((packed)) QCQMICTL_MSG_HDR, *PQCQMICTL_MSG_HDR;
#define QCQMICTL_MSG_HDR_SIZE sizeof(QCQMICTL_MSG_HDR)
typedef struct _QCQMICTL_MSG_HDR_RESP
{
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
UCHAR TransactionId;
USHORT QMICTLType;
USHORT Length;
UCHAR TLVType; // 0x02 - result code
USHORT TLVLength; // 4
USHORT QMUXResult; // QMI_RESULT_SUCCESS
// QMI_RESULT_FAILURE
USHORT QMUXError; // QMI_ERR_INVALID_ARG
// QMI_ERR_NO_MEMORY
// QMI_ERR_INTERNAL
// QMI_ERR_FAULT
} __attribute__ ((packed)) QCQMICTL_MSG_HDR_RESP, *PQCQMICTL_MSG_HDR_RESP;
typedef struct _QCQMICTL_MSG
{
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
UCHAR TransactionId;
USHORT QMICTLType;
USHORT Length;
UCHAR Payload;
} __attribute__ ((packed)) QCQMICTL_MSG, *PQCQMICTL_MSG;
// TLV Header
typedef struct _QCQMICTL_TLV_HDR
{
UCHAR TLVType;
USHORT TLVLength;
} __attribute__ ((packed)) QCQMICTL_TLV_HDR, *PQCQMICTL_TLV_HDR;
#define QCQMICTL_TLV_HDR_SIZE sizeof(QCQMICTL_TLV_HDR)
// QMICTL Type
#define QMICTL_SET_INSTANCE_ID_REQ 0x0020
#define QMICTL_SET_INSTANCE_ID_RESP 0x0020
#define QMICTL_GET_VERSION_REQ 0x0021
#define QMICTL_GET_VERSION_RESP 0x0021
#define QMICTL_GET_CLIENT_ID_REQ 0x0022
#define QMICTL_GET_CLIENT_ID_RESP 0x0022
#define QMICTL_RELEASE_CLIENT_ID_REQ 0x0023
#define QMICTL_RELEASE_CLIENT_ID_RESP 0x0023
#define QMICTL_REVOKE_CLIENT_ID_IND 0x0024
#define QMICTL_INVALID_CLIENT_ID_IND 0x0025
#define QMICTL_SET_DATA_FORMAT_REQ 0x0026
#define QMICTL_SET_DATA_FORMAT_RESP 0x0026
#define QMICTL_SYNC_REQ 0x0027
#define QMICTL_SYNC_RESP 0x0027
#define QMICTL_SYNC_IND 0x0027
#define QMI_MESSAGE_CTL_INTERNAL_PROXY_OPEN 0xFF00
#define QMICTL_FLAG_REQUEST 0x00
#define QMICTL_FLAG_RESPONSE 0x01
#define QMICTL_FLAG_INDICATION 0x02
// QMICTL Message Definitions
typedef struct _QMICTL_SET_INSTANCE_ID_REQ_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_REQ
USHORT Length; // 4
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLVLength; // 1
UCHAR Value; // Host-unique QMI instance for this device driver
} __attribute__ ((packed)) QMICTL_SET_INSTANCE_ID_REQ_MSG, *PQMICTL_SET_INSTANCE_ID_REQ_MSG;
typedef struct _QMICTL_SET_INSTANCE_ID_RESP_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_RESP
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
USHORT TLVLength; // 0x0004
USHORT QMIResult;
USHORT QMIError;
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLV2Length; // 0x0002
USHORT QMI_ID; // Upper byte is assigned by MSM,
// lower assigned by host
} __attribute__ ((packed)) QMICTL_SET_INSTANCE_ID_RESP_MSG, *PQMICTL_SET_INSTANCE_ID_RESP_MSG;
typedef struct _QMICTL_GET_VERSION_REQ_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_GET_VERSION_REQ
USHORT Length; // 0
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLVLength; // var
UCHAR QMUXTypes; // List of one byte QMUX_TYPE values
// 0xFF returns a list of versions for all
// QMUX_TYPEs implemented on the device
} __attribute__ ((packed)) QMICTL_GET_VERSION_REQ_MSG, *PQMICTL_GET_VERSION_REQ_MSG;
typedef struct _QMUX_TYPE_VERSION_STRUCT
{
UCHAR QMUXType;
USHORT MajorVersion;
USHORT MinorVersion;
} __attribute__ ((packed)) QMUX_TYPE_VERSION_STRUCT, *PQMUX_TYPE_VERSION_STRUCT;
typedef struct _ADDENDUM_VERSION_PREAMBLE
{
UCHAR LabelLength;
UCHAR Label;
} __attribute__ ((packed)) ADDENDUM_VERSION_PREAMBLE, *PADDENDUM_VERSION_PREAMBLE;
#define QMICTL_GET_VERSION_RSP_TLV_TYPE_VERSION 0x01
#define QMICTL_GET_VERSION_RSP_TLV_TYPE_ADD_VERSION 0x10
typedef struct _QMICTL_GET_VERSION_RESP_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_GET_VERSION_RESP
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
USHORT TLVLength; // 0x0004
USHORT QMIResult;
USHORT QMIError;
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLV2Length; // var
UCHAR NumElements; // Num of QMUX_TYPE_VERSION_STRUCT
QMUX_TYPE_VERSION_STRUCT TypeVersion[0];
} __attribute__ ((packed)) QMICTL_GET_VERSION_RESP_MSG, *PQMICTL_GET_VERSION_RESP_MSG;
typedef struct _QMICTL_GET_CLIENT_ID_REQ_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_REQ
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLVLength; // 1
UCHAR QMIType; // QMUX type
} __attribute__ ((packed)) QMICTL_GET_CLIENT_ID_REQ_MSG, *PQMICTL_GET_CLIENT_ID_REQ_MSG;
typedef struct _QMICTL_GET_CLIENT_ID_RESP_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_RESP
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
USHORT TLVLength; // 0x0004
USHORT QMIResult; // result code
USHORT QMIError; // error code
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLV2Length; // 2
UCHAR QMIType;
UCHAR ClientId;
} __attribute__ ((packed)) QMICTL_GET_CLIENT_ID_RESP_MSG, *PQMICTL_GET_CLIENT_ID_RESP_MSG;
typedef struct _QMICTL_RELEASE_CLIENT_ID_REQ_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_REQ
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLVLength; // 0x0002
UCHAR QMIType;
UCHAR ClientId;
} __attribute__ ((packed)) QMICTL_RELEASE_CLIENT_ID_REQ_MSG, *PQMICTL_RELEASE_CLIENT_ID_REQ_MSG;
typedef struct _QMICTL_RELEASE_CLIENT_ID_RESP_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_RESP
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
USHORT TLVLength; // 0x0004
USHORT QMIResult; // result code
USHORT QMIError; // error code
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLV2Length; // 2
UCHAR QMIType;
UCHAR ClientId;
} __attribute__ ((packed)) QMICTL_RELEASE_CLIENT_ID_RESP_MSG, *PQMICTL_RELEASE_CLIENT_ID_RESP_MSG;
typedef struct _QMICTL_REVOKE_CLIENT_ID_IND_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLVLength; // 0x0002
UCHAR QMIType;
UCHAR ClientId;
} __attribute__ ((packed)) QMICTL_REVOKE_CLIENT_ID_IND_MSG, *PQMICTL_REVOKE_CLIENT_ID_IND_MSG;
typedef struct _QMICTL_INVALID_CLIENT_ID_IND_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLVLength; // 0x0002
UCHAR QMIType;
UCHAR ClientId;
} __attribute__ ((packed)) QMICTL_INVALID_CLIENT_ID_IND_MSG, *PQMICTL_INVALID_CLIENT_ID_IND_MSG;
typedef struct _QMICTL_SET_DATA_FORMAT_REQ_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_REQ
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
USHORT TLVLength; // 1
UCHAR DataFormat; // 0-default; 1-QoS hdr present
} __attribute__ ((packed)) QMICTL_SET_DATA_FORMAT_REQ_MSG, *PQMICTL_SET_DATA_FORMAT_REQ_MSG;
#ifdef QC_IP_MODE
#define SET_DATA_FORMAT_TLV_TYPE_LINK_PROTO 0x10
#define SET_DATA_FORMAT_LINK_PROTO_ETH 0x0001
#define SET_DATA_FORMAT_LINK_PROTO_IP 0x0002
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT
{
UCHAR TLVType; // Link-Layer Protocol
USHORT TLVLength; // 2
USHORT LinkProt; // 0x1: ETH; 0x2: IP
} QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT, *PQMICTL_SET_DATA_FORMAT_TLV_LINK_PROT;
#ifdef QCMP_UL_TLP
#define SET_DATA_FORMAT_TLV_TYPE_UL_TLP 0x11
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_UL_TLP
{
UCHAR TLVType; // 0x11, Uplink TLP Setting
USHORT TLVLength; // 1
UCHAR UlTlpSetting; // 0x0: Disable; 0x01: Enable
} QMICTL_SET_DATA_FORMAT_TLV_UL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_UL_TLP;
#endif // QCMP_UL_TLP
#ifdef QCMP_DL_TLP
#define SET_DATA_FORMAT_TLV_TYPE_DL_TLP 0x13
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_DL_TLP
{
UCHAR TLVType; // 0x11, Uplink TLP Setting
USHORT TLVLength; // 1
UCHAR DlTlpSetting; // 0x0: Disable; 0x01: Enable
} QMICTL_SET_DATA_FORMAT_TLV_DL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_DL_TLP;
#endif // QCMP_DL_TLP
#endif // QC_IP_MODE
#ifdef MP_QCQOS_ENABLED
#define SET_DATA_FORMAT_TLV_TYPE_QOS_SETTING 0x12
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING
{
UCHAR TLVType; // 0x12, QoS setting
USHORT TLVLength; // 1
UCHAR QosSetting; // 0x0: Disable; 0x01: Enable
} QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING, *PQMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING;
#endif // MP_QCQOS_ENABLED
typedef struct _QMICTL_SET_DATA_FORMAT_RESP_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
USHORT TLVLength; // 0x0004
USHORT QMIResult; // result code
USHORT QMIError; // error code
} __attribute__ ((packed)) QMICTL_SET_DATA_FORMAT_RESP_MSG, *PQMICTL_SET_DATA_FORMAT_RESP_MSG;
typedef struct _QMICTL_SYNC_REQ_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_CTL_SYNC_REQ
USHORT Length; // 0
} __attribute__ ((packed)) QMICTL_SYNC_REQ_MSG, *PQMICTL_SYNC_REQ_MSG;
typedef struct _QMICTL_SYNC_RESP_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_CTL_SYNC_RESP
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
USHORT TLVLength; // 0x0004
USHORT QMIResult;
USHORT QMIError;
} __attribute__ ((packed)) QMICTL_SYNC_RESP_MSG, *PQMICTL_SYNC_RESP_MSG;
typedef struct _QMICTL_SYNC_IND_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
USHORT Length;
} __attribute__ ((packed)) QMICTL_SYNC_IND_MSG, *PQMICTL_SYNC_IND_MSG;
typedef struct _QMICTL_LIBQMI_PROXY_OPEN_MSG
{
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
UCHAR TransactionId;
USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP
USHORT Length;
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
USHORT TLVLength; // 0x0004
char device_path[0]; // result code
} __attribute__ ((packed)) QMICTL_LIBQMI_PROXY_OPEN_MSG, *PQMICTL_LIBQMI_PROXY_OPEN_MSG;
typedef struct _QMICTL_MSG
{
union
{
// Message Header
QCQMICTL_MSG_HDR QMICTLMsgHdr;
QCQMICTL_MSG_HDR_RESP QMICTLMsgHdrRsp;
// QMICTL Message
QMICTL_SET_INSTANCE_ID_REQ_MSG SetInstanceIdReq;
QMICTL_SET_INSTANCE_ID_RESP_MSG SetInstanceIdRsp;
QMICTL_GET_VERSION_REQ_MSG GetVersionReq;
QMICTL_GET_VERSION_RESP_MSG GetVersionRsp;
QMICTL_GET_CLIENT_ID_REQ_MSG GetClientIdReq;
QMICTL_GET_CLIENT_ID_RESP_MSG GetClientIdRsp;
QMICTL_RELEASE_CLIENT_ID_REQ_MSG ReleaseClientIdReq;
QMICTL_RELEASE_CLIENT_ID_RESP_MSG ReleaseClientIdRsp;
QMICTL_REVOKE_CLIENT_ID_IND_MSG RevokeClientIdInd;
QMICTL_INVALID_CLIENT_ID_IND_MSG InvalidClientIdInd;
QMICTL_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq;
QMICTL_SET_DATA_FORMAT_RESP_MSG SetDataFormatRsp;
QMICTL_SYNC_REQ_MSG SyncReq;
QMICTL_SYNC_RESP_MSG SyncRsp;
QMICTL_SYNC_IND_MSG SyncInd;
QMICTL_LIBQMI_PROXY_OPEN_MSG LibQmiProxyOpenReq;
};
} __attribute__ ((packed)) QMICTL_MSG, *PQMICTL_MSG;
#pragma pack(pop)
#endif //QCQCTL_H
-316
View File
@@ -1,316 +0,0 @@
/*
Copyright 2025 Quectel Wireless Solutions Co.,Ltd
Quectel hereby grants customers of Quectel a license to use, modify,
distribute and publish the Software in binary form provided that
customers shall have no right to reverse engineer, reverse assemble,
decompile or reduce to source code form any portion of the Software.
Under no circumstances may customers modify, demonstrate, use, deliver
or disclose any portion of the Software in source code form.
*/
#ifndef USBQMI_H
#define USBQMI_H
typedef uint8_t uint8;
typedef int8_t int8;
typedef uint16_t uint16;
typedef int16_t int16;
typedef uint32_t uint32;
typedef uint64_t uint64;
typedef signed char CHAR;
typedef unsigned char UCHAR;
typedef short SHORT;
typedef unsigned short USHORT;
typedef int INT;
typedef unsigned int UINT;
typedef long LONG;
typedef unsigned int ULONG;
typedef unsigned long long ULONG64;
typedef signed char *PCHAR;
typedef unsigned char *PUCHAR;
typedef int *PINT;
typedef int BOOL;
#define TRUE (1 == 1)
#define FALSE (1 != 1)
#define QMICTL_SUPPORTED_MAJOR_VERSION 1
#define QMICTL_SUPPORTED_MINOR_VERSION 0
#pragma pack(push, 1)
// ========= USB Control Message ==========
#define USB_CTL_MSG_TYPE_QMI 0x01
// USB Control Message
typedef struct _QCUSB_CTL_MSG_HDR
{
UCHAR IFType;
} __attribute__ ((packed)) QCUSB_CTL_MSG_HDR, *PQCUSB_CTL_MSG_HDR;
#define QCUSB_CTL_MSG_HDR_SIZE sizeof(QCUSB_CTL_MSG_HDR)
typedef struct _QCUSB_CTL_MSG
{
UCHAR IFType;
UCHAR Message;
} __attribute__ ((packed)) QCUSB_CTL_MSG, *PQCUSB_CTL_MSG;
#define QCTLV_TYPE_REQUIRED_PARAMETER 0x01
#define QCTLV_TYPE_RESULT_CODE 0x02
// ================= QMI ==================
// Define QMI Type
typedef enum _QMI_SERVICE_TYPE
{
QMUX_TYPE_CTL = 0x00,
QMUX_TYPE_WDS = 0x01,
QMUX_TYPE_DMS = 0x02,
QMUX_TYPE_NAS = 0x03,
QMUX_TYPE_QOS = 0x04,
QMUX_TYPE_WMS = 0x05,
QMUX_TYPE_PDS = 0x06,
QMUX_TYPE_UIM = 0x0B,
QMUX_TYPE_WDS_IPV6 = 0x11,
QMUX_TYPE_WDS_ADMIN = 0x1A,
QMUX_TYPE_COEX = 0x22,
QMUX_TYPE_MAX = 0xFF,
QMUX_TYPE_ALL = 0xFF
} QMI_SERVICE_TYPE;
typedef enum _QMI_RESULT_CODE_TYPE
{
QMI_RESULT_SUCCESS = 0x0000,
QMI_RESULT_FAILURE = 0x0001
} QMI_RESULT_CODE_TYPE;
typedef enum _QMI_ERROR_CODE_TYPE
{
QMI_ERR_NONE = 0x0000
,QMI_ERR_MALFORMED_MSG = 0x0001
,QMI_ERR_NO_MEMORY = 0x0002
,QMI_ERR_INTERNAL = 0x0003
,QMI_ERR_ABORTED = 0x0004
,QMI_ERR_CLIENT_IDS_EXHAUSTED = 0x0005
,QMI_ERR_UNABORTABLE_TRANSACTION = 0x0006
,QMI_ERR_INVALID_CLIENT_ID = 0x0007
,QMI_ERR_NO_THRESHOLDS = 0x0008
,QMI_ERR_INVALID_HANDLE = 0x0009
,QMI_ERR_INVALID_PROFILE = 0x000A
,QMI_ERR_INVALID_PINID = 0x000B
,QMI_ERR_INCORRECT_PIN = 0x000C
,QMI_ERR_NO_NETWORK_FOUND = 0x000D
,QMI_ERR_CALL_FAILED = 0x000E
,QMI_ERR_OUT_OF_CALL = 0x000F
,QMI_ERR_NOT_PROVISIONED = 0x0010
,QMI_ERR_MISSING_ARG = 0x0011
,QMI_ERR_ARG_TOO_LONG = 0x0013
,QMI_ERR_INVALID_TX_ID = 0x0016
,QMI_ERR_DEVICE_IN_USE = 0x0017
,QMI_ERR_OP_NETWORK_UNSUPPORTED = 0x0018
,QMI_ERR_OP_DEVICE_UNSUPPORTED = 0x0019
,QMI_ERR_NO_EFFECT = 0x001A
,QMI_ERR_NO_FREE_PROFILE = 0x001B
,QMI_ERR_INVALID_PDP_TYPE = 0x001C
,QMI_ERR_INVALID_TECH_PREF = 0x001D
,QMI_ERR_INVALID_PROFILE_TYPE = 0x001E
,QMI_ERR_INVALID_SERVICE_TYPE = 0x001F
,QMI_ERR_INVALID_REGISTER_ACTION = 0x0020
,QMI_ERR_INVALID_PS_ATTACH_ACTION = 0x0021
,QMI_ERR_AUTHENTICATION_FAILED = 0x0022
,QMI_ERR_PIN_BLOCKED = 0x0023
,QMI_ERR_PIN_PERM_BLOCKED = 0x0024
,QMI_ERR_SIM_NOT_INITIALIZED = 0x0025
,QMI_ERR_MAX_QOS_REQUESTS_IN_USE = 0x0026
,QMI_ERR_INCORRECT_FLOW_FILTER = 0x0027
,QMI_ERR_NETWORK_QOS_UNAWARE = 0x0028
,QMI_ERR_INVALID_QOS_ID = 0x0029
,QMI_ERR_INVALID_ID = 0x0029
,QMI_ERR_REQUESTED_NUM_UNSUPPORTED = 0x002A
,QMI_ERR_INTERFACE_NOT_FOUND = 0x002B
,QMI_ERR_FLOW_SUSPENDED = 0x002C
,QMI_ERR_INVALID_DATA_FORMAT = 0x002D
,QMI_ERR_GENERAL = 0x002E
,QMI_ERR_UNKNOWN = 0x002F
,QMI_ERR_INVALID_ARG = 0x0030
,QMI_ERR_INVALID_INDEX = 0x0031
,QMI_ERR_NO_ENTRY = 0x0032
,QMI_ERR_DEVICE_STORAGE_FULL = 0x0033
,QMI_ERR_DEVICE_NOT_READY = 0x0034
,QMI_ERR_NETWORK_NOT_READY = 0x0035
,QMI_ERR_CAUSE_CODE = 0x0036
,QMI_ERR_MESSAGE_NOT_SENT = 0x0037
,QMI_ERR_MESSAGE_DELIVERY_FAILURE = 0x0038
,QMI_ERR_INVALID_MESSAGE_ID = 0x0039
,QMI_ERR_ENCODING = 0x003A
,QMI_ERR_AUTHENTICATION_LOCK = 0x003B
,QMI_ERR_INVALID_TRANSITION = 0x003C
,QMI_ERR_NOT_A_MCAST_IFACE = 0x003D
,QMI_ERR_MAX_MCAST_REQUESTS_IN_USE = 0x003E
,QMI_ERR_INVALID_MCAST_HANDLE = 0x003F
,QMI_ERR_INVALID_IP_FAMILY_PREF = 0x0040
,QMI_ERR_SESSION_INACTIVE = 0x0041
,QMI_ERR_SESSION_INVALID = 0x0042
,QMI_ERR_SESSION_OWNERSHIP = 0x0043
,QMI_ERR_INSUFFICIENT_RESOURCES = 0x0044
,QMI_ERR_DISABLED = 0x0045
,QMI_ERR_INVALID_OPERATION = 0x0046
,QMI_ERR_INVALID_QMI_CMD = 0x0047
,QMI_ERR_TPDU_TYPE = 0x0048
,QMI_ERR_SMSC_ADDR = 0x0049
,QMI_ERR_INFO_UNAVAILABLE = 0x004A
,QMI_ERR_SEGMENT_TOO_LONG = 0x004B
,QMI_ERR_SEGMENT_ORDER = 0x004C
,QMI_ERR_BUNDLING_NOT_SUPPORTED = 0x004D
,QMI_ERR_OP_PARTIAL_FAILURE = 0x004E
,QMI_ERR_POLICY_MISMATCH = 0x004F
,QMI_ERR_SIM_FILE_NOT_FOUND = 0x0050
,QMI_ERR_EXTENDED_INTERNAL = 0x0051
,QMI_ERR_ACCESS_DENIED = 0x0052
,QMI_ERR_HARDWARE_RESTRICTED = 0x0053
,QMI_ERR_ACK_NOT_SENT = 0x0054
,QMI_ERR_INJECT_TIMEOUT = 0x0055
,QMI_ERR_INCOMPATIBLE_STATE = 0x005A
,QMI_ERR_FDN_RESTRICT = 0x005B
,QMI_ERR_SUPS_FAILURE_CAUSE = 0x005C
,QMI_ERR_NO_RADIO = 0x005D
,QMI_ERR_NOT_SUPPORTED = 0x005E
,QMI_ERR_NO_SUBSCRIPTION = 0x005F
,QMI_ERR_CARD_CALL_CONTROL_FAILED = 0x0060
,QMI_ERR_NETWORK_ABORTED = 0x0061
,QMI_ERR_MSG_BLOCKED = 0x0062
,QMI_ERR_INVALID_SESSION_TYPE = 0x0064
,QMI_ERR_INVALID_PB_TYPE = 0x0065
,QMI_ERR_NO_SIM = 0x0066
,QMI_ERR_PB_NOT_READY = 0x0067
,QMI_ERR_PIN_RESTRICTION = 0x0068
,QMI_ERR_PIN2_RESTRICTION = 0x0069
,QMI_ERR_PUK_RESTRICTION = 0x006A
,QMI_ERR_PUK2_RESTRICTION = 0x006B
,QMI_ERR_PB_ACCESS_RESTRICTED = 0x006C
,QMI_ERR_PB_DELETE_IN_PROG = 0x006D
,QMI_ERR_PB_TEXT_TOO_LONG = 0x006E
,QMI_ERR_PB_NUMBER_TOO_LONG = 0x006F
,QMI_ERR_PB_HIDDEN_KEY_RESTRICTION = 0x0070
} QMI_ERROR_CODE_TYPE;
#define QCQMI_CTL_FLAG_SERVICE 0x80
#define QCQMI_CTL_FLAG_CTL_POINT 0x00
typedef struct _QCQMI_HDR
{
UCHAR IFType;
USHORT Length;
UCHAR CtlFlags; // reserved
UCHAR QMIType;
UCHAR ClientId;
} __attribute__ ((packed)) QCQMI_HDR, *PQCQMI_HDR;
#define QCQMI_HDR_SIZE (sizeof(QCQMI_HDR)-1)
typedef struct _QCQMI
{
UCHAR IFType;
USHORT Length;
UCHAR CtlFlags; // reserved
UCHAR QMIType;
UCHAR ClientId;
UCHAR SDU;
} __attribute__ ((packed)) QCQMI, *PQCQMI;
typedef struct _QMI_SERVICE_VERSION
{
USHORT Major;
USHORT Minor;
USHORT AddendumMajor;
USHORT AddendumMinor;
} __attribute__ ((packed)) QMI_SERVICE_VERSION, *PQMI_SERVICE_VERSION;
// ================= QMUX ==================
#define QMUX_MSG_OVERHEAD_BYTES 4 // Type(USHORT) Length(USHORT) -- header
#define QMUX_BROADCAST_CID 0xFF
typedef struct _QCQMUX_HDR
{
UCHAR CtlFlags; // 0: single QMUX Msg; 1:
USHORT TransactionId;
} __attribute__ ((packed)) QCQMUX_HDR, *PQCQMUX_HDR;
typedef struct _QCQMUX
{
UCHAR CtlFlags; // 0: single QMUX Msg; 1:
USHORT TransactionId;
UCHAR Message; // Type(2), Length(2), Value
} __attribute__ ((packed)) QCQMUX, *PQCQMUX;
#define QCQMUX_HDR_SIZE sizeof(QCQMUX_HDR)
typedef struct _QCQMUX_MSG_HDR
{
USHORT Type;
USHORT Length;
} __attribute__ ((packed)) QCQMUX_MSG_HDR, *PQCQMUX_MSG_HDR;
#define QCQMUX_MSG_HDR_SIZE sizeof(QCQMUX_MSG_HDR)
typedef struct _QCQMUX_MSG_HDR_RESP
{
USHORT Type;
USHORT Length;
UCHAR TLVType; // 0x02 - result code
USHORT TLVLength; // 4
USHORT QMUXResult; // QMI_RESULT_SUCCESS
// QMI_RESULT_FAILURE
USHORT QMUXError; // QMI_ERR_INVALID_ARG
// QMI_ERR_NO_MEMORY
// QMI_ERR_INTERNAL
// QMI_ERR_FAULT
} __attribute__ ((packed)) QCQMUX_MSG_HDR_RESP, *PQCQMUX_MSG_HDR_RESP;
typedef struct _QCQMUX_TLV
{
UCHAR Type;
USHORT Length;
UCHAR Value;
} __attribute__ ((packed)) QCQMUX_TLV, *PQCQMUX_TLV;
typedef struct _QMI_TLV_HDR
{
UCHAR TLVType;
USHORT TLVLength;
} __attribute__ ((packed)) QMI_TLV_HDR, *PQMI_TLV_HDR;
typedef struct _QMI_TLV
{
UCHAR TLVType;
USHORT TLVLength;
union {
int8_t s8;
uint8_t u8;
int16_t s16;
uint16_t u16;
int32_t s32;
uint32_t u32;
uint64_t u64;
};
} __attribute__ ((packed)) QMI_TLV, *PQMI_TLV;
// QMUX Message Definitions -- QMI SDU
#define QMUX_CTL_FLAG_SINGLE_MSG 0x00
#define QMUX_CTL_FLAG_COMPOUND_MSG 0x01
#define QMUX_CTL_FLAG_TYPE_CMD 0x00
#define QMUX_CTL_FLAG_TYPE_RSP 0x02
#define QMUX_CTL_FLAG_TYPE_IND 0x04
#define QMUX_CTL_FLAG_MASK_COMPOUND 0x01
#define QMUX_CTL_FLAG_MASK_TYPE 0x06 // 00-cmd, 01-rsp, 10-ind
#pragma pack(pop)
#endif // USBQMI_H
-472
View File
@@ -1,472 +0,0 @@
/*
Copyright 2025 Quectel Wireless Solutions Co.,Ltd
Quectel hereby grants customers of Quectel a license to use, modify,
distribute and publish the Software in binary form provided that
customers shall have no right to reverse engineer, reverse assemble,
decompile or reduce to source code form any portion of the Software.
Under no circumstances may customers modify, demonstrate, use, deliver
or disclose any portion of the Software in source code form.
*/
#include "QMIThread.h"
static char line[1024];
static pthread_mutex_t dumpQMIMutex = PTHREAD_MUTEX_INITIALIZER;
#undef dbg
#define dbg( format, arg... ) do {if (strlen(line) < sizeof(line)) snprintf(&line[strlen(line)], sizeof(line) - strlen(line), format, ## arg);} while (0)
PQMI_TLV_HDR GetTLV (PQCQMUX_MSG_HDR pQMUXMsgHdr, int TLVType);
typedef struct {
UINT type;
const char *name;
} QMI_NAME_T;
#define qmi_name_item(type) {type, #type}
#if 0
static const QMI_NAME_T qmi_IFType[] = {
{USB_CTL_MSG_TYPE_QMI, "USB_CTL_MSG_TYPE_QMI"},
};
static const QMI_NAME_T qmi_CtlFlags[] = {
qmi_name_item(QMICTL_CTL_FLAG_CMD),
qmi_name_item(QCQMI_CTL_FLAG_SERVICE),
};
static const QMI_NAME_T qmi_QMIType[] = {
qmi_name_item(QMUX_TYPE_CTL),
qmi_name_item(QMUX_TYPE_WDS),
qmi_name_item(QMUX_TYPE_DMS),
qmi_name_item(QMUX_TYPE_NAS),
qmi_name_item(QMUX_TYPE_QOS),
qmi_name_item(QMUX_TYPE_WMS),
qmi_name_item(QMUX_TYPE_PDS),
qmi_name_item(QMUX_TYPE_WDS_ADMIN),
qmi_name_item(QMUX_TYPE_COEX),
};
static const QMI_NAME_T qmi_ctl_CtlFlags[] = {
qmi_name_item(QMICTL_FLAG_REQUEST),
qmi_name_item(QMICTL_FLAG_RESPONSE),
qmi_name_item(QMICTL_FLAG_INDICATION),
};
#endif
static const QMI_NAME_T qmux_ctl_QMICTLType[] = {
// QMICTL Type
qmi_name_item(QMICTL_SET_INSTANCE_ID_REQ), // 0x0020
qmi_name_item(QMICTL_SET_INSTANCE_ID_RESP), // 0x0020
qmi_name_item(QMICTL_GET_VERSION_REQ), // 0x0021
qmi_name_item(QMICTL_GET_VERSION_RESP), // 0x0021
qmi_name_item(QMICTL_GET_CLIENT_ID_REQ), // 0x0022
qmi_name_item(QMICTL_GET_CLIENT_ID_RESP), // 0x0022
qmi_name_item(QMICTL_RELEASE_CLIENT_ID_REQ), // 0x0023
qmi_name_item(QMICTL_RELEASE_CLIENT_ID_RESP), // 0x0023
qmi_name_item(QMICTL_REVOKE_CLIENT_ID_IND), // 0x0024
qmi_name_item(QMICTL_INVALID_CLIENT_ID_IND), // 0x0025
qmi_name_item(QMICTL_SET_DATA_FORMAT_REQ), // 0x0026
qmi_name_item(QMICTL_SET_DATA_FORMAT_RESP), // 0x0026
qmi_name_item(QMICTL_SYNC_REQ), // 0x0027
qmi_name_item(QMICTL_SYNC_RESP), // 0x0027
qmi_name_item(QMICTL_SYNC_IND), // 0x0027
};
static const QMI_NAME_T qmux_CtlFlags[] = {
qmi_name_item(QMUX_CTL_FLAG_TYPE_CMD),
qmi_name_item(QMUX_CTL_FLAG_TYPE_RSP),
qmi_name_item(QMUX_CTL_FLAG_TYPE_IND),
};
static const QMI_NAME_T qmux_wds_Type[] = {
qmi_name_item(QMIWDS_SET_EVENT_REPORT_REQ), // 0x0001
qmi_name_item(QMIWDS_SET_EVENT_REPORT_RESP), // 0x0001
qmi_name_item(QMIWDS_EVENT_REPORT_IND), // 0x0001
qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_REQ), // 0x0020
qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_RESP), // 0x0020
qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_REQ), // 0x0021
qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_RESP), // 0x0021
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_REQ), // 0x0022
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_RESP), // 0x0022
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_IND), // 0x0022
qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ), // 0x0023
qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP), // 0x0023
qmi_name_item(QMIWDS_GET_PKT_STATISTICS_REQ), // 0x0024
qmi_name_item(QMIWDS_GET_PKT_STATISTICS_RESP), // 0x0024
qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ), // 0x0028
qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_RESP), // 0x0028
qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_REQ), // 0x002B
qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_RESP), // 0x002BD
qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_REQ), // 0x002C
qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_RESP), // 0x002C
qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_REQ), // 0x002D
qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_RESP), // 0x002D
qmi_name_item(QMIWDS_GET_MIP_MODE_REQ), // 0x002F
qmi_name_item(QMIWDS_GET_MIP_MODE_RESP), // 0x002F
qmi_name_item(QMIWDS_GET_DATA_BEARER_REQ), // 0x0037
qmi_name_item(QMIWDS_GET_DATA_BEARER_RESP), // 0x0037
qmi_name_item(QMIWDS_DUN_CALL_INFO_REQ), // 0x0038
qmi_name_item(QMIWDS_DUN_CALL_INFO_RESP), // 0x0038
qmi_name_item(QMIWDS_DUN_CALL_INFO_IND), // 0x0038
qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ), // 0x004D
qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP), // 0x004D
qmi_name_item(QMIWDS_SET_AUTO_CONNECT_REQ), // 0x0051
qmi_name_item(QMIWDS_SET_AUTO_CONNECT_RESP), // 0x0051
qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_REQ), // 0x00A2
qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_RESP), // 0x00A2
};
static const QMI_NAME_T qmux_dms_Type[] = {
// ======================= DMS ==============================
qmi_name_item(QMIDMS_SET_EVENT_REPORT_REQ), // 0x0001
qmi_name_item(QMIDMS_SET_EVENT_REPORT_RESP), // 0x0001
qmi_name_item(QMIDMS_EVENT_REPORT_IND), // 0x0001
qmi_name_item(QMIDMS_GET_DEVICE_CAP_REQ), // 0x0020
qmi_name_item(QMIDMS_GET_DEVICE_CAP_RESP), // 0x0020
qmi_name_item(QMIDMS_GET_DEVICE_MFR_REQ), // 0x0021
qmi_name_item(QMIDMS_GET_DEVICE_MFR_RESP), // 0x0021
qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_REQ), // 0x0022
qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_RESP), // 0x0022
qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_REQ), // 0x0023
qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_RESP), // 0x0023
qmi_name_item(QMIDMS_GET_MSISDN_REQ), // 0x0024
qmi_name_item(QMIDMS_GET_MSISDN_RESP), // 0x0024
qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ), // 0x0025
qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP), // 0x0025
qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_REQ), // 0x0027
qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_RESP), // 0x0027
qmi_name_item(QMIDMS_UIM_VERIFY_PIN_REQ), // 0x0028
qmi_name_item(QMIDMS_UIM_VERIFY_PIN_RESP), // 0x0028
qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_REQ), // 0x0029
qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_RESP), // 0x0029
qmi_name_item(QMIDMS_UIM_CHANGE_PIN_REQ), // 0x002A
qmi_name_item(QMIDMS_UIM_CHANGE_PIN_RESP), // 0x002A
qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_REQ), // 0x002B
qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_RESP), // 0x002B
qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_REQ), // 0x002C
qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_RESP), // 0x002C
qmi_name_item(QMIDMS_GET_OPERATING_MODE_REQ), // 0x002D
qmi_name_item(QMIDMS_GET_OPERATING_MODE_RESP), // 0x002D
qmi_name_item(QMIDMS_SET_OPERATING_MODE_REQ), // 0x002E
qmi_name_item(QMIDMS_SET_OPERATING_MODE_RESP), // 0x002E
qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_REQ), // 0x0031
qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_RESP), // 0x0031
qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_REQ), // 0x0032
qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_RESP), // 0x0032
qmi_name_item(QMIDMS_ACTIVATE_MANUAL_REQ), // 0x0033
qmi_name_item(QMIDMS_ACTIVATE_MANUAL_RESP), // 0x0033
qmi_name_item(QMIDMS_UIM_GET_ICCID_REQ), // 0x003C
qmi_name_item(QMIDMS_UIM_GET_ICCID_RESP), // 0x003C
qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_REQ), // 0x0040
qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_RESP), // 0x0040
qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_REQ), // 0x0041
qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_RESP), // 0x0041
qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_REQ), // 0x0042
qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_RESP), // 0x0042
qmi_name_item(QMIDMS_UIM_GET_IMSI_REQ), // 0x0043
qmi_name_item(QMIDMS_UIM_GET_IMSI_RESP), // 0x0043
qmi_name_item(QMIDMS_UIM_GET_STATE_REQ), // 0x0044
qmi_name_item(QMIDMS_UIM_GET_STATE_RESP), // 0x0044
qmi_name_item(QMIDMS_GET_BAND_CAP_REQ), // 0x0045
qmi_name_item(QMIDMS_GET_BAND_CAP_RESP), // 0x0045
};
static const QMI_NAME_T qmux_qos_Type[] = {
qmi_name_item( QMI_QOS_SET_EVENT_REPORT_REQ), // 0x0001
qmi_name_item( QMI_QOS_SET_EVENT_REPORT_RESP), // 0x0001
qmi_name_item( QMI_QOS_SET_EVENT_REPORT_IND), // 0x0001
qmi_name_item( QMI_QOS_BIND_DATA_PORT_REQ), // 0x002B
qmi_name_item( QMI_QOS_BIND_DATA_PORT_RESP), // 0x002B
qmi_name_item( QMI_QOS_INDICATION_REGISTER_REQ), // 0x002F
qmi_name_item( QMI_QOS_INDICATION_REGISTER_RESP), // 0x002F
qmi_name_item( QMI_QOS_GLOBAL_QOS_FLOW_IND), // 0x0031
qmi_name_item( QMI_QOS_GET_QOS_INFO_REQ), // 0x0033
qmi_name_item( QMI_QOS_GET_QOS_INFO_RESP), // 0x0033
};
static const QMI_NAME_T qmux_nas_Type[] = {
// ======================= NAS ==============================
qmi_name_item(QMINAS_SET_EVENT_REPORT_REQ), // 0x0002
qmi_name_item(QMINAS_SET_EVENT_REPORT_RESP), // 0x0002
qmi_name_item(QMINAS_EVENT_REPORT_IND), // 0x0002
qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_REQ), // 0x0020
qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_RESP), // 0x0020
qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_REQ), // 0x0021
qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_RESP), // 0x0021
qmi_name_item(QMINAS_INITIATE_NW_REGISTER_REQ), // 0x0022
qmi_name_item(QMINAS_INITIATE_NW_REGISTER_RESP), // 0x0022
qmi_name_item(QMINAS_INITIATE_ATTACH_REQ), // 0x0023
qmi_name_item(QMINAS_INITIATE_ATTACH_RESP), // 0x0023
qmi_name_item(QMINAS_GET_SERVING_SYSTEM_REQ), // 0x0024
qmi_name_item(QMINAS_GET_SERVING_SYSTEM_RESP), // 0x0024
qmi_name_item(QMINAS_SERVING_SYSTEM_IND), // 0x0024
qmi_name_item(QMINAS_GET_HOME_NETWORK_REQ), // 0x0025
qmi_name_item(QMINAS_GET_HOME_NETWORK_RESP), // 0x0025
qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_REQ), // 0x0026
qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_RESP), // 0x0026
qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_REQ), // 0x0027
qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_RESP), // 0x0027
qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_REQ), // 0x0028
qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_RESP), // 0x0028
qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_REQ), // 0x0029
qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_RESP), // 0x0029
qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_REQ), // 0x002A
qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_RESP), // 0x002A
qmi_name_item(QMINAS_GET_RF_BAND_INFO_REQ), // 0x0031
qmi_name_item(QMINAS_GET_RF_BAND_INFO_RESP), // 0x0031
qmi_name_item(QMINAS_GET_CELL_LOCATION_INFO_REQ),
qmi_name_item(QMINAS_GET_CELL_LOCATION_INFO_RESP),
qmi_name_item(QMINAS_GET_PLMN_NAME_REQ), // 0x0044
qmi_name_item(QMINAS_GET_PLMN_NAME_RESP), // 0x0044
qmi_name_item(QUECTEL_PACKET_TRANSFER_START_IND), // 0X100
qmi_name_item(QUECTEL_PACKET_TRANSFER_END_IND), // 0X101
qmi_name_item(QMINAS_GET_SYS_INFO_REQ), // 0x004D
qmi_name_item(QMINAS_GET_SYS_INFO_RESP), // 0x004D
qmi_name_item(QMINAS_SYS_INFO_IND), // 0x004D
qmi_name_item(QMINAS_GET_SIG_INFO_REQ),
qmi_name_item(QMINAS_GET_SIG_INFO_RESP),
};
static const QMI_NAME_T qmux_wms_Type[] = {
// ======================= WMS ==============================
qmi_name_item(QMIWMS_SET_EVENT_REPORT_REQ), // 0x0001
qmi_name_item(QMIWMS_SET_EVENT_REPORT_RESP), // 0x0001
qmi_name_item(QMIWMS_EVENT_REPORT_IND), // 0x0001
qmi_name_item(QMIWMS_RAW_SEND_REQ), // 0x0020
qmi_name_item(QMIWMS_RAW_SEND_RESP), // 0x0020
qmi_name_item(QMIWMS_RAW_WRITE_REQ), // 0x0021
qmi_name_item(QMIWMS_RAW_WRITE_RESP), // 0x0021
qmi_name_item(QMIWMS_RAW_READ_REQ), // 0x0022
qmi_name_item(QMIWMS_RAW_READ_RESP), // 0x0022
qmi_name_item(QMIWMS_MODIFY_TAG_REQ), // 0x0023
qmi_name_item(QMIWMS_MODIFY_TAG_RESP), // 0x0023
qmi_name_item(QMIWMS_DELETE_REQ), // 0x0024
qmi_name_item(QMIWMS_DELETE_RESP), // 0x0024
qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_REQ), // 0x0030
qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_RESP), // 0x0030
qmi_name_item(QMIWMS_LIST_MESSAGES_REQ), // 0x0031
qmi_name_item(QMIWMS_LIST_MESSAGES_RESP), // 0x0031
qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_REQ), // 0x0034
qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_RESP), // 0x0034
qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_REQ), // 0x0035
qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_RESP), // 0x0035
qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_REQ), // 0x0036
qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_RESP), // 0x0036
};
static const QMI_NAME_T qmux_wds_admin_Type[] = {
qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_REQ), // 0x0020
qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_RESP), // 0x0020
qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_REQ), // 0x0021
qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_RESP), // 0x0021
qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_REQ), // 0x002B
qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_RESP), // 0x002B
qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_REQ), // 0x002C
qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_RESP), // 0x002C
qmi_name_item(QMI_WDA_SET_LOOPBACK_CONFIG_REQ), // 0x002F
qmi_name_item(QMI_WDA_SET_LOOPBACK_CONFIG_RESP), // 0x002F
qmi_name_item(QMI_WDA_SET_LOOPBACK_CONFIG_IND), // 0x002F
};
static const QMI_NAME_T qmux_uim_Type[] = {
qmi_name_item( QMIUIM_READ_TRANSPARENT_REQ), // 0x0020
qmi_name_item( QMIUIM_READ_TRANSPARENT_RESP), // 0x0020
qmi_name_item( QMIUIM_READ_TRANSPARENT_IND), // 0x0020
qmi_name_item( QMIUIM_READ_RECORD_REQ), // 0x0021
qmi_name_item( QMIUIM_READ_RECORD_RESP), // 0x0021
qmi_name_item( QMIUIM_READ_RECORD_IND), // 0x0021
qmi_name_item( QMIUIM_WRITE_TRANSPARENT_REQ), // 0x0022
qmi_name_item( QMIUIM_WRITE_TRANSPARENT_RESP), // 0x0022
qmi_name_item( QMIUIM_WRITE_TRANSPARENT_IND), // 0x0022
qmi_name_item( QMIUIM_WRITE_RECORD_REQ), // 0x0023
qmi_name_item( QMIUIM_WRITE_RECORD_RESP), // 0x0023
qmi_name_item( QMIUIM_WRITE_RECORD_IND), // 0x0023
qmi_name_item( QMIUIM_SET_PIN_PROTECTION_REQ), // 0x0025
qmi_name_item( QMIUIM_SET_PIN_PROTECTION_RESP), // 0x0025
qmi_name_item( QMIUIM_SET_PIN_PROTECTION_IND), // 0x0025
qmi_name_item( QMIUIM_VERIFY_PIN_REQ), // 0x0026
qmi_name_item( QMIUIM_VERIFY_PIN_RESP), // 0x0026
qmi_name_item( QMIUIM_VERIFY_PIN_IND), // 0x0026
qmi_name_item( QMIUIM_UNBLOCK_PIN_REQ), // 0x0027
qmi_name_item( QMIUIM_UNBLOCK_PIN_RESP), // 0x0027
qmi_name_item( QMIUIM_UNBLOCK_PIN_IND), // 0x0027
qmi_name_item( QMIUIM_CHANGE_PIN_REQ), // 0x0028
qmi_name_item( QMIUIM_CHANGE_PIN_RESP), // 0x0028
qmi_name_item( QMIUIM_CHANGE_PIN_IND), // 0x0028
qmi_name_item( QMIUIM_DEPERSONALIZATION_REQ), // 0x0029
qmi_name_item( QMIUIM_DEPERSONALIZATION_RESP), // 0x0029
qmi_name_item( QMIUIM_EVENT_REG_REQ), // 0x002E
qmi_name_item( QMIUIM_EVENT_REG_RESP), // 0x002E
qmi_name_item( QMIUIM_GET_CARD_STATUS_REQ), // 0x002F
qmi_name_item( QMIUIM_GET_CARD_STATUS_RESP), // 0x002F
qmi_name_item( QMIUIM_STATUS_CHANGE_IND), // 0x0032
};
static const QMI_NAME_T qmux_coex_Type[] = {
qmi_name_item(QMI_COEX_GET_WWAN_STATE_REQ), // 0x0022
qmi_name_item(QMI_COEX_GET_WWAN_STATE_RESP), // 0x0022
};
static const char * qmi_name_get(const QMI_NAME_T *table, size_t size, int type, const char *tag) {
static char unknow[40];
size_t i;
if (qmux_CtlFlags == table) {
if (!strcmp(tag, "_REQ"))
tag = "_CMD";
else if (!strcmp(tag, "_RESP"))
tag = "_RSP";
}
for (i = 0; i < size; i++) {
if (table[i].type == (UINT)type) {
if (!tag || (strstr(table[i].name, tag)))
return table[i].name;
}
}
sprintf(unknow, "unknow_%x", type);
return unknow;
}
#define QMI_NAME(table, type) qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, 0)
#define QMUX_NAME(table, type, tag) qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, tag)
void dump_tlv(PQCQMUX_MSG_HDR pQMUXMsgHdr) {
int TLVFind = 0;
int i;
//dbg("QCQMUX_TLV-----------------------------------\n");
//dbg("{Type,\tLength,\tValue}\n");
while (1) {
PQMI_TLV_HDR TLVHdr = GetTLV(pQMUXMsgHdr, 0x1000 + (++TLVFind));
if (TLVHdr == NULL)
break;
//if ((TLVHdr->TLVType == 0x02) && ((USHORT *)(TLVHdr+1))[0])
{
dbg("{%02x,\t%04x,\t", TLVHdr->TLVType, le16_to_cpu(TLVHdr->TLVLength));
for (i = 0; i < le16_to_cpu(TLVHdr->TLVLength); i++) {
dbg("%02x ", ((UCHAR *)(TLVHdr+1))[i]);
}
dbg("}\n");
}
} // while
}
void dump_ctl(PQCQMICTL_MSG_HDR CTLHdr) {
const char *tag;
//dbg("QCQMICTL_MSG--------------------------------------------\n");
//dbg("CtlFlags: %02x\t\t%s\n", CTLHdr->CtlFlags, QMI_NAME(qmi_ctl_CtlFlags, CTLHdr->CtlFlags));
dbg("TransactionId: %02x\n", CTLHdr->TransactionId);
switch (CTLHdr->CtlFlags) {
case QMICTL_FLAG_REQUEST: tag = "_REQ"; break;
case QMICTL_FLAG_RESPONSE: tag = "_RESP"; break;
case QMICTL_FLAG_INDICATION: tag = "_IND"; break;
default: tag = 0; break;
}
dbg("QMICTLType: %04x\t%s\n", le16_to_cpu(CTLHdr->QMICTLType),
QMUX_NAME(qmux_ctl_QMICTLType, le16_to_cpu(CTLHdr->QMICTLType), tag));
dbg("Length: %04x\n", le16_to_cpu(CTLHdr->Length));
dump_tlv((PQCQMUX_MSG_HDR)(&CTLHdr->QMICTLType));
}
int dump_qmux(QMI_SERVICE_TYPE serviceType, PQCQMUX_HDR QMUXHdr) {
PQCQMUX_MSG_HDR QMUXMsgHdr = (PQCQMUX_MSG_HDR) (QMUXHdr + 1);
const char *tag;
//dbg("QCQMUX--------------------------------------------\n");
switch (QMUXHdr->CtlFlags&QMUX_CTL_FLAG_MASK_TYPE) {
case QMUX_CTL_FLAG_TYPE_CMD: tag = "_REQ"; break;
case QMUX_CTL_FLAG_TYPE_RSP: tag = "_RESP"; break;
case QMUX_CTL_FLAG_TYPE_IND: tag = "_IND"; break;
default: tag = 0; break;
}
//dbg("CtlFlags: %02x\t\t%s\n", QMUXHdr->CtlFlags, QMUX_NAME(qmux_CtlFlags, QMUXHdr->CtlFlags, tag));
dbg("TransactionId: %04x\n", le16_to_cpu(QMUXHdr->TransactionId));
//dbg("QCQMUX_MSG_HDR-----------------------------------\n");
switch (serviceType) {
case QMUX_TYPE_DMS:
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
QMUX_NAME(qmux_dms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
break;
case QMUX_TYPE_NAS:
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
QMUX_NAME(qmux_nas_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
break;
case QMUX_TYPE_WDS:
case QMUX_TYPE_WDS_IPV6:
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
QMUX_NAME(qmux_wds_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
break;
case QMUX_TYPE_WMS:
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
QMUX_NAME(qmux_wms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
break;
case QMUX_TYPE_WDS_ADMIN:
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
QMUX_NAME(qmux_wds_admin_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
break;
case QMUX_TYPE_UIM:
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
QMUX_NAME(qmux_uim_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
break;
case QMUX_TYPE_PDS:
case QMUX_TYPE_QOS:
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
QMUX_NAME(qmux_qos_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
break;
case QMUX_TYPE_COEX:
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
QMUX_NAME(qmux_coex_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
break;
case QMUX_TYPE_CTL:
default:
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), "PDS/QOS/CTL/unknown!");
break;
}
dbg("Length: %04x\n", le16_to_cpu(QMUXMsgHdr->Length));
dump_tlv(QMUXMsgHdr);
return 0;
}
void dump_qmi(void *dataBuffer, int dataLen)
{
PQCQMI_HDR QMIHdr = (PQCQMI_HDR)dataBuffer;
PQCQMUX_HDR QMUXHdr = (PQCQMUX_HDR) (QMIHdr + 1);
PQCQMICTL_MSG_HDR CTLHdr = (PQCQMICTL_MSG_HDR) (QMIHdr + 1);
int i;
if (!debug_qmi)
return;
pthread_mutex_lock(&dumpQMIMutex);
line[0] = 0;
for (i = 0; i < dataLen; i++) {
dbg("%02x ", ((unsigned char *)dataBuffer)[i]);
}
dbg_time("%s", line);
line[0] = 0;
//dbg("QCQMI_HDR-----------------------------------------");
//dbg("IFType: %02x\t\t%s", QMIHdr->IFType, QMI_NAME(qmi_IFType, QMIHdr->IFType));
//dbg("Length: %04x", le16_to_cpu(QMIHdr->Length));
//dbg("CtlFlags: %02x\t\t%s", QMIHdr->CtlFlags, QMI_NAME(qmi_CtlFlags, QMIHdr->CtlFlags));
//dbg("QMIType: %02x\t\t%s", QMIHdr->QMIType, QMI_NAME(qmi_QMIType, QMIHdr->QMIType));
//dbg("ClientId: %02x", QMIHdr->ClientId);
if (QMIHdr->QMIType == QMUX_TYPE_CTL) {
dump_ctl(CTLHdr);
} else {
dump_qmux(QMIHdr->QMIType, QMUXHdr);
}
dbg_time("%s", line);
pthread_mutex_unlock(&dumpQMIMutex);
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-467
View File
@@ -1,467 +0,0 @@
/*
Copyright 2025 Quectel Wireless Solutions Co.,Ltd
Quectel hereby grants customers of Quectel a license to use, modify,
distribute and publish the Software in binary form provided that
customers shall have no right to reverse engineer, reverse assemble,
decompile or reduce to source code form any portion of the Software.
Under no circumstances may customers modify, demonstrate, use, deliver
or disclose any portion of the Software in source code form.
*/
#ifndef __QMI_THREAD_H__
#define __QMI_THREAD_H__
#define CONFIG_GOBINET
#define CONFIG_QMIWWAN
#define CONFIG_SIM
#define CONFIG_APN
#define CONFIG_VERSION
//#define CONFIG_SIGNALINFO
//#define CONFIG_CELLINFO
//#define CONFIG_COEX_WWAN_STATE
#define CONFIG_DEFAULT_PDP 1
//#define CONFIG_IMSI_ICCID
#define QUECTEL_UL_DATA_AGG
//#define QUECTEL_QMI_MERGE
//#define REBOOT_SIM_CARD_WHEN_APN_CHANGE
//#define REBOOT_SIM_CARD_WHEN_LONG_TIME_NO_PS 60 //unit is seconds
//#define CONFIG_QRTR
//#define CONFIG_ENABLE_QOS
//#define CONFIG_REG_QOS_IND
//#define CONFIG_GET_QOS_INFO
//#define CONFIG_GET_QOS_DATA_RATE
#if (defined(CONFIG_REG_QOS_IND) || defined(CONFIG_GET_QOS_INFO) || defined(CONFIG_GET_QOS_DATA_RATE))
#ifndef CONFIG_REG_QOS_IND
#define CONFIG_REG_QOS_IND
#endif
#ifndef CONFIG_ENABLE_QOS
#define CONFIG_ENABLE_QOS
#endif
#endif
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <stddef.h>
#include "qendian.h"
#include "QCQMI.h"
#include "QCQCTL.h"
#include "QCQMUX.h"
#include "util.h"
#define DEVICE_CLASS_UNKNOWN 0
#define DEVICE_CLASS_CDMA 1
#define DEVICE_CLASS_GSM 2
#define WWAN_DATA_CLASS_NONE 0x00000000
#define WWAN_DATA_CLASS_GPRS 0x00000001
#define WWAN_DATA_CLASS_EDGE 0x00000002 /* EGPRS */
#define WWAN_DATA_CLASS_UMTS 0x00000004
#define WWAN_DATA_CLASS_HSDPA 0x00000008
#define WWAN_DATA_CLASS_HSUPA 0x00000010
#define WWAN_DATA_CLASS_LTE 0x00000020
#define WWAN_DATA_CLASS_5G_NSA 0x00000040
#define WWAN_DATA_CLASS_5G_SA 0x00000080
#define WWAN_DATA_CLASS_1XRTT 0x00010000
#define WWAN_DATA_CLASS_1XEVDO 0x00020000
#define WWAN_DATA_CLASS_1XEVDO_REVA 0x00040000
#define WWAN_DATA_CLASS_1XEVDV 0x00080000
#define WWAN_DATA_CLASS_3XRTT 0x00100000
#define WWAN_DATA_CLASS_1XEVDO_REVB 0x00200000 /* for future use */
#define WWAN_DATA_CLASS_UMB 0x00400000
#define WWAN_DATA_CLASS_CUSTOM 0x80000000
struct wwan_data_class_str {
ULONG class;
const char *str;
};
#pragma pack(push, 1)
typedef struct __IPV4 {
uint32_t Address;
uint32_t Gateway;
uint32_t SubnetMask;
uint32_t DnsPrimary;
uint32_t DnsSecondary;
uint32_t Mtu;
} IPV4_T;
typedef struct __IPV6 {
UCHAR Address[16];
UCHAR Gateway[16];
UCHAR SubnetMask[16];
UCHAR DnsPrimary[16];
UCHAR DnsSecondary[16];
UCHAR PrefixLengthIPAddr;
UCHAR PrefixLengthGateway;
ULONG Mtu;
} IPV6_T;
typedef struct {
UINT size;
UINT rx_urb_size;
UINT ep_type;
UINT iface_id;
UINT MuxId;
UINT ul_data_aggregation_max_datagrams; //0x17
UINT ul_data_aggregation_max_size ;//0x18
UINT dl_minimum_padding; //0x1A
} QMAP_SETTING;
//Configured downlink data aggregationprotocol
#define WDA_DL_DATA_AGG_DISABLED (0x00) //DL data aggregation is disabled (default)
#define WDA_DL_DATA_AGG_TLP_ENABLED (0x01) // DL TLP is enabled
#define WDA_DL_DATA_AGG_QC_NCM_ENABLED (0x02) // DL QC_NCM isenabled
#define WDA_DL_DATA_AGG_MBIM_ENABLED (0x03) // DL MBIM isenabled
#define WDA_DL_DATA_AGG_RNDIS_ENABLED (0x04) // DL RNDIS is enabled
#define WDA_DL_DATA_AGG_QMAP_ENABLED (0x05) // DL QMAP isenabled
#define WDA_DL_DATA_AGG_QMAP_V2_ENABLED (0x06) // DL QMAP V2 is enabled
#define WDA_DL_DATA_AGG_QMAP_V3_ENABLED (0x07) // DL QMAP V3 is enabled
#define WDA_DL_DATA_AGG_QMAP_V4_ENABLED (0x08) // DL QMAP V4 is enabled
#define WDA_DL_DATA_AGG_QMAP_V5_ENABLED (0x09) // DL QMAP V5 is enabled
typedef struct {
unsigned int size;
unsigned int rx_urb_size;
unsigned int ep_type;
unsigned int iface_id;
unsigned int qmap_mode;
unsigned int qmap_version;
unsigned int dl_minimum_padding;
char ifname[8][16];
unsigned char mux_id[8];
} RMNET_INFO;
#define IpFamilyV4 (0x04)
#define IpFamilyV6 (0x06)
struct __PROFILE;
struct qmi_device_ops {
int (*init)(struct __PROFILE *profile);
int (*deinit)(void);
int (*send)(PQCQMIMSG pRequest);
void* (*read)(void *pData);
};
#ifdef CONFIG_QRTR
extern const struct qmi_device_ops qrtr_qmidev_ops;
#endif
extern const struct qmi_device_ops gobi_qmidev_ops;
extern const struct qmi_device_ops qmiwwan_qmidev_ops;
extern const struct qmi_device_ops mbim_dev_ops;
extern const struct qmi_device_ops atc_dev_ops;
extern int (*qmidev_send)(PQCQMIMSG pRequest);
struct usb_device_info {
int idVendor;
int idProduct;
int busnum;
int devnum;
int bNumInterfaces;
};
struct usb_interface_info {
int bNumEndpoints;
int bInterfaceClass;
int bInterfaceSubClass;
int bInterfaceProtocol;
char driver[32];
};
#define LIBQMI_PROXY "qmi-proxy" //src/libqmi-glib/qmi-proxy.h
#define LIBMBIM_PROXY "mbim-proxy"
#define QUECTEL_QMI_PROXY "quectel-qmi-proxy"
#define QUECTEL_MBIM_PROXY "quectel-mbim-proxy"
#define QUECTEL_ATC_PROXY "quectel-atc-proxy"
#define QUECTEL_QRTR_PROXY "quectel-qrtr-proxy"
#ifndef bool
#define bool uint8_t
#endif
struct request_ops;
typedef struct __PROFILE {
//user input start
const char *apn;
const char *user;
const char *pd;
int auth;
int iptype;
const char *pincode;
char proxy[32];
int pdp;//pdp_context
int profile_index;//profile_index
int enable_bridge;
bool enable_ipv4;
bool enable_ipv6;
bool no_dhcp;
const char *logfile;
const char *usblogfile;
char expect_adapter[32];
int kill_pdp;
int replication_factor;
//user input end
char qmichannel[32];
char usbnet_adapter[32];
char qmapnet_adapter[32];
char driver_name[32];
int qmap_mode;
int qmap_size;
int qmap_version;
int curIpFamily;
int rawIP;
int muxid;
#ifdef CONFIG_ENABLE_QOS
UINT qos_id;
#endif
int wda_client;
uint32_t udhcpc_ip;
IPV4_T ipv4;
IPV6_T ipv6;
UINT PCSCFIpv4Addr1;
UINT PCSCFIpv4Addr2;
UCHAR PCSCFIpv6Addr1[16];
UCHAR PCSCFIpv6Addr2[16];
bool reattach_flag;
int hardware_interface;
int software_interface;
struct usb_device_info usb_dev;
struct usb_interface_info usb_intf;
int usbmon_fd;
FILE *usbmon_logfile_fp;
bool loopback_state;
char BaseBandVersion[64];
char old_apn[64];
char old_user[64];
char old_pd[64];
int old_auth;
int old_iptype;
const struct qmi_device_ops *qmi_ops;
const struct request_ops *request_ops;
RMNET_INFO rmnet_info;
BOOL bring_up_by_apn_name;
BOOL bring_up_by_apn_type;
int apn_type;
} PROFILE_T;
#ifdef QUECTEL_QMI_MERGE
#define MERGE_PACKET_IDENTITY 0x2c7c
#define MERGE_PACKET_VERSION 0x0001
#define MERGE_PACKET_MAX_PAYLOAD_SIZE 56
typedef struct __QMI_MSG_HEADER {
uint16_t idenity;
uint16_t version;
uint16_t cur_len;
uint16_t total_len;
} QMI_MSG_HEADER;
typedef struct __QMI_MSG_PACKET {
QMI_MSG_HEADER header;
uint16_t len;
char buf[4096];
} QMI_MSG_PACKET;
#endif
typedef enum {
SIM_ABSENT = 0,
SIM_NOT_READY = 1,
SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */
SIM_PIN = 3,
SIM_PUK = 4,
SIM_NETWORK_PERSONALIZATION = 5,
SIM_BAD = 6,
} SIM_Status;
#pragma pack(pop)
#define WDM_DEFAULT_BUFSIZE 256
#define RIL_REQUEST_QUIT 0x1000
#define RIL_INDICATE_DEVICE_CONNECTED 0x1002
#define RIL_INDICATE_DEVICE_DISCONNECTED 0x1003
#define RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED 0x1004
#define RIL_UNSOL_DATA_CALL_LIST_CHANGED 0x1005
#define MODEM_REPORT_RESET_EVENT 0x1006
#define RIL_UNSOL_LOOPBACK_CONFIG_IND 0x1007
#ifdef CONFIG_REG_QOS_IND
#define RIL_UNSOL_GLOBAL_QOS_FLOW_IND_QOS_ID 0x1008
#endif
extern pthread_mutex_t cm_command_mutex;
extern pthread_cond_t cm_command_cond;
extern unsigned int cm_recv_buf[1024];
extern int cm_open_dev(const char *dev);
extern int cm_open_proxy(const char *name);
extern int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t * mutex, unsigned msecs);
extern int QmiThreadSendQMITimeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse, unsigned msecs, const char *funcname);
#define QmiThreadSendQMI(pRequest, ppResponse) QmiThreadSendQMITimeout(pRequest, ppResponse, 30 * 1000, __func__)
extern void QmiThreadRecvQMI(PQCQMIMSG pResponse);
extern void udhcpc_start(PROFILE_T *profile);
extern void udhcpc_stop(PROFILE_T *profile);
extern void ql_set_driver_link_state(PROFILE_T *profile, int link_state);
extern void ql_set_driver_qmap_setting(PROFILE_T *profile, QMAP_SETTING *qmap_settings);
extern void ql_get_driver_rmnet_info(PROFILE_T *profile, RMNET_INFO *rmnet_info);
extern void dump_qmi(void *dataBuffer, int dataLen);
extern void qmidevice_send_event_to_main(int triger_event);
extern void qmidevice_send_event_to_main_ext(int triger_event, void *data, unsigned len);
extern uint8_t qmi_over_mbim_get_client_id(uint8_t QMIType);
extern uint8_t qmi_over_mbim_release_client_id(uint8_t QMIType, uint8_t ClientId);
#ifdef CONFIG_REG_QOS_IND
extern UCHAR ql_get_global_qos_flow_ind_qos_id(PQCQMIMSG pResponse, UINT *qos_id);
#endif
#ifdef CONFIG_GET_QOS_DATA_RATE
extern UCHAR ql_get_global_qos_flow_ind_data_rate(PQCQMIMSG pResponse, void *max_data_rate);
#endif
struct request_ops {
int (*requestBaseBandVersion)(PROFILE_T *profile);
int (*requestSetEthMode)(PROFILE_T *profile);
int (*requestSetLoopBackState)(UCHAR loopback_state, ULONG replication_factor);
int (*requestGetSIMStatus)(SIM_Status *pSIMStatus);
int (*requestEnterSimPin)(const char *pPinCode);
int (*requestSetProfile)(PROFILE_T *profile); // 1 ~ success and apn change, 0 ~ success and no apn change, -1 ~ fail
int (*requestGetProfile)(PROFILE_T *profile);
int (*requestRegistrationState)(UCHAR *pPSAttachedState);
int (*requestSetupDataCall)(PROFILE_T *profile, int curIpFamily);
int (*requestQueryDataCall)(UCHAR *pConnectionStatus, int curIpFamily);
int (*requestDeactivateDefaultPDP)(PROFILE_T *profile, int curIpFamily);
int (*requestGetIPAddress)(PROFILE_T *profile, int curIpFamily);
int (*requestGetSignalInfo)(void);
int (*requestGetCellInfoList)(void);
int (*requestGetICCID)(void);
int (*requestGetIMSI)(void);
int (*requestRadioPower)(int state);
int (*requestRegisterQos)(PROFILE_T *profile);
int (*requestGetQosInfo)(PROFILE_T *profile);
int (*requestGetCoexWWANState)(void);
};
extern const struct request_ops qmi_request_ops;
extern const struct request_ops mbim_request_ops;
extern const struct request_ops atc_request_ops;
extern int get_driver_type(PROFILE_T *profile);
extern BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile);
int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile);
int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile);
extern int ql_bridge_mode_detect(PROFILE_T *profile);
extern int ql_enable_qmi_wwan_rawip_mode(PROFILE_T *profile);
extern int ql_qmap_mode_detect(PROFILE_T *profile);
#ifdef CONFIG_QRTR
extern int rtrmnet_ctl_new_vnd(char *devname, char *vndname, uint8_t muxid,
uint32_t qmap_version, uint32_t ul_agg_cnt, uint32_t ul_agg_size);
extern int rtrmnet_ctl_get_vnd(char *vndname, int *muxid,
int *qmap_version);
#endif
#define qmidev_is_gobinet(_qmichannel) (strncmp(_qmichannel, "/dev/qcqmi", strlen("/dev/qcqmi")) == 0)
#define qmidev_is_qmiwwan(_qmichannel) (strncmp(_qmichannel, "/dev/cdc-wdm", strlen("/dev/cdc-wdm")) == 0)
#define qmidev_is_pciemhi(_qmichannel) (strncmp(_qmichannel, "/dev/mhi_", strlen("/dev/mhi_")) == 0)
#define driver_is_qmi(_drv_name) (strncasecmp(_drv_name, "qmi_wwan", strlen("qmi_wwan")) == 0)
#define driver_is_mbim(_drv_name) (strncasecmp(_drv_name, "cdc_mbim", strlen("cdc_mbim")) == 0)
extern FILE *logfilefp;
extern int debug_qmi;
extern int qmidevice_control_fd[2];
extern int g_donot_exit_when_modem_hangup;
extern void update_resolv_conf(int iptype, const char *ifname, const char *dns1, const char *dns2);
void update_ipv4_address(const char *ifname, const char *ip, const char *gw, unsigned prefix);
void update_ipv6_address(const char *ifname, const char *ip, const char *gw, unsigned prefix);
int reattach_driver(PROFILE_T *profile);
extern void no_trunc_strncpy(char *dest, const char *src, size_t dest_size);
enum
{
DRV_INVALID,
SOFTWARE_QMI,
SOFTWARE_MBIM,
SOFTWARE_ECM_RNDIS_NCM,
SOFTWARE_QRTR,
HARDWARE_PCIE,
HARDWARE_USB,
HARDWARE_IPA,
};
#ifdef USE_IPC_MSG_STATUS_IND
#include <sys/ipc.h>
#include <sys/msg.h>
#define MSG_FILE "/etc/passwd"
#define MSG_TYPE_IPC 1
#define MSGBUFFSZ 16
struct message
{
long mtype;
char mtext[MSGBUFFSZ];
};
enum
{
QCM_PARA_CONFIG_QUERY = 1,
QCM_NETWORK_IPV4_CONNECTED,
QCM_NETWORK_IPV6_CONNECTED,
QCM_NETWORK_IPV4_DISCONNECTED,
QCM_NETWORK_IPV6_DISCONNECTED,
QCM_PREPARE_START_DAIL,
QCM_PREPARE_DAIL_FIAL,
QCM_PREPARE_DAIL_SUCC,
QCM_PREPARE_RESTART_DAIL,
QCM_PROCESS_EXIT,
};
#endif
enum
{
SIG_EVENT_START,
SIG_EVENT_CHECK,
SIG_EVENT_STOP,
};
typedef enum
{
DMS_OP_MODE_ONLINE,
DMS_OP_MODE_LOW_POWER,
DMS_OP_MODE_FACTORY_TEST_MODE,
DMS_OP_MODE_OFFLINE,
DMS_OP_MODE_RESETTING,
DMS_OP_MODE_SHUTTING_DOWN,
DMS_OP_MODE_PERSISTENT_LOW_POWER,
DMS_OP_MODE_MODE_ONLY_LOW_POWER,
DMS_OP_MODE_NET_TEST_GW,
}Device_operating_mode;
#ifdef CM_DEBUG
#define dbg_time(fmt, args...) do { \
fprintf(stdout, "[%15s-%04d: %s] " fmt "\n", __FILE__, __LINE__, get_time(), ##args); \
fflush(stdout);\
if (logfilefp) fprintf(logfilefp, "[%s-%04d: %s] " fmt "\n", __FILE__, __LINE__, get_time(), ##args); \
} while(0)
#else
#define dbg_time(fmt, args...) do { \
fprintf(stdout, "[%s] " fmt "\n", get_time(), ##args); \
fflush(stdout);\
if (logfilefp) fprintf(logfilefp, "[%s] " fmt "\n", get_time(), ##args); \
} while(0)
#endif
#endif
-454
View File
@@ -1,454 +0,0 @@
/*
Copyright 2025 Quectel Wireless Solutions Co.,Ltd
Quectel hereby grants customers of Quectel a license to use, modify,
distribute and publish the Software in binary form provided that
customers shall have no right to reverse engineer, reverse assemble,
decompile or reduce to source code form any portion of the Software.
Under no circumstances may customers modify, demonstrate, use, deliver
or disclose any portion of the Software in source code form.
*/
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <stdio.h>
#include <ctype.h>
#include "QMIThread.h"
#ifdef CONFIG_QMIWWAN
static int cdc_wdm_fd = -1;
static UCHAR qmiclientId[QMUX_TYPE_ALL];
static UCHAR GetQCTLTransactionId(void) {
static int TransactionId = 0;
if (++TransactionId > 0xFF)
TransactionId = 1;
return TransactionId;
}
typedef USHORT (*CUSTOMQCTL)(PQMICTL_MSG pCTLMsg, void *arg);
static PQCQMIMSG ComposeQCTLMsg(USHORT QMICTLType, CUSTOMQCTL customQctlMsgFunction, void *arg) {
UCHAR QMIBuf[WDM_DEFAULT_BUFSIZE];
PQCQMIMSG pRequest = (PQCQMIMSG)QMIBuf;
int Length;
pRequest->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI;
pRequest->QMIHdr.CtlFlags = 0x00;
pRequest->QMIHdr.QMIType = QMUX_TYPE_CTL;
pRequest->QMIHdr.ClientId= 0x00;
pRequest->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST;
pRequest->CTLMsg.QMICTLMsgHdr.TransactionId = GetQCTLTransactionId();
pRequest->CTLMsg.QMICTLMsgHdr.QMICTLType = cpu_to_le16(QMICTLType);
if (customQctlMsgFunction)
pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(customQctlMsgFunction(&pRequest->CTLMsg, arg) - sizeof(QCQMICTL_MSG_HDR));
else
pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(0x0000);
pRequest->QMIHdr.Length = cpu_to_le16(le16_to_cpu(pRequest->CTLMsg.QMICTLMsgHdr.Length) + sizeof(QCQMICTL_MSG_HDR) + sizeof(QCQMI_HDR) - 1);
Length = le16_to_cpu(pRequest->QMIHdr.Length) + 1;
pRequest = (PQCQMIMSG)malloc(Length);
if (pRequest == NULL) {
dbg_time("%s fail to malloc", __func__);
} else {
memcpy(pRequest, QMIBuf, Length);
}
return pRequest;
}
static USHORT CtlGetVersionReq(PQMICTL_MSG QCTLMsg, void *arg)
{
(void)arg;
QCTLMsg->GetVersionReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER;
QCTLMsg->GetVersionReq.TLVLength = cpu_to_le16(0x0001);
QCTLMsg->GetVersionReq.QMUXTypes = QMUX_TYPE_ALL;
return sizeof(QMICTL_GET_VERSION_REQ_MSG);
}
static USHORT CtlGetClientIdReq(PQMICTL_MSG QCTLMsg, void *arg) {
QCTLMsg->GetClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER;
QCTLMsg->GetClientIdReq.TLVLength = cpu_to_le16(0x0001);
QCTLMsg->GetClientIdReq.QMIType = ((UCHAR *)arg)[0];
return sizeof(QMICTL_GET_CLIENT_ID_REQ_MSG);
}
static USHORT CtlReleaseClientIdReq(PQMICTL_MSG QCTLMsg, void *arg) {
QCTLMsg->ReleaseClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER;
QCTLMsg->ReleaseClientIdReq.TLVLength = cpu_to_le16(0x0002);
QCTLMsg->ReleaseClientIdReq.QMIType = ((UCHAR *)arg)[0];
QCTLMsg->ReleaseClientIdReq.ClientId = ((UCHAR *)arg)[1] ;
return sizeof(QMICTL_RELEASE_CLIENT_ID_REQ_MSG);
}
static USHORT CtlLibQmiProxyOpenReq(PQMICTL_MSG QCTLMsg, void *arg)
{
(void)arg;
const char *device_path = (const char *)(arg);
QCTLMsg->LibQmiProxyOpenReq.TLVType = 0x01;
QCTLMsg->LibQmiProxyOpenReq.TLVLength = cpu_to_le16(strlen(device_path));
//strcpy(QCTLMsg->LibQmiProxyOpenReq.device_path, device_path);
//__builtin___strcpy_chk
memcpy(QCTLMsg->LibQmiProxyOpenReq.device_path, device_path, strlen(device_path));
return sizeof(QMICTL_LIBQMI_PROXY_OPEN_MSG) + (strlen(device_path));
}
static int libqmi_proxy_open(const char *cdc_wdm) {
int ret;
PQCQMIMSG pResponse;
ret = QmiThreadSendQMI(ComposeQCTLMsg(QMI_MESSAGE_CTL_INTERNAL_PROXY_OPEN,
CtlLibQmiProxyOpenReq, (void *)cdc_wdm), &pResponse);
if (!ret && pResponse
&& pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0
&& pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) {
ret = 0;
}
else {
return -1;
}
if (pResponse)
free(pResponse);
return ret;
}
static int QmiWwanSendQMI(PQCQMIMSG pRequest) {
struct pollfd pollfds[]= {{cdc_wdm_fd, POLLOUT, 0}};
int ret;
if (cdc_wdm_fd == -1) {
dbg_time("%s cdc_wdm_fd = -1", __func__);
return -ENODEV;
}
if (pRequest->QMIHdr.QMIType != QMUX_TYPE_CTL) {
pRequest->QMIHdr.ClientId = qmiclientId[pRequest->QMIHdr.QMIType];
if (pRequest->QMIHdr.ClientId == 0) {
dbg_time("QMIType %d has no clientID", pRequest->QMIHdr.QMIType);
return -ENODEV;
}
if (pRequest->QMIHdr.QMIType == QMUX_TYPE_WDS_IPV6)
pRequest->QMIHdr.QMIType = QMUX_TYPE_WDS;
}
do {
ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000);
} while ((ret < 0) && (errno == EINTR));
if (pollfds[0].revents & POLLOUT) {
ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1;
ret = write(cdc_wdm_fd, pRequest, nwrites);
if (ret == nwrites) {
ret = 0;
} else {
dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno));
}
} else {
dbg_time("%s poll=%d, revents = 0x%x, errno: %d (%s)", __func__, ret, pollfds[0].revents, errno, strerror(errno));
}
return ret;
}
static UCHAR QmiWwanGetClientID(UCHAR QMIType) {
PQCQMIMSG pResponse;
QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_GET_CLIENT_ID_REQ, CtlGetClientIdReq, &QMIType), &pResponse);
if (pResponse) {
USHORT QMUXResult = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult); // QMI_RESULT_SUCCESS
USHORT QMUXError = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError); // QMI_ERR_INVALID_ARG
//UCHAR QMIType = pResponse->CTLMsg.GetClientIdRsp.QMIType;
UCHAR ClientId = pResponse->CTLMsg.GetClientIdRsp.ClientId;
if (!QMUXResult && !QMUXError && (QMIType == pResponse->CTLMsg.GetClientIdRsp.QMIType)) {
switch (QMIType) {
case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break;
case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break;
case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break;
case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break;
case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break;
case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break;
case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break;
case QMUX_TYPE_COEX: dbg_time("Get clientCOEX = %d", ClientId); break;
case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId);
break;
default: break;
}
return ClientId;
}
}
return 0;
}
static int QmiWwanReleaseClientID(QMI_SERVICE_TYPE QMIType, UCHAR ClientId) {
UCHAR argv[] = {QMIType, ClientId};
QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_RELEASE_CLIENT_ID_REQ, CtlReleaseClientIdReq, argv), NULL);
return 0;
}
static int QmiWwanInit(PROFILE_T *profile) {
unsigned i;
int ret;
PQCQMIMSG pResponse;
if (profile->proxy[0] && !strcmp(profile->proxy, LIBQMI_PROXY)) {
ret = libqmi_proxy_open(profile->qmichannel);
if (ret)
return ret;
}
if (!profile->proxy[0]) {
for (i = 0; i < 10; i++) {
ret = QmiThreadSendQMITimeout(ComposeQCTLMsg(QMICTL_SYNC_REQ, NULL, NULL), NULL, 1 * 1000, __func__);
if (ret != ETIMEDOUT)
break;
sleep(1);
}
if (ret)
return ret;
}
QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_GET_VERSION_REQ, CtlGetVersionReq, NULL), &pResponse);
if (profile->qmap_mode) {
if (pResponse) {
if (pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0 && pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) {
uint8_t NumElements = 0;
for (NumElements = 0; NumElements < pResponse->CTLMsg.GetVersionRsp.NumElements; NumElements++) {
#if 0
dbg_time("QMUXType = %02x Version = %d.%d",
pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].QMUXType,
pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MajorVersion,
pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MinorVersion);
#endif
if (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].QMUXType == QMUX_TYPE_WDS_ADMIN)
profile->qmap_version = (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MinorVersion > 16);
}
}
}
}
if (pResponse) free(pResponse);
qmiclientId[QMUX_TYPE_WDS] = QmiWwanGetClientID(QMUX_TYPE_WDS);
if (profile->enable_ipv6)
qmiclientId[QMUX_TYPE_WDS_IPV6] = QmiWwanGetClientID(QMUX_TYPE_WDS);
qmiclientId[QMUX_TYPE_DMS] = QmiWwanGetClientID(QMUX_TYPE_DMS);
qmiclientId[QMUX_TYPE_NAS] = QmiWwanGetClientID(QMUX_TYPE_NAS);
qmiclientId[QMUX_TYPE_UIM] = QmiWwanGetClientID(QMUX_TYPE_UIM);
qmiclientId[QMUX_TYPE_WDS_ADMIN] = QmiWwanGetClientID(QMUX_TYPE_WDS_ADMIN);
#ifdef CONFIG_COEX_WWAN_STATE
qmiclientId[QMUX_TYPE_COEX] = QmiWwanGetClientID(QMUX_TYPE_COEX);
#endif
#ifdef CONFIG_ENABLE_QOS
qmiclientId[QMUX_TYPE_QOS] = QmiWwanGetClientID(QMUX_TYPE_QOS);
#endif
profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN];
return 0;
}
static int QmiWwanDeInit(void) {
unsigned int i;
for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++)
{
if (qmiclientId[i] != 0)
{
QmiWwanReleaseClientID((QMUX_TYPE_WDS_IPV6 == i ? QMUX_TYPE_WDS : i), qmiclientId[i]);
qmiclientId[i] = 0;
}
}
return 0;
}
static ssize_t qmi_proxy_read (int fd, void *buf, size_t size) {
ssize_t nreads;
PQCQMI_HDR pHdr = (PQCQMI_HDR)buf;
nreads = read(fd, pHdr, sizeof(QCQMI_HDR));
if (nreads == sizeof(QCQMI_HDR) && le16_to_cpu(pHdr->Length) < size) {
nreads += read(fd, pHdr+1, le16_to_cpu(pHdr->Length) + 1 - sizeof(QCQMI_HDR));
}
return nreads;
}
#ifdef QUECTEL_QMI_MERGE
static int QmiWwanMergeQmiRsp(void *buf, ssize_t *src_size) {
static QMI_MSG_PACKET s_QMIPacket;
QMI_MSG_HEADER *header = NULL;
ssize_t size = *src_size;
if((uint16_t)size < sizeof(QMI_MSG_HEADER))
return -1;
header = (QMI_MSG_HEADER *)buf;
if(le16_to_cpu(header->idenity) != MERGE_PACKET_IDENTITY || le16_to_cpu(header->version) != MERGE_PACKET_VERSION || le16_to_cpu(header->cur_len) > le16_to_cpu(header->total_len))
return -1;
if(le16_to_cpu(header->cur_len) == le16_to_cpu(header->total_len)) {
*src_size = le16_to_cpu(header->total_len);
memcpy(buf, buf + sizeof(QMI_MSG_HEADER), *src_size);
s_QMIPacket.len = 0;
return 0;
}
memcpy(s_QMIPacket.buf + s_QMIPacket.len, buf + sizeof(QMI_MSG_HEADER), le16_to_cpu(header->cur_len));
s_QMIPacket.len += le16_to_cpu(header->cur_len);
if (le16_to_cpu(header->cur_len) < MERGE_PACKET_MAX_PAYLOAD_SIZE || s_QMIPacket.len >= le16_to_cpu(header->total_len)) {
memcpy(buf, s_QMIPacket.buf, s_QMIPacket.len);
*src_size = s_QMIPacket.len;
s_QMIPacket.len = 0;
return 0;
}
return -1;
}
#endif
static void * QmiWwanThread(void *pData) {
PROFILE_T *profile = (PROFILE_T *)pData;
const char *cdc_wdm = (const char *)profile->qmichannel;
int wait_for_request_quit = 0;
char num = cdc_wdm[strlen(cdc_wdm)-1];
if (profile->proxy[0]) {
if (!strncmp(profile->proxy, QUECTEL_QMI_PROXY, strlen(QUECTEL_QMI_PROXY))) {
snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QMI_PROXY, num);
}
}
else if (!strncmp(cdc_wdm, "/dev/mhi_IPCR", strlen("/dev/mhi_IPCR"))) {
snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QRTR_PROXY, num);
}
else if (profile->qmap_mode > 1) {
snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QMI_PROXY, num);
}
if (profile->proxy[0])
cdc_wdm_fd = cm_open_proxy(profile->proxy);
else
cdc_wdm_fd = cm_open_dev(cdc_wdm);
if (cdc_wdm_fd == -1) {
dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, cdc_wdm, errno, strerror(errno));
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
pthread_exit(NULL);
return NULL;
}
dbg_time("cdc_wdm_fd = %d", cdc_wdm_fd);
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED);
while (1) {
struct pollfd pollfds[] = {{qmidevice_control_fd[1], POLLIN, 0}, {cdc_wdm_fd, POLLIN, 0}};
int ne, ret, nevents = sizeof(pollfds)/sizeof(pollfds[0]);
do {
ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1);
} while ((ret < 0) && (errno == EINTR));
if (ret == 0 && wait_for_request_quit) {
QmiThreadRecvQMI(NULL);
continue;
}
if (ret <= 0) {
dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno));
break;
}
for (ne = 0; ne < nevents; ne++) {
int fd = pollfds[ne].fd;
short revents = pollfds[ne].revents;
//dbg_time("{%d, %x, %x}", pollfds[ne].fd, pollfds[ne].events, pollfds[ne].revents);
if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
dbg_time("%s poll err/hup/inval", __func__);
dbg_time("poll fd = %d, events = 0x%04x", fd, revents);
if (fd == cdc_wdm_fd) {
} else {
}
if (revents & (POLLHUP | POLLNVAL)) //EC20 bug, Can get POLLERR
goto __QmiWwanThread_quit;
}
if ((revents & POLLIN) == 0)
continue;
if (fd == qmidevice_control_fd[1]) {
int triger_event;
if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) {
//DBG("triger_event = 0x%x", triger_event);
switch (triger_event) {
case RIL_REQUEST_QUIT:
goto __QmiWwanThread_quit;
break;
case SIG_EVENT_STOP:
wait_for_request_quit = 1;
break;
default:
break;
}
}
}
if (fd == cdc_wdm_fd) {
ssize_t nreads;
PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf;
if (!profile->proxy[0])
nreads = read(fd, cm_recv_buf, sizeof(cm_recv_buf));
else
nreads = qmi_proxy_read(fd, cm_recv_buf, sizeof(cm_recv_buf));
//dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno));
if (nreads <= 0) {
dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno));
break;
}
#ifdef QUECTEL_QMI_MERGE
if((profile->qmap_mode == 0 || profile->qmap_mode == 1) && QmiWwanMergeQmiRsp(cm_recv_buf, &nreads))
continue;
#endif
if (nreads != (le16_to_cpu(pResponse->QMIHdr.Length) + 1)) {
dbg_time("%s nreads=%d, pQCQMI->QMIHdr.Length = %d", __func__, (int)nreads, le16_to_cpu(pResponse->QMIHdr.Length));
continue;
}
QmiThreadRecvQMI(pResponse);
}
}
}
__QmiWwanThread_quit:
if (cdc_wdm_fd != -1) { close(cdc_wdm_fd); cdc_wdm_fd = -1; }
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI()
dbg_time("%s exit", __func__);
pthread_exit(NULL);
return NULL;
}
const struct qmi_device_ops qmiwwan_qmidev_ops = {
.init = QmiWwanInit,
.deinit = QmiWwanDeInit,
.send = QmiWwanSendQMI,
.read = QmiWwanThread,
};
uint8_t qmi_over_mbim_get_client_id(uint8_t QMIType) {
return QmiWwanGetClientID(QMIType);
}
uint8_t qmi_over_mbim_release_client_id(uint8_t QMIType, uint8_t ClientId) {
return QmiWwanReleaseClientID(QMIType, ClientId);
}
#endif
-357
View File
@@ -1,357 +0,0 @@
Release Notes
[V1.6.8]
Date: 3/4/2025
enhancement:
1. add QMI dialing status report
fix:
1. fix some bugs
[V1.6.7]
Date: 5/17/2024
enhancement:
1. optimize -a parameter
fix:
1. fix the multiple dialing issue on the SDX35 platform
[V1.6.6]
Date: 1/12/2024
enhancement:
1. support SDX35 platform
[V1.6.5]
Date: 7/3/2023
enhancement:
1. Fix the issue of qmi client id leakage caused by kill 9 killing the client of quectel-qmi-proxy
2. Fix wds_ipv6 client ID can't be released issue
3. Fix wds_ipv6 client ID can't be released issue
4. Resolve PDP_ Context&Profile_ The issue of index mixing
5. Add parameter - d to obtain IP and DNS information through qmi
6. Fix mbim dialing. When the user does not specify apn through - s, prompt the user and exit the dialing program
7. Prioritize the use of IP commands for optimization, and use ifconfig if not available
8. Optimize and add/remove copyright
fix:
[V1.6.4]
Date: 9/7/2022
enhancement:
1. set cflags as -Wall -Wextra -Werror -O1, and fix compile errors
2. some code refactoring
3. add quectel-qrtr-proxy
fix:
1. netmask error when use ifconfig on little endian cpu
[V1.6.2]
Date: 11/18/2021
enhancement:
1. support 'LTE && WiFi Coexistence Solution via QMI'.
If customer want use this feature, need enable CONFIG_COEX_WWAN_STATE in QMIThread.h
[V1.6.1]
Date: 7/20/2021
enhancement:
1. add requestGetCellInfoList requestRadioPower
2. add QMI OVER MBIM
3. support qrtr and rmnet
4. support RG500U PCIE
5. add qos service && get qos flow data_rate_max func
fix:
1. mbim: increase mbim open timeout to 3 seconds. some modem take long time for open cmd.
2. support MsChapV2
3. mbim: invalid memory access when only get one DNS
4. some bug fix for use AT Command to setup data call
[V1.6.0.26]
Date: 4/22/2021
enhancement:
1. add lots of log file to show how to use this tool
2. support pcie mhi multiple call
3. at command: support EC200U/EC200T/EC200S/RG801H/RG500U/
fix:
1. mbim-proxy: fix errors on big endian cpu, ignore mbim open/close cmd from quectel-cm
[V1.6.0.25]
Date: 4/8/2021
enhancement:
fix:
1. fix compile error when use gcc 9.3.0
2. fix yocto 'QA Issue: No GNU_HASH in the ELF binary'
[V1.6.0.24]
Date: 3/9/2021
enhancement:
1. '-p [quectel-][qmi|mbim]-proxy', can connect to quectel/libqmi/libmbim's proxy, even only one data
2. set variable s_9x07 as 1 (from 0), most of modems are base on MDM90x7 and later QCOM chip.
fix:
1. define CHAR as signed char
2. mofidy Makefile to generate more compile warnnings and fix them
[V1.6.0.23]
Date: 2/26/2021
enhancement:
1. support 'AT+QNETDEVCTL' (not release)
fix:
1. modify help/usage
2. fix some memroy access error in mbim-cm.c
[V1.6.0.22]
Date: 2/4/2021
enhancement:
1. support connect to libqmi's qmi-proxy
2. only allow ' 0/1/2/none/pap/chap' for auth of '-s'
3. '-m iface-idx' bind QMAP data call to wwan0_<iface_idx>
fix:
[V1.6.0.21]
Date: 1/28/2021
enhancement:
1. print 5G signal
fix:
1. fix compile errors: -Werror=format-truncation=
[V1.6.0.20]
Date: 12/29/2020
enhancement:
1. Code refactoring
2. support 'AT+QNETDEVCTL' (not release)
fix:
[V1.6.0.19]
Date: 12/4/2020
enhancement:
1. if 'udhcpc's default.script' missed, directy set ip/dns/route by 'ip' co,mand
fix:
[V1.6.0.18]
Date: 12/4/2020
enhancement:
1. Code refactoring
fix:
[V1.6.0.17]
Date: 8/25/2020
enhancement:
1. support MBIM multi-call
2. support unisoc RG500U mbim
3. QUECTEL_QMI_MERGE: some SOC can not read more then 64 bytes (QMI)data via USB Endpoint 0
fix:
[V1.6.0.15]
Date: 7/24/2020
enhancement:
fix:
1. QMAP multi-call, AT+CFUN=4 then AT+CFUN=1, only one call can obtain IP by DHCP
[V1.6.0.14]
Date: 6/10/2020
enhancement:
1. support X55's GobiNet LOOPBACK
fix:
1. very old uclib do not support htole32 and pthread_condattr_setclock
2. pthread_cond_wait tv_nsec >= 1000000000U is wrong
3. do not close socket in udhcpc.c ifc_get_addr()
[V1.6.0.13]
Date: 6/9/2020
enhancement:
1. add some example for openwrt, marco 'QL_OPENWER_NETWORK_SETUP'
fix:
[V1.6.0.12]
Date: 5/29/2020
enhancement:
fix:
1. some EM12's usb-net-qmi/mbim interface is at 8 (not 4)
[V1.6.0.11]
Date: 5/28/2020
enhancement:
fix:
1. fix mbim debug on Big Endian CPU
[V1.6.0.10]
Date: 5/25/2020
enhancement:
fix:
1. set QMAP .ul_data_aggregation_max_datagrams to 11 (from 16)
[V1.6.0.9]
Date: 5/22/2020
enhancement:
fix:
1. dial fail when register to 5G-SA
[V1.6.0.8]
Date: 4/30/2020
enhancement:
1. support '-b' to seletc brige mode
fix:
[V1.6.0.7]
Date: 4/29/2020
enhancement:
1. support QMAP multi-call for qmi_wwan_q and pcie_mhi 's rmnet driver
fix:
[V1.6.0.6]
Date: 4/20/2020
enhancement:
1. support '-k pdn_idx' to hangup call '-n pdn_idx'
fix:
1. fix set dl_minimum_padding as 0, modems do not support this featrue
[V1.6.0.5]
Date: 4/10/2020
enhancement:
1. support X55's QMAPV5 for PCIE
fix:
[V1.6.0.3]
Date: 4/8/2020
enhancement:
1. support multi-modems all use multi-data-calls
fix:
[V1.6.0.2]
Date: 4/7/2020
enhancement:
1. support X55's QMAPV5 for USB
fix:
[V1.6.0.1]
Date: 4/1/2020
enhancement:
1. support QMAP UL AGG (multi data call)
fix:
1. some EM12's usb-net-qmi/mbim interface is at 8 (not 4)
[V1.5.9]
Date: 3/4/2020
enhancement:
1. support pcie mhi multi-APN data call
3. support QMAP UL AGG (single data call)
fix:
1. set 4 bytes aligned for mbim parameters, or cause dial mbim call fail
[V1.5.8]
Date: 2/18/2020
enhancement:
1. support '-l 14' X55's loopback function
fix:
[V1.5.7]
Date: 2/6/2020
enhancement:
1. support '-u usbmon_log_file' to catch usbmon log
fix:
[V1.5.6]
Date: 1/20/202
enhancement:
1. show driver name and version
2. support PCSCF
3. support bridge in mbim
fix:
[V1.5.5]
Date: 12/31/2019
enhancement:
fix:
1. fix some memory access bug in mbim-cm.c
[WCDMA&LTE_QConnectManager_Linux&Android_V1.5.4]
Date: 12/17/2019
enhancement:
1. Add copyright
2. auto detect pcie mhi /dev/mhi*
fix:
[WCDMA&LTE_QConnectManager_Linux&Android_V1.5.3]
Date: 2019/12/11
enhancement:
1. support show SignalInfo, controlled by macro CONFIG_SIGNALINFO
2. support show 5G_NSA/5G_NA
3. support Microsoft Extend MBIM message
fix:
1. quectel-qmi-proxy bugs on Big-Endian CPU
[WCDMA&LTE_QConnectManager_Linux&Android_V1.5.2]
Date: 12/2/2019
enhancement:
1. support requestGetSignalInfo()
fix:
[WCDMA&LTE_QConnectManager_Linux&Android_V1.4.1]
Date: 10/23/2019
enhancement:
1. support QMI_CTL_REVOKE_CLIENT_ID_IND (Quectel define QMI)
2. add copyright
fix:
1. remove SIGUSR
[WCDMA&LTE_QConnectManager_Linux&Android_V1.3.10]
Date: 10/14/2019
enhancement:
1. increase retry interval
fix:
[WCDMA&LTE_QConnectManager_Linux&Android_V1.2.1]
Date: 2019/02/26
enhancement:
1. Implement help message.
root@ubuntu:# ./quectel-CM -h
[02-26_10:39:21:353] Usage: ./quectel-CM [options]
[02-26_10:39:21:353] -s [apn [user password auth]] Set apn/user/password/auth get from your network provider
[02-26_10:39:21:353] -p pincode Verify sim card pin if sim card is locked
[02-26_10:39:21:353] -f logfilename Save log message of this program to file
[02-26_10:39:21:353] -i interface Specify network interface(default auto-detect)
[02-26_10:39:21:353] -4 IPv4 protocol
[02-26_10:39:21:353] -6 IPv6 protocol
[02-26_10:39:21:353] -m muxID Specify muxid when set multi-pdn data connection.
[02-26_10:39:21:353] -n channelID Specify channelID when set multi-pdn data connection(default 1).
[02-26_10:39:21:353] [Examples]
[02-26_10:39:21:353] Example 1: ./quectel-CM
[02-26_10:39:21:353] Example 2: ./quectel-CM -s 3gnet
[02-26_10:39:21:353] Example 3: ./quectel-CM -s 3gnet carl 1234 0 -p 1234 -f gobinet_log.txt
root@ubuntu:#
2. Support bridge mode when set multi-pdn data connections.
3. Host device can access network in bridge mode.
[WCDMA&LTE_QConnectManager_Linux&Android_V1.1.46]
Date: 2019/02/18
enhancement:
1. support only IPV6 data call. quectel-CM now support three dialing methods: IPV4 only, IPV6 only, IPV4V6.
./quectel-CM -4(or no argument) only IPV4
-6 only IPV6
-4 -6 IPV4 && IPV6
[WCDMA&LTE_QConnectManager_Linux&Android_V1.1.45]
Date: 2018/09/13
enhancement:
1. support EG12 PCIE interface
[WCDMA&LTE_QConnectManager_Linux&Android_V1.1.44]
Date: 2018/09/10
enhancement:
1. support setup IPV4&IPV6 data call.
[WCDMA&LTE_QConnectManager_Linux&Android_V1.1.43]
[WCDMA&LTE_QConnectManager_Linux&Android_V1.1.42]
Date: 2018/08/29
enhancement:
1. support QMI_WWAN's QMAP fucntion and bridge mode, please contact Quectel FAE to get qmi_wwan.c patch.
when enable QMI_WWAN's QMAP IP Mux function, must run 'quectel-qmi-proxy -d /dev/cdc-wdmX' before quectel-CM
[WCDMA&LTE_QConnectManager_Linux&Android_V1.1.41]
Date: 2018/05/24
enhancement:
1. fix a cdma data call error
[WCDMA&LTE_QConnectManager_Linux&Android_V1.1.40]
Date: 2018/05/12
enhancement:
1. support GobiNet's QMAP fucntion and bridge mode.
'Quectel_WCDMA&LTE_Linux&Android_GobiNet_Driver_V1.3.5' and later version is required to use QMAP and bridge mode.
for detail, please refer to GobiNet Driver
-283
View File
@@ -1,283 +0,0 @@
/* //device/system/reference-ril/at_tok.c
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include "at_tok.h"
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
/**
* Starts tokenizing an AT response string
* returns -1 if this is not a valid response string, 0 on success.
* updates *p_cur with current position
*/
int at_tok_start(char **p_cur)
{
if (*p_cur == NULL) {
return -1;
}
// skip prefix
// consume "^[^:]:"
*p_cur = strchr(*p_cur, ':');
if (*p_cur == NULL) {
return -1;
}
(*p_cur)++;
return 0;
}
static void skipWhiteSpace(char **p_cur)
{
if (*p_cur == NULL) return;
while (**p_cur != '\0' && isspace(**p_cur)) {
(*p_cur)++;
}
}
static void skipNextComma(char **p_cur)
{
if (*p_cur == NULL) return;
while (**p_cur != '\0' && **p_cur != ',') {
(*p_cur)++;
}
if (**p_cur == ',') {
(*p_cur)++;
}
}
static char * nextTok(char **p_cur)
{
char *ret = NULL;
skipWhiteSpace(p_cur);
if (*p_cur == NULL) {
ret = NULL;
} else if (**p_cur == '"') {
(*p_cur)++;
ret = strsep(p_cur, "\"");
skipNextComma(p_cur);
} else {
ret = strsep(p_cur, ",");
}
return ret;
}
/**
* Parses the next integer in the AT response line and places it in *p_out
* returns 0 on success and -1 on fail
* updates *p_cur
* "base" is the same as the base param in strtol
*/
static int at_tok_nextint_base(char **p_cur, int *p_out, int base, int uns)
{
char *ret;
if (*p_cur == NULL) {
return -1;
}
ret = nextTok(p_cur);
if (ret == NULL) {
return -1;
} else {
long l;
char *end;
if (uns)
l = strtoul(ret, &end, base);
else
l = strtol(ret, &end, base);
*p_out = (int)l;
if (end == ret) {
return -1;
}
}
return 0;
}
/**
* Parses the next base 10 integer in the AT response line
* and places it in *p_out
* returns 0 on success and -1 on fail
* updates *p_cur
*/
int at_tok_nextint(char **p_cur, int *p_out)
{
return at_tok_nextint_base(p_cur, p_out, 10, 0);
}
/**
* Parses the next base 16 integer in the AT response line
* and places it in *p_out
* returns 0 on success and -1 on fail
* updates *p_cur
*/
int at_tok_nexthexint(char **p_cur, int *p_out)
{
return at_tok_nextint_base(p_cur, p_out, 16, 1);
}
int at_tok_nextbool(char **p_cur, char *p_out)
{
int ret;
int result;
ret = at_tok_nextint(p_cur, &result);
if (ret < 0) {
return -1;
}
// booleans should be 0 or 1
if (!(result == 0 || result == 1)) {
return -1;
}
if (p_out != NULL) {
*p_out = (char)result;
}
return ret;
}
int at_tok_nextstr(char **p_cur, char **p_out)
{
if (*p_cur == NULL) {
return -1;
}
*p_out = nextTok(p_cur);
return 0;
}
/** returns 1 on "has more tokens" and 0 if no */
int at_tok_hasmore(char **p_cur)
{
return ! (*p_cur == NULL || **p_cur == '\0');
}
int at_tok_count(const char *in_line)
{
int commas = 0;
const char *p;
if (!in_line)
return 0;
for (p = in_line; *p != '\0' ; p++) {
if (*p == ',') commas++;
}
return commas;
}
//fmt: d ~ int, x ~ hexint, b ~ bool, s ~ str
int at_tok_scanf(const char *in_line, const char *fmt, ...)
{
int n = 0;
int err;
va_list ap;
const char *p = fmt;
void *d;
void *dump;
static char s_line[1024];
char *line = s_line;
if (!in_line)
return 0;
strncpy(s_line, in_line, sizeof(s_line) - 1);
va_start(ap, fmt);
err = at_tok_start(&line);
if (err < 0) goto error;
for (; *p; p++) {
if (*p == ',' || *p == ' ')
continue;
if (*p != '%') {
goto error;
}
p++;
d = va_arg(ap, void *);
if (!d)
d = &dump;
if (!at_tok_hasmore(&line))
break;
if (*line == '-' && *(line + 1) == ',') {
line += 2;
n++;
if (*p == 'd')
*(int *)d = -1;
continue;
}
switch(*p) {
case 'd':
err = at_tok_nextint(&line, (int *)d);
if (err < 0) goto error;
break;
case 'x':
err = at_tok_nexthexint(&line, (int *)d);
if (err < 0) goto error;
break;
case 'b':
err = at_tok_nextbool(&line, (char *)d);
if (err < 0) goto error;
break;
case 's':
err = at_tok_nextstr(&line, (char **)d); //if strdup(line), here return free memory to caller
if (err < 0) goto error;
break;
default:
goto error;
break;
}
n++;
}
va_end(ap);
error:
//free(line);
return n;
}
-33
View File
@@ -1,33 +0,0 @@
/* //device/system/reference-ril/at_tok.h
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#ifndef AT_TOK_H
#define AT_TOK_H 1
int at_tok_start(char **p_cur);
int at_tok_nextint(char **p_cur, int *p_out);
int at_tok_nexthexint(char **p_cur, int *p_out);
int at_tok_nextbool(char **p_cur, char *p_out);
int at_tok_nextstr(char **p_cur, char **out);
int at_tok_hasmore(char **p_cur);
int at_tok_count(const char *in_line);
int at_tok_scanf(const char *line, const char *fmt, ...);
#endif /*AT_TOK_H */
-1056
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-152
View File
@@ -1,152 +0,0 @@
/* //device/system/reference-ril/atchannel.h
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#ifndef ATCHANNEL_H
#define ATCHANNEL_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* define AT_DEBUG to send AT traffic to /tmp/radio-at.log" */
#define AT_DEBUG 0
#if AT_DEBUG
extern void AT_DUMP(const char* prefix, const char* buff, int len);
#else
#define AT_DUMP(prefix,buff,len) do{}while(0)
#endif
#define AT_ERROR_GENERIC -1
#define AT_ERROR_COMMAND_PENDING -2
#define AT_ERROR_CHANNEL_CLOSED -3
#define AT_ERROR_TIMEOUT -4
#define AT_ERROR_INVALID_THREAD -5 /* AT commands may not be issued from
reader thread (or unsolicited response
callback */
#define AT_ERROR_INVALID_RESPONSE -6 /* eg an at_send_command_singleline that
did not get back an intermediate
response */
typedef enum {
NO_RESULT, /* no intermediate response expected */
NUMERIC, /* a single intermediate response starting with a 0-9 */
SINGLELINE, /* a single intermediate response starting with a prefix */
MULTILINE /* multiple line intermediate response
starting with a prefix */
} ATCommandType;
/** a singly-lined list of intermediate responses */
typedef struct ATLine {
struct ATLine *p_next;
char *line;
} ATLine;
/** Free this with at_response_free() */
typedef struct {
int success; /* true if final response indicates
success (eg "OK") */
char *finalResponse; /* eg OK, ERROR */
ATLine *p_intermediates; /* any intermediate responses */
} ATResponse;
/**
* a user-provided unsolicited response handler function
* this will be called from the reader thread, so do not block
* "s" is the line, and "sms_pdu" is either NULL or the PDU response
* for multi-line TS 27.005 SMS PDU responses (eg +CMT:)
*/
typedef void (*ATUnsolHandler)(const char *s, const char *sms_pdu);
int at_open(int fd, ATUnsolHandler h, int proxy);
void at_close();
/* This callback is invoked on the command thread.
You should reset or handshake here to avoid getting out of sync */
void at_set_on_timeout(void (*onTimeout)(void));
/* This callback is invoked on the reader thread (like ATUnsolHandler)
when the input stream closes before you call at_close
(not when you call at_close())
You should still call at_close()
It may also be invoked immediately from the current thread if the read
channel is already closed */
void at_set_on_reader_closed(void (*onClose)(void));
int at_send_command_singleline (const char *command,
const char *responsePrefix,
ATResponse **pp_outResponse);
int at_send_command_numeric (const char *command,
ATResponse **pp_outResponse);
int at_send_command_multiline (const char *command,
const char *responsePrefix,
ATResponse **pp_outResponse);
int at_send_command_raw (const char *command,
const char *raw_data, unsigned int raw_len,
const char *responsePrefix,
ATResponse **pp_outResponse);
int at_handshake();
int at_send_command (const char *command, ATResponse **pp_outResponse);
int at_send_command_sms (const char *command, const char *pdu,
const char *responsePrefix,
ATResponse **pp_outResponse);
void at_response_free(ATResponse *p_response);
int strStartsWith(const char *line, const char *prefix);
typedef enum {
CME_ERROR_NON_CME = -1,
CME_SUCCESS = 0,
CME_OPERATION_NOT_ALLOWED = 3,
CME_OPERATION_NOT_SUPPORTED = 4,
CME_PH_SIM_PIN= 5,
CME_PH_FSIM_PIN = 6,
CME_PH_FSIM_PUK = 7,
CME_SIM_NOT_INSERTED =10,
CME_SIM_PIN_REQUIRED = 11,
CME_SIM_PUK_REQUIRED = 12,
CME_FAILURE = 13,
CME_SIM_BUSY = 14,
CME_SIM_WRONG = 15,
CME_INCORRECT_PASSWORD = 16,
CME_SIM_PIN2_REQUIRED = 17,
CME_SIM_PUK2_REQUIRED = 18,
CME_MEMORY_FULL = 20,
CME_INVALID_INDEX = 21,
CME_NOT_FOUND = 22,
CME_MEMORY_FAILURE = 23,
CME_STRING_TO_LONG = 24,
CME_INVALID_CHAR = 25,
CME_DIALSTR_TO_LONG = 26,
CME_INVALID_DIALCHAR = 27,
} AT_CME_Error;
AT_CME_Error at_get_cme_error(const ATResponse *p_response);
#ifdef __cplusplus
}
#endif
#endif /*ATCHANNEL_H*/
-48
View File
@@ -1,48 +0,0 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.61])
AC_INIT([quectel-CM], [1.0], [xxx@xxx.xxx])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
AC_ARG_WITH(sanitized-headers,
AS_HELP_STRING([--with-sanitized-headers=DIR],
[Specify the location of the sanitized Linux headers]),
[CPPFLAGS="$CPPFLAGS -idirafter $withval"])
AC_ARG_WITH([qrtr],
AC_HELP_STRING([--with-qrtr],
[enable qrtr, building which use qrtr]))
if (test "x${with_qrtr}" = "xyes"); then
#AC_DEFINE(ENABLE_USEQTRT, 1, [Define if uses qrtr])
AC_CHECK_HEADERS([linux/qrtr.h linux/rmnet_data.h])
fi
AM_CONDITIONAL(USE_QRTR, test "x${with_qrtr}" = "xyes")
AC_ARG_WITH([msm-ipc],
AC_HELP_STRING([--with-msm-ipc],
[enable msm-ipc, building which use qrtr]))
if (test "x${with_msm_ipc}" = "xyes"); then
#AC_DEFINE(ENABLE_USEQTRT, 1, [Define if uses qrtr])
AC_CHECK_HEADERS([linux/msm_ipc.h linux/rmnet_data.h])
fi
AM_CONDITIONAL(USE_MSM_IPC, test "x${with_msm_ipc}" = "xyes")
# Checks for library functions.
# Does not strictly follow GNU Coding standards
AM_INIT_AUTOMAKE([foreign subdir-objects])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
-63
View File
@@ -1,63 +0,0 @@
#!/bin/sh
# Busybox udhcpc dispatcher script. Copyright (C) 2009 by Axel Beckert.
#
# Based on the busybox example scripts and the old udhcp source
# package default.* scripts.
RESOLV_CONF="/etc/resolv.conf"
case $1 in
bound|renew)
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
[ -n "$subnet" ] && NETMASK="netmask $subnet"
/sbin/ifconfig $interface $ip $BROADCAST $NETMASK
if [ -n "$router" ]; then
echo "$0: Resetting default routes"
while /sbin/route del default gw 0.0.0.0 dev $interface; do :; done
metric=0
for i in $router; do
/sbin/route add default gw $i dev $interface metric $metric
metric=$(($metric + 1))
done
fi
# Update resolver configuration file
R=""
[ -n "$domain" ] && R="domain $domain
"
for i in $dns; do
echo "$0: Adding DNS $i"
R="${R}nameserver $i
"
done
if [ -x /sbin/resolvconf ]; then
echo -n "$R" | resolvconf -a "${interface}.udhcpc"
else
echo -n "$R" > "$RESOLV_CONF"
fi
;;
deconfig)
if [ -x /sbin/resolvconf ]; then
resolvconf -d "${interface}.udhcpc"
fi
/sbin/ifconfig $interface 0.0.0.0
;;
leasefail)
echo "$0: Lease failed: $message"
;;
nak)
echo "$0: Received a NAK: $message"
;;
*)
echo "$0: Unknown udhcpc command: $1";
exit 1;
;;
esac
-61
View File
@@ -1,61 +0,0 @@
#!/bin/sh
# Busybox udhcpc dispatcher script. Copyright (C) 2009 by Axel Beckert.
#
# Based on the busybox example scripts and the old udhcp source
# package default.* scripts.
RESOLV_CONF="/etc/resolv.conf"
IPCMD=`which ip`
case $1 in
bound|renew)
$IPCMD address add broadcast $broadcast $ip/$subnet dev $interface
if [ -n "$router" ]; then
echo "$0: Resetting default routes"
while $IPCMD route del default dev $interface; do :; done
metric=0
for i in $router; do
$IPCMD route add default dev $interface via $router metric $metric
metric=$(($metric + 1))
done
fi
# Update resolver configuration file
R=""
[ -n "$domain" ] && R="domain $domain
"
for i in $dns; do
echo "$0: Adding DNS $i"
R="${R}nameserver $i
"
done
if [ -x /sbin/resolvconf ]; then
echo -n "$R" | resolvconf -a "${interface}.udhcpc"
else
echo -n "$R" > "$RESOLV_CONF"
fi
;;
deconfig)
if [ -x /sbin/resolvconf ]; then
resolvconf -d "${interface}.udhcpc"
fi
$IPCMD address flush dev $interface
;;
leasefail)
echo "$0: Lease failed: $message"
;;
nak)
echo "$0: Received a NAK: $message"
;;
*)
echo "$0: Unknown udhcpc command: $1";
exit 1;
;;
esac
-756
View File
@@ -1,756 +0,0 @@
/*
Copyright 2025 Quectel Wireless Solutions Co.,Ltd
Quectel hereby grants customers of Quectel a license to use, modify,
distribute and publish the Software in binary form provided that
customers shall have no right to reverse engineer, reverse assemble,
decompile or reduce to source code form any portion of the Software.
Under no circumstances may customers modify, demonstrate, use, deliver
or disclose any portion of the Software in source code form.
*/
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <strings.h>
#include <stdlib.h>
#include <limits.h>
#include <linux/usbdevice_fs.h>
#include <linux/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <time.h>
#include <pthread.h>
#include "QMIThread.h"
#include "ethtool-copy.h"
#define USB_CLASS_VENDOR_SPEC 0xff
#define USB_CLASS_COMM 2
#define USB_CDC_SUBCLASS_ACM 0x02
#define USB_CDC_SUBCLASS_ETHERNET 0x06
#define USB_CDC_SUBCLASS_NCM 0x0d
#define USB_CDC_SUBCLASS_MBIM 0x0e
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
#define CM_MAX_PATHLEN 256
#define CM_INVALID_VAL (~((int)0))
static int RDNIS_MODEL = 0;
/* get first line from file 'fname'
* And convert the content into a hex number, then return this number */
static int file_get_value(const char *fname, int base)
{
FILE *fp = NULL;
long num;
char buff[32 + 1] = {'\0'};
char *endptr = NULL;
fp = fopen(fname, "r");
if (!fp) goto error;
if (fgets(buff, sizeof(buff), fp) == NULL)
goto error;
fclose(fp);
num = (int)strtol(buff, &endptr, base);
if (errno == ERANGE && (num == LONG_MAX || num == LONG_MIN))
goto error;
/* if there is no digit in buff */
if (endptr == buff)
goto error;
if (debug_qmi)
dbg_time("(%s) = %lx", fname, num);
return (int)num;
error:
if (fp) fclose(fp);
return CM_INVALID_VAL;
}
/*
* This function will search the directory 'dirname' and return the first child.
* '.' and '..' is ignored by default
*/
static int dir_get_child(const char *dirname, char *buff, unsigned bufsize, const char *prefix)
{
struct dirent *entptr = NULL;
DIR *dirptr;
buff[0] = 0;
dirptr = opendir(dirname);
if (!dirptr)
return -1;
while ((entptr = readdir(dirptr))) {
if (entptr->d_name[0] == '.')
continue;
if (prefix && strlen(prefix) && strncmp(entptr->d_name, prefix, strlen(prefix)))
continue;
snprintf(buff, bufsize, "%.31s", entptr->d_name);
break;
}
closedir(dirptr);
return 0;
}
static int conf_get_val(const char *fname, const char *key)
{
char buff[128] = {'\0'};
FILE *fp = fopen(fname, "r");
if (!fp)
return CM_INVALID_VAL;
while (fgets(buff, sizeof(buff)-1, fp)) {
char prefix[128] = {'\0'};
char tail[128] = {'\0'};
/* To eliminate cppcheck warnning: Assume string length is no more than 15 */
sscanf(buff, "%15[^=]=%15s", prefix, tail);
if (!strncasecmp(prefix, key, strlen(key))) {
fclose(fp);
return atoi(tail);
}
}
fclose(fp);
return CM_INVALID_VAL;
}
static void query_usb_device_info(char *path, struct usb_device_info *p) {
size_t offset = strlen(path);
memset(p, 0, sizeof(*p));
path[offset] = '\0';
strcat(path, "/idVendor");
p->idVendor = file_get_value(path, 16);
if (p->idVendor == CM_INVALID_VAL)
return;
path[offset] = '\0';
strcat(path, "/idProduct");
p->idProduct = file_get_value(path, 16);
path[offset] = '\0';
strcat(path, "/busnum");
p->busnum = file_get_value(path, 10);
path[offset] = '\0';
strcat(path, "/devnum");
p->devnum = file_get_value(path, 10);
path[offset] = '\0';
strcat(path, "/bNumInterfaces");
p->bNumInterfaces = file_get_value(path, 10);
path[offset] = '\0';
}
static void query_usb_interface_info(char *path, struct usb_interface_info *p) {
char driver[128];
size_t offset = strlen(path);
int n;
memset(p, 0, sizeof(*p));
path[offset] = '\0';
strcat(path, "/bNumEndpoints");
p->bInterfaceClass = file_get_value(path, 16);
path[offset] = '\0';
strcat(path, "/bInterfaceClass");
p->bInterfaceClass = file_get_value(path, 16);
path[offset] = '\0';
strcat(path, "/bInterfaceSubClass");
p->bInterfaceSubClass = file_get_value(path, 16);
path[offset] = '\0';
strcat(path, "/bInterfaceProtocol");
p->bInterfaceProtocol = file_get_value(path, 16);
path[offset] = '\0';
strcat(path, "/driver");
n = readlink(path, driver, sizeof(driver));
if (n > 0) {
driver[n] = 0;
if (debug_qmi) dbg_time("driver -> %s", driver);
n = strlen(driver);
while (n > 0) {
if (driver[n] == '/')
break;
n--;
}
strncpy(p->driver, &driver[n+1], sizeof(p->driver) - 1);
}
path[offset] = '\0';
}
static int detect_path_cdc_wdm_or_qcqmi(char *path, char *devname, size_t bufsize)
{
size_t offset = strlen(path);
char tmp[32];
devname[0] = 0;
if (access(path, R_OK))
return -1;
path[offset] = '\0';
strcat(path, "/GobiQMI");
if (!access(path, R_OK))
goto step_1;
path[offset] = '\0';
strcat(path, "/usbmisc");
if (!access(path, R_OK))
goto step_1;
path[offset] = '\0';
strcat(path, "/usb");
if (!access(path, R_OK))
goto step_1;
return -1;
step_1:
/* get device(qcqmiX|cdc-wdmX) */
if (debug_qmi) dbg_time("%s", path);
dir_get_child(path, tmp, sizeof(tmp), NULL);
if (tmp[0] == '\0')
return -1;
/* There is a chance that, no device(qcqmiX|cdc-wdmX) is generated. We should warn user about that! */
snprintf(devname, bufsize, "/dev/%s", tmp);
if (access(devname, R_OK | F_OK) && errno == ENOENT)
{
int major, minor;
dbg_time("access %s failed, errno: %d (%s)", devname, errno, strerror(errno));
strcat(path, "/");
strcat(path, tmp);
strcat(path, "/uevent");
major = conf_get_val(path, "MAJOR");
minor = conf_get_val(path, "MINOR");
if(major == CM_INVALID_VAL || minor == CM_INVALID_VAL)
dbg_time("get major and minor failed");
else if (mknod(devname, S_IFCHR|0666, (((major & 0xfff) << 8) | (minor & 0xff) | ((minor & 0xfff00) << 12))))
dbg_time("please mknod %s c %d %d", devname, major, minor);
}
return 0;
}
/* To detect the device info of the modem.
* return:
* FALSE -> fail
* TRUE -> ok
*/
BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile) {
struct dirent* ent = NULL;
DIR *pDir;
const char *rootdir = "/sys/bus/usb/devices";
struct {
char path[255*2];
} *pl;
pl = (typeof(pl)) malloc(sizeof(*pl));
memset(pl, 0x00, sizeof(*pl));
pDir = opendir(rootdir);
if (!pDir) {
dbg_time("opendir %s failed: %s", rootdir, strerror(errno));
goto error;
}
while ((ent = readdir(pDir)) != NULL) {
char netcard[32+1] = {'\0'};
char devname[32+5] = {'\0'}; //+strlen("/dev/")
int netIntf;
int driver_type;
if (ent->d_name[0] == 'u')
continue;
snprintf(pl->path, sizeof(pl->path), "%s/%s", rootdir, ent->d_name);
query_usb_device_info(pl->path, &profile->usb_dev);
if (profile->usb_dev.idVendor == CM_INVALID_VAL)
continue;
if (profile->usb_dev.idVendor == 0x2c7c || profile->usb_dev.idVendor == 0x05c6) {
dbg_time("Find %s/%s idVendor=0x%x idProduct=0x%x, bus=0x%03x, dev=0x%03x",
rootdir, ent->d_name, profile->usb_dev.idVendor, profile->usb_dev.idProduct,
profile->usb_dev.busnum, profile->usb_dev.devnum);
}
/* get network interface */
/* NOTICE: there is a case that, bNumberInterface=6, but the net interface is 8 */
/* toolchain-mips_24kc_gcc-5.4.0_musl donot support GLOB_BRACE */
/* RG500U's MBIM is at inteface 0 */
for (netIntf = 0; netIntf < (profile->usb_dev.bNumInterfaces + 8); netIntf++) {
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d/net", rootdir, ent->d_name, netIntf);
dir_get_child(pl->path, netcard, sizeof(netcard), NULL);
if (netcard[0])
break;
}
if (netcard[0] == '\0') { //for centos 2.6.x
const char *n= "usb0";
const char *c = "qcqmi0";
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4/net:%s", rootdir, ent->d_name, n);
if (!access(pl->path, F_OK)) {
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4/GobiQMI:%s", rootdir, ent->d_name, c);
if (!access(pl->path, F_OK)) {
snprintf(qmichannel, bufsize, "/dev/%s", c);
snprintf(usbnet_adapter, bufsize, "%s", n);
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4", rootdir, ent->d_name);
query_usb_interface_info(pl->path, &profile->usb_intf);
break;
}
}
}
if (netcard[0] == '\0')
continue;
/* not '-i iface' */
if (usbnet_adapter[0] && strcmp(usbnet_adapter, netcard))
continue;
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d", rootdir, ent->d_name, netIntf);
query_usb_interface_info(pl->path, &profile->usb_intf);
driver_type = get_driver_type(profile);
if (driver_type == SOFTWARE_QMI || driver_type == SOFTWARE_MBIM) {
detect_path_cdc_wdm_or_qcqmi(pl->path, devname, sizeof(devname));
}
else if (driver_type == SOFTWARE_ECM_RNDIS_NCM)
{
int atIntf = -1;
if (profile->usb_dev.idVendor == 0x2c7c) { //Quectel
switch (profile->usb_dev.idProduct) { //EC200U
case 0x0901: //EC200U
case 0x0902: //EC200D
case 0x8101: //RG801H
atIntf = 2;
break;
case 0x0900: //RG500U
atIntf = 4;
break;
case 0x6026: //EC200T
case 0x6005: //EC200A
case 0x6002: //EC200S
case 0x6001: //EC100Y
atIntf = 3;
break;
case 0x6007: //EG915Q\EG800Q
if(RDNIS_MODEL == 1)
atIntf = 5;
else
atIntf = 3;
break;
default:
dbg_time("unknow at interface for USB idProduct:%04x\n", profile->usb_dev.idProduct);
break;
}
}
if (atIntf != -1) {
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d", rootdir, ent->d_name, atIntf);
dir_get_child(pl->path, devname, sizeof(devname), "tty");
if (devname[0] && !strcmp(devname, "tty")) {
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d/tty", rootdir, ent->d_name, atIntf);
dir_get_child(pl->path, devname, sizeof(devname), "tty");
}
}
}
if (netcard[0] && devname[0]) {
if (devname[0] == '/')
snprintf(qmichannel, bufsize, "%s", devname);
else
snprintf(qmichannel, bufsize, "/dev/%s", devname);
snprintf(usbnet_adapter, bufsize, "%s", netcard);
dbg_time("Auto find qmichannel = %s", qmichannel);
dbg_time("Auto find usbnet_adapter = %s", usbnet_adapter);
break;
}
}
closedir(pDir);
if (qmichannel[0] == '\0' || usbnet_adapter[0] == '\0') {
dbg_time("network interface '%s' or qmidev '%s' is not exist", usbnet_adapter, qmichannel);
goto error;
}
free(pl);
return TRUE;
error:
free(pl);
return FALSE;
}
int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile) {
struct dirent* ent = NULL;
DIR *pDir;
const char *rootdir_mhi[] = {"/sys/bus/mhi_q/devices", "/sys/bus/mhi/devices", NULL};
int i = 0;
char path[256];
int find = 0;
while (rootdir_mhi[i]) {
const char *rootdir = rootdir_mhi[i++];
pDir = opendir(rootdir);
if (!pDir) {
if (errno != ENOENT)
dbg_time("opendir %s failed: %s", rootdir, strerror(errno));
continue;
}
while ((ent = readdir(pDir)) != NULL) {
char netcard[32] = {'\0'};
char devname[32] = {'\0'};
int software_interface = SOFTWARE_QMI;
char *pNode = NULL;
pNode = strstr(ent->d_name, "_IP_HW0"); //0306_00.01.00_IP_HW0
if (!pNode)
continue;
snprintf(path, sizeof(path), "%s/%.32s/net", rootdir, ent->d_name);
dir_get_child(path, netcard, sizeof(netcard), NULL);
if (!netcard[0])
continue;
if (usbnet_adapter[0] && strcmp(netcard, usbnet_adapter)) //not '-i x'
continue;
if (!strcmp(rootdir, "/sys/bus/mhi/devices")) {
snprintf(path, sizeof(path), "%s/%.13s_IPCR", rootdir, ent->d_name); // 13 is sizeof(0306_00.01.00)
if (!access(path, F_OK)) {
/* we also need 'cat /dev/mhi_0306_00.01.00_pipe_14' to enable rmnet as like USB's DTR
or will get error 'requestSetEthMode QMUXResult = 0x1, QMUXError = 0x46' */
sprintf(usbnet_adapter, "%s", netcard);
sprintf(qmichannel, "qrtr-%d", 3); // 3 is sdx modem's node id
profile->software_interface = SOFTWARE_QRTR;
find = 1;
break;
}
continue;
}
snprintf(path, sizeof(path), "%s/%.13s_IPCR", rootdir, ent->d_name);
if (access(path, F_OK)) {
snprintf(path, sizeof(path), "%s/%.13s_QMI0", rootdir, ent->d_name);
if (access(path, F_OK)) {
snprintf(path, sizeof(path), "%s/%.13s_MBIM", rootdir, ent->d_name);
if (!access(path, F_OK))
software_interface = SOFTWARE_MBIM;
}
}
if (access(path, F_OK))
continue;
strncat(path, "/mhi_uci_q", sizeof(path)-1);
dir_get_child(path, devname, sizeof(devname), NULL);
if (!devname[0])
continue;
sprintf(usbnet_adapter, "%s", netcard);
sprintf(qmichannel, "/dev/%s", devname);
profile->software_interface = software_interface;
find = 1;
break;
}
closedir(pDir);
}
return find;
}
int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile) {
if (!access("/sys/class/net/sipa_dummy0", F_OK)) {
strcpy(usbnet_adapter, "sipa_dummy0");
snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "%s%d", "pcie", profile->pdp - 1);
}
else {
dbg_time("atdevice_detect failed");
goto error;
}
if (!access("/dev/stty_nr31", F_OK)) {
strcpy(atchannel, "/dev/stty_nr31");
profile->software_interface = SOFTWARE_ECM_RNDIS_NCM;
}
else {
goto error;
}
return 1;
error:
return 0;
}
int get_driver_type(PROFILE_T *profile)
{
/* QMI_WWAN */
if (profile->usb_intf.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
return SOFTWARE_QMI;
}
else if (profile->usb_intf.bInterfaceClass == USB_CLASS_COMM) {
switch (profile->usb_intf.bInterfaceSubClass) {
case USB_CDC_SUBCLASS_MBIM:
return SOFTWARE_MBIM;
break;
case USB_CDC_SUBCLASS_ETHERNET:
case USB_CDC_SUBCLASS_NCM:
return SOFTWARE_ECM_RNDIS_NCM;
break;
default:
break;
}
}
else if (profile->usb_intf.bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER) {
if (profile->usb_intf.bInterfaceSubClass == 1 && profile->usb_intf.bInterfaceProtocol == 3) {
RDNIS_MODEL = 1;//Some modules in RNDIS mode the usb port definition is different, adding a marker bit to distinguish.
return SOFTWARE_ECM_RNDIS_NCM;
}
}
dbg_time("%s unknow bInterfaceClass=%d, bInterfaceSubClass=%d", __func__,
profile->usb_intf.bInterfaceClass, profile->usb_intf.bInterfaceSubClass);
return DRV_INVALID;
}
struct usbfs_getdriver
{
unsigned int interface;
char driver[255 + 1];
};
struct usbfs_ioctl
{
int ifno; /* interface 0..N ; negative numbers reserved */
int ioctl_code; /* MUST encode size + direction of data so the
* macros in <asm/ioctl.h> give correct values */
void *data; /* param buffer (in, or out) */
};
#define IOCTL_USBFS_DISCONNECT _IO('U', 22)
#define IOCTL_USBFS_CONNECT _IO('U', 23)
int usbfs_is_kernel_driver_alive(int fd, int ifnum)
{
struct usbfs_getdriver getdrv;
getdrv.interface = ifnum;
if (ioctl(fd, USBDEVFS_GETDRIVER, &getdrv) < 0) {
dbg_time("%s ioctl USBDEVFS_GETDRIVER failed, kernel driver may be inactive", __func__);
return 0;
}
dbg_time("%s find interface %d has match the driver %s", __func__, ifnum, getdrv.driver);
return 1;
}
void usbfs_detach_kernel_driver(int fd, int ifnum)
{
struct usbfs_ioctl operate;
operate.data = NULL;
operate.ifno = ifnum;
operate.ioctl_code = IOCTL_USBFS_DISCONNECT;
if (ioctl(fd, USBDEVFS_IOCTL, &operate) < 0) {
dbg_time("%s detach kernel driver failed", __func__);
} else {
dbg_time("%s detach kernel driver success", __func__);
}
}
void usbfs_attach_kernel_driver(int fd, int ifnum)
{
struct usbfs_ioctl operate;
operate.data = NULL;
operate.ifno = ifnum;
operate.ioctl_code = IOCTL_USBFS_CONNECT;
if (ioctl(fd, USBDEVFS_IOCTL, &operate) < 0) {
dbg_time("%s detach kernel driver failed", __func__);
} else {
dbg_time("%s detach kernel driver success", __func__);
}
}
int reattach_driver(PROFILE_T *profile)
{
int ifnum = 4;
int fd;
char devpath[128] = {'\0'};
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", profile->usb_dev.busnum, profile->usb_dev.devnum);
fd = open(devpath, O_RDWR | O_NOCTTY);
if (fd < 0)
{
dbg_time("%s fail to open %s", __func__, devpath);
return -1;
}
usbfs_detach_kernel_driver(fd, ifnum);
usbfs_attach_kernel_driver(fd, ifnum);
close(fd);
return 0;
}
#define SIOCETHTOOL 0x8946
int ql_get_netcard_driver_info(const char *devname)
{
int fd = -1;
struct ethtool_drvinfo drvinfo;
struct ifreq ifr; /* ifreq suitable for ethtool ioctl */
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, devname);
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
dbg_time("Cannot get control socket: errno(%d)(%s)", errno, strerror(errno));
return -1;
}
drvinfo.cmd = ETHTOOL_GDRVINFO;
ifr.ifr_data = (void *)&drvinfo;
if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
dbg_time("ioctl() error: errno(%d)(%s)", errno, strerror(errno));
close(fd);
return -1;
}
dbg_time("netcard driver = %s, driver version = %s", drvinfo.driver, drvinfo.version);
close(fd);
return 0;
}
int ql_get_netcard_carrier_state(const char *devname)
{
int fd = -1;
struct ethtool_value edata;
struct ifreq ifr; /* ifreq suitable for ethtool ioctl */
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, devname);
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
dbg_time("Cannot get control socket: errno(%d)(%s)", errno, strerror(errno));
return -1;
}
edata.cmd = ETHTOOL_GLINK;
edata.data = 0;
ifr.ifr_data = (void *)&edata;
if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
dbg_time("ioctl('%s') error: errno(%d)(%s)", devname, errno, strerror(errno));
return -1;
}
if (!edata.data)
dbg_time("netcard carrier = %d", edata.data);
close(fd);
return edata.data;
}
static void *catch_log(void *arg)
{
PROFILE_T *profile = (PROFILE_T *)arg;
int nreads = 0;
char tbuff[256+32];
char filter[32];
size_t tsize = strlen(get_time()) + 1;
snprintf(filter, sizeof(filter), ":%d:%03d:", profile->usb_dev.busnum, profile->usb_dev.devnum);
while(1) {
nreads = read(profile->usbmon_fd, tbuff + tsize, sizeof(tbuff) - tsize - 1);
if (nreads <= 0) {
if (nreads == -1 && errno == EINTR)
continue;
break;
}
tbuff[tsize+nreads] = '\0'; // printf("%s", buff);
if (!strstr(tbuff+tsize, filter))
continue;
snprintf(tbuff, sizeof(tbuff), "%s", get_time());
tbuff[tsize-1] = ' ';
fwrite(tbuff, strlen(tbuff), 1, profile->usbmon_logfile_fp);
}
return NULL;
}
int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path)
{
char usbmon_path[256];
pthread_t pt;
pthread_attr_t attr;
if (access("/sys/module/usbmon", F_OK)) {
dbg_time("usbmon is not load, please execute \"modprobe usbmon\" or \"insmod usbmon.ko\"");
return -1;
}
if (access("/sys/kernel/debug/usb", F_OK)) {
dbg_time("debugfs is not mount, please execute \"mount -t debugfs none_debugs /sys/kernel/debug\"");
return -1;
}
snprintf(usbmon_path, sizeof(usbmon_path), "/sys/kernel/debug/usb/usbmon/%du", profile->usb_dev.busnum);
profile->usbmon_fd = open(usbmon_path, O_RDONLY);
if (profile->usbmon_fd < 0) {
dbg_time("open %s error(%d) (%s)", usbmon_path, errno, strerror(errno));
return -1;
}
snprintf(usbmon_path, sizeof(usbmon_path), "cat /sys/kernel/debug/usb/devices >> %s", log_path);
if (system(usbmon_path) == -1) {};
profile->usbmon_logfile_fp = fopen(log_path, "wb");
if (!profile->usbmon_logfile_fp) {
dbg_time("open %s error(%d) (%s)", log_path, errno, strerror(errno));
close(profile->usbmon_fd);
profile->usbmon_fd = -1;
return -1;
}
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&pt, &attr, catch_log, (void *)profile);
return 0;
}
void ql_stop_usbmon_log(PROFILE_T *profile) {
if (profile->usbmon_fd > 0)
close(profile->usbmon_fd);
if (profile->usbmon_logfile_fp)
fclose(profile->usbmon_logfile_fp);
}
File diff suppressed because it is too large. Load diff
-71
View File
@@ -1,71 +0,0 @@
root@ZhuoTK:/# dmesg
[ 788.920000] usb 1-1.3: new high-speed USB device number 4 using ehci-platform
[ 789.160000] cdc_mbim 1-1.3:1.4: cdc-wdm0: USB WDM device
[ 789.170000] cdc_mbim 1-1.3:1.4 wwan0: register 'cdc_mbim' at usb-101c0000.ehci-1.3, CDC MBIM, a2:58:dc:4d:dd:ca
root@ZhuoTK:/# quectel-CM -s cmnet &
[04-13_05:24:38:767] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_05:24:38:769] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004
[04-13_05:24:38:771] Auto find qmichannel = /dev/cdc-wdm0
[04-13_05:24:38:771] Auto find usbnet_adapter = wwan0
[04-13_05:24:38:771] netcard driver = cdc_mbim, driver version = 22-Aug-2005
[04-13_05:24:38:771] Modem works in MBIM mode
[04-13_05:24:38:779] cdc_wdm_fd = 7
[04-13_05:24:38:779] mbim_open_device()
[04-13_05:24:39:624] mbim_device_caps_query()
[04-13_05:24:39:656] DeviceId: 866758045439136
[04-13_05:24:39:656] FirmwareInfo: EC25EFAR06A11M4G
[04-13_05:24:39:656] HardwareInfo: QUECTEL Mobile Broadband Modul
[04-13_05:24:39:657] mbim_device_services_query()
[04-13_05:24:39:688] mbim_set_radio_state( 1 )
[04-13_05:24:39:721] HwRadioState: 1, SwRadioState: 1
[04-13_05:24:39:721] mbim_subscriber_status_query()
[04-13_05:24:39:784] SubscriberId: 460028563800461
[04-13_05:24:39:784] SimIccId: 89860015120716380461
[04-13_05:24:39:785] SubscriberReadyState NotInitialized -> Initialized
[04-13_05:24:39:785] mbim_register_state_query()
[04-13_05:24:39:816] RegisterState Unknown -> Home
[04-13_05:24:39:816] mbim_packet_service_query()
[04-13_05:24:39:848] PacketServiceState Unknown -> Attached
[04-13_05:24:39:848] mbim_query_connect(sessionID=0)
[04-13_05:24:39:880] ActivationState Unknown -> Deactivated
[04-13_05:24:39:881] ifconfig wwan0 0.0.0.0
[04-13_05:24:39:899] ifconfig wwan0 down
[04-13_05:24:39:913] mbim_set_connect(onoff=1, sessionID=0)
[04-13_05:24:39:976] ActivationState Deactivated -> Activated
[04-13_05:24:39:977] mbim_ip_config(sessionID=0)
[04-13_05:24:40:008] < SessionId = 0
[04-13_05:24:40:008] < IPv4ConfigurationAvailable = 0xf
[04-13_05:24:40:008] < IPv6ConfigurationAvailable = 0x0
[04-13_05:24:40:008] < IPv4AddressCount = 0x1
[04-13_05:24:40:008] < IPv4AddressOffset = 0x3c
[04-13_05:24:40:009] < IPv6AddressCount = 0x0
[04-13_05:24:40:009] < IPv6AddressOffset = 0x0
[04-13_05:24:40:009] < IPv4 = 10.129.90.29/30
[04-13_05:24:40:009] < gw = 10.129.90.30
[04-13_05:24:40:009] < dns1 = 211.138.180.2
[04-13_05:24:40:009 < dns2 = 211.138.180.3
[04-13_05:24:40:009] < ipv4 mtu = 1500
[04-13_05:24:40:041] ifconfig wwan0 up
[04-13_05:24:40:063] ip -4 address flush dev wwan0
[04-13_05:24:40:073] ip -4 address add 10.129.90.29/30 dev wwan0
[04-13_05:24:40:084] ip -4 route add default via 10.129.90.30 dev wwan0
root@ZhuoTK:/# ifconfig wwan0
wwan0 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA
inet addr:10.129.90.29 Bcast:0.0.0.0 Mask:255.255.255.252
inet6 addr: fe80::a058:dcff:fe4d:ddca/64 Scope:Link
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:380 (380.0 B)
root@ZhuoTK:/# ip ro show
default via 10.129.90.30 dev wwan0
10.129.90.28/30 dev wwan0 proto kernel scope link src 10.129.90.29
192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251
root@ZhuoTK:/# ping www.qq.com
PING www.qq.com (183.194.238.117): 56 data bytes
64 bytes from 183.194.238.117: seq=0 ttl=53 time=58.674 ms
-168
View File
@@ -1,168 +0,0 @@
root@ZhuoTK:/# dmesg
[ 788.920000] usb 1-1.3: new high-speed USB device number 4 using ehci-platform
[ 789.160000] cdc_mbim 1-1.3:1.4: cdc-wdm0: USB WDM device
[ 789.170000] cdc_mbim 1-1.3:1.4 wwan0: register 'cdc_mbim' at usb-101c0000.ehci-1.3, CDC MBIM, a2:58:dc:4d:dd:ca
root@ZhuoTK:/# ip link add link wwan0 name wwan0.1 type vlan id 1
root@ZhuoTK:/# ip link add link wwan0 name wwan0.2 type vlan id 2
root@ZhuoTK:/# ifconfig wwan0.1
wwan0.1 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA
BROADCAST NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@ZhuoTK:/# ifconfig wwan0.2
wwan0.2 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA
BROADCAST NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@ZhuoTK:/# quectel-mbim-proxy &
root@ZhuoTK:/# [04-13_07:04:27:543] mbim_dev_fd=3
[04-13_07:04:27:543] mbim_send_open_msg()
[04-13_07:04:28:321] receive MBIM_OPEN_DONE, status=0
[04-13_07:04:28:321] mbim_server_fd=4
root@ZhuoTK:/# quectel-CM -n 1 -s cmnet &
[04-13_07:04:34:256] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_07:04:34:259] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004
[04-13_07:04:34:260] Auto find qmichannel = /dev/cdc-wdm0
[04-13_07:04:34:260] Auto find usbnet_adapter = wwan0
[04-13_07:04:34:260] netcard driver = cdc_mbim, driver version = 22-Aug-2005
[04-13_07:04:34:261] mbim_qmap_mode = 4, vlan_id = 0x01, qmap_netcard = wwan0.1
[04-13_07:04:34:261] Modem works in MBIM mode
[04-13_07:04:34:261] handle_client_connect client_fd=5, client_idx=1
[04-13_07:04:34:262] connect to quectel-mbim-proxy sockfd = 7
[04-13_07:04:34:262] cdc_wdm_fd = 7
[04-13_07:04:34:262] mbim_open_device()
[04-13_07:04:35:106] mbim_device_caps_query()
[04-13_07:04:35:139] DeviceId: 866758045439136
[04-13_07:04:35:139] FirmwareInfo: EC25EFAR06A11M4G
[04-13_07:04:35:139] HardwareInfo: QUECTEL Mobile Broadband Modul
[04-13_07:04:35:139] mbim_device_services_query()
[04-13_07:04:35:170] mbim_set_radio_state( 1 )
[04-13_07:04:35:202] HwRadioState: 1, SwRadioState: 1
[04-13_07:04:35:202] mbim_subscriber_status_query()
[04-13_07:04:35:267] SubscriberId: 460028563800461
[04-13_07:04:35:267] SimIccId: 89860015120716380461
[04-13_07:04:35:267] SubscriberReadyState NotInitialized -> Initialized
[04-13_07:04:35:267] mbim_register_state_query()
[04-13_07:04:35:297] RegisterState Unknown -> Home
[04-13_07:04:35:298] mbim_packet_service_query()
[04-13_07:04:35:329] PacketServiceState Unknown -> Attached
[04-13_07:04:35:330] mbim_query_connect(sessionID=1)
[04-13_07:04:35:361] ActivationState Unknown -> Deactivated
[04-13_07:04:35:362] ifconfig wwan0.1 0.0.0.0
[04-13_07:04:35:373] ifconfig wwan0.1 down
[04-13_07:04:35:383] mbim_set_connect(onoff=1, sessionID=1)
[04-13_07:04:35:426] ActivationState Deactivated -> Activated
[04-13_07:04:35:426] mbim_ip_config(sessionID=1)
[04-13_07:04:35:457] < SessionId = 1
[04-13_07:04:35:457] < IPv4ConfigurationAvailable = 0xf
[04-13_07:04:35:457] < IPv6ConfigurationAvailable = 0x0
[04-13_07:04:35:457] < IPv4AddressCount = 0x1
[04-13_07:04:35:458] < IPv4AddressOffset = 0x3c
[04-13_07:04:35:458] < IPv6AddressCount = 0x0
[04-13_07:04:35:458] < IPv6AddressOffset = 0x0
[04-13_07:04:35:458] < IPv4 = 10.129.90.29/30
[04-13_07:04:35:458] < gw = 10.129.90.30
[04-13_07:04:35:458] < dns1 = 211.138.180.2
[04-13_07:04:35:458] < dns2 = 211.138.180.3
[04-13_07:04:35:458] < ipv4 mtu = 1500
[04-13_07:04:35:489] ifconfig wwan0 up
[04-13_07:04:35:509] ifconfig wwan0.1 down
[04-13_07:04:35:522] ifconfig wwan0.1 up
[04-13_07:04:35:535] ip -4 address flush dev wwan0.1
[04-13_07:04:35:545] ip -4 address add 10.129.90.29/30 dev wwan0.1
[04-13_07:04:35:556] ip -4 route add default via 10.129.90.30 dev wwan0.1
root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet &
[04-13_07:04:45:150] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_07:04:45:152] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004
[04-13_07:04:45:154] Auto find qmichannel = /dev/cdc-wdm0
[04-13_07:04:45:154] Auto find usbnet_adapter = wwan0
[04-13_07:04:45:154] netcard driver = cdc_mbim, driver version = 22-Aug-2005
[04-13_07:04:45:155] mbim_qmap_mode = 4, vlan_id = 0x02, qmap_netcard = wwan0.2
[04-13_07:04:45:155] Modem works in MBIM mode
[04-13_07:04:45:155] handle_client_connect client_fd=6, client_idx=2
[04-13_07:04:45:156] connect to quectel-mbim-proxy sockfd = 7
[04-13_07:04:45:156] cdc_wdm_fd = 7
[04-13_07:04:45:156] mbim_open_device()
[04-13_07:04:46:025] mbim_device_caps_query()
[04-13_07:04:46:056] DeviceId: 866758045439136
[04-13_07:04:46:056] FirmwareInfo: EC25EFAR06A11M4G
[04-13_07:04:46:056] HardwareInfo: QUECTEL Mobile Broadband Modul
[04-13_07:04:46:056] mbim_device_services_query()
[04-13_07:04:46:088] mbim_set_radio_state( 1 )
[04-13_07:04:46:119] HwRadioState: 1, SwRadioState: 1
[04-13_07:04:46:119] mbim_subscriber_status_query()
[04-13_07:04:46:183] SubscriberId: 460028563800461
[04-13_07:04:46:184] SimIccId: 89860015120716380461
[04-13_07:04:46:184] SubscriberReadyState NotInitialized -> Initialized
[04-13_07:04:46:184] mbim_register_state_query()
[04-13_07:04:46:216] RegisterState Unknown -> Home
[04-13_07:04:46:216] mbim_packet_service_query()
[04-13_07:04:46:248] PacketServiceState Unknown -> Attached
[04-13_07:04:46:248] mbim_query_connect(sessionID=2)
[04-13_07:04:46:280] ActivationState Unknown -> Deactivated
[04-13_07:04:46:280] ifconfig wwan0.2 0.0.0.0
[04-13_07:04:46:291] ifconfig wwan0.2 down
[04-13_07:04:46:304] mbim_set_connect(onoff=1, sessionID=2)
[04-13_07:04:46:504] ActivationState Deactivated -> Activated
[04-13_07:04:46:505] mbim_ip_config(sessionID=2)
[04-13_07:04:46:537] < SessionId = 2
[04-13_07:04:46:537] < IPv4ConfigurationAvailable = 0xf
[04-13_07:04:46:537] < IPv6ConfigurationAvailable = 0x0
[04-13_07:04:46:538] < IPv4AddressCount = 0x1
[04-13_07:04:46:538] < IPv4AddressOffset = 0x3c
[04-13_07:04:46:538] < IPv6AddressCount = 0x0
[04-13_07:04:46:538] < IPv6AddressOffset = 0x0
[04-13_07:04:46:538] < IPv4 = 10.129.37.205/30
[04-13_07:04:46:538] < gw = 10.129.37.206
[04-13_07:04:46:538] < dns1 = 211.138.180.2
[04-13_07:04:46:538] < dns2 = 211.138.180.3
[04-13_07:04:46:538] < ipv4 mtu = 1500
[04-13_07:04:46:569] ifconfig wwan0 up
[04-13_07:04:46:579] ifconfig wwan0.2 up
[04-13_07:04:46:592] ip -4 address flush dev wwan0.2
[04-13_07:04:46:602] ip -4 address add 10.129.37.205/30 dev wwan0.2
[04-13_07:04:46:613] ip -4 route add default via 10.129.37.206 dev wwan0.2
root@ZhuoTK:/# ifconfig wwan0.1
wwan0.1 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA
inet addr:10.129.90.29 Bcast:0.0.0.0 Mask:255.255.255.252
inet6 addr: fe80::a058:dcff:fe4d:ddca/64 Scope:Link
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:304 (304.0 B) TX bytes:1170 (1.1 KiB)
root@ZhuoTK:/# ifconfig wwan0.2
wwan0.2 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA
inet addr:10.129.37.205 Bcast:0.0.0.0 Mask:255.255.255.252
inet6 addr: fe80::a058:dcff:fe4d:ddca/64 Scope:Link
UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:720 (720.0 B)
root@ZhuoTK:/# ip ro del 8.8.8.8/32
RTNETLINK answers: No such process
root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev wwan0.1
root@ZhuoTK:/# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=52 time=98.584 ms
root@ZhuoTK:/# ip ro del 8.8.8.8/32
root@ZhuoTK:/# ip ro del 8.8.8.8/32
RTNETLINK answers: No such process
root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev wwan0.2
root@ZhuoTK:/# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=111 time=101.770 ms
-129
View File
@@ -1,129 +0,0 @@
# ./quectel-CM -s cmnet &
[04-21_17:35:14:362] Quectel_QConnectManager_Linux_V1.6.0.26
[04-21_17:35:14:363] Find /sys/bus/usb/devices/2-4 idVendor=0x2c7c idProduct=0x8101, bus=0x002, dev=0x016
[04-21_17:35:14:363] Auto find qmichannel = /dev/ttyUSB0
[04-21_17:35:14:363] Auto find usbnet_adapter = usb0
[04-21_17:35:14:363] netcard driver = cdc_ncm, driver version = 22-Aug-2005
[04-21_17:35:14:363] Modem works in ECM_RNDIS_NCM mode
[04-21_17:35:14:371] atc_fd = 7
[04-21_17:35:14:371] AT> ATE0Q0V1
[04-21_17:35:14:372] AT< RDATE0Q0V1
[04-21_17:35:14:372] AT< COMMAND NOT SUPPORT
[04-21_17:35:15:373] AT> AT+QCFG="usbnet"
[04-21_17:35:15:373] AT< +QCFG: "usbnet",5
[04-21_17:35:15:373] AT< OK
[04-21_17:35:15:373] AT> AT+QNETDEVCTL=?
[04-21_17:35:15:374] AT< +QNETDEVCTL: (1-11),(0,1),(0,1)
[04-21_17:35:15:374] AT< OK
[04-21_17:35:15:374] AT> AT+CGREG=2
[04-21_17:35:15:376] AT< OK
[04-21_17:35:15:376] AT> AT+CEREG=2
[04-21_17:35:15:381] AT< OK
[04-21_17:35:15:381] AT> AT+C5GREG=2
[04-21_17:35:15:384] AT< OK
[04-21_17:35:15:384] AT> AT+QNETDEVSTATUS=?
[04-21_17:35:15:385] AT< +QNETDEVSTATUS: (1-11)
[04-21_17:35:15:385] AT< OK
[04-21_17:35:15:385] AT> AT+QCFG="NAT"
[04-21_17:35:15:385] AT< +QCFG: "nat",0
[04-21_17:35:15:385] AT< OK
[04-21_17:35:15:385] AT> AT+CGMR
[04-21_17:35:15:386] AT< RG801HEAAAR03A01M8G
[04-21_17:35:15:386] AT< OK
[04-21_17:35:15:386] AT> AT+CPIN?
[04-21_17:35:15:388] AT< +CPIN: READY
[04-21_17:35:15:388] AT< OK
[04-21_17:35:15:389] AT> AT+QCCID
[04-21_17:35:15:393] AT< +QCCID: 89860015120716380461
[04-21_17:35:15:393] AT< OK
[04-21_17:35:15:393] requestGetICCID 89860015120716380461
[04-21_17:35:15:393] AT> AT+CIMI
[04-21_17:35:15:409] AT< 460028563800461
[04-21_17:35:15:409] AT< OK
[04-21_17:35:15:409] requestGetIMSI 460028563800461
[04-21_17:35:15:409] AT> AT+QICSGP=1
[04-21_17:35:15:411] AT< +QICSGP: 1,1,"cment","","",0,,0,
[04-21_17:35:15:411] AT< OK
[04-21_17:35:15:411] AT> AT+QICSGP=1
[04-21_17:35:15:415] AT< +QICSGP: 1,1,"cment","","",0,,0,
[04-21_17:35:15:415] AT< OK
[04-21_17:35:15:415] AT> AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?
[04-21_17:35:15:421] AT< +COPS: 0,0,"CHINA MOBILE",12
[04-21_17:35:15:421] AT< +COPS: 0,1,"CMCC",12
[04-21_17:35:15:421] AT< +COPS: 0,2,"46000",12
[04-21_17:35:15:421] AT< OK
[04-21_17:35:15:421] AT> AT+C5GREG?
[04-21_17:35:15:424] AT< +C5GREG: 2,1,"46550B","0000000170C23000",11,1,"01"
[04-21_17:35:15:424] AT< OK
[04-21_17:35:15:424] AT> at+cops?
[04-21_17:35:15:427] AT< +COPS: 0,2,"46000",12
[04-21_17:35:15:427] AT< OK
[04-21_17:35:15:427] AT> at+qeng="servingcell"
[04-21_17:35:15:441] AT< +QENG: "servingcell","NOCONN","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-54,-10,16,-,-
[04-21_17:35:15:441] AT< OK
[04-21_17:35:15:441] AT> AT+QNETDEVSTATUS=1
[04-21_17:35:15:445] AT< ERROR
[04-21_17:35:15:445] ifconfig usb0 0.0.0.0
[04-21_17:35:15:446] ifconfig usb0 down
[04-21_17:35:15:448] AT> AT+QNETDEVCTL=1,1,0
[04-21_17:35:15:454] AT< OK
[04-21_17:35:15:456] AT> AT+QNETDEVSTATUS=1
[04-21_17:35:15:458] AT< ERROR
[04-21_17:35:15:989] AT< +QNETDEVSTATUS:1,1,"IPV4"
[04-21_17:35:16:459] AT> AT+QNETDEVSTATUS=1
[04-21_17:35:16:461] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600
[04-21_17:35:16:461] AT< OK
[04-21_17:35:16:461] AT> AT+QNETDEVSTATUS=1
[04-21_17:35:16:462] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600
[04-21_17:35:16:462] AT< OK
[04-21_17:35:16:462] requestGetIPAddress 10.25.16.79
[04-21_17:35:16:462] AT> at+cops?
[04-21_17:35:16:463] AT< +COPS: 0,2,"46000",12
[04-21_17:35:16:463] AT< OK
[04-21_17:35:16:463] AT> at+qeng="servingcell"
[04-21_17:35:16:465] AT< +QENG: "servingcell","CONNECT","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-52,-11,15,-,-
[04-21_17:35:16:465] AT< OK
[04-21_17:35:16:465] AT> AT+QNETDEVSTATUS=1
[04-21_17:35:16:466] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600
[04-21_17:35:16:466] AT< OK
[04-21_17:35:16:466] ifconfig usb0 up
[04-21_17:35:16:470] busybox udhcpc -f -n -q -t 5 -i usb0
udhcpc: started, v1.30.1
udhcpc: sending discover
udhcpc: sending select for 10.25.16.79
udhcpc: lease of 10.25.16.79 obtained, lease time 518400
[04-21_17:35:16:602] /etc/udhcpc/default.script: Resetting default routes
SIOCDELRT: No such process
SIOCADDRT: Network is unreachable
[04-21_17:35:16:606] /etc/udhcpc/default.script: Adding DNS 211.138.180.2
[04-21_17:35:16:606] /etc/udhcpc/default.script: Adding DNS 211.138.180.3
[04-21_17:35:16:655] AT> at+cops?
[04-21_17:35:16:656] AT< +COPS: 0,2,"46000",12
[04-21_17:35:16:656] AT< OK
[04-21_17:35:16:656] AT> at+qeng="servingcell"
[04-21_17:35:16:657] AT< +QENG: "servingcell","CONNECT","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-50,-11,17,-,-
[04-21_17:35:16:658] AT< OK
err = 16
[04-21_17:35:16:658] AT> AT+QNETDEVSTATUS=1
[04-21_17:35:16:659] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600
[04-21_17:35:16:659] AT< OK
root@carl-ThinkPad-X1-Carbon-7th:/home/carl/q/quectel-CM# ifconfig usb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.25.16.79 netmask 255.255.255.224 broadcast 10.25.16.95
inet6 fe80::5c98:e9d4:c82d:5f prefixlen 64 scopeid 0x20<link>
ether 0c:5b:8f:27:9a:64 txqueuelen 1000 (Ethernet)
RX packets 7 bytes 1656 (1.6 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 32 bytes 5112 (5.1 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
root@carl-ThinkPad-X1-Carbon-7th:/home/carl/q/quectel-CM# [04-21_17:35:31:670] AT> at+cops?
[04-21_17:35:31:671] AT< +COPS: 0,2,"46000",12
[04-21_17:35:31:671] AT< OK
[04-21_17:35:31:671] AT> at+qeng="servingcell"
[04-21_17:35:31:673] AT< +QENG: "servingcell","CONNECT","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-48,-10,17,-,-
[04-21_17:35:31:673] AT< OK
[04-21_17:35:31:673] AT> AT+QNETDEVSTATUS=1
[04-21_17:35:31:674] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600
[04-21_17:35:31:674] AT< OK
-62
View File
@@ -1,62 +0,0 @@
root@ZhuoTK:/# dmesg
[ 230.590000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00
[ 230.600000] creating qcqmi0
root@ZhuoTK:/# quectel-CM -s cmnet &
[04-13_03:24:58:213] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_03:24:58:216] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004
[04-13_03:24:58:218] Auto find qmichannel = /dev/qcqmi0
[04-13_03:24:58:218] Auto find usbnet_adapter = usb0
[04-13_03:24:58:218] netcard driver = GobiNet, driver version = V1.6.2.13
[04-13_03:24:58:219] Modem works in QMI mode
[04-13_03:24:58:260] Get clientWDS = 7
[04-13_03:24:58:292] Get clientDMS = 8
[04-13_03:24:58:324] Get clientNAS = 9
[04-13_03:24:58:355] Get clientUIM = 10
[04-13_03:24:58:388] Get clientWDA = 11
[04-13_03:24:58:420] requestBaseBandVersion EC25EFAR06A11M4G
[04-13_03:24:58:548] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_03:24:58:549] requestSetProfile[1] cmnet///0
[04-13_03:24:58:613] requestGetProfile[1] cmnet///0
[04-13_03:24:58:645] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE
[04-13_03:24:58:677] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_03:24:58:677] ifconfig usb0 0.0.0.0
[04-13_03:24:58:696] ifconfig usb0 down
[04-13_03:24:59:028] requestSetupDataCall WdsConnectionIPv4Handle: 0x87245bd0
[04-13_03:24:59:189] ifconfig usb0 up
[04-13_03:24:59:214] you are use OpenWrt?
[04-13_03:24:59:215] should not calling udhcpc manually?
[04-13_03:24:59:215] should modify /etc/config/network as below?
[04-13_03:24:59:215] config interface wan
[04-13_03:24:59:215] option ifname usb0
[04-13_03:24:59:215] option proto dhcp
[04-13_03:24:59:215] should use "/sbin/ifstaus wan" to check usb0 's status?
[04-13_03:24:59:216] busybox udhcpc -f -n -q -t 5 -i usb0
[04-13_03:24:59:226] udhcpc (v1.23.2) started
[04-13_03:24:59:238] Sending discover...
[04-13_03:24:59:248] Sending select for 10.198.78.154...
[04-13_03:24:59:251] Lease of 10.198.78.154 obtained, lease time 7200
[04-13_03:24:59:257] udhcpc: ifconfig usb0 10.198.78.154 netmask 255.255.255.252 broadcast +
[04-13_03:24:59:266] udhcpc: setting default routers: 10.198.78.153
root@ZhuoTK:/# ifconfig usb0
usb0 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.198.78.154 Mask:255.255.255.252
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:916 (916.0 B) TX bytes:960 (960.0 B)
root@ZhuoTK:/# ip ro show
default via 10.198.78.153 dev usb0
10.198.78.152/30 dev usb0 proto kernel scope link src 10.198.78.154
192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251
root@ZhuoTK:/# killall quectel-CM
[04-13_03:25:38:779] requestDeactivateDefaultPDP WdsConnectionIPv4Handle
[04-13_03:25:39:061] ifconfig usb0 0.0.0.0
[04-13_03:25:39:072] ifconfig usb0 down
[04-13_03:25:39:284] GobiNetThread exit
[04-13_03:25:39:285] qmi_main exit
Loaded 100 of 276 files, more files were not shown because too many files have changed in this diff. Show more