IOKit: Retrieving USB Name, Vendor ID and Product ID after Serial Connection.

Firstly let me start by saying I'm totally new to using IOKit and fairly new to Swift. That said, I've successfully managed to detect the insertion and removal of my USB serial device in my Swift, MacOS app.

Therefore calling ls /dev/tty.* lists the same devices as via the IOServiceAddMatchingNotification(notifyPort, kIOFirstMatchNotification, IOServiceMatching("IOSerialBSDClient"), matchingCallback, selfPtr, &matchedIterator) call inside the resulting callback.

This is a great start. As you can imagine telling the user you've found "/dev/tty.usbmodem[some number]" isn't particularly user friendly. So once I retrieve the IODialinDevice property from the aforementioned callback is there a way for me to lookup the USB device's Vendor ID and Product ID and ideally retrieve the human readable name for said USB device, so I can then expose that to the User?

Thanks.

Hoping that may help, here is what I do for MacOS, to retrieve some infos (serial number, capacity and vendor): Dictionary entry is "DADeviceVendor" ; device name "DAVolumeName" ; whet do you expect in ProductID ?

func getSerialAndSize(_ url: URL) -> (String, Int, String) {
        
    if let session = DASessionCreate(nil) {
        if let disk : DADisk = DADiskCreateFromVolumePath(nil, session, url as CFURL) {
            // We found a mount point...
            let ioService : io_service_t = DADiskCopyIOMedia(disk)
            let key = "USB Serial Number"
            
            let options : IOOptionBits = IOOptionBits(kIORegistryIterateParents) |
                IOOptionBits(kIORegistryIterateRecursively)
            
            if let sSerial : CFTypeRef = IORegistryEntrySearchCFProperty(ioService, kIOServicePlane, key as CFString, nil, options) {
                
                let dico: CFDictionary = DADiskCopyDescription(disk)!
                let vendor = (dico as NSDictionary)["DADeviceVendor"] as? String ?? "--"
                let driveCapacity = (dico as NSDictionary)["DAMediaSize"] as? Int ?? 0
                return (String(describing: sSerial), driveCapacity, vendor)
            } else {
                return ("", 0, "") 
            }
        }
        
    }
    
    return ("", 0)
    
}

The best way to get the user-visible name for a serial device is via System Configuration framework. For example:

let interfaces = SCNetworkInterfaceCopyAll() as! [SCNetworkInterface]
for interface in interfaces {
    let bsdName = SCNetworkInterfaceGetBSDName(interface) as String? ?? "-"
    let displayName = SCNetworkInterfaceGetLocalizedDisplayName(interface) as String? ?? "-"
    print(bsdName, displayName)
}

In my example this prints:

usbmodem123456781 USB Modem

This is the same name that the system displays in System Preferences > Network.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I did it this way:

func findRemovableVolumes() -> [URL] {
    
    var allMountedURL = [URL]()
    let keys: [URLResourceKey] = [.volumeNameKey, .volumeIsRemovableKey, .volumeIsEjectableKey]
    let paths = FileManager().mountedVolumeURLs(includingResourceValuesForKeys: keys, options: [])
    if let urls = paths {
        for url in urls {
            let components = url.pathComponents
            if components.count > 1 && components[1] == "Volumes" {
                allMountedURL.append(url)
            }
        }
    }
    return allMountedURL
}
        let allMountedURLIncludingDMG = findRemovableVolumes()  

        for url in allMountedURLIncludingDMG {
            let (serial, capa, vendor) = getSerialAndSize(url)

But eskimo may have proposed a simpler way of getting this.

Is using SCNetworkInterfaceCopyAll quicker?

Quicker? Quicker at run time? Or quicker to code? It’s certainly the latter. It’s probably slower at runtime, but do you really care? How often would you be doing this?

Moreover, the key point is that SCNetworkInterfaceCopyAll actually returns the user-visible name of the device rather than a bunch of USB gobbledygook.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

IOKit: Retrieving USB Name, Vendor ID and Product ID after Serial Connection.
 
 
Q