aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/hid_core/resources/palma/palma.h
blob: 477cbf904e87004975679a38c912c8b6ecb643ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <array>
#include <span>

#include "common/common_funcs.h"
#include "common/typed_address.h"
#include "hid_core/hid_result.h"
#include "hid_core/hid_types.h"
#include "hid_core/resources/controller_base.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 Palma final : public ControllerBase {
public:
    using PalmaOperationData = std::array<u8, 0x140>;
    using PalmaApplicationSection = std::array<u8, 0x100>;
    using Address = std::array<u8, 0x6>;

    // This is nn::hid::PalmaOperationType
    enum class PalmaOperationType : u64 {
        PlayActivity,
        SetFrModeType,
        ReadStep,
        EnableStep,
        ResetStep,
        ReadApplicationSection,
        WriteApplicationSection,
        ReadUniqueCode,
        SetUniqueCodeInvalid,
        WriteActivityEntry,
        WriteRgbLedPatternEntry,
        WriteWaveEntry,
        ReadDataBaseIdentificationVersion,
        WriteDataBaseIdentificationVersion,
        SuspendFeature,
        ReadPlayLog,
        ResetPlayLog,
    };

    enum class PackedPalmaOperationType : u32 {
        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 {
        PackedPalmaOperationType 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 {
        alignas(8) Core::HID::NpadIdType npad_id;
    };
    static_assert(sizeof(PalmaConnectionHandle) == 0x8,
                  "PalmaConnectionHandle has incorrect size.");

    explicit Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_);
    ~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, std::span<u8> out_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,
                               Common::ProcessAddress 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