2 * Darwin/MacOS X Support
4 * (c) 2002-2005 Nathan Hjelm <hjelmn@users.sourceforge.net>
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.
11 * - Fixed a bug when using asynchronous callbacks within a multi-threaded application.
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.
19 * - Fixed several memory leaks.
20 * - Readded 10.0 support
21 * - Added support for USB fuctions defined in 10.3 and above
23 * - Applied a patch by Philip Edelbrock <phil@edgedesign.us> that fixes a bug in usb_control_msg.
25 * - Even better error printing.
26 * - Devices that cannot be opened can have their interfaces opened.
28 * - Fixed problem where libusb holds resources after program completion.
29 * - Mouse should no longer freeze up now.
31 * - Bulk functions should work properly now.
33 * - Fixed major bug (device and interface need to be released after use)
35 * - Tested driver with gphoto (works great as long as Image Capture isn't running)
37 * - Implimented clear_halt and resetep
40 * - Added usb_debug line to bulk read and write function.
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.
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>
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
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
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
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
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)
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
;
155 /* stored translation table for pipes to 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
) {
172 case kIOReturnSuccess
:
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";
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";
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
) {
202 case kIOReturnSuccess
:
204 case kIOReturnNotOpen
:
206 case kIOReturnNoDevice
:
207 case kIOUSBNoAsyncPortErr
:
209 case kIOReturnExclusiveAccess
:
211 case kIOUSBPipeStalled
:
212 return LUSBDARWINSTALL
;
213 case kIOReturnBadArgument
:
215 case kIOUSBTransactionTimeout
:
223 static int usb_setup_iterator (io_iterator_t
*deviceIterator
)
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
) {
232 USB_ERROR_STR(-1, "libusb/darwin.c usb_setup_iterator: Could not create a matching dictionary.\n");
235 result
= IOServiceGetMatchingServices(masterPort
, matchingDict
, deviceIterator
);
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
));
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
;
252 if (!IOIteratorIsValid (deviceIterator
) || !(usbDevice
= IOIteratorNext(deviceIterator
)))
255 result
= IOCreatePlugInInterfaceForService(usbDevice
, kIOUSBDeviceUserClientTypeID
,
256 kIOCFPlugInInterfaceID
, &plugInInterface
,
259 result
= IOObjectRelease(usbDevice
);
260 if (result
|| !plugInInterface
)
263 (*plugInInterface
)->QueryInterface(plugInInterface
, CFUUIDGetUUIDBytes(DeviceInterfaceID
),
266 (*plugInInterface
)->Stop(plugInInterface
);
267 IODestroyPlugInInterface (plugInInterface
);
268 plugInInterface
= NULL
;
270 (*(device
))->GetLocationID(device
, locationp
);
275 int usb_os_open(usb_dev_handle
*dev
)
277 struct darwin_dev_handle
*device
;
280 io_iterator_t deviceIterator
;
282 usb_device_t
**darwin_device
;
284 UInt32 location
= *((UInt32
*)dev
->device
->dev
);
290 if (masterPort
== MACH_PORT_NULL
)
293 device
= calloc(1, sizeof(struct darwin_dev_handle
));
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)
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
)
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
);
322 /* No Seize in OS X 10.0 (Darwin 1.4) */
323 result
= (*(device
->device
))->USBDeviceOpen (device
->device
);
326 if (result
!= kIOReturnSuccess
) {
328 case kIOReturnExclusiveAccess
:
330 fprintf (stderr
, "usb_os_open(USBDeviceOpenSeize): %s\n", darwin_error_str(result
));
333 (*(device
->device
))->Release (device
->device
);
334 USB_ERROR_STR(-darwin_to_errno (result
), "usb_os_open(USBDeviceOpenSeize): %s",
335 darwin_error_str(result
));
342 dev
->impl_info
= device
;
344 dev
->altsetting
= -1;
346 device
->num_endpoints
= 0;
347 device
->endpoint_addrs
= NULL
;
352 int usb_os_close(usb_dev_handle
*dev
)
354 struct darwin_dev_handle
*device
;
360 if ((device
= dev
->impl_info
) == NULL
)
363 usb_release_interface(dev
, dev
->interface
);
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
);
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
));
386 static int get_endpoints (struct darwin_dev_handle
*device
)
390 u_int8_t numep
, direction
, number
;
391 u_int8_t dont_care1
, dont_care3
;
392 u_int16_t dont_care2
;
396 if (device
== NULL
|| device
->interface
== NULL
)
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
);
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",
422 USB_ERROR_STR(-darwin_to_errno(ret
), "get_endpoints(GetPipeProperties): %s", darwin_error_str(ret
));
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
;
435 fprintf(stderr
, "libusb/darwin.c get_endpoints: complete.\n");
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
;
445 io_cf_plugin_ref_t
*plugInInterface
= NULL
;
447 IOUSBFindInterfaceRequest request
;
449 struct darwin_dev_handle
*device
;
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
);
468 fprintf ( stderr
, "Interface %d of device is 0x%08x\n",
469 current_interface
, usbInterface
);
474 /* the interface iterator is no longer needed, release it */
475 IOObjectRelease(interface_iterator
);
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. */
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
));
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" );
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
);
545 fprintf ( stderr
, "claim_interface: Interface %d of device is 0x%08x\n",
546 current_interface
, usbInterface
);
550 /* the interface iterator is no longer needed, release it */
551 IOObjectRelease(interface_iterator
);
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
)
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
)
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
);
589 USB_ERROR_STR(-darwin_to_errno(result
), "claim_interface(USBInterfaceOpen): %s",
590 darwin_error_str(result
));
592 result
= get_endpoints (device
);
595 /* this should not happen */
596 usb_release_interface (dev
, interface
);
597 USB_ERROR_STR ( result
, "claim_interface: could not build endpoint table");
603 int usb_set_configuration (usb_dev_handle
*dev
, int configuration
)
605 struct darwin_dev_handle
*device
;
610 fprintf ( stderr
, "usb_set_configuration: called for config %x\n", configuration
);
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
);
628 USB_ERROR_STR(-darwin_to_errno(result
), "usb_set_configuration(SetConfiguration): %s",
629 darwin_error_str(result
));
631 /* Reclaim interface */
633 result
= usb_claim_interface (dev
, interface
);
635 dev
->config
= configuration
;
640 int usb_claim_interface(usb_dev_handle
*dev
, int interface
)
642 struct darwin_dev_handle
*device
= dev
->impl_info
;
647 fprintf ( stderr
, "usb_claim_interface: called for interface %d\n", interface
);
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
);
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 */
669 int usb_release_interface(usb_dev_handle
*dev
, int interface
)
671 struct darwin_dev_handle
*device
;
677 if ((device
= dev
->impl_info
) == NULL
)
680 /* interface is not open */
681 if (!device
->interface
)
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
;
704 dev
->altsetting
= -1;
709 int usb_set_altinterface(usb_dev_handle
*dev
, int alternate
)
711 struct darwin_dev_handle
*device
;
717 if ((device
= dev
->impl_info
) == NULL
)
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
);
727 USB_ERROR_STR(result
, "usb_set_altinterface: could not set alternate interface");
729 dev
->altsetting
= alternate
;
731 result
= get_endpoints (device
);
733 /* this should not happen */
734 USB_ERROR_STR ( result
, "usb_set_altinterface: could not build endpoint table");
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
)
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
)
752 /* No pipe found with the correct endpoint address */
754 fprintf(stderr
, "libusb/darwin.c ep_to_pipeRef: No pipeRef found with endpoint address 0x%02x.\n", ep
);
759 /* argument to handle multiple parameters to rw_completed */
760 struct rw_complete_arg
{
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
;
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
;
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
;
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 */
824 fprintf (stderr
, "libusb/darwin.c usb_bulk_transfer: Transfering %i bytes of data on endpoint 0x%02x\n",
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
);
836 result
= rw_async (device
->interface
, pipeRef
, bytes
, size
, (IOAsyncCallback1
)rw_completed
,
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 */
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
) ) {
857 if (result
== kIOReturnSuccess
) {
858 error_code
= darwin_to_errno (rw_arg
.result
);
859 error_str
= darwin_error_str (rw_arg
.result
);
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
);
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
)
877 rw_async_to_func_t to_func
= NULL
;
878 struct darwin_dev_handle
*device
;
880 if (dev
== NULL
|| dev
->impl_info
== NULL
)
883 device
= dev
->impl_info
;
885 #if !defined (LIBUSB_NO_TIMEOUT_INTERFACE)
886 to_func
= (*(device
->interface
))->WritePipeAsyncTO
;
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)");
896 int usb_bulk_read(usb_dev_handle
*dev
, int ep
, char *bytes
, int size
, int timeout
)
899 rw_async_to_func_t to_func
= NULL
;
900 struct darwin_dev_handle
*device
;
902 if (dev
== NULL
|| dev
->impl_info
== NULL
)
907 device
= dev
->impl_info
;
909 #if !defined (LIBUSB_NO_TIMEOUT_INTERFACE)
910 to_func
= (*(device
->interface
))->ReadPipeAsyncTO
;
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)");
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
,
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
,
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
;
940 #if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
941 IOUSBDevRequestTO urequest
;
943 IOUSBDevRequest urequest
;
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
);
964 result
= (*(device
->device
))->DeviceRequest(device
->device
, &urequest
);
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
;
980 usb_device_t
**device
;
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
) {
992 if (masterPort
== MACH_PORT_NULL
)
996 if ((result
= usb_setup_iterator (&deviceIterator
)) < 0)
999 while ((device
= usb_get_next_device (deviceIterator
, &location
)) != NULL
) {
1000 struct usb_bus
*bus
;
1002 if (location
& 0x00ffffff)
1005 bus
= calloc(1, sizeof(struct usb_bus
));
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
);
1018 fprintf(stderr
, "usb_os_find_busses: Found %s\n", bus
->dirname
);
1020 (*(device
))->Release(device
);
1023 IOObjectRelease(deviceIterator
);
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
;
1037 usb_device_t
**device
;
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
)
1050 if ((result
= usb_setup_iterator (&deviceIterator
)) < 0)
1053 /* Set up request for device descriptor */
1054 req
.bmRequestType
= USBmakebmRequestType(kUSBIn
, kUSBStandard
, kUSBDevice
);
1055 req
.bRequest
= kUSBRqGetDescriptor
;
1056 req
.wValue
= kUSBDeviceDesc
<< 8;
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
);
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
));
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
);
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
);
1109 int usb_os_determine_children(struct usb_bus
*bus
)
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
)
1130 int usb_resetep(usb_dev_handle
*dev
, unsigned int ep
)
1132 struct darwin_dev_handle
*device
;
1134 io_return_t result
= -1;
1141 if ((device
= dev
->impl_info
) == NULL
)
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)
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
));
1159 int usb_clear_halt(usb_dev_handle
*dev
, unsigned int ep
)
1161 struct darwin_dev_handle
*device
;
1163 io_return_t result
= -1;
1170 if ((device
= dev
->impl_info
) == NULL
)
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)
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
));
1188 int usb_reset(usb_dev_handle
*dev
)
1190 struct darwin_dev_handle
*device
;
1197 if ((device
= dev
->impl_info
) == NULL
)
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
));