committed by
german77
36 changed files with 1625 additions and 1415 deletions
-
9src/core/CMakeLists.txt
-
17src/core/hid/emulated_controller.cpp
-
5src/core/hid/hid_core.cpp
-
80src/core/hid/hid_types.h
-
4src/core/hid/input_interpreter.cpp
-
4src/core/hid/input_interpreter.h
-
42src/core/hle/service/hid/controllers/console_six_axis.cpp
-
43src/core/hle/service/hid/controllers/console_six_axis.h
-
10src/core/hle/service/hid/controllers/debug_pad.cpp
-
6src/core/hle/service/hid/controllers/debug_pad.h
-
54src/core/hle/service/hid/controllers/gesture.cpp
-
6src/core/hle/service/hid/controllers/gesture.h
-
10src/core/hle/service/hid/controllers/keyboard.cpp
-
6src/core/hle/service/hid/controllers/keyboard.h
-
11src/core/hle/service/hid/controllers/mouse.cpp
-
6src/core/hle/service/hid/controllers/mouse.h
-
586src/core/hle/service/hid/controllers/npad.cpp
-
126src/core/hle/service/hid/controllers/npad.h
-
86src/core/hle/service/hid/controllers/palma.cpp
-
8src/core/hle/service/hid/controllers/palma.h
-
38src/core/hle/service/hid/controllers/seven_six_axis.cpp
-
31src/core/hle/service/hid/controllers/seven_six_axis.h
-
413src/core/hle/service/hid/controllers/six_axis.cpp
-
111src/core/hle/service/hid/controllers/six_axis.h
-
11src/core/hle/service/hid/controllers/touchscreen.cpp
-
6src/core/hle/service/hid/controllers/touchscreen.h
-
11src/core/hle/service/hid/controllers/xpad.cpp
-
6src/core/hle/service/hid/controllers/xpad.h
-
437src/core/hle/service/hid/hid_server.cpp
-
424src/core/hle/service/hid/hid_system_server.cpp
-
146src/core/hle/service/hid/hid_util.h
-
5src/core/hle/service/hid/irs.cpp
-
155src/core/hle/service/hid/resource_manager.cpp
-
119src/core/hle/service/hid/resource_manager.h
-
3src/core/hle/service/nfc/common/device_manager.cpp
-
5src/core/memory/cheat_engine.cpp
@ -0,0 +1,42 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
|||
#include "core/core.h"
|
|||
#include "core/core_timing.h"
|
|||
#include "core/hid/emulated_console.h"
|
|||
#include "core/hid/hid_core.h"
|
|||
#include "core/hle/service/hid/controllers/console_six_axis.h"
|
|||
#include "core/memory.h"
|
|||
|
|||
namespace Service::HID { |
|||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; |
|||
|
|||
ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) |
|||
: ControllerBase{hid_core_} { |
|||
console = hid_core.GetEmulatedConsole(); |
|||
static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size, |
|||
"ConsoleSharedMemory is bigger than the shared memory"); |
|||
shared_memory = std::construct_at( |
|||
reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); |
|||
} |
|||
|
|||
ConsoleSixAxis::~ConsoleSixAxis() = default; |
|||
|
|||
void ConsoleSixAxis::OnInit() {} |
|||
|
|||
void ConsoleSixAxis::OnRelease() {} |
|||
|
|||
void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { |
|||
if (!IsControllerActivated()) { |
|||
return; |
|||
} |
|||
|
|||
const auto motion_status = console->GetMotion(); |
|||
|
|||
shared_memory->sampling_number++; |
|||
shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; |
|||
shared_memory->verticalization_error = motion_status.verticalization_error; |
|||
shared_memory->gyro_bias = motion_status.gyro_bias; |
|||
} |
|||
|
|||
} // namespace Service::HID
|
|||
@ -0,0 +1,43 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
|||
// SPDX-License-Identifier: GPL-2.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include "common/vector_math.h" |
|||
#include "core/hle/service/hid/controllers/controller_base.h" |
|||
|
|||
namespace Core::HID { |
|||
class EmulatedConsole; |
|||
} // namespace Core::HID |
|||
|
|||
namespace Service::HID { |
|||
class ConsoleSixAxis final : public ControllerBase { |
|||
public: |
|||
explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); |
|||
~ConsoleSixAxis() override; |
|||
|
|||
// Called when the controller is initialized |
|||
void OnInit() override; |
|||
|
|||
// When the controller is released |
|||
void OnRelease() override; |
|||
|
|||
// When the controller is requesting an update for the shared memory |
|||
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; |
|||
|
|||
private: |
|||
// This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat |
|||
struct ConsoleSharedMemory { |
|||
u64 sampling_number{}; |
|||
bool is_seven_six_axis_sensor_at_rest{}; |
|||
INSERT_PADDING_BYTES(3); // padding |
|||
f32 verticalization_error{}; |
|||
Common::Vec3f gyro_bias{}; |
|||
INSERT_PADDING_BYTES(4); // padding |
|||
}; |
|||
static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size"); |
|||
|
|||
ConsoleSharedMemory* shared_memory = nullptr; |
|||
Core::HID::EmulatedConsole* console = nullptr; |
|||
}; |
|||
} // namespace Service::HID |
|||
@ -0,0 +1,413 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|||
|
|||
#include "common/common_types.h"
|
|||
#include "core/core_timing.h"
|
|||
#include "core/hid/emulated_controller.h"
|
|||
#include "core/hid/hid_core.h"
|
|||
#include "core/hle/service/hid/controllers/npad.h"
|
|||
#include "core/hle/service/hid/controllers/six_axis.h"
|
|||
#include "core/hle/service/hid/errors.h"
|
|||
#include "core/hle/service/hid/hid_util.h"
|
|||
|
|||
namespace Service::HID { |
|||
|
|||
SixAxis::SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_) |
|||
: ControllerBase{hid_core_}, npad{npad_} { |
|||
for (std::size_t i = 0; i < controller_data.size(); ++i) { |
|||
auto& controller = controller_data[i]; |
|||
controller.device = hid_core.GetEmulatedControllerByIndex(i); |
|||
} |
|||
} |
|||
|
|||
SixAxis::~SixAxis() = default; |
|||
|
|||
void SixAxis::OnInit() {} |
|||
void SixAxis::OnRelease() {} |
|||
|
|||
void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { |
|||
if (!IsControllerActivated()) { |
|||
return; |
|||
} |
|||
|
|||
for (std::size_t i = 0; i < controller_data.size(); ++i) { |
|||
auto& controller = controller_data[i]; |
|||
|
|||
const auto npad_id = IndexToNpadIdType(i); |
|||
const auto& controller_type = controller.device->GetNpadStyleIndex(); |
|||
|
|||
if (controller_type == Core::HID::NpadStyleIndex::None || |
|||
!controller.device->IsConnected()) { |
|||
continue; |
|||
} |
|||
|
|||
const auto& motion_state = controller.device->GetMotions(); |
|||
auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state; |
|||
auto& sixaxis_handheld_state = controller.sixaxis_handheld_state; |
|||
auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state; |
|||
auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state; |
|||
auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state; |
|||
auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state; |
|||
|
|||
auto& sixaxis_fullkey_lifo = npad->GetSixAxisFullkeyLifo(npad_id); |
|||
auto& sixaxis_handheld_lifo = npad->GetSixAxisHandheldLifo(npad_id); |
|||
auto& sixaxis_dual_left_lifo = npad->GetSixAxisDualLeftLifo(npad_id); |
|||
auto& sixaxis_dual_right_lifo = npad->GetSixAxisDualRightLifo(npad_id); |
|||
auto& sixaxis_left_lifo = npad->GetSixAxisLeftLifo(npad_id); |
|||
auto& sixaxis_right_lifo = npad->GetSixAxisRightLifo(npad_id); |
|||
|
|||
// Clear previous state
|
|||
sixaxis_fullkey_state = {}; |
|||
sixaxis_handheld_state = {}; |
|||
sixaxis_dual_left_state = {}; |
|||
sixaxis_dual_right_state = {}; |
|||
sixaxis_left_lifo_state = {}; |
|||
sixaxis_right_lifo_state = {}; |
|||
|
|||
if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) { |
|||
controller.sixaxis_at_rest = true; |
|||
for (std::size_t e = 0; e < motion_state.size(); ++e) { |
|||
controller.sixaxis_at_rest = |
|||
controller.sixaxis_at_rest && motion_state[e].is_at_rest; |
|||
} |
|||
} |
|||
|
|||
const auto set_motion_state = [&](Core::HID::SixAxisSensorState& state, |
|||
const Core::HID::ControllerMotion& hid_state) { |
|||
using namespace std::literals::chrono_literals; |
|||
static constexpr Core::HID::SixAxisSensorState default_motion_state = { |
|||
.delta_time = std::chrono::nanoseconds(5ms).count(), |
|||
.accel = {0, 0, -1.0f}, |
|||
.orientation = |
|||
{ |
|||
Common::Vec3f{1.0f, 0, 0}, |
|||
Common::Vec3f{0, 1.0f, 0}, |
|||
Common::Vec3f{0, 0, 1.0f}, |
|||
}, |
|||
.attribute = {1}, |
|||
}; |
|||
if (!controller.sixaxis_sensor_enabled) { |
|||
state = default_motion_state; |
|||
return; |
|||
} |
|||
if (!Settings::values.motion_enabled.GetValue()) { |
|||
state = default_motion_state; |
|||
return; |
|||
} |
|||
state.attribute.is_connected.Assign(1); |
|||
state.delta_time = std::chrono::nanoseconds(5ms).count(); |
|||
state.accel = hid_state.accel; |
|||
state.gyro = hid_state.gyro; |
|||
state.rotation = hid_state.rotation; |
|||
state.orientation = hid_state.orientation; |
|||
}; |
|||
|
|||
switch (controller_type) { |
|||
case Core::HID::NpadStyleIndex::None: |
|||
ASSERT(false); |
|||
break; |
|||
case Core::HID::NpadStyleIndex::ProController: |
|||
set_motion_state(sixaxis_fullkey_state, motion_state[0]); |
|||
break; |
|||
case Core::HID::NpadStyleIndex::Handheld: |
|||
set_motion_state(sixaxis_handheld_state, motion_state[0]); |
|||
break; |
|||
case Core::HID::NpadStyleIndex::JoyconDual: |
|||
set_motion_state(sixaxis_dual_left_state, motion_state[0]); |
|||
set_motion_state(sixaxis_dual_right_state, motion_state[1]); |
|||
break; |
|||
case Core::HID::NpadStyleIndex::JoyconLeft: |
|||
set_motion_state(sixaxis_left_lifo_state, motion_state[0]); |
|||
break; |
|||
case Core::HID::NpadStyleIndex::JoyconRight: |
|||
set_motion_state(sixaxis_right_lifo_state, motion_state[1]); |
|||
break; |
|||
case Core::HID::NpadStyleIndex::Pokeball: |
|||
using namespace std::literals::chrono_literals; |
|||
set_motion_state(sixaxis_fullkey_state, motion_state[0]); |
|||
sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count(); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
|
|||
sixaxis_fullkey_state.sampling_number = |
|||
sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; |
|||
sixaxis_handheld_state.sampling_number = |
|||
sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; |
|||
sixaxis_dual_left_state.sampling_number = |
|||
sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1; |
|||
sixaxis_dual_right_state.sampling_number = |
|||
sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1; |
|||
sixaxis_left_lifo_state.sampling_number = |
|||
sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1; |
|||
sixaxis_right_lifo_state.sampling_number = |
|||
sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1; |
|||
|
|||
if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) { |
|||
// This buffer only is updated on handheld on HW
|
|||
sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); |
|||
} else { |
|||
// Handheld doesn't update this buffer on HW
|
|||
sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); |
|||
} |
|||
|
|||
sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state); |
|||
sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state); |
|||
sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state); |
|||
sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state); |
|||
} |
|||
} |
|||
|
|||
Result SixAxis::SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::GyroscopeZeroDriftMode drift_mode) { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
auto& sixaxis = GetSixaxisState(sixaxis_handle); |
|||
auto& controller = GetControllerFromHandle(sixaxis_handle); |
|||
sixaxis.gyroscope_zero_drift_mode = drift_mode; |
|||
controller.device->SetGyroscopeZeroDriftMode(drift_mode); |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
Result SixAxis::GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::GyroscopeZeroDriftMode& drift_mode) const { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
const auto& sixaxis = GetSixaxisState(sixaxis_handle); |
|||
drift_mode = sixaxis.gyroscope_zero_drift_mode; |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
Result SixAxis::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
bool& is_at_rest) const { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
const auto& controller = GetControllerFromHandle(sixaxis_handle); |
|||
is_at_rest = controller.sixaxis_at_rest; |
|||
return ResultSuccess; |
|||
} |
|||
|
|||
Result SixAxis::LoadSixAxisSensorCalibrationParameter( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::SixAxisSensorCalibrationParameter& calibration) const { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
// TODO: Request this data to the controller. On error return 0xd8ca
|
|||
const auto& sixaxis = GetSixaxisState(sixaxis_handle); |
|||
calibration = sixaxis.calibration; |
|||
return ResultSuccess; |
|||
} |
|||
|
|||
Result SixAxis::GetSixAxisSensorIcInformation( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::SixAxisSensorIcInformation& ic_information) const { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
// TODO: Request this data to the controller. On error return 0xd8ca
|
|||
const auto& sixaxis = GetSixaxisState(sixaxis_handle); |
|||
ic_information = sixaxis.ic_information; |
|||
return ResultSuccess; |
|||
} |
|||
|
|||
Result SixAxis::EnableSixAxisSensorUnalteredPassthrough( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
auto& sixaxis = GetSixaxisState(sixaxis_handle); |
|||
sixaxis.unaltered_passtrough = is_enabled; |
|||
return ResultSuccess; |
|||
} |
|||
|
|||
Result SixAxis::IsSixAxisSensorUnalteredPassthroughEnabled( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
const auto& sixaxis = GetSixaxisState(sixaxis_handle); |
|||
is_enabled = sixaxis.unaltered_passtrough; |
|||
return ResultSuccess; |
|||
} |
|||
|
|||
Result SixAxis::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
bool sixaxis_status) { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
auto& controller = GetControllerFromHandle(sixaxis_handle); |
|||
controller.sixaxis_sensor_enabled = sixaxis_status; |
|||
return ResultSuccess; |
|||
} |
|||
|
|||
Result SixAxis::IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
bool& is_fusion_enabled) const { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
const auto& sixaxis = GetSixaxisState(sixaxis_handle); |
|||
is_fusion_enabled = sixaxis.is_fusion_enabled; |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
Result SixAxis::SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
bool is_fusion_enabled) { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
auto& sixaxis = GetSixaxisState(sixaxis_handle); |
|||
sixaxis.is_fusion_enabled = is_fusion_enabled; |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
Result SixAxis::SetSixAxisFusionParameters( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
const auto param1 = sixaxis_fusion_parameters.parameter1; |
|||
if (param1 < 0.0f || param1 > 1.0f) { |
|||
return InvalidSixAxisFusionRange; |
|||
} |
|||
|
|||
auto& sixaxis = GetSixaxisState(sixaxis_handle); |
|||
sixaxis.fusion = sixaxis_fusion_parameters; |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
Result SixAxis::GetSixAxisFusionParameters( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::SixAxisSensorFusionParameters& parameters) const { |
|||
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); |
|||
if (is_valid.IsError()) { |
|||
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); |
|||
return is_valid; |
|||
} |
|||
|
|||
const auto& sixaxis = GetSixaxisState(sixaxis_handle); |
|||
parameters = sixaxis.fusion; |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
SixAxis::SixaxisParameters& SixAxis::GetSixaxisState( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle) { |
|||
auto& controller = GetControllerFromHandle(sixaxis_handle); |
|||
switch (sixaxis_handle.npad_type) { |
|||
case Core::HID::NpadStyleIndex::ProController: |
|||
case Core::HID::NpadStyleIndex::Pokeball: |
|||
return controller.sixaxis_fullkey; |
|||
case Core::HID::NpadStyleIndex::Handheld: |
|||
return controller.sixaxis_handheld; |
|||
case Core::HID::NpadStyleIndex::JoyconDual: |
|||
if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { |
|||
return controller.sixaxis_dual_left; |
|||
} |
|||
return controller.sixaxis_dual_right; |
|||
case Core::HID::NpadStyleIndex::JoyconLeft: |
|||
return controller.sixaxis_left; |
|||
case Core::HID::NpadStyleIndex::JoyconRight: |
|||
return controller.sixaxis_right; |
|||
default: |
|||
return controller.sixaxis_unknown; |
|||
} |
|||
} |
|||
|
|||
const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { |
|||
const auto& controller = GetControllerFromHandle(sixaxis_handle); |
|||
switch (sixaxis_handle.npad_type) { |
|||
case Core::HID::NpadStyleIndex::ProController: |
|||
case Core::HID::NpadStyleIndex::Pokeball: |
|||
return controller.sixaxis_fullkey; |
|||
case Core::HID::NpadStyleIndex::Handheld: |
|||
return controller.sixaxis_handheld; |
|||
case Core::HID::NpadStyleIndex::JoyconDual: |
|||
if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { |
|||
return controller.sixaxis_dual_left; |
|||
} |
|||
return controller.sixaxis_dual_right; |
|||
case Core::HID::NpadStyleIndex::JoyconLeft: |
|||
return controller.sixaxis_left; |
|||
case Core::HID::NpadStyleIndex::JoyconRight: |
|||
return controller.sixaxis_right; |
|||
default: |
|||
return controller.sixaxis_unknown; |
|||
} |
|||
} |
|||
|
|||
SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle( |
|||
const Core::HID::SixAxisSensorHandle& device_handle) { |
|||
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); |
|||
return GetControllerFromNpadIdType(npad_id); |
|||
} |
|||
|
|||
const SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle( |
|||
const Core::HID::SixAxisSensorHandle& device_handle) const { |
|||
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); |
|||
return GetControllerFromNpadIdType(npad_id); |
|||
} |
|||
|
|||
SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) { |
|||
if (!IsNpadIdValid(npad_id)) { |
|||
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); |
|||
npad_id = Core::HID::NpadIdType::Player1; |
|||
} |
|||
const auto npad_index = NpadIdTypeToIndex(npad_id); |
|||
return controller_data[npad_index]; |
|||
} |
|||
|
|||
const SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType( |
|||
Core::HID::NpadIdType npad_id) const { |
|||
if (!IsNpadIdValid(npad_id)) { |
|||
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); |
|||
npad_id = Core::HID::NpadIdType::Player1; |
|||
} |
|||
const auto npad_index = NpadIdTypeToIndex(npad_id); |
|||
return controller_data[npad_index]; |
|||
} |
|||
|
|||
} // namespace Service::HID
|
|||
@ -0,0 +1,111 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include "common/common_types.h" |
|||
#include "core/hid/hid_types.h" |
|||
#include "core/hle/service/hid/controllers/controller_base.h" |
|||
#include "core/hle/service/hid/ring_lifo.h" |
|||
|
|||
namespace Core::HID { |
|||
class EmulatedController; |
|||
} // namespace Core::HID |
|||
|
|||
namespace Service::HID { |
|||
class NPad; |
|||
|
|||
class SixAxis final : public ControllerBase { |
|||
public: |
|||
explicit SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_); |
|||
~SixAxis() override; |
|||
|
|||
// Called when the controller is initialized |
|||
void OnInit() override; |
|||
|
|||
// When the controller is released |
|||
void OnRelease() override; |
|||
|
|||
// When the controller is requesting an update for the shared memory |
|||
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; |
|||
|
|||
Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::GyroscopeZeroDriftMode drift_mode); |
|||
Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::GyroscopeZeroDriftMode& drift_mode) const; |
|||
Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
bool& is_at_rest) const; |
|||
Result EnableSixAxisSensorUnalteredPassthrough( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled); |
|||
Result IsSixAxisSensorUnalteredPassthroughEnabled( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const; |
|||
Result LoadSixAxisSensorCalibrationParameter( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::SixAxisSensorCalibrationParameter& calibration) const; |
|||
Result GetSixAxisSensorIcInformation( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::SixAxisSensorIcInformation& ic_information) const; |
|||
Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
bool sixaxis_status); |
|||
Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
bool& is_fusion_enabled) const; |
|||
Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
bool is_fusion_enabled); |
|||
Result SetSixAxisFusionParameters( |
|||
const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters); |
|||
Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle, |
|||
Core::HID::SixAxisSensorFusionParameters& parameters) const; |
|||
|
|||
private: |
|||
static constexpr std::size_t NPAD_COUNT = 10; |
|||
|
|||
struct SixaxisParameters { |
|||
bool is_fusion_enabled{true}; |
|||
bool unaltered_passtrough{false}; |
|||
Core::HID::SixAxisSensorFusionParameters fusion{}; |
|||
Core::HID::SixAxisSensorCalibrationParameter calibration{}; |
|||
Core::HID::SixAxisSensorIcInformation ic_information{}; |
|||
Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{ |
|||
Core::HID::GyroscopeZeroDriftMode::Standard}; |
|||
}; |
|||
|
|||
struct NpadControllerData { |
|||
Core::HID::EmulatedController* device = nullptr; |
|||
|
|||
// Motion parameters |
|||
bool sixaxis_at_rest{true}; |
|||
bool sixaxis_sensor_enabled{true}; |
|||
SixaxisParameters sixaxis_fullkey{}; |
|||
SixaxisParameters sixaxis_handheld{}; |
|||
SixaxisParameters sixaxis_dual_left{}; |
|||
SixaxisParameters sixaxis_dual_right{}; |
|||
SixaxisParameters sixaxis_left{}; |
|||
SixaxisParameters sixaxis_right{}; |
|||
SixaxisParameters sixaxis_unknown{}; |
|||
|
|||
// Current pad state |
|||
Core::HID::SixAxisSensorState sixaxis_fullkey_state{}; |
|||
Core::HID::SixAxisSensorState sixaxis_handheld_state{}; |
|||
Core::HID::SixAxisSensorState sixaxis_dual_left_state{}; |
|||
Core::HID::SixAxisSensorState sixaxis_dual_right_state{}; |
|||
Core::HID::SixAxisSensorState sixaxis_left_lifo_state{}; |
|||
Core::HID::SixAxisSensorState sixaxis_right_lifo_state{}; |
|||
int callback_key{}; |
|||
}; |
|||
|
|||
SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle); |
|||
const SixaxisParameters& GetSixaxisState( |
|||
const Core::HID::SixAxisSensorHandle& device_handle) const; |
|||
|
|||
NpadControllerData& GetControllerFromHandle( |
|||
const Core::HID::SixAxisSensorHandle& device_handle); |
|||
const NpadControllerData& GetControllerFromHandle( |
|||
const Core::HID::SixAxisSensorHandle& device_handle) const; |
|||
NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); |
|||
const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; |
|||
|
|||
std::shared_ptr<NPad> npad; |
|||
std::array<NpadControllerData, NPAD_COUNT> controller_data{}; |
|||
}; |
|||
} // namespace Service::HID |
|||
437
src/core/hle/service/hid/hid_server.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,146 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include "core/hid/hid_types.h" |
|||
#include "core/hle/service/hid/errors.h" |
|||
|
|||
namespace Service::HID { |
|||
|
|||
constexpr bool IsNpadIdValid(const Core::HID::NpadIdType npad_id) { |
|||
switch (npad_id) { |
|||
case Core::HID::NpadIdType::Player1: |
|||
case Core::HID::NpadIdType::Player2: |
|||
case Core::HID::NpadIdType::Player3: |
|||
case Core::HID::NpadIdType::Player4: |
|||
case Core::HID::NpadIdType::Player5: |
|||
case Core::HID::NpadIdType::Player6: |
|||
case Core::HID::NpadIdType::Player7: |
|||
case Core::HID::NpadIdType::Player8: |
|||
case Core::HID::NpadIdType::Other: |
|||
case Core::HID::NpadIdType::Handheld: |
|||
return true; |
|||
default: |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& handle) { |
|||
const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id)); |
|||
const bool device_index = handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; |
|||
|
|||
if (!npad_id) { |
|||
return InvalidNpadId; |
|||
} |
|||
if (!device_index) { |
|||
return NpadDeviceIndexOutOfRange; |
|||
} |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) { |
|||
switch (handle.npad_type) { |
|||
case Core::HID::NpadStyleIndex::ProController: |
|||
case Core::HID::NpadStyleIndex::Handheld: |
|||
case Core::HID::NpadStyleIndex::JoyconDual: |
|||
case Core::HID::NpadStyleIndex::JoyconLeft: |
|||
case Core::HID::NpadStyleIndex::JoyconRight: |
|||
case Core::HID::NpadStyleIndex::GameCube: |
|||
case Core::HID::NpadStyleIndex::N64: |
|||
case Core::HID::NpadStyleIndex::SystemExt: |
|||
case Core::HID::NpadStyleIndex::System: |
|||
// These support vibration |
|||
break; |
|||
default: |
|||
return VibrationInvalidStyleIndex; |
|||
} |
|||
|
|||
if (!IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id))) { |
|||
return VibrationInvalidNpadId; |
|||
} |
|||
|
|||
if (handle.device_index >= Core::HID::DeviceIndex::MaxDeviceIndex) { |
|||
return VibrationDeviceIndexOutOfRange; |
|||
} |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
/// Converts a Core::HID::NpadIdType to an array index. |
|||
constexpr size_t NpadIdTypeToIndex(Core::HID::NpadIdType npad_id_type) { |
|||
switch (npad_id_type) { |
|||
case Core::HID::NpadIdType::Player1: |
|||
return 0; |
|||
case Core::HID::NpadIdType::Player2: |
|||
return 1; |
|||
case Core::HID::NpadIdType::Player3: |
|||
return 2; |
|||
case Core::HID::NpadIdType::Player4: |
|||
return 3; |
|||
case Core::HID::NpadIdType::Player5: |
|||
return 4; |
|||
case Core::HID::NpadIdType::Player6: |
|||
return 5; |
|||
case Core::HID::NpadIdType::Player7: |
|||
return 6; |
|||
case Core::HID::NpadIdType::Player8: |
|||
return 7; |
|||
case Core::HID::NpadIdType::Handheld: |
|||
return 8; |
|||
case Core::HID::NpadIdType::Other: |
|||
return 9; |
|||
default: |
|||
return 8; |
|||
} |
|||
} |
|||
|
|||
/// Converts an array index to a Core::HID::NpadIdType |
|||
constexpr Core::HID::NpadIdType IndexToNpadIdType(size_t index) { |
|||
switch (index) { |
|||
case 0: |
|||
return Core::HID::NpadIdType::Player1; |
|||
case 1: |
|||
return Core::HID::NpadIdType::Player2; |
|||
case 2: |
|||
return Core::HID::NpadIdType::Player3; |
|||
case 3: |
|||
return Core::HID::NpadIdType::Player4; |
|||
case 4: |
|||
return Core::HID::NpadIdType::Player5; |
|||
case 5: |
|||
return Core::HID::NpadIdType::Player6; |
|||
case 6: |
|||
return Core::HID::NpadIdType::Player7; |
|||
case 7: |
|||
return Core::HID::NpadIdType::Player8; |
|||
case 8: |
|||
return Core::HID::NpadIdType::Handheld; |
|||
case 9: |
|||
return Core::HID::NpadIdType::Other; |
|||
default: |
|||
return Core::HID::NpadIdType::Invalid; |
|||
} |
|||
} |
|||
|
|||
constexpr Core::HID::NpadStyleSet GetStylesetByIndex(std::size_t index) { |
|||
switch (index) { |
|||
case 0: |
|||
return Core::HID::NpadStyleSet::Fullkey; |
|||
case 1: |
|||
return Core::HID::NpadStyleSet::Handheld; |
|||
case 2: |
|||
return Core::HID::NpadStyleSet::JoyDual; |
|||
case 3: |
|||
return Core::HID::NpadStyleSet::JoyLeft; |
|||
case 4: |
|||
return Core::HID::NpadStyleSet::JoyRight; |
|||
case 5: |
|||
return Core::HID::NpadStyleSet::Palma; |
|||
default: |
|||
return Core::HID::NpadStyleSet::None; |
|||
} |
|||
} |
|||
|
|||
} // namespace Service::HID |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue