🍓 Sync 2026-06-04 16:10:22

This commit is contained in:
github-actions[bot] committed 2026-06-04 16:10:22 +08:00
1 parent 50aabfee18
commit 2e06461e78
289 files changed
+114950 -145

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
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))
@@ -0,0 +1,75 @@
--- 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;
@@ -0,0 +1,30 @@
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;
+38
View File
@@ -0,0 +1,38 @@
obj-m += qmi_wwan_f.o
PWD := $(shell pwd)
OUTPUTDIR=/lib/modules/`uname -r`/kernel/drivers/net/usb/
ifeq ($(ARCH),)
ARCH := $(shell uname -m)
endif
ifeq ($(CROSS_COMPILE),)
CROSS_COMPILE :=
endif
ifeq ($(KDIR),)
KDIR := /lib/modules/$(shell uname -r)/build
ifeq ($(ARCH),i686)
ifeq ($(wildcard $KDIR/arch/$ARCH),)
ARCH=i386
endif
endif
endif
ifneq ($(findstring &,${PWD}),)
$(warning "${PWD}")
$(warning "current directory contain special char '&' !")
$(error "please remove it!")
endif
default:
$(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) modules
install: default
cp $(PWD)/qmi_wwan_f.ko /lib/modules/$(shell uname -r)/kernel/drivers/net/usb/
depmod
modprobe -r qmi_wwan_f
modprobe -r qmi_wwan
modprobe qmi_wwan_f
clean:
rm -rf *~ .tmp_versions modules.order Module.symvers
find . -type f -name "*~" -o -name "*.o" -o -name "*.ko" -o -name "*.cmd" -o -name "*.mod.c" | xargs rm -rf
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -11,8 +11,8 @@ LUCI_DESCRIPTION:=LuCI JS interface for the modemband. The package allows set LT
LUCI_DEPENDS:=+modemband
PKG_NAME:=luci-app-modemband
PKG_VERSION:=1.0.25.20240519
PKG_RELEASE:=1
PKG_VERSION:=1.0.24
PKG_RELEASE:=2
PKG_MAINTAINER:=Rafał Wabik <4Rafal@gmail.com>
include $(TOPDIR)/feeds/luci/luci.mk
@@ -12,29 +12,29 @@
Copyright 2022-2024 Rafał Wabik - IceG - From eko.one.pl forum
*/
var CBISelectswitch = form.DummyValue.extend({
renderWidget: function(section_id, option_id, cfgvalue) {
var section = this.section;
return E([], [
E('span', { 'class': 'control-group' }, [
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_5gnsabands');
dropdown.setValue([]);
}),
}, _('Deselect all')),
' ',
E('button', {
'class': 'cbi-button cbi-button-action important',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_5gnsabands');
dropdown.setValue(Object.keys(dropdown.choices));
})
}, _('Select all'))
])
]);
},
var CBISelectswitch = form.DummyValue.extend({
renderWidget: function(section_id, option_id, cfgvalue) {
var section = this.section;
return E([], [
E('span', { 'class': 'control-group' }, [
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_5gnsabands');
dropdown.setValue([]);
}),
}, _('Deselect all')),
' ',
E('button', {
'class': 'cbi-button cbi-button-action important',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_5gnsabands');
dropdown.setValue(Object.keys(dropdown.choices));
})
}, _('Select all'))
])
]);
},
});
var BANDmagic = form.DummyValue.extend({
@@ -176,14 +176,14 @@ function handleAction(ev) {
if (ev === 'reload') {
location.reload();
}
if (ev === 'resetbandz') {
if (ev === 'resetbandz') {
if (confirm(_('Do you really want to set up all possible bands for the modem?')))
{
fs.exec_direct('/usr/bin/modemband.sh', [ 'setbands5gnsa', 'default' ]);
return uci.load('modemband').then(function() {
var nuser = (uci.get('modemband', '@modemband[0]', 'notify'));
if ( nuser != '1' || nuser == null ) {
ui.addNotification(null, E('p', _('The new bands settings have been sent to the modem. If the changes are not visible, a restart of the connection, modem or router may be required.')), 'info');
}
@@ -202,7 +202,7 @@ function handleAction(ev) {
if (ev === 'restartwan') {
return uci.load('modemband').then(function() {
var wname = (uci.get('modemband', '@modemband[0]', 'iface'));
if (wname.includes('@')) {
wname = wname.replace(/@/g, '')
};
@@ -251,7 +251,7 @@ return view.extend({
modemen = modemen.includes('n0') == true ? modemen = _('Bands are disabled...') : modemen.trim();
for (var i = 0; i < json.supported5gnsa.length; i++)
for (var i = 0; i < json.supported5gnsa.length; i++)
{
var txtband = json.supported5gnsa[i].band.toString();
var numb = txtband.match(/\d+$/);
@@ -259,18 +259,18 @@ return view.extend({
sbands = sbands.replace('undefined', '');
}
sbands = sbands.trim();
pollData: poll.add(function() {
return L.resolveDefault(fs.exec_direct('/usr/bin/modemband.sh', [ 'json' ]))
.then(function(res) {
var json = JSON.parse(res);
//modemen = _('Waiting for device...');
if ( json != null ) {
if ( json != null ) {
var renderHTML = "";
var view = document.getElementById("modemlteb");
for (var i = 0; i < json.enabled5gnsa.length; i++)
for (var i = 0; i < json.enabled5gnsa.length; i++)
{
var txtband = json.enabled5gnsa[i].toString();
var numb = txtband.match(/\d+$/);
@@ -288,7 +288,7 @@ return view.extend({
});
});
}
}
}
else {
if (json.error.includes('No supported') == true) {
modemen = '-';
@@ -305,7 +305,7 @@ return view.extend({
} catch (err) {
console.log('Error: ', err.message);
}
}
}
var info = _('Configuration modem frequency bands. More information about the modemband application on the %seko.one.pl forum%s.').format('<a href="https://eko.one.pl/?p=openwrt-modemband" target="_blank">', '</a>');
@@ -347,21 +347,21 @@ return view.extend({
else {
s.tab('bandset', _('Preferred bands settings'));
o = s.taboption('bandset', cbiRichListValue, 'set_5gnsabands',
_('Modification of the bands'),
_('Modification of the bands'),
_("Select the preferred band(s) for the modem."));
for (var i = 0; i < json.supported5gnsa.length; i++)
for (var i = 0; i < json.supported5gnsa.length; i++)
{
o.value(json.supported5gnsa[i].band, _('n')+json.supported5gnsa[i].band,json.supported5gnsa[i].txt);
}
o.multiple = true;
o.placeholder = _('Please select a band(s)');
o.cfgvalue = function(section_id) {
return L.toArray((json.enabled5gnsa).join(' '));
};
o = s.taboption('bandset', CBISelectswitch, '_switch', _('Band selection switch'));
s = m.section(form.TypedSection);
@@ -383,7 +383,7 @@ return view.extend({
o = s.taboption('opt1', SYSTmagic);
}
return m.render();
},
@@ -396,7 +396,7 @@ return view.extend({
args.push(data.modemband.set_5gnsabands);
var ax = args.toString();
ax = ax.replace(/,/g, ' ')
ax.length >= 1 ? fs.exec_direct('/usr/bin/modemband.sh', [ 'setbands5gnsa', ax ]) : ui.addNotification(null, E('p', _('Check if you have selected the bands correctly.')), 'info');
return uci.load('modemband').then(function() {
@@ -404,20 +404,20 @@ return view.extend({
var mrestart = (uci.get('modemband', '@modemband[0]', 'modemrestart'));
var cmdrestart = (uci.get('modemband', '@modemband[0]', 'restartcmd'));
var wname = (uci.get('modemband', '@modemband[0]', 'iface'));
if (wname.includes('@')) {
wname = wname.replace(/@/g, '')
};
var sport = (uci.get('modemband', '@modemband[0]', 'set_port'));
var nuser = (uci.get('modemband', '@modemband[0]', 'notify'));
if ( ax.length >= 1 ) {
if ( nuser != '1' || nuser == null ) {
ui.addNotification(null, E('p', _('The new bands settings have been sent to the modem. If the changes are not visible, a restart of the connection, modem or router may be required.')), 'info');
}
}
if (wrestart == '1') {
fs.exec('/sbin/ifdown', [ wname ]);
fs.exec('sleep 3');
@@ -13,29 +13,29 @@
*/
var CBISelectswitch = form.DummyValue.extend({
renderWidget: function(section_id, option_id, cfgvalue) {
var section = this.section;
return E([], [
E('span', { 'class': 'control-group' }, [
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_5gsabands');
dropdown.setValue([]);
}),
}, _('Deselect all')),
' ',
E('button', {
'class': 'cbi-button cbi-button-action important',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_5gsabands');
dropdown.setValue(Object.keys(dropdown.choices));
})
}, _('Select all'))
])
]);
},
var CBISelectswitch = form.DummyValue.extend({
renderWidget: function(section_id, option_id, cfgvalue) {
var section = this.section;
return E([], [
E('span', { 'class': 'control-group' }, [
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_5gsabands');
dropdown.setValue([]);
}),
}, _('Deselect all')),
' ',
E('button', {
'class': 'cbi-button cbi-button-action important',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_5gsabands');
dropdown.setValue(Object.keys(dropdown.choices));
})
}, _('Select all'))
])
]);
},
});
@@ -178,14 +178,14 @@ function handleAction(ev) {
if (ev === 'reload') {
location.reload();
}
if (ev === 'resetbandz') {
if (ev === 'resetbandz') {
if (confirm(_('Do you really want to set up all possible bands for the modem?')))
{
fs.exec_direct('/usr/bin/modemband.sh', [ 'setbands5gsa', 'default' ]);
return uci.load('modemband').then(function() {
var nuser = (uci.get('modemband', '@modemband[0]', 'notify'));
if ( nuser != '1' || nuser == null ) {
ui.addNotification(null, E('p', _('The new bands settings have been sent to the modem. If the changes are not visible, a restart of the connection, modem or router may be required.')), 'info');
}
@@ -204,7 +204,7 @@ function handleAction(ev) {
if (ev === 'restartwan') {
return uci.load('modemband').then(function() {
var wname = (uci.get('modemband', '@modemband[0]', 'iface'));
if (wname.includes('@')) {
wname = wname.replace(/@/g, '')
};
@@ -243,7 +243,7 @@ return view.extend({
else {
var modem = json.modem;
for (var i = 0; i < json.enabled5gsa.length; i++)
for (var i = 0; i < json.enabled5gsa.length; i++)
{
var txtband = json.enabled5gsa[i].toString();
var numb = txtband.match(/\d+$/);
@@ -252,7 +252,7 @@ return view.extend({
}
modemen = modemen.includes('n0') == true ? modemen = _('Bands are disabled...') : modemen = modemen.trim();
for (var i = 0; i < json.supported5gsa.length; i++)
for (var i = 0; i < json.supported5gsa.length; i++)
{
var txtband = json.supported5gsa[i].band.toString();
var numb = txtband.match(/\d+$/);
@@ -260,17 +260,17 @@ return view.extend({
sbands = sbands.replace('undefined', '');
}
sbands = sbands.trim();
pollData: poll.add(function() {
return L.resolveDefault(fs.exec_direct('/usr/bin/modemband.sh', [ 'json' ]))
.then(function(res) {
var json = JSON.parse(res);
//modemen = _('Waiting for device...');
if ( json != null ) {
if ( json != null ) {
var renderHTML = "";
var view = document.getElementById("modemlteb");
for (var i = 0; i < json.enabled5gsa.length; i++)
for (var i = 0; i < json.enabled5gsa.length; i++)
{
var txtband = json.enabled5gsa[i].toString();
var numb = txtband.match(/\d+$/);
@@ -288,7 +288,7 @@ return view.extend({
});
});
}
}
}
else {
if (json.error.includes('No supported') == true) {
modemen = '-';
@@ -305,7 +305,7 @@ return view.extend({
} catch (err) {
console.log('Error: ', err.message);
}
}
}
var info = _('Configuration modem frequency bands. More information about the modemband application on the %seko.one.pl forum%s.').format('<a href="https://eko.one.pl/?p=openwrt-modemband" target="_blank">', '</a>');
@@ -347,15 +347,15 @@ return view.extend({
else {
s.tab('bandset', _('Preferred bands settings'));
o = s.taboption('bandset', cbiRichListValue, 'set_5gsabands',
_('Modification of the bands'),
_('Modification of the bands'),
_("Select the preferred band(s) for the modem."));
for (var i = 0; i < json.supported5gsa.length; i++)
for (var i = 0; i < json.supported5gsa.length; i++)
{
o.value(json.supported5gsa[i].band, _('n')+json.supported5gsa[i].band,json.supported5gsa[i].txt);
}
o.multiple = true;
o.placeholder = _('Please select a band(s)');
o.cfgvalue = function(section_id) {
@@ -383,7 +383,7 @@ return view.extend({
o = s.taboption('opt1', SYSTmagic);
}
return m.render();
},
@@ -396,7 +396,7 @@ return view.extend({
args.push(data.modemband.set_5gsabands);
var ax = args.toString();
ax = ax.replace(/,/g, ' ')
ax.length >= 1 ? fs.exec_direct('/usr/bin/modemband.sh', [ 'setbands5gsa', ax ]) : ui.addNotification(null, E('p', _('Check if you have selected the bands correctly.')), 'info');
return uci.load('modemband').then(function() {
@@ -404,20 +404,20 @@ return view.extend({
var mrestart = (uci.get('modemband', '@modemband[0]', 'modemrestart'));
var cmdrestart = (uci.get('modemband', '@modemband[0]', 'restartcmd'));
var wname = (uci.get('modemband', '@modemband[0]', 'iface'));
if (wname.includes('@')) {
wname = wname.replace(/@/g, '')
};
var sport = (uci.get('modemband', '@modemband[0]', 'set_port'));
var nuser = (uci.get('modemband', '@modemband[0]', 'notify'));
if ( ax.length >= 1 ) {
if ( nuser != '1' || nuser == null ) {
ui.addNotification(null, E('p', _('The new bands settings have been sent to the modem. If the changes are not visible, a restart of the connection, modem or router may be required.')), 'info');
}
}
if (wrestart == '1') {
fs.exec('/sbin/ifdown', [ wname ]);
fs.exec('sleep 3');
@@ -12,29 +12,29 @@
Copyright 2022-2024 Rafał Wabik - IceG - From eko.one.pl forum
*/
var CBISelectswitch = form.DummyValue.extend({
renderWidget: function(section_id, option_id, cfgvalue) {
var section = this.section;
return E([], [
E('span', { 'class': 'control-group' }, [
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_bands');
dropdown.setValue([]);
}),
}, _('Deselect all')),
' ',
E('button', {
'class': 'cbi-button cbi-button-action important',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_bands');
dropdown.setValue(Object.keys(dropdown.choices));
})
}, _('Select all'))
])
]);
},
var CBISelectswitch = form.DummyValue.extend({
renderWidget: function(section_id, option_id, cfgvalue) {
var section = this.section;
return E([], [
E('span', { 'class': 'control-group' }, [
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_bands');
dropdown.setValue([]);
}),
}, _('Deselect all')),
' ',
E('button', {
'class': 'cbi-button cbi-button-action important',
'click': ui.createHandlerFn(this, function() {
var dropdown = section.getUIElement(section_id, 'set_bands');
dropdown.setValue(Object.keys(dropdown.choices));
})
}, _('Select all'))
])
]);
},
});
var BANDmagic = form.DummyValue.extend({
@@ -224,14 +224,14 @@ function handleAction(ev) {
if (ev === 'reload') {
location.reload();
}
if (ev === 'resetbandz') {
if (ev === 'resetbandz') {
if (confirm(_('Do you really want to set up all possible bands for the modem?')))
{
fs.exec_direct('/usr/bin/modemband.sh', [ 'setbands', 'default' ]);
return uci.load('modemband').then(function() {
var nuser = (uci.get('modemband', '@modemband[0]', 'notify'));
if ( nuser != '1' || nuser == null ) {
ui.addNotification(null, E('p', _('The new bands settings have been sent to the modem. If the changes are not visible, a restart of the connection, modem or router may be required.')), 'info');
}
@@ -250,7 +250,7 @@ function handleAction(ev) {
if (ev === 'restartwan') {
return uci.load('modemband').then(function() {
var wname = (uci.get('modemband', '@modemband[0]', 'iface'));
if (wname.includes('@')) {
wname = wname.replace(/@/g, '')
};
@@ -265,7 +265,7 @@ function handleAction(ev) {
//var sport = (uci.get('modemband', '@modemband[0]', 'set_port'));
fs.exec_direct('/usr/bin/sms_tool', [ '-d' , '/dev/ttyUSB1' , 'at' , 'AT+ZULCA=1' ]);
});
}
if (ev === 'offupload') {
return uci.load('modemband').then(function() {
@@ -304,7 +304,7 @@ return view.extend({
else {
var modem = json.modem;
for (var i = 0; i < json.enabled.length; i++)
for (var i = 0; i < json.enabled.length; i++)
{
var txtband = json.enabled[i].toString();
var numb = txtband.match(/\d+$/);
@@ -313,7 +313,7 @@ return view.extend({
}
modemen = modemen.trim();
for (var i = 0; i < json.supported.length; i++)
for (var i = 0; i < json.supported.length; i++)
{
var txtband = json.supported[i].band.toString();
var numb = txtband.match(/\d+$/);
@@ -321,17 +321,17 @@ return view.extend({
sbands = sbands.replace('undefined', '');
}
sbands = sbands.trim();
pollData: poll.add(function() {
return L.resolveDefault(fs.exec_direct('/usr/bin/modemband.sh', [ 'json' ]))
.then(function(res) {
var json = JSON.parse(res);
//modemen = _('Waiting for device...');
if ( json != null ) {
if ( json != null ) {
var renderHTML = "";
var view = document.getElementById("modemlteb");
for (var i = 0; i < json.enabled.length; i++)
for (var i = 0; i < json.enabled.length; i++)
{
var txtband = json.enabled[i].toString();
var numb = txtband.match(/\d+$/);
@@ -349,7 +349,7 @@ return view.extend({
});
});
}
}
}
else {
if (json.error.includes('No supported') == true) {
modemen = '-';
@@ -365,7 +365,7 @@ return view.extend({
} catch (err) {
console.log('Error: ', err.message);
}
}
}
var info = _('Configuration modem frequency bands. More information about the modemband application on the %seko.one.pl forum%s.').format('<a href="https://eko.one.pl/?p=openwrt-modemband" target="_blank">', '</a>');
@@ -408,23 +408,23 @@ return view.extend({
}
else {
s.tab('bandset', _('Preferred bands settings'));
o = s.taboption('bandset', cbiRichListValue, 'set_bands',
_('Modification of the bands'),
_('Modification of the bands'),
_("Select the preferred band(s) for the modem."));
for (var i = 0; i < json.supported.length; i++)
for (var i = 0; i < json.supported.length; i++)
{
o.value(json.supported[i].band, _('B')+json.supported[i].band,json.supported[i].txt);
}
o.multiple = true;
o.placeholder = _('Please select a band(s)');
o.cfgvalue = function(section_id) {
return L.toArray((json.enabled).join(' '));
};
o = s.taboption('bandset', CBISelectswitch, '_switch', _('Band selection switch'));
s = m.section(form.TypedSection);
@@ -466,7 +466,7 @@ return view.extend({
'</em></div>';
};
}
return m.render();
},
@@ -479,7 +479,7 @@ return view.extend({
args.push(data.modemband.set_bands);
var ax = args.toString();
ax = ax.replace(/,/g, ' ')
ax.length >= 1 ? fs.exec_direct('/usr/bin/modemband.sh', [ 'setbands', ax ]) : ui.addNotification(null, E('p', _('Check if you have selected the bands correctly.')), 'info');
return uci.load('modemband').then(function() {
@@ -487,20 +487,20 @@ return view.extend({
var mrestart = (uci.get('modemband', '@modemband[0]', 'modemrestart'));
var cmdrestart = (uci.get('modemband', '@modemband[0]', 'restartcmd'));
var wname = (uci.get('modemband', '@modemband[0]', 'iface'));
if (wname.includes('@')) {
wname = wname.replace(/@/g, '')
};
var sport = (uci.get('modemband', '@modemband[0]', 'set_port'));
var nuser = (uci.get('modemband', '@modemband[0]', 'notify'));
if ( ax.length >= 1 ) {
if ( nuser != '1' || nuser == null ) {
ui.addNotification(null, E('p', _('The new bands settings have been sent to the modem. If the changes are not visible, a restart of the connection, modem or router may be required.')), 'info');
}
}
if (wrestart == '1') {
fs.exec('/sbin/ifdown', [ wname ]);
fs.exec('sleep 3');
@@ -33,7 +33,7 @@ return view.extend({
o.noaliases = false;
o.default = 'wan';
*/
o = s.option(widgets.NetworkSelect, 'iface', _('Interface'),
_('Network interface for Internet access.')
);
@@ -42,11 +42,11 @@ return view.extend({
o.rmempty = false;
o.default = 'wan';
o = s.option(form.Value, 'set_port', _('Port for communication with the modem'),
o = s.option(form.Value, 'set_port', _('Port for communication with the modem'),
_("Select one of the available ttyUSBX ports."));
devs.sort((a, b) => a.name > b.name);
devs.forEach(dev => o.value('/dev/' + dev.name));
o.placeholder = _('Please select a port');
o.rmempty = false;
@@ -8,7 +8,7 @@
/*
Copyright 2022-2024 Rafał Wabik - IceG - From eko.one.pl forum
MIT License
*/
@@ -3,14 +3,14 @@
'require form';
'require network';
const callFileList = rpc.declare({
var callFileList = rpc.declare({
object: 'file',
method: 'list',
params: [ 'path' ],
expect: { entries: [] },
filter: function(list, params) {
let rv = [];
for (let i = 0; i < list.length; i++)
var rv = [];
for (var i = 0; i < list.length; i++)
if (list[i].name.match(/^cdc-wdm/))
rv.push(params.path + list[i].name);
return rv.sort();
@@ -31,7 +31,7 @@ return network.registerProtocol('quectel', {
return this._ubus('l3_device') || 'quectel-%s'.format(this.sid);
},
getPackageName: function() {
getOpkgPackage: function() {
return 'quectel-cm';
},
@@ -52,14 +52,14 @@ return network.registerProtocol('quectel', {
},
renderFormOptions: function(s) {
let dev = this.getL3Device() || this.getDevice(), o;
var dev = this.getL3Device() || this.getDevice(), o;
o = s.taboption('general', form.Value, '_modem_device', _('Modem device'));
o.ucioption = 'device';
o.rmempty = false;
o.load = function(section_id) {
return callFileList('/dev/').then(L.bind(function(devices) {
for (let i = 0; i < devices.length; i++)
for (var i = 0; i < devices.length; i++)
this.value(devices[i]);
return form.Value.prototype.load.apply(this, [section_id]);
}, this));
@@ -99,7 +99,7 @@ return network.registerProtocol('quectel', {
o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'),
_('Maximum amount of seconds to wait for the modem to become ready'));
o.placeholder = '10';
o.placeholder = '20';
o.datatype = 'min(1)';
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
+28
View File
@@ -0,0 +1,28 @@
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
@@ -0,0 +1,135 @@
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
@@ -0,0 +1,518 @@
#!/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
@@ -0,0 +1,8 @@
_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
@@ -0,0 +1,10 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 3 5 7 8 20"
getinfo() {
echo "Quectel EC20"
}
# +QCFG: "band",0xdf,0x800d5,0x3f
. $RES/_quectel_common
@@ -0,0 +1,36 @@
_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"
}
@@ -0,0 +1,4 @@
# +GTUSBMODE: 40
_DEVICE=/dev/ttyUSB2
. $RES/_fibocom_fm350_common
@@ -0,0 +1,4 @@
# +GTUSBMODE: 41
_DEVICE=/dev/ttyUSB4
. $RES/_fibocom_fm350_common
@@ -0,0 +1,38 @@
_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
}
@@ -0,0 +1,47 @@
_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
}
@@ -0,0 +1,60 @@
_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
}
@@ -0,0 +1,34 @@
_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
}
@@ -0,0 +1,20 @@
_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
@@ -0,0 +1,15 @@
_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
@@ -0,0 +1,8 @@
_DEVICE=/dev/ttyACM0
_DEFAULT_LTE_BANDS="1 3 7 8 20 38"
getinfo() {
echo "ZTE MF286R"
}
. $RES/_zte_common
@@ -0,0 +1,31 @@
_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
}
@@ -0,0 +1,8 @@
_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
@@ -0,0 +1,8 @@
_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
@@ -0,0 +1,83 @@
_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"
}
@@ -0,0 +1,24 @@
_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,"
}
@@ -0,0 +1,8 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 3 5 7 8 20 38 40 41"
getinfo() {
echo "Quectel EC25"
}
. $RES/_quectel_common
@@ -0,0 +1,10 @@
_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
@@ -0,0 +1,10 @@
_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
@@ -0,0 +1,8 @@
_DEVICE=/dev/ttyUSB2
_DEFAULT_LTE_BANDS="1 3 5 7 8 20 28 38 40 41"
getinfo() {
echo "Quectel EG18-EA"
}
. $RES/_quectel_common
@@ -0,0 +1,26 @@
_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"
}
@@ -0,0 +1,33 @@
_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"
}
@@ -0,0 +1,12 @@
_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
@@ -0,0 +1,12 @@
_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
@@ -0,0 +1,12 @@
_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
@@ -0,0 +1,12 @@
_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
@@ -0,0 +1,12 @@
_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
@@ -0,0 +1,12 @@
_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
@@ -0,0 +1,15 @@
_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
@@ -0,0 +1,12 @@
_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
@@ -0,0 +1,8 @@
_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
@@ -0,0 +1,57 @@
_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
}
@@ -0,0 +1,131 @@
# 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
}
@@ -0,0 +1,27 @@
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"
}
@@ -0,0 +1,27 @@
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"
}
@@ -0,0 +1,17 @@
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"
}
@@ -0,0 +1,80 @@
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"
}
@@ -0,0 +1,19 @@
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"
}
+36
View File
@@ -0,0 +1,36 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=quectel-cm
PKG_VERSION:=1.6.8
PKG_RELEASE:=3
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/quectel-cm
SECTION:=net
CATEGORY:=Network
SUBMENU:=WWAN
TITLE:=Qconnector Manager for Quectel WWAN modules
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
define Package/quectel-cm/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/quectel-CM $(1)/usr/bin/quectel-cm
$(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
$(eval $(call BuildPackage,quectel-cm))
+138
View File
@@ -0,0 +1,138 @@
#!/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
@@ -0,0 +1,24 @@
#!/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
@@ -0,0 +1,24 @@
#!/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
@@ -0,0 +1,29 @@
--- 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
@@ -0,0 +1,8 @@
--- 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)
@@ -0,0 +1,15 @@
--- 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
@@ -0,0 +1,36 @@
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
@@ -0,0 +1,242 @@
/*
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
@@ -0,0 +1,46 @@
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
@@ -0,0 +1,22 @@
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
@@ -0,0 +1,7 @@
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
@@ -0,0 +1,389 @@
/*
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
@@ -0,0 +1,316 @@
/*
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
@@ -0,0 +1,472 @@
/*
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
@@ -0,0 +1,467 @@
/*
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
@@ -0,0 +1,454 @@
/*
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
@@ -0,0 +1,357 @@
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
@@ -0,0 +1,283 @@
/* //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
@@ -0,0 +1,33 @@
/* //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
@@ -0,0 +1,152 @@
/* //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
@@ -0,0 +1,48 @@
# -*- 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
@@ -0,0 +1,63 @@
#!/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
@@ -0,0 +1,61 @@
#!/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
@@ -0,0 +1,756 @@
/*
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
@@ -0,0 +1,71 @@
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
@@ -0,0 +1,168 @@
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
@@ -0,0 +1,129 @@
# ./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
@@ -0,0 +1,62 @@
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
+60
View File
@@ -0,0 +1,60 @@
root@ZhuoTK:/# insmod GobiNet.ko
[ 80.460000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13
[ 80.460000] usbcore: registered new interface driver GobiNet
[ 97.710000] usb 1-1.3: new high-speed USB device number 3 using ehci-platform
[ 97.930000] usb 1-1.3: GSM modem (1-port) converter now attached to ttyUSB103
[ 97.950000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00
[ 97.960000] creating qcqmi0
root@ZhuoTK:/# brctl addbr br0
root@ZhuoTK:/# brctl addif br0 eth0.1
root@ZhuoTK:/# brctl addif br0 usb0
root@ZhuoTK:/# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.00ca019197b9 no eth0.1
usb0
root@ZhuoTK:/# quectel-CM -s cment -b &
[04-13_05:13:18:213] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_05:13:18:216] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003
[ 122.270000] net usb0: bridge_mode change to 0x1
[04-13_05:13:18:218] Auto find qmichannel = /dev/qcqmi0
[04-13_05:13:18:218] Auto find usbnet_adapter = usb0
[04-13_05:13:18:218] netcard driver = GobiNet, driver version = V1.6.2.13
[04-13_05:13:18:224] Modem works in QMI mode
[04-13_05:13:18:251] Get clientWDS = 7
[04-13_05:13:18:282] Get clientDMS = 8
[04-13_05:13:18:316] Get clientNAS = 9
[04-13_05:13:18:347] Get clientUIM = 10
[04-13_05:13:18:379] Get clientWDA = 11
[04-13_05:13:18:411] requestBaseBandVersion EC25EFAR06A11M4G
[04-13_05:13:18:539] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_05:13:18:540] requestSetProfile[1] cment///0
[04-13_05:13:18:603] requestGetProfile[1] cment///0
[04-13_05:13:18:637] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE
[04-13_05:13:18:666] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_05:13:18:667] ifconfig usb0 0.0.0.0
[04-13_05:13:18:687] ifconfig usb0 down
[04-13_05:13:19:083] requestSetupDataCall WdsConnectionIPv4Handle: 0x8724d220
[04-13_05:13:19:243] ifconfig usb0 up
[04-13_05:13:19:270] echo '0xa218480' > /sys/class/net/usb0/bridge_ipv4
root@ZhuoTK:/# ifconfig br0 up
[ 135.530000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 135.570000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 135.580000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 135.610000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128
[ 135.620000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128
[ 135.910000] usb0 sip = 0.0.0.0, tip=10.33.132.128, ipv4=10.33.132.128
[ 136.000000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128
[ 136.910000] usb0 sip = 0.0.0.0, tip=10.33.132.128, ipv4=10.33.132.128
[ 137.910000] usb0 sip = 0.0.0.0, tip=10.33.132.128, ipv4=10.33.132.128
[ 138.740000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128
[ 138.910000] usb0 sip = 10.33.132.128, tip=10.33.132.128, ipv4=10.33.132.128
[ 139.000000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128
[ 140.860000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128
[ 143.160000] br0: port 2(usb0) entered forwarding state
[ 143.160000] br0: port 1(eth0.1) entered forwarding state
[ 148.870000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128
[ 149.010000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128
[ 165.630000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128
+45
View File
@@ -0,0 +1,45 @@
root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=1
[ 798.480000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13
[ 798.490000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00
[ 798.510000] creating qcqmi0
[ 798.510000] usbcore: registered new interface driver GobiNet
[ 799.620000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096
[ 799.630000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16
root@ZhuoTK:/# quectel-CM -s cmnet &
[04-13_03:32:31:248] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_03:32:31:251] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x005
[04-13_03:32:31:253] Auto find qmichannel = /dev/qcqmi0
[04-13_03:32:31:253] Auto find usbnet_adapter = usb0
[04-13_03:32:31:253] netcard driver = GobiNet, driver version = V1.6.2.13
[04-13_03:32:31:253] qmap_mode = 1, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0
[04-13_03:32:31:254] Modem works in QMI mode
[04-13_03:32:31:289] Get clientWDS = 7
[04-13_03:32:31:320] Get clientDMS = 8
[04-13_03:32:31:353] Get clientNAS = 9
[04-13_03:32:31:385] Get clientUIM = 10
[04-13_03:32:31:417] requestBaseBandVersion EC25EFAR06A11M4G
[04-13_03:32:31:545] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_03:32:31:545] requestSetProfile[1] cmnet///0
[04-13_03:32:31:609] requestGetProfile[1] cmnet///0
[04-13_03:32:31:641] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE
[04-13_03:32:31:673] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_03:32:31:674] ifconfig usb0 0.0.0.0
[04-13_03:32:31:698] ifconfig usb0 down
[04-13_03:32:31:770] requestSetupDataCall WdsConnectionIPv4Handle: 0x872481a0
[ 857.000000] net usb0: link_state 0x0 -> 0x1
[04-13_03:32:31:902] ifconfig usb0 up
[04-13_03:32:31:928] you are use OpenWrt?
[04-13_03:32:31:928] should not calling udhcpc manually?
[04-13_03:32:31:928] should modify /etc/config/network as below?
[04-13_03:32:31:928] config interface wan
[04-13_03:32:31:928] option ifname usb0
[04-13_03:32:31:929] option proto dhcp
[04-13_03:32:31:929] should use "/sbin/ifstaus wan" to check usb0 's status?
[04-13_03:32:31:929] busybox udhcpc -f -n -q -t 5 -i usb0
[04-13_03:32:31:939] udhcpc (v1.23.2) started
[04-13_03:32:31:951] Sending discover...
[04-13_03:32:31:956] Sending select for 10.199.102.71...
[04-13_03:32:31:959] Lease of 10.199.102.71 obtained, lease time 7200
[04-13_03:32:31:964] udhcpc: ifconfig usb0 10.199.102.71 netmask 255.255.255.240 broadcast +
[04-13_03:32:31:974] udhcpc: setting default routers: 10.199.102.72
@@ -0,0 +1,62 @@
root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=1
[ 41.540000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13
[ 41.550000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00
[ 41.570000] creating qcqmi0
[ 41.570000] usbcore: registered new interface driver GobiNet
[ 42.700000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096
[ 42.710000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16
root@ZhuoTK:/# brctl addbr br0
root@ZhuoTK:/# brctl addif br0 eth0.1
root@ZhuoTK:/# brctl addif br0 usb0
root@ZhuoTK:/# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.00ca019197b9 no eth0.1
usb0
root@ZhuoTK:/# quectel-CM -s cmnet -b &
# [04-13_05:12:29:338] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_05:12:29:340] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003
[ 73.380000] net usb0: bridge_mode change to 0x1
[04-13_05:12:29:342] Auto find qmichannel = /dev/qcqmi0
[04-13_05:12:29:342] Auto find usbnet_adapter = usb0
[04-13_05:12:29:342] netcard driver = GobiNet, driver version = V1.6.2.13
[04-13_05:12:29:343] qmap_mode = 1, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0
[04-13_05:12:29:348] Modem works in QMI mode
[04-13_05:12:29:382] Get clientWDS = 7
[04-13_05:12:29:414] Get clientDMS = 8
[04-13_05:12:29:447] Get clientNAS = 9
[04-13_05:12:29:479] Get clientUIM = 10
[04-13_05:12:29:512] requestBaseBandVersion EC25EFAR06A11M4G
[04-13_05:12:29:640] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_05:12:29:640] requestSetProfile[1] cmnet///0
[04-13_05:12:29:704] requestGetProfile[1] cmnet///0
[04-13_05:12:29:735] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE
[04-13_05:12:29:767] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_05:12:29:768] ifconfig usb0 0.0.0.0
[04-13_05:12:29:792] ifconfig usb0 down
[04-13_05:12:29:863] requestSetupDataCall WdsConnectionIPv4Handle: 0x8724d820
[ 74.030000] net usb0: link_state 0x0 -> 0x1
[04-13_05:12:29:996] ifconfig usb0 up
[04-13_05:12:30:022] echo '0xa16b769' > /sys/class/net/usb0/bridge_ipv4
root@ZhuoTK:/# ifconfig br0 up
[ 82.210000] br0: port 2(usb0) entered forwarding state
[ 82.210000] br0: port 2(usb0) entered forwarding state
[ 82.220000] br0: port 1(eth0.1) entered forwarding state
[ 82.220000] br0: port 1(eth0.1) entered forwarding state
[ 88.830000] rt305x-esw 10110000.esw: link changed 0x01
[ 89.010000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 89.040000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 89.050000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 89.120000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105
[ 89.350000] usb0 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105
[ 89.400000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105
[ 89.520000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105
[ 90.350000] usb0 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105
[ 91.350000] usb0 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105
[ 92.350000] usb0 sip = 10.22.183.105, tip=10.22.183.105, ipv4=10.22.183.105
[ 92.430000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105
[ 92.660000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105
[ 97.240000] br0: port 2(usb0) entered forwarding state
[ 97.240000] br0: port 1(eth0.1) entered forwarding state
+146
View File
@@ -0,0 +1,146 @@
root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=4
[ 970.380000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13
[ 970.380000] usbcore: registered new interface driver GobiNet
[ 989.620000] usb 1-1.3: new high-speed USB device number 6 using ehci-platform
[ 989.860000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00
[ 989.870000] creating qcqmi0
[ 989.880000] GobiNet::qmap_register_device usb0.1
[ 989.880000] GobiNet::qmap_register_device usb0.2
[ 989.890000] GobiNet::qmap_register_device usb0.3
[ 989.890000] GobiNet::qmap_register_device usb0.4
[ 994.820000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096
[ 994.830000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16
root@ZhuoTK:/# quectel-CM -n 1 -s cmnet &
[04-13_03:35:31:878] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_03:35:31:881] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x006
[04-13_03:35:31:882] Auto find qmichannel = /dev/qcqmi0
[04-13_03:35:31:882] Auto find usbnet_adapter = usb0
[04-13_03:35:31:883] netcard driver = GobiNet, driver version = V1.6.2.13
[04-13_03:35:31:883] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0.1
[04-13_03:35:31:883] Modem works in QMI mode
[04-13_03:35:31:896] Get clientWDS = 7
[04-13_03:35:31:927] Get clientDMS = 8
[04-13_03:35:31:959] Get clientNAS = 9
[04-13_03:35:31:992] Get clientUIM = 10
[04-13_03:35:32:024] requestBaseBandVersion EC25EFAR06A11M4G
[04-13_03:35:32:152] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_03:35:32:152] requestSetProfile[1] cmnet///0
[04-13_03:35:32:216] requestGetProfile[1] cmnet///0
[04-13_03:35:32:248] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE
[04-13_03:35:32:279] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_03:35:32:280] ifconfig usb0 down
[04-13_03:35:32:290] ifconfig usb0.1 0.0.0.0
[04-13_03:35:32:301] ifconfig usb0.1 down
[04-13_03:35:32:344] requestSetupDataCall WdsConnectionIPv4Handle: 0x8723eef0
[ 1037.570000] net usb0: link_state 0x0 -> 0x1
[04-13_03:35:32:477] ifconfig usb0 up
[04-13_03:35:32:496] ifconfig usb0.1 up
[04-13_03:35:32:508] you are use OpenWrt?
[04-13_03:35:32:509] should not calling udhcpc manually?
[04-13_03:35:32:509] should modify /etc/config/network as below?
[04-13_03:35:32:509] config interface wan
[04-13_03:35:32:509] option ifname usb0.1
[04-13_03:35:32:509] option proto dhcp
[04-13_03:35:32:509] should use "/sbin/ifstaus wan" to check usb0.1 's status?
[04-13_03:35:32:510] busybox udhcpc -f -n -q -t 5 -i usb0.1
[04-13_03:35:32:520] udhcpc (v1.23.2) started
[04-13_03:35:32:532] Sending discover...
[04-13_03:35:32:540] Sending select for 10.187.142.20...
[04-13_03:35:32:545] Lease of 10.187.142.20 obtained, lease time 7200
[04-13_03:35:32:550] udhcpc: ifconfig usb0.1 10.187.142.20 netmask 255.255.255.248 broadcast +
[04-13_03:35:32:560] udhcpc: setting default routers: 10.187.142.21
root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet &
[04-13_03:35:38:766] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_03:35:38:769] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x006
[04-13_03:35:38:770] Auto find qmichannel = /dev/qcqmi0
[04-13_03:35:38:770] Auto find usbnet_adapter = usb0
[04-13_03:35:38:771] netcard driver = GobiNet, driver version = V1.6.2.13
[04-13_03:35:38:771] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x82, qmap_netcard = usb0.2
[04-13_03:35:38:771] Modem works in QMI mode
[04-13_03:35:38:809] Get clientWDS = 7
[04-13_03:35:38:841] Get clientDMS = 8
[04-13_03:35:38:873] Get clientNAS = 9
[04-13_03:35:38:905] Get clientUIM = 10
[04-13_03:35:38:937] requestBaseBandVersion EC25EFAR06A11M4G
[04-13_03:35:39:065] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_03:35:39:065] requestSetProfile[2] 4gnet///0
[04-13_03:35:39:129] requestGetProfile[2] 4gnet///0
[04-13_03:35:39:161] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE
[04-13_03:35:39:193] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_03:35:39:193] ifconfig usb0.2 0.0.0.0
[04-13_03:35:39:206] ifconfig usb0.2 down
[04-13_03:35:39:417] requestSetupDataCall WdsConnectionIPv4Handle: 0x87252eb0
[ 1044.650000] net usb0: link_state 0x1 -> 0x3
[04-13_03:35:39:550] ifconfig usb0 up
[04-13_03:35:39:560] ifconfig usb0.2 up
[04-13_03:35:39:573] you are use OpenWrt?
[04-13_03:35:39:573] should not calling udhcpc manually?
[04-13_03:35:39:573] should modify /etc/config/network as below?
[04-13_03:35:39:573] config interface wan
[04-13_03:35:39:573] option ifname usb0.2
[04-13_03:35:39:573] option proto dhcp
[04-13_03:35:39:573] should use "/sbin/ifstaus wan" to check usb0.2 's status?
[04-13_03:35:39:574] busybox udhcpc -f -n -q -t 5 -i usb0.2
[04-13_03:35:39:585] udhcpc (v1.23.2) started
[04-13_03:35:39:597] Sending discover...
[04-13_03:35:39:601] Sending select for 10.197.125.183...
[04-13_03:35:39:606] Lease of 10.197.125.183 obtained, lease time 7200
[04-13_03:35:39:611] udhcpc: ifconfig usb0.2 10.197.125.183 netmask 255.255.255.240 broadcast +
[04-13_03:35:39:621] udhcpc: setting default routers: 10.197.125.184
root@ZhuoTK:/# ifconfig usb0.1
usb0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.187.142.20 Mask:255.255.255.248
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:764 (764.0 B) TX bytes:1824 (1.7 KiB)
root@ZhuoTK:/# ifconfig usb0.2
usb0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.197.125.183 Mask:255.255.255.240
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:3 errors:0 dropped:0 overruns:0 frame:0
TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:688 (688.0 B) TX bytes:1224 (1.1 KiB)
root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev usb0.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=74.450 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 usb0.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=52 time=257.851 ms
root@ZhuoTK:/# quectel-CM -k 2
[04-13_03:39:16:986] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_03:39:16:988] /proc/2294/cmdline: quectel-CM -n 2 -s 4gnet
[04-13_03:39:16:988] send SIGINT to process 2294
[04-13_03:39:16:989] requestDeactivateDefaultPDP WdsConnectionIPv4Handle
[ 1262.310000] net usb0: link_state 0x3 -> 0x1
[04-13_03:39:17:216] ifconfig usb0.2 0.0.0.0
[04-13_03:39:17:228] ifconfig usb0.2 down
[04-13_03:39:17:370] GobiNetThread exit
[04-13_03:39:17:371] qmi_main exit
[2]+ Done quectel-CM -n 2 -s 4gnet
root@ZhuoTK:/# ifconfig usb0.2
usb0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
NOARP MTU:1500 Metric:1
RX packets:30 errors:0 dropped:0 overruns:0 frame:0
TX packets:35 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2816 (2.7 KiB) TX bytes:3408 (3.3 KiB)
@@ -0,0 +1,114 @@
root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=4
[ 42.120000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13
[ 42.130000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00
[ 42.140000] creating qcqmi0
[ 42.150000] GobiNet::qmap_register_device usb0.1
[ 42.150000] GobiNet::qmap_register_device usb0.2
[ 42.160000] GobiNet::qmap_register_device usb0.3
[ 42.160000] GobiNet::qmap_register_device usb0.4
[ 42.170000] usbcore: registered new interface driver GobiNet
[ 43.270000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096
[ 43.280000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16
root@ZhuoTK:/# brctl addbr br0
root@ZhuoTK:/# brctl addif br0 eth0.1
root@ZhuoTK:/# brctl addif br0 usb0.1
root@ZhuoTK:/# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.00ca019197b9 no eth0.1
usb0.1
root@ZhuoTK:/# quectel-CM -n 1 -s cmnet -b &
[04-13_05:12:42:155] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_05:12:42:158] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003
[ 86.130000] net usb0.1: bridge_mode change to 0x1
[04-13_05:12:42:159] Auto find qmichannel = /dev/qcqmi0
[04-13_05:12:42:160] Auto find usbnet_adapter = usb0
[04-13_05:12:42:160] netcard driver = GobiNet, driver version = V1.6.2.13
[04-13_05:12:42:160] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0.1
[04-13_05:12:42:166] Modem works in QMI mode
[04-13_05:12:42:181] Get clientWDS = 7
[04-13_05:12:42:213] Get clientDMS = 8
[04-13_05:12:42:246] Get clientNAS = 9
[04-13_05:12:42:278] Get clientUIM = 10
[04-13_05:12:42:310] requestBaseBandVersion EC25EFAR06A11M4G
[04-13_05:12:42:438] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_05:12:42:439] requestSetProfile[1] cmnet///0
[04-13_05:12:42:502] requestGetProfile[1] cmnet///0
[04-13_05:12:42:534] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE
[04-13_05:12:42:565] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_05:12:42:566] ifconfig usb0 down
[04-13_05:12:42:576] ifconfig usb0.1 0.0.0.0
[04-13_05:12:42:587] ifconfig usb0.1 down
[04-13_05:12:42:629] requestSetupDataCall WdsConnectionIPv4Handle: 0x8724d740
[ 86.730000] net usb0: link_state 0x0 -> 0x1
[04-13_05:12:42:762] ifconfig usb0 up
[04-13_05:12:42:782] ifconfig usb0.1 up
[04-13_05:12:42:794] echo '0xa16b769' > /sys/class/net/usb0.1/bridge_ipv4
root@ZhuoTK:/# ifconfig br0 up
[ 98.270000] usb0.1 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 98.360000] usb0.1 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105
[ 98.370000] usb0.1 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105
[ 99.360000] usb0.1 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105
[ 100.360000] usb0.1 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105
[ 100.500000] usb0.1 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105
root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet &
[04-13_05:13:05:715] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_05:13:05:717] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003
[04-13_05:13:05:719] Auto find qmichannel = /dev/qcqmi0
[04-13_05:13:05:719] Auto find usbnet_adapter = usb0
[04-13_05:13:05:719] netcard driver = GobiNet, driver version = V1.6.2.13
[04-13_05:13:05:719] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x82, qmap_netcard = usb0.2
[04-13_05:13:05:720] Modem works in QMI mode
[04-13_05:13:05:734] Get clientWDS = 7
[04-13_05:13:05:766] Get clientDMS = 8
[04-13_05:13:05:798] Get clientNAS = 9
[04-13_05:13:05:830] Get clientUIM = 10
[04-13_05:13:05:861] requestBaseBandVersion EC25EFAR06A11M4G
[04-13_05:13:05:990] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_05:13:05:991] requestSetProfile[2] 4gnet///0
[04-13_05:13:06:054] requestGetProfile[2] 4gnet///0
[04-13_05:13:06:086] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE
[04-13_05:13:06:118] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_05:13:06:119] ifconfig usb0.2 0.0.0.0
[04-13_05:13:06:131] ifconfig usb0.2 down
[04-13_05:13:06:375] requestSetupDataCall WdsConnectionIPv4Handle: 0x872b8c50
[ 110.470000] net usb0: link_state 0x1 -> 0x3
[04-13_05:13:06:507] ifconfig usb0 up
[04-13_05:13:06:518] ifconfig usb0.2 up
[04-13_05:13:06:539] you are use OpenWrt?
[04-13_05:13:06:540] should not calling udhcpc manually?
[04-13_05:13:06:540] should modify /etc/config/network as below?
[04-13_05:13:06:540] config interface wan
[04-13_05:13:06:540] option ifname usb0.2
[04-13_05:13:06:540] option proto dhcp
[04-13_05:13:06:540] should use "/sbin/ifstaus wan" to check usb0.2 's status?
[04-13_05:13:06:540] busybox udhcpc -f -n -q -t 5 -i usb0.2
[04-13_05:13:06:554] udhcpc (v1.23.2) started
[04-13_05:13:06:614] Sending discover...
[04-13_05:13:06:619] Sending select for 10.22.58.141...
[04-13_05:13:06:623] Lease of 10.22.58.141 obtained, lease time 7200
[04-13_05:13:06:629] udhcpc: ifconfig usb0.2 10.22.58.141 netmask 255.255.255.252 broadcast +
[04-13_05:13:06:638] udhcpc: setting default routers: 10.22.58.142
root@ZhuoTK:/# ifconfig usb0.2
usb0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.22.58.141 Mask:255.255.255.252
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:612 (612.0 B) TX bytes:1064 (1.0 KiB)
root@ZhuoTK:/# ip ro show
default via 10.22.58.142 dev usb0.2
10.22.58.140/30 dev usb0.2 proto kernel scope link src 10.22.58.141
192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251
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=69.822 ms
+80
View File
@@ -0,0 +1,80 @@
root@OpenWrt:/# lspci
00:00.0 Class 0604: 17cb:1001
01:00.0 Class ff00: 17cb:0306
root@OpenWrt:/# insmod pcie_mhi.ko mhi_mbim_enabled=1
[ 63.094154] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17
[ 63.094739] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306
[ 63.099373] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit]
[ 63.108476] mhi_q 0000:01:00.0: enabling device (0140 -> 0142)
[ 63.293451] [I][mhi_netdev_enable_iface] Prepare the channels for transfer
[ 63.324757] [I][mhi_netdev_enable_iface] Exited.
[ 63.326265] rmnet_vnd_register_device(rmnet_mhi0.1)=0
root@OpenWrt:/# quectel-CM -s cment &
[04-13_09:25:23:910] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_09:25:23:912] network interface '' or qmidev '' is not exist
[04-13_09:25:23:912] netcard driver = pcie_mhi, driver version = V1.3.0.17
[04-13_09:25:23:913] mbim_qmap_mode = 1, vlan_id = 0x00, qmap_netcard = rmnet_mhi0.1
[04-13_09:25:23:913] Modem works in MBIM mode
[04-13_09:25:23:965] cdc_wdm_fd = 7
[04-13_09:25:23:965] mbim_open_device()
[04-13_09:25:24:549] mbim_device_caps_query()
[04-13_09:25:24:575] DeviceId: 869710030002905
[04-13_09:25:24:575] FirmwareInfo: RM500QGLABR10A03M4G_01.001.03
[04-13_09:25:24:575] HardwareInfo: RM500QGL_VH
[04-13_09:25:24:576] mbim_device_services_query()
[04-13_09:25:24:585] mbim_set_radio_state( 1 )
[04-13_09:25:24:588] HwRadioState: 1, SwRadioState: 1
[04-13_09:25:24:588] mbim_subscriber_status_query()
[04-13_09:25:24:612] SubscriberId: 460028563800461
[04-13_09:25:24:612] SimIccId: 89860015120716380461
[04-13_09:25:24:613] SubscriberReadyState NotInitialized -> Initialized
[04-13_09:25:24:613] mbim_register_state_query()
[04-13_09:25:24:617] RegisterState Unknown -> Home
[04-13_09:25:24:617] mbim_packet_service_query()
[04-13_09:25:24:619] PacketServiceState Unknown -> Attached
[04-13_09:25:24:619] CurrentDataClass = 5G_NSA
[04-13_09:25:24:620] mbim_query_connect(sessionID=0)
[04-13_09:25:24:631] ActivationState Unknown -> Deactivated
[04-13_09:25:24:631] ifconfig rmnet_mhi0 down
[04-13_09:25:24:657] ifconfig rmnet_mhi0.1 0.0.0.0
ifconfig: SIOCSIFFLAGS: Network is down
[04-13_09:25:24:681] ifconfig rmnet_mhi0.1 down
[04-13_09:25:24:705] mbim_register_state_query()
[04-13_09:25:24:709] mbim_packet_service_query()
[04-13_09:25:24:713] CurrentDataClass = 5G_NSA
[04-13_09:25:24:713] mbim_set_connect(onoff=1, sessionID=0)
[04-13_09:25:25:096] ActivationState Deactivated -> Activated
[04-13_09:25:25:097] mbim_ip_config(sessionID=0)
[04-13_09:25:25:100] < SessionId = 0
[04-13_09:25:25:100] < IPv4ConfigurationAvailable = 0xf
[04-13_09:25:25:100] < IPv6ConfigurationAvailable = 0x0
[04-13_09:25:25:101] < IPv4AddressCount = 0x1
[04-13_09:25:25:101] < IPv4AddressOffset = 0x3c
[04-13_09:25:25:101] < IPv6AddressCount = 0x0
[04-13_09:25:25:102] < IPv6AddressOffset = 0x0
[04-13_09:25:25:102] < IPv4 = 10.190.166.229/30
[04-13_09:25:25:103] < gw = 10.190.166.230
[04-13_09:25:25:103] < dns1 = 211.138.180.2
[04-13_09:25:25:103] < dns2 = 211.138.180.3
[04-13_09:25:25:104] < ipv4 mtu = 1500
[04-13_09:25:25:112] ifconfig rmnet_mhi0 up
[04-13_09:25:25:141] ifconfig rmnet_mhi0.1 up
[04-13_09:25:25:170] ip -4 address flush dev rmnet_mhi0.1
[04-13_09:25:25:190] ip -4 address add 10.190.166.229/30 dev rmnet_mhi0.1
[04-13_09:25:25:213] ip -4 route add default via 10.190.166.230 dev rmnet_mhi0.1
root@OpenWrt:/# ifconfig rmnet_mhi0.1
rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.190.166.229 Mask:255.255.255.252
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:19 errors:0 dropped:0 overruns:0 frame:0
TX packets:29 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2326 (2.2 KiB) TX bytes:2991 (2.9 KiB)
root@OpenWrt:/# 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=278.561 ms
+170
View File
@@ -0,0 +1,170 @@
root@OpenWrt:/# lspci
00:00.0 Class 0604: 17cb:1001
01:00.0 Class ff00: 17cb:0304
root@OpenWrt:/# insmod pcie_mhi.ko mhi_mbim_enabled=1 qmap_mode=4
[ 76.596827] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17
[ 76.598596] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0304
[ 76.602863] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit]
[ 76.611323] mhi_q 0000:01:00.0: enabling device (0140 -> 0142)
[ 76.760239] [I][mhi_netdev_enable_iface] Prepare the channels for transfer
[ 76.828699] [I][mhi_netdev_enable_iface] Exited.
[ 76.832727] rmnet_vnd_register_device(rmnet_mhi0.1)=0
[ 76.836596] rmnet_vnd_register_device(rmnet_mhi0.2)=0
[ 76.841170] rmnet_vnd_register_device(rmnet_mhi0.3)=0
[ 76.846373] rmnet_vnd_register_device(rmnet_mhi0.4)=0
root@OpenWrt:~# quectel-mbim-proxy -d /dev/mhi_MBIM &
root@OpenWrt:~# [04-14_03:05:36:296] mbim_dev_fd=3
[04-14_03:05:36:297] mbim_send_open_msg()
[04-14_03:05:36:669] receive MBIM_OPEN_DONE, status=0
[04-14_03:05:36:670] mbim_server_fd=4
root@OpenWrt:~# quectel-CM -n 1 -s cmnet &
[04-14_03:05:45:955] Quectel_QConnectManager_Linux_V1.6.0.25
[04-14_03:05:45:956] network interface '' or qmidev '' is not exist
[04-14_03:05:45:957] netcard driver = pcie_mhi, driver version = V1.3.0.17
[04-14_03:05:45:957] mbim_qmap_mode = 4, vlan_id = 0x01, qmap_netcard = rmnet_mhi0.1
[04-14_03:05:45:958] Modem works in MBIM mode
[04-14_03:05:45:959] connect to quectel-mbim-proxy sockfd = 7
[04-14_03:05:45:959] handle_client_connect client_fd=5, client_idx=1
[04-14_03:05:45:959] cdc_wdm_fd = 7
[04-14_03:05:45:960] mbim_open_device()
[04-14_03:05:45:961] mbim_device_caps_query()
[04-14_03:05:45:967] DeviceId: 860459050041596
[04-14_03:05:45:968] FirmwareInfo: EM120RGLAPR02A03M4G_01.001.07
[04-14_03:05:45:968] HardwareInfo: EM120R_GL
[04-14_03:05:45:968] mbim_device_services_query()
[04-14_03:05:45:972] mbim_set_radio_state( 1 )
[04-14_03:05:45:976] HwRadioState: 1, SwRadioState: 1
[04-14_03:05:45:976] mbim_subscriber_status_query()
[04-14_03:05:45:985] SubscriberId: 460028563800461
[04-14_03:05:45:985] SimIccId: 89860015120716380461
[04-14_03:05:45:986] SubscriberReadyState NotInitialized -> Initialized
[04-14_03:05:45:986] mbim_register_state_query()
[04-14_03:05:45:991] RegisterState Unknown -> Home
[04-14_03:05:45:991] mbim_packet_service_query()
[04-14_03:05:45:995] PacketServiceState Unknown -> Attached
[04-14_03:05:45:996] mbim_query_connect(sessionID=1)
[04-14_03:05:46:000] ActivationState Unknown -> Deactivated
[04-14_03:05:46:000] ifconfig rmnet_mhi0 down
[04-14_03:05:46:024] ifconfig rmnet_mhi0.1 0.0.0.0
ifconfig: SIOCSIFFLAGS: Network is down
[04-14_03:05:46:049] ifconfig rmnet_mhi0.1 down
[04-14_03:05:46:072] mbim_set_connect(onoff=1, sessionID=1)
[04-14_03:05:46:099] ActivationState Deactivated -> Activated
[04-14_03:05:46:099] mbim_ip_config(sessionID=1)
[ 222.484298] net rmnet_mhi0: link_state 0x0 -> 0x1
[04-14_03:05:46:103] < SessionId = 1
[04-14_03:05:46:104] < IPv4ConfigurationAvailable = 0xf
[04-14_03:05:46:104] < IPv6ConfigurationAvailable = 0x0
[04-14_03:05:46:104] < IPv4AddressCount = 0x1
[04-14_03:05:46:105] < IPv4AddressOffset = 0x3c
[ 222.507775] [I][mhi_netdev_open] Opened net dev interface
[04-14_03:05:46:105] < IPv6AddressCount = 0x0
[04-14_03:05:46:105] < IPv6AddressOffset = 0x0
[04-14_03:05:46:106] < IPv4 = 10.38.21.158/30
[04-14_03:05:46:106] < gw = 10.38.21.157
[04-14_03:05:46:106] < dns1 = 211.138.180.2
[04-14_03:05:46:107] < dns2 = 211.138.180.3
[04-14_03:05:46:107] < ipv4 mtu = 1500
[04-14_03:05:46:112] ifconfig rmnet_mhi0 up
[04-14_03:05:46:140] ifconfig rmnet_mhi0.1 up
[04-14_03:05:46:168] ip -4 address flush dev rmnet_mhi0.1
[04-14_03:05:46:190] ip -4 address add 10.38.21.158/30 dev rmnet_mhi0.1
[04-14_03:05:46:212] ip -4 route add default via 10.38.21.157 dev rmnet_mhi0.1
[04-14_03:05:50:730] handle_client_connect client_fd=6, client_idx=2
[ 227.558631] net rmnet_mhi0: link_state 0x1 -> 0x3
root@OpenWrt:~# quectel-CM -n 2 -s 4gnet
[04-14_03:05:50:725] Quectel_QConnectManager_Linux_V1.6.0.25
[04-14_03:05:50:726] network interface '' or qmidev '' is not exist
[04-14_03:05:50:727] netcard driver = pcie_mhi, driver version = V1.3.0.17
[04-14_03:05:50:728] mbim_qmap_mode = 4, vlan_id = 0x02, qmap_netcard = rmnet_mhi0.2
[04-14_03:05:50:729] Modem works in MBIM mode
[04-14_03:05:50:730] connect to quectel-mbim-proxy sockfd = 8
[04-14_03:05:50:730] cdc_wdm_fd = 8
[04-14_03:05:50:731] mbim_open_device()
[04-14_03:05:50:732] mbim_device_caps_query()
[04-14_03:05:50:738] DeviceId: 860459050041596
[04-14_03:05:50:739] FirmwareInfo: EM120RGLAPR02A03M4G_01.001.07
[04-14_03:05:50:739] HardwareInfo: EM120R_GL
[04-14_03:05:50:740] mbim_device_services_query()
[04-14_03:05:50:744] mbim_set_radio_state( 1 )
[04-14_03:05:50:747] HwRadioState: 1, SwRadioState: 1
[04-14_03:05:50:747] mbim_subscriber_status_query()
[04-14_03:05:50:757] SubscriberId: 460028563800461
[04-14_03:05:50:758] SimIccId: 89860015120716380461
[04-14_03:05:50:758] SubscriberReadyState NotInitialized -> Initialized
[04-14_03:05:50:759] mbim_register_state_query()
[04-14_03:05:50:763] RegisterState Unknown -> Home
[04-14_03:05:50:764] mbim_packet_service_query()
[04-14_03:05:50:768] PacketServiceState Unknown -> Attached
[04-14_03:05:50:769] mbim_query_connect(sessionID=2)
[04-14_03:05:50:772] ActivationState Unknown -> Deactivated
[04-14_03:05:50:773] ifconfig rmnet_mhi0.2 0.0.0.0
[04-14_03:05:50:799] ifconfig rmnet_mhi0.2 down
[04-14_03:05:50:834] mbim_set_connect(onoff=1, sessionID=2)
[04-14_03:05:51:170] ActivationState Deactivated -> Activated
[04-14_03:05:51:171] mbim_ip_config(sessionID=2)
[04-14_03:05:51:174] < SessionId = 2
[04-14_03:05:51:174] < IPv4ConfigurationAvailable = 0xf
[04-14_03:05:51:175] < IPv6ConfigurationAvailable = 0x0
[04-14_03:05:51:175] < IPv4AddressCount = 0x1
[04-14_03:05:51:175] < IPv4AddressOffset = 0x3c
[04-14_03:05:51:176] < IPv6AddressCount = 0x0
[04-14_03:05:51:176] < IPv6AddressOffset = 0x0
[04-14_03:05:51:176] < IPv4 = 10.36.109.217/30
[04-14_03:05:51:177] < gw = 10.36.109.218
[04-14_03:05:51:177] < dns1 = 211.138.180.2
[04-14_03:05:51:178] < dns2 = 211.138.180.3
[04-14_03:05:51:178] < ipv4 mtu = 1500
[04-14_03:05:51:182] ifconfig rmnet_mhi0 up
[04-14_03:05:51:206] ifconfig rmnet_mhi0.2 up
[04-14_03:05:51:233] ip -4 address flush dev rmnet_mhi0.2
[04-14_03:05:51:254] ip -4 address add 10.36.109.217/30 dev rmnet_mhi0.2
[04-14_03:05:51:277] ip -4 route add default via 10.36.109.218 dev rmnet_mhi0.2
root@OpenWrt:~# ifconfig rmnet_mhi0.1
rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.38.21.158 Mask:255.255.255.252
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:37 errors:0 dropped:0 overruns:0 frame:0
TX packets:29 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:9907 (9.6 KiB) TX bytes:2764 (2.6 KiB)
root@OpenWrt:~# ifconfig rmnet_mhi0.2
rmnet_mhi0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.36.109.217 Mask:255.255.255.252
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:5 errors:0 dropped:0 overruns:0 frame:0
TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:344 (344.0 B) TX bytes:1152 (1.1 KiB)
root@OpenWrt:~# ip ro del 8.8.8.8/32
RTNETLINK answers: No such process
root@OpenWrt:~# ip ro add 8.8.8.8/32 dev rmnet_mhi0.1
root@OpenWrt:~# 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=73.248 ms
root@OpenWrt:~# ip ro del 8.8.8.8/32
root@OpenWrt:~# ip ro del 8.8.8.8/32
RTNETLINK answers: No such process
root@OpenWrt:~# ip ro add 8.8.8.8/32 dev rmnet_mhi0.2
root@OpenWrt:~# 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=99.637 ms
root@OpenWrt:~# quectel-CM -k 2
[04-14_03:06:58:912] Quectel_QConnectManager_Linux_V1.6.0.25
[04-14_03:06:59:063] /proc/3565/cmdline: quectel-CM -n 2 -s 4gnet
[04-14_03:06:59:064] send SIGINT to process 3565
[ 295.719442] net rmnet_mhi0: link_state 0x3 -> 0x1
[04-14_03:06:59:407] proxy_loop poll fd = 6, revents = 0011
[04-14_03:06:59:408] handle_client_disconnect client_fd=6, client_idx=2
+127
View File
@@ -0,0 +1,127 @@
root@OpenWrt:/# cat /sys/class/net/rmnet_mhi0/qmap_mode
1
root@OpenWrt:/# cat /sys/module/pcie_mhi/parameters/mhi_mbim_enabled
0
root@OpenWrt:/# dmesg | grep mhi
[ 18.442226] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17
[ 18.443032] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306
[ 18.447488] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit]
[ 18.456563] mhi_q 0000:01:00.0: enabling device (0140 -> 0142)
[ 18.464184] [I][mhi_init_pci_dev] msi_required = 5, msi_allocated = 5, msi_irq = 197
[ 18.464215] [I][mhi_power_up] dev_state:RESET
[ 18.464225] [I][mhi_async_power_up] Requested to power on
[ 18.464432] [I][mhi_alloc_coherent] size = 114688, dma_handle = 8d400000
[ 18.464445] [I][mhi_init_dev_ctxt] mhi_ctxt->ctrl_seg = d1766000
[ 18.466003] [I][mhi_async_power_up] dev_state:RESET ee:AMSS
[ 18.466080] [I][mhi_pm_st_worker] Transition to state:READY
[ 18.466109] [I][mhi_pm_st_worker] INVALID_EE -> AMSS
[ 18.466135] [I][mhi_ready_state_transition] Waiting to enter READY state
[ 18.466224] [I][mhi_async_power_up] Power on setup success
[ 18.466265] [I][mhi_pci_probe] Return successful
[ 18.577299] [I][mhi_intvec_threaded_handlr] device ee:AMSS dev_state:READY, pm_state:POR
[ 18.577312] [I][mhi_ready_state_transition] Device in READY State
[ 18.577325] [I][mhi_intvec_threaded_handlr] device ee:AMSS dev_state:READY, INVALID_EE
[ 18.577329] [I][mhi_tryset_pm_state] Transition to pm state from:POR to:POR
[ 18.577337] [I][mhi_init_mmio] Initializing MMIO
[ 18.577344] [I][mhi_init_mmio] CHDBOFF:0x300
[ 18.577361] [I][mhi_init_mmio] ERDBOFF:0x700
[ 18.577372] [I][mhi_init_mmio] Programming all MMIO values.
[ 18.690834] [I][mhi_dump_tre] carl_ev evt_state_change mhistate=2
[ 18.690854] [I][mhi_process_ctrl_ev_ring] MHI state change event to state:M0
[ 18.690866] [I][mhi_pm_m0_transition] Entered With State:READY PM_STATE:POR
[ 18.690879] [I][mhi_tryset_pm_state] Transition to pm state from:POR to:M0
[ 18.694229] [I][mhi_dump_tre] carl_ev evt_ee_state execenv=2
[ 18.694241] [I][mhi_process_ctrl_ev_ring] MHI EE received event:AMSS
[ 18.694293] [I][mhi_pm_st_worker] Transition to state:MISSION MODE
[ 18.694310] [I][mhi_pm_st_worker] INVALID_EE -> AMSS
[ 18.694319] [I][mhi_pm_mission_mode_transition] Processing Mission Mode Transition
[ 18.694341] [I][mhi_init_timesync] No timesync capability found
[ 18.694350] [I][mhi_pm_mission_mode_transition] Adding new devices
[ 18.696365] [I][mhi_dtr_probe] Enter for DTR control channel
[ 18.696383] [I][__mhi_prepare_channel] Entered: preparing channel:18
[ 18.703113] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33
[ 18.703164] [I][__mhi_prepare_channel] Chan:18 successfully moved to start state
[ 18.703174] [I][__mhi_prepare_channel] Entered: preparing channel:19
[ 18.710681] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33
[ 18.710734] [I][__mhi_prepare_channel] Chan:19 successfully moved to start state
[ 18.710804] [I][mhi_dtr_probe] Exit with ret:0
[ 18.711774] [I][mhi_netdev_enable_iface] Prepare the channels for transfer
[ 18.711811] [I][__mhi_prepare_channel] Entered: preparing channel:100
[ 18.732097] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33
[ 18.732151] [I][__mhi_prepare_channel] Chan:100 successfully moved to start state
[ 18.732162] [I][__mhi_prepare_channel] Entered: preparing channel:101
[ 18.744170] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33
[ 18.744219] [I][__mhi_prepare_channel] Chan:101 successfully moved to start state
[ 18.749132] [I][mhi_netdev_enable_iface] Exited.
[ 18.750306] rmnet_vnd_register_device(rmnet_mhi0.1)=0
[ 18.752927] [I][mhi_pm_mission_mode_transition] Exit with ret:0
root@OpenWrt:/# busybox microcom /dev/mhi_DUN
at+cpin?
+CPIN: READY
OK
at+cops?
+COPS: 0,0,"CHINA MOBILE",13
OK
at+csq
+csq: 23,99
OK
root@OpenWrt:/# quectel-CM -s cmnet &
[04-13_09:26:58:077] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_09:26:58:078] network interface '' or qmidev '' is not exist
[04-13_09:26:58:079] netcard driver = pcie_mhi, driver version = V1.3.0.17
[04-13_09:26:58:080] qmap_mode = 1, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1
[04-13_09:26:58:080] Modem works in QMI mode
[04-13_09:26:58:131] cdc_wdm_fd = 7
[04-13_09:26:59:132] QmiWwanInit message timeout
[04-13_09:27:00:140] Get clientWDS = 15
[04-13_09:27:00:144] Get clientDMS = 1
[04-13_09:27:00:147] Get clientNAS = 4
[04-13_09:27:00:151] Get clientUIM = 1
[04-13_09:27:00:155] Get clientWDA = 1
[04-13_09:27:00:158] requestBaseBandVersion RM500QGLABR10A03M4G
[04-13_09:27:00:161] qmap_settings.rx_urb_size = 16384
[04-13_09:27:00:162] qmap_settings.ul_data_aggregation_max_datagrams = 11
[04-13_09:27:00:162] qmap_settings.ul_data_aggregation_max_size = 8192
[04-13_09:27:00:163] qmap_settings.dl_minimum_padding = 0
[04-13_09:27:00:176] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_09:27:00:177] requestSetProfile[1] cmnet///0
[04-13_09:27:00:190] requestGetProfile[1] cmnet///0
[04-13_09:27:00:193] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA
[04-13_09:27:00:197] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_09:27:00:198] ifconfig rmnet_mhi0 down
[04-13_09:27:00:222] ifconfig rmnet_mhi0.1 0.0.0.0
[04-13_09:27:00:247] ifconfig rmnet_mhi0.1 down
[04-13_09:27:00:281] requestSetupDataCall WdsConnectionIPv4Handle: 0x1228bb20
[ 245.284909] net rmnet_mhi0: link_state 0x0 -> 0x1
[04-13_09:27:00:293] ifconfig rmnet_mhi0 up
[ 245.308696] [I][mhi_netdev_open] Opened net dev interface
[04-13_09:27:00:318] ifconfig rmnet_mhi0.1 up
[04-13_09:27:00:353] you are use OpenWrt?
[04-13_09:27:00:354] should not calling udhcpc manually?
[04-13_09:27:00:354] should modify /etc/config/network as below?
[04-13_09:27:00:355] config interface wan
[04-13_09:27:00:355] option ifname rmnet_mhi0.1
[04-13_09:27:00:355] option proto dhcp
[04-13_09:27:00:356] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status?
[04-13_09:27:00:356] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1
udhcpc: started, v1.28.3
udhcpc: sending discover
udhcpc: sending select for 10.128.73.23
udhcpc: lease of 10.128.73.23 obtained, lease time 7200
[04-13_09:27:00:710] udhcpc: ifconfig rmnet_mhi0.1 10.128.73.23 netmask 255.255.255.240 broadcast +
[04-13_09:27:00:742] udhcpc: setting default routers: 10.128.73.24
root@OpenWrt:/# ifconfig rmnet_mhi0.1
rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.128.73.23 Mask:255.255.255.240
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:612 (612.0 B) TX bytes:684 (684.0 B)
@@ -0,0 +1,76 @@
root@OpenWrt:/# lspci
00:00.0 Class 0604: 17cb:1001
01:00.0 Class ff00: 17cb:0306
root@OpenWrt:~# insmod pcie_mhi.ko
[ 77.949271] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17
[ 77.950949] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306
[ 77.955331] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit]
[ 77.963756] mhi_q 0000:01:00.0: enabling device (0140 -> 0142)
[ 78.048911] [I][mhi_netdev_enable_iface] Prepare the channels for transfer
[ 78.092304] [I][mhi_netdev_enable_iface] Exited.
[ 78.096580] rmnet_vnd_register_device(rmnet_mhi0.1)=0
root@OpenWrt:~# brctl addbr br0
root@OpenWrt:~# brctl addif br0 rmnet_mhi0.1
root@OpenWrt:~# brctl addif br0 eth1
[ 250.017213] device eth1 entered promiscuous mode
root@OpenWrt:~# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.00001c353487 no eth1
rmnet_mhi0.1
root@OpenWrt:~# quectel-CM -s cmnet -b &
[04-14_06:43:28:473] Quectel_QConnectManager_Linux_V1.6.0.25
[04-14_06:43:28:474] network interface '' or qmidev '' is not exist
[04-14_06:43:28:475] netcard driver = pcie_mhi, driver version = V1.3.0.17
[04-14_06:43:28:476] qmap_mode = 1, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1
[04-14_06:43:28:477] Modem works in QMI mode
[04-14_06:43:28:531] cdc_wdm_fd = 7
[04-14_06:43:29:532] QmiWwanInit message timeout
[04-14_06:43:30:540] Get clientWDS = 15
[04-14_06:43:30:543] Get clientDMS = 1
[04-14_06:43:30:546] Get clientNAS = 4
[04-14_06:43:30:550] Get clientUIM = 1
[04-14_06:43:30:553] Get clientWDA = 1
[04-14_06:43:30:557] requestBaseBandVersion RM500QGLABR10A03M4G
[04-14_06:43:30:560] qmap_settings.rx_urb_size = 16384
[04-14_06:43:30:561] qmap_settings.ul_data_aggregation_max_datagrams = 11
[04-14_06:43:30:561] qmap_settings.ul_data_aggregation_max_size = 8192
[04-14_06:43:30:561] qmap_settings.dl_minimum_padding = 0
[04-14_06:43:30:575] requestGetSIMStatus SIMStatus: SIM_READY
[04-14_06:43:30:575] requestSetProfile[1] cmnet///0
[04-14_06:43:30:588] requestGetProfile[1] cmnet///0
[04-14_06:43:30:591] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA
[04-14_06:43:30:595] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-14_06:43:30:595] ifconfig rmnet_mhi0 down
[04-14_06:43:30:620] ifconfig rmnet_mhi0.1 0.0.0.0
ifconfig: SIOCSIFFLAGS: Network is down
[04-14_06:43:30:644] ifconfig rmnet_mhi0.1 down
[04-14_06:43:30:679] requestSetupDataCall WdsConnectionIPv4Handle: 0xb41f47d0
[ 263.869899] net rmnet_mhi0: link_state 0x0 -> 0x1
[04-14_06:43:30:693] ifconfig rmnet_mhi0 up
[ 263.892647] [I][mhi_netdev_open] Opened net dev interface
[04-14_06:43:30:718] ifconfig rmnet_mhi0.1 up
[04-14_06:43:30:746] echo '0xa59316b' > /sys/class/net/rmnet_mhi0.1/bridge_ipv4
root@OpenWrt:~# ifconfig br0 up
[ 268.800026] br0: port 2(eth1) entered forwarding state
[ 268.800336] br0: port 2(eth1) entered forwarding state
[ 268.804251] br0: port 1(rmnet_mhi0.1) entered forwarding state
[ 268.809465] br0: port 1(rmnet_mhi0.1) entered forwarding state
[ 283.845790] br0: port 2(eth1) entered forwarding state
[ 296.512489] rmnet_mhi0.1 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 296.515756] rmnet_mhi0.1 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 296.586584] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107
[ 296.672356] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107
[ 296.792061] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107
[ 296.832822] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107
[ 296.941073] rmnet_mhi0.1 sip = 0.0.0.0, tip=10.89.49.107, ipv4=10.89.49.107
[ 297.941310] rmnet_mhi0.1 sip = 0.0.0.0, tip=10.89.49.107, ipv4=10.89.49.107
[ 298.941528] rmnet_mhi0.1 sip = 0.0.0.0, tip=10.89.49.107, ipv4=10.89.49.107
[ 299.941704] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.107, ipv4=10.89.49.107
[ 300.024484] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107
[ 300.051995] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107
[ 303.915933] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107
+138
View File
@@ -0,0 +1,138 @@
root@OpenWrt:/# lspci
00:00.0 Class 0604: 17cb:1001
01:00.0 Class ff00: 17cb:0306
root@OpenWrt:/# insmod pcie_mhi.ko qmap_mode=4
[ 61.988878] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17
[ 61.989484] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306
[ 61.994039] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit]
[ 62.003208] mhi_q 0000:01:00.0: enabling device (0140 -> 0142)
[ 62.191947] [I][mhi_netdev_enable_iface] Prepare the channels for transfer
[ 62.224065] [I][mhi_netdev_enable_iface] Exited.
[ 62.225619] rmnet_vnd_register_device(rmnet_mhi0.1)=0
[ 62.229289] rmnet_vnd_register_device(rmnet_mhi0.2)=0
[ 62.234378] rmnet_vnd_register_device(rmnet_mhi0.3)=0
[ 62.240039] rmnet_vnd_register_device(rmnet_mhi0.4)=0
root@OpenWrt:/# quectel-qmi-proxy -d /dev/mhi_QMI0 &
[04-13_09:25:12:278] Will use cdc-wdm='/dev/mhi_QMI0', proxy='quectel-qmi-proxy0'
[04-13_09:25:12:297] qmi_proxy_init enter
[04-13_09:25:12:297] qmi_proxy_loop enter thread_id 0xb6e88d44
[04-13_09:25:14:298] qmi_proxy_init succful
[04-13_09:25:14:299] local server: quectel-qmi-proxy0 sockfd = 4
[04-13_09:25:14:299] qmi_proxy_server_fd = 4
root@OpenWrt:/# quectel-CM -n 1 -s cmnet &
[04-13_09:25:32:336] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_09:25:32:337] network interface '' or qmidev '' is not exist
[04-13_09:25:32:338] netcard driver = pcie_mhi, driver version = V1.3.0.17
[04-13_09:25:32:339] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1
[04-13_09:25:32:340] Modem works in QMI mode
[04-13_09:25:32:341] connect to quectel-qmi-proxy0 sockfd = 7
[04-13_09:25:32:342] cdc_wdm_fd = 7
[04-13_09:25:32:380] requestBaseBandVersion RM500QGLABR10A03M4G
[04-13_09:25:32:382] qmap_settings.rx_urb_size = 16384
[04-13_09:25:32:383] qmap_settings.ul_data_aggregation_max_datagrams = 11
[04-13_09:25:32:383] qmap_settings.ul_data_aggregation_max_size = 8192
[04-13_09:25:32:384] qmap_settings.dl_minimum_padding = 0
[04-13_09:25:32:394] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_09:25:32:395] requestSetProfile[1] cmnet///0
[04-13_09:25:32:409] requestGetProfile[1] cmnet///0
[04-13_09:25:32:414] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA
[04-13_09:25:32:418] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_09:25:32:419] ifconfig rmnet_mhi0 down
[04-13_09:25:32:448] ifconfig rmnet_mhi0.1 0.0.0.0
[04-13_09:25:32:473] ifconfig rmnet_mhi0.1 down
[04-13_09:25:32:514] requestSetupDataCall WdsConnectionIPv4Handle: 0x2313a2a0
[ 121.648172] net rmnet_mhi0: link_state 0x0 -> 0x1
[04-13_09:25:32:525] ifconfig rmnet_mhi0 up
[ 121.671210] [I][mhi_netdev_open] Opened net dev interface
[04-13_09:25:32:551] ifconfig rmnet_mhi0.1 up
[04-13_09:25:32:586] you are use OpenWrt?
[04-13_09:25:32:587] should not calling udhcpc manually?
[04-13_09:25:32:587] should modify /etc/config/network as below?
[04-13_09:25:32:587] config interface wan
[04-13_09:25:32:588] option ifname rmnet_mhi0.1
[04-13_09:25:32:588] option proto dhcp
[04-13_09:25:32:589] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status?
[04-13_09:25:32:589] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1
udhcpc: started, v1.28.3
udhcpc: sending discover
udhcpc: sending select for 10.174.91.70
udhcpc: lease of 10.174.91.70 obtained, lease time 7200
[04-13_09:25:32:980] udhcpc: ifconfig rmnet_mhi0.1 10.174.91.70 netmask 255.255.255.252 broadcast +
[04-13_09:25:33:007] udhcpc: setting default routers: 10.174.91.69
root@OpenWrt:/# quectel-CM -n 2 -s 4gnet &
[04-13_09:25:42:976] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_09:25:42:977] network interface '' or qmidev '' is not exist
[04-13_09:25:42:978] netcard driver = pcie_mhi, driver version = V1.3.0.17
[04-13_09:25:42:978] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x82, qmap_netcard = rmnet_mhi0.2
[04-13_09:25:42:979] Modem works in QMI mode
[04-13_09:25:42:981] connect to quectel-qmi-proxy0 sockfd = 7
[04-13_09:25:42:982] cdc_wdm_fd = 7
[04-13_09:25:43:010] requestBaseBandVersion RM500QGLABR10A03M4G
[04-13_09:25:43:013] qmap_settings.rx_urb_size = 16384
[04-13_09:25:43:014] qmap_settings.ul_data_aggregation_max_datagrams = 11
[04-13_09:25:43:014] qmap_settings.ul_data_aggregation_max_size = 8192
[04-13_09:25:43:015] qmap_settings.dl_minimum_padding = 0
[04-13_09:25:43:030] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_09:25:43:030] requestSetProfile[2] 4gnet///0
[04-13_09:25:43:046] requestGetProfile[2] 4gnet///0
[04-13_09:25:43:050] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA
[04-13_09:25:43:054] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_09:25:43:055] ifconfig rmnet_mhi0.2 0.0.0.0
[04-13_09:25:43:082] ifconfig rmnet_mhi0.2 down
[04-13_09:25:43:507] requestSetupDataCall WdsConnectionIPv4Handle: 0x2332a780
[ 132.641313] net rmnet_mhi0: link_state 0x1 -> 0x3
[04-13_09:25:43:519] ifconfig rmnet_mhi0 up
[04-13_09:25:43:543] ifconfig rmnet_mhi0.2 up
[04-13_09:25:43:570] you are use OpenWrt?
[04-13_09:25:43:570] should not calling udhcpc manually?
[04-13_09:25:43:571] should modify /etc/config/network as below?
[04-13_09:25:43:571] config interface wan
[04-13_09:25:43:571] option ifname rmnet_mhi0.2
[04-13_09:25:43:572] option proto dhcp
[04-13_09:25:43:572] should use "/sbin/ifstaus wan" to check rmnet_mhi0.2 's status?
[04-13_09:25:43:573] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.2
udhcpc: started, v1.28.3
udhcpc: sending discover
udhcpc: sending select for 10.163.253.197
udhcpc: lease of 10.163.253.197 obtained, lease time 7200
[04-13_09:25:43:810] udhcpc: ifconfig rmnet_mhi0.2 10.163.253.197 netmask 255.255.255.252 broadcast +
[04-13_09:25:43:836] udhcpc: setting default routers: 10.163.253.198
root@OpenWrt:/# ifconfig rmnet_mhi0.1
rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.174.91.70 Mask:255.255.255.252
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:612 (612.0 B) TX bytes:1380 (1.3 KiB)
root@OpenWrt:/# ifconfig rmnet_mhi0.2
rmnet_mhi0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.163.253.197 Mask:255.255.255.252
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:612 (612.0 B) TX bytes:684 (684.0 B)
root@OpenWrt:/# ip ro del 8.8.8.8/32
RTNETLINK answers: No such process
root@OpenWrt:/# ip ro add 8.8.8.8/32 dev rmnet_mhi0.1
root@OpenWrt:/# 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=390.869 ms
root@OpenWrt:/# ip ro del 8.8.8.8/32
root@OpenWrt:/# ip ro del 8.8.8.8/32
RTNETLINK answers: No such process
root@OpenWrt:/# ip ro add 8.8.8.8/32 dev rmnet_mhi0.2
root@OpenWrt:/# 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=314.395 ms
@@ -0,0 +1,147 @@
root@OpenWrt:~# lspci
00:00.0 Class 0604: 17cb:1001
01:00.0 Class ff00: 17cb:0306
root@OpenWrt:~#
root@OpenWrt:~# insmod pcie_mhi.ko qmap_mode=4
[ 200.906104] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17
[ 200.907913] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306
[ 200.912164] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit]
[ 200.920593] mhi_q 0000:01:00.0: enabling device (0140 -> 0142)
root@OpenWrt:~# [ 201.112214] [I][mhi_netdev_enable_iface] Prepare the channels for transfer
[ 201.154640] [I][mhi_netdev_enable_iface] Exited.
[ 201.159271] rmnet_vnd_register_device(rmnet_mhi0.1)=0
[ 201.162953] rmnet_vnd_register_device(rmnet_mhi0.2)=0
[ 201.167698] rmnet_vnd_register_device(rmnet_mhi0.3)=0
[ 201.172178] rmnet_vnd_register_device(rmnet_mhi0.4)=0
root@OpenWrt:~# brctl addbr br0
root@OpenWrt:~# brctl addif br0 eth1
root@OpenWrt:~# brctl addif br0 rmnet_mhi0.2
root@OpenWrt:~# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.00001c353487 no eth1
rmnet_mhi0.2
root@OpenWrt:~# quectel-qmi-proxy -d /dev/mhi_QMI0 &
[04-14_06:44:01:556] Will use cdc-wdm='/dev/mhi_QMI0', proxy='quectel-qmi-proxy0'
[04-14_06:44:01:573] qmi_proxy_init enter
[04-14_06:44:01:573] qmi_proxy_loop enter thread_id 0xb6f20d44
[04-14_06:44:03:574] qmi_proxy_init succful
[04-14_06:44:03:574] local server: quectel-qmi-proxy0 sockfd = 4
[04-14_06:44:03:575] qmi_proxy_server_fd = 4
root@OpenWrt:~# quectel-CM -n 1 -s cmnet &
[04-14_06:47:53:303] Quectel_QConnectManager_Linux_V1.6.0.25
[04-14_06:47:53:314] network interface '' or qmidev '' is not exist
[04-14_06:47:53:315] netcard driver = pcie_mhi, driver version = V1.3.0.17
[04-14_06:47:53:316] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1
[04-14_06:47:53:316] Modem works in QMI mode
[04-14_06:47:53:318] connect to quectel-qmi-proxy0 sockfd = 7
[04-14_06:47:53:318] cdc_wdm_fd = 7
[04-14_06:47:53:326] Get clientWDS = 15
[04-14_06:47:53:329] Get clientDMS = 2
[04-14_06:47:53:334] Get clientNAS = 4
[04-14_06:47:53:338] Get clientUIM = 1
[04-14_06:47:53:343] Get clientWDA = 1
[04-14_06:47:53:347] requestBaseBandVersion RM500QGLABR10A03M4G
[04-14_06:47:53:351] qmap_settings.rx_urb_size = 16384
[04-14_06:47:53:352] qmap_settings.ul_data_aggregation_max_datagrams = 11
[04-14_06:47:53:352] qmap_settings.ul_data_aggregation_max_size = 8192
[04-14_06:47:53:352] qmap_settings.dl_minimum_padding = 0
[04-14_06:47:53:369] requestGetSIMStatus SIMStatus: SIM_READY
[04-14_06:47:53:370] requestSetProfile[1] cmnet///0
[04-14_06:47:53:402] requestGetProfile[1] cmnet///0
[04-14_06:47:53:407] requestRegistrationState2 MCC: 0, MNC: 0, PS: Detached, DataCap: UNKNOW
[04-14_06:47:53:411] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-14_06:47:53:412] ifconfig rmnet_mhi0 down
[04-14_06:47:53:436] ifconfig rmnet_mhi0.1 0.0.0.0
[04-14_06:47:53:460] ifconfig rmnet_mhi0.1 down
[04-14_06:48:26:399] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW
[04-14_06:48:26:405] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW
[04-14_06:48:26:411] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW
[04-14_06:48:26:970] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA
[04-14_06:48:26:992] requestSetupDataCall WdsConnectionIPv4Handle: 0x34176710
[04-14_06:48:27:005] ifconfig rmnet_mhi0 up
[04-14_06:48:27:031] ifconfig rmnet_mhi0.1 up
[04-14_06:48:27:057] you are use OpenWrt?
[04-14_06:48:27:057] should not calling udhcpc manually?
[04-14_06:48:27:080] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status?
[04-14_06:48:27:081] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1
[04-14_06:48:27:363] udhcpc: ifconfig rmnet_mhi0.1 10.245.22.3 netmask 255.255.255.248 broadcast +
[04-14_06:48:27:398] udhcpc: setting default routers: 10.245.22.4
[04-14_06:48:27:491] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA
root@OpenWrt:~# quectel-CM -n 2 -s 4gnet -b &
[04-14_06:48:06:842] Quectel_QConnectManager_Linux_V1.6.0.25
[04-14_06:48:06:853] network interface '' or qmidev '' is not exist
[04-14_06:48:06:854] netcard driver = pcie_mhi, driver version = V1.3.0.17
[04-14_06:48:06:855] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x82, qmap_netcard = rmnet_mhi0.2
[04-14_06:48:06:855] Modem works in QMI mode
[04-14_06:48:06:857] connect to quectel-qmi-proxy0 sockfd = 7
[04-14_06:48:06:858] cdc_wdm_fd = 7
[04-14_06:48:06:864] Get clientWDS = 16
[04-14_06:48:06:867] Get clientDMS = 3
[04-14_06:48:06:871] Get clientNAS = 5
[04-14_06:48:06:874] Get clientUIM = 2
[04-14_06:48:06:879] Get clientWDA = 2
[04-14_06:48:06:886] requestBaseBandVersion RM500QGLABR10A03M4G
[04-14_06:48:06:891] qmap_settings.rx_urb_size = 16384
[04-14_06:48:06:891] qmap_settings.ul_data_aggregation_max_datagrams = 11
[04-14_06:48:06:892] qmap_settings.ul_data_aggregation_max_size = 8192
[04-14_06:48:06:892] qmap_settings.dl_minimum_padding = 0
[04-14_06:48:06:909] requestGetSIMStatus SIMStatus: SIM_READY
[04-14_06:48:06:909] requestSetProfile[2] 4gnet///0
[04-14_06:48:06:940] requestGetProfile[2] 4gnet///0
[04-14_06:48:06:944] requestRegistrationState2 MCC: 0, MNC: 0, PS: Detached, DataCap: UNKNOW
[04-14_06:48:06:949] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-14_06:48:06:949] ifconfig rmnet_mhi0 down
[04-14_06:48:06:973] ifconfig rmnet_mhi0.2 0.0.0.0
[04-14_06:48:06:998] ifconfig rmnet_mhi0.2 down
[04-14_06:48:26:400] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW
[04-14_06:48:26:405] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW
[04-14_06:48:26:411] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW
[04-14_06:48:26:970] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA
[04-14_06:48:27:220] requestSetupDataCall WdsConnectionIPv4Handle: 0x341450a0
[04-14_06:48:27:228] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA
[04-14_06:48:27:238] ifconfig rmnet_mhi0 up
[04-14_06:48:27:263] ifconfig rmnet_mhi0.2 up
[04-14_06:48:27:313] echo '0xaf51be9' > /sys/class/net/rmnet_mhi0.2/bridge_ipv4
root@OpenWrt:~# ifconfig rmnet_mhi0.1
rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet addr:10.245.22.3 Mask:255.255.255.248
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:1836 (1.7 KiB) TX bytes:2052 (2.0 KiB)
root@OpenWrt:~# ifconfig rmnet_mhi0.2
rmnet_mhi0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00
inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:347 errors:0 dropped:0 overruns:0 frame:0
TX packets:795 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:119871 (117.0 KiB) TX bytes:121254 (118.4 KiB)
root@OpenWrt:~# ifconfig br0 up
[ 520.005476] rmnet_mhi0.2 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 520.025896] rmnet_mhi0.2 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 520.028002] rmnet_mhi0.2 PC Mac Address: 00:0e:c6:a6:6c:f1
[ 520.144371] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233
[ 520.410052] rmnet_mhi0.2 sip = 0.0.0.0, tip=10.245.27.233, ipv4=10.245.27.233
[ 520.414504] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233
[ 520.847074] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233
[ 521.410241] rmnet_mhi0.2 sip = 0.0.0.0, tip=10.245.27.233, ipv4=10.245.27.233
[ 522.410455] rmnet_mhi0.2 sip = 0.0.0.0, tip=10.245.27.233, ipv4=10.245.27.233
[ 522.822594] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233
[ 523.410638] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.233, ipv4=10.245.27.233
[ 523.510028] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233
[ 523.997961] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233
[ 543.799483] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233
[ 543.929301] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233
+65
View File
@@ -0,0 +1,65 @@
root@ZhuoTK:/# dmesg
[ 15.840000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device
[ 15.860000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode
[ 15.860000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 1520
[ 15.870000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, WWAN/QMI device, da:0b:ce:b2:db:21
root@ZhuoTK:/# quectel-CM -s cment &
[04-13_03:20:20:456] Quectel_QConnectManager_Linux_V1.6.0.25
[04-13_03:20:20:459] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003
[04-13_03:20:20:460] Auto find qmichannel = /dev/cdc-wdm0
[04-13_03:20:20:460] Auto find usbnet_adapter = wwan0
[04-13_03:20:20:461] netcard driver = qmi_wwan_q, driver version = V1.2.0.23
[04-13_03:20:20:461] Modem works in QMI mode
[04-13_03:20:20:469] cdc_wdm_fd = 7
[04-13_03:20:20:547] Get clientWDS = 4
[04-13_03:20:20:579] Get clientDMS = 1
[04-13_03:20:20:611] Get clientNAS = 4
[04-13_03:20:20:643] Get clientUIM = 1
[04-13_03:20:20:675] Get clientWDA = 1
[04-13_03:20:20:707] requestBaseBandVersion EC25EFAR06A11M4G
[04-13_03:20:20:836] requestGetSIMStatus SIMStatus: SIM_READY
[04-13_03:20:20:836] requestSetProfile[1] cment///0
[04-13_03:20:20:899] requestGetProfile[1] cment///0
[04-13_03:20:20:931] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE
[04-13_03:20:20:963] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[04-13_03:20:20:963] ifconfig wwan0 0.0.0.0
[04-13_03:20:20:976] ifconfig wwan0 down
[04-13_03:20:21:186] requestSetupDataCall WdsConnectionIPv4Handle: 0x8723e780
[04-13_03:20:21:316] ifconfig wwan0 up
[04-13_03:20:21:329] you are use OpenWrt?
[04-13_03:20:21:330] should not calling udhcpc manually?
[04-13_03:20:21:330] should modify /etc/config/network as below?
[04-13_03:20:21:330] config interface wan
[04-13_03:20:21:330] option ifname wwan0
[04-13_03:20:21:330] option proto dhcp
[04-13_03:20:21:330] should use "/sbin/ifstaus wan" to check wwan0 's status?
[04-13_03:20:21:331] busybox udhcpc -f -n -q -t 5 -i wwan0
[04-13_03:20:21:341] udhcpc (v1.23.2) started
[04-13_03:20:21:353] Sending discover...
[04-13_03:20:21:362] Sending select for 10.90.1.113...
[04-13_03:20:21:365] Lease of 10.90.1.113 obtained, lease time 7200
[04-13_03:20:21:370] udhcpc: ifconfig wwan0 10.90.1.113 netmask 255.255.255.252 broadcast +
[04-13_03:20:21:380] udhcpc: setting default routers: 10.90.1.114
root@ZhuoTK:/# ifconfig wwan0
wwan0 Link encap:Ethernet HWaddr 00:CA:01:91:97:BA
inet addr:10.90.1.113 Mask:255.255.255.252
inet6 addr: fe80::2ca:1ff:fe91:97ba/64 Scope:Link
UP RUNNING NOARP MTU:1500 Metric:1
RX packets:38 errors:0 dropped:0 overruns:0 frame:0
TX packets:46 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:5244 (5.1 KiB) TX bytes:6964 (6.8 KiB)
root@ZhuoTK:/# ip ro show
default via 10.90.1.114 dev wwan0
10.90.1.112/30 dev wwan0 proto kernel scope link src 10.90.1.113
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:20:46:130] requestDeactivateDefaultPDP WdsConnectionIPv4Handle
[04-13_03:20:46:406] ifconfig wwan0 0.0.0.0
[04-13_03:20:46:418] ifconfig wwan0 down
[04-13_03:20:46:600] QmiWwanThread exit
[04-13_03:20:46:600] qmi_main exit
Loaded 100 of 289 files, more files were not shown because too many files have changed in this diff. Show more