├── .npmignore ├── docs ├── api │ ├── assets │ │ ├── images │ │ │ ├── icons.png │ │ │ ├── icons@2x.png │ │ │ ├── widgets.png │ │ │ └── widgets@2x.png │ │ └── js │ │ │ └── search.js │ ├── interfaces │ │ ├── dualshock4touchpad.html │ │ ├── dualshock4touchpadtouch.html │ │ ├── dualshock4state.html │ │ └── dualshock4analogstate.html │ ├── globals.html │ ├── enums │ │ └── dualshock4interface.html │ ├── index.html │ └── classes │ │ ├── dualshock4rumble.html │ │ ├── dualshock4lightbar.html │ │ └── dualshock4.html ├── index.html └── demo.539144ec.css ├── demo ├── index.js ├── index.html └── Demo.vue ├── src ├── util │ ├── normalize.ts │ └── colorConversion.ts ├── rumble.ts ├── lightbar.ts ├── state.ts └── index.ts ├── rollup.config.js ├── LICENSE ├── package.json ├── .gitignore ├── README.md └── tsconfig.json /.npmignore: -------------------------------------------------------------------------------- 1 | .cache 2 | demo 3 | docs 4 | src 5 | .vscode 6 | rollup.config.js 7 | tsconfig.json 8 | -------------------------------------------------------------------------------- /docs/api/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBITLINK/WebHID-DS4/HEAD/docs/api/assets/images/icons.png -------------------------------------------------------------------------------- /docs/api/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBITLINK/WebHID-DS4/HEAD/docs/api/assets/images/icons@2x.png -------------------------------------------------------------------------------- /docs/api/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBITLINK/WebHID-DS4/HEAD/docs/api/assets/images/widgets.png -------------------------------------------------------------------------------- /docs/api/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBITLINK/WebHID-DS4/HEAD/docs/api/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /demo/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Demo from './Demo.vue' 3 | 4 | new Vue({ 5 | el: '#app', 6 | render: (h) => h(Demo) 7 | }) 8 | -------------------------------------------------------------------------------- /src/util/normalize.ts: -------------------------------------------------------------------------------- 1 | export function normalizeThumbstick (input : number, deadZone = 0) { 2 | const rel = (input - 128) / 128 3 | if (Math.abs(rel) <= deadZone) return 0 4 | return Math.min(1, Math.max(-1, rel)) 5 | } 6 | 7 | export function normalizeTrigger (input : number, deadZone = 0) { 8 | return Math.min(1, Math.max(deadZone, input / 255)) 9 | } 10 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from 'rollup-plugin-typescript2' 2 | import commonjs from 'rollup-plugin-commonjs' 3 | import resolve from 'rollup-plugin-node-resolve' 4 | 5 | export default { 6 | input: './src/index.ts', 7 | output: [ 8 | { file: 'dist/webhid-ds4.js', format: 'cjs' }, 9 | { file: 'dist/webhid-ds4.esm.js', format: 'esm' } 10 | ], 11 | plugins: [ 12 | typescript(), 13 | commonjs({ extensions: ['.js', '.ts'] }), 14 | resolve({ preferBuiltins: false }) 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | WebHID DualShock 4 Demo

WebHID DualShock 4 Demo

Library Documentation / GitHub / NPM Package
-------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebHID DualShock 4 Demo 7 | 8 | 9 | 10 |

WebHID DualShock 4 Demo

11 |
12 | Library Documentation / GitHub / NPM Package 13 |
14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/demo.539144ec.css: -------------------------------------------------------------------------------- 1 | body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;font-weight:300;margin:auto;padding:16px;max-width:960px}h1,h2,h3,h4,h5{font-weight:100}a{color:#689f38;text-decoration:none}code{padding:4px;border-radius:2px}code,pre{background:#e0e0e0}pre{width:100%;padding:8px;border-radius:5px;border:1px solid #bdbdbd;overflow-x:auto}blockquote{border-left:2px solid #bdbdbd;padding-left:4px;margin-left:0}img{max-height:70vh;max-width:100%}.analogs .analog,.buttons .btn{display:inline-block;background:#aaa;margin:4px;padding:8px;transition:opacity .3s ease}.analogs .analog{min-width:64px}.name{text-transform:capitalize} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 TheBITLINK aka BIT 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /src/util/colorConversion.ts: -------------------------------------------------------------------------------- 1 | export function processHue (p : number, q : number, t : number) { 2 | if (t < 0) t += 1 3 | if (t > 1) t -= 1 4 | if (t < 1/6) return p + (q - p) * 6 * t 5 | if (t < 1/2) return q 6 | if (t < 2/3) return p + (q - p) * (2/3 - t) * 6 7 | return p 8 | } 9 | 10 | /** 11 | * Converts an HSL color value to RGB. Conversion formula 12 | * adapted from http://en.wikipedia.org/wiki/HSL_color_space. 13 | * 14 | * Assumes h, s, and l are contained in the set [0, 1] and 15 | * returns r, g, and b in the set [0, 255]. 16 | * 17 | * @param h - The hue 18 | * @param s - The saturation 19 | * @param l - The lightness 20 | * @returns The RGB representation 21 | */ 22 | export function hslToRgb (h : number, s : number, l : number) { 23 | const outColor = { r: 0, g: 0, b: 0 } 24 | 25 | if (s === 0) { 26 | outColor.r = outColor.g = outColor.b = l * 255 // Achromatic 27 | } else { 28 | var q = l < 0.5 ? l * (1 + s) : l + s - l * s 29 | var p = 2 * l - q 30 | 31 | outColor.r = processHue(p, q, h + 1 / 3) * 255 32 | outColor.g = processHue(p, q, h) * 255 33 | outColor.b = processHue(p, q, h - 1 / 3) * 255 34 | } 35 | 36 | return outColor 37 | } 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webhid-ds4", 3 | "version": "1.0.3", 4 | "description": "An API wrapper built over the experimental WebHID API to communicate with DualShock 4 controllers", 5 | "main": "dist/webhid-ds4.js", 6 | "module": "dist/webhid-ds4.esm.js", 7 | "types": "dist/index.d.ts", 8 | "repository": "https://github.com/TheBITLINK/WebHID-DS4", 9 | "author": "TheBITLINK aka BIT ", 10 | "license": "MIT", 11 | "private": false, 12 | "scripts": { 13 | "build": "rollup -c", 14 | "build-docs": "parcel build demo/index.html -d docs --public-url ./ && typedoc" 15 | }, 16 | "devDependencies": { 17 | "@types/crc": "^3.4.0", 18 | "@types/events": "^3.0.0", 19 | "@types/w3c-web-hid": "^1.0.0", 20 | "@vue/component-compiler-utils": "^3.0.0", 21 | "parcel-bundler": "^1.12.5", 22 | "rollup": "^1.26.2", 23 | "rollup-plugin-commonjs": "^10.1.0", 24 | "rollup-plugin-node-resolve": "^5.2.0", 25 | "rollup-plugin-typescript2": "^0.24.3", 26 | "tslib": "^1.10.0", 27 | "typedoc": "^0.20.36", 28 | "typescript": "^3.6.3", 29 | "vue": "^2.6.10", 30 | "vue-hot-reload-api": "^2.3.4", 31 | "vue-template-compiler": "^2.6.10" 32 | }, 33 | "dependencies": { 34 | "crc": "^3.8.0" 35 | }, 36 | "browserslist": [ 37 | "last 1 Chrome version" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /src/rumble.ts: -------------------------------------------------------------------------------- 1 | import { DualShock4 } from './index' 2 | 3 | /** 4 | * Stores and manages the rumble state. 5 | */ 6 | export default class DualShock4Rumble { 7 | /** @ignore */ 8 | constructor (private controller : DualShock4) { 9 | } 10 | 11 | /** @ignore */ 12 | private _light = 0 13 | /** @ignore */ 14 | private _heavy = 0 15 | 16 | /** 17 | * Sends rumble data to the controller. 18 | * @ignore 19 | */ 20 | updateRumble () { 21 | if (!this.controller.device) { 22 | throw new Error('Controller not initialized. You must call .init() first!') 23 | } 24 | return this.controller.sendLocalState() 25 | } 26 | 27 | /** Light Rumble Intensity (0-255) */ 28 | get light () { 29 | return this._light 30 | } 31 | 32 | set light (value : number) { 33 | this._light = Math.max(0, Math.min(255, value)) 34 | this.updateRumble() 35 | } 36 | 37 | /** Heavy Rumble Intensity (0-255) */ 38 | get heavy () { 39 | return this._heavy 40 | } 41 | 42 | set heavy (value : number) { 43 | this._heavy = Math.max(0, Math.min(255, value)) 44 | this.updateRumble() 45 | } 46 | 47 | /** 48 | * Set the rumble intensity 49 | * @param light - Light rumble intensity (0-255) 50 | * @param heavy - Heavy rumble intensity (0-255) 51 | */ 52 | async setRumbleIntensity (light : number, heavy : number) { 53 | this._light = Math.min(255, Math.max(0, light)) 54 | this._heavy = Math.min(255, Math.max(0, heavy)) 55 | return this.updateRumble() 56 | } 57 | } -------------------------------------------------------------------------------- /src/lightbar.ts: -------------------------------------------------------------------------------- 1 | import { DualShock4 } from './index' 2 | import { hslToRgb } from './util/colorConversion' 3 | 4 | /** 5 | * Stores and manages the lightbar state. 6 | */ 7 | export default class DualShock4Lightbar { 8 | /** @ignore */ 9 | constructor (private controller : DualShock4) { 10 | } 11 | 12 | /** @ignore */ 13 | private _r = 0 14 | /** @ignore */ 15 | private _g = 0 16 | /** @ignore */ 17 | private _b = 0 18 | 19 | /** 20 | * Send Lightbar data to the controller. 21 | * @ignore 22 | */ 23 | updateLightbar () { 24 | if (!this.controller.device) { 25 | throw new Error('Controller not initialized. You must call .init() first!') 26 | } 27 | return this.controller.sendLocalState() 28 | } 29 | 30 | /** Red Color Intensity (0-255) */ 31 | get r () { 32 | return this._r 33 | } 34 | 35 | set r (value : number) { 36 | this._r = Math.min(255, Math.max(0, value)) 37 | this.updateLightbar() 38 | } 39 | 40 | /** Green Color Intensity (0-255) */ 41 | get g () { 42 | return this._g 43 | } 44 | 45 | set g (value : number) { 46 | this._g = Math.min(255, Math.max(0, value)) 47 | this.updateLightbar() 48 | } 49 | 50 | /** Blue Color Intensity (0-255) */ 51 | get b () { 52 | return this._b 53 | } 54 | 55 | set b (value : number) { 56 | this._b = Math.min(255, Math.max(0, value)) 57 | this.updateLightbar() 58 | } 59 | 60 | /** 61 | * Sets the lightbar color (RGB) 62 | * @param r - Red color intensity (0-255) 63 | * @param g - Green color intensity (0-255) 64 | * @param b - Blue color intensity (0-255) 65 | */ 66 | async setColorRGB (r : number, g : number, b : number) { 67 | this._r = Math.min(255, Math.max(0, r)) 68 | this._g = Math.min(255, Math.max(0, g)) 69 | this._b = Math.min(255, Math.max(0, b)) 70 | return this.updateLightbar() 71 | } 72 | 73 | /** 74 | * Sets the lightbar color (HSL) 75 | * @param h - Hue 76 | * @param s - Saturation 77 | * @param l - Lightness 78 | */ 79 | async setColorHSL (h : number, s : number, l : number) { 80 | const color = hslToRgb(h, s, l) 81 | return this.setColorRGB(color.r, color.g, color.b) 82 | } 83 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # Bundled Output 107 | dist/ 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebHID-DS4 2 | 3 | A browser API for Sony DualShock 4 controllers built over the WebHID API. 4 | 5 | Provides high level APIs to access most of the controller's features over USB and Bluetooth. 6 | 7 | ### Supported Features 8 | 9 | - USB and Bluetooth connectivity 10 | - Gyro & Accelerometer data 11 | - Touchpad Input 12 | - Buttons & Analogs 13 | - Lightbar RGB values 14 | - Rumble motors 15 | 16 | ### Known Issues 17 | 18 | - Setting the lightbar colors and rumble intensity over Bluetooth is currently broken. 19 | - There's currently no way to detect if a controller has been disconnected. 20 | - There's currently no way to detect if a controller has already been connected either. 21 | - Not all DS4 Models are supported by this library. I only have a CUH-ZCT2U, so that's what i used to test. Support for third party controllers is not guaranteed. 22 | 23 | ### Installation 24 | 25 | ```npm install --save webhid-ds4``` 26 | 27 | ### Usage Example 28 | 29 | ```js 30 | import { DualShock4 } from 'webhid-ds4' 31 | 32 | // The WebHID device can only be requested upon user interaction 33 | document.getElementById('connectButton').addEventListener('click', async () => { 34 | const DS4 = new DualShock4() 35 | // This will request the WebHID device and initialize the controller 36 | await DS4.init() 37 | // Define a custom lightbar color 38 | await DS4.lightbar.setColorRGB(170, 255, 0) 39 | // The state object is updated periodically with the current controller state 40 | function logInputs () { 41 | requestAnimationFrame(logInputs) 42 | document.getElementById('triangle').innerText = `Triangle Button: ${DS4.state.buttons.triangle}` 43 | document.getElementById('circle').innerText = `Circle Button: ${DS4.state.buttons.circle}` 44 | document.getElementById('cross').innerText = `Cross Button: ${DS4.state.buttons.cross}` 45 | document.getElementById('square').innerText = `Square Button: ${DS4.state.buttons.square}` 46 | 47 | document.getElementById('leftStick').innerText = `Left Stick: ${DS4.state.axes.leftStickX}, ${DS4.state.axes.leftStickY}` 48 | document.getElementById('rightStick').innerText = `Right Stick: ${DS4.state.axes.rightStickX}, ${DS4.state.axes.rightStickY}` 49 | } 50 | logInputs() 51 | }) 52 | ``` 53 | 54 | ### Documentation 55 | 56 | API Documentation is available [here](https://thebitlink.github.io/WebHID-DS4/api/) 57 | -------------------------------------------------------------------------------- /demo/Demo.vue: -------------------------------------------------------------------------------- 1 | 51 | 116 | 139 | -------------------------------------------------------------------------------- /src/state.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Controller State 3 | * 4 | * Stores information about the current controller state, and its components. 5 | */ 6 | export interface DualShock4State { 7 | /** Interface used for communication (USB/Bluetooth) */ 8 | interface : DualShock4Interface 9 | 10 | /** Battery Level (0-100) */ 11 | battery : number 12 | /** Is the battery being charged? */ 13 | charging : boolean 14 | 15 | /** Analog positions */ 16 | axes : DualShock4AnalogState 17 | /** Buttons pressed */ 18 | buttons : DualShock4ButtonState 19 | /** Touchpad */ 20 | touchpad : DualShock4Touchpad 21 | 22 | /** Timestamp of the last report */ 23 | timestamp : number 24 | } 25 | 26 | /** 27 | * Button State 28 | * 29 | * Stores information about the buttons that are currently being held. 30 | */ 31 | export interface DualShock4ButtonState { 32 | /** Triangle Button */ 33 | triangle : boolean 34 | /** Circle Button */ 35 | circle : boolean 36 | /** Cross Button */ 37 | cross : boolean 38 | /** Square Button */ 39 | square : boolean 40 | 41 | /** D-Pad Up */ 42 | dPadUp : boolean 43 | /** D-Pad Right */ 44 | dPadRight : boolean 45 | /** D-Pad Down */ 46 | dPadDown : boolean 47 | /** D-Pad Left */ 48 | dPadLeft : boolean 49 | 50 | /** L1 Button */ 51 | l1 : boolean 52 | /** L2 Trigger (non-analog value) */ 53 | l2 : boolean 54 | /** L3 Button */ 55 | l3 : boolean 56 | 57 | /** R1 Button */ 58 | r1 : boolean 59 | /** R2 Trigger (non-analog value) */ 60 | r2 : boolean 61 | /** R3 Button */ 62 | r3 : boolean 63 | 64 | /** Options Button */ 65 | options : boolean 66 | /** Share Button */ 67 | share : boolean 68 | /** PS Button */ 69 | playStation : boolean 70 | 71 | /** Touchpad Button */ 72 | touchPadClick : boolean 73 | } 74 | 75 | /** 76 | * Analog State 77 | * 78 | * Stores information for analog axes. 79 | * 80 | * - Values for thumbsticks are stored using the range **-1.0** (left, top) to **1.0** (right, bottom). 81 | * 82 | * - Values for triggers use the range **0.0** (released) to **1.0** (pressed) 83 | * 84 | * - Values for accelerometer and gyroscope use the raw input from the sensors. 85 | */ 86 | export interface DualShock4AnalogState { 87 | /** Left Stick Horizontal position. */ 88 | leftStickX : number 89 | /** Left Stick Vertical position. */ 90 | leftStickY : number 91 | 92 | /** Right Stick Horizontal position. */ 93 | rightStickX : number 94 | /** Right Stick Vertical position. */ 95 | rightStickY : number 96 | 97 | /** Left trigger analog value */ 98 | l2 : number 99 | /** Right trigger analog value */ 100 | r2 : number 101 | 102 | /** Accelerometer X */ 103 | accelX : number 104 | /** Accelerometer Y */ 105 | accelY : number 106 | /** Accelerometer Z */ 107 | accelZ : number 108 | 109 | /** Angular velocity X */ 110 | gyroX : number 111 | /** Angular velocity Y */ 112 | gyroY : number 113 | /** Angular velocity Z */ 114 | gyroZ : number 115 | } 116 | 117 | /** Touchpad State */ 118 | export interface DualShock4Touchpad { 119 | /** Current touches */ 120 | touches : DualShock4TouchpadTouch[] 121 | } 122 | 123 | /** 124 | * Touchpad Touch Information 125 | * 126 | * The touchpad's resolution is 1920x943. 127 | */ 128 | export interface DualShock4TouchpadTouch { 129 | /** Touch ID. Changes with every new touch. */ 130 | touchId : number 131 | /** X Position. */ 132 | x : number 133 | /** Y Position. */ 134 | y : number 135 | } 136 | 137 | /** 138 | * Current Interface 139 | */ 140 | export enum DualShock4Interface { 141 | Disconnected = 'none', 142 | /** The controller is connected over USB */ 143 | USB = 'usb', 144 | /** The controller is connected over BT */ 145 | Bluetooth = 'bt' 146 | } 147 | 148 | /** 149 | * Default / Initial State 150 | * @ignore 151 | */ 152 | export const defaultState : DualShock4State = { 153 | interface: DualShock4Interface.Disconnected, 154 | battery: 0, 155 | charging: false, 156 | 157 | axes: { 158 | leftStickX: 0, 159 | leftStickY: 0, 160 | rightStickX: 0, 161 | rightStickY: 0, 162 | 163 | l2: 0, 164 | r2: 0, 165 | 166 | accelX: 0, 167 | accelY: 0, 168 | accelZ: 0, 169 | 170 | gyroX: 0, 171 | gyroY: 0, 172 | gyroZ: 0 173 | }, 174 | 175 | buttons: { 176 | triangle: false, 177 | circle: false, 178 | cross: false, 179 | square: false, 180 | 181 | dPadUp: false, 182 | dPadRight: false, 183 | dPadDown: false, 184 | dPadLeft: false, 185 | 186 | l1: false, 187 | l2: false, 188 | l3: false, 189 | 190 | r1: false, 191 | r2: false, 192 | r3: false, 193 | 194 | options: false, 195 | share: false, 196 | playStation: false, 197 | touchPadClick: false 198 | }, 199 | 200 | touchpad: { 201 | touches: [] 202 | }, 203 | 204 | timestamp: -1 205 | } 206 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ 6 | "module": "es2015", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 7 | // "lib": [], /* Specify library files to be included in the compilation. */ 8 | // "allowJs": true, /* Allow javascript files to be compiled. */ 9 | // "checkJs": true, /* Report errors in .js files. */ 10 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 11 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 12 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 13 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 14 | // "outFile": "./", /* Concatenate and emit output to single file. */ 15 | "outDir": "./dist", /* Redirect output structure to the directory. */ 16 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 17 | // "composite": true, /* Enable project compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true, /* Enable all strict type-checking options. */ 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | // "types": [], /* Type declaration files to be included in compilation. */ 48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 49 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 51 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 52 | 53 | /* Source Map Options */ 54 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 55 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 56 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 57 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 58 | 59 | /* Experimental Options */ 60 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 61 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 62 | }, 63 | "typedocOptions": { 64 | "src": "./src", 65 | "out": "./docs/api", 66 | "ignoreCompilerErrors": true, 67 | "excludeExternals": true, 68 | "externalPattern": "**/node_modules/**/*", 69 | "mode": "file", 70 | "exclude": [ 71 | "**/util/**" 72 | ] 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { defaultState, DualShock4Interface } from './state' 2 | import DualShock4Lightbar from './lightbar' 3 | import DualShock4Rumble from './rumble' 4 | import { normalizeThumbstick, normalizeTrigger } from './util/normalize' 5 | import { Buffer } from 'buffer' 6 | import { crc32 } from 'crc' 7 | 8 | /** 9 | * Main class. 10 | */ 11 | export class DualShock4 { 12 | /** Internal WebHID device */ 13 | device ?: HIDDevice 14 | 15 | /** Raw contents of the last HID Report sent by the controller. */ 16 | lastReport ?: ArrayBuffer 17 | /** Raw contents of the last HID Report sent to the controller. */ 18 | lastSentReport ?: ArrayBuffer 19 | 20 | /** Current controller state */ 21 | state = defaultState 22 | 23 | /** Allows lightbar control */ 24 | lightbar = new DualShock4Lightbar(this) 25 | /** Allows rumble control */ 26 | rumble = new DualShock4Rumble(this) 27 | 28 | constructor () { 29 | if (!navigator.hid || !navigator.hid.requestDevice) { 30 | throw new Error('WebHID not supported by browser or not available.') 31 | } 32 | } 33 | 34 | /** 35 | * Initializes the WebHID API and requests access to the device. 36 | * 37 | * This function must be called in the context of user interaction 38 | * (i.e in a click event handler), otherwise it might not work. 39 | */ 40 | async init () { 41 | if (this.device && this.device.opened) return 42 | 43 | const devices = await navigator.hid.requestDevice({ 44 | // TODO: Add more compatible controllers? 45 | filters: [ 46 | // Official Sony Controllers 47 | { vendorId: 0x054C, productId: 0x0BA0 }, 48 | { vendorId: 0x054C, productId: 0x05C4 }, 49 | { vendorId: 0x054C, productId: 0x09CC }, 50 | { vendorId: 0x054C, productId: 0x05C5 }, 51 | // Razer Raiju 52 | { vendorId: 0x1532, productId: 0x1000 }, 53 | { vendorId: 0x1532, productId: 0x1007 }, 54 | { vendorId: 0x1532, productId: 0x1004 }, 55 | { vendorId: 0x1532, productId: 0x1009 }, 56 | // Nacon Revol 57 | { vendorId: 0x146B, productId: 0x0D01 }, 58 | { vendorId: 0x146B, productId: 0x0D02 }, 59 | { vendorId: 0x146B, productId: 0x0D08 }, 60 | // Other third party controllers 61 | { vendorId: 0x0F0D, productId: 0x00EE }, 62 | { vendorId: 0x7545, productId: 0x0104 }, 63 | { vendorId: 0x2E95, productId: 0x7725 }, 64 | { vendorId: 0x11C0, productId: 0x4001 }, 65 | { vendorId: 0x0C12, productId: 0x57AB }, 66 | { vendorId: 0x0C12, productId: 0x0E16 }, 67 | { vendorId: 0x0F0D, productId: 0x0084 } 68 | ] 69 | }) 70 | 71 | this.device = devices[0] 72 | 73 | await this.device.open() 74 | 75 | this.device.oninputreport = (e : HIDInputReportEvent) => this.processControllerReport(e) 76 | } 77 | 78 | /** 79 | * Parses a report sent from the controller and updates the state. 80 | * 81 | * This function is called internally by the library each time a report is received. 82 | * 83 | * @param report - HID Report sent by the controller. 84 | */ 85 | private processControllerReport (report : HIDInputReportEvent) { 86 | const { data } = report 87 | this.lastReport = data.buffer 88 | 89 | // Interface is unknown 90 | if (this.state.interface === DualShock4Interface.Disconnected) { 91 | if (data.byteLength === 63) { 92 | this.state.interface = DualShock4Interface.USB 93 | } else { 94 | this.state.interface = DualShock4Interface.Bluetooth 95 | this.device!.receiveFeatureReport(0x02) 96 | return 97 | } 98 | // Player 1 Color 99 | this.lightbar.setColorRGB(0, 0, 64).catch(e => console.error(e)) 100 | } 101 | 102 | this.state.timestamp = report.timeStamp 103 | 104 | // USB Reports 105 | if (this.state.interface === DualShock4Interface.USB && report.reportId === 0x01) { 106 | this.updateState(data) 107 | } 108 | // Bluetooth Reports 109 | if (this.state.interface === DualShock4Interface.Bluetooth && report.reportId === 0x11) { 110 | this.updateState(new DataView(data.buffer, 2)) 111 | this.device!.receiveFeatureReport(0x02) 112 | } 113 | } 114 | 115 | /** 116 | * Updates the controller state using normalized data from the last report. 117 | * 118 | * This function is called internally by the library each time a report is received. 119 | * 120 | * @param data - Normalized data from the HID report. 121 | */ 122 | private updateState (data : DataView) { 123 | // Update thumbsticks 124 | this.state.axes.leftStickX = normalizeThumbstick(data.getUint8(0)) 125 | this.state.axes.leftStickY = normalizeThumbstick(data.getUint8(1)) 126 | this.state.axes.rightStickX = normalizeThumbstick(data.getUint8(2)) 127 | this.state.axes.rightStickY = normalizeThumbstick(data.getUint8(3)) 128 | 129 | // Update main buttons 130 | const buttons1 = data.getUint8(4) 131 | this.state.buttons.triangle = !!(buttons1 & 0x80) 132 | this.state.buttons.circle = !!(buttons1 & 0x40) 133 | this.state.buttons.cross = !!(buttons1 & 0x20) 134 | this.state.buttons.square = !!(buttons1 & 0x10) 135 | // Update D-Pad 136 | const dPad = buttons1 & 0x0F 137 | this.state.buttons.dPadUp = dPad === 7 || dPad === 0 || dPad === 1 138 | this.state.buttons.dPadRight = dPad === 1 || dPad === 2 || dPad === 3 139 | this.state.buttons.dPadDown = dPad === 3 || dPad === 4 || dPad === 5 140 | this.state.buttons.dPadLeft = dPad === 5 || dPad === 6 || dPad === 7 141 | // Update additional buttons 142 | const buttons2 = data.getUint8(5) 143 | this.state.buttons.l1 = !!(buttons2 & 0x01) 144 | this.state.buttons.r1 = !!(buttons2 & 0x02) 145 | this.state.buttons.l2 = !!(buttons2 & 0x04) 146 | this.state.buttons.r2 = !!(buttons2 & 0x08) 147 | this.state.buttons.share = !!(buttons2 & 0x10) 148 | this.state.buttons.options = !!(buttons2 & 0x20) 149 | this.state.buttons.l3 = !!(buttons2 & 0x40) 150 | this.state.buttons.r3 = !!(buttons2 & 0x80) 151 | const buttons3 = data.getUint8(6) 152 | this.state.buttons.playStation = !!(buttons3 & 0x01) 153 | this.state.buttons.touchPadClick = !!(buttons3 & 0x02) 154 | 155 | // Update Triggers 156 | this.state.axes.l2 = normalizeTrigger(data.getUint8(7)) 157 | this.state.axes.r2 = normalizeTrigger(data.getUint8(8)) 158 | 159 | // Update battery level 160 | this.state.charging = !!(data.getUint8(29) & 0x10) 161 | if (this.state.charging) { 162 | this.state.battery = Math.min(Math.floor((data.getUint8(29) & 0x0F) * 100 / 11)) 163 | } else { 164 | this.state.battery = Math.min(100, Math.floor((data.getUint8(29) & 0x0F) * 100 / 8)) 165 | } 166 | 167 | // Update motion input 168 | this.state.axes.gyroX = data.getUint16(13) 169 | this.state.axes.gyroY = data.getUint16(15) 170 | this.state.axes.gyroZ = data.getUint16(17) 171 | this.state.axes.accelX = data.getInt16(19) 172 | this.state.axes.accelY = data.getInt16(21) 173 | this.state.axes.accelZ = data.getInt16(23) 174 | 175 | // Update touchpad 176 | this.state.touchpad.touches = [] 177 | if (!(data.getUint8(34) & 0x80)) { 178 | this.state.touchpad.touches.push({ 179 | touchId: data.getUint8(34) & 0x7F, 180 | x: (data.getUint8(36) & 0x0F) << 8 | data.getUint8(35), 181 | y: data.getUint8(37) << 4 | (data.getUint8(36) & 0xF0) >> 4 182 | }) 183 | } 184 | if (!(data.getUint8(38) & 0x80)) { 185 | this.state.touchpad.touches.push({ 186 | touchId: data.getUint8(38) & 0x7F, 187 | x: (data.getUint8(40) & 0x0F) << 8 | data.getUint8(39), 188 | y: data.getUint8(41) << 4 | (data.getUint8(40) & 0xF0) >> 4 189 | }) 190 | } 191 | } 192 | 193 | /** 194 | * Sends the local rumble and lightbar state to the controller. 195 | * 196 | * This function is called automatically in most cases. 197 | * 198 | * **Currently broken over Bluetooth, doesn't do anything** 199 | */ 200 | async sendLocalState () { 201 | if (!this.device) throw new Error('Controller not initialized. You must call .init() first!') 202 | 203 | if (this.state.interface === DualShock4Interface.USB) { 204 | const report = new Uint8Array(16) 205 | 206 | // Report ID 207 | report[0] = 0x05 208 | 209 | // Enable Rumble (0x01), Lightbar (0x02) 210 | report[1] = 0xF0 | 0x01 | 0x02 211 | 212 | // Light rumble motor 213 | report[4] = this.rumble.light 214 | // Heavy rumble motor 215 | report[5] = this.rumble.heavy 216 | 217 | // Lightbar Red 218 | report[6] = this.lightbar.r 219 | // Lightbar Green 220 | report[7] = this.lightbar.g 221 | // Lightbar Blue 222 | report[8] = this.lightbar.b 223 | 224 | this.lastSentReport = report.buffer 225 | 226 | return this.device.sendReport(report[0], report.slice(1)) 227 | } else { 228 | const report = new Uint16Array(79) 229 | const crcBytes = new Uint8Array(4) 230 | const crcDv = new DataView(crcBytes.buffer) 231 | 232 | // Header 233 | report[0] = 0xA2 234 | // Report ID 235 | report[1] = 0x11 236 | 237 | // Poll Rate 238 | report[2] = 0x80 239 | // Enable rumble and lights 240 | report[4] = 0xFF 241 | 242 | // Light rumble motor 243 | report[7] = this.rumble.light 244 | // Heavy rumble motor 245 | report[8] = this.rumble.heavy 246 | 247 | // Lightbar Red 248 | report[9] = this.lightbar.r 249 | // Lightbar Green 250 | report[10] = this.lightbar.g 251 | // Lightbar Blue 252 | report[11] = this.lightbar.b 253 | 254 | crcDv.setUint32(0, crc32(Buffer.from(report.slice(0, 75)))) 255 | report[75] = crcBytes[3] 256 | report[76] = crcBytes[2] 257 | report[77] = crcBytes[1] 258 | report[78] = crcBytes[0] 259 | 260 | this.lastSentReport = report.buffer 261 | 262 | return this.device.sendReport(report[1], report.slice(2)) 263 | } 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /docs/api/interfaces/dualshock4touchpad.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DualShock4Touchpad | webhid-ds4 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | Menu 46 |
47 |
48 |
49 |
50 |
51 |
52 | 60 |

Interface DualShock4Touchpad

61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |

Hierarchy

69 |
    70 |
  • 71 | DualShock4Touchpad 72 |
  • 73 |
74 |
75 |
76 |

Index

77 |
78 |
79 |
80 |

Properties

81 | 84 |
85 |
86 |
87 |
88 |
89 |

Properties

90 |
91 | 92 |

touches

93 | 94 | 99 |
100 |
101 |
102 | 151 |
152 |
153 | 213 |
214 |

Generated using TypeDoc

215 |
216 |
217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /docs/api/globals.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | webhid-ds4 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | Menu 46 |
47 |
48 |
49 |
50 |
51 |
52 | 57 |

webhid-ds4

58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |

Index

66 |
67 |
68 |
69 |

Enumerations

70 | 73 |
74 |
75 |

Classes

76 | 81 |
82 |
83 |

Interfaces

84 | 91 |
92 |
93 |
94 |
95 |
96 | 136 |
137 |
138 | 198 |
199 |

Generated using TypeDoc

200 |
201 |
202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /docs/api/assets/js/search.js: -------------------------------------------------------------------------------- 1 | var typedoc = typedoc || {}; 2 | typedoc.search = typedoc.search || {}; 3 | typedoc.search.data = {"kinds":{"4":"Enumeration","16":"Enumeration member","128":"Class","256":"Interface","512":"Constructor","1024":"Property","2048":"Method","262144":"Accessor"},"rows":[{"id":0,"kind":256,"name":"DualShock4State","url":"interfaces/dualshock4state.html","classes":"tsd-kind-interface"},{"id":1,"kind":1024,"name":"interface","url":"interfaces/dualshock4state.html#interface","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4State"},{"id":2,"kind":1024,"name":"battery","url":"interfaces/dualshock4state.html#battery","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4State"},{"id":3,"kind":1024,"name":"charging","url":"interfaces/dualshock4state.html#charging","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4State"},{"id":4,"kind":1024,"name":"axes","url":"interfaces/dualshock4state.html#axes","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4State"},{"id":5,"kind":1024,"name":"buttons","url":"interfaces/dualshock4state.html#buttons","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4State"},{"id":6,"kind":1024,"name":"touchpad","url":"interfaces/dualshock4state.html#touchpad","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4State"},{"id":7,"kind":1024,"name":"timestamp","url":"interfaces/dualshock4state.html#timestamp","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4State"},{"id":8,"kind":256,"name":"DualShock4ButtonState","url":"interfaces/dualshock4buttonstate.html","classes":"tsd-kind-interface"},{"id":9,"kind":1024,"name":"triangle","url":"interfaces/dualshock4buttonstate.html#triangle","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":10,"kind":1024,"name":"circle","url":"interfaces/dualshock4buttonstate.html#circle","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":11,"kind":1024,"name":"cross","url":"interfaces/dualshock4buttonstate.html#cross","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":12,"kind":1024,"name":"square","url":"interfaces/dualshock4buttonstate.html#square","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":13,"kind":1024,"name":"dPadUp","url":"interfaces/dualshock4buttonstate.html#dpadup","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":14,"kind":1024,"name":"dPadRight","url":"interfaces/dualshock4buttonstate.html#dpadright","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":15,"kind":1024,"name":"dPadDown","url":"interfaces/dualshock4buttonstate.html#dpaddown","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":16,"kind":1024,"name":"dPadLeft","url":"interfaces/dualshock4buttonstate.html#dpadleft","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":17,"kind":1024,"name":"l1","url":"interfaces/dualshock4buttonstate.html#l1","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":18,"kind":1024,"name":"l2","url":"interfaces/dualshock4buttonstate.html#l2","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":19,"kind":1024,"name":"l3","url":"interfaces/dualshock4buttonstate.html#l3","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":20,"kind":1024,"name":"r1","url":"interfaces/dualshock4buttonstate.html#r1","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":21,"kind":1024,"name":"r2","url":"interfaces/dualshock4buttonstate.html#r2","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":22,"kind":1024,"name":"r3","url":"interfaces/dualshock4buttonstate.html#r3","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":23,"kind":1024,"name":"options","url":"interfaces/dualshock4buttonstate.html#options","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":24,"kind":1024,"name":"share","url":"interfaces/dualshock4buttonstate.html#share","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":25,"kind":1024,"name":"playStation","url":"interfaces/dualshock4buttonstate.html#playstation","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":26,"kind":1024,"name":"touchPadClick","url":"interfaces/dualshock4buttonstate.html#touchpadclick","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4ButtonState"},{"id":27,"kind":256,"name":"DualShock4AnalogState","url":"interfaces/dualshock4analogstate.html","classes":"tsd-kind-interface"},{"id":28,"kind":1024,"name":"leftStickX","url":"interfaces/dualshock4analogstate.html#leftstickx","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":29,"kind":1024,"name":"leftStickY","url":"interfaces/dualshock4analogstate.html#leftsticky","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":30,"kind":1024,"name":"rightStickX","url":"interfaces/dualshock4analogstate.html#rightstickx","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":31,"kind":1024,"name":"rightStickY","url":"interfaces/dualshock4analogstate.html#rightsticky","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":32,"kind":1024,"name":"l2","url":"interfaces/dualshock4analogstate.html#l2","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":33,"kind":1024,"name":"r2","url":"interfaces/dualshock4analogstate.html#r2","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":34,"kind":1024,"name":"accelX","url":"interfaces/dualshock4analogstate.html#accelx","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":35,"kind":1024,"name":"accelY","url":"interfaces/dualshock4analogstate.html#accely","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":36,"kind":1024,"name":"accelZ","url":"interfaces/dualshock4analogstate.html#accelz","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":37,"kind":1024,"name":"gyroX","url":"interfaces/dualshock4analogstate.html#gyrox","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":38,"kind":1024,"name":"gyroY","url":"interfaces/dualshock4analogstate.html#gyroy","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":39,"kind":1024,"name":"gyroZ","url":"interfaces/dualshock4analogstate.html#gyroz","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4AnalogState"},{"id":40,"kind":256,"name":"DualShock4Touchpad","url":"interfaces/dualshock4touchpad.html","classes":"tsd-kind-interface"},{"id":41,"kind":1024,"name":"touches","url":"interfaces/dualshock4touchpad.html#touches","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4Touchpad"},{"id":42,"kind":256,"name":"DualShock4TouchpadTouch","url":"interfaces/dualshock4touchpadtouch.html","classes":"tsd-kind-interface"},{"id":43,"kind":1024,"name":"touchId","url":"interfaces/dualshock4touchpadtouch.html#touchid","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4TouchpadTouch"},{"id":44,"kind":1024,"name":"x","url":"interfaces/dualshock4touchpadtouch.html#x","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4TouchpadTouch"},{"id":45,"kind":1024,"name":"y","url":"interfaces/dualshock4touchpadtouch.html#y","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"DualShock4TouchpadTouch"},{"id":46,"kind":4,"name":"DualShock4Interface","url":"enums/dualshock4interface.html","classes":"tsd-kind-enum"},{"id":47,"kind":16,"name":"Disconnected","url":"enums/dualshock4interface.html#disconnected","classes":"tsd-kind-enum-member tsd-parent-kind-enum","parent":"DualShock4Interface"},{"id":48,"kind":16,"name":"USB","url":"enums/dualshock4interface.html#usb","classes":"tsd-kind-enum-member tsd-parent-kind-enum","parent":"DualShock4Interface"},{"id":49,"kind":16,"name":"Bluetooth","url":"enums/dualshock4interface.html#bluetooth","classes":"tsd-kind-enum-member tsd-parent-kind-enum","parent":"DualShock4Interface"},{"id":50,"kind":128,"name":"DualShock4Lightbar","url":"classes/dualshock4lightbar.html","classes":"tsd-kind-class"},{"id":51,"kind":1024,"name":"controller","url":"classes/dualshock4lightbar.html#controller","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-private","parent":"DualShock4Lightbar"},{"id":52,"kind":262144,"name":"r","url":"classes/dualshock4lightbar.html#r","classes":"tsd-kind-accessor tsd-parent-kind-class","parent":"DualShock4Lightbar"},{"id":53,"kind":262144,"name":"g","url":"classes/dualshock4lightbar.html#g","classes":"tsd-kind-accessor tsd-parent-kind-class","parent":"DualShock4Lightbar"},{"id":54,"kind":262144,"name":"b","url":"classes/dualshock4lightbar.html#b","classes":"tsd-kind-accessor tsd-parent-kind-class","parent":"DualShock4Lightbar"},{"id":55,"kind":2048,"name":"setColorRGB","url":"classes/dualshock4lightbar.html#setcolorrgb","classes":"tsd-kind-method tsd-parent-kind-class","parent":"DualShock4Lightbar"},{"id":56,"kind":2048,"name":"setColorHSL","url":"classes/dualshock4lightbar.html#setcolorhsl","classes":"tsd-kind-method tsd-parent-kind-class","parent":"DualShock4Lightbar"},{"id":57,"kind":128,"name":"DualShock4Rumble","url":"classes/dualshock4rumble.html","classes":"tsd-kind-class"},{"id":58,"kind":1024,"name":"controller","url":"classes/dualshock4rumble.html#controller","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-private","parent":"DualShock4Rumble"},{"id":59,"kind":262144,"name":"light","url":"classes/dualshock4rumble.html#light","classes":"tsd-kind-accessor tsd-parent-kind-class","parent":"DualShock4Rumble"},{"id":60,"kind":262144,"name":"heavy","url":"classes/dualshock4rumble.html#heavy","classes":"tsd-kind-accessor tsd-parent-kind-class","parent":"DualShock4Rumble"},{"id":61,"kind":2048,"name":"setRumbleIntensity","url":"classes/dualshock4rumble.html#setrumbleintensity","classes":"tsd-kind-method tsd-parent-kind-class","parent":"DualShock4Rumble"},{"id":62,"kind":128,"name":"DualShock4","url":"classes/dualshock4.html","classes":"tsd-kind-class"},{"id":63,"kind":1024,"name":"device","url":"classes/dualshock4.html#device","classes":"tsd-kind-property tsd-parent-kind-class","parent":"DualShock4"},{"id":64,"kind":1024,"name":"lastReport","url":"classes/dualshock4.html#lastreport","classes":"tsd-kind-property tsd-parent-kind-class","parent":"DualShock4"},{"id":65,"kind":1024,"name":"lastSentReport","url":"classes/dualshock4.html#lastsentreport","classes":"tsd-kind-property tsd-parent-kind-class","parent":"DualShock4"},{"id":66,"kind":1024,"name":"state","url":"classes/dualshock4.html#state","classes":"tsd-kind-property tsd-parent-kind-class","parent":"DualShock4"},{"id":67,"kind":1024,"name":"lightbar","url":"classes/dualshock4.html#lightbar","classes":"tsd-kind-property tsd-parent-kind-class","parent":"DualShock4"},{"id":68,"kind":1024,"name":"rumble","url":"classes/dualshock4.html#rumble","classes":"tsd-kind-property tsd-parent-kind-class","parent":"DualShock4"},{"id":69,"kind":512,"name":"constructor","url":"classes/dualshock4.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"DualShock4"},{"id":70,"kind":2048,"name":"init","url":"classes/dualshock4.html#init","classes":"tsd-kind-method tsd-parent-kind-class","parent":"DualShock4"},{"id":71,"kind":2048,"name":"processControllerReport","url":"classes/dualshock4.html#processcontrollerreport","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-private","parent":"DualShock4"},{"id":72,"kind":2048,"name":"updateState","url":"classes/dualshock4.html#updatestate","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-private","parent":"DualShock4"},{"id":73,"kind":2048,"name":"sendLocalState","url":"classes/dualshock4.html#sendlocalstate","classes":"tsd-kind-method tsd-parent-kind-class","parent":"DualShock4"}]}; -------------------------------------------------------------------------------- /docs/api/enums/dualshock4interface.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DualShock4Interface | webhid-ds4 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | Menu 46 |
47 |
48 |
49 |
50 |
51 |
52 | 60 |

Enumeration DualShock4Interface

61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |

Index

69 |
70 |
71 |
72 |

Enumeration members

73 | 78 |
79 |
80 |
81 |
82 |
83 |

Enumeration members

84 |
85 | 86 |

Bluetooth

87 |
Bluetooth: = "bt"
88 | 93 |
94 |
95 | 96 |

Disconnected

97 |
Disconnected: = "none"
98 | 103 |
104 |
105 | 106 |

USB

107 |
USB: = "usb"
108 | 113 |
114 |
115 |
116 | 171 |
172 |
173 | 233 |
234 |

Generated using TypeDoc

235 |
236 |
237 | 238 | 239 | 240 | -------------------------------------------------------------------------------- /docs/api/interfaces/dualshock4touchpadtouch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DualShock4TouchpadTouch | webhid-ds4 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | Menu 46 |
47 |
48 |
49 |
50 |
51 |
52 | 60 |

Interface DualShock4TouchpadTouch

61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |

Hierarchy

69 |
    70 |
  • 71 | DualShock4TouchpadTouch 72 |
  • 73 |
74 |
75 |
76 |

Index

77 |
78 |
79 |
80 |

Properties

81 | 86 |
87 |
88 |
89 |
90 |
91 |

Properties

92 |
93 | 94 |

touchId

95 |
touchId: number
96 | 101 |
102 |
103 | 104 |

x

105 |
x: number
106 | 111 |
112 |
113 | 114 |

y

115 |
y: number
116 | 121 |
122 |
123 |
124 | 179 |
180 |
181 | 241 |
242 |

Generated using TypeDoc

243 |
244 |
245 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /docs/api/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | webhid-ds4 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | Menu 46 |
47 |
48 |
49 |
50 |
51 |
52 | 57 |

webhid-ds4

58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | 66 |

WebHID-DS4

67 |
68 |

A browser API for Sony DualShock 4 controllers built over the WebHID API.

69 |

Provides high level APIs to access most of the controller's features over USB and Bluetooth.

70 | 71 |

Supported Features

72 |
73 |
    74 |
  • USB and Bluetooth connectivity
  • 75 |
  • Gyro & Accelerometer data
  • 76 |
  • Touchpad Input
  • 77 |
  • Buttons & Analogs
  • 78 |
  • Lightbar RGB values
  • 79 |
  • Rumble motors
  • 80 |
81 | 82 |

Known Issues

83 |
84 |
    85 |
  • Setting the lightbar colors and rumble intensity over Bluetooth is currently broken.
  • 86 |
  • There's currently no way to detect if a controller has been disconnected.
  • 87 |
  • There's currently no way to detect if a controller has already been connected either.
  • 88 |
  • Not all DS4 Models are supported by this library. I only have a CUH-ZCT2U, so that's what i used to test. Support for third party controllers is not guaranteed.
  • 89 |
90 | 91 |

Installation

92 |
93 |

npm install --save webhid-ds4

94 | 95 |

Usage Example

96 |
97 |
import { DualShock4 } from 'webhid-ds4'
 98 | 
 99 | // The WebHID device can only be requested upon user interaction
100 | document.getElementById('connectButton').addEventListener('click', async () => {
101 |   const DS4 = new DualShock4()
102 |   // This will request the WebHID device and initialize the controller
103 |   await DS4.init()
104 |   // Define a custom lightbar color
105 |   await DS4.lightbar.setColorRGB(170, 255, 0)
106 |   // The state object is updated periodically with the current controller state
107 |   function logInputs () {
108 |     requestAnimationFrame(logInputs)
109 |     document.getElementById('triangle').innerText = `Triangle Button: ${DS4.state.buttons.triangle}`
110 |     document.getElementById('circle').innerText = `Circle Button: ${DS4.state.buttons.circle}`
111 |     document.getElementById('cross').innerText = `Cross Button: ${DS4.state.buttons.cross}`
112 |     document.getElementById('square').innerText = `Square Button: ${DS4.state.buttons.square}`
113 | 
114 |     document.getElementById('leftStick').innerText = `Left Stick: ${DS4.state.axes.leftStickX}, ${DS4.state.axes.leftStickY}`
115 |     document.getElementById('rightStick').innerText = `Right Stick: ${DS4.state.axes.rightStickX}, ${DS4.state.axes.rightStickY}`
116 |   }
117 |   logInputs()
118 | })
119 | 120 |

Documentation

121 |
122 |

API Documentation is available here

123 |
124 |
125 | 165 |
166 |
167 | 227 |
228 |

Generated using TypeDoc

229 |
230 |
231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /docs/api/classes/dualshock4rumble.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DualShock4Rumble | webhid-ds4 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | Menu 46 |
47 |
48 |
49 |
50 |
51 |
52 | 60 |

Class DualShock4Rumble

61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |

Hierarchy

69 |
    70 |
  • 71 | DualShock4Rumble 72 |
  • 73 |
74 |
75 |
76 |

Index

77 |
78 |
79 |
80 |

Properties

81 | 84 |
85 |
86 |

Accessors

87 | 91 |
92 |
93 |

Methods

94 | 97 |
98 |
99 |
100 |
101 |
102 |

Properties

103 |
104 | 105 |

Private controller

106 |
controller: DualShock4
107 | 112 |
113 |
114 |
115 |

Accessors

116 |
117 | 118 |

heavy

119 |
heavy:
120 | 126 |
127 |
128 | 129 |

light

130 |
light:
131 | 137 |
138 |
139 |
140 |

Methods

141 |
142 | 143 |

setRumbleIntensity

144 |
    145 |
  • setRumbleIntensity(light: number, heavy: number): Promise<void>
  • 146 |
147 |
    148 |
  • 149 | 154 |

    Parameters

    155 |
      156 |
    • 157 |
      light: number
      158 |
    • 159 |
    • 160 |
      heavy: number
      161 |
    • 162 |
    163 |

    Returns Promise<void>

    164 |
  • 165 |
166 |
167 |
168 |
169 | 227 |
228 |
229 | 289 |
290 |

Generated using TypeDoc

291 |
292 |
293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /docs/api/interfaces/dualshock4state.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DualShock4State | webhid-ds4 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | Menu 46 |
47 |
48 |
49 |
50 |
51 |
52 | 60 |

Interface DualShock4State

61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |

Hierarchy

69 |
    70 |
  • 71 | DualShock4State 72 |
  • 73 |
74 |
75 |
76 |

Index

77 |
78 |
79 |
80 |

Properties

81 | 90 |
91 |
92 |
93 |
94 |
95 |

Properties

96 |
97 | 98 |

axes

99 | 100 | 105 |
106 |
107 | 108 |

battery

109 |
battery: number
110 | 115 |
116 |
117 | 118 |

buttons

119 | 120 | 125 |
126 |
127 | 128 |

charging

129 |
charging: boolean
130 | 135 |
136 |
137 | 138 |

interface

139 | 140 | 145 |
146 |
147 | 148 |

timestamp

149 |
timestamp: number
150 | 155 |
156 |
157 | 158 |

touchpad

159 | 160 | 165 |
166 |
167 |
168 | 235 |
236 |
237 | 297 |
298 |

Generated using TypeDoc

299 |
300 |
301 | 302 | 303 | 304 | -------------------------------------------------------------------------------- /docs/api/classes/dualshock4lightbar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DualShock4Lightbar | webhid-ds4 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | Menu 46 |
47 |
48 |
49 |
50 |
51 |
52 | 60 |

Class DualShock4Lightbar

61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |

Hierarchy

69 |
    70 |
  • 71 | DualShock4Lightbar 72 |
  • 73 |
74 |
75 |
76 |

Index

77 |
78 |
79 |
80 |

Properties

81 | 84 |
85 |
86 |

Accessors

87 |
    88 |
  • b
  • 89 |
  • g
  • 90 |
  • r
  • 91 |
92 |
93 |
94 |

Methods

95 | 99 |
100 |
101 |
102 |
103 |
104 |

Properties

105 |
106 | 107 |

Private controller

108 |
controller: DualShock4
109 | 114 |
115 |
116 |
117 |

Accessors

118 |
119 | 120 |

b

121 |
b:
122 | 128 |
129 |
130 | 131 |

g

132 |
g:
133 | 139 |
140 |
141 | 142 |

r

143 |
r:
144 | 150 |
151 |
152 |
153 |

Methods

154 |
155 | 156 |

setColorHSL

157 |
    158 |
  • setColorHSL(h: number, s: number, l: number): Promise<void>
  • 159 |
160 |
    161 |
  • 162 | 167 |

    Parameters

    168 |
      169 |
    • 170 |
      h: number
      171 |
    • 172 |
    • 173 |
      s: number
      174 |
    • 175 |
    • 176 |
      l: number
      177 |
    • 178 |
    179 |

    Returns Promise<void>

    180 |
  • 181 |
182 |
183 |
184 | 185 |

setColorRGB

186 |
    187 |
  • setColorRGB(r: number, g: number, b: number): Promise<void>
  • 188 |
189 |
    190 |
  • 191 | 196 |

    Parameters

    197 |
      198 |
    • 199 |
      r: number
      200 |
    • 201 |
    • 202 |
      g: number
      203 |
    • 204 |
    • 205 |
      b: number
      206 |
    • 207 |
    208 |

    Returns Promise<void>

    209 |
  • 210 |
211 |
212 |
213 |
214 | 278 |
279 |
280 | 340 |
341 |

Generated using TypeDoc

342 |
343 |
344 | 345 | 346 | 347 | -------------------------------------------------------------------------------- /docs/api/interfaces/dualshock4analogstate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DualShock4AnalogState | webhid-ds4 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | Menu 46 |
47 |
48 |
49 |
50 |
51 |
52 | 60 |

Interface DualShock4AnalogState

61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |

Hierarchy

69 |
    70 |
  • 71 | DualShock4AnalogState 72 |
  • 73 |
74 |
75 |
76 |

Index

77 |
78 |
79 |
80 |

Properties

81 | 95 |
96 |
97 |
98 |
99 |
100 |

Properties

101 |
102 | 103 |

accelX

104 |
accelX: number
105 | 110 |
111 |
112 | 113 |

accelY

114 |
accelY: number
115 | 120 |
121 |
122 | 123 |

accelZ

124 |
accelZ: number
125 | 130 |
131 |
132 | 133 |

gyroX

134 |
gyroX: number
135 | 140 |
141 |
142 | 143 |

gyroY

144 |
gyroY: number
145 | 150 |
151 |
152 | 153 |

gyroZ

154 |
gyroZ: number
155 | 160 |
161 |
162 | 163 |

l2

164 |
l2: number
165 | 170 |
171 |
172 | 173 |

leftStickX

174 |
leftStickX: number
175 | 180 |
181 |
182 | 183 |

leftStickY

184 |
leftStickY: number
185 | 190 |
191 |
192 | 193 |

r2

194 |
r2: number
195 | 200 |
201 |
202 | 203 |

rightStickX

204 |
rightStickX: number
205 | 210 |
211 |
212 | 213 |

rightStickY

214 |
rightStickY: number
215 | 220 |
221 |
222 |
223 | 305 |
306 |
307 | 367 |
368 |

Generated using TypeDoc

369 |
370 |
371 | 372 | 373 | 374 | -------------------------------------------------------------------------------- /docs/api/classes/dualshock4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DualShock4 | webhid-ds4 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | Menu 46 |
47 |
48 |
49 |
50 |
51 |
52 | 60 |

Class DualShock4

61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |

Hierarchy

69 |
    70 |
  • 71 | DualShock4 72 |
  • 73 |
74 |
75 |
76 |

Index

77 |
78 |
79 |
80 |

Constructors

81 | 84 |
85 |
86 |

Properties

87 | 95 |
96 |
97 |

Methods

98 | 104 |
105 |
106 |
107 |
108 |
109 |

Constructors

110 |
111 | 112 |

constructor

113 | 116 |
    117 |
  • 118 | 123 |

    Returns DualShock4

    124 |
  • 125 |
126 |
127 |
128 |
129 |

Properties

130 |
131 | 132 |

Optional device

133 |
device: HIDDevice
134 | 139 |
140 |
141 | 142 |

Optional lastReport

143 |
lastReport: ArrayBuffer
144 | 149 |
150 |
151 | 152 |

Optional lastSentReport

153 |
lastSentReport: ArrayBuffer
154 | 159 |
160 |
161 | 162 |

lightbar

163 |
lightbar: DualShock4Lightbar = new DualShock4Lightbar(this)
164 | 169 |
170 |
171 | 172 |

rumble

173 |
rumble: DualShock4Rumble = new DualShock4Rumble(this)
174 | 179 |
180 |
181 | 182 |

state

183 |
state: DualShock4State = defaultState
184 | 189 |
190 |
191 |
192 |

Methods

193 |
194 | 195 |

init

196 |
    197 |
  • init(): Promise<void>
  • 198 |
199 |
    200 |
  • 201 | 206 |

    Returns Promise<void>

    207 |
  • 208 |
209 |
210 |
211 | 212 |

Private processControllerReport

213 |
    214 |
  • processControllerReport(report: HIDInputReportEvent): void
  • 215 |
216 |
    217 |
  • 218 | 223 |

    Parameters

    224 |
      225 |
    • 226 |
      report: HIDInputReportEvent
      227 |
    • 228 |
    229 |

    Returns void

    230 |
  • 231 |
232 |
233 |
234 | 235 |

sendLocalState

236 |
    237 |
  • sendLocalState(): Promise<void>
  • 238 |
239 |
    240 |
  • 241 | 246 |

    Returns Promise<void>

    247 |
  • 248 |
249 |
250 |
251 | 252 |

Private updateState

253 |
    254 |
  • updateState(data: DataView): void
  • 255 |
256 |
    257 |
  • 258 | 263 |

    Parameters

    264 |
      265 |
    • 266 |
      data: DataView
      267 |
    • 268 |
    269 |

    Returns void

    270 |
  • 271 |
272 |
273 |
274 |
275 | 354 |
355 |
356 | 416 |
417 |

Generated using TypeDoc

418 |
419 |
420 | 421 | 422 | 423 | --------------------------------------------------------------------------------