Reginleif88/huion-note-x10-ble

GitHub: Reginleif88/huion-note-x10-ble

为 Huion Note X10 蓝牙笔提供 Linux 下的完整驱动与逆向工程支持,解决 BlueZ 兼容与笔数据解析问题。

Stars: 1 | Forks: 0

# Huion Note X10 - BLE Linux 驱动 [![平台](https://img.shields.io/badge/Platform-Linux-blue?logo=linux&logoColor=white)](https://github.com/Reginleif88/huion-note-x10-ble) [![许可证](https://img.shields.io/badge/License-MIT-blue)](./LICENSE) [![BLE](https://img.shields.io/badge/BLE-5.0_GATT-0082FC?logo=bluetooth&logoColor=white)](https://www.bluez.org/) [![状态](https://img.shields.io/badge/Status-Working-green)](./notes/journey.md) Linux 平台上用于 Huion Note X10 触控笔的 BLE 用户空间驱动。通过 Ghidra 和 Android BLE 抓包对 Huion 的 macOS/Windows v15 驱动进行逆向工程。 ## 安装 ### 1. 修补 BlueZ(必需) Huion Note X10 固件在每次 BLE 连接参数更新后会发送重复的 `Exchange MTU Request` 数据包。未修补的 BlueZ 会将其视为协议违规并断开连接,导致笔数据流大约每 4 秒中断一次。 在 `src/shared/att.c` 中应用 2 行补丁即可丢弃重复数据包而不是断开连接: ``` --- a/src/shared/att.c +++ b/src/shared/att.c @@ -1082,9 +1082,8 @@ if (chan->in_req) { DBG(att, "(chan %p) Received request while " - "another is pending: 0x%02x", + "another is pending: 0x%02x " + "(dropping duplicate)", chan, opcode); - io_shutdown(chan->io); - bt_att_unref(chan->att); - return false; + return true; } ``` **NixOS:** 通过 `hardware.bluetooth.package` 覆盖自动应用 —— 请参阅 `modules/huion-ble.nix`。
Debian / Ubuntu ``` sudo apt build-dep bluez && sudo apt install devscripts apt source bluez && cd bluez-*/ cp /path/to/patches/fix-duplicate-mtu-request.patch . patch -p1 < fix-duplicate-mtu-request.patch debuild -us -uc -b cd .. && sudo dpkg -i bluez_*.deb sudo apt-mark hold bluez sudo systemctl restart bluetooth ```
Arch Linux ``` asp update bluez && asp checkout bluez && cd bluez/trunk/ cp /path/to/patches/fix-duplicate-mtu-request.patch . # 将内容添加到 PKGBUILD 的 prepare():patch -p1 < "$srcdir/../fix-duplicate-mtu-request.patch" makepkg -si ```
Fedora ``` sudo dnf install rpm-build dnf-utils && sudo dnf builddep bluez dnf download --source bluez && rpm -i bluez-*.src.rpm cp /path/to/patches/fix-duplicate-mtu-request.patch ~/rpmbuild/SOURCES/ # 编辑 ~/rpmbuild/SPECS/bluez.spec — 添加 PatchN 和 %patchN 行 rpmbuild -bb ~/rpmbuild/SPECS/bluez.spec sudo rpm -Uvh ~/rpmbuild/RPMS/x86_64/bluez-*.rpm sudo systemctl restart bluetooth ```
从源码安装(任意发行版) ``` wget https://www.kernel.org/pub/linux/bluetooth/bluez-5.84.tar.xz tar xf bluez-5.84.tar.xz && cd bluez-5.84/ patch -p1 < /path/to/patches/fix-duplicate-mtu-request.patch ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var \ --enable-library --enable-tools make -j$(nproc) && sudo make install sudo systemctl restart bluetooth ```
### 2. 安装依赖 ``` pip install dbus-fast # 或者:nix-shell -p python3Packages.dbus-fast ``` ### 3. 配对平板 打开平板电源,通过桌面的蓝牙设置(或 `bluetoothctl`)将其配对。信任该设备以便自动重连。 ### 4. 安装 udev 规则 这些规则授予用户对 `/dev/uinput` 的访问权限,并在平板连接时自动解除绑定 `hid-generic`(防止 HOGP 干扰)。 ``` sudo cp 99-huion-note-x10.rules /etc/udev/rules.d/ sudo udevadm control --reload-rules sudo usermod -aG input $USER ``` 注销并重新登录,使用户组变更生效。 ### 5. 安装驱动 ``` mkdir -p ~/.local/share/huion-note-x10 cp huion_ble_driver.py ~/.local/share/huion-note-x10/ ``` 选择与握笔方式匹配的服务文件,复制并启用它。**只安装两者之一,不要同时安装。** ``` # 纵向(最常见 — 手持设备垂直放置,笔迹方向): cp huion-note-x10-portrait.service ~/.config/systemd/user/ systemctl --user daemon-reload systemctl --user enable --now huion-note-x10-portrait # 横向(平板原生坐标轴,短边水平): cp huion-note-x10-landscape.service ~/.config/systemd/user/ systemctl --user daemon-reload systemctl --user enable --now huion-note-x10-landscape ``` 如果选错了,禁用它(`systemctl --user disable --now ...`)再启用另一个。 如需进一步自定义 — 固定特定 MAC、使用不同的旋转方向(`portrait_ccw`、`inverted`)或启用调试日志 — 请使用 drop-in 配置: ``` systemctl --user edit huion-note-x10-portrait # or -landscape ``` ``` [Service] ExecStart= ExecStart=/usr/bin/python3 %h/.local/share/huion-note-x10/huion_ble_driver.py --orientation portrait_ccw --mac XX:XX:XX:XX:XX:XX ``` 空的 `ExecStart=` 行会清除厂商默认值;下一行会替换它。 ### 6. 验证 ``` # 检查服务状态(如果选择该变体,请替换为 -landscape): systemctl --user status huion-note-x10-portrait # 检查虚拟输入设备 libinput list-devices | grep -A5 "Huion Note X10" # 观察原始笔事件 sudo evtest # pick "Huion Note X10 BLE" # 确认:压力 0-8191,X/Y 轴根据 --orientation 互换 # landscape / inverted → X 0-28200, Y 0-37400 # portrait_cw / portrait_ccw(默认)→ X 0-37400, Y 0-28200 ``` 如果在 evtest 中笔迹跟踪正常,那么它可以在任何应用程序 (Krita、GIMP、xournalpp 等)通过标准 Linux 输入栈正常工作。 ### 快速测试(无需安装) ``` python3 huion_ble_driver.py # default orientation (portrait_cw) python3 huion_ble_driver.py --orientation landscape # native device frame ``` ## 配置平板 ### 方向 设备的原生坐标框架是横向(短边在顶部/底部),但 Note X10 实际握持方式为纵向。驱动会在输出前旋转原始坐标,因此操作系统和应用程序看到的平板方向与您实际握持方向一致。 | `--orientation` | 旋转 | 识别方式 | |-----------------|------|---------------------------------------------------| | `landscape` | 0° | 原生设备框架 — 短边在顶部/底部 | | `portrait_cw` | 270° | 平板纵向握持;默认用于 X10 | | `portrait_ccw` | 90° | 纵向镜像(与 `portrait_cw` 相反) | | `inverted` | 180° | 平板倒置相对于原生方向 | **选择正确方向的方法**:运行驱动并从平板顶部边缘向底部滑动笔。屏幕上的光标应从上到下移动。如果光标横向或反向移动,请尝试其他值直到跟踪正确。 ``` python3 huion_ble_driver.py --orientation portrait_ccw ``` **Systemd 模式。** 仓库中提供了两个服务文件: - `huion-note-x10-portrait.service` → 传递 `--orientation portrait_cw` - `huion-note-x10-landscape.service` → 传递 `--orientation landscape` 安装与您的握持方向匹配的服务文件(参见[步骤 5](#5-install-the-driver))。 对于 `portrait_ccw`、`inverted` 或固定的 `--mac`,请通过 `systemctl --user edit ` 覆盖 `ExecStart` — 示例在步骤 5 中。 **禁用合成器端旋转。** 旋转现在由驱动程序接管;任何合成器级别的平板旋转必须关闭: - Hyprland:`input:tablet:transform = 0`(或删除该行) - Sway / libinput 校准矩阵:重置为单位矩阵 如果驱动和合成器同时旋转,效果会叠加,导致光标跟踪角度错误。 ### 其他输入配置 该驱动创建一个标准的 Linux 输入设备。压力曲线、屏幕映射和活动区域由现有 Linux 工具处理: - **[OpenTabletDriver](https://opentabletdriver.net/)** — 用于压力曲线、区域映射、平滑处理和按键绑定的图形界面 - **libinput / xinput** — 命令行屏幕映射: # 将平板映射到特定显示器(X11) xinput map-to-output "Huion Note X10 BLE" HDMI-1 # 坐标变换矩阵(Wayland/X11) xinput set-prop "Huion Note X10 BLE" "Coordinate Transformation Matrix" 1 0 0 0 1 0 0 0 1 - **Krita / GIMP / MyPaint** — 平板/输入设置中的内置压力曲线编辑器 ## 工作原理 1. 通过 BlueZ D-Bus 连接,使用 `AcquireNotify`/`AcquireWrite` 获取原始文件描述符 2. 在 FFE2 上启用指示(写入 CCCD — 触发笔平板模式) 3. 发送笔平板模式握手:`cd c9/c8/ca 00 00 00 00 00 00` 4. 从 FFE1 通知文件描述符读取 `55 54` 笔数据数据包 5. 将 `ABS_X`、`ABS_Y`、`ABS_PRESSURE`、`ABS_TILT_X/Y` 注入 `/dev/uinput` 6. 通过电池查询(`cd d1`)每 5 秒保持活跃 ``` ┌──────────────┐ BLE GATT ┌───────────────────────┐ │ Huion Note │◄───────────────►│ BlueZ (patched) │ │ X10 │ FFE0 service │ │ │ │ FFE1: notify │ AcquireNotify → fd │ │ │ FFE2: indicate │ StartNotify (CCCD) │ │ │ FFE2: write │ AcquireWrite → fd │ └──────────────┘ └──────────┬────────────┘ │ raw fds ┌──────────▼────────────┐ │ huion_ble_driver.py │ │ parse 55 54 packets │ │ handshake + keepalive │ └──────────┬────────────┘ │ ioctls ┌──────────▼───────────┐ │ /dev/uinput │ │ → libinput → app │ └──────────────────────┘ ``` ## 设备信息 | 字段 | 值 | |-------|-------| | 产品 | Huion Note X10 | | 内部型号 | HUION_T218 | | 笔 | PW320 Scribo 笔(双笔尖:圆珠笔用于纸张,塑料用于绘图) | | BLE | 5.0 GATT,VID `0x256C`,PID `0x8251` | | 厂商 GATT 服务 | `0000FFE0`(FFE1 = 笔数据通知,FFE2 = 命令写入) | | 笔数据 | `55 54` 头,14 字节(24 位坐标、16 位压力、有符号 int8 倾斜) | | 分辨率 | 28200 x 37400 | | 压力 | 8192 级(13 位) | ## 为何没有现有的驱动可用 - **hid-uclogic** — 仅 USB 总线(bus `0003`),忽略 BLE(bus `0005`) - **Huion Linux 驱动 v15** — BLE 代码存在但被故意禁用(`is_ble_tablet_online()` 存根返回 false) - **OpenTabletDriver** — 仅 USB 传输,不支持 BLE - **BlueZ HOGP** — 将设备识别为键盘(HID Report Map = Usage 0x6)。笔数据使用厂商 FFE0/FFE1,而非 HID ## 依赖项 - Python 3.10+ - [`dbus-fast`](https://github.com/Bluetooth-Devices/dbus-fast) — 用于 BlueZ 的异步 D-Bus 客户端 - BlueZ 5.x(已修补 — 参见上文) - Linux 内核 4.5+(用于 `UI_DEV_SETUP` / `UI_ABS_SETUP` uinput ioctl) ## 逆向工程 该 BLE 协议完全未记录。通过三个阶段进行逆向工程: 1. **二进制考古学** — 提取 Huion 的官方驱动(Linux v15.0、macOS v15.7、Windows v15.7)。通过 `strings`/`nm`/`objdump` 找到厂商 GATT UUID(`FFE0/FFE1/FFE2`)和命令 ID。发现 Linux 驱动中的 BLE 代码被故意禁用。 2. **Android BLE 抓包** — 使用 Bluetooth HCI 抓包日志捕获 Huion Note 应用与平板之间的流量。解码了记事模式协议:`cd XX 08 P0 P1 P2 P3 ed` 帧格式,11 字节笔数据包含 16 位坐标。 3. **Ghidra 逆向 macOS 驱动** — 分析 `libTabletSession.dylib` 以找到笔平板模式,该模式使用不同的命令 ID(`0xC8/0xC9/0xCA/0xD1`)和笔数据格式(`55 54` 头,14 字节,24 位坐标 + 倾斜)。 关键发现: - 当 FFE2 的 CCCD 指定位被写入(对 FFE2 上的 `StartNotify` 的响应)时,设备进入笔平板模式 — 通过逆向 macOS 驱动的 `setNotifyValue:1` 在两个特征上找到。 - 设备固件在每次连接参数更新后发送 9 个重复的 ATT MTU 请求,这会崩溃 BlueZ 的 GATT 客户端 — 通过对 `att.c` 的 2 行补丁修复。 请参阅 [`notes/journey.md`](notes/journey.md) 获取完整的逆向工程会话日志。 ## 项目结构 ``` huion_ble_driver.py — BLE tablet driver (dbus_fast + uinput) patches/ fix-duplicate-mtu-request.patch — BlueZ att.c patch for firmware MTU bug huion-note-x10-portrait.service — systemd user service (portrait_cw) huion-note-x10-landscape.service — systemd user service (landscape) 99-huion-note-x10.rules — udev rules (uinput access + HOGP unbind) notes/journey.md — Full RE session log Archives/ — RE artifacts (Ghidra, captures, scripts) ``` ## 许可证 根据 [MIT 许可证](LICENSE) 授权。 Huion 和 Note X10 是 Huion 的商标。本项目与 Huion 无关,也未得到其认可。
标签:Arch Linux, BLE, BlueZ补丁, Debian, GATT, Ghidra, HID, Huion Note X10, Linux硬件驱动, Linux驱动, MTU请求, NixOS, Waymore结果处理, 倾斜, 全功能笔, 压感, 反向工程, 固件分析, 威胁情报, 开发者工具, 开源驱动, 用户空间驱动, 硬件兼容, 笔平板, 绘图板驱动, 蓝牙5.0, 蓝牙驱动, 输入设备, 逆向工具, 重复包处理