| 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,
|
|
|