📄 darwin.c
字号:
/* * 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#endiftypedef 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 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -