Port and device detection
Udev
The ModemManager
daemon does not attempt to detect by itself which modems are available in the system. It instead relies on the udevd
daemon and the port addition and removal events produced whenever the port states change in the kernel.
ModemManager
also uses an explicit query on udev
during bootup in order to know which ports were detected and exposed before the daemon was ready to receive new addition and removal events.
Only per-port events are monitored; i.e. explicit port addition and removals. Other events associated with the modem device, like full device addition or removal notifications or per-interface notifications (in USB devices for example) are ignored. On a new device detection, this logic will therefore receive one addition event for each port exposed by the modem.
The ModemManager
device detection procedure keeps some timeouts in place so that the logic stops waiting for more ports to be notified after some time. This logic assumes that new port additions in a given device happen in a timely manner, which is the most usual case; if for any reason one of the ports ends up being notified much later than the others, the port may end up fully ignored.
Monitored subsystems
Each plugin in ModemManager
registers a list of subsystems it is interested in monitoring. When the available plugins are loaded, the daemon will therefore compile a list of all subsystems that the registered plugins are requesting.
The subsystems usually monitored are:
tty
subsystem: where all serial ports are exposed (e.g.ttyS0
,ttyUSB0
,ttyACM0
,ttyHS0
…).usbmisc
subsystem: where thecdc-wdm
ports (either QMI, MBIM or AT) are exposed.net
subsystem: where all the network ports are exposed.wwan
subsystem: where all control ports for PCIe devices and some Qualcomm SoCs are exposed. This subsystem also exposes control ports for QMI and MBIM USB devices, in addition to the originalcdc-wdm
ports in theusbmisc
subsystem, but these are considered duplicates and ignored byModemManager
.qrtr
subsystem: This is not a real device subsystem in the kernel, butModemManager
uses this to reference modem management nodes exposed in the Qualcomm specific QRTR bus. Given that these nodes don’t have any exposure insysfs
, there is no way to bindudev
tags to them.
udev tags
The tags in udev
have several different primary purposes, but in general they can be seen as a way ModemManager
uses to configure device specific behaviors.
ModemManager
ships and documents several generic udev
tags that can be applied to any type of device, and several plugin-specific tags that are meaningful to a set of devices or to a specific manufacturer. The generic udev
tags are included and explained in the ModemManager
API documentation.
Generic candidate ports and grouping rules
These are rules that allow ModemManager
to identify which devices should be detected and probed as possible cellular devices.
Generic port or device ignoring rules
These are rules that allow the user to deny access to certain ports on a given device, or to full devices.
Generic port type hint rules
These are rules that allow the probing logic of ModemManager
to decide faster what kind of protocol is expected in a given port, as well as specifying behavior that is expected in that port (e.g. in AT ports there may be one port that is targeted to be used for PPP and not for general control).
- ID_MM_PORT_TYPE_AT_PRIMARY
- ID_MM_PORT_TYPE_AT_SECONDARY
- ID_MM_PORT_TYPE_AT_GPS_CONTROL
- ID_MM_PORT_TYPE_AT_PPP
- ID_MM_PORT_TYPE_QCDM
- ID_MM_PORT_TYPE_GPS
- ID_MM_PORT_TYPE_AUDIO
- ID_MM_PORT_TYPE_QMI
- ID_MM_PORT_TYPE_MBIM
Generic RS232 port configuration rules
Plugin-specific device identification rules
Certain modems, like the Ericsson MBM modules, require explicit tags to identify them as being modems that can be controlled by ModemManager
. This is usually required with manufacturers that ship many types of different devices under the same USB or PCI vendor identification.
Feature configuration/disabling rules
There are cases where some specific features are non-functional in a given device, or even worse, they may end up triggering irrecoverable firmware crashes. When they are identified, feature specific udev
tags are set in the relevant modem ports so that ModemManager
knows it should avoid using that feature. Notable examples include the AT^NDISDUP
support in Huawei devices or the AT+CPOL
based management in multiple plugins.
Adding new udev tags
Users can specify udev
tags themselves, by creating new rules files that are installed (usually) under /lib/udev/rules.d
. There aren’t many requirements to this user rules files, but the existing ones are important:
- The rules file names should be prefixed by either
78-mm-
or79-mm-
. This is so that the user-defined rules are processed after the generic rules (which are all installed as77-mm-
) and before the candidate rules (in the80-mm-
prefixed rules file). - Even though official udev rules allow running multiple actions matching a set of rules, the
ModemManager
udev
rules always process one single action on every line. This is a limitation of the customudev
rule parser used inopenwrt
. - Following the same pattern as the
ModemManager
udev
rules, the rules should be run onadd
,change
,move
andbind
ACTION
s. - Port specific tags should be applied to specific ports (e.g. USB ports identified by the USB interface number).
- Device specific tags should be applied to all control ports in the same way or to the full device if there is one in the
sysfs
tree. - Beware of
SUBSYSTEMS
vsSUBSYSTEM
, orATTRS
vsATTR
and so on. One (without the trailingS
) matches a specific device in the device hierarchy, while the other (with the trailingS
) matches a device and all its parents on the hierarchy. For example, a TTY port in a USB device will definitely matchSUBSYSTEMS==”usb”
(because a direct parent of the TTY port will be the physical USB device) but it will also matchSUBSYSTEMS==”pci”
(because the USB controller where the device is managed is hanging off the PCI bus). - Writing udev rules is tricky, so following what the existing rules do is always a good approach.
A new set of rules specified by a user could look like this:
$ cat /lib/udev/rules.d/78-mm-my-rules.rules
ACTION!="add|change|move|bind", GOTO="mm_my_rules_end"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1234", GOTO="mm_my_rules"
GOTO="mm_my_rules_end"
LABEL="mm_my_rules"
# Store interface number in an env var
SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", \
ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}"
# USB iface #0 will be primary AT port
ATTRS{idVendor}=="1234", ATTRS{idProduct}=="abcd", ENV{.MM_USBIFNUM}=="00", \
SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1"
# USB iface #1 will be PPP port
ATTRS{idVendor}=="1234", ATTRS{idProduct}=="abcd", ENV{.MM_USBIFNUM}=="01", \
SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PPP}="1"
LABEL="mm_my_rules_end"
Once the new file in the filesystem is created, validating whether the tags are correctly applied would involve two steps:
- First, reloading and applying the rules:
$ sudo udevadm control –reload
$ sudo udevadm trigger
- Second, showing which tags are available in the target port:
$ sudo udevadm info -p /sys/class/tty/ttyUSB0
Hotplug in Openwrt
There is no udev
in openwrt
, so ModemManager
has an alternative way to get notified of the port addition and removal events. In this operating system, the ModemManager
package installs a set of hotplug
scripts that are called by the openwrt
init system whenever port state changes happen in the kernel. As in the case of udev
, ModemManager
processes per-port events and determines at runtime which ports should be aggregated into the same modem object.
During ModemManager
bootup, the init script in openwrt
will ensure that all the port addition and removal events that happened before the daemon was ready to process them are properly queued up so that they get processed in the same order as they originally happened.
There is also no udev
rules processing in openwrt
, and so ModemManager
does its own processing of the rules in a way that should be mostly equivalent to how udev
processes them. The built-in udev
processor in ModemManager
is not as complete as the original one, so adding custom rules may not always work, unless the new rules are equivalent to other existing ones and therefore implicitly supported.
Port selection filters in ModemManager
The ModemManager
daemon will not probe all possible control ports it finds, as doing so would break a lot of non-modem ports that devices expose as TTYs. But this was not the default behavior in older releases, and the ModemManager
daemon would end up poking serial ports at will while breaking the communication attempted by the real user processes of those serial ports. Users reported issues where the daemon poked Arduino serial ports, GPS devices, or even screen readers for the visually impaired. A lot of effort was put into improving this situation, which led to a series of changes during several years to reach the state we have now.
- Until release 1.8.0, the default behavior of
ModemManager
was to by default attempt to probe TTY ports unless they were deny-listed explicitly. The project would maintain a large list ofudev
rules identifying devices that are not modems but still exposed TTYs, but (no surprise) keeping that list up to date was a mess and very error prone. - In release 1.8.0, a new set of filter types was introduced:
- The old behavior, where ports were probed unless explicitly flagged with a specific
udev
tag, was still the default one and the filter was named “default”. With this filter, platform serial ports (e.g. real RS232 physical ports in the system) could be automatically probed if a manual scan operation was triggered. - “whitelist-only” filter, in which
ModemManager
would only probe control ports if they were explicitly flagged with theID_MM_DEVICE_PROCESS
udev
tag. - “strict” , in which
ModemManager
would by default not probe the TTY ports unless it knew with a high amount of certainty that the port was a modem port; e.g. with rules checking for AT protocol support definitions inttyACM
ports, looking at which kernel drivers are in use, or even based on port type hint rules already defined inModemManager
. The option to request a manual scan was also removed when this filter was used. Platform RS232 ports need to be explicitly flagged (e.g. withID_MM_DEVICE_PROCESS
) to be probed. - “paranoid” filter was equal to the “strict” mode but also applied the list of denied devices that the “default” filter was based on.
- The old behavior, where ports were probed unless explicitly flagged with a specific
- In release 1.14.0,
ModemManager
would switch to use the “strict” filter by default if no other one was explicitly selected. The old “default” filter was renamed to “legacy” and considered deprecated. - In release 1.18.0 the “legacy” and “paranoid” filter types were fully removed, along with all the lists of udev rules for denied devices.
- In release 1.20.0 the “whitelist-only” filter was renamed to “allowlist-only”, while deprecating the older name.
Since 1.20.0 only the “strict” and “allowlist-only” filter types are used, defaulting to “strict” if none is explicitly selected. These filters will be mapped to more detailed rules applied by ModemManager
upon device detection.
E.g. when the “strict” filter is selected, all the heuristics to detect cellular device ports are enabled, as seen in the daemon debug logs:
[filter] created
[filter] explicit allowlist: yes
[filter] explicit blocklist: yes
[filter] plugin allowlist: yes
[filter] qrtr devices allowed: yes
[filter] virtual devices forbidden: yes
[filter] net devices allowed: yes
[filter] usbmisc devices allowed: yes
[filter] rpmsg devices allowed: yes
[filter] wwan devices allowed: yes
[filter] tty devices:
[filter] platform driver check: yes
[filter] driver check: yes
[filter] cdc-acm interface check: yes
[filter] with net check: yes
[filter] default: forbidden
When the “allowlist-only” filter is selected, the amount of rules enabled is limited to only one, the explicit allowlist:
[filter] created
[filter] explicit allowlist: yes
[filter] explicit blocklist: no
[filter] plugin allowlist: no
[filter] qrtr devices allowed: no
[filter] virtual devices forbidden: no
[filter] net devices allowed: no
[filter] usbmisc devices allowed: no
[filter] rpmsg devices allowed: no
[filter] wwan devices allowed: no
[filter] tty devices: no
Worth noting, ModemManager
does not touch the network ports of a modem in any way. During the daemon startup there isn’t a strict list of rules to decide whether a network port is part of a modem device or not, the network ports are seen as additional ports in a modem if other control ports are found and validated.
Example device detection logs
The following log shows the device detection phase of a device during ModemManager bootup, with comments about what is happening at each moment.
// ttyUSB0 is detected via udev, a set of port identification
// parameters are preloaded.
[34.337] [ttyUSB0] port contents loaded:
[34.338] [ttyUSB0] bus: usb
[34.339] [ttyUSB0] interface: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1/2-4.1.1:1.2
[34.340] [ttyUSB0] device: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1
[34.340] [ttyUSB0] driver: qcserial
[34.341] [ttyUSB0] vendor: 1199
[34.341] [ttyUSB0] product: 9091
[34.342] [ttyUSB0] revision: 0006
[34.343] [base-manager] adding port ttyUSB0 at sysfs path: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1/2-4.1.1:1.2/ttyUSB0/tty/ttyUSB0
// The currently active filter flags the port as allowed and specifies
// why. In this case, the specific vid (1199) is allowlisted by the
// Sierra plugin.
[34.359] [filter] (tty/ttyUSB0) port allowed: device is allowlisted by plugin (vid)
// ttyUSB0 is the first port detected in the modem device.
[34.360] [base-manager] port ttyUSB0 is first in device /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1
// A new support task is created for the device, which will determine
// which plugin takes care of managing it. In this case, the task is
// not yet launched because there is a “minimum wait time” that
// ModemManager waits before starting the probing tasks (a few
// seconds).
[34.373] [plugin-manager] task 0: new support task for device: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1
[34.391] [plugin-manager] task 0: port grabbed: ttyUSB0
[34.393] [plugin-manager] task 0,ttyUSB0: new support task for port
[34.393] [plugin-manager] task 0,ttyUSB0: deferred until min wait time elapsed
// ttyUSB1 is detected via udev, a set of port identification
// parameters are preloaded.
[34.398] [ttyUSB1] port contents loaded:
[34.398] [ttyUSB1] bus: usb
[34.398] [ttyUSB1] interface: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1/2-4.1.1:1.3
[34.398] [ttyUSB1] device: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1
[34.399] [ttyUSB1] driver: qcserial
[34.399] [ttyUSB1] vendor: 1199
[34.399] [ttyUSB1] product: 9091
[34.399] [ttyUSB1] revision: 0006
[34.399] [base-manager] adding port ttyUSB1 at sysfs path: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1/2-4.1.1:1.3/ttyUSB1/tty/ttyUSB1
[34.402] [filter] (tty/ttyUSB1) port allowed: device is allowlisted by plugin (vid)
// ttyUSB1 is added as an additional port to the already existing
// device.
[34.404] [base-manager] additional port ttyUSB1 in device /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1
// The support task is notified about the new ttyUSB1 port, but still
// deferred.
[34.405] [plugin-manager] task 0: port grabbed: ttyUSB1
[34.407] [plugin-manager] task 0,ttyUSB1: new support task for port
[34.407] [plugin-manager] task 0,ttyUSB1: deferred until min wait time elapsed
// wwan0 net port is detected via udev, a set of port identification
// parameters are preloaded.
[34.779] [wwan0] port contents loaded:
[34.779] [wwan0] bus: usb
[34.779] [wwan0] interface: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1/2-4.1.1:1.0
[34.779] [wwan0] device: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1
[34.779] [wwan0] driver: cdc_mbim
[34.780] [wwan0] vendor: 1199
[34.780] [wwan0] product: 9091
[34.780] [wwan0] revision: 0006
[34.780] [base-manager] adding port wwan0 at sysfs path: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1/2-4.1.1:1.0/net/wwan0
[34.782] [filter] (net/wwan0) port allowed: device is allowlisted by plugin (vid)
[34.783] [base-manager] additional port wwan0 in device /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1
// The support task is notified about the new wwan0 port, but still
// deferred.
[34.784] [plugin-manager] task 0: port grabbed: wwan0
[34.784] [plugin-manager] task 0,wwan0: new support task for port
[34.785] [plugin-manager] task 0,wwan0: deferred until min wait time elapsed
// cdc-wdm2 net port is detected via udev, a set of port
// identification parameters are preloaded.
[34.817] [cdc-wdm2] port contents loaded:
[34.817] [cdc-wdm2] bus: usb
[34.817] [cdc-wdm2] interface: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1/2-4.1.1:1.0
[34.817] [cdc-wdm2] device: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1
[34.817] [cdc-wdm2] driver: cdc_mbim
[34.817] [cdc-wdm2] vendor: 1199
[34.818] [cdc-wdm2] product: 9091
[34.818] [cdc-wdm2] revision: 0006
[34.818] [base-manager] adding port cdc-wdm2 at sysfs path: /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1/2-4.1.1:1.0/usbmisc/cdc-wdm2
[34.819] [filter] (usbmisc/cdc-wdm2) port allowed: device is allowlisted by plugin (vid)
[34.819] [base-manager] additional port cdc-wdm2 in device /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1
// The support task is notified about the new cdc-wdm2 port, but still
// deferred.
[34.820] [plugin-manager] task 0: port grabbed: cdc-wdm2
[34.820] [plugin-manager] task 0,cdc-wdm2: new support task for port
[34.820] [plugin-manager] task 0,cdc-wdm2: deferred until min wait time elapsed
// Once the “minimum wait time” elapses, the support task launches
// per-port checks to decide which plugin should manage the device.
[35.878] [plugin-manager] task 0: min wait time elapsed
// In this case, cdc-wdm2 is the first port that gets checked. The
// logic will go over all existing plugins to decide which ones can
// manage the port. Initially, the logs will include messages for all
// the plugins that cannot manage the port and why.
[35.885] [plugin/tp-link] port cdc-wdm2 filtered by implicit MBIM driver
[35.887] [plugin/simtech] port cdc-wdm2 filtered by implicit MBIM driver
[35.887] [plugin/via] port cdc-wdm2 filtered by subsystem
...
[35.896] [plugin/x22x] port cdc-wdm2 filtered by implicit MBIM driver
[35.896] [plugin/u-blox] port cdc-wdm2 filtered by subsystem
// Once all plugins have been checked, a list of possible plugins is
// built and each plugin is then asked to probe each port.
[35.899] [plugin-manager] task 0,cdc-wdm2: found '2' plugins to try
[35.900] [plugin-manager] task 0,cdc-wdm2: will try with plugin 'sierra'
[35.900] [plugin-manager] task 0,cdc-wdm2: will try with plugin 'generic'
[35.901] [plugin-manager] task 0,cdc-wdm2: started
[35.901] [plugin-manager] task 0,cdc-wdm2: checking with plugin 'sierra'
// The list of probe types required is decided per port type. For a
// MBIM device, only checking MBIM capabilities is enough.
[35.906] [plugin/sierra] probes required for port cdc-wdm2: 'mbim'
[35.908] [cdc-wdm2/probe] launching port probing: 'mbim'
// The next port to be checked is wwan0, again it goes through all the
// different available plugins.
[35.910] [plugin/tp-link] port wwan0 filtered by implicit MBIM driver
[35.910] [plugin/simtech] port wwan0 filtered by implicit MBIM driver
…
[35.915] [plugin/x22x] port wwan0 filtered by implicit MBIM driver
[35.915] [plugin/u-blox] port wwan0 filtered by implicit MBIM driver
// And the list of possible plugins is built for the wwan0 port.
[35.915] [plugin-manager] task 0,wwan0: found '2' plugins to try
[35.915] [plugin-manager] task 0,wwan0: will try with plugin 'sierra'
[35.915] [plugin-manager] task 0,wwan0: will try with plugin 'generic'
[35.915] [plugin-manager] task 0,wwan0: started
[35.915] [plugin-manager] task 0,wwan0: checking with plugin 'sierra'
// The probing of network ports does absolutely nothing, the operation
// will just be deferred until some other port suggests a plugin to be
// selected.
[35.917] [plugin/sierra] probing of port wwan0 deferred until result suggested
// The next port to be checked is ttyUSB1, again it goes through all
// the different available plugins.
[35.917] [plugin/tp-link] port ttyUSB1 filtered by implicit MBIM driver
[35.917] [plugin/simtech] port ttyUSB1 filtered by implicit MBIM driver
…
[35.921] [plugin/x22x] port ttyUSB1 filtered by implicit MBIM driver
[35.921] [plugin/u-blox] port ttyUSB1 filtered by implicit MBIM driver
// And the list of possible plugins is built for the ttyUSB1 port.
[35.922] [plugin-manager] task 0,ttyUSB1: found '2' plugins to try
[35.922] [plugin-manager] task 0,ttyUSB1: will try with plugin 'sierra'
[35.922] [plugin-manager] task 0,ttyUSB1: will try with plugin 'generic'
[35.922] [plugin-manager] task 0,ttyUSB1: started
[35.922] [plugin-manager] task 0,ttyUSB1: checking with plugin 'sierra'
// For the ttyUSB1 port we need to check different things that the
// plugin requires, it needs to know whether its AT or QCDM, and if
// it’s AT, whether it supports Intel specific XMM operations.
[35.925] [plugin/sierra] probes required for port ttyUSB1: 'at, at-xmm, qcdm'
// The port is known to be possibly AT because it’s flagged with a
// udev tag as a primary or secondary AT port, so all non-AT related
// probes are removed.
[35.925] [ttyUSB1/probe] no QCDM/QMI/MBIM probing in possible AT port
[35.926] [ttyUSB1/probe] port is not QCDM-capable
[35.926] [ttyUSB1/probe] port is not QMI-capable
[35.927] [ttyUSB1/probe] port is not MBIM-capable
[35.927] [ttyUSB1/probe] launching port probing: 'at, at-xmm'
// The next port to be checked is ttyUSB0, again it goes through all
// the different available plugins.
[35.928] [plugin/tp-link] port ttyUSB0 filtered by implicit MBIM driver
[35.928] [plugin/simtech] port ttyUSB0 filtered by implicit MBIM driver
…
[35.932] [plugin-manager] task 0,ttyUSB0: found '2' plugins to try
[35.932] [plugin-manager] task 0,ttyUSB0: will try with plugin 'sierra'
[35.933] [plugin-manager] task 0,ttyUSB0: will try with plugin 'generic'
[35.933] [plugin-manager] task 0,ttyUSB0: started
[35.933] [plugin-manager] task 0,ttyUSB0: checking with plugin 'sierra'
// As in the ttyUSB1 case, for ttyUSB0 the plugin also requires
// certain probes to be launched.
[35.933] [plugin/sierra] probes required for port ttyUSB0: 'at, at-xmm, qcdm'
// But ttyUSB0 is flagged in udev as being a GPS data port, so all
// probes end up removed, there is nothing to probe in such a port.
[35.934] [ttyUSB0/probe] GPS port detected
[35.934] [ttyUSB0/probe] port is not AT-capable
[35.935] [ttyUSB0/probe] port is not QCDM-capable
[35.935] [ttyUSB0/probe] port is not QMI-capable
[35.935] [ttyUSB0/probe] port is not MBIM-capable
[35.936] [ttyUSB0/probe] port probing finished: no more probings needed
// ttyUSB0 is the first port to finish all its probings, so the result
// of the suggested plugin is forwarded to all the other ports.
[35.938] [plugin-manager] task 0,wwan0: deferring support check until result suggested
[35.941] [plugin-manager] task 0,ttyUSB0: found best plugin for port (sierra)
[35.942] [plugin-manager] task 0,ttyUSB0: finished in '1.549135' seconds
[35.951] [plugin-manager] task 0,ttyUSB0: found best plugin: sierra
[35.954] [plugin-manager] task 0,cdc-wdm2: got suggested plugin (sierra)
// The suggested plugin helps complete the wwan0 port probe task that was
// deferred.
[35.954] [plugin-manager] task 0,wwan0: deferred task completed, got suggested plugin (sierra)
[35.955] [plugin-manager] task 0,ttyUSB1: got suggested plugin (sierra)
[35.957] [plugin-manager] task 0: still 3 running probes (3 active): cdc-wdm2, wwan0, ttyUSB1
// The MBIM probing task in cdc-wdm2 starts.
[35.961] [cdc-wdm2/probe] probing MBIM...
// The AT probing task ttyUSB1 starts. Note that the port type udev
// tag only provides a hint of the protocol that may be supported, the
// daemon still checks for explicit AT protocol support.
[36.036] [ttyUSB1/at] opening serial port...
[36.045] [ttyUSB1/at] setting up baudrate: 57600
[36.048] [ttyUSB1/at] no flow control explicitly requested for device
[36.051] [ttyUSB1/at] port attributes not fully set
[36.055] [ttyUSB1/at] device open count is 1 (open)
[36.058] [plugin-manager] task 0,wwan0: checking with plugin 'sierra'
[36.058] [plugin/sierra] probing of port wwan0 deferred until result suggested
[36.081] [plugin-manager] task 0,wwan0: completed, got suggested plugin (sierra)
[36.081] [plugin-manager] task 0,wwan0: finished in '1.297005' seconds
[36.082] [plugin-manager] task 0,wwan0: best plugin matches device reported one: sierra
[36.083] [plugin-manager] task 0: still 2 running probes (2 active): cdc-wdm2, ttyUSB1
// The MBIM port probing task finishes and reports whether the port is
// MBIM capable.
[36.260] [cdc-wdm2/probe] port is MBIM-capable
[36.262] [/dev/cdc-wdm2] closing device...
[36.286] [plugin-manager] task 0,cdc-wdm2: found best plugin for port (sierra)
[36.286] [plugin-manager] task 0,cdc-wdm2: finished in '1.465742' seconds
[36.286] [plugin-manager] task 0,cdc-wdm2: best plugin matches device reported one: sierra
[36.287] [plugin-manager] task 0: still 1 running probes (1 active): ttyUSB1
[36.321] [plugin-manager] task 0: extra probing time elapsed
[36.321] [plugin-manager] task 0: still 1 running probes (1 active): ttyUSB1
[36.878] [plugin-manager] task 0: min probing time elapsed
[36.879] [plugin-manager] task 0: still 1 running probes (1 active): ttyUSB1
// AT probing in this case completely fails in ttyUSB1, so it is
// flagged as not being AT capable.
[42.778] [ttyUSB1/at] --> 'AT<CR>'
[45.778] [ttyUSB1/at] --> 'AT<CR>'
[48.777] [ttyUSB1/at] --> 'AT<CR>'
[51.776] [ttyUSB1/at] --> 'AT<CR>'
[54.778] [ttyUSB1/probe] port is not AT-capable
[54.780] [plugin-manager] task 0,ttyUSB1: found best plugin for port (sierra)
[54.780] [plugin-manager] task 0,ttyUSB1: finished in '20.373198' seconds
[54.785] [plugin-manager] task 0,ttyUSB1: best plugin matches device reported one: sierra
// The whole device probing sequence takes around 20s in this case,
// mainly due to the AT command timeouts happening in ttyUSB1.
[54.785] [plugin-manager] task 0: no more ports to probe
[54.785] [plugin-manager] task 0: finished in '20.412880' seconds
// The plugin manager ends up creating a new modem object via the
// Sierra plugin.
[54.787] [device /sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1] creating modem with plugin 'sierra' and '4' ports
[54.791] [plugin/sierra] (sierra) MBIM-powered Sierra modem found...
[54.894] [cdc-wdm2/mbim] port monitoring enabled in MBIM port
[54.898] [modem0] port 'usbmisc/cdc-wdm2' grabbed
[54.901] [modem0] port 'net/wwan0' grabbed
[54.902] [plugin/sierra] could not grab port ttyUSB1: Cannot add port 'tty/ttyUSB1', unhandled port type
[54.905] [modem0] port 'tty/ttyUSB0' grabbed
[54.910] [modem0] net/wwan0: net (data)
[54.911] [modem0] tty/ttyUSB0: gps (nmea)
[54.912] [modem0] usbmisc/cdc-wdm2: mbim
[54.938] [base-manager] modem for device '/sys/devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1.1' successfully created