From 1c2eb8c6a5aa1e35c335bdd5f0f1248d77813d93 Mon Sep 17 00:00:00 2001 From: NotLokry Date: Wed, 19 Aug 2026 19:02:11 +0300 Subject: [PATCH 1/4] Remove unnecessary tabs --- src/app/App.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/App.tsx b/src/app/App.tsx index b1a389e..a87ad29 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -36,6 +36,7 @@ import { TeevolutionDpiLightingCard, } from "./cards/AdvancedCards"; import { cardAvailability } from "./cards/availability"; +import type { MouseStatus } from "@openmouse/protocol/drivers"; function on(tab: WorkspaceTab, tabs: readonly WorkspaceTab[]): boolean { return tabs.includes(tab); @@ -278,7 +279,14 @@ export function App(): ReactNode { panel.current?.scrollTo({ top: 0, behavior: preferences.reducedMotion ? "auto" : "smooth" }); }, [snapshot.workspaceTab]); - const tabs = WORKSPACE_TAB_ORDER; + const filterTabs = (status:MouseStatus|null):readonly WorkspaceTab[] => { + var tempTabs = WORKSPACE_TAB_ORDER; + if(status==null)return tempTabs; + if(!status.lighting)tempTabs=tempTabs.filter(tab=>tab!="lighting") + if(!status.analogButtonTuning)tempTabs=tempTabs.filter(tab=>tab!="buttons") + return tempTabs + } + const tabs = filterTabs(status); const onTabKey = (event: KeyboardEvent, current: WorkspaceTab): void => { const index = tabs.indexOf(current); let next: number; From d1dc454c34e712b995d98ebb6e57e82422678413 Mon Sep 17 00:00:00 2001 From: Shubhadeep <68454330+jazzstack@users.noreply.github.com> Date: Wed, 19 Aug 2026 21:53:04 +0530 Subject: [PATCH 2/4] fix: correct X8 SE VID note and add session doc X8 SE uses VID 0x1d57 (not 0x25a7) with the GearHub protocol. Updated the supported-mice entry to reflect this. --- session.md | 84 +++++++++++++++++++++++++++++++++++++++++++ src/supported-mice.ts | 2 +- 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 session.md diff --git a/session.md b/session.md new file mode 100644 index 0000000..89acba8 --- /dev/null +++ b/session.md @@ -0,0 +1,84 @@ +# Session: Attack Shark X8 SE Support Fix + +## Date +2026-08-19 + +## Problem +Attack Shark X8 SE was listed as "supported" but not working — DPI, polling rate, and battery were all returning zero/null. + +## USB Dump Analysis (`mousedata.pcapng`) + +Parsed 80,502 USB packets from the pcapng capture (linkType 249 — USBPcap). + +### Device Enumeration +- **X8 SE**: VID `0x1d57`, PID `0xfa60` — bus 2, device 11 +- 4 HID interfaces: + - IF 0: Boot Keyboard, EP `0x81` (67-byte report desc) + - IF 1: Boot Mouse, EP `0x82` (73-byte report desc) — 27,471 packets, 7-byte reports (`buttons + X/Y delta`) + - IF 2: Non-boot HID, EP `0x83` (206-byte report desc) — 54 packets, always `03 02 40 01 64` + - IF 3: Boot Keyboard, EP `0x84` (27-byte report desc) + +### Key Finding +**No HID feature report exchanges** in the entire capture. The driver never successfully communicated with the device via feature reports. + +## Root Cause + +The `detectFamily()` function in `attackshark/hid.ts` was routing all VID `0x1d57` devices to the `"1d57"` family (R1/X11 protocol). But the X8 SE uses the **GearHub protocol** (`25a7` family) despite sharing the same VID. + +The 0x1d57 family uses: +- Feature report `0x06` for polling rate +- Feature report `0xa0` for DPI read +- Battery signature `[0x03, 0x55, 0x40, 0x01]` + +The X8 SE uses the 0x25a7 GearHub protocol: +- Feature report `0x00` (64-byte MU class commands) +- Command `0x80` for firmware revision +- Command `0xD4` for DPI slots +- Command `0x04` for polling rate + +## Fixes Applied + +### 1. `mouse-protocol/src/drivers/attackshark/hid.ts` + +**`detectFamily()`** — Added vendor control collection check for VID `0x1d57`: + +```typescript +if (device.vendorId === VID_1D57) { + // Some 0x1d57 mice (X8 SE, X11) use the GearHub protocol despite + // sharing the R1 VID. Distinguish by checking for a vendor-specific + // collection (usagePage 0xffff) which the GearHub interface exposes. + if (device.collections.some(hasVendorControl)) return "25a7"; + return device.collections.some(hasFeatureReports) ? "1d57" : null; +} +``` + +**`getDpiOptions()`** — Added DPI presets for `25a7` family: + +```typescript +if (this.family === "25a7") { + return [400, 800, 1200, 1600, 2400, 3200, 6400, 12000, 26000]; +} +``` + +### 2. `openmouse/src/supported-mice.ts` + +Fixed X8 SE note: +``` +- "0x25a7 GearHub protocol — DPI, polling, firmware" ++ "0x1d57 VID, GearHub protocol — DPI, polling, firmware" +``` + +### 3. Built & Deployed + +- Built `mouse-protocol` (`npm run build`) +- Copied dist to `openmouse/node_modules/@openmouse/protocol/dist/` +- All 463 protocol tests pass + +## Detection Logic (after fix) + +| VID | Collection check | Family | Protocol | +|-----|-----------------|--------|----------| +| `0x1d57` | `hasVendorControl` (usagePage 0xffff) | `"25a7"` | GearHub (64-byte feature reports) | +| `0x1d57` | `hasFeatureReports` (any) | `"1d57"` | R1/X11 (report 0x06/0xa0) | +| `0x25a7` | `hasVendorControl` | `"25a7"` | GearHub | +| `0x373e` | `hasVendorControl` (not Lamzu) | `"373e"` | Lamzu OEM | diff --git a/src/supported-mice.ts b/src/supported-mice.ts index 3996d97..3f3c433 100644 --- a/src/supported-mice.ts +++ b/src/supported-mice.ts @@ -202,7 +202,7 @@ export const MICE: Mouse[] = [ { brand: "Attack Shark", model: "X8 Ultra", status: "likely", req: 3, note: "0x25a7 GearHub protocol — needs hardware test" }, { brand: "Attack Shark", model: "X8 SE", status: "supported", req: 2, - note: "0x25a7 GearHub protocol — DPI, polling, firmware" }, + note: "0x1d57 VID, GearHub protocol — DPI, polling, firmware" }, { brand: "Attack Shark", model: "X1", status: "likely", req: 2, note: "0x25a7 GearHub protocol — needs hardware test" }, { brand: "Attack Shark", model: "V3 Pro", status: "likely", req: 1, From c9dc5bf759c98e470eed491ba8194d760240b6a7 Mon Sep 17 00:00:00 2001 From: NotLokry Date: Wed, 19 Aug 2026 19:30:36 +0300 Subject: [PATCH 3/4] Fixed with a more reliable source --- src/app/App.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/app/App.tsx b/src/app/App.tsx index a87ad29..17b6b8a 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -113,7 +113,7 @@ function Workspace({ const tab = snapshot.workspaceTab; if (!status) return null; const has = cardAvailability(snapshot); - + console.log(has) const show = (available: boolean, tabs: readonly WorkspaceTab[]): boolean => available && on(tab, tabs); const performance = [ @@ -281,10 +281,18 @@ export function App(): ReactNode { const filterTabs = (status:MouseStatus|null):readonly WorkspaceTab[] => { var tempTabs = WORKSPACE_TAB_ORDER; + const has = cardAvailability(snapshot); if(status==null)return tempTabs; - if(!status.lighting)tempTabs=tempTabs.filter(tab=>tab!="lighting") - if(!status.analogButtonTuning)tempTabs=tempTabs.filter(tab=>tab!="buttons") - return tempTabs + if(!has.lighting)tempTabs=tempTabs.filter(tab=>tab!="lighting") + if(!has.eggButtons&& + !has.razerButtons&& + !has.mxMasterButtons&& + !has.debounce&& + !has.lightforce&& + !has.eggSpdt&& + !has.superstrike + )tempTabs=tempTabs.filter(tab=>tab!="buttons") + return tempTabs; } const tabs = filterTabs(status); const onTabKey = (event: KeyboardEvent, current: WorkspaceTab): void => { From a4c1fdf78a1eb3d1bbda2015cd8ef21765fb8194 Mon Sep 17 00:00:00 2001 From: NotLokry Date: Wed, 19 Aug 2026 19:31:29 +0300 Subject: [PATCH 4/4] Removed console log --- src/app/App.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/App.tsx b/src/app/App.tsx index 17b6b8a..f59a9cd 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -113,7 +113,6 @@ function Workspace({ const tab = snapshot.workspaceTab; if (!status) return null; const has = cardAvailability(snapshot); - console.log(has) const show = (available: boolean, tabs: readonly WorkspaceTab[]): boolean => available && on(tab, tabs); const performance = [