dualsense-ts 6.15.0 → 6.15.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -3
- package/README.md +20 -20
- package/dist/dualsense.d.ts +4 -4
- package/dist/dualsense.js +5 -5
- package/dist/dualsense_access.d.ts +11 -11
- package/dist/dualsense_access.js +1 -1
- package/dist/elements/trigger_feedback.d.ts +1 -1
- package/dist/elements/trigger_feedback.js +1 -1
- package/dist/hid/access/access_node_hid_provider.d.ts +2 -2
- package/dist/hid/access/access_node_hid_provider.js +3 -3
- package/dist/hid/access_hid.d.ts +1 -1
- package/dist/hid/access_hid.js +1 -1
- package/dist/hid/calibration.d.ts +1 -1
- package/dist/hid/calibration.js +1 -1
- package/dist/hid/command.d.ts +6 -6
- package/dist/hid/command.js +3 -3
- package/dist/hid/dsp.d.ts +6 -6
- package/dist/hid/dsp.js +6 -6
- package/dist/hid/dualsense_hid.d.ts +4 -4
- package/dist/hid/dualsense_hid.js +8 -8
- package/dist/hid/factory_info.d.ts +8 -2
- package/dist/hid/factory_info.d.ts.map +1 -1
- package/dist/hid/factory_info.js +10 -1
- package/dist/hid/factory_info.js.map +1 -1
- package/dist/hid/node_hid_provider.d.ts +2 -2
- package/dist/hid/node_hid_provider.js +1 -1
- package/dist/hid/web_hid_provider.d.ts +1 -1
- package/dist/hid/web_hid_provider.js +3 -3
- package/dist/manager.d.ts +4 -4
- package/dist/manager.js +13 -13
- package/dist/motion/madgwick.d.ts +2 -2
- package/dist/motion/madgwick.js +3 -3
- package/dist/motion/orientation.d.ts +3 -3
- package/dist/motion/orientation.js +3 -3
- package/dist/motion/quaternion.d.ts +2 -2
- package/dist/motion/quaternion.js +2 -2
- package/dist/motion/shake.d.ts +8 -8
- package/dist/motion/shake.js +9 -9
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -19,7 +19,7 @@ All notable changes to `dualsense-ts` are documented here. This project uses [Se
|
|
|
19
19
|
|
|
20
20
|
- **DualSense Access controller support**: new `DualsenseAccess` class with full input reading and LED control over USB and Bluetooth
|
|
21
21
|
- **Inputs**: 8 hardware buttons (B1–B8), center button, PS button, profile cycle button, analog stick (X/Y/click), battery level and charge status, active profile ID (1–3)
|
|
22
|
-
- **LED output**: RGB lightbar, 3-segment profile LEDs (off/on/fade/sweep), 6-segment player indicator (patterns 1–4), white status LED
|
|
22
|
+
- **LED output**: RGB lightbar, 3-segment profile LEDs (off/on/fade/sweep), 6-segment player indicator (patterns 1–4), white status LED - all controllable over both USB and BT
|
|
23
23
|
- **Bluetooth**: full Report 0x31 support with automatic firmware animation dismiss on connect, CRC32 output reports, and Feature Report 0x05 mode switch
|
|
24
24
|
- **Transports**: `AccessNodeHIDProvider` (node-hid) with multi-device enumeration and serial number targeting, `AccessWebHIDProvider` (WebHID) with permission dialog and device replacement, `AccessNullHIDProvider` (headless/testing)
|
|
25
25
|
- **Identity**: firmware version, factory info (serial number, body color, board revision), and MAC address loaded automatically on connect with retry/backoff
|
|
@@ -36,10 +36,10 @@ All notable changes to `dualsense-ts` are documented here. This project uses [Se
|
|
|
36
36
|
### Added
|
|
37
37
|
|
|
38
38
|
- **Orientation tracking**: `controller.orientation` provides fused 3D orientation (pitch, yaw, roll, quaternion) via a zero-dependency Madgwick AHRS filter, plus accelerometer-only `tiltPitch`/`tiltRoll` for drift-free gravity-reference applications. Filter gain (`beta`) is tunable at runtime
|
|
39
|
-
- **Shake detection**: `controller.shake` detects shake intensity, frequency, and active state using per-axis Goertzel frequency analysis on first-difference signals. Reports both `frequency` (reversal rate) and `fundamental` (oscillation frequency), with a live `spectrum` of frequency bin powers. Configurable `threshold`, `windowSize`, `sustain`, `freqStep`, `freqMin`, and `freqMax`
|
|
39
|
+
- **Shake detection**: `controller.shake` detects shake intensity, frequency, and active state using per-axis Goertzel frequency analysis on first-difference signals. Reports both `frequency` (reversal rate) and `fundamental` (oscillation frequency), with a live `spectrum` of frequency bin powers. Configurable `threshold`, `windowSize`, `sustain`, `freqStep`, `freqMin`, and `freqMax` - all tunable at runtime
|
|
40
40
|
- Axis remapping from DualSense Y-up to Madgwick Z-up convention for correct symmetric tilt behavior
|
|
41
41
|
- Zero-gradient guard in the Madgwick filter to prevent NaN when gravity is already aligned
|
|
42
|
-
- New `motion/` module: `Orientation`, `ShakeDetector`, `MadgwickFilter`, quaternion math
|
|
42
|
+
- New `motion/` module: `Orientation`, `ShakeDetector`, `MadgwickFilter`, quaternion math - all zero-dependency
|
|
43
43
|
|
|
44
44
|
## [6.12.0] - 2026-04-14
|
|
45
45
|
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Check out the **[interactive docs](https://nsfm.github.io/dualsense-ts/)**! Conn
|
|
|
11
11
|
- **Automatic connection and reconnection** even when connection type changes
|
|
12
12
|
- **[Multiplayer support](https://nsfm.github.io/dualsense-ts/multiplayer)**, allowing up to 31 connected controllers at a time
|
|
13
13
|
- **Lighting control** covering [RGB light bars](https://nsfm.github.io/dualsense-ts/outputs/lightbar), [player LEDs](https://nsfm.github.io/dualsense-ts/outputs/player-leds), and [mute button](https://nsfm.github.io/dualsense-ts/outputs/mute-led)
|
|
14
|
-
- **Full haptics control** over independent [left/right rumble](https://nsfm.github.io/dualsense-ts/outputs/rumble)
|
|
14
|
+
- **Full haptics control** over independent [left/right rumble](https://nsfm.github.io/dualsense-ts/outputs/rumble) and [trigger haptics](https://nsfm.github.io/dualsense-ts/outputs/trigger-effects)
|
|
15
15
|
- **[Touchpad support](https://nsfm.github.io/dualsense-ts/inputs/touchpad)** with full multi-touch handling
|
|
16
16
|
- **[Motion tracking](https://nsfm.github.io/dualsense-ts/inputs/motion)** via factory-calibrated gyroscope and accelerometer, with built-in [orientation tracking](https://nsfm.github.io/dualsense-ts/api/orientation) and [shake detection](https://nsfm.github.io/dualsense-ts/api/shake-detector)
|
|
17
17
|
- **[Battery status](https://nsfm.github.io/dualsense-ts/inputs/battery)** including level and charging state
|
|
@@ -61,7 +61,7 @@ controller.connection.active; // returns true while the controller is available
|
|
|
61
61
|
controller.wireless; // returns true while connected over bluetooth
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
When the user switches from wired to wireless or vice versa, `dualsense-ts`
|
|
64
|
+
When the user switches from wired to wireless or vice versa, `dualsense-ts` reconnects to the same device.
|
|
65
65
|
|
|
66
66
|
### [Input APIs](https://nsfm.github.io/dualsense-ts/inputs)
|
|
67
67
|
|
|
@@ -197,7 +197,7 @@ controller.accelerometer.z.on("change", ({ magnitude }) => {
|
|
|
197
197
|
});
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
Gyroscope and accelerometer readings are automatically calibrated using each controller's factory calibration data, which removes gyro bias drift and accelerometer zero-point offset.
|
|
200
|
+
Gyroscope and accelerometer readings are automatically calibrated using each controller's factory calibration data, which removes gyro bias drift and accelerometer zero-point offset. You can inspect the resolved calibration factors via `controller.calibration`, and the [Factory Calibration](https://nsfm.github.io/dualsense-ts/inputs/motion) docs cover the details.
|
|
201
201
|
|
|
202
202
|
#### [Orientation Tracking](https://nsfm.github.io/dualsense-ts/api/orientation)
|
|
203
203
|
|
|
@@ -210,7 +210,7 @@ const { pitch, yaw, roll } = controller.orientation;
|
|
|
210
210
|
// Quaternion for 3D rendering
|
|
211
211
|
const [w, x, y, z] = controller.orientation.quaternion;
|
|
212
212
|
|
|
213
|
-
// Accelerometer-only tilt
|
|
213
|
+
// Accelerometer-only tilt - no drift, no yaw
|
|
214
214
|
const steer = controller.orientation.tiltRoll;
|
|
215
215
|
|
|
216
216
|
// Tune the filter: lower beta = smoother, higher = less drift
|
|
@@ -277,7 +277,7 @@ controller.battery.level.on("change", ({ state }) => {
|
|
|
277
277
|
});
|
|
278
278
|
```
|
|
279
279
|
|
|
280
|
-
After connection it may take a second for these values to populate.
|
|
280
|
+
After connection it may take a second for these values to populate. The battery level is not a precise reading - it changes in 10% increments and is prone to flip-flopping. `dualsense-ts` makes an attempt to buffer and normalize these values.
|
|
281
281
|
|
|
282
282
|
#### [Rumble](https://nsfm.github.io/dualsense-ts/outputs/rumble)
|
|
283
283
|
|
|
@@ -315,7 +315,7 @@ controller.right.trigger.feedback.set({
|
|
|
315
315
|
strength: 0.8,
|
|
316
316
|
});
|
|
317
317
|
|
|
318
|
-
// Weapon trigger
|
|
318
|
+
// Weapon trigger - resistance with snap release
|
|
319
319
|
controller.right.trigger.feedback.set({
|
|
320
320
|
effect: TriggerEffect.Weapon,
|
|
321
321
|
start: 0.2,
|
|
@@ -342,7 +342,7 @@ console.log(controller.right.trigger.feedback.config);
|
|
|
342
342
|
console.log(controller.right.trigger.feedback.effect); // TriggerEffect.Off
|
|
343
343
|
```
|
|
344
344
|
|
|
345
|
-
|
|
345
|
+
If the controller disconnects and reconnects, your feedback settings are restored automatically.
|
|
346
346
|
|
|
347
347
|
#### Trigger effects
|
|
348
348
|
|
|
@@ -356,7 +356,7 @@ Feedback state is automatically restored if the controller disconnects and recon
|
|
|
356
356
|
| `TriggerEffect.Vibration` | Zone-based oscillation with amplitude and frequency |
|
|
357
357
|
| `TriggerEffect.Machine` | Dual-amplitude vibration with frequency and period control |
|
|
358
358
|
|
|
359
|
-
Each effect accepts
|
|
359
|
+
Each effect accepts its own set of configuration options - your editor's type hints will show you what's available. To find the right values, try the [interactive docs](https://nsfm.github.io/dualsense-ts/outputs/trigger-effects), which have slider controls for every effect and parameter.
|
|
360
360
|
|
|
361
361
|
Effect names are based on [Nielk1's DualSense trigger effect documentation](https://gist.github.com/Nielk1/6d54cc2c00d2201ccb8c2720ad7538db).
|
|
362
362
|
|
|
@@ -367,17 +367,17 @@ You can control the controller's lightbar as well as the [player indicator](http
|
|
|
367
367
|
```typescript
|
|
368
368
|
import { PlayerID, Brightness } from "dualsense-ts";
|
|
369
369
|
|
|
370
|
-
// Light bar
|
|
370
|
+
// Light bar - set color with {r, g, b} (0–255 per channel)
|
|
371
371
|
controller.lightbar.set({ r: 255, g: 0, b: 128 });
|
|
372
372
|
controller.lightbar.color; // { r: 255, g: 0, b: 128 }
|
|
373
373
|
|
|
374
|
-
// Light bar pulse effects
|
|
374
|
+
// Light bar pulse effects - firmware-driven one-shot animations
|
|
375
375
|
// This overrides your custom color
|
|
376
376
|
controller.lightbar.fadeBlue(); // Fades to blue and holds
|
|
377
377
|
// You must call `fadeOut()` to restore custom lightbar colors
|
|
378
378
|
controller.lightbar.fadeOut(); // Fades to black, then returns to set color
|
|
379
379
|
|
|
380
|
-
// Player indicator LEDs
|
|
380
|
+
// Player indicator LEDs - 5 white LEDs, individually addressable
|
|
381
381
|
controller.playerLeds.set(PlayerID.Player1); // Use a preset pattern
|
|
382
382
|
controller.playerLeds.setLed(0, true); // Toggle individual LEDs (0–4)
|
|
383
383
|
controller.playerLeds.setLed(4, true);
|
|
@@ -516,7 +516,7 @@ The output report exposes per-subsystem power save flags. The **mute flags** (ha
|
|
|
516
516
|
// Mute haptic output (confirmed working)
|
|
517
517
|
controller.powerSave.hapticsMuted = true;
|
|
518
518
|
|
|
519
|
-
// Send disable flags (advisory
|
|
519
|
+
// Send disable flags (advisory - no confirmed observable effect)
|
|
520
520
|
controller.powerSave.set({ motion: false, touch: false });
|
|
521
521
|
|
|
522
522
|
// Re-enable everything
|
|
@@ -537,7 +537,7 @@ import { Dualsense, type Input } from "dualsense-ts";
|
|
|
537
537
|
const controller = new Dualsense();
|
|
538
538
|
export const ControllerContext = createContext(controller);
|
|
539
539
|
|
|
540
|
-
// Hook
|
|
540
|
+
// Hook - subscribes to any input, re-renders on change
|
|
541
541
|
function useControllerInput<T extends Input<T>>(
|
|
542
542
|
selector: (c: Dualsense) => T,
|
|
543
543
|
): T {
|
|
@@ -595,8 +595,8 @@ This only applies to the first connection for each controller.
|
|
|
595
595
|
### Accessing controllers
|
|
596
596
|
|
|
597
597
|
```typescript
|
|
598
|
-
manager.controllers; // readonly Dualsense[]
|
|
599
|
-
manager.get(0); // Dualsense | undefined
|
|
598
|
+
manager.controllers; // readonly Dualsense[] - all managed controllers
|
|
599
|
+
manager.get(0); // Dualsense | undefined - by slot index
|
|
600
600
|
manager.count; // number of managed slots (including disconnected)
|
|
601
601
|
manager.state.active; // number of currently connected controllers
|
|
602
602
|
|
|
@@ -702,7 +702,7 @@ controller.left.analog.on("change", (s) => move(s.x.state, s.y.state));
|
|
|
702
702
|
controller.dpad.up.on("press", () => selectPrevious());
|
|
703
703
|
```
|
|
704
704
|
|
|
705
|
-
Available mapped inputs: `left` / `right` ([Unisense](https://nsfm.github.io/dualsense-ts/api/unisense)
|
|
705
|
+
Available mapped inputs: `left` / `right` ([Unisense](https://nsfm.github.io/dualsense-ts/api/unisense) - stick, trigger, bumper), `dpad`, `cross`, `circle`, `square`, `triangle`, `touchpad` (button only), `options`, `create`, `mute`.
|
|
706
706
|
|
|
707
707
|
### [LED control](https://nsfm.github.io/dualsense-ts/access/led-control)
|
|
708
708
|
|
|
@@ -714,12 +714,12 @@ import { AccessProfileLedMode, AccessPlayerIndicator } from "dualsense-ts";
|
|
|
714
714
|
// RGB lightbar (same API as DualSense)
|
|
715
715
|
access.lightbar.set({ r: 255, g: 0, b: 128 });
|
|
716
716
|
|
|
717
|
-
// Profile LEDs
|
|
717
|
+
// Profile LEDs - 3-segment arc
|
|
718
718
|
access.profileLeds.set(AccessProfileLedMode.Sweep);
|
|
719
719
|
access.profileLeds.set(AccessProfileLedMode.Fade);
|
|
720
720
|
access.profileLeds.set(AccessProfileLedMode.Off);
|
|
721
721
|
|
|
722
|
-
// Player indicator
|
|
722
|
+
// Player indicator - 6-segment ring
|
|
723
723
|
access.playerIndicator.set(AccessPlayerIndicator.Player1);
|
|
724
724
|
access.playerIndicator.set(AccessPlayerIndicator.Off);
|
|
725
725
|
|
|
@@ -743,7 +743,7 @@ console.log(`Board: ${access.factoryInfo.boardRevision}`);
|
|
|
743
743
|
|
|
744
744
|
### Browser usage
|
|
745
745
|
|
|
746
|
-
In Node.js, `new DualsenseAccess()` auto-connects
|
|
746
|
+
In Node.js, `new DualsenseAccess()` auto-connects without any extra setup. In the browser, WebHID requires a one-time user gesture to grant device permission:
|
|
747
747
|
|
|
748
748
|
```typescript
|
|
749
749
|
import { DualsenseAccess } from "dualsense-ts";
|
|
@@ -819,7 +819,7 @@ sudo modprobe hidp
|
|
|
819
819
|
sudo systemctl restart bluetooth
|
|
820
820
|
```
|
|
821
821
|
|
|
822
|
-
This is a BlueZ-specific issue
|
|
822
|
+
This is a BlueZ-specific issue; Windows and macOS pair without any fuss. The standard DualSense is not affected.
|
|
823
823
|
|
|
824
824
|
## Migration Guide
|
|
825
825
|
|
package/dist/dualsense.d.ts
CHANGED
|
@@ -102,7 +102,7 @@ export declare class Dualsense extends Input<Dualsense> {
|
|
|
102
102
|
*/
|
|
103
103
|
readonly shake: ShakeDetector;
|
|
104
104
|
/** Monotonic sensor timestamp in microseconds from the controller's clock.
|
|
105
|
-
* Updated with each input report
|
|
105
|
+
* Updated with each input report - useful for correlating motion sensor
|
|
106
106
|
* readings with other inputs across frames. Wraps at 2^32 (~71.6 minutes). */
|
|
107
107
|
sensorTimestamp: number;
|
|
108
108
|
/** Previous sensor timestamp for computing dt (microseconds). */
|
|
@@ -129,7 +129,7 @@ export declare class Dualsense extends Input<Dualsense> {
|
|
|
129
129
|
/**
|
|
130
130
|
* IMU calibration factors derived from the controller's factory calibration
|
|
131
131
|
* data (Feature Report 0x05). Applied automatically to gyroscope and
|
|
132
|
-
* accelerometer readings
|
|
132
|
+
* accelerometer readings - exposed here for inspection and diagnostics.
|
|
133
133
|
*/
|
|
134
134
|
get calibration(): ResolvedCalibration;
|
|
135
135
|
/** A virtual button representing whether or not a controller is connected */
|
|
@@ -152,8 +152,8 @@ export declare class Dualsense extends Input<Dualsense> {
|
|
|
152
152
|
/**
|
|
153
153
|
* Play a built-in test tone via the onboard DSP.
|
|
154
154
|
* Works over both USB and Bluetooth. Call `stopTestTone()` to stop.
|
|
155
|
-
* @param target Output destination
|
|
156
|
-
* @param tone Which tone to play
|
|
155
|
+
* @param target Output destination - "speaker" (default) or "headphone"
|
|
156
|
+
* @param tone Which tone to play - "1khz" (default), "100hz", or "both"
|
|
157
157
|
*/
|
|
158
158
|
startTestTone(target?: "speaker" | "headphone", tone?: "1khz" | "100hz" | "both"): Promise<void>;
|
|
159
159
|
/** Stop the DSP test tone */
|
package/dist/dualsense.js
CHANGED
|
@@ -24,7 +24,7 @@ class Dualsense extends input_1.Input {
|
|
|
24
24
|
/**
|
|
25
25
|
* IMU calibration factors derived from the controller's factory calibration
|
|
26
26
|
* data (Feature Report 0x05). Applied automatically to gyroscope and
|
|
27
|
-
* accelerometer readings
|
|
27
|
+
* accelerometer readings - exposed here for inspection and diagnostics.
|
|
28
28
|
*/
|
|
29
29
|
get calibration() {
|
|
30
30
|
return this.hid.calibration;
|
|
@@ -60,7 +60,7 @@ class Dualsense extends input_1.Input {
|
|
|
60
60
|
/** Per-subsystem power save controls (disable touch, motion, haptics, audio) */
|
|
61
61
|
this.powerSave = new elements_1.PowerSaveControl();
|
|
62
62
|
/** Monotonic sensor timestamp in microseconds from the controller's clock.
|
|
63
|
-
* Updated with each input report
|
|
63
|
+
* Updated with each input report - useful for correlating motion sensor
|
|
64
64
|
* readings with other inputs across frames. Wraps at 2^32 (~71.6 minutes). */
|
|
65
65
|
this.sensorTimestamp = 0;
|
|
66
66
|
/** Previous sensor timestamp for computing dt (microseconds). */
|
|
@@ -164,7 +164,7 @@ class Dualsense extends input_1.Input {
|
|
|
164
164
|
this.connection[input_1.InputSet](false);
|
|
165
165
|
// If a HID instance was supplied externally (e.g. by DualsenseManager),
|
|
166
166
|
// the owner is responsible for driving discovery + reconnection.
|
|
167
|
-
// `hid: null` creates a headless instance with no provider
|
|
167
|
+
// `hid: null` creates a headless instance with no provider - useful for
|
|
168
168
|
// placeholder controllers in UIs where WebHID may not be available.
|
|
169
169
|
// Otherwise, construct a default platform provider and run our own
|
|
170
170
|
// discovery loop.
|
|
@@ -324,8 +324,8 @@ class Dualsense extends input_1.Input {
|
|
|
324
324
|
/**
|
|
325
325
|
* Play a built-in test tone via the onboard DSP.
|
|
326
326
|
* Works over both USB and Bluetooth. Call `stopTestTone()` to stop.
|
|
327
|
-
* @param target Output destination
|
|
328
|
-
* @param tone Which tone to play
|
|
327
|
+
* @param target Output destination - "speaker" (default) or "headphone"
|
|
328
|
+
* @param tone Which tone to play - "1khz" (default), "100hz", or "both"
|
|
329
329
|
*/
|
|
330
330
|
async startTestTone(target = "speaker", tone = "1khz") {
|
|
331
331
|
return this.hid.startTestTone(target, tone);
|
|
@@ -93,27 +93,27 @@ export declare class DualsenseAccess extends Input<DualsenseAccess> {
|
|
|
93
93
|
readonly profile: Momentary;
|
|
94
94
|
/** Analog stick (x, y, button = stick click) */
|
|
95
95
|
readonly stick: Analog;
|
|
96
|
-
/** Left stick, trigger (L2), and bumper (L1)
|
|
96
|
+
/** Left stick, trigger (L2), and bumper (L1) - profile-mapped */
|
|
97
97
|
readonly left: Unisense;
|
|
98
|
-
/** Right stick, trigger (R2), and bumper (R1)
|
|
98
|
+
/** Right stick, trigger (R2), and bumper (R1) - profile-mapped */
|
|
99
99
|
readonly right: Unisense;
|
|
100
|
-
/** D-pad
|
|
100
|
+
/** D-pad - profile-mapped */
|
|
101
101
|
readonly dpad: Dpad;
|
|
102
|
-
/** Cross button
|
|
102
|
+
/** Cross button - profile-mapped */
|
|
103
103
|
readonly cross: Momentary;
|
|
104
|
-
/** Circle button
|
|
104
|
+
/** Circle button - profile-mapped */
|
|
105
105
|
readonly circle: Momentary;
|
|
106
|
-
/** Square button
|
|
106
|
+
/** Square button - profile-mapped */
|
|
107
107
|
readonly square: Momentary;
|
|
108
|
-
/** Triangle button
|
|
108
|
+
/** Triangle button - profile-mapped */
|
|
109
109
|
readonly triangle: Momentary;
|
|
110
|
-
/** Touchpad (button only, contacts stay at neutral)
|
|
110
|
+
/** Touchpad (button only, contacts stay at neutral) - profile-mapped */
|
|
111
111
|
readonly touchpad: Touchpad;
|
|
112
|
-
/** Options button
|
|
112
|
+
/** Options button - profile-mapped */
|
|
113
113
|
readonly options: Momentary;
|
|
114
|
-
/** Create button
|
|
114
|
+
/** Create button - profile-mapped */
|
|
115
115
|
readonly create: Momentary;
|
|
116
|
-
/** Mute button
|
|
116
|
+
/** Mute button - profile-mapped */
|
|
117
117
|
readonly mute: Mute;
|
|
118
118
|
/** Battery level and charging status */
|
|
119
119
|
readonly battery: Battery;
|
package/dist/dualsense_access.js
CHANGED
|
@@ -204,7 +204,7 @@ class DualsenseAccess extends input_1.Input {
|
|
|
204
204
|
this.pendingBattery.peakLevel = 0;
|
|
205
205
|
}, 1000));
|
|
206
206
|
// Output loop (30Hz)
|
|
207
|
-
// When any subsystem changes, send all 4 in one report
|
|
207
|
+
// When any subsystem changes, send all 4 in one report - the Access
|
|
208
208
|
// controller over BT requires combined mutator + LED_FLAGS_1.
|
|
209
209
|
this.timers.push(setInterval(() => {
|
|
210
210
|
if (!this.connection.active)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Canonical trigger effect types from the DualSense firmware */
|
|
2
2
|
export declare enum TriggerEffect {
|
|
3
|
-
/** No resistance
|
|
3
|
+
/** No resistance - default linear feel */
|
|
4
4
|
Off = "off",
|
|
5
5
|
/** Zone-based continuous resistance */
|
|
6
6
|
Feedback = "feedback",
|
|
@@ -5,7 +5,7 @@ exports.buildTriggerEffectBlock = buildTriggerEffectBlock;
|
|
|
5
5
|
/** Canonical trigger effect types from the DualSense firmware */
|
|
6
6
|
var TriggerEffect;
|
|
7
7
|
(function (TriggerEffect) {
|
|
8
|
-
/** No resistance
|
|
8
|
+
/** No resistance - default linear feel */
|
|
9
9
|
TriggerEffect["Off"] = "off";
|
|
10
10
|
/** Zone-based continuous resistance */
|
|
11
11
|
TriggerEffect["Feedback"] = "feedback";
|
|
@@ -20,9 +20,9 @@ export declare class AccessNodeHIDProvider extends AccessHIDProvider {
|
|
|
20
20
|
wireless?: boolean;
|
|
21
21
|
buffer?: Buffer;
|
|
22
22
|
private connecting;
|
|
23
|
-
/** Target device path
|
|
23
|
+
/** Target device path - mutable so the manager can update it */
|
|
24
24
|
targetPath?: string;
|
|
25
|
-
/** Target serial number
|
|
25
|
+
/** Target serial number - stable identifier for reconnection */
|
|
26
26
|
targetSerial?: string;
|
|
27
27
|
constructor(options?: AccessNodeHIDProviderOptions);
|
|
28
28
|
/** List all available DualSense Access controllers */
|
|
@@ -50,7 +50,7 @@ class AccessNodeHIDProvider extends access_hid_provider_1.AccessHIDProvider {
|
|
|
50
50
|
const { HID, devices } = nodeHid;
|
|
51
51
|
const allDevices = devices(access_hid_provider_1.AccessHIDProvider.vendorId, access_hid_provider_1.AccessHIDProvider.productId);
|
|
52
52
|
// Filter to the correct HID usage (gamepad). BT devices expose
|
|
53
|
-
// multiple hidraw nodes
|
|
53
|
+
// multiple hidraw nodes - only one has the right usagePage/usage.
|
|
54
54
|
const controllers = allDevices.filter((d) => d.usagePage === access_hid_provider_1.AccessHIDProvider.usagePage &&
|
|
55
55
|
d.usage === access_hid_provider_1.AccessHIDProvider.usage);
|
|
56
56
|
// Find a suitable controller: targeted path, then serial match, then first unclaimed
|
|
@@ -77,12 +77,12 @@ class AccessNodeHIDProvider extends access_hid_provider_1.AccessHIDProvider {
|
|
|
77
77
|
this.serialNumber = target.serialNumber ?? undefined;
|
|
78
78
|
access_hid_provider_1.AccessHIDProvider.claimedDevices.add(target.path);
|
|
79
79
|
// Read Feature Report 0x05 to trigger BT full mode (same as DualSense).
|
|
80
|
-
// No IMU calibration to parse
|
|
80
|
+
// No IMU calibration to parse - Access has no IMU.
|
|
81
81
|
try {
|
|
82
82
|
device.getFeatureReport(0x05, 41);
|
|
83
83
|
}
|
|
84
84
|
catch {
|
|
85
|
-
/* non-fatal
|
|
85
|
+
/* non-fatal - USB doesn't strictly need this */
|
|
86
86
|
}
|
|
87
87
|
device.on("data", (arg) => {
|
|
88
88
|
this.buffer = arg;
|
package/dist/hid/access_hid.d.ts
CHANGED
|
@@ -172,7 +172,7 @@ export declare const AccessMutator: {
|
|
|
172
172
|
/** Combined: all LED subsystems */
|
|
173
173
|
readonly ALL_LEDS: 21;
|
|
174
174
|
};
|
|
175
|
-
/** Scope B flag bits (AccessOutput.SCOPE_B byte)
|
|
175
|
+
/** Scope B flag bits (AccessOutput.SCOPE_B byte) - needed for BT output */
|
|
176
176
|
export declare const AccessScopeB: {
|
|
177
177
|
/** Required for lightbar RGB over BT (both this AND AccessMutator.LED must be set) */
|
|
178
178
|
readonly LED: 4;
|
package/dist/hid/access_hid.js
CHANGED
|
@@ -181,7 +181,7 @@ exports.AccessMutator = {
|
|
|
181
181
|
/** Combined: all LED subsystems */
|
|
182
182
|
ALL_LEDS: 0x15, // STATUS_LED | LED | PLAYER_INDICATOR_LED
|
|
183
183
|
};
|
|
184
|
-
/** Scope B flag bits (AccessOutput.SCOPE_B byte)
|
|
184
|
+
/** Scope B flag bits (AccessOutput.SCOPE_B byte) - needed for BT output */
|
|
185
185
|
exports.AccessScopeB = {
|
|
186
186
|
/** Required for lightbar RGB over BT (both this AND AccessMutator.LED must be set) */
|
|
187
187
|
LED: 0x04,
|
|
@@ -69,7 +69,7 @@ export declare const DefaultResolvedCalibration: ResolvedCalibration;
|
|
|
69
69
|
* Parse Feature Report 0x05 into an {@link IMUCalibration}.
|
|
70
70
|
*
|
|
71
71
|
* The report may or may not include the report-ID byte as the first
|
|
72
|
-
* element depending on platform
|
|
72
|
+
* element depending on platform - the parser auto-detects.
|
|
73
73
|
*/
|
|
74
74
|
export declare function parseIMUCalibration(buf: Uint8Array): IMUCalibration;
|
|
75
75
|
/**
|
package/dist/hid/calibration.js
CHANGED
|
@@ -44,7 +44,7 @@ function readInt16LE(buf, offset) {
|
|
|
44
44
|
* Parse Feature Report 0x05 into an {@link IMUCalibration}.
|
|
45
45
|
*
|
|
46
46
|
* The report may or may not include the report-ID byte as the first
|
|
47
|
-
* element depending on platform
|
|
47
|
+
* element depending on platform - the parser auto-detects.
|
|
48
48
|
*/
|
|
49
49
|
function parseIMUCalibration(buf) {
|
|
50
50
|
const off = buf[0] === REPORT_ID ? 1 : 0;
|
package/dist/hid/command.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export declare enum PlayerID {
|
|
|
26
26
|
Player4 = 27,
|
|
27
27
|
All = 31
|
|
28
28
|
}
|
|
29
|
-
/** Audio output routing
|
|
29
|
+
/** Audio output routing - controls how L/R channels map to headphone and speaker */
|
|
30
30
|
export declare enum AudioOutput {
|
|
31
31
|
/** Stereo L+R to headphone, speaker muted */
|
|
32
32
|
Headphone = 0,
|
|
@@ -49,7 +49,7 @@ export declare enum MicFlag {
|
|
|
49
49
|
EchoCancellation = 4,
|
|
50
50
|
NoiseCancellation = 8
|
|
51
51
|
}
|
|
52
|
-
/** Microphone input mode
|
|
52
|
+
/** Microphone input mode - bits 6-7 of audio flags */
|
|
53
53
|
export declare enum MicMode {
|
|
54
54
|
/** Default mode */
|
|
55
55
|
Default = 0,
|
|
@@ -58,7 +58,7 @@ export declare enum MicMode {
|
|
|
58
58
|
/** Automatic speech recognition mode */
|
|
59
59
|
ASR = 128
|
|
60
60
|
}
|
|
61
|
-
/** Power save control
|
|
61
|
+
/** Power save control - per-subsystem mute/disable flags (byte 10) */
|
|
62
62
|
export declare enum PowerSave {
|
|
63
63
|
DisableTouch = 1,
|
|
64
64
|
DisableMotion = 2,
|
|
@@ -95,9 +95,9 @@ type Intensity = number;
|
|
|
95
95
|
export interface DualsenseCommand extends Uint8Array {
|
|
96
96
|
/** Packet type */
|
|
97
97
|
[0]: 0x2;
|
|
98
|
-
/** Scope A
|
|
98
|
+
/** Scope A - which subsystems are affected */
|
|
99
99
|
[1]: CommandScopeA | 0xff;
|
|
100
|
-
/** Scope B
|
|
100
|
+
/** Scope B - which subsystems are affected */
|
|
101
101
|
[2]: CommandScopeB | (0x1 | 0x2 | 0x4 | 0x10 | 0x40);
|
|
102
102
|
/** Right rumble intensity */
|
|
103
103
|
[3]: Intensity;
|
|
@@ -113,7 +113,7 @@ export interface DualsenseCommand extends Uint8Array {
|
|
|
113
113
|
[8]: number;
|
|
114
114
|
/** Mute button LED mode */
|
|
115
115
|
[9]: MuteLedMode;
|
|
116
|
-
/** Power save control
|
|
116
|
+
/** Power save control - per-subsystem mute/disable bitfield */
|
|
117
117
|
[10]: PowerSave | 0x00;
|
|
118
118
|
[11]: number;
|
|
119
119
|
[12]: number;
|
package/dist/hid/command.js
CHANGED
|
@@ -34,7 +34,7 @@ var PlayerID;
|
|
|
34
34
|
PlayerID[PlayerID["Player4"] = 27] = "Player4";
|
|
35
35
|
PlayerID[PlayerID["All"] = 31] = "All";
|
|
36
36
|
})(PlayerID || (exports.PlayerID = PlayerID = {}));
|
|
37
|
-
/** Audio output routing
|
|
37
|
+
/** Audio output routing - controls how L/R channels map to headphone and speaker */
|
|
38
38
|
var AudioOutput;
|
|
39
39
|
(function (AudioOutput) {
|
|
40
40
|
/** Stereo L+R to headphone, speaker muted */
|
|
@@ -60,7 +60,7 @@ var MicFlag;
|
|
|
60
60
|
MicFlag[MicFlag["EchoCancellation"] = 4] = "EchoCancellation";
|
|
61
61
|
MicFlag[MicFlag["NoiseCancellation"] = 8] = "NoiseCancellation";
|
|
62
62
|
})(MicFlag || (exports.MicFlag = MicFlag = {}));
|
|
63
|
-
/** Microphone input mode
|
|
63
|
+
/** Microphone input mode - bits 6-7 of audio flags */
|
|
64
64
|
var MicMode;
|
|
65
65
|
(function (MicMode) {
|
|
66
66
|
/** Default mode */
|
|
@@ -70,7 +70,7 @@ var MicMode;
|
|
|
70
70
|
/** Automatic speech recognition mode */
|
|
71
71
|
MicMode[MicMode["ASR"] = 128] = "ASR";
|
|
72
72
|
})(MicMode || (exports.MicMode = MicMode = {}));
|
|
73
|
-
/** Power save control
|
|
73
|
+
/** Power save control - per-subsystem mute/disable flags (byte 10) */
|
|
74
74
|
var PowerSave;
|
|
75
75
|
(function (PowerSave) {
|
|
76
76
|
PowerSave[PowerSave["DisableTouch"] = 1] = "DisableTouch";
|
package/dist/hid/dsp.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare enum DspDevice {
|
|
|
33
33
|
Memory = 3,
|
|
34
34
|
AnalogData = 4,
|
|
35
35
|
Touch = 5,
|
|
36
|
-
/** Audio DSP
|
|
36
|
+
/** Audio DSP - test tone, codec, mic calibration */
|
|
37
37
|
Audio = 6,
|
|
38
38
|
AdaptiveTrigger = 7,
|
|
39
39
|
Bullet = 8,
|
|
@@ -63,7 +63,7 @@ export declare enum AudioAction {
|
|
|
63
63
|
*
|
|
64
64
|
* Both tones can play simultaneously ([1, 1, 1]).
|
|
65
65
|
* No other byte values (0–255) produce additional tones.
|
|
66
|
-
* Write-only
|
|
66
|
+
* Write-only - returns no response data.
|
|
67
67
|
*/
|
|
68
68
|
WaveoutCtrl = 2,
|
|
69
69
|
/**
|
|
@@ -78,7 +78,7 @@ export declare enum AudioAction {
|
|
|
78
78
|
* Headphone: params[4] = 4, params[6] = 6
|
|
79
79
|
* All other bytes: zero in reference impl, no effect found in sweep (0–10).
|
|
80
80
|
*
|
|
81
|
-
* Write-only
|
|
81
|
+
* Write-only - returns no response data.
|
|
82
82
|
*/
|
|
83
83
|
SetPathSelector = 4,
|
|
84
84
|
/** Speaker compensation (EQ/filter). Write-only. */
|
|
@@ -97,13 +97,13 @@ export declare enum AudioAction {
|
|
|
97
97
|
TryMicCalibGain = 11,
|
|
98
98
|
/** Set compensation status. Write-only. */
|
|
99
99
|
SetCompStatus = 12,
|
|
100
|
-
/** Get compensation status. No response observed
|
|
100
|
+
/** Get compensation status. No response observed - may require prior SetCompStatus. */
|
|
101
101
|
GetCompStatus = 13,
|
|
102
102
|
/** Execute forced compensation. Write-only. */
|
|
103
103
|
ExecForceComp = 14,
|
|
104
104
|
/** Set auto-calibration status. Write-only. */
|
|
105
105
|
SetAutoCalibStatus = 15,
|
|
106
|
-
/** Get auto-calibration status. No response observed
|
|
106
|
+
/** Get auto-calibration status. No response observed - may require prior SetAutoCalibStatus. */
|
|
107
107
|
GetAutoCalibStatus = 16,
|
|
108
108
|
/**
|
|
109
109
|
* Direct register write to ALC5524 codec. Write-only.
|
|
@@ -123,7 +123,7 @@ export declare enum DspStatus {
|
|
|
123
123
|
Idle = 0,
|
|
124
124
|
Running = 1,
|
|
125
125
|
Complete = 2,
|
|
126
|
-
/** Multi-part response
|
|
126
|
+
/** Multi-part response - more data follows */
|
|
127
127
|
CompleteMulti = 3,
|
|
128
128
|
Timeout = 255
|
|
129
129
|
}
|
package/dist/hid/dsp.js
CHANGED
|
@@ -37,7 +37,7 @@ var DspDevice;
|
|
|
37
37
|
DspDevice[DspDevice["Memory"] = 3] = "Memory";
|
|
38
38
|
DspDevice[DspDevice["AnalogData"] = 4] = "AnalogData";
|
|
39
39
|
DspDevice[DspDevice["Touch"] = 5] = "Touch";
|
|
40
|
-
/** Audio DSP
|
|
40
|
+
/** Audio DSP - test tone, codec, mic calibration */
|
|
41
41
|
DspDevice[DspDevice["Audio"] = 6] = "Audio";
|
|
42
42
|
DspDevice[DspDevice["AdaptiveTrigger"] = 7] = "AdaptiveTrigger";
|
|
43
43
|
DspDevice[DspDevice["Bullet"] = 8] = "Bullet";
|
|
@@ -68,7 +68,7 @@ var AudioAction;
|
|
|
68
68
|
*
|
|
69
69
|
* Both tones can play simultaneously ([1, 1, 1]).
|
|
70
70
|
* No other byte values (0–255) produce additional tones.
|
|
71
|
-
* Write-only
|
|
71
|
+
* Write-only - returns no response data.
|
|
72
72
|
*/
|
|
73
73
|
AudioAction[AudioAction["WaveoutCtrl"] = 2] = "WaveoutCtrl";
|
|
74
74
|
/**
|
|
@@ -83,7 +83,7 @@ var AudioAction;
|
|
|
83
83
|
* Headphone: params[4] = 4, params[6] = 6
|
|
84
84
|
* All other bytes: zero in reference impl, no effect found in sweep (0–10).
|
|
85
85
|
*
|
|
86
|
-
* Write-only
|
|
86
|
+
* Write-only - returns no response data.
|
|
87
87
|
*/
|
|
88
88
|
AudioAction[AudioAction["SetPathSelector"] = 4] = "SetPathSelector";
|
|
89
89
|
/** Speaker compensation (EQ/filter). Write-only. */
|
|
@@ -102,13 +102,13 @@ var AudioAction;
|
|
|
102
102
|
AudioAction[AudioAction["TryMicCalibGain"] = 11] = "TryMicCalibGain";
|
|
103
103
|
/** Set compensation status. Write-only. */
|
|
104
104
|
AudioAction[AudioAction["SetCompStatus"] = 12] = "SetCompStatus";
|
|
105
|
-
/** Get compensation status. No response observed
|
|
105
|
+
/** Get compensation status. No response observed - may require prior SetCompStatus. */
|
|
106
106
|
AudioAction[AudioAction["GetCompStatus"] = 13] = "GetCompStatus";
|
|
107
107
|
/** Execute forced compensation. Write-only. */
|
|
108
108
|
AudioAction[AudioAction["ExecForceComp"] = 14] = "ExecForceComp";
|
|
109
109
|
/** Set auto-calibration status. Write-only. */
|
|
110
110
|
AudioAction[AudioAction["SetAutoCalibStatus"] = 15] = "SetAutoCalibStatus";
|
|
111
|
-
/** Get auto-calibration status. No response observed
|
|
111
|
+
/** Get auto-calibration status. No response observed - may require prior SetAutoCalibStatus. */
|
|
112
112
|
AudioAction[AudioAction["GetAutoCalibStatus"] = 16] = "GetAutoCalibStatus";
|
|
113
113
|
/**
|
|
114
114
|
* Direct register write to ALC5524 codec. Write-only.
|
|
@@ -129,7 +129,7 @@ var DspStatus;
|
|
|
129
129
|
DspStatus[DspStatus["Idle"] = 0] = "Idle";
|
|
130
130
|
DspStatus[DspStatus["Running"] = 1] = "Running";
|
|
131
131
|
DspStatus[DspStatus["Complete"] = 2] = "Complete";
|
|
132
|
-
/** Multi-part response
|
|
132
|
+
/** Multi-part response - more data follows */
|
|
133
133
|
DspStatus[DspStatus["CompleteMulti"] = 3] = "CompleteMulti";
|
|
134
134
|
DspStatus[DspStatus["Timeout"] = 255] = "Timeout";
|
|
135
135
|
})(DspStatus || (exports.DspStatus = DspStatus = {}));
|
|
@@ -53,7 +53,7 @@ export declare class DualsenseHID {
|
|
|
53
53
|
on(type: string, callback: ErrorCallback): void;
|
|
54
54
|
/**
|
|
55
55
|
* Subscribe to notification when firmware/factory info finishes loading
|
|
56
|
-
* after a connect. Fires once per connection
|
|
56
|
+
* after a connect. Fires once per connection - either when identity has
|
|
57
57
|
* been resolved, or when we've given up retrying. If identity is already
|
|
58
58
|
* resolved at the time of subscription, the callback fires synchronously.
|
|
59
59
|
*/
|
|
@@ -155,15 +155,15 @@ export declare class DualsenseHID {
|
|
|
155
155
|
* Start a DSP test tone on speaker or headphone.
|
|
156
156
|
* Sets volume routing via the standard output report before triggering.
|
|
157
157
|
*
|
|
158
|
-
* @param target Output destination
|
|
159
|
-
* @param tone Which tone to play
|
|
158
|
+
* @param target Output destination - "speaker" (default) or "headphone"
|
|
159
|
+
* @param tone Which tone to play - "1khz" (default), "100hz", or "both"
|
|
160
160
|
*/
|
|
161
161
|
startTestTone(target?: "speaker" | "headphone", tone?: "1khz" | "100hz" | "both"): Promise<void>;
|
|
162
162
|
/** Stop the DSP test tone */
|
|
163
163
|
stopTestTone(): Promise<void>;
|
|
164
164
|
/**
|
|
165
165
|
* Send a raw DSP test command (Feature Report 0x80).
|
|
166
|
-
* For experimentation
|
|
166
|
+
* For experimentation - lets you send arbitrary device/action/params.
|
|
167
167
|
*/
|
|
168
168
|
sendTestCommand(deviceId: number, actionId: number, params?: Uint8Array): Promise<void>;
|
|
169
169
|
/** Feature report ID for DSP test responses */
|