Turn a USB cellular modem into a phone line for Asterisk.
This channel driver connects Asterisk to modems managed by ModemManager and gives you:
- Voice calls (incoming and outgoing) over the modem's USB audio function
- SMS send and receive
- MMS receive — handled natively in the driver, no mmsd-tng daemon needed; attachments are saved to disk and exposed to the dialplan
- Automatic audio device detection — the driver finds the modem's ALSA sound card by itself; no audio configuration needed in the common case
- Per-modem init AT commands — for modems that need a setup command after
every boot (e.g. Quectel
AT+QPCMV=1,2to enable USB voice audio)
Everything works with stock distribution packages: no rebuilds of Asterisk, ModemManager, or any other package are required, and no non-default build options anywhere.
Developing or packaging? See DEV_README.md.
Prebuilt packages for every release are attached to GitHub Releases.
Download the .apk matching your package architecture (shown by
apk info --print-arch or in your firmware's profile), then:
apk add --allow-untrusted ./asterisk-chan-modemmanager-*.apkDependencies (asterisk, ModemManager, ALSA, the required asterisk bridge and
codec modules, and kmod-usb-audio) are installed automatically when the
package feeds are configured.
One-time setup — Asterisk runs as the asterisk user, which needs access to
the modem's sound card and (optionally) an AT port:
# add 'asterisk' to the audio and dialout groups in /etc/group:
sed -i -e 's/^audio:.*/&,asterisk/' -e 's/^dialout:.*/&,asterisk/' /etc/group
service asterisk restartIf you use init_commands and ModemManager holds every AT port of your modem,
free one with an ignore rule (ModemManager parses /lib/udev/rules.d itself
on OpenWrt, no udev needed). Example for a Quectel RM500Q (USB interface 03 =
second AT port):
# /lib/udev/rules.d/78-mm-chan-modemmanager-init-port.rules
ACTION!="add|change|move|bind", GOTO="end"
SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}"
ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0800", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_IGNORE}="1"
LABEL="end"
Then set init_port = /dev/ttyUSBx (the ignored port) in the config and
restart ModemManager.
Download the .deb built for your Ubuntu release (the package is pinned
to that release's Asterisk ABI — a 24.04 package will not install on 26.04
and vice versa), then:
sudo apt install ./asterisk-chan-modemmanager_*.debThis pulls in Asterisk and all libraries automatically. Add the asterisk
user to the audio and dialout groups if it isn't already:
sudo usermod -aG audio,dialout asterisk
sudo systemctl restart asteriskDebian stable has not shipped an Asterisk package since 2023 (only sid
carries one), so there is no prebuilt Debian package. On sid you can build
your own with dpkg-buildpackage -us -uc -b (see
DEV_README.md).
Config file: /etc/asterisk/modemmanager.conf (the full annotated reference
is modemmanager.conf.sample). You declare your modem(s) and SIM(s); the
driver matches them to live hardware dynamically, so replugging or swapping
slots keeps working.
Find your identifiers with mmcli:
mmcli -L # list modems
mmcli -m 0 | grep device # DeviceIdentifier -> [modem] identifier
mmcli -m 0 --sim 0 # ICCID -> [sim] identifierMinimal working example:
[modem1]
type = modem
identifier = 0123456789abcdef0123456789abcdef01234567 ; mmcli DeviceIdentifier
; audio devices default to auto-detection; set explicitly only if that fails:
;input_device = plughw:CARD=Device,DEV=0
;output_device = plughw:CARD=Device,DEV=0
; Quectel modems need this after every boot for USB voice audio:
init_commands = AT+QPCMV=1,2
;init_port = /dev/ttyUSB3 ; optional: pin the AT port used for init_commands
[sim1]
type = sim
identifier = 8982123456781234567 ; ICCID
context = from-mobile ; incoming calls land here
message_context = from-mobile-sms ; incoming SMS/MMS land here
exten = sSet your carrier's MMSC per SIM. Bringing up the MMS APN bearer/routing is your responsibility (same as with mmsd-tng):
[sim1]
; ...
mmsc = http://mms.example.com:9084
mms_interface = wwan0 ; bind fetches to the MMS bearer's netdev
;mms_proxy = 10.0.0.1:8080
;mms_spool = /var/spool/asterisk/mmsIPv6-only carriers with NAT64 (verified on LGU+): some MMSCs publish a native AAAA record that silently drops HTTP — real handsets reach them via the IPv4 A record through 464XLAT/NAT64. If MMS fetches time out on an IPv6-only bearer:
- Discover the NAT64 prefix (RFC 7050): query
AAAA ipv4only.arpaagainst the bearer's DNS server. - Resolve the MMSC's A record, map it into the prefix, and pin it in
/etc/hosts, e.g.2001:db8:64ff::c0a8:e60e mms.example.com.
The pin also covers retrieval URLs on other ports of the same host.
Dialplan:
; Outgoing call through the SIM
exten => _X.,1,Dial(ModemManager/8982123456781234567/${EXTEN},30)
; Outgoing SMS
same => n,MessageSend(ModemManager:+821012345678@8982123456781234567)
; Incoming calls arrive in the SIM's `context`; SMS/MMS arrive as MESSAGE
; in `message_context` (MMS: `mms_context` if set). MMS metadata:
[from-mobile-sms]
exten => s,1,Verbose(1,SMS from ${MESSAGE(from)}: ${MESSAGE(body)})
same => n,Verbose(1,MMS attachments: ${MESSAGE_DATA(MMS_ATTACHMENT_COUNT)})
same => n,Verbose(1,First file: ${MESSAGE_DATA(MMS_ATTACHMENT_FILE_1)} (${MESSAGE_DATA(MMS_ATTACHMENT_TYPE_1)}))
same => n,Verbose(1,Subject: ${MESSAGE_DATA(MMS_SUBJECT)})
CLI: modemmanager list available shows detected modems, SIMs and ALSA
devices.
| Symptom | Likely cause / fix |
|---|---|
| Call connects but no audio | asterisk user not in audio group; on OpenWrt kmod-usb-audio missing; on Quectel AT+QPCMV=1,2 not applied (set init_commands — it resets on every modem boot) |
| "No translator path" / "Could not create class basic" (OpenWrt) | Missing asterisk codec/bridge packages — installed automatically by this package's dependencies since 1.0.0; apk fix or reinstall |
init_commands never sent / port busy |
ModemManager holds all AT ports. Add the ID_MM_PORT_IGNORE rule above and set init_port |
| MMS notification arrives but fetch fails | Is the MMS APN bearer up and routed? On IPv6-only bearers, apply the NAT64 pin above |
| SMS/call sending rejected while registered fine | Usually carrier-side provisioning of the SIM (e.g. data-only SIM); test the SIM in a phone |
| Wrong ALSA device picked | Set input_device/output_device explicitly; candidates are listed by modemmanager list available |
- Asterisk: 20 – 23
- Distributions: OpenWrt 25.12, Ubuntu 24.04 / 26.04 (Debian sid: build from source). On OpenWrt the package exists for every architecture whose kernel has sound support — a few audio-less targets (e.g. at91/sama7) cannot run it and have no package.
- Modems: voice support must be exposed through ModemManager and call audio must be reachable as a USB audio class ALSA device (tty audio is not supported). Tested: Quectel RM500Q, EM05, EC25 on UMTS(CS) and VoLTE/5G(PS).
- Carriers: tested on LGU+ (Korea) including VoLTE, SMS, MMS over an IPv6-only bearer with NAT64.
GPL-2.0-only. src/mms/vendor/ contains the WSP/MMS codec vendored from
mmsd-tng (GPL-2).