From aa171e23369fdb52ce334abc4c5e6248131599be Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Wed, 29 Apr 2015 15:43:05 +0100 Subject: Add g_usb_device_get_custom_index() This allows us to get the string index for a given interface descriptor. --- gusb/Makefile.am | 1 + gusb/gusb-device.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ gusb/gusb-device.h | 7 ++++++ gusb/gusb-self-test.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ gusb/libgusb.ver | 4 ++++ 5 files changed, 130 insertions(+) diff --git a/gusb/Makefile.am b/gusb/Makefile.am index 13c2f07..05a3db4 100644 --- a/gusb/Makefile.am +++ b/gusb/Makefile.am @@ -109,6 +109,7 @@ vapi_DATA = $(VAPIGEN_VAPIS) endif EXTRA_DIST = \ + libgusb.ver \ gusb-version.h.in \ gusb.pc.in diff --git a/gusb/gusb-device.c b/gusb/gusb-device.c index 815e3bb..ca53653 100644 --- a/gusb/gusb-device.c +++ b/gusb/gusb-device.c @@ -419,6 +419,64 @@ g_usb_device_open (GUsbDevice *device, return g_usb_device_libusb_error_to_gerror (device, rc, error); } +/** + * g_usb_device_get_custom_index: + * @device: a #GUsbDevice + * @class_id: a device class, e.g. 0xff for VENDOR + * @subclass_id: a device subclass + * @protocol_id: a protocol number + * @error: a #GError, or %NULL + * + * Gets the string index from the vendor class interface descriptor. + * + * Return value: a non-zero index, or 0x00 for failure + * + * Since: 0.2.5 + **/ +guint8 +g_usb_device_get_custom_index (GUsbDevice *device, + guint8 class_id, + guint8 subclass_id, + guint8 protocol_id, + GError **error) +{ + const struct libusb_interface_descriptor *ifp; + gint rc; + guint8 idx = 0x00; + guint i; + struct libusb_config_descriptor *config; + + rc = libusb_get_active_config_descriptor (device->priv->device, &config); + if (!g_usb_device_libusb_error_to_gerror (device, rc, error)) + return NULL; + + /* find the right data */ + for (i = 0; i < config->bNumInterfaces; i++) { + ifp = &config->interface[i].altsetting[0]; + if (ifp->bInterfaceClass != class_id) + continue; + if (ifp->bInterfaceSubClass != subclass_id) + continue; + if (ifp->bInterfaceProtocol != protocol_id) + continue; + idx = ifp->iInterface; + break; + } + + /* nothing matched */ + if (idx == 0x00) { + g_set_error (error, + G_USB_DEVICE_ERROR, + G_USB_DEVICE_ERROR_NOT_SUPPORTED, + "no vendor descriptor for class 0x%02x, " + "subclass 0x%02x and protocol 0x%02x", + class_id, subclass_id, protocol_id); + } + + libusb_free_config_descriptor (config); + return idx; +} + /** * g_usb_device_close: * @device: a #GUsbDevice diff --git a/gusb/gusb-device.h b/gusb/gusb-device.h index dc1c368..9c86ee5 100644 --- a/gusb/gusb-device.h +++ b/gusb/gusb-device.h @@ -100,6 +100,8 @@ typedef enum { G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER = 1 << 0, } GUsbDeviceClaimInterfaceFlags; +#define G_USB_DEVICE_CLASS_VENDOR 0xff + struct _GUsbDevice { GObject parent; @@ -139,6 +141,11 @@ guint8 g_usb_device_get_device_protocol (GUsbDevice *dev guint8 g_usb_device_get_manufacturer_index (GUsbDevice *device); guint8 g_usb_device_get_product_index (GUsbDevice *device); guint8 g_usb_device_get_serial_number_index (GUsbDevice *device); +guint8 g_usb_device_get_custom_index (GUsbDevice *device, + guint8 class_id, + guint8 subclass_id, + guint8 protocol_id, + GError **error); gboolean g_usb_device_open (GUsbDevice *device, GError **error); diff --git a/gusb/gusb-self-test.c b/gusb/gusb-self-test.c index 05905cd..6656942 100644 --- a/gusb/gusb-self-test.c +++ b/gusb/gusb-self-test.c @@ -464,6 +464,65 @@ out: g_object_unref (ctx); } +static void +gusb_device_ch2_func (void) +{ + GError *error = NULL; + GUsbContext *ctx; + GUsbDevice *device; + gboolean ret; + gchar *tmp = NULL; + guint8 idx; + + ctx = g_usb_context_new (&error); + g_assert_no_error (error); + g_assert (ctx != NULL); + + g_usb_context_set_debug (ctx, G_LOG_LEVEL_ERROR); + + /* coldplug, and get the ColorHug */ + device = g_usb_context_find_by_vid_pid (ctx, + 0x273f, + 0x1004, + &error); + if (device == NULL && + error->domain == G_USB_DEVICE_ERROR && + error->code == G_USB_DEVICE_ERROR_NO_DEVICE) { + g_print ("No device detected!\n"); + g_error_free (error); + goto out; + } + g_assert_no_error (error); + g_assert (device != NULL); + + /* open */ + ret = g_usb_device_open (device, &error); + g_assert_no_error (error); + g_assert (ret); + + /* get vendor data */ + idx = g_usb_device_get_custom_index (device, + G_USB_DEVICE_CLASS_VENDOR, + 'F', 'W', &error); + g_assert_no_error (error); + g_assert_cmpint (idx, ==, 3); + + /* get the firmware version */ + tmp = g_usb_device_get_string_descriptor (device, idx, &error); + g_assert_no_error (error); + g_assert_cmpstr (tmp, ==, "2.0.3"); + g_free (tmp); + + /* close */ + ret = g_usb_device_close (device, &error); + g_assert_no_error (error); + g_assert (ret); + + g_object_unref (device); +out: + g_object_unref (ctx); +} + int main (int argc, char **argv) @@ -479,6 +538,7 @@ main (int argc, g_test_add_func ("/gusb/device", gusb_device_func); g_test_add_func ("/gusb/device[huey]", gusb_device_huey_func); g_test_add_func ("/gusb/device[munki]", gusb_device_munki_func); + g_test_add_func ("/gusb/device[colorhug2]", gusb_device_ch2_func); return g_test_run (); } diff --git a/gusb/libgusb.ver b/gusb/libgusb.ver index e6cf69e..c292cb2 100644 --- a/gusb/libgusb.ver +++ b/gusb/libgusb.ver @@ -34,3 +34,7 @@ LIBGUSB_0.2.4 { g_usb_context_find_by_platform_id; } LIBGUSB_0.2.2; +LIBGUSB_0.2.5 { + global: + g_usb_device_get_custom_index; +} LIBGUSB_0.2.4; -- cgit v1.2.1