diff options
-rw-r--r-- | src/80-mm-candidate.rules | 2 | ||||
-rw-r--r-- | src/mm-base-modem.c | 14 | ||||
-rw-r--r-- | src/mm-device.c | 11 | ||||
-rw-r--r-- | src/mm-manager.c | 39 | ||||
-rw-r--r-- | src/mm-plugin.c | 7 | ||||
-rw-r--r-- | src/mm-port-probe.c | 52 | ||||
-rw-r--r-- | src/mm-port.h | 6 |
7 files changed, 106 insertions, 25 deletions
diff --git a/src/80-mm-candidate.rules b/src/80-mm-candidate.rules index e99ae3ad..9c2d7f89 100644 --- a/src/80-mm-candidate.rules +++ b/src/80-mm-candidate.rules @@ -11,6 +11,6 @@ ACTION!="add|change|move", GOTO="mm_candidate_end" SUBSYSTEM=="tty", ENV{ID_MM_CANDIDATE}="1" SUBSYSTEM=="net", ENV{ID_MM_CANDIDATE}="1" +KERNEL=="cdc-wdm*", SUBSYSTEM=="usb", DRIVERS=="qmi_wwan", ENV{ID_MM_CANDIDATE}="1" LABEL="mm_candidate_end" - diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c index aa844642..6c5c562a 100644 --- a/src/mm-base-modem.c +++ b/src/mm-base-modem.c @@ -161,7 +161,8 @@ mm_base_modem_grab_port (MMBaseModem *self, /* Only allow 'tty' and 'net' ports */ if (!g_str_equal (subsys, "net") && - !g_str_equal (subsys, "tty")) { + !g_str_equal (subsys, "tty") && + !(g_str_equal (subsys, "usb") && g_str_has_prefix (name, "cdc-wdm"))) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, @@ -228,8 +229,17 @@ mm_base_modem_grab_port (MMBaseModem *self, MM_PORT_SUBSYS, MM_PORT_SUBSYS_NET, MM_PORT_TYPE, MM_PORT_TYPE_NET, NULL)); + } + /* QMI ports... */ + else if (g_str_equal (subsys, "usb") && + g_str_has_prefix (name, "cdc-wdm")) { + port = MM_PORT (g_object_new (MM_TYPE_PORT, + MM_PORT_DEVICE, name, + MM_PORT_SUBSYS, MM_PORT_SUBSYS_USB, + MM_PORT_TYPE, MM_PORT_TYPE_QMI, + NULL)); } else - /* We already filter out before all non-tty, non-net ports */ + /* We already filter out before all non-tty, non-net, non-wdm ports */ g_assert_not_reached(); mm_dbg ("(%s) type '%s' claimed by %s", diff --git a/src/mm-device.c b/src/mm-device.c index 6af43dae..faf7c942 100644 --- a/src/mm-device.c +++ b/src/mm-device.c @@ -140,6 +140,17 @@ get_device_ids (GUdevDevice *device, /* Platform devices don't usually have a VID/PID */ success = TRUE; goto out; + } else if (!strcmp (parent_subsys, "usb") && + !strcmp (g_udev_device_get_driver (parent), "qmi_wwan")) { + /* Need to look for vendor/product in the parent of the QMI device */ + GUdevDevice *qmi_parent; + + qmi_parent = g_udev_device_get_parent (parent); + if (qmi_parent) { + vid = g_udev_device_get_property (qmi_parent, "ID_VENDOR_ID"); + pid = g_udev_device_get_property (qmi_parent, "ID_MODEL_ID"); + g_object_unref (qmi_parent); + } } } } diff --git a/src/mm-manager.c b/src/mm-manager.c index 5dc8bc87..23ef8e68 100644 --- a/src/mm-manager.c +++ b/src/mm-manager.c @@ -321,16 +321,22 @@ device_removed (MMManager *self, GUdevDevice *udev_device) { MMDevice *device; + const gchar *subsys; + const gchar *name; g_return_if_fail (udev_device != NULL); - if (!g_str_equal (g_udev_device_get_subsystem (udev_device), "usb")) { - /* Handle tty/net port removal */ + subsys = g_udev_device_get_subsystem (udev_device); + name = g_udev_device_get_name (udev_device); + + if (!g_str_equal (subsys, "usb") || + (name && g_str_has_prefix (name, "cdc-wdm"))) { + /* Handle tty/net/wdm port removal */ device = find_device_by_port (self, udev_device); if (device) { mm_info ("(%s/%s): released by modem %s", - g_udev_device_get_subsystem (udev_device), - g_udev_device_get_name (udev_device), + subsys, + name, g_udev_device_get_sysfs_path (mm_device_peek_udev_device (device))); mm_device_release_port (device, udev_device); @@ -372,22 +378,24 @@ handle_uevent (GUdevClient *client, gpointer user_data) { MMManager *self = MM_MANAGER (user_data); - const char *subsys; + const gchar *subsys; + const gchar *name; g_return_if_fail (action != NULL); /* A bit paranoid */ subsys = g_udev_device_get_subsystem (device); g_return_if_fail (subsys != NULL); - g_return_if_fail (!strcmp (subsys, "tty") || !strcmp (subsys, "net") || !strcmp (subsys, "usb")); + g_return_if_fail (g_str_equal (subsys, "tty") || g_str_equal (subsys, "net") || g_str_equal (subsys, "usb")); - /* We only care about tty/net devices when adding modem ports, + /* We only care about tty/net and usb/cdc-wdm devices when adding modem ports, * but for remove, also handle usb parent device remove events */ - if ( (!strcmp (action, "add") || !strcmp (action, "move") || !strcmp (action, "change")) - && (strcmp (subsys, "usb") != 0)) + name = g_udev_device_get_name (device); + if ( (g_str_equal (action, "add") || g_str_equal (action, "move") || g_str_equal (action, "change")) + && (!g_str_equal (subsys, "usb") || (name && g_str_has_prefix (name, "cdc-wdm")))) device_added (self, device); - else if (!strcmp (action, "remove")) + else if (g_str_equal (action, "remove")) device_removed (self, device); } @@ -415,6 +423,17 @@ mm_manager_start (MMManager *manager) } g_list_free (devices); + devices = g_udev_client_query_by_subsystem (manager->priv->udev, "usb"); + for (iter = devices; iter; iter = g_list_next (iter)) { + const gchar *name; + + name = g_udev_device_get_name (G_UDEV_DEVICE (iter->data)); + if (name && g_str_has_prefix (name, "cdc-wdm")) + device_added (manager, G_UDEV_DEVICE (iter->data)); + g_object_unref (G_OBJECT (iter->data)); + } + g_list_free (devices); + mm_dbg ("Finished device scan..."); } diff --git a/src/mm-plugin.c b/src/mm-plugin.c index a9ce28b0..ef0453bf 100644 --- a/src/mm-plugin.c +++ b/src/mm-plugin.c @@ -589,9 +589,10 @@ mm_plugin_supports_port (MMPlugin *self, g_udev_device_get_subsystem (port), g_udev_device_get_name (port)); - /* Before launching any probing, check if the port is a net device (which - * cannot be probed). */ - if (g_str_equal (g_udev_device_get_subsystem (port), "net")) { + /* Before launching any probing, check if the port is a net OR a wdm device + * (which cannot be probed). */ + if (g_str_equal (g_udev_device_get_subsystem (port), "net") || + g_str_equal (g_udev_device_get_subsystem (port), "cdc-wdm")) { g_simple_async_result_set_op_res_gpointer ( async_result, GUINT_TO_POINTER (MM_PLUGIN_SUPPORTS_PORT_DEFER_UNTIL_SUGGESTED), diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c index 58fcb301..9c374a55 100644 --- a/src/mm-port-probe.c +++ b/src/mm-port-probe.c @@ -1006,9 +1006,16 @@ mm_port_probe_run (MMPortProbe *self, gboolean mm_port_probe_is_at (MMPortProbe *self) { + const gchar *subsys; + const gchar *name; + g_return_val_if_fail (MM_IS_PORT_PROBE (self), FALSE); - if (g_str_equal (g_udev_device_get_subsystem (self->priv->port), "net")) + subsys = g_udev_device_get_subsystem (self->priv->port); + name = g_udev_device_get_name (self->priv->port); + if (g_str_equal (subsys, "net") || + (g_str_equal (subsys, "usb") && + g_str_has_prefix (name, "cdc-wdm"))) return FALSE; return (self->priv->flags & MM_PORT_PROBE_AT ? @@ -1034,9 +1041,16 @@ mm_port_probe_list_has_at_port (GList *list) gboolean mm_port_probe_is_qcdm (MMPortProbe *self) { + const gchar *subsys; + const gchar *name; + g_return_val_if_fail (MM_IS_PORT_PROBE (self), FALSE); - if (g_str_equal (g_udev_device_get_subsystem (self->priv->port), "net")) + subsys = g_udev_device_get_subsystem (self->priv->port); + name = g_udev_device_get_name (self->priv->port); + if (g_str_equal (subsys, "net") || + (g_str_equal (subsys, "usb") && + g_str_has_prefix (name, "cdc-wdm"))) return FALSE; return (self->priv->flags & MM_PORT_PROBE_QCDM ? @@ -1047,11 +1061,21 @@ mm_port_probe_is_qcdm (MMPortProbe *self) MMPortType mm_port_probe_get_port_type (MMPortProbe *self) { + const gchar *subsys; + const gchar *name; + g_return_val_if_fail (MM_IS_PORT_PROBE (self), FALSE); - if (g_str_equal (g_udev_device_get_subsystem (self->priv->port), "net")) + subsys = g_udev_device_get_subsystem (self->priv->port); + name = g_udev_device_get_name (self->priv->port); + + if (g_str_equal (subsys, "net")) return MM_PORT_TYPE_NET; + if (g_str_equal (subsys, "usb") && + g_str_has_prefix (name, "cdc-wdm")) + return MM_PORT_TYPE_QMI; + if (self->priv->flags & MM_PORT_PROBE_QCDM && self->priv->is_qcdm) return MM_PORT_TYPE_QCDM; @@ -1098,9 +1122,16 @@ mm_port_probe_get_port (MMPortProbe *self) const gchar * mm_port_probe_get_vendor (MMPortProbe *self) { - g_return_val_if_fail (MM_IS_PORT_PROBE (self), NULL); + const gchar *subsys; + const gchar *name; - if (g_str_equal (g_udev_device_get_subsystem (self->priv->port), "net")) + g_return_val_if_fail (MM_IS_PORT_PROBE (self), FALSE); + + subsys = g_udev_device_get_subsystem (self->priv->port); + name = g_udev_device_get_name (self->priv->port); + if (g_str_equal (subsys, "net") || + (g_str_equal (subsys, "usb") && + g_str_has_prefix (name, "cdc-wdm"))) return NULL; return (self->priv->flags & MM_PORT_PROBE_AT_VENDOR ? @@ -1111,9 +1142,16 @@ mm_port_probe_get_vendor (MMPortProbe *self) const gchar * mm_port_probe_get_product (MMPortProbe *self) { - g_return_val_if_fail (MM_IS_PORT_PROBE (self), NULL); + const gchar *subsys; + const gchar *name; - if (g_str_equal (g_udev_device_get_subsystem (self->priv->port), "net")) + g_return_val_if_fail (MM_IS_PORT_PROBE (self), FALSE); + + subsys = g_udev_device_get_subsystem (self->priv->port); + name = g_udev_device_get_name (self->priv->port); + if (g_str_equal (subsys, "net") || + (g_str_equal (subsys, "usb") && + g_str_has_prefix (name, "cdc-wdm"))) return NULL; return (self->priv->flags & MM_PORT_PROBE_AT_PRODUCT ? diff --git a/src/mm-port.h b/src/mm-port.h index 539f1a11..182dd230 100644 --- a/src/mm-port.h +++ b/src/mm-port.h @@ -23,8 +23,9 @@ typedef enum { /*< underscore_name=mm_port_subsys >*/ MM_PORT_SUBSYS_UNKNOWN = 0x0, MM_PORT_SUBSYS_TTY, MM_PORT_SUBSYS_NET, + MM_PORT_SUBSYS_USB, - MM_PORT_SUBSYS_LAST = MM_PORT_SUBSYS_NET /*< skip >*/ + MM_PORT_SUBSYS_LAST = MM_PORT_SUBSYS_USB /*< skip >*/ } MMPortSubsys; typedef enum { /*< underscore_name=mm_port_type >*/ @@ -34,8 +35,9 @@ typedef enum { /*< underscore_name=mm_port_type >*/ MM_PORT_TYPE_AT, MM_PORT_TYPE_QCDM, MM_PORT_TYPE_GPS, + MM_PORT_TYPE_QMI, - MM_PORT_TYPE_LAST = MM_PORT_TYPE_GPS /*< skip >*/ + MM_PORT_TYPE_LAST = MM_PORT_TYPE_QMI /*< skip >*/ } MMPortType; #define MM_TYPE_PORT (mm_port_get_type ()) |