service: hid: Create appropriate hid resources
parent
8da5bd27e9
commit
cff2d0e19e
@ -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
|
File diff suppressed because it is too large
Load Diff
@ -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
|
Loading…
Reference in New Issue