summaryrefslogtreecommitdiffstats
path: root/libusb/darwin.c
diff options
context:
space:
mode:
Diffstat (limited to 'libusb/darwin.c')
-rw-r--r--libusb/darwin.c1209
1 files changed, 0 insertions, 1209 deletions
diff --git a/libusb/darwin.c b/libusb/darwin.c
deleted file mode 100644
index 6f90ecc..0000000
--- a/libusb/darwin.c
+++ /dev/null
@@ -1,1209 +0,0 @@
-/*
- * Darwin/MacOS X Support
- *
- * (c) 2002-2005 Nathan Hjelm <hjelmn@users.sourceforge.net>
- *
- * (04/17/2005):
- * - Lots of minor fixes.
- * - Endpoint table now made by claim_interface to fix a bug.
- * - Merged Read/Write to make modifications easier.
- * (03/25/2005):
- * - Fixed a bug when using asynchronous callbacks within a multi-threaded application.
- * (03/14/2005):
- * - Added an endpoint table to speed up bulk transfers.
- * 0.1.11 (02/22/2005):
- * - Updated error checking in read/write routines to check completion codes.
- * - Updated set_configuration so that the open interface is reclaimed before completion.
- * - Fixed several typos.
- * 0.1.8 (01/12/2004):
- * - Fixed several memory leaks.
- * - Readded 10.0 support
- * - Added support for USB fuctions defined in 10.3 and above
- * (01/02/2003):
- * - Applied a patch by Philip Edelbrock <phil@edgedesign.us> that fixes a bug in usb_control_msg.
- * (12/16/2003):
- * - Even better error printing.
- * - Devices that cannot be opened can have their interfaces opened.
- * 0.1.6 (05/12/2002):
- * - Fixed problem where libusb holds resources after program completion.
- * - Mouse should no longer freeze up now.
- * 0.1.2 (02/13/2002):
- * - Bulk functions should work properly now.
- * 0.1.1 (02/11/2002):
- * - Fixed major bug (device and interface need to be released after use)
- * 0.1.0 (01/06/2002):
- * - Tested driver with gphoto (works great as long as Image Capture isn't running)
- * 0.1d (01/04/2002):
- * - Implimented clear_halt and resetep
- * - Uploaded to CVS.
- * 0.1b (01/04/2002):
- * - Added usb_debug line to bulk read and write function.
- * 0.1a (01/03/2002):
- * - Driver mostly completed using the macosx driver I wrote for my rioutil software.
- *
- * Derived from Linux version by Richard Tobin.
- * Also partly derived from BSD version.
- *
- * This library is covered by the LGPL, read LICENSE for details.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-
-/* standard includes for darwin/os10 (IOKit) */
-#include <mach/mach_port.h>
-#include <IOKit/IOCFBundle.h>
-#include <IOKit/usb/IOUSBLib.h>
-#include <IOKit/IOCFPlugIn.h>
-
-#include "usbi.h"
-
-/* some defines */
-/* IOUSBInterfaceInferface */
-#if defined (kIOUSBInterfaceInterfaceID220)
-
-// #warning "libusb being compiled for 10.4 or later"
-#define usb_interface_t IOUSBInterfaceInterface220
-#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
-#define InterfaceVersion 220
-
-#elif defined (kIOUSBInterfaceInterfaceID197)
-
-// #warning "libusb being compiled for 10.3 or later"
-#define usb_interface_t IOUSBInterfaceInterface197
-#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID197
-#define InterfaceVersion 197
-
-#elif defined (kIOUSBInterfaceInterfaceID190)
-
-// #warning "libusb being compiled for 10.2 or later"
-#define usb_interface_t IOUSBInterfaceInterface190
-#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID190
-#define InterfaceVersion 190
-
-#elif defined (kIOUSBInterfaceInterfaceID182)
-
-// #warning "libusb being compiled for 10.1 or later"
-#define usb_interface_t IOUSBInterfaceInterface182
-#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID182
-#define InterfaceVersion 182
-
-#else
-
-/* No timeout functions available! Time to upgrade your os. */
-#warning "libusb being compiled without support for timeout bulk functions! 10.0 and up"
-#define usb_interface_t IOUSBInterfaceInterface
-#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID
-#define LIBUSB_NO_TIMEOUT_INTERFACE
-#define InterfaceVersion 180
-
-#endif
-
-/* IOUSBDeviceInterface */
-#if defined (kIOUSBDeviceInterfaceID197)
-
-#define usb_device_t IOUSBDeviceInterface197
-#define DeviceInterfaceID kIOUSBDeviceInterfaceID197
-#define DeviceVersion 197
-
-#elif defined (kIOUSBDeviceInterfaceID187)
-
-#define usb_device_t IOUSBDeviceInterface187
-#define DeviceInterfaceID kIOUSBDeviceInterfaceID187
-#define DeviceVersion 187
-
-#elif defined (kIOUSBDeviceInterfaceID182)
-
-#define usb_device_t IOUSBDeviceInterface182
-#define DeviceInterfaceID kIOUSBDeviceInterfaceID182
-#define DeviceVersion 182
-
-#else
-
-#define usb_device_t IOUSBDeviceInterface
-#define DeviceInterfaceID kIOUSBDeviceInterfaceID
-#define LIBUSB_NO_TIMEOUT_DEVICE
-#define LIBUSB_NO_SEIZE_DEVICE
-#define DeviceVersion 180
-
-#endif
-
-typedef IOReturn io_return_t;
-typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
-typedef SInt32 s_int32_t;
-typedef IOReturn (*rw_async_func_t)(void *self, UInt8 pipeRef, void *buf, UInt32 size,
- IOAsyncCallback1 callback, void *refcon);
-typedef IOReturn (*rw_async_to_func_t)(void *self, UInt8 pipeRef, void *buf, UInt32 size,
- UInt32 noDataTimeout, UInt32 completionTimeout,
- IOAsyncCallback1 callback, void *refcon);
-
-#if !defined(IO_OBJECT_NULL)
-#define IO_OBJECT_NULL ((io_object_t)0)
-#endif
-
-/* Darwin/OS X impl does not use fd field, instead it uses this */
-struct darwin_dev_handle {
- usb_device_t **device;
- usb_interface_t **interface;
- int open;
-
- /* stored translation table for pipes to endpoints */
- int num_endpoints;
- unsigned char *endpoint_addrs;
-};
-
-static CFMutableDictionaryRef matchingDict;
-static IONotificationPortRef gNotifyPort;
-static mach_port_t masterPort = MACH_PORT_NULL;
-
-static void darwin_cleanup (void)
-{
- IONotificationPortDestroy(gNotifyPort);
- mach_port_deallocate(mach_task_self(), masterPort);
-}
-
-static char *darwin_error_str (int result) {
- switch (result) {
- case kIOReturnSuccess:
- return "no error";
- case kIOReturnNotOpen:
- return "device not opened for exclusive access";
- case kIOReturnNoDevice:
- return "no connection to an IOService";
- case kIOUSBNoAsyncPortErr:
- return "no async port has been opened for interface";
- case kIOReturnExclusiveAccess:
- return "another process has device opened for exclusive access";
- case kIOUSBPipeStalled:
- return "pipe is stalled";
- case kIOReturnError:
- return "could not establish a connection to the Darwin kernel";
- case kIOUSBTransactionTimeout:
- return "transaction timed out";
- case kIOReturnBadArgument:
- return "invalid argument";
- case kIOReturnAborted:
- return "transaction aborted";
- default:
- return "unknown error";
- }
-}
-
-/* not a valid errorno outside darwin.c */
-#define LUSBDARWINSTALL (ELAST+1)
-
-static int darwin_to_errno (int result) {
- switch (result) {
- case kIOReturnSuccess:
- return 0;
- case kIOReturnNotOpen:
- return EBADF;
- case kIOReturnNoDevice:
- case kIOUSBNoAsyncPortErr:
- return ENXIO;
- case kIOReturnExclusiveAccess:
- return EBUSY;
- case kIOUSBPipeStalled:
- return LUSBDARWINSTALL;
- case kIOReturnBadArgument:
- return EINVAL;
- case kIOUSBTransactionTimeout:
- return ETIMEDOUT;
- case kIOReturnError:
- default:
- return 1;
- }
-}
-
-static int usb_setup_iterator (io_iterator_t *deviceIterator)
-{
- int result;
-
- /* set up the matching dictionary for class IOUSBDevice and its subclasses.
- It will be consumed by the IOServiceGetMatchingServices call */
- if ((matchingDict = IOServiceMatching(kIOUSBDeviceClassName)) == NULL) {
- darwin_cleanup ();
-
- USB_ERROR_STR(-1, "libusb/darwin.c usb_setup_iterator: Could not create a matching dictionary.\n");
- }
-
- result = IOServiceGetMatchingServices(masterPort, matchingDict, deviceIterator);
- matchingDict = NULL;
-
- if (result != kIOReturnSuccess)
- USB_ERROR_STR (-darwin_to_errno (result), "libusb/darwin.c usb_setup_iterator: IOServiceGetMatchingServices: %s\n",
- darwin_error_str(result));
-
- return 0;
-}
-
-static usb_device_t **usb_get_next_device (io_iterator_t deviceIterator, UInt32 *locationp)
-{
- io_cf_plugin_ref_t *plugInInterface = NULL;
- usb_device_t **device;
- io_service_t usbDevice;
- long result, score;
-
- if (!IOIteratorIsValid (deviceIterator) || !(usbDevice = IOIteratorNext(deviceIterator)))
- return NULL;
-
- result = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID,
- kIOCFPlugInInterfaceID, &plugInInterface,
- &score);
-
- result = IOObjectRelease(usbDevice);
- if (result || !plugInInterface)
- return NULL;
-
- (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID),
- (LPVOID)&device);
-
- (*plugInInterface)->Stop(plugInInterface);
- IODestroyPlugInInterface (plugInInterface);
- plugInInterface = NULL;
-
- (*(device))->GetLocationID(device, locationp);
-
- return device;
-}
-
-int usb_os_open(usb_dev_handle *dev)
-{
- struct darwin_dev_handle *device;
-
- io_return_t result;
- io_iterator_t deviceIterator;
-
- usb_device_t **darwin_device;
-
- UInt32 location = *((UInt32 *)dev->device->dev);
- UInt32 dlocation;
-
- if (!dev)
- USB_ERROR(-ENXIO);
-
- if (masterPort == MACH_PORT_NULL)
- USB_ERROR(-EINVAL);
-
- device = calloc(1, sizeof(struct darwin_dev_handle));
- if (!device)
- USB_ERROR(-ENOMEM);
-
- if (usb_debug > 3)
- fprintf(stderr, "usb_os_open: %04x:%04x\n",
- dev->device->descriptor.idVendor,
- dev->device->descriptor.idProduct);
-
- if ((result = usb_setup_iterator (&deviceIterator)) < 0)
- return result;
-
- /* This port of libusb uses locations to keep track of devices. */
- while ((darwin_device = usb_get_next_device (deviceIterator, &dlocation)) != NULL) {
- if (dlocation == location)
- break;
-
- (*darwin_device)->Release(darwin_device);
- }
-
- IOObjectRelease(deviceIterator);
- device->device = darwin_device;
-
- if (device->device == NULL)
- USB_ERROR_STR (-ENOENT, "usb_os_open: %s\n", "Device not found!");
-
-#if !defined (LIBUSB_NO_SEIZE_DEVICE)
- result = (*(device->device))->USBDeviceOpenSeize (device->device);
-#else
- /* No Seize in OS X 10.0 (Darwin 1.4) */
- result = (*(device->device))->USBDeviceOpen (device->device);
-#endif
-
- if (result != kIOReturnSuccess) {
- switch (result) {
- case kIOReturnExclusiveAccess:
- if (usb_debug > 0)
- fprintf (stderr, "usb_os_open(USBDeviceOpenSeize): %s\n", darwin_error_str(result));
- break;
- default:
- (*(device->device))->Release (device->device);
- USB_ERROR_STR(-darwin_to_errno (result), "usb_os_open(USBDeviceOpenSeize): %s",
- darwin_error_str(result));
- }
-
- device->open = 0;
- } else
- device->open = 1;
-
- dev->impl_info = device;
- dev->interface = -1;
- dev->altsetting = -1;
-
- device->num_endpoints = 0;
- device->endpoint_addrs = NULL;
-
- return 0;
-}
-
-int usb_os_close(usb_dev_handle *dev)
-{
- struct darwin_dev_handle *device;
- io_return_t result;
-
- if (!dev)
- USB_ERROR(-ENXIO);
-
- if ((device = dev->impl_info) == NULL)
- USB_ERROR(-ENOENT);
-
- usb_release_interface(dev, dev->interface);
-
- if (usb_debug > 3)
- fprintf(stderr, "usb_os_close: %04x:%04x\n",
- dev->device->descriptor.idVendor,
- dev->device->descriptor.idProduct);
-
- if (device->open == 1)
- result = (*(device->device))->USBDeviceClose(device->device);
- else
- result = kIOReturnSuccess;
-
- /* device may not need to be released, but if it has to... */
- (*(device->device))->Release(device->device);
-
- if (result != kIOReturnSuccess)
- USB_ERROR_STR(-darwin_to_errno(result), "usb_os_close(USBDeviceClose): %s", darwin_error_str(result));
-
- free (device);
-
- return 0;
-}
-
-static int get_endpoints (struct darwin_dev_handle *device)
-{
- io_return_t ret;
-
- u_int8_t numep, direction, number;
- u_int8_t dont_care1, dont_care3;
- u_int16_t dont_care2;
-
- int i;
-
- if (device == NULL || device->interface == NULL)
- return -EINVAL;
-
- if (usb_debug > 1)
- fprintf(stderr, "libusb/darwin.c get_endpoints: building table of endpoints.\n");
-
- /* retrieve the total number of endpoints on this interface */
- ret = (*(device->interface))->GetNumEndpoints(device->interface, &numep);
- if ( ret ) {
- if ( usb_debug > 1 )
- fprintf ( stderr, "get_endpoints: interface is %p\n", device->interface );
-
- USB_ERROR_STR ( -ret, "get_endpoints: can't get number of endpoints for interface" );
- }
-
- free (device->endpoint_addrs);
- device->endpoint_addrs = calloc (sizeof (unsigned char), numep);
-
- /* iterate through pipe references */
- for (i = 1 ; i <= numep ; i++) {
- ret = (*(device->interface))->GetPipeProperties(device->interface, i, &direction, &number,
- &dont_care1, &dont_care2, &dont_care3);
-
- if (ret != kIOReturnSuccess) {
- fprintf (stderr, "get_endpoints: an error occurred getting pipe information on pipe %d\n",
- i );
- USB_ERROR_STR(-darwin_to_errno(ret), "get_endpoints(GetPipeProperties): %s", darwin_error_str(ret));
- }
-
- if (usb_debug > 1)
- fprintf (stderr, "get_endpoints: Pipe %i: DIR: %i number: %i\n", i, direction, number);
-
- device->endpoint_addrs[i - 1] = ((direction << 7 & USB_ENDPOINT_DIR_MASK) |
- (number & USB_ENDPOINT_ADDRESS_MASK));
- }
-
- device->num_endpoints = numep;
-
- if (usb_debug > 1)
- fprintf(stderr, "libusb/darwin.c get_endpoints: complete.\n");
-
- return 0;
-}
-
-static int claim_interface (usb_dev_handle *dev, int interface)
-{
- io_iterator_t interface_iterator;
- io_service_t usbInterface = IO_OBJECT_NULL;
- io_return_t result;
- io_cf_plugin_ref_t *plugInInterface = NULL;
-
- IOUSBFindInterfaceRequest request;
-
- struct darwin_dev_handle *device;
- long score;
- int current_interface;
-
- device = dev->impl_info;
-
- request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
- request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
- request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
- request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
-
- result = (*(device->device))->CreateInterfaceIterator(device->device, &request, &interface_iterator);
- if (result != kIOReturnSuccess)
- USB_ERROR_STR (-darwin_to_errno(result), "claim_interface(CreateInterfaceIterator): %s",
- darwin_error_str(result));
-
- for ( current_interface=0 ; current_interface <= interface ; current_interface++ ) {
- usbInterface = IOIteratorNext(interface_iterator);
- if ( usb_debug > 3 )
- fprintf ( stderr, "Interface %d of device is 0x%08x\n",
- current_interface, usbInterface );
- }
-
- current_interface--;
-
- /* the interface iterator is no longer needed, release it */
- IOObjectRelease(interface_iterator);
-
- if (!usbInterface) {
- u_int8_t nConfig; /* Index of configuration to use */
- IOUSBConfigurationDescriptorPtr configDesc; /* to describe which configuration to select */
- /* Only a composite class device with no vendor-specific driver will
- be configured. Otherwise, we need to do it ourselves, or there
- will be no interfaces for the device. */
-
- if ( usb_debug > 3 )
- fprintf ( stderr,"claim_interface: No interface found; selecting configuration\n" );
-
- result = (*(device->device))->GetNumberOfConfigurations ( device->device, &nConfig );
- if (result != kIOReturnSuccess)
- USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(GetNumberOfConfigurations): %s",
- darwin_error_str(result));
-
- if (nConfig < 1)
- USB_ERROR_STR(-ENXIO ,"claim_interface(GetNumberOfConfigurations): no configurations");
- else if ( nConfig > 1 && usb_debug > 0 )
- fprintf ( stderr, "claim_interface: device has more than one"
- " configuration, using the first (warning)\n" );
-
- if ( usb_debug > 3 )
- fprintf ( stderr, "claim_interface: device has %d configuration%s\n",
- (int)nConfig, (nConfig>1?"s":"") );
-
- /* Always use the first configuration */
- result = (*(device->device))->GetConfigurationDescriptorPtr ( (device->device), 0, &configDesc );
- if (result != kIOReturnSuccess) {
- if (device->open == 1) {
- (*(device->device))->USBDeviceClose ( (device->device) );
- (*(device->device))->Release ( (device->device) );
- }
-
- USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(GetConfigurationDescriptorPtr): %s",
- darwin_error_str(result));
- } else if ( usb_debug > 3 )
- fprintf ( stderr, "claim_interface: configuration value is %d\n",
- configDesc->bConfigurationValue );
-
- if (device->open == 1) {
- result = (*(device->device))->SetConfiguration ( (device->device), configDesc->bConfigurationValue );
-
- if (result != kIOReturnSuccess) {
- (*(device->device))->USBDeviceClose ( (device->device) );
- (*(device->device))->Release ( (device->device) );
-
- USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(SetConfiguration): %s",
- darwin_error_str(result));
- }
-
- dev->config = configDesc->bConfigurationValue;
- }
-
- request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
- request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
- request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
- request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
-
- /* Now go back and get the chosen interface */
- result = (*(device->device))->CreateInterfaceIterator(device->device, &request, &interface_iterator);
- if (result != kIOReturnSuccess)
- USB_ERROR_STR (-darwin_to_errno(result), "claim_interface(CreateInterfaceIterator): %s",
- darwin_error_str(result));
-
- for (current_interface = 0 ; current_interface <= interface ; current_interface++) {
- usbInterface = IOIteratorNext(interface_iterator);
-
- if ( usb_debug > 3 )
- fprintf ( stderr, "claim_interface: Interface %d of device is 0x%08x\n",
- current_interface, usbInterface );
- }
- current_interface--;
-
- /* the interface iterator is no longer needed, release it */
- IOObjectRelease(interface_iterator);
-
- if (!usbInterface)
- USB_ERROR_STR (-ENOENT, "claim_interface: interface iterator returned NULL");
- }
-
- result = IOCreatePlugInInterfaceForService(usbInterface,
- kIOUSBInterfaceUserClientTypeID,
- kIOCFPlugInInterfaceID,
- &plugInInterface, &score);
- /* No longer need the usbInterface object after getting the plug-in */
- result = IOObjectRelease(usbInterface);
- if (result || !plugInInterface)
- USB_ERROR(-ENOENT);
-
- /* Now create the device interface for the interface */
- result = (*plugInInterface)->QueryInterface(plugInInterface,
- CFUUIDGetUUIDBytes(InterfaceInterfaceID),
- (LPVOID) &device->interface);
-
- /* No longer need the intermediate plug-in */
- (*plugInInterface)->Stop(plugInInterface);
- IODestroyPlugInInterface (plugInInterface);
-
- if (result != kIOReturnSuccess)
- USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(QueryInterface): %s",
- darwin_error_str(result));
-
- if (!device->interface)
- USB_ERROR(-EACCES);
-
- if ( usb_debug > 3 )
- fprintf ( stderr, "claim_interface: Interface %d of device from QueryInterface is %p\n",
- current_interface, device->interface);
-
- /* claim the interface */
- result = (*(device->interface))->USBInterfaceOpen(device->interface);
- if (result)
- USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(USBInterfaceOpen): %s",
- darwin_error_str(result));
-
- result = get_endpoints (device);
-
- if (result) {
- /* this should not happen */
- usb_release_interface (dev, interface);
- USB_ERROR_STR ( result, "claim_interface: could not build endpoint table");
- }
-
- return 0;
-}
-
-int usb_set_configuration (usb_dev_handle *dev, int configuration)
-{
- struct darwin_dev_handle *device;
- io_return_t result;
- int interface;
-
- if ( usb_debug > 3 )
- fprintf ( stderr, "usb_set_configuration: called for config %x\n", configuration );
-
- if (!dev)
- USB_ERROR_STR ( -ENXIO, "usb_set_configuration: called with null device\n" );
-
- if ((device = dev->impl_info) == NULL)
- USB_ERROR_STR ( -ENOENT, "usb_set_configuration: device not properly initialized" );
-
- /* Setting configuration will invalidate the interface, so we need
- to reclaim it. First, dispose of existing interface, if any. */
- interface = dev->interface;
-
- if ( device->interface )
- usb_release_interface(dev, dev->interface);
-
- result = (*(device->device))->SetConfiguration(device->device, configuration);
-
- if (result)
- USB_ERROR_STR(-darwin_to_errno(result), "usb_set_configuration(SetConfiguration): %s",
- darwin_error_str(result));
-
- /* Reclaim interface */
- if (interface != -1)
- result = usb_claim_interface (dev, interface);
-
- dev->config = configuration;
-
- return result;
-}
-
-int usb_claim_interface(usb_dev_handle *dev, int interface)
-{
- struct darwin_dev_handle *device = dev->impl_info;
-
- io_return_t result;
-
- if ( usb_debug > 3 )
- fprintf ( stderr, "usb_claim_interface: called for interface %d\n", interface );
-
- if (!device)
- USB_ERROR_STR ( -ENOENT, "usb_claim_interface: device is NULL" );
-
- if (!(device->device))
- USB_ERROR_STR ( -EINVAL, "usb_claim_interface: device->device is NULL" );
-
- /* If we have already claimed an interface, release it */
- if ( device->interface )
- usb_release_interface(dev, dev->interface);
-
- result = claim_interface ( dev, interface );
- if ( result )
- USB_ERROR_STR ( result, "usb_claim_interface: couldn't claim interface" );
-
- dev->interface = interface;
-
- /* interface is claimed and async IO is set up: return 0 */
- return 0;
-}
-
-int usb_release_interface(usb_dev_handle *dev, int interface)
-{
- struct darwin_dev_handle *device;
- io_return_t result;
-
- if (!dev)
- USB_ERROR(-ENXIO);
-
- if ((device = dev->impl_info) == NULL)
- USB_ERROR(-ENOENT);
-
- /* interface is not open */
- if (!device->interface)
- return 0;
-
- result = (*(device->interface))->USBInterfaceClose(device->interface);
-
- if (result != kIOReturnSuccess)
- USB_ERROR_STR(-darwin_to_errno(result), "usb_release_interface(USBInterfaceClose): %s",
- darwin_error_str(result));
-
- result = (*(device->interface))->Release(device->interface);
-
- if (result != kIOReturnSuccess)
- USB_ERROR_STR(-darwin_to_errno(result), "usb_release_interface(Release): %s",
- darwin_error_str(result));
-
- device->interface = NULL;
-
- free (device->endpoint_addrs);
-
- device->num_endpoints = 0;
- device->endpoint_addrs = NULL;
-
- dev->interface = -1;
- dev->altsetting = -1;
-
- return 0;
-}
-
-int usb_set_altinterface(usb_dev_handle *dev, int alternate)
-{
- struct darwin_dev_handle *device;
- io_return_t result;
-
- if (!dev)
- USB_ERROR(-ENXIO);
-
- if ((device = dev->impl_info) == NULL)
- USB_ERROR(-ENOENT);
-
- /* interface is not open */
- if (!device->interface)
- USB_ERROR_STR(-EACCES, "usb_set_altinterface: interface used without being claimed");
-
- result = (*(device->interface))->SetAlternateInterface(device->interface, alternate);
-
- if (result)
- USB_ERROR_STR(result, "usb_set_altinterface: could not set alternate interface");
-
- dev->altsetting = alternate;
-
- result = get_endpoints (device);
- if (result) {
- /* this should not happen */
- USB_ERROR_STR ( result, "usb_set_altinterface: could not build endpoint table");
- }
-
- return 0;
-}
-
-/* simple function that figures out what pipeRef is associated with an endpoint */
-static int ep_to_pipeRef (struct darwin_dev_handle *device, int ep)
-{
- int i;
-
- if (usb_debug > 1)
- fprintf(stderr, "libusb/darwin.c ep_to_pipeRef: Converting ep address to pipeRef.\n");
-
- for (i = 0 ; i < device->num_endpoints ; i++)
- if (device->endpoint_addrs[i] == ep)
- return i + 1;
-
- /* No pipe found with the correct endpoint address */
- if (usb_debug > 1)
- fprintf(stderr, "libusb/darwin.c ep_to_pipeRef: No pipeRef found with endpoint address 0x%02x.\n", ep);
-
- return -1;
-}
-
-/* argument to handle multiple parameters to rw_completed */
-struct rw_complete_arg {
- UInt32 io_size;
- IOReturn result;
- CFRunLoopRef cf_loop;
-};
-
-static void rw_completed(void *refcon, io_return_t result, void *io_size)
-{
- struct rw_complete_arg *rw_arg = (struct rw_complete_arg *)refcon;
-
- if (usb_debug > 2)
- fprintf(stderr, "io async operation completed: %s, size=%lu, result=0x%08x\n", darwin_error_str(result),
- (UInt32)io_size, result);
-
- rw_arg->io_size = (UInt32)io_size;
- rw_arg->result = result;
-
- CFRunLoopStop(rw_arg->cf_loop);
-}
-
-static int usb_bulk_transfer (usb_dev_handle *dev, int ep, char *bytes, int size, int timeout,
- rw_async_func_t rw_async, rw_async_to_func_t rw_async_to)
-{
- struct darwin_dev_handle *device;
-
- io_return_t result = -1;
-
- CFRunLoopSourceRef cfSource;
- int pipeRef;
-
- struct rw_complete_arg rw_arg;
-
- u_int8_t transferType;
-
- /* None of the values below are used in libusb for bulk transfers */
- u_int8_t direction, number, interval;
- u_int16_t maxPacketSize;
-
- if (!dev)
- USB_ERROR_STR ( -ENXIO, "usb_bulk_transfer: Called with NULL device" );
-
- if ((device = dev->impl_info) == NULL)
- USB_ERROR_STR ( -ENOENT, "usb_bulk_transfer: Device not open" );
-
- /* interface is not open */
- if (!device->interface)
- USB_ERROR_STR(-EACCES, "usb_bulk_transfer: Interface used before it was opened");
-
-
- /* Set up transfer */
- if ((pipeRef = ep_to_pipeRef(device, ep)) < 0)
- USB_ERROR_STR ( -EINVAL, "usb_bulk_transfer: Invalid pipe reference" );
-
- (*(device->interface))->GetPipeProperties (device->interface, pipeRef, &direction, &number,
- &transferType, &maxPacketSize, &interval);
-
- (*(device->interface))->CreateInterfaceAsyncEventSource(device->interface, &cfSource);
- CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
-
- bzero((void *)&rw_arg, sizeof(struct rw_complete_arg));
- rw_arg.cf_loop = CFRunLoopGetCurrent();
- /* Transfer set up complete */
-
- if (usb_debug > 0)
- fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: Transfering %i bytes of data on endpoint 0x%02x\n",
- size, ep);
-
- /* Bulk transfer */
- if (transferType == kUSBInterrupt && usb_debug > 3)
- fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: USB pipe is an interrupt pipe. Timeouts will not be used.\n");
-
- if ( transferType != kUSBInterrupt && rw_async_to != NULL)
-
- result = rw_async_to (device->interface, pipeRef, bytes, size, timeout, timeout,
- (IOAsyncCallback1)rw_completed, (void *)&rw_arg);
- else
- result = rw_async (device->interface, pipeRef, bytes, size, (IOAsyncCallback1)rw_completed,
- (void *)&rw_arg);
-
- if (result == kIOReturnSuccess) {
- /* wait for write to complete */
- if (CFRunLoopRunInMode(kCFRunLoopDefaultMode, (timeout+999)/1000, true) == kCFRunLoopRunTimedOut) {
- (*(device->interface))->AbortPipe(device->interface, pipeRef);
- CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); /* Pick up aborted callback */
- if (usb_debug)
- fprintf(stderr, "usb_bulk_read: input timed out\n");
- }
- }
-
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
-
- /* Check the return code of both the write and completion functions. */
- if (result != kIOReturnSuccess || (rw_arg.result != kIOReturnSuccess &&
- rw_arg.result != kIOReturnAborted) ) {
- int error_code;
- char *error_str;
-
- if (result == kIOReturnSuccess) {
- error_code = darwin_to_errno (rw_arg.result);
- error_str = darwin_error_str (rw_arg.result);
- } else {
- error_code = darwin_to_errno(result);
- error_str = darwin_error_str (result);
- }
-
- if (transferType != kUSBInterrupt && rw_async_to != NULL)
- USB_ERROR_STR(-error_code, "usb_bulk_transfer (w/ Timeout): %s", error_str);
- else
- USB_ERROR_STR(-error_code, "usb_bulk_transfer (No Timeout): %s", error_str);
- }
-
- return rw_arg.io_size;
-}
-
-int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
-{
- int result;
- rw_async_to_func_t to_func = NULL;
- struct darwin_dev_handle *device;
-
- if (dev == NULL || dev->impl_info == NULL)
- return -EINVAL;
-
- device = dev->impl_info;
-
-#if !defined (LIBUSB_NO_TIMEOUT_INTERFACE)
- to_func = (*(device->interface))->WritePipeAsyncTO;
-#endif
-
- if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout,
- (*(device->interface))->WritePipeAsync, to_func)) < 0)
- USB_ERROR_STR (result, "usb_bulk_write: An error occured during write (see messages above)");
-
- return result;
-}
-
-int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
-{
- int result;
- rw_async_to_func_t to_func = NULL;
- struct darwin_dev_handle *device;
-
- if (dev == NULL || dev->impl_info == NULL)
- return -EINVAL;
-
- ep |= 0x80;
-
- device = dev->impl_info;
-
-#if !defined (LIBUSB_NO_TIMEOUT_INTERFACE)
- to_func = (*(device->interface))->ReadPipeAsyncTO;
-#endif
-
- if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout,
- (*(device->interface))->ReadPipeAsync, to_func)) < 0)
- USB_ERROR_STR (result, "usb_bulk_read: An error occured during read (see messages above)");
-
- return result;
-}
-
-/* interrupt endpoints seem to be treated just like any other endpoint under OSX/Darwin */
-int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
- int timeout)
-{
- return usb_bulk_write (dev, ep, bytes, size, timeout);
-}
-
-int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
- int timeout)
-{
- return usb_bulk_read (dev, ep, bytes, size, timeout);
-}
-
-int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
- int value, int index, char *bytes, int size, int timeout)
-{
- struct darwin_dev_handle *device = dev->impl_info;
-
- io_return_t result;
-
-#if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
- IOUSBDevRequestTO urequest;
-#else
- IOUSBDevRequest urequest;
-#endif
-
- if (usb_debug >= 3)
- fprintf(stderr, "usb_control_msg: %d %d %d %d %p %d %d\n",
- requesttype, request, value, index, bytes, size, timeout);
-
- bzero(&urequest, sizeof(urequest));
-
- urequest.bmRequestType = requesttype;
- urequest.bRequest = request;
- urequest.wValue = value;
- urequest.wIndex = index;
- urequest.wLength = size;
- urequest.pData = bytes;
-#if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
- urequest.completionTimeout = timeout;
- urequest.noDataTimeout = timeout;
-
- result = (*(device->device))->DeviceRequestTO(device->device, &urequest);
-#else
- result = (*(device->device))->DeviceRequest(device->device, &urequest);
-#endif
- if (result != kIOReturnSuccess)
- USB_ERROR_STR(-darwin_to_errno(result), "usb_control_msg(DeviceRequestTO): %s", darwin_error_str(result));
-
- /* Bytes transfered is stored in the wLenDone field*/
- return urequest.wLenDone;
-}
-
-int usb_os_find_busses(struct usb_bus **busses)
-{
- struct usb_bus *fbus = NULL;
-
- io_iterator_t deviceIterator;
- io_return_t result;
-
- usb_device_t **device;
-
- UInt32 location;
-
- char buf[20];
- int i = 1;
-
- /* Create a master port for communication with IOKit (this should
- have been created if the user called usb_init() )*/
- if (masterPort == MACH_PORT_NULL) {
- usb_init ();
-
- if (masterPort == MACH_PORT_NULL)
- USB_ERROR(-ENOENT);
- }
-
- if ((result = usb_setup_iterator (&deviceIterator)) < 0)
- return result;
-
- while ((device = usb_get_next_device (deviceIterator, &location)) != NULL) {
- struct usb_bus *bus;
-
- if (location & 0x00ffffff)
- continue;
-
- bus = calloc(1, sizeof(struct usb_bus));
- if (bus == NULL)
- USB_ERROR(-ENOMEM);
-
- sprintf(buf, "%03i", i++);
- bus->location = location;
-
- strncpy(bus->dirname, buf, sizeof(bus->dirname) - 1);
- bus->dirname[sizeof(bus->dirname) - 1] = 0;
-
- LIST_ADD(fbus, bus);
-
- if (usb_debug >= 2)
- fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname);
-
- (*(device))->Release(device);
- }
-
- IOObjectRelease(deviceIterator);
-
- *busses = fbus;
-
- return 0;
-}
-
-int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices)
-{
- struct usb_device *fdev = NULL;
-
- io_iterator_t deviceIterator;
- io_return_t result;
-
- usb_device_t **device;
-
- u_int16_t address;
- UInt32 location;
- UInt32 bus_loc = bus->location;
-
- /* for use in retrieving device description */
- IOUSBDevRequest req;
-
- /* a master port should have been created by usb_os_init */
- if (masterPort == MACH_PORT_NULL)
- USB_ERROR(-ENOENT);
-
- if ((result = usb_setup_iterator (&deviceIterator)) < 0)
- return result;
-
- /* Set up request for device descriptor */
- req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
- req.bRequest = kUSBRqGetDescriptor;
- req.wValue = kUSBDeviceDesc << 8;
- req.wIndex = 0;
- req.wLength = sizeof(IOUSBDeviceDescriptor);
-
-
- while ((device = usb_get_next_device (deviceIterator, &location)) != NULL) {
- unsigned char device_desc[DEVICE_DESC_LENGTH];
-
- result = (*(device))->GetDeviceAddress(device, (USBDeviceAddress *)&address);
-
- if (usb_debug >= 2)
- fprintf(stderr, "usb_os_find_devices: Found USB device at location 0x%08lx\n", location);
-
- /* first byte of location appears to be associated with the device's bus */
- if (location >> 24 == bus_loc >> 24) {
- struct usb_device *dev;
-
- dev = calloc(1, sizeof(struct usb_device));
- if (dev == NULL)
- USB_ERROR(-ENOMEM);
-
- dev->bus = bus;
-
- req.pData = device_desc;
- result = (*(device))->DeviceRequest(device, &req);
-
- usb_parse_descriptor(device_desc, "bbwbbbbwwwbbbb", &dev->descriptor);
-
- sprintf(dev->filename, "%03i-%04x-%04x-%02x-%02x", address,
- dev->descriptor.idVendor, dev->descriptor.idProduct,
- dev->descriptor.bDeviceClass, dev->descriptor.bDeviceSubClass);
-
- dev->dev = (USBDeviceAddress *)malloc(4);
- memcpy(dev->dev, &location, 4);
-
- LIST_ADD(fdev, dev);
-
- if (usb_debug >= 2)
- fprintf(stderr, "usb_os_find_devices: Found %s on %s at location 0x%08lx\n",
- dev->filename, bus->dirname, location);
- }
-
- /* release the device now */
- (*(device))->Release(device);
- }
-
- IOObjectRelease(deviceIterator);
-
- *devices = fdev;
-
- return 0;
-}
-
-int usb_os_determine_children(struct usb_bus *bus)
-{
- /* Nothing yet */
- return 0;
-}
-
-void usb_os_init(void)
-{
- if (masterPort == MACH_PORT_NULL) {
- IOMasterPort(masterPort, &masterPort);
-
- gNotifyPort = IONotificationPortCreate(masterPort);
- }
-}
-
-void usb_os_cleanup (void)
-{
- if (masterPort != MACH_PORT_NULL)
- darwin_cleanup ();
-}
-
-int usb_resetep(usb_dev_handle *dev, unsigned int ep)
-{
- struct darwin_dev_handle *device;
-
- io_return_t result = -1;
-
- int pipeRef;
-
- if (!dev)
- USB_ERROR(-ENXIO);
-
- if ((device = dev->impl_info) == NULL)
- USB_ERROR(-ENOENT);
-
- /* interface is not open */
- if (!device->interface)
- USB_ERROR_STR(-EACCES, "usb_resetep: interface used without being claimed");
-
- if ((pipeRef = ep_to_pipeRef(device, ep)) == -1)
- USB_ERROR(-EINVAL);
-
- result = (*(device->interface))->ResetPipe(device->interface, pipeRef);
-
- if (result != kIOReturnSuccess)
- USB_ERROR_STR(-darwin_to_errno(result), "usb_resetep(ResetPipe): %s", darwin_error_str(result));
-
- return 0;
-}
-
-int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
-{
- struct darwin_dev_handle *device;
-
- io_return_t result = -1;
-
- int pipeRef;
-
- if (!dev)
- USB_ERROR(-ENXIO);
-
- if ((device = dev->impl_info) == NULL)
- USB_ERROR(-ENOENT);
-
- /* interface is not open */
- if (!device->interface)
- USB_ERROR_STR(-EACCES, "usb_clear_halt: interface used without being claimed");
-
- if ((pipeRef = ep_to_pipeRef(device, ep)) == -1)
- USB_ERROR(-EINVAL);
-
- result = (*(device->interface))->ClearPipeStall(device->interface, pipeRef);
-
- if (result != kIOReturnSuccess)
- USB_ERROR_STR(-darwin_to_errno(result), "usb_clear_halt(ClearPipeStall): %s", darwin_error_str(result));
-
- return 0;
-}
-
-int usb_reset(usb_dev_handle *dev)
-{
- struct darwin_dev_handle *device;
-
- io_return_t result;
-
- if (!dev)
- USB_ERROR(-ENXIO);
-
- if ((device = dev->impl_info) == NULL)
- USB_ERROR(-ENOENT);
-
- if (!device->device)
- USB_ERROR_STR(-ENOENT, "usb_reset: no such device");
-
- result = (*(device->device))->ResetDevice(device->device);
-
- if (result != kIOReturnSuccess)
- USB_ERROR_STR(-darwin_to_errno(result), "usb_reset(ResetDevice): %s", darwin_error_str(result));
-
- return 0;
-}