Get IOHIDDevice from UnsafeRawPointer?

Hello!


I am trying to write an application for macOS. I am using Cocoa and Swift and targeting macOS 10.13.


My goal is to open a USB HID device. I am using IOKit.hid


Summary of issue:

let devices = IOHIDManagerCopyDevices(manager)
if (devices != nil) {
     var refs =<unsaferawpointer?>
          UnsafeMutablePointer<unsaferawpointer?>.allocate(capacity: CFSetGetCount(devices))
            
     CFSetGetValues(devices, refs)

     var deviceHandle = refs![0]
}
  1. IOHIDManagerCopyDevices(...) gives me a CFSetRef
  2. I unpack the CFSetRef using CFSetGetValues(...); the second argument is of type UnsafeMutablePointer<UnsafeRawPointer?>?
  3. Now, I want to get the first item, call it deviceHandle
  4. deviceHandle is of type UnsafeRawPointer? ........ but I want an IOHIDDevice😟


I'm still very new to development for Apple platforms so please let me know if I'm missing anything obvious

But I'm stumped as to how to convert my UnsafeRawPointer? to an IOHIDDevice.


The below gives me an EXC_BAD_INSTRUCTION (EXC_I386_INVOP):

var test = deviceHandle as! IOHIDDevice


I have already confirmed that the pointer's _rawValue is correct by comparing with another implementation using IOHIDManagerRegisterDeviceMatchingCallback(), but I would prefer to do this synchronously


Is there an easy way to convert my UnsafeRawPointer? to IOHIDDevice?


Thanks

Kevin

Accepted Reply

Working with CFSet APIs from Swift is sort of a bunch of messes, and even an experienced Swift programmer would not try.


`CFSet` is bridgeabe to Swift `Set` (under a certain condition, which is fulfilled in many of the Apple's frameworks), and it would be far easier to access.


Please try somehting like this:

if let devices = IOHIDManagerCopyDevices(manager) as? Set<IOHIDDevice> {
    if let deviceHandle = devices.first {
        print(deviceHandle)
        //...
    } else {
        print("no devices")
    }
} else {
    print("devices not available")
}

You can use `deviceHandle` as an `IOHIDDevice` in this scenario.


I would prefer to do this synchronously

Asynchronous is the modern way to work with IOs. you should better be accustomed to it.

Replies

Working with CFSet APIs from Swift is sort of a bunch of messes, and even an experienced Swift programmer would not try.


`CFSet` is bridgeabe to Swift `Set` (under a certain condition, which is fulfilled in many of the Apple's frameworks), and it would be far easier to access.


Please try somehting like this:

if let devices = IOHIDManagerCopyDevices(manager) as? Set<IOHIDDevice> {
    if let deviceHandle = devices.first {
        print(deviceHandle)
        //...
    } else {
        print("no devices")
    }
} else {
    print("devices not available")
}

You can use `deviceHandle` as an `IOHIDDevice` in this scenario.


I would prefer to do this synchronously

Asynchronous is the modern way to work with IOs. you should better be accustomed to it.

Thanks OOPer for the solution! Confirmed working


You're right about sync vs async. I will add async design next. Small steps 🙂