返回 2026-05-15
⚙️ 工程

为旧款 Griffin PowerMate 开发新驱动New Driver for the Old Griffin PowerMate

daringfireball.net·2026-05-14

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 上默认不执行任何操作;本库会接管设备并将事件传递给你的应用程序。

报告格式(来自设备)

  • 字节 0:按钮状态 — 0 = 释放,1 = 按下
  • 字节 1:旋转增量 — 有符号数;正值为顺时针,负值为逆时针(通常每份报告为 ±1 到 ±7)。设备不直接报告速度;驱动程序根据报告之间的时间间隔来推算旋转速率(每秒增量)。
  • 构建与运行

    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. 事件类型

  • PowerMateEvent.buttonDown / buttonUp — 旋钮按下/释放
  • PowerMateEvent.buttonClick — 短按并释放(低于 longPressThreshold 阈值)
  • PowerMateEvent.buttonLongPress — 按住至少 longPressThreshold 时间后释放
  • PowerMateEvent.rotate(delta: Int, rate: Double?) — delta 为带符号的步进数(如 +1、-2);rate 是每秒的旋转速度(首次报告时为 nil)
  • 设置 longPressThreshold(默认 0.4 秒)以调整长按判定标准。可使用 onClick 和 onLongPress(或通过代理)进行分别处理

    使用 driver.isConnected 检查设备当前是否已连接

    LED(底座中的蓝色指示灯)

    底座内置一个蓝色 LED,可用于反馈提示。仅在设备连接时(isConnected == true)控制该 LED

  • setLEDBrightness(_ value: UInt8) — 静态亮度值 0–255(0 表示关闭)
  • setLEDPulseAsleep(_ on: Bool) / setLEDPulseAwake(_ on: Bool) — 开启或关闭“休眠”或“唤醒”状态下的内置脉冲效果
  • setLEDPulseMode(table:op:arg:) — 自定义脉冲模式:table 取值 0–2,op 0 = 较慢,1 = 正常,2 = 较快,arg 用于 op 0/2 的参数(1–255)
  • LED 命令通过 USB 厂商控制请求发送(与 Linux 驱动相同的协议)。若命令成功发送则返回 true;若 USB 设备正忙(例如其他进程已打开该设备),LED 调用可能失败

    映射到系统操作

  • 滚动:在 onRotate 回调中创建一个 CGEventScrollWheelEvent(例如 CGEventCreateScrollWheelEvent)并发布它,或将 delta 值传入你自己的滚动逻辑
  • 点击:在 onButtonDown / onButtonUp 中创建并发布鼠标点击 CGEvent,或调用你自己的点击处理函数
  • 媒体或其他操作:将 onRotate 和 onButtonDown 映射为你所需的功能(如音量调节、快捷键等)
  • 发布事件可能需要你在系统设置 → 隐私与安全性中为应用启用“输入监控”(或“辅助功能”)权限

    如果设备无响应

  • 拔下再重新插入 PowerMate,然后重新启动你的应用
  • 退出其他可能正在使用 PowerMate 的软件(例如旧的 PowerMate 应用程序)
  • 驱动程序使用 kIOHIDOptionsTypeSeizeDevice,因此会独占访问设备;同一时间只能有一个进程使用它
  • 要求

  • macOS 13+
  • Swift 5.9+
  • 参考

  • Linux PowerMate 驱动(报告格式:字节 0 = 按钮状态,字节 1 = 旋转量)
  • 在 Linux 上恢复 Griffin PowerMate 的使用
  • Apple IOKit HID:IOHIDManager、IOHIDDeviceOpen、IOHIDDeviceRegisterInputReportCallback
  • 需要完整排版与评论请前往来源站点阅读。