Blog Archives

Naming devices in ModemManager


No more “which is now the index of this modem…?”

DBus object path and index

When modems are detected by ModemManager and exposed in DBus, they are assigned an unique DBus object path, with a common prefix and a unique index number, e.g.:


This path is the one used by the mmcli command line tool to operate on a modem, so users can identify the device by the full path or just by the index, e.g. this two calls are totally equivalent:

$ mmcli -m /org/freedesktop/ModemManager1/Modem/0
$ mmcli -m 0

This logic looks good, except for the fact that there isn’t a fixed DBus object path for each modem detected: i.e. the index given to a device is the next one available, and if the device is power cycled or unplugged and replugged, a different index will be given to it.


Systems like NetworkManager handle this index change gracefully, just by assuming that the exposed device isn’t the same one as the one exposed earlier with a different index. If settings need to be applied to a specific device, they will be stored associated with the EquipmentIdentifier property of the modem, which is the same across reboots (i.e. the IMEI for GSM/UMTS/LTE devices).

User-provided names

The 1.8 stable release of ModemManager will come with support for user-provided names assigned to devices. A use case of this new feature is for example those custom systems where the user would like to assign a name to a device based on the USB port in which it is connected (e.g. assuming the USB hardware layout doesn’t change across reboots).

The user can specify the names (UID, unique IDs) just by tagging in udev the physical device that owns all ports of a modem with the new ID_MM_PHYSDEV_UID property. This tags need to be applied before the ID_MM_CANDIDATE properties, and therefore the rules file should be named before the 80-mm-candidate.rules one, for example like this:

$ cat /lib/udev/rules.d/78-mm-naming.rules

ACTION!="add|change|move", GOTO="mm_naming_rules_end"

The value of the new ID_MM_PHYSDEV_UID property will be used in the Device property exposed in the DBus object, and can also be used directly in mmcli calls instead of the path or index, e.g.:

$ mmcli -m USB4
 System | device: 'USB4'
        | drivers: 'qmi_wwan, qcserial'
        | plugin: 'Sierra'
        | primary port: 'cdc-wdm2'

Given that the same property value will always be set for the modem in a specific device path, this user provided names may unequivocally identify a specific modem even when the device is power-cycled, unplugged and replugged or even the whole system rebooted.

Binding the property to the device path is just an example of what could be done. There is no restriction on what the logic is to apply the ID_MM_PHYSDEV_UID property, so users may also choose other different approaches.

This support is already in ModemManager git master, and as already said, will be included in the stable 1.8 release, whenever that is.

TL;DR? ModemManager now supports assigning unique names to devices that stay even across full system reboots.

Dell-branded Sierra Wireless 3G/4G modem not online?


Your Dell modem not getting online?

It’s not uncommon to find weird mobile broadband modems that for one reason or another don’t end up working as expected with NetworkManager/ModemManager; but the new 3G/4G modems in Dell laptops are at a total different level. These Dell-branded devices are really Sierra Wireless powered modems, e.g. the Dell 5808 is a Sierra Wireless MC7355, or the Dell DW5570 is a Sierra Wireless MC8805.

Looks like not only Dell-branded modems are affected by this issue. According to some user reports HP-branded modems like the HP lt4111 (based on the Sierra Wireless EM7355) are also affected by the issue.

Late last year we started to receive several bugreports in the ModemManager and libqmi mailing lists for these kind of devices. Basically, the modem would never get to a proper online mode with the RF transceivers powered and therefore would never even get registered in the mobile network. This was happening to both QMI and MBIM based configurations, and the direct error message reported by libqmi when trying to get into online mode was just… not very very helpful.

  $ sudo qmicli -d /dev/cdc-wdm1 --dms-get-operating-mode
  [/dev/cdc-wdm1] Operating mode retrieved:
    Mode: 'low-power'
    HW restricted: 'no'

  $ sudo qmicli -d /dev/cdc-wdm1 --dms-set-operating-mode=online
  error: couldn't set operating mode: QMI protocol error (3): 'Internal'

The issue was reported to the kernel, assuming that this would likely be a new missing rfkill related setup in newer Dell laptops. One of the users reported in that same bugreport that actually using Sierra’s GobiNet driver instead of qmi_wwan would end up putting the modem in online mode, so just switching drivers during boot would make it work. WTF?

Digging in Sierra’s GobiNet QMI driver

Well, without much hope of finding anything, and given that I had just bought such a Dell modem myself for testing a new “Dell” plugin, I decided to dig into Sierra’s kernel driver sources. Apart from some already known things (e.g. they use the WDA service to set the net data format in new modems instead of the old CTL service), these lines popped:

  if (is9x15)
    // Set FCC Authentication
    result = QMIDMSSWISetFCCAuth( pDev );
    if (result != 0)
      return result;

The Sierra GobiNet driver is sending some magic “FCC auth” command during boot to the modem; which according to the driver sources maps to command 0x555F in the DMS service. Hey I should try that!

