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
4 changes: 2 additions & 2 deletions docs/ADDING-A-CONTROLLER.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ If the vid:pid matches a known controller family, the existing protocol driver p

| Family | Driver class | Examples |
| --- | --- | --- |
| PlayStation (DS4 + DS5) | `DualSenseDriver` | DualSense, DualSense Edge, DualShock 4, GameSir Super Nova/Cyclone in DS4 mode |
| PlayStation (DS4 + DS5) | `PlayStationDriver` | DualSense, DualSense Edge, DualShock 4, GameSir Super Nova/Cyclone in DS4 mode |
| Nintendo Switch Pro | `SwitchProDriver` | Switch Pro, GameSir Cyclone in Switch mode |
| Xbox | `XboxDriver` | All Xbox families (Gamepad-API only, no WebHID features) |
| Steam Controller 2026 | `SteamControllerDriver` | (stub — real HID parsing TBD) |
Expand Down Expand Up @@ -87,7 +87,7 @@ This prints:
> yaw gyroY_std=257.2 likely axis: gyro Y
> ```
>
> The "winner" line told us GameSir packs IMU at byte 12/18 — three bytes earlier than Sony's DualSense layout (15/21). That single insight fixed a months-old latent bug: the existing DualSense parser was *also* wrong for real Sony DS4 (which uses the same byte-12 layout), it had only ever been validated against a DualSense (DS5). The fix in [packages/core/src/drivers/dualsense-driver.js](../packages/core/src/drivers/dualsense-driver.js) branches on `entry.mode === 'ds4'` and lights up both clones and real Sony DS4 hardware simultaneously.
> The "winner" line told us GameSir packs IMU at byte 12/18 — three bytes earlier than Sony's DualSense layout (15/21). That single insight fixed a months-old latent bug: the existing PlayStation parser was *also* wrong for real Sony DS4 (which uses the same byte-12 layout), it had only ever been validated against a DualSense (DS5). The fix in [packages/core/src/drivers/playstation-driver.js](../packages/core/src/drivers/playstation-driver.js) branches on `entry.mode === 'ds4'` and lights up both clones and real Sony DS4 hardware simultaneously.

## 5 — Update `devices.js`

Expand Down
2 changes: 1 addition & 1 deletion packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Vendor-agnostic gamepad drivers, WebHID sensor fusion, and the slot/claim `Contr
| `@usersfirst/controller-core/sensor-fusion` | `SensorFusion` (gyro orientation + bias calibration + drift correction) |
| `@usersfirst/controller-core/drivers/controller-registry` | Registry lookup (`getEntry`, `getDriver`, `identifyFromGamepadId`, `getGamepadQuirks`, ...) |
| `@usersfirst/controller-core/drivers/base-driver` | Abstract `ControllerDriver` (protocol interface) |
| `@usersfirst/controller-core/drivers/dualsense-driver` | DualSense / DualShock 4 protocol — gyro, accel, touchpad, lightbar |
| `@usersfirst/controller-core/drivers/playstation-driver` | PlayStation (DualSense + DualShock 4) protocol — gyro, accel, touchpad, lightbar. Registered under the `'dualsense'` protocol key. |
| `@usersfirst/controller-core/drivers/switch-pro-driver` | Switch Pro protocol — IMU enable + gyro |
| `@usersfirst/controller-core/drivers/xbox-driver` | Xbox identity stub (Gamepad-API only on Chromium; no WebHID capabilities today) |
| `@usersfirst/controller-core/drivers/steam-controller-driver` | Steam Controller 2026 identity stub (placeholder for full Steam Input parsing) |
Expand Down
11 changes: 8 additions & 3 deletions packages/core/src/devices.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,19 @@
// }
// ============================================================

import { DualSenseDriver } from './drivers/dualsense-driver.js';
import { PlayStationDriver } from './drivers/playstation-driver.js';
import { SwitchProDriver } from './drivers/switch-pro-driver.js';
import { XboxDriver } from './drivers/xbox-driver.js';
import { SteamControllerDriver } from './drivers/steam-controller-driver.js';

