[gnome-multi-writer] Add hub quirks for Plugable devices



commit 5abe374ebde13ceb11a3d71aaccd6e7794ff7320
Author: Richard Hughes <richard hughsie com>
Date:   Wed Jan 21 18:09:09 2015 +0000

    Add hub quirks for Plugable devices
    
    Joshua from Plugable was kind enough to send me 2 USB 2.0 hubs and 2 USB 3.0
    hubs. I've added all the quirk data and the ASCII art for the hubs, and also
    added the 'count number of ICs' heuristic to detect the different USB 3.0 hubs.

 src/gmw-device.c |  341 +++++++++++++++++++++++++++++++++++++++++++++---------
 src/gmw-device.h |    1 +
 2 files changed, 285 insertions(+), 57 deletions(-)
---
diff --git a/src/gmw-device.c b/src/gmw-device.c
index e05cb5b..6c4958b 100644
--- a/src/gmw-device.c
+++ b/src/gmw-device.c
@@ -592,6 +592,7 @@ typedef struct {
        guint16          hub_parent_pid;        /* +2, or 0x0000 */
        guint16          child_vid;             /* -1, or 0x0000 */
        guint16          child_pid;             /* -1, or 0x0000 */
+       guint8           number_ics;            /* number of hub ICs detected */
        guint8           device_port;           /* electrical, not physical */
        guint8           chain_len;             /* internal chain number */
        const gchar     *hub_label;             /* decal on the box */
@@ -605,6 +606,132 @@ static GPtrArray *g_usb_device_get_children (GUsbDevice *d) {return g_ptr_array_
 #endif
 
 /**
+ * gmw_device_get_toplevel_hub:
+ **/
+static GUsbDevice *
+gmw_device_get_toplevel_hub (GmwDevice *device)
+{
+       GmwDevicePrivate *priv = gmw_device_get_instance_private (device);
+       _cleanup_object_unref_ GUsbDevice *usb_hub = NULL;
+       _cleanup_object_unref_ GUsbDevice *usb_hub_parent = NULL;
+
+       /* is this a USB hub already */
+       if (g_usb_device_get_device_class (priv->usb_device) == 0x09) {
+               usb_hub = g_object_ref (priv->usb_device);
+       } else {
+               usb_hub = g_usb_device_get_parent (priv->usb_device);
+               if (usb_hub == NULL)
+                       return NULL;
+       }
+
+       /* if the usb hub has a parent with the same vendor, assume this
+        * hub is actually nested -- we only go up the tree 2 hops */
+       usb_hub_parent = g_usb_device_get_parent (usb_hub);
+       if (usb_hub_parent != NULL &&
+           g_usb_device_get_vid (usb_hub_parent) == g_usb_device_get_vid (usb_hub))
+               return g_object_ref (usb_hub_parent);
+
+       /* otherwise just return the hub */
+       return g_object_ref (usb_hub);
+}
+
+/**
+ * gmw_device_get_quirk_string:
+ **/
+gchar *
+gmw_device_get_quirk_string (GmwDevice *device)
+{
+       GmwDevicePrivate *priv = gmw_device_get_instance_private (device);
+       GUsbDevice *child_tmp;
+       guint i;
+       guint number_ics = 0;
+       _cleanup_object_unref_ GUsbDevice *usb_hub_child = NULL;
+       _cleanup_object_unref_ GUsbDevice *usb_hub = NULL;
+       _cleanup_object_unref_ GUsbDevice *usb_hub_parent = NULL;
+       _cleanup_object_unref_ GUsbDevice *usb_hub_top = NULL;
+       _cleanup_ptrarray_unref_ GPtrArray *children = NULL;
+       _cleanup_ptrarray_unref_ GPtrArray *children_top = NULL;
+       _cleanup_string_free_ GString *str = NULL;
+
+       /* no tree to walk */
+       if (priv->usb_device == NULL)
+               return NULL;
+
+       /* is this a USB hub already */
+       if (g_usb_device_get_device_class (priv->usb_device) == 0x09) {
+               usb_hub = g_object_ref (priv->usb_device);
+       } else {
+               usb_hub = g_usb_device_get_parent (priv->usb_device);
+               if (usb_hub == NULL)
+                       return NULL;
+       }
+
+       /* hub */
+       str = g_string_new ("{ ");
+       g_string_append_printf (str, "0x%04x, 0x%04x, ",
+                               g_usb_device_get_vid (usb_hub),
+                               g_usb_device_get_pid (usb_hub));
+
+       /* parent */
+       usb_hub_top = gmw_device_get_toplevel_hub (device);
+       if (usb_hub_top == NULL) {
+               g_string_append_printf (str, "0x%02x, ", 0x00);
+               g_string_append_printf (str, "0x%04x, 0x%04x, ", 0x0000, 0x0000);
+       } else {
+               g_string_append_printf (str, "0x%02x, ",
+                                       g_usb_device_get_port_number (usb_hub));
+               g_string_append_printf (str, "0x%04x, 0x%04x, ",
+                                       g_usb_device_get_vid (usb_hub_top),
+                                       g_usb_device_get_pid (usb_hub_top));
+       }
+
+       /* get any child hub */
+       children = g_usb_device_get_children (usb_hub);
+       for (i = 0; i < children->len; i++) {
+               child_tmp = g_ptr_array_index (children, i);
+               if (g_usb_device_get_device_class (child_tmp) != 0x09)
+                       continue;
+               if (usb_hub_child == NULL)
+                       usb_hub_child = g_object_ref (child_tmp);
+       }
+       if (usb_hub_child == NULL) {
+               g_string_append_printf (str, "0x%04x, 0x%04x, ",
+                                       0x0000, 0x0000);
+       } else {
+               g_string_append_printf (str, "0x%04x, 0x%04x, ",
+                                       g_usb_device_get_vid (usb_hub_child),
+                                       g_usb_device_get_pid (usb_hub_child));
+       }
+
+       /* count child USB hubs in the device */
+       if (usb_hub_top != NULL) {
+               children_top = g_usb_device_get_children (usb_hub_top);
+               for (i = 0; i < children_top->len; i++) {
+                       child_tmp = g_ptr_array_index (children_top, i);
+                       if (g_usb_device_get_device_class (child_tmp) != 0x09)
+                               continue;
+                       number_ics++;
+               }
+       }
+       g_string_append_printf (str, "0x%02x, ", number_ics);
+
+       /* device port */
+       g_string_append_printf (str, "0x%02x, ",
+                               g_usb_device_get_port_number (priv->usb_device));
+
+       /* chain length */
+       g_string_append_printf (str, "0x%01x, ", usb_hub_child ? 0x00 : 0x01);
+
+       /* label */
+       if (priv->hub_label == NULL)
+               g_string_append_printf (str, "NULL },");
+       else
+               g_string_append_printf (str, "\"%s\" },", priv->hub_label);
+
+       return g_strdup (str->str);
+}
+
+/**
  * gmw_device_set_usb_device:
  **/
 void
@@ -616,6 +743,7 @@ gmw_device_set_usb_device (GmwDevice *device, GUsbDevice *usb_device)
        _cleanup_free_ gchar *hub_id = NULL;
        _cleanup_object_unref_ GUsbDevice *usb_hub = NULL;
        _cleanup_object_unref_ GUsbDevice *usb_hub_parent = NULL;
+       _cleanup_object_unref_ GUsbDevice *usb_hub_toplevel = NULL;
        const GmwDeviceQuirk quirks[] = {
        /*
         * Orico PIO Series Hub
@@ -628,17 +756,16 @@ gmw_device_set_usb_device (GmwDevice *device, GUsbDevice *usb_device)
         *   1|  2|  3|         1|  2|  3|  4|   5|  6|
         *   #01 #02 #03       #04 #05 #06 #10  #09 #08
         */
-       /*     hub      hub-port  parent-hub     child-device  d-prt  chain */
-       { 0x1a40, 0x0101, 0x00, 0x0000, 0x0000, 0x1a40, 0x0201, 0x01, 0x0, "01" },
-       { 0x1a40, 0x0101, 0x00, 0x0000, 0x0000, 0x1a40, 0x0201, 0x02, 0x0, "02" },
-       { 0x1a40, 0x0101, 0x00, 0x0000, 0x0000, 0x1a40, 0x0201, 0x03, 0x0, "03" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x01, 0x1, "04" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x02, 0x1, "05" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x03, 0x1, "06" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x04, 0x1, "07" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x07, 0x1, "08" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x06, 0x1, "09" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x05, 0x1, "10" },
+       { 0x1a40, 0x0101, 0x00, 0x0000, 0x0000, 0x1a40, 0x0201, 0x02, 0x01, 0x0, "01" },
+       { 0x1a40, 0x0101, 0x00, 0x0000, 0x0000, 0x1a40, 0x0201, 0x02, 0x02, 0x0, "02" },
+       { 0x1a40, 0x0101, 0x00, 0x0000, 0x0000, 0x1a40, 0x0201, 0x02, 0x03, 0x0, "03" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x02, 0x01, 0x1, "04" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x02, 0x02, 0x1, "05" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x02, 0x03, 0x1, "06" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x02, 0x04, 0x1, "07" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x02, 0x07, 0x1, "08" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x02, 0x06, 0x1, "09" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0101, 0x0000, 0x0000, 0x02, 0x05, 0x1, "10" },
 
        /*
         * MegaHub - 36 Port Powered USB 2.0 Hub
@@ -657,44 +784,125 @@ gmw_device_set_usb_device (GmwDevice *device, GUsbDevice *usb_device)
         *                  |     04B 04T 04M 03B 02B 03M 03T
         *                  \..
         */
-       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0201, 0x07, 0x0, "TP1" },
-       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0201, 0x02, 0x0, "TP2" },
-       { 0x1a40, 0x0201, 0x05, 0x1a40, 0x0201, 0x0000, 0x0000, 0x04, 0x1, "01T" },
-       { 0x1a40, 0x0201, 0x05, 0x1a40, 0x0201, 0x0000, 0x0000, 0x07, 0x1, "01M" },
-       { 0x1a40, 0x0201, 0x05, 0x1a40, 0x0201, 0x0000, 0x0000, 0x03, 0x1, "01B" },
-       { 0x1a40, 0x0201, 0x05, 0x1a40, 0x0201, 0x0000, 0x0000, 0x01, 0x1, "02T" },
-       { 0x1a40, 0x0201, 0x05, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x1, "02M" },
-       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x05, 0x1, "02B" },
-       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x07, 0x1, "03T" },
-       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x1, "03M" },
-       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x04, 0x1, "03B" },
-       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x1, "04T" },
-       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x03, 0x1, "04M" },
-       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x01, 0x1, "04B" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x1, "05T" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x05, 0x1, "05M" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x07, 0x1, "05B" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x03, 0x1, "06T" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x1, "06M" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x04, 0x1, "06B" },
-       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x05, 0x1, "07T" },
-       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x1, "07M" },
-       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x01, 0x1, "07B" },
-       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x04, 0x1, "08T" },
-       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x07, 0x1, "08M" },
-       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x03, 0x1, "08B" },
-       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x01, 0x1, "09T" },
-       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x1, "09M" },
-       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x05, 0x1, "09B" },
-       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x07, 0x1, "10T" },
-       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x1, "10M" },
-       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x04, 0x1, "10B" },
-       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x1, "11T" },
-       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x03, 0x1, "11M" },
-       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x01, 0x1, "11B" },
-
-       /* /----hub---------\   /-parent-hub-\   /-children-\   /pt\  /ch\ */
-       { 0x0000, 0x0000, 0x00, 0x0000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, NULL }
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0201, 0x06, 0x07, 0x0, "TP1" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0201, 0x06, 0x02, 0x0, "TP2" },
+       { 0x1a40, 0x0201, 0x05, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x04, 0x1, "01T" },
+       { 0x1a40, 0x0201, 0x05, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x07, 0x1, "01M" },
+       { 0x1a40, 0x0201, 0x05, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x03, 0x1, "01B" },
+       { 0x1a40, 0x0201, 0x05, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x01, 0x1, "02T" },
+       { 0x1a40, 0x0201, 0x05, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x02, 0x1, "02M" },
+       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x05, 0x1, "02B" },
+       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x07, 0x1, "03T" },
+       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x06, 0x1, "03M" },
+       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x04, 0x1, "03B" },
+       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x02, 0x1, "04T" },
+       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x03, 0x1, "04M" },
+       { 0x1a40, 0x0201, 0x06, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x01, 0x1, "04B" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x06, 0x1, "05T" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x05, 0x1, "05M" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x07, 0x1, "05B" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x03, 0x1, "06T" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x02, 0x1, "06M" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x04, 0x1, "06B" },
+       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x05, 0x1, "07T" },
+       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x06, 0x1, "07M" },
+       { 0x1a40, 0x0201, 0x04, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x01, 0x1, "07B" },
+       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x04, 0x1, "08T" },
+       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x07, 0x1, "08M" },
+       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x03, 0x1, "08B" },
+       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x01, 0x1, "09T" },
+       { 0x1a40, 0x0201, 0x03, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x02, 0x1, "09M" },
+       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x05, 0x1, "09B" },
+       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x07, 0x1, "10T" },
+       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x06, 0x1, "10M" },
+       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x04, 0x1, "10B" },
+       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x02, 0x1, "11T" },
+       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x03, 0x1, "11M" },
+       { 0x1a40, 0x0201, 0x01, 0x1a40, 0x0201, 0x0000, 0x0000, 0x06, 0x01, 0x1, "11B" },
+
+       /*
+        * Plugable 10 Port USB 2.0 Hub (with charging)
+        *
+        *  [USB]
+        *    |
+        * [____0x1a40:0x0201_____] --7-- [0x1a40:0x0101]
+        *  1|  2|  3|  4|  5|  6|        1|  2|  3|  4|
+        *  FR4 FR3 FR2 FR1 BK2 BK1       TP1 TP2 FR6 FR5
+        */
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x01, 0x0, "FR4" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x02, 0x0, "FR3" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x03, 0x0, "FR2" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x04, 0x0, "FR1" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x05, 0x0, "BK2" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x06, 0x0, "BK1" },
+       { 0x1a40, 0x0101, 0x07, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x01, 0x1, "TP1" },
+       { 0x1a40, 0x0101, 0x07, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x02, 0x1, "TP2" },
+       { 0x1a40, 0x0101, 0x07, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x03, 0x1, "FR6" },
+       { 0x1a40, 0x0101, 0x07, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x04, 0x1, "FR5" },
+
+       /*
+        * Plugable 10 Port USB 2.0 Hub (no charging)
+        *
+        *  [USB]
+        *    |
+        * [____0x1a40:0x0201_____] --7-- [0x1a40:0x0101]
+        *  1|  2|  3|  4|  5|  6|        1|  2|  3|  4|
+        *  BK1 BK2 TP1 TP2 FR1 FR2       FR6 FR5 FR4 FR3
+        */
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x01, 0x0, "BK1" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x02, 0x0, "BK2" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x03, 0x0, "TP1" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x04, 0x0, "TP2" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x05, 0x0, "FR1" },
+       { 0x1a40, 0x0201, 0x00, 0x0000, 0x0000, 0x1a40, 0x0101, 0x02, 0x06, 0x0, "FR2" },
+       { 0x1a40, 0x0101, 0x07, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x01, 0x1, "FR6" },
+       { 0x1a40, 0x0101, 0x07, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x02, 0x1, "FR5" },
+       { 0x1a40, 0x0101, 0x07, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x03, 0x1, "FR4" },
+       { 0x1a40, 0x0101, 0x07, 0x1a40, 0x0201, 0x0000, 0x0000, 0x02, 0x04, 0x1, "FR3" },
+
+       /*
+        * Plugable 7 Port USB 3.0 Hub with dual charging ports
+        *
+        *  [USB]
+        *    |
+        * [0x2109:0x2812]--1-- [0x1a40:0x0201]
+        *   2|  3|  4|         1|  2|  3|  4|
+        *   #05 #06 #07       #02 #03 #04 #01
+        */
+       { 0x2109, 0x2812, 0x00, 0x0000, 0x0000, 0x2109, 0x2812, 0x02, 0x02, 0x0, "05" },
+       { 0x2109, 0x2812, 0x00, 0x0000, 0x0000, 0x2109, 0x2812, 0x02, 0x03, 0x0, "06" },
+       { 0x2109, 0x2812, 0x00, 0x0000, 0x0000, 0x2109, 0x2812, 0x02, 0x04, 0x0, "07" },
+       { 0x2109, 0x2812, 0x01, 0x2109, 0x2812, 0x0000, 0x0000, 0x02, 0x01, 0x1, "02" },
+       { 0x2109, 0x2812, 0x01, 0x2109, 0x2812, 0x0000, 0x0000, 0x02, 0x02, 0x1, "03" },
+       { 0x2109, 0x2812, 0x01, 0x2109, 0x2812, 0x0000, 0x0000, 0x02, 0x03, 0x1, "04" },
+       { 0x2109, 0x2812, 0x01, 0x2109, 0x2812, 0x0000, 0x0000, 0x02, 0x04, 0x1, "01" },
+
+       /*
+        * Plugable 10 Port USB 3.0 Hub
+        *
+        *  [USB]
+        *    |
+        * [0x2109:0x2812]--1-- [0x2109:0x2812]
+        *   2|  4|    |        1|  2|  3|  4|
+        *   FR3 TP1   |        BK2 BK1 FR1 FR2
+        *             |
+        *             \----3-- [0x2109:0x2812]
+        *                      1|  2|  3|  4|
+        *                      FR4 FR5 FR6 TP2
+        */
+       { 0x2109, 0x2812, 0x00, 0x0000, 0x0000, 0x2109, 0x2812, 0x03, 0x02, 0x0, "FR3" },
+       { 0x2109, 0x2812, 0x00, 0x0000, 0x0000, 0x2109, 0x2812, 0x03, 0x04, 0x0, "TP1" },
+       { 0x2109, 0x2812, 0x01, 0x2109, 0x2812, 0x0000, 0x0000, 0x03, 0x01, 0x1, "BK2" },
+       { 0x2109, 0x2812, 0x01, 0x2109, 0x2812, 0x0000, 0x0000, 0x03, 0x02, 0x1, "BK1" },
+       { 0x2109, 0x2812, 0x01, 0x2109, 0x2812, 0x0000, 0x0000, 0x03, 0x03, 0x1, "FR1" },
+       { 0x2109, 0x2812, 0x01, 0x2109, 0x2812, 0x0000, 0x0000, 0x03, 0x04, 0x1, "FR2" },
+       { 0x2109, 0x2812, 0x03, 0x2109, 0x2812, 0x0000, 0x0000, 0x03, 0x01, 0x1, "FR4" },
+       { 0x2109, 0x2812, 0x03, 0x2109, 0x2812, 0x0000, 0x0000, 0x03, 0x02, 0x1, "FR5" },
+       { 0x2109, 0x2812, 0x03, 0x2109, 0x2812, 0x0000, 0x0000, 0x03, 0x03, 0x1, "FR6" },
+       { 0x2109, 0x2812, 0x03, 0x2109, 0x2812, 0x0000, 0x0000, 0x03, 0x04, 0x1, "TP2" },
+
+       /*     hub      hub-port  parent-hub     child-device   chps  dprt  chn  labl */
+       { 0x0000, 0x0000, 0x00, 0x0000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, NULL }
        };
 
        g_return_if_fail (GMW_IS_DEVICE (device));
