dualsense-ts
Version:
The natural interface for your DualSense Classic and DualSense Access controllers, with Typescript
177 lines • 8.75 kB
TypeScript
import { PulseOptions, Brightness, MuteLedMode } from "./command";
import { HIDProvider, DualsenseHIDState } from "./hid_provider";
import { FirmwareInfo } from "./firmware_info";
import { FactoryInfo } from "./factory_info";
import type { ResolvedCalibration } from "./calibration";
export type HIDCallback = (state: DualsenseHIDState) => void;
export type ErrorCallback = (error: Error) => void;
export type ReadyCallback = () => void;
export type ConnectionCallback = (connected: boolean) => void;
/** Coordinates a HIDProvider and tracks the latest HID state */
export declare class DualsenseHID {
readonly provider: HIDProvider;
/** Subscribers waiting for HID state updates */
private readonly subscribers;
/** Subscribers waiting for error updates */
private readonly errorSubscribers;
/** Subscribers waiting for firmware/factory info to become available */
private readonly readySubscribers;
/** Subscribers tracking transport-level connect/disconnect events */
private readonly connectionSubscribers;
/** True once firmware/factory info has been loaded for the current connection */
private identityResolved;
/** Pending retry timer for identity loading after a transient failure */
private identityRetryTimer?;
/** Number of identity-load attempts made for the current connection */
private identityRetryCount;
/** Queue of pending HID commands */
private pendingCommands;
/** Most recent HID state of the device */
state: DualsenseHIDState;
/** Firmware and hardware information, populated after connection */
firmwareInfo: FirmwareInfo;
/** Factory information (serial, color, board revision), populated after connection */
factoryInfo: FactoryInfo;
/** Bluetooth MAC address from Feature Report 0x09, populated after connection */
macAddress?: string;
/**
* Precomputed IMU calibration factors, populated during provider connection.
* Applied automatically to gyro and accelerometer readings in each input report.
*/
get calibration(): ResolvedCalibration;
/** Active interval timer for the command flush loop */
private commandTimer?;
constructor(provider: HIDProvider, refreshRate?: number);
/** Stop the command flush loop and cancel pending identity retries */
dispose(): void;
get wireless(): boolean;
/** Register a handler for HID state updates */
register(callback: HIDCallback): void;
/** Cancel a previously registered handler */
unregister(callback: HIDCallback): void;
/** Add a subscriber for errors */
on(type: string, callback: ErrorCallback): void;
/**
* Subscribe to notification when firmware/factory info finishes loading
* after a connect. Fires once per connection — either when identity has
* been resolved, or when we've given up retrying. If identity is already
* resolved at the time of subscription, the callback fires synchronously.
*/
onReady(callback: ReadyCallback): () => void;
/** True if firmware/factory info has been loaded (or given up on) for the current connection */
get ready(): boolean;
/**
* Subscribe to transport-level connect/disconnect events. Useful for
* mirroring connection state into an Input without polling. Returns
* an unsubscribe function.
*/
onConnectionChange(callback: ConnectionCallback): () => void;
/**
* Stable hardware identity for this controller, derived from the most
* trustworthy info available. Prefers the Bluetooth MAC address (from
* Feature Report 0x09, works on every transport and platform), then
* falls back to the factory serial, then firmware deviceInfo.
* Returns undefined until identity info has been read.
*/
get identity(): string | undefined;
/** Update the HID state and pass it along to all state subscribers */
private set;
/** Pass errors along to all error subscribers */
private handleError;
/** Maximum identity-load retry attempts per connection */
private static readonly IDENTITY_MAX_ATTEMPTS;
/** Backoff schedule (ms) for identity-load retries */
private static readonly IDENTITY_BACKOFF_MS;
/**
* Attempt to read firmware + factory info for the current connection,
* with retry on failure. Marks identity as resolved on success or after
* exhausting all attempts (so consumers don't wait forever).
*
* If cached firmware/factory info exists from a prior session, identity
* is resolved immediately (so the connection event has full details),
* then a background verification re-reads the device to confirm.
*/
private loadIdentity;
/** Mark identity loading as complete and notify subscribers */
private markIdentityResolved;
/** Cancel any pending identity-load retry */
private cancelIdentityRetry;
/** In-flight firmware info fetch, deduped across callers within a connection */
private firmwareFetch?;
/** In-flight factory info fetch, deduped across callers within a connection */
private factoryFetch?;
/**
* Read firmware info from the controller (Feature Report 0x20).
* Idempotent: returns the cached value if already fetched, or the
* in-flight promise if a fetch is already underway.
*/
fetchFirmwareInfo(): Promise<FirmwareInfo>;
/**
* Read factory info (serial number, body color, board revision) from the controller.
* Requires firmware info to be fetched first for feature gating.
* Idempotent across the lifetime of a single connection.
*/
fetchFactoryInfo(): Promise<FactoryInfo>;
/** Condense all pending commands into one HID feature report */
private static buildFeatureReport;
/** Set intensity for left and right rumbles */
setRumble(left: number, right: number): void;
/** Set left trigger effect from an 11-byte effect block */
setLeftTriggerFeedback(block: Uint8Array): void;
/** Set right trigger effect from an 11-byte effect block */
setRightTriggerFeedback(block: Uint8Array): void;
/** Set microphone mute LED mode */
setMicrophoneLED(mode: MuteLedMode): void;
/** Set player indicator LEDs from a 5-bit bitmask and brightness */
setPlayerLeds(bitmask: number, brightness?: Brightness): void;
/** Set headphone volume (0x00–0x7F) */
setHeadphoneVolume(volume: number): void;
/** Set internal speaker volume (0x00–0x64, where 0x64 is full volume) */
setSpeakerVolume(volume: number): void;
/** Set internal microphone volume (0x00–0x40) */
setMicrophoneVolume(volume: number): void;
/** Set audio output routing and microphone flags */
setAudioFlags(flags: number): void;
/** Set power save control bitfield (per-subsystem mute/disable) */
setPowerSave(flags: number): void;
/** Set speaker preamp gain (0–7) and optional beam forming */
setSpeakerPreamp(gain: number, beamForming?: boolean): void;
/** Set the light bar color and pulse effect */
setLightbar(r: number, g: number, b: number, pulse?: PulseOptions): void;
/** Feature report ID for DSP test commands */
private static readonly TEST_REPORT_ID;
/** DSP device ID for audio subsystem */
private static readonly DSP_DEVICE_AUDIO;
/** Action ID: configure output routing before waveout */
private static readonly DSP_ACTION_CONFIGURE;
/** Action ID: start or stop waveform playback */
private static readonly DSP_ACTION_WAVEOUT;
/**
* Build a feature report 0x80 payload.
* Format: [reportId, deviceId, actionId, ...params]
*/
private static buildTestCommand;
/**
* Start a DSP test tone on speaker or headphone.
* Sets volume routing via the standard output report before triggering.
*
* @param target Output destination — "speaker" (default) or "headphone"
* @param tone Which tone to play — "1khz" (default), "100hz", or "both"
*/
startTestTone(target?: "speaker" | "headphone", tone?: "1khz" | "100hz" | "both"): Promise<void>;
/** Stop the DSP test tone */
stopTestTone(): Promise<void>;
/**
* Send a raw DSP test command (Feature Report 0x80).
* For experimentation — lets you send arbitrary device/action/params.
*/
sendTestCommand(deviceId: number, actionId: number, params?: Uint8Array): Promise<void>;
/** Feature report ID for DSP test responses */
private static readonly TEST_RESPONSE_ID;
/**
* Read the DSP test response (Feature Report 0x81).
* Returns the raw response bytes, or undefined if not available.
*/
readTestResponse(): Promise<Uint8Array | undefined>;
}
//# sourceMappingURL=dualsense_hid.d.ts.map