home
products
contribute
download
documentation
forum
Home
Forums
New posts
Search forums
What's new
New posts
All posts
Latest activity
Members
Registered members
Current visitors
Donate
Log in
Register
What's new
Search
Search
Search titles only
By:
New posts
Search forums
Search titles only
By:
Menu
Log in
Register
Navigation
Install the app
Install
More options
Contact us
Close Menu
Forums
MediaPortal 1
Support
General Support
How use HID compatible gamepad in mediaportal
Contact us
RSS
JavaScript is disabled. For a better experience, please enable JavaScript in your browser before proceeding.
You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an
alternative browser
.
Reply to thread
Message
<blockquote data-quote="Stéphane Lenclud" data-source="post: 1124692" data-attributes="member: 140174"><p>Note for future implementation of proper gamepad support see example there:</p><p><a href="https://dxr.mozilla.org/mozilla-central/source/hal/windows/WindowsGamepad.cpp" target="_blank">https://dxr.mozilla.org/mozilla-central/source/hal/windows/WindowsGamepad.cpp</a></p><p>Now moved to:</p><p><a href="https://dxr.mozilla.org/mozilla-central/source/dom/gamepad/windows/WindowsGamepad.cpp" target="_blank">https://dxr.mozilla.org/mozilla-central/source/dom/gamepad/windows/WindowsGamepad.cpp</a></p><p></p><p>Google search: <a href="https://www.google.de/search?q=HID+gamepad+handling+direction+pad" target="_blank">https://www.google.de/search?q=HID+gamepad+handling+direction+pad</a></p><p></p><p>Here is a copy of the code linked above</p><p>[SPOILER="See Code"]</p><p>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */</p><p>/* This Source Code Form is subject to the terms of the Mozilla Public</p><p>* License, v. 2.0. If a copy of the MPL was not distributed with this</p><p>* file, You can obtain one at <a href="http://mozilla.org/MPL/2.0/" target="_blank">http://mozilla.org/MPL/2.0/</a>. */</p><p>#include <algorithm></p><p>#include <cstddef></p><p>#ifndef UNICODE</p><p>#define UNICODE</p><p>#endif</p><p>#include <windows.h></p><p>#include <hidsdi.h></p><p>#include <stdio.h></p><p>#include <xinput.h></p><p>#include "nsIComponentManager.h"</p><p>#include "nsIObserver.h"</p><p>#include "nsIObserverService.h"</p><p>#include "nsITimer.h"</p><p>#include "nsTArray.h"</p><p>#include "mozilla/ArrayUtils.h"</p><p>#include "mozilla/dom/GamepadService.h"</p><p>#include "mozilla/Services.h"</p><p>namespace {</p><p>using namespace mozilla::dom;</p><p>using mozilla::ArrayLength;</p><p>// USB HID usage tables, page 1 (Hat switch)</p><p>const unsigned kUsageDpad = 0x39;</p><p>// USB HID usage tables, page 1, 0x30 = X</p><p>const unsigned kFirstAxis = 0x30;</p><p>// USB HID usage tables</p><p>const unsigned kDesktopUsagePage = 0x1;</p><p>const unsigned kButtonUsagePage = 0x9;</p><p>// Arbitrary. In practice 10 buttons/6 axes is the near maximum.</p><p>const unsigned kMaxButtons = 32;</p><p>const unsigned kMaxAxes = 32;</p><p>// Multiple devices-changed notifications can be sent when a device</p><p>// is connected, because USB devices consist of multiple logical devices.</p><p>// Therefore, we wait a bit after receiving one before looking for</p><p>// device changes.</p><p>const uint32_t kDevicesChangedStableDelay = 200;</p><p>// XInput is a purely polling-driven API, so we need to</p><p>// poll it periodically. 50ms is arbitrarily chosen.</p><p>const uint32_t kXInputPollInterval = 50;</p><p>const UINT kRawInputError = (UINT)-1;</p><p>#ifndef XUSER_MAX_COUNT</p><p>#define XUSER_MAX_COUNT 4</p><p>#endif</p><p>const struct {</p><p>int usagePage;</p><p>int usage;</p><p>} kUsagePages[] = {</p><p>// USB HID usage tables, page 1</p><p>{ kDesktopUsagePage, 4 }, // Joystick</p><p>{ kDesktopUsagePage, 5 } // Gamepad</p><p>};</p><p>const struct {</p><p>WORD button;</p><p>int mapped;</p><p>} kXIButtonMap[] = {</p><p>{ XINPUT_GAMEPAD_DPAD_UP, 12 },</p><p>{ XINPUT_GAMEPAD_DPAD_DOWN, 13 },</p><p>{ XINPUT_GAMEPAD_DPAD_LEFT, 14 },</p><p>{ XINPUT_GAMEPAD_DPAD_RIGHT, 15 },</p><p>{ XINPUT_GAMEPAD_START, 9 },</p><p>{ XINPUT_GAMEPAD_BACK, 8 },</p><p>{ XINPUT_GAMEPAD_LEFT_THUMB, 10 },</p><p>{ XINPUT_GAMEPAD_RIGHT_THUMB, 11 },</p><p>{ XINPUT_GAMEPAD_LEFT_SHOULDER, 4 },</p><p>{ XINPUT_GAMEPAD_RIGHT_SHOULDER, 5 },</p><p>{ XINPUT_GAMEPAD_A, 0 },</p><p>{ XINPUT_GAMEPAD_B, 1 },</p><p>{ XINPUT_GAMEPAD_X, 2 },</p><p>{ XINPUT_GAMEPAD_Y, 3 }</p><p>};</p><p>const size_t kNumMappings = ArrayLength(kXIButtonMap);</p><p>enum GamepadType {</p><p>kNoGamepad = 0,</p><p>kRawInputGamepad,</p><p>kXInputGamepad</p><p>};</p><p>class WindowsGamepadService;</p><p>WindowsGamepadService* gService = nullptr;</p><p>struct Gamepad {</p><p>GamepadType type;</p><p>// Handle to raw input device</p><p>HANDLE handle;</p><p>// XInput Index of the user's controller. Passed to XInputGetState.</p><p>DWORD userIndex;</p><p>// Last-known state of the controller.</p><p>XINPUT_STATE state;</p><p>// ID from the GamepadService, also used as the index into</p><p>// WindowsGamepadService::mGamepads.</p><p>int id;</p><p>// Information about the physical device.</p><p>unsigned numAxes;</p><p>unsigned numButtons;</p><p>bool hasDpad;</p><p>HIDP_VALUE_CAPS dpadCaps;</p><p>bool buttons[kMaxButtons];</p><p>struct {</p><p>HIDP_VALUE_CAPS caps;</p><p>double value;</p><p>} axes[kMaxAxes];</p><p>// Used during rescan to find devices that were disconnected.</p><p>bool present;</p><p>};</p><p>// Drop this in favor of decltype when we require a new enough SDK.</p><p>typedef void (WINAPI *XInputEnable_func)(BOOL);</p><p>// RAII class to wrap loading the XInput DLL</p><p>class XInputLoader {</p><p>public:</p><p>XInputLoader() : module(nullptr),</p><p>mXInputEnable(nullptr),</p><p>mXInputGetState(nullptr) {</p><p>// xinput1_4.dll exists on Windows 8</p><p>// xinput9_1_0.dll exists on Windows 7 and Vista</p><p>// xinput1_3.dll shipped with the DirectX SDK</p><p>const wchar_t* dlls[] = {L"xinput1_4.dll",</p><p>L"xinput9_1_0.dll",</p><p>L"xinput1_3.dll"};</p><p>const size_t kNumDLLs = ArrayLength(dlls);</p><p>for (size_t i = 0; i < kNumDLLs; ++i) {</p><p>module = LoadLibraryW(dlls<em>);</em></p><p><em>if (module) {</em></p><p><em>mXInputEnable = reinterpret_cast<XInputEnable_func>(</em></p><p><em>GetProcAddress(module, "XInputEnable"));</em></p><p><em>mXInputGetState = reinterpret_cast<decltype(XInputGetState)*>(</em></p><p><em>GetProcAddress(module, "XInputGetState"));</em></p><p><em>if (mXInputEnable) {</em></p><p><em>mXInputEnable(TRUE);</em></p><p><em>}</em></p><p><em>break;</em></p><p><em>}</em></p><p><em>}</em></p><p><em>}</em></p><p><em>~XInputLoader() {</em></p><p><em>//mXInputEnable = nullptr;</em></p><p><em>mXInputGetState = nullptr;</em></p><p><em>if (module) {</em></p><p><em>FreeLibrary(module);</em></p><p><em>}</em></p><p><em>}</em></p><p><em>operator bool() {</em></p><p><em>return module && mXInputGetState;</em></p><p><em>}</em></p><p><em>HMODULE module;</em></p><p><em>decltype(XInputGetState) *mXInputGetState;</em></p><p><em>XInputEnable_func mXInputEnable;</em></p><p><em>};</em></p><p><em>bool</em></p><p><em>GetPreparsedData(HANDLE handle, nsTArray<uint8_t>& data)</em></p><p><em>{</em></p><p><em>UINT size;</em></p><p><em>if (GetRawInputDeviceInfo(handle, RIDI_PREPARSEDDATA, nullptr, &size) == kRawInputError) {</em></p><p><em>return false;</em></p><p><em>}</em></p><p><em>data.SetLength(size);</em></p><p><em>return GetRawInputDeviceInfo(handle, RIDI_PREPARSEDDATA,</em></p><p><em>data.Elements(), &size) > 0;</em></p><p><em>}</em></p><p><em>/*</em></p><p><em>* Given an axis value and a minimum and maximum range,</em></p><p><em>* scale it to be in the range -1.0 .. 1.0.</em></p><p><em>*/</em></p><p><em>double</em></p><p><em>ScaleAxis(ULONG value, LONG min, LONG max)</em></p><p><em>{</em></p><p><em>return 2.0 * (value - min) / (max - min) - 1.0;</em></p><p><em>}</em></p><p><em>/*</em></p><p><em>* Given a value from a d-pad (POV hat in USB HID terminology),</em></p><p><em>* represent it as 4 buttons, one for each cardinal direction.</em></p><p><em>*/</em></p><p><em>void</em></p><p><em>UnpackDpad(LONG dpad_value, const Gamepad* gamepad, bool buttons[kMaxButtons])</em></p><p><em>{</em></p><p><em>const unsigned kUp = gamepad->numButtons - 4;</em></p><p><em>const unsigned kDown = gamepad->numButtons - 3;</em></p><p><em>const unsigned kLeft = gamepad->numButtons - 2;</em></p><p><em>const unsigned kRight = gamepad->numButtons - 1;</em></p><p><em>// Different controllers have different ways of representing</em></p><p><em>// "nothing is pressed", but they're all outside the range of values.</em></p><p><em>if (dpad_value < gamepad->dpadCaps.LogicalMin</em></p><p><em>|| dpad_value > gamepad->dpadCaps.LogicalMax) {</em></p><p><em>// Nothing is pressed.</em></p><p><em>return;</em></p><p><em>}</em></p><p><em>// Normalize value to start at 0.</em></p><p><em>int value = dpad_value - gamepad->dpadCaps.LogicalMin;</em></p><p><em>// Value will be in the range 0-7. The value represents the</em></p><p><em>// position of the d-pad around a circle, with 0 being straight up,</em></p><p><em>// 2 being right, 4 being straight down, and 6 being left.</em></p><p><em>if (value < 2 || value > 6) {</em></p><p><em>buttons[kUp] = true;</em></p><p><em>}</em></p><p><em>if (value > 2 && value < 6) {</em></p><p><em>buttons[kDown] = true;</em></p><p><em>}</em></p><p><em>if (value > 4) {</em></p><p><em>buttons[kLeft] = true;</em></p><p><em>}</em></p><p><em>if (value > 0 && value < 4) {</em></p><p><em>buttons[kRight] = true;</em></p><p><em>}</em></p><p><em>}</em></p><p><em>/*</em></p><p><em>* Return true if this USB HID usage page and usage are of a type we</em></p><p><em>* know how to handle.</em></p><p><em>*/</em></p><p><em>bool</em></p><p><em>SupportedUsage(USHORT page, USHORT usage)</em></p><p><em>{</em></p><p><em>for (unsigned i = 0; i < ArrayLength(kUsagePages); i++) {</em></p><p><em>if (page == kUsagePages<em>.usagePage && usage == kUsagePages<em>.usage) {</em></em></em></p><p><em><em><em>return true;</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>return false;</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>class Observer : public nsIObserver {</em></em></em></p><p><em><em><em>public:</em></em></em></p><p><em><em><em>NS_DECL_ISUPPORTS</em></em></em></p><p><em><em><em>NS_DECL_NSIOBSERVER</em></em></em></p><p><em><em><em>Observer(WindowsGamepadService& svc) : mSvc(svc),</em></em></em></p><p><em><em><em>mObserving(true)</em></em></em></p><p><em><em><em>{</em></em></em></p><p><em><em><em>nsresult rv;</em></em></em></p><p><em><em><em>mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);</em></em></em></p><p><em><em><em>nsCOMPtr<nsIObserverService> observerService =</em></em></em></p><p><em><em><em>mozilla::services::GetObserverService();</em></em></em></p><p><em><em><em>observerService->AddObserver(this,</em></em></em></p><p><em><em><em>NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID,</em></em></em></p><p><em><em><em>false);</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>void Stop()</em></em></em></p><p><em><em><em>{</em></em></em></p><p><em><em><em>if (mTimer) {</em></em></em></p><p><em><em><em>mTimer->Cancel();</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>if (mObserving) {</em></em></em></p><p><em><em><em>nsCOMPtr<nsIObserverService> observerService =</em></em></em></p><p><em><em><em>mozilla::services::GetObserverService();</em></em></em></p><p><em><em><em>observerService->RemoveObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID);</em></em></em></p><p><em><em><em>mObserving = false;</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>void SetDeviceChangeTimer()</em></em></em></p><p><em><em><em>{</em></em></em></p><p><em><em><em>// Set stable timer, since we will get multiple devices-changed</em></em></em></p><p><em><em><em>// notifications at once</em></em></em></p><p><em><em><em>if (mTimer) {</em></em></em></p><p><em><em><em>mTimer->Cancel();</em></em></em></p><p><em><em><em>mTimer->Init(this, kDevicesChangedStableDelay, nsITimer::TYPE_ONE_SHOT);</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>private:</em></em></em></p><p><em><em><em>virtual ~Observer()</em></em></em></p><p><em><em><em>{</em></em></em></p><p><em><em><em>Stop();</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>// Gamepad service owns us, we just hold a reference back to it.</em></em></em></p><p><em><em><em>WindowsGamepadService& mSvc;</em></em></em></p><p><em><em><em>nsCOMPtr<nsITimer> mTimer;</em></em></em></p><p><em><em><em>bool mObserving;</em></em></em></p><p><em><em><em>};</em></em></em></p><p><em><em><em>NS_IMPL_ISUPPORTS(Observer, nsIObserver);</em></em></em></p><p><em><em><em>class HIDLoader {</em></em></em></p><p><em><em><em>public:</em></em></em></p><p><em><em><em>HIDLoader() : mModule(LoadLibraryW(L"hid.dll")),</em></em></em></p><p><em><em><em>mHidD_GetProductString(nullptr),</em></em></em></p><p><em><em><em>mHidP_GetCaps(nullptr),</em></em></em></p><p><em><em><em>mHidP_GetButtonCaps(nullptr),</em></em></em></p><p><em><em><em>mHidP_GetValueCaps(nullptr),</em></em></em></p><p><em><em><em>mHidP_GetUsages(nullptr),</em></em></em></p><p><em><em><em>mHidP_GetUsageValue(nullptr),</em></em></em></p><p><em><em><em>mHidP_GetScaledUsageValue(nullptr)</em></em></em></p><p><em><em><em>{</em></em></em></p><p><em><em><em>if (mModule) {</em></em></em></p><p><em><em><em>mHidD_GetProductString = reinterpret_cast<decltype(HidD_GetProductString)*>(GetProcAddress(mModule, "HidD_GetProductString"));</em></em></em></p><p><em><em><em>mHidP_GetCaps = reinterpret_cast<decltype(HidP_GetCaps)*>(GetProcAddress(mModule, "HidP_GetCaps"));</em></em></em></p><p><em><em><em>mHidP_GetButtonCaps = reinterpret_cast<decltype(HidP_GetButtonCaps)*>(GetProcAddress(mModule, "HidP_GetButtonCaps"));</em></em></em></p><p><em><em><em>mHidP_GetValueCaps = reinterpret_cast<decltype(HidP_GetValueCaps)*>(GetProcAddress(mModule, "HidP_GetValueCaps"));</em></em></em></p><p><em><em><em>mHidP_GetUsages = reinterpret_cast<decltype(HidP_GetUsages)*>(GetProcAddress(mModule, "HidP_GetUsages"));</em></em></em></p><p><em><em><em>mHidP_GetUsageValue = reinterpret_cast<decltype(HidP_GetUsageValue)*>(GetProcAddress(mModule, "HidP_GetUsageValue"));</em></em></em></p><p><em><em><em>mHidP_GetScaledUsageValue = reinterpret_cast<decltype(HidP_GetScaledUsageValue)*>(GetProcAddress(mModule, "HidP_GetScaledUsageValue"));</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>~HIDLoader() {</em></em></em></p><p><em><em><em>if (mModule) {</em></em></em></p><p><em><em><em>FreeLibrary(mModule);</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>operator bool() {</em></em></em></p><p><em><em><em>return mModule &&</em></em></em></p><p><em><em><em>mHidD_GetProductString &&</em></em></em></p><p><em><em><em>mHidP_GetCaps &&</em></em></em></p><p><em><em><em>mHidP_GetButtonCaps &&</em></em></em></p><p><em><em><em>mHidP_GetValueCaps &&</em></em></em></p><p><em><em><em>mHidP_GetUsages &&</em></em></em></p><p><em><em><em>mHidP_GetUsageValue &&</em></em></em></p><p><em><em><em>mHidP_GetScaledUsageValue;</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>decltype(HidD_GetProductString) *mHidD_GetProductString;</em></em></em></p><p><em><em><em>decltype(HidP_GetCaps) *mHidP_GetCaps;</em></em></em></p><p><em><em><em>decltype(HidP_GetButtonCaps) *mHidP_GetButtonCaps;</em></em></em></p><p><em><em><em>decltype(HidP_GetValueCaps) *mHidP_GetValueCaps;</em></em></em></p><p><em><em><em>decltype(HidP_GetUsages) *mHidP_GetUsages;</em></em></em></p><p><em><em><em>decltype(HidP_GetUsageValue) *mHidP_GetUsageValue;</em></em></em></p><p><em><em><em>decltype(HidP_GetScaledUsageValue) *mHidP_GetScaledUsageValue;</em></em></em></p><p><em><em><em>private:</em></em></em></p><p><em><em><em>HMODULE mModule;</em></em></em></p><p><em><em><em>};</em></em></em></p><p><em><em><em>class WindowsGamepadService {</em></em></em></p><p><em><em><em>public:</em></em></em></p><p><em><em><em>WindowsGamepadService();</em></em></em></p><p><em><em><em>virtual ~WindowsGamepadService()</em></em></em></p><p><em><em><em>{</em></em></em></p><p><em><em><em>Cleanup();</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>enum DeviceChangeType {</em></em></em></p><p><em><em><em>DeviceChangeNotification,</em></em></em></p><p><em><em><em>DeviceChangeStable</em></em></em></p><p><em><em><em>};</em></em></em></p><p><em><em><em>void DevicesChanged(DeviceChangeType type);</em></em></em></p><p><em><em><em>void Startup();</em></em></em></p><p><em><em><em>void Shutdown();</em></em></em></p><p><em><em><em>// Parse gamepad input from a WM_INPUT message.</em></em></em></p><p><em><em><em>bool HandleRawInput(HRAWINPUT handle);</em></em></em></p><p><em><em><em>private:</em></em></em></p><p><em><em><em>void ScanForDevices();</em></em></em></p><p><em><em><em>// Look for connected raw input devices.</em></em></em></p><p><em><em><em>void ScanForRawInputDevices();</em></em></em></p><p><em><em><em>// Look for connected XInput devices.</em></em></em></p><p><em><em><em>bool ScanForXInputDevices();</em></em></em></p><p><em><em><em>bool HaveXInputGamepad(int userIndex);</em></em></em></p><p><em><em><em>// Timer callback for XInput polling</em></em></em></p><p><em><em><em>static void XInputPollTimerCallback(nsITimer* aTimer, void* aClosure);</em></em></em></p><p><em><em><em>void PollXInput();</em></em></em></p><p><em><em><em>void CheckXInputChanges(Gamepad& gamepad, XINPUT_STATE& state);</em></em></em></p><p><em><em><em>// Get information about a raw input gamepad.</em></em></em></p><p><em><em><em>bool GetRawGamepad(HANDLE handle);</em></em></em></p><p><em><em><em>void Cleanup();</em></em></em></p><p><em><em><em>// List of connected devices.</em></em></em></p><p><em><em><em>nsTArray<Gamepad> mGamepads;</em></em></em></p><p><em><em><em>nsRefPtr<Observer> mObserver;</em></em></em></p><p><em><em><em>nsCOMPtr<nsITimer> mXInputPollTimer;</em></em></em></p><p><em><em><em>HIDLoader mHID;</em></em></em></p><p><em><em><em>XInputLoader mXInput;</em></em></em></p><p><em><em><em>};</em></em></em></p><p><em><em><em>WindowsGamepadService::WindowsGamepadService()</em></em></em></p><p><em><em><em>{</em></em></em></p><p><em><em><em>nsresult rv;</em></em></em></p><p><em><em><em>mXInputPollTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);</em></em></em></p><p><em><em><em>mObserver = new Observer(*this);</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>void</em></em></em></p><p><em><em><em>WindowsGamepadService:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite5" alt=":confused:" title="Confused :confused:" loading="lazy" data-shortname=":confused:" />canForRawInputDevices()</em></em></em></p><p><em><em><em>{</em></em></em></p><p><em><em><em>if (!mHID) {</em></em></em></p><p><em><em><em>return;</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>UINT numDevices;</em></em></em></p><p><em><em><em>if (GetRawInputDeviceList(nullptr, &numDevices, sizeof(RAWINPUTDEVICELIST))</em></em></em></p><p><em><em><em>== kRawInputError) {</em></em></em></p><p><em><em><em>return;</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>nsTArray<RAWINPUTDEVICELIST> devices(numDevices);</em></em></em></p><p><em><em><em>devices.SetLength(numDevices);</em></em></em></p><p><em><em><em>if (GetRawInputDeviceList(devices.Elements(), &numDevices,</em></em></em></p><p><em><em><em>sizeof(RAWINPUTDEVICELIST)) == kRawInputError) {</em></em></em></p><p><em><em><em>return;</em></em></em></p><p><em><em><em>}</em></em></em></p><p><em><em><em>for (unsigned i = 0; i < devices.Length(); i++) {</em></em></em></p><p><em><em><em>if (devices<em>.dwType == RIM_TYPEHID) {</em></em></em></em></p><p><em><em><em><em>GetRawGamepad(devices<em>.hDevice);</em></em></em></em></em></p><p><em><em><em><em><em>}</em></em></em></em></em></p><p><em><em><em><em><em>}</em></em></em></em></em></p><p><em><em><em><em><em>}</em></em></em></em></em></p><p><em><em><em><em><em>bool</em></em></em></em></em></p><p><em><em><em><em><em>WindowsGamepadService::HaveXInputGamepad(int userIndex)</em></em></em></em></em></p><p><em><em><em><em><em>{</em></em></em></em></em></p><p><em><em><em><em><em>for (unsigned int i = 0; i < mGamepads.Length(); i++) {</em></em></em></em></em></p><p><em><em><em><em><em>if (mGamepads<em>.type == kXInputGamepad</em></em></em></em></em></em></p><p><em><em><em><em><em><em>&& mGamepads<em>.userIndex == userIndex) {</em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em>mGamepads<em>.present = true;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>return true;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>return false;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>bool</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>WindowsGamepadService:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite5" alt=":confused:" title="Confused :confused:" loading="lazy" data-shortname=":confused:" />canForXInputDevices()</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>MOZ_ASSERT(mXInput, "XInput should be present!");</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService());</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>if (!gamepadsvc) {</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>return false;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>bool found = false;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>for (int i = 0; i < XUSER_MAX_COUNT; i++) {</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>XINPUT_STATE state = {};</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>if (mXInput.mXInputGetState(i, &state) != ERROR_SUCCESS) {</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>continue;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>found = true;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>// See if this device is already present in our list.</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>if (HaveXInputGamepad(i)) {</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>continue;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>// Not already present, add it.</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>Gamepad gamepad = {};</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>gamepad.type = kXInputGamepad;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>gamepad.present = true;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>gamepad.state = state;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>gamepad.userIndex = i;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>gamepad.numButtons = kStandardGamepadButtons;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>gamepad.numAxes = kStandardGamepadAxes;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>gamepad.id = gamepadsvc->AddGamepad("xinput",</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>GamepadMappingType:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite5" alt=":confused:" title="Confused :confused:" loading="lazy" data-shortname=":confused:" />tandard,</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>kStandardGamepadButtons,</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>kStandardGamepadAxes);</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>mGamepads.AppendElement(gamepad);</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>return found;</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>void</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>WindowsGamepadService:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite5" alt=":confused:" title="Confused :confused:" loading="lazy" data-shortname=":confused:" />canForDevices()</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>for (int i = mGamepads.Length() - 1; i >= 0; i--) {</em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em>mGamepads<em>.present = false;</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>if (mHID) {</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>ScanForRawInputDevices();</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>if (mXInput) {</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>mXInputPollTimer->Cancel();</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>if (ScanForXInputDevices()) {</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>mXInputPollTimer->InitWithFuncCallback(XInputPollTimerCallback,</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>this,</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>kXInputPollInterval,</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>nsITimer::TYPE_REPEATING_SLACK);</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService());</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>if (!gamepadsvc) {</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>return;</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>// Look for devices that are no longer present and remove them.</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>for (int i = mGamepads.Length() - 1; i >= 0; i--) {</em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em>if (!mGamepads<em>.present) {</em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em>gamepadsvc->RemoveGamepad(mGamepads<em>.id);</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>mGamepads.RemoveElementAt(i);</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>// static</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>void</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>WindowsGamepadService::XInputPollTimerCallback(nsITimer* aTimer,</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>void* aClosure)</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>WindowsGamepadService* self =</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>reinterpret_cast<WindowsGamepadService*>(aClosure);</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>self->PollXInput();</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>void</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>WindowsGamepadService:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite7" alt=":p" title="Stick Out Tongue :p" loading="lazy" data-shortname=":p" />ollXInput()</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>for (unsigned int i = 0; i < mGamepads.Length(); i++) {</em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em>if (mGamepads<em>.type != kXInputGamepad) {</em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em>continue;</em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em>XINPUT_STATE state = {};</em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em>DWORD res = mXInput.mXInputGetState(mGamepads<em>.userIndex, &state);</em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em>if (res == ERROR_SUCCESS</em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em>&& state.dwPacketNumber != mGamepads<em>.state.dwPacketNumber) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em>CheckXInputChanges(mGamepads<em>, state);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>void WindowsGamepadService::CheckXInputChanges(Gamepad& gamepad,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>XINPUT_STATE& state) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService());</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>// Handle digital buttons first</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>for (size_t b = 0; b < kNumMappings; b++) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (state.Gamepad.wButtons & kXIButtonMap<strong>.button &&</strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong>!(gamepad.state.Gamepad.wButtons & kXIButtonMap<strong>.button)) {</strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong>// Button pressed</strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong>gamepadsvc->NewButtonEvent(gamepad.id, kXIButtonMap<strong>.mapped, true);</strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong>} else if (!(state.Gamepad.wButtons & kXIButtonMap<strong>.button) &&</strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong>gamepad.state.Gamepad.wButtons & kXIButtonMap<strong>.button) {</strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong>// Button released</strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong>gamepadsvc->NewButtonEvent(gamepad.id, kXIButtonMap<strong>.mapped, false);</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>// Then triggers</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>if (state.Gamepad.bLeftTrigger != gamepad.state.Gamepad.bLeftTrigger) {</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>bool pressed =</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>state.Gamepad.bLeftTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>gamepadsvc->NewButtonEvent(gamepad.id, kButtonLeftTrigger,</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>pressed, state.Gamepad.bLeftTrigger / 255.0);</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>if (state.Gamepad.bRightTrigger != gamepad.state.Gamepad.bRightTrigger) {</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>bool pressed =</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>state.Gamepad.bRightTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>gamepadsvc->NewButtonEvent(gamepad.id, kButtonRightTrigger,</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>pressed, state.Gamepad.bRightTrigger / 255.0);</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>// Finally deal with analog sticks</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>// TODO: bug 1001955 - Support deadzones.</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>if (state.Gamepad.sThumbLX != gamepad.state.Gamepad.sThumbLX) {</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>gamepadsvc->NewAxisMoveEvent(gamepad.id, kLeftStickXAxis,</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>state.Gamepad.sThumbLX / 32767.0);</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>if (state.Gamepad.sThumbLY != gamepad.state.Gamepad.sThumbLY) {</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>gamepadsvc->NewAxisMoveEvent(gamepad.id, kLeftStickYAxis,</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>-1.0 * state.Gamepad.sThumbLY / 32767.0);</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>if (state.Gamepad.sThumbRX != gamepad.state.Gamepad.sThumbRX) {</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>gamepadsvc->NewAxisMoveEvent(gamepad.id, kRightStickXAxis,</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>state.Gamepad.sThumbRX / 32767.0);</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>if (state.Gamepad.sThumbRY != gamepad.state.Gamepad.sThumbRY) {</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>gamepadsvc->NewAxisMoveEvent(gamepad.id, kRightStickYAxis,</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>-1.0 * state.Gamepad.sThumbRY / 32767.0);</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>gamepad.state = state;</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>// Used to sort a list of axes by HID usage.</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>class HidValueComparator {</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>public:</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>bool Equals(const HIDP_VALUE_CAPS& c1, const HIDP_VALUE_CAPS& c2) const</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>{</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>return c1.UsagePage == c2.UsagePage && c1.Range.UsageMin == c2.Range.UsageMin;</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>bool LessThan(const HIDP_VALUE_CAPS& c1, const HIDP_VALUE_CAPS& c2) const</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>{</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>if (c1.UsagePage == c2.UsagePage) {</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>return c1.Range.UsageMin < c2.Range.UsageMin;</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>return c1.UsagePage < c2.UsagePage;</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>};</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>bool</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>WindowsGamepadService::GetRawGamepad(HANDLE handle)</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>{</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>if (!mHID) {</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>return false;</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>}</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>for (unsigned i = 0; i < mGamepads.Length(); i++) {</strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong>if (mGamepads<em>.type == kRawInputGamepad && mGamepads<em>.handle == handle) {</em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em>mGamepads<em>.present = true;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>return true;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>RID_DEVICE_INFO rdi = {};</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>UINT size = rdi.cbSize = sizeof(RID_DEVICE_INFO);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (GetRawInputDeviceInfo(handle, RIDI_DEVICEINFO, &rdi, &size) == kRawInputError) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>return false;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>// Ensure that this is a device we care about</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (!SupportedUsage(rdi.hid.usUsagePage, rdi.hid.usUsage)) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>return false;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>Gamepad gamepad = {};</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>// Device name is a mostly-opaque string.</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (GetRawInputDeviceInfo(handle, RIDI_DEVICENAME, nullptr, &size) == kRawInputError) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>return false;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>nsTArray<wchar_t> devname(size);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>devname.SetLength(size);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (GetRawInputDeviceInfo(handle, RIDI_DEVICENAME, devname.Elements(), &size) == kRawInputError) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>return false;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>// Per <a href="http://[URL]http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014.aspx" target="_blank">[URL]http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014.aspx</a>[/url]</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>// device names containing "IG_" are XInput controllers. Ignore those</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>// devices since we'll handle them with XInput.</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (wcsstr(devname.Elements(), L"IG_")) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>return false;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>// Product string is a human-readable name.</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>// Per <a href="http://[URL]http://msdn.microsoft.com/en-us/library/windows/hardware/ff539681%28v=vs.85%29.aspx" target="_blank">[URL]http://msdn.microsoft.com/en-us/library/windows/hardware/ff539681(v=vs.85).aspx</a>[/url]</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>// "For USB devices, the maximum string length is 126 wide characters (not including the terminating NULL character)."</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>wchar_t name[128] = { 0 };</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>size = sizeof(name);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>nsTArray<char> gamepad_name;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>HANDLE hid_handle = CreateFile(devname.Elements(), GENERIC_READ | GENERIC_WRITE,</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (hid_handle) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (mHID.mHidD_GetProductString(hid_handle, &name, size)) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>int bytes = WideCharToMultiByte(CP_UTF8, 0, name, -1, nullptr, 0, nullptr,</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>nullptr);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>gamepad_name.SetLength(bytes);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>WideCharToMultiByte(CP_UTF8, 0, name, -1, gamepad_name.Elements(),</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>bytes, nullptr, nullptr);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>CloseHandle(hid_handle);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (gamepad_name.Length() == 0 || !gamepad_name[0]) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>const char kUnknown[] = "Unknown Gamepad";</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>gamepad_name.SetLength(ArrayLength(kUnknown));</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>strcpy_s(gamepad_name.Elements(), gamepad_name.Length(), kUnknown);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>char gamepad_id[256] = { 0 };</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>_snprintf_s(gamepad_id, _TRUNCATE, "%04x-%04x-%s", rdi.hid.dwVendorId,</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>rdi.hid.dwProductId, gamepad_name.Elements());</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>nsTArray<uint8_t> preparsedbytes;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (!GetPreparsedData(handle, preparsedbytes)) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>return false;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>PHIDP_PREPARSED_DATA parsed =</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>reinterpret_cast<PHIDP_PREPARSED_DATA>(preparsedbytes.Elements());</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>HIDP_CAPS caps;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (mHID.mHidP_GetCaps(parsed, &caps) != HIDP_STATUS_SUCCESS) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>return false;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>// Enumerate buttons.</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>USHORT count = caps.NumberInputButtonCaps;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>nsTArray<HIDP_BUTTON_CAPS> buttonCaps(count);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>buttonCaps.SetLength(count);</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>if (mHID.mHidP_GetButtonCaps(HidP_Input, buttonCaps.Elements(), &count, parsed)</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>!= HIDP_STATUS_SUCCESS) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>return false;</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>}</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>for (unsigned i = 0; i < count; i++) {</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>// Each buttonCaps is typically a range of buttons.</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>gamepad.numButtons +=</em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em>buttonCaps<em>.Range.UsageMax - buttonCaps<em>.Range.UsageMin + 1;</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>}</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>gamepad.numButtons = std::min(gamepad.numButtons, kMaxButtons);</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>// Enumerate value caps, which represent axes and d-pads.</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>count = caps.NumberInputValueCaps;</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>nsTArray<HIDP_VALUE_CAPS> valueCaps(count);</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>valueCaps.SetLength(count);</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>if (mHID.mHidP_GetValueCaps(HidP_Input, valueCaps.Elements(), &count, parsed)</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>!= HIDP_STATUS_SUCCESS) {</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>return false;</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>}</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>nsTArray<HIDP_VALUE_CAPS> axes;</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>// Sort the axes by usagePage and usage to expose a consistent ordering.</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>HidValueComparator comparator;</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>for (unsigned i = 0; i < count; i++) {</em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em>if (valueCaps<em>.UsagePage == kDesktopUsagePage</em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em>&& valueCaps<em>.Range.UsageMin == kUsageDpad</em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em>// Don't know how to handle d-pads that return weird values.</em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em>&& valueCaps<em>.LogicalMax - valueCaps<em>.LogicalMin == 7</em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em>// Can't overflow buttons</em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em>&& gamepad.numButtons + 4 < kMaxButtons) {</em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em>// d-pad gets special handling.</em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em>// Ostensibly HID devices can expose multiple d-pads, but this</em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em>// doesn't happen in practice.</em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em>gamepad.hasDpad = true;</em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em>gamepad.dpadCaps = valueCaps<em>;</em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em>// Expose d-pad as 4 additional buttons.</em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em>gamepad.numButtons += 4;</em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em>} else {</em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em>axes.InsertElementSorted(valueCaps<em>, comparator);</em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em>gamepad.numAxes = std::min<size_t>(axes.Length(), kMaxAxes);</em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em>for (unsigned i = 0; i < gamepad.numAxes; i++) {</em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em>if (i >= kMaxAxes) {</em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em>break;</em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em>gamepad.axes<em>.caps = axes<em>;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad.type = kRawInputGamepad;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad.handle = handle;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad.present = true;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService());</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>if (!gamepadsvc) {</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>return false;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad.id = gamepadsvc->AddGamepad(gamepad_id,</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>GamepadMappingType::_empty,</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad.numButtons,</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad.numAxes);</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>mGamepads.AppendElement(gamepad);</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>return true;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>bool</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>WindowsGamepadService::HandleRawInput(HRAWINPUT handle)</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>if (!mHID) {</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>return false;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService());</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>if (!gamepadsvc) {</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>return false;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>// First, get data from the handle</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>UINT size;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>GetRawInputData(handle, RID_INPUT, nullptr, &size, sizeof(RAWINPUTHEADER));</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>nsTArray<uint8_t> data(size);</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>data.SetLength(size);</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>if (GetRawInputData(handle, RID_INPUT, data.Elements(), &size,</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>sizeof(RAWINPUTHEADER)) == kRawInputError) {</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>return false;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>PRAWINPUT raw = reinterpret_cast<PRAWINPUT>(data.Elements());</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>Gamepad* gamepad = nullptr;</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>for (unsigned i = 0; i < mGamepads.Length(); i++) {</em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em>if (mGamepads<em>.type == kRawInputGamepad</em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&& mGamepads<em>.handle == raw->header.hDevice) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad = &mGamepads<em>;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>break;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (gamepad == nullptr) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>return false;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>// Second, get the preparsed data</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>nsTArray<uint8_t> parsedbytes;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (!GetPreparsedData(raw->header.hDevice, parsedbytes)) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>return false;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>PHIDP_PREPARSED_DATA parsed =</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>reinterpret_cast<PHIDP_PREPARSED_DATA>(parsedbytes.Elements());</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>// Get all the pressed buttons.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>nsTArray<USAGE> usages(gamepad->numButtons);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>usages.SetLength(gamepad->numButtons);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>ULONG usageLength = gamepad->numButtons;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (mHID.mHidP_GetUsages(HidP_Input, kButtonUsagePage, 0, usages.Elements(),</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&usageLength, parsed, (PCHAR)raw->data.hid.bRawData,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>raw->data.hid.dwSizeHid) != HIDP_STATUS_SUCCESS) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>return false;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>bool buttons[kMaxButtons] = { false };</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>usageLength = std::min<ULONG>(usageLength, kMaxButtons);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>for (unsigned i = 0; i < usageLength; i++) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>buttons[usages<em> - 1] = true;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (gamepad->hasDpad) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>// Get d-pad position as 4 buttons.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>ULONG value;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (mHID.mHidP_GetUsageValue(HidP_Input, gamepad->dpadCaps.UsagePage, 0, gamepad->dpadCaps.Range.UsageMin, &value, parsed, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid) == HIDP_STATUS_SUCCESS) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>UnpackDpad(static_cast<LONG>(value), gamepad, buttons);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>for (unsigned i = 0; i < gamepad->numButtons; i++) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (gamepad->buttons<em> != buttons<em>) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepadsvc->NewButtonEvent(gamepad->id, i, buttons<em>);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad->buttons<em> = buttons<em>;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>// Get all axis values.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>for (unsigned i = 0; i < gamepad->numAxes; i++) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>double new_value;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (gamepad->axes<em>.caps.LogicalMin < 0) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>LONG value;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (mHID.mHidP_GetScaledUsageValue(HidP_Input, gamepad->axes<em>.caps.UsagePage,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>0, gamepad->axes<em>.caps.Range.UsageMin,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&value, parsed,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>(PCHAR)raw->data.hid.bRawData,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>raw->data.hid.dwSizeHid)</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>!= HIDP_STATUS_SUCCESS) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>continue;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>new_value = ScaleAxis(value, gamepad->axes<em>.caps.LogicalMin,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad->axes<em>.caps.LogicalMax);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>else {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>ULONG value;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (mHID.mHidP_GetUsageValue(HidP_Input, gamepad->axes<em>.caps.UsagePage, 0,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad->axes<em>.caps.Range.UsageMin, &value,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>parsed, (PCHAR)raw->data.hid.bRawData,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>raw->data.hid.dwSizeHid) != HIDP_STATUS_SUCCESS) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>continue;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>new_value = ScaleAxis(value, gamepad->axes<em>.caps.LogicalMin,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad->axes<em>.caps.LogicalMax);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (gamepad->axes<em>.value != new_value) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepadsvc->NewAxisMoveEvent(gamepad->id, i, new_value);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gamepad->axes<em>.value = new_value;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>return true;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>void</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>WindowsGamepadService:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite5" alt=":confused:" title="Confused :confused:" loading="lazy" data-shortname=":confused:" />tartup()</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>ScanForDevices();</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>void</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>WindowsGamepadService:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite5" alt=":confused:" title="Confused :confused:" loading="lazy" data-shortname=":confused:" />hutdown()</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Cleanup();</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>void</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>WindowsGamepadService::Cleanup()</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (mXInputPollTimer) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>mXInputPollTimer->Cancel();</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>mGamepads.Clear();</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>void</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>WindowsGamepadService:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin :D" loading="lazy" data-shortname=":D" />evicesChanged(DeviceChangeType type)</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (type == DeviceChangeNotification) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>mObserver->SetDeviceChangeTimer();</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>} else if (type == DeviceChangeStable) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>ScanForDevices();</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>NS_IMETHODIMP</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Observer::Observe(nsISupports* aSubject,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>const char* aTopic,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>const char16_t* aData)</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (strcmp(aTopic, "timer-callback") == 0) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>mSvc.DevicesChanged(WindowsGamepadService:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin :D" loading="lazy" data-shortname=":D" />eviceChangeStable);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>} else if (strcmp(aTopic, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID) == 0) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Stop();</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>return NS_OK;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>HWND sHWnd = nullptr;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>bool</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>RegisterRawInput(HWND hwnd, bool enable)</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>nsTArray<RAWINPUTDEVICE> rid(ArrayLength(kUsagePages));</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>rid.SetLength(ArrayLength(kUsagePages));</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>for (unsigned i = 0; i < rid.Length(); i++) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>rid<em>.usUsagePage = kUsagePages<em>.usagePage;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>rid<em>.usUsage = kUsagePages<em>.usage;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>rid<em>.dwFlags =</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>enable ? RIDEV_EXINPUTSINK | RIDEV_DEVNOTIFY : RIDEV_REMOVE;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>rid<em>.hwndTarget = hwnd;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (!RegisterRawInputDevices(rid.Elements(), rid.Length(),</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>sizeof(RAWINPUTDEVICE))) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>return false;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>return true;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>static</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>LRESULT CALLBACK</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>GamepadWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>const unsigned int DBT_DEVICEARRIVAL = 0x8000;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>const unsigned int DBT_DEVICEREMOVECOMPLETE = 0x8004;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>const unsigned int DBT_DEVNODES_CHANGED = 0x7;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>switch (msg) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>case WM_DEVICECHANGE:</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (wParam == DBT_DEVICEARRIVAL ||</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>wParam == DBT_DEVICEREMOVECOMPLETE ||</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>wParam == DBT_DEVNODES_CHANGED) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (gService) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gService->DevicesChanged(WindowsGamepadService:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin :D" loading="lazy" data-shortname=":D" />eviceChangeNotification);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>break;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>case WM_INPUT:</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (gService) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gService->HandleRawInput(reinterpret_cast<HRAWINPUT>(lParam));</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>break;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>return DefWindowProc(hwnd, msg, wParam, lParam);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>} // namespace</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>namespace mozilla {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>namespace hal_impl {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>void StartMonitoringGamepadStatus()</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (gService) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>return;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gService = new WindowsGamepadService();</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gService->Startup();</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (sHWnd == nullptr) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>WNDCLASSW wc;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>HMODULE hSelf = GetModuleHandle(nullptr);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (!GetClassInfoW(hSelf, L"MozillaGamepadClass", &wc)) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>ZeroMemory(&wc, sizeof(WNDCLASSW));</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>wc.hInstance = hSelf;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>wc.lpfnWndProc = GamepadWindowProc;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>wc.lpszClassName = L"MozillaGamepadClass";</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>RegisterClassW(&wc);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>sHWnd = CreateWindowW(L"MozillaGamepadClass", L"Gamepad Watcher",</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>0, 0, 0, 0, 0,</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>nullptr, nullptr, hSelf, nullptr);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>RegisterRawInput(sHWnd, true);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>void StopMonitoringGamepadStatus()</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>{</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (!gService) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>return;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>if (sHWnd) {</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>RegisterRawInput(sHWnd, false);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>DestroyWindow(sHWnd);</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>sHWnd = nullptr;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gService->Shutdown();</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>delete gService;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>gService = nullptr;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>}</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>} // namespace hal_impl</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>} // namespace mozilla</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><strong><strong><strong><strong><strong><strong><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></strong></strong></strong></strong></strong></strong></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>[/SPOILER]</p></blockquote><p></p>
[QUOTE="Stéphane Lenclud, post: 1124692, member: 140174"] Note for future implementation of proper gamepad support see example there: [URL]https://dxr.mozilla.org/mozilla-central/source/hal/windows/WindowsGamepad.cpp[/URL] Now moved to: [URL]https://dxr.mozilla.org/mozilla-central/source/dom/gamepad/windows/WindowsGamepad.cpp[/URL] Google search: [URL]https://www.google.de/search?q=HID+gamepad+handling+direction+pad[/URL] Here is a copy of the code linked above [SPOILER="See Code"] /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at [URL]http://mozilla.org/MPL/2.0/[/URL]. */ #include <algorithm> #include <cstddef> #ifndef UNICODE #define UNICODE #endif #include <windows.h> #include <hidsdi.h> #include <stdio.h> #include <xinput.h> #include "nsIComponentManager.h" #include "nsIObserver.h" #include "nsIObserverService.h" #include "nsITimer.h" #include "nsTArray.h" #include "mozilla/ArrayUtils.h" #include "mozilla/dom/GamepadService.h" #include "mozilla/Services.h" namespace { using namespace mozilla::dom; using mozilla::ArrayLength; // USB HID usage tables, page 1 (Hat switch) const unsigned kUsageDpad = 0x39; // USB HID usage tables, page 1, 0x30 = X const unsigned kFirstAxis = 0x30; // USB HID usage tables const unsigned kDesktopUsagePage = 0x1; const unsigned kButtonUsagePage = 0x9; // Arbitrary. In practice 10 buttons/6 axes is the near maximum. const unsigned kMaxButtons = 32; const unsigned kMaxAxes = 32; // Multiple devices-changed notifications can be sent when a device // is connected, because USB devices consist of multiple logical devices. // Therefore, we wait a bit after receiving one before looking for // device changes. const uint32_t kDevicesChangedStableDelay = 200; // XInput is a purely polling-driven API, so we need to // poll it periodically. 50ms is arbitrarily chosen. const uint32_t kXInputPollInterval = 50; const UINT kRawInputError = (UINT)-1; #ifndef XUSER_MAX_COUNT #define XUSER_MAX_COUNT 4 #endif const struct { int usagePage; int usage; } kUsagePages[] = { // USB HID usage tables, page 1 { kDesktopUsagePage, 4 }, // Joystick { kDesktopUsagePage, 5 } // Gamepad }; const struct { WORD button; int mapped; } kXIButtonMap[] = { { XINPUT_GAMEPAD_DPAD_UP, 12 }, { XINPUT_GAMEPAD_DPAD_DOWN, 13 }, { XINPUT_GAMEPAD_DPAD_LEFT, 14 }, { XINPUT_GAMEPAD_DPAD_RIGHT, 15 }, { XINPUT_GAMEPAD_START, 9 }, { XINPUT_GAMEPAD_BACK, 8 }, { XINPUT_GAMEPAD_LEFT_THUMB, 10 }, { XINPUT_GAMEPAD_RIGHT_THUMB, 11 }, { XINPUT_GAMEPAD_LEFT_SHOULDER, 4 }, { XINPUT_GAMEPAD_RIGHT_SHOULDER, 5 }, { XINPUT_GAMEPAD_A, 0 }, { XINPUT_GAMEPAD_B, 1 }, { XINPUT_GAMEPAD_X, 2 }, { XINPUT_GAMEPAD_Y, 3 } }; const size_t kNumMappings = ArrayLength(kXIButtonMap); enum GamepadType { kNoGamepad = 0, kRawInputGamepad, kXInputGamepad }; class WindowsGamepadService; WindowsGamepadService* gService = nullptr; struct Gamepad { GamepadType type; // Handle to raw input device HANDLE handle; // XInput Index of the user's controller. Passed to XInputGetState. DWORD userIndex; // Last-known state of the controller. XINPUT_STATE state; // ID from the GamepadService, also used as the index into // WindowsGamepadService::mGamepads. int id; // Information about the physical device. unsigned numAxes; unsigned numButtons; bool hasDpad; HIDP_VALUE_CAPS dpadCaps; bool buttons[kMaxButtons]; struct { HIDP_VALUE_CAPS caps; double value; } axes[kMaxAxes]; // Used during rescan to find devices that were disconnected. bool present; }; // Drop this in favor of decltype when we require a new enough SDK. typedef void (WINAPI *XInputEnable_func)(BOOL); // RAII class to wrap loading the XInput DLL class XInputLoader { public: XInputLoader() : module(nullptr), mXInputEnable(nullptr), mXInputGetState(nullptr) { // xinput1_4.dll exists on Windows 8 // xinput9_1_0.dll exists on Windows 7 and Vista // xinput1_3.dll shipped with the DirectX SDK const wchar_t* dlls[] = {L"xinput1_4.dll", L"xinput9_1_0.dll", L"xinput1_3.dll"}; const size_t kNumDLLs = ArrayLength(dlls); for (size_t i = 0; i < kNumDLLs; ++i) { module = LoadLibraryW(dlls[I]); if (module) { mXInputEnable = reinterpret_cast<XInputEnable_func>( GetProcAddress(module, "XInputEnable")); mXInputGetState = reinterpret_cast<decltype(XInputGetState)*>( GetProcAddress(module, "XInputGetState")); if (mXInputEnable) { mXInputEnable(TRUE); } break; } } } ~XInputLoader() { //mXInputEnable = nullptr; mXInputGetState = nullptr; if (module) { FreeLibrary(module); } } operator bool() { return module && mXInputGetState; } HMODULE module; decltype(XInputGetState) *mXInputGetState; XInputEnable_func mXInputEnable; }; bool GetPreparsedData(HANDLE handle, nsTArray<uint8_t>& data) { UINT size; if (GetRawInputDeviceInfo(handle, RIDI_PREPARSEDDATA, nullptr, &size) == kRawInputError) { return false; } data.SetLength(size); return GetRawInputDeviceInfo(handle, RIDI_PREPARSEDDATA, data.Elements(), &size) > 0; } /* * Given an axis value and a minimum and maximum range, * scale it to be in the range -1.0 .. 1.0. */ double ScaleAxis(ULONG value, LONG min, LONG max) { return 2.0 * (value - min) / (max - min) - 1.0; } /* * Given a value from a d-pad (POV hat in USB HID terminology), * represent it as 4 buttons, one for each cardinal direction. */ void UnpackDpad(LONG dpad_value, const Gamepad* gamepad, bool buttons[kMaxButtons]) { const unsigned kUp = gamepad->numButtons - 4; const unsigned kDown = gamepad->numButtons - 3; const unsigned kLeft = gamepad->numButtons - 2; const unsigned kRight = gamepad->numButtons - 1; // Different controllers have different ways of representing // "nothing is pressed", but they're all outside the range of values. if (dpad_value < gamepad->dpadCaps.LogicalMin || dpad_value > gamepad->dpadCaps.LogicalMax) { // Nothing is pressed. return; } // Normalize value to start at 0. int value = dpad_value - gamepad->dpadCaps.LogicalMin; // Value will be in the range 0-7. The value represents the // position of the d-pad around a circle, with 0 being straight up, // 2 being right, 4 being straight down, and 6 being left. if (value < 2 || value > 6) { buttons[kUp] = true; } if (value > 2 && value < 6) { buttons[kDown] = true; } if (value > 4) { buttons[kLeft] = true; } if (value > 0 && value < 4) { buttons[kRight] = true; } } /* * Return true if this USB HID usage page and usage are of a type we * know how to handle. */ bool SupportedUsage(USHORT page, USHORT usage) { for (unsigned i = 0; i < ArrayLength(kUsagePages); i++) { if (page == kUsagePages[I].usagePage && usage == kUsagePages[I].usage) { return true; } } return false; } class Observer : public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER Observer(WindowsGamepadService& svc) : mSvc(svc), mObserving(true) { nsresult rv; mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService(); observerService->AddObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, false); } void Stop() { if (mTimer) { mTimer->Cancel(); } if (mObserving) { nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService(); observerService->RemoveObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID); mObserving = false; } } void SetDeviceChangeTimer() { // Set stable timer, since we will get multiple devices-changed // notifications at once if (mTimer) { mTimer->Cancel(); mTimer->Init(this, kDevicesChangedStableDelay, nsITimer::TYPE_ONE_SHOT); } } private: virtual ~Observer() { Stop(); } // Gamepad service owns us, we just hold a reference back to it. WindowsGamepadService& mSvc; nsCOMPtr<nsITimer> mTimer; bool mObserving; }; NS_IMPL_ISUPPORTS(Observer, nsIObserver); class HIDLoader { public: HIDLoader() : mModule(LoadLibraryW(L"hid.dll")), mHidD_GetProductString(nullptr), mHidP_GetCaps(nullptr), mHidP_GetButtonCaps(nullptr), mHidP_GetValueCaps(nullptr), mHidP_GetUsages(nullptr), mHidP_GetUsageValue(nullptr), mHidP_GetScaledUsageValue(nullptr) { if (mModule) { mHidD_GetProductString = reinterpret_cast<decltype(HidD_GetProductString)*>(GetProcAddress(mModule, "HidD_GetProductString")); mHidP_GetCaps = reinterpret_cast<decltype(HidP_GetCaps)*>(GetProcAddress(mModule, "HidP_GetCaps")); mHidP_GetButtonCaps = reinterpret_cast<decltype(HidP_GetButtonCaps)*>(GetProcAddress(mModule, "HidP_GetButtonCaps")); mHidP_GetValueCaps = reinterpret_cast<decltype(HidP_GetValueCaps)*>(GetProcAddress(mModule, "HidP_GetValueCaps")); mHidP_GetUsages = reinterpret_cast<decltype(HidP_GetUsages)*>(GetProcAddress(mModule, "HidP_GetUsages")); mHidP_GetUsageValue = reinterpret_cast<decltype(HidP_GetUsageValue)*>(GetProcAddress(mModule, "HidP_GetUsageValue")); mHidP_GetScaledUsageValue = reinterpret_cast<decltype(HidP_GetScaledUsageValue)*>(GetProcAddress(mModule, "HidP_GetScaledUsageValue")); } } ~HIDLoader() { if (mModule) { FreeLibrary(mModule); } } operator bool() { return mModule && mHidD_GetProductString && mHidP_GetCaps && mHidP_GetButtonCaps && mHidP_GetValueCaps && mHidP_GetUsages && mHidP_GetUsageValue && mHidP_GetScaledUsageValue; } decltype(HidD_GetProductString) *mHidD_GetProductString; decltype(HidP_GetCaps) *mHidP_GetCaps; decltype(HidP_GetButtonCaps) *mHidP_GetButtonCaps; decltype(HidP_GetValueCaps) *mHidP_GetValueCaps; decltype(HidP_GetUsages) *mHidP_GetUsages; decltype(HidP_GetUsageValue) *mHidP_GetUsageValue; decltype(HidP_GetScaledUsageValue) *mHidP_GetScaledUsageValue; private: HMODULE mModule; }; class WindowsGamepadService { public: WindowsGamepadService(); virtual ~WindowsGamepadService() { Cleanup(); } enum DeviceChangeType { DeviceChangeNotification, DeviceChangeStable }; void DevicesChanged(DeviceChangeType type); void Startup(); void Shutdown(); // Parse gamepad input from a WM_INPUT message. bool HandleRawInput(HRAWINPUT handle); private: void ScanForDevices(); // Look for connected raw input devices. void ScanForRawInputDevices(); // Look for connected XInput devices. bool ScanForXInputDevices(); bool HaveXInputGamepad(int userIndex); // Timer callback for XInput polling static void XInputPollTimerCallback(nsITimer* aTimer, void* aClosure); void PollXInput(); void CheckXInputChanges(Gamepad& gamepad, XINPUT_STATE& state); // Get information about a raw input gamepad. bool GetRawGamepad(HANDLE handle); void Cleanup(); // List of connected devices. nsTArray<Gamepad> mGamepads; nsRefPtr<Observer> mObserver; nsCOMPtr<nsITimer> mXInputPollTimer; HIDLoader mHID; XInputLoader mXInput; }; WindowsGamepadService::WindowsGamepadService() { nsresult rv; mXInputPollTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); mObserver = new Observer(*this); } void WindowsGamepadService::confused:canForRawInputDevices() { if (!mHID) { return; } UINT numDevices; if (GetRawInputDeviceList(nullptr, &numDevices, sizeof(RAWINPUTDEVICELIST)) == kRawInputError) { return; } nsTArray<RAWINPUTDEVICELIST> devices(numDevices); devices.SetLength(numDevices); if (GetRawInputDeviceList(devices.Elements(), &numDevices, sizeof(RAWINPUTDEVICELIST)) == kRawInputError) { return; } for (unsigned i = 0; i < devices.Length(); i++) { if (devices[I].dwType == RIM_TYPEHID) { GetRawGamepad(devices[I].hDevice); } } } bool WindowsGamepadService::HaveXInputGamepad(int userIndex) { for (unsigned int i = 0; i < mGamepads.Length(); i++) { if (mGamepads[I].type == kXInputGamepad && mGamepads[I].userIndex == userIndex) { mGamepads[I].present = true; return true; } } return false; } bool WindowsGamepadService::confused:canForXInputDevices() { MOZ_ASSERT(mXInput, "XInput should be present!"); nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService()); if (!gamepadsvc) { return false; } bool found = false; for (int i = 0; i < XUSER_MAX_COUNT; i++) { XINPUT_STATE state = {}; if (mXInput.mXInputGetState(i, &state) != ERROR_SUCCESS) { continue; } found = true; // See if this device is already present in our list. if (HaveXInputGamepad(i)) { continue; } // Not already present, add it. Gamepad gamepad = {}; gamepad.type = kXInputGamepad; gamepad.present = true; gamepad.state = state; gamepad.userIndex = i; gamepad.numButtons = kStandardGamepadButtons; gamepad.numAxes = kStandardGamepadAxes; gamepad.id = gamepadsvc->AddGamepad("xinput", GamepadMappingType::confused:tandard, kStandardGamepadButtons, kStandardGamepadAxes); mGamepads.AppendElement(gamepad); } return found; } void WindowsGamepadService::confused:canForDevices() { for (int i = mGamepads.Length() - 1; i >= 0; i--) { mGamepads[I].present = false; } if (mHID) { ScanForRawInputDevices(); } if (mXInput) { mXInputPollTimer->Cancel(); if (ScanForXInputDevices()) { mXInputPollTimer->InitWithFuncCallback(XInputPollTimerCallback, this, kXInputPollInterval, nsITimer::TYPE_REPEATING_SLACK); } } nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService()); if (!gamepadsvc) { return; } // Look for devices that are no longer present and remove them. for (int i = mGamepads.Length() - 1; i >= 0; i--) { if (!mGamepads[I].present) { gamepadsvc->RemoveGamepad(mGamepads[I].id); mGamepads.RemoveElementAt(i); } } } // static void WindowsGamepadService::XInputPollTimerCallback(nsITimer* aTimer, void* aClosure) { WindowsGamepadService* self = reinterpret_cast<WindowsGamepadService*>(aClosure); self->PollXInput(); } void WindowsGamepadService::pollXInput() { for (unsigned int i = 0; i < mGamepads.Length(); i++) { if (mGamepads[I].type != kXInputGamepad) { continue; } XINPUT_STATE state = {}; DWORD res = mXInput.mXInputGetState(mGamepads[I].userIndex, &state); if (res == ERROR_SUCCESS && state.dwPacketNumber != mGamepads[I].state.dwPacketNumber) { CheckXInputChanges(mGamepads[I], state); } } } void WindowsGamepadService::CheckXInputChanges(Gamepad& gamepad, XINPUT_STATE& state) { nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService()); // Handle digital buttons first for (size_t b = 0; b < kNumMappings; b++) { if (state.Gamepad.wButtons & kXIButtonMap[B].button && !(gamepad.state.Gamepad.wButtons & kXIButtonMap[B].button)) { // Button pressed gamepadsvc->NewButtonEvent(gamepad.id, kXIButtonMap[B].mapped, true); } else if (!(state.Gamepad.wButtons & kXIButtonMap[B].button) && gamepad.state.Gamepad.wButtons & kXIButtonMap[b].button) { // Button released gamepadsvc->NewButtonEvent(gamepad.id, kXIButtonMap[b].mapped, false); } } // Then triggers if (state.Gamepad.bLeftTrigger != gamepad.state.Gamepad.bLeftTrigger) { bool pressed = state.Gamepad.bLeftTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD; gamepadsvc->NewButtonEvent(gamepad.id, kButtonLeftTrigger, pressed, state.Gamepad.bLeftTrigger / 255.0); } if (state.Gamepad.bRightTrigger != gamepad.state.Gamepad.bRightTrigger) { bool pressed = state.Gamepad.bRightTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD; gamepadsvc->NewButtonEvent(gamepad.id, kButtonRightTrigger, pressed, state.Gamepad.bRightTrigger / 255.0); } // Finally deal with analog sticks // TODO: bug 1001955 - Support deadzones. if (state.Gamepad.sThumbLX != gamepad.state.Gamepad.sThumbLX) { gamepadsvc->NewAxisMoveEvent(gamepad.id, kLeftStickXAxis, state.Gamepad.sThumbLX / 32767.0); } if (state.Gamepad.sThumbLY != gamepad.state.Gamepad.sThumbLY) { gamepadsvc->NewAxisMoveEvent(gamepad.id, kLeftStickYAxis, -1.0 * state.Gamepad.sThumbLY / 32767.0); } if (state.Gamepad.sThumbRX != gamepad.state.Gamepad.sThumbRX) { gamepadsvc->NewAxisMoveEvent(gamepad.id, kRightStickXAxis, state.Gamepad.sThumbRX / 32767.0); } if (state.Gamepad.sThumbRY != gamepad.state.Gamepad.sThumbRY) { gamepadsvc->NewAxisMoveEvent(gamepad.id, kRightStickYAxis, -1.0 * state.Gamepad.sThumbRY / 32767.0); } gamepad.state = state; } // Used to sort a list of axes by HID usage. class HidValueComparator { public: bool Equals(const HIDP_VALUE_CAPS& c1, const HIDP_VALUE_CAPS& c2) const { return c1.UsagePage == c2.UsagePage && c1.Range.UsageMin == c2.Range.UsageMin; } bool LessThan(const HIDP_VALUE_CAPS& c1, const HIDP_VALUE_CAPS& c2) const { if (c1.UsagePage == c2.UsagePage) { return c1.Range.UsageMin < c2.Range.UsageMin; } return c1.UsagePage < c2.UsagePage; } }; bool WindowsGamepadService::GetRawGamepad(HANDLE handle) { if (!mHID) { return false; } for (unsigned i = 0; i < mGamepads.Length(); i++) { if (mGamepads[i].type == kRawInputGamepad && mGamepads[i].handle == handle) { mGamepads[i].present = true; return true; } } RID_DEVICE_INFO rdi = {}; UINT size = rdi.cbSize = sizeof(RID_DEVICE_INFO); if (GetRawInputDeviceInfo(handle, RIDI_DEVICEINFO, &rdi, &size) == kRawInputError) { return false; } // Ensure that this is a device we care about if (!SupportedUsage(rdi.hid.usUsagePage, rdi.hid.usUsage)) { return false; } Gamepad gamepad = {}; // Device name is a mostly-opaque string. if (GetRawInputDeviceInfo(handle, RIDI_DEVICENAME, nullptr, &size) == kRawInputError) { return false; } nsTArray<wchar_t> devname(size); devname.SetLength(size); if (GetRawInputDeviceInfo(handle, RIDI_DEVICENAME, devname.Elements(), &size) == kRawInputError) { return false; } // Per [url][URL]http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014.aspx[/URL][/url] // device names containing "IG_" are XInput controllers. Ignore those // devices since we'll handle them with XInput. if (wcsstr(devname.Elements(), L"IG_")) { return false; } // Product string is a human-readable name. // Per [url][URL]http://msdn.microsoft.com/en-us/library/windows/hardware/ff539681%28v=vs.85%29.aspx[/URL][/url] // "For USB devices, the maximum string length is 126 wide characters (not including the terminating NULL character)." wchar_t name[128] = { 0 }; size = sizeof(name); nsTArray<char> gamepad_name; HANDLE hid_handle = CreateFile(devname.Elements(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hid_handle) { if (mHID.mHidD_GetProductString(hid_handle, &name, size)) { int bytes = WideCharToMultiByte(CP_UTF8, 0, name, -1, nullptr, 0, nullptr, nullptr); gamepad_name.SetLength(bytes); WideCharToMultiByte(CP_UTF8, 0, name, -1, gamepad_name.Elements(), bytes, nullptr, nullptr); } CloseHandle(hid_handle); } if (gamepad_name.Length() == 0 || !gamepad_name[0]) { const char kUnknown[] = "Unknown Gamepad"; gamepad_name.SetLength(ArrayLength(kUnknown)); strcpy_s(gamepad_name.Elements(), gamepad_name.Length(), kUnknown); } char gamepad_id[256] = { 0 }; _snprintf_s(gamepad_id, _TRUNCATE, "%04x-%04x-%s", rdi.hid.dwVendorId, rdi.hid.dwProductId, gamepad_name.Elements()); nsTArray<uint8_t> preparsedbytes; if (!GetPreparsedData(handle, preparsedbytes)) { return false; } PHIDP_PREPARSED_DATA parsed = reinterpret_cast<PHIDP_PREPARSED_DATA>(preparsedbytes.Elements()); HIDP_CAPS caps; if (mHID.mHidP_GetCaps(parsed, &caps) != HIDP_STATUS_SUCCESS) { return false; } // Enumerate buttons. USHORT count = caps.NumberInputButtonCaps; nsTArray<HIDP_BUTTON_CAPS> buttonCaps(count); buttonCaps.SetLength(count); if (mHID.mHidP_GetButtonCaps(HidP_Input, buttonCaps.Elements(), &count, parsed) != HIDP_STATUS_SUCCESS) { return false; } for (unsigned i = 0; i < count; i++) { // Each buttonCaps is typically a range of buttons. gamepad.numButtons += buttonCaps[i].Range.UsageMax - buttonCaps[i].Range.UsageMin + 1; } gamepad.numButtons = std::min(gamepad.numButtons, kMaxButtons); // Enumerate value caps, which represent axes and d-pads. count = caps.NumberInputValueCaps; nsTArray<HIDP_VALUE_CAPS> valueCaps(count); valueCaps.SetLength(count); if (mHID.mHidP_GetValueCaps(HidP_Input, valueCaps.Elements(), &count, parsed) != HIDP_STATUS_SUCCESS) { return false; } nsTArray<HIDP_VALUE_CAPS> axes; // Sort the axes by usagePage and usage to expose a consistent ordering. HidValueComparator comparator; for (unsigned i = 0; i < count; i++) { if (valueCaps[i].UsagePage == kDesktopUsagePage && valueCaps[i].Range.UsageMin == kUsageDpad // Don't know how to handle d-pads that return weird values. && valueCaps[i].LogicalMax - valueCaps[i].LogicalMin == 7 // Can't overflow buttons && gamepad.numButtons + 4 < kMaxButtons) { // d-pad gets special handling. // Ostensibly HID devices can expose multiple d-pads, but this // doesn't happen in practice. gamepad.hasDpad = true; gamepad.dpadCaps = valueCaps[i]; // Expose d-pad as 4 additional buttons. gamepad.numButtons += 4; } else { axes.InsertElementSorted(valueCaps[i], comparator); } } gamepad.numAxes = std::min<size_t>(axes.Length(), kMaxAxes); for (unsigned i = 0; i < gamepad.numAxes; i++) { if (i >= kMaxAxes) { break; } gamepad.axes[i].caps = axes[i]; } gamepad.type = kRawInputGamepad; gamepad.handle = handle; gamepad.present = true; nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService()); if (!gamepadsvc) { return false; } gamepad.id = gamepadsvc->AddGamepad(gamepad_id, GamepadMappingType::_empty, gamepad.numButtons, gamepad.numAxes); mGamepads.AppendElement(gamepad); return true; } bool WindowsGamepadService::HandleRawInput(HRAWINPUT handle) { if (!mHID) { return false; } nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService()); if (!gamepadsvc) { return false; } // First, get data from the handle UINT size; GetRawInputData(handle, RID_INPUT, nullptr, &size, sizeof(RAWINPUTHEADER)); nsTArray<uint8_t> data(size); data.SetLength(size); if (GetRawInputData(handle, RID_INPUT, data.Elements(), &size, sizeof(RAWINPUTHEADER)) == kRawInputError) { return false; } PRAWINPUT raw = reinterpret_cast<PRAWINPUT>(data.Elements()); Gamepad* gamepad = nullptr; for (unsigned i = 0; i < mGamepads.Length(); i++) { if (mGamepads[i].type == kRawInputGamepad && mGamepads[i].handle == raw->header.hDevice) { gamepad = &mGamepads[i]; break; } } if (gamepad == nullptr) { return false; } // Second, get the preparsed data nsTArray<uint8_t> parsedbytes; if (!GetPreparsedData(raw->header.hDevice, parsedbytes)) { return false; } PHIDP_PREPARSED_DATA parsed = reinterpret_cast<PHIDP_PREPARSED_DATA>(parsedbytes.Elements()); // Get all the pressed buttons. nsTArray<USAGE> usages(gamepad->numButtons); usages.SetLength(gamepad->numButtons); ULONG usageLength = gamepad->numButtons; if (mHID.mHidP_GetUsages(HidP_Input, kButtonUsagePage, 0, usages.Elements(), &usageLength, parsed, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid) != HIDP_STATUS_SUCCESS) { return false; } bool buttons[kMaxButtons] = { false }; usageLength = std::min<ULONG>(usageLength, kMaxButtons); for (unsigned i = 0; i < usageLength; i++) { buttons[usages[i] - 1] = true; } if (gamepad->hasDpad) { // Get d-pad position as 4 buttons. ULONG value; if (mHID.mHidP_GetUsageValue(HidP_Input, gamepad->dpadCaps.UsagePage, 0, gamepad->dpadCaps.Range.UsageMin, &value, parsed, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid) == HIDP_STATUS_SUCCESS) { UnpackDpad(static_cast<LONG>(value), gamepad, buttons); } } for (unsigned i = 0; i < gamepad->numButtons; i++) { if (gamepad->buttons[i] != buttons[i]) { gamepadsvc->NewButtonEvent(gamepad->id, i, buttons[i]); gamepad->buttons[i] = buttons[i]; } } // Get all axis values. for (unsigned i = 0; i < gamepad->numAxes; i++) { double new_value; if (gamepad->axes[i].caps.LogicalMin < 0) { LONG value; if (mHID.mHidP_GetScaledUsageValue(HidP_Input, gamepad->axes[i].caps.UsagePage, 0, gamepad->axes[i].caps.Range.UsageMin, &value, parsed, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid) != HIDP_STATUS_SUCCESS) { continue; } new_value = ScaleAxis(value, gamepad->axes[i].caps.LogicalMin, gamepad->axes[i].caps.LogicalMax); } else { ULONG value; if (mHID.mHidP_GetUsageValue(HidP_Input, gamepad->axes[i].caps.UsagePage, 0, gamepad->axes[i].caps.Range.UsageMin, &value, parsed, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid) != HIDP_STATUS_SUCCESS) { continue; } new_value = ScaleAxis(value, gamepad->axes[i].caps.LogicalMin, gamepad->axes[i].caps.LogicalMax); } if (gamepad->axes[i].value != new_value) { gamepadsvc->NewAxisMoveEvent(gamepad->id, i, new_value); gamepad->axes[i].value = new_value; } } return true; } void WindowsGamepadService::confused:tartup() { ScanForDevices(); } void WindowsGamepadService::confused:hutdown() { Cleanup(); } void WindowsGamepadService::Cleanup() { if (mXInputPollTimer) { mXInputPollTimer->Cancel(); } mGamepads.Clear(); } void WindowsGamepadService::DevicesChanged(DeviceChangeType type) { if (type == DeviceChangeNotification) { mObserver->SetDeviceChangeTimer(); } else if (type == DeviceChangeStable) { ScanForDevices(); } } NS_IMETHODIMP Observer::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { if (strcmp(aTopic, "timer-callback") == 0) { mSvc.DevicesChanged(WindowsGamepadService::DeviceChangeStable); } else if (strcmp(aTopic, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID) == 0) { Stop(); } return NS_OK; } HWND sHWnd = nullptr; bool RegisterRawInput(HWND hwnd, bool enable) { nsTArray<RAWINPUTDEVICE> rid(ArrayLength(kUsagePages)); rid.SetLength(ArrayLength(kUsagePages)); for (unsigned i = 0; i < rid.Length(); i++) { rid[i].usUsagePage = kUsagePages[i].usagePage; rid[i].usUsage = kUsagePages[i].usage; rid[i].dwFlags = enable ? RIDEV_EXINPUTSINK | RIDEV_DEVNOTIFY : RIDEV_REMOVE; rid[i].hwndTarget = hwnd; } if (!RegisterRawInputDevices(rid.Elements(), rid.Length(), sizeof(RAWINPUTDEVICE))) { return false; } return true; } static LRESULT CALLBACK GamepadWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { const unsigned int DBT_DEVICEARRIVAL = 0x8000; const unsigned int DBT_DEVICEREMOVECOMPLETE = 0x8004; const unsigned int DBT_DEVNODES_CHANGED = 0x7; switch (msg) { case WM_DEVICECHANGE: if (wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE || wParam == DBT_DEVNODES_CHANGED) { if (gService) { gService->DevicesChanged(WindowsGamepadService::DeviceChangeNotification); } } break; case WM_INPUT: if (gService) { gService->HandleRawInput(reinterpret_cast<HRAWINPUT>(lParam)); } break; } return DefWindowProc(hwnd, msg, wParam, lParam); } } // namespace namespace mozilla { namespace hal_impl { void StartMonitoringGamepadStatus() { if (gService) { return; } gService = new WindowsGamepadService(); gService->Startup(); if (sHWnd == nullptr) { WNDCLASSW wc; HMODULE hSelf = GetModuleHandle(nullptr); if (!GetClassInfoW(hSelf, L"MozillaGamepadClass", &wc)) { ZeroMemory(&wc, sizeof(WNDCLASSW)); wc.hInstance = hSelf; wc.lpfnWndProc = GamepadWindowProc; wc.lpszClassName = L"MozillaGamepadClass"; RegisterClassW(&wc); } sHWnd = CreateWindowW(L"MozillaGamepadClass", L"Gamepad Watcher", 0, 0, 0, 0, 0, nullptr, nullptr, hSelf, nullptr); RegisterRawInput(sHWnd, true); } } void StopMonitoringGamepadStatus() { if (!gService) { return; } if (sHWnd) { RegisterRawInput(sHWnd, false); DestroyWindow(sHWnd); sHWnd = nullptr; } gService->Shutdown(); delete gService; gService = nullptr; } } // namespace hal_impl } // namespace mozilla [/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/b][/b][/B][/B][/B][/B][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/SPOILER][I][I][I][I][I][I][I][I][I][I][I][I][I][I][I][B][B][B][B][B][b][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/b][/B][/B][/B][/B][/B][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I] [/QUOTE]
Insert quotes…
Verification
Post reply
Forums
MediaPortal 1
Support
General Support
How use HID compatible gamepad in mediaportal
Contact us
RSS
Top
Bottom