diff options
Diffstat (limited to 'src/input_common')
| -rw-r--r-- | src/input_common/CMakeLists.txt | 11 | ||||
| -rw-r--r-- | src/input_common/drivers/gc_adapter.cpp | 10 | ||||
| -rw-r--r-- | src/input_common/drivers/gc_adapter.h | 4 | ||||
| -rw-r--r-- | src/input_common/drivers/mouse.cpp | 2 | ||||
| -rw-r--r-- | src/input_common/drivers/sdl_driver.cpp | 72 | ||||
| -rw-r--r-- | src/input_common/drivers/sdl_driver.h | 4 | ||||
| -rw-r--r-- | src/input_common/drivers/virtual_amiibo.cpp | 101 | ||||
| -rw-r--r-- | src/input_common/drivers/virtual_amiibo.h | 61 | ||||
| -rw-r--r-- | src/input_common/input_engine.cpp | 37 | ||||
| -rw-r--r-- | src/input_common/input_engine.h | 24 | ||||
| -rw-r--r-- | src/input_common/input_poller.cpp | 96 | ||||
| -rw-r--r-- | src/input_common/input_poller.h | 10 | ||||
| -rw-r--r-- | src/input_common/main.cpp | 21 | ||||
| -rw-r--r-- | src/input_common/main.h | 7 |
14 files changed, 422 insertions, 38 deletions
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index 4b91b88ce..cc6f0ffc0 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt | |||
| @@ -18,6 +18,8 @@ add_library(input_common STATIC | |||
| 18 | drivers/touch_screen.h | 18 | drivers/touch_screen.h |
| 19 | drivers/udp_client.cpp | 19 | drivers/udp_client.cpp |
| 20 | drivers/udp_client.h | 20 | drivers/udp_client.h |
| 21 | drivers/virtual_amiibo.cpp | ||
| 22 | drivers/virtual_amiibo.h | ||
| 21 | helpers/stick_from_buttons.cpp | 23 | helpers/stick_from_buttons.cpp |
| 22 | helpers/stick_from_buttons.h | 24 | helpers/stick_from_buttons.h |
| 23 | helpers/touch_from_buttons.cpp | 25 | helpers/touch_from_buttons.cpp |
| @@ -37,21 +39,14 @@ add_library(input_common STATIC | |||
| 37 | if (MSVC) | 39 | if (MSVC) |
| 38 | target_compile_options(input_common PRIVATE | 40 | target_compile_options(input_common PRIVATE |
| 39 | /W4 | 41 | /W4 |
| 40 | /WX | ||
| 41 | 42 | ||
| 42 | /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data | 43 | /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data |
| 43 | /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data | ||
| 44 | /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch | ||
| 45 | /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data | 44 | /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data |
| 45 | /we4800 # Implicit conversion from 'type' to bool. Possible information loss | ||
| 46 | ) | 46 | ) |
| 47 | else() | 47 | else() |
| 48 | target_compile_options(input_common PRIVATE | 48 | target_compile_options(input_common PRIVATE |
| 49 | -Werror | ||
| 50 | -Werror=conversion | 49 | -Werror=conversion |
| 51 | -Werror=ignored-qualifiers | ||
| 52 | $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> | ||
| 53 | $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> | ||
| 54 | -Werror=unused-variable | ||
| 55 | ) | 50 | ) |
| 56 | endif() | 51 | endif() |
| 57 | 52 | ||
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp index 27a0ffb0d..826fa2109 100644 --- a/src/input_common/drivers/gc_adapter.cpp +++ b/src/input_common/drivers/gc_adapter.cpp | |||
| @@ -90,7 +90,7 @@ GCAdapter::~GCAdapter() { | |||
| 90 | 90 | ||
| 91 | void GCAdapter::AdapterInputThread(std::stop_token stop_token) { | 91 | void GCAdapter::AdapterInputThread(std::stop_token stop_token) { |
| 92 | LOG_DEBUG(Input, "Input thread started"); | 92 | LOG_DEBUG(Input, "Input thread started"); |
| 93 | Common::SetCurrentThreadName("yuzu:input:GCAdapter"); | 93 | Common::SetCurrentThreadName("GCAdapter"); |
| 94 | s32 payload_size{}; | 94 | s32 payload_size{}; |
| 95 | AdapterPayload adapter_payload{}; | 95 | AdapterPayload adapter_payload{}; |
| 96 | 96 | ||
| @@ -214,7 +214,7 @@ void GCAdapter::UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_ | |||
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | void GCAdapter::AdapterScanThread(std::stop_token stop_token) { | 216 | void GCAdapter::AdapterScanThread(std::stop_token stop_token) { |
| 217 | Common::SetCurrentThreadName("yuzu:input:ScanGCAdapter"); | 217 | Common::SetCurrentThreadName("ScanGCAdapter"); |
| 218 | usb_adapter_handle = nullptr; | 218 | usb_adapter_handle = nullptr; |
| 219 | pads = {}; | 219 | pads = {}; |
| 220 | while (!stop_token.stop_requested() && !Setup()) { | 220 | while (!stop_token.stop_requested() && !Setup()) { |
| @@ -324,7 +324,7 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) { | |||
| 324 | return true; | 324 | return true; |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | Common::Input::VibrationError GCAdapter::SetRumble( | 327 | Common::Input::VibrationError GCAdapter::SetVibration( |
| 328 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { | 328 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { |
| 329 | const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f; | 329 | const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f; |
| 330 | const auto processed_amplitude = | 330 | const auto processed_amplitude = |
| @@ -338,6 +338,10 @@ Common::Input::VibrationError GCAdapter::SetRumble( | |||
| 338 | return Common::Input::VibrationError::None; | 338 | return Common::Input::VibrationError::None; |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | bool GCAdapter::IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) { | ||
| 342 | return rumble_enabled; | ||
| 343 | } | ||
| 344 | |||
| 341 | void GCAdapter::UpdateVibrations() { | 345 | void GCAdapter::UpdateVibrations() { |
| 342 | // Use 8 states to keep the switching between on/off fast enough for | 346 | // Use 8 states to keep the switching between on/off fast enough for |
| 343 | // a human to feel different vibration strenght | 347 | // a human to feel different vibration strenght |
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index 8682da847..7f81767f7 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h | |||
| @@ -25,9 +25,11 @@ public: | |||
| 25 | explicit GCAdapter(std::string input_engine_); | 25 | explicit GCAdapter(std::string input_engine_); |
| 26 | ~GCAdapter() override; | 26 | ~GCAdapter() override; |
| 27 | 27 | ||
| 28 | Common::Input::VibrationError SetRumble( | 28 | Common::Input::VibrationError SetVibration( |
| 29 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; | 29 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; |
| 30 | 30 | ||
| 31 | bool IsVibrationEnabled(const PadIdentifier& identifier) override; | ||
| 32 | |||
| 31 | /// Used for automapping features | 33 | /// Used for automapping features |
| 32 | std::vector<Common::ParamPackage> GetInputDevices() const override; | 34 | std::vector<Common::ParamPackage> GetInputDevices() const override; |
| 33 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; | 35 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; |
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index 4909fa8d7..98c3157a8 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp | |||
| @@ -37,7 +37,7 @@ Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | void Mouse::UpdateThread(std::stop_token stop_token) { | 39 | void Mouse::UpdateThread(std::stop_token stop_token) { |
| 40 | Common::SetCurrentThreadName("yuzu:input:Mouse"); | 40 | Common::SetCurrentThreadName("Mouse"); |
| 41 | constexpr int update_time = 10; | 41 | constexpr int update_time = 10; |
| 42 | while (!stop_token.stop_requested()) { | 42 | while (!stop_token.stop_requested()) { |
| 43 | if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { | 43 | if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { |
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 5cc1ccbd9..45ce588f0 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp | |||
| @@ -40,8 +40,8 @@ public: | |||
| 40 | void EnableMotion() { | 40 | void EnableMotion() { |
| 41 | if (sdl_controller) { | 41 | if (sdl_controller) { |
| 42 | SDL_GameController* controller = sdl_controller.get(); | 42 | SDL_GameController* controller = sdl_controller.get(); |
| 43 | has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL); | 43 | has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE; |
| 44 | has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO); | 44 | has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE; |
| 45 | if (has_accel) { | 45 | if (has_accel) { |
| 46 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); | 46 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); |
| 47 | } | 47 | } |
| @@ -114,6 +114,20 @@ public: | |||
| 114 | } | 114 | } |
| 115 | return false; | 115 | return false; |
| 116 | } | 116 | } |
| 117 | |||
| 118 | void EnableVibration(bool is_enabled) { | ||
| 119 | has_vibration = is_enabled; | ||
| 120 | is_vibration_tested = true; | ||
| 121 | } | ||
| 122 | |||
| 123 | bool HasVibration() const { | ||
| 124 | return has_vibration; | ||
| 125 | } | ||
| 126 | |||
| 127 | bool IsVibrationTested() const { | ||
| 128 | return is_vibration_tested; | ||
| 129 | } | ||
| 130 | |||
| 117 | /** | 131 | /** |
| 118 | * The Pad identifier of the joystick | 132 | * The Pad identifier of the joystick |
| 119 | */ | 133 | */ |
| @@ -236,6 +250,8 @@ private: | |||
| 236 | u64 last_motion_update{}; | 250 | u64 last_motion_update{}; |
| 237 | bool has_gyro{false}; | 251 | bool has_gyro{false}; |
| 238 | bool has_accel{false}; | 252 | bool has_accel{false}; |
| 253 | bool has_vibration{false}; | ||
| 254 | bool is_vibration_tested{false}; | ||
| 239 | BasicMotion motion; | 255 | BasicMotion motion; |
| 240 | }; | 256 | }; |
| 241 | 257 | ||
| @@ -436,7 +452,7 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en | |||
| 436 | initialized = true; | 452 | initialized = true; |
| 437 | if (start_thread) { | 453 | if (start_thread) { |
| 438 | poll_thread = std::thread([this] { | 454 | poll_thread = std::thread([this] { |
| 439 | Common::SetCurrentThreadName("yuzu:input:SDL"); | 455 | Common::SetCurrentThreadName("SDL_MainLoop"); |
| 440 | using namespace std::chrono_literals; | 456 | using namespace std::chrono_literals; |
| 441 | while (initialized) { | 457 | while (initialized) { |
| 442 | SDL_PumpEvents(); | 458 | SDL_PumpEvents(); |
| @@ -444,7 +460,7 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en | |||
| 444 | } | 460 | } |
| 445 | }); | 461 | }); |
| 446 | vibration_thread = std::thread([this] { | 462 | vibration_thread = std::thread([this] { |
| 447 | Common::SetCurrentThreadName("yuzu:input:SDL_Vibration"); | 463 | Common::SetCurrentThreadName("SDL_Vibration"); |
| 448 | using namespace std::chrono_literals; | 464 | using namespace std::chrono_literals; |
| 449 | while (initialized) { | 465 | while (initialized) { |
| 450 | SendVibrations(); | 466 | SendVibrations(); |
| @@ -517,7 +533,7 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const { | |||
| 517 | return devices; | 533 | return devices; |
| 518 | } | 534 | } |
| 519 | 535 | ||
| 520 | Common::Input::VibrationError SDLDriver::SetRumble( | 536 | Common::Input::VibrationError SDLDriver::SetVibration( |
| 521 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { | 537 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { |
| 522 | const auto joystick = | 538 | const auto joystick = |
| 523 | GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port)); | 539 | GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port)); |
| @@ -546,13 +562,6 @@ Common::Input::VibrationError SDLDriver::SetRumble( | |||
| 546 | .type = Common::Input::VibrationAmplificationType::Exponential, | 562 | .type = Common::Input::VibrationAmplificationType::Exponential, |
| 547 | }; | 563 | }; |
| 548 | 564 | ||
| 549 | if (vibration.type == Common::Input::VibrationAmplificationType::Test) { | ||
| 550 | if (!joystick->RumblePlay(new_vibration)) { | ||
| 551 | return Common::Input::VibrationError::Unknown; | ||
| 552 | } | ||
| 553 | return Common::Input::VibrationError::None; | ||
| 554 | } | ||
| 555 | |||
| 556 | vibration_queue.Push(VibrationRequest{ | 565 | vibration_queue.Push(VibrationRequest{ |
| 557 | .identifier = identifier, | 566 | .identifier = identifier, |
| 558 | .vibration = new_vibration, | 567 | .vibration = new_vibration, |
| @@ -561,6 +570,45 @@ Common::Input::VibrationError SDLDriver::SetRumble( | |||
| 561 | return Common::Input::VibrationError::None; | 570 | return Common::Input::VibrationError::None; |
| 562 | } | 571 | } |
| 563 | 572 | ||
| 573 | bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) { | ||
| 574 | const auto joystick = | ||
| 575 | GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port)); | ||
| 576 | |||
| 577 | constexpr Common::Input::VibrationStatus test_vibration{ | ||
| 578 | .low_amplitude = 1, | ||
| 579 | .low_frequency = 160.0f, | ||
| 580 | .high_amplitude = 1, | ||
| 581 | .high_frequency = 320.0f, | ||
| 582 | .type = Common::Input::VibrationAmplificationType::Exponential, | ||
| 583 | }; | ||
| 584 | |||
| 585 | constexpr Common::Input::VibrationStatus zero_vibration{ | ||
| 586 | .low_amplitude = 0, | ||
| 587 | .low_frequency = 160.0f, | ||
| 588 | .high_amplitude = 0, | ||
| 589 | .high_frequency = 320.0f, | ||
| 590 | .type = Common::Input::VibrationAmplificationType::Exponential, | ||
| 591 | }; | ||
| 592 | |||
| 593 | if (joystick->IsVibrationTested()) { | ||
| 594 | return joystick->HasVibration(); | ||
| 595 | } | ||
| 596 | |||
| 597 | // First vibration might fail | ||
| 598 | joystick->RumblePlay(test_vibration); | ||
| 599 | |||
| 600 | // Wait for about 15ms to ensure the controller is ready for the stop command | ||
| 601 | std::this_thread::sleep_for(std::chrono::milliseconds(15)); | ||
| 602 | |||
| 603 | if (!joystick->RumblePlay(zero_vibration)) { | ||
| 604 | joystick->EnableVibration(false); | ||
| 605 | return false; | ||
| 606 | } | ||
| 607 | |||
| 608 | joystick->EnableVibration(true); | ||
| 609 | return true; | ||
| 610 | } | ||
| 611 | |||
| 564 | void SDLDriver::SendVibrations() { | 612 | void SDLDriver::SendVibrations() { |
| 565 | while (!vibration_queue.Empty()) { | 613 | while (!vibration_queue.Empty()) { |
| 566 | VibrationRequest request; | 614 | VibrationRequest request; |
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index fc3a44572..d1b4471cf 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h | |||
| @@ -61,9 +61,11 @@ public: | |||
| 61 | 61 | ||
| 62 | bool IsStickInverted(const Common::ParamPackage& params) override; | 62 | bool IsStickInverted(const Common::ParamPackage& params) override; |
| 63 | 63 | ||
| 64 | Common::Input::VibrationError SetRumble( | 64 | Common::Input::VibrationError SetVibration( |
| 65 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; | 65 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; |
| 66 | 66 | ||
| 67 | bool IsVibrationEnabled(const PadIdentifier& identifier) override; | ||
| 68 | |||
| 67 | private: | 69 | private: |
| 68 | struct VibrationRequest { | 70 | struct VibrationRequest { |
| 69 | PadIdentifier identifier; | 71 | PadIdentifier identifier; |
diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp new file mode 100644 index 000000000..0cd5129da --- /dev/null +++ b/src/input_common/drivers/virtual_amiibo.cpp | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <cstring> | ||
| 5 | #include <fmt/format.h> | ||
| 6 | |||
| 7 | #include "common/fs/file.h" | ||
| 8 | #include "common/fs/fs.h" | ||
| 9 | #include "common/fs/path_util.h" | ||
| 10 | #include "common/logging/log.h" | ||
| 11 | #include "common/settings.h" | ||
| 12 | #include "input_common/drivers/virtual_amiibo.h" | ||
| 13 | |||
| 14 | namespace InputCommon { | ||
| 15 | constexpr PadIdentifier identifier = { | ||
| 16 | .guid = Common::UUID{}, | ||
| 17 | .port = 0, | ||
| 18 | .pad = 0, | ||
| 19 | }; | ||
| 20 | |||
| 21 | VirtualAmiibo::VirtualAmiibo(std::string input_engine_) : InputEngine(std::move(input_engine_)) {} | ||
| 22 | |||
| 23 | VirtualAmiibo::~VirtualAmiibo() = default; | ||
| 24 | |||
| 25 | Common::Input::PollingError VirtualAmiibo::SetPollingMode( | ||
| 26 | [[maybe_unused]] const PadIdentifier& identifier_, | ||
| 27 | const Common::Input::PollingMode polling_mode_) { | ||
| 28 | polling_mode = polling_mode_; | ||
| 29 | |||
| 30 | if (polling_mode == Common::Input::PollingMode::NFC) { | ||
| 31 | if (state == State::Initialized) { | ||
| 32 | state = State::WaitingForAmiibo; | ||
| 33 | } | ||
| 34 | } else { | ||
| 35 | if (state == State::AmiiboIsOpen) { | ||
| 36 | CloseAmiibo(); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | return Common::Input::PollingError::None; | ||
| 41 | } | ||
| 42 | |||
| 43 | Common::Input::NfcState VirtualAmiibo::SupportsNfc( | ||
| 44 | [[maybe_unused]] const PadIdentifier& identifier_) const { | ||
| 45 | return Common::Input::NfcState::Success; | ||
| 46 | } | ||
| 47 | |||
| 48 | Common::Input::NfcState VirtualAmiibo::WriteNfcData( | ||
| 49 | [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { | ||
| 50 | const Common::FS::IOFile amiibo_file{file_path, Common::FS::FileAccessMode::ReadWrite, | ||
| 51 | Common::FS::FileType::BinaryFile}; | ||
| 52 | |||
| 53 | if (!amiibo_file.IsOpen()) { | ||
| 54 | LOG_ERROR(Core, "Amiibo is already on use"); | ||
| 55 | return Common::Input::NfcState::WriteFailed; | ||
| 56 | } | ||
| 57 | |||
| 58 | if (!amiibo_file.Write(data)) { | ||
| 59 | LOG_ERROR(Service_NFP, "Error writting to file"); | ||
| 60 | return Common::Input::NfcState::WriteFailed; | ||
| 61 | } | ||
| 62 | |||
| 63 | return Common::Input::NfcState::Success; | ||
| 64 | } | ||
| 65 | |||
| 66 | VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const { | ||
| 67 | return state; | ||
| 68 | } | ||
| 69 | |||
| 70 | VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { | ||
| 71 | const Common::FS::IOFile amiibo_file{filename, Common::FS::FileAccessMode::Read, | ||
| 72 | Common::FS::FileType::BinaryFile}; | ||
| 73 | |||
| 74 | if (state != State::WaitingForAmiibo) { | ||
| 75 | return Info::WrongDeviceState; | ||
| 76 | } | ||
| 77 | |||
| 78 | if (!amiibo_file.IsOpen()) { | ||
| 79 | return Info::UnableToLoad; | ||
| 80 | } | ||
| 81 | |||
| 82 | amiibo_data.resize(amiibo_size); | ||
| 83 | |||
| 84 | if (amiibo_file.Read(amiibo_data) < amiibo_size_without_password) { | ||
| 85 | return Info::NotAnAmiibo; | ||
| 86 | } | ||
| 87 | |||
| 88 | file_path = filename; | ||
| 89 | state = State::AmiiboIsOpen; | ||
| 90 | SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, amiibo_data}); | ||
| 91 | return Info::Success; | ||
| 92 | } | ||
| 93 | |||
| 94 | VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() { | ||
| 95 | state = polling_mode == Common::Input::PollingMode::NFC ? State::WaitingForAmiibo | ||
| 96 | : State::Initialized; | ||
| 97 | SetNfc(identifier, {Common::Input::NfcState::AmiiboRemoved, {}}); | ||
| 98 | return Info::Success; | ||
| 99 | } | ||
| 100 | |||
| 101 | } // namespace InputCommon | ||
diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h new file mode 100644 index 000000000..9eac07544 --- /dev/null +++ b/src/input_common/drivers/virtual_amiibo.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "input_common/input_engine.h" | ||
| 12 | |||
| 13 | namespace Common::FS { | ||
| 14 | class IOFile; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace InputCommon { | ||
| 18 | |||
| 19 | class VirtualAmiibo final : public InputEngine { | ||
| 20 | public: | ||
| 21 | enum class State { | ||
| 22 | Initialized, | ||
| 23 | WaitingForAmiibo, | ||
| 24 | AmiiboIsOpen, | ||
| 25 | }; | ||
| 26 | |||
| 27 | enum class Info { | ||
| 28 | Success, | ||
| 29 | UnableToLoad, | ||
| 30 | NotAnAmiibo, | ||
| 31 | WrongDeviceState, | ||
| 32 | Unknown, | ||
| 33 | }; | ||
| 34 | |||
| 35 | explicit VirtualAmiibo(std::string input_engine_); | ||
| 36 | ~VirtualAmiibo() override; | ||
| 37 | |||
| 38 | // Sets polling mode to a controller | ||
| 39 | Common::Input::PollingError SetPollingMode( | ||
| 40 | const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) override; | ||
| 41 | |||
| 42 | Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override; | ||
| 43 | |||
| 44 | Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_, | ||
| 45 | const std::vector<u8>& data) override; | ||
| 46 | |||
| 47 | State GetCurrentState() const; | ||
| 48 | |||
| 49 | Info LoadAmiibo(const std::string& amiibo_file); | ||
| 50 | Info CloseAmiibo(); | ||
| 51 | |||
| 52 | private: | ||
| 53 | static constexpr std::size_t amiibo_size = 0x21C; | ||
| 54 | static constexpr std::size_t amiibo_size_without_password = amiibo_size - 0x8; | ||
| 55 | |||
| 56 | std::string file_path{}; | ||
| 57 | State state{State::Initialized}; | ||
| 58 | std::vector<u8> amiibo_data; | ||
| 59 | Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Pasive}; | ||
| 60 | }; | ||
| 61 | } // namespace InputCommon | ||
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index 6ede0e4b0..61cfd0911 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp | |||
| @@ -102,6 +102,17 @@ void InputEngine::SetCamera(const PadIdentifier& identifier, | |||
| 102 | TriggerOnCameraChange(identifier, value); | 102 | TriggerOnCameraChange(identifier, value); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | void InputEngine::SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value) { | ||
| 106 | { | ||
| 107 | std::scoped_lock lock{mutex}; | ||
| 108 | ControllerData& controller = controller_list.at(identifier); | ||
| 109 | if (!configuring) { | ||
| 110 | controller.nfc = value; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | TriggerOnNfcChange(identifier, value); | ||
| 114 | } | ||
| 115 | |||
| 105 | bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { | 116 | bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { |
| 106 | std::scoped_lock lock{mutex}; | 117 | std::scoped_lock lock{mutex}; |
| 107 | const auto controller_iter = controller_list.find(identifier); | 118 | const auto controller_iter = controller_list.find(identifier); |
| @@ -189,6 +200,18 @@ Common::Input::CameraStatus InputEngine::GetCamera(const PadIdentifier& identifi | |||
| 189 | return controller.camera; | 200 | return controller.camera; |
| 190 | } | 201 | } |
| 191 | 202 | ||
| 203 | Common::Input::NfcStatus InputEngine::GetNfc(const PadIdentifier& identifier) const { | ||
| 204 | std::scoped_lock lock{mutex}; | ||
| 205 | const auto controller_iter = controller_list.find(identifier); | ||
| 206 | if (controller_iter == controller_list.cend()) { | ||
| 207 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | ||
| 208 | identifier.pad, identifier.port); | ||
| 209 | return {}; | ||
| 210 | } | ||
| 211 | const ControllerData& controller = controller_iter->second; | ||
| 212 | return controller.nfc; | ||
| 213 | } | ||
| 214 | |||
| 192 | void InputEngine::ResetButtonState() { | 215 | void InputEngine::ResetButtonState() { |
| 193 | for (const auto& controller : controller_list) { | 216 | for (const auto& controller : controller_list) { |
| 194 | for (const auto& button : controller.second.buttons) { | 217 | for (const auto& button : controller.second.buttons) { |
| @@ -355,6 +378,20 @@ void InputEngine::TriggerOnCameraChange(const PadIdentifier& identifier, | |||
| 355 | } | 378 | } |
| 356 | } | 379 | } |
| 357 | 380 | ||
| 381 | void InputEngine::TriggerOnNfcChange(const PadIdentifier& identifier, | ||
| 382 | [[maybe_unused]] const Common::Input::NfcStatus& value) { | ||
| 383 | std::scoped_lock lock{mutex_callback}; | ||
| 384 | for (const auto& poller_pair : callback_list) { | ||
| 385 | const InputIdentifier& poller = poller_pair.second; | ||
| 386 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Nfc, 0)) { | ||
| 387 | continue; | ||
| 388 | } | ||
| 389 | if (poller.callback.on_change) { | ||
| 390 | poller.callback.on_change(); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 358 | bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier, | 395 | bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier, |
| 359 | const PadIdentifier& identifier, EngineInputType type, | 396 | const PadIdentifier& identifier, EngineInputType type, |
| 360 | int index) const { | 397 | int index) const { |
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index f6b3c4610..d4c264a8e 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h | |||
| @@ -42,6 +42,7 @@ enum class EngineInputType { | |||
| 42 | Camera, | 42 | Camera, |
| 43 | HatButton, | 43 | HatButton, |
| 44 | Motion, | 44 | Motion, |
| 45 | Nfc, | ||
| 45 | }; | 46 | }; |
| 46 | 47 | ||
| 47 | namespace std { | 48 | namespace std { |
| @@ -107,12 +108,17 @@ public: | |||
| 107 | [[maybe_unused]] const Common::Input::LedStatus& led_status) {} | 108 | [[maybe_unused]] const Common::Input::LedStatus& led_status) {} |
| 108 | 109 | ||
| 109 | // Sets rumble to a controller | 110 | // Sets rumble to a controller |
| 110 | virtual Common::Input::VibrationError SetRumble( | 111 | virtual Common::Input::VibrationError SetVibration( |
| 111 | [[maybe_unused]] const PadIdentifier& identifier, | 112 | [[maybe_unused]] const PadIdentifier& identifier, |
| 112 | [[maybe_unused]] const Common::Input::VibrationStatus& vibration) { | 113 | [[maybe_unused]] const Common::Input::VibrationStatus& vibration) { |
| 113 | return Common::Input::VibrationError::NotSupported; | 114 | return Common::Input::VibrationError::NotSupported; |
| 114 | } | 115 | } |
| 115 | 116 | ||
| 117 | // Returns true if device supports vibrations | ||
| 118 | virtual bool IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) { | ||
| 119 | return false; | ||
| 120 | } | ||
| 121 | |||
| 116 | // Sets polling mode to a controller | 122 | // Sets polling mode to a controller |
| 117 | virtual Common::Input::PollingError SetPollingMode( | 123 | virtual Common::Input::PollingError SetPollingMode( |
| 118 | [[maybe_unused]] const PadIdentifier& identifier, | 124 | [[maybe_unused]] const PadIdentifier& identifier, |
| @@ -127,6 +133,18 @@ public: | |||
| 127 | return Common::Input::CameraError::NotSupported; | 133 | return Common::Input::CameraError::NotSupported; |
| 128 | } | 134 | } |
| 129 | 135 | ||
| 136 | // Request nfc data from a controller | ||
| 137 | virtual Common::Input::NfcState SupportsNfc( | ||
| 138 | [[maybe_unused]] const PadIdentifier& identifier) const { | ||
| 139 | return Common::Input::NfcState::NotSupported; | ||
| 140 | } | ||
| 141 | |||
| 142 | // Writes data to an nfc tag | ||
| 143 | virtual Common::Input::NfcState WriteNfcData([[maybe_unused]] const PadIdentifier& identifier, | ||
| 144 | [[maybe_unused]] const std::vector<u8>& data) { | ||
| 145 | return Common::Input::NfcState::NotSupported; | ||
| 146 | } | ||
| 147 | |||
| 130 | // Returns the engine name | 148 | // Returns the engine name |
| 131 | [[nodiscard]] const std::string& GetEngineName() const; | 149 | [[nodiscard]] const std::string& GetEngineName() const; |
| 132 | 150 | ||
| @@ -183,6 +201,7 @@ public: | |||
| 183 | Common::Input::BatteryLevel GetBattery(const PadIdentifier& identifier) const; | 201 | Common::Input::BatteryLevel GetBattery(const PadIdentifier& identifier) const; |
| 184 | BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const; | 202 | BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const; |
| 185 | Common::Input::CameraStatus GetCamera(const PadIdentifier& identifier) const; | 203 | Common::Input::CameraStatus GetCamera(const PadIdentifier& identifier) const; |
| 204 | Common::Input::NfcStatus GetNfc(const PadIdentifier& identifier) const; | ||
| 186 | 205 | ||
| 187 | int SetCallback(InputIdentifier input_identifier); | 206 | int SetCallback(InputIdentifier input_identifier); |
| 188 | void SetMappingCallback(MappingCallback callback); | 207 | void SetMappingCallback(MappingCallback callback); |
| @@ -195,6 +214,7 @@ protected: | |||
| 195 | void SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value); | 214 | void SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value); |
| 196 | void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value); | 215 | void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value); |
| 197 | void SetCamera(const PadIdentifier& identifier, const Common::Input::CameraStatus& value); | 216 | void SetCamera(const PadIdentifier& identifier, const Common::Input::CameraStatus& value); |
| 217 | void SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value); | ||
| 198 | 218 | ||
| 199 | virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const { | 219 | virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const { |
| 200 | return "Unknown"; | 220 | return "Unknown"; |
| @@ -208,6 +228,7 @@ private: | |||
| 208 | std::unordered_map<int, BasicMotion> motions; | 228 | std::unordered_map<int, BasicMotion> motions; |
| 209 | Common::Input::BatteryLevel battery{}; | 229 | Common::Input::BatteryLevel battery{}; |
| 210 | Common::Input::CameraStatus camera{}; | 230 | Common::Input::CameraStatus camera{}; |
| 231 | Common::Input::NfcStatus nfc{}; | ||
| 211 | }; | 232 | }; |
| 212 | 233 | ||
| 213 | void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value); | 234 | void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value); |
| @@ -218,6 +239,7 @@ private: | |||
| 218 | const BasicMotion& value); | 239 | const BasicMotion& value); |
| 219 | void TriggerOnCameraChange(const PadIdentifier& identifier, | 240 | void TriggerOnCameraChange(const PadIdentifier& identifier, |
| 220 | const Common::Input::CameraStatus& value); | 241 | const Common::Input::CameraStatus& value); |
| 242 | void TriggerOnNfcChange(const PadIdentifier& identifier, const Common::Input::NfcStatus& value); | ||
| 221 | 243 | ||
| 222 | bool IsInputIdentifierEqual(const InputIdentifier& input_identifier, | 244 | bool IsInputIdentifierEqual(const InputIdentifier& input_identifier, |
| 223 | const PadIdentifier& identifier, EngineInputType type, | 245 | const PadIdentifier& identifier, EngineInputType type, |
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index ffb9b945e..4ac182147 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp | |||
| @@ -691,9 +691,56 @@ public: | |||
| 691 | } | 691 | } |
| 692 | 692 | ||
| 693 | void OnChange() { | 693 | void OnChange() { |
| 694 | const auto camera_status = GetStatus(); | ||
| 695 | |||
| 694 | const Common::Input::CallbackStatus status{ | 696 | const Common::Input::CallbackStatus status{ |
| 695 | .type = Common::Input::InputType::IrSensor, | 697 | .type = Common::Input::InputType::IrSensor, |
| 696 | .camera_status = GetStatus(), | 698 | .camera_status = camera_status.format, |
| 699 | .raw_data = camera_status.data, | ||
| 700 | }; | ||
| 701 | |||
| 702 | TriggerOnChange(status); | ||
| 703 | } | ||
| 704 | |||
| 705 | private: | ||
| 706 | const PadIdentifier identifier; | ||
| 707 | int callback_key; | ||
| 708 | InputEngine* input_engine; | ||
| 709 | }; | ||
| 710 | |||
| 711 | class InputFromNfc final : public Common::Input::InputDevice { | ||
| 712 | public: | ||
| 713 | explicit InputFromNfc(PadIdentifier identifier_, InputEngine* input_engine_) | ||
| 714 | : identifier(identifier_), input_engine(input_engine_) { | ||
| 715 | UpdateCallback engine_callback{[this]() { OnChange(); }}; | ||
| 716 | const InputIdentifier input_identifier{ | ||
| 717 | .identifier = identifier, | ||
| 718 | .type = EngineInputType::Nfc, | ||
| 719 | .index = 0, | ||
| 720 | .callback = engine_callback, | ||
| 721 | }; | ||
| 722 | callback_key = input_engine->SetCallback(input_identifier); | ||
| 723 | } | ||
| 724 | |||
| 725 | ~InputFromNfc() override { | ||
| 726 | input_engine->DeleteCallback(callback_key); | ||
| 727 | } | ||
| 728 | |||
| 729 | Common::Input::NfcStatus GetStatus() const { | ||
| 730 | return input_engine->GetNfc(identifier); | ||
| 731 | } | ||
| 732 | |||
| 733 | void ForceUpdate() override { | ||
| 734 | OnChange(); | ||
| 735 | } | ||
| 736 | |||
| 737 | void OnChange() { | ||
| 738 | const auto nfc_status = GetStatus(); | ||
| 739 | |||
| 740 | const Common::Input::CallbackStatus status{ | ||
| 741 | .type = Common::Input::InputType::Nfc, | ||
| 742 | .nfc_status = nfc_status.state, | ||
| 743 | .raw_data = nfc_status.data, | ||
| 697 | }; | 744 | }; |
| 698 | 745 | ||
| 699 | TriggerOnChange(status); | 746 | TriggerOnChange(status); |
| @@ -716,7 +763,11 @@ public: | |||
| 716 | 763 | ||
| 717 | Common::Input::VibrationError SetVibration( | 764 | Common::Input::VibrationError SetVibration( |
| 718 | const Common::Input::VibrationStatus& vibration_status) override { | 765 | const Common::Input::VibrationStatus& vibration_status) override { |
| 719 | return input_engine->SetRumble(identifier, vibration_status); | 766 | return input_engine->SetVibration(identifier, vibration_status); |
| 767 | } | ||
| 768 | |||
| 769 | bool IsVibrationEnabled() override { | ||
| 770 | return input_engine->IsVibrationEnabled(identifier); | ||
| 720 | } | 771 | } |
| 721 | 772 | ||
| 722 | Common::Input::PollingError SetPollingMode(Common::Input::PollingMode polling_mode) override { | 773 | Common::Input::PollingError SetPollingMode(Common::Input::PollingMode polling_mode) override { |
| @@ -727,6 +778,14 @@ public: | |||
| 727 | return input_engine->SetCameraFormat(identifier, camera_format); | 778 | return input_engine->SetCameraFormat(identifier, camera_format); |
| 728 | } | 779 | } |
| 729 | 780 | ||
| 781 | Common::Input::NfcState SupportsNfc() const override { | ||
| 782 | return input_engine->SupportsNfc(identifier); | ||
| 783 | } | ||
| 784 | |||
| 785 | Common::Input::NfcState WriteNfcData(const std::vector<u8>& data) override { | ||
| 786 | return input_engine->WriteNfcData(identifier, data); | ||
| 787 | } | ||
| 788 | |||
| 730 | private: | 789 | private: |
| 731 | const PadIdentifier identifier; | 790 | const PadIdentifier identifier; |
| 732 | InputEngine* input_engine; | 791 | InputEngine* input_engine; |
| @@ -742,8 +801,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateButtonDevice( | |||
| 742 | 801 | ||
| 743 | const auto button_id = params.Get("button", 0); | 802 | const auto button_id = params.Get("button", 0); |
| 744 | const auto keyboard_key = params.Get("code", 0); | 803 | const auto keyboard_key = params.Get("code", 0); |
| 745 | const auto toggle = params.Get("toggle", false); | 804 | const auto toggle = params.Get("toggle", false) != 0; |
| 746 | const auto inverted = params.Get("inverted", false); | 805 | const auto inverted = params.Get("inverted", false) != 0; |
| 747 | input_engine->PreSetController(identifier); | 806 | input_engine->PreSetController(identifier); |
| 748 | input_engine->PreSetButton(identifier, button_id); | 807 | input_engine->PreSetButton(identifier, button_id); |
| 749 | input_engine->PreSetButton(identifier, keyboard_key); | 808 | input_engine->PreSetButton(identifier, keyboard_key); |
| @@ -765,8 +824,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice( | |||
| 765 | 824 | ||
| 766 | const auto button_id = params.Get("hat", 0); | 825 | const auto button_id = params.Get("hat", 0); |
| 767 | const auto direction = input_engine->GetHatButtonId(params.Get("direction", "")); | 826 | const auto direction = input_engine->GetHatButtonId(params.Get("direction", "")); |
| 768 | const auto toggle = params.Get("toggle", false); | 827 | const auto toggle = params.Get("toggle", false) != 0; |
| 769 | const auto inverted = params.Get("inverted", false); | 828 | const auto inverted = params.Get("inverted", false) != 0; |
| 770 | 829 | ||
| 771 | input_engine->PreSetController(identifier); | 830 | input_engine->PreSetController(identifier); |
| 772 | input_engine->PreSetHatButton(identifier, button_id); | 831 | input_engine->PreSetHatButton(identifier, button_id); |
| @@ -824,7 +883,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateAnalogDevice( | |||
| 824 | .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f), | 883 | .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f), |
| 825 | .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f), | 884 | .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f), |
| 826 | .inverted = params.Get("invert", "+") == "-", | 885 | .inverted = params.Get("invert", "+") == "-", |
| 827 | .toggle = static_cast<bool>(params.Get("toggle", false)), | 886 | .toggle = params.Get("toggle", false) != 0, |
| 828 | }; | 887 | }; |
| 829 | input_engine->PreSetController(identifier); | 888 | input_engine->PreSetController(identifier); |
| 830 | input_engine->PreSetAxis(identifier, axis); | 889 | input_engine->PreSetAxis(identifier, axis); |
| @@ -840,8 +899,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTriggerDevice( | |||
| 840 | }; | 899 | }; |
| 841 | 900 | ||
| 842 | const auto button = params.Get("button", 0); | 901 | const auto button = params.Get("button", 0); |
| 843 | const auto toggle = params.Get("toggle", false); | 902 | const auto toggle = params.Get("toggle", false) != 0; |
| 844 | const auto inverted = params.Get("inverted", false); | 903 | const auto inverted = params.Get("inverted", false) != 0; |
| 845 | 904 | ||
| 846 | const auto axis = params.Get("axis", 0); | 905 | const auto axis = params.Get("axis", 0); |
| 847 | const Common::Input::AnalogProperties properties = { | 906 | const Common::Input::AnalogProperties properties = { |
| @@ -871,8 +930,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice( | |||
| 871 | }; | 930 | }; |
| 872 | 931 | ||
| 873 | const auto button = params.Get("button", 0); | 932 | const auto button = params.Get("button", 0); |
| 874 | const auto toggle = params.Get("toggle", false); | 933 | const auto toggle = params.Get("toggle", false) != 0; |
| 875 | const auto inverted = params.Get("inverted", false); | 934 | const auto inverted = params.Get("inverted", false) != 0; |
| 876 | 935 | ||
| 877 | const auto axis_x = params.Get("axis_x", 0); | 936 | const auto axis_x = params.Get("axis_x", 0); |
| 878 | const Common::Input::AnalogProperties properties_x = { | 937 | const Common::Input::AnalogProperties properties_x = { |
| @@ -978,6 +1037,18 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateCameraDevice( | |||
| 978 | return std::make_unique<InputFromCamera>(identifier, input_engine.get()); | 1037 | return std::make_unique<InputFromCamera>(identifier, input_engine.get()); |
| 979 | } | 1038 | } |
| 980 | 1039 | ||
| 1040 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateNfcDevice( | ||
| 1041 | const Common::ParamPackage& params) { | ||
| 1042 | const PadIdentifier identifier = { | ||
| 1043 | .guid = Common::UUID{params.Get("guid", "")}, | ||
| 1044 | .port = static_cast<std::size_t>(params.Get("port", 0)), | ||
| 1045 | .pad = static_cast<std::size_t>(params.Get("pad", 0)), | ||
| 1046 | }; | ||
| 1047 | |||
| 1048 | input_engine->PreSetController(identifier); | ||
| 1049 | return std::make_unique<InputFromNfc>(identifier, input_engine.get()); | ||
| 1050 | } | ||
| 1051 | |||
| 981 | InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_) | 1052 | InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_) |
| 982 | : input_engine(std::move(input_engine_)) {} | 1053 | : input_engine(std::move(input_engine_)) {} |
| 983 | 1054 | ||
| @@ -989,6 +1060,9 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::Create( | |||
| 989 | if (params.Has("camera")) { | 1060 | if (params.Has("camera")) { |
| 990 | return CreateCameraDevice(params); | 1061 | return CreateCameraDevice(params); |
| 991 | } | 1062 | } |
| 1063 | if (params.Has("nfc")) { | ||
| 1064 | return CreateNfcDevice(params); | ||
| 1065 | } | ||
| 992 | if (params.Has("button") && params.Has("axis")) { | 1066 | if (params.Has("button") && params.Has("axis")) { |
| 993 | return CreateTriggerDevice(params); | 1067 | return CreateTriggerDevice(params); |
| 994 | } | 1068 | } |
diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h index 4410a8415..d7db13ce4 100644 --- a/src/input_common/input_poller.h +++ b/src/input_common/input_poller.h | |||
| @@ -222,6 +222,16 @@ private: | |||
| 222 | std::unique_ptr<Common::Input::InputDevice> CreateCameraDevice( | 222 | std::unique_ptr<Common::Input::InputDevice> CreateCameraDevice( |
| 223 | const Common::ParamPackage& params); | 223 | const Common::ParamPackage& params); |
| 224 | 224 | ||
| 225 | /** | ||
| 226 | * Creates a nfc device from the parameters given. | ||
| 227 | * @param params contains parameters for creating the device: | ||
| 228 | * - "guid": text string for identifying controllers | ||
| 229 | * - "port": port of the connected device | ||
| 230 | * - "pad": slot of the connected controller | ||
| 231 | * @returns a unique input device with the parameters specified | ||
| 232 | */ | ||
| 233 | std::unique_ptr<Common::Input::InputDevice> CreateNfcDevice(const Common::ParamPackage& params); | ||
| 234 | |||
| 225 | std::shared_ptr<InputEngine> input_engine; | 235 | std::shared_ptr<InputEngine> input_engine; |
| 226 | }; | 236 | }; |
| 227 | } // namespace InputCommon | 237 | } // namespace InputCommon |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 75a57b9fc..b2064ef95 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "input_common/drivers/tas_input.h" | 11 | #include "input_common/drivers/tas_input.h" |
| 12 | #include "input_common/drivers/touch_screen.h" | 12 | #include "input_common/drivers/touch_screen.h" |
| 13 | #include "input_common/drivers/udp_client.h" | 13 | #include "input_common/drivers/udp_client.h" |
| 14 | #include "input_common/drivers/virtual_amiibo.h" | ||
| 14 | #include "input_common/helpers/stick_from_buttons.h" | 15 | #include "input_common/helpers/stick_from_buttons.h" |
| 15 | #include "input_common/helpers/touch_from_buttons.h" | 16 | #include "input_common/helpers/touch_from_buttons.h" |
| 16 | #include "input_common/input_engine.h" | 17 | #include "input_common/input_engine.h" |
| @@ -87,6 +88,15 @@ struct InputSubsystem::Impl { | |||
| 87 | Common::Input::RegisterFactory<Common::Input::OutputDevice>(camera->GetEngineName(), | 88 | Common::Input::RegisterFactory<Common::Input::OutputDevice>(camera->GetEngineName(), |
| 88 | camera_output_factory); | 89 | camera_output_factory); |
| 89 | 90 | ||
| 91 | virtual_amiibo = std::make_shared<VirtualAmiibo>("virtual_amiibo"); | ||
| 92 | virtual_amiibo->SetMappingCallback(mapping_callback); | ||
| 93 | virtual_amiibo_input_factory = std::make_shared<InputFactory>(virtual_amiibo); | ||
| 94 | virtual_amiibo_output_factory = std::make_shared<OutputFactory>(virtual_amiibo); | ||
| 95 | Common::Input::RegisterFactory<Common::Input::InputDevice>(virtual_amiibo->GetEngineName(), | ||
| 96 | virtual_amiibo_input_factory); | ||
| 97 | Common::Input::RegisterFactory<Common::Input::OutputDevice>(virtual_amiibo->GetEngineName(), | ||
| 98 | virtual_amiibo_output_factory); | ||
| 99 | |||
| 90 | #ifdef HAVE_SDL2 | 100 | #ifdef HAVE_SDL2 |
| 91 | sdl = std::make_shared<SDLDriver>("sdl"); | 101 | sdl = std::make_shared<SDLDriver>("sdl"); |
| 92 | sdl->SetMappingCallback(mapping_callback); | 102 | sdl->SetMappingCallback(mapping_callback); |
| @@ -327,6 +337,7 @@ struct InputSubsystem::Impl { | |||
| 327 | std::shared_ptr<TasInput::Tas> tas_input; | 337 | std::shared_ptr<TasInput::Tas> tas_input; |
| 328 | std::shared_ptr<CemuhookUDP::UDPClient> udp_client; | 338 | std::shared_ptr<CemuhookUDP::UDPClient> udp_client; |
| 329 | std::shared_ptr<Camera> camera; | 339 | std::shared_ptr<Camera> camera; |
| 340 | std::shared_ptr<VirtualAmiibo> virtual_amiibo; | ||
| 330 | 341 | ||
| 331 | std::shared_ptr<InputFactory> keyboard_factory; | 342 | std::shared_ptr<InputFactory> keyboard_factory; |
| 332 | std::shared_ptr<InputFactory> mouse_factory; | 343 | std::shared_ptr<InputFactory> mouse_factory; |
| @@ -335,6 +346,7 @@ struct InputSubsystem::Impl { | |||
| 335 | std::shared_ptr<InputFactory> udp_client_input_factory; | 346 | std::shared_ptr<InputFactory> udp_client_input_factory; |
| 336 | std::shared_ptr<InputFactory> tas_input_factory; | 347 | std::shared_ptr<InputFactory> tas_input_factory; |
| 337 | std::shared_ptr<InputFactory> camera_input_factory; | 348 | std::shared_ptr<InputFactory> camera_input_factory; |
| 349 | std::shared_ptr<InputFactory> virtual_amiibo_input_factory; | ||
| 338 | 350 | ||
| 339 | std::shared_ptr<OutputFactory> keyboard_output_factory; | 351 | std::shared_ptr<OutputFactory> keyboard_output_factory; |
| 340 | std::shared_ptr<OutputFactory> mouse_output_factory; | 352 | std::shared_ptr<OutputFactory> mouse_output_factory; |
| @@ -342,6 +354,7 @@ struct InputSubsystem::Impl { | |||
| 342 | std::shared_ptr<OutputFactory> udp_client_output_factory; | 354 | std::shared_ptr<OutputFactory> udp_client_output_factory; |
| 343 | std::shared_ptr<OutputFactory> tas_output_factory; | 355 | std::shared_ptr<OutputFactory> tas_output_factory; |
| 344 | std::shared_ptr<OutputFactory> camera_output_factory; | 356 | std::shared_ptr<OutputFactory> camera_output_factory; |
| 357 | std::shared_ptr<OutputFactory> virtual_amiibo_output_factory; | ||
| 345 | 358 | ||
| 346 | #ifdef HAVE_SDL2 | 359 | #ifdef HAVE_SDL2 |
| 347 | std::shared_ptr<SDLDriver> sdl; | 360 | std::shared_ptr<SDLDriver> sdl; |
| @@ -402,6 +415,14 @@ const Camera* InputSubsystem::GetCamera() const { | |||
| 402 | return impl->camera.get(); | 415 | return impl->camera.get(); |
| 403 | } | 416 | } |
| 404 | 417 | ||
| 418 | VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() { | ||
| 419 | return impl->virtual_amiibo.get(); | ||
| 420 | } | ||
| 421 | |||
| 422 | const VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() const { | ||
| 423 | return impl->virtual_amiibo.get(); | ||
| 424 | } | ||
| 425 | |||
| 405 | std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const { | 426 | std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const { |
| 406 | return impl->GetInputDevices(); | 427 | return impl->GetInputDevices(); |
| 407 | } | 428 | } |
diff --git a/src/input_common/main.h b/src/input_common/main.h index 9a969e747..ced252383 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h | |||
| @@ -33,6 +33,7 @@ class Camera; | |||
| 33 | class Keyboard; | 33 | class Keyboard; |
| 34 | class Mouse; | 34 | class Mouse; |
| 35 | class TouchScreen; | 35 | class TouchScreen; |
| 36 | class VirtualAmiibo; | ||
| 36 | struct MappingData; | 37 | struct MappingData; |
| 37 | } // namespace InputCommon | 38 | } // namespace InputCommon |
| 38 | 39 | ||
| @@ -101,6 +102,12 @@ public: | |||
| 101 | /// Retrieves the underlying camera input device. | 102 | /// Retrieves the underlying camera input device. |
| 102 | [[nodiscard]] const Camera* GetCamera() const; | 103 | [[nodiscard]] const Camera* GetCamera() const; |
| 103 | 104 | ||
| 105 | /// Retrieves the underlying virtual amiibo input device. | ||
| 106 | [[nodiscard]] VirtualAmiibo* GetVirtualAmiibo(); | ||
| 107 | |||
| 108 | /// Retrieves the underlying virtual amiibo input device. | ||
| 109 | [[nodiscard]] const VirtualAmiibo* GetVirtualAmiibo() const; | ||
| 110 | |||
| 104 | /** | 111 | /** |
| 105 | * Returns all available input devices that this Factory can create a new device with. | 112 | * Returns all available input devices that this Factory can create a new device with. |
| 106 | * Each returned ParamPackage should have a `display` field used for display, a `engine` field | 113 | * Each returned ParamPackage should have a `display` field used for display, a `engine` field |