ModemManager in OpenWRT (take #2)

mm-openwrt

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 netifd.

OpenWRT already has some support for a lot of the devices that ModemManager is able to manage (e.g. through the uqmi, umbim or 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 qmicli, 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 qmicli or mbimcli commands).

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:

https://bitbucket.org/aleksander0m/modemmanager-openwrt

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 udev, the 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"

This new way of notifying device events made it very easy to integrate the automatic device discovery supported in ModemManager directly via tty and net hotplug scripts (see mm_report_event()).

With the integration in the hotplug scripts, ModemManager will automatically detect and probe the different ports exposed by the broadband modem devices.

udev rules

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-modems operation 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.

DBus

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.

Example configuration

The following snippet shows an example interface configuration to set in /etc/config/network.

 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).

TL;DR?

You can now have your 2G/3G/4G mobile broadband modems managed with ModemManager and netifd in your OpenWRT based system.

Posted on January 7, 2017, in Development, FreeDesktop Planet, GNOME Planet, Planets and tagged , , , . Bookmark the permalink. 24 Comments.

  1. Hi Aleksander,

    I’ve got one of those MC74xx modems (MC7430) here in Australia and I am having a terrible time getting it to do anything useful on Linux.

    In Windows, I can get it to register and connect on two different network SIMs (Telstra and Optus) using the Sierra Skylight tool.

    In Ubuntu Linux, I have tried the following drivers:

    – Stock Linux
    – Gobi.Net

    In OpenWrt, I have tried the following drivers:
    – Stock OpenWrt
    – Your ModemManager feed

    The result is ultimately the same for all Linux attempts:

    – Serial ports come up just fine (ttyUSB0, ttyUSB1, ttyUSB2)
    – CDC interfaces come up (cdc-wdm0, cdc-wdm1)
    – Drivers detect that its QMI or MBIM (depending on how I’ve set it at the time with AT commands)

    However the issue is- both QMI and MBIM timeout, whenever you try to run any of the commands against either CDC interfaces.

    The most success I’ve had is with your ModemManager package, but it’s really only capable of ensuring the device is in high power mode, registered, etc- still cannot get it to connect and pass data.

    I’ve read that this is device is raw-IP only; how do I get it to play the game?

    Regards,

    Ed

  2. For the MC74xx in QMI raw-ip mode you need Linux kernel >= 4.5 or, if using Ubuntu 16.04, you can try this PPA I prepared, that backports the raw-ip support patches to a 4.4 kernel: https://launchpad.net/~aleksander-m/+archive/ubuntu/kernel-xenial-qmi-raw-ip.

    For the MC74xx in MBIM mode, you probably just can use the stock kernel you have.

    BUT in both cases, make sure you use the latest ModemManager 1.6.x stable version, because we have included several patches to make those modems work properly in the latest releases. I have no idea what default MM version comes with Ubuntu, but likely (very likely) an old one. You may get a more recent MM version for Ubuntu 16.04 with this PPA I maintain: https://launchpad.net/~aleksander-m/+archive/ubuntu/modemmanager-xenial

    I know people successfully using those 2 PPAs and getting MC74xx working properly.

  3. Hi Aleksander,

    Thanks for the follow-up; using your PPAs I managed to get the modem working using QMI.

    I’m puzzled though, with the raw-ip interface on the correct way to learn about and set the IP; I know ModemManager outputs the IP, mask, gateway and DNS into the logs (when using QMI), but it doesn’t seem to do so for MBIM or whatever asynchronous (serial I assume?)

    Of note- it turned out my primary issue was USB2 versus USB3; all the devices come up just fine in USB2 mode, but the QMI and MBIM interfaces just don’t seem to work at all.

    Unfortunately this is an issue for me, as long term I wanna run this on an embedded system and all my devices are USB2 only!

    Do you know of a way to query for the IPs that should be assigned using AT commands? I can’t see anything obvious looking through the Sierra AT doco or the generic 3gpp stuff.

    Thanks again,

    Regards,

    Ed

  4. HI Aleksander,

    Scratch that last comment, mostly. I managed to get the modem to do almost everything I want on OpenWrt using MBIM (but not with QMI).

    And it integrates nicely in /etc/config/network as per your configuration recommendation.

    The only real issue I have is that (only on OpenWrt) I receive zero bytes, regardless how long I leave the connection up for (though it does correctly assign the IPs and whatnot).

    The device I’m working with is a GL.inet dev board, I will try on a Compex WPJ344 with your feed added as soon as I can get the ethernet switch to play the game on OpenWrt (can only get it to run LEDE presently).

    Thanks again,

    Ed

  5. Bronwyn Perkins

    Hi Aleksander,

    I’m trying to get a Dell 5808e modem working in OpenWRT in QMI mode, would using your ModemManager setup allow OpenWRT to send the FCC Auth command you mentioned in your article last February? I suspect that’s my sticking point at the moment, the modem is behaving exactly as it does under Ubuntu before that command is sent (with a manual config; ModemManager+libqmi runs it fine there after your changes made it in)

    -BP

  6. Yes, FCC auth would be sent automatically to the modem if using ModemManager, both for QMI and MBIM modes 🙂

  7. Bronwyn Perkins

    Got it compiled and installed today, and it runs like a champ right out of the box. Thanks!

  8. For the MC74xx and EM74xx modules, make sure your OpenWRT kernel has the following fix for a proper run in MBIM mode:
    https://patchwork.ozlabs.org/patch/643815/
    (since v4.4.16 in the 4.4.x series)

  9. Michael Steiner

    Hello Alexander, Did you try to compile with new Openwrt (Lede) ? It doesn’t seem to work, could you check please?

    Thank you

    Michael

  10. Didn’t try, no. Patches welcome 😉

  11. Michael Steiner

    Sorry, I don’t how to resolve this error?

    make[8]: Entering directory ‘/home/mike/lede/build_dir/target-arm_cortex-a9+vfpv3_musl_eabi/libmbim-1.15.0-20161123/src/libmbim-glib’
    CC libmbim_glib_core_la-mbim-device.lo
    mbim-device.c: In function ‘initable_init_async’:
    mbim-device.c:2168:15: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
    ctx->self = g_object_ref (initable);
    ^
    cc1: all warnings being treated as errors

    Any tips?

  12. Patch against aleksander’s repo to update to latest versions of libmbim/libqmi/modemmanager here http://jakorasia.info/stuff/openwrt/0001-Update-package-versions.patch

    Did not test on actual hardware yet, but it compiles with lede/openwrt master…

  13. Michael Steiner

    Thank you very much, I will test it 🙂

  14. hy, I am also looking for building openwrt with modemmanager but it does not work.
    am I doing this correct?

    toni@ubuntu-17:~/lede/feeds/modemmanager$ git am –signoff < /home/toni/0001-Update-package-versions.patch
    Applying: Update package versions
    .git/rebase-apply/patch:81: space before tab in indent.
    $(AM_V_GEN) if test -d "$(srcdir)/.git"; then \
    .git/rebase-apply/patch:343: space before tab in indent.
    uml290 \
    .git/rebase-apply/patch:477: trailing whitespace.

    warning: 3 lines add whitespace errors.
    toni@ubuntu-17:~/lede/feeds/modemmanager$

  15. Steiner Michael

    Yes, same situation I have. But patch is successfully applied; You can check the files and all changes are applied; Then Openwrt compiled successfully.

  16. I will be updating the repo sometime this week

  17. hy, it compiles good on AR71xx for example wdr4300 – my first device
    but i wanted to use modemmanager on my second device – this is ramips/mt7621/mir3g – XIAOMI MI WIFI 3G router

    when i try to compile i get the following error:
    cp: cannot stat ‘/home/toni/lede/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.16/lib/libgcc_s.so.*’: No such file or directory
    Makefile:569: recipe for target ‘/home/toni/lede/bin/targets/ramips/mt7621/packages/libgcc_unknown-1_mipsel_24kc.ipk’ failed
    make[2]: *** [/home/toni/lede/bin/targets/ramips/mt7621/packages/libgcc_unknown-1_mipsel_24kc.ipk] Error 1
    make[2]: Leaving directory ‘/home/toni/lede/package/libs/toolchain’
    package/Makefile:105: recipe for target ‘package/libs/toolchain/compile’ failed
    make[1]: *** [package/libs/toolchain/compile] Error 2
    make[1]: Leaving directory ‘/home/toni/lede’
    /home/toni/lede/include/toplevel.mk:198: recipe for target ‘package/libmbim/compile’ failed
    make: *** [package/libmbim/compile] Error 2
    toni@ubuntu-17:~/lede$

    is it possible to compile modemmanager on that specific target / architecture?

  18. it works also on ramips/mt7621/mir3g – XIAOMI MI WIFI 3G router 😉
    seems I did not apply the patch on the second directory where i checked out the TRUNK

  19. Does ModemManager provides specific interfaces for NB-IoT and eMTC ?

  20. Does the modem provide specific interfaces for NM-IoT or eMTC? 🙂

  21. The eMTC/NB-IoT module is SIM7000E.

  22. saxy1337@gmail.com

    hy, tried to update my openwrt installation, but I can’t compile modemmanager:

    make[7]: Entering directory ‘/home/toni/openwrt/build_dir/target-mipsel_24kc_musl/modemmanager-1.8.0/libmm-glib/generated’
    GEN mm-enums-types.h
    GEN mm-errors-types.h
    GEN mm-gdbus-manager.c
    Traceback (most recent call last):
    File “/home/toni/openwrt/staging_dir/target-mipsel_24kc_musl/usr/bin/gdbus-codegen”, line 53, in
    from codegen import codegen_main
    ImportError: No module named codegen
    Makefile:1109: recipe for target ‘mm-gdbus-manager.c’ failed
    make[7]: *** [mm-gdbus-manager.c] Error 1
    make[7]: Leaving directory ‘/home/toni/openwrt/build_dir/target-mipsel_24kc_musl/modemmanager-1.8.0/libmm-glib/generated’
    Makefile:1163: recipe for target ‘all-recursive’ failed
    make[6]: *** [all-recursive] Error 1
    make[6]: Leaving directory ‘/home/toni/openwrt/build_dir/target-mipsel_24kc_musl/modemmanager-1.8.0/libmm-glib’
    Makefile:505: recipe for target ‘all-recursive’ failed
    make[5]: *** [all-recursive] Error 1
    make[5]: Leaving directory ‘/home/toni/openwrt/build_dir/target-mipsel_24kc_musl/modemmanager-1.8.0’
    Makefile:437: recipe for target ‘all’ failed
    make[4]: *** [all] Error 2
    make[4]: Leaving directory ‘/home/toni/openwrt/build_dir/target-mipsel_24kc_musl/modemmanager-1.8.0’
    Makefile:141: recipe for target ‘/home/toni/openwrt/build_dir/target-mipsel_24kc_musl/modemmanager-1.8.0/.built’ failed
    make[3]: *** [/home/toni/openwrt/build_dir/target-mipsel_24kc_musl/modemmanager-1.8.0/.built] Error 2
    make[3]: Leaving directory ‘/home/toni/openwrt/feeds/modemmanager/modemmanager’
    time: package/feeds/modemmanager/modemmanager/compile#27.30#5.52#40.60
    package/Makefile:107: recipe for target ‘package/feeds/modemmanager/modemmanager/compile’ failed
    make[2]: *** [package/feeds/modemmanager/modemmanager/compile] Error 2
    make[2]: Leaving directory ‘/home/toni/openwrt’
    package/Makefile:103: recipe for target ‘/home/toni/openwrt/staging_dir/target-mipsel_24kc_musl/stamp/.package_compile’ failed
    make[1]: *** [/home/toni/openwrt/staging_dir/target-mipsel_24kc_musl/stamp/.package_compile] Error 2
    make[1]: Leaving directory ‘/home/toni/openwrt’
    /home/toni/openwrt/include/toplevel.mk:216: recipe for target ‘world’ failed
    make: *** [world] Error 2

  23. ModemManager for OpenWRT works great. Makes the Sierra Wireless cards much more useful.

    One question: Have you ever been able to compile the packages with an OpenWRT SDK? I have no issues compiling a full build, but building with an SDK always fails. I’ve tried multiple targets using 18.06.1 SDKs.

  1. Pingback: Links 9/1/2017: Dell’s Latest XPS 13, GPD Pocket With GNU/Linux | Techrights

Leave a comment