diff options
author | Morph <39850852+Morph1984@users.noreply.github.com> | 2021-02-16 10:46:56 +0100 |
---|---|---|
committer | Morph <39850852+Morph1984@users.noreply.github.com> | 2021-02-21 16:32:59 +0100 |
commit | ec19a85890f8185de3da3d21e07e52089e6e3689 (patch) | |
tree | 32e7ea19ab2468a25776bf09341131de1b0404bb /src/core | |
parent | Merge pull request #5971 from ameerj/reslimit-dtor (diff) | |
download | yuzu-ec19a85890f8185de3da3d21e07e52089e6e3689.tar yuzu-ec19a85890f8185de3da3d21e07e52089e6e3689.tar.gz yuzu-ec19a85890f8185de3da3d21e07e52089e6e3689.tar.bz2 yuzu-ec19a85890f8185de3da3d21e07e52089e6e3689.tar.lz yuzu-ec19a85890f8185de3da3d21e07e52089e6e3689.tar.xz yuzu-ec19a85890f8185de3da3d21e07e52089e6e3689.tar.zst yuzu-ec19a85890f8185de3da3d21e07e52089e6e3689.zip |
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/hle/service/hid/hid.cpp | 123 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid.h | 10 |
2 files changed, 130 insertions, 3 deletions
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 1e2677320..3d0fe42f6 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -273,8 +273,8 @@ Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} { {204, &Hid::PermitVibration, "PermitVibration"}, {205, &Hid::IsVibrationPermitted, "IsVibrationPermitted"}, {206, &Hid::SendVibrationValues, "SendVibrationValues"}, - {207, nullptr, "SendVibrationGcErmCommand"}, - {208, nullptr, "GetActualVibrationGcErmCommand"}, + {207, &Hid::SendVibrationGcErmCommand, "SendVibrationGcErmCommand"}, + {208, &Hid::GetActualVibrationGcErmCommand, "GetActualVibrationGcErmCommand"}, {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, @@ -1093,7 +1093,22 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { VibrationDeviceInfo vibration_device_info; - vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; + switch (vibration_device_handle.npad_type) { + case Controller_NPad::NpadType::ProController: + case Controller_NPad::NpadType::Handheld: + case Controller_NPad::NpadType::JoyconDual: + case Controller_NPad::NpadType::JoyconLeft: + case Controller_NPad::NpadType::JoyconRight: + default: + vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; + break; + case Controller_NPad::NpadType::GameCube: + vibration_device_info.type = VibrationDeviceType::GcErm; + break; + case Controller_NPad::NpadType::Pokeball: + vibration_device_info.type = VibrationDeviceType::Unknown; + break; + } switch (vibration_device_handle.device_index) { case Controller_NPad::DeviceIndex::Left: @@ -1215,6 +1230,108 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } +void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + struct Parameters { + Controller_NPad::DeviceHandle vibration_device_handle; + u64 applet_resource_user_id; + VibrationGcErmCommand gc_erm_command; + }; + static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); + + const auto parameters{rp.PopRaw<Parameters>()}; + + /** + * Note: This uses yuzu-specific behavior such that the StopHard command produces + * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below, + * in order to differentiate between Stop and StopHard commands. + * This is done to reuse the controller vibration functions made for regular controllers. + */ + const auto vibration_value = [parameters] { + switch (parameters.gc_erm_command) { + case VibrationGcErmCommand::Stop: + return Controller_NPad::VibrationValue{ + .amp_low = 0.0f, + .freq_low = 160.0f, + .amp_high = 0.0f, + .freq_high = 320.0f, + }; + case VibrationGcErmCommand::Start: + return Controller_NPad::VibrationValue{ + .amp_low = 1.0f, + .freq_low = 160.0f, + .amp_high = 1.0f, + .freq_high = 320.0f, + }; + case VibrationGcErmCommand::StopHard: + return Controller_NPad::VibrationValue{ + .amp_low = 0.0f, + .freq_low = 0.0f, + .amp_high = 0.0f, + .freq_high = 0.0f, + }; + default: + return Controller_NPad::DEFAULT_VIBRATION_VALUE; + } + }(); + + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .VibrateController(parameters.vibration_device_handle, vibration_value); + + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " + "gc_erm_command={}", + parameters.vibration_device_handle.npad_type, + parameters.vibration_device_handle.npad_id, + parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, + parameters.gc_erm_command); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + struct Parameters { + Controller_NPad::DeviceHandle vibration_device_handle; + INSERT_PADDING_WORDS_NOINIT(1); + u64 applet_resource_user_id; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; + + const auto last_vibration = applet_resource->GetController<Controller_NPad>(HidController::NPad) + .GetLastVibration(parameters.vibration_device_handle); + + const auto gc_erm_command = [last_vibration] { + if (last_vibration.amp_low != 0.0f || last_vibration.amp_high != 0.0f) { + return VibrationGcErmCommand::Start; + } + + /** + * Note: This uses yuzu-specific behavior such that the StopHard command produces + * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function + * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands. + * This is done to reuse the controller vibration functions made for regular controllers. + */ + if (last_vibration.freq_low == 0.0f && last_vibration.freq_high == 0.0f) { + return VibrationGcErmCommand::StopHard; + } + + return VibrationGcErmCommand::Stop; + }(); + + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.vibration_device_handle.npad_type, + parameters.vibration_device_handle.npad_id, + parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(gc_erm_command); +} + void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 7cc0433e2..99d155586 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -136,6 +136,8 @@ private: void PermitVibration(Kernel::HLERequestContext& ctx); void IsVibrationPermitted(Kernel::HLERequestContext& ctx); void SendVibrationValues(Kernel::HLERequestContext& ctx); + void SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx); + void GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx); void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); void IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx); @@ -154,7 +156,9 @@ private: void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx); enum class VibrationDeviceType : u32 { + Unknown = 0, LinearResonantActuator = 1, + GcErm = 2, }; enum class VibrationDevicePosition : u32 { @@ -163,6 +167,12 @@ private: Right = 2, }; + enum class VibrationGcErmCommand : u64 { + Stop = 0, + Start = 1, + StopHard = 2, + }; + struct VibrationDeviceInfo { VibrationDeviceType type{}; VibrationDevicePosition position{}; |