This the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

ModemManager

The ModemManager project

This section provides information about the ModemManager daemon, the libmm-glib library, and the mmcli command line tool.

1 - Dependencies

Build and runtime dependencies of the ModemManager daemon.

Common dependencies

Before you can compile the ModemManager project, you will need at least the following tools:

  • A compliant C toolchain: e.g. glibc or musl libc, gcc or clang/llvm.
  • pkg-config, a tool for tracking the compilation flags needed for libraries.
  • The glib2 library.
    • For ModemManager >= 1.18, glib2 >= 2.56.
    • For ModemManager >= 1.14, glib2 >= 2.48
    • For ModemManager >= 1.6 and < 1.14, glib2 >= 2.36
    • For ModemManager >= 1.0 and < 1.6, glib2 >= 2.32
  • The libgudev library.
    • For ModemManager >= 1.18, libgudev >= 232.
    • For ModemManager >= 1.0 and < 1.18, libgudev >= 147.
  • The gettext tools.
    • For ModemManager >= 1.8, gettext >= 0.19.8.
    • For ModemManager >= 1.6 and < 1.8, gettext >= 0.19.3.
    • For ModemManager >= 1.0 and < 1.6, gettext >= 0.17.

In addition to the previous mandatory requirements, the project also has several optional dependencies that would be needed when enabling additional project features:

  • libmbim, in order to use the MBIM protocol.
    • For ModemManager >= 1.18, libmbim >= 1.26.
    • For ModemManager >= 1.14, libmbim >= 1.24.
    • For ModemManager >= 1.8 and < 1.14, libmbim >= 1.18.
    • For ModemManager >= 1.6 and < 1.8, libmbim >= 1.14.
    • For ModemManager >= 1.0 and < 1.6, libmbim >= 1.4.
  • libqmi, in order to use the QMI protocol.
    • For ModemManager >= 1.18, libqmi >= 1.30.
    • For ModemManager >= 1.16, libqmi >= 1.28.
    • For ModemManager >= 1.14 and < 1.16, libqmi >= 1.26.
    • For ModemManager >= 1.12 and < 1.14, libqmi >= 1.24.
    • For ModemManager >= 1.10 and < 1.12, libqmi >= 1.22.
    • For ModemManager >= 1.8 and < 1.10, libqmi >= 1.20.
    • For ModemManager >= 1.6 and < 1.8, libqmi >= 1.16.
    • For ModemManager >= 1.2 and < 1.6, libqmi >= 1.6.
    • For ModemManager >= 1.0 and < 1.2, libqmi >= 1.4.
  • libqrtr-glib, in order to use Qualcomm SoCs with the QRTR bus.
    • For ModemManager >= 1.18, libqrtr-glib >= 1.0.
  • libpolkit-gobject >= 0.97, in order to allow access control on the DBus methods.
  • systemd support libraries (libsystemd >= 209 or libsystemd-login >= 183), for the optional suspend and resume support.
  • gtk-doc tools, in order to regenerate the documentation.
  • gobject-introspection, in order to generate the introspection support.

Dependencies when building ModemManager 1.18 or later with meson

When building with meson, the following additional dependencies are required:

The following optional dependencies are available when building with meson:

  • bash-completion, in order to add completion support for the command line tools.

Dependencies when building ModemManager 1.18 or earlier with GNU autotools

When building with the GNU autotools, the following additional dependencies are required:

There are two main ways to build the library using GNU autotools: from a git repository checkout and from a source release tarball. When building from a git checkout instead of from a source tarball, the following additional dependencies are required:

2 - Building

How to build and install ModemManager.

This section provides information about how to build and install the ModemManager daemon and its libraries and utilities.

2.1 - Building ModemManager 1.18 or later with Meson

How to build and install the ModemManager daemon and libraries using the meson and ninja build systems.

The first stable series with support for building with the meson suite is 1.18. All the older stable series before 1.18 exclusively used the GNU autotools build system.

Building from a git checkout

