## Probing

Whenever a new device is detected by ModemManager, port probing process will get started, so that we can determine which kind of ports we have, and also which plugin we need to use for the specific device. Devices may expose one or more ports, and all of them will follow the same probing logic.

The whole probing process, including pre-probing and post-probing filters, is implemented in the core ModemManager daemon. Plugins will just configure their own special needs in the probing process, so that only the steps required by the given plugin are executed. For example, plugins which do not support RS232 devices will not need AT-based vendor or product filters.

### Pre-probing filters

Pre-probing filters are those which control whether the probing, as requested by the specific plugin, takes place.

- Allowed vendor IDs

  Plugins can provide a list of udev-reported vendor IDs to be used as pre-probing filters. If the vendor ID reported by the device via udev is found in the list provided by the plugin, port probing will be launched as requested by the given plugin.

  This filter is specified by the MM_PLUGIN_ALLOWED_VENDOR_IDS property in the MMPlugin object provided by the plugin.

- Product IDs

  Plugins can provide a list of udev-reported pairs of vendor and product IDs to be used as pre-probing filters.

  If the vendor ID and product ID pair reported by the device via udev is found in the list of 'allowed' pairs provided by the plugin, port probing will be launched as requested by the given plugin. This additional filter should be used when the plugin is expected to work only with a given specific product of a given vendor.

  If the vendor ID and product ID pair reported by the device via udev is found in the list of 'forbidden' pairs provided by the plugin, port probing will not be launched by this plugin. This additional filter should be used when the plugin supports all devices of a given vendor except for some specific ones.

  These filters are specified by the MM_PLUGIN_ALLOWED_PRODUCT_IDS and MM_PLUGIN_FORBIDDEN_PRODUCT_IDS properties in the MMPlugin object provided by the plugin.

- Subsystems

  Plugins can specify which subsystems they expect, so that we filter out any port detected with a subsystem not listed by the plugin.

  This filter is specified by the MM_PLUGIN_ALLOWED_SUBSYSTEMS property in the MMPlugin object provided by the plugin.

- Drivers

  Plugins can specify which drivers they expect, so that we filter out any port detected being managed by a driver not listed by the plugin.

  Plugins can also specify which drivers they do not expect, so that we filter out any port detected being managed by a driver listed by the plugin.

  These filters are specified by the MM_PLUGIN_ALLOWED_DRIVERS and MM_PLUGIN_FORBIDDEN_DRIVERS properties in the MMPlugin object provided by the plugin.

- udev tags

  Plugins can provide a list of udev tags, so that we filter out any port detected which doesn't expose any of the given tags.

  This filter is specified by the MM_PLUGIN_ALLOWED_UDEV_TAGS property in the MMPlugin object provided by the plugin.

### Probing sequence

Whenever all pre-probing filters of a given plugin pass, ModemManager will run the probing sequence as requested by the specific plugin. The main purpose of the probing sequence step is to determine the type of port being probed, and also prepare the information required in any expected post-probing filter.

- Custom initialization

  This property allows plugins to provide an asynchronous method which will get executed as soon as the AT port gets opened. This method may be used for any purpose, like running an early command in the ports as soon as possible, or querying the modem for info about the port layout.

  This configuration is specified by the MM_PLUGIN_CUSTOM_INIT property in the MMPlugin object provided by the plugin.

- AT allowed

  This boolean property allows plugins to specify that they expect and support AT serial ports.

  This configuration is specified by the MM_PLUGIN_ALLOWED_AT property in the MMPlugin object provided by the plugin.

- Single AT expected

  This boolean property allows plugins to specify that they only expect and support one AT serial port. Whenever the first AT port is grabbed, any remaining AT probing in ports of the same device will get cancelled.

  This configuration is specified by the MM_PLUGIN_ALLOWED_SINGLE_AT property in the MMPlugin object provided by the plugin.

- Custom AT probing

  This property allows plugins to specify custom commands to check whether a port is AT or not. By default, the 'AT' command will be used if no custom one specified.

  This configuration is specified by the MM_PLUGIN_CUSTOM_AT_PROBE property in the MMPlugin object provided by the plugin.

- QCDM allowed

  This boolean property allows plugins to specify that they expect and support QCDM serial ports.

  This configuration is specified by the MM_PLUGIN_ALLOWED_QCDM property in the MMPlugin object provided by the plugin.

- Check Icera support

  This boolean property allows plugins to specify that they want to have the Icera support checks included in the probing sequence. They can afterwards get the result of the support check to decide whether they want to create a Icera-based modem object or not.

  This configuration is specified by the MM_PLUGIN_ICERA_PROBE property in the MMPlugin object provided by the plugin.

### Post-probing filters

Post-probing filters are required to identify whether a plugin can handle a given modem, in special cases where the information retrieved from udev is either not enough or wrong. This covers, for example, RS232 modems connected through a RS232 to USB converter, where udev-reported vendor ID is that of the converter, not the one of the modem.

