USB device communication - Arti3DPlayer/USBDeviceSwift GitHub Wiki

Create USBDeviceMonitor object globally, set vid and pid of devices that you need to listen and run monitor in new thread for listen USB devices


import Cocoa
import USBDeviceSwift

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    //make sure that stm32DeviceMonitor always exist
    let stm32DeviceMonitor = USBDeviceMonitor([
        VIDPID(vendorId: 0x0483, productId: 0xdf11)
    ])

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application
        let stm32DeviceDaemon = Thread(target: stm32DeviceMonitor, selector:#selector(stm32DeviceMonitor.start), object: nil)
        stm32DeviceDaemon.start()
    }
}

note - start function using RunLoop that blocks thread don't run monitor in Main thread

There are two global notifications:

USBDeviceConnected

USBDeviceDisconnected

Listen them in our ViewController:

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        NotificationCenter.default.addObserver(self, selector: #selector(self.usbConnected), name: .USBDeviceConnected, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.usbDisconnected), name: .USBDeviceDisconnected, object: nil)
    }

    // getting connected device data
    func usbConnected(notification: NSNotification) {
         guard let nobj = notification.object as? NSDictionary else {
             return
         }

         guard let deviceInfo:USBDevice = nobj["device"] as? USBDevice else {
             return
         }
    }

    // getting disconnected device id
    func usbDisconnected(notification: NSNotification) {
         guard let nobj = notification.object as? NSDictionary else {
             return
         }

        guard let deviceInfo:USBDevice = nobj["id"] as? UInt64 else {
            return
        }
    }
}

USBDeviceConnected notification - returns USBDevice with all basic info

USBDeviceDisconnected notification - returns id from IORegistryEntryGetRegistryEntryID

Send command to USB device example:

enum STM32DeviceError: Error {
    case DeviceInterfaceNotFound
    case InvalidData(desc:String)
    case RequestError(desc:String)
}

func getStatus() throws -> [UInt8] {
    //Getting device interface from our pointer
    guard let deviceInterface = self.deviceInfo.deviceInterfacePtrPtr?.pointee?.pointee else {
        throw STM32DeviceError.DeviceInterfaceNotFound
    }

    var kr:Int32 = 0
    let length:Int = 6
    var requestPtr:[UInt8] = [UInt8](repeating: 0, count: length)
    // Creating request
    var request = IOUSBDevRequest(bmRequestType: 161,
                                  bRequest: 0x03,
                                  wValue: 0,
                                  wIndex: 0,
                                  wLength: UInt16(length),
                                  pData: &requestPtr,
                                  wLenDone: 255)

    kr = deviceInterface.DeviceRequest(self.deviceInfo.deviceInterfacePtrPtr, &request)

    if (kr != kIOReturnSuccess) {
        throw STM32DeviceError.RequestError(desc: "Get device status request error: \(kr)")
    }

    // Getting our data
    return requestPtr
}

See full example in STM32DeviceExample folder