When using meson, the builds are always triggered from git checkouts, there is no source release tarball involved. The basic build steps would be as follows:

  $ git clone --depth 1 --branch 1.30.0 https://gitlab.freedesktop.org/mobile-broadband/libqmi.git
  $ cd libqmi
  $ meson setup build --prefix=/usr --sysconfdir=/etc
  $ ninja -C build

Optional switches

Additional optional switches that may be given to the meson command above would be:

  • In Debian/Ubuntu systems the default location for libraries depends on the architecture of the build, so instead of the default /usr/lib path that would be in effect due to --prefix=/usr, the user should also give an explicit --libdir path pointing to the correct location. E.g. on a 64bit Ubuntu/Debian build, the user would use --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu.
  • If the MBIM protocol support is required, the additional -Dmbim=enabled should be given. Omitting this switch will imply auto-detecting whether the feature can be built with the already installed dependencies.
  • If the QMI protocol support is required, the additional -Dqmi=enabled should be given. Omitting this switch will imply auto-detecting whether the feature can be built with the already installed dependencies.
  • If the QRTR protocol support is required, the additional -Dqrtr=enabled should be given. Omitting this switch will imply auto-detecting whether the feature can be built with the already installed dependencies.
  • The suspend/resume handling is enabled by default. In order to disable it, the additional -Dsystemd_suspend_resume=false should be given.
  • The gtk-doc documentation is disabled by default. In order to enable it, the additional -Dgtk_doc=true switch should be given.
  • The GObject introspection support for the libmm-glib library is enabled by default. In order to disable it, the additional -Dintrospection=false switch should be given.
  • The bash-completion support is enabled by default. In order to disable it, the additional -Dbash_completion=false switch should be given.
  • The default build type in meson if none explicitly specified is debug, which means debug symbols are included and optimization is fully disabled. The --buildtype=release switch can be used to remove debug symbols and to enable optimization level to the maximum.

An example project build using all the above optional switches could be:

  $ meson setup build                     \
      --prefix=/usr                       \
      --sysconfdir=/etc                   \
      --libdir=/usr/lib/x86_64-linux-gnu  \
      --buildtype=release                 \
      -Dqmi=enabled                       \
      -Dmbim=enabled                      \
      -Dqrtr=enabled                      \
      -Dsystemd_suspend_resume=false      \
      -Dgtk_doc=true                      \
      -Dintrospection=disabled            \
      -Dbash_completion=false
  $ ninja -C build

Installing

The installation on the prefix selected during meson setup can be done with the following command:

  $ sudo ninja -C build install

Please note that the command above will install the library in the system default path for libraries, possibly overwriting any previous libmm-glib library that may already exist from a package manager installed package. See the FAQ section for comments on how to install in /usr/local instead.

Uninstalling

If you have manually installed the project with the steps above, it can be uninstalled in the same way:

  $ sudo ninja -C build uninstall

If the manual install overwrote the package manager installed files, it is suggested to force a re-install of the corresponding packages at this point, so that the system is not left with missing files.

2.2 - Building ModemManager 1.18 or earlier using GNU autotools

How to build and install the ModemManager daemon and libraries using GNU autotools.

The last stable series with support for building with the GNU autotools suite is 1.18. All the new stable series after 1.18 will exclusively use the meson build system.

Building from a release source tarball

The basic build and installation of the project can be done from an official release source tarball, in the following way:

  $ wget https://www.freedesktop.org/software/ModemManager/ModemManager-1.18.0.tar.xz
  $ tar -Jxvf ModemManager-1.18.0.tar.xz
  $ cd ModemManager-1.18.0
  $ ./configure --prefix=/usr --sysconfdir=/etc
  $ make

Optional switches

