summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2015-04-29 15:43:05 +0100
committerRichard Hughes <richard@hughsie.com>2015-04-29 16:38:29 +0100
commitaa171e23369fdb52ce334abc4c5e6248131599be (patch)
tree7d66e66da83d50791c78f4824b4086c886b301cd
parent0d27ed093cb3de84f7fdf66ada6d6089720c08fe (diff)
downloadgusb-aa171e23369fdb52ce334abc4c5e6248131599be.tar.gz
Add g_usb_device_get_custom_index()
This allows us to get the string index for a given interface descriptor.
-rw-r--r--gusb/Makefile.am1
-rw-r--r--gusb/gusb-device.c58
-rw-r--r--gusb/gusb-device.h7
-rw-r--r--gusb/gusb-self-test.c60
-rw-r--r--gusb/libgusb.ver4
5 files changed, 130 insertions, 0 deletions
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
@@ -420,6 +420,64 @@ g_usb_device_open (GUsbDevice *device,
}
/**
+ * 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
* @error: a #GError, or %NULL
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;