Update TODO list
[trut64.git] / libusb / darwin.c
blob6f90ecc9a18a6cd2791a3b589cff32020262a0b0
1 /*
2 * Darwin/MacOS X Support
4 * (c) 2002-2005 Nathan Hjelm <hjelmn@users.sourceforge.net>
6 * (04/17/2005):
7 * - Lots of minor fixes.
8 * - Endpoint table now made by claim_interface to fix a bug.
9 * - Merged Read/Write to make modifications easier.
10 * (03/25/2005):
11 * - Fixed a bug when using asynchronous callbacks within a multi-threaded application.
12 * (03/14/2005):
13 * - Added an endpoint table to speed up bulk transfers.
14 * 0.1.11 (02/22/2005):
15 * - Updated error checking in read/write routines to check completion codes.
16 * - Updated set_configuration so that the open interface is reclaimed before completion.
17 * - Fixed several typos.
18 * 0.1.8 (01/12/2004):
19 * - Fixed several memory leaks.
20 * - Readded 10.0 support
21 * - Added support for USB fuctions defined in 10.3 and above
22 * (01/02/2003):
23 * - Applied a patch by Philip Edelbrock <phil@edgedesign.us> that fixes a bug in usb_control_msg.
24 * (12/16/2003):
25 * - Even better error printing.
26 * - Devices that cannot be opened can have their interfaces opened.
27 * 0.1.6 (05/12/2002):
28 * - Fixed problem where libusb holds resources after program completion.
29 * - Mouse should no longer freeze up now.
30 * 0.1.2 (02/13/2002):
31 * - Bulk functions should work properly now.
32 * 0.1.1 (02/11/2002):
33 * - Fixed major bug (device and interface need to be released after use)
34 * 0.1.0 (01/06/2002):
35 * - Tested driver with gphoto (works great as long as Image Capture isn't running)
36 * 0.1d (01/04/2002):
37 * - Implimented clear_halt and resetep
38 * - Uploaded to CVS.
39 * 0.1b (01/04/2002):
40 * - Added usb_debug line to bulk read and write function.
41 * 0.1a (01/03/2002):
42 * - Driver mostly completed using the macosx driver I wrote for my rioutil software.
44 * Derived from Linux version by Richard Tobin.
45 * Also partly derived from BSD version.
47 * This library is covered by the LGPL, read LICENSE for details.
50 #ifdef HAVE_CONFIG_H
51 #include "config.h"
52 #endif
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <unistd.h>
58 /* standard includes for darwin/os10 (IOKit) */
59 #include <mach/mach_port.h>
60 #include <IOKit/IOCFBundle.h>
61 #include <IOKit/usb/IOUSBLib.h>
62 #include <IOKit/IOCFPlugIn.h>
64 #include "usbi.h"
66 /* some defines */
67 /* IOUSBInterfaceInferface */
68 #if defined (kIOUSBInterfaceInterfaceID220)
70 // #warning "libusb being compiled for 10.4 or later"
71 #define usb_interface_t IOUSBInterfaceInterface220
72 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
73 #define InterfaceVersion 220
75 #elif defined (kIOUSBInterfaceInterfaceID197)
77 // #warning "libusb being compiled for 10.3 or later"
78 #define usb_interface_t IOUSBInterfaceInterface197
79 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID197
80 #define InterfaceVersion 197
82 #elif defined (kIOUSBInterfaceInterfaceID190)
84 // #warning "libusb being compiled for 10.2 or later"
85 #define usb_interface_t IOUSBInterfaceInterface190
86 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID190
87 #define InterfaceVersion 190
89 #elif defined (kIOUSBInterfaceInterfaceID182)
91 // #warning "libusb being compiled for 10.1 or later"
92 #define usb_interface_t IOUSBInterfaceInterface182
93 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID182
94 #define InterfaceVersion 182
96 #else
98 /* No timeout functions available! Time to upgrade your os. */
99 #warning "libusb being compiled without support for timeout bulk functions! 10.0 and up"
100 #define usb_interface_t IOUSBInterfaceInterface
101 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID
102 #define LIBUSB_NO_TIMEOUT_INTERFACE
103 #define InterfaceVersion 180
105 #endif
107 /* IOUSBDeviceInterface */
108 #if defined (kIOUSBDeviceInterfaceID197)
110 #define usb_device_t IOUSBDeviceInterface197
111 #define DeviceInterfaceID kIOUSBDeviceInterfaceID197
112 #define DeviceVersion 197
114 #elif defined (kIOUSBDeviceInterfaceID187)
116 #define usb_device_t IOUSBDeviceInterface187
117 #define DeviceInterfaceID kIOUSBDeviceInterfaceID187
118 #define DeviceVersion 187
120 #elif defined (kIOUSBDeviceInterfaceID182)
122 #define usb_device_t IOUSBDeviceInterface182
123 #define DeviceInterfaceID kIOUSBDeviceInterfaceID182
124 #define DeviceVersion 182
126 #else
128 #define usb_device_t IOUSBDeviceInterface
129 #define DeviceInterfaceID kIOUSBDeviceInterfaceID
130 #define LIBUSB_NO_TIMEOUT_DEVICE
131 #define LIBUSB_NO_SEIZE_DEVICE
132 #define DeviceVersion 180
134 #endif
136 typedef IOReturn io_return_t;
137 typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
138 typedef SInt32 s_int32_t;
139 typedef IOReturn (*rw_async_func_t)(void *self, UInt8 pipeRef, void *buf, UInt32 size,
140 IOAsyncCallback1 callback, void *refcon);
141 typedef IOReturn (*rw_async_to_func_t)(void *self, UInt8 pipeRef, void *buf, UInt32 size,
142 UInt32 noDataTimeout, UInt32 completionTimeout,
143 IOAsyncCallback1 callback, void *refcon);
145 #if !defined(IO_OBJECT_NULL)
146 #define IO_OBJECT_NULL ((io_object_t)0)
147 #endif
149 /* Darwin/OS X impl does not use fd field, instead it uses this */
150 struct darwin_dev_handle {
151 usb_device_t **device;
152 usb_interface_t **interface;
153 int open;
155 /* stored translation table for pipes to endpoints */
156 int num_endpoints;
157 unsigned char *endpoint_addrs;
160 static CFMutableDictionaryRef matchingDict;
161 static IONotificationPortRef gNotifyPort;
162 static mach_port_t masterPort = MACH_PORT_NULL;
164 static void darwin_cleanup (void)
166 IONotificationPortDestroy(gNotifyPort);
167 mach_port_deallocate(mach_task_self(), masterPort);
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";
197 /* not a valid errorno outside darwin.c */
198 #define LUSBDARWINSTALL (ELAST+1)
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;
223 static int usb_setup_iterator (io_iterator_t *deviceIterator)
225 int result;
227 /* set up the matching dictionary for class IOUSBDevice and its subclasses.
228 It will be consumed by the IOServiceGetMatchingServices call */
229 if ((matchingDict = IOServiceMatching(kIOUSBDeviceClassName)) == NULL) {
230 darwin_cleanup ();
232 USB_ERROR_STR(-1, "libusb/darwin.c usb_setup_iterator: Could not create a matching dictionary.\n");
235 result = IOServiceGetMatchingServices(masterPort, matchingDict, deviceIterator);
236 matchingDict = NULL;
238 if (result != kIOReturnSuccess)
239 USB_ERROR_STR (-darwin_to_errno (result), "libusb/darwin.c usb_setup_iterator: IOServiceGetMatchingServices: %s\n",
240 darwin_error_str(result));
242 return 0;
245 static usb_device_t **usb_get_next_device (io_iterator_t deviceIterator, UInt32 *locationp)
247 io_cf_plugin_ref_t *plugInInterface = NULL;
248 usb_device_t **device;
249 io_service_t usbDevice;
250 long result, score;
252 if (!IOIteratorIsValid (deviceIterator) || !(usbDevice = IOIteratorNext(deviceIterator)))
253 return NULL;
255 result = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID,
256 kIOCFPlugInInterfaceID, &plugInInterface,
257 &score);
259 result = IOObjectRelease(usbDevice);
260 if (result || !plugInInterface)
261 return NULL;
263 (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID),
264 (LPVOID)&device);
266 (*plugInInterface)->Stop(plugInInterface);
267 IODestroyPlugInInterface (plugInInterface);
268 plugInInterface = NULL;
270 (*(device))->GetLocationID(device, locationp);
272 return device;
275 int usb_os_open(usb_dev_handle *dev)
277 struct darwin_dev_handle *device;
279 io_return_t result;
280 io_iterator_t deviceIterator;
282 usb_device_t **darwin_device;
284 UInt32 location = *((UInt32 *)dev->device->dev);
285 UInt32 dlocation;
287 if (!dev)
288 USB_ERROR(-ENXIO);
290 if (masterPort == MACH_PORT_NULL)
291 USB_ERROR(-EINVAL);
293 device = calloc(1, sizeof(struct darwin_dev_handle));
294 if (!device)
295 USB_ERROR(-ENOMEM);
297 if (usb_debug > 3)
298 fprintf(stderr, "usb_os_open: %04x:%04x\n",
299 dev->device->descriptor.idVendor,
300 dev->device->descriptor.idProduct);
302 if ((result = usb_setup_iterator (&deviceIterator)) < 0)
303 return result;
305 /* This port of libusb uses locations to keep track of devices. */
306 while ((darwin_device = usb_get_next_device (deviceIterator, &dlocation)) != NULL) {
307 if (dlocation == location)
308 break;
310 (*darwin_device)->Release(darwin_device);
313 IOObjectRelease(deviceIterator);
314 device->device = darwin_device;
316 if (device->device == NULL)
317 USB_ERROR_STR (-ENOENT, "usb_os_open: %s\n", "Device not found!");
319 #if !defined (LIBUSB_NO_SEIZE_DEVICE)
320 result = (*(device->device))->USBDeviceOpenSeize (device->device);
321 #else
322 /* No Seize in OS X 10.0 (Darwin 1.4) */
323 result = (*(device->device))->USBDeviceOpen (device->device);
324 #endif
326 if (result != kIOReturnSuccess) {
327 switch (result) {
328 case kIOReturnExclusiveAccess:
329 if (usb_debug > 0)
330 fprintf (stderr, "usb_os_open(USBDeviceOpenSeize): %s\n", darwin_error_str(result));
331 break;
332 default:
333 (*(device->device))->Release (device->device);
334 USB_ERROR_STR(-darwin_to_errno (result), "usb_os_open(USBDeviceOpenSeize): %s",
335 darwin_error_str(result));
338 device->open = 0;
339 } else
340 device->open = 1;
342 dev->impl_info = device;
343 dev->interface = -1;
344 dev->altsetting = -1;
346 device->num_endpoints = 0;
347 device->endpoint_addrs = NULL;
349 return 0;
352 int usb_os_close(usb_dev_handle *dev)
354 struct darwin_dev_handle *device;
355 io_return_t result;
357 if (!dev)
358 USB_ERROR(-ENXIO);
360 if ((device = dev->impl_info) == NULL)
361 USB_ERROR(-ENOENT);
363 usb_release_interface(dev, dev->interface);
365 if (usb_debug > 3)
366 fprintf(stderr, "usb_os_close: %04x:%04x\n",
367 dev->device->descriptor.idVendor,
368 dev->device->descriptor.idProduct);
370 if (device->open == 1)
371 result = (*(device->device))->USBDeviceClose(device->device);
372 else
373 result = kIOReturnSuccess;
375 /* device may not need to be released, but if it has to... */
376 (*(device->device))->Release(device->device);
378 if (result != kIOReturnSuccess)
379 USB_ERROR_STR(-darwin_to_errno(result), "usb_os_close(USBDeviceClose): %s", darwin_error_str(result));
381 free (device);
383 return 0;
386 static int get_endpoints (struct darwin_dev_handle *device)
388 io_return_t ret;
390 u_int8_t numep, direction, number;
391 u_int8_t dont_care1, dont_care3;
392 u_int16_t dont_care2;
394 int i;
396 if (device == NULL || device->interface == NULL)
397 return -EINVAL;
399 if (usb_debug > 1)
400 fprintf(stderr, "libusb/darwin.c get_endpoints: building table of endpoints.\n");
402 /* retrieve the total number of endpoints on this interface */
403 ret = (*(device->interface))->GetNumEndpoints(device->interface, &numep);
404 if ( ret ) {
405 if ( usb_debug > 1 )
406 fprintf ( stderr, "get_endpoints: interface is %p\n", device->interface );
408 USB_ERROR_STR ( -ret, "get_endpoints: can't get number of endpoints for interface" );
411 free (device->endpoint_addrs);
412 device->endpoint_addrs = calloc (sizeof (unsigned char), numep);
414 /* iterate through pipe references */
415 for (i = 1 ; i <= numep ; i++) {
416 ret = (*(device->interface))->GetPipeProperties(device->interface, i, &direction, &number,
417 &dont_care1, &dont_care2, &dont_care3);
419 if (ret != kIOReturnSuccess) {
420 fprintf (stderr, "get_endpoints: an error occurred getting pipe information on pipe %d\n",
421 i );
422 USB_ERROR_STR(-darwin_to_errno(ret), "get_endpoints(GetPipeProperties): %s", darwin_error_str(ret));
425 if (usb_debug > 1)
426 fprintf (stderr, "get_endpoints: Pipe %i: DIR: %i number: %i\n", i, direction, number);
428 device->endpoint_addrs[i - 1] = ((direction << 7 & USB_ENDPOINT_DIR_MASK) |
429 (number & USB_ENDPOINT_ADDRESS_MASK));
432 device->num_endpoints = numep;
434 if (usb_debug > 1)
435 fprintf(stderr, "libusb/darwin.c get_endpoints: complete.\n");
437 return 0;
440 static int claim_interface (usb_dev_handle *dev, int interface)
442 io_iterator_t interface_iterator;
443 io_service_t usbInterface = IO_OBJECT_NULL;
444 io_return_t result;
445 io_cf_plugin_ref_t *plugInInterface = NULL;
447 IOUSBFindInterfaceRequest request;
449 struct darwin_dev_handle *device;
450 long score;
451 int current_interface;
453 device = dev->impl_info;
455 request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
456 request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
457 request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
458 request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
460 result = (*(device->device))->CreateInterfaceIterator(device->device, &request, &interface_iterator);
461 if (result != kIOReturnSuccess)
462 USB_ERROR_STR (-darwin_to_errno(result), "claim_interface(CreateInterfaceIterator): %s",
463 darwin_error_str(result));
465 for ( current_interface=0 ; current_interface <= interface ; current_interface++ ) {
466 usbInterface = IOIteratorNext(interface_iterator);
467 if ( usb_debug > 3 )
468 fprintf ( stderr, "Interface %d of device is 0x%08x\n",
469 current_interface, usbInterface );
472 current_interface--;
474 /* the interface iterator is no longer needed, release it */
475 IOObjectRelease(interface_iterator);
477 if (!usbInterface) {
478 u_int8_t nConfig; /* Index of configuration to use */
479 IOUSBConfigurationDescriptorPtr configDesc; /* to describe which configuration to select */
480 /* Only a composite class device with no vendor-specific driver will
481 be configured. Otherwise, we need to do it ourselves, or there
482 will be no interfaces for the device. */
484 if ( usb_debug > 3 )
485 fprintf ( stderr,"claim_interface: No interface found; selecting configuration\n" );
487 result = (*(device->device))->GetNumberOfConfigurations ( device->device, &nConfig );
488 if (result != kIOReturnSuccess)
489 USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(GetNumberOfConfigurations): %s",
490 darwin_error_str(result));
492 if (nConfig < 1)
493 USB_ERROR_STR(-ENXIO ,"claim_interface(GetNumberOfConfigurations): no configurations");
494 else if ( nConfig > 1 && usb_debug > 0 )
495 fprintf ( stderr, "claim_interface: device has more than one"
496 " configuration, using the first (warning)\n" );
498 if ( usb_debug > 3 )
499 fprintf ( stderr, "claim_interface: device has %d configuration%s\n",
500 (int)nConfig, (nConfig>1?"s":"") );
502 /* Always use the first configuration */
503 result = (*(device->device))->GetConfigurationDescriptorPtr ( (device->device), 0, &configDesc );
504 if (result != kIOReturnSuccess) {
505 if (device->open == 1) {
506 (*(device->device))->USBDeviceClose ( (device->device) );
507 (*(device->device))->Release ( (device->device) );
510 USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(GetConfigurationDescriptorPtr): %s",
511 darwin_error_str(result));
512 } else if ( usb_debug > 3 )
513 fprintf ( stderr, "claim_interface: configuration value is %d\n",
514 configDesc->bConfigurationValue );
516 if (device->open == 1) {
517 result = (*(device->device))->SetConfiguration ( (device->device), configDesc->bConfigurationValue );
519 if (result != kIOReturnSuccess) {
520 (*(device->device))->USBDeviceClose ( (device->device) );
521 (*(device->device))->Release ( (device->device) );
523 USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(SetConfiguration): %s",
524 darwin_error_str(result));
527 dev->config = configDesc->bConfigurationValue;
530 request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
531 request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
532 request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
533 request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
535 /* Now go back and get the chosen interface */
536 result = (*(device->device))->CreateInterfaceIterator(device->device, &request, &interface_iterator);
537 if (result != kIOReturnSuccess)
538 USB_ERROR_STR (-darwin_to_errno(result), "claim_interface(CreateInterfaceIterator): %s",
539 darwin_error_str(result));
541 for (current_interface = 0 ; current_interface <= interface ; current_interface++) {
542 usbInterface = IOIteratorNext(interface_iterator);
544 if ( usb_debug > 3 )
545 fprintf ( stderr, "claim_interface: Interface %d of device is 0x%08x\n",
546 current_interface, usbInterface );
548 current_interface--;
550 /* the interface iterator is no longer needed, release it */
551 IOObjectRelease(interface_iterator);
553 if (!usbInterface)
554 USB_ERROR_STR (-ENOENT, "claim_interface: interface iterator returned NULL");
557 result = IOCreatePlugInInterfaceForService(usbInterface,
558 kIOUSBInterfaceUserClientTypeID,
559 kIOCFPlugInInterfaceID,
560 &plugInInterface, &score);
561 /* No longer need the usbInterface object after getting the plug-in */
562 result = IOObjectRelease(usbInterface);
563 if (result || !plugInInterface)
564 USB_ERROR(-ENOENT);
566 /* Now create the device interface for the interface */
567 result = (*plugInInterface)->QueryInterface(plugInInterface,
568 CFUUIDGetUUIDBytes(InterfaceInterfaceID),
569 (LPVOID) &device->interface);
571 /* No longer need the intermediate plug-in */
572 (*plugInInterface)->Stop(plugInInterface);
573 IODestroyPlugInInterface (plugInInterface);
575 if (result != kIOReturnSuccess)
576 USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(QueryInterface): %s",
577 darwin_error_str(result));
579 if (!device->interface)
580 USB_ERROR(-EACCES);
582 if ( usb_debug > 3 )
583 fprintf ( stderr, "claim_interface: Interface %d of device from QueryInterface is %p\n",
584 current_interface, device->interface);
586 /* claim the interface */
587 result = (*(device->interface))->USBInterfaceOpen(device->interface);
588 if (result)
589 USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(USBInterfaceOpen): %s",
590 darwin_error_str(result));
592 result = get_endpoints (device);
594 if (result) {
595 /* this should not happen */
596 usb_release_interface (dev, interface);
597 USB_ERROR_STR ( result, "claim_interface: could not build endpoint table");
600 return 0;
603 int usb_set_configuration (usb_dev_handle *dev, int configuration)
605 struct darwin_dev_handle *device;
606 io_return_t result;
607 int interface;
609 if ( usb_debug > 3 )
610 fprintf ( stderr, "usb_set_configuration: called for config %x\n", configuration );
612 if (!dev)
613 USB_ERROR_STR ( -ENXIO, "usb_set_configuration: called with null device\n" );
615 if ((device = dev->impl_info) == NULL)
616 USB_ERROR_STR ( -ENOENT, "usb_set_configuration: device not properly initialized" );
618 /* Setting configuration will invalidate the interface, so we need
619 to reclaim it. First, dispose of existing interface, if any. */
620 interface = dev->interface;
622 if ( device->interface )
623 usb_release_interface(dev, dev->interface);
625 result = (*(device->device))->SetConfiguration(device->device, configuration);
627 if (result)
628 USB_ERROR_STR(-darwin_to_errno(result), "usb_set_configuration(SetConfiguration): %s",
629 darwin_error_str(result));
631 /* Reclaim interface */
632 if (interface != -1)
633 result = usb_claim_interface (dev, interface);
635 dev->config = configuration;
637 return result;
640 int usb_claim_interface(usb_dev_handle *dev, int interface)
642 struct darwin_dev_handle *device = dev->impl_info;
644 io_return_t result;
646 if ( usb_debug > 3 )
647 fprintf ( stderr, "usb_claim_interface: called for interface %d\n", interface );
649 if (!device)
650 USB_ERROR_STR ( -ENOENT, "usb_claim_interface: device is NULL" );
652 if (!(device->device))
653 USB_ERROR_STR ( -EINVAL, "usb_claim_interface: device->device is NULL" );
655 /* If we have already claimed an interface, release it */
656 if ( device->interface )
657 usb_release_interface(dev, dev->interface);
659 result = claim_interface ( dev, interface );
660 if ( result )
661 USB_ERROR_STR ( result, "usb_claim_interface: couldn't claim interface" );
663 dev->interface = interface;
665 /* interface is claimed and async IO is set up: return 0 */
666 return 0;
669 int usb_release_interface(usb_dev_handle *dev, int interface)
671 struct darwin_dev_handle *device;
672 io_return_t result;
674 if (!dev)
675 USB_ERROR(-ENXIO);
677 if ((device = dev->impl_info) == NULL)
678 USB_ERROR(-ENOENT);
680 /* interface is not open */
681 if (!device->interface)
682 return 0;
684 result = (*(device->interface))->USBInterfaceClose(device->interface);
686 if (result != kIOReturnSuccess)
687 USB_ERROR_STR(-darwin_to_errno(result), "usb_release_interface(USBInterfaceClose): %s",
688 darwin_error_str(result));
690 result = (*(device->interface))->Release(device->interface);
692 if (result != kIOReturnSuccess)
693 USB_ERROR_STR(-darwin_to_errno(result), "usb_release_interface(Release): %s",
694 darwin_error_str(result));
696 device->interface = NULL;
698 free (device->endpoint_addrs);
700 device->num_endpoints = 0;
701 device->endpoint_addrs = NULL;
703 dev->interface = -1;
704 dev->altsetting = -1;
706 return 0;
709 int usb_set_altinterface(usb_dev_handle *dev, int alternate)
711 struct darwin_dev_handle *device;
712 io_return_t result;
714 if (!dev)
715 USB_ERROR(-ENXIO);
717 if ((device = dev->impl_info) == NULL)
718 USB_ERROR(-ENOENT);
720 /* interface is not open */
721 if (!device->interface)
722 USB_ERROR_STR(-EACCES, "usb_set_altinterface: interface used without being claimed");
724 result = (*(device->interface))->SetAlternateInterface(device->interface, alternate);
726 if (result)
727 USB_ERROR_STR(result, "usb_set_altinterface: could not set alternate interface");
729 dev->altsetting = alternate;
731 result = get_endpoints (device);
732 if (result) {
733 /* this should not happen */
734 USB_ERROR_STR ( result, "usb_set_altinterface: could not build endpoint table");
737 return 0;
740 /* simple function that figures out what pipeRef is associated with an endpoint */
741 static int ep_to_pipeRef (struct darwin_dev_handle *device, int ep)
743 int i;
745 if (usb_debug > 1)
746 fprintf(stderr, "libusb/darwin.c ep_to_pipeRef: Converting ep address to pipeRef.\n");
748 for (i = 0 ; i < device->num_endpoints ; i++)
749 if (device->endpoint_addrs[i] == ep)
750 return i + 1;
752 /* No pipe found with the correct endpoint address */
753 if (usb_debug > 1)
754 fprintf(stderr, "libusb/darwin.c ep_to_pipeRef: No pipeRef found with endpoint address 0x%02x.\n", ep);
756 return -1;
759 /* argument to handle multiple parameters to rw_completed */
760 struct rw_complete_arg {
761 UInt32 io_size;
762 IOReturn result;
763 CFRunLoopRef cf_loop;
766 static void rw_completed(void *refcon, io_return_t result, void *io_size)
768 struct rw_complete_arg *rw_arg = (struct rw_complete_arg *)refcon;
770 if (usb_debug > 2)
771 fprintf(stderr, "io async operation completed: %s, size=%lu, result=0x%08x\n", darwin_error_str(result),
772 (UInt32)io_size, result);
774 rw_arg->io_size = (UInt32)io_size;
775 rw_arg->result = result;
777 CFRunLoopStop(rw_arg->cf_loop);
780 static int usb_bulk_transfer (usb_dev_handle *dev, int ep, char *bytes, int size, int timeout,
781 rw_async_func_t rw_async, rw_async_to_func_t rw_async_to)
783 struct darwin_dev_handle *device;
785 io_return_t result = -1;
787 CFRunLoopSourceRef cfSource;
788 int pipeRef;
790 struct rw_complete_arg rw_arg;
792 u_int8_t transferType;
794 /* None of the values below are used in libusb for bulk transfers */
795 u_int8_t direction, number, interval;
796 u_int16_t maxPacketSize;
798 if (!dev)
799 USB_ERROR_STR ( -ENXIO, "usb_bulk_transfer: Called with NULL device" );
801 if ((device = dev->impl_info) == NULL)
802 USB_ERROR_STR ( -ENOENT, "usb_bulk_transfer: Device not open" );
804 /* interface is not open */
805 if (!device->interface)
806 USB_ERROR_STR(-EACCES, "usb_bulk_transfer: Interface used before it was opened");
809 /* Set up transfer */
810 if ((pipeRef = ep_to_pipeRef(device, ep)) < 0)
811 USB_ERROR_STR ( -EINVAL, "usb_bulk_transfer: Invalid pipe reference" );
813 (*(device->interface))->GetPipeProperties (device->interface, pipeRef, &direction, &number,
814 &transferType, &maxPacketSize, &interval);
816 (*(device->interface))->CreateInterfaceAsyncEventSource(device->interface, &cfSource);
817 CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
819 bzero((void *)&rw_arg, sizeof(struct rw_complete_arg));
820 rw_arg.cf_loop = CFRunLoopGetCurrent();
821 /* Transfer set up complete */
823 if (usb_debug > 0)
824 fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: Transfering %i bytes of data on endpoint 0x%02x\n",
825 size, ep);
827 /* Bulk transfer */
828 if (transferType == kUSBInterrupt && usb_debug > 3)
829 fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: USB pipe is an interrupt pipe. Timeouts will not be used.\n");
831 if ( transferType != kUSBInterrupt && rw_async_to != NULL)
833 result = rw_async_to (device->interface, pipeRef, bytes, size, timeout, timeout,
834 (IOAsyncCallback1)rw_completed, (void *)&rw_arg);
835 else
836 result = rw_async (device->interface, pipeRef, bytes, size, (IOAsyncCallback1)rw_completed,
837 (void *)&rw_arg);
839 if (result == kIOReturnSuccess) {
840 /* wait for write to complete */
841 if (CFRunLoopRunInMode(kCFRunLoopDefaultMode, (timeout+999)/1000, true) == kCFRunLoopRunTimedOut) {
842 (*(device->interface))->AbortPipe(device->interface, pipeRef);
843 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); /* Pick up aborted callback */
844 if (usb_debug)
845 fprintf(stderr, "usb_bulk_read: input timed out\n");
849 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
851 /* Check the return code of both the write and completion functions. */
852 if (result != kIOReturnSuccess || (rw_arg.result != kIOReturnSuccess &&
853 rw_arg.result != kIOReturnAborted) ) {
854 int error_code;
855 char *error_str;
857 if (result == kIOReturnSuccess) {
858 error_code = darwin_to_errno (rw_arg.result);
859 error_str = darwin_error_str (rw_arg.result);
860 } else {
861 error_code = darwin_to_errno(result);
862 error_str = darwin_error_str (result);
865 if (transferType != kUSBInterrupt && rw_async_to != NULL)
866 USB_ERROR_STR(-error_code, "usb_bulk_transfer (w/ Timeout): %s", error_str);
867 else
868 USB_ERROR_STR(-error_code, "usb_bulk_transfer (No Timeout): %s", error_str);
871 return rw_arg.io_size;
874 int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
876 int result;
877 rw_async_to_func_t to_func = NULL;
878 struct darwin_dev_handle *device;
880 if (dev == NULL || dev->impl_info == NULL)
881 return -EINVAL;
883 device = dev->impl_info;
885 #if !defined (LIBUSB_NO_TIMEOUT_INTERFACE)
886 to_func = (*(device->interface))->WritePipeAsyncTO;
887 #endif
889 if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout,
890 (*(device->interface))->WritePipeAsync, to_func)) < 0)
891 USB_ERROR_STR (result, "usb_bulk_write: An error occured during write (see messages above)");
893 return result;
896 int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
898 int result;
899 rw_async_to_func_t to_func = NULL;
900 struct darwin_dev_handle *device;
902 if (dev == NULL || dev->impl_info == NULL)
903 return -EINVAL;
905 ep |= 0x80;
907 device = dev->impl_info;
909 #if !defined (LIBUSB_NO_TIMEOUT_INTERFACE)
910 to_func = (*(device->interface))->ReadPipeAsyncTO;
911 #endif
913 if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout,
914 (*(device->interface))->ReadPipeAsync, to_func)) < 0)
915 USB_ERROR_STR (result, "usb_bulk_read: An error occured during read (see messages above)");
917 return result;
920 /* interrupt endpoints seem to be treated just like any other endpoint under OSX/Darwin */
921 int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
922 int timeout)
924 return usb_bulk_write (dev, ep, bytes, size, timeout);
927 int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
928 int timeout)
930 return usb_bulk_read (dev, ep, bytes, size, timeout);
933 int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
934 int value, int index, char *bytes, int size, int timeout)
936 struct darwin_dev_handle *device = dev->impl_info;
938 io_return_t result;
940 #if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
941 IOUSBDevRequestTO urequest;
942 #else
943 IOUSBDevRequest urequest;
944 #endif
946 if (usb_debug >= 3)
947 fprintf(stderr, "usb_control_msg: %d %d %d %d %p %d %d\n",
948 requesttype, request, value, index, bytes, size, timeout);
950 bzero(&urequest, sizeof(urequest));
952 urequest.bmRequestType = requesttype;
953 urequest.bRequest = request;
954 urequest.wValue = value;
955 urequest.wIndex = index;
956 urequest.wLength = size;
957 urequest.pData = bytes;
958 #if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
959 urequest.completionTimeout = timeout;
960 urequest.noDataTimeout = timeout;
962 result = (*(device->device))->DeviceRequestTO(device->device, &urequest);
963 #else
964 result = (*(device->device))->DeviceRequest(device->device, &urequest);
965 #endif
966 if (result != kIOReturnSuccess)
967 USB_ERROR_STR(-darwin_to_errno(result), "usb_control_msg(DeviceRequestTO): %s", darwin_error_str(result));
969 /* Bytes transfered is stored in the wLenDone field*/
970 return urequest.wLenDone;
973 int usb_os_find_busses(struct usb_bus **busses)
975 struct usb_bus *fbus = NULL;
977 io_iterator_t deviceIterator;
978 io_return_t result;
980 usb_device_t **device;
982 UInt32 location;
984 char buf[20];
985 int i = 1;
987 /* Create a master port for communication with IOKit (this should
988 have been created if the user called usb_init() )*/
989 if (masterPort == MACH_PORT_NULL) {
990 usb_init ();
992 if (masterPort == MACH_PORT_NULL)
993 USB_ERROR(-ENOENT);
996 if ((result = usb_setup_iterator (&deviceIterator)) < 0)
997 return result;
999 while ((device = usb_get_next_device (deviceIterator, &location)) != NULL) {
1000 struct usb_bus *bus;
1002 if (location & 0x00ffffff)
1003 continue;
1005 bus = calloc(1, sizeof(struct usb_bus));
1006 if (bus == NULL)
1007 USB_ERROR(-ENOMEM);
1009 sprintf(buf, "%03i", i++);
1010 bus->location = location;
1012 strncpy(bus->dirname, buf, sizeof(bus->dirname) - 1);
1013 bus->dirname[sizeof(bus->dirname) - 1] = 0;
1015 LIST_ADD(fbus, bus);
1017 if (usb_debug >= 2)
1018 fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname);
1020 (*(device))->Release(device);
1023 IOObjectRelease(deviceIterator);
1025 *busses = fbus;
1027 return 0;
1030 int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices)
1032 struct usb_device *fdev = NULL;
1034 io_iterator_t deviceIterator;
1035 io_return_t result;
1037 usb_device_t **device;
1039 u_int16_t address;
1040 UInt32 location;
1041 UInt32 bus_loc = bus->location;
1043 /* for use in retrieving device description */
1044 IOUSBDevRequest req;
1046 /* a master port should have been created by usb_os_init */
1047 if (masterPort == MACH_PORT_NULL)
1048 USB_ERROR(-ENOENT);
1050 if ((result = usb_setup_iterator (&deviceIterator)) < 0)
1051 return result;
1053 /* Set up request for device descriptor */
1054 req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
1055 req.bRequest = kUSBRqGetDescriptor;
1056 req.wValue = kUSBDeviceDesc << 8;
1057 req.wIndex = 0;
1058 req.wLength = sizeof(IOUSBDeviceDescriptor);
1061 while ((device = usb_get_next_device (deviceIterator, &location)) != NULL) {
1062 unsigned char device_desc[DEVICE_DESC_LENGTH];
1064 result = (*(device))->GetDeviceAddress(device, (USBDeviceAddress *)&address);
1066 if (usb_debug >= 2)
1067 fprintf(stderr, "usb_os_find_devices: Found USB device at location 0x%08lx\n", location);
1069 /* first byte of location appears to be associated with the device's bus */
1070 if (location >> 24 == bus_loc >> 24) {
1071 struct usb_device *dev;
1073 dev = calloc(1, sizeof(struct usb_device));
1074 if (dev == NULL)
1075 USB_ERROR(-ENOMEM);
1077 dev->bus = bus;
1079 req.pData = device_desc;
1080 result = (*(device))->DeviceRequest(device, &req);
1082 usb_parse_descriptor(device_desc, "bbwbbbbwwwbbbb", &dev->descriptor);
1084 sprintf(dev->filename, "%03i-%04x-%04x-%02x-%02x", address,
1085 dev->descriptor.idVendor, dev->descriptor.idProduct,
1086 dev->descriptor.bDeviceClass, dev->descriptor.bDeviceSubClass);
1088 dev->dev = (USBDeviceAddress *)malloc(4);
1089 memcpy(dev->dev, &location, 4);
1091 LIST_ADD(fdev, dev);
1093 if (usb_debug >= 2)
1094 fprintf(stderr, "usb_os_find_devices: Found %s on %s at location 0x%08lx\n",
1095 dev->filename, bus->dirname, location);
1098 /* release the device now */
1099 (*(device))->Release(device);
1102 IOObjectRelease(deviceIterator);
1104 *devices = fdev;
1106 return 0;
1109 int usb_os_determine_children(struct usb_bus *bus)
1111 /* Nothing yet */
1112 return 0;
1115 void usb_os_init(void)
1117 if (masterPort == MACH_PORT_NULL) {
1118 IOMasterPort(masterPort, &masterPort);
1120 gNotifyPort = IONotificationPortCreate(masterPort);
1124 void usb_os_cleanup (void)
1126 if (masterPort != MACH_PORT_NULL)
1127 darwin_cleanup ();
1130 int usb_resetep(usb_dev_handle *dev, unsigned int ep)
1132 struct darwin_dev_handle *device;
1134 io_return_t result = -1;
1136 int pipeRef;
1138 if (!dev)
1139 USB_ERROR(-ENXIO);
1141 if ((device = dev->impl_info) == NULL)
1142 USB_ERROR(-ENOENT);
1144 /* interface is not open */
1145 if (!device->interface)
1146 USB_ERROR_STR(-EACCES, "usb_resetep: interface used without being claimed");
1148 if ((pipeRef = ep_to_pipeRef(device, ep)) == -1)
1149 USB_ERROR(-EINVAL);
1151 result = (*(device->interface))->ResetPipe(device->interface, pipeRef);
1153 if (result != kIOReturnSuccess)
1154 USB_ERROR_STR(-darwin_to_errno(result), "usb_resetep(ResetPipe): %s", darwin_error_str(result));
1156 return 0;
1159 int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
1161 struct darwin_dev_handle *device;
1163 io_return_t result = -1;
1165 int pipeRef;
1167 if (!dev)
1168 USB_ERROR(-ENXIO);
1170 if ((device = dev->impl_info) == NULL)
1171 USB_ERROR(-ENOENT);
1173 /* interface is not open */
1174 if (!device->interface)
1175 USB_ERROR_STR(-EACCES, "usb_clear_halt: interface used without being claimed");
1177 if ((pipeRef = ep_to_pipeRef(device, ep)) == -1)
1178 USB_ERROR(-EINVAL);
1180 result = (*(device->interface))->ClearPipeStall(device->interface, pipeRef);
1182 if (result != kIOReturnSuccess)
1183 USB_ERROR_STR(-darwin_to_errno(result), "usb_clear_halt(ClearPipeStall): %s", darwin_error_str(result));
1185 return 0;
1188 int usb_reset(usb_dev_handle *dev)
1190 struct darwin_dev_handle *device;
1192 io_return_t result;
1194 if (!dev)
1195 USB_ERROR(-ENXIO);
1197 if ((device = dev->impl_info) == NULL)
1198 USB_ERROR(-ENOENT);
1200 if (!device->device)
1201 USB_ERROR_STR(-ENOENT, "usb_reset: no such device");
1203 result = (*(device->device))->ResetDevice(device->device);
1205 if (result != kIOReturnSuccess)
1206 USB_ERROR_STR(-darwin_to_errno(result), "usb_reset(ResetDevice): %s", darwin_error_str(result));
1208 return 0;