Additional optional switches that may be given to the configure command above would be:

  • In Debian/Ubuntu systems the default location for libraries depends on the architecture of the build, so instead of the default /usr/lib path that would be in effect due to --prefix=/usr, the user should also give an explicit --libdir path pointing to the correct location. E.g. on a 64bit Ubuntu/Debian build, the user would use --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu.
  • If the MBIM protocol support is required, the additional --with-mbim should be given. Omitting this switch will imply auto-detecting whether the feature can be built with the already installed dependencies.
  • If the QMI protocol support is required, the additional --with-qmi should be given. Omitting this switch will imply auto-detecting whether the feature can be built with the already installed dependencies.
  • If the QRTR protocol support is required, the additional --with-qrtr should be given. Omitting this switch will imply auto-detecting whether the feature can be built with the already installed dependencies.
  • If the suspend/resume handling is required, the additional --with-suspend-resume=systemd should be given. Omitting this switch will imply auto-detecting whether the feature can be built with the already installed dependencies.
  • If the documentation should be rebuilt, the additional --enable-gtk-doc switch should be given. Omitting this switch will imply auto-detecting whether the documentation can be rebuilt with the already installed dependencies.
  • If the introspection support for the libmm-glib library should be included in the build, the additional --enable-introspection switch should be given. Omitting this switch will imply auto-detecting whether the introspection can be built with the already installed dependencies.
  • When developing changes to the project or debugging issues, it is recommended to build with debug symbols so that running the program under gdb produces useful backtrace information. This can be achieved by providing user compiler flags like these: CFLAGS="-ggdb -O0"

An example project build using all the above optional switches could be:

  $ ./configure                          \
      --prefix=/usr                      \
      --sysconfdir=/etc                  \
      --libdir=/usr/lib/x86_64-linux-gnu \
      --with-qmi                         \
      --with-mbim                        \
      --with-suspend-resume=systemd      \
      --enable-gtk-doc                   \
      --enable-introspection             \
      CFLAGS="-ggdb -O0"
  $ make

Running ./configure --help will show all the possible switches that are supported.

Building from a git checkout

When building from a git checkout, there is one single additional step required to build the project: running the included autogen.sh in order to setup the GNU autotools project and generate a configure script:

  $ git clone https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git
  $ cd ModemManager
  $ NOCONFIGURE=1 ./autogen.sh
  $ ./configure --prefix=/usr --sysconfdir=/etc
  $ make

The same optional switches may be given to the configure script when building from a git checkout.

Installing

The installation on the prefix selected during configure can be done with the following command:

  $ sudo make install

Please note that the command above will install the library in the system default path for libraries, possibly overwriting any previous libmm-glib library that may already exist from a package manager installed package. See the FAQ section for comments on how to install in /usr/local instead.

Location of the DBus service files

By default the DBus service files provided by ModemManager are installed under <prefix>/share/dbus-1/system.d/. If the user uses the default /usr/local prefix instead of the suggested /usr prefix, the DBus service files would be installed in a path that is completely ignored by DBus. If the service files haven’t changed with respect to the one provided by the package manager, this issue can probably be ignored.

Location of the udev rules

By default the udev rules provided by ModemManager are installed under /lib/udev/rules.d/, out of the prefix provided by the user. If the user uses the default /usr/local prefix instead of the suggested /usr prefix, the udev rules would not change location. Changing the location of where the udev rules are installed so that the package manager provided ones are not overwritten can be done e.g. with --with-udev-base-dir=/usr/local/lib/udev/rules.d, but note that these rules will not be actively used by udev as they are not installed in a standard path.

Location of the systemd init files

By default the systemd init files provided by ModemManager are installed under the path specified by the systemd library pkg-config file in the systemdsystemunitdir variable, e.g. /lib/systemd/system/. This path is completely independent to the prefix provided by the user. Changing the location of where the systemd init files are installed so that the package manager provided ones are not overwritten can be done e.g. with --with-systemdsystemunitdir=/usr/local/lib/systemd/system, but note that the init file will not be actively used by systemd as it is not installed in a standard path.

Uninstalling

If you have manually installed the project with the steps above, it can be uninstalled in the same way:

  $ sudo make uninstall

If the manual install overwrote the package manager installed files, it is suggested to force a re-install of the corresponding packages at this point, so that the system is not left with missing files.

3 - Debugging

Debugging issues with the ModemManager daemon

Daemon debug logs

Gathering debug logs of both NetworkManager and ModemManager daemons involves several steps. Although these daemons allow to configure the log level manually while running, some of the issues to debug may require a full reboot of both processes, so the steps below try to cover the most generic case.

Note that the debug logs may contain sensitive information (e.g. PIN number, APN settings, SMS contents). Feel free to remove that information when providing logs to the developers, specifying which was the information removed.

The NetworkManager daemon debug logs would only be required to analyze connectivity related problems. If the issue is unrelated to data connectivity, just the ModemManager daemon debug log should be enough.

When using systemd

Mask and stop the services:

$> sudo systemctl disable NetworkManager ModemManager
$> sudo systemctl stop NetworkManager ModemManager

Manually run with debug enabled:

$> sudo /usr/sbin/ModemManager --debug
$> sudo /usr/sbin/NetworkManager --debug --log-level=DEBUG

Now, reproduce your issue, and gather debug logs. Use Ctrl+C to stop both processes.

Then, unmask the services and start them:

$> sudo systemctl enable NetworkManager ModemManager
$> sudo systemctl start NetworkManager ModemManager

When not using systemd

If you are not using systemd, you can avoid getting the processes automatically launched (e.g. by DBus activation) by moving the program files to another path:

$> sudo mv /usr/sbin/NetworkManager /
$> sudo mv /usr/sbin/ModemManager /
$> sudo killall -TERM NetworkManager
$> sudo killall -TERM ModemManager

Manually run with debug enabled (using the new path):

$> sudo /ModemManager --debug
$> sudo /NetworkManager --debug --log-level=DEBUG

Now, reproduce your issue, and gather debug logs. Use Ctrl+C to stop both processes.

Finally, recover the original places for the program files:

$> sudo mv /ModemManager /usr/sbin/
$> sudo mv /NetworkManager /usr/sbin/

qmi-proxy or mbim-proxy debug logs

Sometimes debugging problems in ModemManager requires not only the daemon’s own debug log, but also the verbose logs of the qmi-proxy or mbim-proxy processes, which are the ones synchronizing the access to the QMI or MBIM control ports. In order to gather these additional logs, explicitly kill the processes and manually launch them in a separate terminal BEFORE running ModemManager --debug:

$> sudo killall mbim-proxy
$> sudo /usr/libexec/mbim-proxy --no-exit --verbose

$> sudo killall qmi-proxy
$> sudo /usr/libexec/qmi-proxy --no-exit --verbose

Usually only one of these proxies is used, there is no need to debug both at the same time.

4 - FCC unlock procedure

FCC unlock procedure integration in ModemManager.

What is the FCC lock?

The FCC lock is a software lock integrated in WWAN modules shipped by several different laptop manufacturers like Lenovo, Dell, or HP. This locks prevents the WWAN module from being put online until some specific unlock procedure (usually a magic command sent to the module) is done.

If the specific unlock procedure is not done, any attempt to enable the radio with any kind of protocol will fail:

  • AT+CFUN=1 will fail, likely with just an ERROR response.
  • QMI DMS Set Operating Mode (ONLINE) will fail, likely with an Invalid transition error.
  • MBIM Radio State (ON) will fail, likely with an Operation not allowed error.

The purpose of this lock is, according to the manufacturers, to have a way to bind the WWAN module to a specific laptop, so that the whole bundle of laptop+module can go through the FCC certification process for radio-enabled devices in the USA. This lock has no other known purpose out of the US regulation.

The FCC lock is also part of a mutual authentication attempt between module and laptop:

  • The laptop BIOS comes with an allowlist of modules that can be installed in the laptop.
  • The WWAN module comes with a FCC lock that should be unlocked by approved laptops only.

Laptop manufacturers should in theory provide a custom FCC unlock tool so that users can use the modules, but the reality is sometimes far from ideal:

  • The unlock tools may be provided only for Windows, if the laptops were not FCC certified to be used in GNU/Linux distributions.
  • The unlock tools are usually provided as proprietary binary programs that are non-auditable and still need to be run as root in the system.
  • The unlock tools will perform system checks to detect which kind of laptop the module is installed in, and if it is not one of the laptops certified by the vendor for use under GNU/Linux, the tool may not unlock the modem, even if the same setup can be used in Windows.
  • The unlock tools sometimes fail to be available for Linux users by the time the laptops are ready to be sold.

