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