267 lines
9.3 KiB
Diff
267 lines
9.3 KiB
Diff
From 9db8a316a880caddf82227f69d7a8607fb674146 Mon Sep 17 00:00:00 2001
|
|
From: Linus Walleij <linus.walleij@stericsson.com>
|
|
Date: Wed, 19 Jan 2011 19:20:34 +0100
|
|
Subject: [PATCH] Fixup device OS descriptor probe code
|
|
|
|
This was to dangerous, so now we only probe:
|
|
|
|
- Devices that are of known classes to conatin MTP extensions:
|
|
COMM, PTP, CUSTOM and per-interface.
|
|
- Unless the device is CUSTOM, it needs to contain atleast one
|
|
CUSTOM interface.
|
|
- Clear halt on EP 0 after probe if it fails with error.
|
|
|
|
Signed-off-by: Linus Walleij <triad@df.lth.se>
|
|
---
|
|
src/libusb-glue.c | 208 +++++++++++++++++++++++++++++++----------------------
|
|
1 files changed, 121 insertions(+), 87 deletions(-)
|
|
|
|
diff --git a/src/libusb-glue.c b/src/libusb-glue.c
|
|
index ea22384..ca8c47d 100644
|
|
--- a/src/libusb-glue.c
|
|
+++ b/src/libusb-glue.c
|
|
@@ -229,13 +229,18 @@ static int probe_device_descriptor(struct usb_device *dev, FILE *dumpfile)
|
|
unsigned char buf[1024], cmd;
|
|
int i;
|
|
int ret;
|
|
+ /* This is to indicate if we find some vendor interface */
|
|
+ int found_vendor_spec_interface = 0;
|
|
|
|
/*
|
|
- * Don't examine hubs or HID devices, no point in that.
|
|
- * (Some Kensington mice really don't like this.)
|
|
+ * Don't examine devices that are not likely to
|
|
+ * contain any MTP interface, update this the day
|
|
+ * you find some weird combination...
|
|
*/
|
|
- if (dev->descriptor.bDeviceClass == USB_CLASS_HUB ||
|
|
- dev->descriptor.bDeviceClass == USB_CLASS_HID) {
|
|
+ if (dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE &&
|
|
+ dev->descriptor.bDeviceClass != USB_CLASS_COMM &&
|
|
+ dev->descriptor.bDeviceClass != USB_CLASS_PTP &&
|
|
+ dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
|
|
return 0;
|
|
}
|
|
|
|
@@ -270,6 +275,15 @@ static int probe_device_descriptor(struct usb_device *dev, FILE *dumpfile)
|
|
&dev->config[i].interface[j].altsetting[k];
|
|
|
|
/*
|
|
+ * We only want to probe for the OS descriptor if the
|
|
+ * device is USB_CLASS_VENDOR_SPEC or one of the interfaces
|
|
+ * in it is, so flag if we find an interface like this.
|
|
+ */
|
|
+ if (intf->bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
|
|
+ found_vendor_spec_interface = 1;
|
|
+ }
|
|
+
|
|
+ /*
|
|
* Check for Still Image Capture class with PIMA 15740 protocol,
|
|
* also known as PTP
|
|
*/
|
|
@@ -329,98 +343,118 @@ static int probe_device_descriptor(struct usb_device *dev, FILE *dumpfile)
|
|
LIBMTP_INFO("dev->config is NULL in probe_device_descriptor yet dev->descriptor.bNumConfigurations > 0\n");
|
|
}
|
|
|
|
- /* Read the special descriptor */
|
|
- ret = usb_get_descriptor(devh, 0x03, 0xee, buf, sizeof(buf));
|
|
+ /*
|
|
+ * Only probe for OS descriptor if the device is vendor specific
|
|
+ * or one of the interfaces found is.
|
|
+ */
|
|
+ if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC ||
|
|
+ found_vendor_spec_interface) {
|
|
|
|
- // Dump it, if requested
|
|
- if (dumpfile != NULL && ret > 0) {
|
|
- fprintf(dumpfile, "Microsoft device descriptor 0xee:\n");
|
|
- data_dump_ascii(dumpfile, buf, ret, 16);
|
|
- }
|
|
+ /* Read the special descriptor */
|
|
+ ret = usb_get_descriptor(devh, 0x03, 0xee, buf, sizeof(buf));
|
|
|
|
- /* Check if descriptor length is at least 10 bytes */
|
|
- if (ret < 10) {
|
|
- usb_close(devh);
|
|
- return 0;
|
|
- }
|
|
+ /*
|
|
+ * If something failed we're probably stalled to we need
|
|
+ * to clear the stall off the endpoint and say this is not
|
|
+ * MTP.
|
|
+ */
|
|
+ if (ret < 0) {
|
|
+ /* EP0 is the default control endpoint */
|
|
+ usb_clear_halt(devh, 0);
|
|
+ usb_close(devh);
|
|
+ return 0;
|
|
+ }
|
|
|
|
- /* Check if this device has a Microsoft Descriptor */
|
|
- if (!((buf[2] == 'M') && (buf[4] == 'S') &&
|
|
- (buf[6] == 'F') && (buf[8] == 'T'))) {
|
|
- usb_close(devh);
|
|
- return 0;
|
|
- }
|
|
+ // Dump it, if requested
|
|
+ if (dumpfile != NULL && ret > 0) {
|
|
+ fprintf(dumpfile, "Microsoft device descriptor 0xee:\n");
|
|
+ data_dump_ascii(dumpfile, buf, ret, 16);
|
|
+ }
|
|
|
|
- /* Check if device responds to control message 1 or if there is an error */
|
|
- cmd = buf[16];
|
|
- ret = usb_control_msg (devh,
|
|
- USB_ENDPOINT_IN | USB_RECIP_DEVICE | USB_TYPE_VENDOR,
|
|
- cmd,
|
|
- 0,
|
|
- 4,
|
|
- (char *) buf,
|
|
- sizeof(buf),
|
|
- USB_TIMEOUT_DEFAULT);
|
|
-
|
|
- // Dump it, if requested
|
|
- if (dumpfile != NULL && ret > 0) {
|
|
- fprintf(dumpfile, "Microsoft device response to control message 1, CMD 0x%02x:\n", cmd);
|
|
- data_dump_ascii(dumpfile, buf, ret, 16);
|
|
- }
|
|
+ /* Check if descriptor length is at least 10 bytes */
|
|
+ if (ret < 10) {
|
|
+ usb_close(devh);
|
|
+ return 0;
|
|
+ }
|
|
|
|
- /* If this is true, the device either isn't MTP or there was an error */
|
|
- if (ret <= 0x15) {
|
|
- /* TODO: If there was an error, flag it and let the user know somehow */
|
|
- /* if(ret == -1) {} */
|
|
- usb_close(devh);
|
|
- return 0;
|
|
- }
|
|
+ /* Check if this device has a Microsoft Descriptor */
|
|
+ if (!((buf[2] == 'M') && (buf[4] == 'S') &&
|
|
+ (buf[6] == 'F') && (buf[8] == 'T'))) {
|
|
+ usb_close(devh);
|
|
+ return 0;
|
|
+ }
|
|
|
|
- /* Check if device is MTP or if it is something like a USB Mass Storage
|
|
- device with Janus DRM support */
|
|
- if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) {
|
|
- usb_close(devh);
|
|
- return 0;
|
|
- }
|
|
+ /* Check if device responds to control message 1 or if there is an error */
|
|
+ cmd = buf[16];
|
|
+ ret = usb_control_msg (devh,
|
|
+ USB_ENDPOINT_IN | USB_RECIP_DEVICE | USB_TYPE_VENDOR,
|
|
+ cmd,
|
|
+ 0,
|
|
+ 4,
|
|
+ (char *) buf,
|
|
+ sizeof(buf),
|
|
+ USB_TIMEOUT_DEFAULT);
|
|
+
|
|
+ // Dump it, if requested
|
|
+ if (dumpfile != NULL && ret > 0) {
|
|
+ fprintf(dumpfile, "Microsoft device response to control message 1, CMD 0x%02x:\n", cmd);
|
|
+ data_dump_ascii(dumpfile, buf, ret, 16);
|
|
+ }
|
|
|
|
- /* After this point we are probably dealing with an MTP device */
|
|
+ /* If this is true, the device either isn't MTP or there was an error */
|
|
+ if (ret <= 0x15) {
|
|
+ /* TODO: If there was an error, flag it and let the user know somehow */
|
|
+ /* if(ret == -1) {} */
|
|
+ usb_close(devh);
|
|
+ return 0;
|
|
+ }
|
|
|
|
- /*
|
|
- * Check if device responds to control message 2, which is
|
|
- * the extended device parameters. Most devices will just
|
|
- * respond with a copy of the same message as for the first
|
|
- * message, some respond with zero-length (which is OK)
|
|
- * and some with pure garbage. We're not parsing the result
|
|
- * so this is not very important.
|
|
- */
|
|
- ret = usb_control_msg (devh,
|
|
- USB_ENDPOINT_IN | USB_RECIP_DEVICE | USB_TYPE_VENDOR,
|
|
- cmd,
|
|
- 0,
|
|
- 5,
|
|
- (char *) buf,
|
|
- sizeof(buf),
|
|
- USB_TIMEOUT_DEFAULT);
|
|
-
|
|
- // Dump it, if requested
|
|
- if (dumpfile != NULL && ret > 0) {
|
|
- fprintf(dumpfile, "Microsoft device response to control message 2, CMD 0x%02x:\n", cmd);
|
|
- data_dump_ascii(dumpfile, buf, ret, 16);
|
|
- }
|
|
+ /* Check if device is MTP or if it is something like a USB Mass Storage
|
|
+ device with Janus DRM support */
|
|
+ if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) {
|
|
+ usb_close(devh);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* After this point we are probably dealing with an MTP device */
|
|
+
|
|
+ /*
|
|
+ * Check if device responds to control message 2, which is
|
|
+ * the extended device parameters. Most devices will just
|
|
+ * respond with a copy of the same message as for the first
|
|
+ * message, some respond with zero-length (which is OK)
|
|
+ * and some with pure garbage. We're not parsing the result
|
|
+ * so this is not very important.
|
|
+ */
|
|
+ ret = usb_control_msg (devh,
|
|
+ USB_ENDPOINT_IN | USB_RECIP_DEVICE | USB_TYPE_VENDOR,
|
|
+ cmd,
|
|
+ 0,
|
|
+ 5,
|
|
+ (char *) buf,
|
|
+ sizeof(buf),
|
|
+ USB_TIMEOUT_DEFAULT);
|
|
+
|
|
+ // Dump it, if requested
|
|
+ if (dumpfile != NULL && ret > 0) {
|
|
+ fprintf(dumpfile, "Microsoft device response to control message 2, CMD 0x%02x:\n", cmd);
|
|
+ data_dump_ascii(dumpfile, buf, ret, 16);
|
|
+ }
|
|
|
|
- /* If this is true, the device errored against control message 2 */
|
|
- if (ret == -1) {
|
|
- /* TODO: Implement callback function to let managing program know there
|
|
- was a problem, along with description of the problem */
|
|
- LIBMTP_ERROR("Potential MTP Device with VendorID:%04x and "
|
|
- "ProductID:%04x encountered an error responding to "
|
|
- "control message 2.\n"
|
|
- "Problems may arrise but continuing\n",
|
|
- dev->descriptor.idVendor, dev->descriptor.idProduct);
|
|
- } else if (dumpfile != NULL && ret == 0) {
|
|
- fprintf(dumpfile, "Zero-length response to control message 2 (OK)\n");
|
|
- } else if (dumpfile != NULL) {
|
|
- fprintf(dumpfile, "Device responds to control message 2 with some data.\n");
|
|
+ /* If this is true, the device errored against control message 2 */
|
|
+ if (ret == -1) {
|
|
+ /* TODO: Implement callback function to let managing program know there
|
|
+ was a problem, along with description of the problem */
|
|
+ LIBMTP_ERROR("Potential MTP Device with VendorID:%04x and "
|
|
+ "ProductID:%04x encountered an error responding to "
|
|
+ "control message 2.\n"
|
|
+ "Problems may arrise but continuing\n",
|
|
+ dev->descriptor.idVendor, dev->descriptor.idProduct);
|
|
+ } else if (dumpfile != NULL && ret == 0) {
|
|
+ fprintf(dumpfile, "Zero-length response to control message 2 (OK)\n");
|
|
+ } else if (dumpfile != NULL) {
|
|
+ fprintf(dumpfile, "Device responds to control message 2 with some data.\n");
|
|
+ }
|
|
}
|
|
|
|
/* Close the USB device handle */
|
|
--
|
|
1.7.3.4
|
|
|