我正在努力掌握IOKit,我觉得我很接近,但还没有.请原谅我的困惑.
我设法编写了检测我的USB设备的代码(USB电缆末端的一个简单按钮,它有一个Windows驱动程序,但没有Mac驱动程序).
我按下按钮时试图获得某种回调.
当设备连接到USB或移除时,我设法收到回叫.现在,我试图找出按下按钮时如何获得通知,但我无法弄明白.文档对我来说非常混乱,因为IOKit似乎可以同时使用c ++和c,具体取决于你如何访问它(内核扩展或用户空间驱动程序,或类似的东西.不确定我有正确的术语.
我已经尝试添加一些方法来获取回调,当任何中断值发生变化时,您将在代码中看到.但没有任何反应.
这是我当前的AppDelegate.m文件以及设备上的USB Probe信息.
Low Speed device @ 5 (0x14100000): ............................................. Composite device: "DL100B Dream Cheeky Generic Controller" Port Information: 0x101a Number Of Endpoints (includes EP0): Device Descriptor Configuration Descriptor (current config) Length (and contents): 34 Number of Interfaces: 1 Configuration Value: 1 Attributes: 0x80 (bus-powered) MaxPower: 500 mA Interface #0 - HID Alternate Setting 0 Number of Endpoints 1 Interface Class: 3 (HID) Interface Subclass; 0 Interface Protocol: 0 HID Descriptor Endpoint 0x81 - Interrupt Input Address: 0x81 (IN) Attributes: 0x03 (Interrupt) Max Packet Size: 8 Polling Interval: 10 ms
App Delegate.m文件:
// // USBHIDAppDelegate.m // USBHID // // Created by Michael Dolinar on 12-05-02. // Copyright (c) 2012 __MyCompanyName__. All rights reserved. // #import "USBHIDAppDelegate.h" #import "IOKit/hid/IOHIDManager.h" #include#include #include #include @implementation USBHIDAppDelegate @synthesize window = _window; // New USB device specified in the matching dictionary has been added (callback function) static void Handle_DeviceMatchingCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef){ // Retrieve the device name & serial number NSString *devName = [NSString stringWithUTF8String: CFStringGetCStringPtr( IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR("Product")), kCFStringEncodingMacRoman)]; UInt32 serialString = CFStringGetCStringPtr( IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR("SerialNumber")), kCFStringEncodingMacRoman); NSString *devSerialNumber; if (serialString == 0) { devSerialNumber = @"No Serial Number"; } else { devSerialNumber = [NSString stringWithUTF8String:serialString]; } // Log the device reference, Name, Serial Number & device count NSLog(@"\nDevice added: %p\nModel: %@\nSerial Number:%@\nDevice count: %ld", inIOHIDDeviceRef, devName, devSerialNumber, USBDeviceCount(inSender)); //Open the device (Was missing) IOReturn err = IOHIDDeviceOpen(inIOHIDDeviceRef, 0);
//应该在这里检查错误......
IOHIDDeviceRegisterInputValueCallback(inIOHIDDeviceRef, Handle_IOHIDDeviceInputValueCallback, NULL);
//还必须在这里再次注册RunLoop ...还缺少IOHIDDeviceScheduleWithRunLoop(inIOHIDDeviceRef,CFRunLoopGetCurrent(),kCFRunLoopCommonModes);
} static void Handle_IOHIDDeviceInputValueCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDValueRef inIOHIDValueRef ) { NSLog(@"Value changed"); } // USB device specified in the matching dictionary has been removed (callback function) static void Handle_DeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef){ // Log the device ID & device count NSLog(@"\nDevice removed: %p\nDevice count: %ld", (void *)inIOHIDDeviceRef, USBDeviceCount(inSender)); IOHIDDeviceRegisterInputValueCallback(inIOHIDDeviceRef, NULL, NULL); //Remove callback } // Counts the number of devices in the device set (incudes all USB devices that match our dictionary) static long USBDeviceCount(IOHIDManagerRef HIDManager){ // The device set includes all USB devices that match our matching dictionary. Fetch it. CFSetRef devSet = IOHIDManagerCopyDevices(HIDManager); // The devSet will be NULL if there are 0 devices, so only try to count the devices if devSet exists if(devSet) return CFSetGetCount(devSet); // There were no matching devices (devSet was NULL), so return a count of 0 return 0; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application SInt32 idVendor = 0x1D34;//0x062A;//0x1d34; //0x1AAD; //// set vendor id SInt32 idProduct = 0x000D;//0x0000;//0x000d; //0x000F; //// set product id // Create an HID Manager IOHIDManagerRef HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); // Create a Matching Dictionary CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // Specify a device manufacturer in the Matching Dictionary CFDictionarySetValue(matchDict, CFSTR(kIOHIDVendorIDKey), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &idVendor)); CFDictionarySetValue(matchDict, CFSTR(kIOHIDProductKey), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &idProduct)); // Register the Matching Dictionary to the HID Manager IOHIDManagerSetDeviceMatching(HIDManager, matchDict); // Register a callback for USB device detection with the HID Manager IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, &Handle_DeviceMatchingCallback, NULL); // Register a callback fro USB device removal with the HID Manager IOHIDManagerRegisterDeviceRemovalCallback(HIDManager, &Handle_DeviceRemovalCallback, NULL); // Register the HID Manager on our app’s run loop IOHIDManagerScheduleWithRunLoop(HIDManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode); // Open the HID Manager IOReturn IOReturn = IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone); if(IOReturn) NSLog(@"IOHIDManagerOpen failed."); // Couldn't open the HID manager! TODO: proper error handling } @end
我甚至不确定设备是否正在发送任何东西......我尝试在7级中使用USB记录器进行记录,但只按下按钮似乎没有显示任何内容......我怎样才能确保它实际上正在工作?
更新:能够使用这个用于了解BigRedButton的Ruby Open Source项目来检测按钮按下.所以我知道它确实有效.我还重新编写了代码,仅在实际检测到设备时注册值更改,并在删除设备时将其删除.此时仍然没有.
更新2:让这个工作!两个问题......我没有打开设备进行读取,也没有在Current RunLoop上注册设备本身,这也是必需的.来自WWDC 2011的Userland设备访问的WWDC视频非常有用.我还必须说,我使用的BigRedBUtton可能不是一个标准设备,并且从未像计划那样工作,但我想要使用的实际设备就像一个魅力并且给我输入!因为WWDC视频,现在一切都很好!