昨年末の↑この記事は、内部でls /dev/cu*
コマンドを実行して、その結果を使う方法でした。それに対し、今回は IOKitのAPIを使用して シリアルポートのパス名を取得する方法です。
元ネタは次のブログで公開されていたC言語のコードで、それをSwiftに書き直したものです。

コード
main.swift
import Foundation
import IOKit
import IOKit.serial
let main: () = {
guard let serialBSDService = IOServiceMatching(kIOSerialBSDServiceValue) else { return }
guard var dict = serialBSDService as NSDictionary as? [String: AnyObject] else { return }
dict[kIOSerialBSDTypeKey] = kIOSerialBSDAllTypes as AnyObject
var serialPortIterator = io_iterator_t()
guard IOServiceGetMatchingServices(kIOMainPortDefault, serialBSDService, &serialPortIterator) == kIOReturnSuccess else { return }
while case let modemService = IOIteratorNext(serialPortIterator), modemService != 0 {
let prop = IORegistryEntryCreateCFProperty(modemService, kIOCalloutDeviceKey as CFString, kCFAllocatorDefault, IOOptionBits(0))
if let value = prop?.takeUnretainedValue(), let bsdPath = value as? String {
print(bsdPath)
}
}
IOObjectRelease(serialPortIterator)
}()
実行例
% swift main.swift
/dev/cu.wlan-debug
/dev/cu.usbmodemHIDEF1
/dev/cu.Bluetooth-Incoming-Port
/dev/cu.usbserial-53250003491
さすがネイティブ、早いです。
後日、chooserialコマンドも、こちらの方法に変更します。