-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathbase.h
303 lines (254 loc) · 10.6 KB
/
base.h
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#ifndef BASE_H_
#define BASE_H_
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "configuration.h"
#include "layout.h"
#include "utils.h"
class GenericDevice {
public:
virtual void SetTag(uint8_t tag) { tag_ = tag; }
virtual uint8_t GetTag() { return tag_; }
// Called when the config has been updated.
virtual void OnUpdateConfig(const Config* config){};
// Override this if the device needs to behave differently when in and out of
// config mode. One example would be USB output devices, where during config
// mode it doesn't report any key code or mouse movement to the host.
virtual void SetConfigMode(bool is_config_mode){};
// Called during initialization to create the default config. Note that it'll
// be called even when there's a valid config json file in the filesystem. The
// default config specifies the structure of the config sub-tree to later
// parse the json file.
virtual std::pair<std::string, std::shared_ptr<Config>>
CreateDefaultConfig() {
return std::make_pair<std::string, std::shared_ptr<Config>>("", NULL);
}
protected:
uint8_t tag_;
};
class GenericOutputDevice : virtual public GenericDevice {
public:
virtual void SetSlow(bool slow) { slow_ = slow; }
virtual bool IsSlow() { return slow_; }
// OutputTick is called from a different task than the rest methods.
virtual void OutputTick() = 0;
virtual void StartOfInputTick() = 0;
virtual void FinalizeInputTickOutput() = 0;
protected:
bool slow_;
};
class KeyboardOutputDevice : virtual public GenericOutputDevice {
public:
virtual void SendKeycode(uint8_t keycode) = 0;
virtual void SendKeycode(const std::vector<uint8_t>& keycode) = 0;
virtual void SendConsumerKeycode(uint16_t keycode) = 0;
virtual void ChangeActiveLayers(const std::vector<bool>& layers) = 0;
};
class MouseOutputDevice : virtual public GenericOutputDevice {
public:
virtual void MouseKeycode(uint8_t keycode) = 0;
virtual void MouseMovement(int8_t x, int8_t y) = 0;
virtual void Pan(int8_t horizontal, int8_t vertical) = 0;
};
class Suspendable {
public:
virtual void SuspendEvent(bool is_suspend) = 0;
};
class ScreenOutputDevice : virtual public GenericOutputDevice,
virtual public Suspendable {
public:
enum Mode { ADD = 0, SUBTRACT, INVERT };
enum Font { F5X8 = 0, F8X8, F12X16, F16X32 };
class CustomFont {
public:
// Follows the format that the first two bytes are per character size
// (width x height)
virtual const uint8_t* GetFont() const = 0;
};
virtual size_t GetNumRows() const = 0;
virtual size_t GetNumCols() const = 0;
virtual bool IsConfigMode() const = 0;
// These functions allow you to draw directly from an input device. However,
// it's advised aginst so because one input device doesn't have a way of
// knowing what other input devices are drawing. It's better to create device
// mixins like the examples in display_mixins.h. Mixins are also more
// reusable.
virtual void SetPixel(size_t row, size_t col, Mode mode) = 0;
virtual void DrawLine(size_t start_row, size_t start_col, size_t end_row,
size_t end_col, Mode mode) = 0;
virtual void DrawRect(size_t start_row, size_t start_col, size_t end_row,
size_t end_col, bool fill, Mode mode) = 0;
virtual void DrawText(size_t row, size_t col, const std::string& text,
Font font, Mode mode) = 0;
virtual void DrawText(size_t row, size_t col, const std::string& text,
const CustomFont& font, Mode mode) = 0;
virtual void DrawBuffer(const std::vector<uint8_t>& buffer, size_t start_row,
size_t start_col, size_t end_row, size_t end_col) = 0;
virtual void Clear() = 0;
};
template <typename T>
class ScreenMixinBase : virtual public ScreenOutputDevice {
private:
// Just to make sure subclass implements the Register method.
static Status Unused(uint8_t key, bool slow, const std::shared_ptr<T> ptr) {
return T::Register(key, slow, ptr);
};
};
class LEDOutputDevice : virtual public GenericOutputDevice,
virtual public Suspendable {
public:
struct LEDIndicators {
bool num_lock : 1;
bool caps_lock : 1;
bool scroll_lock : 1;
bool compose : 1;
bool kana : 1;
LEDIndicators()
: num_lock(false),
caps_lock(false),
scroll_lock(false),
compose(false),
kana(false) {}
bool operator==(const LEDIndicators&) const = default;
};
virtual void IncreaseBrightness() = 0;
virtual void DecreaseBrightness() = 0;
virtual void IncreaseAnimationSpeed() = 0;
virtual void DecreaseAnimationSpeed() = 0;
virtual size_t NumPixels() const = 0;
virtual void SetFixedColor(uint8_t w, uint8_t r, uint8_t g, uint8_t b) = 0;
virtual void SetPixel(size_t idx, uint8_t w, uint8_t r, uint8_t g,
uint8_t b) = 0;
virtual void SetLedStatus(LEDIndicators indicators) = 0;
};
class MiscOutputDevice : virtual public GenericOutputDevice {
public:
virtual void Output(const std::string& output_string) = 0;
};
class ConfigModifier;
class GenericInputDevice : virtual public GenericDevice {
public:
// Everything is called from the same task, including methods in base class.
virtual void InputLoopStart() = 0;
virtual void InputTick() = 0;
virtual void SetKeyboardOutputs(
const std::vector<std::shared_ptr<KeyboardOutputDevice>>* devices);
virtual void SetMouseOutputs(
const std::vector<std::shared_ptr<MouseOutputDevice>>* device);
virtual void SetScreenOutputs(
const std::vector<std::shared_ptr<ScreenOutputDevice>>* device);
virtual void SetLEDOutputs(
const std::vector<std::shared_ptr<LEDOutputDevice>>* device);
virtual void SetMiscOutputs(
const std::vector<std::shared_ptr<MiscOutputDevice>>* device);
virtual void SetConfigModifier(
std::shared_ptr<ConfigModifier> config_modifier);
protected:
const std::vector<std::shared_ptr<KeyboardOutputDevice>>* keyboard_output_;
const std::vector<std::shared_ptr<MouseOutputDevice>>* mouse_output_;
const std::vector<std::shared_ptr<ScreenOutputDevice>>* screen_output_;
const std::vector<std::shared_ptr<LEDOutputDevice>>* led_output_;
const std::vector<std::shared_ptr<MiscOutputDevice>>* misc_output_;
std::shared_ptr<ConfigModifier> config_modifier_;
};
class ConfigModifier : virtual public GenericOutputDevice,
virtual public GenericInputDevice {
public:
virtual void Up() = 0;
virtual void Down() = 0;
virtual void Select() = 0;
void SetConfigModifier(
const std::shared_ptr<ConfigModifier> config_modifier) override final {}
// No config for config modifier
std::pair<std::string, std::shared_ptr<Config>> CreateDefaultConfig()
override final {
return GenericDevice::CreateDefaultConfig();
}
};
using GenericInputDeviceCreator =
std::function<std::shared_ptr<GenericInputDevice>()>;
using KeyboardOutputDeviceCreator =
std::function<std::shared_ptr<KeyboardOutputDevice>()>;
using MouseOutputDeviceCreator =
std::function<std::shared_ptr<MouseOutputDevice>()>;
using ScreenOutputDeviceCreator =
std::function<std::shared_ptr<ScreenOutputDevice>()>;
using LEDOutputDeviceCreator =
std::function<std::shared_ptr<LEDOutputDevice>()>;
using MiscOutputDeviceCreator =
std::function<std::shared_ptr<MiscOutputDevice>()>;
using ConfigModifierCreator =
std::function<std::shared_ptr<ConfigModifier>(ConfigObject* global_config)>;
class DeviceRegistry {
public:
static Status RegisterInputDevice(uint8_t key,
GenericInputDeviceCreator func);
static Status RegisterKeyboardOutputDevice(uint8_t key, bool slow,
KeyboardOutputDeviceCreator func);
static Status RegisterMouseOutputDevice(uint8_t key, bool slow,
MouseOutputDeviceCreator func);
static Status RegisterScreenOutputDevice(uint8_t key, bool slow,
ScreenOutputDeviceCreator func);
static Status RegisterLEDOutputDevice(uint8_t key, bool slow,
LEDOutputDeviceCreator func);
static Status RegisterMiscOutputDevice(uint8_t key, bool slow,
MiscOutputDeviceCreator func);
static Status RegisterConfigModifier(ConfigModifierCreator func);
static std::vector<std::shared_ptr<GenericInputDevice>> GetInputDevices();
static std::vector<std::shared_ptr<GenericOutputDevice>> GetOutputDevices(
bool is_slow);
static void UpdateConfig();
static void CreateDefaultConfig();
static void SaveConfig();
private:
DeviceRegistry() : initialized_(false) {}
void InitializeAllDevices();
void AddConfig(GenericDevice* device);
void UpdateConfigImpl();
void CreateDefaultConfigImpl();
static DeviceRegistry* GetRegistry();
std::map<uint8_t, std::pair<bool, GenericInputDeviceCreator>> input_creators_;
std::map<uint8_t, std::pair<bool, KeyboardOutputDeviceCreator>>
keyboard_creators_;
std::map<uint8_t, std::pair<bool, MouseOutputDeviceCreator>> mouse_creators_;
std::map<uint8_t, std::pair<bool, ScreenOutputDeviceCreator>>
screen_output_creators_;
std::map<uint8_t, std::pair<bool, LEDOutputDeviceCreator>>
led_output_creators_;
std::map<uint8_t, std::pair<bool, MiscOutputDeviceCreator>>
misc_output_creators_;
std::optional<ConfigModifierCreator> config_modifier_creator_;
bool initialized_;
std::vector<std::shared_ptr<GenericInputDevice>> input_devices_;
std::vector<std::shared_ptr<KeyboardOutputDevice>> keyboard_devices_;
std::vector<std::shared_ptr<MouseOutputDevice>> mouse_devices_;
std::vector<std::shared_ptr<ScreenOutputDevice>> screen_devices_;
std::vector<std::shared_ptr<LEDOutputDevice>> led_devices_;
std::vector<std::shared_ptr<MiscOutputDevice>> misc_devices_;
std::shared_ptr<ConfigModifier> config_modifier_;
ConfigObject global_config_;
std::map<GenericDevice*, std::pair<std::string, Config*>> device_to_config_;
};
class IBPDriverBase {
public:
virtual Status IBPInitialize() = 0;
};
using IBPDriverCreator = std::function<std::shared_ptr<IBPDriverBase>()>;
// IBP stands for Inter Board Protocol.
class IBPDriverRegistry {
public:
static Status RegisterDriver(uint8_t key, IBPDriverCreator func);
static Status InitializeAll();
private:
IBPDriverRegistry() : initialized_(false) {}
static IBPDriverRegistry* GetRegistry();
bool initialized_;
std::map<uint8_t, IBPDriverCreator> driver_creators_;
std::map<uint8_t, std::shared_ptr<IBPDriverBase>> drivers_;
};
#endif /* BASE_H_ */