UNPKG

dualsense-ts

Version:

The natural interface for your DualSense and DualSense Access controllers, with Typescript

147 lines 9.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AccessHIDProvider = exports.DefaultAccessHIDState = exports.AccessInputId = void 0; const hid_provider_1 = require("../hid_provider"); const access_hid_1 = require("../access_hid"); const access_hid_state_1 = require("./access_hid_state"); Object.defineProperty(exports, "AccessInputId", { enumerable: true, get: function () { return access_hid_state_1.AccessInputId; } }); Object.defineProperty(exports, "DefaultAccessHIDState", { enumerable: true, get: function () { return access_hid_state_1.DefaultAccessHIDState; } }); /** Supports a connection to a physical or virtual DualSense Access device */ class AccessHIDProvider { constructor() { /** Callback to use for new input events */ this.onData = () => { }; /** Callback to use for Error events */ this.onError = () => { }; /** Callback fired the moment a device is fully attached and ready for I/O */ this.onConnect = () => { }; /** Callback fired the moment a device detaches (cleanly or via error) */ this.onDisconnect = () => { }; } /** * Selects the correct method for reading the report. */ processReport(buffer) { const reportId = buffer.readUint8(0); switch (reportId) { case 0x01: return this.wireless ? this.processBluetoothInputReport01(buffer) : this.processUsbInputReport01(buffer); case 0x31: return this.processBluetoothInputReport31(buffer); default: this.onError(new Error(`Cannot process report, unexpected report id: ${reportId}`)); this.disconnect(); return { ...access_hid_state_1.DefaultAccessHIDState }; } } /** Reset the provider state when the device is disconnected */ reset() { const wasAttached = this.device !== undefined; if (this.deviceId) { AccessHIDProvider.claimedDevices.delete(this.deviceId); } this.device = undefined; this.wireless = undefined; this.buffer = undefined; this.deviceId = undefined; this.serialNumber = undefined; this.onData(access_hid_state_1.DefaultAccessHIDState); if (wasAttached) this.onDisconnect(); } /** * Process a BT input report 0x01 (limited mode, pre-Feature 0x05). * Only has the mapped DualSense-compatible header, no Access-specific data. * Raw inputs stay at defaults; mapped inputs are parsed from bytes 1–10. */ processBluetoothInputReport01(buffer) { return { ...access_hid_state_1.DefaultAccessHIDState, ...this.parseMappedHeader(buffer, 0), }; } /** Process BT input report 0x31 (full mode, offset +1 from USB) */ processBluetoothInputReport31(buffer) { const o = access_hid_1.AccessInput.BT_OFFSET; // +1 return this.parseAccessReport(buffer, o); } /** Process USB input report 0x01 (full Access report) */ processUsbInputReport01(buffer) { return this.parseAccessReport(buffer, 0); } /** Parse mapped header (bytes 1–10, DualSense-compatible format) */ parseMappedHeader(buffer, offset) { const buttonsAndDpad = buffer.readUint8(access_hid_1.AccessInput.HAT_BUTTONS + offset); const faceButtons = buttonsAndDpad >> 4; const dpad = buttonsAndDpad & 0b1111; const miscButtons = buffer.readUint8(access_hid_1.AccessInput.BUTTONS_2 + offset); const lastButtons = buffer.readUint8(access_hid_1.AccessInput.BUTTONS_3 + offset); return { [access_hid_state_1.AccessInputId.MappedLeftStickX]: (0, hid_provider_1.mapAxis)(buffer.readUint8(access_hid_1.AccessInput.MAPPED_STICK_LX + offset)), [access_hid_state_1.AccessInputId.MappedLeftStickY]: -(0, hid_provider_1.mapAxis)(buffer.readUint8(access_hid_1.AccessInput.MAPPED_STICK_LY + offset)), [access_hid_state_1.AccessInputId.MappedRightStickX]: (0, hid_provider_1.mapAxis)(buffer.readUint8(access_hid_1.AccessInput.MAPPED_STICK_RX + offset)), [access_hid_state_1.AccessInputId.MappedRightStickY]: -(0, hid_provider_1.mapAxis)(buffer.readUint8(access_hid_1.AccessInput.MAPPED_STICK_RY + offset)), [access_hid_state_1.AccessInputId.MappedL2]: (0, hid_provider_1.mapTrigger)(buffer.readUint8(access_hid_1.AccessInput.MAPPED_L2 + offset)), [access_hid_state_1.AccessInputId.MappedR2]: (0, hid_provider_1.mapTrigger)(buffer.readUint8(access_hid_1.AccessInput.MAPPED_R2 + offset)), [access_hid_state_1.AccessInputId.DpadUp]: dpad < 2 || dpad === 7, [access_hid_state_1.AccessInputId.DpadDown]: dpad > 2 && dpad < 6, [access_hid_state_1.AccessInputId.DpadLeft]: dpad > 4 && dpad < 8, [access_hid_state_1.AccessInputId.DpadRight]: dpad > 0 && dpad < 4, [access_hid_state_1.AccessInputId.Triangle]: (faceButtons & 8) > 0, [access_hid_state_1.AccessInputId.Circle]: (faceButtons & 4) > 0, [access_hid_state_1.AccessInputId.Cross]: (faceButtons & 2) > 0, [access_hid_state_1.AccessInputId.Square]: (faceButtons & 1) > 0, [access_hid_state_1.AccessInputId.L1]: (miscButtons & 1) > 0, [access_hid_state_1.AccessInputId.R1]: (miscButtons & 2) > 0, [access_hid_state_1.AccessInputId.L2Button]: (miscButtons & 4) > 0, [access_hid_state_1.AccessInputId.R2Button]: (miscButtons & 8) > 0, [access_hid_state_1.AccessInputId.Create]: (miscButtons & 16) > 0, [access_hid_state_1.AccessInputId.Options]: (miscButtons & 32) > 0, [access_hid_state_1.AccessInputId.L3]: (miscButtons & 64) > 0, [access_hid_state_1.AccessInputId.R3]: (miscButtons & 128) > 0, [access_hid_state_1.AccessInputId.TouchButton]: (lastButtons & 2) > 0, [access_hid_state_1.AccessInputId.MuteButton]: (lastButtons & 4) > 0, }; } /** Parse Access-specific fields from the report buffer at the given offset */ parseAccessReport(buffer, offset) { const rawButtons1 = buffer.readUint8(access_hid_1.AccessInput.RAW_BUTTONS_1 + offset); const rawButtons2 = buffer.readUint8(access_hid_1.AccessInput.RAW_BUTTONS_2 + offset); const batteryByte = buffer.readUint8(access_hid_1.AccessInput.BATTERY + offset); const profileByte = buffer.readUint8(access_hid_1.AccessInput.PROFILE + offset); return { ...this.parseMappedHeader(buffer, offset), [access_hid_state_1.AccessInputId.B1]: (rawButtons1 & access_hid_1.AccessButton1.B1) > 0, [access_hid_state_1.AccessInputId.B2]: (rawButtons1 & access_hid_1.AccessButton1.B2) > 0, [access_hid_state_1.AccessInputId.B3]: (rawButtons1 & access_hid_1.AccessButton1.B3) > 0, [access_hid_state_1.AccessInputId.B4]: (rawButtons1 & access_hid_1.AccessButton1.B4) > 0, [access_hid_state_1.AccessInputId.B5]: (rawButtons1 & access_hid_1.AccessButton1.B5) > 0, [access_hid_state_1.AccessInputId.B6]: (rawButtons1 & access_hid_1.AccessButton1.B6) > 0, [access_hid_state_1.AccessInputId.B7]: (rawButtons1 & access_hid_1.AccessButton1.B7) > 0, [access_hid_state_1.AccessInputId.B8]: (rawButtons1 & access_hid_1.AccessButton1.B8) > 0, [access_hid_state_1.AccessInputId.Center]: (rawButtons2 & access_hid_1.AccessButton2.CENTER) > 0, [access_hid_state_1.AccessInputId.StickClick]: (rawButtons2 & access_hid_1.AccessButton2.STICK) > 0, [access_hid_state_1.AccessInputId.PS]: (rawButtons2 & access_hid_1.AccessButton2.PS) > 0, [access_hid_state_1.AccessInputId.Profile]: (rawButtons2 & access_hid_1.AccessButton2.PROFILE) > 0, [access_hid_state_1.AccessInputId.StickX]: (0, hid_provider_1.mapAxis)(buffer.readUint8(access_hid_1.AccessInput.RAW_STICK_X + offset)), [access_hid_state_1.AccessInputId.StickY]: (0, hid_provider_1.mapAxis)(buffer.readUint8(access_hid_1.AccessInput.RAW_STICK_Y + offset)), [access_hid_state_1.AccessInputId.BatteryLevel]: (0, hid_provider_1.mapBatteryLevel)(batteryByte), [access_hid_state_1.AccessInputId.BatteryStatus]: (batteryByte >> 4), [access_hid_state_1.AccessInputId.ProfileId]: (profileByte & 0x07) || 1, }; } } exports.AccessHIDProvider = AccessHIDProvider; /** HID vendorId for a DualSense Access controller */ AccessHIDProvider.vendorId = 0x054c; /** HID productId for a DualSense Access controller */ AccessHIDProvider.productId = 0x0e5f; /** HID usagePage for a DualSense Access controller */ AccessHIDProvider.usagePage = 0x0001; /** HID usage for a DualSense Access controller */ AccessHIDProvider.usage = 0x0005; /** Global set of device paths currently claimed by a provider instance */ AccessHIDProvider.claimedDevices = new Set(); //# sourceMappingURL=access_hid_provider.js.map