From e3a73f5361f7c81a6beeb659a3628a4ea0e72a14 Mon Sep 17 00:00:00 2001 From: ydw1904 Date: Thu, 8 Oct 2026 11:24:30 +0800 Subject: [PATCH] feat: wire the Glorious Model O 2 PRO 4K/8K driver into the connect flow Adds GloriousCore2HidClient to NEEDS_OPEN so its input-report handling is set up on connect, gives the glorious-core2 family the advanced section and the debounce card in traits (it has no sleep command wired in), and marks the Model O2 Pro 4K/8K as having a driver PR in the supported mirror (only that row). An availability test covers the cards the family opens: debounce, Motion Sync and the profile card, but not sleep or signal. Needs the mouse-protocol release that contains the driver before the @openmouse/protocol pin can be bumped. Requested in Discord ticket 0160. Co-Authored-By: Claude Sonnet 5.5 --- src/app/cards/availability.test.ts | 25 +++++++++++++++++++++++++ src/device/controller.ts | 3 ++- src/device/traits.ts | 3 +++ src/supported-devices-data.ts | 2 +- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/app/cards/availability.test.ts b/src/app/cards/availability.test.ts index 4835206b..3894c0c4 100644 --- a/src/app/cards/availability.test.ts +++ b/src/app/cards/availability.test.ts @@ -596,3 +596,28 @@ test("the Incott card follows the fields the device reported, not a brand trait" })); assert.equal(silent.incott, false); }); + +test("the Glorious Model O2 Pro 4K/8K opens debounce, Motion Sync and the profile card, but not sleep or signal", () => { + const cards = cardAvailability(snapshot({ + status: { + brand: "Glorious", + ui: { + family: "glorious-core2", + showAdvancedSection: true, + hideAngleSnapping: true, + hideRippleControl: true, + hideSleepCard: true, + hideSignalCard: true, + }, + debounceMs: 10, + motionSync: true, + activeProfile: 1, + profileCount: 3, + }, + })); + assert.equal(cards.debounce, true); + assert.equal(cards.processing, true); + assert.equal(cards.onboardProfiles, true); + assert.equal(cards.sleep, false); + assert.equal(cards.signal, false); +}); diff --git a/src/device/controller.ts b/src/device/controller.ts index 1ae066c1..a7badff7 100644 --- a/src/device/controller.ts +++ b/src/device/controller.ts @@ -160,6 +160,7 @@ import { Keychron8kNordicHidClient } from "@openmouse/protocol/drivers/keychron/ import type { GloriousLighting } from "@openmouse/protocol/glorious"; import { GloriousHidClient } from "@openmouse/protocol/drivers/glorious/hid"; import { GloriousClassicHidClient } from "@openmouse/protocol/drivers/glorious/classic-hid"; +import { GloriousCore2HidClient } from "@openmouse/protocol/drivers/glorious/core2-hid"; import { MchoseHidClient } from "@openmouse/protocol/drivers/mchose/hid"; import { MchoseDockHidClient } from "@openmouse/protocol/drivers/mchose/dock-hid"; import { MchoseA5ProMaxHidClient } from "@openmouse/protocol/drivers/mchose/a5-gen1-hid"; @@ -267,7 +268,7 @@ function activeAs(...classes: ClientClass[]): T | null { const DM_CLASSES = [WLMouseHidClient, LamzuHidClient, LamzuAtlantisHidClient, AtkHidClient, AtkBitmouseHidClient, NinjutsoHidClient] as const; const RAZER_CLASSES = [RazerHidClient, RazerViperMiniHidClient, RazerViperHidClient, RazerCobraHidClient] as const; -const NEEDS_OPEN = [LamzuAtlantisHidClient, TeevolutionHidClient, VgnF2HidClient, KeychronNapeHidClient, Keychron8kNordicHidClient, WLMouseBeastX4kHidClient, ModdoHidClient, ZaunkoenigHidClient, CorsairHidClient, FantechHidClient, WallhackMouseHidClient, WallhackKeyboardHidClient, GloriousHidClient, GloriousClassicHidClient, MchoseHidClient, MchoseDockHidClient, MchoseA5ProMaxHidClient, MchoseV3HidClient, MicrosoftHidClient, DareuHidClient, IncottHidClient, BytechHidClient, RapooHidClient, FaterHidClient, CoolerMasterHidClient, RedragonM690ProHidClient] as const; +const NEEDS_OPEN = [LamzuAtlantisHidClient, TeevolutionHidClient, VgnF2HidClient, KeychronNapeHidClient, Keychron8kNordicHidClient, WLMouseBeastX4kHidClient, ModdoHidClient, ZaunkoenigHidClient, CorsairHidClient, FantechHidClient, WallhackMouseHidClient, WallhackKeyboardHidClient, GloriousHidClient, GloriousClassicHidClient, GloriousCore2HidClient, MchoseHidClient, MchoseDockHidClient, MchoseA5ProMaxHidClient, MchoseV3HidClient, MicrosoftHidClient, DareuHidClient, IncottHidClient, BytechHidClient, RapooHidClient, FaterHidClient, CoolerMasterHidClient, RedragonM690ProHidClient] as const; const PULSAR_CLASSES = [PulsarHidClient, PulsarProHidClient, PulsarXs1HidClient] as const; const logitechClient = (): LogitechHidppClient | null => activeAs(LogitechHidppClient); diff --git a/src/device/traits.ts b/src/device/traits.ts index 66cedc10..27e71472 100644 --- a/src/device/traits.ts +++ b/src/device/traits.ts @@ -79,6 +79,9 @@ const BY_FAMILY: Readonly>> = { // it publishes its own sleep and debounce option lists. "mchose-v3": { advancedSection: true, sleep: true, debounce: true }, dareu: { advancedSection: true, sleep: true }, + // The Model O2 Pro 4K/8K writes a debounce block and a motion sync flag; it + // has no sleep command wired in, so no sleep flag. + "glorious-core2": { advancedSection: true, debounce: true }, // Incott supports a 0-30 ms debounce and a 1-900 s sleep timer over its own // vendor protocol, not the CompX direct-mode transport, so it takes the // plain flags rather than DIRECT_MODE (its advancedSection already comes diff --git a/src/supported-devices-data.ts b/src/supported-devices-data.ts index 0c4fc0e3..c34f889d 100644 --- a/src/supported-devices-data.ts +++ b/src/supported-devices-data.ts @@ -224,7 +224,7 @@ export const SUPPORTED_DEVICES: readonly SupportedDeviceEntry[] = [ { brand: "Glorious", model: "Model O", status: "supported", pids: [0x2011, 0x2022] }, { brand: "Glorious", model: "Model D Wireless", status: "supported", pids: [0x2012, 0x2023] }, { brand: "Glorious", model: "Model D", status: "supported", pids: [0x2012] }, - { brand: "Glorious", model: "Model O2 Pro 4K/8K", status: "likely", pids: [0x201b, 0x2035] }, + { brand: "Glorious", model: "Model O2 Pro 4K/8K", status: "pr", pids: [0x201b, 0x2035] }, { brand: "Glorious", model: "Model O Pro", status: "supported", pids: [0x2015, 0x2027] }, { brand: "Glorious", model: "Model D2 Pro Wireless 8K", status: "likely", pids: [0x201c, 0x2036] }, { brand: "Glorious", model: "Model O3 Wireless", status: "likely", pids: [0xa312, 0xa300] },