FCC unlock procedures in ModemManager < 1.18.4

When the first FCC unlocked modems were shipped in Dell laptops sometime around 2015, users of GNU/Linux distributions started to complain about not being able to use their WWAN modules. These modems were rebranded Sierra Wireless devices, and surprisingly, using the Sierra Wireless provided kernel drivers the modules were unlocked successfully. This lead to finding the QMIDMSSWISetFCCAuth() operation (DMS 0x555F) in the Sierra SDK, which was successfully reverse engineered into libqmi 1.12.4.

The FCC unlock logic done for these modules was added into ModemManager 1.4.4 for all QMI capable devices, just attempting to run it any time we found the attempt to put the module online failed.

In 2018, Dell included newer FCC locked modems, like the Foxconn rebranded DW5821e, in their laptops. Dell also provided a Windows unlock tool (DW5821e and DW5829e Click Cust Kit), and likely some built-in unlock tool hidden in the Ubuntu-based preinstallations they shipped in the laptops when sold with GNU/Linux. During this time, there were some attempts to reverse engineer the unlock procedure using a USB monitoring capture from Windows when running the Cust Kit tool, but none of them seemed to be usable for some reason.

Fast forward to 2021, when Lenovo shipped the newest X1 Nano and Carbon Gen9 laptops with new FCC locked modules, and users started to complain again. These laptops were released with 3 different approved modules: Foxconn SDX55, Quectel EM120, and Fibocom L860. By the time the first SDX55 modules were available there was still no unlock tool provided by Lenovo, so there was not much anyone could do. But the SDX55 was a Foxconn module, same as the DW5821e for which the Dell Cust Kit tool was reverse engineered, and so users tried that same procedure that never worked with the DW5821e, just to find that it worked fine with the SDX55. This unlock procedure was included in libqmi 1.28.6, and integrated for automatic unlocking in ModemManager 1.16.6.

Not much later, users started to complain about the Quectel EM120 module being locked. A user of this module was able reverse engineer the Lenovo-provided lenovo-wwan-dpr tool and discover the magic MBIM command that was being sent in this case. This procedure has not been integrated for automatic unlock in any ModemManager version.

Whether to automatically unlock or not the modules in ModemManager

When the first FCC unlock procedure was reverse engineered for the rebranded Sierra Wireless modules, there was not much discussion on whether the procedure should be run or not by ModemManager. It was obviously defeating the purpose of the laptop manufacturer, but so was the Sierra Wireless driver source provided by Sierra Wireless themselves. If they were doing it, why should ModemManager not do it?

The picture with the new WWAN modules in Lenovo laptops is completely different, though. The FCC unlock procedure for the EM120 was reverse engineered from the Lenovo-provided lenovo-wwan-dpr tool, which performs not only the FCC unlock, but also dynamic power reduction based on sensors in the laptop. This means that the actual magic command used to unlock the module may be somehow related to some SAR level defaults configured in the WWAN module, and as we don’t have the full picture of what it does or doesn’t, it can be considered a bit risky to perform the automatic unlock unconditionally. The same reasoning would apply for the Foxconn SDX55, for which not even a Lenovo provided tool was used to reverse engineer the unlock procedure. The sad truth is that only the laptop vendors and modem manufacturers know what those commands are really doing, and they may be doing more than FCC unlocking the modules. If the procedures are related in any way to SAR levels and dynamic power reduction, ModemManager should better not automatically unlock these modules.

This discussion went on for several months, both publicly in gitlab issues and mailing list, and privately via emails and calls with the laptop vendors, modem manufacturers and other key members of the community. After much thought, the ModemManager maintainer took a clear way forward that would hopefully meet halfway of both sides: ModemManager will keep on providing support for the known FCC unlock procedures, but no longer automatically: the user must install and select the FCC unlock procedure needed in the specific laptop being used.

FCC unlock procedures in ModemManager >= 1.18.4

