Software Consulting & Engineering Requirements to Production

Stumbling blocks - the Quectel EM05-G LTE Modem under Fedora 39

An attempt to collect all the scattered information needed for a successful connection to an LTE network using the Quectel EM05-G as found in the Lenovo T14s Gen 3 AMD. The notes pair specific problems with solutions for this setup.

Introduction

Context

At the time of writing:

  • libmbim-utils-1.28.4-2.fc39.x86_64
  • ModemManager-1.20.6-3.fc39.x86_64

Open issues:

  • Suspend Resume
  • SIM Locking

Sources

The Goal

In the end, we want a working connection via mobile broadband (3GPP, LTE / 4G).

Mai 14 21:09:06 spacegray ModemManager[18425]: <info>  [modem0] 3GPP registration state changed (idle -> registering)
Mai 14 21:09:06 spacegray ModemManager[18425]: <info>  [modem0] 3GPP registration state changed (registering -> home)
Mai 14 21:09:06 spacegray ModemManager[18425]: <info>  [modem0] state changed (enabled -> registered)
Mai 14 21:09:06 spacegray ModemManager[18425]: <info>  [modem0] simple connect state (7/10): wait to get packet service state attached
Mai 14 21:09:06 spacegray ModemManager[18425]: <info>  [modem0] simple connect state (8/10): bearer
Mai 14 21:09:07 spacegray ModemManager[18425]: <info>  [modem0] simple connect state (9/10): connect
Mai 14 21:09:07 spacegray ModemManager[18425]: <info>  [modem0] state changed (registered -> connecting)
Mai 14 21:09:07 spacegray ModemManager[18425]: <info>  [modem0/bearer0] reloading stats is supported by the device
Mai 14 21:09:07 spacegray ModemManager[18425]: <info>  [modem0] state changed (connecting -> connected)
Mai 14 21:09:07 spacegray ModemManager[18425]: <info>  [modem0] simple connect state (10/10): all done
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4219] device (cdc-wdm0): state change: prepare -> config (reason 'none', sys-iface-state: 'managed')
Mai 14 21:09:07 spacegray audit[2085]: NETFILTER_CFG table=firewalld:11 family=1 entries=25 op=nft_register_rule pid=2085 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4564] device (cdc-wdm0): state change: config -> ip-config (reason 'none', sys-iface-state: 'managed')
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4580] modem-broadband[cdc-wdm0]: IPv4 static configuration:
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4581] modem-broadband[cdc-wdm0]:   address 10.132.224.163/29 brd* 10.132.224.167 lft forever pref forever lifetime 11934-0[0,0] src wwan
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4582] modem-broadband[cdc-wdm0]:   gateway 10.132.224.164
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4582] modem-broadband[cdc-wdm0]:   DNS 62.109.121.17
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4582] modem-broadband[cdc-wdm0]:   DNS 62.109.121.18
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4582] modem-broadband[cdc-wdm0]:   MTU 1500
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4583] modem-broadband[cdc-wdm0]: IPv6 base configuration:
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4583] modem-broadband[cdc-wdm0]:   address 2a02:3033:211:91e4:b951:de93:c1a4:862b/64 lft forever pref forever lifetime 11934-0[0,0] src unknown (slaac disabled)
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4583] modem-broadband[cdc-wdm0]:   gateway 2a02:3033:211:91e4:6d17:ba87:e991:c32e
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4584] modem-broadband[cdc-wdm0]:   DNS 2a02:3018:0:40ff::aaaa
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4584] modem-broadband[cdc-wdm0]:   DNS 2a02:3018:0:40ff::bbbb
...
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.4684] device (cdc-wdm0): state change: ip-config -> ip-check (reason 'none', sys-iface-state: 'managed')
...
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.5187] device (cdc-wdm0): state change: ip-check -> secondaries (reason 'none', sys-iface-state: 'managed')
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.5191] device (cdc-wdm0): state change: secondaries -> activated (reason 'none', sys-iface-state: 'managed')
Mai 14 21:09:07 spacegray NetworkManager[2110]: <info>  [1715713747.5198] device (cdc-wdm0): Activation: successful, device activated.

Which device is in my laptop?

The Quectel EM05-G is hooked up to the internal USB bus. As such, you can use lsusb to figure out the specific vendor and device IDs.

lsusb | rg Quectel
# Bus 001 Device 003: ID 2c7c:030a Quectel Wireless Solutions Co., Ltd. Quectel EM05-G

Enabling the Frontend

In some forums, frontend activation is described in terms of an FCC lock. I lack the knowledge to confirm the relation to the FCC, but the lock does disable the radio power source.

sudo mbimcli --device-open-proxy --device=/dev/cdc-wdm0 --quectel-set-radio-state=on

Mobile Provider Selection

Since I am in Europe, or Germany specifically, I want to register automatically with any available provider. Depending on your country, I have no idea if this can cause additional costs or not.

