背景
macOSでUSB-シリアル通信コンバータを使うことが多く、以前から挿抜の検出をしたいと思っていました。
主に、後からUSB-シリアル通信コンバータを挿入した際、macOSアプリを再起動しなくてもデバイスのリストを更新してくれる機能が欲しかったです。
これは稀ですが、通信中にUSB-シリアル通信コンバータを抜いた時、通信を自動的に止めたいとも思っていました。
シリアル通信デバイス
昔はMacの背面にシリアルポートがついていましたが、今はUSB-シリアル通信に変わっています。
FTDIやSilicon Labsなどが便利なUSB-UARTブリッジチップを提供してくれています。
macOS内では
$ ls -l /dev/tty.*
crw-rw-rw- 1 root wheel 0x9000002 6 16 18:51 /dev/tty.Bluetooth-Incoming-Port
crw-rw-rw- 1 root wheel 0x900000a 6 18 05:39 /dev/tty.usbmodem15303
crw-rw-rw- 1 root wheel 0x900000c 6 18 05:39 /dev/tty.usbmodem206835814E481
crw-rw-rw- 1 root wheel 0x900000e 6 18 05:43 /dev/tty.usbserial-210244678243
crw-rw-rw- 1 root wheel 0x9000006 6 18 05:38 /dev/tty.usbserial-AG0JGOAK
crw-rw-rw- 1 root wheel 0x9000000 6 16 18:51 /dev/tty.wlan-debug
というように、シリアル通信デバイスとして認識されているものは、Swiftを使ってシリアル通信を実現することができます。
USBデバイスとして扱わないと挿抜検出はできない
シリアル通信デバイスとして扱えば通信アプリは開発できます。
しかし、挿抜検出、ベンダーID・プロダクトIDの取得はUSBデバイスとして扱わなくてはいけないことがわかりました。
その時、こちらのサイトが参考になりました。
USB Connection Delegate on Swift
【追記】2024.06.18
USBDevice_Path_in_Swift.playground
発見したシリアル通信デバイスと、発見したUSBデバイスを照らし合わせることで、シリアル通信デバイスがUSBデバイスであれば、ベンダーID・プロダクトIDを取得できます。
両者はBSD Pathが同じなので、それで照らし合わせて同一デバイスであることがわかります。
参考にしたサイトのソースコードを実行してみると、Mac本体内部にUSB HUBがあることもわかります。
接続している電子楽器なども検出されました。
こんなことができる
シリアル通信デバイスはUSBで接続されているとは限りません。
そこで、USBで接続されているデバイスにはUSBのアイコンをつけ、さらにプロダクト名で表示するようにしてみました。
USBデバイスでないものは、昔のMacで使われてたシリアルポートに近いアイコンをつけてみました。