diff options
Diffstat (limited to 'src/input_common/drivers')
| -rw-r--r-- | src/input_common/drivers/joycon.cpp | 133 | ||||
| -rw-r--r-- | src/input_common/drivers/joycon.h | 18 | ||||
| -rw-r--r-- | src/input_common/drivers/sdl_driver.cpp | 32 | ||||
| -rw-r--r-- | src/input_common/drivers/virtual_amiibo.cpp | 132 | ||||
| -rw-r--r-- | src/input_common/drivers/virtual_amiibo.h | 17 |
5 files changed, 298 insertions, 34 deletions
diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp index b2b5677c8..52494e0d9 100644 --- a/src/input_common/drivers/joycon.cpp +++ b/src/input_common/drivers/joycon.cpp | |||
| @@ -195,8 +195,8 @@ void Joycons::RegisterNewDevice(SDL_hid_device_info* device_info) { | |||
| 195 | OnMotionUpdate(port, type, id, value); | 195 | OnMotionUpdate(port, type, id, value); |
| 196 | }}, | 196 | }}, |
| 197 | .on_ring_data = {[this](f32 ring_data) { OnRingConUpdate(ring_data); }}, | 197 | .on_ring_data = {[this](f32 ring_data) { OnRingConUpdate(ring_data); }}, |
| 198 | .on_amiibo_data = {[this, port, type](const std::vector<u8>& amiibo_data) { | 198 | .on_amiibo_data = {[this, port, type](const Joycon::TagInfo& tag_info) { |
| 199 | OnAmiiboUpdate(port, type, amiibo_data); | 199 | OnAmiiboUpdate(port, type, tag_info); |
| 200 | }}, | 200 | }}, |
| 201 | .on_camera_data = {[this, port](const std::vector<u8>& camera_data, | 201 | .on_camera_data = {[this, port](const std::vector<u8>& camera_data, |
| 202 | Joycon::IrsResolution format) { | 202 | Joycon::IrsResolution format) { |
| @@ -291,13 +291,105 @@ Common::Input::NfcState Joycons::SupportsNfc(const PadIdentifier& identifier_) c | |||
| 291 | return Common::Input::NfcState::Success; | 291 | return Common::Input::NfcState::Success; |
| 292 | }; | 292 | }; |
| 293 | 293 | ||
| 294 | Common::Input::NfcState Joycons::StartNfcPolling(const PadIdentifier& identifier) { | ||
| 295 | auto handle = GetHandle(identifier); | ||
| 296 | if (handle == nullptr) { | ||
| 297 | return Common::Input::NfcState::Unknown; | ||
| 298 | } | ||
| 299 | return TranslateDriverResult(handle->StartNfcPolling()); | ||
| 300 | }; | ||
| 301 | |||
| 302 | Common::Input::NfcState Joycons::StopNfcPolling(const PadIdentifier& identifier) { | ||
| 303 | auto handle = GetHandle(identifier); | ||
| 304 | if (handle == nullptr) { | ||
| 305 | return Common::Input::NfcState::Unknown; | ||
| 306 | } | ||
| 307 | return TranslateDriverResult(handle->StopNfcPolling()); | ||
| 308 | }; | ||
| 309 | |||
| 310 | Common::Input::NfcState Joycons::ReadAmiiboData(const PadIdentifier& identifier, | ||
| 311 | std::vector<u8>& out_data) { | ||
| 312 | auto handle = GetHandle(identifier); | ||
| 313 | if (handle == nullptr) { | ||
| 314 | return Common::Input::NfcState::Unknown; | ||
| 315 | } | ||
| 316 | return TranslateDriverResult(handle->ReadAmiiboData(out_data)); | ||
| 317 | } | ||
| 318 | |||
| 294 | Common::Input::NfcState Joycons::WriteNfcData(const PadIdentifier& identifier, | 319 | Common::Input::NfcState Joycons::WriteNfcData(const PadIdentifier& identifier, |
| 295 | const std::vector<u8>& data) { | 320 | const std::vector<u8>& data) { |
| 296 | auto handle = GetHandle(identifier); | 321 | auto handle = GetHandle(identifier); |
| 297 | if (handle->WriteNfcData(data) != Joycon::DriverResult::Success) { | 322 | if (handle == nullptr) { |
| 298 | return Common::Input::NfcState::WriteFailed; | 323 | return Common::Input::NfcState::Unknown; |
| 299 | } | 324 | } |
| 300 | return Common::Input::NfcState::Success; | 325 | return TranslateDriverResult(handle->WriteNfcData(data)); |
| 326 | }; | ||
| 327 | |||
| 328 | Common::Input::NfcState Joycons::ReadMifareData(const PadIdentifier& identifier, | ||
| 329 | const Common::Input::MifareRequest& request, | ||
| 330 | Common::Input::MifareRequest& data) { | ||
| 331 | auto handle = GetHandle(identifier); | ||
| 332 | if (handle == nullptr) { | ||
| 333 | return Common::Input::NfcState::Unknown; | ||
| 334 | } | ||
| 335 | |||
| 336 | const auto command = static_cast<Joycon::MifareCmd>(request.data[0].command); | ||
| 337 | std::vector<Joycon::MifareReadChunk> read_request{}; | ||
| 338 | for (const auto& request_data : request.data) { | ||
| 339 | if (request_data.command == 0) { | ||
| 340 | continue; | ||
| 341 | } | ||
| 342 | Joycon::MifareReadChunk chunk = { | ||
| 343 | .command = command, | ||
| 344 | .sector_key = {}, | ||
| 345 | .sector = request_data.sector, | ||
| 346 | }; | ||
| 347 | memcpy(chunk.sector_key.data(), request_data.key.data(), | ||
| 348 | sizeof(Joycon::MifareReadChunk::sector_key)); | ||
| 349 | read_request.emplace_back(chunk); | ||
| 350 | } | ||
| 351 | |||
| 352 | std::vector<Joycon::MifareReadData> read_data(read_request.size()); | ||
| 353 | const auto result = handle->ReadMifareData(read_request, read_data); | ||
| 354 | if (result == Joycon::DriverResult::Success) { | ||
| 355 | for (std::size_t i = 0; i < read_request.size(); i++) { | ||
| 356 | data.data[i] = { | ||
| 357 | .command = static_cast<u8>(command), | ||
| 358 | .sector = read_data[i].sector, | ||
| 359 | .key = {}, | ||
| 360 | .data = read_data[i].data, | ||
| 361 | }; | ||
| 362 | } | ||
| 363 | } | ||
| 364 | return TranslateDriverResult(result); | ||
| 365 | }; | ||
| 366 | |||
| 367 | Common::Input::NfcState Joycons::WriteMifareData(const PadIdentifier& identifier, | ||
| 368 | const Common::Input::MifareRequest& request) { | ||
| 369 | auto handle = GetHandle(identifier); | ||
| 370 | if (handle == nullptr) { | ||
| 371 | return Common::Input::NfcState::Unknown; | ||
| 372 | } | ||
| 373 | |||
| 374 | const auto command = static_cast<Joycon::MifareCmd>(request.data[0].command); | ||
| 375 | std::vector<Joycon::MifareWriteChunk> write_request{}; | ||
| 376 | for (const auto& request_data : request.data) { | ||
| 377 | if (request_data.command == 0) { | ||
| 378 | continue; | ||
| 379 | } | ||
| 380 | Joycon::MifareWriteChunk chunk = { | ||
| 381 | .command = command, | ||
| 382 | .sector_key = {}, | ||
| 383 | .sector = request_data.sector, | ||
| 384 | .data = {}, | ||
| 385 | }; | ||
| 386 | memcpy(chunk.sector_key.data(), request_data.key.data(), | ||
| 387 | sizeof(Joycon::MifareReadChunk::sector_key)); | ||
| 388 | memcpy(chunk.data.data(), request_data.data.data(), sizeof(Joycon::MifareWriteChunk::data)); | ||
| 389 | write_request.emplace_back(chunk); | ||
| 390 | } | ||
| 391 | |||
| 392 | return TranslateDriverResult(handle->WriteMifareData(write_request)); | ||
| 301 | }; | 393 | }; |
| 302 | 394 | ||
| 303 | Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identifier, | 395 | Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identifier, |
| @@ -403,11 +495,20 @@ void Joycons::OnRingConUpdate(f32 ring_data) { | |||
| 403 | } | 495 | } |
| 404 | 496 | ||
| 405 | void Joycons::OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type, | 497 | void Joycons::OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type, |
| 406 | const std::vector<u8>& amiibo_data) { | 498 | const Joycon::TagInfo& tag_info) { |
| 407 | const auto identifier = GetIdentifier(port, type); | 499 | const auto identifier = GetIdentifier(port, type); |
| 408 | const auto nfc_state = amiibo_data.empty() ? Common::Input::NfcState::AmiiboRemoved | 500 | const auto nfc_state = tag_info.uuid_length == 0 ? Common::Input::NfcState::AmiiboRemoved |
| 409 | : Common::Input::NfcState::NewAmiibo; | 501 | : Common::Input::NfcState::NewAmiibo; |
| 410 | SetNfc(identifier, {nfc_state, amiibo_data}); | 502 | |
| 503 | const Common::Input::NfcStatus nfc_status{ | ||
| 504 | .state = nfc_state, | ||
| 505 | .uuid_length = tag_info.uuid_length, | ||
| 506 | .protocol = tag_info.protocol, | ||
| 507 | .tag_type = tag_info.tag_type, | ||
| 508 | .uuid = tag_info.uuid, | ||
| 509 | }; | ||
| 510 | |||
| 511 | SetNfc(identifier, nfc_status); | ||
| 411 | } | 512 | } |
| 412 | 513 | ||
| 413 | void Joycons::OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data, | 514 | void Joycons::OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data, |
| @@ -726,4 +827,18 @@ std::string Joycons::JoyconName(Joycon::ControllerType type) const { | |||
| 726 | return "Unknown Switch Controller"; | 827 | return "Unknown Switch Controller"; |
| 727 | } | 828 | } |
| 728 | } | 829 | } |
| 830 | |||
| 831 | Common::Input::NfcState Joycons::TranslateDriverResult(Joycon::DriverResult result) const { | ||
| 832 | switch (result) { | ||
| 833 | case Joycon::DriverResult::Success: | ||
| 834 | return Common::Input::NfcState::Success; | ||
| 835 | case Joycon::DriverResult::Disabled: | ||
| 836 | return Common::Input::NfcState::WrongDeviceState; | ||
| 837 | case Joycon::DriverResult::NotSupported: | ||
| 838 | return Common::Input::NfcState::NotSupported; | ||
| 839 | default: | ||
| 840 | return Common::Input::NfcState::Unknown; | ||
| 841 | } | ||
| 842 | } | ||
| 843 | |||
| 729 | } // namespace InputCommon | 844 | } // namespace InputCommon |
diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h index e3f0ad78f..4c323d7d6 100644 --- a/src/input_common/drivers/joycon.h +++ b/src/input_common/drivers/joycon.h | |||
| @@ -15,6 +15,7 @@ using SerialNumber = std::array<u8, 15>; | |||
| 15 | struct Battery; | 15 | struct Battery; |
| 16 | struct Color; | 16 | struct Color; |
| 17 | struct MotionData; | 17 | struct MotionData; |
| 18 | struct TagInfo; | ||
| 18 | enum class ControllerType : u8; | 19 | enum class ControllerType : u8; |
| 19 | enum class DriverResult; | 20 | enum class DriverResult; |
| 20 | enum class IrsResolution; | 21 | enum class IrsResolution; |
| @@ -39,9 +40,18 @@ public: | |||
| 39 | Common::Input::DriverResult SetCameraFormat(const PadIdentifier& identifier, | 40 | Common::Input::DriverResult SetCameraFormat(const PadIdentifier& identifier, |
| 40 | Common::Input::CameraFormat camera_format) override; | 41 | Common::Input::CameraFormat camera_format) override; |
| 41 | 42 | ||
| 42 | Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override; | 43 | Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier) const override; |
| 43 | Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_, | 44 | Common::Input::NfcState StartNfcPolling(const PadIdentifier& identifier) override; |
| 45 | Common::Input::NfcState StopNfcPolling(const PadIdentifier& identifier) override; | ||
| 46 | Common::Input::NfcState ReadAmiiboData(const PadIdentifier& identifier, | ||
| 47 | std::vector<u8>& out_data) override; | ||
| 48 | Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier, | ||
| 44 | const std::vector<u8>& data) override; | 49 | const std::vector<u8>& data) override; |
| 50 | Common::Input::NfcState ReadMifareData(const PadIdentifier& identifier, | ||
| 51 | const Common::Input::MifareRequest& request, | ||
| 52 | Common::Input::MifareRequest& out_data) override; | ||
| 53 | Common::Input::NfcState WriteMifareData(const PadIdentifier& identifier, | ||
| 54 | const Common::Input::MifareRequest& request) override; | ||
| 45 | 55 | ||
| 46 | Common::Input::DriverResult SetPollingMode( | 56 | Common::Input::DriverResult SetPollingMode( |
| 47 | const PadIdentifier& identifier, const Common::Input::PollingMode polling_mode) override; | 57 | const PadIdentifier& identifier, const Common::Input::PollingMode polling_mode) override; |
| @@ -82,7 +92,7 @@ private: | |||
| 82 | const Joycon::MotionData& value); | 92 | const Joycon::MotionData& value); |
| 83 | void OnRingConUpdate(f32 ring_data); | 93 | void OnRingConUpdate(f32 ring_data); |
| 84 | void OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type, | 94 | void OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type, |
| 85 | const std::vector<u8>& amiibo_data); | 95 | const Joycon::TagInfo& amiibo_data); |
| 86 | void OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data, | 96 | void OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data, |
| 87 | Joycon::IrsResolution format); | 97 | Joycon::IrsResolution format); |
| 88 | 98 | ||
| @@ -102,6 +112,8 @@ private: | |||
| 102 | /// Returns the name of the device in text format | 112 | /// Returns the name of the device in text format |
| 103 | std::string JoyconName(Joycon::ControllerType type) const; | 113 | std::string JoyconName(Joycon::ControllerType type) const; |
| 104 | 114 | ||
| 115 | Common::Input::NfcState TranslateDriverResult(Joycon::DriverResult result) const; | ||
| 116 | |||
| 105 | std::jthread scan_thread; | 117 | std::jthread scan_thread; |
| 106 | 118 | ||
| 107 | // Joycon types are split by type to ease supporting dualjoycon configurations | 119 | // Joycon types are split by type to ease supporting dualjoycon configurations |
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 9a0439bb5..9f26392b1 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp | |||
| @@ -150,6 +150,8 @@ public: | |||
| 150 | if (sdl_controller) { | 150 | if (sdl_controller) { |
| 151 | const auto type = SDL_GameControllerGetType(sdl_controller.get()); | 151 | const auto type = SDL_GameControllerGetType(sdl_controller.get()); |
| 152 | return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) || | 152 | return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) || |
| 153 | (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT) || | ||
| 154 | (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) || | ||
| 153 | (type == SDL_CONTROLLER_TYPE_PS5); | 155 | (type == SDL_CONTROLLER_TYPE_PS5); |
| 154 | } | 156 | } |
| 155 | return false; | 157 | return false; |
| @@ -228,9 +230,8 @@ public: | |||
| 228 | return false; | 230 | return false; |
| 229 | } | 231 | } |
| 230 | 232 | ||
| 231 | Common::Input::BatteryLevel GetBatteryLevel() { | 233 | Common::Input::BatteryLevel GetBatteryLevel(SDL_JoystickPowerLevel battery_level) { |
| 232 | const auto level = SDL_JoystickCurrentPowerLevel(sdl_joystick.get()); | 234 | switch (battery_level) { |
| 233 | switch (level) { | ||
| 234 | case SDL_JOYSTICK_POWER_EMPTY: | 235 | case SDL_JOYSTICK_POWER_EMPTY: |
| 235 | return Common::Input::BatteryLevel::Empty; | 236 | return Common::Input::BatteryLevel::Empty; |
| 236 | case SDL_JOYSTICK_POWER_LOW: | 237 | case SDL_JOYSTICK_POWER_LOW: |
| @@ -378,7 +379,6 @@ void SDLDriver::InitJoystick(int joystick_index) { | |||
| 378 | if (joystick_map.find(guid) == joystick_map.end()) { | 379 | if (joystick_map.find(guid) == joystick_map.end()) { |
| 379 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); | 380 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); |
| 380 | PreSetController(joystick->GetPadIdentifier()); | 381 | PreSetController(joystick->GetPadIdentifier()); |
| 381 | SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); | ||
| 382 | joystick->EnableMotion(); | 382 | joystick->EnableMotion(); |
| 383 | joystick_map[guid].emplace_back(std::move(joystick)); | 383 | joystick_map[guid].emplace_back(std::move(joystick)); |
| 384 | return; | 384 | return; |
| @@ -398,7 +398,6 @@ void SDLDriver::InitJoystick(int joystick_index) { | |||
| 398 | const int port = static_cast<int>(joystick_guid_list.size()); | 398 | const int port = static_cast<int>(joystick_guid_list.size()); |
| 399 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller); | 399 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller); |
| 400 | PreSetController(joystick->GetPadIdentifier()); | 400 | PreSetController(joystick->GetPadIdentifier()); |
| 401 | SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); | ||
| 402 | joystick->EnableMotion(); | 401 | joystick->EnableMotion(); |
| 403 | joystick_guid_list.emplace_back(std::move(joystick)); | 402 | joystick_guid_list.emplace_back(std::move(joystick)); |
| 404 | } | 403 | } |
| @@ -438,8 +437,6 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { | |||
| 438 | if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { | 437 | if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { |
| 439 | const PadIdentifier identifier = joystick->GetPadIdentifier(); | 438 | const PadIdentifier identifier = joystick->GetPadIdentifier(); |
| 440 | SetButton(identifier, event.jbutton.button, true); | 439 | SetButton(identifier, event.jbutton.button, true); |
| 441 | // Battery doesn't trigger an event so just update every button press | ||
| 442 | SetBattery(identifier, joystick->GetBatteryLevel()); | ||
| 443 | } | 440 | } |
| 444 | break; | 441 | break; |
| 445 | } | 442 | } |
| @@ -466,6 +463,13 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { | |||
| 466 | } | 463 | } |
| 467 | break; | 464 | break; |
| 468 | } | 465 | } |
| 466 | case SDL_JOYBATTERYUPDATED: { | ||
| 467 | if (auto joystick = GetSDLJoystickBySDLID(event.jbattery.which)) { | ||
| 468 | const PadIdentifier identifier = joystick->GetPadIdentifier(); | ||
| 469 | SetBattery(identifier, joystick->GetBatteryLevel(event.jbattery.level)); | ||
| 470 | } | ||
| 471 | break; | ||
| 472 | } | ||
| 469 | case SDL_JOYDEVICEREMOVED: | 473 | case SDL_JOYDEVICEREMOVED: |
| 470 | LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); | 474 | LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); |
| 471 | CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); | 475 | CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); |
| @@ -483,6 +487,10 @@ void SDLDriver::CloseJoysticks() { | |||
| 483 | } | 487 | } |
| 484 | 488 | ||
| 485 | SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_engine_)) { | 489 | SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_engine_)) { |
| 490 | // Set our application name. Currently passed to DBus by SDL and visible to the user through | ||
| 491 | // their desktop environment. | ||
| 492 | SDL_SetHint(SDL_HINT_APP_NAME, "yuzu"); | ||
| 493 | |||
| 486 | if (!Settings::values.enable_raw_input) { | 494 | if (!Settings::values.enable_raw_input) { |
| 487 | // Disable raw input. When enabled this setting causes SDL to die when a web applet opens | 495 | // Disable raw input. When enabled this setting causes SDL to die when a web applet opens |
| 488 | SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0"); | 496 | SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0"); |
| @@ -501,6 +509,9 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en | |||
| 501 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "0"); | 509 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "0"); |
| 502 | } else { | 510 | } else { |
| 503 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1"); | 511 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1"); |
| 512 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED, "0"); | ||
| 513 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS, "0"); | ||
| 514 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, "1"); | ||
| 504 | } | 515 | } |
| 505 | 516 | ||
| 506 | // Disable hidapi drivers for pro controllers when the custom joycon driver is enabled | 517 | // Disable hidapi drivers for pro controllers when the custom joycon driver is enabled |
| @@ -508,8 +519,11 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en | |||
| 508 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "0"); | 519 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "0"); |
| 509 | } else { | 520 | } else { |
| 510 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1"); | 521 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1"); |
| 522 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, "0"); | ||
| 511 | } | 523 | } |
| 512 | 524 | ||
| 525 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, "1"); | ||
| 526 | |||
| 513 | // Disable hidapi driver for xbox. Already default on Windows, this causes conflict with native | 527 | // Disable hidapi driver for xbox. Already default on Windows, this causes conflict with native |
| 514 | // driver on Linux. | 528 | // driver on Linux. |
| 515 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0"); | 529 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0"); |
| @@ -789,7 +803,9 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p | |||
| 789 | // This list also excludes Screenshot since there's not really a mapping for that | 803 | // This list also excludes Screenshot since there's not really a mapping for that |
| 790 | ButtonBindings switch_to_sdl_button; | 804 | ButtonBindings switch_to_sdl_button; |
| 791 | 805 | ||
| 792 | if (SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) { | 806 | if (SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO || |
| 807 | SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT || | ||
| 808 | SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) { | ||
| 793 | switch_to_sdl_button = GetNintendoButtonBinding(joystick); | 809 | switch_to_sdl_button = GetNintendoButtonBinding(joystick); |
| 794 | } else { | 810 | } else { |
| 795 | switch_to_sdl_button = GetDefaultButtonBinding(); | 811 | switch_to_sdl_button = GetDefaultButtonBinding(); |
diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp index f8bafe553..180eb53ef 100644 --- a/src/input_common/drivers/virtual_amiibo.cpp +++ b/src/input_common/drivers/virtual_amiibo.cpp | |||
| @@ -29,14 +29,13 @@ Common::Input::DriverResult VirtualAmiibo::SetPollingMode( | |||
| 29 | 29 | ||
| 30 | switch (polling_mode) { | 30 | switch (polling_mode) { |
| 31 | case Common::Input::PollingMode::NFC: | 31 | case Common::Input::PollingMode::NFC: |
| 32 | if (state == State::Initialized) { | 32 | state = State::Initialized; |
| 33 | state = State::WaitingForAmiibo; | ||
| 34 | } | ||
| 35 | return Common::Input::DriverResult::Success; | 33 | return Common::Input::DriverResult::Success; |
| 36 | default: | 34 | default: |
| 37 | if (state == State::AmiiboIsOpen) { | 35 | if (state == State::TagNearby) { |
| 38 | CloseAmiibo(); | 36 | CloseAmiibo(); |
| 39 | } | 37 | } |
| 38 | state = State::Disabled; | ||
| 40 | return Common::Input::DriverResult::NotSupported; | 39 | return Common::Input::DriverResult::NotSupported; |
| 41 | } | 40 | } |
| 42 | } | 41 | } |
| @@ -45,6 +44,39 @@ Common::Input::NfcState VirtualAmiibo::SupportsNfc( | |||
| 45 | [[maybe_unused]] const PadIdentifier& identifier_) const { | 44 | [[maybe_unused]] const PadIdentifier& identifier_) const { |
| 46 | return Common::Input::NfcState::Success; | 45 | return Common::Input::NfcState::Success; |
| 47 | } | 46 | } |
| 47 | Common::Input::NfcState VirtualAmiibo::StartNfcPolling(const PadIdentifier& identifier_) { | ||
| 48 | if (state != State::Initialized) { | ||
| 49 | return Common::Input::NfcState::WrongDeviceState; | ||
| 50 | } | ||
| 51 | state = State::WaitingForAmiibo; | ||
| 52 | return Common::Input::NfcState::Success; | ||
| 53 | } | ||
| 54 | |||
| 55 | Common::Input::NfcState VirtualAmiibo::StopNfcPolling(const PadIdentifier& identifier_) { | ||
| 56 | if (state == State::Disabled) { | ||
| 57 | return Common::Input::NfcState::WrongDeviceState; | ||
| 58 | } | ||
| 59 | if (state == State::TagNearby) { | ||
| 60 | CloseAmiibo(); | ||
| 61 | } | ||
| 62 | state = State::Initialized; | ||
| 63 | return Common::Input::NfcState::Success; | ||
| 64 | } | ||
| 65 | |||
| 66 | Common::Input::NfcState VirtualAmiibo::ReadAmiiboData(const PadIdentifier& identifier_, | ||
| 67 | std::vector<u8>& out_data) { | ||
| 68 | if (state != State::TagNearby) { | ||
| 69 | return Common::Input::NfcState::WrongDeviceState; | ||
| 70 | } | ||
| 71 | |||
| 72 | if (status.tag_type != 1U << 1) { | ||
| 73 | return Common::Input::NfcState::InvalidTagType; | ||
| 74 | } | ||
| 75 | |||
| 76 | out_data.resize(nfc_data.size()); | ||
| 77 | memcpy(out_data.data(), nfc_data.data(), nfc_data.size()); | ||
| 78 | return Common::Input::NfcState::Success; | ||
| 79 | } | ||
| 48 | 80 | ||
| 49 | Common::Input::NfcState VirtualAmiibo::WriteNfcData( | 81 | Common::Input::NfcState VirtualAmiibo::WriteNfcData( |
| 50 | [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { | 82 | [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { |
| @@ -66,6 +98,69 @@ Common::Input::NfcState VirtualAmiibo::WriteNfcData( | |||
| 66 | return Common::Input::NfcState::Success; | 98 | return Common::Input::NfcState::Success; |
| 67 | } | 99 | } |
| 68 | 100 | ||
| 101 | Common::Input::NfcState VirtualAmiibo::ReadMifareData(const PadIdentifier& identifier_, | ||
| 102 | const Common::Input::MifareRequest& request, | ||
| 103 | Common::Input::MifareRequest& out_data) { | ||
| 104 | if (state != State::TagNearby) { | ||
| 105 | return Common::Input::NfcState::WrongDeviceState; | ||
| 106 | } | ||
| 107 | |||
| 108 | if (status.tag_type != 1U << 6) { | ||
| 109 | return Common::Input::NfcState::InvalidTagType; | ||
| 110 | } | ||
| 111 | |||
| 112 | for (std::size_t i = 0; i < request.data.size(); i++) { | ||
| 113 | if (request.data[i].command == 0) { | ||
| 114 | continue; | ||
| 115 | } | ||
| 116 | out_data.data[i].command = request.data[i].command; | ||
| 117 | out_data.data[i].sector = request.data[i].sector; | ||
| 118 | |||
| 119 | const std::size_t sector_index = | ||
| 120 | request.data[i].sector * sizeof(Common::Input::MifareData::data); | ||
| 121 | |||
| 122 | if (nfc_data.size() < sector_index + sizeof(Common::Input::MifareData::data)) { | ||
| 123 | return Common::Input::NfcState::WriteFailed; | ||
| 124 | } | ||
| 125 | |||
| 126 | // Ignore the sector key as we don't support it | ||
| 127 | memcpy(out_data.data[i].data.data(), nfc_data.data() + sector_index, | ||
| 128 | sizeof(Common::Input::MifareData::data)); | ||
| 129 | } | ||
| 130 | |||
| 131 | return Common::Input::NfcState::Success; | ||
| 132 | } | ||
| 133 | |||
| 134 | Common::Input::NfcState VirtualAmiibo::WriteMifareData( | ||
| 135 | const PadIdentifier& identifier_, const Common::Input::MifareRequest& request) { | ||
| 136 | if (state != State::TagNearby) { | ||
| 137 | return Common::Input::NfcState::WrongDeviceState; | ||
| 138 | } | ||
| 139 | |||
| 140 | if (status.tag_type != 1U << 6) { | ||
| 141 | return Common::Input::NfcState::InvalidTagType; | ||
| 142 | } | ||
| 143 | |||
| 144 | for (std::size_t i = 0; i < request.data.size(); i++) { | ||
| 145 | if (request.data[i].command == 0) { | ||
| 146 | continue; | ||
| 147 | } | ||
| 148 | |||
| 149 | const std::size_t sector_index = | ||
| 150 | request.data[i].sector * sizeof(Common::Input::MifareData::data); | ||
| 151 | |||
| 152 | if (nfc_data.size() < sector_index + sizeof(Common::Input::MifareData::data)) { | ||
| 153 | return Common::Input::NfcState::WriteFailed; | ||
| 154 | } | ||
| 155 | |||
| 156 | // Ignore the sector key as we don't support it | ||
| 157 | memcpy(nfc_data.data() + sector_index, request.data[i].data.data(), | ||
| 158 | sizeof(Common::Input::MifareData::data)); | ||
| 159 | } | ||
| 160 | |||
| 161 | return Common::Input::NfcState::Success; | ||
| 162 | } | ||
| 163 | |||
| 69 | VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const { | 164 | VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const { |
| 70 | return state; | 165 | return state; |
| 71 | } | 166 | } |
| @@ -82,6 +177,7 @@ VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { | |||
| 82 | switch (nfc_file.GetSize()) { | 177 | switch (nfc_file.GetSize()) { |
| 83 | case AmiiboSize: | 178 | case AmiiboSize: |
| 84 | case AmiiboSizeWithoutPassword: | 179 | case AmiiboSizeWithoutPassword: |
| 180 | case AmiiboSizeWithSignature: | ||
| 85 | data.resize(AmiiboSize); | 181 | data.resize(AmiiboSize); |
| 86 | if (nfc_file.Read(data) < AmiiboSizeWithoutPassword) { | 182 | if (nfc_file.Read(data) < AmiiboSizeWithoutPassword) { |
| 87 | return Info::NotAnAmiibo; | 183 | return Info::NotAnAmiibo; |
| @@ -109,24 +205,33 @@ VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(std::span<u8> data) { | |||
| 109 | switch (data.size_bytes()) { | 205 | switch (data.size_bytes()) { |
| 110 | case AmiiboSize: | 206 | case AmiiboSize: |
| 111 | case AmiiboSizeWithoutPassword: | 207 | case AmiiboSizeWithoutPassword: |
| 208 | case AmiiboSizeWithSignature: | ||
| 112 | nfc_data.resize(AmiiboSize); | 209 | nfc_data.resize(AmiiboSize); |
| 210 | status.tag_type = 1U << 1; | ||
| 211 | status.uuid_length = 7; | ||
| 113 | break; | 212 | break; |
| 114 | case MifareSize: | 213 | case MifareSize: |
| 115 | nfc_data.resize(MifareSize); | 214 | nfc_data.resize(MifareSize); |
| 215 | status.tag_type = 1U << 6; | ||
| 216 | status.uuid_length = 4; | ||
| 116 | break; | 217 | break; |
| 117 | default: | 218 | default: |
| 118 | return Info::NotAnAmiibo; | 219 | return Info::NotAnAmiibo; |
| 119 | } | 220 | } |
| 120 | 221 | ||
| 121 | state = State::AmiiboIsOpen; | 222 | status.uuid = {}; |
| 223 | status.protocol = 1; | ||
| 224 | state = State::TagNearby; | ||
| 225 | status.state = Common::Input::NfcState::NewAmiibo, | ||
| 122 | memcpy(nfc_data.data(), data.data(), data.size_bytes()); | 226 | memcpy(nfc_data.data(), data.data(), data.size_bytes()); |
| 123 | SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data}); | 227 | memcpy(status.uuid.data(), nfc_data.data(), status.uuid_length); |
| 228 | SetNfc(identifier, status); | ||
| 124 | return Info::Success; | 229 | return Info::Success; |
| 125 | } | 230 | } |
| 126 | 231 | ||
| 127 | VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { | 232 | VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { |
| 128 | if (state == State::AmiiboIsOpen) { | 233 | if (state == State::TagNearby) { |
| 129 | SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data}); | 234 | SetNfc(identifier, status); |
| 130 | return Info::Success; | 235 | return Info::Success; |
| 131 | } | 236 | } |
| 132 | 237 | ||
| @@ -134,9 +239,14 @@ VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { | |||
| 134 | } | 239 | } |
| 135 | 240 | ||
| 136 | VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() { | 241 | VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() { |
| 137 | state = polling_mode == Common::Input::PollingMode::NFC ? State::WaitingForAmiibo | 242 | if (state != State::TagNearby) { |
| 138 | : State::Initialized; | 243 | return Info::Success; |
| 139 | SetNfc(identifier, {Common::Input::NfcState::AmiiboRemoved, {}}); | 244 | } |
| 245 | |||
| 246 | state = State::WaitingForAmiibo; | ||
| 247 | status.state = Common::Input::NfcState::AmiiboRemoved; | ||
| 248 | SetNfc(identifier, status); | ||
| 249 | status.tag_type = 0; | ||
| 140 | return Info::Success; | 250 | return Info::Success; |
| 141 | } | 251 | } |
| 142 | 252 | ||
diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h index 34e97cd91..490f38e05 100644 --- a/src/input_common/drivers/virtual_amiibo.h +++ b/src/input_common/drivers/virtual_amiibo.h | |||
| @@ -20,9 +20,10 @@ namespace InputCommon { | |||
| 20 | class VirtualAmiibo final : public InputEngine { | 20 | class VirtualAmiibo final : public InputEngine { |
| 21 | public: | 21 | public: |
| 22 | enum class State { | 22 | enum class State { |
| 23 | Disabled, | ||
| 23 | Initialized, | 24 | Initialized, |
| 24 | WaitingForAmiibo, | 25 | WaitingForAmiibo, |
| 25 | AmiiboIsOpen, | 26 | TagNearby, |
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 28 | enum class Info { | 29 | enum class Info { |
| @@ -41,9 +42,17 @@ public: | |||
| 41 | const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) override; | 42 | const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) override; |
| 42 | 43 | ||
| 43 | Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override; | 44 | Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override; |
| 44 | 45 | Common::Input::NfcState StartNfcPolling(const PadIdentifier& identifier_) override; | |
| 46 | Common::Input::NfcState StopNfcPolling(const PadIdentifier& identifier_) override; | ||
| 47 | Common::Input::NfcState ReadAmiiboData(const PadIdentifier& identifier_, | ||
| 48 | std::vector<u8>& out_data) override; | ||
| 45 | Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_, | 49 | Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_, |
| 46 | const std::vector<u8>& data) override; | 50 | const std::vector<u8>& data) override; |
| 51 | Common::Input::NfcState ReadMifareData(const PadIdentifier& identifier_, | ||
| 52 | const Common::Input::MifareRequest& data, | ||
| 53 | Common::Input::MifareRequest& out_data) override; | ||
| 54 | Common::Input::NfcState WriteMifareData(const PadIdentifier& identifier_, | ||
| 55 | const Common::Input::MifareRequest& data) override; | ||
| 47 | 56 | ||
| 48 | State GetCurrentState() const; | 57 | State GetCurrentState() const; |
| 49 | 58 | ||
| @@ -57,11 +66,13 @@ public: | |||
| 57 | private: | 66 | private: |
| 58 | static constexpr std::size_t AmiiboSize = 0x21C; | 67 | static constexpr std::size_t AmiiboSize = 0x21C; |
| 59 | static constexpr std::size_t AmiiboSizeWithoutPassword = AmiiboSize - 0x8; | 68 | static constexpr std::size_t AmiiboSizeWithoutPassword = AmiiboSize - 0x8; |
| 69 | static constexpr std::size_t AmiiboSizeWithSignature = AmiiboSize + 0x20; | ||
| 60 | static constexpr std::size_t MifareSize = 0x400; | 70 | static constexpr std::size_t MifareSize = 0x400; |
| 61 | 71 | ||
| 62 | std::string file_path{}; | 72 | std::string file_path{}; |
| 63 | State state{State::Initialized}; | 73 | State state{State::Disabled}; |
| 64 | std::vector<u8> nfc_data; | 74 | std::vector<u8> nfc_data; |
| 75 | Common::Input::NfcStatus status; | ||
| 65 | Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Passive}; | 76 | Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Passive}; |
| 66 | }; | 77 | }; |
| 67 | } // namespace InputCommon | 78 | } // namespace InputCommon |