ModemManager plugins exist in order to handle all non-standard vendor-specific behaviour that needs to get supported.
Plugins will provide their own Modem object implementations, usually subclassing the generic MMBroadbandModem object. As previously explained, this object implements every interface that may be exported by the Modem object in DBus; and then, depending on the per-interface support checks, the interface will end up being really exported or not.
Each interface defines every step to be run during the initialization, enabling or disabling sequences. Then, the object implementing the interface may or may not provide the implementation of such step. By default, the generic MMBroadbandModem object implements already most of the steps in the interfaces providing common features:
Vendor-specific subclasses of MMBroadbandModem are then able to either provide their own implementation of a given step (in the image below, a custom implementation for capabilities checking); or even completely disable the step if they know that there is no way to run it (in the image below, revision string loading is removed).
These subclass-able steps are all implemented as standard GIO asynchronous functions,
so subclassing a step involves implementing both the async method which receives the
input arguments to the action and the corresponding
method
which provides the results of the action once the operation is ready.
_finish()
It is worth noting that these steps and the asynchronous methods implementing them don't assume that an AT port will be used to implement the real action. This means that any other kind of port may be really used (e.g. QCDM or QMI) in the implementation, or even that a static reply can be returned (e.g. Iridium modems will always report "Iridium" as current OperatorName).