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 |