summaryrefslogtreecommitdiff
path: root/src/input_common/helpers/joycon_driver.cpp
diff options
context:
space:
mode:
authorGravatar liamwhite2023-06-29 10:01:19 -0400
committerGravatar GitHub2023-06-29 10:01:19 -0400
commit4c705db73edfa3c7210eb5821b3f4e5324d642d1 (patch)
tree470116d2d52b3a74ad0cd761304f0f65386af708 /src/input_common/helpers/joycon_driver.cpp
parentMerge pull request #10946 from goldenx86/amdBlending (diff)
parentinput_common: Allow timeouts to happen while scanning for a ring (diff)
downloadyuzu-4c705db73edfa3c7210eb5821b3f4e5324d642d1.tar.gz
yuzu-4c705db73edfa3c7210eb5821b3f4e5324d642d1.tar.xz
yuzu-4c705db73edfa3c7210eb5821b3f4e5324d642d1.zip
Merge pull request #10937 from german77/ring
input_common: Remove duplicated enum and fix ring detection
Diffstat (limited to '')
-rw-r--r--src/input_common/helpers/joycon_driver.cpp129
1 files changed, 65 insertions, 64 deletions
diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp
index ec984a647..cf51f3481 100644
--- a/src/input_common/helpers/joycon_driver.cpp
+++ b/src/input_common/helpers/joycon_driver.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/input.h"
4#include "common/logging/log.h" 5#include "common/logging/log.h"
5#include "common/scope_exit.h" 6#include "common/scope_exit.h"
6#include "common/swap.h" 7#include "common/swap.h"
@@ -28,13 +29,13 @@ void JoyconDriver::Stop() {
28 input_thread = {}; 29 input_thread = {};
29} 30}
30 31
31DriverResult JoyconDriver::RequestDeviceAccess(SDL_hid_device_info* device_info) { 32Common::Input::DriverResult JoyconDriver::RequestDeviceAccess(SDL_hid_device_info* device_info) {
32 std::scoped_lock lock{mutex}; 33 std::scoped_lock lock{mutex};
33 34
34 handle_device_type = ControllerType::None; 35 handle_device_type = ControllerType::None;
35 GetDeviceType(device_info, handle_device_type); 36 GetDeviceType(device_info, handle_device_type);
36 if (handle_device_type == ControllerType::None) { 37 if (handle_device_type == ControllerType::None) {
37 return DriverResult::UnsupportedControllerType; 38 return Common::Input::DriverResult::UnsupportedControllerType;
38 } 39 }
39 40
40 hidapi_handle->handle = 41 hidapi_handle->handle =
@@ -43,15 +44,15 @@ DriverResult JoyconDriver::RequestDeviceAccess(SDL_hid_device_info* device_info)
43 if (!hidapi_handle->handle) { 44 if (!hidapi_handle->handle) {
44 LOG_ERROR(Input, "Yuzu can't gain access to this device: ID {:04X}:{:04X}.", 45 LOG_ERROR(Input, "Yuzu can't gain access to this device: ID {:04X}:{:04X}.",
45 device_info->vendor_id, device_info->product_id); 46 device_info->vendor_id, device_info->product_id);
46 return DriverResult::HandleInUse; 47 return Common::Input::DriverResult::HandleInUse;
47 } 48 }
48 SDL_hid_set_nonblocking(hidapi_handle->handle, 1); 49 SDL_hid_set_nonblocking(hidapi_handle->handle, 1);
49 return DriverResult::Success; 50 return Common::Input::DriverResult::Success;
50} 51}
51 52
52DriverResult JoyconDriver::InitializeDevice() { 53Common::Input::DriverResult JoyconDriver::InitializeDevice() {
53 if (!hidapi_handle->handle) { 54 if (!hidapi_handle->handle) {
54 return DriverResult::InvalidHandle; 55 return Common::Input::DriverResult::InvalidHandle;
55 } 56 }
56 std::scoped_lock lock{mutex}; 57 std::scoped_lock lock{mutex};
57 disable_input_thread = true; 58 disable_input_thread = true;
@@ -87,7 +88,7 @@ DriverResult JoyconDriver::InitializeDevice() {
87 rumble_protocol = std::make_unique<RumbleProtocol>(hidapi_handle); 88 rumble_protocol = std::make_unique<RumbleProtocol>(hidapi_handle);
88 89
89 // Get fixed joycon info 90 // Get fixed joycon info
90 if (generic_protocol->GetVersionNumber(version) != DriverResult::Success) { 91 if (generic_protocol->GetVersionNumber(version) != Common::Input::DriverResult::Success) {
91 // If this command fails the device doesn't accept configuration commands 92 // If this command fails the device doesn't accept configuration commands
92 input_only_device = true; 93 input_only_device = true;
93 } 94 }
@@ -129,7 +130,7 @@ DriverResult JoyconDriver::InitializeDevice() {
129 } 130 }
130 131
131 disable_input_thread = false; 132 disable_input_thread = false;
132 return DriverResult::Success; 133 return Common::Input::DriverResult::Success;
133} 134}
134 135
135void JoyconDriver::InputThread(std::stop_token stop_token) { 136void JoyconDriver::InputThread(std::stop_token stop_token) {
@@ -229,7 +230,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
229 if (!amiibo_detected) { 230 if (!amiibo_detected) {
230 Joycon::TagInfo tag_info; 231 Joycon::TagInfo tag_info;
231 const auto result = nfc_protocol->GetTagInfo(tag_info); 232 const auto result = nfc_protocol->GetTagInfo(tag_info);
232 if (result == DriverResult::Success) { 233 if (result == Common::Input::DriverResult::Success) {
233 joycon_poller->UpdateAmiibo(tag_info); 234 joycon_poller->UpdateAmiibo(tag_info);
234 amiibo_detected = true; 235 amiibo_detected = true;
235 } 236 }
@@ -255,7 +256,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
255 } 256 }
256} 257}
257 258
258DriverResult JoyconDriver::SetPollingMode() { 259Common::Input::DriverResult JoyconDriver::SetPollingMode() {
259 SCOPE_EXIT({ disable_input_thread = false; }); 260 SCOPE_EXIT({ disable_input_thread = false; });
260 disable_input_thread = true; 261 disable_input_thread = true;
261 262
@@ -270,7 +271,7 @@ DriverResult JoyconDriver::SetPollingMode() {
270 } 271 }
271 272
272 if (input_only_device) { 273 if (input_only_device) {
273 return DriverResult::NotSupported; 274 return Common::Input::DriverResult::NotSupported;
274 } 275 }
275 276
276 if (irs_protocol->IsEnabled()) { 277 if (irs_protocol->IsEnabled()) {
@@ -289,7 +290,7 @@ DriverResult JoyconDriver::SetPollingMode() {
289 290
290 if (irs_enabled && supported_features.irs) { 291 if (irs_enabled && supported_features.irs) {
291 auto result = irs_protocol->EnableIrs(); 292 auto result = irs_protocol->EnableIrs();
292 if (result == DriverResult::Success) { 293 if (result == Common::Input::DriverResult::Success) {
293 return result; 294 return result;
294 } 295 }
295 irs_protocol->DisableIrs(); 296 irs_protocol->DisableIrs();
@@ -299,7 +300,7 @@ DriverResult JoyconDriver::SetPollingMode() {
299 300
300 if (nfc_enabled && supported_features.nfc) { 301 if (nfc_enabled && supported_features.nfc) {
301 auto result = nfc_protocol->EnableNfc(); 302 auto result = nfc_protocol->EnableNfc();
302 if (result == DriverResult::Success) { 303 if (result == Common::Input::DriverResult::Success) {
303 return result; 304 return result;
304 } 305 }
305 nfc_protocol->DisableNfc(); 306 nfc_protocol->DisableNfc();
@@ -309,10 +310,10 @@ DriverResult JoyconDriver::SetPollingMode() {
309 310
310 if (hidbus_enabled && supported_features.hidbus) { 311 if (hidbus_enabled && supported_features.hidbus) {
311 auto result = ring_protocol->EnableRingCon(); 312 auto result = ring_protocol->EnableRingCon();
312 if (result == DriverResult::Success) { 313 if (result == Common::Input::DriverResult::Success) {
313 result = ring_protocol->StartRingconPolling(); 314 result = ring_protocol->StartRingconPolling();
314 } 315 }
315 if (result == DriverResult::Success) { 316 if (result == Common::Input::DriverResult::Success) {
316 ring_connected = true; 317 ring_connected = true;
317 return result; 318 return result;
318 } 319 }
@@ -324,7 +325,7 @@ DriverResult JoyconDriver::SetPollingMode() {
324 325
325 if (passive_enabled && supported_features.passive) { 326 if (passive_enabled && supported_features.passive) {
326 const auto result = generic_protocol->EnablePassiveMode(); 327 const auto result = generic_protocol->EnablePassiveMode();
327 if (result == DriverResult::Success) { 328 if (result == Common::Input::DriverResult::Success) {
328 return result; 329 return result;
329 } 330 }
330 LOG_ERROR(Input, "Error enabling passive mode"); 331 LOG_ERROR(Input, "Error enabling passive mode");
@@ -332,7 +333,7 @@ DriverResult JoyconDriver::SetPollingMode() {
332 333
333 // Default Mode 334 // Default Mode
334 const auto result = generic_protocol->EnableActiveMode(); 335 const auto result = generic_protocol->EnableActiveMode();
335 if (result != DriverResult::Success) { 336 if (result != Common::Input::DriverResult::Success) {
336 LOG_ERROR(Input, "Error enabling active mode"); 337 LOG_ERROR(Input, "Error enabling active mode");
337 } 338 }
338 // Switch calls this function after enabling active mode 339 // Switch calls this function after enabling active mode
@@ -396,26 +397,26 @@ bool JoyconDriver::IsPayloadCorrect(int status, std::span<const u8> buffer) {
396 return true; 397 return true;
397} 398}
398 399
399DriverResult JoyconDriver::SetVibration(const VibrationValue& vibration) { 400Common::Input::DriverResult JoyconDriver::SetVibration(const VibrationValue& vibration) {
400 std::scoped_lock lock{mutex}; 401 std::scoped_lock lock{mutex};
401 if (disable_input_thread) { 402 if (disable_input_thread) {
402 return DriverResult::HandleInUse; 403 return Common::Input::DriverResult::HandleInUse;
403 } 404 }
404 return rumble_protocol->SendVibration(vibration); 405 return rumble_protocol->SendVibration(vibration);
405} 406}
406 407
407DriverResult JoyconDriver::SetLedConfig(u8 led_pattern) { 408Common::Input::DriverResult JoyconDriver::SetLedConfig(u8 led_pattern) {
408 std::scoped_lock lock{mutex}; 409 std::scoped_lock lock{mutex};
409 if (disable_input_thread) { 410 if (disable_input_thread) {
410 return DriverResult::HandleInUse; 411 return Common::Input::DriverResult::HandleInUse;
411 } 412 }
412 return generic_protocol->SetLedPattern(led_pattern); 413 return generic_protocol->SetLedPattern(led_pattern);
413} 414}
414 415
415DriverResult JoyconDriver::SetIrsConfig(IrsMode mode_, IrsResolution format_) { 416Common::Input::DriverResult JoyconDriver::SetIrsConfig(IrsMode mode_, IrsResolution format_) {
416 std::scoped_lock lock{mutex}; 417 std::scoped_lock lock{mutex};
417 if (disable_input_thread) { 418 if (disable_input_thread) {
418 return DriverResult::HandleInUse; 419 return Common::Input::DriverResult::HandleInUse;
419 } 420 }
420 disable_input_thread = true; 421 disable_input_thread = true;
421 const auto result = irs_protocol->SetIrsConfig(mode_, format_); 422 const auto result = irs_protocol->SetIrsConfig(mode_, format_);
@@ -423,7 +424,7 @@ DriverResult JoyconDriver::SetIrsConfig(IrsMode mode_, IrsResolution format_) {
423 return result; 424 return result;
424} 425}
425 426
426DriverResult JoyconDriver::SetPassiveMode() { 427Common::Input::DriverResult JoyconDriver::SetPassiveMode() {
427 std::scoped_lock lock{mutex}; 428 std::scoped_lock lock{mutex};
428 motion_enabled = false; 429 motion_enabled = false;
429 hidbus_enabled = false; 430 hidbus_enabled = false;
@@ -433,7 +434,7 @@ DriverResult JoyconDriver::SetPassiveMode() {
433 return SetPollingMode(); 434 return SetPollingMode();
434} 435}
435 436
436DriverResult JoyconDriver::SetActiveMode() { 437Common::Input::DriverResult JoyconDriver::SetActiveMode() {
437 if (is_ring_disabled_by_irs) { 438 if (is_ring_disabled_by_irs) {
438 is_ring_disabled_by_irs = false; 439 is_ring_disabled_by_irs = false;
439 SetActiveMode(); 440 SetActiveMode();
@@ -449,11 +450,11 @@ DriverResult JoyconDriver::SetActiveMode() {
449 return SetPollingMode(); 450 return SetPollingMode();
450} 451}
451 452
452DriverResult JoyconDriver::SetIrMode() { 453Common::Input::DriverResult JoyconDriver::SetIrMode() {
453 std::scoped_lock lock{mutex}; 454 std::scoped_lock lock{mutex};
454 455
455 if (!supported_features.irs) { 456 if (!supported_features.irs) {
456 return DriverResult::NotSupported; 457 return Common::Input::DriverResult::NotSupported;
457 } 458 }
458 459
459 if (ring_connected) { 460 if (ring_connected) {
@@ -468,11 +469,11 @@ DriverResult JoyconDriver::SetIrMode() {
468 return SetPollingMode(); 469 return SetPollingMode();
469} 470}
470 471
471DriverResult JoyconDriver::SetNfcMode() { 472Common::Input::DriverResult JoyconDriver::SetNfcMode() {
472 std::scoped_lock lock{mutex}; 473 std::scoped_lock lock{mutex};
473 474
474 if (!supported_features.nfc) { 475 if (!supported_features.nfc) {
475 return DriverResult::NotSupported; 476 return Common::Input::DriverResult::NotSupported;
476 } 477 }
477 478
478 motion_enabled = true; 479 motion_enabled = true;
@@ -483,11 +484,11 @@ DriverResult JoyconDriver::SetNfcMode() {
483 return SetPollingMode(); 484 return SetPollingMode();
484} 485}
485 486
486DriverResult JoyconDriver::SetRingConMode() { 487Common::Input::DriverResult JoyconDriver::SetRingConMode() {
487 std::scoped_lock lock{mutex}; 488 std::scoped_lock lock{mutex};
488 489
489 if (!supported_features.hidbus) { 490 if (!supported_features.hidbus) {
490 return DriverResult::NotSupported; 491 return Common::Input::DriverResult::NotSupported;
491 } 492 }
492 493
493 motion_enabled = true; 494 motion_enabled = true;
@@ -499,20 +500,20 @@ DriverResult JoyconDriver::SetRingConMode() {
499 const auto result = SetPollingMode(); 500 const auto result = SetPollingMode();
500 501
501 if (!ring_connected) { 502 if (!ring_connected) {
502 return DriverResult::NoDeviceDetected; 503 return Common::Input::DriverResult::NoDeviceDetected;
503 } 504 }
504 505
505 return result; 506 return result;
506} 507}
507 508
508DriverResult JoyconDriver::StartNfcPolling() { 509Common::Input::DriverResult JoyconDriver::StartNfcPolling() {
509 std::scoped_lock lock{mutex}; 510 std::scoped_lock lock{mutex};
510 511
511 if (!supported_features.nfc) { 512 if (!supported_features.nfc) {
512 return DriverResult::NotSupported; 513 return Common::Input::DriverResult::NotSupported;
513 } 514 }
514 if (!nfc_protocol->IsEnabled()) { 515 if (!nfc_protocol->IsEnabled()) {
515 return DriverResult::Disabled; 516 return Common::Input::DriverResult::Disabled;
516 } 517 }
517 518
518 disable_input_thread = true; 519 disable_input_thread = true;
@@ -522,14 +523,14 @@ DriverResult JoyconDriver::StartNfcPolling() {
522 return result; 523 return result;
523} 524}
524 525
525DriverResult JoyconDriver::StopNfcPolling() { 526Common::Input::DriverResult JoyconDriver::StopNfcPolling() {
526 std::scoped_lock lock{mutex}; 527 std::scoped_lock lock{mutex};
527 528
528 if (!supported_features.nfc) { 529 if (!supported_features.nfc) {
529 return DriverResult::NotSupported; 530 return Common::Input::DriverResult::NotSupported;
530 } 531 }
531 if (!nfc_protocol->IsEnabled()) { 532 if (!nfc_protocol->IsEnabled()) {
532 return DriverResult::Disabled; 533 return Common::Input::DriverResult::Disabled;
533 } 534 }
534 535
535 disable_input_thread = true; 536 disable_input_thread = true;
@@ -544,17 +545,17 @@ DriverResult JoyconDriver::StopNfcPolling() {
544 return result; 545 return result;
545} 546}
546 547
547DriverResult JoyconDriver::ReadAmiiboData(std::vector<u8>& out_data) { 548Common::Input::DriverResult JoyconDriver::ReadAmiiboData(std::vector<u8>& out_data) {
548 std::scoped_lock lock{mutex}; 549 std::scoped_lock lock{mutex};
549 550
550 if (!supported_features.nfc) { 551 if (!supported_features.nfc) {
551 return DriverResult::NotSupported; 552 return Common::Input::DriverResult::NotSupported;
552 } 553 }
553 if (!nfc_protocol->IsEnabled()) { 554 if (!nfc_protocol->IsEnabled()) {
554 return DriverResult::Disabled; 555 return Common::Input::DriverResult::Disabled;
555 } 556 }
556 if (!amiibo_detected) { 557 if (!amiibo_detected) {
557 return DriverResult::ErrorWritingData; 558 return Common::Input::DriverResult::ErrorWritingData;
558 } 559 }
559 560
560 out_data.resize(0x21C); 561 out_data.resize(0x21C);
@@ -565,17 +566,17 @@ DriverResult JoyconDriver::ReadAmiiboData(std::vector<u8>& out_data) {
565 return result; 566 return result;
566} 567}
567 568
568DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) { 569Common::Input::DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) {
569 std::scoped_lock lock{mutex}; 570 std::scoped_lock lock{mutex};
570 571
571 if (!supported_features.nfc) { 572 if (!supported_features.nfc) {
572 return DriverResult::NotSupported; 573 return Common::Input::DriverResult::NotSupported;
573 } 574 }
574 if (!nfc_protocol->IsEnabled()) { 575 if (!nfc_protocol->IsEnabled()) {
575 return DriverResult::Disabled; 576 return Common::Input::DriverResult::Disabled;
576 } 577 }
577 if (!amiibo_detected) { 578 if (!amiibo_detected) {
578 return DriverResult::ErrorWritingData; 579 return Common::Input::DriverResult::ErrorWritingData;
579 } 580 }
580 581
581 disable_input_thread = true; 582 disable_input_thread = true;
@@ -585,18 +586,18 @@ DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) {
585 return result; 586 return result;
586} 587}
587 588
588DriverResult JoyconDriver::ReadMifareData(std::span<const MifareReadChunk> data, 589Common::Input::DriverResult JoyconDriver::ReadMifareData(std::span<const MifareReadChunk> data,
589 std::span<MifareReadData> out_data) { 590 std::span<MifareReadData> out_data) {
590 std::scoped_lock lock{mutex}; 591 std::scoped_lock lock{mutex};
591 592
592 if (!supported_features.nfc) { 593 if (!supported_features.nfc) {
593 return DriverResult::NotSupported; 594 return Common::Input::DriverResult::NotSupported;
594 } 595 }
595 if (!nfc_protocol->IsEnabled()) { 596 if (!nfc_protocol->IsEnabled()) {
596 return DriverResult::Disabled; 597 return Common::Input::DriverResult::Disabled;
597 } 598 }
598 if (!amiibo_detected) { 599 if (!amiibo_detected) {
599 return DriverResult::ErrorWritingData; 600 return Common::Input::DriverResult::ErrorWritingData;
600 } 601 }
601 602
602 disable_input_thread = true; 603 disable_input_thread = true;
@@ -606,17 +607,17 @@ DriverResult JoyconDriver::ReadMifareData(std::span<const MifareReadChunk> data,
606 return result; 607 return result;
607} 608}
608 609
609DriverResult JoyconDriver::WriteMifareData(std::span<const MifareWriteChunk> data) { 610Common::Input::DriverResult JoyconDriver::WriteMifareData(std::span<const MifareWriteChunk> data) {
610 std::scoped_lock lock{mutex}; 611 std::scoped_lock lock{mutex};
611 612
612 if (!supported_features.nfc) { 613 if (!supported_features.nfc) {
613 return DriverResult::NotSupported; 614 return Common::Input::DriverResult::NotSupported;
614 } 615 }
615 if (!nfc_protocol->IsEnabled()) { 616 if (!nfc_protocol->IsEnabled()) {
616 return DriverResult::Disabled; 617 return Common::Input::DriverResult::Disabled;
617 } 618 }
618 if (!amiibo_detected) { 619 if (!amiibo_detected) {
619 return DriverResult::ErrorWritingData; 620 return Common::Input::DriverResult::ErrorWritingData;
620 } 621 }
621 622
622 disable_input_thread = true; 623 disable_input_thread = true;
@@ -675,8 +676,8 @@ void JoyconDriver::SetCallbacks(const JoyconCallbacks& callbacks) {
675 joycon_poller->SetCallbacks(callbacks); 676 joycon_poller->SetCallbacks(callbacks);
676} 677}
677 678
678DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info, 679Common::Input::DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info,
679 ControllerType& controller_type) { 680 ControllerType& controller_type) {
680 static constexpr std::array<std::pair<u32, ControllerType>, 6> supported_devices{ 681 static constexpr std::array<std::pair<u32, ControllerType>, 6> supported_devices{
681 std::pair<u32, ControllerType>{0x2006, ControllerType::Left}, 682 std::pair<u32, ControllerType>{0x2006, ControllerType::Left},
682 {0x2007, ControllerType::Right}, 683 {0x2007, ControllerType::Right},
@@ -686,25 +687,25 @@ DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info,
686 687
687 controller_type = ControllerType::None; 688 controller_type = ControllerType::None;
688 if (device_info->vendor_id != nintendo_vendor_id) { 689 if (device_info->vendor_id != nintendo_vendor_id) {
689 return DriverResult::UnsupportedControllerType; 690 return Common::Input::DriverResult::UnsupportedControllerType;
690 } 691 }
691 692
692 for (const auto& [product_id, type] : supported_devices) { 693 for (const auto& [product_id, type] : supported_devices) {
693 if (device_info->product_id == static_cast<u16>(product_id)) { 694 if (device_info->product_id == static_cast<u16>(product_id)) {
694 controller_type = type; 695 controller_type = type;
695 return Joycon::DriverResult::Success; 696 return Common::Input::DriverResult::Success;
696 } 697 }
697 } 698 }
698 return Joycon::DriverResult::UnsupportedControllerType; 699 return Common::Input::DriverResult::UnsupportedControllerType;
699} 700}
700 701
701DriverResult JoyconDriver::GetSerialNumber(SDL_hid_device_info* device_info, 702Common::Input::DriverResult JoyconDriver::GetSerialNumber(SDL_hid_device_info* device_info,
702 SerialNumber& serial_number) { 703 SerialNumber& serial_number) {
703 if (device_info->serial_number == nullptr) { 704 if (device_info->serial_number == nullptr) {
704 return DriverResult::Unknown; 705 return Common::Input::DriverResult::Unknown;
705 } 706 }
706 std::memcpy(&serial_number, device_info->serial_number, 15); 707 std::memcpy(&serial_number, device_info->serial_number, 15);
707 return Joycon::DriverResult::Success; 708 return Common::Input::DriverResult::Success;
708} 709}
709 710
710} // namespace InputCommon::Joycon 711} // namespace InputCommon::Joycon