diff options
author | Richard Hughes <richard@hughsie.com> | 2015-11-08 20:33:16 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2015-11-08 20:33:16 +0000 |
commit | d01f88d16addbc1bec3f7372e8c90f4fc849cb77 (patch) | |
tree | b02b5d1f430baf4a36ebdbfd32c9fb84285f8a75 | |
parent | 19e69a86ef611f5481541a85ab21925b114b69dd (diff) | |
download | gusb-wip/hughsie/dfu.tar.gz |
-rw-r--r-- | gusb/Makefile.am | 3 | ||||
-rw-r--r-- | gusb/gusb-autocleanups.h | 1 | ||||
-rw-r--r-- | gusb/gusb-device.c | 106 | ||||
-rw-r--r-- | gusb/gusb-device.h | 11 | ||||
-rw-r--r-- | gusb/gusb-interface-private.h | 34 | ||||
-rw-r--r-- | gusb/gusb-interface.c | 247 | ||||
-rw-r--r-- | gusb/gusb-interface.h | 68 | ||||
-rw-r--r-- | gusb/gusb.h | 1 |
8 files changed, 439 insertions, 32 deletions
diff --git a/gusb/Makefile.am b/gusb/Makefile.am index 5c45ac5..4307b7c 100644 --- a/gusb/Makefile.am +++ b/gusb/Makefile.am @@ -27,6 +27,8 @@ libgusbbase_include_HEADERS = \ gusb-device.h \ gusb-device-private.h \ gusb-device-list.h \ + gusb-interface.h \ + gusb-interface-private.h \ gusb-source.h \ gusb-util.h @@ -34,6 +36,7 @@ libgusb_la_SOURCES = \ gusb-context.c \ gusb-device.c \ gusb-device-list.c \ + gusb-interface.c \ gusb-source.c \ gusb-util.c diff --git a/gusb/gusb-autocleanups.h b/gusb/gusb-autocleanups.h index 0adf613..ce7dc45 100644 --- a/gusb/gusb-autocleanups.h +++ b/gusb/gusb-autocleanups.h @@ -29,6 +29,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUsbContext, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUsbDevice, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUsbInterface, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUsbDeviceList, g_object_unref) #endif diff --git a/gusb/gusb-device.c b/gusb/gusb-device.c index 1ef6572..11a5d98 100644 --- a/gusb/gusb-device.c +++ b/gusb/gusb-device.c @@ -38,6 +38,7 @@ #include "gusb-util.h" #include "gusb-device.h" #include "gusb-device-private.h" +#include "gusb-interface-private.h" /** * GUsbDevicePrivate: @@ -490,11 +491,11 @@ g_usb_device_get_custom_index (GUsbDevice *device, * * Gets the interface number from the vendor class interface descriptor. * - * Return value: an interface number, or 0xff for failure + * Return value: (transfer full): a #GUsbInterface or %NULL for not found * - * Since: 0.2.5 + * Since: 0.2.8 **/ -guint8 +GUsbInterface * g_usb_device_get_interface (GUsbDevice *device, guint8 class_id, guint8 subclass_id, @@ -503,7 +504,7 @@ g_usb_device_get_interface (GUsbDevice *device, { const struct libusb_interface_descriptor *ifp; gint rc; - guint8 iface_num = 0xff; + GUsbInterface *interface = NULL; guint i; struct libusb_config_descriptor *config; @@ -520,12 +521,12 @@ g_usb_device_get_interface (GUsbDevice *device, continue; if (ifp->bInterfaceProtocol != protocol_id) continue; - iface_num = ifp->bInterfaceNumber; + interface = _g_usb_interface_new (ifp); break; } /* nothing matched */ - if (iface_num == 0xff) { + if (interface == NULL) { g_set_error (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_NOT_SUPPORTED, @@ -535,53 +536,48 @@ g_usb_device_get_interface (GUsbDevice *device, } libusb_free_config_descriptor (config); - return iface_num; + return interface; } /** - * g_usb_device_get_interface: + * g_usb_device_get_interfaces: * @device: a #GUsbDevice - * @iface: an interface number * @error: a #GError, or %NULL * - * Gets any extra data from the interface. + * Gets all the interfaces exported by the device. * - * Return value: (transfer full): a #GBytes, or %NULL for failure + * Return value: (transfer container): an array of #GUsbInterface or %NULL for error * - * Since: 0.2.5 + * Since: 0.2.8 **/ -GBytes * -g_usb_device_get_interface_data (GUsbDevice *device, guint8 iface, GError **error) +GPtrArray * +g_usb_device_get_interfaces (GUsbDevice *device, GError **error) { const struct libusb_interface_descriptor *ifp; gint rc; guint i; - GBytes *bytes = NULL; + guint j; struct libusb_config_descriptor *config; + GPtrArray *array = NULL; 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 */ + /* get all interfaces */ + array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); 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; + GUsbInterface *interface = NULL; + for (j = 0; j < (guint) config->interface[i].num_altsetting; j++) { + ifp = &config->interface[i].altsetting[j]; + interface = _g_usb_interface_new (ifp); + g_ptr_array_add (array, interface); } - } - - /* nothing matched */ - if (bytes == NULL) { - g_set_error (error, - G_USB_DEVICE_ERROR, - G_USB_DEVICE_ERROR_NOT_SUPPORTED, - "no interface 0x%02x", iface); + break; } libusb_free_config_descriptor (config); - return bytes; + return array; } /** @@ -807,6 +803,40 @@ g_usb_device_release_interface (GUsbDevice *device, } /** + * g_usb_device_set_interface_alt: + * @device: a #GUsbDevice + * @interface: bInterfaceNumber of the interface you wish to release + * @alt: alternative setting number + * @error: a #GError, or %NULL + * + * Sets an alternate setting on an interface. + * + * Return value: %TRUE on success + * + * Since: 0.2.8 + **/ +gboolean +g_usb_device_set_interface_alt (GUsbDevice *device, + gint interface, + gint alt, + GError **error) +{ + gint rc; + + g_return_val_if_fail (G_USB_IS_DEVICE (device), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (device->priv->handle == NULL) + return g_usb_device_not_open_error (device, error); + + rc = libusb_set_interface_alt_setting (device->priv->handle, interface, alt); + if (rc != LIBUSB_SUCCESS) + return g_usb_device_libusb_error_to_gerror (device, rc, error); + + return TRUE; +} + +/** * g_usb_device_get_string_descriptor: * @desc_index: the index for the string descriptor to retreive * @error: a #GError, or %NULL @@ -1657,6 +1687,24 @@ g_usb_device_get_pid (GUsbDevice *device) } /** + * g_usb_device_get_version_bcd: + * @device: a #GUsbDevice + * + * Gets the BCD firmware version number for the device. + * + * Return value: a version number in BCD format. + * + * Since: 0.2.8 + **/ +guint16 +g_usb_device_get_version_bcd (GUsbDevice *device) +{ + g_return_val_if_fail (G_USB_IS_DEVICE (device), 0); + + return device->priv->desc.bcdDevice; +} + +/** * g_usb_device_get_vid_as_str: * @device: a #GUsbDevice * diff --git a/gusb/gusb-device.h b/gusb/gusb-device.h index 9b6ef79..4579b64 100644 --- a/gusb/gusb-device.h +++ b/gusb/gusb-device.h @@ -26,6 +26,7 @@ #include <gio/gio.h> #include <gusb/gusb-util.h> +#include <gusb/gusb-interface.h> G_BEGIN_DECLS @@ -159,6 +160,7 @@ guint8 g_usb_device_get_port_number (GUsbDevice *device); guint16 g_usb_device_get_vid (GUsbDevice *device); guint16 g_usb_device_get_pid (GUsbDevice *device); +guint16 g_usb_device_get_version_bcd (GUsbDevice *device); const gchar *g_usb_device_get_vid_as_str (GUsbDevice *device); const gchar *g_usb_device_get_pid_as_str (GUsbDevice *device); guint8 g_usb_device_get_device_class (GUsbDevice *device); @@ -174,13 +176,12 @@ guint8 g_usb_device_get_custom_index (GUsbDevice *device, guint8 protocol_id, GError **error); -guint8 g_usb_device_get_interface (GUsbDevice *device, +GUsbInterface *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, +GPtrArray *g_usb_device_get_interfaces (GUsbDevice *device, GError **error); gboolean g_usb_device_open (GUsbDevice *device, @@ -205,6 +206,10 @@ gboolean g_usb_device_release_interface (GUsbDevice *device, gint interface, GUsbDeviceClaimInterfaceFlags flags, GError **error); +gboolean g_usb_device_set_interface_alt (GUsbDevice *device, + gint interface, + gint alt, + GError **error); gchar *g_usb_device_get_string_descriptor (GUsbDevice *device, guint8 desc_index, diff --git a/gusb/gusb-interface-private.h b/gusb/gusb-interface-private.h new file mode 100644 index 0000000..386cc1f --- /dev/null +++ b/gusb/gusb-interface-private.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GUSB_INTERFACE_PRIVATE_H__ +#define __GUSB_INTERFACE_PRIVATE_H__ + +#include <libusb-1.0/libusb.h> + +#include <gusb/gusb-interface.h> + +G_BEGIN_DECLS + +GUsbInterface *_g_usb_interface_new (const struct libusb_interface_descriptor *iface); + +G_END_DECLS + +#endif /* __GUSB_INTERFACE_PRIVATE_H__ */ diff --git a/gusb/gusb-interface.c b/gusb/gusb-interface.c new file mode 100644 index 0000000..8f8daa9 --- /dev/null +++ b/gusb/gusb-interface.c @@ -0,0 +1,247 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +/** + * SECTION:gusb-interface + * @short_description: GLib interface integration for libusb + * + * This object is a thin glib wrapper around a libusb_interface_descriptor + */ + +#include "config.h" + +#include <string.h> + +#include "gusb-interface.h" +#include "gusb-interface-private.h" + +/** + * GUsbInterfacePrivate: + * + * Private #GUsbInterface data + **/ +struct _GUsbInterfacePrivate +{ + struct libusb_interface_descriptor iface; + GBytes *extra; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (GUsbInterface, g_usb_interface, G_TYPE_OBJECT) + +static void +g_usb_interface_finalize (GObject *object) +{ + GUsbInterface *interface = G_USB_INTERFACE (object); + GUsbInterfacePrivate *priv = interface->priv; + + g_bytes_unref (priv->extra); + + G_OBJECT_CLASS (g_usb_interface_parent_class)->finalize (object); +} + +static void +g_usb_interface_class_init (GUsbInterfaceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = g_usb_interface_finalize; +} + +static void +g_usb_interface_init (GUsbInterface *interface) +{ + interface->priv = g_usb_interface_get_instance_private (interface); +} + +/** + * _g_usb_interface_new: + * + * Return value: a new #GUsbInterface object. + * + * Since: 0.2.8 + **/ +GUsbInterface * +_g_usb_interface_new (const struct libusb_interface_descriptor *iface) +{ + GUsbInterface *interface; + interface = g_object_new (G_USB_TYPE_INTERFACE, NULL); + + /* copy the data */ + memcpy (&interface->priv->iface, + iface, + sizeof (struct libusb_interface_descriptor)); + interface->priv->extra = g_bytes_new (iface->extra, iface->extra_length); + + return G_USB_INTERFACE (interface); +} + +/** + * g_usb_interface_get_length: + * @interface: a #GUsbInterface + * + * Gets the USB bus number for the interface. + * + * Return value: The 8-bit bus number + * + * Since: 0.2.8 + **/ +guint8 +g_usb_interface_get_length (GUsbInterface *interface) +{ + g_return_val_if_fail (G_USB_IS_INTERFACE (interface), 0); + return interface->priv->iface.bLength; +} + +/** + * g_usb_interface_get_kind: + * @interface: a #GUsbInterface + * + * Gets the type of interface. + * + * Return value: The 8-bit address + * + * Since: 0.2.8 + **/ +guint8 +g_usb_interface_get_kind (GUsbInterface *interface) +{ + g_return_val_if_fail (G_USB_IS_INTERFACE (interface), 0); + return interface->priv->iface.bDescriptorType; +} + +/** + * g_usb_interface_get_number: + * @interface: a #GUsbInterface + * + * Gets the interface number. + * + * Return value: The interface ID + * + * Since: 0.2.8 + **/ +guint8 +g_usb_interface_get_number (GUsbInterface *interface) +{ + g_return_val_if_fail (G_USB_IS_INTERFACE (interface), 0); + return interface->priv->iface.bInterfaceNumber; +} + +/** + * g_usb_interface_get_alternate: + * @interface: a #GUsbInterface + * + * Gets the alternate setting for the interface. + * + * Return value: alt setting, typically zero. + * + * Since: 0.2.8 + **/ +guint8 +g_usb_interface_get_alternate (GUsbInterface *interface) +{ + g_return_val_if_fail (G_USB_IS_INTERFACE (interface), 0); + return interface->priv->iface.bAlternateSetting; +} + +/** + * g_usb_interface_get_class: + * @interface: a #GUsbInterface + * + * Gets the interface class, typically a #GUsbInterfaceClassCode. + * + * Return value: a interface class number, e.g. 0x09 is a USB hub. + * + * Since: 0.2.8 + **/ +guint8 +g_usb_interface_get_class (GUsbInterface *interface) +{ + g_return_val_if_fail (G_USB_IS_INTERFACE (interface), 0); + return interface->priv->iface.bInterfaceClass; +} + +/** + * g_usb_interface_get_subclass: + * @interface: a #GUsbInterface + * + * Gets the interface subclass qualified by the class number. + * See g_usb_interface_get_class(). + * + * Return value: a interface subclass number. + * + * Since: 0.2.8 + **/ +guint8 +g_usb_interface_get_subclass (GUsbInterface *interface) +{ + g_return_val_if_fail (G_USB_IS_INTERFACE (interface), 0); + return interface->priv->iface.bInterfaceSubClass; +} + +/** + * g_usb_interface_get_protocol: + * @interface: a #GUsbInterface + * + * Gets the interface protocol qualified by the class and subclass numbers. + * See g_usb_interface_get_class() and g_usb_interface_get_subclass(). + * + * Return value: a interface protocol number. + * + * Since: 0.2.8 + **/ +guint8 +g_usb_interface_get_protocol (GUsbInterface *interface) +{ + g_return_val_if_fail (G_USB_IS_INTERFACE (interface), 0); + return interface->priv->iface.bInterfaceProtocol; +} + +/** + * g_usb_interface_get_index: + * @interface: a #GUsbInterface + * + * Gets the index for the string descriptor. + * + * Return value: a string descriptor index. + * + * Since: 0.2.8 + **/ +guint8 +g_usb_interface_get_index (GUsbInterface *interface) +{ + g_return_val_if_fail (G_USB_IS_INTERFACE (interface), 0); + return interface->priv->iface.iInterface; +} + +/** + * g_usb_interface_get_extra: + * @interface: a #GUsbInterface + * + * Gets any extra data from the interface. + * + * Return value: (transfer none): a #GBytes, or %NULL for failure + * + * Since: 0.2.8 + **/ +GBytes * +g_usb_interface_get_extra (GUsbInterface *interface) +{ + g_return_val_if_fail (G_USB_IS_INTERFACE (interface), NULL); + return interface->priv->extra; +} diff --git a/gusb/gusb-interface.h b/gusb/gusb-interface.h new file mode 100644 index 0000000..816373b --- /dev/null +++ b/gusb/gusb-interface.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GUSB_INTERFACE_H__ +#define __GUSB_INTERFACE_H__ + +#include <glib-object.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define G_USB_TYPE_INTERFACE (g_usb_interface_get_type ()) +#define G_USB_INTERFACE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_USB_TYPE_INTERFACE, GUsbInterface)) +#define G_USB_IS_INTERFACE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_USB_TYPE_INTERFACE)) + +typedef struct _GUsbInterfacePrivate GUsbInterfacePrivate; +typedef struct _GUsbInterface GUsbInterface; +typedef struct _GUsbInterfaceClass GUsbInterfaceClass; + +struct _GUsbInterface +{ + GObject parent; + GUsbInterfacePrivate *priv; +}; + +struct _GUsbInterfaceClass +{ + GObjectClass parent_class; + /*< private >*/ + /* + * If adding fields to this struct, remove corresponding + * amount of padding to avoid changing overall struct size + */ + gpointer _gusb_reserved[31]; +}; + +GType g_usb_interface_get_type (void); + +guint8 g_usb_interface_get_length (GUsbInterface *interface); +guint8 g_usb_interface_get_kind (GUsbInterface *interface); +guint8 g_usb_interface_get_number (GUsbInterface *interface); +guint8 g_usb_interface_get_alternate (GUsbInterface *interface); +guint8 g_usb_interface_get_class (GUsbInterface *interface); +guint8 g_usb_interface_get_subclass (GUsbInterface *interface); +guint8 g_usb_interface_get_protocol (GUsbInterface *interface); +guint8 g_usb_interface_get_index (GUsbInterface *interface); +GBytes *g_usb_interface_get_extra (GUsbInterface *interface); + +G_END_DECLS + +#endif /* __GUSB_INTERFACE_H__ */ diff --git a/gusb/gusb.h b/gusb/gusb.h index 50a9cd0..56d08e1 100644 --- a/gusb/gusb.h +++ b/gusb/gusb.h @@ -26,6 +26,7 @@ #include <gusb/gusb-autocleanups.h> #include <gusb/gusb-context.h> +#include <gusb/gusb-interface.h> #include <gusb/gusb-source.h> #include <gusb/gusb-device.h> #include <gusb/gusb-device-list.h> |