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
2 changes: 2 additions & 0 deletions src/devices/razer/TESTING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,6 +5,8 @@ control interface open and reads then time out.

Supported identifiers:

- `1532:00a5` — Viper V2 Pro, wired
- `1532:00a6` — Viper V2 Pro, Stock receiver
- `1532:00c0` — Viper V3 Pro, wired
- `1532:00c1` — Viper V3 Pro, HyperSpeed receiver

Expand Down
8 changes: 7 additions & 1 deletion src/devices/razer/hid.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,6 +24,8 @@ interface RazerProduct {
model: string;
wireless: boolean;
pollingRates: readonly number[];
// Defaults to DPI_MAX when omitted
maxDpi?: number;
}

// The cable tops out at 1000 Hz on this model, which is also the ceiling the
Expand All@@ -32,6 +34,10 @@ const RATES_WIRED: readonly number[] = [125, 500, 1000];
const RATES_RECEIVER: readonly number[] = [125, 500, 1000, 2000, 4000, 8000];

const PRODUCTS: ReadonlyMap<number, RazerProduct> = new Map([
// Stock receiver, not 8K HyperPolling.
[0x00a5, { model: "Viper V2 Pro", wireless: false, pollingRates: RATES_WIRED, maxDpi: 30000 }],
[0x00a6, { model: "Viper V2 Pro", wireless: true, pollingRates: RATES_WIRED, maxDpi: 30000 }],

[0x00c0, { model: "Viper V3 Pro", wireless: false, pollingRates: RATES_WIRED }],
[0x00c1, { model: "Viper V3 Pro", wireless: true, pollingRates: RATES_RECEIVER }],
]);
Expand DownExpand Up@@ -88,7 +94,7 @@ export class RazerHidClient {
}

maxDpi(): number {
return DPI_MAX;
return this.profile()?.maxDpi ?? DPI_MAX;
}

getSupportedPollingRates(): number[] {
Expand Down
11 changes: 8 additions & 3 deletions src/devices/vendors.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,10 +14,14 @@ export const VENDOR_ID = {
atk: 0x373b,
} as const;

// Viper V3 Pro exposes its control channel as a Generic Desktop Mouse
// collection. Limit this broad collection filter to its two known PIDs so it
// cannot also surface unrelated Razer keyboards or the Viper V4 Pro's ordinary
// Viper V2/V3 Pro expose their control channel as a Generic Desktop Mouse
// collection. Limit this broad collection filter to known PIDs so it cannot
// also surface unrelated Razer keyboards or the Viper V4 Pro's ordinary
// boot-mouse interfaces.
export const RAZER_VIPER_V2_CONTROL_FILTERS: HIDDeviceFilter[] = [0x00a5, 0x00a6].map(
(productId) => ({ vendorId: VENDOR_ID.razer, productId, usagePage: 0x01, usage: 0x02 }),
);

export const RAZER_VIPER_V3_CONTROL_FILTERS: HIDDeviceFilter[] = [0x00c0, 0x00c1].map(
(productId) => ({ vendorId: VENDOR_ID.razer, productId, usagePage: 0x01, usage: 0x02 }),
);
Expand DownExpand Up@@ -89,6 +93,7 @@ export const SUPPORTED_HID_FILTERS: HIDDeviceFilter[] = [
{ vendorId: VENDOR_ID.lamzu },
{ vendorId: VENDOR_ID.orbital, usagePage: 0xff0a, usage: 1 },
...TEEVOLUTION_PRODUCT_IDS.map((productId) => ({ vendorId: VENDOR_ID.teevolution, productId })),
...RAZER_VIPER_V2_CONTROL_FILTERS,
...RAZER_VIPER_V3_CONTROL_FILTERS,
{ vendorId: VENDOR_ID.vgn, productId: 0xfb56 },
{ vendorId: VENDOR_ID.vgn, productId: 0xfb57 },
Expand Down