Hi all, I've been lately trying to improve the probing process in ModemManager, so that it is faster and easier to maintain, keeping in mind the different specific needs of the current plugins.
The current status of the work can be seen in the 'probing-refactor' branch in the following git repo: git://gitorious.org/aleksander/modemmanager.git It currently only compiles some plugins (Cinterion, Nokia and Generic) which are the ones ported to the new probing process being suggested here. The branch is organized in logical commits so that it can be easily reviewed (hope so, at least). I had mixed feelings on whether I should suggest all these new things before having it fully ready, but I think it makes sense to at least discuss them before I spend more time on it. 1. Plugin Manager ----------------------------------------------- The MMManager object handled too many different tasks, that it made sense to me to have an independent MMPluginManager object which takes care of: * Finding plugins and loading them * Controlling the requests to find the best plugin to support a given port. So whenever a new port is found/detected, we can just pass it to mm_plugin_manager_find_port_support() and wait for the async method to return the best plugin found for it. When devices with multiple ports are detected, the Plugin Manager also takes care of propagating the first best plugin found to support checks of ports in the same device. This Plugin Manager work is at the beginning of the branch; and quite independent to the rest of the changes (in other words, directly mergeable to master if you guys like it). 2. Port Support Checks ----------------------------------------------- The whole probing process is now done in a new MMPortProbe object (somewhat equivalent to the MMPluginBaseSupportsTask object, which was removed). The object serves as a temporary storage for already probed information (as the MMPluginBaseSupportsTask one), but also allows specifying what needs to be probed in the port and does also the real probing. The MMPluginBase will control whether a probing is needed, and will also process the results of the probing reported by the MMPortProbe object. Specific plugins are able to set at construction time different property values to modify the both the probing process and the pre- and post-probing filters to run. See the ported Nokia plugin as example: https://gitorious.org/aleksander/modemmanager/commit/d2992abdb1f386962063e6b61ae8bf26eb0f995a The whole port support check done by every plugin can be summarized in the following steps: * [MMPluginBase] Check whether we need to launch probing (pre-probing filters). * [MMPortProbe] Launch port probing, get probing results. * [MMPluginBase] Check whether the results we got are the ones expected (post-probing filters). * [MMPluginBase] Report port support check results. 2.1 Pre-probing filters Pre-probing filters are those which control whether the probing, as requested by the specific plugin, takes place. The best example of this filter type is the VENDOR_IDS one: The probing request will be aborted (and therefore report as unsupported) unless the port reports a Vendor ID equal to one in the given array. * MM_PLUGIN_BASE_ALLOWED_VENDOR_IDS: A plugin can set this property to a 0-terminated array of uint16s containing the udev-reported vendor IDs it can handle, e.g.: static const guint16 vendor_ids[] = { 0x0421 , 0 }; return MM_PLUGIN ( g_object_new (MM_TYPE_PLUGIN_NOKIA, ... MM_PLUGIN_BASE_ALLOWED_VENDOR_IDS, vendor_ids, NULL)); Other pre-probing filters considered and already implemented are Subsystems, Drivers, Product ID and Udev Tags. See: https://gitorious.org/aleksander/modemmanager/commit/142d0161070777a8a8cac44e8320b07b70fb437a 2.2 Probing-specific configurations If the port passed all pre-probing filters, a probing process can be started. The specific probing to be done directly depends on the requested post-probing filters. Some examples: ** Cinterion modems do not expose QCDM ports, therefore no QCDM port probing is needed. ** ZTE modems are never RS232, therefore no Vendor/Product AT-probing is needed. If all the requested probing information is already cached, the probing is not launched again. This may happen when probing a port in a RS232 modem, where capabilities and Vendor-string probing may be done by an earlier plugin. When any AT-specific probing is requested (capabilities, vendor, product), we first check whether the port is an AT port or not (just sending "AT" and not expecting any error). If the port is found to be an AT port, capabilities/vendor/product probing can continue. We will only check if the port is to be QCDM if the plugin object was created with MM_PLUGIN_BASE_ALLOWED_QCDM set to TRUE. As before, plugins are allowed to specify custom initialization commands, in this case with the MM_PLUGIN_BASE_CUSTOM_INIT property which expects a NULL-terminated array of the new MMPortProbeAtCommand structs. This custom initialization can also be used to check whether the port is an AT port or not. As an example, the Nokia plugin may use: static gboolean parse_init (const gchar *response, const GError *error, GValue *result, GError **result_error) { if (error) /* Go on to next command */ 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 } }; return MM_PLUGIN ( g_object_new (MM_TYPE_PLUGIN_NOKIA, ... MM_PLUGIN_BASE_CUSTOM_INIT, custom_init, NULL)); This is, "ATE1 E0" will be sent up to 3 times, and if we kept getting errors in all 3 tries, the port is reported as not being an AT port. Being able to say whether a port is AT or not from the custom init is just about convenience, the custom init command is of course not for that and the callback is allowed to return without setting the output 'result'. Also, if the callback sets 'result_error', the whole probing process would get cancelled. See: https://gitorious.org/aleksander/modemmanager/commit/40e66ea506101a0af6922bde24ad9579392f0429 2.3 Post-probing filters Post-probing filters are those which control whether the plugin can support the port once the desired probing results are ready. The best example of this filter type is the CAPABILITIES one: The support request will report unsupported unless the probed capabilities from the port match the capabilities given in the property. * MM_PLUGIN_BASE_ALLOWED_CAPABILITIES: A plugin can set this property to a guint representing a mask of flags where supported capabilities are given, e.g.: static const guint32 capabilities = MM_PORT_PROBE_CAPABILITY_GSM_OR_CDMA; return MM_PLUGIN ( g_object_new (MM_TYPE_PLUGIN_NOKIA, ... MM_PLUGIN_BASE_ALLOWED_CAPABILITIES, capabilities, NULL)); Other post-probing filters considered and implemented are Vendor Strings and Product Strings (used only in plugins supporting RS232 devices). See: https://gitorious.org/aleksander/modemmanager/commit/bc1d62ddb58abbff3eea21196deac8cf9eff3473 2.4 Port support results Given a port, there is always a single plugin that may support it. MM currently reports 'support level' values (given as an integer in the [0-100] range), but the truth seems to be that only one single plugin ends up reporting a support_level > 0 (due to the udev or AT-probed vendor/product filtering). Therefore, a new SUPPORTED state was added to the possible replies of the port support check done by the plugins, to be used instead of reporting a support_level > 0. The whole supports_port() method was also changed so that it always reports results asynchronously (so there is no longer need for IN_PROGRESS status). This eases a lot the management of port support requests within the Plugin Manager. See: https://gitorious.org/aleksander/modemmanager/commit/b07189f14fe6e88a87cd8db5312d9fdf6734e680 3. TODOs ----------------------------------------------- 3.1 Port Grabbing: In the same way that the port support checking was fully moved to the MMPluginBase, port grabbing can also possibly be completely moved out of the plugin implementations. For example, letting plugins specify in a new property the GType of the modem object to create when GSM capability is found, and such. 3.2 Port remaining plugins to the new probing process. I first wanted to discuss all these ideas in the list before going on with that. Comments? Cheers! -- Aleksander _______________________________________________ networkmanager-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/networkmanager-list
