|
|
|
@ -9,6 +9,7 @@ |
|
|
|
#include "core/core.h"
|
|
|
|
#include "core/core_timing.h"
|
|
|
|
#include "core/frontend/input.h"
|
|
|
|
#include "core/hardware_properties.h"
|
|
|
|
#include "core/hle/ipc_helpers.h"
|
|
|
|
#include "core/hle/kernel/k_readable_event.h"
|
|
|
|
#include "core/hle/kernel/k_shared_memory.h"
|
|
|
|
@ -34,10 +35,9 @@ |
|
|
|
namespace Service::HID { |
|
|
|
|
|
|
|
// Updating period for each HID device.
|
|
|
|
// HID is polled every 15ms, this value was derived from
|
|
|
|
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet
|
|
|
|
constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // (1ms, 1000Hz)
|
|
|
|
constexpr auto motion_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.666Hz)
|
|
|
|
// Period time is obtained by measuring the number of samples in a second
|
|
|
|
constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz)
|
|
|
|
constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
|
|
|
|
constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; |
|
|
|
|
|
|
|
IAppletResource::IAppletResource(Core::System& system_, |
|
|
|
@ -89,7 +89,7 @@ IAppletResource::IAppletResource(Core::System& system_, |
|
|
|
system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); |
|
|
|
system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event); |
|
|
|
|
|
|
|
ReloadInputDevices(); |
|
|
|
system.HIDCore().ReloadInputDevices(); |
|
|
|
} |
|
|
|
|
|
|
|
void IAppletResource::ActivateController(HidController controller) { |
|
|
|
@ -117,11 +117,7 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, |
|
|
|
std::chrono::nanoseconds ns_late) { |
|
|
|
auto& core_timing = system.CoreTiming(); |
|
|
|
|
|
|
|
const bool should_reload = false; |
|
|
|
for (const auto& controller : controllers) { |
|
|
|
if (should_reload) { |
|
|
|
controller->OnLoadInputDevices(); |
|
|
|
} |
|
|
|
controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(), |
|
|
|
SHARED_MEMORY_SIZE); |
|
|
|
} |
|
|
|
@ -891,7 +887,7 @@ void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { |
|
|
|
void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { |
|
|
|
IPC::RequestParser rp{ctx}; |
|
|
|
const auto applet_resource_user_id{rp.Pop<u64>()}; |
|
|
|
const auto hold_type{rp.PopEnum<Controller_NPad::NpadHoldType>()}; |
|
|
|
const auto hold_type{rp.PopEnum<Controller_NPad::NpadJoyHoldType>()}; |
|
|
|
|
|
|
|
applet_resource->GetController<Controller_NPad>(HidController::NPad).SetHoldType(hold_type); |
|
|
|
|
|
|
|
@ -924,7 +920,7 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx |
|
|
|
const auto parameters{rp.PopRaw<Parameters>()}; |
|
|
|
|
|
|
|
applet_resource->GetController<Controller_NPad>(HidController::NPad) |
|
|
|
.SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); |
|
|
|
.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single); |
|
|
|
|
|
|
|
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", |
|
|
|
parameters.npad_id, parameters.applet_resource_user_id); |
|
|
|
@ -946,7 +942,7 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { |
|
|
|
const auto parameters{rp.PopRaw<Parameters>()}; |
|
|
|
|
|
|
|
applet_resource->GetController<Controller_NPad>(HidController::NPad) |
|
|
|
.SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); |
|
|
|
.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single); |
|
|
|
|
|
|
|
LOG_WARNING(Service_HID, |
|
|
|
"(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", |
|
|
|
@ -968,7 +964,7 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { |
|
|
|
const auto parameters{rp.PopRaw<Parameters>()}; |
|
|
|
|
|
|
|
applet_resource->GetController<Controller_NPad>(HidController::NPad) |
|
|
|
.SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Dual); |
|
|
|
.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Dual); |
|
|
|
|
|
|
|
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", |
|
|
|
parameters.npad_id, parameters.applet_resource_user_id); |
|
|
|
@ -1134,36 +1130,36 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { |
|
|
|
IPC::RequestParser rp{ctx}; |
|
|
|
const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; |
|
|
|
|
|
|
|
VibrationDeviceInfo vibration_device_info; |
|
|
|
Core::HID::VibrationDeviceInfo vibration_device_info; |
|
|
|
|
|
|
|
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: |
|
|
|
case Core::HID::NpadType::ProController: |
|
|
|
case Core::HID::NpadType::Handheld: |
|
|
|
case Core::HID::NpadType::JoyconDual: |
|
|
|
case Core::HID::NpadType::JoyconLeft: |
|
|
|
case Core::HID::NpadType::JoyconRight: |
|
|
|
default: |
|
|
|
vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; |
|
|
|
vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator; |
|
|
|
break; |
|
|
|
case Controller_NPad::NpadType::GameCube: |
|
|
|
vibration_device_info.type = VibrationDeviceType::GcErm; |
|
|
|
case Core::HID::NpadType::GameCube: |
|
|
|
vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm; |
|
|
|
break; |
|
|
|
case Controller_NPad::NpadType::Pokeball: |
|
|
|
vibration_device_info.type = VibrationDeviceType::Unknown; |
|
|
|
case Core::HID::NpadType::Pokeball: |
|
|
|
vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
switch (vibration_device_handle.device_index) { |
|
|
|
case Controller_NPad::DeviceIndex::Left: |
|
|
|
vibration_device_info.position = VibrationDevicePosition::Left; |
|
|
|
vibration_device_info.position = Core::HID::VibrationDevicePosition::Left; |
|
|
|
break; |
|
|
|
case Controller_NPad::DeviceIndex::Right: |
|
|
|
vibration_device_info.position = VibrationDevicePosition::Right; |
|
|
|
vibration_device_info.position = Core::HID::VibrationDevicePosition::Right; |
|
|
|
break; |
|
|
|
case Controller_NPad::DeviceIndex::None: |
|
|
|
default: |
|
|
|
UNREACHABLE_MSG("DeviceIndex should never be None!"); |
|
|
|
vibration_device_info.position = VibrationDevicePosition::None; |
|
|
|
vibration_device_info.position = Core::HID::VibrationDevicePosition::None; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1278,7 +1274,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { |
|
|
|
struct Parameters { |
|
|
|
Controller_NPad::DeviceHandle vibration_device_handle; |
|
|
|
u64 applet_resource_user_id; |
|
|
|
VibrationGcErmCommand gc_erm_command; |
|
|
|
Core::HID::VibrationGcErmCommand gc_erm_command; |
|
|
|
}; |
|
|
|
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); |
|
|
|
|
|
|
|
@ -1292,21 +1288,21 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { |
|
|
|
*/ |
|
|
|
const auto vibration_value = [parameters] { |
|
|
|
switch (parameters.gc_erm_command) { |
|
|
|
case VibrationGcErmCommand::Stop: |
|
|
|
case Core::HID::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: |
|
|
|
case Core::HID::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: |
|
|
|
case Core::HID::VibrationGcErmCommand::StopHard: |
|
|
|
return Controller_NPad::VibrationValue{ |
|
|
|
.amp_low = 0.0f, |
|
|
|
.freq_low = 0.0f, |
|
|
|
@ -1348,7 +1344,7 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { |
|
|
|
|
|
|
|
const auto gc_erm_command = [last_vibration] { |
|
|
|
if (last_vibration.amp_low != 0.0f || last_vibration.amp_high != 0.0f) { |
|
|
|
return VibrationGcErmCommand::Start; |
|
|
|
return Core::HID::VibrationGcErmCommand::Start; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
@ -1358,10 +1354,10 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { |
|
|
|
* 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 Core::HID::VibrationGcErmCommand::StopHard; |
|
|
|
} |
|
|
|
|
|
|
|
return VibrationGcErmCommand::Stop; |
|
|
|
return Core::HID::VibrationGcErmCommand::Stop; |
|
|
|
}(); |
|
|
|
|
|
|
|
LOG_DEBUG(Service_HID, |
|
|
|
@ -2037,9 +2033,6 @@ public: |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
void ReloadInputDevices() { |
|
|
|
} |
|
|
|
|
|
|
|
void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { |
|
|
|
std::make_shared<Hid>(system)->InstallAsService(service_manager); |
|
|
|
std::make_shared<HidBus>(system)->InstallAsService(service_manager); |
|
|
|
|