| Index: src/libusb-glue.c
|
| ===================================================================
|
| --- src/libusb-glue.c (revision 166547)
|
| +++ src/libusb-glue.c (working copy)
|
| @@ -100,16 +100,18 @@
|
| static struct usb_bus* init_usb();
|
| static void close_usb(PTP_USB* ptp_usb);
|
| static int find_interface_and_endpoints(struct usb_device *dev,
|
| + uint8_t *conf,
|
| uint8_t *interface,
|
| + uint8_t *altsetting,
|
| int* inep,
|
| int* inep_maxpacket,
|
| int* outep,
|
| int* outep_maxpacket,
|
| int* intep);
|
| static void clear_stall(PTP_USB* ptp_usb);
|
| -static int init_ptp_usb (PTPParams* params, PTP_USB* ptp_usb, struct usb_device* dev);
|
| -static short ptp_write_func (unsigned long,PTPDataHandler*,void *data,unsigned long*);
|
| -static short ptp_read_func (unsigned long,PTPDataHandler*,void *data,unsigned long*,int);
|
| +static int init_ptp_usb(PTPParams* params, PTP_USB* ptp_usb, struct usb_device* dev);
|
| +static short ptp_write_func(unsigned long,PTPDataHandler*,void *data,unsigned long*);
|
| +static short ptp_read_func(unsigned long,PTPDataHandler*,void *data,unsigned long*,int);
|
| static int usb_clear_stall_feature(PTP_USB* ptp_usb, int ep);
|
| static int usb_get_endpoint_status(PTP_USB* ptp_usb, int ep, uint16_t* status);
|
|
|
| @@ -1622,7 +1624,7 @@
|
| return PTP_RC_OK;
|
| }
|
|
|
| -static int init_ptp_usb (PTPParams* params, PTP_USB* ptp_usb, struct usb_device* dev)
|
| +static int init_ptp_usb(PTPParams* params, PTP_USB* ptp_usb, struct usb_device* dev)
|
| {
|
| usb_dev_handle *device_handle;
|
| char buf[255];
|
| @@ -1649,6 +1651,7 @@
|
| return -1;
|
| }
|
| ptp_usb->handle = device_handle;
|
| +
|
| #ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
|
| /*
|
| * If this device is known to be wrongfully claimed by other kernel
|
| @@ -1666,33 +1669,46 @@
|
| }
|
| }
|
| #endif
|
| -#ifdef __WIN32__
|
| - // Only needed on Windows, and cause problems on other platforms.
|
| - if (usb_set_configuration(device_handle, dev->config->bConfigurationValue)) {
|
| - perror("usb_set_configuration()");
|
| - return -1;
|
| +
|
| + /*
|
| + * 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.
|
| + */
|
| + if (dev->config->bConfigurationValue != ptp_usb->config) {
|
| + if (usb_set_configuration(device_handle, dev->config->bConfigurationValue)) {
|
| + perror("error in usb_set_configuration()- continuing anyway");
|
| + }
|
| }
|
| -#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
|
| +
|
| + /*
|
| + * 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 = usb_claim_interface(device_handle, (int) ptp_usb->interface);
|
|
|
| if (usbresult != 0)
|
| fprintf(stderr, "ignoring usb_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 = usb_set_altinterface(device_handle, 0);
|
| - if (usbresult)
|
| - fprintf(stderr, "ignoring usb_claim_interface = %d", usbresult);
|
| +#if 0 /* Disable this always, no idea on how to handle it */
|
| + if (dev->config->interface[].altsetting[] !=
|
| + ptp_usb->altsetting) {
|
| + fprintf(stderr, "desired altsetting different from current, trying to set altsetting\n");
|
| + usbresult = usb_set_altinterface(device_handle, 0);
|
| + if (usbresult)
|
| + fprintf(stderr, "ignoring error from usb_claim_interface = %d\n", usbresult);
|
| + }
|
| #endif
|
| +#endif
|
|
|
| if (FLAG_SWITCH_MODE_BLACKBERRY(ptp_usb)) {
|
| int ret;
|
| @@ -1827,66 +1843,75 @@
|
| * Self-explanatory?
|
| */
|
| static int find_interface_and_endpoints(struct usb_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;
|
| + uint8_t i;
|
|
|
| // Loop over the device configurations
|
| for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
|
| uint8_t j;
|
|
|
| + *conf = dev->config->bConfigurationValue;;
|
| +
|
| // Loop over each configurations interfaces
|
| for (j = 0; j < dev->config[i].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;
|
| struct usb_endpoint_descriptor *ep;
|
|
|
| - // MTP devices shall have 3 endpoints, ignore those interfaces
|
| - // that haven't.
|
| - no_ep = dev->config[i].interface[j].altsetting->bNumEndpoints;
|
| - if (no_ep != 3)
|
| - continue;
|
| + // Inspect the altsettings of this interface
|
| + for (k = 0; k < dev->config[i].interface[j].num_altsetting; k++) {
|
|
|
| - *interface = dev->config[i].interface[j].altsetting->bInterfaceNumber;
|
| - ep = dev->config[i].interface[j].altsetting->endpoint;
|
| + // MTP devices shall have 3 endpoints, ignore those interfaces
|
| + // that haven't.
|
| + no_ep = dev->config[i].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 == USB_ENDPOINT_TYPE_BULK) {
|
| - if ((ep[k].bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
|
| - USB_ENDPOINT_DIR_MASK) {
|
| - *inep = ep[k].bEndpointAddress;
|
| - *inep_maxpacket = ep[k].wMaxPacketSize;
|
| - found_inep = 1;
|
| + *interface = dev->config[i].interface[j].altsetting[k].bInterfaceNumber;
|
| + *altsetting = dev->config[i].interface[j].altsetting[k].bAlternateSetting;
|
| + ep = dev->config[i].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 == USB_ENDPOINT_TYPE_BULK) {
|
| + if ((ep[l].bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
|
| + USB_ENDPOINT_DIR_MASK) {
|
| + *inep = ep[l].bEndpointAddress;
|
| + *inep_maxpacket = ep[l].wMaxPacketSize;
|
| + found_inep = 1;
|
| + }
|
| + if ((ep[l].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == 0) {
|
| + *outep = ep[l].bEndpointAddress;
|
| + *outep_maxpacket = ep[l].wMaxPacketSize;
|
| + found_outep = 1;
|
| + }
|
| + } else if (ep[l].bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT) {
|
| + if ((ep[l].bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
|
| + USB_ENDPOINT_DIR_MASK) {
|
| + *intep = ep[l].bEndpointAddress;
|
| + found_intep = 1;
|
| + }
|
| }
|
| - if ((ep[k].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == 0) {
|
| - *outep = ep[k].bEndpointAddress;
|
| - *outep_maxpacket = ep[k].wMaxPacketSize;
|
| - found_outep = 1;
|
| - }
|
| - } else if (ep[k].bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT) {
|
| - if ((ep[k].bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
|
| - USB_ENDPOINT_DIR_MASK) {
|
| - *intep = ep[k].bEndpointAddress;
|
| - found_intep = 1;
|
| - }
|
| }
|
| - }
|
| - if (found_inep && found_outep && found_intep)
|
| - // We assigned the endpoints so return here.
|
| - return 0;
|
| - // Else loop to next interface/config
|
| - }
|
| - }
|
| + if (found_inep && found_outep && found_intep)
|
| + // We assigned the endpoints so return here.
|
| + return 0;
|
| + // Else loop to next interface/config
|
| + } /* Next altsetting */
|
| + } /* Next interface */
|
| + } /* Next config */
|
| return -1;
|
| }
|
|
|
| @@ -1954,7 +1979,9 @@
|
|
|
| /* Assign interface and endpoints to usbinfo... */
|
| err = find_interface_and_endpoints(libusb_device,
|
| + &ptp_usb->config,
|
| &ptp_usb->interface,
|
| + &ptp_usb->altsetting,
|
| &ptp_usb->inep,
|
| &ptp_usb->inep_maxpacket,
|
| &ptp_usb->outep,
|
|
|