2 Replies
      Latest reply on Feb 15, 2020 8:35 AM by kedxu
      kedxu Level 1 Level 1 (0 points)

        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

        • Re: Get IOHIDDevice from UnsafeRawPointer?
          OOPer Level 8 Level 8 (5,615 points)

          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.