mac 下读写非hid的usb设备

来源:互联网 发布:数控车床攻丝编程实例 编辑:程序博客网 时间:2024/05/12 11:43

DeviceObject.h


#import <Foundation/Foundation.h>#include <IOKit/usb/IOUSBLib.h>#include <IOKit/IOCFPlugIn.h>@interface DeviceObject : NSObject@property(nonatomic,assign)io_object_t              notification;@property(nonatomic,assign)IOUSBInterfaceInterface  **interface;@property(nonatomic,assign)UInt32                   locationID;@property(nonatomic,assign)CFStringRefdeviceName;@property(nonatomic,assign)IOUSBDeviceInterface     **dev;@property(nonatomic,assign)UInt8                    pipeIn;@property(nonatomic,assign)UInt8                    pipeOut;@property(nonatomic,assign)UInt16                   maxPacketSizeIn;@property(nonatomic,assign)UInt16                   maxPacketSizeOut;@end


DeviceObject.m


#import "DeviceObject.h"@implementation DeviceObject@synthesize notification;@synthesize interface;@synthesize locationID;@synthesize deviceName;@synthesize dev;@synthesize pipeIn;@synthesize pipeOut;@synthesize maxPacketSizeIn;@synthesize maxPacketSizeOut;@end


UsbMonitor.h



#import <Foundation/Foundation.h>#include <IOKit/IOKitLib.h>#include <IOKit/IOMessage.h>#include <IOKit/IOCFPlugIn.h>#include <IOKit/usb/IOUSBLib.h>#import "DeviceObject.h"@protocol UsbMonitorDelegate <NSObject>@optional- (void)usbDidPlunIn:(DeviceObject*)usbObject;- (void)usbDidRemove:(DeviceObject*)usbObject;@end@interface UsbMonitor : NSObject {}@property(nonatomic,strong)NSMutableArray* arrayDevices;@property(nonatomic,strong)id<UsbMonitorDelegate> delegate;+ (UsbMonitor *)sharedUsbMonitorManager;- (id)initWithVID:(long)vid withPID:(long)pid;- (id)initWithVID:(long)vid withPID:(long)pid withDelegate:(id<UsbMonitorDelegate>)gate;- (DeviceObject*)getObjectByID:(long)localid;- (IOReturn)WriteSync:(DeviceObject*)pDev buffer:(char*) writeBuffer size:(unsigned int)size;- (IOReturn)WriteAsync:(DeviceObject*)pDev buffer:(char*)writeBuffer size:(unsigned int)size;- (IOReturn)ReadSync:(DeviceObject*)pDev buffer:(char*)buff size:(unsigned int)size;- (IOReturn)ReadAsync:(DeviceObject*)pDev buffer:(char*)buff size:(unsigned int)size;- (NSMutableArray*)getDeviceArray;@end


UsbMonitor.m


