diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/huawei/mm-plugin-huawei.c | 139 |
1 files changed, 63 insertions, 76 deletions
diff --git a/plugins/huawei/mm-plugin-huawei.c b/plugins/huawei/mm-plugin-huawei.c index eda6bf05..cf1ed6f8 100644 --- a/plugins/huawei/mm-plugin-huawei.c +++ b/plugins/huawei/mm-plugin-huawei.c @@ -28,6 +28,8 @@ #include "mm-log.h" #include "mm-plugin-huawei.h" #include "mm-broadband-modem-huawei.h" +#include "mm-modem-helpers-huawei.h" +#include "mm-huawei-enums-types.h" #if defined WITH_QMI #include "mm-broadband-modem-qmi.h" @@ -68,12 +70,8 @@ first_interface_context_free (FirstInterfaceContext *ctx) g_slice_free (FirstInterfaceContext, ctx); } -#define TAG_HUAWEI_PCUI_PORT "huawei-pcui-port" -#define TAG_HUAWEI_MODEM_PORT "huawei-modem-port" -#define TAG_HUAWEI_NDIS_PORT "huawei-ndis-port" -#define TAG_HUAWEI_DIAG_PORT "huawei-diag-port" -#define TAG_GETPORTMODE_SUPPORTED "getportmode-supported" -#define TAG_AT_PORT_FLAGS "at-port-flags" +#define TAG_GETPORTMODE_RESULT "getportmode-result" +#define TAG_AT_PORT_FLAGS "at-port-flags" typedef struct { MMPortSerialAt *port; @@ -100,41 +98,21 @@ huawei_custom_init_finish (MMPortProbe *probe, static void huawei_custom_init_step (GTask *task); -static gboolean -cache_port_mode (MMDevice *device, - const gchar *reply, - const gchar *type, - const gchar *tag) -{ - gchar *p; - gulong i; - - /* Get the USB interface number of the PCUI port */ - p = strstr (reply, type); - if (p) { - errno = 0; - /* shift by 1 so NULL return from g_object_get_data() means no tag */ - i = 1 + strtol (p + strlen (type), NULL, 10); - if (i > 0 && i < 256 && errno == 0) { - g_object_set_data (G_OBJECT (device), tag, GINT_TO_POINTER ((gint) i)); - return TRUE; - } - } - return FALSE; -} - static void getportmode_ready (MMPortSerialAt *port, GAsyncResult *res, GTask *task) { + MMDevice *device; MMPortProbe *probe; HuaweiCustomInitContext *ctx; const gchar *response; - GError *error = NULL; + GArray *modes; + g_autoptr(GError) error = NULL; - probe = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); + probe = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + device = mm_port_probe_peek_device (probe); response = mm_port_serial_at_command_finish (port, res, &error); if (error) { @@ -143,41 +121,23 @@ getportmode_ready (MMPortSerialAt *port, /* If any error occurred that was not ERROR or COMMAND NOT SUPPORT then * retry the command. */ - if (!g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN)) - goto out; - - /* Port mode not supported */ - } else { - MMDevice *device; - guint n_cached_port_modes = 0; - - mm_obj_dbg (probe, "port mode layout retrieved"); - - /* Results are cached in the parent device object */ - device = mm_port_probe_peek_device (probe); - n_cached_port_modes += cache_port_mode (device, response, "PCUI:", TAG_HUAWEI_PCUI_PORT); - n_cached_port_modes += cache_port_mode (device, response, "MDM:", TAG_HUAWEI_MODEM_PORT); - n_cached_port_modes += cache_port_mode (device, response, "NDIS:", TAG_HUAWEI_NDIS_PORT); - n_cached_port_modes += cache_port_mode (device, response, "DIAG:", TAG_HUAWEI_DIAG_PORT); - /* GETPORTMODE response format in newer devices... (e.g. E3372) */ - n_cached_port_modes += cache_port_mode (device, response, "pcui:", TAG_HUAWEI_PCUI_PORT); - n_cached_port_modes += cache_port_mode (device, response, "modem:", TAG_HUAWEI_MODEM_PORT); - - if (n_cached_port_modes > 0) - g_object_set_data (G_OBJECT (device), TAG_GETPORTMODE_SUPPORTED, GUINT_TO_POINTER (TRUE)); - - /* Mark port as being AT already */ - mm_port_probe_set_result_at (probe, TRUE); + if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN)) + ctx->getportmode_done = TRUE; + huawei_custom_init_step (task); + return; } - ctx->getportmode_done = TRUE; + /* Mark port as being AT already */ + mm_port_probe_set_result_at (probe, TRUE); -out: - if (error) - g_error_free (error); + /* Flag as GETPORTMODE already done */ + ctx->getportmode_done = TRUE; + modes = mm_huawei_parse_getportmode_response (response, probe, &error); + if (!modes) + mm_obj_warn (probe, "failed to parse ^GETPORTMODE response: %s", error->message); + else + g_object_set_data_full (G_OBJECT (device), TAG_GETPORTMODE_RESULT, modes, (GDestroyNotify) g_array_unref); huawei_custom_init_step (task); } @@ -427,50 +387,77 @@ huawei_custom_init (MMPortProbe *probe, /*****************************************************************************/ +static gint +probe_cmp_by_usbif (MMPortProbe *a, + MMPortProbe *b) +{ + return ((gint) mm_kernel_device_get_property_as_int_hex (mm_port_probe_peek_port (a), "ID_USB_INTERFACE_NUM") - + (gint) mm_kernel_device_get_property_as_int_hex (mm_port_probe_peek_port (b), "ID_USB_INTERFACE_NUM")); +} + static guint propagate_getportmode_hints (MMPlugin *self, GList *probes, gboolean *primary_flagged) { MMDevice *device; + GArray *modes; GList *l; + GList *tty_probes = NULL; guint n_ports_with_hints = 0; + guint mode_i = 0; g_assert (probes != NULL); device = mm_port_probe_peek_device (MM_PORT_PROBE (probes->data)); + modes = g_object_get_data (G_OBJECT (device), TAG_GETPORTMODE_RESULT); /* Nothing to do if GETPORTMODE is flagged as not supported */ - if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (device), TAG_GETPORTMODE_SUPPORTED))) + if (!modes) return 0; - /* Propagate the getportmode tags to the specific port probes */ + /* Build a list of TTY port probes (AT and not-AT) sorted by interface number */ for (l = probes; l; l = g_list_next (l)) { + MMPortProbe *probe; + + probe = MM_PORT_PROBE (l->data); + if (g_str_equal (mm_port_probe_get_port_subsys (probe), "tty")) + tty_probes = g_list_insert_sorted (tty_probes, probe, (GCompareFunc) probe_cmp_by_usbif); + } + + /* Propagate the getportmode tags to the specific port probes */ + for (l = tty_probes, mode_i = 0; l; l = g_list_next (l)) { MMPortProbe *probe; MMPortSerialAtFlag at_port_flags = MM_PORT_SERIAL_AT_FLAG_NONE; - guint usbif; + MMHuaweiPortMode port_mode; probe = MM_PORT_PROBE (l->data); - if (!mm_port_probe_is_at (probe)) + /* Look for the next serial port mode applicable */ + while (!MM_HUAWEI_PORT_MODE_IS_SERIAL (g_array_index (modes, MMHuaweiPortMode, mode_i)) && (mode_i < modes->len)) + mode_i++; + if (mode_i == modes->len) { + mm_obj_dbg (probe, "missing port mode hint"); continue; + } - usbif = mm_kernel_device_get_property_as_int_hex (mm_port_probe_peek_port (probe), "ID_USB_INTERFACE_NUM"); + port_mode = g_array_index (modes, MMHuaweiPortMode, mode_i); + if (!mm_port_probe_is_at (probe)) { + mm_obj_dbg (probe, "port mode hint for non-AT port: %s", mm_huawei_port_mode_get_string (port_mode)); + mode_i++; + continue; + } - if (usbif + 1 == GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (device), TAG_HUAWEI_PCUI_PORT))) { + mm_obj_dbg (probe, "port mode hint for AT port: %s", mm_huawei_port_mode_get_string (port_mode)); + if (port_mode == MM_HUAWEI_PORT_MODE_PCUI) at_port_flags = MM_PORT_SERIAL_AT_FLAG_PRIMARY; - *primary_flagged = TRUE; - } else if (usbif + 1 == GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (device), TAG_HUAWEI_MODEM_PORT))) { + else if (port_mode == MM_HUAWEI_PORT_MODE_MODEM) at_port_flags = MM_PORT_SERIAL_AT_FLAG_PPP; - } else if (!g_object_get_data (G_OBJECT (device), TAG_HUAWEI_MODEM_PORT) && - usbif + 1 == GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (device), TAG_HUAWEI_NDIS_PORT))) { - /* If NDIS reported only instead of MDM, use it */ - at_port_flags = MM_PORT_SERIAL_AT_FLAG_PPP; - } if (at_port_flags != MM_PORT_SERIAL_AT_FLAG_NONE) { n_ports_with_hints++; g_object_set_data (G_OBJECT (probe), TAG_AT_PORT_FLAGS, GUINT_TO_POINTER (at_port_flags)); } + mode_i++; } return n_ports_with_hints; |