Since release 1.18.4, the ModemManager daemon no longer automatically performs the FCC unlock procedure by default. The user must, under their own responsibility, enable the automatic FCC unlock as shipped by ModemManager.

ModemManager ships several scripts installed under ${datadir}/ModemManager/fcc-unlock.available.d, and named as vid:pid with either the PCI or USB vendor and product IDs. E.g. in a system where ${datadir} is /usr/share:

  • For the HP 820 G1 (EM7355): /usr/share/ModemManager/fcc-unlock.available.d/03f0:4e1d
  • For the Dell DW5570 (MC8805): /usr/share/ModemManager/fcc-unlock.available.d/413c:81a3
  • For the Dell DW5808 (MC7355): /usr/share/ModemManager/fcc-unlock.available.d/413c:81a8
  • For the Lenovo-shipped EM7455: /usr/share/ModemManager/fcc-unlock.available.d/1199:9079
  • For the Foxconn SDX55: /usr/share/ModemManager/fcc-unlock.available.d/105b:e0ab
  • For the Quectel EM120: /usr/share/ModemManager/fcc-unlock.available.d/1eac:1001

These scripts in ${datadir} are not automatically used by ModemManager. In order for ModemManager to automatically attempt a specific FCC unlock procedure, the user must create a link to the script from ${datadir}/ModemManager/fcc-unlock.available.d into the ${sysconfdir}/ModemManager/fcc-unlock.d directory. E.g. in a system where ${datadir} is /usr/share and ${sysconfdir} is /etc:

 $ sudo ln -sft /etc/ModemManager/fcc-unlock.d /usr/share/ModemManager/fcc-unlock.available.d/<vid>:<pid>

ModemManager will only use the unlock script required for the specific vid:pid the module exposes, so users may also choose to link all the files from ${datadir}/ModemManager/fcc-unlock.available.d into ${sysconfdir}/ModemManager/fcc-unlock.d. E.g. in a system where ${datadir} is /usr/share and ${sysconfdir} is /etc:

 $ sudo ln -sft /etc/ModemManager/fcc-unlock.d /usr/share/ModemManager/fcc-unlock.available.d/*

It is suggested that GNU/Linux distributions do not ship these FCC unlock scripts enabled in the ${sysconfdir}/ModemManager/fcc-unlock.d directory themselves, for the same reasons that ModemManager does not to perform the automatic unlock unconditionally.

The ${sysconfdir}/ModemManager/fcc-unlock.d path should be exclusively used for links or programs manually installed by the user.

The scripts shipped by ModemManager use either mbimcli or qmicli to perform the raw FCC unlock procedure. The user should make sure those tools are installed in the system, as they are not direct dependencies of ModemManager in any way. E.g. in Debian/Ubuntu systems, these tools are provided by the libmbim-utils and libqmi-utils packages.

Integration with third party FCC unlock tools

Laptop vendors and modem manufacturers may also provide their own FCC unlock tools, e.g. running their own proprietary binary programs to perform the unlock in the safest way they know. These tools may be packaged for each distribution, and should be installed in ${libdir}/ModemManager/fcc-unlock.d.

The third party FCC unlock tools will allow an easy integration of the procedure with ModemManager, so that the unlock is performed only when required to do so (when attempting to go online) and not at random times (which would make the state of the modem cached by ModemManager inconsistent).

Third party FCC unlock scripts or programs should consider the same limitations as imposed to the ModemManager shipped ones:

  • Must be owned by the root user.
  • Must be readable and executable by the owner exclusively and not setuid.
  • Will receive the full modem DBus path as first argument, followed by the control port names (without /dev prefix) of the modem to unlock.
  • Must not launch processes on background; i.e. these are not service management scripts.
  • Must run in less than 5 seconds, or otherwise they will be killed by ModemManager.
  • Must return 0 on success.

Once the tool is run by ModemManager, the daemon will attempt again to bring the modem into online power state using the protocol specific messages. If this operation fails again, the FCC unlock procedure will not be automatically tried any more.

The ${libdir}/ModemManager/fcc-unlock.d path should be exclusively used for links or programs installed by third party packages.