Home Blog

WWAN on the P14s, continued: data works, voice never will

The eSIM post ended with the modem enabled, a CMLink profile installed, and no working connection. That last part is now fixed. Along the way I spent an hour debugging a problem that had already been solved, which is the more useful story.

The connection works

The APN was the missing piece. My candidate list was cmlink, cmi-connect, and cmnet, all of which are the obvious guesses for a China Mobile profile. The one that works is 3gnet:

nmcli connection add type gsm ifname "*" con-name 5g apn 3gnet
nmcli connection up 5g

That registers as roaming on CHINA MOBILE (CMLink) over LTE and brings up a bearer:

state: registered
power state: on
access tech: lte
registration: roaming
IP4.ADDRESS[1]: 10.179.108.239/27
IP4.GATEWAY:    10.179.108.240
IP4.DNS[1]:     223.119.47.220

Round trip to 223.5.5.5 is about 87 ms. Signal quality sits at 22 percent, which is not great, but it carries traffic.

It cannot make phone calls

Worth stating plainly, because the hardware looks like it should. The RM520N-GL is a data-only module. Quectel's RM5xx series has no voice support: no VoLTE, no circuit-switched voice, and nothing in ModemManager's voice interface that does anything.

Even if the firmware had voice, there is no audio path. The M.2 card exposes no PCM route into the laptop's sound system, so there is no wire to carry a microphone or a speaker. A voice-capable module in this slot would still need that plumbing to exist.

If you want calls over the cellular data link, use VoIP. That is the whole answer.

The warning that is not the problem

ModemManager logs this during startup:

[modem0] Cannot power-up: sotware radio switch is OFF
[modem0] couldn't enable interface: 'Invalid transition'
[modem0] failed enabling modem: Invalid transition

The typo in "sotware" is upstream, and it is a useful string to grep for. This message is the classic FCC-lock symptom, so it reads like a smoking gun.

On this machine it is not. The FCC unlock link was already in place, and nine seconds later the same boot logs:

[modem0] power state updated: on
[modem0] 3GPP registration state changed (registering -> roaming)
[modem0] state changed (enabled -> registered)

The modem needs a moment after the MHI device appears before it accepts a power-up. ModemManager tries too early, warns, retries, and succeeds. Seeing that warning once per boot is normal. Seeing it repeat forever is the real failure.

Read the right boot

The trap that cost me the hour: journalctl -u ModemManager -n 60 does not mean "the last 60 lines from this boot". It means the last 60 lines in the journal, and if the unit has been quiet since startup, those lines can be from days ago. I read a loop of failures from a previous boot, diagnosed an FCC lock that had been fixed the day before, and wrote a script to apply a symlink that already existed.

Pass -b:

journalctl -u ModemManager -b
journalctl --list-boots

--list-boots is the cheap sanity check. If the timestamps in your log do not sit inside the current boot window, you are debugging the past.

The same trap applies to the fix itself. ls -l /etc/ModemManager/fcc-unlock.d/ is one command, and running it before theorizing would have ended the whole detour immediately. Check the state you are about to change.

Off by default

I do not want the modem attaching a bearer whenever the machine boots. It stays registered on the network, which costs nothing, and comes up only on request:

nmcli connection modify 5g connection.autoconnect no

Wi-Fi keeps the default route at metric 600. When the modem is up it adds a second default at metric 700, so it sits behind Wi-Fi and only carries traffic when Wi-Fi is gone.

A small helper

The modem index moves when ModemManager restarts, so anything with mmcli -m 0 hardcoded breaks eventually. This looks it up:

#!/bin/bash
set -uo pipefail

CONN="5g"
PCI_ID="1eac:1007"
AVAIL="/usr/share/ModemManager/fcc-unlock.available.d/${PCI_ID}"
DEST_DIR="/etc/ModemManager/fcc-unlock.d"

modem_index() {
    mmcli -L 2>/dev/null | grep -oP '/Modem/\K[0-9]+' | head -1
}

case "${1:-status}" in
    up)
        nmcli connection up "$CONN" && ip route show default
        ;;
    down)
        nmcli connection down "$CONN"
        ;;
    status)
        idx=$(modem_index)
        [[ -z "$idx" ]] && { echo "No modem found."; exit 1; }
        mmcli -m "$idx" | grep -E \
          'state:|power state:|access tech:|signal quality:|operator name:|registration:'
        nmcli -f NAME,DEVICE,STATE connection show --active | grep -E "NAME|$CONN" \
          || echo "$CONN is down"
        ;;
    unlock)
        [[ $EUID -ne 0 ]] && { echo "Run as root."; exit 1; }
        mkdir -p "$DEST_DIR"
        ln -sf "$AVAIL" "${DEST_DIR}/${PCI_ID}"
        systemctl restart ModemManager
        ;;
esac

unlock is there for the case where the radio really is stuck. Note the PCI ID: this card sits behind the MHI bus as 1eac:1007, not the USB ID 2c7c:0801 that the Quectel documentation quotes. ModemManager matches on the PCI ID, so the symlink in /etc/ModemManager/fcc-unlock.d/ must be named 1eac:1007.

Still open

The SIM reports lock: sim-pin2 with fixed-dialing in its enabled locks. FDN does not block data, and data works, so I have left it alone. It is worth remembering if an APN change ever fails for no visible reason.