forked from tmackay/g13
-
Notifications
You must be signed in to change notification settings - Fork 0
/
g13_manager.cpp
289 lines (247 loc) · 8.01 KB
/
g13_manager.cpp
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
//
// Created by khampf on 13-05-2020.
//
#include "g13_manager.hpp"
#include "g13_device.hpp"
#include "g13_keys.hpp"
#include "helper.hpp"
#include <csignal>
#include <libevdev-1.0/libevdev/libevdev.h>
#include <log4cpp/OstreamAppender.hh>
#include <memory>
#include <chrono>
#include <thread>
namespace G13 {
// definitions
bool G13_Manager::running = true;
std::map<std::string, std::string> G13_Manager::stringConfigValues;
libusb_context *G13_Manager::libusbContext;
std::vector<G13::G13_Device *> G13_Manager::g13s;
libusb_hotplug_callback_handle G13_Manager::hotplug_cb_handle[3];
const int G13_Manager::class_id = LIBUSB_HOTPLUG_MATCH_ANY;
std::map<G13_KEY_INDEX, std::string> G13_Manager::g13_key_to_name;
std::map<std::string, G13_KEY_INDEX> G13_Manager::g13_name_to_key;
std::map<LINUX_KEY_VALUE, std::string> G13_Manager::input_key_to_name;
std::map<std::string, LINUX_KEY_VALUE> G13_Manager::input_name_to_key;
libusb_device **G13_Manager::devs;
std::string G13_Manager::logoFilename;
G13_Manager::G13_Manager() /* : libusbContext(nullptr), devs(nullptr)*/ {
InitKeynames();
}
void G13_Manager::Cleanup() {
G13_OUT("Cleaning up");
for (auto handle : hotplug_cb_handle) {
libusb_hotplug_deregister_callback(libusbContext, handle);
}
// TODO: This might be better with an iterator and also g13s.erase(iter)
for (auto g13 : g13s) {
// g13->Cleanup();
delete g13;
}
libusb_exit(libusbContext);
}
void G13_Manager::InitKeynames() {
int key_index = 0;
// setup maps to let us convert between strings and G13 key names
for (auto &name : G13::G13_KEY_STRINGS) {
g13_key_to_name[key_index] = name;
g13_name_to_key[name] = key_index;
G13_DBG("mapping G13 " << name << " = " << key_index);
key_index++;
}
// setup maps to let us convert between strings and linux key names
for (auto &symbol : G13::G13_SYMBOLS) {
auto keyname = std::string("KEY_" + std::string(symbol));
int code = libevdev_event_code_from_name(EV_KEY, keyname.c_str());
if (code < 0) {
G13_ERR("No input event code found for " << keyname);
} else {
// TODO: this seems to map ok but the result is off
// assert(keyname.compare(libevdev_event_code_get_name(EV_KEY,code)) ==
// 0); linux/input-event-codes.h
input_key_to_name[code] = symbol;
input_name_to_key[symbol] = code;
G13_DBG("mapping " << symbol << " " << keyname << "=" << code);
}
}
// setup maps to let us convert between strings and linux button names
for (auto &symbol : G13::G13_BTN_SEQ) {
auto name = std::string("M" + std::string(symbol));
auto keyname = std::string("BTN_" + std::string(symbol));
int code = libevdev_event_code_from_name(EV_KEY, keyname.c_str());
if (code < 0) {
G13_ERR("No input event code found for " << keyname);
} else {
input_key_to_name[code] = name;
input_name_to_key[name] = code;
G13_DBG("mapping " << name << " " << keyname << "=" << code);
}
}
}
void G13_Manager::SignalHandler(int signal) {
G13_OUT("Caught signal " << signal << " (" << strsignal(signal) << ")");
running = false;
// TODO: Should we break usblib handling with a reset?
}
std::string G13_Manager::getStringConfigValue(const std::string &name) {
try {
return Helper::find_or_throw(stringConfigValues, name);
} catch (...) {
return "";
}
}
void G13_Manager::setStringConfigValue(const std::string &name,
const std::string &value) {
G13_DBG("setStringConfigValue " << name << " = " << Helper::repr(value));
stringConfigValues[name] = value;
}
std::string G13_Manager::MakePipeName(G13::G13_Device *d, bool is_input) {
if (is_input) {
std::string config_base = getStringConfigValue("pipe_in");
if (!config_base.empty()) {
if (d->id_within_manager() == 0) {
return config_base;
} else {
return config_base + "-" + std::to_string(d->id_within_manager());
}
}
return CONTROL_DIR + "g13-" + std::to_string(d->id_within_manager());
} else {
std::string config_base = getStringConfigValue("pipe_out");
if (!config_base.empty()) {
if (d->id_within_manager() == 0) {
return config_base;
} else {
return config_base + "-" + std::to_string(d->id_within_manager());
}
}
return CONTROL_DIR + "g13-" + std::to_string(d->id_within_manager()) +
"_out";
}
}
G13::LINUX_KEY_VALUE G13_Manager::FindG13KeyValue(const std::string &keyname) {
auto i = g13_name_to_key.find(keyname);
if (i == g13_name_to_key.end()) {
return G13::BAD_KEY_VALUE;
}
return i->second;
}
G13::LINUX_KEY_VALUE
G13_Manager::FindInputKeyValue(const std::string &keyname) {
// if there is a KEY_ prefix, strip it off
if (!strncmp(keyname.c_str(), "KEY_", 4)) {
return FindInputKeyValue(keyname.c_str() + 4);
}
auto i = input_name_to_key.find(keyname);
if (i == input_name_to_key.end()) {
return G13::BAD_KEY_VALUE;
}
return i->second;
}
std::string G13_Manager::FindInputKeyName(G13::LINUX_KEY_VALUE v) {
try {
return Helper::find_or_throw(input_key_to_name, v);
} catch (...) {
return "(unknown linux key)";
}
}
std::string G13_Manager::FindG13KeyName(G13::G13_KEY_INDEX v) {
try {
return Helper::find_or_throw(g13_key_to_name, v);
} catch (...) {
return "(unknown G13 key)";
}
}
void G13_Manager::DisplayKeys() {
typedef std::map<std::string, int> mapType;
G13_OUT("Known keys on G13:");
G13_OUT(Helper::map_keys_out(g13_name_to_key));
G13_OUT("Known keys to map to:");
G13_OUT(Helper::map_keys_out(input_name_to_key));
}
int G13_Manager::Run() {
DisplayKeys();
ssize_t cnt;
int error;
error = libusb_init(&libusbContext);
if (error != LIBUSB_SUCCESS) {
G13_ERR("libusb initialization error: "
<< G13_Device::DescribeLibusbErrorCode(error));
Cleanup();
return EXIT_FAILURE;
}
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, 3);
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
cnt = libusb_get_device_list(libusbContext, &devs);
if (cnt < 0) {
G13_ERR("Error while getting device list");
Cleanup();
return EXIT_FAILURE;
}
DiscoverG13s(devs, cnt);
libusb_free_device_list(devs, 1);
G13_OUT("Found " << g13s.size() << " G13s");
if (g13s.empty()) {
G13_ERR("Unable to open any device");
Cleanup();
return EXIT_FAILURE;
}
} else {
ArmHotplugCallbacks();
}
signal(SIGINT, SignalHandler);
signal(SIGTERM, SignalHandler);
for (auto g13 : g13s) {
// This can not be done from the event handler (will give LIBUSB_ERROR_BUSY)
SetupDevice(g13);
}
do {
if (g13s.empty()) {
G13_OUT("Waiting for device to show up ...");
error = libusb_handle_events(libusbContext);
G13_DBG("USB Event wakeup with " << g13s.size() << " devices registered");
if (error != LIBUSB_SUCCESS) {
G13_ERR("Error: " << G13_Device::DescribeLibusbErrorCode(error));
} else {
for (auto g13 : g13s) {
// This can not be done from the event handler (will give
// LIBUSB_ERROR_BUSY)
SetupDevice(g13);
}
}
}
// Main loop
for (auto g13 : g13s) {
int status = g13->ReadKeypresses();
if (!g13s.empty()) {
// Cleanup might have removed the object before this loop has run
// TODO: This will not work with multiplt devices and can be better
g13->ReadCommandsFromPipe();
};
if (status < 0) {
running = false;
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} while (running);
Cleanup();
G13_OUT("Exit");
return EXIT_SUCCESS;
}
/*
libusb_context *G13_Manager::getCtx() {
return libusbContext;
}
void G13_Manager::setCtx(libusb_context *newLibusbContext) {
libusbContext = newLibusbContext;
}
*/
/*
const std::string &G13_Manager::getLogoFilename() {
return logoFilename;
}
*/
void G13_Manager::setLogoFilename(const std::string &newLogoFilename) {
logoFilename = newLogoFilename;
}
} // namespace G13