#import "UsbMonitor.h"@implementation UsbMonitor@synthesize arrayDevices;@synthesize delegate;static UsbMonitor *sharedInstance = nil;IONotificationPortRefgNotifyPort;io_iterator_tgAddedIter;CFRunLoopRefgRunLoop;void SignalHandler(int sigraised) {    fprintf(stderr, "\nInterrupted.\n");    exit(0);}void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) {    kern_return_tkr;    DeviceObject*privateDataRef = (__bridge DeviceObject *) refCon;        if (messageType == kIOMessageServiceIsTerminated) {        for (DeviceObject* usbObj in [UsbMonitor sharedUsbMonitorManager].arrayDevices) {            if (usbObj.locationID == privateDataRef.locationID) {                NSLog(@"delete id=%08x",usbObj.locationID);                [[UsbMonitor sharedUsbMonitorManager].arrayDevices removeObject:usbObj];                break;            }        }                if ([[UsbMonitor sharedUsbMonitorManager].delegate respondsToSelector:@selector(usbDidRemove:)]) {            [[UsbMonitor sharedUsbMonitorManager].delegate usbDidRemove:privateDataRef];        }                CFRelease(privateDataRef.deviceName);                if (privateDataRef.interface) {            (*(privateDataRef.interface))->USBInterfaceClose(privateDataRef.interface);            (*(privateDataRef.interface))->Release(privateDataRef.interface);        }                if (privateDataRef.dev) {            (*(privateDataRef.dev))->USBDeviceClose(privateDataRef.dev);            kr = (*privateDataRef.dev)->Release(privateDataRef.dev);        }                kr = IOObjectRelease(privateDataRef.notification);    }}void DeviceAdded(void *refCon, io_iterator_t iterator) {    kern_return_tkr;    io_service_tusbDevice;    IOCFPlugInInterface**plugInInterface = NULL;    SInt32score;    HRESULT res;        while ((usbDevice = IOIteratorNext(iterator))) {        io_name_tdeviceName;        CFStringRefdeviceNameAsCFString;        DeviceObject*privateDataRef = [[DeviceObject alloc]init];        UInt32locationID;                kr = IORegistryEntryGetName(usbDevice, deviceName);        if (KERN_SUCCESS != kr) {            deviceName[0] = '\0';        }                deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault,deviceName,kCFStringEncodingASCII);        //NSLog(@"deviceName:%@",deviceNameAsCFString);                privateDataRef.deviceName = deviceNameAsCFString;        kr = IOCreatePlugInInterfaceForService(usbDevice,kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,&plugInInterface, &score);                if ((kIOReturnSuccess != kr) || !plugInInterface) {            NSLog(@"IOCreatePlugInInterfaceForService returned 0x%08x.",kr);            continue;        }                IOUSBDeviceInterface     **oneDev = NULL;        res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),(LPVOID*)&oneDev);        privateDataRef.dev = oneDev;                (*plugInInterface)->Release(plugInInterface);        if (res || privateDataRef.dev == NULL) {            NSLog(@"QueryInterface returned %d.\n", (int)res);            continue;        }                kr = (*privateDataRef.dev)->GetLocationID(privateDataRef.dev, &locationID);        if (KERN_SUCCESS != kr) {            NSLog(@"GetLocationID returned 0x%08x.\n", kr);            continue;        } else {            NSLog(@"Location ID: 0x%08x", locationID);        }        privateDataRef.locationID = locationID;                kr = (*privateDataRef.dev)->USBDeviceOpen(privateDataRef.dev);        if(kr != kIOReturnSuccess) {            NSLog(@"Usb Open Fail!");            (*privateDataRef.dev)->USBDeviceClose(privateDataRef.dev);            (void) (*privateDataRef.dev)->Release(privateDataRef.dev);            privateDataRef.dev = NULL;            continue;        }                //configure device        UInt8                numConfig;        IOUSBConfigurationDescriptorPtr configDesc;                //Get the number of configurations.        kr = (*privateDataRef.dev)->GetNumberOfConfigurations(privateDataRef.dev, &numConfig);        if(numConfig == 0)            continue;                //Get the configuration descriptor for index 0        kr = (*privateDataRef.dev)->GetConfigurationDescriptorPtr(privateDataRef.dev, 0, &configDesc);        if(kr != kIOReturnSuccess) {            NSLog(@"Unable to get configuration descriptor for index 0 (err = %08x)\n",kr);            continue;        }        kr = [[UsbMonitor sharedUsbMonitorManager] FindUSBInterface:privateDataRef];        if (kr != kIOReturnSuccess) {            NSLog(@"Interface Open Fail!");            (*privateDataRef.dev)->USBDeviceClose(privateDataRef.dev);            (*privateDataRef.dev)->Release(privateDataRef.dev);            privateDataRef.dev = NULL;            continue ;        }                io_object_t              oneIter;        kr = IOServiceAddInterestNotification(gNotifyPort,usbDevice,kIOGeneralInterest,DeviceNotification,(__bridge void*)privateDataRef,&oneIter);        privateDataRef.notification = oneIter;                if (KERN_SUCCESS != kr) {            NSLog(@"IOServiceAddInterestNotification returned 0x%08x", kr);        }                kr = IOObjectRelease(usbDevice);    }}void usbMonitorCallBack(void *refcon, IOReturn result, void *arg0) {    if (result == kIOReturnSuccess && refcon) {        //u32 *pLen = (u32 *)refcon;        //*pLen = reinterpret_cast<long>arg0;    }    NSLog(@"read and write callback!");    CFRunLoopStop(CFRunLoopGetCurrent());}+ (UsbMonitor *)sharedUsbMonitorManager {    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        if (sharedInstance == nil)            sharedInstance = [(UsbMonitor *)[super allocWithZone:NULL] init];    });    return sharedInstance;}+ (id)allocWithZone:(NSZone *)zone {    return [self sharedUsbMonitorManager];}- (id)copyWithZone:(NSZone *)zone {    return self;}- (id)initWithVID:(long)vid withPID:(long)pid {    self = [super init];    if (self) {        arrayDevices = [NSMutableArray new];                CFMutableDictionaryRef matchingDict;        CFRunLoopSourceRefrunLoopSource;        CFNumberRefnumberRef;        kern_return_tkr;        longusbVendor = vid;        longusbProduct = pid;                matchingDict = IOServiceMatching(kIOUSBDeviceClassName);        if (matchingDict == NULL) {            return nil;        }                numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor);        CFDictionarySetValue(matchingDict,CFSTR(kUSBVendorID),numberRef);        CFRelease(numberRef);                numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct);        CFDictionarySetValue(matchingDict,CFSTR(kUSBProductID),numberRef);        CFRelease(numberRef);        numberRef = NULL;                gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);        runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);                gRunLoop = CFRunLoopGetCurrent();        CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode);                kr = IOServiceAddMatchingNotification(gNotifyPort,kIOFirstMatchNotification,matchingDict,DeviceAdded,NULL,&gAddedIter);                DeviceAdded(NULL, gAddedIter);                CFRunLoopRun();            }    return self;}- (id)initWithVID:(long)vid withPID:(long)pid withDelegate:(id<UsbMonitorDelegate>)gate {    self = [super init];    if (self) {        arrayDevices = [NSMutableArray new];                CFMutableDictionaryRef matchingDict;        CFRunLoopSourceRefrunLoopSource;        CFNumberRefnumberRef;        kern_return_tkr;        longusbVendor = vid;        longusbProduct = pid;        delegate = gate;//        sig_toldHandler;//        //        oldHandler = signal(SIGINT, SignalHandler);//        if (oldHandler == SIG_ERR) {//            fprintf(stderr, "Could not establish new signal handler.");//        }                matchingDict = IOServiceMatching(kIOUSBDeviceClassName);        if (matchingDict == NULL) {            return nil;        }                numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor);        CFDictionarySetValue(matchingDict,CFSTR(kUSBVendorID),numberRef);        CFRelease(numberRef);                numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct);        CFDictionarySetValue(matchingDict,CFSTR(kUSBProductID),numberRef);        CFRelease(numberRef);        numberRef = NULL;                gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);        runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);                gRunLoop = CFRunLoopGetCurrent();        CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode);                kr = IOServiceAddMatchingNotification(gNotifyPort,kIOFirstMatchNotification,matchingDict,DeviceAdded,NULL,&gAddedIter);                DeviceAdded(NULL, gAddedIter);                CFRunLoopRun();    }    return self;}-(void)dealloc {    for (DeviceObject* dev in arrayDevices) {        (*(dev.interface))->USBInterfaceClose(dev.interface);        (*(dev.interface))->Release(dev.interface);        (*(dev.dev))->USBDeviceClose(dev.dev);        (*(dev.dev))->Release(dev.dev);    }    [arrayDevices removeAllObjects];}-(IOReturn) FindUSBInterface:(DeviceObject*)usbObject {    IOReturn                        kr = kIOReturnError;    IOUSBFindInterfaceRequest       request;    io_iterator_t                   iterator;    io_service_t                    usbInterface;    IOCFPlugInInterface             **plugInInterface = NULL;    IOUSBInterfaceInterface         **interface = NULL;    HRESULT                         result;    SInt32                          score;    UInt8                           interfaceNumEndpoints;    UInt8                           pipeRef;    UInt16                          maxPacketSize = 0;    UInt8                           pipeIn = 0xff;    UInt8                           pipeOut = 0xff;    UInt16                          maxPacketSizeIn = 0;    UInt16                          maxPacketSizeOut = 0;        //Iterate all usb interface    request.bInterfaceClass = kIOUSBFindInterfaceDontCare;    request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;    request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;    request.bAlternateSetting = kIOUSBFindInterfaceDontCare;        //Get an iterator for the interfaces on the device    kr = (*usbObject.dev)->CreateInterfaceIterator(usbObject.dev, &request, &iterator);    if(kr != kIOReturnSuccess) {        NSLog(@"Unable to CreateInterfaceIterator %08x\n", kr);        return kr;    }        kr = kIOReturnError;    while((usbInterface = IOIteratorNext(iterator))) {        pipeIn = 0xff;        pipeOut = 0xff;        kr = IOCreatePlugInInterfaceForService(usbInterface,                                               kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID,                                               &plugInInterface, &score);        kr = IOObjectRelease(usbInterface);        if(kr != kIOReturnSuccess || !plugInInterface) {            NSLog(@"Unable to create a plug-in (%08x)\n", kr);            break;        }                result = (*plugInInterface)->QueryInterface(plugInInterface,                           CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID *)&interface);        IODestroyPlugInInterface(plugInInterface);        if(result || !interface) {            NSLog(@"Unable to create a interface for the device interface %08x\n",(int)result);            break;        }        //kr = (*interface)->USBInterfaceClose(interface);        kr = (*interface)->USBInterfaceOpen(interface);        if(kr != kIOReturnSuccess) {            NSLog(@"Unable to open interface for the device interface %08x\n", kr);            (*interface)->USBInterfaceClose(interface);            (void) (*interface)->Release(interface);            interface = NULL;            break;        }        kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);        if(kr != kIOReturnSuccess) {            (void) (*interface)->USBInterfaceClose(interface);            (void) (*interface)->Release(interface);            interface = NULL;            break;        }        for(pipeRef = 1; pipeRef <= interfaceNumEndpoints; pipeRef++) {            IOReturn     kr2;            UInt8        direction;            UInt8        number;            UInt8        transferType;            UInt8        interval;                        kr2 = (*interface)->GetPipeProperties(interface, pipeRef, &direction,&number, &transferType, &maxPacketSize, &interval);            if(kr2 != kIOReturnSuccess) {                NSLog(@"Unable to get properties of pipe %d (%08x)\n",pipeRef, kr2);            } else {                if(transferType == kUSBBulk) {                    if(direction == kUSBIn) {                        pipeIn = pipeRef;                        maxPacketSizeIn = maxPacketSize;                    }                    else if(direction == kUSBOut) {                        pipeOut = pipeRef;                        maxPacketSizeOut = maxPacketSize;                    }                }            }        }        if (pipeIn != 0xff && pipeOut != 0xff) {            usbObject.interface = interface;            usbObject.pipeIn = pipeIn;            usbObject.pipeOut = pipeOut;            usbObject.maxPacketSizeIn = maxPacketSizeIn;            usbObject.maxPacketSizeOut = maxPacketSizeOut;            BOOL isIn = NO;            for (DeviceObject* obj in arrayDevices) {                if (obj.locationID == usbObject.locationID) {                    isIn = YES;                    break ;                }            }            if (!isIn) {                [arrayDevices addObject:usbObject];            }            if ([delegate respondsToSelector:@selector(usbDidPlunIn:)]) {                [delegate usbDidPlunIn:usbObject];            }            return kIOReturnSuccess;        }        (*interface)->USBInterfaceClose(interface);        (*interface)->Release(interface);        interface = NULL;    }    return kr;}- (DeviceObject*)getObjectByID:(long)localid {    for (DeviceObject* obj in arrayDevices) {        if (obj.locationID == localid) {            return obj;        }    }    return nil;}//同步-(IOReturn)WriteSync:(DeviceObject*)pDev buffer:(char*) writeBuffer size:(unsigned int)size{    if (pDev && pDev.interface) {        if(size <= pDev.maxPacketSizeOut) {            return [self WriteAsync:pDev buffer:writeBuffer size:size];        }        kern_return_t kr = 0;        char *tmp = writeBuffer;        unsigned int nWrite = (size > pDev.maxPacketSizeOut ? pDev.maxPacketSizeOut : size);        unsigned int nLeft = size;        while(1) {            if((int)nLeft <= 0) {                break;            }            kr = (*(pDev.interface))->WritePipe(pDev.interface,pDev.pipeOut, (void *)tmp, nWrite);            if(kr != kIOReturnSuccess)                break;            tmp += nWrite;            nLeft -= nWrite;            nWrite = (nLeft > pDev.maxPacketSizeOut ? pDev.maxPacketSizeOut : nLeft);        }        return kr;    }        return kIOReturnNoDevice;}//异步-(IOReturn)WriteAsync:(DeviceObject*)pDev buffer:(char*)writeBuffer size:(unsigned int)size {    if (pDev == nil||pDev.interface == nil) {        return kIOReturnNoDevice;    }        IOReturn                  err;    CFRunLoopSourceRef        cfSource;    unsigned int*             pWrite;        err = (*(pDev.interface))->CreateInterfaceAsyncEventSource(pDev.interface, &cfSource);    if (err) {        NSLog(@"transferData: unable to create event source, err = %08x\n", err);        return err;    }    CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);        err = (*(pDev.interface))->WritePipeAsync(pDev.interface, pDev.pipeOut, (void *)writeBuffer, size,                                         (IOAsyncCallback1)usbMonitorCallBack, (void*)pWrite);    if (err != kIOReturnSuccess) {        NSLog(@"transferData: WritePipeAsyncFailed, err = %08x\n", err);        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);        *pWrite = 0;        return err;    }        CFRunLoopRun();    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);        return err;}-(IOReturn)ReadSync:(DeviceObject*)pDev buffer:(char*)buff size:(unsigned int)size {    if (pDev && pDev.interface) {        if(sizeof(buff) <= pDev.maxPacketSizeIn) {            return [self ReadAsync:pDev buffer:buff size:size];        }        kern_return_t kr = 0;        UInt32 nRead = pDev.maxPacketSizeIn;        unsigned int nLeft = size;        char *tmp = (char *)buff;                while(1) {            if((int)nLeft <= 0)                break;                        kr = (*(pDev.interface))->ReadPipe(pDev.interface,                   pDev.pipeIn, (void *)tmp, &nRead);            if(kr != kIOReturnSuccess) {                printf("transferData: Readsync Failed, err = %08x\n", kr);                break;            }                        tmp += nRead;            nLeft -= nRead;            nRead = pDev.maxPacketSizeIn;        }        int nRet = ((int)nLeft > 0 ? nLeft : 0);        size = size - nRet;        return kr;    }    return kIOReturnNoDevice;}-(IOReturn)ReadAsync:(DeviceObject*)pDev buffer:(char*)buff size:(unsigned int)size {    if (pDev == nil||pDev.interface == nil) {        return kIOReturnNoDevice;    }        IOReturn                    err;    CFRunLoopSourceRef          cfSource;    unsigned int*               pRead;        err = (*(pDev.interface))->CreateInterfaceAsyncEventSource(pDev.interface, &cfSource);    if (err) {        NSLog(@"transferData: unable to create event source, err = %08x\n", err);        return err;    }    CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);        err = (*(pDev.interface))->ReadPipeAsync(pDev.interface, pDev.pipeIn, buff, size,(IOAsyncCallback1)usbMonitorCallBack, (void*)pRead);    if (err != kIOReturnSuccess) {        NSLog(@"transferData: size %u, ReadAsyncFailed, err = %08x\n", size, err);        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);        pRead = nil;        pDev = nil;        return err;    }        CFRunLoopRun();    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);        return err;}- (NSMutableArray*)getDeviceArray {    return arrayDevices;}@end


2 0