mirror of https://git.suyu.dev/suyu/suyu
Merge pull request #8934 from german77/palma_release
service: hid: Partially implement palma controllermerge-requests/60/head
commit
dbb9d601df
@ -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<u8>(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
|
@ -0,0 +1,163 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#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<u8, 0x140>;
|
||||||
|
|
||||||
|
// 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
|
Loading…
Reference in New Issue