sudo mbimcli --device="/dev/cdc-wdm0" -p --register-automatic

Integration with ModemManager

To integrate with ModemManager, we need to link /usr/share/ModemManager/fcc-unlock.available.d/2c7c to the full vendor and device ID above.

At this time, there are two known PCI identifiers in use, 030a for an "older" iteration and 0313.

sudo ln -s -f "/usr/share/ModemManager/fcc-unlock.available.d/2c7c" "/etc/ModemManager/fcc-unlock.d/2c7c:030a"
sudo ln -s -f "/usr/share/ModemManager/fcc-unlock.available.d/2c7c" "/etc/ModemManager/fcc-unlock.d/2c7c:0313"

The content of the file is as follows:

#!/bin/bash

# SPDX-License-Identifier: CC0-1.0
# 2022 Leah Oswald <mail@leahoswald.de>
#
# Queltec EM05-G FCC unlock mechanism
#

# require program name and at least 2 arguments
[ $# -lt 2 ] && exit 1

# first argument is DBus path, not needed here
shift

# second and next arguments are control port names
for PORT in "$@"; do
  # match port name
  echo "$PORT" | grep -q cdc-wdm && {
    CDC_WDM_PORT=$PORT
    break
  }
done

# fail if no cdc-wdm port exposed
[ -n "$CDC_WDM_PORT" ] || exit 2

# run mbimcli operation
mbimcli --device-open-proxy --device="/dev/$CDC_WDM_PORT" --quectel-set-radio-state=on
exit $?

ModemManager should pick up the linked unlock script automatically.

SIM Locking

When the SIM locks itself again, it's a bit of a pain to figure that out. There is no pop-up that asks you to re-enter the PIN.

Adding a second-to-last line to the lockup script to enter the PIN automatically is the best approach.

Note that disabling the PIN on the SIM via mbimcli is NOT what you want!

GUI

The ModemManager integration leaves much to be desired. Besides the occasional SIM unlock - you need the PUK1 for that (!) and it fails on the CLI - I tend to use the command line to get a reasonable amount of feedback if the panel doesn't respond quickly enough. Rule of thumb: If you get connectivity issues, the PIN is the first thing to check.

Suspend Resume

Occasionally, the device disappears after resuming from suspend to RAM.

Check journalctl --since="5min ago". I saw a missing directory once, and creating it fixed the issue.

Mai 15 13:57:46 spacegray NetworkManager[2110]: <info>  [1715774266.1051] device (ttyUSB0): state change: prepare -> config (reason 'none', sys-iface-state: 'managed')
Mai 15 13:57:46 spacegray NetworkManager[2110]: <info>  [1715774266.1053] modem["ttyUSB0"]: using modem-specified IP timeout: 20 seconds
Mai 15 13:57:46 spacegray NetworkManager[2110]: <info>  [1715774266.1053] ppp-manager: starting PPP connection
Mai 15 13:57:46 spacegray NetworkManager[2110]: <info>  [1715774266.1081] ppp-manager: pppd started with pid 81512
Mai 15 13:57:46 spacegray pppd[81512]: Plugin /usr/lib64/pppd/2.5.0/nm-pppd-plugin.so loaded.
Mai 15 13:57:46 spacegray NetworkManager[81512]: Plugin /usr/lib64/pppd/2.5.0/nm-pppd-plugin.so loaded.
Mai 15 13:57:46 spacegray pppd[81512]: nm-ppp-plugin: initializing
Mai 15 13:57:46 spacegray pppd[81512]: pppd 2.5.0 started by root, uid 0
Mai 15 13:57:46 spacegray pppd[81512]: nm-ppp-plugin: status 2 / phase 'serial connection'
Mai 15 13:57:46 spacegray pppd[81512]: Can't create lock file /run/pppd/lock/LCK..ttyUSB0: No such file or directory
Mai 15 13:57:46 spacegray NetworkManager[81512]: Can't create lock file /run/pppd/lock/LCK..ttyUSB0: No such file or directory
Mai 15 13:57:46 spacegray pppd[81512]: nm-ppp-plugin: status 0 / phase 'dead'
Mai 15 13:57:46 spacegray pppd[81512]: nm-ppp-plugin: cleaning up
Mai 15 13:57:46 spacegray pppd[81512]: Exit.

which is fixed by

sudo mkdir -p /run/pppd/lock

Useful status queries

journalctl -xn -f
sudo mbimcli --device="/dev/cdc-wdm0" -p --query-ip-configuration
sudo mbimcli --device="/dev/cdc-wdm0" -p --query-pin-state
sudo mbimcli --device="/dev/cdc-wdm0" -p --quectel-query-radio-state
# not a typo, it is mmcli from modem manager
sudo mmcli -m 0

At times, the modem becomes unresponsive, and the only solution I have found is to reboot. Unloading and reloading the driver modules might be sufficient (untested).