We chain up the Generic plugin created MMBroadbandModem objects within the
GDBusObjectManagerServer in MMManager, so that they get properly exported in
DBus.
There is no single case where more than one plugin may end up wanting to support
a given port, and therefore there is no need to report the numeric support level
when reporting SUPPORTED.
Some devices support 'net' devices, which cannot be AT or QCDM probed.
If the port being checked for support corresponds to an already existing modem,
the port will be reported as SUPPORTED.
If this is the first port of the modem being checked for support, we will just
DEFER the support check until we get a modem created.
If the plugin does a Vendor ID check and it passes, it doesn't need Vendor
string probing.
If the plugin does a Vendor ID check and it fails:
- If Vendor strings reported, it needs Vendor probing.
- If Vendor strings not reported, fail as unsupported.
If the plugin does a Product ID check and it passes, it doesn't need Product
string probing.
If the plugin does a Product ID check and it fails:
- If Product strings reported, it needs Product probing.
- If Product strings not reported, fail as unsupported.
Once probing is finished, the plugin will check whether the port is supported
or not based on the following filters:
- Capabilities
- Reported Vendor string
- Reported Product string
Before any real probing is launched in the port, the plugin will check whether
it can skip the request based on the following filters:
- Subsystems
- Drivers
- udev-reported Vendor ID
- udev-reported Product ID
- udev-reported Tags
The previous 'MMPluginBaseSupportsTask' object is more or less equivalent to the
new `MMPortProbe' in terms of what information it contains. The main difference
being that the new `MMPortProbe' object handles internally the whole probing
flow as needed: only the needed probing sequences are done. For example, vendor
or product string probing will only be performed if a plugin requests it.
The plugins can set this property to filter support check requests by the
availability of a given udev tag in the port. The value given to the property
should be a NULL-terminated array of C strings, e.g.:
const gchar *tags[] = { "ID_MM_X22X_TAGGED", NULL };
The plugins can set this property to filter support check requests by physical
device driver. The value given to the property should be a NULL-terminated array
of C strings, e.g.:
const gchar *drivers[] = { "qcserial", NULL };
The plugins can set this property to provide a custom value for the send delay
used for characters sent to the AT port during probing.
The value given to the property should be a guint64 specifying the delay in
microseconds.
The plugins can set this property to filter support check requests by probed
capabilities.
The value given to the property should be a guint built as a mask of
MM_PORT_PROBE_CAPABILITY flags, e.g.:
const guint capabilities = (MM_PORT_PROBE_CAPABILITY_GSM |
MM_PORT_PROBE_CAPABILITY_CDMA);
The plugins can set these properties to filter support check requests by
AT-reported Vendor string and Product string.
The value given to the properties should be a NULL-terminated array of strings,
e.g.,
static const gchar *vendor_strings[] = { "cinterion" , NULL };
The plugins can set this property to provide custom initialization commands that
should be issued to the modem before real probing starts.
The value given to the property should be an array of MMPortProbeAtCommand
variables finished with a last one exposing a NULL command, e.g.:
static gboolean
parse_init (const gchar *response,
const GError *error,
GValue *result,
GError **result_error)
{
if (error)
return FALSE;
/* If we didn't get any error, it is an AT port */
g_value_init (result, G_TYPE_BOOLEAN);
g_value_set_boolean (result, TRUE);
return TRUE;
}
static gboolean
parse_init_last (const gchar *response,
const GError *error,
GValue *result,
GError **result_error)
{
g_value_init (result, G_TYPE_BOOLEAN);
/* On last error, report as not being an AT port */
g_value_set_boolean (result, error ? FALSE : TRUE);
return TRUE;
}
static const MMPortProbeAtCommand custom_init[] = {
{ "ATE1 E0", parse_init },
{ "ATE1 E0", parse_init },
{ "ATE1 E0", parse_init_last },
{ NULL }
};
The plugins can set these properties to filter support check requests by
udev-reported Vendor ID and Product ID.
The value given to the properties should be a 0-terminated array of guint16s,
e.g.,
static const guint16 vendor_ids[] = { 0x0421 , 0 };
The plugins can set this property to filter support check requests by subsystem.
The value given to the property should be a NULL-terminated array of C strings,
e.g.:
const gchar *subsystems[] = { "tty", NULL };
We now have 'supports_port' (async method) and 'supports_port_finish' (to get
the result of the async method), so it makes sense to rename the method to
'supports_port_cancel'.
Before this change, supports check was either synchronous (e.g. in some
UNSUPPORTED cases) or asynchronous (when IN_PROGRESS was returned).
With this fix, the supports check requested to the plugin will always be
completed asynchronously; either directly in an idle before launching any real
probing operation, or once the probing operation is finished.
Therefore, it is not expected to get a IN_PROGRESS reply in
mm_plugin_supports_port_finish(), only UNSUPPORTED|SUPPORTED|DEFERRED.
Make port roles more flexible. We have modems that do PPP
on interfaces other than the primary interface, and that
wasn't possible with the old code. So clean up all that
logic and move the port organization code into the core
so we can reduce code in the plugins.
In the new world order, the plugins say whether the port
is a QCDM port, an AT port, or ignored. If it's an AT
port the plugins get to tag it as primary, secondary, or
PPP, or any combination of the 3. This allows for modems
where PPP should really be done on the secondary port
(Huawei E220, Sierra devices) so that the primary port
stays open for command and status.
Modem subclasses no longer get asked to handle port grabbing
themselves. Instead, that's now done by the generic classes
(MMGenericCdma and MMGenericGsm) and the plugins are notified
when a port is grabbed so they can add unsolicited response
handlers for it. After all ports are grabbed by the generic
classes, they get "organized", which assigns various ports
to the roles of PRIMARY, SECONDARY, DATA, and QCDM based
on specific rules and hints that the plugin provided (which
are expressed as MMAtPortFlags). The plugins then have
a chance to perform fixups on the primary port if they choose.
The plugin code is responsible for determining the port
hints (ie MMAtPortFlags) at probe time, instead of having
a combination of the plugin and the modem class do the
job. This simplifies things greatly for the plugins at
the expense of more complicated logic in the core.
On a ZTE MF626, sometimes the aux port will respond only with
"ERROR" to probing commands (while the SIM is starting up) and
previously we'd lose the port because we were only looking for
valid probe responses. But if the port returns ERROR or CME ERROR
etc we know it's an AT port and that we can use it once we've
gotten the type response (CDMA or GSM) from the main port.
We need to ensure that the supports task always has the results of the probing,
no matter if the probing was just launched by the plugin grabbing the port, or
by a previous plugin. We do this during supports_port(), by propagating to the
supports task any possible previously cached probing results.
Note that even if a plugin says it wants to be sorted last, the generic plugin
will always be the last one. Also, there is no order guaranteed between two
plugins that request to be sorted last.
Port probing is extended to also query for Vendor ID and Product ID. This allows
plugins to check whether the reported IDs are expected, and thus we enable
plugins to handle modems connected via RS232 ports (where udev doesn't give any
vendor ID) or modems connected via a USB adapter (where udev gives the vendor ID
of the adapter).
Note that this effectively means that a plugin which expects these kind of modem
connections will end up always launching port probing as they won't only rely on
the vendor ID reported by udev.
Previously plugins could only stop probing, *or* stop probing and
indicate support for a device. For the Alcatel X200/X060s debacle
we need to stop probing and indicate that the plugin does not
support the device at all.
Instead of having two places that custom init stuff got processed
(a hook in the MMPluginBase class itself and a callback too) just
use a callback, and simplify it somewhat so that the plugin tracks
how many tries it cares about and what to do based on the response
or error.
It's only used during probing where some port types (Sierra CnS
and some Icera devices) may send streams of data that we can't
understand until we close the port. It interferes with some SMS
operations, so turn it off for ports opened after probing.
Pass the device's hardware IDs through modem creation and use them
when calculating the device's identifier. Add a bunch of testcases
for real hardware to ensure we don't break the device ID in the
future unless we really want to.