为旧款 Griffin PowerMate 开发新驱动New Driver for the Old Griffin PowerMate
James Lockman 发布了一个开源驱动,使老旧的 Griffin PowerMate 旋钮设备在现代系统中恢复功能。该设备是一个可旋转和按压的旋钮,底部配有蓝色 LED,可通过亮度变化反映系统状态。该驱动旨在重现其最初用于音视频制作的滚动旋钮控制体验。尽管现代控制器功能更丰富,但这款简洁设备仍因其直观操作而受到部分用户青睐。
适用于现代 macOS 的 Griffin PowerMate 驱动程序
这个小巧的驱动程序让 Griffin PowerMate——一个来自往昔时代的实用小设备——重新焕发活力。PowerMate 究竟是什么?它就是一个可以旋转或按压的旋钮,仅此而已。它的底座还有一个蓝色 LED 灯,其亮度会根据你的操作而变化。
刚推出时,它被设计用来辅助音视频制作,为你的桌面增加一个可滚动的旋钮。当然,如今市面上已有许多功能更丰富的现代控制器,但这个早期设备却有一种……怀旧……的魅力。
安装方法:打开 DMG 文件,将 PowerMate Agent 拖拽到应用程序文件夹中,然后启动 PowerMate Agent。当然,如果没有 PowerMate 本身,它什么也做不了,所以去你那个塞满旧 USB 设备的抽屉里把它找出来吧!你会在顶部菜单栏看到一个新选项,用于控制 PowerMate 的行为。
PowerMate 充当滚动控制器,因此如果当前窗口或控件支持滚动,旋转旋钮即可滚动窗口或增减所选值。如果你不喜欢默认的滚动方向,还可以将其反转。
PowerMate 同时也可以作为鼠标按钮使用。短按按钮相当于一次鼠标点击;长按则相当于右键点击。你还可以更改设置,使长按变为双击。
是不是很简单?
技术细节。
这是一个小巧的 macOS 驱动程序,通过 USB HID 协议打开 Griffin PowerMate(VID 0x077d, PID 0x0410),读取其 6 字节报告,并暴露按钮和旋转事件,以便你将它们映射为各种操作(例如滚动、点击、媒体按键等)。
该设备在总线上有报告输出,但在 macOS 上默认不执行任何操作;本库会接管设备并将事件传递给你的应用程序。
报告格式(来自设备)
构建与运行
cd /path/to/USB
swift build
swift run PowerMateDemo插入 PowerMate 后,旋转旋钮或按下按钮,演示程序就会打印出事件信息。按 Ctrl+C 停止运行。
全局驱动程序(PowerMate Agent)
PowerMateAgent 将旋钮和按钮转换为键盘/滚动事件,所有应用程序都能接收到这些事件(浏览器、编辑器等等):
菜单和子菜单检测使用 Accessibility API:当聚焦的 UI 元素是菜单(含子菜单)时,旋转发送方向键,点击发送回车键。请在系统设置 → 隐私与安全中为应用授予 Accessibility 权限,否则子菜单可能“卡住”无法正常滚动。若未启用 Accessibility,长按仍会进入备用“菜单模式”(持续发送方向键,直到点击或 5 秒超时)。
LED 在你旋转时会闪烁,空闲时变暗;按住按钮期间保持常亮。
swift run PowerMateAgent首次运行时,macOS 会提示请求输入监控权限。请在系统设置 → 隐私与安全 → 输入监控中授予该权限,并添加(或启用)终端或编译生成的可执行文件,然后重新启动代理程序。
要在后台运行:使用 swift run PowerMateAgent &,或直接运行编译好的二进制文件 ./.build/debug/PowerMateAgent,若想让它随登录自动启动,可将其添加到登录项中。
要创建已签名并经过公证的应用程序(或安装程序),以便他人在使用时不会遇到安全警告,请参见 DISTRIBUTION.md。你需要一个 Apple Developer 账户;用户首次使用拨号时仍需授予输入监控(或辅助功能)权限。
在你的应用中使用
1. 添加包
在你的应用的 Package.swift 文件中(或在 Xcode 中:文件 → 添加包依赖项):
dependencies: [
.package(path: "/path/to/USB"), // or your clone URL
],
targets: [
.target(name: "YourApp", dependencies: ["PowerMateDriver"]),
]2. 启动驱动并映射事件
import PowerMateDriver
let driver = PowerMateDriver()
// Optional: use closures for simple mapping
driver.onRotate = { delta, rate in
// delta > 0 = clockwise, delta < 0 = counter-clockwise
// rate = deltas per second (nil on first report); use for speed-dependent mapping
// e.g. scroll: CGEventCreateScrollWheelEvent(..., delta * lineHeight)
}
driver.onButtonDown = { /* e.g. simulate click or toggle */ }
driver.onButtonUp = { }
// Or use the delegate for all events
driver.delegate = self // implement PowerMateDriverDelegate
driver.start()
// Keep run loop running (e.g. main thread in an app)3. 事件类型
设置 longPressThreshold(默认 0.4 秒)以调整长按判定标准。可使用 onClick 和 onLongPress(或通过代理)进行分别处理
使用 driver.isConnected 检查设备当前是否已连接
LED(底座中的蓝色指示灯)
底座内置一个蓝色 LED,可用于反馈提示。仅在设备连接时(isConnected == true)控制该 LED
LED 命令通过 USB 厂商控制请求发送(与 Linux 驱动相同的协议)。若命令成功发送则返回 true;若 USB 设备正忙(例如其他进程已打开该设备),LED 调用可能失败
映射到系统操作
发布事件可能需要你在系统设置 → 隐私与安全性中为应用启用“输入监控”(或“辅助功能”)权限
如果设备无响应
要求
参考
需要完整排版与评论请前往来源站点阅读。