📄 darwin.c
字号:
/* * Darwin/MacOS X Support * * (c) 2002-2004 Nathan Hjelm <hjelmn@users.sourceforge.net> * * 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. * * this driver is EXPERIMENTAL, use at your own risk and e-mail me bug reports. * * 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 "usbi.h"#include <unistd.h>/* standard includes for darwin/os10 (IOKit) */#include <IOKit/IOCFBundle.h>#include <IOKit/usb/IOUSBLib.h>#include <IOKit/IOCFPlugIn.h>/* some defines *//* IOUSBInterfaceInferface */#if defined (IOUSBINTERFACE_FUNCS_197)#warning "libusb being compiled for 10.3 or higher"#define usb_interface_t IOUSBInterfaceInterface197#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID197#define InterfaceVersion 197#elif defined (IOUSBINTERFACE_FUNCS_190)#warning "libusb being compiled for 10.2 or higher"#define usb_interface_t IOUSBInterfaceInterface190#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID190#define InterfaceVersion 190#elif defined (IOUSBINTERFACE_FUNCS_182)#warning "libusb being compiled for 10.1 or higher"#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 timout 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 (IOUSBDEVICE_FUNCS_197)#define usb_device_t IOUSBDeviceInterface197#define DeviceInterfaceID kIOUSBDeviceInterfaceID197#define DeviceVersion 197#elif defined (IOUSBDEVICE_FUNCS_187)#define usb_device_t IOUSBDeviceInterface187#define DeviceInterfaceID kIOUSBDeviceInterfaceID187#define DeviceVersion 187#elif defined (IOUSBDEVICE_FUNCS_182)#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#define io_return_t IOReturn/* 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;};static CFRunLoopSourceRef runLoopSource;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 asyc 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 Darin kernel"; case kIOReturnBadArgument: return "invalid argument"; 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 kIOReturnError: default: return 1; }}int usb_os_open(usb_dev_handle *dev){ struct darwin_dev_handle *device; io_return_t result; io_iterator_t deviceIterator; io_service_t usbDevice; usb_device_t **darwin_device; IOCFPlugInInterface **plugInInterface = NULL; long score; UInt16 address, vendor; UInt32 location = *((UInt32 *)dev->device->dev); UInt32 dlocation; if (!dev) USB_ERROR(-ENXIO); if (!masterPort) 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); /* 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(-ENOMEM); } result = IOServiceGetMatchingServices(masterPort, matchingDict, &deviceIterator); matchingDict = NULL; if (result != kIOReturnSuccess) USB_ERROR_STR(-darwin_to_errno (result), "usb_os_open(IOServiceGetMatchingServices): %s", darwin_error_str(result)); while (IOIteratorIsValid (deviceIterator) && (usbDevice = IOIteratorNext(deviceIterator))) { /* Create an intermediate plug-in */ result = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); result = IOObjectRelease(usbDevice); if (result || !plugInInterface) continue; (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID), (LPVOID)&darwin_device); (*plugInInterface)->Stop(plugInInterface); IODestroyPlugInInterface (plugInInterface); plugInInterface = NULL; if (!darwin_device) continue; result = (*(darwin_device))->GetLocationID(darwin_device, (UInt32 *)&dlocation); if (dlocation == location) { device->device = darwin_device; break; } (*darwin_device)->Release(darwin_device); } IOObjectRelease(deviceIterator);#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; 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 claim_interface ( struct darwin_dev_handle *device, int interface )static int claim_interface ( usb_dev_handle *dev, int interface ){ io_iterator_t interface_iterator; io_service_t usbInterface; struct darwin_dev_handle *device; io_return_t result; IOUSBFindInterfaceRequest request; IOCFPlugInInterface **plugInInterface = NULL; 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%x\n", current_interface, (void *)usbInterface ); } current_interface--; /* the interface iterator is no longer needed, release it */ IOObjectRelease(interface_iterator); if (!usbInterface) { UInt8 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 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -