From 232e1ee6a2bb8ce4c9c04eae07e3f853ff03fbdc Mon Sep 17 00:00:00 2001 From: Shubhadeep Date: Mon, 17 Aug 2026 08:39:05 +0530 Subject: [PATCH 1/3] feat(fantech): add WG14P Yari Pro support Add Fantech Yari Pro WG14P (VID 0x3151, PID 0x503D) to: - check-scan.ts: BRANDS + OPENMOUSE_SUPPORTED - supported-mice.ts: device catalog entry (PID 0x503d) - supported-mice.test.ts: PID_UNIVERSE - controller.ts: FantechHidClient import + NEEDS_OPEN - traits.ts: fantech family traits - device-images.ts: Fantech fallback Protocol reverse-engineered from qmk.top web configurator: - Command-based protocol (Family B) - Get DPI: cmd 144, Set DPI: cmd 16 - Get Report Rate: cmd 131, Set Report Rate: cmd 8 - DPI stored as LE uint16 at bytes [8+slot*2..9+slot*2] - Rate encoding: 0=8000Hz, 1=4000Hz, 2=2000Hz, 3=1000Hz, 4=500Hz, 5=125Hz --- src/check-scan.ts | 2 ++ src/device/controller.ts | 3 ++- src/device/traits.ts | 1 + src/supported-mice.test.ts | 4 +++- src/supported-mice.ts | 3 +++ src/ui/device-images.ts | 1 + 6 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/check-scan.ts b/src/check-scan.ts index 89acba2..2456fd3 100644 --- a/src/check-scan.ts +++ b/src/check-scan.ts @@ -30,10 +30,12 @@ export const BRANDS: Record = { 0x1915: "Orbital", 0x0C45: "Redragon", 0x1BCF: "Alienware", + 0x3151: "Fantech", }; const OPENMOUSE_SUPPORTED = new Set([ 0x1532, 0x046D, 0x3710, 0x3367, 0x36A7, 0x373E, 0x3554, 0x373B, 0x361D, 0x3434, 0x2FE3, 0x1915, + 0x3151, ]); /** diff --git a/src/device/controller.ts b/src/device/controller.ts index d7e9447..c6e1a3c 100644 --- a/src/device/controller.ts +++ b/src/device/controller.ts @@ -109,6 +109,7 @@ import { TeevolutionHidClient } from "@openmouse/protocol/drivers/teevolution/hi import { teevolutionProfileForCid } from "@openmouse/protocol/teevolution"; import { VgnF2HidClient } from "@openmouse/protocol/drivers/vgn/hid"; import { KeychronHidClient } from "@openmouse/protocol/drivers/keychron/hid"; +import { FantechHidClient } from "@openmouse/protocol/drivers/fantech/hid"; import { SUPPORTED_HID_FILTERS } from "@openmouse/protocol/drivers/vendors"; import { WLMouseHidClient } from "@openmouse/protocol/drivers/wlmouse/hid"; import { parsePreviewMode, previewsEnabled, type PreviewMode } from "../preview-modes"; @@ -160,7 +161,7 @@ function activeAs(...classes: ClientClass[]): T | null { const DM_CLASSES = [WLMouseHidClient, LamzuHidClient, AtkHidClient, NinjutsoHidClient] as const; const RAZER_CLASSES = [RazerHidClient, RazerViperMiniHidClient, RazerViperHidClient, RazerCobraHidClient] as const; -const NEEDS_OPEN = [TeevolutionHidClient, VgnF2HidClient, KeychronHidClient, ModdoHidClient, ZaunkoenigHidClient] as const; +const NEEDS_OPEN = [TeevolutionHidClient, VgnF2HidClient, KeychronHidClient, ModdoHidClient, ZaunkoenigHidClient, FantechHidClient] as const; const DEDICATED = [ ...DM_CLASSES, ...RAZER_CLASSES, ...NEEDS_OPEN, EggOp1HidClient, LogitechHidppClient, OrbitalHidClient, RazerViperV4ProHidClient, FinalmouseHidClient, diff --git a/src/device/traits.ts b/src/device/traits.ts index 9b463bd..53d088a 100644 --- a/src/device/traits.ts +++ b/src/device/traits.ts @@ -46,6 +46,7 @@ const BY_FAMILY: Readonly>> = { atk: DIRECT_MODE, ninjutso: { ...DIRECT_MODE, ninjutso: true }, "keychron-nape": { advancedSection: true, sleep: true, directMode: true }, + fantech: { advancedSection: true, sleep: true, directMode: true }, }; const BY_BRAND: Readonly> = { diff --git a/src/supported-mice.test.ts b/src/supported-mice.test.ts index 40c8a0d..c293d46 100644 --- a/src/supported-mice.test.ts +++ b/src/supported-mice.test.ts @@ -2,7 +2,7 @@ import assert from "node:assert/strict"; import test from "node:test"; import { DEVICE_DRIVERS } from "@openmouse/protocol/drivers/registry"; -import { WLMOUSE_PRODUCTS } from "@openmouse/protocol/drivers/vendors"; +import { WLMOUSE_PRODUCTS, VENDOR_ID } from "@openmouse/protocol/drivers/vendors"; import { EGG_DEVICE_PROFILES } from "@openmouse/protocol/endgame-gear-op1"; import { KEYCHRON_PRODUCTS } from "@openmouse/protocol/keychron"; import { LAMZU_PRODUCTS } from "@openmouse/protocol/lamzu"; @@ -105,6 +105,8 @@ const PID_UNIVERSE = new Set([ ...PULSAR_XS1_PRODUCT_IDS, // Finalmouse ULX dongle (drivers/finalmouse/hid.ts). 0x0100, + // Fantech WG14P Yari Pro (drivers/fantech/hid.ts). + 0x503d, ]); test("every pinned PID on a coverage claim exists in the protocol registry", () => { const withPids: Array = MICE.filter( diff --git a/src/supported-mice.ts b/src/supported-mice.ts index b6c1b47..83fc996 100644 --- a/src/supported-mice.ts +++ b/src/supported-mice.ts @@ -487,6 +487,9 @@ export const MICE: Mouse[] = [ note: "A4tech / Bloody protocol — not implemented" }, { brand: "Fantech", model: "THOR II X16", status: "driver", req: 1, note: "Fantech protocol — not implemented" }, + { brand: "Fantech", model: "WG14P Yari Pro", status: "supported", req: 1, + pids: [0x503d], + note: "PID 0x503d — vendor interface (0xFFFF:0x02) in Fantech driver" }, { brand: "Cooler Master", model: "MasterMouse MM720", status: "driver", req: 1, note: "CM protocol — not implemented" }, { brand: "Cooler Master", model: "MM711", status: "driver", req: 1, diff --git a/src/ui/device-images.ts b/src/ui/device-images.ts index ecc3a11..4a56e69 100644 --- a/src/ui/device-images.ts +++ b/src/ui/device-images.ts @@ -94,5 +94,6 @@ export function deviceImage(device: HIDDevice | null | undefined, displayName = // Pulsar 4K Wireless Receiver ships with the X2 V2 4K dongle kit; the receiver // product id is not yet published, so match the name reported by WebHID. if (/pulsar/i.test(displayName)) return "/devices/pulsar-x2-v2.png"; + if (/fantech/i.test(displayName)) return "/devices/unknown-device.png"; return "/devices/unknown-device.png"; } From e1e8a1ce3b6089b8b7a8dd6a259a123d52ce0411 Mon Sep 17 00:00:00 2001 From: Shubhadeep Date: Mon, 17 Aug 2026 09:00:56 +0530 Subject: [PATCH 2/3] ci: retrigger checks after mouse-protocol merge From 1cb4578d8b248bc46922d320ef8ae968f89f6364 Mon Sep 17 00:00:00 2001 From: Shubhadeep Date: Mon, 17 Aug 2026 09:03:59 +0530 Subject: [PATCH 3/3] fix(deps): update @openmouse/protocol to include Fantech driver --- package-lock.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index fd45d6e..06123d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "openmouse", "version": "0.1.0", "dependencies": { - "@openmouse/protocol": "https://github.com/OpenMouse-Project/mouse-protocol.git", + "@openmouse/protocol": "github:OpenMouse-Project/mouse-protocol", "preact": "^10.29.8" }, "devDependencies": { @@ -460,8 +460,7 @@ }, "node_modules/@openmouse/protocol": { "version": "0.1.0", - "resolved": "git+https://github.com/OpenMouse-Project/mouse-protocol.git#ba64a12d7633d58967c213cd44eef10d12e465e0", - "integrity": "sha512-htpO6JBZSdbkx5NUfBaABufH7CXfjqA+C8rx4zGYdjb/FXrb9LE5nt7suuIvt03E8185x2I8dUyg/AjpJKjgvQ==", + "resolved": "git+ssh://git@github.com/OpenMouse-Project/mouse-protocol.git#a93768d2935141cc24b29cf0b099883c9f30cbc2", "engines": { "node": ">=20" }