{"id":19478874,"url":"https://github.com/xan105/node-xinput-ffi","last_synced_at":"2025-06-21T12:36:00.215Z","repository":{"id":40005855,"uuid":"285917276","full_name":"xan105/node-xinput-ffi","owner":"xan105","description":"Access native XInput functions as well as some helpers based around them.","archived":false,"fork":false,"pushed_at":"2025-02-09T03:10:50.000Z","size":324,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-11T11:20:18.429Z","etag":null,"topics":["ffi","gamepad","nodejs","pid","rumble","vibrate","vid","windows","xinput"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xan105.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"xan105","custom":"https://www.paypal.me/xan105"}},"created_at":"2020-08-07T20:41:13.000Z","updated_at":"2025-05-16T15:09:26.000Z","dependencies_parsed_at":"2023-12-07T07:29:21.920Z","dependency_job_id":"5c85782f-f801-4862-b48e-09b13469a175","html_url":"https://github.com/xan105/node-xinput-ffi","commit_stats":{"total_commits":91,"total_committers":1,"mean_commits":91.0,"dds":0.0,"last_synced_commit":"dc9a528b4870eb479a5ad0125b4164b336d6f262"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/xan105/node-xinput-ffi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xan105%2Fnode-xinput-ffi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xan105%2Fnode-xinput-ffi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xan105%2Fnode-xinput-ffi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xan105%2Fnode-xinput-ffi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xan105","download_url":"https://codeload.github.com/xan105/node-xinput-ffi/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xan105%2Fnode-xinput-ffi/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261125618,"owners_count":23113275,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ffi","gamepad","nodejs","pid","rumble","vibrate","vid","windows","xinput"],"created_at":"2024-11-10T19:51:51.077Z","updated_at":"2025-06-21T12:35:55.200Z","avatar_url":"https://github.com/xan105.png","language":"JavaScript","funding_links":["https://github.com/sponsors/xan105","https://www.paypal.me/xan105"],"categories":[],"sub_categories":[],"readme":"About\n=====\n\nAccess native XInput functions as well as some helpers based around them.\n\nThis lib hooks directly to the system's dll (xinput1_4.dll, xinput1_3.dll or xinput9_1_0.dll).\u003cbr/\u003e\nIt aims to implement and expose XInput functions as close as possible to the document.\u003cbr/\u003e\n\n🔍 \"Hidden\" XInput functions such as `XInputGetCapabilitiesEx()` are exposed as well.\n\nExamples\n========\n\n\u003cdetails\u003e\n  \u003csummary\u003eVibration via helper function\u003c/summary\u003e\n  \n```js\nimport { rumble } from \"xinput-ffi\";\n\n//Rumble 1st XInput gamepad\nawait rumble();\n\n//Now with 100% force\nawait rumble({force: 100}); \n\n//low-frequency rumble motor(left) at 50% \n//and high-frequency rumble motor (right) at 25%\nawait rumble({force: [50,25]});\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eXInput function\u003c/summary\u003e\n  \n```js\nimport * as XInput from \"xinput-ffi\";\n\nconst capabilities = await XInput.getCapabilities({translate: true});\nconsole.log(capabilities);\n/* Output:\n{\n  type: 'XINPUT_DEVTYPE_GAMEPAD',\n  subType: 'XINPUT_DEVSUBTYPE_GAMEPAD',\n  flags: [ 'XINPUT_CAPS_VOICE_SUPPORTED', 'XINPUT_CAPS_PMD_SUPPORTED' ],\n  gamepad: {\n    wButtons: [\n      'XINPUT_GAMEPAD_DPAD_UP',\n      'XINPUT_GAMEPAD_DPAD_DOWN',\n      //etc...\n    ],\n    bLeftTrigger: 255,\n    bRightTrigger: 255,\n    sThumbLX: -64,\n    sThumbLY: -64,\n    sThumbRX: -64,\n    sThumbRY: -64\n  },\n  vibration: { wLeftMotorSpeed: 255, wRightMotorSpeed: 255 }\n}\n*/\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\"Hidden\" XInput function\u003c/summary\u003e\n  \n```js\nimport * as XInput from \"xinput-ffi\";\n\nconst state = await XInput.getStateEx();\nconsole.log(state);\n/*Output:\n{\n  dwPacketNumber: 6510,\n  gamepad: {\n    wButtons: [ 'XINPUT_GAMEPAD_GUIDE' ],\n    bLeftTrigger: 0,\n    bRightTrigger: 0,\n    sThumbLX: -1024,\n    sThumbLY: 767,\n    sThumbRX: 257,\n    sThumbRY: 767\n  }\n}\n*/\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eMiscellaneous\u003c/summary\u003e\n  \n```js \nimport * as XInput from \"xinput-ffi\";\n\n//Check connected status for all controller\nconsole.log(await XInput.listConnected());\n// [true,false,false,false] Only 1st gamepad is connected\n  \n//Identify connected XInput devices\nconsole.log (await XInput.identify({XInputOnly: true})); \n/* Output:\n  [\n    {\n      name: 'Xbox360 Controller',\n      manufacturer: 'Microsoft Corp.',\n      vendorID: 1118,\n      productID: 654,\n      xinput: true,\n      interfaces: [ 'USB', 'HID' ],\n      guid: [\n        '{745a17a0-74d3-11d0-b6fe-00a0c90f57da}',\n        '{d61ca365-5af4-4486-998b-9db4734c6ca3}'\n      ]\n    }\n  ]\n*/\n```\n\n\u003c/details\u003e\n\n### Electron\n\n\u003cdetails\u003e\n  \u003csummary\u003eSimple XInput menu navigation\u003c/summary\u003e\n  \nHere is an example of a simple XInput menu navigation system using the high level XInput implementation found in this module (helper).\n\n+ main process\n\n```js\n\nlet gamepad;\n\nmainWin.once(\"ready-to-show\", async() =\u003e { \n\n  const { XInputGamepad } = await import(\"xinput-ffi\");\n  gamepad = new XInputGamepad();\n  \n  //send input to renderer\n  gamepad.on(\"input\", (buttons)=\u003e{ \n    setImmediate(() =\u003e {\n      mainWin.webContents.send(\"onGamepadInput\", buttons); \n    });\n  });\n  \n  gamepad.poll(); //gamepad event loop\n  mainWin.show();\n  mainWin.focus();\n  \n});\n\n//gain/loose focus\nmainWin.on(\"blur\", () =\u003e {\n  gamepad?.pause();\n});\nmainWin.on(\"focus\", () =\u003e {\n  gamepad?.resume();\n});\n\n//clean up\nmainWin.on(\"close\", () =\u003e {\n  gamepad?.stop();\n  gamepad = null; //deref\n});\n\nmainWin.on(\"closed\", () =\u003e {\n  mainWin = null; //deref\n});\n\nmainWin.loadFile(path/to/file);\n```\n\n+  contextBridge (preload)\n\n```js\ncontextBridge.exposeInMainWorld(\"ipcRenderer\", {\n  onGamepadInput: (callback) =\u003e ipcRenderer.on(\"onGamepadInput\", callback)\n});\n```\n\n+ renderer\n\n```js\nwindow.ipcRenderer.onGamepadInput((event, input) =\u003e {\n    switch(input[0]){\n      case \"XINPUT_GAMEPAD_DPAD_UP\":\n        //do something\n        break;\n      default:\n        console.log(input);\n    }\n  });\n```\n\n\u003c/details\u003e\n\nInstallation\n============\n\n```\nnpm install xinput-ffi\n```\n\nAPI\n===\n\n⚠️ This module is only available as an ECMAScript module (ESM) starting with version 2.0.0.\u003cbr /\u003e\nPrevious version(s) are CommonJS (CJS) with an ESM wrapper.\n\n## Named export\n\nSummary:\n\n- [constants](#const-constants--object)\n- [XInput function](#xinput-function)\n- [Helper functions](#helper-functions)\n- [Identify device | VID/PID](#identify-device--vidpid)\n- [High level implementation of XInput](#high-level-implementation-of-xinput)\n\n### `const constants = object`\n\n  XInput controller constants for convenience.\n  \n```js  \n  import { constants } from \"xinput-ffi\";\n  console.log(constants.XUSER_MAX_COUNT); //4\n```\n  \n💡 Also available under its own namespace.\n  \n```js\n  import { XUSER_MAX_COUNT } from \"xinput-ffi/constants\";\n  console.log(XUSER_MAX_COUNT); //4\n```\n\n### XInput function\n\n📖 [Microsoft documentation](https://docs.microsoft.com/en-us/windows/win32/xinput/functions)\n\n- ✔️ [XInputEnable](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputenable)\n- ❌ [XInputGetAudioDeviceIds]() _\u003e deprecated: doesn't work on modern Windows system._\n- ✔️ [XInputGetBatteryInformation](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputgetbatteryinformation)\n- ✔️ [XInputGetCapabilities](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputgetcapabilities) \n- ❌ [XInputGetDSoundAudioDeviceGuids]() _\u003e deprecated: doesn't work on modern Windows system._\n- ✔️ [XInputGetKeystroke](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputgetkeystroke)\n- ✔️ [XInputGetState](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputgetstate)\n- ✔️ [XInputSetState](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputsetstate)\n\n\"Hidden\" and undocumented functions\u003cbr/\u003e\n📖 [Reverse Engineer's log](https://reverseengineerlog.blogspot.com/2016/06/xinputs-hidden-functions.html)\n\n- ✔️ XInputGetStateEx\n- ✔️ XInputWaitForGuideButton\n- ✔️ XInputCancelGuideButtonWait\n- ✔️ XInputPowerOffController\n- ⚠️ XInputGetBaseBusInformation _\u003e Not working with all gamepad._\n- ✔️ XInputGetCapabilitiesEx\n\nNB: Depending on which XInput dll version you are using *(1_4, 1_3, 9_1_0)* some functions won't be available.\n\n#### `enable(enable: boolean): Promise\u003cvoid\u003e`\n\nEnable/Disable all XInput gamepads.\u003cbr/\u003e\nThis function is meant to be called when an application gains or loses focus.\n\nNB:\n - Stop any rumble currently playing when set to false.\n - This may trigger `ERR_DEVICE_NOT_CONNECTED` for set/getState(Ex) when set to false and there was no prior input ever.\n \n📖 [XInputEnable](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputenable)\n \n#### `getBatteryInformation(option?: number | object): Promise\u003cobject\u003e`\n\nRetrieves the battery type and charge status of a wireless controller.\n\n⚙️ options:\n\n- dwUserIndex?: number (0)\n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n- devType?: number (0)\n\nSpecifies which device associated with this controller should be queried.\u003cbr/\u003e\n0: GAMEPAD or 1: HEADSET\n\n- translate?: boolean (true)\n\nWhen a value is known it will be 'translated' to its string equivalent value otherwise its integer value.\u003cbr/\u003e\nIf you want the raw data only set it to false.\n\n💡 If `option` is a number it will be used as dwUserIndex.\u003cbr/\u003e\n\nReturns an object like a 📖 [XINPUT_BATTERY_INFORMATION](https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_battery_information) structure.\n\nExample\n```js\nawait getBatteryInformation();\nawait getBatteryInformation(0);\nawait getBatteryInformation({dwUserIndex: 0});\n//output\n{\n  batteryType: 'BATTERY_TYPE_WIRED',\n  batteryLevel: 'BATTERY_LEVEL_FULL'\n}\n```\n\nIf you want raw data output\n```js\nawait getBatteryInformation({translate: false});\n//output\n{\n  batteryType: 1,\n  batteryLevel: 3\n}\n```\n\n📖 [XInputGetBatteryInformation](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputgetbatteryinformation)\n\n#### `getCapabilities(option?: number | object): Promise\u003cobject\u003e`\n\nRetrieves the capabilities and features of the specified controller.\n\n⚙️ options:\n\n- dwUserIndex?: number (0)\n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n- dwFlags?: number (1)\n\nInput flags that identify the controller type. \u003cbr/\u003e\nIf this value is 0, then the capabilities of all controllers connected to the system are returned.\u003cbr/\u003e\nCurrently, only 1: XINPUT_FLAG_GAMEPAD is supported.\n\n- translate?: boolean (true)\n\nWhen a value is known it will be 'translated' to its string equivalent value otherwise its integer value.\u003cbr/\u003e\nIf you want the raw data only set it to false.\n\n💡 If `option` is a number it will be used as dwUserIndex.\u003cbr/\u003e\n\nReturns an object like a 📖 [XINPUT_CAPABILITIES](https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_capabilities) structure.\n\nExample\n```js\nawait getCapabilities();\nawait getCapabilities(0);\nawait getCapabilities({dwUserIndex: 0});\n//Output\n{\n  type: 'XINPUT_DEVTYPE_GAMEPAD',\n  subType: 'XINPUT_DEVSUBTYPE_GAMEPAD',\n  flags: [ 'XINPUT_CAPS_VOICE_SUPPORTED', 'XINPUT_CAPS_PMD_SUPPORTED' ],\n  gamepad: {\n    wButtons: [\n      'XINPUT_GAMEPAD_DPAD_UP',\n      'XINPUT_GAMEPAD_DPAD_DOWN',\n      'XINPUT_GAMEPAD_DPAD_LEFT',\n      'XINPUT_GAMEPAD_DPAD_RIGHT',\n      'XINPUT_GAMEPAD_START',\n      'XINPUT_GAMEPAD_BACK',\n      'XINPUT_GAMEPAD_LEFT_THUMB',\n      'XINPUT_GAMEPAD_RIGHT_THUMB',\n      'XINPUT_GAMEPAD_LEFT_SHOULDER',\n      'XINPUT_GAMEPAD_RIGHT_SHOULDER',\n      'XINPUT_GAMEPAD_A',\n      'XINPUT_GAMEPAD_B',\n      'XINPUT_GAMEPAD_X',\n      'XINPUT_GAMEPAD_Y'\n    ],\n    bLeftTrigger: 255,\n    bRightTrigger: 255,\n    sThumbLX: -64,\n    sThumbLY: -64,\n    sThumbRX: -64,\n    sThumbRY: -64\n  },\n  vibration: { wLeftMotorSpeed: 255, wRightMotorSpeed: 255 }\n}\n```\n\nIf you want raw data output\n```js\nawait getCapabilities({translate: false});\n//output\n{\n  type: 1,\n  subType: 1,\n  flags: 12,\n  gamepad: {\n    wButtons: 65535,\n    bLeftTrigger: 255,\n    bRightTrigger: 255,\n    sThumbLX: -64,\n    sThumbLY: -64,\n    sThumbRX: -64,\n    sThumbRY: -64\n  },\n  vibration: { wLeftMotorSpeed: 255, wRightMotorSpeed: 255 }\n}\n```\n\n📖 [XInputGetCapabilities](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputgetcapabilities)\n\n#### `getKeystroke(option?: number | object): Promise\u003cobject\u003e`\n\nRetrieves a gamepad input event.\u003cbr/\u003e\nTo be honest, this isn't really useful since the chatpad feature wasn't implemented on Windows.\u003cbr/\u003e\n⚠️ NB: If no new keys have been pressed, this will throw with ERROR_EMPTY.\n\n⚙️ options:\n\n- dwUserIndex?: number (0)\n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n- translate?: boolean (true)\n\nWhen a value is known it will be 'translated' to its string equivalent value otherwise its integer value.\u003cbr/\u003e\nIf you want the raw data only set it to false.\n\n💡 If `option` is a number it will be used as dwUserIndex.\u003cbr/\u003e\n\nReturns an object like a 📖 [XINPUT_KEYSTROKE](https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_keystroke) structure.\n\nExample\n```js\nawait getKeystroke();\nawait getKeystroke(0);\nawait getKeystroke({dwUserIndex: 0});\n//Output\n{\n  virtualKey: 'VK_PAD_A',\n  unicode: 0,\n  flags: [ 'XINPUT_KEYSTROKE_KEYDOWN' ],\n  userIndex: 0,\n  hidCode: 0\n}\n```\n\nIf you want raw data output\n```js\nawait getKeystroke({translate: false});\n//output\n{ \n  virtualKey: 22528, \n  unicode: 0, \n  flags: 1, \n  userIndex: 0, \n  hidCode: 0 \n}\n```\n\n📖 [XInputGetKeystroke](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputgetkeystroke)\n\n#### `getState(option?: number | object): Promise\u003cobject\u003e`\n\nRetrieves the current state of the specified controller.\n\n⚙️ options:\n\n- dwUserIndex?: number (0)\n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n- translate?: boolean (true)\n\nWhen a value is known it will be 'translated' to its string equivalent value otherwise its integer value.\u003cbr/\u003e\nIf you want the raw data only set it to false.\n\n💡 If `option` is a number it will be used as dwUserIndex.\u003cbr/\u003e\n\nReturns an object like a 📖 [XINPUT_STATE](https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_state) structure.\n\nExample\n```js\nawait getState();\nawait getState(0);\nawait getState({dwUserIndex: 0});\n//Output\n{\n  dwPacketNumber: 18165,\n  gamepad: { \n    wButtons: ['XINPUT_GAMEPAD_A'],\n    bLeftTrigger: 0,\n    bRightTrigger: 0,\n    sThumbLX: 128,\n    sThumbLY: 641,\n    sThumbRX: -1156,\n    sThumbRY: -129\n  }\n}\n```\n\nIf you want raw data output\n```js\nawait getState({translate: false});\n//output\n{\n  dwPacketNumber: 322850,\n  gamepad: {\n    wButtons: 4096,\n    bLeftTrigger: 0,\n    bRightTrigger: 0,\n    sThumbLX: 257,\n    sThumbLY: 767,\n    sThumbRX: 773,\n    sThumbRY: 1279\n  }\n}\n```\n\n💡 Thumbsticks: as explained by Microsoft you should [implement dead zone correctly](https://docs.microsoft.com/en-us/windows/win32/xinput/getting-started-with-xinput#dead-zone).\u003cbr/\u003e\nThis is done for you in [getButtonsDown()](https://github.com/xan105/node-xinput-ffi#getbuttonsdown-option-object-object)\n\n📖 [XInputGetState](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputgetstate)\n\n#### `setState(lowFrequency: number, highFrequency: number, option ?: number | object): Promise\u003cvoid\u003e`\n\nSends data to a connected controller. This function is used to activate the vibration function of a controller.\n\n⚙️ options:\n\n- dwUserIndex?: number (0)\n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n- usePercent?: boolean (true)\n\n`XInputSetState` valid values are in the range 0 to 65535.\u003cbr /\u003e\nZero signifies no motor use; 65535 signifies 100 percent motor use.\u003cbr /\u003e\n`lowFrequency` and `highFrequency` are in % (0-100) for convenience when you set this to true.\n\n💡 If `option` is a number it will be used as dwUserIndex.\u003cbr/\u003e\n\nNB:\n- You need to keep the event-loop alive otherwise the vibration will terminate with your program.\u003cbr /\u003e\n- You need to reset the state to 0 for both frequency before using setState again.\u003cbr /\u003e\n\nBoth are done for you with [rumble()](https://github.com/xan105/node-xinput-ffi#rumble-option-object-void)\n\n📖 [XInputSetState](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputsetstate)\n\n#### `getStateEx(option?: number | object): Promise\u003cobject\u003e`\n\nThe same as `XInputGetState`, adding the \"Guide\" button (0x0400).\n\n⚙️ options:\n\n- dwUserIndex?: number (0)\n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n- translate?: boolean (true)\n\nWhen a value is known it will be 'translated' to its string equivalent value otherwise its integer value.\u003cbr/\u003e\nIf you want the raw data only set it to false.\n\n💡 If `option` is a number it will be used as dwUserIndex.\u003cbr/\u003e\n\nReturns an object like a 📖 [XINPUT_STATE](https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_state) structure.\n\nExample\n```js\nawait getStateEx();\nawait getStateEx(0);\nawait getStateEx({dwUserIndex: 0});\n//Output\n{\n  dwPacketNumber: 18165,\n  gamepad: { \n    wButtons: ['XINPUT_GAMEPAD_GUIDE'],\n    bLeftTrigger: 0,\n    bRightTrigger: 0,\n    sThumbLX: 128,\n    sThumbLY: 641,\n    sThumbRX: -1156,\n    sThumbRY: -129\n  }\n}\n```\n\nIf you want raw data output\n```js\nawait getStateEx({translate: false});\n//output\n{\n  dwPacketNumber: 322850,\n  gamepad: {\n    wButtons: 1024,\n    bLeftTrigger: 0,\n    bRightTrigger: 0,\n    sThumbLX: 257,\n    sThumbLY: 767,\n    sThumbRX: 773,\n    sThumbRY: 1279\n  }\n}\n```\n\n#### `waitForGuideButton(option?: number | object): Promise\u003cvoid\u003e`\n\nWait until Guide button is pressed.\n\n⚙️ options:\n\n- dwUserIndex?: number (0)\n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n- dwFlags?: number (0)\n\nWait behavior:\u003cbr/\u003e\n0: Blocking 1: Async\u003cbr/\u003e\nIt's not clear on how to get the async option to report.\n\n💡 If `option` is a number it will be used as dwUserIndex.\u003cbr/\u003e\n\n#### `cancelGuideButtonWait(option?: number | object): Promise\u003cvoid\u003e`\n\nIf `XInputWaitForGuideButton` was activated in async mode, this will stop it.\n\n⚙️ options:\n\n- dwUserIndex?: number (0)\n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n💡 If `option` is a number it will be used as dwUserIndex.\u003cbr/\u003e\n\n#### `powerOffController(option?: number | object): Promise\u003cvoid\u003e`\n\nPower off a controller.\n\n⚙️ options:\n\n- dwUserIndex?: number (0)\n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n💡 If `option` is a number it will be used as dwUserIndex.\u003cbr/\u003e\n\n#### `getBaseBusInformation(option?: number | object): Promise\u003cobject\u003e`\n\n⚠️ Not working on all gamepads. It can refuse and return `ERROR_DEVICE_NOT_CONNECTED`, even if connected.\n\n⚙️ options:\n\n- dwBusIndex?: number (0)\n\nBus index. Can be a value from 0 to 16.\n\n💡 If `option` is a number it will be used as dwBusIndex?.\u003cbr/\u003e\n\nReturns an object like the following structure:\n```c++\nstruct XINPUT_BASE_BUS_INFORMATION\n{\n  WORD VendorId, //unknown\n  WORD ProductId, //unknown\n  WORD InputId, //unknown\n  WORD Field_6, //unknown\n  DWORD Field_8, //unknown\n  BYTE Field_C, //unknown\n  BYTE Field_D, //unknown\n  BYTE Field_E, //unknown\n  BYTE Field_F //unknown\n }\n```\n\n#### `getCapabilitiesEx(option?: number | object): Promise\u003cobject\u003e`\n\nThe same as `XInputGetCapabilities` but with added properties such as vendorID and productID.\n\n⚙️ options:\n\n- dwUserIndex?: number (0)\n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n- translate?: boolean (true)\n\nWhen a value is known it will be 'translated' to its string equivalent value otherwise its integer value.\u003cbr/\u003e\nIf you want the raw data only set it to false.\n\n💡 If `option` is a number it will be used as dwUserIndex.\u003cbr/\u003e\n\nReturns an object similar to 📖 [XINPUT_CAPABILITIES](https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_capabilities) structure.\u003cbr/\u003e\nSee below for details.\n\nExample\n```js\nawait getCapabilitiesEx();\nawait getCapabilitiesEx(0);\nawait getCapabilitiesEx({dwUserIndex: 0});\n//Output\n{\n  capabilities: {\n    type: 'XINPUT_DEVTYPE_GAMEPAD',\n    dubType: 'XINPUT_DEVSUBTYPE_GAMEPAD',\n    flags: [ 'XINPUT_CAPS_VOICE_SUPPORTED', 'XINPUT_CAPS_PMD_SUPPORTED' ],\n    gamepad: {\n      wButtons: [\n        'XINPUT_GAMEPAD_DPAD_UP',\n        'XINPUT_GAMEPAD_DPAD_DOWN',\n        'XINPUT_GAMEPAD_DPAD_LEFT',\n        'XINPUT_GAMEPAD_DPAD_RIGHT',\n        'XINPUT_GAMEPAD_START',\n        'XINPUT_GAMEPAD_BACK',\n        'XINPUT_GAMEPAD_LEFT_THUMB',\n        'XINPUT_GAMEPAD_RIGHT_THUMB',\n        'XINPUT_GAMEPAD_LEFT_SHOULDER',\n        'XINPUT_GAMEPAD_RIGHT_SHOULDER',\n        'XINPUT_GAMEPAD_A',\n        'XINPUT_GAMEPAD_B',\n        'XINPUT_GAMEPAD_X',\n        'XINPUT_GAMEPAD_Y'\n      ],\n      bLeftTrigger: 255,\n      bRightTrigger: 255,\n      sThumbLX: -64,\n      sThumbLY: -64,\n      sThumbRX: -64,\n      sThumbRY: -64\n    },\n    vibration: { wLeftMotorSpeed: 255, wRightMotorSpeed: 255 }\n  },\n  vendorId: 'Microsoft Corp.',\n  productId: 'Xbox360 Controller',\n  productVersion: 276,\n}\n```\n\nIf you want raw data output\n```js\nawait getCapabilitiesEx({translate: false});\n//output\n{\n  capabilities: {\n    type: 1,\n    dubType: 1,\n    flags: 12,\n    gamepad: {\n      wButtons: 62463,\n      bLeftTrigger: 255,\n      bRightTrigger: 255,\n      sThumbLX: -64,\n      sThumbLY: -64,\n      sThumbRX: -64,\n      sThumbRY: -64\n    },\n    vibration: { \n      wLeftMotorSpeed: 255, \n      wRightMotorSpeed: 255 \n    }\n  },\n  vendorId: 1118,\n  productId: 654,\n  productVersion: 276,\n}\n```\n\n\u003c/details\u003e\n\n### Helper functions\n\nThe following are sugar/helper functions based upon the previous XInput functions.\n\n#### `isConnected(gamepad?: number): Promise\u003cboolean\u003e`\n\nWhether the specified controller is connected or not.\u003cbr /\u003e\nReturns true/false.\n\n#### `listConnected(): Promise\u003cboolean[]\u003e`\n\nReturns an array of connected status for all controller.\u003cbr /\u003e\neg: [true,false,false,false] =\u003e Only 1st gamepad is connected\n\n#### `getButtonsDown(option?: object): Promise\u003cobject\u003e`\n\nNormalize `getState()/getStateEx()` information for convenience:\u003cbr/\u003e \nThumbStick position, magnitude, direction (taking the deadzone into account).\u003cbr/\u003e \nTrigger state and force (taking threshold into account).\u003cbr/\u003e\nWhich buttons are pressed if any.\u003cbr/\u003e\n\n⚙️ options:\n\n- gamepad?: number (0) \n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n- deadzone?: number | number[] ( [7849,8689] )\n\nThumbstick deadzone(s):\u003cbr/\u003e\nEither an integer (both thumbstick with the same value) or an array of 2 integer: [left,right]\u003cbr/\u003e\n      \n- directionThreshold?: number (0.2)\n\nfloat [0.0,1.0] to handle cardinal direction.\u003cbr/\u003e\nSet it to `0` so `direction[]` only reports \"UP RIGHT\", \"UP LEFT\", \"DOWN LEFT\", \"DOWN RIGHT\".\u003cbr/\u003e\nOtherwise \"RIGHT\", \"LEFT\", \"UP\", \"DOWN\" will be added to the above using threshold to \u003cbr/\u003e\ndifferentiate the 2 axes by using range of [-threshold,threshold].\n\n💡 If you **just** want \"RIGHT\", \"LEFT\", \"UP\" and \"DOWN\" the easiest way is to set this to `0.8` with the default deadzone.\u003cbr/\u003e\nAlternatively play with this value and/or deadzone to decide on a thresold and ignore when `direction[]` has a length of 2.\n          \n- triggerThreshold?: number (30)\n\nTrigger activation threshold. Range [0,255].\n\n=\u003e Returns an object where:\n- int packetNumber : dwPacketNumber; This value is increased every time the state of the controller has changed.\n- []string buttons : list of currently pressed [buttons](https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_gamepad#members)\n- trigger.left/right :\n  + boolean active : is the trigger pressed down ? (below triggerThreshold will not set active to true)\n  + int force : by how much ? [0,255]\n- thumb.left/right :\n  + float x: normalized (deadzone) x axis [0.0,1.0]. 0 is centered. Negative values is left. Positive values is right.\n  + float y: normalized (deadzone) y axis [0.0,1.0]. 0 is centered. Negative values is down. Positive values is up.\n  + float magnitude: normalized (deadzone) magnitude [0.0,1.0] (by how far is the thumbstick from the center ? 1 is fully pushed).\n  + []string direction: Human readable direction of the thumbstick. eg: [\"UP\", \"RIGHT\"]. See directionThreshold above for details.\n\n```js\n{\n  packetNumber: 132309,\n  buttons: [ 'XINPUT_GAMEPAD_A' ],\n  trigger: {\n    left: { active: true, force: 255 },\n    right: { active: false, force: 0 }\n  },\n  thumb: {\n    left: {\n      x: -0.6960457056589758,\n      y: 0.717997476063599,\n      magnitude: 1,\n      direction: [ 'UP', 'LEFT' ]\n    },\n    right: {\n      x: 0.039307955814283674,\n      y: 0.9992271436513833,\n      magnitude: 1,\n      direction: [ 'UP' ]\n    }\n  }\n}\n```\n  \n#### `rumble(option?: object): Promise\u003cvoid\u003e`\n\nThis function is used to activate the vibration function of a controller.\u003cbr /\u003e\n\n⚙️ options:\n\n- gamepad?: number (0) \n\nIndex of the user's controller. Can be a value from 0 to 3.\n\n- force?: number | number[] ([50,25])\n\nVibration force in % (0-100) to apply to the motors.\u003cbr/\u003e\nEither an integer (both motor with the same value) or an array of 2 integer: [left,right]\n\n- duration?: number (2500)\n\nVibration duration in ms. Max: ~2500 ms.\n\n- forceEnableGamepad?: boolean (false)\n\nUse `enable()` to force the activation of XInput gamepad before vibration.\n \n- forceStateWhileRumble?: boolean (false)\n\nBruteforce _-ly_ (spam) `setState()` for the duration of the vibration. Use this when a 3rd party reset your state or whatever.\u003cbr/\u003e \n⚠️ Usage of this option is not recommended use only when needed.\n\n### Identify device | VID/PID\n\nXInput doesn't provide VID/PID **by design**.\u003cbr /\u003e\nEven if with `XInputGetCapabilitiesEx` you can get the vendorID and productID, it will most likely be a Xbox Controller (real one or through XInput emulation).\u003cbr /\u003e\n\nUse `identify()` (see below) to query `WMI _Win32_PNPEntity` to scan for known gamepads.\u003cbr /\u003e\nIt won't tell you which is connected to which XInput slot tho.\n\n#### `identify(option?: object): Promise\u003cobject[]\u003e`\n\n⚠️ Requires PowerShell.\n\nList all **known** HID and USB connected devices **by matching with entries in** `./lib/util/HardwareID.js`\n\n⚙️ options:\n\n- XInputOnly?: boolean (true)\n\nReturn only XInput gamepad.\n\n=\u003e Return an array of object where\n- string name : device name\n- string manufacturer : vendor name\n- number vendorID : vendor id\n- number productID : product id\n- string[] interfaces : PNPentity interface(s) found; Available: HID and USB\n- string[] guid: classguid(s) found\n- boolean xinput: a XInput device or not\n\n💡 object are unique by their vid/pid\n\nOutput example with a DS4(wireless) and ds4windows(XInput wrapper):\n```js\nimport { identify } from \"xinput-ffi\";\nawait identify();\n//Output\n[\n  {\n    name: 'DualShock 4 (v2)',\n    manufacturer: 'Sony Corp.',\n    vendorID: 1356,\n    productID: 2508,\n    xinput: false,\n    interfaces: [ 'USB', 'HID' ],\n    guid: [\n      '{36fc9e60-c465-11cf-8056-444553540000}',\n      '{745a17a0-74d3-11d0-b6fe-00a0c90f57da}',\n      '{4d36e96c-e325-11ce-bfc1-08002be10318}'\n    ]\n  },\n  {\n    name: 'DualShock 4 USB Wireless Adaptor',\n    manufacturer: 'Sony Corp.',\n    vendorID: 1356,\n    productID: 2976,\n    xinput: false,\n    interfaces: [ 'USB', 'HID' ],\n    guid: [\n      '{745a17a0-74d3-11d0-b6fe-00a0c90f57da}',\n      '{36fc9e60-c465-11cf-8056-444553540000}',\n      '{4d36e96c-e325-11ce-bfc1-08002be10318}'\n    ]\n  },\n  {\n    name: 'Xbox360 Controller',\n    manufacturer: 'Microsoft Corp.',\n    vendorID: 1118,\n    productID: 654,\n    xinput: true,\n    interfaces: [ 'USB', 'HID' ],\n    guid: [\n      '{745a17a0-74d3-11d0-b6fe-00a0c90f57da}',\n      '{d61ca365-5af4-4486-998b-9db4734c6ca3}'\n    ]\n  }\n]\n```\n\n### High level implementation of XInput\n\nThis is a high level implementation of XInput to get the gamepad's input on the fly in a human readable way.\nThis serves as an example to demonstrate how to use the XInput functions and helpers based around them.\nThe purpose of this class is to drive a simple navigation menu system with a XInput compatible controller (real XInput or through XInput emulation).\n\nThis leverages the new Node.js timersPromises setInterval() to keep the event loop alive and do the gamepad polling.\n\n#### `XInputGamepad(option: object): Class`\n\n\u003e This class extends EventEmitter from node:events\n\n**Options**\n\n- hz?: number (30)\n\n  This will determinate the polling rate. Usually 60hz (1000/60 = ~16ms) is used. If I'm not mistaken this is what the Chrome browser uses. But for our use case we don't need to poll that fast so it defaults to 30hz (~33ms). Increasing this value improves latency, but may cause a loss in performance due to more CPU time spent. The max accepted is 250hz (4ms).\n\n- multitap?: boolean (true)\n\n  Scan for all 4 XInput slots to find any Gamepad. Set to false to only poll XInput slot 0 and potentially reduce the number of FFI calls per gamepad tick (event loop).\n\n- joystickAsDPAD?: boolean (true)\n\n  Convert the left joystick analog axis to DPAD buttons. For our use case, driving a simple navigation menu, this is useful.\n\n- inputFeedback?: boolean (false)\n  \n  Vibrate shortly and lightly on any button activation. This is just for fun and/or debug.\n\n**Events**\n\n`input(buttons: string[])`\n\nList of activated buttons (human readable) of the first controller found.\u003cbr /\u003e\nA button is \"activated\" on press (button down) then release (button up).\n\n💡 NB: Triggers axis are converted into non standard XInput button name : `GAMEPAD_LEFT_TRIGGER` and `GAMEPAD_RIGHT_TRIGGER` (_on/off behavior_).\n\n\u003cdetails\u003e\u003csummary\u003eXInput Button names:\u003c/summary\u003e\n\n```\n\"XINPUT_GAMEPAD_DPAD_UP\",\n\"XINPUT_GAMEPAD_DPAD_DOWN\",\n\"XINPUT_GAMEPAD_DPAD_LEFT\",\n\"XINPUT_GAMEPAD_DPAD_RIGHT\",\n\"XINPUT_GAMEPAD_START\",\n\"XINPUT_GAMEPAD_BACK\",\n\"XINPUT_GAMEPAD_LEFT_THUMB\",\n\"XINPUT_GAMEPAD_RIGHT_THUMB\",\n\"XINPUT_GAMEPAD_LEFT_SHOULDER\",\n\"XINPUT_GAMEPAD_RIGHT_SHOULDER\",\n\"XINPUT_GAMEPAD_GUIDE\",\n\"XINPUT_GAMEPAD_A\",\n\"XINPUT_GAMEPAD_B\",\n\"XINPUT_GAMEPAD_X\",\n\"XINPUT_GAMEPAD_Y\"\n```\n\n💡 NB: XInput constants are available under the `constants` namespace.\n\n```js\nimport { BUTTONS } from \"xinput-ffi/constants\";\n//or\nimport { constants } from \"xinput-ffi\"\n```\n\n\u003c/details\u003e\n\nExample:\n\n```js\nimport { XInputGamepad } from \"xinput-ffi\";\n\nconst gamepad = new XInputGamepad({ hz: 60 });\n\ngamepad.on(\"input\", (buttons)=\u003e{ \n  setImmediate(() =\u003e {\n    console.log(buttons);\n  });\n});\n\ngamepad.poll();\n```\n  \n**Methods**\n\n##### `poll()`\n\nStart the gamepad event loop. This will keep the Node.js event loop going.\n\n❌ Will throw on unexpected error.\n\n##### `stop()`\n\nStop the gamepad event loop.\n\nNB: This method will remove every event listener.\n\n##### `pause()`\n\nThis function is meant to be called when an application loses focus.\n\n_cf: [XInputEnable](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputenable)_\n\n##### `resume()`\n\nThis function is meant to be called when an application gains focus.\n\n_cf: [XInputEnable](https://docs.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputenable)_\n\n#### `vibrate(option: object): Promise\u003cvoid\u003e`\n\nVibrate the first controller found. Shorthand to the helper fn `rumble()`.\n\n💡 Expose only `force` and `duration` options of `rumble()`.\n\n❌ Will throw on error other than `ERROR_DEVICE_NOT_CONNECTED`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxan105%2Fnode-xinput-ffi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxan105%2Fnode-xinput-ffi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxan105%2Fnode-xinput-ffi/lists"}