Как писать в конечную точку IOHIDDevice с помощью IOKit - PullRequest
1 голос
/ 20 июня 2020

Я пишу настольное приложение для Ma c OS Catalina. На данный момент под лицензией GPL. Я мог бы сделать его лицензированным MIT в будущем, но это вторично. Он написан на Swift и поддерживает некоторые геймпады с использованием пользовательского пространства IOKit. Я заставил его работать для контроллера Dualshock 4 и Xbox 360, используя HID API. Сейчас я реализую поддержку контроллера Xbox One, но ему необходимо получить последовательность байтов, прежде чем он начнет отправлять отчеты (0x05, 0x20). Я видел это в нескольких проектах kext C / C ++, но я изо всех сил пытаюсь понять, как это сделать в моем приложении в пользовательском пространстве. Я могу получить IOHIDDevice, но я не мог понять, как получить оттуда конечную точку. Можно ли это сделать даже на уровне HID, или мне нужно использовать API более низкого уровня, например USB или Bluetooth? Я хотел избежать использования libusb только для этого, так как он уже работал с другими контроллерами.

Другое предложение, которое я нашел, касалось этого вопроса: Поддержка геймпада и джойстика на Ma c OS X в пользователе пробел , но образец кода для Ma c предоставлен не был. И замена дескриптора устройства звучит для меня излишне просто для выполнения sh этого. Кроме того, он предлагает libusb.

Некоторые части моего кода:

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
}

1 Ответ

0 голосов
/ 21 июня 2020

Вы можете получить ссылку на объект IOService, соответствующий IOHIDDevice, используя IOHIDDeviceGetService(). Затем вы можете пройти по цепочке провайдеров реестра ввода-вывода , чтобы найти базовый объект IOUSBInterface / IOUSBHostInterface. Однако драйвер generi c HID предположительно получит эксклюзивный доступ к интерфейсу USB, поэтому отправка передачи по каналу, по-видимому, не будет разрешена без предварительного запуска драйвера HID.

...