LTE Modem Firmware (QMI)

OpenWRT allows to select a custom Firmware for the DSL Chipset.
Is this also possible for LTE Modems? Let me explain:

Besides USB LTE Sticks, there are also Modems as expansion card, typically in Mini PCI Express or M.2 NGFF (B-Key) formfactor which are often used in Notebooks, but also in LTE Routers. These cards can easily be used with every router via USB adapter, for example this or this.

As far as i know, the difference compared to USB Sticks is, that the Firmware is not permanently flashed to the device itself, at least not completely. Parts of it is loaded into the device during every boot. As an example, let's take some older Qualcomm MDM9625 chipset which is used in alot of devices and can be obtained cheap nowadays.

Here's one device as sample:
HP lt4120 Snapdragon x5 LTE (rebranded T77W595 from "HON HAI" aka. Foxconn).
After installing the Driver from the HP Website, you can find the firmware file under:
C:\Program Files (x86)\HP lt4120 Snapdragon X5 LTE\Image

Also, here's a guide from somebody who already utilized the firmware under Linux:

So, if there would be an easy way in LuCI like for DSL chipsets, that would be awesome!

Best Regards!

This model LT4120 sounds like something to avoid. That is not standard. Nearly all PCI LTE modems hold their complete firmware permanently in flash on the modem card. A firmware load is only needed if it is desired to upgrade. It is not necessary to routinely boot any firmware into the card at startup.

Also whether the card is PCI or M2, that is only the physical shape. The electrical interface is always USB. Thus simple passive adapters exist to "convert" the card to plug into a USB port.

I think the post in the blog was not clear, that script is only running ONCE to update firwmare and reconfigure the modem. Then you can place the modem in the router and it will work like other modems.

The script is clearly flashing firmware to modem, at the end of firmware load commands it is asking a modem reboot, that would clear the RAM and anything after that comes from onboard modem flash storage. So I don't think that is needed every boot.

Also the config upload step is very likely a permanent load https://github.com/borovsky/x5-snapdragon-linux/blob/master/copy-firmware.sh#L90

As for the udev script https://github.com/borovsky/x5-snapdragon-linux/blob/master/udev/99-hp-lt4120.rules
OpenWrt has no udev, and afaik you usually select the modem interface manually so it does not need this.

Going back to the previous blog post, it seems correct.

After flashing
After flashing modem still don't work. Looks like it require one more part: selecting active config, that is done by MCFG.exe executable. Looks like it use PDC service interface, that completely missed in libqmi. So it will be next target.

this is just a single command, to tell the modem what of the onboard configs it should use.
From his scripts it is
qmicli -p -d "$DEVICE" --pdc-activate-config="$ACTIVE_CONFIG_ID"

I still think this is a permanent command, but I don't know.

asking a modem expert
@bmork

2 Likes

The Gobi 1k and 2k modems loaded firmware in RAM using the gobi-loader. But these are 10+ year old 3G modems and not very relevant anymore.

All later modems I know of, store their firmware in flash. But Qualcomm continued to provide different "firmwares" for different operators, like for the early Gobi modems, stored on the host. When switching to an operator requiring a different firmware, the drivers would automatically reboot the modem and flash the correct firmware. Not exactly the best user experience if you ask me...

In most cases, the differences between these firmware versions were just a few configuration defaults. Rebooting the modem and flashing the whole image just to change a few settings is a bit of an overkill.

Newer modems got support for multiple images on flash, making it possible to do such switching without loading anything new. But the modem would still reboot and copy files, and sometimes whole images, around. This can take a lot of time. So it's still not very user friendly.

Anyway, most users won't change operator so they don't need to flash anything unless they want to upgrade the firmware image stored on the modem. And most operators will work fine with generic firmware/defaults. So if you have a known good firmware on the modem, then I don't see any reason to want to flash a new one.

We do have some support for modem firmware upgrades (like qmi-firmware-update for some Sierra Wireless modems), but the procedure and images are vendor and mdoel specific so streamlining the process is probably not going to happen. Users with externally connected modems usually prefer to temporarily use a host supported by vendor tools for the occasional upgrade.

3 Likes

Thanks for your quick answers. I tried setting up the LTE Modem using this guide, but i failed. My expectation would be that every Qualcomm Chipset works with QMI, but maybe i am missing something. Step 3 is where i failed:

root@OpenWrt:~# ls -l /dev/cdc-wdm0
ls: /dev/cdc-wdm0: No such file or directory

cat /sys/kernel/debug/usb/devices

root@OpenWrt:~# cat /sys/kernel/debug/usb/devices

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480  MxCh= 1
B:  Alloc=  0/800 us ( 0%), #Int=  0, #Iso=  0
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0002 Rev= 4.14
S:  Manufacturer=Linux 4.14.241 ehci_hcd
S:  Product=EHCI Host Controller
S:  SerialNumber=101c0000.ehci
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   4 Ivl=256ms

T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs=  3
P:  Vendor=03f0 ProdID=9d1d Rev= 2.28
S:  Manufacturer=HP
S:  Product=HP lt4120 Snapdragon X5 LTE
S:  SerialNumber=0123456789ABCDEF
C:  #Ifs= 5 Cfg#= 1 Atr=e0 MxPwr=500mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:  If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=
E:  Ad=83(I) Atr=03(Int.) MxPS=   8 Ivl=32ms
E:  Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:  If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E:  Ad=85(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
E:  Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:  If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E:  Ad=87(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
E:  Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:  If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E:  Ad=89(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
E:  Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
C:* #Ifs= 2 Cfg#= 2 Atr=e0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=(none)
E:  Ad=82(I) Atr=03(Int.) MxPS=  16 Ivl=32ms
I:* If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver=(none)
I:  If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=(none)
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
C:  #Ifs= 3 Cfg#= 3 Atr=e0 MxPwr=500mA
A:  FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=0e Prot=00
I:  If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0e Prot=00 Driver=
E:  Ad=82(I) Atr=03(Int.) MxPS=  64 Ivl=32ms
I:  If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=02 Driver=
I:  If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:  If#= 2 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=ff Driver=
E:  Ad=83(I) Atr=03(Int.) MxPS=  64 Ivl=32ms

T:  Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 1
B:  Alloc=  0/900 us ( 0%), #Int=  0, #Iso=  0
D:  Ver= 1.10 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0001 Rev= 4.14
S:  Manufacturer=Linux 4.14.241 ohci_hcd
S:  Product=Generic Platform OHCI controller
S:  SerialNumber=101c1000.ohci
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   2 Ivl=255ms

dmesg

root@OpenWrt:~# dmesg
[    0.000000] Linux version 4.14.241 (builder@buildhost) (gcc version 7.5.0 (OpenWrt GCC 7.5.0 r11364-ef56c85848)) #0 Thu Jul 29 19:50:28 2021
[    0.000000] Board has DDR2
[    0.000000] Analog PMU set to hw control
[    0.000000] Digital PMU set to hw control
[    0.000000] SoC Type: MediaTek MT7628AN ver:1 eco:2
[    0.000000] bootconsole [early0] enabled
[    0.000000] CPU0 revision is: 00019655 (MIPS 24KEc)
[    0.000000] MIPS: machine is TP-Link TL-MR3420 v5
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 04000000 @ 00000000 (usable)
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
[    0.000000] Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] On node 0 totalpages: 16384
[    0.000000] free_area_init_node: node 0, pgdat 80485ab0, node_mem_map 81000040
[    0.000000]   Normal zone: 128 pages used for memmap
[    0.000000]   Normal zone: 0 pages reserved
[    0.000000]   Normal zone: 16384 pages, LIFO batch:3
[    0.000000] random: get_random_bytes called from 0x80487740 with crng_init=0
[    0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[    0.000000] pcpu-alloc: [0] 0
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 16256
[    0.000000] Kernel command line: console=ttyS0,115200 rootfstype=squashfs,jffs2
[    0.000000] PID hash table entries: 256 (order: -2, 1024 bytes)
[    0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Writing ErrCtl register=00063d0a
[    0.000000] Readback ErrCtl register=00063d0a
[    0.000000] Memory: 58816K/65536K available (3937K kernel code, 183K rwdata, 504K rodata, 1188K init, 208K bss, 6720K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS: 256
[    0.000000] intc: using register map from devicetree
[    0.000000] CPU Clock: 580MHz
[    0.000000] timer_probe: no matching timers found
[    0.000000] clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 6590553264 ns
[    0.000010] sched_clock: 32 bits at 290MHz, resolution 3ns, wraps every 7405115902ns
[    0.007571] Calibrating delay loop... 385.84 BogoMIPS (lpj=1929216)
[    0.073516] pid_max: default: 32768 minimum: 301
[    0.078181] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.084538] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.096496] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.105988] futex hash table entries: 256 (order: -1, 3072 bytes)
[    0.111924] pinctrl core: initialized pinctrl subsystem
[    0.119400] NET: Registered protocol family 16
[    0.143596] mt7621_gpio 10000600.gpio: registering 32 gpios
[    0.149243] mt7621_gpio 10000600.gpio: registering 32 gpios
[    0.154749] mt7621_gpio 10000600.gpio: registering 32 gpios
[    0.164919] clocksource: Switched to clocksource MIPS
[    0.170895] NET: Registered protocol family 2
[    0.175257] IP idents hash table entries: 2048 (order: 2, 16384 bytes)
[    0.182222] TCP established hash table entries: 1024 (order: 0, 4096 bytes)
[    0.188979] TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
[    0.195092] TCP: Hash tables configured (established 1024 bind 1024)
[    0.201332] UDP hash table entries: 256 (order: 0, 4096 bytes)
[    0.206981] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[    0.213235] NET: Registered protocol family 1
[    0.217453] PCI: CLS 0 bytes, default 32
[    0.220610] Crashlog allocated RAM at address 0x3f00000
[    0.227249] workingset: timestamp_bits=30 max_order=14 bucket_order=0
[    0.238896] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.244469] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
[    0.264226] io scheduler noop registered
[    0.268018] io scheduler deadline registered (default)
[    0.273762] Serial: 8250/16550 driver, 16 ports, IRQ sharing enabled
[    0.282471] console [ttyS0] disabled
[    0.285971] 10000c00.uartlite: ttyS0 at MMIO 0x10000c00 (irq = 28, base_baud = 2500000) is a 16550A
[    0.294674] console [ttyS0] enabled
[    0.301715] bootconsole [early0] disabled
[    0.311134] spi-mt7621 10000b00.spi: sys_freq: 193333333
[    0.324870] m25p80 spi0.0: gd25q64 (8192 Kbytes)
[    0.329672] 4 fixed-partitions partitions found on MTD device spi0.0
[    0.336138] Creating 4 MTD partitions on "spi0.0":
[    0.341005] 0x000000000000-0x000000020000 : "boot"
[    0.346730] 0x000000020000-0x0000007c0000 : "firmware"
[    0.354682] 2 tplink-fw partitions found on MTD device firmware
[    0.360763] Creating 2 MTD partitions on "firmware":
[    0.365831] 0x000000000000-0x00000018007e : "kernel"
[    0.371729] 0x000000180080-0x0000007a0000 : "rootfs"
[    0.377536] mtd: device 3 (rootfs) set to be root filesystem
[    0.384748] 1 squashfs-split partitions found on MTD device rootfs
[    0.391111] 0x0000003e0000-0x0000007a0000 : "rootfs_data"
[    0.397444] 0x0000007c0000-0x0000007d0000 : "config"
[    0.403240] 0x0000007d0000-0x000000800000 : "factory"
[    0.409863] libphy: Fixed MDIO Bus: probed
[    0.426182] rt3050-esw 10110000.esw: link changed 0x00
[    0.432955] mtk_soc_eth 10100000.ethernet eth0: mediatek frame engine at 0xb0100000, irq 5
[    0.443015] NET: Registered protocol family 10
[    0.451571] Segment Routing with IPv6
[    0.455465] NET: Registered protocol family 17
[    0.460024] bridge: filtering via arp/ip/ip6tables is no longer available by default. Update your scripts to load br_netfilter if you need this.
[    0.473185] 8021q: 802.1Q VLAN Support v1.8
[    0.487528] VFS: Mounted root (squashfs filesystem) readonly on device 31:3.
[    0.501193] Freeing unused kernel memory: 1188K
[    0.505820] This architecture does not have kernel memory protection.
[    1.596056] init: Console is alive
[    1.599758] init: - watchdog -
[    2.204930] random: fast init done
[    2.776089] kmodloader: loading kernel modules from /etc/modules-boot.d/*
[    2.860763] usbcore: registered new interface driver usbfs
[    2.866489] usbcore: registered new interface driver hub
[    2.871961] usbcore: registered new device driver usb
[    2.882645] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    2.890975] ehci-platform: EHCI generic platform driver
[    2.906645] phy phy-10120000.usbphy.0: remote usb device wakeup disabled
[    2.913447] phy phy-10120000.usbphy.0: UTMI 16bit 30MHz
[    2.918778] ehci-platform 101c0000.ehci: EHCI Host Controller
[    2.924664] ehci-platform 101c0000.ehci: new USB bus registered, assigned bus number 1
[    2.932835] ehci-platform 101c0000.ehci: irq 26, io mem 0x101c0000
[    2.964948] ehci-platform 101c0000.ehci: USB 2.0 started, EHCI 1.00
[    2.972225] hub 1-0:1.0: USB hub found
[    2.976493] hub 1-0:1.0: 1 port detected
[    2.983630] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    2.991524] ohci-platform: OHCI generic platform driver
[    2.997173] ohci-platform 101c1000.ohci: Generic Platform OHCI controller
[    3.004095] ohci-platform 101c1000.ohci: new USB bus registered, assigned bus number 2
[    3.012259] ohci-platform 101c1000.ohci: irq 26, io mem 0x101c1000
[    3.089854] hub 2-0:1.0: USB hub found
[    3.094043] hub 2-0:1.0: 1 port detected
[    3.103317] kmodloader: done loading kernel modules from /etc/modules-boot.d/*
[    3.121241] init: - preinit -
[    4.425022] rt3050-esw 10110000.esw: link changed 0x00
[    4.596796] random: procd: uninitialized urandom read (4 bytes read)
[    7.480348] rt3050-esw 10110000.esw: link changed 0x02
[    7.726751] rt3050-esw 10110000.esw: link changed 0x00
[    7.959295] jffs2: notice: (396) jffs2_build_xattr_subsystem: complete building xattr subsystem, 7 of xdatum (3 unchecked, 4 orphan) and 35 of xref (4 dead, 0 orphan) found.
[    7.981522] mount_root: switching to jffs2 overlay
[    8.012598] overlayfs: upper fs does not support tmpfile.
[    8.029681] urandom-seed: Seeding with /etc/urandom.seed
[    8.217011] procd: - early -
[    8.220060] procd: - watchdog -
[    8.927232] random: jshn: uninitialized urandom read (4 bytes read)
[    9.012150] procd: - watchdog -
[    9.016451] procd: - ubus -
[    9.265812] random: ubusd: uninitialized urandom read (4 bytes read)
[    9.286316] random: ubusd: uninitialized urandom read (4 bytes read)
[    9.306243] procd: - init -
[    9.785060] usb 1-1: new high-speed USB device number 2 using ehci-platform
[   10.092773] usb 1-1: usbfs: process 502 (usbmode) did not claim interface 1 before use
[   10.325636] usb 1-1: usbfs: interface 1 claimed by usbfs while 'usbmode' sets config #0
[   10.535453] rt3050-esw 10110000.esw: link changed 0x02
[   10.971681] kmodloader: loading kernel modules from /etc/modules.d/*
[   11.116167] usb 1-1: usbfs: process 568 (usbmode) did not claim interface 1 before use
[   11.298124] ip6_tables: (C) 2000-2006 Netfilter Core Team
[   11.351775] usb 1-1: usbfs: interface 1 claimed by usbfs while 'usbmode' sets config #0
[   11.366707] usbcore: registered new interface driver cdc_wdm
[   11.395935] Loading modules backported from Linux version v4.19.193-0-g1722257b8ece
[   11.403713] Backport generated by backports.git v4.19.193-1-0-gaa2cc8ea
[   11.466637] ip_tables: (C) 2000-2006 Netfilter Core Team
[   11.505323] nf_conntrack version 0.5.0 (1024 buckets, 4096 max)
[   11.798865] usbcore: registered new interface driver usbserial
[   11.804867] usbcore: registered new interface driver usbserial_generic
[   11.811644] usbserial: USB Serial support registered for generic
[   11.985708] xt_time: kernel timezone is -0000
[   11.991501] urngd: v1.0.2 started.
[   12.132302] usb 1-1: usbfs: process 647 (usbmode) did not claim interface 1 before use
[   12.215108] mt76_wmac 10300000.wmac: ASIC revision: 76280001
[   12.367124] usb 1-1: usbfs: interface 1 claimed by usbfs while 'usbmode' sets config #0
[   12.470564] random: crng init done
[   12.474030] random: 6 urandom warning(s) missed due to ratelimiting
[   13.257681] mt76_wmac 10300000.wmac: Firmware Version: 20151201
[   13.263702] mt76_wmac 10300000.wmac: Build Time: 20151201183641
[   13.304942] mt76_wmac 10300000.wmac: firmware init done
[   13.474702] ieee80211 phy0: Selected rate control algorithm 'minstrel_ht'
[   13.510017] PPP generic driver version 2.4.2
[   13.525897] NET: Registered protocol family 24
[   13.553952] usbcore: registered new interface driver qmi_wwan
[   13.608625] usbcore: registered new interface driver option
[   13.614360] usbserial: USB Serial support registered for GSM modem (1-port)
[   13.725272] kmodloader: done loading kernel modules from /etc/modules.d/*
[   19.302842] rt3050-esw 10110000.esw: link changed 0x00
[   20.362361] usb 1-1: usbfs: process 1022 (usbmode) did not claim interface 1 before use
[   20.637441] usb 1-1: usbfs: interface 1 claimed by usbfs while 'usbmode' sets config #0
[   23.415370] rt3050-esw 10110000.esw: link changed 0x02
[   25.554126] br-lan: port 1(eth0.1) entered blocking state
[   25.559688] br-lan: port 1(eth0.1) entered disabled state
[   25.565528] device eth0.1 entered promiscuous mode
[   25.570390] device eth0 entered promiscuous mode
[   25.600468] br-lan: port 1(eth0.1) entered blocking state
[   25.606024] br-lan: port 1(eth0.1) entered forwarding state
[   25.611910] IPv6: ADDRCONF(NETDEV_UP): br-lan: link is not ready
[   26.603977] IPv6: ADDRCONF(NETDEV_CHANGE): br-lan: link becomes ready

This modem presents 3 different configurations (the "C" prefix), and you can see by the * that Linux has selected cfg #2. Cfg #1 was skpped becasue the first interface there is vendor specific. This is somewhat unwanted now that we have plenty of drivers for vendor specific USB functions. But it has been like that from the very beginning of USB and we can't change it without breaking stuff for those who depend on it.

Anyway, cfg #2 has a CDC ECM function and I guess you haven't installed kmod-usb-net-cdc-ether.

But as you say: You will probably use this is QMI mode, which I guess is cfg #1 or MBIM mode which is cfg #3. Take a look at the usbmode configurations. It has the tools to automatically switch these modes, but might not be confgured properly for your modem? I see from the log that it is trying to do something. Not sure exactly what.

In theory, changing configuration is as simple as writing the requested number to /sys/bus/usb/devices/1-1/bConfigurationValue. But many modem firmwares are picky about when you do that, so it's always best to do it as early as possible after discovery. You could use it for testing though. Should at least load the proper drivers. And might work too

EDIT: I looked at the usb_modeswitch data for this modem and found that it has Configuration=0. Which is a magic value meaning "don't touch". Cfg #3 will be selected by the default MBIM preference, if the cdc_mbim driver is installed. See original reasoning here: https://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?t=2630

I'm not sure if the OpenWrt usbmode package replicates this logic or not, but it might be worth trying to install kmod-usb-net-cdc-mbim and then reboot

EDIT2: No, usbmode doesn't do that automagic MBIM mode. You have to explicitly request it. Actually looks like a bug to fix. Simply using all those Configuration=0.entries without translation makes no sense

1 Like

you can look at the commands that are run on hotplug of the modem in the udev script of the person in the blog post to see if it helps understanding

It seems it is setting the modem to cfg 3, but the comment says it's forcing config 1

but he is also loading qmi_wwan module which is for QMI I think

2 Likes

Anyway, cfg #2 has a CDC ECM function and I guess you haven't installed kmod-usb-net-cdc-ether.

exactly, i didn't. My initial plan was to go with qmi...
So, looks like i have 3 possible ways to go:

QMI
CDC ECM
MBIM

What is the preferred or best way? Is there any difference in performance, compatibility or any other advantages/disadvantages? What would you do?

I would use either QMI or MBIM. ECM has no well-defined management protocol. I assume it runs a web portal, looking more like a router. Not my cup of tea :slight_smile:

MBIM is most likely the only mode ever tested by the vendor, since this is a laptop modem and Windows 8 and newer requires MBIM. So I'd probably go for that. Always safest to do whatever Windows does.

2 Likes

Hi @bmork

Alright, then i'll try to go with MBIM. I have a few questions left before i try:

  1. kmod-usb-net-cdc-ether is only needed for CDC ECM function, correct?

  2. The package "luci-proto-qmi" is used to set up things in LuCI. Is such a package also available for MBIM? If not: i read here that "QMI over MBIM" is possible, does that mean the luci-proto-qmi package would also work in MBIM mode? If not: am i not able to configure things in LuCI if i use the MBIM mode?

  3. You wrote that usbmode doesn't automatically switch to MBIM mode. If found this guide, but it seems like i am to dumb to understand what i have to do. I don't have to change the vendor and product id, right? I only have to change the cfg of the device. I guess this is done with the "messages"? How do i know what message to send?

Also: thank you for your help!

  1. correct
  2. I don't know if there is a specific luci frontend for mbim. maybe someone else? There is always luci-proto-modemmanager (using modemmanager obviously), if your running this on a powerful enough router
  3. I believe the default entry for your modem is something like this:
                "03f0:9d1d": {
                        "*": {
                                "msg": [  ],
                                "config": 0
                        }
                }

Change the "config" value to 1 for QMI, 2 for ECM or 3 for MBIM (based on the /sys/kernel/debug/usb/devices you posted earlier).

This modem doesn't use any magic messages to switch personalities. So "msg" is not in use.

1 Like

There is an open PR about it in Luci repo https://github.com/openwrt/luci/pull/4360 and an accompanying PR from the same developer https://github.com/openwrt/openwrt/pull/3317 (closed after he lost patience) and another PR in the core repo that would also let the Luci app work https://github.com/openwrt/openwrt/pull/2759 that is still open.
Seems like nobody is able to review it in years so it's just there bitrotting while interested parties just carry it as a patch in their own builds.

So luci-proto-modemmanager is the only way for gui support of MBIM at the moment.

1 Like

Thanks!

i changed 0 to 3, but still, the 2 config is loaded.... I made sure that 03f0:9d1d are the correct id's.
Any idea, why i can't load the 3. config? I noticed that some other devices inside the usb-mode.json have brackets around the number, could that be the reason?

weird.. i am not able to install luci-proto-modemmanager via opkg. I got a generic error "can not install..."

I am able to find modemmanager, but not luci-proto-modemmanager

That package is available from next OpenWrt release onwards. It's not in OpenWrt 19.07 release.

If you need that package you must first upgrade your firmware to OpenWrt 21.02-rc4 (release candidate 4) version

You can find a release for your device from here https://downloads.openwrt.org/releases/21.02.0-rc4/targets/ travel down the same folders as the link you used to download the version 19.07 to find the firmware file, or tell me what device that is and I can find the firmware in there

1 Like

awesome, thanks! I'm going to try that release tomorrow.

Sorry, I have no idea why that doesn't work. My experience with usbmode is limited. Could be something obvious I'm missing. I don't know how to debug it further. Let's hope there is an expert in the room...

One thing you could try is to replace the "config" setting with "mode": "MBIM". That's an alternate way to say the same thing. Shouldn't make a difference but worth trying just in case

Make sure you got the commas right when you edit JSON structs. There is a comma after each record/element except the last one in each block.

The "config" setting is a single integer. There should be no brackets around it. I assume the other numbers you look at is "t_product" or "msg"? These are arrays and need brackets.

That worked! I wasn't able to select any config using the "config" parameter. No matter which value i entered (1, 2 or 3), the config was always #2. But when i used the "mode" parameter instead, i was able to switch to MBIM mode (= cfg #3).

Unfortunately, my TP-Link TL-MR3420 has not enough space to run 21.02.0-rc4 and luci-proto-modemmanager. But since i would like to have a GUI for setting up the Modem settings, my only option is to continue using OpenWRT 19.07.8 along with luci-proto-qmi.

But that requires to run the modem in QMI mode. Unfortunately, "mode": "QMI" does not work :frowning:
Is QMI also a valid option for the "mode" parameter? Maybe another notation?

Yes, that would be "config": 1.

The "config": setting doesn't work at all. No matter which value i entered (1, 2 or 3), the active config was always #2.

But when i used the "mode" parameter instead, i was able to switch to MBIM mode (= cfg #3).