I’ve been lately working on integrating ModemManager in OpenWRT, in order to provide a unique and consolidated way to configure and manage mobile broadband modems (2G, 3G, 4G, Iridium…), all working with
OpenWRT already has some support for a lot of the devices that ModemManager is able to manage (e.g. through the
wwan packages), but unlike the current solutions, ModemManager doesn’t require protocol-specific configurations or setups for the different devices; i.e. the configuration for a modem running in MBIM mode may be the same one as the configuration for a modem requiring AT commands and a PPP session.
Currently the OpenWRT package prepared is based on ModemManager git master, and therefore it supports: QMI modems (including the new MC74XX series which are raw-ip only and don’t support DMS UIM operations), MBIM modems, devices requiring QMI over MBIM operations (e.g. FCC auth), and of course generic AT+PPP based modems, Cinterion, Huawei (both AT+PPP and AT+NDISDUP), Icera, Haier, Linktop, Longcheer, Ericsson MBM, Motorola, Nokia, Novatel, Option (AT+PPP and HSO), Pantech, Samsung, Sierra Wireless (AT+PPP and DirectIP), Simtech, Telit, u-blox, Wavecom, ZTE… and even Iridium and Thuraya satellite modems. All with the same configuration.
Along with ModemManager itself, the OpenWRT feed also contains libqmi and libmbim, which provide the
mbimcli, and soon the
qmi-firmware-update utilities. Note that you can also use these command line tools, even if ModemManager is running, via the qmi-proxy and mbim-proxy setups (i.e. just adding
-p to the
This is not the first time I’ve tried to do this; but this time I believe it is a much more complete setup and likely ready for others to play with it. You can jump to the modemmanager-openwrt bitbucket repository and follow the instructions to include it in your OpenWRT builds:
The following sections try to get into a bit more detail of which were the changes required to make all this work.
And of course, thanks to VeloCloud for sponsoring the development of the latest ModemManager features that made this integration possible 🙂
udev vs hotplug
One of the latest biggest features merged in ModemManager was the possibility to run without
udev support; i.e. without automatically monitoring the device addition and removals happening in the system.
Instead of using
mmcli command line tool ended up with a new
--report-kernel-event that can be used to report the device addition and removals manually, e.g.:
$ mmcli --report-kernel-event="action=add,subsystem=tty,name=ttyUSB0" $ mmcli --report-kernel-event="action=add,subsystem=net,name=wwan0"
With the integration in the hotplug scripts, ModemManager will automatically detect and probe the different ports exposed by the broadband modem devices.
ModemManager relies on udev rules for different things:
- Blacklisting devices: E.g. we don’t want ModemManager to claim and probe the TTYs exposed by Arduinos or braille displays. The package includes a USB vid:pid based blacklist of devices that expose TTY ports and are not modems to be managed by ModemManager.
- Blacklisting ports: There are cases where we don’t want the automatic logic selection to grab and use some specific modem ports, so the package also provides a much shorter list of ports blacklisted from actual modem devices. E.g. the QMI implementation in some ZTE devices is so poor that we decided to completely skip it and fallback to AT+PPP.
- Greylisting USB serial adapters: The TTY ports exposed by USB serial adapters aren’t probed automatically, as we don’t know what’s connected in the serial side. If we want to have a serial modem, though, the
mmcli --scan-modemsoperation may be executed, which will include the probing of these greylisted devices.
- Specifying port type hints: Some devices expose multiple AT ports, but with different purposes. E.g. a modem may expose a port for AT control and another port for the actual PPP session, and choosing the wrong one will not work. ModemManager includes a list of port type hints so that the automatic selection of which port is for what purpose is done transparently.
As we’re not using udev when running in OpenWRT, ModemManager includes now a custom generic udev rules parser that uses sysfs properties to process and apply the rules.
procd based startup
The ModemManager daemon is setup to be started and controlled via
procd. The init script controlling the startup will also take care of scheduling the re-play of the hotplug events that had earlier triggered
--report-kernel-event actions (they’re cached in
/tmp); e.g. to cope with events coming before the daemon started or to handle daemon restarts gracefully.
Well, no, I didn’t port ModemManager to use
ubus 🙂 If you want to run ModemManager under OpenWRT you’ll also need to have the
DBus daemon running.
netifd protocol handler
When using ModemManager, the user shouldn’t need to know the peculiarities of the modem being used: all modems and protocols (QMI, MBIM, Generic AT, vendor-specific AT…) are all managed via the same single DBus interfaces. All the modem control commands are internal to ModemManager, and the only additional considerations needed are related to how to setup the network interface once the modem is connected, e.g.:
- PPP: some modems require a PPP session over a serial port.
- Static: some modems require static IP configuration on a network interface.
- DHCP: some modems require dynamic IP configuration on a network interface.
The OpenWRT package for ModemManager includes a custom protocol handler that enables the modemmanager protocol to be used when configuring network interfaces. This new protocol handler takes care of configuring and bringing up the interfaces as required when the modem gets into connected state.
The following snippet shows an example interface configuration to set in
config interface 'broadband' option device '/sys/devices/platform/soc/20980000.usb/usb1/1-1/1-1.2/1-1.2.1' option proto 'modemmanager' option apn 'ac.vodafone.es' option username 'vodafone' option password 'vodafone' option pincode '7423' option lowpower '1'
The settings currently supported are the following ones:
- device: The full sysfs path of the broadband modem device needs to be configured. Relying on the interface names exposed by the kernel is never a good idea, as these may change e.g. across reboots or when more than one modem device is available in the system.
- proto: As said earlier, the new modemmanager protocol needs to be configured.
- apn: If the connection requires an APN, the APN to use.
- username: If the access point requires authentication, the username to use.
- password: If the access point requires authentication, the password to use.
- pincode: If the SIM card requires a PIN, the code to use to unlock it.
- lowpower: If enabled, this setting will request the modem to go into low-power state (i.e. IMSI detach and RF off) when the interface is disconnected.
As you can see, the configuration can be used for any kind of modem device, regardless of what control protocol it uses, which interfaces are exposed, or how the connection is established. The settings are currently only IPv4 only, but adding IPv6 support shouldn’t be a big issue, patches welcome 🙂
SMS, USSD, GPS…
The main purpose of using a mobile broadband modem is of course the connectivity itself, but it also may provide many more features. ModemManager provides specific interfaces and
mmcli actions for the secondary features which are also available in the OpenWRT integration, including:
- SMS messaging (both 3GPP and 3GPP2).
- Location information (3GPP LAC/CID, CDMA Base station, GPS…).
- Time information (as reported by the operator).
- 3GPP USSD operations (e.g. to query prepaid balance to the operator).
- Extended signal quality information (RSSI, Ec/Io, LTE RSRQ and RSRP…).
- OMA device management operations (e.g. to activate CDMA devices).
- Voice call control.
Worth noting that not all these features are available for all modem types (e.g. SMS messaging is available for most devices, but OMA DM is only supported in QMI based modems).
You can now have your 2G/3G/4G mobile broadband modems managed with ModemManager and netifd in your OpenWRT based system.
It’s been almost 4 years working for Lanedo, and I don’t regret a single day having worked for them. Still, I believe it was a time for a change in my life, and since February 1st I am now working as a freelance developer.
I’ve really been involved in pretty different things during my professional life… antivirus desktop applications and gateways, satellite orbit determination and time synchronization systems, VoIP-based push-to-talk server development, and of course NetworkManager, ModemManager, libqmi, libmbim, Tracker, OpenWRT or GTK+.
I would love to keep on working on all these Free Software projects, but I’m also open to exploring new technologies. Change is always good, they say.
So, if you’re looking for a passionate software engineer to develop, improve or integrate your system, just check my website and get in touch. I’d love to hear about your needs and issues and how we can solve them together 🙂
So I wanted to have ModemManager in OpenWRT to handle my mobile broadband connections.
OpenWRT has its own built-in support to handle mobile broadband modems of different types, mainly for AT-controlled modems, but also for QMI-controlled modems through libqmi and qmicli (now available in upstream OpenWRT). But hell, why not package ModemManager for that work, and provide a unified single DBus API to control any kind of mobile broadband modem in the same way?
ModemManager itself isn’t a very complex daemon, so it doesn’t have many dependencies, just: glib/gio, dbus, udev/gudev and libqmi. In the world of OpenWRT, though, none of these are blessed dependencies, as they have a lightweight replacement for everything: libubox (instead of glib), ubus (instead of dbus) and hotplug2 (instead of udev). These replacements target minimal embedded systems, and are perfectly integrated into OpenWRT and provide the building blocks of other core software like the netifd network interface daemon.
Still, having ModemManager available as a OpenWRT package seems like a good idea if you’re not very constrained by the hardware you’re going to use. If you are building a system which should support multiple broadband modems from different vendors, or just building a base system for one specific modem model but leaving the door open to change the model in the future, ModemManager seems a good choice.
systemd’s udev in OpenWRT
Since April 2012, udev sources are now integrated within the systemd source code. And that means that udev packages in OpenWRT would need to get updated in order to get built from that new repository. systemd provides some hints on what would be the best way of creating a minimal systemd build which can be used to gather just the udev-specific libraries and binaries. The easiest way involves compiling the whole systemd package with all optional features disabled, and that would get us not only systemd (which we won’t need), but also udevd and libudev. Easy, yes, but then we have some issues in the environment that we would need to handle…
In OpenWRT, the udev package is available in the trunk repository, where only the core OpenWRT packages are given. But in order to get the new udev compiled out of systemd we end up needing additional dependencies (dbus, libcap) which are only available in the packages repository. Moreover, if you also want to compile the glib-based gudev library, glib is also needed, which is also only available in the packages repository. And you cannot require a package from trunk to depend on a package from packages, so… ended up creating a new systemd-udev package within the packages repository.
As I was targeting the uClibc toolchain, I also ended up requiring some additional patches both in uClibc (e.g. to enable utmpx) and systemd to get the thing properly compiled. The patches applied in the systemd sources are just to handle missing features in uClibc (execvpe, secure_getenv…). Whenever uClibc includes those, we’ll be able to remove those patches.
ModemManager in OpenWRT
I prepared an easy setup of ModemManager packaging in OpenWRT, where all possible plugins get compiled. It wouldn’t have been difficult to allow selecting via configuration which plugins to get compiled, but didn’t want to spend time on that.
I sent the patches to the OpenWRT mailing list already, but if you want to give it a quick try, you can just clone the Lanedo OpenWRT repositories (trunk and packages) from gitorious.org:
$> git clone git://gitorious.org/lanedo/openwrt.git
$> git clone git://gitorious.org/lanedo/openwrt-packages.git
You’ll want both ‘modemmanager-support‘ branches in those git repositories.
ModemManager will be available under the ‘Network’ section in the OpenWRT build configuration; but only after explicitly selecting the following kernel modules (all under Kernel Modules/USB support):
Once all above are enabled, ModemManager can be selected, and it will itself pull all its other required dependencies (systemd-udev, glib, dbus, libqmi…).
No LuCI? No connection manager?
Well, not yet :). If you want to use ModemManager you still need to have your own connection manager software to manage the connectivity. ModemManager will get your mobile broadband modem connected, but you still need to either call pppd or setup the wwan interface yourself (depending on the data port type). This is really not a big deal; and you can just setup a shell script using the provided mmcli command line interface to talk to ModemManager.