OLD | NEW |
(Empty) | |
| 1 Index: src/libusb-glue.h |
| 2 =================================================================== |
| 3 --- src/libusb-glue.h (revision 162277) |
| 4 +++ src/libusb-glue.h (working copy) |
| 5 @@ -3,7 +3,7 @@ |
| 6 * Low-level USB interface glue towards libusb. |
| 7 * |
| 8 * Copyright (C) 2005-2007 Richard A. Low <richard@wentnet.com> |
| 9 - * Copyright (C) 2005-2011 Linus Walleij <triad@df.lth.se> |
| 10 + * Copyright (C) 2005-2012 Linus Walleij <triad@df.lth.se> |
| 11 * Copyright (C) 2006-2011 Marcus Meissner |
| 12 * Copyright (C) 2007 Ted Bullock |
| 13 * Copyright (C) 2008 Chris Bagwell <chris@cnpbagwell.com> |
| 14 @@ -91,7 +91,9 @@ |
| 15 #ifdef HAVE_LIBOPENUSB |
| 16 openusb_dev_handle_t* handle; |
| 17 #endif |
| 18 + uint8_t config; |
| 19 uint8_t interface; |
| 20 + uint8_t altsetting; |
| 21 int inep; |
| 22 int inep_maxpacket; |
| 23 int outep; |
| 24 Index: src/libusb1-glue.c |
| 25 =================================================================== |
| 26 --- src/libusb1-glue.c (revision 162277) |
| 27 +++ src/libusb1-glue.c (working copy) |
| 28 @@ -87,7 +87,9 @@ |
| 29 static LIBMTP_error_number_t init_usb(); |
| 30 static void close_usb(PTP_USB* ptp_usb); |
| 31 static int find_interface_and_endpoints(libusb_device *dev, |
| 32 + uint8_t *conf, |
| 33 uint8_t *interface, |
| 34 + uint8_t *altsetting, |
| 35 int* inep, |
| 36 int* inep_maxpacket, |
| 37 int* outep, |
| 38 @@ -297,6 +299,7 @@ |
| 39 && intf->bInterfaceSubClass == 0x01 |
| 40 && intf->bInterfaceProtocol == 0x01) { |
| 41 if (dumpfile != NULL) { |
| 42 + fprintf(dumpfile, "Configuration %d, interface %d, altsetting %d:
\n", i, j, k); |
| 43 fprintf(dumpfile, " Found PTP device, check vendor " |
| 44 "extension...\n"); |
| 45 } |
| 46 @@ -321,7 +324,7 @@ |
| 47 fprintf(dumpfile, " Interface description contains the string \"
MTP\"\n"); |
| 48 fprintf(dumpfile, " Device recognized as MTP, no further probing
.\n"); |
| 49 } |
| 50 - libusb_free_config_descriptor (config); |
| 51 + libusb_free_config_descriptor(config); |
| 52 libusb_close(devh); |
| 53 return 1; |
| 54 } |
| 55 @@ -334,13 +337,14 @@ |
| 56 if (config->interface[j].altsetting[k].bInterfaceClass != |
| 57 LIBUSB_CLASS_MASS_STORAGE) { |
| 58 LIBMTP_INFO("avoid probing device using attached kernel interface\
n"); |
| 59 - libusb_free_config_descriptor (config); |
| 60 + libusb_free_config_descriptor(config); |
| 61 return 0; |
| 62 } |
| 63 } |
| 64 } |
| 65 - } |
| 66 - } |
| 67 + } |
| 68 + libusb_free_config_descriptor(config); |
| 69 + } |
| 70 |
| 71 /* |
| 72 * Only probe for OS descriptor if the device is vendor specific |
| 73 @@ -1623,11 +1627,12 @@ |
| 74 return PTP_RC_OK; |
| 75 } |
| 76 |
| 77 -static int init_ptp_usb (PTPParams* params, PTP_USB* ptp_usb, libusb_device* de
v) |
| 78 +static int init_ptp_usb(PTPParams* params, PTP_USB* ptp_usb, libusb_device* dev
) |
| 79 { |
| 80 libusb_device_handle *device_handle; |
| 81 unsigned char buf[255]; |
| 82 int ret, usbresult; |
| 83 + struct libusb_config_descriptor *config; |
| 84 |
| 85 params->sendreq_func=ptp_usb_sendreq; |
| 86 params->senddata_func=ptp_usb_senddata; |
| 87 @@ -1646,50 +1651,81 @@ |
| 88 |
| 89 ret = libusb_open(dev, &device_handle); |
| 90 if (ret != LIBUSB_SUCCESS) { |
| 91 - perror("usb_open()"); |
| 92 + perror("libusb_open() failed!"); |
| 93 return -1; |
| 94 } |
| 95 ptp_usb->handle = device_handle; |
| 96 + |
| 97 /* |
| 98 * If this device is known to be wrongfully claimed by other kernel |
| 99 * drivers (such as mass storage), then try to unload it to make it |
| 100 * accessible from user space. |
| 101 */ |
| 102 if (FLAG_UNLOAD_DRIVER(ptp_usb) && |
| 103 - libusb_kernel_driver_active (device_handle, ptp_usb->interface) |
| 104 + libusb_kernel_driver_active(device_handle, ptp_usb->interface) |
| 105 ) { |
| 106 - if (LIBUSB_SUCCESS != libusb_detach_kernel_driver (device_handle, ptp_usb
->interface)) { |
| 107 - return -1; |
| 108 + if (LIBUSB_SUCCESS != libusb_detach_kernel_driver(device_handle, ptp_usb-
>interface)) { |
| 109 + perror("libusb_detach_kernel_driver() failed, continuing anyway..."); |
| 110 } |
| 111 } |
| 112 -#ifdef __WIN32__ |
| 113 - // Only needed on Windows, and cause problems on other platforms. |
| 114 - if (libusb_set_configuration(device_handle, dev->config->bConfigurationValue)
) { |
| 115 - perror("usb_set_configuration()"); |
| 116 + |
| 117 + /* |
| 118 + * Check if the config is set to something else than what we want |
| 119 + * to use. Only set the configuration if we absolutely have to. |
| 120 + * Also do not bail out if we fail. |
| 121 + */ |
| 122 + ret = libusb_get_active_config_descriptor(dev, &config); |
| 123 + if (ret != LIBUSB_SUCCESS) { |
| 124 + perror("libusb_get_active_config_descriptor(1) failed"); |
| 125 return -1; |
| 126 } |
| 127 -#endif |
| 128 - // It seems like on kernel 2.6.31 if we already have it open on another |
| 129 - // pthread in our app, we'll get an error if we try to claim it again, |
| 130 - // but that error is harmless because our process already claimed the interfa
ce |
| 131 + if (config->bConfigurationValue != ptp_usb->config) { |
| 132 + fprintf(stderr, "desired configuration different from current, trying to se
t configuration\n"); |
| 133 + if (libusb_set_configuration(device_handle, ptp_usb->config)) { |
| 134 + perror("libusb_set_configuration() failed, continuing anyway..."); |
| 135 + } |
| 136 + /* Re-fetch the config descriptor if we changed */ |
| 137 + libusb_free_config_descriptor(config); |
| 138 + ret = libusb_get_active_config_descriptor(dev, &config); |
| 139 + if (ret != LIBUSB_SUCCESS) { |
| 140 + perror("libusb_get_active_config_descriptor(2) failed"); |
| 141 + return -1; |
| 142 + } |
| 143 + } |
| 144 + |
| 145 + /* |
| 146 + * It seems like on kernel 2.6.31 if we already have it open on another |
| 147 + * pthread in our app, we'll get an error if we try to claim it again, |
| 148 + * but that error is harmless because our process already claimed the interfa
ce |
| 149 + */ |
| 150 usbresult = libusb_claim_interface(device_handle, ptp_usb->interface); |
| 151 |
| 152 if (usbresult != 0) |
| 153 - fprintf(stderr, "ignoring usb_claim_interface = %d", usbresult); |
| 154 + fprintf(stderr, "ignoring libusb_claim_interface() = %d", usbresult); |
| 155 |
| 156 - // FIXME : Discovered in the Barry project |
| 157 - // kernels >= 2.6.28 don't set the interface the same way as |
| 158 - // previous versions did, and the Blackberry gets confused |
| 159 - // if it isn't explicitly set |
| 160 - // See above, same issue with pthreads means that if this fails it is not |
| 161 - // fatal |
| 162 - // However, this causes problems on Macs so disable here |
| 163 + /* |
| 164 + * If the altsetting is set to something different than we want, switch |
| 165 + * it. |
| 166 + * |
| 167 + * FIXME: this seems to cause trouble on the Mac:s so disable it. Retry |
| 168 + * this on the Mac now that it only sets this when the altsetting differs. |
| 169 + */ |
| 170 #ifndef __APPLE__ |
| 171 - usbresult = libusb_set_interface_alt_setting(device_handle, ptp_usb->interfac
e, 0); |
| 172 - if (usbresult) |
| 173 - fprintf(stderr, "ignoring usb_claim_interface = %d", usbresult); |
| 174 +#if 0 /* Disable this always, no idea on how to handle it */ |
| 175 + if (config->interface[].altsetting[].bAlternateSetting != |
| 176 + ptp_usb->altsetting) { |
| 177 + fprintf(stderr, "desired altsetting different from current, trying to set a
ltsetting\n"); |
| 178 + usbresult = libusb_set_interface_alt_setting(device_handle, |
| 179 + ptp_usb->interface, |
| 180 + ptp_usb->altsetting); |
| 181 + if (usbresult != 0) |
| 182 + fprintf(stderr, "ignoring libusb_set_interface_alt_setting() = %d\n", usb
result); |
| 183 + } |
| 184 #endif |
| 185 +#endif |
| 186 |
| 187 + libusb_free_config_descriptor(config); |
| 188 + |
| 189 if (FLAG_SWITCH_MODE_BLACKBERRY(ptp_usb)) { |
| 190 int ret; |
| 191 |
| 192 @@ -1823,76 +1859,88 @@ |
| 193 * Self-explanatory? |
| 194 */ |
| 195 static int find_interface_and_endpoints(libusb_device *dev, |
| 196 + uint8_t *conf, |
| 197 uint8_t *interface, |
| 198 + uint8_t *altsetting, |
| 199 int* inep, |
| 200 int* inep_maxpacket, |
| 201 int* outep, |
| 202 int *outep_maxpacket, |
| 203 int* intep) |
| 204 { |
| 205 - int i, ret; |
| 206 + uint8_t i, ret; |
| 207 struct libusb_device_descriptor desc; |
| 208 |
| 209 - ret = libusb_get_device_descriptor (dev, &desc); |
| 210 - if (ret != LIBUSB_SUCCESS) return -1; |
| 211 + ret = libusb_get_device_descriptor(dev, &desc); |
| 212 + if (ret != LIBUSB_SUCCESS) |
| 213 + return -1; |
| 214 |
| 215 // Loop over the device configurations |
| 216 for (i = 0; i < desc.bNumConfigurations; i++) { |
| 217 uint8_t j; |
| 218 struct libusb_config_descriptor *config; |
| 219 |
| 220 - ret = libusb_get_config_descriptor (dev, i, &config); |
| 221 + ret = libusb_get_config_descriptor(dev, i, &config); |
| 222 + if (ret != 0) |
| 223 + continue; |
| 224 + |
| 225 + *conf = config->bConfigurationValue; |
| 226 + |
| 227 if (ret != LIBUSB_SUCCESS) continue; |
| 228 // Loop over each configurations interfaces |
| 229 for (j = 0; j < config->bNumInterfaces; j++) { |
| 230 - uint8_t k; |
| 231 + uint8_t k, l; |
| 232 uint8_t no_ep; |
| 233 int found_inep = 0; |
| 234 int found_outep = 0; |
| 235 int found_intep = 0; |
| 236 const struct libusb_endpoint_descriptor *ep; |
| 237 |
| 238 - // MTP devices shall have 3 endpoints, ignore those interfaces |
| 239 - // that haven't. |
| 240 - no_ep = config->interface[j].altsetting->bNumEndpoints; |
| 241 - if (no_ep != 3) |
| 242 - continue; |
| 243 + // Inspect the altsettings of this interface... |
| 244 + for (k = 0; k < config->interface[j].num_altsetting; k++) { |
| 245 |
| 246 - *interface = config->interface[j].altsetting->bInterfaceNumber; |
| 247 - ep = config->interface[j].altsetting->endpoint; |
| 248 + // MTP devices shall have 3 endpoints, ignore those interfaces |
| 249 + // that haven't. |
| 250 + no_ep = config->interface[j].altsetting[k].bNumEndpoints; |
| 251 + if (no_ep != 3) |
| 252 + continue; |
| 253 |
| 254 - // Loop over the three endpoints to locate two bulk and |
| 255 - // one interrupt endpoint and FAIL if we cannot, and continue. |
| 256 - for (k = 0; k < no_ep; k++) { |
| 257 - if (ep[k].bmAttributes == LIBUSB_TRANSFER_TYPE_BULK) { |
| 258 - if ((ep[k].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == |
| 259 - LIBUSB_ENDPOINT_DIR_MASK) { |
| 260 - *inep = ep[k].bEndpointAddress; |
| 261 - *inep_maxpacket = ep[k].wMaxPacketSize; |
| 262 - found_inep = 1; |
| 263 + *interface = config->interface[j].altsetting[k].bInterfaceNumber; |
| 264 + *altsetting = config->interface[j].altsetting[k].bAlternateSetting; |
| 265 + ep = config->interface[j].altsetting[k].endpoint; |
| 266 + |
| 267 + // Loop over the three endpoints to locate two bulk and |
| 268 + // one interrupt endpoint and FAIL if we cannot, and continue. |
| 269 + for (l = 0; l < no_ep; l++) { |
| 270 + if (ep[l].bmAttributes == LIBUSB_TRANSFER_TYPE_BULK) { |
| 271 + if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == |
| 272 + LIBUSB_ENDPOINT_DIR_MASK) { |
| 273 + *inep = ep[l].bEndpointAddress; |
| 274 + *inep_maxpacket = ep[l].wMaxPacketSize; |
| 275 + found_inep = 1; |
| 276 + } |
| 277 + if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == 0) { |
| 278 + *outep = ep[l].bEndpointAddress; |
| 279 + *outep_maxpacket = ep[l].wMaxPacketSize; |
| 280 + found_outep = 1; |
| 281 + } |
| 282 + } else if (ep[l].bmAttributes == LIBUSB_TRANSFER_TYPE_INTERRUPT) { |
| 283 + if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == |
| 284 + LIBUSB_ENDPOINT_DIR_MASK) { |
| 285 + *intep = ep[l].bEndpointAddress; |
| 286 + found_intep = 1; |
| 287 + } |
| 288 } |
| 289 - if ((ep[k].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == 0) { |
| 290 - *outep = ep[k].bEndpointAddress; |
| 291 - *outep_maxpacket = ep[k].wMaxPacketSize; |
| 292 - found_outep = 1; |
| 293 - } |
| 294 - } else if (ep[k].bmAttributes == LIBUSB_TRANSFER_TYPE_INTERRUPT) { |
| 295 - if ((ep[k].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == |
| 296 - LIBUSB_ENDPOINT_DIR_MASK) { |
| 297 - *intep = ep[k].bEndpointAddress; |
| 298 - found_intep = 1; |
| 299 - } |
| 300 } |
| 301 - } |
| 302 - if (found_inep && found_outep && found_intep) { |
| 303 - libusb_free_config_descriptor (config); |
| 304 - // We assigned the endpoints so return here. |
| 305 - return 0; |
| 306 - } |
| 307 - // Else loop to next interface/config |
| 308 - } |
| 309 - libusb_free_config_descriptor (config); |
| 310 - } |
| 311 + if (found_inep && found_outep && found_intep) { |
| 312 + libusb_free_config_descriptor(config); |
| 313 + // We assigned the endpoints so return here. |
| 314 + return 0; |
| 315 + } |
| 316 + } // Next altsetting |
| 317 + } // Next interface |
| 318 + libusb_free_config_descriptor(config); |
| 319 + } // Next config |
| 320 return -1; |
| 321 } |
| 322 |
| 323 @@ -1921,14 +1969,14 @@ |
| 324 if (init_usb_ret != LIBMTP_ERROR_NONE) |
| 325 return init_usb_ret; |
| 326 |
| 327 - nrofdevs = libusb_get_device_list (NULL, &devs); |
| 328 + nrofdevs = libusb_get_device_list(NULL, &devs); |
| 329 for (i = 0; i < nrofdevs ; i++) { |
| 330 - if (libusb_get_bus_number (devs[i]) != device->bus_location) |
| 331 + if (libusb_get_bus_number(devs[i]) != device->bus_location) |
| 332 continue; |
| 333 - if (libusb_get_device_address (devs[i]) != device->devnum) |
| 334 + if (libusb_get_device_address(devs[i]) != device->devnum) |
| 335 continue; |
| 336 |
| 337 - ret = libusb_get_device_descriptor (devs[i], &desc); |
| 338 + ret = libusb_get_device_descriptor(devs[i], &desc); |
| 339 if (ret != LIBUSB_SUCCESS) continue; |
| 340 |
| 341 if(desc.idVendor == device->device_entry.vendor_id && |
| 342 @@ -1967,7 +2015,9 @@ |
| 343 |
| 344 /* Assign interface and endpoints to usbinfo... */ |
| 345 err = find_interface_and_endpoints(ldevice, |
| 346 + &ptp_usb->config, |
| 347 &ptp_usb->interface, |
| 348 + &ptp_usb->altsetting, |
| 349 &ptp_usb->inep, |
| 350 &ptp_usb->inep_maxpacket, |
| 351 &ptp_usb->outep, |
OLD | NEW |