summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2015-11-07 12:52:50 +0000
committerRichard Hughes <richard@hughsie.com>2015-11-07 12:58:38 +0000
commit19e69a86ef611f5481541a85ab21925b114b69dd (patch)
treef5f54ede93c3dd6aee737d8a09ee4a2b57a31f31
parent0c5eb813279c67607e17dfd99087358d34c6c8f5 (diff)
downloadgusb-19e69a86ef611f5481541a85ab21925b114b69dd.tar.gz
Add g_usb_device_get_interface()
This is required for libdfu.
-rw-r--r--gusb/gusb-device.c111
-rw-r--r--gusb/gusb-device.h11
2 files changed, 119 insertions, 3 deletions
diff --git a/gusb/gusb-device.c b/gusb/gusb-device.c
index 8d3b521..1ef6572 100644
--- a/gusb/gusb-device.c
+++ b/gusb/gusb-device.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2010-2011 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2010-2015 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
* Copyright (C) 2011 Debarshi Ray <debarshir@src.gnome.org>
*
@@ -115,6 +115,9 @@ g_usb_device_get_property (GObject *object,
case PROP_LIBUSB_DEVICE:
g_value_set_pointer (value, priv->device);
break;
+ case PROP_CONTEXT:
+ g_value_set_object (value, priv->context);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -194,7 +197,7 @@ g_usb_device_class_init (GUsbDeviceClass *klass)
g_param_spec_object ("context", NULL, NULL,
G_USB_TYPE_CONTEXT,
G_PARAM_CONSTRUCT_ONLY|
- G_PARAM_WRITABLE);
+ G_PARAM_READWRITE);
/**
* GUsbDevice:platform-id:
@@ -478,6 +481,110 @@ g_usb_device_get_custom_index (GUsbDevice *device,
}
/**
+ * g_usb_device_get_interface:
+ * @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 interface number from the vendor class interface descriptor.
+ *
+ * Return value: an interface number, or 0xff for failure
+ *
+ * Since: 0.2.5
+ **/
+guint8
+g_usb_device_get_interface (GUsbDevice *device,
+ guint8 class_id,
+ guint8 subclass_id,
+ guint8 protocol_id,
+ GError **error)
+{
+ const struct libusb_interface_descriptor *ifp;
+ gint rc;
+ guint8 iface_num = 0xff;
+ 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;
+ iface_num = ifp->bInterfaceNumber;
+ break;
+ }
+
+ /* nothing matched */
+ if (iface_num == 0xff) {
+ g_set_error (error,
+ G_USB_DEVICE_ERROR,
+ G_USB_DEVICE_ERROR_NOT_SUPPORTED,
+ "no interface for class 0x%02x, "
+ "subclass 0x%02x and protocol 0x%02x",
+ class_id, subclass_id, protocol_id);
+ }
+
+ libusb_free_config_descriptor (config);
+ return iface_num;
+}
+
+/**
+ * g_usb_device_get_interface:
+ * @device: a #GUsbDevice
+ * @iface: an interface number
+ * @error: a #GError, or %NULL
+ *
+ * Gets any extra data from the interface.
+ *
+ * Return value: (transfer full): a #GBytes, or %NULL for failure
+ *
+ * Since: 0.2.5
+ **/
+GBytes *
+g_usb_device_get_interface_data (GUsbDevice *device, guint8 iface, GError **error)
+{
+ const struct libusb_interface_descriptor *ifp;
+ gint rc;
+ guint i;
+ GBytes *bytes = NULL;
+ 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 (iface == ifp->bInterfaceNumber) {
+ bytes = g_bytes_new (config->extra, config->extra_length);
+ break;
+ }
+ }
+
+ /* nothing matched */
+ if (bytes == NULL) {
+ g_set_error (error,
+ G_USB_DEVICE_ERROR,
+ G_USB_DEVICE_ERROR_NOT_SUPPORTED,
+ "no interface 0x%02x", iface);
+ }
+
+ libusb_free_config_descriptor (config);
+ return bytes;
+}
+
+/**
* 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 74849a1..9b6ef79 100644
--- a/gusb/gusb-device.h
+++ b/gusb/gusb-device.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2010-2011 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2010-2015 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
*
* Licensed under the GNU Lesser General Public License Version 2.1
@@ -174,6 +174,15 @@ guint8 g_usb_device_get_custom_index (GUsbDevice *device,
guint8 protocol_id,
GError **error);
+guint8 g_usb_device_get_interface (GUsbDevice *device,
+ guint8 class_id,
+ guint8 subclass_id,
+ guint8 protocol_id,
+ GError **error);
+GBytes *g_usb_device_get_interface_data (GUsbDevice *device,
+ guint8 iface,
+ GError **error);
+
gboolean g_usb_device_open (GUsbDevice *device,
GError **error);
gboolean g_usb_device_close (GUsbDevice *device,