diff --git a/src/drivers/razer/devices.test.ts b/src/drivers/razer/devices.test.ts index 175b4eb9..a652c0ed 100644 --- a/src/drivers/razer/devices.test.ts +++ b/src/drivers/razer/devices.test.ts @@ -145,6 +145,9 @@ test("the wired DeathAdder V3 writes polling on the extended command", () => { const wired = RAZER_PRODUCTS.get(0x00b2); assert.equal(wired?.wireless, false); assert.equal(wired?.highRatePolling, true); + // Both writes stay on 0x1f. The dongle's commit uses 0xff; copying that + // here would address a transaction this mouse does not use for the commit. + assert.equal(wired?.extendedPollingCommitTransactionId, RAZER_TRANSACTION_ID); // The rate the hardware was found at has to survive the round trip, or the // picker offers a value the mouse is already sitting at and cannot be set to. assert.ok(wired?.pollingRates.includes(2000)); diff --git a/src/drivers/razer/hid.test.ts b/src/drivers/razer/hid.test.ts index 2d21e14b..a57fb7c3 100644 --- a/src/drivers/razer/hid.test.ts +++ b/src/drivers/razer/hid.test.ts @@ -869,6 +869,23 @@ test("Mouse Dock Pro with a HyperPolling mouse unlocks the 8 kHz ladder", async assert.deepEqual(status.supportedPollingRates, [...RATES_8K]); }); +test("the wired DeathAdder V3 commits polling with selector 0x01 on the same transaction id", async () => { + // Issue #222: selector 0x00 alone is acknowledged and the read-back stays + // at the old rate. OpenRazer follows it with selector 0x01, still on 0x1f. + const { client, sent } = fakeMouse( + { tracking: 0, liftOff: 2, landing: 1, asymmetric: false }, + { productId: 0x00b2 }, + ); + + const confirmed = await client.setPollingRate(2000); + + assert.equal(confirmed, 2000); + const writes = sent.filter((packet) => packet[6] === 0x00 && packet[7] === 0x40); + assert.equal(writes.length, 2); + assert.deepEqual([writes[0][1], writes[0][8], writes[0][9]], [0x1f, 0x00, 0x04]); + assert.deepEqual([writes[1][1], writes[1][8], writes[1][9]], [0x1f, 0x01, 0x04]); +}); + test("HyperPolling dongle commits an 8 kHz change through both selectors", async () => { const { client, sent } = fakeMouse( { tracking: 0, liftOff: 2, landing: 1, asymmetric: false }, diff --git a/src/razer/devices.ts b/src/razer/devices.ts index 1f46af7e..f6a1db85 100644 --- a/src/razer/devices.ts +++ b/src/razer/devices.ts @@ -124,10 +124,10 @@ export interface RazerProduct { */ highRatePolling: boolean; /** - * Some early HyperPolling devices commit an extended polling change with a - * second write: selector `0x01` on a different transaction id. OpenRazer - * does this for the standalone HyperPolling dongle after the ordinary - * selector-`0x00` write. Omitted for devices that need only one write. + * Commit an extended polling change with a second write, selector `0x01`, + * on this transaction id. OpenRazer sends the ordinary selector-`0x00` + * write first. The HyperPolling dongle puts the commit on `0xff`; the wired + * DeathAdder V3 keeps both writes on `0x1f`. Omitted when one write is enough. */ extendedPollingCommitTransactionId?: number; /** @@ -497,12 +497,18 @@ const PRODUCT_DEFINITIONS: ReadonlyArray<[number, Omit