Index: patches/13_cherrypick_15d18e31.patch |
=================================================================== |
--- patches/13_cherrypick_15d18e31.patch (revision 0) |
+++ patches/13_cherrypick_15d18e31.patch (revision 0) |
@@ -0,0 +1,351 @@ |
+Index: src/libusb-glue.h |
+=================================================================== |
+--- src/libusb-glue.h (revision 162277) |
++++ src/libusb-glue.h (working copy) |
+@@ -3,7 +3,7 @@ |
+ * Low-level USB interface glue towards libusb. |
+ * |
+ * Copyright (C) 2005-2007 Richard A. Low <richard@wentnet.com> |
+- * Copyright (C) 2005-2011 Linus Walleij <triad@df.lth.se> |
++ * Copyright (C) 2005-2012 Linus Walleij <triad@df.lth.se> |
+ * Copyright (C) 2006-2011 Marcus Meissner |
+ * Copyright (C) 2007 Ted Bullock |
+ * Copyright (C) 2008 Chris Bagwell <chris@cnpbagwell.com> |
+@@ -91,7 +91,9 @@ |
+ #ifdef HAVE_LIBOPENUSB |
+ openusb_dev_handle_t* handle; |
+ #endif |
++ uint8_t config; |
+ uint8_t interface; |
++ uint8_t altsetting; |
+ int inep; |
+ int inep_maxpacket; |
+ int outep; |
+Index: src/libusb1-glue.c |
+=================================================================== |
+--- src/libusb1-glue.c (revision 162277) |
++++ src/libusb1-glue.c (working copy) |
+@@ -87,7 +87,9 @@ |
+ static LIBMTP_error_number_t init_usb(); |
+ static void close_usb(PTP_USB* ptp_usb); |
+ static int find_interface_and_endpoints(libusb_device *dev, |
++ uint8_t *conf, |
+ uint8_t *interface, |
++ uint8_t *altsetting, |
+ int* inep, |
+ int* inep_maxpacket, |
+ int* outep, |
+@@ -297,6 +299,7 @@ |
+ && intf->bInterfaceSubClass == 0x01 |
+ && intf->bInterfaceProtocol == 0x01) { |
+ if (dumpfile != NULL) { |
++ fprintf(dumpfile, "Configuration %d, interface %d, altsetting %d:\n", i, j, k); |
+ fprintf(dumpfile, " Found PTP device, check vendor " |
+ "extension...\n"); |
+ } |
+@@ -321,7 +324,7 @@ |
+ fprintf(dumpfile, " Interface description contains the string \"MTP\"\n"); |
+ fprintf(dumpfile, " Device recognized as MTP, no further probing.\n"); |
+ } |
+- libusb_free_config_descriptor (config); |
++ libusb_free_config_descriptor(config); |
+ libusb_close(devh); |
+ return 1; |
+ } |
+@@ -334,13 +337,14 @@ |
+ if (config->interface[j].altsetting[k].bInterfaceClass != |
+ LIBUSB_CLASS_MASS_STORAGE) { |
+ LIBMTP_INFO("avoid probing device using attached kernel interface\n"); |
+- libusb_free_config_descriptor (config); |
++ libusb_free_config_descriptor(config); |
+ return 0; |
+ } |
+ } |
+ } |
+- } |
+- } |
++ } |
++ libusb_free_config_descriptor(config); |
++ } |
+ |
+ /* |
+ * Only probe for OS descriptor if the device is vendor specific |
+@@ -1623,11 +1627,12 @@ |
+ return PTP_RC_OK; |
+ } |
+ |
+-static int init_ptp_usb (PTPParams* params, PTP_USB* ptp_usb, libusb_device* dev) |
++static int init_ptp_usb(PTPParams* params, PTP_USB* ptp_usb, libusb_device* dev) |
+ { |
+ libusb_device_handle *device_handle; |
+ unsigned char buf[255]; |
+ int ret, usbresult; |
++ struct libusb_config_descriptor *config; |
+ |
+ params->sendreq_func=ptp_usb_sendreq; |
+ params->senddata_func=ptp_usb_senddata; |
+@@ -1646,50 +1651,81 @@ |
+ |
+ ret = libusb_open(dev, &device_handle); |
+ if (ret != LIBUSB_SUCCESS) { |
+- perror("usb_open()"); |
++ perror("libusb_open() failed!"); |
+ return -1; |
+ } |
+ ptp_usb->handle = device_handle; |
++ |
+ /* |
+ * If this device is known to be wrongfully claimed by other kernel |
+ * drivers (such as mass storage), then try to unload it to make it |
+ * accessible from user space. |
+ */ |
+ if (FLAG_UNLOAD_DRIVER(ptp_usb) && |
+- libusb_kernel_driver_active (device_handle, ptp_usb->interface) |
++ libusb_kernel_driver_active(device_handle, ptp_usb->interface) |
+ ) { |
+- if (LIBUSB_SUCCESS != libusb_detach_kernel_driver (device_handle, ptp_usb->interface)) { |
+- return -1; |
++ if (LIBUSB_SUCCESS != libusb_detach_kernel_driver(device_handle, ptp_usb->interface)) { |
++ perror("libusb_detach_kernel_driver() failed, continuing anyway..."); |
+ } |
+ } |
+-#ifdef __WIN32__ |
+- // Only needed on Windows, and cause problems on other platforms. |
+- if (libusb_set_configuration(device_handle, dev->config->bConfigurationValue)) { |
+- perror("usb_set_configuration()"); |
++ |
++ /* |
++ * Check if the config is set to something else than what we want |
++ * to use. Only set the configuration if we absolutely have to. |
++ * Also do not bail out if we fail. |
++ */ |
++ ret = libusb_get_active_config_descriptor(dev, &config); |
++ if (ret != LIBUSB_SUCCESS) { |
++ perror("libusb_get_active_config_descriptor(1) failed"); |
+ return -1; |
+ } |
+-#endif |
+- // It seems like on kernel 2.6.31 if we already have it open on another |
+- // pthread in our app, we'll get an error if we try to claim it again, |
+- // but that error is harmless because our process already claimed the interface |
++ if (config->bConfigurationValue != ptp_usb->config) { |
++ fprintf(stderr, "desired configuration different from current, trying to set configuration\n"); |
++ if (libusb_set_configuration(device_handle, ptp_usb->config)) { |
++ perror("libusb_set_configuration() failed, continuing anyway..."); |
++ } |
++ /* Re-fetch the config descriptor if we changed */ |
++ libusb_free_config_descriptor(config); |
++ ret = libusb_get_active_config_descriptor(dev, &config); |
++ if (ret != LIBUSB_SUCCESS) { |
++ perror("libusb_get_active_config_descriptor(2) failed"); |
++ return -1; |
++ } |
++ } |
++ |
++ /* |
++ * It seems like on kernel 2.6.31 if we already have it open on another |
++ * pthread in our app, we'll get an error if we try to claim it again, |
++ * but that error is harmless because our process already claimed the interface |
++ */ |
+ usbresult = libusb_claim_interface(device_handle, ptp_usb->interface); |
+ |
+ if (usbresult != 0) |
+- fprintf(stderr, "ignoring usb_claim_interface = %d", usbresult); |
++ fprintf(stderr, "ignoring libusb_claim_interface() = %d", usbresult); |
+ |
+- // FIXME : Discovered in the Barry project |
+- // kernels >= 2.6.28 don't set the interface the same way as |
+- // previous versions did, and the Blackberry gets confused |
+- // if it isn't explicitly set |
+- // See above, same issue with pthreads means that if this fails it is not |
+- // fatal |
+- // However, this causes problems on Macs so disable here |
++ /* |
++ * If the altsetting is set to something different than we want, switch |
++ * it. |
++ * |
++ * FIXME: this seems to cause trouble on the Mac:s so disable it. Retry |
++ * this on the Mac now that it only sets this when the altsetting differs. |
++ */ |
+ #ifndef __APPLE__ |
+- usbresult = libusb_set_interface_alt_setting(device_handle, ptp_usb->interface, 0); |
+- if (usbresult) |
+- fprintf(stderr, "ignoring usb_claim_interface = %d", usbresult); |
++#if 0 /* Disable this always, no idea on how to handle it */ |
++ if (config->interface[].altsetting[].bAlternateSetting != |
++ ptp_usb->altsetting) { |
++ fprintf(stderr, "desired altsetting different from current, trying to set altsetting\n"); |
++ usbresult = libusb_set_interface_alt_setting(device_handle, |
++ ptp_usb->interface, |
++ ptp_usb->altsetting); |
++ if (usbresult != 0) |
++ fprintf(stderr, "ignoring libusb_set_interface_alt_setting() = %d\n", usbresult); |
++ } |
+ #endif |
++#endif |
+ |
++ libusb_free_config_descriptor(config); |
++ |
+ if (FLAG_SWITCH_MODE_BLACKBERRY(ptp_usb)) { |
+ int ret; |
+ |
+@@ -1823,76 +1859,88 @@ |
+ * Self-explanatory? |
+ */ |
+ static int find_interface_and_endpoints(libusb_device *dev, |
++ uint8_t *conf, |
+ uint8_t *interface, |
++ uint8_t *altsetting, |
+ int* inep, |
+ int* inep_maxpacket, |
+ int* outep, |
+ int *outep_maxpacket, |
+ int* intep) |
+ { |
+- int i, ret; |
++ uint8_t i, ret; |
+ struct libusb_device_descriptor desc; |
+ |
+- ret = libusb_get_device_descriptor (dev, &desc); |
+- if (ret != LIBUSB_SUCCESS) return -1; |
++ ret = libusb_get_device_descriptor(dev, &desc); |
++ if (ret != LIBUSB_SUCCESS) |
++ return -1; |
+ |
+ // Loop over the device configurations |
+ for (i = 0; i < desc.bNumConfigurations; i++) { |
+ uint8_t j; |
+ struct libusb_config_descriptor *config; |
+ |
+- ret = libusb_get_config_descriptor (dev, i, &config); |
++ ret = libusb_get_config_descriptor(dev, i, &config); |
++ if (ret != 0) |
++ continue; |
++ |
++ *conf = config->bConfigurationValue; |
++ |
+ if (ret != LIBUSB_SUCCESS) continue; |
+ // Loop over each configurations interfaces |
+ for (j = 0; j < config->bNumInterfaces; j++) { |
+- uint8_t k; |
++ uint8_t k, l; |
+ uint8_t no_ep; |
+ int found_inep = 0; |
+ int found_outep = 0; |
+ int found_intep = 0; |
+ const struct libusb_endpoint_descriptor *ep; |
+ |
+- // MTP devices shall have 3 endpoints, ignore those interfaces |
+- // that haven't. |
+- no_ep = config->interface[j].altsetting->bNumEndpoints; |
+- if (no_ep != 3) |
+- continue; |
++ // Inspect the altsettings of this interface... |
++ for (k = 0; k < config->interface[j].num_altsetting; k++) { |
+ |
+- *interface = config->interface[j].altsetting->bInterfaceNumber; |
+- ep = config->interface[j].altsetting->endpoint; |
++ // MTP devices shall have 3 endpoints, ignore those interfaces |
++ // that haven't. |
++ no_ep = config->interface[j].altsetting[k].bNumEndpoints; |
++ if (no_ep != 3) |
++ continue; |
+ |
+- // Loop over the three endpoints to locate two bulk and |
+- // one interrupt endpoint and FAIL if we cannot, and continue. |
+- for (k = 0; k < no_ep; k++) { |
+- if (ep[k].bmAttributes == LIBUSB_TRANSFER_TYPE_BULK) { |
+- if ((ep[k].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == |
+- LIBUSB_ENDPOINT_DIR_MASK) { |
+- *inep = ep[k].bEndpointAddress; |
+- *inep_maxpacket = ep[k].wMaxPacketSize; |
+- found_inep = 1; |
++ *interface = config->interface[j].altsetting[k].bInterfaceNumber; |
++ *altsetting = config->interface[j].altsetting[k].bAlternateSetting; |
++ ep = config->interface[j].altsetting[k].endpoint; |
++ |
++ // Loop over the three endpoints to locate two bulk and |
++ // one interrupt endpoint and FAIL if we cannot, and continue. |
++ for (l = 0; l < no_ep; l++) { |
++ if (ep[l].bmAttributes == LIBUSB_TRANSFER_TYPE_BULK) { |
++ if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == |
++ LIBUSB_ENDPOINT_DIR_MASK) { |
++ *inep = ep[l].bEndpointAddress; |
++ *inep_maxpacket = ep[l].wMaxPacketSize; |
++ found_inep = 1; |
++ } |
++ if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == 0) { |
++ *outep = ep[l].bEndpointAddress; |
++ *outep_maxpacket = ep[l].wMaxPacketSize; |
++ found_outep = 1; |
++ } |
++ } else if (ep[l].bmAttributes == LIBUSB_TRANSFER_TYPE_INTERRUPT) { |
++ if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == |
++ LIBUSB_ENDPOINT_DIR_MASK) { |
++ *intep = ep[l].bEndpointAddress; |
++ found_intep = 1; |
++ } |
+ } |
+- if ((ep[k].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == 0) { |
+- *outep = ep[k].bEndpointAddress; |
+- *outep_maxpacket = ep[k].wMaxPacketSize; |
+- found_outep = 1; |
+- } |
+- } else if (ep[k].bmAttributes == LIBUSB_TRANSFER_TYPE_INTERRUPT) { |
+- if ((ep[k].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == |
+- LIBUSB_ENDPOINT_DIR_MASK) { |
+- *intep = ep[k].bEndpointAddress; |
+- found_intep = 1; |
+- } |
+ } |
+- } |
+- if (found_inep && found_outep && found_intep) { |
+- libusb_free_config_descriptor (config); |
+- // We assigned the endpoints so return here. |
+- return 0; |
+- } |
+- // Else loop to next interface/config |
+- } |
+- libusb_free_config_descriptor (config); |
+- } |
++ if (found_inep && found_outep && found_intep) { |
++ libusb_free_config_descriptor(config); |
++ // We assigned the endpoints so return here. |
++ return 0; |
++ } |
++ } // Next altsetting |
++ } // Next interface |
++ libusb_free_config_descriptor(config); |
++ } // Next config |
+ return -1; |
+ } |
+ |
+@@ -1921,14 +1969,14 @@ |
+ if (init_usb_ret != LIBMTP_ERROR_NONE) |
+ return init_usb_ret; |
+ |
+- nrofdevs = libusb_get_device_list (NULL, &devs); |
++ nrofdevs = libusb_get_device_list(NULL, &devs); |
+ for (i = 0; i < nrofdevs ; i++) { |
+- if (libusb_get_bus_number (devs[i]) != device->bus_location) |
++ if (libusb_get_bus_number(devs[i]) != device->bus_location) |
+ continue; |
+- if (libusb_get_device_address (devs[i]) != device->devnum) |
++ if (libusb_get_device_address(devs[i]) != device->devnum) |
+ continue; |
+ |
+- ret = libusb_get_device_descriptor (devs[i], &desc); |
++ ret = libusb_get_device_descriptor(devs[i], &desc); |
+ if (ret != LIBUSB_SUCCESS) continue; |
+ |
+ if(desc.idVendor == device->device_entry.vendor_id && |
+@@ -1967,7 +2015,9 @@ |
+ |
+ /* Assign interface and endpoints to usbinfo... */ |
+ err = find_interface_and_endpoints(ldevice, |
++ &ptp_usb->config, |
+ &ptp_usb->interface, |
++ &ptp_usb->altsetting, |
+ &ptp_usb->inep, |
+ &ptp_usb->inep_maxpacket, |
+ &ptp_usb->outep, |