iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
以前、Cocoa LifeというCocoa勉強会の会誌で、ジョイスティックをアプリケーションで扱うお話として、HID Device Interface入門という記事を書いたが、これをSwiftで挑戦してみようと思う。
今回対象となるのは、SmartScroll。左手で扱うトラックボール。知人がドライバを書いていたのだが、最新のOSに対応していないので、挑戦することにした。
以前の開発環境には、USB Proberというアプリが存在したが、今の開発環境ではなくなった。そこで、当時から存在していたIORegistryExplorerを使うことにする。これは、別途、Additional Toolsとしてダウンロードしてインストールするものだ。
以下が、その結果。
赤い枠で囲まれた値が、機器の特定に必要となる情報だ。
今回、デモ用ということでコマンドラインツールとしてアプリを製作することにしたのだが、戸惑ったのは、main()関数をSwiftではどう書くか?結論は、main()関数は書かないということのようだ。
import Foundation
import CoreFoundation
import IOKit
import IOKit.usb.IOUSBLib
exit(0)
main()関数の戻り値は、exit()関数の引数で渡すということになる。
IORegistryExplorerで取得した値のVendor IDとProduct IDを使って機器を特定することにするのだが、それを定数として定義する。
let kOurVendorID = 0x56a /* Vendor ID of the USB device */
let kOurProductID = 0x50 /* Product ID of device */
機器を探す条件の辞書を用意する。
var masterPort: mach_port_t = 0
let usbVendor: Int32 = Int32(kOurVendorID)
let usbProduct: Int32 = Int32(kOurProductID)
let kr: kern_return_t = IOMasterPort(mach_port_t(MACH_PORT_NULL), &masterPort)
var matchingDict = IOServiceMatching(kIOUSBDeviceClassName) as? [String: Any]
matchingDict![kUSBVendorID] = usbVendor
matchingDict![kUSBProductID] = usbProduct
検索条件を設定して、RunLoopで待つことにする。
private var gNotifyPort: IONotificationPortRef? = nil
private var gAddedIter: io_iterator_t = 0
gNotifyPort = IONotificationPortCreate(masterPort)
let runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort).takeUnretainedValue()
private var gRunLoop: CFRunLoop? = CFRunLoopGetCurrent()
CFRunLoopAddSource(gRunLoop, runLoopSource, CFRunLoopMode.defaultMode)
let _ = IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification, matchingDict! as CFDictionary, DeviceAdded, nil, &gAddedIter)
DeviceAdded(nil, gAddedIter)
CFRunLoopRun()
機器を見つけると呼ばれる関数の定義は以下の感じだ。
func DeviceAdded(_ refCon: UnsafeMutableRawPointer?, _ iterator: io_iterator_t) {
print(#function)
}
これで動作確認してみたのだが、うまく動かない。申し訳ないが今回は時間切ということで続きは勉強会で!