Mac开发之HID通讯开发
1.Frameworks:IOKit.framework
2.导入头文件
#import <IOKit/hid/IOHIDLib.h>
3.初始化IOHIDManager
IOHIDManagerRef managerRef = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
4.进行配对设置,可以过滤其他USB设备。
1).无配对设备
IOHIDManagerSetDeviceMatching(managerRef, NULL);
2).单类设备配对
NSMutableDictionary* dict= [NSMutableDictionary dictionary];
[dict setValue:[NSNumber numberWithLong:pid] forKey:[NSString stringWithCString:kIOHIDProductIDKey encoding:NSUTF8StringEncoding]];
[dict setValue:[NSNumber numberWithLong:vid] forKey:[NSString stringWithCString:kIOHIDVendorIDKey encoding:NSUTF8StringEncoding]];
IOHIDManagerSetDeviceMatching(managerRef, (__bridge CFMutableDictionaryRef)dict);
3).多种设备配对设置
NSMutableArray *arr = [NSMutableArray array];
[arr addObject:dict];
IOHIDManagerSetDeviceMatchingMultiple(managerRef, (__bridge CFMutableArrayRef)arr);
5.注册插拔设备的callback
IOHIDManagerRegisterDeviceMatchingCallback(managerRef, &HandleDeviceMatchingCallback, NULL); IOHIDManagerRegisterDeviceRemovalCallback(managerRef, &HandleDeviceRemovalCallback, NULL);
6.加入RunLoop
IOHIDManagerScheduleWithRunLoop(managerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
7.打开IOHIDManager
IOReturn IOReturn = IOHIDManagerOpen(managerRef, kIOHIDOptionsTypeNone); if(kIOReturnSuccess != IOReturn) puts("IOHIDManagerOpen failed.");
8.实现插拔callback
void Handle_DeviceMatchingCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef) { CFTypeRef ref; int32_t nVendorID, nProductID; ref = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey)); if (CFGetTypeID(ref) == CFNumberGetTypeID()) { CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &nVendorID); } ref = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey)); if (CFGetTypeID(ref) == CFNumberGetTypeID()) { CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &nProductID); } NSLog(@"insert hid, vid is:%d, pid is:%d",nVendorID, nProductID); CFRelease(ref); } void Handle_DeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef) { CFTypeRef ref; int32_t nVendorID, nProductID; ref = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey)); if (CFGetTypeID(ref) == CFNumberGetTypeID()) { CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &nVendorID); } ref = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey)); if (CFGetTypeID(ref) == CFNumberGetTypeID()) { CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &nProductID); } NSLog(@"remove hid, vid is:%d, pid is:%d",nVendorID, nProductID); CFRelease(ref); }
9.插入设备获取到IOHIDDeviceRef inIOHIDDeviceRef后,打开IOHIDDeviceRef
IOReturn ret = IOHIDDeviceOpen(inIOHIDDeviceRef,options); if (ret != kIOReturnSuccess) { printf("Open device failed!\n");return; }
10.注册接收数据方法,即可接收数据
unsigned char InputBuffer[64];
IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), MyInputCallback, NULL);
11.接收数据callback,处理usb发送来的数据
unsigned char ReceiveData[64];
void MyInputCallback(void* context, IOReturn result, void* sender, IOHIDReportType type, uint32_t reportID, uint8_t *report,CFIndex reportLength) { memcpy(ReceiveData,report,sizeof(ReceiveData));
}
12.向USB设备发送指令
IOReturn ret = IOHIDDeviceSetReport(inIOHIDDeviceRef
, kIOHIDReportTypeOutput, 0, (uint8_t*)outbuffer, size);
if (ret != kIOReturnSuccess) {
PRINTMSG("发送hid数据失败,error number: %x\r\n",ret);
return ret;
}
13.断开设备
IOReturn ret = IOHIDDeviceClose(inIOHIDDeviceRef,0L); if (ret == kIOReturnSuccess) { NSLog(@"断开成功"); }
14.可能出现的问题
1)
TCC deny IOHIDDeviceOpen
Open device failed!
需要赋予输入监听权限
2)赋予权限后依然不能打开hid
需要sandbox页赋予USB权限