gpt4 book ai didi

cocoa - 使用中断输入端点使用 IOKit 获取回调

转载 作者:行者123 更新时间:2023-12-03 16:11:17 27 4
gpt4 key购买 nike

我正在尝试掌握 IOKit,我觉得我已经很接近了,但还没有达到目标。所以请原谅我的困惑。

我已经成功编写了检测我的 USB 设备的代码(USB 电缆末端的一个简单按钮,有 Windows 驱动程序,但没有 Mac 驱动程序)。

我试图在按下按钮时获得某种回调。

当设备连接到 USB 或移除时,我设法收到回调。现在,我试图找出如何在按下按钮时获得通知,但我无法弄清楚。该文档让我感到非常困惑,因为 IOKit 似乎可以使用 c++ 和 c 语言,具体取决于您访问它的方式(内核扩展或用户空间驱动程序,或类似的东西。不确定我是否有正确的术语。

我尝试添加几个方法来在任何中断值发生变化时获取回调,正如您将在代码中看到的那样。但什么也没发生。

这是我当前的 AppDelegate.m 文件以及设备上的 USB 探针信息。

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 <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/usb/USBSpec.h>

@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 记录器进行记录,但仅按下按钮似乎没有显示任何内容...我如何确定它是实际工作吗?

更新:能够使用 this Ruby Open Source project 检测按钮按下情况对于我用来学习这一点的 BigRedButton。所以我知道它确实有效。我还修改了代码,仅在实际检测到设备时才注册值更改,并在设备被删除时将其删除。此时仍然什么都没有。

更新 2:让它发挥作用!有两个问题...我没有打开设备进行读取,也没有在当前 RunLoop 上注册设备本身,这也是必需的。 WWDC 2011 上有关 Userland 设备访问的精彩 WWDC 视频给了我很大帮助。我还必须说,我使用的 BigRedBUtton 可能不是一个标准设备,并且从未按计划工作,但我想要使用的实际设备就像一个魅力,并为我提供输入!多亏了 WWDC 视频,现在一切都好了!

最佳答案

最后,现在我已经打开设备并将设备安排在当前运行循环上,上面的代码就可以工作了。此外,更换设备使我能够使用另一台设备,该设备似乎提供了更可预测的体验来改变其值。我建议任何对此感兴趣的人观看 WWDC 2011 上的 Userland Device Access 视频,以深入了解其工作原理(视频大约 30 分钟)

更新:设备 react 不同的原因有点复杂。首先,每个 USB HID 设备可以有多个“配置”,并且默认的一个可能未启用。你必须明确地这样做。然后,第二部分是关于理解从设备发送的值。这是通过理解“HID 设备报告描述符”来完成的,“HID 设备报告描述符”详细描述了返回的每种值(称为报告)及其位和字节的排列方式。

在 OS X 上,一个很好的读物是 New HID Manager APIs for Mac OS X version 10.5技术说明。虽然它可以追溯到 10.5,但它是最新版本,包含所有适当的调用,可以更好地理解这一切是如何工作的。

此外,要了解描述符,this tutorial很有帮助。

关于cocoa - 使用中断输入端点使用 IOKit 获取回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20600349/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com