Adding the new command support in libqmi wasn’t difficult, so in some minutes I was ready to test it… and worked.

  $ sudo qmicli -d /dev/cdc-wdm1 --dms-get-operating-mode
  [/dev/cdc-wdm1] Operating mode retrieved:
    Mode: 'low-power'
    HW restricted: 'no'

  $ sudo qmicli -d /dev/cdc-wdm1 --dms-set-fcc-authentication
  [/dev/cdc-wdm1] Successfully set FCC authentication

  $ sudo qmicli -d /dev/cdc-wdm1 --dms-get-operating-mode
  [/dev/cdc-wdm1] Operating mode retrieved:
    Mode: 'online'
    HW restricted: 'no'

Support for this is already available automatically when using libqmi and ModemManager git master. It will hit the next stable releases likely as well.

These fixes have been already released in ModemManager 1.4.4 and libqmi 1.12.4.


Well, I don’t know if there is any command in MBIM to do the same operation (likely there is in a Sierra-specific service), but one thing we could anyway try to do is to use “QMI embedded in MBIM“, which Bjørn has already tested some times. I’ll try to test that some day, but I’ll need to get another modem as my DW5570 only comes up with a QMI configuration. For now, if you’re stuck with this problem using MBIM, you can likely just select USB configuration #1 using usb_modeswitch and get the modem switched to QMI mode.

If your modem is being managed in MBIM and not in QMI, you can now use Collin McMillan’s tool to issue the QMI FCC Auth command embedded in MBIM transactions.


Dell-branded Sierra Wireless modems need the “FCC Auth” command (QMI DMS service, 0x555F) before they can be brought online; supported in libqmi and ModemManager already.

Simulating 2G/3G/4G modem behavior in ModemManager tests

Unit testing is a very powerful approach to quickly find issues that may have been introduced in your software. I have always been very interested in unit testing, even more since my first professional job at Panda Security was implementing a whole new unit testing system for a desktop antivirus.

In ModemManager we had some unit testing support, but it was really only focused on making sure that our AT response parsers worked correctly. These tests are of course very important, not saying they aren’t, but they only cover a very small subset of the implementation.

Supporting completely different devices from multiple vendors with completely different behaviors, while still providing a unified interface for all of them is a very challenging task. In particular, making changes to fix the behavior of one device may lead to broken behavior with others, and the AT response parser unit tests really are not up to the task of finding those issues. So, in order to improve that, we have now included a nice black box system testing environment along with the common unit tests, which can not only simulate AT-based modems, but also let us play with the ModemManager DBus interface directly. And all this by just running make check!

Keep on reading if you want to know how all this was setup🙂


Every test using the new black box system testing will run a common test setup method before the actual test (and a common teardown method after having run it). This setup method will take care of launching a private DBus session using the excellent GTestDBus implementation in GLib/GIO. Once the new bus is ready to use, the test setup will also request a Ping() to the standard org.freedesktop.DBus.Peer interface in ModemManager, which in turn will make the daemon get started by DBus. Once the test fixture is setup, the test itself will be able to make use of the ModemManager process running in the private session, without any interference with the ModemManager that may already be running in the standard system-level bus.


Each test will then setup the simulation of the modem, by launching a separate thread running a Unix-domain socket service. This socket will have an abstract address, and will allow other processes to get connected to send/receive data. In addition to the socket service, the simulator will also read a dictionary of AT requests and responses from a text file included in the test context. This pair of socket and AT chat build together the simulation of an AT port of a modem: AT requests will arrive through the socket, and the simulator will reply the corresponding AT response gathered from the AT chat dictionary. If the dictionary doesn’t have the response expected for a given request, it will just reply “ERROR”.


But the private ModemManager instance doesn’t know anything about the new modem simulator being available, as there is no real physical port being created that ModemManager could get notified about via udev. So, once the simulator is in place, the test will report the abstract address of the socket via the SetProfile() method in the new org.freedesktop.ModemManager.Test interface. This method will just tell ModemManager that a given new virtual AT port is available in a given abstract socket address, and ModemManager will go on creating a new AT virtual port object internally and treat it as if it were a new TTY reported by udev.


As soon as ModemManager knows about the new virtual AT port, it will start probing it and creating a whole Modem object internally. Of course, for this to work well, the simulated modem needs to be able to reply correctly to most AT requests sent by ModemManager. The current implementation provides a generic AT chat dictionary for 3GPP (GSM, UMTS, HSPA, LTE…) devices, and the overall idea is that tests can load first the generic one to get a basic subset of responses, and then load a vendor-specific one with vendor-specific responses (overriding the generic ones if needed).


And of course, the last step is the test itself. Once every previous step has been successfully executed, the tester can now play with the standard ModemManager interfaces in DBus, querying for modems, requesting PIN unlock, enabling or disabling the device, and so on.

The currently available setup is not fully featured yet, it just provides some basic building blocks to be able to extend the black box system tests further more. The real work comes now, adding new behavior tests and writing new AT chat dictionaries to simulate different devices. If you want to play yourself with this setup, get the latest code from git master!