简体   繁体   English

如何使用 IOKit 写入 IOHIDDevice 端点

[英]How to write to IOHIDDevice endpoint with IOKit

I'm writing a desktop app for Mac OS Catalina.我正在为 Mac OS Catalina 编写一个桌面应用程序。 GPL licensed for now.目前 GPL 许可。 I might make it MIT licensed in the future, but that's secondary.将来我可能会使其获得 MIT 许可,但这是次要的。 It is written in Swift and supports some gamepads using user space IOKit.它是用 Swift 编写的,并支持一些使用用户空间 IOKit 的游戏手柄。 I got it working for Dualshock 4 and Xbox 360 controller using HID APIs.我使用 HID API 让它适用于 Dualshock 4 和 Xbox 360 controller。 Now I'm implementing support for the Xbox One controller, but it needs to receive a byte sequence before it starts sending reports (0x05, 0x20).现在我正在实现对 Xbox One controller 的支持,但它需要在开始发送报告(0x05、0x20)之前接收一个字节序列。 I saw this in several C/C++ kext projects but I'm struggling to figure out how to do this within my app in user space.我在几个 C/C++ kext 项目中看到了这一点,但我正在努力弄清楚如何在我的应用程序中的用户空间中做到这一点。 I'm able to get an IOHIDDevice but I couldn't figure out how to get an endpoint from there.我能够获得一个 IOHIDDevice,但我不知道如何从那里获得一个端点。 Can this even be done from a HID level or do I need to use a lower level API like USB or Bluetooth?这甚至可以从 HID 级别完成,还是我需要使用较低级别的 API,例如 USB 或蓝牙? I wanted to avoid using libusb just for this since I already got it working with other controllers.我想避免为此使用 libusb,因为我已经让它与其他控制器一起使用。

Other suggestion I found was on this question: Gamepad and joystick support on Mac OS X in user space but no sample code for Mac was provided.我发现的其他建议是关于这个问题: Gamepad and joystick support on Mac OS X in user space但没有提供 Mac 的示例代码。 And replacing a device descriptor sounds a bit overkill for me just to accomplish this.替换设备描述符对我来说听起来有点矫枉过正。 Also, it suggests libusb.此外,它建议使用 libusb。

Some parts of my code:我的代码的某些部分:

let hidManager = IOHIDManagerCreate(kCFAllocatorDefault, IOOptionBits(kIOHIDOptionsTypeNone))
let deviceCriteria:NSArray = [
    [
        kIOHIDDeviceUsagePageKey: kHIDPage_GenericDesktop,
        kIOHIDDeviceUsageKey: kHIDUsage_GD_GamePad
    ]
]
IOHIDManagerSetDeviceMatchingMultiple(hidManager, deviceCriteria)
IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetCurrent(), CFRunLoopMode.defaultMode.rawValue)
IOHIDManagerOpen(hidManager, IOOptionBits(kIOHIDOptionsTypeNone))
IOHIDManagerRegisterDeviceMatchingCallback(...)

func hidDeviceAddedCallback(_ result:IOReturn, sender:UnsafeMutableRawPointer, device:IOHIDDevice) {
    // from here I usually send hid reports using IOHIDDeviceSetReport(device, kIOHIDReportTypeOutput, etc...)
    // but now I need to write directly to and endpoint of an interface
}

You can grab a reference to the IOService object corresponding to an IOHIDDevice using IOHIDDeviceGetService() .您可以使用IOHIDDeviceGetService()获取与 IOHIDDevice 对应的IOService IOHIDDevice的引用。 You can then walk up the I/O registry provider chain to find the underlying IOUSBInterface / IOUSBHostInterface object.然后,您可以沿着 I/O 注册表提供程序链查找底层IOUSBInterface / IOUSBHostInterface object。 However, the generic HID driver will presumably have acquired exclusive access to the USB interface, so submitting a transfer on the pipe presumably won't be permitted without kicking off the HID driver first.但是,通用 HID 驱动程序可能已经获得了对 USB 接口的独占访问权限,因此如果不首先启动 HID 驱动程序,可能不允许在 pipe 上提交传输。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM