Modem HOWTO: mobile broadband, serial devices and dial-up today
On a Linux system today, "modem" almost always means a cellular (LTE or 5G) module, managed by ModemManager and NetworkManager. Below that sits the plain serial port, which you still meet with USB serial adapters, microcontroller boards and the occasional analog modem. This page covers all three, with the commands to check that each one works.
The classic Modem-HOWTO (last revised in 2007) and Serial-HOWTO (last revised in 2011) are kept by the Linux Documentation Project at tldp.org. They describe IRQ jumpers, setserial and ISA cards. This page is written for current hardware and current distributions.
Which kind of modem do you have?
| Type | Typical device nodes | Handled by |
|---|---|---|
| USB or M.2 cellular module (QMI or MBIM) | /dev/cdc-wdm0, a wwan0 network interface, extra ttyUSB ports | ModemManager + NetworkManager |
| PCIe cellular module (newer laptops) | /dev/wwan0mbim0, /dev/wwan0at0, wwan0 | Kernel WWAN subsystem (since Linux 5.13) + ModemManager |
| AT-command serial modem (RS-232 or USB) | /dev/ttyS0, /dev/ttyUSB0, /dev/ttyACM0 | ModemManager (AT control, PPP data) or pppd directly |
| USB serial adapter or board (not a modem) | /dev/ttyUSB0, /dev/ttyACM0 | A terminal program such as picocom |
A single USB modem often exposes several ports at once: a control port, a network interface and one or more serial ports for AT commands or GPS. ModemManager groups them into one modem object. Some USB modems first appear as a USB disk holding Windows drivers; the usb-modeswitch package switches them into modem mode automatically.
Old "Winmodems" (software modems that leave the signal processing to a Windows driver) were the big problem of the dial-up era. They are now rare, and most never had free Linux drivers. If you need dial-up, buy an external modem that speaks AT commands; USB models usually appear as /dev/ttyACM0.
Mobile broadband with ModemManager
Install and check
Desktop installs of the major distributions normally ship ModemManager and NetworkManager. On a minimal or server install:
sudo apt install modemmanager network-manager # Debian, Ubuntu
sudo dnf install ModemManager NetworkManager-wwan # Fedora, RHEL, Alma, Rocky
sudo pacman -S modemmanager networkmanager # Arch
sudo systemctl enable --now ModemManager
List the modems ModemManager has found, then show the details of one by its index:
mmcli -L
mmcli -m 0
The detail view shows the manufacturer and model, the firmware, the ports in use, the state (for example locked, disabled, registered or connected), signal quality, the operator and the SIM path. If mmcli -L lists nothing, run lsusb or lspci to check that the hardware is visible at all, and journalctl -u ModemManager -b for the reason.
Unlock the SIM
If the state is locked, the SIM wants its PIN. The SIM has its own index, shown in the modem details:
sudo mmcli -i 0 --pin=1234
Count your attempts. Three wrong PINs usually lock the SIM until you enter the PUK from the carrier. Check the PIN before scripting this.
Connect with NetworkManager (recommended)
ModemManager only talks to the modem: it registers on the network and opens a data "bearer". It does not configure IP addresses on the host. NetworkManager reads the IP settings from the bearer and applies them, so the normal way to get online is a NetworkManager connection profile:
sudo nmcli connection add type gsm con-name mobile gsm.apn internet
sudo nmcli connection up mobile
Replace internet with your carrier's APN (access point name). Add gsm.username, gsm.password and gsm.pin if your carrier or SIM needs them. The profile needs no interface name; without one, NetworkManager uses it for whichever modem is present, which is simpler because modem interface names can change. With gsm.auto-config yes, NetworkManager takes the APN and login from the mobile broadband provider database instead (see nm-settings-nmcli(5)).
Check the result:
nmcli device status
mmcli -m 0 # state should now be "connected"
mmcli -b 0 # bearer: IP method, address, DNS, MTU
ip addr show wwan0
Useful mmcli commands
sudo mmcli -m 0 --enable
mmcli -m 0 --signal-setup=30 # refresh signal figures every 30 s
mmcli -m 0 --signal-get # RSSI, RSRP, RSRQ, SNR
sudo mmcli -m 0 --3gpp-scan --timeout=300
mmcli -m 0 --messaging-list-sms
sudo mmcli -m 0 --messaging-create-sms="text='Hello',number='+15551234567'"
sudo mmcli -s 0 --send # send SMS number 0 from the list
sudo mmcli -m 0 --location-enable-gps-nmea
sudo mmcli -m 0 --location-get
sudo mmcli -m 0 --simple-disconnect
mmcli -m 0 --simple-connect="apn=internet" also exists. It opens the bearer but leaves the IP setup to you, which makes it a testing tool rather than a way to get online.
Laptop modules that refuse to go online
Some WWAN modules shipped by Lenovo, Dell and HP have an "FCC lock": they stay in low-power mode until a vendor-specific unlock command is sent. Since ModemManager 1.18.4 the unlock scripts are installed but not active. They live in /usr/share/ModemManager/fcc-unlock.available.d/, named by USB or PCI vid:pid. Read the ModemManager FCC unlock page first, then enable the one for your module at your own responsibility:
lspci -nn | grep -i -e wwan -e modem # or lsusb, to find vid:pid
sudo ln -sft /etc/ModemManager/fcc-unlock.d \
/usr/share/ModemManager/fcc-unlock.available.d/105b:e0ab
sudo systemctl restart ModemManager
The scripts call qmicli or mbimcli, from the libqmi-utils and libmbim-utils packages on Debian and Ubuntu.
Serial devices
Names and permissions
Built-in UARTs are /dev/ttyS0 and up. USB serial adapters with a vendor chip (FTDI, Prolific, CH340, CP210x) appear as /dev/ttyUSB0; devices that follow the USB CDC-ACM standard (many microcontroller boards and modems) appear as /dev/ttyACM0. The numbers depend on plug-in order, so use the stable links udev creates:
ls -l /dev/serial/by-id/
sudo dmesg | grep -i tty # which driver claimed the device
Serial devices are not world-writable. The default udev rules from systemd give them the group dialout; Arch Linux patches this to uucp. Check, then add yourself to whatever group the device shows:
ls -l /dev/ttyUSB0
# crw-rw---- 1 root dialout 188, 0 ... /dev/ttyUSB0
sudo usermod -aG dialout "$USER" # Arch: sudo usermod -aG uucp "$USER"
Log out and in again for the new group to apply. Running the terminal program with sudo works too, but it is a bad habit.
Talk to the device
picocom is small and needs no configuration file:
sudo apt install picocom # or dnf / pacman
picocom -b 115200 /dev/ttyUSB0
picocom -b 115200 -f h /dev/ttyS0 # with RTS/CTS hardware flow control
Leave picocom with Ctrl-a then Ctrl-x. For an AT modem, type AT and Enter; the answer should be OK. ATI usually prints the model. minicom (minicom -D /dev/ttyUSB0 -b 115200) and screen /dev/ttyUSB0 115200 do the same job. To set port parameters without a terminal program, use stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parenb.
Stop ModemManager from probing your board
Under its default "strict" filter policy, ModemManager probes a generic tty only when it is fairly sure the device is a modem. If it still grabs a board (you see AT commands arriving, or a device that resets on plug-in), tag the device so ModemManager ignores it. Find the IDs with udevadm info -a /dev/ttyACM0, then create /etc/udev/rules.d/79-mm-ignore-myboard.rules:
ACTION!="add|change|move|bind", GOTO="mm_myboard_end"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0043", ENV{ID_MM_DEVICE_IGNORE}="1"
LABEL="mm_myboard_end"
sudo udevadm control --reload
sudo udevadm trigger
Use your board's own vendor and product IDs; the ones above are only an example. Unplug and replug the device afterwards.
Dial-up, briefly
Analog dial-up still exists for out-of-band access to remote sites and for a few rural users. ModemManager and NetworkManager can drive an AT modem and run PPP over it. Without them, pppd with a chat script does the job: a peers file sets the device and options, and the chat script dials. The full set-up, including the secrets files and debugging, is on the PPP HOWTO page. A minimal chat script, /etc/chatscripts/dialup, looks like this:
ABORT BUSY
ABORT 'NO CARRIER'
'' ATZ
OK ATDT5551234
CONNECT ''
Troubleshooting checklist
- Hardware visible?
lsusb,lspci -nn,sudo dmesg -wwhile you plug it in. - Driver bound?
lspci -korlsusb -tshows the driver per interface (qmi_wwan,cdc_mbim,option,cdc_acm). - Seen by ModemManager?
mmcli -L; if not,journalctl -u ModemManager -b. - State stuck at locked: SIM PIN. Stuck at disabled or failed: try
sudo mmcli -m 0 --enableand read the error; on laptops, think of the FCC lock. - Registered but no data: wrong APN, or the plan does not allow data. Check
mmcli -b 0for an IP address. - Serial "Permission denied": group membership (
idshows your groups) or another program holding the port (sudo fuser /dev/ttyUSB0). - Garbage on a serial console: wrong speed. 115200 and 9600 are the usual values.
Sources
- mmcli(1) manual page, ModemManager project
- WWAN device types, ModemManager documentation
- Port and device detection, ModemManager documentation
- IP connectivity setup in LTE modems, ModemManager documentation
- FCC unlock, ModemManager documentation
- nmcli(1), Debian 13 (NetworkManager 1.52)
- nm-settings-nmcli(5): gsm settings, Debian 13
- 50-udev-default.rules (serial devices in group dialout), systemd
- Arch Linux systemd package build (dialout replaced by uucp)
- picocom(1), Debian 13
- chat(8), Debian 13
- Modem-HOWTO (v0.39, 2007) and Serial-HOWTO (v2.27, 2011), Linux Documentation Project