1 /*
2  * Darwin/MacOS X Support
3  *
4  * (c) 2002-2006 Nathan Hjelm <hjelmn@users.sourceforge.net>
5  *
6  * (06/26/2006):
7  *   - Bulk functions no longer use async transfer functions.
8  * (04/17/2005):
9  *   - Lots of minor fixes.
10  *   - Endpoint table now made by claim_interface to fix a bug.
11  *   - Merged Read/Write to make modifications easier.
12  * (03/25/2005):
13  *   - Fixed a bug when using asynchronous callbacks within a multi-threaded application.
14  * (03/14/2005):
15  *   - Added an endpoint table to speed up bulk transfers.
16  * 0.1.11 (02/22/2005):
17  *   - Updated error checking in read/write routines to check completion codes.
18  *   - Updated set_configuration so that the open interface is reclaimed before completion.
19  *   - Fixed several typos.
20  * 0.1.8 (01/12/2004):
21  *   - Fixed several memory leaks.
22  *   - Readded 10.0 support
23  *   - Added support for USB fuctions defined in 10.3 and above
24  * (01/02/2003):
25  *   - Applied a patch by Philip Edelbrock <phil@edgedesign.us> that fixes a bug in usb_control_msg.
26  * (12/16/2003):
27  *   - Even better error printing.
28  *   - Devices that cannot be opened can have their interfaces opened.
29  * 0.1.6 (05/12/2002):
30  *   - Fixed problem where libusb holds resources after program completion.
31  *   - Mouse should no longer freeze up now.
32  * 0.1.2 (02/13/2002):
33  *   - Bulk functions should work properly now.
34  * 0.1.1 (02/11/2002):
35  *   - Fixed major bug (device and interface need to be released after use)
36  * 0.1.0 (01/06/2002):
37  *   - Tested driver with gphoto (works great as long as Image Capture isn't running)
38  * 0.1d  (01/04/2002):
39  *   - Implimented clear_halt and resetep
40  *   - Uploaded to CVS.
41  * 0.1b  (01/04/2002):
42  *   - Added usb_debug line to bulk read and write function.
43  * 0.1a  (01/03/2002):
44  *   - Driver mostly completed using the macosx driver I wrote for my rioutil software.
45  *
46  * Derived from Linux version by Richard Tobin.
47  * Also partly derived from BSD version.
48  *
49  * This library is covered by the LGPL, read LICENSE for details.
50  */
51 
52 #ifdef HAVE_CONFIG_H
53 #include "config.h"
54 #endif
55 
56 #include <stdlib.h>
57 #include <stdio.h>
58 #include <unistd.h>
59 
60 /* standard includes for darwin/os10 (IOKit) */
61 #include <mach/mach_port.h>
62 #include <IOKit/IOCFBundle.h>
63 #include <IOKit/usb/IOUSBLib.h>
64 #include <IOKit/IOCFPlugIn.h>
65 
66 #include "usbi.h"
67 
68 /* some defines */
69 /* IOUSBInterfaceInferface */
70 #if defined (kIOUSBInterfaceInterfaceID220)
71 
72 // #warning "libusb being compiled for 10.4 or later"
73 #define usb_interface_t IOUSBInterfaceInterface220
74 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
75 #define InterfaceVersion 220
76 
77 #elif defined (kIOUSBInterfaceInterfaceID197)
78 
79 // #warning "libusb being compiled for 10.3 or later"
80 #define usb_interface_t IOUSBInterfaceInterface197
81 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID197
82 #define InterfaceVersion 197
83 
84 #elif defined (kIOUSBInterfaceInterfaceID190)
85 
86 // #warning "libusb being compiled for 10.2 or later"
87 #define usb_interface_t IOUSBInterfaceInterface190
88 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID190
89 #define InterfaceVersion 190
90 
91 #elif defined (kIOUSBInterfaceInterfaceID182)
92 
93 // #warning "libusb being compiled for 10.1 or later"
94 #define usb_interface_t IOUSBInterfaceInterface182
95 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID182
96 #define InterfaceVersion 182
97 
98 #else
99 
100 /* No timeout functions available! Time to upgrade your os. */
101 #warning "libusb being compiled without support for timeout bulk functions! 10.0 and up"
102 #define usb_interface_t IOUSBInterfaceInterface
103 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID
104 #define LIBUSB_NO_TIMEOUT_INTERFACE
105 #define InterfaceVersion 180
106 
107 #endif
108 
109 /* IOUSBDeviceInterface */
110 #if defined (kIOUSBDeviceInterfaceID197)
111 
112 #define usb_device_t    IOUSBDeviceInterface197
113 #define DeviceInterfaceID kIOUSBDeviceInterfaceID197
114 #define DeviceVersion 197
115 
116 #elif defined (kIOUSBDeviceInterfaceID187)
117 
118 #define usb_device_t    IOUSBDeviceInterface187
119 #define DeviceInterfaceID kIOUSBDeviceInterfaceID187
120 #define DeviceVersion 187
121 
122 #elif defined (kIOUSBDeviceInterfaceID182)
123 
124 #define usb_device_t    IOUSBDeviceInterface182
125 #define DeviceInterfaceID kIOUSBDeviceInterfaceID182
126 #define DeviceVersion 182
127 
128 #else
129 
130 #define usb_device_t    IOUSBDeviceInterface
131 #define DeviceInterfaceID kIOUSBDeviceInterfaceID
132 #define LIBUSB_NO_TIMEOUT_DEVICE
133 #define LIBUSB_NO_SEIZE_DEVICE
134 #define DeviceVersion 180
135 
136 #endif
137 
138 typedef IOReturn io_return_t;
139 typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
140 typedef SInt32 s_int32_t;
141 typedef IOReturn (*rw_async_func_t)(void *self, UInt8 pipeRef, void *buf, UInt32 size,
142 				    IOAsyncCallback1 callback, void *refcon);
143 typedef IOReturn (*rw_async_to_func_t)(void *self, UInt8 pipeRef, void *buf, UInt32 size,
144 				       UInt32 noDataTimeout, UInt32 completionTimeout,
145 				       IOAsyncCallback1 callback, void *refcon);
146 
147 #if !defined(IO_OBJECT_NULL)
148 #define IO_OBJECT_NULL ((io_object_t)0)
149 #endif
150 
151 struct darwin_dev_handle {
152   usb_device_t **device;
153   usb_interface_t **interface;
154   int open;
155 
156   /* stored translation table for pipes to endpoints */
157   int num_endpoints;
158   unsigned char *endpoint_addrs;
159 };
160 
161 static IONotificationPortRef gNotifyPort;
162 static mach_port_t masterPort = MACH_PORT_NULL;
163 
darwin_cleanup(void)164 static void darwin_cleanup (void)
165 {
166   IONotificationPortDestroy(gNotifyPort);
167   mach_port_deallocate(mach_task_self(), masterPort);
168 }
169 
darwin_error_str(int result)170 static char *darwin_error_str (int result) {
171   switch (result) {
172   case kIOReturnSuccess:
173     return "no error";
174   case kIOReturnNotOpen:
175     return "device not opened for exclusive access";
176   case kIOReturnNoDevice:
177     return "no connection to an IOService";
178   case kIOUSBNoAsyncPortErr:
179     return "no async port has been opened for interface";
180   case kIOReturnExclusiveAccess:
181     return "another process has device opened for exclusive access";
182   case kIOUSBPipeStalled:
183     return "pipe is stalled";
184   case kIOReturnError:
185     return "could not establish a connection to the Darwin kernel";
186   case kIOUSBTransactionTimeout:
187     return "transaction timed out";
188   case kIOReturnBadArgument:
189     return "invalid argument";
190   case kIOReturnAborted:
191     return "transaction aborted";
192   default:
193     return "unknown error";
194   }
195 }
196 
197 /* not a valid errorno outside darwin.c */
198 #define LUSBDARWINSTALL (ELAST+1)
199 
darwin_to_errno(int result)200 static int darwin_to_errno (int result) {
201   switch (result) {
202   case kIOReturnSuccess:
203     return 0;
204   case kIOReturnNotOpen:
205     return EBADF;
206   case kIOReturnNoDevice:
207   case kIOUSBNoAsyncPortErr:
208     return ENXIO;
209   case kIOReturnExclusiveAccess:
210     return EBUSY;
211   case kIOUSBPipeStalled:
212     return LUSBDARWINSTALL;
213   case kIOReturnBadArgument:
214     return EINVAL;
215   case kIOUSBTransactionTimeout:
216     return ETIMEDOUT;
217   case kIOReturnError:
218   default:
219     return 1;
220   }
221 }
222 
usb_setup_iterator(io_iterator_t * deviceIterator)223 static int usb_setup_iterator (io_iterator_t *deviceIterator)
224 {
225   int result;
226   CFMutableDictionaryRef matchingDict;
227 
228   /* set up the matching dictionary for class IOUSBDevice and its subclasses.
229      It will be consumed by the IOServiceGetMatchingServices call */
230   if ((matchingDict = IOServiceMatching(kIOUSBDeviceClassName)) == NULL) {
231     darwin_cleanup ();
232 
233     USB_ERROR_STR(-1, "libusb/darwin.c usb_setup_iterator: Could not create a matching dictionary.\n");
234   }
235 
236   result = IOServiceGetMatchingServices(masterPort, matchingDict, deviceIterator);
237   matchingDict = NULL;
238 
239   if (result != kIOReturnSuccess)
240     USB_ERROR_STR (-darwin_to_errno (result), "libusb/darwin.c usb_setup_iterator: IOServiceGetMatchingServices: %s\n",
241 		   darwin_error_str(result));
242 
243   return 0;
244 }
245 
usb_get_next_device(io_iterator_t deviceIterator,UInt32 * locationp)246 static usb_device_t **usb_get_next_device (io_iterator_t deviceIterator, UInt32 *locationp)
247 {
248   io_cf_plugin_ref_t *plugInInterface = NULL;
249   usb_device_t **device;
250   io_service_t usbDevice;
251   long result;
252   SInt32 score;
253 
254   if (!IOIteratorIsValid (deviceIterator) || !(usbDevice = IOIteratorNext(deviceIterator)))
255     return NULL;
256 
257   result = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID,
258 					     kIOCFPlugInInterfaceID, &plugInInterface,
259 					     &score);
260 
261   result = IOObjectRelease(usbDevice);
262   if (result || !plugInInterface)
263     return NULL;
264 
265   (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID),
266 				     (LPVOID)&device);
267 
268   (*plugInInterface)->Stop(plugInInterface);
269   IODestroyPlugInInterface (plugInInterface);
270   plugInInterface = NULL;
271 
272   (*(device))->GetLocationID(device, locationp);
273 
274   return device;
275 }
276 
usb_os_open(usb_dev_handle * dev)277 int usb_os_open(usb_dev_handle *dev)
278 {
279   struct darwin_dev_handle *device;
280 
281   io_return_t result;
282   io_iterator_t deviceIterator;
283 
284   usb_device_t **darwin_device;
285 
286   UInt32 location = *((UInt32 *)dev->device->dev);
287   UInt32 dlocation;
288 
289   if (!dev)
290     USB_ERROR(-ENXIO);
291 
292   if (masterPort == MACH_PORT_NULL)
293     USB_ERROR(-EINVAL);
294 
295   device = calloc(1, sizeof(struct darwin_dev_handle));
296   if (!device)
297     USB_ERROR(-ENOMEM);
298 
299   if (usb_debug > 3)
300     fprintf(stderr, "usb_os_open: %04x:%04x\n",
301 	    dev->device->descriptor.idVendor,
302 	    dev->device->descriptor.idProduct);
303 
304   if ((result = usb_setup_iterator (&deviceIterator)) < 0)
305     return result;
306 
307   /* This port of libusb uses locations to keep track of devices. */
308   while ((darwin_device = usb_get_next_device (deviceIterator, &dlocation)) != NULL) {
309     if (dlocation == location)
310       break;
311 
312     (*darwin_device)->Release(darwin_device);
313   }
314 
315   IOObjectRelease(deviceIterator);
316   device->device = darwin_device;
317 
318   if (device->device == NULL)
319     USB_ERROR_STR (-ENOENT, "usb_os_open: %s\n", "Device not found!");
320 
321 #if !defined (LIBUSB_NO_SEIZE_DEVICE)
322   result = (*(device->device))->USBDeviceOpenSeize (device->device);
323 #else
324   /* No Seize in OS X 10.0 (Darwin 1.4) */
325   result = (*(device->device))->USBDeviceOpen (device->device);
326 #endif
327 
328   if (result != kIOReturnSuccess) {
329     switch (result) {
330     case kIOReturnExclusiveAccess:
331       if (usb_debug > 0)
332 	fprintf (stderr, "usb_os_open(USBDeviceOpenSeize): %s\n", darwin_error_str(result));
333       break;
334     default:
335       (*(device->device))->Release (device->device);
336       USB_ERROR_STR(-darwin_to_errno (result), "usb_os_open(USBDeviceOpenSeize): %s",
337 		    darwin_error_str(result));
338     }
339 
340     device->open = 0;
341   } else
342     device->open = 1;
343 
344   dev->impl_info = device;
345   dev->interface = -1;
346   dev->altsetting = -1;
347 
348   device->num_endpoints  = 0;
349   device->endpoint_addrs = NULL;
350 
351   return 0;
352 }
353 
usb_os_close(usb_dev_handle * dev)354 int usb_os_close(usb_dev_handle *dev)
355 {
356   struct darwin_dev_handle *device;
357   io_return_t result;
358 
359   if (!dev)
360     USB_ERROR(-ENXIO);
361 
362   if ((device = dev->impl_info) == NULL)
363     USB_ERROR(-ENOENT);
364 
365   usb_release_interface(dev, dev->interface);
366 
367   if (usb_debug > 3)
368     fprintf(stderr, "usb_os_close: %04x:%04x\n",
369 	    dev->device->descriptor.idVendor,
370 	    dev->device->descriptor.idProduct);
371 
372   if (device->open == 1)
373     result = (*(device->device))->USBDeviceClose(device->device);
374   else
375     result = kIOReturnSuccess;
376 
377   /* device may not need to be released, but if it has to... */
378   (*(device->device))->Release(device->device);
379 
380   if (result != kIOReturnSuccess)
381     USB_ERROR_STR(-darwin_to_errno(result), "usb_os_close(USBDeviceClose): %s", darwin_error_str(result));
382 
383   free (device);
384 
385   return 0;
386 }
387 
get_endpoints(struct darwin_dev_handle * device)388 static int get_endpoints (struct darwin_dev_handle *device)
389 {
390   io_return_t ret;
391 
392   u_int8_t numep, direction, number;
393   u_int8_t dont_care1, dont_care3;
394   u_int16_t dont_care2;
395 
396   int i;
397 
398   if (device == NULL || device->interface == NULL)
399     return -EINVAL;
400 
401   if (usb_debug > 1)
402     fprintf(stderr, "libusb/darwin.c get_endpoints: building table of endpoints.\n");
403 
404   /* retrieve the total number of endpoints on this interface */
405   ret = (*(device->interface))->GetNumEndpoints(device->interface, &numep);
406   if ( ret ) {
407     if ( usb_debug > 1 )
408       fprintf ( stderr, "get_endpoints: interface is %p\n", device->interface );
409 
410     USB_ERROR_STR ( -ret, "get_endpoints: can't get number of endpoints for interface" );
411   }
412 
413   free (device->endpoint_addrs);
414   device->endpoint_addrs = calloc (sizeof (unsigned char), numep);
415 
416   /* iterate through pipe references */
417   for (i = 1 ; i <= numep ; i++) {
418     ret = (*(device->interface))->GetPipeProperties(device->interface, i, &direction, &number,
419 						    &dont_care1, &dont_care2, &dont_care3);
420 
421     if (ret != kIOReturnSuccess) {
422       fprintf (stderr, "get_endpoints: an error occurred getting pipe information on pipe %d\n",
423 	       i );
424       USB_ERROR_STR(-darwin_to_errno(ret), "get_endpoints(GetPipeProperties): %s", darwin_error_str(ret));
425     }
426 
427     if (usb_debug > 1)
428       fprintf (stderr, "get_endpoints: Pipe %i: DIR: %i number: %i\n", i, direction, number);
429 
430     device->endpoint_addrs[i - 1] = ((direction << 7 & USB_ENDPOINT_DIR_MASK) |
431 				     (number & USB_ENDPOINT_ADDRESS_MASK));
432   }
433 
434   device->num_endpoints = numep;
435 
436   if (usb_debug > 1)
437     fprintf(stderr, "libusb/darwin.c get_endpoints: complete.\n");
438 
439   return 0;
440 }
441 
claim_interface(usb_dev_handle * dev,int interface)442 static int claim_interface (usb_dev_handle *dev, int interface)
443 {
444   io_iterator_t interface_iterator;
445   io_service_t  usbInterface = IO_OBJECT_NULL;
446   io_return_t result;
447   io_cf_plugin_ref_t *plugInInterface = NULL;
448 
449   IOUSBFindInterfaceRequest request;
450 
451   struct darwin_dev_handle *device;
452   SInt32 score;
453   int current_interface;
454 
455   device = dev->impl_info;
456 
457   request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
458   request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
459   request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
460   request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
461 
462   result = (*(device->device))->CreateInterfaceIterator(device->device, &request, &interface_iterator);
463   if (result != kIOReturnSuccess)
464     USB_ERROR_STR (-darwin_to_errno(result), "claim_interface(CreateInterfaceIterator): %s",
465 		   darwin_error_str(result));
466 
467   for ( current_interface=0 ; current_interface <= interface ; current_interface++ ) {
468     usbInterface = IOIteratorNext(interface_iterator);
469     if ( usb_debug > 3 )
470       fprintf ( stderr, "Interface %d of device is 0x%08x\n",
471 		current_interface, usbInterface );
472   }
473 
474   current_interface--;
475 
476   /* the interface iterator is no longer needed, release it */
477   IOObjectRelease(interface_iterator);
478 
479   if (!usbInterface) {
480     u_int8_t nConfig;			     /* Index of configuration to use */
481     IOUSBConfigurationDescriptorPtr configDesc; /* to describe which configuration to select */
482     /* Only a composite class device with no vendor-specific driver will
483        be configured. Otherwise, we need to do it ourselves, or there
484        will be no interfaces for the device. */
485 
486     if ( usb_debug > 3 )
487       fprintf ( stderr,"claim_interface: No interface found; selecting configuration\n" );
488 
489     result = (*(device->device))->GetNumberOfConfigurations ( device->device, &nConfig );
490     if (result != kIOReturnSuccess)
491       USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(GetNumberOfConfigurations): %s",
492 		    darwin_error_str(result));
493 
494     if (nConfig < 1)
495       USB_ERROR_STR(-ENXIO ,"claim_interface(GetNumberOfConfigurations): no configurations");
496     else if ( nConfig > 1 && usb_debug > 0 )
497       fprintf ( stderr, "claim_interface: device has more than one"
498 		" configuration, using the first (warning)\n" );
499 
500     if ( usb_debug > 3 )
501       fprintf ( stderr, "claim_interface: device has %d configuration%s\n",
502 		(int)nConfig, (nConfig>1?"s":"") );
503 
504     /* Always use the first configuration */
505     result = (*(device->device))->GetConfigurationDescriptorPtr ( (device->device), 0, &configDesc );
506     if (result != kIOReturnSuccess) {
507       if (device->open == 1) {
508         (*(device->device))->USBDeviceClose ( (device->device) );
509         (*(device->device))->Release ( (device->device) );
510       }
511 
512       USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(GetConfigurationDescriptorPtr): %s",
513 		    darwin_error_str(result));
514     } else if ( usb_debug > 3 )
515       fprintf ( stderr, "claim_interface: configuration value is %d\n",
516 		configDesc->bConfigurationValue );
517 
518     if (device->open == 1) {
519       result = (*(device->device))->SetConfiguration ( (device->device), configDesc->bConfigurationValue );
520 
521       if (result != kIOReturnSuccess) {
522 	(*(device->device))->USBDeviceClose ( (device->device) );
523 	(*(device->device))->Release ( (device->device) );
524 
525 	USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(SetConfiguration): %s",
526 		      darwin_error_str(result));
527       }
528 
529       dev->config = configDesc->bConfigurationValue;
530     }
531 
532     request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
533     request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
534     request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
535     request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
536 
537     /* Now go back and get the chosen interface */
538     result = (*(device->device))->CreateInterfaceIterator(device->device, &request, &interface_iterator);
539     if (result != kIOReturnSuccess)
540       USB_ERROR_STR (-darwin_to_errno(result), "claim_interface(CreateInterfaceIterator): %s",
541 		     darwin_error_str(result));
542 
543     for (current_interface = 0 ; current_interface <= interface ; current_interface++) {
544       usbInterface = IOIteratorNext(interface_iterator);
545 
546       if ( usb_debug > 3 )
547 	fprintf ( stderr, "claim_interface: Interface %d of device is 0x%08x\n",
548 		  current_interface, usbInterface );
549     }
550     current_interface--;
551 
552     /* the interface iterator is no longer needed, release it */
553     IOObjectRelease(interface_iterator);
554 
555     if (!usbInterface)
556       USB_ERROR_STR (-ENOENT, "claim_interface: interface iterator returned NULL");
557   }
558 
559   result = IOCreatePlugInInterfaceForService(usbInterface,
560 					     kIOUSBInterfaceUserClientTypeID,
561 					     kIOCFPlugInInterfaceID,
562 					     &plugInInterface, &score);
563   /* No longer need the usbInterface object after getting the plug-in */
564   result = IOObjectRelease(usbInterface);
565   if (result || !plugInInterface)
566     USB_ERROR(-ENOENT);
567 
568   /* Now create the device interface for the interface */
569   result = (*plugInInterface)->QueryInterface(plugInInterface,
570 					      CFUUIDGetUUIDBytes(InterfaceInterfaceID),
571 					      (LPVOID) &device->interface);
572 
573   /* No longer need the intermediate plug-in */
574   (*plugInInterface)->Stop(plugInInterface);
575   IODestroyPlugInInterface (plugInInterface);
576 
577   if (result != kIOReturnSuccess)
578     USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(QueryInterface): %s",
579 		  darwin_error_str(result));
580 
581   if (!device->interface)
582     USB_ERROR(-EACCES);
583 
584   if ( usb_debug > 3 )
585     fprintf ( stderr, "claim_interface: Interface %d of device from QueryInterface is %p\n",
586 	      current_interface, device->interface);
587 
588   /* claim the interface */
589   result = (*(device->interface))->USBInterfaceOpen(device->interface);
590   if (result)
591     USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(USBInterfaceOpen): %s",
592 		  darwin_error_str(result));
593 
594   result = get_endpoints (device);
595 
596   if (result) {
597     /* this should not happen */
598     usb_release_interface (dev, interface);
599     USB_ERROR_STR ( result, "claim_interface: could not build endpoint table");
600   }
601 
602   return 0;
603 }
604 
usb_set_configuration(usb_dev_handle * dev,int configuration)605 int usb_set_configuration (usb_dev_handle *dev, int configuration)
606 {
607   struct darwin_dev_handle *device;
608   io_return_t result;
609   int interface;
610 
611   if ( usb_debug > 3 )
612     fprintf ( stderr, "usb_set_configuration: called for config %x\n", configuration );
613 
614   if (!dev)
615     USB_ERROR_STR ( -ENXIO, "usb_set_configuration: called with null device\n" );
616 
617   if ((device = dev->impl_info) == NULL)
618     USB_ERROR_STR ( -ENOENT, "usb_set_configuration: device not properly initialized" );
619 
620   /* Setting configuration will invalidate the interface, so we need
621      to reclaim it. First, dispose of existing interface, if any. */
622   interface = dev->interface;
623 
624   if ( device->interface )
625     usb_release_interface(dev, dev->interface);
626 
627   result = (*(device->device))->SetConfiguration(device->device, configuration);
628 
629   if (result)
630     USB_ERROR_STR(-darwin_to_errno(result), "usb_set_configuration(SetConfiguration): %s",
631 		  darwin_error_str(result));
632 
633   /* Reclaim interface */
634   if (interface != -1)
635     result = usb_claim_interface (dev, interface);
636 
637   dev->config = configuration;
638 
639   return result;
640 }
641 
usb_claim_interface(usb_dev_handle * dev,int interface)642 int usb_claim_interface(usb_dev_handle *dev, int interface)
643 {
644   struct darwin_dev_handle *device = dev->impl_info;
645 
646   io_return_t result;
647 
648   if ( usb_debug > 3 )
649     fprintf ( stderr, "usb_claim_interface: called for interface %d\n", interface );
650 
651   if (!device)
652     USB_ERROR_STR ( -ENOENT, "usb_claim_interface: device is NULL" );
653 
654   if (!(device->device))
655     USB_ERROR_STR ( -EINVAL, "usb_claim_interface: device->device is NULL" );
656 
657   /* If we have already claimed an interface, release it */
658   if ( device->interface )
659     usb_release_interface(dev, dev->interface);
660 
661   result = claim_interface ( dev, interface );
662   if ( result )
663     USB_ERROR_STR ( result, "usb_claim_interface: couldn't claim interface" );
664 
665   dev->interface = interface;
666 
667   /* interface is claimed and async IO is set up: return 0 */
668   return 0;
669 }
670 
usb_release_interface(usb_dev_handle * dev,int interface)671 int usb_release_interface(usb_dev_handle *dev, int interface)
672 {
673   struct darwin_dev_handle *device;
674   io_return_t result;
675 
676   if (!dev)
677     USB_ERROR(-ENXIO);
678 
679   if ((device = dev->impl_info) == NULL)
680     USB_ERROR(-ENOENT);
681 
682   /* interface is not open */
683   if (!device->interface)
684     return 0;
685 
686   result = (*(device->interface))->USBInterfaceClose(device->interface);
687 
688   if (result != kIOReturnSuccess)
689     USB_ERROR_STR(-darwin_to_errno(result), "usb_release_interface(USBInterfaceClose): %s",
690 		  darwin_error_str(result));
691 
692   result = (*(device->interface))->Release(device->interface);
693 
694   if (result != kIOReturnSuccess)
695     USB_ERROR_STR(-darwin_to_errno(result), "usb_release_interface(Release): %s",
696 		  darwin_error_str(result));
697 
698   device->interface = NULL;
699 
700   free (device->endpoint_addrs);
701 
702   device->num_endpoints  = 0;
703   device->endpoint_addrs = NULL;
704 
705   dev->interface = -1;
706   dev->altsetting = -1;
707 
708   return 0;
709 }
710 
usb_set_altinterface(usb_dev_handle * dev,int alternate)711 int usb_set_altinterface(usb_dev_handle *dev, int alternate)
712 {
713   struct darwin_dev_handle *device;
714   io_return_t result;
715 
716   if (!dev)
717     USB_ERROR(-ENXIO);
718 
719   if ((device = dev->impl_info) == NULL)
720     USB_ERROR(-ENOENT);
721 
722   /* interface is not open */
723   if (!device->interface)
724     USB_ERROR_STR(-EACCES, "usb_set_altinterface: interface used without being claimed");
725 
726   result = (*(device->interface))->SetAlternateInterface(device->interface, alternate);
727 
728   if (result)
729     USB_ERROR_STR(result, "usb_set_altinterface: could not set alternate interface");
730 
731   dev->altsetting = alternate;
732 
733   result = get_endpoints (device);
734   if (result) {
735     /* this should not happen */
736     USB_ERROR_STR ( result, "usb_set_altinterface: could not build endpoint table");
737   }
738 
739   return 0;
740 }
741 
742 /* simple function that figures out what pipeRef is associated with an endpoint */
ep_to_pipeRef(struct darwin_dev_handle * device,int ep)743 static int ep_to_pipeRef (struct darwin_dev_handle *device, int ep)
744 {
745   int i;
746 
747   if (usb_debug > 1)
748     fprintf(stderr, "libusb/darwin.c ep_to_pipeRef: Converting ep address to pipeRef.\n");
749 
750   for (i = 0 ; i < device->num_endpoints ; i++)
751     if (device->endpoint_addrs[i] == ep)
752       return i + 1;
753 
754   /* No pipe found with the correct endpoint address */
755   if (usb_debug > 1)
756     fprintf(stderr, "libusb/darwin.c ep_to_pipeRef: No pipeRef found with endpoint address 0x%02x.\n", ep);
757 
758   return -1;
759 }
760 
usb_bulk_transfer(usb_dev_handle * dev,int ep,char * bytes,u_int32_t size,int timeout,int usb_bt_read)761 static int usb_bulk_transfer (usb_dev_handle *dev, int ep, char *bytes, u_int32_t size, int timeout, int usb_bt_read)
762 {
763   struct darwin_dev_handle *device;
764 
765   io_return_t result = -1;
766 
767   int pipeRef;
768 
769   u_int8_t  transferType, direction, number, interval;
770   u_int16_t maxPacketSize;
771 
772   if (!dev)
773     USB_ERROR_STR ( -ENXIO, "libusb/darwin.c usb_bulk_transfer: Called with NULL device" );
774 
775   if ((device = dev->impl_info) == NULL)
776     USB_ERROR_STR ( -ENOENT, "libusb/darwin.c usb_bulk_transfer: Device not open" );
777 
778   /* interface is not open */
779   if (!device->interface)
780     USB_ERROR_STR(-EACCES, "libusb/darwin.c usb_bulk_transfer: Interface used before it was opened");
781 
782 
783   /* Set up transfer */
784   if ((pipeRef = ep_to_pipeRef(device, ep)) < 0)
785     USB_ERROR_STR ( -EINVAL, "libusb/darwin.c usb_bulk_transfer: Invalid pipe reference" );
786 
787   (*(device->interface))->GetPipeProperties (device->interface, pipeRef, &direction, &number,
788 					     &transferType, &maxPacketSize, &interval);
789   /* Transfer set up complete */
790 
791   if (usb_debug > 0)
792     fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: Transfering %i bytes of data on endpoint 0x%02x\n", size, ep);
793 
794   /* Do bulk transfer */
795   if (transferType == kUSBInterrupt && usb_debug > 3)
796     fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: USB pipe is an interrupt pipe. Timeouts will not be used.\n");
797 
798 #if !defined(LIBUSB_NO_TIMEOUT_INTERFACE)
799   if ( transferType != kUSBInterrupt) {
800     if (usb_bt_read != 0)
801       result = (*(device->interface))->ReadPipeTO (device->interface, pipeRef, bytes, (UInt32 *)&size, timeout, timeout);
802     else
803       result = (*(device->interface))->WritePipeTO (device->interface, pipeRef, bytes, size, timeout, timeout);
804 
805     /* pipe bits may need to be cleared after a timeout. should this be done here or in user code? */
806     if (result == kIOUSBTransactionTimeout && (*(device->interface))->GetPipeStatus (device->interface, pipeRef) == kIOUSBPipeStalled)
807       usb_clear_halt (dev, ep);
808   } else
809 #endif
810   {
811     if (usb_bt_read != 0)
812       result = (*(device->interface))->ReadPipe (device->interface, pipeRef, bytes, (UInt32 *)&size);
813     else
814       result = (*(device->interface))->WritePipe (device->interface, pipeRef, bytes, size);
815   }
816 
817   if (result != kIOReturnSuccess)
818     USB_ERROR_STR (-darwin_to_errno (result), "libusb/darwin.c usb_bulk_transfer: %s", darwin_error_str (result));
819 
820   return size;
821 }
822 
823 #if 0
824 /* NOT USED */
825 /* argument to handle multiple parameters to rw_completed */
826 struct rw_complete_arg {
827   UInt32        io_size;
828   IOReturn      result;
829   CFRunLoopRef  cf_loop;
830 };
831 
832 static void rw_completed(void *refcon, io_return_t result, void *io_size)
833 {
834   struct rw_complete_arg *rw_arg = (struct rw_complete_arg *)refcon;
835 
836   if (usb_debug > 2)
837     fprintf(stderr, "io async operation completed: %s, size=%lu, result=0x%08x\n", darwin_error_str(result),
838 	    (UInt32)io_size, result);
839 
840   rw_arg->io_size = (UInt32)io_size;
841   rw_arg->result  = result;
842 
843   CFRunLoopStop(rw_arg->cf_loop);
844 }
845 
846 static int usb_bulk_transfer_async (usb_dev_handle *dev, int ep, char *bytes, int size, int timeout,
847 			      rw_async_func_t rw_async, rw_async_to_func_t rw_async_to)
848 {
849   struct darwin_dev_handle *device;
850 
851   io_return_t result = -1;
852 
853   CFRunLoopSourceRef cfSource;
854   int pipeRef;
855 
856   struct rw_complete_arg rw_arg;
857 
858   u_int8_t  transferType;
859 
860   /* None of the values below are used in libusb for bulk transfers */
861   u_int8_t  direction, number, interval;
862   u_int16_t maxPacketSize;
863 
864   if (!dev)
865     USB_ERROR_STR ( -ENXIO, "usb_bulk_transfer: Called with NULL device" );
866 
867   if ((device = dev->impl_info) == NULL)
868     USB_ERROR_STR ( -ENOENT, "usb_bulk_transfer: Device not open" );
869 
870   /* interface is not open */
871   if (!device->interface)
872     USB_ERROR_STR(-EACCES, "usb_bulk_transfer: Interface used before it was opened");
873 
874 
875   /* Set up transfer */
876   if ((pipeRef = ep_to_pipeRef(device, ep)) < 0)
877     USB_ERROR_STR ( -EINVAL, "usb_bulk_transfer: Invalid pipe reference" );
878 
879   (*(device->interface))->GetPipeProperties (device->interface, pipeRef, &direction, &number,
880 					     &transferType, &maxPacketSize, &interval);
881 
882   bzero((void *)&rw_arg, sizeof(struct rw_complete_arg));
883   rw_arg.cf_loop = CFRunLoopGetCurrent();
884   CFRetain (rw_arg.cf_loop);
885 
886   (*(device->interface))->CreateInterfaceAsyncEventSource(device->interface, &cfSource);
887   CFRunLoopAddSource(rw_arg.cf_loop, cfSource, kCFRunLoopDefaultMode);
888   /* Transfer set up complete */
889 
890   if (usb_debug > 0)
891     fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: Transfering %i bytes of data on endpoint 0x%02x\n",
892 	     size, ep);
893 
894   /* Bulk transfer */
895   if (transferType == kUSBInterrupt && usb_debug > 3)
896     fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: USB pipe is an interrupt pipe. Timeouts will not be used.\n");
897 
898   if ( transferType != kUSBInterrupt && rw_async_to != NULL)
899 
900     result = rw_async_to (device->interface, pipeRef, bytes, size, timeout, timeout,
901 			  (IOAsyncCallback1)rw_completed, (void *)&rw_arg);
902   else
903     result = rw_async (device->interface, pipeRef, bytes, size, (IOAsyncCallback1)rw_completed,
904 		       (void *)&rw_arg);
905 
906   if (result == kIOReturnSuccess) {
907     /* wait for write to complete */
908     if (CFRunLoopRunInMode(kCFRunLoopDefaultMode, (timeout+999)/1000, true) == kCFRunLoopRunTimedOut) {
909       (*(device->interface))->AbortPipe(device->interface, pipeRef);
910       CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); /* Pick up aborted callback */
911       if (usb_debug)
912 	fprintf(stderr, "usb_bulk_transfer: timed out\n");
913     }
914   }
915 
916   CFRunLoopRemoveSource(rw_arg.cf_loop, cfSource, kCFRunLoopDefaultMode);
917   CFRelease (rw_arg.cf_loop);
918 
919   /* Check the return code of both the write and completion functions. */
920   if (result != kIOReturnSuccess || (rw_arg.result != kIOReturnSuccess &&
921       rw_arg.result != kIOReturnAborted) ) {
922     int error_code;
923     char *error_str;
924 
925     if (result == kIOReturnSuccess) {
926       error_code = darwin_to_errno (rw_arg.result);
927       error_str  = darwin_error_str (rw_arg.result);
928     } else {
929       error_code = darwin_to_errno(result);
930       error_str  = darwin_error_str (result);
931     }
932 
933     if (transferType != kUSBInterrupt && rw_async_to != NULL)
934       USB_ERROR_STR(-error_code, "usb_bulk_transfer (w/ Timeout): %s", error_str);
935     else
936       USB_ERROR_STR(-error_code, "usb_bulk_transfer (No Timeout): %s", error_str);
937   }
938 
939   return rw_arg.io_size;
940 }
941 #endif
942 
usb_bulk_write(usb_dev_handle * dev,int ep,char * bytes,int size,int timeout)943 int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
944 {
945   int result;
946 
947   if (dev == NULL || dev->impl_info == NULL)
948     return -EINVAL;
949 
950   if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout, 0)) < 0)
951     USB_ERROR_STR (result, "usb_bulk_write: An error occured during write (see messages above)");
952 
953   return result;
954 }
955 
usb_bulk_read(usb_dev_handle * dev,int ep,char * bytes,int size,int timeout)956 int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
957 {
958   int result;
959 
960   if (dev == NULL || dev->impl_info == NULL)
961     return -EINVAL;
962 
963   ep |= 0x80;
964 
965   if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout, 1)) < 0)
966     USB_ERROR_STR (result, "usb_bulk_read: An error occured during read (see messages above)");
967 
968   return result;
969 }
970 
971 /* interrupt endpoints appear to be treated the same as non-interrupt endpoints under OSX/Darwin */
usb_interrupt_write(usb_dev_handle * dev,int ep,char * bytes,int size,int timeout)972 int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
973 	int timeout)
974 {
975   return usb_bulk_write (dev, ep, bytes, size, timeout);
976 }
977 
usb_interrupt_read(usb_dev_handle * dev,int ep,char * bytes,int size,int timeout)978 int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
979 	int timeout)
980 {
981   return usb_bulk_read (dev, ep, bytes, size, timeout);
982 }
983 
usb_control_msg(usb_dev_handle * dev,int requesttype,int request,int value,int index,char * bytes,int size,int timeout)984 int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
985 		    int value, int index, char *bytes, int size, int timeout)
986 {
987   struct darwin_dev_handle *device = dev->impl_info;
988 
989   io_return_t result;
990 
991 #if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
992   IOUSBDevRequestTO urequest;
993 #else
994   IOUSBDevRequest urequest;
995 #endif
996 
997   if (usb_debug >= 3)
998     fprintf(stderr, "usb_control_msg: %d %d %d %d %p %d %d\n",
999             requesttype, request, value, index, bytes, size, timeout);
1000 
1001   bzero(&urequest, sizeof(urequest));
1002 
1003   urequest.bmRequestType = requesttype;
1004   urequest.bRequest = request;
1005   urequest.wValue = value;
1006   urequest.wIndex = index;
1007   urequest.wLength = size;
1008   urequest.pData = bytes;
1009 #if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
1010   urequest.completionTimeout = timeout;
1011   urequest.noDataTimeout = timeout;
1012 
1013   result = (*(device->device))->DeviceRequestTO(device->device, &urequest);
1014 #else
1015   result = (*(device->device))->DeviceRequest(device->device, &urequest);
1016 #endif
1017   if (result != kIOReturnSuccess)
1018     USB_ERROR_STR(-darwin_to_errno(result), "usb_control_msg(DeviceRequestTO): %s", darwin_error_str(result));
1019 
1020   /* Bytes transfered is stored in the wLenDone field*/
1021   return urequest.wLenDone;
1022 }
1023 
usb_os_find_busses(struct usb_bus ** busses)1024 int usb_os_find_busses(struct usb_bus **busses)
1025 {
1026   struct usb_bus *fbus = NULL;
1027 
1028   io_iterator_t deviceIterator;
1029   io_return_t result;
1030 
1031   usb_device_t **device;
1032 
1033   UInt32 location;
1034 
1035   char buf[20];
1036   int i = 1;
1037 
1038   /* Create a master port for communication with IOKit (this should
1039      have been created if the user called usb_init() )*/
1040   if (masterPort == MACH_PORT_NULL) {
1041     usb_init ();
1042 
1043     if (masterPort == MACH_PORT_NULL)
1044       USB_ERROR(-ENOENT);
1045   }
1046 
1047   if ((result = usb_setup_iterator (&deviceIterator)) < 0)
1048     return result;
1049 
1050   while ((device = usb_get_next_device (deviceIterator, &location)) != NULL) {
1051     struct usb_bus *bus;
1052 
1053     if (location & 0x00ffffff)
1054       continue;
1055 
1056     bus = calloc(1, sizeof(struct usb_bus));
1057     if (bus == NULL)
1058       USB_ERROR(-ENOMEM);
1059 
1060     sprintf(buf, "%03i", i++);
1061     bus->location = location;
1062 
1063     strncpy(bus->dirname, buf, sizeof(bus->dirname) - 1);
1064     bus->dirname[sizeof(bus->dirname) - 1] = 0;
1065 
1066     LIST_ADD(fbus, bus);
1067 
1068     if (usb_debug >= 2)
1069       fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname);
1070 
1071     (*(device))->Release(device);
1072   }
1073 
1074   IOObjectRelease(deviceIterator);
1075 
1076   *busses = fbus;
1077 
1078   return 0;
1079 }
1080 
usb_os_find_devices(struct usb_bus * bus,struct usb_device ** devices)1081 int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices)
1082 {
1083   struct usb_device *fdev = NULL;
1084 
1085   io_iterator_t deviceIterator;
1086   io_return_t result;
1087 
1088   usb_device_t **device;
1089 
1090   u_int16_t address;
1091   UInt32 location;
1092   UInt32 bus_loc = bus->location;
1093 
1094   /* for use in retrieving device description */
1095   IOUSBDevRequest req;
1096 
1097   /* a master port should have been created by usb_os_init */
1098   if (masterPort == MACH_PORT_NULL)
1099     USB_ERROR(-ENOENT);
1100 
1101   if ((result = usb_setup_iterator (&deviceIterator)) < 0)
1102     return result;
1103 
1104   /* Set up request for device descriptor */
1105   req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
1106   req.bRequest = kUSBRqGetDescriptor;
1107   req.wValue = kUSBDeviceDesc << 8;
1108   req.wIndex = 0;
1109   req.wLength = sizeof(IOUSBDeviceDescriptor);
1110 
1111 
1112   while ((device = usb_get_next_device (deviceIterator, &location)) != NULL) {
1113     unsigned char device_desc[DEVICE_DESC_LENGTH];
1114 
1115     result = (*(device))->GetDeviceAddress(device, (USBDeviceAddress *)&address);
1116 
1117     if (usb_debug >= 2)
1118       fprintf(stderr, "usb_os_find_devices: Found USB device at location 0x%08lx\n", (long) location);
1119 
1120     /* first byte of location appears to be associated with the device's bus */
1121     if (location >> 24 == bus_loc >> 24) {
1122       struct usb_device *dev;
1123 
1124       dev = calloc(1, sizeof(struct usb_device));
1125       if (dev == NULL)
1126 	USB_ERROR(-ENOMEM);
1127 
1128       dev->bus = bus;
1129 
1130       req.pData = device_desc;
1131       result = (*(device))->DeviceRequest(device, &req);
1132 
1133       usb_parse_descriptor(device_desc, "bbwbbbbwwwbbbb", &dev->descriptor);
1134 
1135       sprintf(dev->filename, "%03i-%04x-%04x-%02x-%02x", address,
1136 	      dev->descriptor.idVendor, dev->descriptor.idProduct,
1137 	      dev->descriptor.bDeviceClass, dev->descriptor.bDeviceSubClass);
1138 
1139       dev->dev = (USBDeviceAddress *)malloc(4);
1140       memcpy(dev->dev, &location, 4);
1141 
1142       LIST_ADD(fdev, dev);
1143 
1144       if (usb_debug >= 2)
1145 	fprintf(stderr, "usb_os_find_devices: Found %s on %s at location 0x%08lx\n",
1146 		dev->filename, bus->dirname, (long) location);
1147     }
1148 
1149     /* release the device now */
1150     (*(device))->Release(device);
1151   }
1152 
1153   IOObjectRelease(deviceIterator);
1154 
1155   *devices = fdev;
1156 
1157   return 0;
1158 }
1159 
usb_os_determine_children(struct usb_bus * bus)1160 int usb_os_determine_children(struct usb_bus *bus)
1161 {
1162   /* Nothing yet */
1163   return 0;
1164 }
1165 
usb_os_init(void)1166 void usb_os_init(void)
1167 {
1168   if (masterPort == MACH_PORT_NULL) {
1169     IOMasterPort(masterPort, &masterPort);
1170 
1171     gNotifyPort = IONotificationPortCreate(masterPort);
1172   }
1173 }
1174 
usb_os_cleanup(void)1175 void usb_os_cleanup (void)
1176 {
1177   if (masterPort != MACH_PORT_NULL)
1178     darwin_cleanup ();
1179 }
1180 
usb_resetep(usb_dev_handle * dev,unsigned int ep)1181 int usb_resetep(usb_dev_handle *dev, unsigned int ep)
1182 {
1183   struct darwin_dev_handle *device;
1184 
1185   io_return_t result = -1;
1186 
1187   int pipeRef;
1188 
1189   if (!dev)
1190     USB_ERROR(-ENXIO);
1191 
1192   if ((device = dev->impl_info) == NULL)
1193     USB_ERROR(-ENOENT);
1194 
1195   /* interface is not open */
1196   if (!device->interface)
1197     USB_ERROR_STR(-EACCES, "usb_resetep: interface used without being claimed");
1198 
1199   if ((pipeRef = ep_to_pipeRef(device, ep)) == -1)
1200     USB_ERROR(-EINVAL);
1201 
1202   result = (*(device->interface))->ResetPipe(device->interface, pipeRef);
1203 
1204   if (result != kIOReturnSuccess)
1205     USB_ERROR_STR(-darwin_to_errno(result), "usb_resetep(ResetPipe): %s", darwin_error_str(result));
1206 
1207   return 0;
1208 }
1209 
usb_clear_halt(usb_dev_handle * dev,unsigned int ep)1210 int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
1211 {
1212   struct darwin_dev_handle *device;
1213 
1214   io_return_t result = -1;
1215 
1216   int pipeRef;
1217 
1218   if (!dev)
1219     USB_ERROR(-ENXIO);
1220 
1221   if ((device = dev->impl_info) == NULL)
1222     USB_ERROR(-ENOENT);
1223 
1224   /* interface is not open */
1225   if (!device->interface)
1226     USB_ERROR_STR(-EACCES, "usb_clear_halt: interface used without being claimed");
1227 
1228   if ((pipeRef = ep_to_pipeRef(device, ep)) == -1)
1229     USB_ERROR(-EINVAL);
1230 
1231 #if (InterfaceVersion < 190)
1232   result = (*(device->interface))->ClearPipeStall(device->interface, pipeRef);
1233 #else
1234   /* newer versions of darwin support clearing additional bits on the device's endpoint */
1235   result = (*(device->interface))->ClearPipeStallBothEnds(device->interface, pipeRef);
1236 #endif
1237 
1238   if (result != kIOReturnSuccess)
1239     USB_ERROR_STR(-darwin_to_errno(result), "usb_clear_halt(ClearPipeStall): %s", darwin_error_str(result));
1240 
1241   return 0;
1242 }
1243 
usb_reset(usb_dev_handle * dev)1244 int usb_reset(usb_dev_handle *dev)
1245 {
1246   struct darwin_dev_handle *device;
1247 
1248   io_return_t result;
1249 
1250   if (!dev)
1251     USB_ERROR(-ENXIO);
1252 
1253   if ((device = dev->impl_info) == NULL)
1254     USB_ERROR(-ENOENT);
1255 
1256   if (!device->device)
1257     USB_ERROR_STR(-ENOENT, "usb_reset: no such device");
1258 
1259   result = (*(device->device))->ResetDevice(device->device);
1260 
1261   if (result != kIOReturnSuccess)
1262     USB_ERROR_STR(-darwin_to_errno(result), "usb_reset(ResetDevice): %s", darwin_error_str(result));
1263 
1264   return 0;
1265 }
1266