From 17ecfb0ecc833596c43755c80d461cddb9b3b0d7 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sun, 4 May 2008 16:20:46 +0100 Subject: Descriptor reading functionality --- libusb/descriptor.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ libusb/libusb.h | 45 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/libusb/descriptor.c b/libusb/descriptor.c index 544a3fd..30c6ac5 100644 --- a/libusb/descriptor.c +++ b/libusb/descriptor.c @@ -446,3 +446,60 @@ API_EXPORTED const struct libusb_config_descriptor *libusb_get_config_descriptor return dev->config; } +/** \ingroup desc + * Retrieve a string descriptor in C style ASCII. + * + * Wrapper around libusb_get_string_descriptor(). Uses the first language + * supported by the device. + * + * \param dev a device handle + * \param desc_index the index of the descriptor to retrieve + * \param data output buffer for ASCII string descriptor + * \param length size of data buffer + * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure + */ +API_EXPORTED int libusb_get_string_descriptor_ascii(libusb_device_handle *dev, + uint8_t desc_index, unsigned char *data, int length) +{ + unsigned char tbuf[255]; /* Some devices choke on size > 255 */ + int r, langid, si, di; + + /* Asking for the zero'th index is special - it returns a string + * descriptor that contains all the language IDs supported by the device. + * Typically there aren't many - often only one. The language IDs are 16 + * bit numbers, and they start at the third byte in the descriptor. See + * USB 2.0 specification section 9.6.7 for more information. */ + r = libusb_get_string_descriptor(dev, 0, 0, tbuf, sizeof(tbuf)); + if (r < 0) + return r; + + if (r < 4) + return LIBUSB_ERROR_IO; + + langid = tbuf[2] | (tbuf[3] << 8); + + r = libusb_get_string_descriptor(dev, desc_index, langid, tbuf, + sizeof(tbuf)); + if (r < 0) + return r; + + if (tbuf[1] != LIBUSB_DT_STRING) + return LIBUSB_ERROR_IO; + + if (tbuf[0] > r) + return LIBUSB_ERROR_IO; + + for (di = 0, si = 2; si < tbuf[0]; si += 2) { + if (di >= (length - 1)) + break; + + if (tbuf[si + 1]) /* high byte */ + data[di++] = '?'; + else + data[di++] = tbuf[si]; + } + + data[di] = 0; + return di; +} + diff --git a/libusb/libusb.h b/libusb/libusb.h index 779dcff..09401c2 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -883,6 +883,51 @@ int libusb_interrupt_transfer(libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *actual_length, unsigned int timeout); +/** \ingroup desc + * Retrieve a descriptor from the default control pipe. + * This is a convenience function which formulates the appropriate control + * message to retrieve the descriptor. + * + * \param dev a device handle + * \param desc_type the descriptor type, see \ref libusb_descriptor_type + * \param desc_index the index of the descriptor to retrieve + * \param data output buffer for descriptor + * \param length size of data buffer + * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure + */ +static inline int libusb_get_descriptor(libusb_device_handle *dev, + uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) +{ + return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, + LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data, + length, 1000); +} + +/** \ingroup desc + * Retrieve a descriptor from a device. + * This is a convenience function which formulates the appropriate control + * message to retrieve the descriptor. The string returned is Unicode, as + * detailed in the USB specifications. + * + * \param dev a device handle + * \param desc_index the index of the descriptor to retrieve + * \param langid the language ID for the string descriptor + * \param data output buffer for descriptor + * \param length size of data buffer + * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure + * \see libusb_get_string_descriptor_ascii + */ +static inline int libusb_get_string_descriptor(libusb_device_handle *dev, + uint8_t desc_index, uint16_t langid, unsigned char *data, int length) +{ + return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, + LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc_index, + langid, data, length, 1000); +} + +int libusb_get_string_descriptor_ascii(libusb_device_handle *dev, + uint8_t index, unsigned char *data, int length); + /* polling and timeouts */ /** \ingroup poll -- cgit v1.2.1