Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/drivers/razer/devices.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,12 @@ const EXPECTED_DIVERGENCE: ReadonlyMap<number, { ours: number; openRazer: number
// Not a mouse in OpenRazer's table; the dock answers on the paired mouse's
// generation id. Confirmed with a Naga V2 Pro.
[0x00a4, { ours: 0x1f, openRazer: 0xff, why: "hardware report with Naga V2 Pro: dock answers on 0x1f" }],
// DeathAdder V4 Pro Carbon Fiber Edition: not in OpenRazer's table at all
// yet (a cosmetic SKU, likely too new), so the audit map has no entry and
// the fallback would be 0xff. Assumed to share 0x00be/0x00bf's 0x1f as the
// same electronics under a different shell — unverified either way.
[0x00ef, { ours: 0x1f, openRazer: 0xff, why: "not yet in OpenRazer; assumed same generation as 0x00be" }],
[0x00f0, { ours: 0x1f, openRazer: 0xff, why: "not yet in OpenRazer; assumed same generation as 0x00bf" }],
]);

test("every transaction id matches OpenRazer, or is a divergence with a reason", () => {
Expand Down
11 changes: 7 additions & 4 deletions src/drivers/razer/hid.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -532,13 +532,16 @@ test("the DeathAdder V2 is accepted on either interface shape", () => {
});

test("a nativeOnly model is never accepted, whatever the interface shape", () => {
// The DeathAdder V4 Pro 0x00be has its control channel on a collection the
// browser refuses to expose. A granted device may still enumerate through
// getDevices()/auto-reconnect, so isSupported must refuse it regardless.
// The Viper Ultimate wireless receiver 0x007b has its control channel on a
// collection the browser refuses to expose. A granted device may still
// enumerate through getDevices()/auto-reconnect, so isSupported must refuse
// it regardless. (The DeathAdder V4 Pro used to be this test's example —
// Razer's own live AvailableDevices.json now lists it, so it's no longer
// nativeOnly; see devices.ts.)
// Arrange
const mouse = {
vendorId: 0x1532,
productId: 0x00be,
productId: 0x007b,
collections: [{ usagePage: 0x01, usage: 0x02, featureReports: [], children: [] }],
} as unknown as HIDDevice;
const vendor = {
Expand Down
25 changes: 20 additions & 5 deletions src/razer/devices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ const TRANSACTION_1F: readonly number[] = [
// name. The SE reference separately mentions `0xff`, but only for the
// HyperPolling dongle indicator command, which this driver does not send.
0x00de, 0x00df,
// DeathAdder V4 Pro Carbon Fiber Edition. Same electronics as `0x00be`/
// `0x00bf` under a cosmetic SKU (Razer's own live `AvailableDevices.json`
// groups them the same way, receiver id one above the mouse id), so it
// shares that pair's transaction id — not independently audited.
0x00ef, 0x00f0,
];

/**
Expand Down Expand Up @@ -614,15 +619,25 @@ const PRODUCT_DEFINITIONS: ReadonlyArray<[number, Omit<RazerProduct, "transactio
// has measured it — see TESTING.md.
[0x00b7, { model: "DeathAdder V3 Pro", ...MODERN_RECEIVER, highRatePolling: false, maxDpi: DPI_FOCUS_PRO }],
[0x00b9, { model: "Basilisk V3 X HyperSpeed", ...LEGACY_RECEIVER, maxDpi: 18_000 }],
// The control channel is on a Chrome-protected collection: with Synapse fully
// stopped the diagnostics harness got "no feature report channel" on every
// interface, in both the wired and wireless roles. Native HAL only.
// Was nativeOnly: the control channel used to sit on a Chrome-protected
// collection (with Synapse fully stopped the diagnostics harness got "no
// feature report channel" on every interface, wired and wireless both —
// see git blame). Razer's own live `AvailableDevices.json` on Synapse Web
// now lists this model (productId 190/191, i.e. 0x00be/0x00bf), meaning a
// firmware or descriptor update moved the control channel off that
// collection. Re-tested and confirmed reachable over WebHID.
// OpenRazer PR #2508: both the cable and the HyperPolling dongle reach
// 8000 Hz on this model (the wired half is not capped at MODERN_WIRED's
// usual 1000 Hz — a HyperPolling receiver ships in the box, so the cable
// gets the same ceiling as the dongle).
[0x00be, { model: "DeathAdder V4 Pro (Wired)", ...MODERN_WIRED, pollingRates: RATES_8K, highRatePolling: true, maxDpi: DPI_DEATHADDER_V4_PRO, nativeOnly: true }],
[0x00bf, { model: "DeathAdder V4 Pro", ...HYPERPOLLING_RECEIVER, maxDpi: DPI_DEATHADDER_V4_PRO, nativeOnly: true }],
[0x00be, { model: "DeathAdder V4 Pro (Wired)", ...MODERN_WIRED, pollingRates: RATES_8K, highRatePolling: true, maxDpi: DPI_DEATHADDER_V4_PRO }],
[0x00bf, { model: "DeathAdder V4 Pro", ...HYPERPOLLING_RECEIVER, maxDpi: DPI_DEATHADDER_V4_PRO }],
// Carbon Fiber Edition — cosmetic SKU on its own product ids, listed
// alongside 0x00be/0x00bf in Razer's live AvailableDevices.json
// (productId 239/240). Not independently hardware-tested; same specs
// assumed as the standard edition until proven otherwise.
[0x00ef, { model: "DeathAdder V4 Pro Carbon Fiber Edition (Wired)", ...MODERN_WIRED, pollingRates: RATES_8K, highRatePolling: true, maxDpi: DPI_DEATHADDER_V4_PRO }],
[0x00f0, { model: "DeathAdder V4 Pro Carbon Fiber Edition", ...HYPERPOLLING_RECEIVER, maxDpi: DPI_DEATHADDER_V4_PRO }],
[0x00c2, { model: "DeathAdder V3 Pro (Wired)", ...MODERN_WIRED, maxDpi: DPI_FOCUS_PRO }],
[0x00c3, { model: "DeathAdder V3 Pro", ...MODERN_RECEIVER, maxDpi: DPI_FOCUS_PRO }],
[0x00c4, { model: "DeathAdder V3 HyperSpeed (Wired)", ...MODERN_WIRED, maxDpi: DPI_FOCUS_PRO }],
Expand Down