Repository navigation
Expand file tree
/
Copy pathkeyboard_impl.cpp
More file actions
194 lines (177 loc) · 6.6 KB
/
Copy pathkeyboard_impl.cpp
File metadata and controls
194 lines (177 loc) · 6.6 KB
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
186
187
188
189
190
191
192
193
194
#include "prx/libSceKeyboard/include/KeyboardState.hpp"
#include "prx/libc/include/General.hpp"
#include "prx/libkernel/Time/include/Time.hpp"
#include <algorithm>
#include <array>
#include <mutex>
namespace {
std::mutex keyboardMutex;
std::array<KeyboardData, KEYBOARD_MAX_DATA_NUM> history{};
int head = 0;
int count = 0;
bool initialized = false;
bool opened = false;
bool connected = true;
std::uint32_t led = 0;
std::uint32_t modifiers = 0;
std::array<std::uint16_t, KEYBOARD_MAX_KEYCODES> keys{};
int keyCount = 0;
constexpr char US_NORMAL[] = "1234567890\n\0\b\t -=[]\\\0;'`,./";
constexpr char US_SHIFTED[] = "!@#$%^&*()\n\0\b\t _+{}|\0:\"~<>?";
constexpr char JIS_NORMAL[] = "1234567890\n\0\b\t -^@[]];:\0,./";
constexpr char JIS_SHIFTED[] = "!\"#$%&'()\0\n\0\b\t =~`{}}+*\0<>?";
constexpr char KEYPAD_DIGITS[] = "1234567890.";
KeyboardData snapshot() {
KeyboardData data{};
data.timestamp = sceKernelGetProcessTime();
data.connected = connected;
data.length = keyCount;
data.led = led;
data.modifier_key = modifiers;
std::copy_n(keys.begin(), keyCount, data.key_code);
return data;
}
void enqueue(const KeyboardData& data) {
if (count == KEYBOARD_MAX_DATA_NUM) {
head = (head + 1) % KEYBOARD_MAX_DATA_NUM;
--count;
}
history[(head + count) % KEYBOARD_MAX_DATA_NUM] = data;
++count;
}
void clearKeys() {
modifiers = 0;
keyCount = 0;
}
bool updateKey(std::uint16_t keyCode, bool pressed) {
if (keyCode >= KEYBOARD_KEY_LEFT_CTRL && keyCode <= KEYBOARD_KEY_RIGHT_GUI) {
const std::uint32_t bit = 1u << (keyCode - KEYBOARD_KEY_LEFT_CTRL);
const std::uint32_t updated = pressed ? modifiers | bit : modifiers & ~bit;
if (updated == modifiers) return false;
modifiers = updated;
return true;
}
const auto end = keys.begin() + keyCount;
const auto found = std::find(keys.begin(), end, keyCode);
if (pressed) {
if (found != end || keyCount == static_cast<int>(KEYBOARD_MAX_KEYCODES)) return false;
keys[keyCount++] = keyCode;
return true;
}
if (found == end) return false;
std::copy(found + 1, end, found);
--keyCount;
return true;
}
std::uint16_t character(bool jis, std::uint32_t ledState, std::uint32_t modifierKey, std::uint16_t keyCode) {
const bool shift = (modifierKey & (KEYBOARD_MOD_LEFT_SHIFT | KEYBOARD_MOD_RIGHT_SHIFT)) != 0;
if (keyCode >= 0x04 && keyCode <= 0x1d) {
const bool upper = shift != ((ledState & KEYBOARD_LED_CAPS_LOCK) != 0);
return static_cast<std::uint16_t>((upper ? 'A' : 'a') + keyCode - 0x04);
}
if (keyCode >= 0x1e && keyCode <= 0x38) {
const char* table = jis ? (shift ? JIS_SHIFTED : JIS_NORMAL) : (shift ? US_SHIFTED : US_NORMAL);
return static_cast<unsigned char>(table[keyCode - 0x1e]);
}
if (jis && keyCode == 0x87) return shift ? '_' : '\\';
if (jis && keyCode == 0x89) return shift ? '|' : '\\';
switch (keyCode) {
case 0x54: return '/';
case 0x55: return '*';
case 0x56: return '-';
case 0x57: return '+';
case 0x58: return '\n';
default: break;
}
if (keyCode >= 0x59 && keyCode <= 0x63 && (ledState & KEYBOARD_LED_NUM_LOCK) != 0) {
return static_cast<unsigned char>(KEYPAD_DIGITS[keyCode - 0x59]);
}
return 0;
}
}
namespace Keyboard {
int Initialize() {
std::lock_guard lock(keyboardMutex);
initialized = true;
return KEYBOARD_OK;
}
int Open(int userId, std::int32_t type, std::int32_t index) {
std::lock_guard lock(keyboardMutex);
if (!initialized) return KEYBOARD_ERROR_NOT_INITIALIZED;
if (userId < 0 || type != 0 || index != 0) return KEYBOARD_ERROR_INVALID_ARG;
if (opened) return KEYBOARD_ERROR_ALREADY_OPENED;
opened = true;
clearKeys();
head = 0;
count = 0;
enqueue(snapshot());
return KEYBOARD_HANDLE;
}
int Close(std::int32_t handle) {
std::lock_guard lock(keyboardMutex);
if (!initialized) return KEYBOARD_ERROR_NOT_INITIALIZED;
if (handle != KEYBOARD_HANDLE || !opened) return KEYBOARD_ERROR_INVALID_HANDLE;
opened = false;
clearKeys();
head = 0;
count = 0;
return KEYBOARD_OK;
}
int Read(std::int32_t handle, KeyboardData* data, std::int32_t num) {
std::lock_guard lock(keyboardMutex);
if (!initialized) return KEYBOARD_ERROR_NOT_INITIALIZED;
if (handle != KEYBOARD_HANDLE || !opened) return KEYBOARD_ERROR_INVALID_HANDLE;
if (data == nullptr || num <= 0 || num > KEYBOARD_MAX_DATA_NUM) return KEYBOARD_ERROR_INVALID_ARG;
const int available = std::min(count, num);
for (int i = 0; i < available; ++i) {
data[i] = history[head];
head = (head + 1) % KEYBOARD_MAX_DATA_NUM;
}
count -= available;
return available;
}
int ReadState(std::int32_t handle, KeyboardData* data) {
std::lock_guard lock(keyboardMutex);
if (!initialized) return KEYBOARD_ERROR_NOT_INITIALIZED;
if (handle != KEYBOARD_HANDLE || !opened) return KEYBOARD_ERROR_INVALID_HANDLE;
if (data == nullptr) return KEYBOARD_ERROR_INVALID_ARG;
*data = snapshot();
return KEYBOARD_OK;
}
int GetKey2Char(std::int32_t handle, std::int32_t arrange, std::uint32_t ledState, std::uint32_t modifierKey, std::uint16_t keyCode, KeyboardCharData* charData) {
{
std::lock_guard lock(keyboardMutex);
if (!initialized) return KEYBOARD_ERROR_NOT_INITIALIZED;
if (handle != KEYBOARD_HANDLE || !opened) return KEYBOARD_ERROR_INVALID_HANDLE;
}
if (charData == nullptr) return KEYBOARD_ERROR_INVALID_ARG;
if (arrange != KEYBOARD_ARRANGEMENT_101 && arrange != KEYBOARD_ARRANGEMENT_106) return KEYBOARD_ERROR_INVALID_ARG;
if (arrange == KEYBOARD_ARRANGEMENT_106 && (ledState & KEYBOARD_LED_KANA) != 0) {
NotImplemented_nid_no_patch(__func__);
return KEYBOARD_ERROR_INVALID_ARG;
}
*charData = {};
charData->char_code = character(arrange == KEYBOARD_ARRANGEMENT_106, ledState, modifierKey, keyCode);
charData->processed = charData->char_code != 0;
charData->length = charData->processed ? 1 : 0;
return KEYBOARD_OK;
}
void Publish(const KeyboardInputEvent& event) {
std::lock_guard lock(keyboardMutex);
if (event.connectionChange) {
if (connected == event.connected) return;
connected = event.connected;
if (!connected) clearKeys();
} else if (!connected) {
return;
}
if (!opened) return;
if (event.resetKeys) clearKeys();
if (event.keyCode != 0) {
const bool ledChanged = led != event.led;
led = event.led;
if (!updateKey(event.keyCode, event.pressed) && !ledChanged) return;
}
enqueue(snapshot());
}
}