- Allowed vendor strings

  Plugins can provide a list of vendor strings to be used as post-probing filters. If the vendor string reported by the device via AT commands is found in the list provided by the plugin, the plugin will report that it can handle this modem.

  This filter is specified by the MM_PLUGIN_ALLOWED_VENDOR_STRINGS property in the MMPlugin object provided by the plugin.

- Product strings

  Plugins can provide a list of pairs of vendor and product strings to be used as post-probing filters.

  If the vendor and product string pair reported by the device via AT commands is found in the 'allowed' list provided by the plugin, the plugin will report that it can handle this modem. This additional filter should be used when the plugin is expected to work only with a given specific product of a given vendor.

  If the vendor and product string pair reported by the device via AT commands is found in the 'forbidden list provided by the plugin, the plugin will report that it cannot handle this modem. This additional filter should be used when the plugin supports all devices of a given vendor, except for some specific ones.

  These filters are specified by the MM_PLUGIN_ALLOWED_PRODUCT_STRINGS and MM_PLUGIN_FORBIDDEN_PRODUCT_STRINGS properties in the MMPlugin object provided by the plugin.

- Icera support

  Plugins can specify that they only support Icera-based modems, or that they do not support any Icera-based modem. When either of this configurations is enabled, the Icera support checks will be included in the probing sequence, and the result of the check will help to determine whether the plugin supports the modem or not.

  This filter is specified by the MM_PLUGIN_ALLOWED_ICERA and MM_PLUGIN_FORBIDDEN_ICERA properties in the MMPlugin object provided by the plugin.

Plugins which require post-probing filters will always be sorted last, and therefore they will be the last ones being checked for pre-probing filters. This is due to the fact that we need to assume that these plugins aren't able to determine port support just with pre-probing filters, as we want to avoid unnecessary probing sequences launched. Also note that the Generic plugin is anyway always the last one in the list.

### Probing setup examples

Example 1. Probing setup for a plugin requiring udev-based vendor/product checks

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    G_MODULE_EXPORT MMPlugin *
    mm_plugin_create (void)
    {
        static const gchar *subsystems[] = { "tty", NULL };
        static const guint16 vendor_ids[] = { 0xabcd, 0 };
        static const mm_uint16_pair product_ids[] = {
            { 0x1234, 0xffff }
        };
        static const gchar *vendor_strings[] = { "vendor", NULL };

        return MM_PLUGIN (
            g_object_new (MM_TYPE_PLUGIN_IRIDIUM,
                          MM_PLUGIN_NAME, "Example",

                          /* Next items are pre-probing filters */
                          MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems,
                          MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids,
                          MM_PLUGIN_ALLOWED_PRODUCT_IDS, product_ids,

                          /* Next items are probing sequence setup */
                          MM_PLUGIN_ALLOWED_AT, TRUE,

                          /* No post-probing filters */
                          NULL));
    }

Example 2. Probing setup for a plugin requiring AT-probed vendor/product checks

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    G_MODULE_EXPORT MMPlugin *
    mm_plugin_create (void)
    {
        static const gchar *subsystems[] = { "tty", NULL };
        static const gchar *vendor_strings[] = { "vendor", NULL };
        static const mm_str_pair product_strings[] = { "another-vendor", "product xyz" };

        return MM_PLUGIN (
            g_object_new (MM_TYPE_PLUGIN_IRIDIUM,
                          MM_PLUGIN_NAME, "Example",

                          /* Next items are pre-probing filters */
                          MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems,

                          /* Next items are probing sequence setup */
                          MM_PLUGIN_ALLOWED_AT, TRUE,

                          /* Next items are post-probing filters */
                          MM_PLUGIN_VENDOR_STRINGS, vendor_strings,
                          MM_PLUGIN_PRODUCT_STRINGS, product_strings,
                          NULL));
    }

Example 3. Probing setup for a plugin with custom initialization requirements

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    static gboolean
    parse_custom_at (const gchar *response,
                     const GError *error,
                     GValue *result,
                     GError **result_error)
    {
        if (error) {
            *result_error = g_error_copy (error);
            return FALSE;
        }

        /* Otherwise, done. And also report that it's an AT port. */
        g_value_init (result, G_TYPE_BOOLEAN);
        g_value_set_boolean (result, TRUE);
        return TRUE;
    }

    static const MMPortProbeAtCommand custom_at_probe[] = {
        { "AT+SOMETHING", parse_custom_at },
        { NULL }
    };

    G_MODULE_EXPORT MMPlugin *
    mm_plugin_create (void)
    {
        static const gchar *subsystems[] = { "tty", NULL };
        static const guint16 vendor_ids[] = { 0xabcd, 0 };

        return MM_PLUGIN (
            g_object_new (MM_TYPE_PLUGIN_EXAMPLE,
                          MM_PLUGIN_NAME, "Example",

                          /* Next items are pre-probing filters */
                          MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems,
                          MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids,

                          /* Next items are probing sequence setup */
                          MM_PLUGIN_CUSTOM_AT_PROBE, custom_at_probe,
                          MM_PLUGIN_ALLOWED_AT,      TRUE,

                          /* No post-probing filters */
                          NULL));
    }