GamepadRemapping.cpp (71952B)
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/. */ 6 7 // Based on 8 // https://cs.chromium.org/chromium/src/device/gamepad/gamepad_standard_mappings.h 9 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. 13 14 #include "mozilla/dom/GamepadRemapping.h" 15 16 #include <unordered_map> 17 #include <vector> 18 19 #include "mozilla/dom/GamepadPlatformService.h" 20 21 namespace mozilla::dom { 22 23 const float BUTTON_THRESHOLD_VALUE = 0.1f; 24 25 float NormalizeTouch(long aValue, long aMin, long aMax) { 26 return (2.f * (aValue - aMin) / static_cast<float>(aMax - aMin)) - 1.f; 27 } 28 29 double AxisToButtonValue(double aValue) { 30 // Mapping axis value range from (-1, +1) to (0, +1). 31 return (aValue + 1.0f) * 0.5f; 32 } 33 34 void FetchDpadFromAxis(GamepadHandle aHandle, double dir) { 35 bool up = false; 36 bool right = false; 37 bool down = false; 38 bool left = false; 39 40 // Dpad is mapped as a direction on one axis, where -1 is up and it 41 // increases clockwise to 1, which is up + left. It's set to a large (> 1.f) 42 // number when nothing is depressed, except on start up, sometimes it's 0.0 43 // for no data, rather than the large number. 44 if (dir != 0.0f) { 45 up = (dir >= -1.f && dir < -0.7f) || (dir >= .95f && dir <= 1.f); 46 right = dir >= -.75f && dir < -.1f; 47 down = dir >= -.2f && dir < .45f; 48 left = dir >= .4f && dir <= 1.f; 49 } 50 51 RefPtr<GamepadPlatformService> service = 52 GamepadPlatformService::GetParentService(); 53 if (!service) { 54 return; 55 } 56 57 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_UP, up); 58 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_RIGHT, right); 59 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_DOWN, down); 60 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_LEFT, left); 61 } 62 63 class DefaultRemapper final : public GamepadRemapper { 64 public: 65 virtual uint32_t GetAxisCount() const override { return numAxes; } 66 67 virtual uint32_t GetButtonCount() const override { return numButtons; } 68 69 virtual void SetAxisCount(uint32_t aAxisCount) override { 70 numAxes = aAxisCount; 71 } 72 73 virtual void SetButtonCount(uint32_t aButtonCount) override { 74 numButtons = aButtonCount; 75 } 76 77 virtual GamepadMappingType GetMappingType() const override { 78 return GamepadMappingType::_empty; 79 } 80 81 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 82 double aValue) const override { 83 if (GetAxisCount() <= aAxis) { 84 NS_WARNING( 85 nsPrintfCString("Axis idx '%d' doesn't support in DefaultRemapper().", 86 aAxis) 87 .get()); 88 return; 89 } 90 RefPtr<GamepadPlatformService> service = 91 GamepadPlatformService::GetParentService(); 92 if (!service) { 93 return; 94 } 95 service->NewAxisMoveEvent(aHandle, aAxis, aValue); 96 } 97 98 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 99 bool aPressed) const override { 100 if (GetButtonCount() <= aButton) { 101 NS_WARNING( 102 nsPrintfCString( 103 "Button idx '%d' doesn't support in DefaultRemapper().", aButton) 104 .get()); 105 return; 106 } 107 RefPtr<GamepadPlatformService> service = 108 GamepadPlatformService::GetParentService(); 109 if (!service) { 110 return; 111 } 112 service->NewButtonEvent(aHandle, aButton, aPressed); 113 } 114 115 private: 116 uint32_t numAxes; 117 uint32_t numButtons; 118 }; 119 120 class ADT1Remapper final : public GamepadRemapper { 121 public: 122 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 123 124 virtual uint32_t GetButtonCount() const override { 125 return BUTTON_INDEX_COUNT; 126 } 127 128 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 129 double aValue) const override { 130 RefPtr<GamepadPlatformService> service = 131 GamepadPlatformService::GetParentService(); 132 if (!service) { 133 return; 134 } 135 136 switch (aAxis) { 137 case 0: 138 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 139 break; 140 case 1: 141 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 142 break; 143 case 2: 144 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 145 break; 146 case 3: { 147 const double value = AxisToButtonValue(aValue); 148 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 149 value > BUTTON_THRESHOLD_VALUE, value); 150 break; 151 } 152 case 4: { 153 const double value = AxisToButtonValue(aValue); 154 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 155 value > BUTTON_THRESHOLD_VALUE, value); 156 break; 157 } 158 case 5: 159 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 160 break; 161 case 9: 162 FetchDpadFromAxis(aHandle, aValue); 163 break; 164 default: 165 NS_WARNING( 166 nsPrintfCString("Axis idx '%d' doesn't support in ADT1Remapper().", 167 aAxis) 168 .get()); 169 break; 170 } 171 } 172 173 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 174 bool aPressed) const override { 175 RefPtr<GamepadPlatformService> service = 176 GamepadPlatformService::GetParentService(); 177 if (!service) { 178 return; 179 } 180 181 if (GetButtonCount() <= aButton) { 182 NS_WARNING( 183 nsPrintfCString("Button idx '%d' doesn't support in ADT1Remapper().", 184 aButton) 185 .get()); 186 return; 187 } 188 189 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 190 {3, BUTTON_INDEX_TERTIARY}, 191 {4, BUTTON_INDEX_QUATERNARY}, 192 {6, BUTTON_INDEX_LEFT_SHOULDER}, 193 {7, BUTTON_INDEX_RIGHT_SHOULDER}, 194 {12, BUTTON_INDEX_META}, 195 {13, BUTTON_INDEX_LEFT_THUMBSTICK}, 196 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}}; 197 198 auto find = buttonMapping.find(aButton); 199 if (find != buttonMapping.end()) { 200 service->NewButtonEvent(aHandle, find->second, aPressed); 201 } else { 202 service->NewButtonEvent(aHandle, aButton, aPressed); 203 } 204 } 205 }; 206 207 class TwoAxesEightKeysRemapper final : public GamepadRemapper { 208 public: 209 virtual uint32_t GetAxisCount() const override { return 0; } 210 211 virtual uint32_t GetButtonCount() const override { 212 return BUTTON_INDEX_COUNT - 1; 213 } 214 215 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 216 double aValue) const override { 217 RefPtr<GamepadPlatformService> service = 218 GamepadPlatformService::GetParentService(); 219 if (!service) { 220 return; 221 } 222 223 switch (aAxis) { 224 case 0: 225 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_LEFT, 226 AxisNegativeAsButton(aValue)); 227 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_RIGHT, 228 AxisPositiveAsButton(aValue)); 229 break; 230 case 1: 231 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_UP, 232 AxisNegativeAsButton(aValue)); 233 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_DOWN, 234 AxisPositiveAsButton(aValue)); 235 break; 236 default: 237 NS_WARNING( 238 nsPrintfCString( 239 "Axis idx '%d' doesn't support in TwoAxesEightKeysRemapper().", 240 aAxis) 241 .get()); 242 break; 243 } 244 } 245 246 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 247 bool aPressed) const override { 248 RefPtr<GamepadPlatformService> service = 249 GamepadPlatformService::GetParentService(); 250 if (!service) { 251 return; 252 } 253 254 if (GetButtonCount() <= aButton) { 255 NS_WARNING( 256 nsPrintfCString( 257 "Button idx '%d' doesn't support in TwoAxesEightKeysRemapper().", 258 aButton) 259 .get()); 260 return; 261 } 262 263 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 264 {0, BUTTON_INDEX_QUATERNARY}, 265 {2, BUTTON_INDEX_PRIMARY}, 266 {3, BUTTON_INDEX_TERTIARY}}; 267 268 auto find = buttonMapping.find(aButton); 269 if (find != buttonMapping.end()) { 270 service->NewButtonEvent(aHandle, find->second, aPressed); 271 } else { 272 service->NewButtonEvent(aHandle, aButton, aPressed); 273 } 274 } 275 }; 276 277 class StadiaControllerRemapper final : public GamepadRemapper { 278 public: 279 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 280 281 virtual uint32_t GetButtonCount() const override { 282 return STADIA_BUTTON_COUNT; 283 } 284 285 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 286 double aValue) const override { 287 RefPtr<GamepadPlatformService> service = 288 GamepadPlatformService::GetParentService(); 289 if (!service) { 290 return; 291 } 292 293 switch (aAxis) { 294 case 0: 295 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 296 break; 297 case 1: 298 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 299 break; 300 case 2: 301 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 302 break; 303 case 3: 304 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 305 break; 306 case 4: { 307 const double value = AxisToButtonValue(aValue); 308 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 309 value > BUTTON_THRESHOLD_VALUE, value); 310 break; 311 } 312 case 5: { 313 const double value = AxisToButtonValue(aValue); 314 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 315 value > BUTTON_THRESHOLD_VALUE, value); 316 break; 317 } 318 default: 319 NS_WARNING( 320 nsPrintfCString( 321 "Axis idx '%d' doesn't support in StadiaControllerRemapper().", 322 aAxis) 323 .get()); 324 break; 325 } 326 } 327 328 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 329 bool aPressed) const override { 330 RefPtr<GamepadPlatformService> service = 331 GamepadPlatformService::GetParentService(); 332 if (!service) { 333 return; 334 } 335 336 if (STADIA_BUTTON_COUNT <= aButton) { 337 NS_WARNING( 338 nsPrintfCString( 339 "Button idx '%d' doesn't support in StadiaControllerRemapper().", 340 aButton) 341 .get()); 342 return; 343 } 344 345 service->NewButtonEvent(aHandle, aButton, aPressed); 346 } 347 348 private: 349 enum STADIAButtons { 350 STADIA_BUTTON_EXTRA1 = BUTTON_INDEX_COUNT, 351 STADIA_BUTTON_EXTRA2, 352 STADIA_BUTTON_COUNT 353 }; 354 }; 355 356 class Playstation3Remapper final : public GamepadRemapper { 357 public: 358 Playstation3Remapper() = default; 359 360 uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 361 362 uint32_t GetButtonCount() const override { return BUTTON_INDEX_COUNT; } 363 364 void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 365 double aValue) const override { 366 RefPtr<GamepadPlatformService> service = 367 GamepadPlatformService::GetParentService(); 368 if (!service) { 369 return; 370 } 371 372 switch (aAxis) { 373 case 0: 374 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 375 break; 376 case 1: 377 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 378 break; 379 case 2: 380 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 381 break; 382 case 5: 383 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 384 break; 385 default: 386 NS_WARNING( 387 nsPrintfCString( 388 "Axis idx '%d' doesn't support in Playstation3Remapper().", 389 aAxis) 390 .get()); 391 break; 392 } 393 } 394 395 void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 396 bool aPressed) const override { 397 RefPtr<GamepadPlatformService> service = 398 GamepadPlatformService::GetParentService(); 399 if (!service) { 400 return; 401 } 402 403 constexpr std::array buttonMapping = {BUTTON_INDEX_BACK_SELECT, 404 BUTTON_INDEX_LEFT_THUMBSTICK, 405 BUTTON_INDEX_RIGHT_THUMBSTICK, 406 BUTTON_INDEX_START, 407 BUTTON_INDEX_DPAD_UP, 408 BUTTON_INDEX_DPAD_RIGHT, 409 BUTTON_INDEX_DPAD_DOWN, 410 BUTTON_INDEX_DPAD_LEFT, 411 BUTTON_INDEX_LEFT_TRIGGER, 412 BUTTON_INDEX_RIGHT_TRIGGER, 413 BUTTON_INDEX_LEFT_SHOULDER, 414 BUTTON_INDEX_RIGHT_SHOULDER, 415 BUTTON_INDEX_QUATERNARY, 416 BUTTON_INDEX_SECONDARY, 417 BUTTON_INDEX_PRIMARY, 418 BUTTON_INDEX_TERTIARY, 419 BUTTON_INDEX_META}; 420 421 if (buttonMapping.size() <= aButton) { 422 NS_WARNING( 423 nsPrintfCString( 424 "Button idx '%d' doesn't support in Playstation3Remapper().", 425 aButton) 426 .get()); 427 return; 428 } 429 service->NewButtonEvent(aHandle, buttonMapping[aButton], aPressed); 430 } 431 }; 432 433 class Dualshock4Remapper final : public GamepadRemapper { 434 public: 435 Dualshock4Remapper() { 436 mLastTouches.SetLength(TOUCH_EVENT_COUNT); 437 mLastTouchId.SetLength(TOUCH_EVENT_COUNT); 438 } 439 440 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 441 442 virtual uint32_t GetButtonCount() const override { 443 return DUALSHOCK_BUTTON_COUNT; 444 } 445 446 virtual uint32_t GetLightIndicatorCount() const override { 447 return LIGHT_INDICATOR_COUNT; 448 } 449 450 virtual void GetLightIndicators( 451 nsTArray<GamepadLightIndicatorType>& aTypes) const override { 452 const uint32_t len = GetLightIndicatorCount(); 453 aTypes.SetLength(len); 454 for (uint32_t i = 0; i < len; ++i) { 455 aTypes[i] = GamepadLightIndicatorType::Rgb; 456 } 457 } 458 459 virtual uint32_t GetTouchEventCount() const override { 460 return TOUCH_EVENT_COUNT; 461 } 462 463 virtual void GetLightColorReport( 464 uint8_t aRed, uint8_t aGreen, uint8_t aBlue, 465 std::vector<uint8_t>& aReport) const override { 466 const size_t report_length = 32; 467 aReport.resize(report_length); 468 aReport.assign(report_length, 0); 469 470 aReport[0] = 0x05; // report ID USB only 471 aReport[1] = 0x02; // LED only 472 aReport[6] = aRed; 473 aReport[7] = aGreen; 474 aReport[8] = aBlue; 475 } 476 477 virtual uint32_t GetMaxInputReportLength() const override { 478 return MAX_INPUT_LEN; 479 } 480 481 virtual void ProcessTouchData(GamepadHandle aHandle, void* aInput) override { 482 nsTArray<GamepadTouchState> touches(TOUCH_EVENT_COUNT); 483 touches.SetLength(TOUCH_EVENT_COUNT); 484 uint8_t* rawData = (uint8_t*)aInput; 485 486 const uint32_t kTouchDimensionX = 1920; 487 const uint32_t kTouchDimensionY = 942; 488 bool touch0Pressed = (((rawData[35] & 0xff) >> 7) == 0); 489 bool touch1Pressed = (((rawData[39] & 0xff) >> 7) == 0); 490 491 if ((touch0Pressed && (rawData[35] & 0xff) < mLastTouchId[0]) || 492 (touch1Pressed && (rawData[39] & 0xff) < mLastTouchId[1])) { 493 mTouchIdBase += 128; 494 } 495 496 if (touch0Pressed) { 497 touches[0].touchId = mTouchIdBase + (rawData[35] & 0x7f); 498 touches[0].surfaceId = 0; 499 touches[0].position[0] = NormalizeTouch( 500 ((rawData[37] & 0xf) << 8) | rawData[36], 0, (kTouchDimensionX - 1)); 501 touches[0].position[1] = 502 NormalizeTouch(rawData[38] << 4 | ((rawData[37] & 0xf0) >> 4), 0, 503 (kTouchDimensionY - 1)); 504 touches[0].surfaceDimensions[0] = kTouchDimensionX; 505 touches[0].surfaceDimensions[1] = kTouchDimensionY; 506 touches[0].isSurfaceDimensionsValid = true; 507 mLastTouchId[0] = rawData[35] & 0x7f; 508 } 509 if (touch1Pressed) { 510 touches[1].touchId = mTouchIdBase + (rawData[39] & 0x7f); 511 touches[1].surfaceId = 0; 512 touches[1].position[0] = 513 NormalizeTouch((((rawData[41] & 0xf) << 8) | rawData[40]) + 1, 0, 514 (kTouchDimensionX - 1)); 515 touches[1].position[1] = 516 NormalizeTouch(rawData[42] << 4 | ((rawData[41] & 0xf0) >> 4), 0, 517 (kTouchDimensionY - 1)); 518 touches[1].surfaceDimensions[0] = kTouchDimensionX; 519 touches[1].surfaceDimensions[1] = kTouchDimensionY; 520 touches[1].isSurfaceDimensionsValid = true; 521 mLastTouchId[1] = rawData[39] & 0x7f; 522 } 523 524 RefPtr<GamepadPlatformService> service = 525 GamepadPlatformService::GetParentService(); 526 if (!service) { 527 return; 528 } 529 530 // Avoid to send duplicate untouched events to the gamepad service. 531 if ((mLastTouches[0] != touch0Pressed) || touch0Pressed) { 532 service->NewMultiTouchEvent(aHandle, 0, touches[0]); 533 } 534 if ((mLastTouches[1] != touch1Pressed) || touch1Pressed) { 535 service->NewMultiTouchEvent(aHandle, 1, touches[1]); 536 } 537 mLastTouches[0] = touch0Pressed; 538 mLastTouches[1] = touch1Pressed; 539 } 540 541 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 542 double aValue) const override { 543 RefPtr<GamepadPlatformService> service = 544 GamepadPlatformService::GetParentService(); 545 if (!service) { 546 return; 547 } 548 549 switch (aAxis) { 550 case 0: 551 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 552 break; 553 case 1: 554 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 555 break; 556 case 2: 557 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 558 break; 559 case 3: { 560 const double value = AxisToButtonValue(aValue); 561 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 562 value > BUTTON_THRESHOLD_VALUE, value); 563 break; 564 } 565 case 4: { 566 const double value = AxisToButtonValue(aValue); 567 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 568 value > BUTTON_THRESHOLD_VALUE, value); 569 break; 570 } 571 case 5: 572 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 573 break; 574 case 9: 575 FetchDpadFromAxis(aHandle, aValue); 576 break; 577 default: 578 NS_WARNING( 579 nsPrintfCString( 580 "Axis idx '%d' doesn't support in Dualshock4Remapper().", aAxis) 581 .get()); 582 break; 583 } 584 } 585 586 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 587 bool aPressed) const override { 588 RefPtr<GamepadPlatformService> service = 589 GamepadPlatformService::GetParentService(); 590 if (!service) { 591 return; 592 } 593 594 constexpr std::array<uint32_t, 14> buttonMapping = { 595 BUTTON_INDEX_TERTIARY, 596 BUTTON_INDEX_PRIMARY, 597 BUTTON_INDEX_SECONDARY, 598 BUTTON_INDEX_QUATERNARY, 599 BUTTON_INDEX_LEFT_SHOULDER, 600 BUTTON_INDEX_RIGHT_SHOULDER, 601 BUTTON_INDEX_LEFT_TRIGGER, 602 BUTTON_INDEX_RIGHT_TRIGGER, 603 BUTTON_INDEX_BACK_SELECT, 604 BUTTON_INDEX_START, 605 BUTTON_INDEX_LEFT_THUMBSTICK, 606 BUTTON_INDEX_RIGHT_THUMBSTICK, 607 BUTTON_INDEX_META, 608 DUALSHOCK_BUTTON_TOUCHPAD}; 609 610 if (buttonMapping.size() <= aButton) { 611 NS_WARNING(nsPrintfCString( 612 "Button idx '%d' doesn't support in Dualshock4Remapper().", 613 aButton) 614 .get()); 615 return; 616 } 617 618 service->NewButtonEvent(aHandle, buttonMapping[aButton], aPressed); 619 } 620 621 private: 622 enum Dualshock4Buttons { 623 DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT, 624 DUALSHOCK_BUTTON_COUNT 625 }; 626 627 static const uint32_t LIGHT_INDICATOR_COUNT = 1; 628 static const uint32_t TOUCH_EVENT_COUNT = 2; 629 static const uint32_t MAX_INPUT_LEN = 68; 630 631 nsTArray<unsigned long> mLastTouchId; 632 nsTArray<bool> mLastTouches; 633 unsigned long mTouchIdBase = 0; 634 }; 635 636 class Xbox360Remapper final : public GamepadRemapper { 637 public: 638 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 639 640 virtual uint32_t GetButtonCount() const override { 641 return BUTTON_INDEX_COUNT; 642 } 643 644 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 645 double aValue) const override { 646 RefPtr<GamepadPlatformService> service = 647 GamepadPlatformService::GetParentService(); 648 if (!service) { 649 return; 650 } 651 652 switch (aAxis) { 653 case 0: 654 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 655 break; 656 case 1: 657 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 658 break; 659 case 2: { 660 const double value = AxisToButtonValue(aValue); 661 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 662 value > BUTTON_THRESHOLD_VALUE, value); 663 break; 664 } 665 case 3: 666 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 667 break; 668 case 4: 669 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 670 break; 671 case 5: { 672 const double value = AxisToButtonValue(aValue); 673 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 674 value > BUTTON_THRESHOLD_VALUE, value); 675 break; 676 } 677 default: 678 NS_WARNING( 679 nsPrintfCString( 680 "Axis idx '%d' doesn't support in Xbox360Remapper().", aAxis) 681 .get()); 682 break; 683 } 684 } 685 686 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 687 bool aPressed) const override { 688 RefPtr<GamepadPlatformService> service = 689 GamepadPlatformService::GetParentService(); 690 if (!service) { 691 return; 692 } 693 694 if (GetButtonCount() <= aButton) { 695 NS_WARNING( 696 nsPrintfCString( 697 "Button idx '%d' doesn't support in Xbox360Remapper().", aButton) 698 .get()); 699 return; 700 } 701 702 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 703 {6, BUTTON_INDEX_LEFT_THUMBSTICK}, {7, BUTTON_INDEX_RIGHT_THUMBSTICK}, 704 {8, BUTTON_INDEX_START}, {9, BUTTON_INDEX_BACK_SELECT}, 705 {10, BUTTON_INDEX_META}, {11, BUTTON_INDEX_DPAD_UP}, 706 {12, BUTTON_INDEX_DPAD_DOWN}, {13, BUTTON_INDEX_DPAD_LEFT}, 707 {14, BUTTON_INDEX_DPAD_RIGHT}}; 708 709 auto find = buttonMapping.find(aButton); 710 if (find != buttonMapping.end()) { 711 service->NewButtonEvent(aHandle, find->second, aPressed); 712 } else { 713 service->NewButtonEvent(aHandle, aButton, aPressed); 714 } 715 } 716 }; 717 718 class XboxOneSRemapper final : public GamepadRemapper { 719 public: 720 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 721 722 virtual uint32_t GetButtonCount() const override { 723 return BUTTON_INDEX_COUNT; 724 } 725 726 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 727 double aValue) const override { 728 RefPtr<GamepadPlatformService> service = 729 GamepadPlatformService::GetParentService(); 730 if (!service) { 731 return; 732 } 733 734 switch (aAxis) { 735 case 0: 736 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 737 break; 738 case 1: 739 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 740 break; 741 case 2: { 742 const double value = AxisToButtonValue(aValue); 743 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 744 value > BUTTON_THRESHOLD_VALUE, value); 745 break; 746 } 747 case 3: 748 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 749 break; 750 case 4: 751 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 752 break; 753 case 5: { 754 const double value = AxisToButtonValue(aValue); 755 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 756 value > BUTTON_THRESHOLD_VALUE, value); 757 break; 758 } 759 case 9: 760 FetchDpadFromAxis(aHandle, aValue); 761 break; 762 default: 763 NS_WARNING( 764 nsPrintfCString( 765 "Axis idx '%d' doesn't support in XboxOneSRemapper().", aAxis) 766 .get()); 767 break; 768 } 769 } 770 771 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 772 bool aPressed) const override { 773 RefPtr<GamepadPlatformService> service = 774 GamepadPlatformService::GetParentService(); 775 if (!service) { 776 return; 777 } 778 779 if (GetButtonCount() <= aButton) { 780 NS_WARNING( 781 nsPrintfCString( 782 "Button idx '%d' doesn't support in XboxOneSRemapper().", aButton) 783 .get()); 784 return; 785 } 786 787 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 788 {6, BUTTON_INDEX_BACK_SELECT}, 789 {7, BUTTON_INDEX_START}, 790 {8, BUTTON_INDEX_LEFT_THUMBSTICK}, 791 {9, BUTTON_INDEX_RIGHT_THUMBSTICK}, 792 {10, BUTTON_INDEX_META}}; 793 794 auto find = buttonMapping.find(aButton); 795 if (find != buttonMapping.end()) { 796 service->NewButtonEvent(aHandle, find->second, aPressed); 797 } else { 798 service->NewButtonEvent(aHandle, aButton, aPressed); 799 } 800 } 801 }; 802 803 class XboxOneS2016FirmwareRemapper final : public GamepadRemapper { 804 public: 805 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 806 807 virtual uint32_t GetButtonCount() const override { 808 return BUTTON_INDEX_COUNT; 809 } 810 811 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 812 double aValue) const override { 813 RefPtr<GamepadPlatformService> service = 814 GamepadPlatformService::GetParentService(); 815 if (!service) { 816 return; 817 } 818 819 switch (aAxis) { 820 case 0: 821 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 822 break; 823 case 1: 824 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 825 break; 826 case 2: 827 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 828 break; 829 case 3: { 830 const double value = AxisToButtonValue(aValue); 831 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 832 value > BUTTON_THRESHOLD_VALUE, value); 833 break; 834 } 835 case 4: { 836 const double value = AxisToButtonValue(aValue); 837 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 838 value > BUTTON_THRESHOLD_VALUE, value); 839 break; 840 } 841 case 5: 842 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 843 break; 844 case 9: 845 FetchDpadFromAxis(aHandle, aValue); 846 break; 847 default: 848 NS_WARNING(nsPrintfCString("Axis idx '%d' doesn't support in " 849 "XboxOneS2016FirmwareRemapper().", 850 aAxis) 851 .get()); 852 break; 853 } 854 } 855 856 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 857 bool aPressed) const override { 858 RefPtr<GamepadPlatformService> service = 859 GamepadPlatformService::GetParentService(); 860 if (!service) { 861 return; 862 } 863 864 if (GetButtonCount() <= aButton) { 865 NS_WARNING(nsPrintfCString("Button idx '%d' doesn't support in " 866 "XboxOneS2016FirmwareRemapper().", 867 aButton) 868 .get()); 869 return; 870 } 871 872 // kMicrosoftProductXboxOneSWireless2016 controller received a firmware 873 // update in 2019 that changed which field is populated with the meta button 874 // state. In order to cover the old and new cases, we have to check both 875 // fields of {12, 15} buttons. 876 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 877 {0, BUTTON_INDEX_PRIMARY}, 878 {1, BUTTON_INDEX_SECONDARY}, 879 {3, BUTTON_INDEX_TERTIARY}, 880 {4, BUTTON_INDEX_QUATERNARY}, 881 {6, BUTTON_INDEX_LEFT_SHOULDER}, 882 {7, BUTTON_INDEX_RIGHT_SHOULDER}, 883 {11, BUTTON_INDEX_START}, 884 {12, BUTTON_INDEX_META}, 885 {13, BUTTON_INDEX_LEFT_THUMBSTICK}, 886 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}, 887 {15, BUTTON_INDEX_META}, 888 {16, BUTTON_INDEX_BACK_SELECT}}; 889 890 auto find = buttonMapping.find(aButton); 891 if (find != buttonMapping.end()) { 892 service->NewButtonEvent(aHandle, find->second, aPressed); 893 } else { 894 service->NewButtonEvent(aHandle, aButton, aPressed); 895 } 896 } 897 }; 898 899 class XboxOneRemapper final : public GamepadRemapper { 900 public: 901 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 902 903 virtual uint32_t GetButtonCount() const override { 904 return BUTTON_INDEX_COUNT; 905 } 906 907 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 908 double aValue) const override { 909 RefPtr<GamepadPlatformService> service = 910 GamepadPlatformService::GetParentService(); 911 if (!service) { 912 return; 913 } 914 915 switch (aAxis) { 916 case 0: 917 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 918 break; 919 case 1: 920 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 921 break; 922 case 2: 923 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 924 break; 925 case 3: 926 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 927 break; 928 case 9: 929 FetchDpadFromAxis(aHandle, aValue); 930 break; 931 case 10: { 932 const double value = AxisToButtonValue(aValue); 933 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 934 value > BUTTON_THRESHOLD_VALUE, value); 935 break; 936 } 937 case 11: { 938 const double value = AxisToButtonValue(aValue); 939 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 940 value > BUTTON_THRESHOLD_VALUE, value); 941 break; 942 } 943 default: 944 NS_WARNING( 945 nsPrintfCString( 946 "Axis idx '%d' doesn't support in XboxOneRemapper().", aAxis) 947 .get()); 948 break; 949 } 950 } 951 952 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 953 bool aPressed) const override { 954 RefPtr<GamepadPlatformService> service = 955 GamepadPlatformService::GetParentService(); 956 if (!service) { 957 return; 958 } 959 960 if (GetButtonCount() <= aButton) { 961 NS_WARNING( 962 nsPrintfCString( 963 "Button idx '%d' doesn't support in XboxOneRemapper().", aButton) 964 .get()); 965 return; 966 } 967 968 // Accessing {30, 31} buttons looks strange to me 969 // and without an avilable device to help verify it. 970 // It is according to `MapperXboxOneBluetooth()` in 971 // https://cs.chromium.org/chromium/src/device/gamepad/gamepad_standard_mappings_mac.mm 972 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 973 {0, BUTTON_INDEX_PRIMARY}, 974 {1, BUTTON_INDEX_SECONDARY}, 975 {3, BUTTON_INDEX_TERTIARY}, 976 {4, BUTTON_INDEX_QUATERNARY}, 977 {6, BUTTON_INDEX_LEFT_SHOULDER}, 978 {7, BUTTON_INDEX_RIGHT_SHOULDER}, 979 {11, BUTTON_INDEX_START}, 980 {13, BUTTON_INDEX_LEFT_THUMBSTICK}, 981 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}, 982 {30, BUTTON_INDEX_META}, 983 {31, BUTTON_INDEX_BACK_SELECT}}; 984 985 auto find = buttonMapping.find(aButton); 986 if (find != buttonMapping.end()) { 987 service->NewButtonEvent(aHandle, find->second, aPressed); 988 } else { 989 service->NewButtonEvent(aHandle, aButton, aPressed); 990 } 991 } 992 }; 993 994 class XboxSeriesXRemapper final : public GamepadRemapper { 995 public: 996 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 997 998 virtual uint32_t GetButtonCount() const override { 999 return BUTTON_INDEX_COUNT; 1000 } 1001 1002 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1003 double aValue) const override { 1004 RefPtr<GamepadPlatformService> service = 1005 GamepadPlatformService::GetParentService(); 1006 if (!service) { 1007 return; 1008 } 1009 1010 switch (aAxis) { 1011 case 0: 1012 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1013 break; 1014 case 1: 1015 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1016 break; 1017 case 2: 1018 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 1019 break; 1020 case 5: 1021 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 1022 break; 1023 case 9: 1024 FetchDpadFromAxis(aHandle, aValue); 1025 break; 1026 case 148: { 1027 const double value = AxisToButtonValue(aValue); 1028 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 1029 value > BUTTON_THRESHOLD_VALUE, value); 1030 break; 1031 } 1032 case 149: { 1033 const double value = AxisToButtonValue(aValue); 1034 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 1035 value > BUTTON_THRESHOLD_VALUE, value); 1036 break; 1037 } 1038 default: 1039 NS_WARNING( 1040 nsPrintfCString( 1041 "Axis idx '%d' doesn't support in XboxSeriesXRemapper().", 1042 aAxis) 1043 .get()); 1044 break; 1045 } 1046 } 1047 1048 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1049 bool aPressed) const override { 1050 RefPtr<GamepadPlatformService> service = 1051 GamepadPlatformService::GetParentService(); 1052 if (!service) { 1053 return; 1054 } 1055 1056 if (GetButtonCount() <= aButton) { 1057 NS_WARNING( 1058 nsPrintfCString( 1059 "Button idx '%d' doesn't support in XboxSeriesXRemapper().", 1060 aButton) 1061 .get()); 1062 return; 1063 } 1064 1065 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 1066 {0, BUTTON_INDEX_PRIMARY}, 1067 {1, BUTTON_INDEX_SECONDARY}, 1068 {3, BUTTON_INDEX_TERTIARY}, 1069 {4, BUTTON_INDEX_QUATERNARY}, 1070 {6, BUTTON_INDEX_LEFT_SHOULDER}, 1071 {7, BUTTON_INDEX_RIGHT_SHOULDER}, 1072 {10, BUTTON_INDEX_BACK_SELECT}, 1073 {11, BUTTON_INDEX_START}, 1074 {12, BUTTON_INDEX_META}, 1075 {13, BUTTON_INDEX_LEFT_THUMBSTICK}, 1076 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}}; 1077 1078 auto find = buttonMapping.find(aButton); 1079 if (find != buttonMapping.end()) { 1080 service->NewButtonEvent(aHandle, find->second, aPressed); 1081 } else { 1082 service->NewButtonEvent(aHandle, aButton, aPressed); 1083 } 1084 } 1085 }; 1086 1087 class LogitechDInputRemapper final : public GamepadRemapper { 1088 public: 1089 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 1090 1091 virtual uint32_t GetButtonCount() const override { 1092 // The Logitech button (BUTTON_INDEX_META) is not accessible through the 1093 // device's D-mode. 1094 return BUTTON_INDEX_COUNT - 1; 1095 } 1096 1097 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1098 double aValue) const override { 1099 RefPtr<GamepadPlatformService> service = 1100 GamepadPlatformService::GetParentService(); 1101 if (!service) { 1102 return; 1103 } 1104 1105 switch (aAxis) { 1106 case 0: 1107 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1108 break; 1109 case 1: 1110 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1111 break; 1112 case 2: 1113 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 1114 break; 1115 case 5: 1116 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 1117 break; 1118 case 9: 1119 FetchDpadFromAxis(aHandle, aValue); 1120 break; 1121 default: 1122 NS_WARNING( 1123 nsPrintfCString( 1124 "Axis idx '%d' doesn't support in LogitechDInputRemapper().", 1125 aAxis) 1126 .get()); 1127 break; 1128 } 1129 } 1130 1131 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1132 bool aPressed) const override { 1133 RefPtr<GamepadPlatformService> service = 1134 GamepadPlatformService::GetParentService(); 1135 if (!service) { 1136 return; 1137 } 1138 1139 if (GetButtonCount() <= aButton) { 1140 NS_WARNING( 1141 nsPrintfCString( 1142 "Button idx '%d' doesn't support in LogitechDInputRemapper().", 1143 aButton) 1144 .get()); 1145 return; 1146 } 1147 1148 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 1149 {0, BUTTON_INDEX_TERTIARY}, 1150 {1, BUTTON_INDEX_PRIMARY}, 1151 {2, BUTTON_INDEX_SECONDARY}}; 1152 1153 auto find = buttonMapping.find(aButton); 1154 if (find != buttonMapping.end()) { 1155 service->NewButtonEvent(aHandle, find->second, aPressed); 1156 } else { 1157 service->NewButtonEvent(aHandle, aButton, aPressed); 1158 } 1159 } 1160 }; 1161 1162 class SwitchJoyConRemapper final : public GamepadRemapper { 1163 public: 1164 virtual uint32_t GetAxisCount() const override { return 2; } 1165 1166 virtual uint32_t GetButtonCount() const override { 1167 return BUTTON_INDEX_COUNT; 1168 } 1169 1170 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1171 double aValue) const override { 1172 if (GetAxisCount() <= aAxis) { 1173 NS_WARNING( 1174 nsPrintfCString( 1175 "Axis idx '%d' doesn't support in SwitchJoyConRemapper().", aAxis) 1176 .get()); 1177 return; 1178 } 1179 RefPtr<GamepadPlatformService> service = 1180 GamepadPlatformService::GetParentService(); 1181 if (!service) { 1182 return; 1183 } 1184 1185 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1186 } 1187 1188 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1189 bool aPressed) const override { 1190 RefPtr<GamepadPlatformService> service = 1191 GamepadPlatformService::GetParentService(); 1192 if (!service) { 1193 return; 1194 } 1195 1196 service->NewButtonEvent(aHandle, aButton, aPressed); 1197 } 1198 }; 1199 1200 class SwitchProRemapper final : public GamepadRemapper { 1201 public: 1202 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 1203 1204 virtual uint32_t GetButtonCount() const override { 1205 // The Switch Pro controller has a Capture button that has no equivalent in 1206 // the Standard Gamepad. 1207 return SWITCHPRO_BUTTON_COUNT; 1208 } 1209 1210 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1211 double aValue) const override { 1212 if (GetAxisCount() <= aAxis) { 1213 NS_WARNING( 1214 nsPrintfCString( 1215 "Axis idx '%d' doesn't support in SwitchProRemapper().", aAxis) 1216 .get()); 1217 return; 1218 } 1219 RefPtr<GamepadPlatformService> service = 1220 GamepadPlatformService::GetParentService(); 1221 if (!service) { 1222 return; 1223 } 1224 1225 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1226 } 1227 1228 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1229 bool aPressed) const override { 1230 RefPtr<GamepadPlatformService> service = 1231 GamepadPlatformService::GetParentService(); 1232 if (!service) { 1233 return; 1234 } 1235 1236 service->NewButtonEvent(aHandle, aButton, aPressed); 1237 } 1238 1239 private: 1240 enum SwitchProButtons { 1241 SWITCHPRO_BUTTON_EXTRA = BUTTON_INDEX_COUNT, 1242 SWITCHPRO_BUTTON_COUNT 1243 }; 1244 }; 1245 1246 class NvShieldRemapper final : public GamepadRemapper { 1247 public: 1248 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 1249 1250 virtual uint32_t GetButtonCount() const override { 1251 return SHIELD_BUTTON_COUNT; 1252 } 1253 1254 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1255 double aValue) const override { 1256 RefPtr<GamepadPlatformService> service = 1257 GamepadPlatformService::GetParentService(); 1258 if (!service) { 1259 return; 1260 } 1261 1262 switch (aAxis) { 1263 case 0: 1264 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1265 break; 1266 case 1: 1267 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1268 break; 1269 case 2: 1270 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 1271 break; 1272 case 3: { 1273 const double value = AxisToButtonValue(aValue); 1274 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 1275 value > BUTTON_THRESHOLD_VALUE, value); 1276 break; 1277 } 1278 case 4: { 1279 const double value = AxisToButtonValue(aValue); 1280 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 1281 value > BUTTON_THRESHOLD_VALUE, value); 1282 break; 1283 } 1284 case 5: 1285 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 1286 break; 1287 case 9: 1288 FetchDpadFromAxis(aHandle, aValue); 1289 break; 1290 default: 1291 NS_WARNING( 1292 nsPrintfCString( 1293 "Axis idx '%d' doesn't support in NvShieldRemapper().", aAxis) 1294 .get()); 1295 break; 1296 } 1297 } 1298 1299 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1300 bool aPressed) const override { 1301 RefPtr<GamepadPlatformService> service = 1302 GamepadPlatformService::GetParentService(); 1303 if (!service) { 1304 return; 1305 } 1306 1307 if (GetButtonCount() <= aButton) { 1308 NS_WARNING( 1309 nsPrintfCString( 1310 "Button idx '%d' doesn't support in NvShieldRemapper().", aButton) 1311 .get()); 1312 return; 1313 } 1314 1315 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 1316 {2, BUTTON_INDEX_META}, 1317 {3, BUTTON_INDEX_TERTIARY}, 1318 {4, BUTTON_INDEX_QUATERNARY}, 1319 {5, SHIELD_BUTTON_CIRCLE}, 1320 {6, BUTTON_INDEX_LEFT_SHOULDER}, 1321 {7, BUTTON_INDEX_RIGHT_SHOULDER}, 1322 {9, BUTTON_INDEX_BACK_SELECT}, 1323 {11, BUTTON_INDEX_START}, 1324 {13, BUTTON_INDEX_LEFT_THUMBSTICK}, 1325 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}}; 1326 1327 auto find = buttonMapping.find(aButton); 1328 if (find != buttonMapping.end()) { 1329 service->NewButtonEvent(aHandle, find->second, aPressed); 1330 } else { 1331 service->NewButtonEvent(aHandle, aButton, aPressed); 1332 } 1333 } 1334 1335 private: 1336 enum ShieldButtons { 1337 SHIELD_BUTTON_CIRCLE = BUTTON_INDEX_COUNT, 1338 SHIELD_BUTTON_COUNT 1339 }; 1340 }; 1341 1342 class NvShield2017Remapper final : public GamepadRemapper { 1343 public: 1344 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 1345 1346 virtual uint32_t GetButtonCount() const override { 1347 return SHIELD2017_BUTTON_COUNT; 1348 } 1349 1350 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1351 double aValue) const override { 1352 RefPtr<GamepadPlatformService> service = 1353 GamepadPlatformService::GetParentService(); 1354 if (!service) { 1355 return; 1356 } 1357 1358 switch (aAxis) { 1359 case 0: 1360 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1361 break; 1362 case 1: 1363 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1364 break; 1365 case 2: 1366 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 1367 break; 1368 case 3: { 1369 const double value = AxisToButtonValue(aValue); 1370 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 1371 value > BUTTON_THRESHOLD_VALUE, value); 1372 break; 1373 } 1374 case 4: { 1375 const double value = AxisToButtonValue(aValue); 1376 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 1377 value > BUTTON_THRESHOLD_VALUE, value); 1378 break; 1379 } 1380 case 5: 1381 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 1382 break; 1383 case 9: 1384 FetchDpadFromAxis(aHandle, aValue); 1385 break; 1386 default: 1387 NS_WARNING( 1388 nsPrintfCString( 1389 "Axis idx '%d' doesn't support in NvShield2017Remapper().", 1390 aAxis) 1391 .get()); 1392 break; 1393 } 1394 } 1395 1396 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1397 bool aPressed) const override { 1398 RefPtr<GamepadPlatformService> service = 1399 GamepadPlatformService::GetParentService(); 1400 if (!service) { 1401 return; 1402 } 1403 1404 if (GetButtonCount() <= aButton) { 1405 NS_WARNING( 1406 nsPrintfCString( 1407 "Button idx '%d' doesn't support in NvShield2017Remapper().", 1408 aButton) 1409 .get()); 1410 return; 1411 } 1412 1413 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 1414 {2, BUTTON_INDEX_META}, 1415 {3, BUTTON_INDEX_TERTIARY}, 1416 {4, BUTTON_INDEX_QUATERNARY}, 1417 {5, BUTTON_INDEX_START}, 1418 {6, BUTTON_INDEX_LEFT_SHOULDER}, 1419 {7, BUTTON_INDEX_RIGHT_SHOULDER}, 1420 {8, BUTTON_INDEX_BACK_SELECT}, 1421 {11, SHIELD2017_BUTTON_PLAYPAUSE}, 1422 {13, BUTTON_INDEX_LEFT_THUMBSTICK}, 1423 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}}; 1424 1425 auto find = buttonMapping.find(aButton); 1426 if (find != buttonMapping.end()) { 1427 service->NewButtonEvent(aHandle, find->second, aPressed); 1428 } else { 1429 service->NewButtonEvent(aHandle, aButton, aPressed); 1430 } 1431 } 1432 1433 private: 1434 enum Shield2017Buttons { 1435 SHIELD2017_BUTTON_PLAYPAUSE = BUTTON_INDEX_COUNT, 1436 SHIELD2017_BUTTON_COUNT 1437 }; 1438 }; 1439 1440 class IBuffaloRemapper final : public GamepadRemapper { 1441 public: 1442 virtual uint32_t GetAxisCount() const override { return 2; } 1443 1444 virtual uint32_t GetButtonCount() const override { 1445 return BUTTON_INDEX_COUNT - 1; /* no meta */ 1446 } 1447 1448 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1449 double aValue) const override { 1450 RefPtr<GamepadPlatformService> service = 1451 GamepadPlatformService::GetParentService(); 1452 if (!service) { 1453 return; 1454 } 1455 1456 switch (aAxis) { 1457 case 0: 1458 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1459 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_LEFT, 1460 AxisNegativeAsButton(aValue)); 1461 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_RIGHT, 1462 AxisPositiveAsButton(aValue)); 1463 break; 1464 case 1: 1465 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1466 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_UP, 1467 AxisNegativeAsButton(aValue)); 1468 service->NewButtonEvent(aHandle, BUTTON_INDEX_DPAD_DOWN, 1469 AxisPositiveAsButton(aValue)); 1470 break; 1471 default: 1472 NS_WARNING( 1473 nsPrintfCString( 1474 "Axis idx '%d' doesn't support in IBuffaloRemapper().", aAxis) 1475 .get()); 1476 break; 1477 } 1478 } 1479 1480 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1481 bool aPressed) const override { 1482 RefPtr<GamepadPlatformService> service = 1483 GamepadPlatformService::GetParentService(); 1484 if (!service) { 1485 return; 1486 } 1487 1488 if (GetButtonCount() <= aButton) { 1489 NS_WARNING( 1490 nsPrintfCString( 1491 "Button idx '%d' doesn't support in IBuffaloRemapper().", aButton) 1492 .get()); 1493 return; 1494 } 1495 1496 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 1497 {0, BUTTON_INDEX_SECONDARY}, {1, BUTTON_INDEX_PRIMARY}, 1498 {2, BUTTON_INDEX_QUATERNARY}, {3, BUTTON_INDEX_TERTIARY}, 1499 {5, BUTTON_INDEX_RIGHT_TRIGGER}, {6, BUTTON_INDEX_BACK_SELECT}, 1500 {7, BUTTON_INDEX_START}}; 1501 1502 auto find = buttonMapping.find(aButton); 1503 if (find != buttonMapping.end()) { 1504 service->NewButtonEvent(aHandle, find->second, aPressed); 1505 } else { 1506 service->NewButtonEvent(aHandle, aButton, aPressed); 1507 } 1508 } 1509 }; 1510 1511 class XSkillsRemapper final : public GamepadRemapper { 1512 public: 1513 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 1514 1515 virtual uint32_t GetButtonCount() const override { 1516 return GAMECUBE_BUTTON_COUNT; 1517 } 1518 1519 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1520 double aValue) const override { 1521 RefPtr<GamepadPlatformService> service = 1522 GamepadPlatformService::GetParentService(); 1523 if (!service) { 1524 return; 1525 } 1526 1527 switch (aAxis) { 1528 case 0: 1529 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1530 break; 1531 case 1: 1532 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1533 break; 1534 case 2: 1535 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 1536 break; 1537 case 3: { 1538 const double value = AxisToButtonValue(aValue); 1539 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 1540 value > BUTTON_THRESHOLD_VALUE, value); 1541 break; 1542 } 1543 case 4: { 1544 const double value = AxisToButtonValue(aValue); 1545 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 1546 value > BUTTON_THRESHOLD_VALUE, value); 1547 break; 1548 } 1549 case 5: 1550 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 1551 break; 1552 default: 1553 NS_WARNING( 1554 nsPrintfCString( 1555 "Axis idx '%d' doesn't support in XSkillsRemapper().", aAxis) 1556 .get()); 1557 break; 1558 } 1559 } 1560 1561 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1562 bool aPressed) const override { 1563 RefPtr<GamepadPlatformService> service = 1564 GamepadPlatformService::GetParentService(); 1565 if (!service) { 1566 return; 1567 } 1568 1569 if (GetButtonCount() <= aButton) { 1570 NS_WARNING( 1571 nsPrintfCString( 1572 "Button idx '%d' doesn't support in XSkillsRemapper().", aButton) 1573 .get()); 1574 return; 1575 } 1576 1577 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 1578 {0, BUTTON_INDEX_PRIMARY}, // A 1579 {1, BUTTON_INDEX_TERTIARY}, // B 1580 {2, BUTTON_INDEX_SECONDARY}, // X 1581 {3, BUTTON_INDEX_QUATERNARY}, // Y 1582 {4, GAMECUBE_BUTTON_LEFT_TRIGGER_CLICK}, 1583 {5, GAMECUBE_BUTTON_RIGHT_TRIGGER_CLICK}, 1584 {6, BUTTON_INDEX_RIGHT_SHOULDER}, 1585 {7, BUTTON_INDEX_START}, 1586 {8, BUTTON_INDEX_DPAD_LEFT}, 1587 {9, BUTTON_INDEX_DPAD_RIGHT}, 1588 {10, BUTTON_INDEX_DPAD_DOWN}, 1589 {11, BUTTON_INDEX_DPAD_UP}}; 1590 1591 auto find = buttonMapping.find(aButton); 1592 if (find != buttonMapping.end()) { 1593 service->NewButtonEvent(aHandle, find->second, aPressed); 1594 } else { 1595 service->NewButtonEvent(aHandle, aButton, aPressed); 1596 } 1597 } 1598 1599 private: 1600 enum GamecubeButtons { 1601 GAMECUBE_BUTTON_LEFT_TRIGGER_CLICK = BUTTON_INDEX_COUNT, 1602 GAMECUBE_BUTTON_RIGHT_TRIGGER_CLICK, 1603 GAMECUBE_BUTTON_COUNT 1604 }; 1605 }; 1606 1607 class BoomN64PsxRemapper final : public GamepadRemapper { 1608 public: 1609 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 1610 1611 virtual uint32_t GetButtonCount() const override { 1612 return BUTTON_INDEX_COUNT - 1; // no meta 1613 } 1614 1615 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1616 double aValue) const override { 1617 RefPtr<GamepadPlatformService> service = 1618 GamepadPlatformService::GetParentService(); 1619 if (!service) { 1620 return; 1621 } 1622 1623 switch (aAxis) { 1624 case 0: 1625 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1626 break; 1627 case 1: 1628 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1629 break; 1630 case 2: 1631 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 1632 break; 1633 case 5: 1634 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 1635 break; 1636 default: 1637 NS_WARNING( 1638 nsPrintfCString( 1639 "Axis idx '%d' doesn't support in BoomN64PsxRemapper().", aAxis) 1640 .get()); 1641 break; 1642 } 1643 } 1644 1645 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1646 bool aPressed) const override { 1647 RefPtr<GamepadPlatformService> service = 1648 GamepadPlatformService::GetParentService(); 1649 if (!service) { 1650 return; 1651 } 1652 1653 static constexpr std::array buttonMapping = { 1654 BUTTON_INDEX_QUATERNARY, BUTTON_INDEX_SECONDARY, 1655 BUTTON_INDEX_PRIMARY, BUTTON_INDEX_TERTIARY, 1656 BUTTON_INDEX_LEFT_TRIGGER, BUTTON_INDEX_RIGHT_TRIGGER, 1657 BUTTON_INDEX_LEFT_SHOULDER, BUTTON_INDEX_RIGHT_SHOULDER, 1658 BUTTON_INDEX_BACK_SELECT, BUTTON_INDEX_LEFT_THUMBSTICK, 1659 BUTTON_INDEX_RIGHT_THUMBSTICK, BUTTON_INDEX_START, 1660 BUTTON_INDEX_DPAD_UP, BUTTON_INDEX_DPAD_RIGHT, 1661 BUTTON_INDEX_DPAD_DOWN, BUTTON_INDEX_DPAD_LEFT}; 1662 1663 if (buttonMapping.size() <= aButton) { 1664 NS_WARNING(nsPrintfCString( 1665 "Button idx '%d' doesn't support in BoomN64PsxRemapper().", 1666 aButton) 1667 .get()); 1668 return; 1669 } 1670 1671 service->NewButtonEvent(aHandle, buttonMapping[aButton], aPressed); 1672 } 1673 1674 private: 1675 enum GamecubeButtons { 1676 GAMECUBE_BUTTON_LEFT_TRIGGER_CLICK = BUTTON_INDEX_COUNT, 1677 GAMECUBE_BUTTON_RIGHT_TRIGGER_CLICK, 1678 GAMECUBE_BUTTON_COUNT 1679 }; 1680 }; 1681 1682 class StadiaControllerOldFirmwareRemapper final : public GamepadRemapper { 1683 public: 1684 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 1685 1686 virtual uint32_t GetButtonCount() const override { 1687 return ANALOG_GAMEPAD_BUTTON_COUNT; 1688 } 1689 1690 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1691 double aValue) const override { 1692 RefPtr<GamepadPlatformService> service = 1693 GamepadPlatformService::GetParentService(); 1694 if (!service) { 1695 return; 1696 } 1697 1698 switch (aAxis) { 1699 case 0: 1700 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1701 break; 1702 case 1: 1703 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1704 break; 1705 case 2: 1706 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 1707 break; 1708 case 3: { 1709 const double value = AxisToButtonValue(aValue); 1710 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 1711 value > BUTTON_THRESHOLD_VALUE, value); 1712 break; 1713 } 1714 case 4: { 1715 const double value = AxisToButtonValue(aValue); 1716 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 1717 value > BUTTON_THRESHOLD_VALUE, value); 1718 break; 1719 } 1720 case 5: 1721 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 1722 break; 1723 case 9: 1724 FetchDpadFromAxis(aHandle, aValue); 1725 break; 1726 default: 1727 NS_WARNING( 1728 nsPrintfCString( 1729 "Axis idx '%d' doesn't support in AnalogGamepadRemapper().", 1730 aAxis) 1731 .get()); 1732 break; 1733 } 1734 } 1735 1736 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1737 bool aPressed) const override { 1738 RefPtr<GamepadPlatformService> service = 1739 GamepadPlatformService::GetParentService(); 1740 if (!service) { 1741 return; 1742 } 1743 1744 if (GetButtonCount() <= aButton) { 1745 NS_WARNING( 1746 nsPrintfCString( 1747 "Button idx '%d' doesn't support in AnalogGamepadRemapper().", 1748 aButton) 1749 .get()); 1750 return; 1751 } 1752 1753 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 1754 {3, BUTTON_INDEX_TERTIARY}, 1755 {4, BUTTON_INDEX_QUATERNARY}, 1756 {6, BUTTON_INDEX_LEFT_SHOULDER}, 1757 {7, BUTTON_INDEX_RIGHT_SHOULDER}, 1758 {10, BUTTON_INDEX_BACK_SELECT}, 1759 {11, BUTTON_INDEX_META}, 1760 {12, BUTTON_INDEX_START}, 1761 {13, BUTTON_INDEX_LEFT_THUMBSTICK}, 1762 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}, 1763 {16, ANALOG_GAMEPAD_BUTTON_EXTRA}, 1764 {17, ANALOG_GAMEPAD_BUTTON_EXTRA2}}; 1765 1766 auto find = buttonMapping.find(aButton); 1767 if (find != buttonMapping.end()) { 1768 service->NewButtonEvent(aHandle, find->second, aPressed); 1769 } else { 1770 service->NewButtonEvent(aHandle, aButton, aPressed); 1771 } 1772 } 1773 1774 private: 1775 enum AnalogGamepadButtons { 1776 ANALOG_GAMEPAD_BUTTON_EXTRA = BUTTON_INDEX_COUNT, 1777 ANALOG_GAMEPAD_BUTTON_EXTRA2, 1778 ANALOG_GAMEPAD_BUTTON_COUNT 1779 }; 1780 }; 1781 1782 class RazerServalRemapper final : public GamepadRemapper { 1783 public: 1784 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 1785 1786 virtual uint32_t GetButtonCount() const override { 1787 return BUTTON_INDEX_COUNT - 1; /* no meta */ 1788 } 1789 1790 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1791 double aValue) const override { 1792 RefPtr<GamepadPlatformService> service = 1793 GamepadPlatformService::GetParentService(); 1794 if (!service) { 1795 return; 1796 } 1797 1798 switch (aAxis) { 1799 case 0: 1800 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1801 break; 1802 case 1: 1803 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1804 break; 1805 case 2: 1806 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 1807 break; 1808 case 3: { 1809 const double value = AxisToButtonValue(aValue); 1810 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 1811 value > BUTTON_THRESHOLD_VALUE, value); 1812 break; 1813 } 1814 case 4: { 1815 const double value = AxisToButtonValue(aValue); 1816 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 1817 value > BUTTON_THRESHOLD_VALUE, value); 1818 break; 1819 } 1820 case 5: 1821 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 1822 break; 1823 case 9: 1824 FetchDpadFromAxis(aHandle, aValue); 1825 break; 1826 default: 1827 NS_WARNING( 1828 nsPrintfCString( 1829 "Axis idx '%d' doesn't support in RazerServalRemapper().", 1830 aAxis) 1831 .get()); 1832 break; 1833 } 1834 } 1835 1836 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1837 bool aPressed) const override { 1838 RefPtr<GamepadPlatformService> service = 1839 GamepadPlatformService::GetParentService(); 1840 if (!service) { 1841 return; 1842 } 1843 1844 if (GetButtonCount() <= aButton) { 1845 NS_WARNING( 1846 nsPrintfCString( 1847 "Button idx '%d' doesn't support in RazerServalRemapper().", 1848 aButton) 1849 .get()); 1850 return; 1851 } 1852 1853 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 1854 {3, BUTTON_INDEX_TERTIARY}, {4, BUTTON_INDEX_QUATERNARY}, 1855 {6, BUTTON_INDEX_LEFT_SHOULDER}, {7, BUTTON_INDEX_RIGHT_SHOULDER}, 1856 {10, BUTTON_INDEX_BACK_SELECT}, {11, BUTTON_INDEX_START}, 1857 {12, BUTTON_INDEX_START}, {13, BUTTON_INDEX_LEFT_THUMBSTICK}, 1858 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}}; 1859 1860 auto find = buttonMapping.find(aButton); 1861 if (find != buttonMapping.end()) { 1862 service->NewButtonEvent(aHandle, find->second, aPressed); 1863 } else { 1864 service->NewButtonEvent(aHandle, aButton, aPressed); 1865 } 1866 } 1867 }; 1868 1869 class MogaProRemapper final : public GamepadRemapper { 1870 public: 1871 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 1872 1873 virtual uint32_t GetButtonCount() const override { 1874 return BUTTON_INDEX_COUNT - 1; /* no meta */ 1875 } 1876 1877 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1878 double aValue) const override { 1879 RefPtr<GamepadPlatformService> service = 1880 GamepadPlatformService::GetParentService(); 1881 if (!service) { 1882 return; 1883 } 1884 1885 switch (aAxis) { 1886 case 0: 1887 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1888 break; 1889 case 1: 1890 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1891 break; 1892 case 2: 1893 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 1894 break; 1895 case 3: { 1896 const double value = AxisToButtonValue(aValue); 1897 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 1898 value > BUTTON_THRESHOLD_VALUE, value); 1899 break; 1900 } 1901 case 4: { 1902 const double value = AxisToButtonValue(aValue); 1903 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 1904 value > BUTTON_THRESHOLD_VALUE, value); 1905 break; 1906 } 1907 case 5: 1908 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 1909 break; 1910 case 9: 1911 FetchDpadFromAxis(aHandle, aValue); 1912 break; 1913 default: 1914 NS_WARNING( 1915 nsPrintfCString( 1916 "Axis idx '%d' doesn't support in MogaProRemapper().", aAxis) 1917 .get()); 1918 break; 1919 } 1920 } 1921 1922 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 1923 bool aPressed) const override { 1924 RefPtr<GamepadPlatformService> service = 1925 GamepadPlatformService::GetParentService(); 1926 if (!service) { 1927 return; 1928 } 1929 1930 if (GetButtonCount() <= aButton) { 1931 NS_WARNING( 1932 nsPrintfCString( 1933 "Button idx '%d' doesn't support in MogaProRemapper().", aButton) 1934 .get()); 1935 return; 1936 } 1937 1938 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 1939 {3, BUTTON_INDEX_TERTIARY}, {4, BUTTON_INDEX_QUATERNARY}, 1940 {6, BUTTON_INDEX_LEFT_SHOULDER}, {7, BUTTON_INDEX_RIGHT_SHOULDER}, 1941 {11, BUTTON_INDEX_START}, {13, BUTTON_INDEX_LEFT_THUMBSTICK}, 1942 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}}; 1943 1944 auto find = buttonMapping.find(aButton); 1945 if (find != buttonMapping.end()) { 1946 service->NewButtonEvent(aHandle, find->second, aPressed); 1947 } else { 1948 service->NewButtonEvent(aHandle, aButton, aPressed); 1949 } 1950 } 1951 }; 1952 1953 class OnLiveWirelessRemapper final : public GamepadRemapper { 1954 public: 1955 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 1956 1957 virtual uint32_t GetButtonCount() const override { 1958 return BUTTON_INDEX_COUNT; 1959 } 1960 1961 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 1962 double aValue) const override { 1963 RefPtr<GamepadPlatformService> service = 1964 GamepadPlatformService::GetParentService(); 1965 if (!service) { 1966 return; 1967 } 1968 1969 switch (aAxis) { 1970 case 0: 1971 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 1972 break; 1973 case 1: 1974 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 1975 break; 1976 case 2: { 1977 const double value = AxisToButtonValue(aValue); 1978 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 1979 value > BUTTON_THRESHOLD_VALUE, value); 1980 break; 1981 } 1982 case 3: 1983 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 1984 break; 1985 case 4: 1986 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 1987 break; 1988 case 5: { 1989 const double value = AxisToButtonValue(aValue); 1990 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 1991 value > BUTTON_THRESHOLD_VALUE, value); 1992 break; 1993 } 1994 case 9: 1995 FetchDpadFromAxis(aHandle, aValue); 1996 break; 1997 default: 1998 NS_WARNING( 1999 nsPrintfCString( 2000 "Axis idx '%d' doesn't support in OnLiveWirelessRemapper().", 2001 aAxis) 2002 .get()); 2003 break; 2004 } 2005 } 2006 2007 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 2008 bool aPressed) const override { 2009 RefPtr<GamepadPlatformService> service = 2010 GamepadPlatformService::GetParentService(); 2011 if (!service) { 2012 return; 2013 } 2014 2015 if (GetButtonCount() <= aButton) { 2016 NS_WARNING( 2017 nsPrintfCString( 2018 "Button idx '%d' doesn't support in OnLiveWirelessRemapper().", 2019 aButton) 2020 .get()); 2021 return; 2022 } 2023 2024 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 2025 {3, BUTTON_INDEX_TERTIARY}, 2026 {4, BUTTON_INDEX_QUATERNARY}, 2027 {6, BUTTON_INDEX_LEFT_SHOULDER}, 2028 {7, BUTTON_INDEX_RIGHT_SHOULDER}, 2029 {12, BUTTON_INDEX_META}, 2030 {13, BUTTON_INDEX_LEFT_THUMBSTICK}, 2031 {14, BUTTON_INDEX_RIGHT_THUMBSTICK}}; 2032 2033 auto find = buttonMapping.find(aButton); 2034 if (find != buttonMapping.end()) { 2035 service->NewButtonEvent(aHandle, find->second, aPressed); 2036 } else { 2037 service->NewButtonEvent(aHandle, aButton, aPressed); 2038 } 2039 } 2040 }; 2041 2042 class OUYARemapper final : public GamepadRemapper { 2043 public: 2044 virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; } 2045 2046 virtual uint32_t GetButtonCount() const override { 2047 return BUTTON_INDEX_COUNT; 2048 } 2049 2050 virtual void RemapAxisMoveEvent(GamepadHandle aHandle, uint32_t aAxis, 2051 double aValue) const override { 2052 RefPtr<GamepadPlatformService> service = 2053 GamepadPlatformService::GetParentService(); 2054 if (!service) { 2055 return; 2056 } 2057 2058 switch (aAxis) { 2059 case 0: 2060 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_X, aValue); 2061 break; 2062 case 1: 2063 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_LEFT_STICK_Y, aValue); 2064 break; 2065 case 2: { 2066 const double value = AxisToButtonValue(aValue); 2067 service->NewButtonEvent(aHandle, BUTTON_INDEX_LEFT_TRIGGER, 2068 value > BUTTON_THRESHOLD_VALUE, value); 2069 break; 2070 } 2071 case 3: 2072 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_X, aValue); 2073 break; 2074 case 4: 2075 service->NewAxisMoveEvent(aHandle, AXIS_INDEX_RIGHT_STICK_Y, aValue); 2076 break; 2077 case 5: { 2078 const double value = AxisToButtonValue(aValue); 2079 service->NewButtonEvent(aHandle, BUTTON_INDEX_RIGHT_TRIGGER, 2080 value > BUTTON_THRESHOLD_VALUE, value); 2081 break; 2082 } 2083 default: 2084 NS_WARNING( 2085 nsPrintfCString("Axis idx '%d' doesn't support in OUYARemapper().", 2086 aAxis) 2087 .get()); 2088 break; 2089 } 2090 } 2091 2092 virtual void RemapButtonEvent(GamepadHandle aHandle, uint32_t aButton, 2093 bool aPressed) const override { 2094 RefPtr<GamepadPlatformService> service = 2095 GamepadPlatformService::GetParentService(); 2096 if (!service) { 2097 return; 2098 } 2099 2100 if (GetButtonCount() <= aButton) { 2101 NS_WARNING( 2102 nsPrintfCString("Button idx '%d' doesn't support in OUYARemapper().", 2103 aButton) 2104 .get()); 2105 return; 2106 } 2107 2108 const std::unordered_map<uint32_t, uint32_t> buttonMapping = { 2109 {1, BUTTON_INDEX_TERTIARY}, {2, BUTTON_INDEX_QUATERNARY}, 2110 {3, BUTTON_INDEX_SECONDARY}, {6, BUTTON_INDEX_LEFT_THUMBSTICK}, 2111 {7, BUTTON_INDEX_RIGHT_THUMBSTICK}, {8, BUTTON_INDEX_DPAD_UP}, 2112 {9, BUTTON_INDEX_DPAD_DOWN}, {10, BUTTON_INDEX_DPAD_LEFT}, 2113 {11, BUTTON_INDEX_DPAD_RIGHT}, {15, BUTTON_INDEX_META}}; 2114 2115 auto find = buttonMapping.find(aButton); 2116 if (find != buttonMapping.end()) { 2117 service->NewButtonEvent(aHandle, find->second, aPressed); 2118 } else { 2119 service->NewButtonEvent(aHandle, aButton, aPressed); 2120 } 2121 } 2122 }; 2123 2124 already_AddRefed<GamepadRemapper> GetGamepadRemapper(const uint16_t aVendorId, 2125 const uint16_t aProductId, 2126 bool& aUsingDefault) { 2127 const std::vector<GamepadRemappingData> remappingRules = { 2128 {GamepadId::kAsusTekProduct4500, new ADT1Remapper()}, 2129 {GamepadId::kDragonRiseProduct0011, new TwoAxesEightKeysRemapper()}, 2130 {GamepadId::kGoogleProduct2c40, new ADT1Remapper()}, 2131 {GamepadId::kGoogleProduct9400, new StadiaControllerRemapper()}, 2132 {GamepadId::kLogitechProductc216, new LogitechDInputRemapper()}, 2133 {GamepadId::kLogitechProductc218, new LogitechDInputRemapper()}, 2134 {GamepadId::kLogitechProductc219, new LogitechDInputRemapper()}, 2135 {GamepadId::kMicrosoftProductXbox360Wireless, new Xbox360Remapper()}, 2136 {GamepadId::kMicrosoftProductXbox360Wireless2, new Xbox360Remapper()}, 2137 {GamepadId::kMicrosoftProductXboxOneElite2Wireless, 2138 new XboxOneRemapper()}, 2139 {GamepadId::kMicrosoftProductXboxOneSWireless, new XboxOneSRemapper()}, 2140 {GamepadId::kMicrosoftProductXboxOneSWireless2016, 2141 new XboxOneS2016FirmwareRemapper()}, 2142 {GamepadId::kMicrosoftProductXboxAdaptiveWireless, new XboxOneRemapper()}, 2143 {GamepadId::kMicrosoftProductXboxSeriesXWireless, 2144 new XboxSeriesXRemapper()}, 2145 {GamepadId::kNintendoProduct2006, new SwitchJoyConRemapper()}, 2146 {GamepadId::kNintendoProduct2007, new SwitchJoyConRemapper()}, 2147 {GamepadId::kNintendoProduct2009, new SwitchProRemapper()}, 2148 {GamepadId::kNintendoProduct200e, new SwitchProRemapper()}, 2149 {GamepadId::kNvidiaProduct7210, new NvShieldRemapper()}, 2150 {GamepadId::kNvidiaProduct7214, new NvShield2017Remapper()}, 2151 {GamepadId::kPadixProduct2060, new IBuffaloRemapper()}, 2152 {GamepadId::kPlayComProduct0005, new XSkillsRemapper()}, 2153 {GamepadId::kPrototypeVendorProduct0667, new BoomN64PsxRemapper()}, 2154 {GamepadId::kPrototypeVendorProduct9401, 2155 new StadiaControllerOldFirmwareRemapper()}, 2156 {GamepadId::kRazer1532Product0900, new RazerServalRemapper()}, 2157 {GamepadId::kSonyProduct0268, new Playstation3Remapper()}, 2158 {GamepadId::kSonyProduct05c4, new Dualshock4Remapper()}, 2159 {GamepadId::kSonyProduct09cc, new Dualshock4Remapper()}, 2160 {GamepadId::kSonyProduct0ba0, new Dualshock4Remapper()}, 2161 {GamepadId::kVendor20d6Product6271, new MogaProRemapper()}, 2162 {GamepadId::kVendor2378Product1008, new OnLiveWirelessRemapper()}, 2163 {GamepadId::kVendor2378Product100a, new OnLiveWirelessRemapper()}, 2164 {GamepadId::kVendor2836Product0001, new OUYARemapper()}}; 2165 const GamepadId id = static_cast<GamepadId>((aVendorId << 16) | aProductId); 2166 2167 for (uint32_t i = 0; i < remappingRules.size(); ++i) { 2168 if (id == remappingRules[i].id) { 2169 aUsingDefault = false; 2170 return do_AddRef(remappingRules[i].remapping.get()); 2171 } 2172 } 2173 2174 RefPtr<GamepadRemapper> defaultRemapper = new DefaultRemapper(); 2175 aUsingDefault = true; 2176 return do_AddRef(defaultRemapper.get()); 2177 } 2178 2179 } // namespace mozilla::dom