Получите устройство ForceFeedback в Swift

Я могу получить спрятанное устройство, подобное этому

import ForceFeedback
import IOKit.hid

private func createDeviceMatchingDictionary( usagePage: Int, usage: Int) -> CFMutableDictionary {
    let dict = [
        kIOHIDDeviceUsageKey: usage,
        kIOHIDDeviceUsagePageKey: usagePage
        ] as NSDictionary

    return dict.mutableCopy() as! NSMutableDictionary;
}

let manager = IOHIDManagerCreate(kCFAllocatorDefault, IOOptionBits(kIOHIDOptionsTypeNone));
let trackpad = createDeviceMatchingDictionary(usagePage: kHIDPage_GenericDesktop, usage: kHIDUsage_GD_Mouse)

IOHIDManagerOpen(manager, IOOptionBits(kIOHIDOptionsTypeNone) )
IOHIDManagerSetDeviceMatching(manager, trackpad)

let devices = IOHIDManagerCopyDevices(manager)

Однако ничто из этого не возвращает ни io_service_t, ни UnsafeMutablePointer<FFDeviceObjectReference>, необходимых для использования FFCreateDevice()

Как получить устройство принудительной обратной связи и использовать на нем FFCreateEffect?


person pfg    schedule 19.04.2018    source источник


Ответы (1)


Идея многих фреймворков в стиле Objective-C или C заключается в том, что вы передаете указатели на объекты, которые, как вы ожидаете, будут созданы функцией, а функции возвращают коды, чтобы вы знали, была ли операция успешной или нет.

Вы можете использовать IOHIDDeviceGetService(device), чтобы получить io_service_t. Затем вы можете создать необязательный объект типа FFDeviceObjectReference и передать его ссылку на FFCreateDevice. Вот (непроверенный) пример, который, кажется, должен работать:

import IOKit.hid
import ForceFeedback

class ForceFeedback {

    public func listen() {

        let hidManager = IOHIDManagerCreate(kCFAllocatorDefault, IOOptionBits(kIOHIDOptionsTypeNone))
        let hidDevices = [
            kIOHIDDeviceUsagePageKey: kHIDPage_GenericDesktop,
            kIOHIDDeviceUsageKey: kHIDUsage_GD_Mouse
        ]

        IOHIDManagerSetDeviceMatching(hidManager, hidDevices as CFDictionary)

        let deviceMatchingCallback: IOHIDDeviceCallback = {context, result, sender, device in

            var ffDevice: FFDeviceObjectReference? = nil
            let result = FFCreateDevice(IOHIDDeviceGetService(device), &ffDevice)
            if result != FF_OK {
                print("could not create force feedback device")
            }

            var ffEffect: FFEffectObjectReference? = nil
            var effectDefinition = FFEFFECT() // You'd create your effect here

            // Pick your UUID and build it here. For example, this is the constant force effect type
            // E559C460-C5CD-11D6-8A1C-00039353BD00
            let constantForce: CFUUID = CFUUIDCreateWithBytes(kCFAllocatorDefault,
                                                              0xE5, 0x59, 0xC4, 0x60, 0xC5, 0xCD, 0x11, 0xD6,
                                                              0x8A, 0x1C, 0x00, 0x03, 0x93, 0x53, 0xBD, 0x00)

            let effectResult = FFDeviceCreateEffect(ffDevice, constantForce, &effectDefinition, &ffEffect)
            if effectResult != FF_OK {
                print("could not create effect")
            }

            // Start and stop your effect
            // Don't forget to clean up your ffDevice and ffEffect when done.
        }

        // bridge your context and send it as a parameter instead of nil if needed
        IOHIDManagerRegisterDeviceMatchingCallback(hidManager, deviceMatchingCallback, nil)

        IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetCurrent(), CFRunLoopMode.defaultMode.rawValue)
        CFRunLoopRun()
    }

}

Обратите внимание, что я регистрирую обратный вызов HID, чтобы код запускался при добавлении устройства.

person Ryan H    schedule 28.05.2018
comment
Не удается создать устройство обратной связи, результат равен -2147483644 и я не могу его сравнить ни с одним из возвращаемых значений, кроме FFERR_INTERNAL, потому что Integer literal '...' overflows when stored into signed 'Builtin.Int32'. Я пытаюсь сравнить результат с FFERR_INVALIDPARAM FFERR_NOINTERFACE FFERR_OUTOFMEMORY и FFERR_INTERNAL, но не могу распечатать или сравнить с первыми тремя - person pfg; 28.05.2018
comment
Хм. Я получаю эту ошибку переполнения при попытке распечатать эти значения FFERR. Похоже, Apple не очень любит этот фреймворк Swift. Взгляните на ForceFeedback.swift в github.com/MaddTheSane/SwiftMacTypes. Этот парень объявил все коды ошибок в пользовательском перечислении. -2147483644 там соответствует noInterface, но я не знаю, куда идти дальше. - person Ryan H; 29.05.2018