Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / dom / gamepad / GamepadRemapping.cpp
blob2c3ec252f55fd883c76e082f7ac702a2ee8109c4
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 // Based on
8 // https://cs.chromium.org/chromium/src/device/gamepad/gamepad_standard_mappings.h
10 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
11 // Use of this source code is governed by a BSD-style license that can be
12 // found in the LICENSE file.
14 #include "mozilla/dom/GamepadRemapping.h"
15 #include "mozilla/dom/GamepadPlatformService.h"
17 #include <vector>
18 #include <unordered_map>
20 namespace mozilla::dom {
22 const float BUTTON_THRESHOLD_VALUE = 0.1f;
24 float NormalizeTouch(long aValue, long aMin, long aMax) {
25 return (2.f * (aValue - aMin) / static_cast<float>(aMax - aMin)) - 1.f;
28 double AxisToButtonValue(double aValue) {
29 // Mapping axis value range from (-1, +1) to (0, +1).
30 return (aValue + 1.0f) * 0.5f;
33 void FetchDpadFromAxis(GamepadHandle aHandle, double dir) {
34 bool up = false;
35 bool right = false;
36 bool down = false;
37 bool left = false;
39 // Dpad is mapped as a direction on one axis, where -1 is up and it
40 // increases clockwise to 1, which is up + left. It's set to a large (> 1.f)
41 // number when nothing is depressed, except on start up, sometimes it's 0.0
42 // for no data, rather than the large number.
43 if (dir != 0.0f) {
44 up = (dir >= -1.f && dir < -0.7f) || (dir >= .95f && dir <= 1.f);
45 right = dir >= -.75f && dir < -.1f;
46 down = dir >= -.2f && dir < .45f;
47 left = dir >= .4f && dir <= 1.f;
50 RefPtr<GamepadPlatformService> service =
51 GamepadPlatformService::GetParentService();
52 if (!service) {
53 return;
56 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_UP, up);
57 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_RIGHT, right);
58 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_DOWN, down);
59 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_LEFT, left);
62 class DefaultRemapper final : public GamepadRemapper {
63 public:
64 virtual uint32_t GetAxisCount() const override { return numAxes; }
66 virtual uint32_t GetButtonCount() const override { return numButtons; }
68 virtual void SetAxisCount(uint32_t aAxisCount) override {
69 numAxes = aAxisCount;
72 virtual void SetButtonCount(uint32_t aButtonCount) override {
73 numButtons = aButtonCount;
76 virtual GamepadMappingType GetMappingType() const override {
77 return GamepadMappingType::_empty;
80 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
81 double aValue) const override {
82 if (GetAxisCount() <= aAxis) {
83 NS_WARNING(
84 nsPrintfCString("Axis idx '%d' doesn't support in DefaultRemapper().",
85 aAxis)
86 .get());
87 return;
89 RefPtr<GamepadPlatformService> service =
90 GamepadPlatformService::GetParentService();
91 if (!service) {
92 return;
94 service->NewAxisMoveEvent(aHandle, aAxis, aValue);
97 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
98 bool aPressed) const override {
99 if (GetButtonCount() <= aButton) {
100 NS_WARNING(
101 nsPrintfCString(
102 "Button idx '%d' doesn't support in DefaultRemapper().", aButton)
103 .get());
104 return;
106 RefPtr<GamepadPlatformService> service =
107 GamepadPlatformService::GetParentService();
108 if (!service) {
109 return;
111 service->NewButtonEvent(aHandle, aButton, aPressed);
114 private:
115 uint32_t numAxes;
116 uint32_t numButtons;
119 class ADT1Remapper final : public GamepadRemapper {
120 public:
121 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
123 virtual uint32_t GetButtonCount() const override {
124 return BUTTON_INDEX_COUNT;
127 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
128 double aValue) const override {
129 RefPtr<GamepadPlatformService> service =
130 GamepadPlatformService::GetParentService();
131 if (!service) {
132 return;
135 switch (aAxis) {
136 case 0:
137 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
138 break;
139 case 1:
140 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
141 break;
142 case 2:
143 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
144 break;
145 case 3: {
146 const double value = AxisToButtonValue(aValue);
147 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
148 value > BUTTON_THRESHOLD_VALUE, value);
149 break;
151 case 4: {
152 const double value = AxisToButtonValue(aValue);
153 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
154 value > BUTTON_THRESHOLD_VALUE, value);
155 break;
157 case 5:
158 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
159 break;
160 case 9:
161 FetchDpadFromAxis(aHandle, aValue);
162 break;
163 default:
164 NS_WARNING(
165 nsPrintfCString("Axis idx '%d' doesn't support in ADT1Remapper().",
166 aAxis)
167 .get());
168 break;
172 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
173 bool aPressed) const override {
174 RefPtr<GamepadPlatformService> service =
175 GamepadPlatformService::GetParentService();
176 if (!service) {
177 return;
180 if (GetButtonCount() <= aButton) {
181 NS_WARNING(
182 nsPrintfCString("Button idx '%d' doesn't support in ADT1Remapper().",
183 aButton)
184 .get());
185 return;
188 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
189 {3, BUTTON_INDEX_TERTIARY},
190 {4, BUTTON_INDEX_QUATERNARY},
191 {6, BUTTON_INDEX_LEFT_SHOULDER},
192 {7, BUTTON_INDEX_RIGHT_SHOULDER},
193 {12, BUTTON_INDEX_META},
194 {13, BUTTON_INDEX_LEFT_THUMBSTICK},
195 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}};
197 auto find = buttonMapping.find(aButton);
198 if (find != buttonMapping.end()) {
199 service->NewButtonEvent(aHandle, find->second, aPressed);
200 } else {
201 service->NewButtonEvent(aHandle, aButton, aPressed);
206 class TwoAxesEightKeysRemapper final : public GamepadRemapper {
207 public:
208 virtual uint32_t GetAxisCount() const override { return 0; }
210 virtual uint32_t GetButtonCount() const override {
211 return BUTTON_INDEX_COUNT - 1;
214 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
215 double aValue) const override {
216 RefPtr<GamepadPlatformService> service =
217 GamepadPlatformService::GetParentService();
218 if (!service) {
219 return;
222 switch (aAxis) {
223 case 0:
224 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_LEFT,
225 AxisNegativeAsButton(aValue));
226 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_RIGHT,
227 AxisPositiveAsButton(aValue));
228 break;
229 case 1:
230 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_UP,
231 AxisNegativeAsButton(aValue));
232 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_DOWN,
233 AxisPositiveAsButton(aValue));
234 break;
235 default:
236 NS_WARNING(
237 nsPrintfCString(
238 "Axis idx '%d' doesn't support in TwoAxesEightKeysRemapper().",
239 aAxis)
240 .get());
241 break;
245 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
246 bool aPressed) const override {
247 RefPtr<GamepadPlatformService> service =
248 GamepadPlatformService::GetParentService();
249 if (!service) {
250 return;
253 if (GetButtonCount() <= aButton) {
254 NS_WARNING(
255 nsPrintfCString(
256 "Button idx '%d' doesn't support in TwoAxesEightKeysRemapper().",
257 aButton)
258 .get());
259 return;
262 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
263 {0, BUTTON_INDEX_QUATERNARY},
264 {2, BUTTON_INDEX_PRIMARY},
265 {3, BUTTON_INDEX_TERTIARY}};
267 auto find = buttonMapping.find(aButton);
268 if (find != buttonMapping.end()) {
269 service->NewButtonEvent(aHandle, find->second, aPressed);
270 } else {
271 service->NewButtonEvent(aHandle, aButton, aPressed);
276 class StadiaControllerRemapper final : public GamepadRemapper {
277 public:
278 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
280 virtual uint32_t GetButtonCount() const override {
281 return STADIA_BUTTON_COUNT;
284 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
285 double aValue) const override {
286 RefPtr<GamepadPlatformService> service =
287 GamepadPlatformService::GetParentService();
288 if (!service) {
289 return;
292 switch (aAxis) {
293 case 0:
294 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
295 break;
296 case 1:
297 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
298 break;
299 case 2:
300 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
301 break;
302 case 3:
303 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
304 break;
305 case 4: {
306 const double value = AxisToButtonValue(aValue);
307 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
308 value > BUTTON_THRESHOLD_VALUE, value);
309 break;
311 case 5: {
312 const double value = AxisToButtonValue(aValue);
313 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
314 value > BUTTON_THRESHOLD_VALUE, value);
315 break;
317 default:
318 NS_WARNING(
319 nsPrintfCString(
320 "Axis idx '%d' doesn't support in StadiaControllerRemapper().",
321 aAxis)
322 .get());
323 break;
327 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
328 bool aPressed) const override {
329 RefPtr<GamepadPlatformService> service =
330 GamepadPlatformService::GetParentService();
331 if (!service) {
332 return;
335 if (STADIA_BUTTON_COUNT <= aButton) {
336 NS_WARNING(
337 nsPrintfCString(
338 "Button idx '%d' doesn't support in StadiaControllerRemapper().",
339 aButton)
340 .get());
341 return;
344 service->NewButtonEvent(aHandle, aButton, aPressed);
347 private:
348 enum STADIAButtons {
349 STADIA_BUTTON_EXTRA1 = BUTTON_INDEX_COUNT,
350 STADIA_BUTTON_EXTRA2,
351 STADIA_BUTTON_COUNT
355 class Playstation3Remapper final : public GamepadRemapper {
356 public:
357 Playstation3Remapper() = default;
359 uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
361 uint32_t GetButtonCount() const override { return BUTTON_INDEX_COUNT; }
363 void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
364 double aValue) const override {
365 RefPtr<GamepadPlatformService> service =
366 GamepadPlatformService::GetParentService();
367 if (!service) {
368 return;
371 switch (aAxis) {
372 case 0:
373 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
374 break;
375 case 1:
376 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
377 break;
378 case 2:
379 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
380 break;
381 case 5:
382 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
383 break;
384 default:
385 NS_WARNING(
386 nsPrintfCString(
387 "Axis idx '%d' doesn't support in Playstation3Remapper().",
388 aAxis)
389 .get());
390 break;
394 void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
395 bool aPressed) const override {
396 RefPtr<GamepadPlatformService> service =
397 GamepadPlatformService::GetParentService();
398 if (!service) {
399 return;
402 constexpr std::array buttonMapping = {BUTTON_INDEX_BACK_SELECT,
403 BUTTON_INDEX_LEFT_THUMBSTICK,
404 BUTTON_INDEX_RIGHT_THUMBSTICK,
405 BUTTON_INDEX_START,
406 BUTTON_INDEX_DPAD_UP,
407 BUTTON_INDEX_DPAD_RIGHT,
408 BUTTON_INDEX_DPAD_DOWN,
409 BUTTON_INDEX_DPAD_LEFT,
410 BUTTON_INDEX_LEFT_TRIGGER,
411 BUTTON_INDEX_RIGHT_TRIGGER,
412 BUTTON_INDEX_LEFT_SHOULDER,
413 BUTTON_INDEX_RIGHT_SHOULDER,
414 BUTTON_INDEX_QUATERNARY,
415 BUTTON_INDEX_SECONDARY,
416 BUTTON_INDEX_PRIMARY,
417 BUTTON_INDEX_TERTIARY,
418 BUTTON_INDEX_META};
420 if (buttonMapping.size() <= aButton) {
421 NS_WARNING(
422 nsPrintfCString(
423 "Button idx '%d' doesn't support in Playstation3Remapper().",
424 aButton)
425 .get());
426 return;
428 service->NewButtonEvent(aHandle, buttonMapping[aButton], aPressed);
432 class Dualshock4Remapper final : public GamepadRemapper {
433 public:
434 Dualshock4Remapper() {
435 mLastTouches.SetLength(TOUCH_EVENT_COUNT);
436 mLastTouchId.SetLength(TOUCH_EVENT_COUNT);
439 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
441 virtual uint32_t GetButtonCount() const override {
442 return DUALSHOCK_BUTTON_COUNT;
445 virtual uint32_t GetLightIndicatorCount() const override {
446 return LIGHT_INDICATOR_COUNT;
449 virtual void GetLightIndicators(
450 nsTArray<GamepadLightIndicatorType>& aTypes) const override {
451 const uint32_t len = GetLightIndicatorCount();
452 aTypes.SetLength(len);
453 for (uint32_t i = 0; i < len; ++i) {
454 aTypes[i] = GamepadLightIndicatorType::Rgb;
458 virtual uint32_t GetTouchEventCount() const override {
459 return TOUCH_EVENT_COUNT;
462 virtual void GetLightColorReport(
463 uint8_t aRed, uint8_t aGreen, uint8_t aBlue,
464 std::vector<uint8_t>& aReport) const override {
465 const size_t report_length = 32;
466 aReport.resize(report_length);
467 aReport.assign(report_length, 0);
469 aReport[0] = 0x05; // report ID USB only
470 aReport[1] = 0x02; // LED only
471 aReport[6] = aRed;
472 aReport[7] = aGreen;
473 aReport[8] = aBlue;
476 virtual uint32_t GetMaxInputReportLength() const override {
477 return MAX_INPUT_LEN;
480 virtual void ProcessTouchData(GamepadHandle aHandle, void* aInput) override {
481 nsTArray<GamepadTouchState> touches(TOUCH_EVENT_COUNT);
482 touches.SetLength(TOUCH_EVENT_COUNT);
483 uint8_t* rawData = (uint8_t*)aInput;
485 const uint32_t kTouchDimensionX = 1920;
486 const uint32_t kTouchDimensionY = 942;
487 bool touch0Pressed = (((rawData[35] & 0xff) >> 7) == 0);
488 bool touch1Pressed = (((rawData[39] & 0xff) >> 7) == 0);
490 if ((touch0Pressed && (rawData[35] & 0xff) < mLastTouchId[0]) ||
491 (touch1Pressed && (rawData[39] & 0xff) < mLastTouchId[1])) {
492 mTouchIdBase += 128;
495 if (touch0Pressed) {
496 touches[0].touchId = mTouchIdBase + (rawData[35] & 0x7f);
497 touches[0].surfaceId = 0;
498 touches[0].position[0] = NormalizeTouch(
499 ((rawData[37] & 0xf) << 8) | rawData[36], 0, (kTouchDimensionX - 1));
500 touches[0].position[1] =
501 NormalizeTouch(rawData[38] << 4 | ((rawData[37] & 0xf0) >> 4), 0,
502 (kTouchDimensionY - 1));
503 touches[0].surfaceDimensions[0] = kTouchDimensionX;
504 touches[0].surfaceDimensions[1] = kTouchDimensionY;
505 touches[0].isSurfaceDimensionsValid = true;
506 mLastTouchId[0] = rawData[35] & 0x7f;
508 if (touch1Pressed) {
509 touches[1].touchId = mTouchIdBase + (rawData[39] & 0x7f);
510 touches[1].surfaceId = 0;
511 touches[1].position[0] =
512 NormalizeTouch((((rawData[41] & 0xf) << 8) | rawData[40]) + 1, 0,
513 (kTouchDimensionX - 1));
514 touches[1].position[1] =
515 NormalizeTouch(rawData[42] << 4 | ((rawData[41] & 0xf0) >> 4), 0,
516 (kTouchDimensionY - 1));
517 touches[1].surfaceDimensions[0] = kTouchDimensionX;
518 touches[1].surfaceDimensions[1] = kTouchDimensionY;
519 touches[1].isSurfaceDimensionsValid = true;
520 mLastTouchId[1] = rawData[39] & 0x7f;
523 RefPtr<GamepadPlatformService> service =
524 GamepadPlatformService::GetParentService();
525 if (!service) {
526 return;
529 // Avoid to send duplicate untouched events to the gamepad service.
530 if ((mLastTouches[0] != touch0Pressed) || touch0Pressed) {
531 service->NewMultiTouchEvent(aHandle, 0, touches[0]);
533 if ((mLastTouches[1] != touch1Pressed) || touch1Pressed) {
534 service->NewMultiTouchEvent(aHandle, 1, touches[1]);
536 mLastTouches[0] = touch0Pressed;
537 mLastTouches[1] = touch1Pressed;
540 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
541 double aValue) const override {
542 RefPtr<GamepadPlatformService> service =
543 GamepadPlatformService::GetParentService();
544 if (!service) {
545 return;
548 switch (aAxis) {
549 case 0:
550 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
551 break;
552 case 1:
553 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
554 break;
555 case 2:
556 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
557 break;
558 case 3: {
559 const double value = AxisToButtonValue(aValue);
560 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
561 value > BUTTON_THRESHOLD_VALUE, value);
562 break;
564 case 4: {
565 const double value = AxisToButtonValue(aValue);
566 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
567 value > BUTTON_THRESHOLD_VALUE, value);
568 break;
570 case 5:
571 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
572 break;
573 case 9:
574 FetchDpadFromAxis(aHandle, aValue);
575 break;
576 default:
577 NS_WARNING(
578 nsPrintfCString(
579 "Axis idx '%d' doesn't support in Dualshock4Remapper().", aAxis)
580 .get());
581 break;
585 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
586 bool aPressed) const override {
587 RefPtr<GamepadPlatformService> service =
588 GamepadPlatformService::GetParentService();
589 if (!service) {
590 return;
593 constexpr std::array<uint32_t, 14> buttonMapping = {
594 BUTTON_INDEX_TERTIARY,
595 BUTTON_INDEX_PRIMARY,
596 BUTTON_INDEX_SECONDARY,
597 BUTTON_INDEX_QUATERNARY,
598 BUTTON_INDEX_LEFT_SHOULDER,
599 BUTTON_INDEX_RIGHT_SHOULDER,
600 BUTTON_INDEX_LEFT_TRIGGER,
601 BUTTON_INDEX_RIGHT_TRIGGER,
602 BUTTON_INDEX_BACK_SELECT,
603 BUTTON_INDEX_START,
604 BUTTON_INDEX_LEFT_THUMBSTICK,
605 BUTTON_INDEX_RIGHT_THUMBSTICK,
606 BUTTON_INDEX_META,
607 DUALSHOCK_BUTTON_TOUCHPAD};
609 if (buttonMapping.size() <= aButton) {
610 NS_WARNING(nsPrintfCString(
611 "Button idx '%d' doesn't support in Dualshock4Remapper().",
612 aButton)
613 .get());
614 return;
617 service->NewButtonEvent(aHandle, buttonMapping[aButton], aPressed);
620 private:
621 enum Dualshock4Buttons {
622 DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT,
623 DUALSHOCK_BUTTON_COUNT
626 static const uint32_t LIGHT_INDICATOR_COUNT = 1;
627 static const uint32_t TOUCH_EVENT_COUNT = 2;
628 static const uint32_t MAX_INPUT_LEN = 68;
630 nsTArray<unsigned long> mLastTouchId;
631 nsTArray<bool> mLastTouches;
632 unsigned long mTouchIdBase = 0;
635 class Xbox360Remapper final : public GamepadRemapper {
636 public:
637 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
639 virtual uint32_t GetButtonCount() const override {
640 return BUTTON_INDEX_COUNT;
643 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
644 double aValue) const override {
645 RefPtr<GamepadPlatformService> service =
646 GamepadPlatformService::GetParentService();
647 if (!service) {
648 return;
651 switch (aAxis) {
652 case 0:
653 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
654 break;
655 case 1:
656 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
657 break;
658 case 2: {
659 const double value = AxisToButtonValue(aValue);
660 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
661 value > BUTTON_THRESHOLD_VALUE, value);
662 break;
664 case 3:
665 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
666 break;
667 case 4:
668 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
669 break;
670 case 5: {
671 const double value = AxisToButtonValue(aValue);
672 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
673 value > BUTTON_THRESHOLD_VALUE, value);
674 break;
676 default:
677 NS_WARNING(
678 nsPrintfCString(
679 "Axis idx '%d' doesn't support in Xbox360Remapper().", aAxis)
680 .get());
681 break;
685 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
686 bool aPressed) const override {
687 RefPtr<GamepadPlatformService> service =
688 GamepadPlatformService::GetParentService();
689 if (!service) {
690 return;
693 if (GetButtonCount() <= aButton) {
694 NS_WARNING(
695 nsPrintfCString(
696 "Button idx '%d' doesn't support in Xbox360Remapper().", aButton)
697 .get());
698 return;
701 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
702 {6, BUTTON_INDEX_LEFT_THUMBSTICK}, {7, BUTTON_INDEX_RIGHT_THUMBSTICK},
703 {8, BUTTON_INDEX_START}, {9, BUTTON_INDEX_BACK_SELECT},
704 {10, BUTTON_INDEX_META}, {11, BUTTON_INDEX_DPAD_UP},
705 {12, BUTTON_INDEX_DPAD_DOWN}, {13, BUTTON_INDEX_DPAD_LEFT},
706 {14, BUTTON_INDEX_DPAD_RIGHT}};
708 auto find = buttonMapping.find(aButton);
709 if (find != buttonMapping.end()) {
710 service->NewButtonEvent(aHandle, find->second, aPressed);
711 } else {
712 service->NewButtonEvent(aHandle, aButton, aPressed);
717 class XboxOneSRemapper final : public GamepadRemapper {
718 public:
719 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
721 virtual uint32_t GetButtonCount() const override {
722 return BUTTON_INDEX_COUNT;
725 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
726 double aValue) const override {
727 RefPtr<GamepadPlatformService> service =
728 GamepadPlatformService::GetParentService();
729 if (!service) {
730 return;
733 switch (aAxis) {
734 case 0:
735 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
736 break;
737 case 1:
738 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
739 break;
740 case 2: {
741 const double value = AxisToButtonValue(aValue);
742 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
743 value > BUTTON_THRESHOLD_VALUE, value);
744 break;
746 case 3:
747 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
748 break;
749 case 4:
750 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
751 break;
752 case 5: {
753 const double value = AxisToButtonValue(aValue);
754 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
755 value > BUTTON_THRESHOLD_VALUE, value);
756 break;
758 case 9:
759 FetchDpadFromAxis(aHandle, aValue);
760 break;
761 default:
762 NS_WARNING(
763 nsPrintfCString(
764 "Axis idx '%d' doesn't support in XboxOneSRemapper().", aAxis)
765 .get());
766 break;
770 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
771 bool aPressed) const override {
772 RefPtr<GamepadPlatformService> service =
773 GamepadPlatformService::GetParentService();
774 if (!service) {
775 return;
778 if (GetButtonCount() <= aButton) {
779 NS_WARNING(
780 nsPrintfCString(
781 "Button idx '%d' doesn't support in XboxOneSRemapper().", aButton)
782 .get());
783 return;
786 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
787 {6, BUTTON_INDEX_BACK_SELECT},
788 {7, BUTTON_INDEX_START},
789 {8, BUTTON_INDEX_LEFT_THUMBSTICK},
790 {9, BUTTON_INDEX_RIGHT_THUMBSTICK},
791 {10, BUTTON_INDEX_META}};
793 auto find = buttonMapping.find(aButton);
794 if (find != buttonMapping.end()) {
795 service->NewButtonEvent(aHandle, find->second, aPressed);
796 } else {
797 service->NewButtonEvent(aHandle, aButton, aPressed);
802 class XboxOneS2016FirmwareRemapper final : public GamepadRemapper {
803 public:
804 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
806 virtual uint32_t GetButtonCount() const override {
807 return BUTTON_INDEX_COUNT;
810 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
811 double aValue) const override {
812 RefPtr<GamepadPlatformService> service =
813 GamepadPlatformService::GetParentService();
814 if (!service) {
815 return;
818 switch (aAxis) {
819 case 0:
820 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
821 break;
822 case 1:
823 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
824 break;
825 case 2:
826 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
827 break;
828 case 3: {
829 const double value = AxisToButtonValue(aValue);
830 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
831 value > BUTTON_THRESHOLD_VALUE, value);
832 break;
834 case 4: {
835 const double value = AxisToButtonValue(aValue);
836 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
837 value > BUTTON_THRESHOLD_VALUE, value);
838 break;
840 case 5:
841 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
842 break;
843 case 9:
844 FetchDpadFromAxis(aHandle, aValue);
845 break;
846 default:
847 NS_WARNING(nsPrintfCString("Axis idx '%d' doesn't support in "
848 "XboxOneS2016FirmwareRemapper().",
849 aAxis)
850 .get());
851 break;
855 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
856 bool aPressed) const override {
857 RefPtr<GamepadPlatformService> service =
858 GamepadPlatformService::GetParentService();
859 if (!service) {
860 return;
863 if (GetButtonCount() <= aButton) {
864 NS_WARNING(nsPrintfCString("Button idx '%d' doesn't support in "
865 "XboxOneS2016FirmwareRemapper().",
866 aButton)
867 .get());
868 return;
871 // kMicrosoftProductXboxOneSWireless2016 controller received a firmware
872 // update in 2019 that changed which field is populated with the meta button
873 // state. In order to cover the old and new cases, we have to check both
874 // fields of {12, 15} buttons.
875 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
876 {0, BUTTON_INDEX_PRIMARY},
877 {1, BUTTON_INDEX_SECONDARY},
878 {3, BUTTON_INDEX_TERTIARY},
879 {4, BUTTON_INDEX_QUATERNARY},
880 {6, BUTTON_INDEX_LEFT_SHOULDER},
881 {7, BUTTON_INDEX_RIGHT_SHOULDER},
882 {11, BUTTON_INDEX_START},
883 {12, BUTTON_INDEX_META},
884 {13, BUTTON_INDEX_LEFT_THUMBSTICK},
885 {14, BUTTON_INDEX_RIGHT_THUMBSTICK},
886 {15, BUTTON_INDEX_META},
887 {16, BUTTON_INDEX_BACK_SELECT}};
889 auto find = buttonMapping.find(aButton);
890 if (find != buttonMapping.end()) {
891 service->NewButtonEvent(aHandle, find->second, aPressed);
892 } else {
893 service->NewButtonEvent(aHandle, aButton, aPressed);
898 class XboxOneRemapper final : public GamepadRemapper {
899 public:
900 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
902 virtual uint32_t GetButtonCount() const override {
903 return BUTTON_INDEX_COUNT;
906 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
907 double aValue) const override {
908 RefPtr<GamepadPlatformService> service =
909 GamepadPlatformService::GetParentService();
910 if (!service) {
911 return;
914 switch (aAxis) {
915 case 0:
916 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
917 break;
918 case 1:
919 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
920 break;
921 case 2:
922 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
923 break;
924 case 3:
925 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
926 break;
927 case 9:
928 FetchDpadFromAxis(aHandle, aValue);
929 break;
930 case 10: {
931 const double value = AxisToButtonValue(aValue);
932 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
933 value > BUTTON_THRESHOLD_VALUE, value);
934 break;
936 case 11: {
937 const double value = AxisToButtonValue(aValue);
938 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
939 value > BUTTON_THRESHOLD_VALUE, value);
940 break;
942 default:
943 NS_WARNING(
944 nsPrintfCString(
945 "Axis idx '%d' doesn't support in XboxOneRemapper().", aAxis)
946 .get());
947 break;
951 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
952 bool aPressed) const override {
953 RefPtr<GamepadPlatformService> service =
954 GamepadPlatformService::GetParentService();
955 if (!service) {
956 return;
959 if (GetButtonCount() <= aButton) {
960 NS_WARNING(
961 nsPrintfCString(
962 "Button idx '%d' doesn't support in XboxOneRemapper().", aButton)
963 .get());
964 return;
967 // Accessing {30, 31} buttons looks strange to me
968 // and without an avilable device to help verify it.
969 // It is according to `MapperXboxOneBluetooth()` in
970 // https://cs.chromium.org/chromium/src/device/gamepad/gamepad_standard_mappings_mac.mm
971 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
972 {0, BUTTON_INDEX_PRIMARY},
973 {1, BUTTON_INDEX_SECONDARY},
974 {3, BUTTON_INDEX_TERTIARY},
975 {4, BUTTON_INDEX_QUATERNARY},
976 {6, BUTTON_INDEX_LEFT_SHOULDER},
977 {7, BUTTON_INDEX_RIGHT_SHOULDER},
978 {11, BUTTON_INDEX_START},
979 {13, BUTTON_INDEX_LEFT_THUMBSTICK},
980 {14, BUTTON_INDEX_RIGHT_THUMBSTICK},
981 {30, BUTTON_INDEX_META},
982 {31, BUTTON_INDEX_BACK_SELECT}};
984 auto find = buttonMapping.find(aButton);
985 if (find != buttonMapping.end()) {
986 service->NewButtonEvent(aHandle, find->second, aPressed);
987 } else {
988 service->NewButtonEvent(aHandle, aButton, aPressed);
993 class XboxSeriesXRemapper final : public GamepadRemapper {
994 public:
995 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
997 virtual uint32_t GetButtonCount() const override {
998 return BUTTON_INDEX_COUNT;
1001 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1002 double aValue) const override {
1003 RefPtr<GamepadPlatformService> service =
1004 GamepadPlatformService::GetParentService();
1005 if (!service) {
1006 return;
1009 switch (aAxis) {
1010 case 0:
1011 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1012 break;
1013 case 1:
1014 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1015 break;
1016 case 2:
1017 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
1018 break;
1019 case 5:
1020 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
1021 break;
1022 case 9:
1023 FetchDpadFromAxis(aHandle, aValue);
1024 break;
1025 case 148: {
1026 const double value = AxisToButtonValue(aValue);
1027 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
1028 value > BUTTON_THRESHOLD_VALUE, value);
1029 break;
1031 case 149: {
1032 const double value = AxisToButtonValue(aValue);
1033 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
1034 value > BUTTON_THRESHOLD_VALUE, value);
1035 break;
1037 default:
1038 NS_WARNING(
1039 nsPrintfCString(
1040 "Axis idx '%d' doesn't support in XboxSeriesXRemapper().",
1041 aAxis)
1042 .get());
1043 break;
1047 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1048 bool aPressed) const override {
1049 RefPtr<GamepadPlatformService> service =
1050 GamepadPlatformService::GetParentService();
1051 if (!service) {
1052 return;
1055 if (GetButtonCount() <= aButton) {
1056 NS_WARNING(
1057 nsPrintfCString(
1058 "Button idx '%d' doesn't support in XboxSeriesXRemapper().",
1059 aButton)
1060 .get());
1061 return;
1064 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
1065 {0, BUTTON_INDEX_PRIMARY},
1066 {1, BUTTON_INDEX_SECONDARY},
1067 {3, BUTTON_INDEX_TERTIARY},
1068 {4, BUTTON_INDEX_QUATERNARY},
1069 {6, BUTTON_INDEX_LEFT_SHOULDER},
1070 {7, BUTTON_INDEX_RIGHT_SHOULDER},
1071 {10, BUTTON_INDEX_BACK_SELECT},
1072 {11, BUTTON_INDEX_START},
1073 {12, BUTTON_INDEX_META},
1074 {13, BUTTON_INDEX_LEFT_THUMBSTICK},
1075 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}};
1077 auto find = buttonMapping.find(aButton);
1078 if (find != buttonMapping.end()) {
1079 service->NewButtonEvent(aHandle, find->second, aPressed);
1080 } else {
1081 service->NewButtonEvent(aHandle, aButton, aPressed);
1086 class LogitechDInputRemapper final : public GamepadRemapper {
1087 public:
1088 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
1090 virtual uint32_t GetButtonCount() const override {
1091 // The Logitech button (BUTTON_INDEX_META) is not accessible through the
1092 // device's D-mode.
1093 return BUTTON_INDEX_COUNT - 1;
1096 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1097 double aValue) const override {
1098 RefPtr<GamepadPlatformService> service =
1099 GamepadPlatformService::GetParentService();
1100 if (!service) {
1101 return;
1104 switch (aAxis) {
1105 case 0:
1106 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1107 break;
1108 case 1:
1109 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1110 break;
1111 case 2:
1112 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
1113 break;
1114 case 5:
1115 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
1116 break;
1117 case 9:
1118 FetchDpadFromAxis(aHandle, aValue);
1119 break;
1120 default:
1121 NS_WARNING(
1122 nsPrintfCString(
1123 "Axis idx '%d' doesn't support in LogitechDInputRemapper().",
1124 aAxis)
1125 .get());
1126 break;
1130 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1131 bool aPressed) const override {
1132 RefPtr<GamepadPlatformService> service =
1133 GamepadPlatformService::GetParentService();
1134 if (!service) {
1135 return;
1138 if (GetButtonCount() <= aButton) {
1139 NS_WARNING(
1140 nsPrintfCString(
1141 "Button idx '%d' doesn't support in LogitechDInputRemapper().",
1142 aButton)
1143 .get());
1144 return;
1147 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
1148 {0, BUTTON_INDEX_TERTIARY},
1149 {1, BUTTON_INDEX_PRIMARY},
1150 {2, BUTTON_INDEX_SECONDARY}};
1152 auto find = buttonMapping.find(aButton);
1153 if (find != buttonMapping.end()) {
1154 service->NewButtonEvent(aHandle, find->second, aPressed);
1155 } else {
1156 service->NewButtonEvent(aHandle, aButton, aPressed);
1161 class SwitchJoyConRemapper final : public GamepadRemapper {
1162 public:
1163 virtual uint32_t GetAxisCount() const override { return 2; }
1165 virtual uint32_t GetButtonCount() const override {
1166 return BUTTON_INDEX_COUNT;
1169 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1170 double aValue) const override {
1171 if (GetAxisCount() <= aAxis) {
1172 NS_WARNING(
1173 nsPrintfCString(
1174 "Axis idx '%d' doesn't support in SwitchJoyConRemapper().", aAxis)
1175 .get());
1176 return;
1178 RefPtr<GamepadPlatformService> service =
1179 GamepadPlatformService::GetParentService();
1180 if (!service) {
1181 return;
1184 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1187 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1188 bool aPressed) const override {
1189 RefPtr<GamepadPlatformService> service =
1190 GamepadPlatformService::GetParentService();
1191 if (!service) {
1192 return;
1195 service->NewButtonEvent(aHandle, aButton, aPressed);
1199 class SwitchProRemapper final : public GamepadRemapper {
1200 public:
1201 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
1203 virtual uint32_t GetButtonCount() const override {
1204 // The Switch Pro controller has a Capture button that has no equivalent in
1205 // the Standard Gamepad.
1206 return SWITCHPRO_BUTTON_COUNT;
1209 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1210 double aValue) const override {
1211 if (GetAxisCount() <= aAxis) {
1212 NS_WARNING(
1213 nsPrintfCString(
1214 "Axis idx '%d' doesn't support in SwitchProRemapper().", aAxis)
1215 .get());
1216 return;
1218 RefPtr<GamepadPlatformService> service =
1219 GamepadPlatformService::GetParentService();
1220 if (!service) {
1221 return;
1224 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1227 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1228 bool aPressed) const override {
1229 RefPtr<GamepadPlatformService> service =
1230 GamepadPlatformService::GetParentService();
1231 if (!service) {
1232 return;
1235 service->NewButtonEvent(aHandle, aButton, aPressed);
1238 private:
1239 enum SwitchProButtons {
1240 SWITCHPRO_BUTTON_EXTRA = BUTTON_INDEX_COUNT,
1241 SWITCHPRO_BUTTON_COUNT
1245 class NvShieldRemapper final : public GamepadRemapper {
1246 public:
1247 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
1249 virtual uint32_t GetButtonCount() const override {
1250 return SHIELD_BUTTON_COUNT;
1253 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1254 double aValue) const override {
1255 RefPtr<GamepadPlatformService> service =
1256 GamepadPlatformService::GetParentService();
1257 if (!service) {
1258 return;
1261 switch (aAxis) {
1262 case 0:
1263 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1264 break;
1265 case 1:
1266 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1267 break;
1268 case 2:
1269 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
1270 break;
1271 case 3: {
1272 const double value = AxisToButtonValue(aValue);
1273 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
1274 value > BUTTON_THRESHOLD_VALUE, value);
1275 break;
1277 case 4: {
1278 const double value = AxisToButtonValue(aValue);
1279 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
1280 value > BUTTON_THRESHOLD_VALUE, value);
1281 break;
1283 case 5:
1284 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
1285 break;
1286 case 9:
1287 FetchDpadFromAxis(aHandle, aValue);
1288 break;
1289 default:
1290 NS_WARNING(
1291 nsPrintfCString(
1292 "Axis idx '%d' doesn't support in NvShieldRemapper().", aAxis)
1293 .get());
1294 break;
1298 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1299 bool aPressed) const override {
1300 RefPtr<GamepadPlatformService> service =
1301 GamepadPlatformService::GetParentService();
1302 if (!service) {
1303 return;
1306 if (GetButtonCount() <= aButton) {
1307 NS_WARNING(
1308 nsPrintfCString(
1309 "Button idx '%d' doesn't support in NvShieldRemapper().", aButton)
1310 .get());
1311 return;
1314 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
1315 {2, BUTTON_INDEX_META},
1316 {3, BUTTON_INDEX_TERTIARY},
1317 {4, BUTTON_INDEX_QUATERNARY},
1318 {5, SHIELD_BUTTON_CIRCLE},
1319 {6, BUTTON_INDEX_LEFT_SHOULDER},
1320 {7, BUTTON_INDEX_RIGHT_SHOULDER},
1321 {9, BUTTON_INDEX_BACK_SELECT},
1322 {11, BUTTON_INDEX_START},
1323 {13, BUTTON_INDEX_LEFT_THUMBSTICK},
1324 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}};
1326 auto find = buttonMapping.find(aButton);
1327 if (find != buttonMapping.end()) {
1328 service->NewButtonEvent(aHandle, find->second, aPressed);
1329 } else {
1330 service->NewButtonEvent(aHandle, aButton, aPressed);
1334 private:
1335 enum ShieldButtons {
1336 SHIELD_BUTTON_CIRCLE = BUTTON_INDEX_COUNT,
1337 SHIELD_BUTTON_COUNT
1341 class NvShield2017Remapper final : public GamepadRemapper {
1342 public:
1343 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
1345 virtual uint32_t GetButtonCount() const override {
1346 return SHIELD2017_BUTTON_COUNT;
1349 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1350 double aValue) const override {
1351 RefPtr<GamepadPlatformService> service =
1352 GamepadPlatformService::GetParentService();
1353 if (!service) {
1354 return;
1357 switch (aAxis) {
1358 case 0:
1359 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1360 break;
1361 case 1:
1362 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1363 break;
1364 case 2:
1365 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
1366 break;
1367 case 3: {
1368 const double value = AxisToButtonValue(aValue);
1369 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
1370 value > BUTTON_THRESHOLD_VALUE, value);
1371 break;
1373 case 4: {
1374 const double value = AxisToButtonValue(aValue);
1375 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
1376 value > BUTTON_THRESHOLD_VALUE, value);
1377 break;
1379 case 5:
1380 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
1381 break;
1382 case 9:
1383 FetchDpadFromAxis(aHandle, aValue);
1384 break;
1385 default:
1386 NS_WARNING(
1387 nsPrintfCString(
1388 "Axis idx '%d' doesn't support in NvShield2017Remapper().",
1389 aAxis)
1390 .get());
1391 break;
1395 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1396 bool aPressed) const override {
1397 RefPtr<GamepadPlatformService> service =
1398 GamepadPlatformService::GetParentService();
1399 if (!service) {
1400 return;
1403 if (GetButtonCount() <= aButton) {
1404 NS_WARNING(
1405 nsPrintfCString(
1406 "Button idx '%d' doesn't support in NvShield2017Remapper().",
1407 aButton)
1408 .get());
1409 return;
1412 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
1413 {2, BUTTON_INDEX_META},
1414 {3, BUTTON_INDEX_TERTIARY},
1415 {4, BUTTON_INDEX_QUATERNARY},
1416 {5, BUTTON_INDEX_START},
1417 {6, BUTTON_INDEX_LEFT_SHOULDER},
1418 {7, BUTTON_INDEX_RIGHT_SHOULDER},
1419 {8, BUTTON_INDEX_BACK_SELECT},
1420 {11, SHIELD2017_BUTTON_PLAYPAUSE},
1421 {13, BUTTON_INDEX_LEFT_THUMBSTICK},
1422 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}};
1424 auto find = buttonMapping.find(aButton);
1425 if (find != buttonMapping.end()) {
1426 service->NewButtonEvent(aHandle, find->second, aPressed);
1427 } else {
1428 service->NewButtonEvent(aHandle, aButton, aPressed);
1432 private:
1433 enum Shield2017Buttons {
1434 SHIELD2017_BUTTON_PLAYPAUSE = BUTTON_INDEX_COUNT,
1435 SHIELD2017_BUTTON_COUNT
1439 class IBuffaloRemapper final : public GamepadRemapper {
1440 public:
1441 virtual uint32_t GetAxisCount() const override { return 2; }
1443 virtual uint32_t GetButtonCount() const override {
1444 return BUTTON_INDEX_COUNT - 1; /* no meta */
1447 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1448 double aValue) const override {
1449 RefPtr<GamepadPlatformService> service =
1450 GamepadPlatformService::GetParentService();
1451 if (!service) {
1452 return;
1455 switch (aAxis) {
1456 case 0:
1457 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1458 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_LEFT,
1459 AxisNegativeAsButton(aValue));
1460 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_RIGHT,
1461 AxisPositiveAsButton(aValue));
1462 break;
1463 case 1:
1464 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1465 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_UP,
1466 AxisNegativeAsButton(aValue));
1467 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_DOWN,
1468 AxisPositiveAsButton(aValue));
1469 break;
1470 default:
1471 NS_WARNING(
1472 nsPrintfCString(
1473 "Axis idx '%d' doesn't support in IBuffaloRemapper().", aAxis)
1474 .get());
1475 break;
1479 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1480 bool aPressed) const override {
1481 RefPtr<GamepadPlatformService> service =
1482 GamepadPlatformService::GetParentService();
1483 if (!service) {
1484 return;
1487 if (GetButtonCount() <= aButton) {
1488 NS_WARNING(
1489 nsPrintfCString(
1490 "Button idx '%d' doesn't support in IBuffaloRemapper().", aButton)
1491 .get());
1492 return;
1495 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
1496 {0, BUTTON_INDEX_SECONDARY}, {1, BUTTON_INDEX_PRIMARY},
1497 {2, BUTTON_INDEX_QUATERNARY}, {3, BUTTON_INDEX_TERTIARY},
1498 {5, BUTTON_INDEX_RIGHT_TRIGGER}, {6, BUTTON_INDEX_BACK_SELECT},
1499 {7, BUTTON_INDEX_START}};
1501 auto find = buttonMapping.find(aButton);
1502 if (find != buttonMapping.end()) {
1503 service->NewButtonEvent(aHandle, find->second, aPressed);
1504 } else {
1505 service->NewButtonEvent(aHandle, aButton, aPressed);
1510 class XSkillsRemapper final : public GamepadRemapper {
1511 public:
1512 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
1514 virtual uint32_t GetButtonCount() const override {
1515 return GAMECUBE_BUTTON_COUNT;
1518 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1519 double aValue) const override {
1520 RefPtr<GamepadPlatformService> service =
1521 GamepadPlatformService::GetParentService();
1522 if (!service) {
1523 return;
1526 switch (aAxis) {
1527 case 0:
1528 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1529 break;
1530 case 1:
1531 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1532 break;
1533 case 2:
1534 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
1535 break;
1536 case 3: {
1537 const double value = AxisToButtonValue(aValue);
1538 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
1539 value > BUTTON_THRESHOLD_VALUE, value);
1540 break;
1542 case 4: {
1543 const double value = AxisToButtonValue(aValue);
1544 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
1545 value > BUTTON_THRESHOLD_VALUE, value);
1546 break;
1548 case 5:
1549 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
1550 break;
1551 default:
1552 NS_WARNING(
1553 nsPrintfCString(
1554 "Axis idx '%d' doesn't support in XSkillsRemapper().", aAxis)
1555 .get());
1556 break;
1560 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1561 bool aPressed) const override {
1562 RefPtr<GamepadPlatformService> service =
1563 GamepadPlatformService::GetParentService();
1564 if (!service) {
1565 return;
1568 if (GetButtonCount() <= aButton) {
1569 NS_WARNING(
1570 nsPrintfCString(
1571 "Button idx '%d' doesn't support in XSkillsRemapper().", aButton)
1572 .get());
1573 return;
1576 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
1577 {0, BUTTON_INDEX_PRIMARY}, // A
1578 {1, BUTTON_INDEX_TERTIARY}, // B
1579 {2, BUTTON_INDEX_SECONDARY}, // X
1580 {3, BUTTON_INDEX_QUATERNARY}, // Y
1581 {4, GAMECUBE_BUTTON_LEFT_TRIGGER_CLICK},
1582 {5, GAMECUBE_BUTTON_RIGHT_TRIGGER_CLICK},
1583 {6, BUTTON_INDEX_RIGHT_SHOULDER},
1584 {7, BUTTON_INDEX_START},
1585 {8, BUTTON_INDEX_DPAD_LEFT},
1586 {9, BUTTON_INDEX_DPAD_RIGHT},
1587 {10, BUTTON_INDEX_DPAD_DOWN},
1588 {11, BUTTON_INDEX_DPAD_UP}};
1590 auto find = buttonMapping.find(aButton);
1591 if (find != buttonMapping.end()) {
1592 service->NewButtonEvent(aHandle, find->second, aPressed);
1593 } else {
1594 service->NewButtonEvent(aHandle, aButton, aPressed);
1598 private:
1599 enum GamecubeButtons {
1600 GAMECUBE_BUTTON_LEFT_TRIGGER_CLICK = BUTTON_INDEX_COUNT,
1601 GAMECUBE_BUTTON_RIGHT_TRIGGER_CLICK,
1602 GAMECUBE_BUTTON_COUNT
1606 class BoomN64PsxRemapper final : public GamepadRemapper {
1607 public:
1608 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
1610 virtual uint32_t GetButtonCount() const override {
1611 return BUTTON_INDEX_COUNT - 1; // no meta
1614 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1615 double aValue) const override {
1616 RefPtr<GamepadPlatformService> service =
1617 GamepadPlatformService::GetParentService();
1618 if (!service) {
1619 return;
1622 switch (aAxis) {
1623 case 0:
1624 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1625 break;
1626 case 1:
1627 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1628 break;
1629 case 2:
1630 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
1631 break;
1632 case 5:
1633 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
1634 break;
1635 default:
1636 NS_WARNING(
1637 nsPrintfCString(
1638 "Axis idx '%d' doesn't support in BoomN64PsxRemapper().", aAxis)
1639 .get());
1640 break;
1644 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1645 bool aPressed) const override {
1646 RefPtr<GamepadPlatformService> service =
1647 GamepadPlatformService::GetParentService();
1648 if (!service) {
1649 return;
1652 static constexpr std::array buttonMapping = {
1653 BUTTON_INDEX_QUATERNARY, BUTTON_INDEX_SECONDARY,
1654 BUTTON_INDEX_PRIMARY, BUTTON_INDEX_TERTIARY,
1655 BUTTON_INDEX_LEFT_TRIGGER, BUTTON_INDEX_RIGHT_TRIGGER,
1656 BUTTON_INDEX_LEFT_SHOULDER, BUTTON_INDEX_RIGHT_SHOULDER,
1657 BUTTON_INDEX_BACK_SELECT, BUTTON_INDEX_LEFT_THUMBSTICK,
1658 BUTTON_INDEX_RIGHT_THUMBSTICK, BUTTON_INDEX_START,
1659 BUTTON_INDEX_DPAD_UP, BUTTON_INDEX_DPAD_RIGHT,
1660 BUTTON_INDEX_DPAD_DOWN, BUTTON_INDEX_DPAD_LEFT};
1662 if (buttonMapping.size() <= aButton) {
1663 NS_WARNING(nsPrintfCString(
1664 "Button idx '%d' doesn't support in BoomN64PsxRemapper().",
1665 aButton)
1666 .get());
1667 return;
1670 service->NewButtonEvent(aHandle, buttonMapping[aButton], aPressed);
1673 private:
1674 enum GamecubeButtons {
1675 GAMECUBE_BUTTON_LEFT_TRIGGER_CLICK = BUTTON_INDEX_COUNT,
1676 GAMECUBE_BUTTON_RIGHT_TRIGGER_CLICK,
1677 GAMECUBE_BUTTON_COUNT
1681 class StadiaControllerOldFirmwareRemapper final : public GamepadRemapper {
1682 public:
1683 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
1685 virtual uint32_t GetButtonCount() const override {
1686 return ANALOG_GAMEPAD_BUTTON_COUNT;
1689 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1690 double aValue) const override {
1691 RefPtr<GamepadPlatformService> service =
1692 GamepadPlatformService::GetParentService();
1693 if (!service) {
1694 return;
1697 switch (aAxis) {
1698 case 0:
1699 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1700 break;
1701 case 1:
1702 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1703 break;
1704 case 2:
1705 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
1706 break;
1707 case 3: {
1708 const double value = AxisToButtonValue(aValue);
1709 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
1710 value > BUTTON_THRESHOLD_VALUE, value);
1711 break;
1713 case 4: {
1714 const double value = AxisToButtonValue(aValue);
1715 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
1716 value > BUTTON_THRESHOLD_VALUE, value);
1717 break;
1719 case 5:
1720 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
1721 break;
1722 case 9:
1723 FetchDpadFromAxis(aHandle, aValue);
1724 break;
1725 default:
1726 NS_WARNING(
1727 nsPrintfCString(
1728 "Axis idx '%d' doesn't support in AnalogGamepadRemapper().",
1729 aAxis)
1730 .get());
1731 break;
1735 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1736 bool aPressed) const override {
1737 RefPtr<GamepadPlatformService> service =
1738 GamepadPlatformService::GetParentService();
1739 if (!service) {
1740 return;
1743 if (GetButtonCount() <= aButton) {
1744 NS_WARNING(
1745 nsPrintfCString(
1746 "Button idx '%d' doesn't support in AnalogGamepadRemapper().",
1747 aButton)
1748 .get());
1749 return;
1752 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
1753 {3, BUTTON_INDEX_TERTIARY},
1754 {4, BUTTON_INDEX_QUATERNARY},
1755 {6, BUTTON_INDEX_LEFT_SHOULDER},
1756 {7, BUTTON_INDEX_RIGHT_SHOULDER},
1757 {10, BUTTON_INDEX_BACK_SELECT},
1758 {11, BUTTON_INDEX_META},
1759 {12, BUTTON_INDEX_START},
1760 {13, BUTTON_INDEX_LEFT_THUMBSTICK},
1761 {14, BUTTON_INDEX_RIGHT_THUMBSTICK},
1762 {16, ANALOG_GAMEPAD_BUTTON_EXTRA},
1763 {17, ANALOG_GAMEPAD_BUTTON_EXTRA2}};
1765 auto find = buttonMapping.find(aButton);
1766 if (find != buttonMapping.end()) {
1767 service->NewButtonEvent(aHandle, find->second, aPressed);
1768 } else {
1769 service->NewButtonEvent(aHandle, aButton, aPressed);
1773 private:
1774 enum AnalogGamepadButtons {
1775 ANALOG_GAMEPAD_BUTTON_EXTRA = BUTTON_INDEX_COUNT,
1776 ANALOG_GAMEPAD_BUTTON_EXTRA2,
1777 ANALOG_GAMEPAD_BUTTON_COUNT
1781 class RazerServalRemapper final : public GamepadRemapper {
1782 public:
1783 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
1785 virtual uint32_t GetButtonCount() const override {
1786 return BUTTON_INDEX_COUNT - 1; /* no meta */
1789 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1790 double aValue) const override {
1791 RefPtr<GamepadPlatformService> service =
1792 GamepadPlatformService::GetParentService();
1793 if (!service) {
1794 return;
1797 switch (aAxis) {
1798 case 0:
1799 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1800 break;
1801 case 1:
1802 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1803 break;
1804 case 2:
1805 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
1806 break;
1807 case 3: {
1808 const double value = AxisToButtonValue(aValue);
1809 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
1810 value > BUTTON_THRESHOLD_VALUE, value);
1811 break;
1813 case 4: {
1814 const double value = AxisToButtonValue(aValue);
1815 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
1816 value > BUTTON_THRESHOLD_VALUE, value);
1817 break;
1819 case 5:
1820 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
1821 break;
1822 case 9:
1823 FetchDpadFromAxis(aHandle, aValue);
1824 break;
1825 default:
1826 NS_WARNING(
1827 nsPrintfCString(
1828 "Axis idx '%d' doesn't support in RazerServalRemapper().",
1829 aAxis)
1830 .get());
1831 break;
1835 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1836 bool aPressed) const override {
1837 RefPtr<GamepadPlatformService> service =
1838 GamepadPlatformService::GetParentService();
1839 if (!service) {
1840 return;
1843 if (GetButtonCount() <= aButton) {
1844 NS_WARNING(
1845 nsPrintfCString(
1846 "Button idx '%d' doesn't support in RazerServalRemapper().",
1847 aButton)
1848 .get());
1849 return;
1852 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
1853 {3, BUTTON_INDEX_TERTIARY}, {4, BUTTON_INDEX_QUATERNARY},
1854 {6, BUTTON_INDEX_LEFT_SHOULDER}, {7, BUTTON_INDEX_RIGHT_SHOULDER},
1855 {10, BUTTON_INDEX_BACK_SELECT}, {11, BUTTON_INDEX_START},
1856 {12, BUTTON_INDEX_START}, {13, BUTTON_INDEX_LEFT_THUMBSTICK},
1857 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}};
1859 auto find = buttonMapping.find(aButton);
1860 if (find != buttonMapping.end()) {
1861 service->NewButtonEvent(aHandle, find->second, aPressed);
1862 } else {
1863 service->NewButtonEvent(aHandle, aButton, aPressed);
1868 class MogaProRemapper final : public GamepadRemapper {
1869 public:
1870 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
1872 virtual uint32_t GetButtonCount() const override {
1873 return BUTTON_INDEX_COUNT - 1; /* no meta */
1876 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1877 double aValue) const override {
1878 RefPtr<GamepadPlatformService> service =
1879 GamepadPlatformService::GetParentService();
1880 if (!service) {
1881 return;
1884 switch (aAxis) {
1885 case 0:
1886 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1887 break;
1888 case 1:
1889 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1890 break;
1891 case 2:
1892 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
1893 break;
1894 case 3: {
1895 const double value = AxisToButtonValue(aValue);
1896 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
1897 value > BUTTON_THRESHOLD_VALUE, value);
1898 break;
1900 case 4: {
1901 const double value = AxisToButtonValue(aValue);
1902 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
1903 value > BUTTON_THRESHOLD_VALUE, value);
1904 break;
1906 case 5:
1907 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
1908 break;
1909 case 9:
1910 FetchDpadFromAxis(aHandle, aValue);
1911 break;
1912 default:
1913 NS_WARNING(
1914 nsPrintfCString(
1915 "Axis idx '%d' doesn't support in MogaProRemapper().", aAxis)
1916 .get());
1917 break;
1921 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
1922 bool aPressed) const override {
1923 RefPtr<GamepadPlatformService> service =
1924 GamepadPlatformService::GetParentService();
1925 if (!service) {
1926 return;
1929 if (GetButtonCount() <= aButton) {
1930 NS_WARNING(
1931 nsPrintfCString(
1932 "Button idx '%d' doesn't support in MogaProRemapper().", aButton)
1933 .get());
1934 return;
1937 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
1938 {3, BUTTON_INDEX_TERTIARY}, {4, BUTTON_INDEX_QUATERNARY},
1939 {6, BUTTON_INDEX_LEFT_SHOULDER}, {7, BUTTON_INDEX_RIGHT_SHOULDER},
1940 {11, BUTTON_INDEX_START}, {13, BUTTON_INDEX_LEFT_THUMBSTICK},
1941 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}};
1943 auto find = buttonMapping.find(aButton);
1944 if (find != buttonMapping.end()) {
1945 service->NewButtonEvent(aHandle, find->second, aPressed);
1946 } else {
1947 service->NewButtonEvent(aHandle, aButton, aPressed);
1952 class OnLiveWirelessRemapper final : public GamepadRemapper {
1953 public:
1954 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
1956 virtual uint32_t GetButtonCount() const override {
1957 return BUTTON_INDEX_COUNT;
1960 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
1961 double aValue) const override {
1962 RefPtr<GamepadPlatformService> service =
1963 GamepadPlatformService::GetParentService();
1964 if (!service) {
1965 return;
1968 switch (aAxis) {
1969 case 0:
1970 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
1971 break;
1972 case 1:
1973 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
1974 break;
1975 case 2: {
1976 const double value = AxisToButtonValue(aValue);
1977 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
1978 value > BUTTON_THRESHOLD_VALUE, value);
1979 break;
1981 case 3:
1982 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
1983 break;
1984 case 4:
1985 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
1986 break;
1987 case 5: {
1988 const double value = AxisToButtonValue(aValue);
1989 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
1990 value > BUTTON_THRESHOLD_VALUE, value);
1991 break;
1993 case 9:
1994 FetchDpadFromAxis(aHandle, aValue);
1995 break;
1996 default:
1997 NS_WARNING(
1998 nsPrintfCString(
1999 "Axis idx '%d' doesn't support in OnLiveWirelessRemapper().",
2000 aAxis)
2001 .get());
2002 break;
2006 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
2007 bool aPressed) const override {
2008 RefPtr<GamepadPlatformService> service =
2009 GamepadPlatformService::GetParentService();
2010 if (!service) {
2011 return;
2014 if (GetButtonCount() <= aButton) {
2015 NS_WARNING(
2016 nsPrintfCString(
2017 "Button idx '%d' doesn't support in OnLiveWirelessRemapper().",
2018 aButton)
2019 .get());
2020 return;
2023 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
2024 {3, BUTTON_INDEX_TERTIARY},
2025 {4, BUTTON_INDEX_QUATERNARY},
2026 {6, BUTTON_INDEX_LEFT_SHOULDER},
2027 {7, BUTTON_INDEX_RIGHT_SHOULDER},
2028 {12, BUTTON_INDEX_META},
2029 {13, BUTTON_INDEX_LEFT_THUMBSTICK},
2030 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}};
2032 auto find = buttonMapping.find(aButton);
2033 if (find != buttonMapping.end()) {
2034 service->NewButtonEvent(aHandle, find->second, aPressed);
2035 } else {
2036 service->NewButtonEvent(aHandle, aButton, aPressed);
2041 class OUYARemapper final : public GamepadRemapper {
2042 public:
2043 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
2045 virtual uint32_t GetButtonCount() const override {
2046 return BUTTON_INDEX_COUNT;
2049 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis,
2050 double aValue) const override {
2051 RefPtr<GamepadPlatformService> service =
2052 GamepadPlatformService::GetParentService();
2053 if (!service) {
2054 return;
2057 switch (aAxis) {
2058 case 0:
2059 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue);
2060 break;
2061 case 1:
2062 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue);
2063 break;
2064 case 2: {
2065 const double value = AxisToButtonValue(aValue);
2066 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER,
2067 value > BUTTON_THRESHOLD_VALUE, value);
2068 break;
2070 case 3:
2071 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue);
2072 break;
2073 case 4:
2074 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue);
2075 break;
2076 case 5: {
2077 const double value = AxisToButtonValue(aValue);
2078 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER,
2079 value > BUTTON_THRESHOLD_VALUE, value);
2080 break;
2082 default:
2083 NS_WARNING(
2084 nsPrintfCString("Axis idx '%d' doesn't support in OUYARemapper().",
2085 aAxis)
2086 .get());
2087 break;
2091 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton,
2092 bool aPressed) const override {
2093 RefPtr<GamepadPlatformService> service =
2094 GamepadPlatformService::GetParentService();
2095 if (!service) {
2096 return;
2099 if (GetButtonCount() <= aButton) {
2100 NS_WARNING(
2101 nsPrintfCString("Button idx '%d' doesn't support in OUYARemapper().",
2102 aButton)
2103 .get());
2104 return;
2107 const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
2108 {1, BUTTON_INDEX_TERTIARY}, {2, BUTTON_INDEX_QUATERNARY},
2109 {3, BUTTON_INDEX_SECONDARY}, {6, BUTTON_INDEX_LEFT_THUMBSTICK},
2110 {7, BUTTON_INDEX_RIGHT_THUMBSTICK}, {8, BUTTON_INDEX_DPAD_UP},
2111 {9, BUTTON_INDEX_DPAD_DOWN}, {10, BUTTON_INDEX_DPAD_LEFT},
2112 {11, BUTTON_INDEX_DPAD_RIGHT}, {15, BUTTON_INDEX_META}};
2114 auto find = buttonMapping.find(aButton);
2115 if (find != buttonMapping.end()) {
2116 service->NewButtonEvent(aHandle, find->second, aPressed);
2117 } else {
2118 service->NewButtonEvent(aHandle, aButton, aPressed);
2123 already_AddRefed<GamepadRemapper> GetGamepadRemapper(const uint16_t aVendorId,
2124 const uint16_t aProductId,
2125 bool& aUsingDefault) {
2126 const std::vector<GamepadRemappingData> remappingRules = {
2127 {GamepadId::kAsusTekProduct4500, new ADT1Remapper()},
2128 {GamepadId::kDragonRiseProduct0011, new TwoAxesEightKeysRemapper()},
2129 {GamepadId::kGoogleProduct2c40, new ADT1Remapper()},
2130 {GamepadId::kGoogleProduct9400, new StadiaControllerRemapper()},
2131 {GamepadId::kLogitechProductc216, new LogitechDInputRemapper()},
2132 {GamepadId::kLogitechProductc218, new LogitechDInputRemapper()},
2133 {GamepadId::kLogitechProductc219, new LogitechDInputRemapper()},
2134 {GamepadId::kMicrosoftProductXbox360Wireless, new Xbox360Remapper()},
2135 {GamepadId::kMicrosoftProductXbox360Wireless2, new Xbox360Remapper()},
2136 {GamepadId::kMicrosoftProductXboxOneElite2Wireless,
2137 new XboxOneRemapper()},
2138 {GamepadId::kMicrosoftProductXboxOneSWireless, new XboxOneSRemapper()},
2139 {GamepadId::kMicrosoftProductXboxOneSWireless2016,
2140 new XboxOneS2016FirmwareRemapper()},
2141 {GamepadId::kMicrosoftProductXboxAdaptiveWireless, new XboxOneRemapper()},
2142 {GamepadId::kMicrosoftProductXboxSeriesXWireless,
2143 new XboxSeriesXRemapper()},
2144 {GamepadId::kNintendoProduct2006, new SwitchJoyConRemapper()},
2145 {GamepadId::kNintendoProduct2007, new SwitchJoyConRemapper()},
2146 {GamepadId::kNintendoProduct2009, new SwitchProRemapper()},
2147 {GamepadId::kNintendoProduct200e, new SwitchProRemapper()},
2148 {GamepadId::kNvidiaProduct7210, new NvShieldRemapper()},
2149 {GamepadId::kNvidiaProduct7214, new NvShield2017Remapper()},
2150 {GamepadId::kPadixProduct2060, new IBuffaloRemapper()},
2151 {GamepadId::kPlayComProduct0005, new XSkillsRemapper()},
2152 {GamepadId::kPrototypeVendorProduct0667, new BoomN64PsxRemapper()},
2153 {GamepadId::kPrototypeVendorProduct9401,
2154 new StadiaControllerOldFirmwareRemapper()},
2155 {GamepadId::kRazer1532Product0900, new RazerServalRemapper()},
2156 {GamepadId::kSonyProduct0268, new Playstation3Remapper()},
2157 {GamepadId::kSonyProduct05c4, new Dualshock4Remapper()},
2158 {GamepadId::kSonyProduct09cc, new Dualshock4Remapper()},
2159 {GamepadId::kSonyProduct0ba0, new Dualshock4Remapper()},
2160 {GamepadId::kVendor20d6Product6271, new MogaProRemapper()},
2161 {GamepadId::kVendor2378Product1008, new OnLiveWirelessRemapper()},
2162 {GamepadId::kVendor2378Product100a, new OnLiveWirelessRemapper()},
2163 {GamepadId::kVendor2836Product0001, new OUYARemapper()}};
2164 const GamepadId id = static_cast<GamepadId>((aVendorId << 16) | aProductId);
2166 for (uint32_t i = 0; i < remappingRules.size(); ++i) {
2167 if (id == remappingRules[i].id) {
2168 aUsingDefault = false;
2169 return do_AddRef(remappingRules[i].remapping.get());
2173 RefPtr<GamepadRemapper> defaultRemapper = new DefaultRemapper();
2174 aUsingDefault = true;
2175 return do_AddRef(defaultRemapper.get());
2178 } // namespace mozilla::dom