From 23589ad9b8a3d2e1eecd0243d592ce5c6e4138e6 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 18 Jan 2022 20:08:56 -0600 Subject: service: hid: Partially implement palma controller --- src/core/hle/service/hid/controllers/npad.cpp | 6 +- src/core/hle/service/hid/controllers/palma.cpp | 229 +++++++++++++++++++++++++ src/core/hle/service/hid/controllers/palma.h | 163 ++++++++++++++++++ 3 files changed, 397 insertions(+), 1 deletion(-) create mode 100644 src/core/hle/service/hid/controllers/palma.cpp create mode 100644 src/core/hle/service/hid/controllers/palma.h (limited to 'src/core/hle/service/hid/controllers') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index cb29004e8..f8972ec7a 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -660,7 +660,6 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing ASSERT(false); break; case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::Pokeball: set_motion_state(sixaxis_fullkey_state, motion_state[0]); break; case Core::HID::NpadStyleIndex::Handheld: @@ -676,6 +675,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing 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; } diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp new file mode 100644 index 000000000..575d4e626 --- /dev/null +++ b/src/core/hle/service/hid/controllers/palma.cpp @@ -0,0 +1,229 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core_timing.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_readable_event.h" +#include "core/hle/service/hid/controllers/palma.h" +#include "core/hle/service/kernel_helpers.h" + +namespace Service::HID { + +Controller_Palma::Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, + KernelHelpers::ServiceContext& service_context_) + : ControllerBase{hid_core_}, service_context{service_context_} { + controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); + operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent"); +} + +Controller_Palma::~Controller_Palma() = default; + +void Controller_Palma::OnInit() {} + +void Controller_Palma::OnRelease() {} + +void Controller_Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) { + if (!IsControllerActivated()) { + return; + } +} + +Result Controller_Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id, + PalmaConnectionHandle& handle) { + active_handle.npad_id = npad_id; + handle = active_handle; + return ResultSuccess; +} + +Result Controller_Palma::InitializePalma(const PalmaConnectionHandle& handle) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + ActivateController(); + return ResultSuccess; +} + +Kernel::KReadableEvent& Controller_Palma::AcquirePalmaOperationCompleteEvent( + const PalmaConnectionHandle& handle) const { + if (handle.npad_id != active_handle.npad_id) { + LOG_ERROR(Service_HID, "Invalid npad id {}", handle.npad_id); + } + return operation_complete_event->GetReadableEvent(); +} + +Result Controller_Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle, + PalmaOperationType& operation_type, + PalmaOperationData& data) const { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + operation_type = operation.operation; + data = operation.data; + return ResultSuccess; +} + +Result Controller_Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, + u64 palma_activity) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + operation.operation = PalmaOperationType::PlayActivity; + operation.result = PalmaResultSuccess; + operation.data = {}; + operation_complete_event->GetWritableEvent().Signal(); + return ResultSuccess; +} + +Result Controller_Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle, + PalmaFrModeType fr_mode_) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + fr_mode = fr_mode_; + return ResultSuccess; +} + +Result Controller_Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + operation.operation = PalmaOperationType::ReadStep; + operation.result = PalmaResultSuccess; + operation.data = {}; + operation_complete_event->GetWritableEvent().Signal(); + return ResultSuccess; +} + +Result Controller_Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + return ResultSuccess; +} + +Result Controller_Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + return ResultSuccess; +} + +void Controller_Palma::ReadPalmaApplicationSection() {} + +void Controller_Palma::WritePalmaApplicationSection() {} + +Result Controller_Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + operation.operation = PalmaOperationType::ReadUniqueCode; + operation.result = PalmaResultSuccess; + operation.data = {}; + operation_complete_event->GetWritableEvent().Signal(); + return ResultSuccess; +} + +Result Controller_Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + operation.operation = PalmaOperationType::SetUniqueCodeInvalid; + operation.result = PalmaResultSuccess; + operation.data = {}; + operation_complete_event->GetWritableEvent().Signal(); + return ResultSuccess; +} + +void Controller_Palma::WritePalmaActivityEntry() {} + +Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, + u64 unknown) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + operation.operation = PalmaOperationType::WriteRgbLedPatternEntry; + operation.result = PalmaResultSuccess; + operation.data = {}; + operation_complete_event->GetWritableEvent().Signal(); + return ResultSuccess; +} + +Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, + u8* t_mem, u64 size) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + operation.operation = PalmaOperationType::WriteWaveEntry; + operation.result = PalmaResultSuccess; + operation.data = {}; + operation_complete_event->GetWritableEvent().Signal(); + return ResultSuccess; +} + +Result Controller_Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, + s32 database_id_version_) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + database_id_version = database_id_version_; + operation.operation = PalmaOperationType::ReadDataBaseIdentificationVersion; + operation.result = PalmaResultSuccess; + operation.data[0] = {}; + operation_complete_event->GetWritableEvent().Signal(); + return ResultSuccess; +} + +Result Controller_Palma::GetPalmaDataBaseIdentificationVersion( + const PalmaConnectionHandle& handle) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + operation.operation = PalmaOperationType::ReadDataBaseIdentificationVersion; + operation.result = PalmaResultSuccess; + operation.data = {}; + operation.data[0] = static_cast(database_id_version); + operation_complete_event->GetWritableEvent().Signal(); + return ResultSuccess; +} + +void Controller_Palma::SuspendPalmaFeature() {} + +Result Controller_Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + return operation.result; +} +void Controller_Palma::ReadPalmaPlayLog() {} + +void Controller_Palma::ResetPalmaPlayLog() {} + +void Controller_Palma::SetIsPalmaAllConnectable(bool is_all_connectable) { + // If true controllers are able to be paired + is_connectable = is_all_connectable; +} + +void Controller_Palma::SetIsPalmaPairedConnectable() {} + +Result Controller_Palma::PairPalma(const PalmaConnectionHandle& handle) { + if (handle.npad_id != active_handle.npad_id) { + return InvalidPalmaHandle; + } + // TODO: Do something + return ResultSuccess; +} + +void Controller_Palma::SetPalmaBoostMode(bool boost_mode) {} + +void Controller_Palma::CancelWritePalmaWaveEntry() {} + +void Controller_Palma::EnablePalmaBoostMode() {} + +void Controller_Palma::GetPalmaBluetoothAddress() {} + +void Controller_Palma::SetDisallowedPalmaConnection() {} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/palma.h b/src/core/hle/service/hid/controllers/palma.h new file mode 100644 index 000000000..1d7fc94e1 --- /dev/null +++ b/src/core/hle/service/hid/controllers/palma.h @@ -0,0 +1,163 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/errors.h" + +namespace Kernel { +class KEvent; +class KReadableEvent; +} // namespace Kernel + +namespace Service::KernelHelpers { +class ServiceContext; +} + +namespace Core::HID { +class EmulatedController; +} // namespace Core::HID + +namespace Service::HID { +class Controller_Palma final : public ControllerBase { +public: + using PalmaOperationData = std::array; + + // This is nn::hid::PalmaOperationType + enum class PalmaOperationType { + PlayActivity, + SetFrModeType, + ReadStep, + EnableStep, + ResetStep, + ReadApplicationSection, + WriteApplicationSection, + ReadUniqueCode, + SetUniqueCodeInvalid, + WriteActivityEntry, + WriteRgbLedPatternEntry, + WriteWaveEntry, + ReadDataBaseIdentificationVersion, + WriteDataBaseIdentificationVersion, + SuspendFeature, + ReadPlayLog, + ResetPlayLog, + }; + + // This is nn::hid::PalmaWaveSet + enum class PalmaWaveSet : u64 { + Small, + Medium, + Large, + }; + + // This is nn::hid::PalmaFrModeType + enum class PalmaFrModeType : u64 { + Off, + B01, + B02, + B03, + Downloaded, + }; + + // This is nn::hid::PalmaFeature + enum class PalmaFeature : u64 { + FrMode, + RumbleFeedback, + Step, + MuteSwitch, + }; + + // This is nn::hid::PalmaOperationInfo + struct PalmaOperationInfo { + PalmaOperationType operation{}; + Result result{PalmaResultSuccess}; + PalmaOperationData data{}; + }; + static_assert(sizeof(PalmaOperationInfo) == 0x148, "PalmaOperationInfo is an invalid size"); + + // This is nn::hid::PalmaActivityEntry + struct PalmaActivityEntry { + u32 rgb_led_pattern_index; + INSERT_PADDING_BYTES(2); + PalmaWaveSet wave_set; + u32 wave_index; + INSERT_PADDING_BYTES(12); + }; + static_assert(sizeof(PalmaActivityEntry) == 0x20, "PalmaActivityEntry is an invalid size"); + + struct PalmaConnectionHandle { + Core::HID::NpadIdType npad_id; + INSERT_PADDING_BYTES(4); // Unknown + }; + static_assert(sizeof(PalmaConnectionHandle) == 0x8, + "PalmaConnectionHandle has incorrect size."); + + explicit Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, + KernelHelpers::ServiceContext& service_context_); + ~Controller_Palma() 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 GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id, PalmaConnectionHandle& handle); + Result InitializePalma(const PalmaConnectionHandle& handle); + Kernel::KReadableEvent& AcquirePalmaOperationCompleteEvent( + const PalmaConnectionHandle& handle) const; + Result GetPalmaOperationInfo(const PalmaConnectionHandle& handle, + PalmaOperationType& operation_type, + PalmaOperationData& data) const; + Result PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity); + Result SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_); + Result ReadPalmaStep(const PalmaConnectionHandle& handle); + Result EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled); + Result ResetPalmaStep(const PalmaConnectionHandle& handle); + Result ReadPalmaUniqueCode(const PalmaConnectionHandle& handle); + Result SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle); + Result WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown); + Result WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, u8* t_mem, + u64 size); + Result SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, + s32 database_id_version_); + Result GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle); + Result GetPalmaOperationResult(const PalmaConnectionHandle& handle) const; + void SetIsPalmaAllConnectable(bool is_all_connectable); + Result PairPalma(const PalmaConnectionHandle& handle); + void SetPalmaBoostMode(bool boost_mode); + +private: + void ReadPalmaApplicationSection(); + void WritePalmaApplicationSection(); + void WritePalmaActivityEntry(); + void SuspendPalmaFeature(); + void ReadPalmaPlayLog(); + void ResetPalmaPlayLog(); + void SetIsPalmaPairedConnectable(); + void CancelWritePalmaWaveEntry(); + void EnablePalmaBoostMode(); + void GetPalmaBluetoothAddress(); + void SetDisallowedPalmaConnection(); + + bool is_connectable{}; + s32 database_id_version{}; + PalmaOperationInfo operation{}; + PalmaFrModeType fr_mode{}; + PalmaConnectionHandle active_handle{}; + + Core::HID::EmulatedController* controller; + + Kernel::KEvent* operation_complete_event; + KernelHelpers::ServiceContext& service_context; +}; + +} // namespace Service::HID -- cgit v1.2.3