summaryrefslogtreecommitdiff
path: root/src/input_common/drivers/sdl_driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/drivers/sdl_driver.cpp')
-rw-r--r--src/input_common/drivers/sdl_driver.cpp129
1 files changed, 105 insertions, 24 deletions
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 9835d99d2..9f26392b1 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -109,14 +109,37 @@ public:
109 } 109 }
110 110
111 bool RumblePlay(const Common::Input::VibrationStatus vibration) { 111 bool RumblePlay(const Common::Input::VibrationStatus vibration) {
112 constexpr u32 rumble_max_duration_ms = 1000; 112 constexpr u32 rumble_max_duration_ms = 2000;
113 constexpr f32 low_start_sensitivity_limit = 140.0;
114 constexpr f32 low_width_sensitivity_limit = 400.0;
115 constexpr f32 high_start_sensitivity_limit = 200.0;
116 constexpr f32 high_width_sensitivity_limit = 700.0;
117 // Try to provide some feeling of the frequency by reducing the amplitude depending on it.
118 f32 low_frequency_scale = 1.0;
119 if (vibration.low_frequency > low_start_sensitivity_limit) {
120 low_frequency_scale =
121 std::max(1.0f - (vibration.low_frequency - low_start_sensitivity_limit) /
122 low_width_sensitivity_limit,
123 0.3f);
124 }
125 f32 low_amplitude = vibration.low_amplitude * low_frequency_scale;
126
127 f32 high_frequency_scale = 1.0;
128 if (vibration.high_frequency > high_start_sensitivity_limit) {
129 high_frequency_scale =
130 std::max(1.0f - (vibration.high_frequency - high_start_sensitivity_limit) /
131 high_width_sensitivity_limit,
132 0.3f);
133 }
134 f32 high_amplitude = vibration.high_amplitude * high_frequency_scale;
135
113 if (sdl_controller) { 136 if (sdl_controller) {
114 return SDL_GameControllerRumble( 137 return SDL_GameControllerRumble(sdl_controller.get(), static_cast<u16>(low_amplitude),
115 sdl_controller.get(), static_cast<u16>(vibration.low_amplitude), 138 static_cast<u16>(high_amplitude),
116 static_cast<u16>(vibration.high_amplitude), rumble_max_duration_ms) != -1; 139 rumble_max_duration_ms) != -1;
117 } else if (sdl_joystick) { 140 } else if (sdl_joystick) {
118 return SDL_JoystickRumble(sdl_joystick.get(), static_cast<u16>(vibration.low_amplitude), 141 return SDL_JoystickRumble(sdl_joystick.get(), static_cast<u16>(low_amplitude),
119 static_cast<u16>(vibration.high_amplitude), 142 static_cast<u16>(high_amplitude),
120 rumble_max_duration_ms) != -1; 143 rumble_max_duration_ms) != -1;
121 } 144 }
122 145
@@ -127,6 +150,8 @@ public:
127 if (sdl_controller) { 150 if (sdl_controller) {
128 const auto type = SDL_GameControllerGetType(sdl_controller.get()); 151 const auto type = SDL_GameControllerGetType(sdl_controller.get());
129 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) ||
130 (type == SDL_CONTROLLER_TYPE_PS5); 155 (type == SDL_CONTROLLER_TYPE_PS5);
131 } 156 }
132 return false; 157 return false;
@@ -205,9 +230,8 @@ public:
205 return false; 230 return false;
206 } 231 }
207 232
208 Common::Input::BatteryLevel GetBatteryLevel() { 233 Common::Input::BatteryLevel GetBatteryLevel(SDL_JoystickPowerLevel battery_level) {
209 const auto level = SDL_JoystickCurrentPowerLevel(sdl_joystick.get()); 234 switch (battery_level) {
210 switch (level) {
211 case SDL_JOYSTICK_POWER_EMPTY: 235 case SDL_JOYSTICK_POWER_EMPTY:
212 return Common::Input::BatteryLevel::Empty; 236 return Common::Input::BatteryLevel::Empty;
213 case SDL_JOYSTICK_POWER_LOW: 237 case SDL_JOYSTICK_POWER_LOW:
@@ -334,11 +358,27 @@ void SDLDriver::InitJoystick(int joystick_index) {
334 358
335 const auto guid = GetGUID(sdl_joystick); 359 const auto guid = GetGUID(sdl_joystick);
336 360
361 if (Settings::values.enable_joycon_driver) {
362 if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e &&
363 (guid.uuid[8] == 0x06 || guid.uuid[8] == 0x07)) {
364 LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index);
365 SDL_JoystickClose(sdl_joystick);
366 return;
367 }
368 }
369
370 if (Settings::values.enable_procon_driver) {
371 if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && guid.uuid[8] == 0x09) {
372 LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index);
373 SDL_JoystickClose(sdl_joystick);
374 return;
375 }
376 }
377
337 std::scoped_lock lock{joystick_map_mutex}; 378 std::scoped_lock lock{joystick_map_mutex};
338 if (joystick_map.find(guid) == joystick_map.end()) { 379 if (joystick_map.find(guid) == joystick_map.end()) {
339 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);
340 PreSetController(joystick->GetPadIdentifier()); 381 PreSetController(joystick->GetPadIdentifier());
341 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
342 joystick->EnableMotion(); 382 joystick->EnableMotion();
343 joystick_map[guid].emplace_back(std::move(joystick)); 383 joystick_map[guid].emplace_back(std::move(joystick));
344 return; 384 return;
@@ -358,7 +398,6 @@ void SDLDriver::InitJoystick(int joystick_index) {
358 const int port = static_cast<int>(joystick_guid_list.size()); 398 const int port = static_cast<int>(joystick_guid_list.size());
359 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);
360 PreSetController(joystick->GetPadIdentifier()); 400 PreSetController(joystick->GetPadIdentifier());
361 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
362 joystick->EnableMotion(); 401 joystick->EnableMotion();
363 joystick_guid_list.emplace_back(std::move(joystick)); 402 joystick_guid_list.emplace_back(std::move(joystick));
364} 403}
@@ -398,8 +437,6 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
398 if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { 437 if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) {
399 const PadIdentifier identifier = joystick->GetPadIdentifier(); 438 const PadIdentifier identifier = joystick->GetPadIdentifier();
400 SetButton(identifier, event.jbutton.button, true); 439 SetButton(identifier, event.jbutton.button, true);
401 // Battery doesn't trigger an event so just update every button press
402 SetBattery(identifier, joystick->GetBatteryLevel());
403 } 440 }
404 break; 441 break;
405 } 442 }
@@ -426,6 +463,13 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
426 } 463 }
427 break; 464 break;
428 } 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 }
429 case SDL_JOYDEVICEREMOVED: 473 case SDL_JOYDEVICEREMOVED:
430 LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); 474 LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which);
431 CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); 475 CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which));
@@ -443,6 +487,10 @@ void SDLDriver::CloseJoysticks() {
443} 487}
444 488
445SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_engine_)) { 489SDLDriver::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
446 if (!Settings::values.enable_raw_input) { 494 if (!Settings::values.enable_raw_input) {
447 // 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
448 SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0"); 496 SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0");
@@ -456,9 +504,25 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
456 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); 504 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
457 SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); 505 SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
458 506
459 // Use hidapi driver for joycons. This will allow joycons to be detected as a GameController and 507 // Disable hidapi drivers for joycon controllers when the custom joycon driver is enabled
460 // not a generic one 508 if (Settings::values.enable_joycon_driver) {
461 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1"); 509 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "0");
510 } else {
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");
515 }
516
517 // Disable hidapi drivers for pro controllers when the custom joycon driver is enabled
518 if (Settings::values.enable_procon_driver) {
519 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "0");
520 } else {
521 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1");
522 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, "0");
523 }
524
525 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, "1");
462 526
463 // 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
464 // driver on Linux. 528 // driver on Linux.
@@ -548,7 +612,7 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
548 return devices; 612 return devices;
549} 613}
550 614
551Common::Input::VibrationError SDLDriver::SetVibration( 615Common::Input::DriverResult SDLDriver::SetVibration(
552 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { 616 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) {
553 const auto joystick = 617 const auto joystick =
554 GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port)); 618 GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port));
@@ -582,14 +646,14 @@ Common::Input::VibrationError SDLDriver::SetVibration(
582 .vibration = new_vibration, 646 .vibration = new_vibration,
583 }); 647 });
584 648
585 return Common::Input::VibrationError::None; 649 return Common::Input::DriverResult::Success;
586} 650}
587 651
588bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) { 652bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) {
589 const auto joystick = 653 const auto joystick =
590 GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port)); 654 GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port));
591 655
592 constexpr Common::Input::VibrationStatus test_vibration{ 656 static constexpr Common::Input::VibrationStatus test_vibration{
593 .low_amplitude = 1, 657 .low_amplitude = 1,
594 .low_frequency = 160.0f, 658 .low_frequency = 160.0f,
595 .high_amplitude = 1, 659 .high_amplitude = 1,
@@ -597,7 +661,7 @@ bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) {
597 .type = Common::Input::VibrationAmplificationType::Exponential, 661 .type = Common::Input::VibrationAmplificationType::Exponential,
598 }; 662 };
599 663
600 constexpr Common::Input::VibrationStatus zero_vibration{ 664 static constexpr Common::Input::VibrationStatus zero_vibration{
601 .low_amplitude = 0, 665 .low_amplitude = 0,
602 .low_frequency = 160.0f, 666 .low_frequency = 160.0f,
603 .high_amplitude = 0, 667 .high_amplitude = 0,
@@ -625,12 +689,27 @@ bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) {
625} 689}
626 690
627void SDLDriver::SendVibrations() { 691void SDLDriver::SendVibrations() {
692 std::vector<VibrationRequest> filtered_vibrations{};
628 while (!vibration_queue.Empty()) { 693 while (!vibration_queue.Empty()) {
629 VibrationRequest request; 694 VibrationRequest request;
630 vibration_queue.Pop(request); 695 vibration_queue.Pop(request);
631 const auto joystick = GetSDLJoystickByGUID(request.identifier.guid.RawString(), 696 const auto joystick = GetSDLJoystickByGUID(request.identifier.guid.RawString(),
632 static_cast<int>(request.identifier.port)); 697 static_cast<int>(request.identifier.port));
633 joystick->RumblePlay(request.vibration); 698 const auto it = std::find_if(filtered_vibrations.begin(), filtered_vibrations.end(),
699 [request](VibrationRequest vibration) {
700 return vibration.identifier == request.identifier;
701 });
702 if (it == filtered_vibrations.end()) {
703 filtered_vibrations.push_back(std::move(request));
704 continue;
705 }
706 *it = request;
707 }
708
709 for (const auto& vibration : filtered_vibrations) {
710 const auto joystick = GetSDLJoystickByGUID(vibration.identifier.guid.RawString(),
711 static_cast<int>(vibration.identifier.port));
712 joystick->RumblePlay(vibration.vibration);
634 } 713 }
635} 714}
636 715
@@ -721,10 +800,12 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p
721 800
722 // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. 801 // This list is missing ZL/ZR since those are not considered buttons in SDL GameController.
723 // We will add those afterwards 802 // We will add those afterwards
724 // This list also excludes Screenshot since theres not really a mapping for that 803 // This list also excludes Screenshot since there's not really a mapping for that
725 ButtonBindings switch_to_sdl_button; 804 ButtonBindings switch_to_sdl_button;
726 805
727 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) {
728 switch_to_sdl_button = GetNintendoButtonBinding(joystick); 809 switch_to_sdl_button = GetNintendoButtonBinding(joystick);
729 } else { 810 } else {
730 switch_to_sdl_button = GetDefaultButtonBinding(); 811 switch_to_sdl_button = GetDefaultButtonBinding();
@@ -980,7 +1061,7 @@ MotionMapping SDLDriver::GetMotionMappingForDevice(const Common::ParamPackage& p
980 1061
981Common::Input::ButtonNames SDLDriver::GetUIName(const Common::ParamPackage& params) const { 1062Common::Input::ButtonNames SDLDriver::GetUIName(const Common::ParamPackage& params) const {
982 if (params.Has("button")) { 1063 if (params.Has("button")) {
983 // TODO(German77): Find how to substitue the values for real button names 1064 // TODO(German77): Find how to substitute the values for real button names
984 return Common::Input::ButtonNames::Value; 1065 return Common::Input::ButtonNames::Value;
985 } 1066 }
986 if (params.Has("hat")) { 1067 if (params.Has("hat")) {