summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2008-05-04 16:20:46 +0100
committerDaniel Drake <dsd@gentoo.org>2008-05-04 16:20:46 +0100
commit17ecfb0ecc833596c43755c80d461cddb9b3b0d7 (patch)
tree1c1f3e1e34083baa72dd8de633fe842687308008
parentbdce367d1bd8691465844b2411c85215498f517d (diff)
downloadlibusb-17ecfb0ecc833596c43755c80d461cddb9b3b0d7.tar.gz
Descriptor reading functionality
-rw-r--r--libusb/descriptor.c57
-rw-r--r--libusb/libusb.h45
2 files changed, 102 insertions, 0 deletions
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