Core: Cache device descriptors in the core

Discussion: It is necessary to cache the device descriptor in the core to
support reading the descriptors after a device is disconnected. We could
either 1) allow each backend to handle this caching (which would most
certainly duplicate code), or 2) cache the descritors when a device
is added. This patch does the later.

Further discussion: It might be beneficial to cache more than just the
device descriptors in the core. It might also be worthwhile caching the
configuration and BOS descriptors as well.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Nathan Hjelm
2012-11-29 13:53:41 -07:00
committed by Hans de Goede
parent 913a233ec2
commit 8399b52062
5 changed files with 30 additions and 20 deletions
+2 -4
View File
@@ -537,15 +537,13 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx,
int usbi_sanitize_device(struct libusb_device *dev)
{
int r;
unsigned char raw_desc[DEVICE_DESC_LENGTH];
uint8_t num_configurations;
int host_endian;
r = usbi_backend->get_device_descriptor(dev, raw_desc, &host_endian);
r = usbi_device_cache_descriptor(dev);
if (r < 0)
return r;
num_configurations = raw_desc[DEVICE_DESC_LENGTH - 1];
num_configurations = dev->device_descriptor.bNumConfigurations;
if (num_configurations > USB_MAXCONFIG) {
usbi_err(DEVICE_CTX(dev), "too many configurations");
return LIBUSB_ERROR_IO;
+21 -15
View File
@@ -437,6 +437,25 @@ err:
return r;
}
int usbi_device_cache_descriptor(libusb_device *dev)
{
int r, host_endian;
r = usbi_backend->get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor,
&host_endian);
if (r < 0)
return r;
if (!host_endian) {
dev->device_descriptor.bcdUSB = libusb_le16_to_cpu(dev->device_descriptor.bcdUSB);
dev->device_descriptor.idVendor = libusb_le16_to_cpu(dev->device_descriptor.idVendor);
dev->device_descriptor.idProduct = libusb_le16_to_cpu(dev->device_descriptor.idProduct);
dev->device_descriptor.bcdDevice = libusb_le16_to_cpu(dev->device_descriptor.bcdDevice);
}
return LIBUSB_SUCCESS;
}
/** \ingroup desc
* Get the USB device descriptor for a given device.
*
@@ -449,22 +468,9 @@ err:
int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
struct libusb_device_descriptor *desc)
{
unsigned char raw_desc[DEVICE_DESC_LENGTH];
int host_endian = 0;
int r;
usbi_dbg("");
r = usbi_backend->get_device_descriptor(dev, raw_desc, &host_endian);
if (r < 0)
return r;
memcpy((unsigned char *) desc, raw_desc, sizeof(raw_desc));
if (!host_endian) {
desc->bcdUSB = libusb_le16_to_cpu(desc->bcdUSB);
desc->idVendor = libusb_le16_to_cpu(desc->idVendor);
desc->idProduct = libusb_le16_to_cpu(desc->idProduct);
desc->bcdDevice = libusb_le16_to_cpu(desc->bcdDevice);
}
memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor,
sizeof (dev->device_descriptor));
return 0;
}
+4
View File
@@ -288,6 +288,9 @@ struct libusb_device {
struct list_head list;
unsigned long session_data;
struct libusb_device_descriptor device_descriptor;
unsigned char os_priv[0];
};
@@ -394,6 +397,7 @@ int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer);
int usbi_parse_descriptor(unsigned char *source, const char *descriptor,
void *dest, int host_endian);
int usbi_device_cache_descriptor(libusb_device *dev);
int usbi_get_config_index_by_value(struct libusb_device *dev,
uint8_t bConfigurationValue, int *idx);
+2
View File
@@ -1170,6 +1170,8 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
force_hcd_device_descriptor(dev);
}
usbi_sanitize_device(dev);
usbi_dbg("(bus: %d, addr: %d, depth: %d, port: %d): '%s'",
dev->bus_number, dev->device_address, priv->depth, priv->port, device_id);
+1 -1
View File
@@ -1 +1 @@
#define LIBUSB_NANO 10649
#define LIBUSB_NANO 10650