/** Protocol id → driver class. Add a new protocol here when a new driver lands. */
// Protocol id → driver class. The 'dualsense' key historically named
// just the DS5 protocol; it now covers PlayStation's DS4 + DS5 layouts
// (the class was renamed to PlayStationDriver to reflect that, but the
// key is preserved so the visualizer's PROFILES['dualsense'] GLB
// continues to load for all Sony entries without needing a per-entry
// controllerProfile override).
export const PROTOCOLS = {
'dualsense': DualSenseDriver,
'dualsense': PlayStationDriver,
'switch-pro': SwitchProDriver,
'xbox': XboxDriver,
'steam-controller': SteamControllerDriver,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/drivers/controller-registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class ControllerRegistry {

/**
* Find the driver class for a vid:pid. Returns the protocol implementation
* (DualSenseDriver, SwitchProDriver, etc.) or null.
* (PlayStationDriver, SwitchProDriver, etc.) or null.
* @returns {typeof ControllerDriver|null}
*/
static getDriver(vendorId, productId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
// ============================================================
// DUALSENSE / DUALSHOCK 4 DRIVER
// PLAYSTATION DRIVER — DualSense (DS5) + DualShock 4 (DS4) protocol
// ============================================================
//
// Covers both Sony PlayStation HID protocols and any clones that spoof
// them (GameSir Super Nova / Cyclone 2 in DS4 mode, etc.). The two
// protocols share most of the input-report layout, differing mainly in
// IMU byte offsets — that branch is driven by the dictionary entry's
// `mode` field ('ds5' vs 'ds4'), not by a separate driver class.
//
// Registered in PROTOCOLS under the key 'dualsense' (preserved as-is so
// existing visualizer profile mappings keep working without forcing a
// controllerProfile override on every Sony PlayStation entry).
//
// Identity (vid:pid, name, capabilities, gamepad-id pattern) lives in
// devices.js — this class is purely the protocol implementation.

import { ControllerDriver } from './base-driver.js';

// Identity (vid:pid, name, capabilities, gamepad-id pattern) lives in
// devices.js — this class is the DualSense/DualShock 4 protocol only.

export class DualSenseDriver extends ControllerDriver {
export class PlayStationDriver extends ControllerDriver {

constructor(device, connectionType, entry = null) {
super(device, connectionType, entry);
Expand Down Expand Up @@ -129,8 +139,8 @@ export class DualSenseDriver extends ControllerDriver {

// ── Touchpad — 2 touch points, 4 bytes each ──
const touchpad = [
DualSenseDriver._parseTouchPoint(data, touchOffset),
DualSenseDriver._parseTouchPoint(data, touchOffset + 4)
PlayStationDriver._parseTouchPoint(data, touchOffset),
PlayStationDriver._parseTouchPoint(data, touchOffset + 4)
];

// Touchpad click: bit 1 of the PS byte
Expand Down Expand Up @@ -394,7 +404,7 @@ export class DualSenseDriver extends ControllerDriver {
crcInput[0] = 0xA2;
crcInput[1] = 0x31;
crcInput.set(buf.subarray(0, PAYLOAD_LEN - 4), 2);
const crc = DualSenseDriver._crc32(crcInput);
const crc = PlayStationDriver._crc32(crcInput);
buf[PAYLOAD_LEN - 4] = crc & 0xFF;
buf[PAYLOAD_LEN - 3] = (crc >>> 8) & 0xFF;
buf[PAYLOAD_LEN - 2] = (crc >>> 16) & 0xFF;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export {

export { ControllerDriver } from './drivers/base-driver.js';
export { ControllerRegistry } from './drivers/controller-registry.js';
export { DualSenseDriver } from './drivers/dualsense-driver.js';
export { PlayStationDriver } from './drivers/playstation-driver.js';
export { SwitchProDriver } from './drivers/switch-pro-driver.js';
export { XboxDriver } from './drivers/xbox-driver.js';
export { SteamControllerDriver } from './drivers/steam-controller-driver.js';
Expand Down