@@ -711,21 +919,21 @@ gmw_device_set_usb_device (GmwDevice *device, GUsbDevice *usb_device)
                        return;
        }
 
-       /* find the two parents */
+       /* match */
+       usb_hub_toplevel = gmw_device_get_toplevel_hub (device);
        usb_hub_parent = g_usb_device_get_parent (usb_hub);
-       g_debug ("Quirk info: 0x%04x:0x%04x 0x%02x->"
-                            "0x%04x:0x%04x 0x%02x->"
-                            "0x%04x:0x%04x 0x%02x",
-                g_usb_device_get_vid (usb_hub),
-                g_usb_device_get_pid (usb_hub),
-                g_usb_device_get_port_number (usb_hub),
+       g_debug ("Quirk info: 0x%04x:0x%04x 0x%02x -> "
+                "0x%04x:0x%04x 0x%02x -> "
+                "0x%04x:0x%04x 0x%02x",
                 usb_hub_parent ? g_usb_device_get_vid (usb_hub_parent) : 0x0,
                 usb_hub_parent ? g_usb_device_get_pid (usb_hub_parent) : 0x0,
                 usb_hub_parent ? g_usb_device_get_port_number (usb_hub_parent) : 0x0,
+                g_usb_device_get_vid (usb_hub),
+                g_usb_device_get_pid (usb_hub),
+                g_usb_device_get_port_number (usb_hub),
                 g_usb_device_get_vid (usb_device),
                 g_usb_device_get_pid (usb_device),
                 g_usb_device_get_port_number (usb_device));
-
        for (i = 0; quirks[i].hub_label != NULL; i++) {
                /* check grandparent */
                if (usb_hub_parent != NULL && quirks[i].hub_parent_vid != 0x0000) {
@@ -767,6 +975,25 @@ gmw_device_set_usb_device (GmwDevice *device, GUsbDevice *usb_device)
                                continue;
                }
 
+               /* check number of children */
+               if (usb_hub_toplevel != NULL && quirks[i].number_ics != 0x00) {
+                       GUsbDevice *tmp;
+                       guint child_cnt = 1;
+                       _cleanup_ptrarray_unref_ GPtrArray *children = NULL;
+
+                       children = g_usb_device_get_children (usb_hub_toplevel);
+                       for (j = 0; j < children->len; j++) {
+                               tmp = g_ptr_array_index (children, j);
+                               if (g_usb_device_get_device_class (tmp) == 0x09)
+                                       child_cnt++;
+                       }
+                       if (child_cnt != quirks[i].number_ics) {
+                               g_debug ("no matching quirk %i != %i",
+                                        child_cnt, quirks[i].number_ics);
+                               continue;
+                       }
+               }
+
                /* check port number */
                if (quirks[i].device_port != 0x00) {
                        if (quirks[i].device_port != g_usb_device_get_port_number (usb_device))
diff --git a/src/gmw-device.h b/src/gmw-device.h
index 533156d..af0b7a5 100644
--- a/src/gmw-device.h
+++ b/src/gmw-device.h
@@ -57,6 +57,7 @@ GType          gmw_device_get_type            (void);
 GmwDevice      *gmw_device_new                 (void);
 const gchar    *gmw_device_get_icon            (GmwDevice      *device);
 gchar          *gmw_device_get_description     (GmwDevice      *device);
+gchar          *gmw_device_get_quirk_string    (GmwDevice      *device);
 GmwDeviceState  gmw_device_get_state           (GmwDevice      *device);
 UDisksBlock    *gmw_device_get_udisks_block    (GmwDevice      *device);
 const gchar    *gmw_device_get_name            (GmwDevice      *device);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]