g13d: Kill off the old daemon

We no longer need this -- g13gui.g13 does everything and more.
This commit is contained in:
June Tate-Gans 2021-05-02 16:23:37 -05:00
parent 8ebe1e2fc2
commit f4daed3148
28 changed files with 0 additions and 3210 deletions

View File

@ -1,39 +0,0 @@
cmake_minimum_required(VERSION 3.16.3)
project(g13d LANGUAGES CXX VERSION "0.1.0")
configure_file("config.h.in" "config.h")
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror")
add_executable(pbm2lpbm pbm2lpbm.cc)
add_executable(g13d
action.cc
device.cc
font.cc
profile.cc
lcd.cc
main.cc
stick.cc
manager.cc
repr.cc
)
target_compile_definitions(g13d PRIVATE BOOST_LOG_DYN_LINK=1)
find_package(PkgConfig)
pkg_check_modules(libusb-1.0 REQUIRED libusb-1.0)
find_package(Boost REQUIRED COMPONENTS system log program_options)
target_link_libraries(g13d
${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}
${libusb-1.0_LIBRARIES})
install(TARGETS g13d pbm2lpbm RUNTIME)
install(CODE "
execute_process(COMMAND install -d -m 0660 -o root -g input /run/g13d)
message(STATUS \"Install: /run/g13d\")
")

View File

@ -1,97 +0,0 @@
#include "action.h"
#include <boost/range/adaptor/reversed.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include "manager.h"
#include "repr.h"
namespace G13 {
Action::~Action() {
}
Action_Keys::Action_Keys(Device &keypad,
const std::string &keys_string)
: Action(keypad) {
std::vector<std::string> keys;
boost::split(keys, keys_string, boost::is_any_of("+"));
BOOST_FOREACH (std::string const &key, keys) {
auto kval = manager().find_input_key_value(key);
if (kval == BAD_KEY_VALUE) {
throw CommandException("create action unknown key : " + key);
}
_keys.push_back(kval);
}
std::vector<int> _keys;
}
Action_Keys::~Action_Keys() {
}
void Action_Keys::act(Device &g13, bool is_down) {
if (is_down) {
for (auto key : _keys) {
g13.send_event(EV_KEY, key, is_down);
G13_LOG(trace, "sending KEY DOWN " << key);
}
} else {
for (auto key : boost::adaptors::reverse(_keys)) {
g13.send_event(EV_KEY, key, is_down);
G13_LOG(trace, "sending KEY UP " << key);
}
}
}
void Action_Keys::dump(std::ostream &out) const {
out << " SEND KEYS: ";
for (size_t i = 0; i < _keys.size(); i++) {
if (i) out << " + ";
out << manager().find_input_key_name(_keys[i]);
}
}
Action_PipeOut::Action_PipeOut(Device &keypad,
const std::string &out)
: Action(keypad),
_out(out + "\n") {
}
Action_PipeOut::~Action_PipeOut() {
}
void Action_PipeOut::act(Device &kp, bool is_down) {
if (is_down) {
kp.write_output_pipe(_out);
}
}
void Action_PipeOut::dump(std::ostream &o) const {
o << "WRITE PIPE : " << repr(_out);
}
Action_Command::Action_Command(Device &keypad,
const std::string &cmd)
: Action(keypad),
_cmd(cmd) {
}
Action_Command::~Action_Command() {
}
void Action_Command::act(Device &kp, bool is_down) {
if (is_down) {
keypad().command(_cmd.c_str());
}
}
void Action_Command::dump(std::ostream &o) const {
o << "COMMAND : " << repr(_cmd);
}
} // namespace G13

View File

@ -1,139 +0,0 @@
#ifndef ACTION_H
#define ACTION_H
#include <memory>
#include <ostream>
#include <vector>
#include "g13.h"
namespace G13 {
class Device;
class Manager;
/*! holds potential actions which can be bound to G13 activity
*
*/
class Action {
public:
Action(Device &keypad) : _keypad(keypad) {
}
virtual ~Action();
virtual void act(Device &, bool is_down) = 0;
virtual void dump(std::ostream &) const = 0;
void act(bool is_down) {
act(keypad(), is_down);
}
Device &keypad() {
return _keypad;
}
const Device &keypad() const {
return _keypad;
}
Manager &manager();
const Manager &manager() const;
private:
Device &_keypad;
};
/*!
* action to send one or more keystrokes
*/
class Action_Keys : public Action {
public:
Action_Keys(Device &keypad, const std::string &keys);
virtual ~Action_Keys();
virtual void act(Device &, bool is_down);
virtual void dump(std::ostream &) const;
std::vector<linux_keyvalue> _keys;
};
/*!
* action to send a string to the output pipe
*/
class Action_PipeOut : public Action {
public:
Action_PipeOut(Device &keypad, const std::string &out);
virtual ~Action_PipeOut();
virtual void act(Device &, bool is_down);
virtual void dump(std::ostream &) const;
std::string _out;
};
/*!
* action to send a command to the g13
*/
class Action_Command : public Action {
public:
Action_Command(Device &keypad, const std::string &cmd);
virtual ~Action_Command();
virtual void act(Device &, bool is_down);
virtual void dump(std::ostream &) const;
std::string _cmd;
};
typedef std::shared_ptr<Action> ActionPtr;
template <class PARENT_T>
class Actionable {
public:
Actionable(PARENT_T &parent_arg, const std::string &name)
: _name(name),
_parent_ptr(&parent_arg) {
}
virtual ~Actionable() {
_parent_ptr = 0;
}
ActionPtr action() const {
return _action;
}
const std::string &name() const {
return _name;
}
PARENT_T &parent() {
return *_parent_ptr;
}
const PARENT_T &parent() const {
return *_parent_ptr;
}
Manager &manager() {
return _parent_ptr->manager();
}
const Manager &manager() const {
return _parent_ptr->manager();
}
virtual void clear_action() {
_action.reset();
}
virtual void set_action(const ActionPtr &action) {
_action = action;
}
protected:
std::string _name;
ActionPtr _action;
private:
PARENT_T *_parent_ptr;
};
} // namespace G13
#endif // ACTION_H

View File

@ -1,44 +0,0 @@
#ifndef BOUNDS_H
#define BOUNDS_H
#include <ostream>
#include "coord.h"
namespace G13 {
template <class T>
class Bounds {
public:
Bounds(const Coord<T> &_tl, const Coord<T> &_br) : tl(_tl), br(_br) {
}
Bounds(T x1, T y1, T x2, T y2) : tl(x1, y1), br(x2, y2) {
}
bool contains(const Coord<T> &pos) const {
return tl.x <= pos.x && tl.y <= pos.y && pos.x <= br.x && pos.y <= br.y;
}
void expand(const Coord<T> &pos) {
if (pos.x < tl.x) tl.x = pos.x;
if (pos.y < tl.y) tl.y = pos.y;
if (pos.x > br.x) br.x = pos.x;
if (pos.y > br.y) br.y = pos.y;
}
Coord<T> tl;
Coord<T> br;
};
template <class T>
std::ostream &operator<<(std::ostream &o, const Bounds<T> &b) {
o << "{ " << b.tl.x << " x " << b.tl.y << " / " << b.br.x << " x " << b.br.y
<< " }";
return o;
};
} // namespace G13
#endif // BOUNDS_H

View File

@ -1,10 +0,0 @@
#ifndef CONFIG_H
#define CONFIG_H
#define PROJECT_NAME "@PROJECT_NAME@"
#define PROJECT_VER "@PROJECT_VERSION@"
#define PROJECT_VER_MAJOR "@PROJECT_VERSION_MAJOR@"
#define PROJECT_VER_MINOR "@PROJECT_VERSION_MINOR@"
#define PROJECT_VER_PATCH "@PROJECT_VERSION_PATCH@"
#endif // CONFIG_H

View File

@ -1,27 +0,0 @@
#ifndef COORD_H
#define COORD_H
namespace G13 {
template <class T>
class Coord {
public:
Coord() : x(), y() {
}
Coord(T _x, T _y) : x(_x), y(_y) {
}
T x;
T y;
};
template <class T>
std::ostream &operator<<(std::ostream &o, const Coord<T> &c) {
o << "{ " << c.x << " x " << c.y << " }";
return o;
};
} // namespace G13
#endif // COORD_H

View File

@ -1,625 +0,0 @@
#include "device.h"
#include <fcntl.h>
#include <libusb-1.0/libusb.h>
#include <linux/uinput.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include "logo.h"
#include "manager.h"
#include "repr.h"
namespace G13 {
static std::string describe_libusb_error_code(int code) {
#define TEST_libusb_error(r, data, elem) \
case BOOST_PP_CAT(LIBUSB_, elem): \
return BOOST_PP_STRINGIZE(elem);
switch (code) {
BOOST_PP_SEQ_FOR_EACH(
TEST_libusb_error, _,
(SUCCESS)(ERROR_IO)(ERROR_INVALID_PARAM)(ERROR_ACCESS)(ERROR_NO_DEVICE)(
ERROR_NOT_FOUND)(ERROR_BUSY)(ERROR_TIMEOUT)(ERROR_OVERFLOW)(
ERROR_PIPE)(ERROR_INTERRUPTED)(ERROR_NO_MEM)(ERROR_NOT_SUPPORTED)(
ERROR_OTHER))
}
return "unknown error";
}
int g13_create_fifo(const char *fifo_name) {
mkfifo(fifo_name, 0666);
chmod(fifo_name, 0660);
return open(fifo_name, O_RDWR | O_NONBLOCK);
}
int g13_create_uinput(void) {
struct uinput_user_dev uinp;
const char *dev_uinput_fname =
access("/dev/input/uinput", F_OK) == 0
? "/dev/input/uinput"
: access("/dev/uinput", F_OK) == 0 ? "/dev/uinput" : 0;
if (!dev_uinput_fname) {
G13_LOG(error, "Could not find an uinput device");
return -1;
}
if (access(dev_uinput_fname, W_OK) != 0) {
G13_LOG(error, dev_uinput_fname << " doesn't grant write permissions");
return -1;
}
int ufile = open(dev_uinput_fname, O_WRONLY | O_NDELAY);
if (ufile <= 0) {
G13_LOG(error, "Could not open uinput");
return -1;
}
memset(&uinp, 0, sizeof(uinp));
char name[] = "G13";
strncpy(uinp.name, name, sizeof(uinp.name));
uinp.id.version = 1;
uinp.id.bustype = BUS_USB;
uinp.id.product = G13_PRODUCT_ID;
uinp.id.vendor = G13_VENDOR_ID;
uinp.absmin[ABS_X] = 0;
uinp.absmin[ABS_Y] = 0;
uinp.absmax[ABS_X] = 0xff;
uinp.absmax[ABS_Y] = 0xff;
// uinp.absfuzz[ABS_X] = 4;
// uinp.absfuzz[ABS_Y] = 4;
// uinp.absflat[ABS_X] = 0x80;
// uinp.absflat[ABS_Y] = 0x80;
ioctl(ufile, UI_SET_EVBIT, EV_KEY);
ioctl(ufile, UI_SET_EVBIT, EV_ABS);
/* ioctl(ufile, UI_SET_EVBIT, EV_REL);*/
ioctl(ufile, UI_SET_MSCBIT, MSC_SCAN);
ioctl(ufile, UI_SET_ABSBIT, ABS_X);
ioctl(ufile, UI_SET_ABSBIT, ABS_Y);
/* ioctl(ufile, UI_SET_RELBIT, REL_X);
ioctl(ufile, UI_SET_RELBIT, REL_Y);*/
for (int i = 0; i < 256; i++)
ioctl(ufile, UI_SET_KEYBIT, i);
ioctl(ufile, UI_SET_KEYBIT, BTN_THUMB);
int retcode = write(ufile, &uinp, sizeof(uinp));
if (retcode < 0) {
G13_LOG(error, "Could not write to uinput device (" << retcode << ")");
return -1;
}
retcode = ioctl(ufile, UI_DEV_CREATE);
if (retcode) {
G13_LOG(error, "Error creating uinput device for G13");
return -1;
}
return ufile;
}
void Device::send_event(int type, int code, int val) {
memset(&_event, 0, sizeof(_event));
gettimeofday(&_event.time, 0);
_event.type = type;
_event.code = code;
_event.value = val;
// TODO(jtgans): Make this actually verify it writes all bytes
auto result = write(_uinput_fid, &_event, sizeof(_event));
if (result < 0) {
G13_LOG(error, "Unable to send event: " << strerror(errno));
exit(1);
}
}
void Device::write_output_pipe(const std::string &out) {
// TODO(jtgans): Make this actually verify it writes all bytes
auto result = write(_output_pipe_fid, out.c_str(), out.size());
if (result < 0) {
G13_LOG(error, "Unable to write to output pipe: " << strerror(errno));
exit(1);
}
}
void Device::set_mode_leds(int leds) {
unsigned char usb_data[] = {5, 0, 0, 0, 0};
usb_data[1] = leds;
int r = libusb_control_transfer(
handle, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, 9, 0x305,
0, usb_data, 5, 1000);
if (r != 5) {
G13_LOG(error, "Problem sending data");
return;
}
}
void Device::set_key_color(int red, int green, int blue) {
int error;
unsigned char usb_data[] = {5, 0, 0, 0, 0};
usb_data[1] = red;
usb_data[2] = green;
usb_data[3] = blue;
error = libusb_control_transfer(
handle, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, 9, 0x307,
0, usb_data, 5, 1000);
if (error != 5) {
G13_LOG(error, "Problem sending data");
return;
}
}
void Device::register_context(libusb_context *_ctx) {
ctx = _ctx;
int leds = 0;
int red = 0;
int green = 0;
int blue = 255;
init_lcd();
set_mode_leds(leds);
set_key_color(red, green, blue);
write_lcd(g13_logo, sizeof(g13_logo));
_uinput_fid = g13_create_uinput();
_input_pipe_name = _manager.make_pipe_name(this, true);
_input_pipe_fid = g13_create_fifo(_input_pipe_name.c_str());
_output_pipe_name = _manager.make_pipe_name(this, false);
_output_pipe_fid = g13_create_fifo(_output_pipe_name.c_str());
if (_input_pipe_fid == -1) {
G13_LOG(error, "failed opening pipe");
}
}
void Device::cleanup() {
remove(_input_pipe_name.c_str());
remove(_output_pipe_name.c_str());
ioctl(_uinput_fid, UI_DEV_DESTROY);
close(_uinput_fid);
libusb_release_interface(handle, 0);
libusb_close(handle);
}
/*! reads and processes key state report from G13
*
*/
int Device::read_keys() {
unsigned char buffer[G13_REPORT_SIZE];
int size;
int error =
libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_IN | G13_KEY_ENDPOINT,
buffer, G13_REPORT_SIZE, &size, 100);
if (error && error != LIBUSB_ERROR_TIMEOUT) {
G13_LOG(error, "Error while reading keys: "
<< error << " (" << describe_libusb_error_code(error)
<< ")");
// G13_LOG( error, "Stopping daemon" );
// return -1;
}
if (size == G13_REPORT_SIZE) {
parse_joystick(buffer);
_current_profile->parse_keys(buffer);
send_event(EV_SYN, SYN_REPORT, 0);
}
return 0;
}
void Device::read_config_file(const std::string &filename) {
std::ifstream s(filename);
G13_LOG(info, "reading configuration from " << filename);
while (s.good()) {
// grab a line
char buf[1024];
buf[0] = 0;
buf[sizeof(buf) - 1] = 0;
s.getline(buf, sizeof(buf) - 1);
// strip comment
char *comment = strchr(buf, '#');
if (comment) {
comment--;
while (comment > buf && isspace(*comment))
comment--;
*comment = 0;
}
// send it
if (buf[0]) {
G13_LOG(info, " cfg: " << buf);
command(buf);
}
}
}
void Device::read_commands() {
fd_set set;
FD_ZERO(&set);
FD_SET(_input_pipe_fid, &set);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int ret = select(_input_pipe_fid + 1, &set, 0, 0, &tv);
if (ret > 0) {
unsigned char buf[1024 * 1024];
memset(buf, 0, 1024 * 1024);
ret = read(_input_pipe_fid, buf, 1024 * 1024);
G13_LOG(trace, "read " << ret << " characters");
if (ret ==
960) { // TODO probably image, for now, don't test, just assume image
lcd().image(buf, ret);
} else {
std::string buffer = reinterpret_cast<const char *>(buf);
std::vector<std::string> lines;
boost::split(lines, buffer, boost::is_any_of("\n\r"));
BOOST_FOREACH (std::string const &cmd, lines) {
std::vector<std::string> command_comment;
boost::split(command_comment, cmd, boost::is_any_of("#"));
if (command_comment.size() > 0 &&
command_comment[0] != std::string("")) {
G13_LOG(info, "command: " << command_comment[0]);
command(command_comment[0].c_str());
}
}
}
}
}
Device::Device(Manager &manager, libusb_device_handle *handle,
int _id)
: _id_within_manager(_id),
handle(handle),
ctx(0),
_uinput_fid(-1),
_manager(manager),
_lcd(*this),
_stick(*this) {
_current_profile = ProfilePtr(new Profile(*this, "default"));
_profiles["default"] = _current_profile;
for (unsigned int i = 0; i < sizeof(keys); i++) {
keys[i] = false;
}
lcd().image_clear();
_init_fonts();
_init_commands();
}
FontPtr Device::switch_to_font(const std::string &name) {
FontPtr rv = _fonts[name];
if (rv) {
_current_font = rv;
}
return rv;
}
void Device::switch_to_profile(const std::string &name) {
_current_profile = profile(name);
}
ProfilePtr Device::profile(const std::string &name) {
ProfilePtr rv = _profiles[name];
if (!rv) {
rv = ProfilePtr(new Profile(*_current_profile, name));
_profiles[name] = rv;
}
return rv;
}
ActionPtr Device::make_action(const std::string &action) {
if (!action.size()) {
throw CommandException("empty action string");
}
if (action[0] == '>') {
return ActionPtr(new Action_PipeOut(*this, &action[1]));
} else if (action[0] == '!') {
return ActionPtr(new Action_Command(*this, &action[1]));
} else {
return ActionPtr(new Action_Keys(*this, action));
}
throw CommandException("can't create action for " + action);
}
void Device::dump(std::ostream &o, int detail) {
o << "G13 id=" << id_within_manager() << std::endl
<< " input_pipe_name=" << repr(_input_pipe_name) << std::endl
<< " output_pipe_name=" << repr(_output_pipe_name) << std::endl
<< " current_profile=" << _current_profile->name() << std::endl
<< " current_font=" << _current_font->name() << std::endl;
if (detail > 0) {
o << "STICK" << std::endl;
stick().dump(o);
if (detail == 1) {
_current_profile->dump(o);
} else {
for (auto i = _profiles.begin(); i != _profiles.end(); i++) {
i->second->dump(o);
}
}
}
}
inline const char *advance_ws(const char *&source, std::string &dest) {
const char *space = source ? strchr(source, ' ') : 0;
if (space) {
dest = std::string(source, space - source);
source = space + 1;
} else {
dest = source;
source = 0;
}
return source;
};
struct command_adder {
command_adder(Device::CommandFunctionTable &t, const char *name)
: _t(t),
_name(name) {
}
Device::CommandFunctionTable &_t;
std::string _name;
command_adder &operator+=(Device::COMMAND_FUNCTION f) {
_t[_name] = f;
return *this;
};
};
#define RETURN_FAIL(message) \
{ \
G13_LOG(error, message); \
return; \
}
#define G13_DEVICE_COMMAND(name) \
; \
command_adder BOOST_PP_CAT(add_, name)(_command_table, \
BOOST_PP_STRINGIZE(name)); \
BOOST_PP_CAT(add_, name) += [this](const char *remainder)
void Device::_init_commands() {
G13_DEVICE_COMMAND(out) {
lcd().write_string(remainder);
}
G13_DEVICE_COMMAND(pos) {
int row, col;
if (sscanf(remainder, "%i %i", &row, &col) == 2) {
lcd().write_pos(row, col);
} else {
RETURN_FAIL("bad pos : " << remainder);
}
}
G13_DEVICE_COMMAND(bind) {
std::string keyname;
advance_ws(remainder, keyname);
std::string action = remainder;
try {
if (auto key = _current_profile->find_key(keyname)) {
key->set_action(make_action(action));
} else if (auto stick_key = _stick.zone(keyname)) {
stick_key->set_action(make_action(action));
} else {
RETURN_FAIL("bind key " << keyname << " unknown");
}
G13_LOG(trace, "bind " << keyname << " [" << action << "]");
} catch (const std::exception &ex) {
RETURN_FAIL("bind " << keyname << " " << action
<< " failed : " << ex.what());
}
}
G13_DEVICE_COMMAND(unbind) {
std::string keyname = remainder;
try {
if (auto key = _current_profile->find_key(keyname)) {
key->clear_action();
} else if (auto stick_key = _stick.zone(keyname)) {
stick_key->clear_action();
} else {
RETURN_FAIL("unbind key " << keyname << " unknown");
}
G13_LOG(trace, "unbind " << keyname);
} catch (const std::exception &ex) {
RETURN_FAIL("unbind " << keyname
<< " failed : " << ex.what())
}
}
G13_DEVICE_COMMAND(profile) {
switch_to_profile(remainder);
}
G13_DEVICE_COMMAND(font) {
switch_to_font(remainder);
}
G13_DEVICE_COMMAND(mod) {
set_mode_leds(atoi(remainder));
}
G13_DEVICE_COMMAND(textmode) {
lcd().text_mode = atoi(remainder);
}
G13_DEVICE_COMMAND(rgb) {
int red, green, blue;
if (sscanf(remainder, "%i %i %i", &red, &green, &blue) == 3) {
set_key_color(red, green, blue);
} else {
RETURN_FAIL("rgb bad format: <" << remainder << ">");
}
}
#define STICKMODE_TEST(r, data, elem) \
if (mode == BOOST_PP_STRINGIZE(elem)) { \
_stick.set_mode(BOOST_PP_CAT(STICK_, elem)); \
return; \
} else
G13_DEVICE_COMMAND(stickmode) {
std::string mode = remainder;
BOOST_PP_SEQ_FOR_EACH(
STICKMODE_TEST, _,
(ABSOLUTE)(RELATIVE)(KEYS)(CALCENTER)(CALBOUNDS)(CALNORTH)) {
RETURN_FAIL("unknown stick mode : <" << mode << ">");
}
}
G13_DEVICE_COMMAND(stickzone) {
std::string operation, zonename;
advance_ws(remainder, operation);
advance_ws(remainder, zonename);
if (operation == "add") {
_stick.zone(zonename, true);
} else {
StickZone *zone = _stick.zone(zonename);
if (!zone) {
throw CommandException("unknown stick zone");
}
if (operation == "action") {
zone->set_action(make_action(remainder));
} else if (operation == "bounds") {
double x1, y1, x2, y2;
if (sscanf(remainder, "%lf %lf %lf %lf", &x1, &y1, &x2, &y2) != 4) {
throw CommandException("bad bounds format");
}
zone->set_bounds(ZoneBounds(x1, y1, x2, y2));
} else if (operation == "del") {
_stick.remove_zone(*zone);
} else {
RETURN_FAIL("unknown stickzone operation: <" << operation << ">");
}
}
}
G13_DEVICE_COMMAND(dump) {
std::string target;
advance_ws(remainder, target);
if (target == "all") {
dump(std::cout, 3);
} else if (target == "current") {
dump(std::cout, 1);
} else if (target == "summary") {
dump(std::cout, 0);
} else {
RETURN_FAIL("unknown dump target: <" << target << ">");
}
}
G13_DEVICE_COMMAND(log_level) {
std::string level;
advance_ws(remainder, level);
manager().set_log_level(level);
}
G13_DEVICE_COMMAND(refresh) {
lcd().image_send();
}
G13_DEVICE_COMMAND(clear) {
lcd().image_clear();
lcd().image_send();
};
}
void Device::command(char const *str) {
const char *remainder = str;
try {
std::string cmd;
advance_ws(remainder, cmd);
auto i = _command_table.find(cmd);
if (i == _command_table.end()) {
RETURN_FAIL("unknown command : " << cmd)
}
COMMAND_FUNCTION f = i->second;
f(remainder);
return;
} catch (const std::exception &ex) {
RETURN_FAIL("command failed : " << ex.what());
}
}
void Device::init_lcd() {
int error = libusb_control_transfer(handle, 0, 9, 1, 0, 0, 0, 1000);
if (error) {
G13_LOG(error, "Error when initializing lcd endpoint");
}
}
void Device::write_lcd(unsigned char *data, size_t size) {
init_lcd();
if (size != G13_LCD_BUFFER_SIZE) {
G13_LOG(error, "Invalid LCD data size " << size << ", should be "
<< G13_LCD_BUFFER_SIZE);
return;
}
unsigned char buffer[G13_LCD_BUFFER_SIZE + 32];
memset(buffer, 0, G13_LCD_BUFFER_SIZE + 32);
buffer[0] = 0x03;
memcpy(buffer + 32, data, G13_LCD_BUFFER_SIZE);
int bytes_written;
int error = libusb_interrupt_transfer(
handle, LIBUSB_ENDPOINT_OUT | G13_LCD_ENDPOINT, buffer,
G13_LCD_BUFFER_SIZE + 32, &bytes_written, 1000);
if (error)
G13_LOG(error, "Error when transferring image: "
<< error << ", " << bytes_written << " bytes written");
}
void Device::write_lcd_file(const std::string &filename) {
std::filebuf *pbuf;
std::ifstream filestr;
size_t size;
filestr.open(filename.c_str());
pbuf = filestr.rdbuf();
size = pbuf->pubseekoff(0, std::ios::end, std::ios::in);
pbuf->pubseekpos(0, std::ios::in);
char buffer[size];
pbuf->sgetn(buffer, size);
filestr.close();
write_lcd((unsigned char *)buffer, size);
}
void Device::parse_joystick(unsigned char *buf) {
_stick.parse_joystick(buf);
}
} // namespace G13

View File

@ -1,135 +0,0 @@
#ifndef DEVICE_H
#define DEVICE_H
#include <libusb-1.0/libusb.h>
#include <linux/input.h>
#include <map>
#include <ostream>
#include <string>
#include "font.h"
#include "lcd.h"
#include "profile.h"
#include "stick.h"
namespace G13 {
class Manager;
class Device {
public:
Device(Manager &manager, libusb_device_handle *handle, int id);
Manager &manager() {
return _manager;
}
const Manager &manager() const {
return _manager;
}
G13_LCD &lcd() {
return _lcd;
}
const G13_LCD &lcd() const {
return _lcd;
}
Stick &stick() {
return _stick;
}
const Stick &stick() const {
return _stick;
}
FontPtr switch_to_font(const std::string &name);
void switch_to_profile(const std::string &name);
ProfilePtr profile(const std::string &name);
void dump(std::ostream &, int detail = 0);
void command(char const *str);
void read_commands();
void read_config_file(const std::string &filename);
int read_keys();
void parse_joystick(unsigned char *buf);
ActionPtr make_action(const std::string &);
void set_key_color(int red, int green, int blue);
void set_mode_leds(int leds);
void send_event(int type, int code, int val);
void write_output_pipe(const std::string &out);
void write_lcd(unsigned char *data, size_t size);
bool is_set(int key);
bool update(int key, bool v);
// used by Manager
void cleanup();
void register_context(libusb_context *ctx);
void write_lcd_file(const std::string &filename);
Font &current_font() {
return *_current_font;
}
Profile &current_profile() {
return *_current_profile;
}
int id_within_manager() const {
return _id_within_manager;
}
typedef std::function<void(const char *)> COMMAND_FUNCTION;
typedef std::map<std::string, COMMAND_FUNCTION> CommandFunctionTable;
protected:
void _init_fonts();
void init_lcd();
void _init_commands();
// typedef void (COMMAND_FUNCTION)( Device*, const char *, const char * );
CommandFunctionTable _command_table;
struct timeval _event_time;
struct input_event _event;
int _id_within_manager;
libusb_device_handle *handle;
libusb_context *ctx;
int _uinput_fid;
int _input_pipe_fid;
std::string _input_pipe_name;
int _output_pipe_fid;
std::string _output_pipe_name;
std::map<std::string, FontPtr> _fonts;
FontPtr _current_font;
std::map<std::string, ProfilePtr> _profiles;
ProfilePtr _current_profile;
Manager &_manager;
G13_LCD _lcd;
Stick _stick;
bool keys[G13_NUM_KEYS];
};
inline bool Device::is_set(int key) {
return keys[key];
}
inline bool Device::update(int key, bool v) {
bool old = keys[key];
keys[key] = v;
return old != v;
}
} // namespace G13
#endif // DEVICE_H

View File

@ -1,38 +0,0 @@
#ifndef FIND_OR_THROW_H
#define FIND_OR_THROW_H
#include <map>
namespace G13 {
class NotFoundException : public std::exception {
public:
const char *what() throw();
};
template <class K_T, class V_T>
inline const V_T &find_or_throw(const std::map<K_T, V_T> &m,
const K_T &target) {
auto i = m.find(target);
if (i == m.end()) {
throw NotFoundException();
}
return i->second;
};
template <class K_T, class V_T>
inline V_T &find_or_throw(std::map<K_T, V_T> &m, const K_T &target) {
auto i = m.find(target);
if (i == m.end()) {
throw NotFoundException();
}
return i->second;
};
} // namespace G13
#endif // FIND_OR_THROW_H

View File

@ -1,65 +0,0 @@
#include "font.h"
#include "device.h"
using namespace std;
namespace G13 {
#include "font8x8.h"
Font::Font() : _name("default"), _width(8) {
}
Font::Font(const std::string &name, unsigned int width)
: _name(name),
_width(width) {
}
void FontChar::set_character(unsigned char *data, int width,
unsigned flags) {
unsigned char *dest = bits_regular;
memset(dest, 0, CHAR_BUF_SIZE);
if (flags && FF_ROTATE) {
for (int x = 0; x < width; x++) {
unsigned char x_mask = 1 << x;
for (int y = 0; y < 8; y++) {
if (data[y] & x_mask) {
dest[x] |= 1 << y;
}
}
}
} else {
memcpy(dest, data, width);
}
for (int x = 0; x < width; x++) {
bits_inverted[x] = ~dest[x];
}
}
template <typename T, int size>
int GetFontCharacterCount(T (&)[size]) {
return size;
}
template <class ARRAY_T, class FLAGST>
void Font::install_font(ARRAY_T &data, FLAGST flags, int first) {
for (int i = 0; i < GetFontCharacterCount(data); i++) {
_chars[i + first].set_character(&data[i][0], _width, flags);
}
}
void Device::_init_fonts() {
_current_font = FontPtr(new Font("8x8", 8));
_fonts[_current_font->name()] = _current_font;
_current_font->install_font(font8x8_basic, FontChar::FF_ROTATE, 0);
FontPtr fiveXeight(new Font("5x8", 5));
fiveXeight->install_font(font5x8, 0, 32);
_fonts[fiveXeight->name()] = fiveXeight;
}
} // namespace G13

View File

@ -1,57 +0,0 @@
#ifndef FONT_H
#define FONT_H
#include <memory.h>
#include <memory>
namespace G13 {
class FontChar {
public:
static const int CHAR_BUF_SIZE = 8;
enum FONT_FLAGS { FF_ROTATE = 0x01 };
FontChar() {
memset(bits_regular, 0, CHAR_BUF_SIZE);
memset(bits_inverted, 0, CHAR_BUF_SIZE);
}
void set_character(unsigned char *data, int width, unsigned flags);
unsigned char bits_regular[CHAR_BUF_SIZE];
unsigned char bits_inverted[CHAR_BUF_SIZE];
};
class Font {
public:
Font();
Font(const std::string &name, unsigned int width = 8);
void set_character(unsigned int c, unsigned char *data);
template <class ARRAY_T, class FLAGST>
void install_font(ARRAY_T &data, FLAGST flags, int first = 0);
const std::string &name() const {
return _name;
}
unsigned int width() const {
return _width;
}
const FontChar &char_data(unsigned int x) {
return _chars[x];
}
protected:
std::string _name;
unsigned int _width;
FontChar _chars[256];
};
typedef std::shared_ptr<Font> FontPtr;
} // namespace G13
#endif // FONT_H

View File

@ -1,360 +0,0 @@
// font data from https://github.com/dhepper/font8x8
// Constant: font8x8_basic
// Contains an 8x8 font map for unicode points U+0000 - U+007F (basic latin)
unsigned char font8x8_basic[128][8] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul)
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
{0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
{0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
{0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
{0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
{0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
{0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
{0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
{0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
{0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
{0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
{0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
{0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
{0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
{0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
{0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
{0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
{0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
{0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
{0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
{0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
{0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
{0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
{0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
{0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
{0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (//)
{0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
{0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
{0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
{0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
{0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
{0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
{0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
{0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
{0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
{0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
{0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
{0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
{0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
{0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
{0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
{0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
{0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
{0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
{0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
{0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
{0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
{0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
{0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
{0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
{0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
{0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
{0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
{0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
{0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
{0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
{0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
{0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
{0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
{0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
{0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
{0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
{0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
{0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
{0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
{0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
{0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
{0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
{0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
{0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
{0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
{0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
{0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
{0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
{0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
{0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
{0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
{0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
{0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
{0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
{0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
{0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
{0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
{0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
{0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
{0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
{0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
{0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
{0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
{0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
{0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
{0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F
};
unsigned char font5x8[][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 (Space)
{0x00, 0x00, 0x9E, 0x00, 0x00}, // 0x21 !
{0x00, 0x0E, 0x00, 0x0E, 0x00}, // 0x22 "
{0x28, 0xFE, 0x28, 0xFE, 0x28}, // 0x23 #
{0x48, 0x54, 0xFE, 0x54, 0x24}, // 0x24 $
{0x46, 0x26, 0x10, 0xC8, 0xC4}, // 0x25 %
{0x6C, 0x92, 0xAA, 0x44, 0xA0}, // 0x26 &
{0x00, 0x0A, 0x06, 0x00, 0x00}, // 0x27 '
{0x00, 0x38, 0x44, 0x82, 0x00}, // 0x28 (
{0x00, 0x82, 0x44, 0x38, 0x00}, // 0x29 )
{0x10, 0x54, 0x38, 0x54, 0x10}, // 0x2A *
{0x10, 0x10, 0x7C, 0x10, 0x10}, // 0x2B +
{0x00, 0xA0, 0x60, 0x00, 0x00}, // 0x2C ,
{0x10, 0x10, 0x10, 0x10, 0x10}, // 0x2D -
{0x00, 0x60, 0x60, 0x00, 0x00}, // 0x2E .
{0x40, 0x20, 0x10, 0x08, 0x04}, // 0x2F /
{0x7C, 0xA2, 0x92, 0x8A, 0x7C}, // 0x30 0
{0x00, 0x84, 0xFE, 0x80, 0x00}, // 0x31 1
{0x84, 0xC2, 0xA2, 0x92, 0x8C}, // 0x32 2
{0x42, 0x82, 0x8A, 0x96, 0x62}, // 0x33 3
{0x30, 0x28, 0x24, 0xFE, 0x20}, // 0x34 4
{0x4E, 0x8A, 0x8A, 0x8A, 0x72}, // 0x35 5
{0x78, 0x94, 0x92, 0x92, 0x60}, // 0x36 6
{0x02, 0xE2, 0x12, 0x0A, 0x06}, // 0x37 7
{0x6C, 0x92, 0x92, 0x92, 0x6C}, // 0x38 8
{0x0C, 0x92, 0x92, 0x52, 0x3C}, // 0x39 9
{0x00, 0x6C, 0x6C, 0x00, 0x00}, // 0x3A :
{0x00, 0xAC, 0x6C, 0x00, 0x00}, // 0x3B ;
{0x00, 0x10, 0x28, 0x44, 0x82}, // 0x3C <
{0x28, 0x28, 0x28, 0x28, 0x28}, // 0x3D =
{0x82, 0x44, 0x28, 0x10, 0x00}, // 0x3E >
{0x04, 0x02, 0xA2, 0x12, 0x0C}, // 0x3F ?
{0x64, 0x92, 0xF2, 0x82, 0x7C}, // 0x40 @
{0xFC, 0x22, 0x22, 0x22, 0xFC}, // 0x41 A
{0xFE, 0x92, 0x92, 0x92, 0x6C}, // 0x42 B
{0x7C, 0x82, 0x82, 0x82, 0x44}, // 0x43 C
{0xFE, 0x82, 0x82, 0x44, 0x38}, // 0x44 D
{0xFE, 0x92, 0x92, 0x92, 0x82}, // 0x45 E
{0xFE, 0x12, 0x12, 0x02, 0x02}, // 0x46 F
{0x7C, 0x82, 0x82, 0xA2, 0x64}, // 0x47 G
{0xFE, 0x10, 0x10, 0x10, 0xFE}, // 0x48 H
{0x00, 0x82, 0xFE, 0x82, 0x00}, // 0x49 I
{0x40, 0x80, 0x82, 0x7E, 0x02}, // 0x4A J
{0xFE, 0x10, 0x28, 0x44, 0x82}, // 0x4B K
{0xFE, 0x80, 0x80, 0x80, 0x80}, // 0x4C L
{0xFE, 0x04, 0x08, 0x04, 0xFE}, // 0x4D M
{0xFE, 0x08, 0x10, 0x20, 0xFE}, // 0x4E N
{0x7C, 0x82, 0x82, 0x82, 0x7C}, // 0x4F O
{0xFE, 0x12, 0x12, 0x12, 0x0C}, // 0x50 P
{0x7C, 0x82, 0xA2, 0x42, 0xBC}, // 0x51 Q
{0xFE, 0x12, 0x32, 0x52, 0x8C}, // 0x52 R
{0x8C, 0x92, 0x92, 0x92, 0x62}, // 0x53 S
{0x02, 0x02, 0xFE, 0x02, 0x02}, // 0x54 T
{0x7E, 0x80, 0x80, 0x80, 0x7E}, // 0x55 U
{0x3E, 0x40, 0x80, 0x40, 0x3E}, // 0x56 V
{0xFE, 0x40, 0x30, 0x40, 0xFE}, // 0x57 W
{0xC6, 0x28, 0x10, 0x28, 0xC6}, // 0x58 X
{0x06, 0x08, 0xF0, 0x08, 0x06}, // 0x59 Y
{0xC2, 0xA2, 0x92, 0x8A, 0x86}, // 0x5A Z
{0x00, 0x00, 0xFE, 0x82, 0x82}, // 0x5B [
{0x04, 0x08, 0x10, 0x20, 0x40}, // 0x5C "\"
{0x82, 0x82, 0xFE, 0x00, 0x00}, // 0x5D ]
{0x08, 0x04, 0x02, 0x04, 0x08}, // 0x5E ^
{0x80, 0x80, 0x80, 0x80, 0x80}, // 0x5F _
{0x00, 0x02, 0x04, 0x08, 0x00}, // 0x60 `
{0x40, 0xA8, 0xA8, 0xA8, 0xF0}, // 0x61 a
{0xFE, 0x90, 0x88, 0x88, 0x70}, // 0x62 b
{0x70, 0x88, 0x88, 0x88, 0x40}, // 0x63 c
{0x70, 0x88, 0x88, 0x90, 0xFE}, // 0x64 d
{0x70, 0xA8, 0xA8, 0xA8, 0x30}, // 0x65 e
{0x10, 0xFC, 0x12, 0x02, 0x04}, // 0x66 f
{0x10, 0x28, 0xA8, 0xA8, 0x78}, // 0x67 g
{0xFE, 0x10, 0x08, 0x08, 0xF0}, // 0x68 h
{0x00, 0x88, 0xFA, 0x80, 0x00}, // 0x69 i
{0x40, 0x80, 0x88, 0x7A, 0x00}, // 0x6A j
{0x00, 0xFE, 0x20, 0x50, 0x88}, // 0x6B k
{0x00, 0x82, 0xFE, 0x80, 0x00}, // 0x6C l
{0xF8, 0x08, 0x30, 0x08, 0xF0}, // 0x6D m
{0xF8, 0x10, 0x08, 0x08, 0xF0}, // 0x6E n
{0x70, 0x88, 0x88, 0x88, 0x70}, // 0x6F o
{0xF8, 0x28, 0x28, 0x28, 0x10}, // 0x70 p
{0x10, 0x28, 0x28, 0x30, 0xF8}, // 0x71 q
{0xF8, 0x10, 0x08, 0x08, 0x10}, // 0x72 r
{0x90, 0xA8, 0xA8, 0xA8, 0x40}, // 0x73 s
{0x08, 0x7E, 0x88, 0x80, 0x40}, // 0x74 t
{0x78, 0x80, 0x80, 0x40, 0xF8}, // 0x75 u
{0x38, 0x40, 0x80, 0x40, 0x38}, // 0x76 v
{0x78, 0x80, 0x60, 0x80, 0x78}, // 0x77 w
{0x88, 0x50, 0x20, 0x50, 0x88}, // 0x78 x
{0x18, 0xA0, 0xA0, 0xA0, 0x78}, // 0x79 y
{0x88, 0xC8, 0xA8, 0x98, 0x88}, // 0x7A z
{0x00, 0x10, 0x6C, 0x82, 0x00}, // 0x7B {
{0x00, 0x00, 0xFE, 0x00, 0x00}, // 0x7C |
{0x00, 0x82, 0x6C, 0x10, 0x00}, // 0x7D }
{0x20, 0x10, 0x10, 0x20, 0x10}, // 0x7E
{0xF0, 0x88, 0x84, 0x88, 0xF0}, // 0x7F 
{0x28, 0x7C, 0xAA, 0x82, 0x44}, // 0x80 €
{0xF0, 0x29, 0x27, 0x21, 0xFF}, // 0x81 
{0x00, 0xA0, 0x60, 0x00, 0x00}, // 0x82
{0x40, 0x90, 0x7C, 0x12, 0x04}, // 0x83 ƒ
{0xC0, 0xA0, 0x00, 0xC0, 0xA0}, // 0x84 „
{0x80, 0x00, 0x80, 0x00, 0x80}, // 0x85 …
{0x00, 0x04, 0xFE, 0x04, 0x00}, // 0x86 †
{0x00, 0x44, 0xFE, 0x44, 0x00}, // 0x87 ‡
{0x00, 0x04, 0x02, 0x04, 0x00}, // 0x88 ˆ
{0xC3, 0xD3, 0x08, 0xC4, 0xC2}, // 0x89 ‰
{0x4C, 0x93, 0x92, 0x93, 0x64}, // 0x8A Š
{0x00, 0x10, 0x28, 0x00, 0x00}, // 0x8B
{0x7C, 0x82, 0x82, 0x7C, 0x92}, // 0x8C Œ
{0x02, 0xFE, 0x90, 0x90, 0x60}, // 0x8D 
{0xC2, 0xA3, 0x92, 0x8B, 0x86}, // 0x8E Ž
{0x44, 0x92, 0x8A, 0x92, 0x7C}, // 0x8F 
{0x70, 0x88, 0x90, 0x60, 0x98}, // 0x90 
{0x00, 0x02, 0x04, 0x08, 0x00}, // 0x91
{0x00, 0x08, 0x04, 0x02, 0x00}, // 0x92
{0x02, 0x04, 0x0A, 0x04, 0x08}, // 0x93 “
{0x08, 0x04, 0x0A, 0x04, 0x02}, // 0x94 ”
{0x00, 0x38, 0x38, 0x38, 0x00}, // 0x95 •
{0x00, 0x10, 0x10, 0x10, 0x10}, // 0x96
{0x10, 0x10, 0x10, 0x10, 0x10}, // 0x97 —
{0x02, 0x01, 0x02, 0x04, 0x02}, // 0x98 ˜
{0xF1, 0x5B, 0x55, 0x51, 0x51}, // 0x99 ™
{0x90, 0xA9, 0xAA, 0xA9, 0x40}, // 0x9A š
{0x00, 0x88, 0x50, 0x20, 0x00}, // 0x9B
{0x70, 0x88, 0x70, 0xA8, 0xB0}, // 0x9C ϡ
{0x38, 0x7C, 0xF8, 0x7C, 0x38}, // 0x9D 
{0x88, 0xC9, 0xAA, 0x99, 0x88}, // 0x9E ž
{0x1C, 0x21, 0xC0, 0x21, 0x1C}, // 0x9F Ÿ
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA0
{0x00, 0x00, 0xF2, 0x00, 0x00}, // 0xA1 ¡
{0x38, 0x44, 0xFE, 0x44, 0x20}, // 0xA2 ¢
{0x90, 0x7C, 0x92, 0x82, 0x40}, // 0xA3 £
{0x44, 0x38, 0x28, 0x38, 0x44}, // 0xA4 ¤
{0x2A, 0x2C, 0xF8, 0x2C, 0x2A}, // 0xA5 ¥
{0x00, 0x00, 0xEE, 0x00, 0x00}, // 0xA6 ¦
{0x40, 0x94, 0xAA, 0x52, 0x04}, // 0xA7 §
{0x00, 0x02, 0x00, 0x02, 0x00}, // 0xA8 ¨
{0xFE, 0x82, 0xBA, 0x92, 0xFE}, // 0xA9 ©
{0x90, 0xAA, 0xAA, 0xAA, 0xBC}, // 0xAA ª
{0x20, 0x50, 0xA8, 0x50, 0x88}, // 0xAB «
{0x20, 0x20, 0x20, 0x20, 0xE0}, // 0xAC ¬
{0x20, 0x20, 0x20, 0x20, 0x20}, // 0xAD ­
{0xFE, 0x82, 0xCA, 0xA2, 0xFE}, // 0xAE ®
{0x02, 0x02, 0x02, 0x02, 0x02}, // 0xAF ¯
{0x0E, 0x11, 0x11, 0x0E, 0x00}, // 0xB0 °
{0x88, 0x88, 0xBE, 0x88, 0x88}, // 0xB1 ±
{0x12, 0x19, 0x15, 0x12, 0x00}, // 0xB2 ²
{0x11, 0x15, 0x15, 0x0A, 0x00}, // 0xB3 ³
{0x00, 0x08, 0x04, 0x02, 0x00}, // 0xB4 ´
{0xFE, 0x20, 0x20, 0x10, 0x3E}, // 0xB5 µ
{0x0C, 0x12, 0x12, 0xFE, 0xFE}, // 0xB6 ¶
{0x00, 0x30, 0x30, 0x00, 0x00}, // 0xB7 ·
{0x00, 0x80, 0xB0, 0x40, 0x00}, // 0xB8 ¸
{0x00, 0x02, 0x0F, 0x00, 0x00}, // 0xB9 ¹
{0x00, 0x02, 0x05, 0x02, 0x00}, // 0xBA º
{0x44, 0x28, 0x54, 0x28, 0x10}, // 0xBB »
{0x22, 0x1F, 0x68, 0x54, 0xFA}, // 0xBC ¼
{0x02, 0x1F, 0x90, 0xC8, 0xB0}, // 0xBD ½
{0x15, 0x1F, 0x60, 0x50, 0xF8}, // 0xBE ¾
{0x60, 0x90, 0x8A, 0x80, 0x40}, // 0xBF ¿
{0xF0, 0x29, 0x26, 0x28, 0xF0}, // 0xC0 À
{0xF0, 0x28, 0x26, 0x29, 0xF0}, // 0xC1 Á
{0xF0, 0x2A, 0x29, 0x2A, 0xF0}, // 0xC2 Â
{0xF2, 0x29, 0x29, 0x2A, 0xF1}, // 0xC3 Ã
{0xF0, 0x29, 0x24, 0x29, 0xF0}, // 0xC4 Ä
{0xF0, 0x2A, 0x2D, 0x2A, 0xF0}, // 0xC5 Å
{0xF8, 0x24, 0xFE, 0x92, 0x92}, // 0xC6 Æ
{0x1E, 0x21, 0xA1, 0xE1, 0x12}, // 0xC7 Ç
{0xF8, 0xA9, 0xAA, 0xA8, 0x88}, // 0xC8 È
{0xF8, 0xA8, 0xAA, 0xA9, 0x88}, // 0xC9 É
{0xF8, 0xAA, 0xA9, 0xAA, 0x88}, // 0xCA Ê
{0xF8, 0xAA, 0xA8, 0xAA, 0x88}, // 0xCB Ë
{0x00, 0x89, 0xFA, 0x88, 0x00}, // 0xCC Ì
{0x00, 0x88, 0xFA, 0x89, 0x00}, // 0xCD Í
{0x00, 0x8A, 0xF9, 0x8A, 0x00}, // 0xCE Î
{0x00, 0x8A, 0xF8, 0x8A, 0x00}, // 0xCF Ï
{0x10, 0xFE, 0x92, 0x82, 0x7C}, // 0xD0 Ð
{0xFA, 0x11, 0x21, 0x42, 0xF9}, // 0xD1 Ñ
{0x78, 0x85, 0x86, 0x84, 0x78}, // 0xD2 Ò
{0x78, 0x84, 0x86, 0x85, 0x78}, // 0xD3 Ó
{0x70, 0x8A, 0x89, 0x8A, 0x70}, // 0xD4 Ô
{0x72, 0x89, 0x89, 0x8A, 0x71}, // 0xD5 Õ
{0x78, 0x85, 0x84, 0x85, 0x78}, // 0xD6 Ö
{0x44, 0x28, 0x10, 0x28, 0x44}, // 0xD7 ×
{0x10, 0xAA, 0xFE, 0xAA, 0x10}, // 0xD8 Ø
{0x7C, 0x81, 0x82, 0x80, 0x7C}, // 0xD9 Ù
{0x7C, 0x80, 0x82, 0x81, 0x7C}, // 0xDA Ú
{0x78, 0x82, 0x81, 0x82, 0x78}, // 0xDB Û
{0x7C, 0x81, 0x80, 0x81, 0x7C}, // 0xDC Ü
{0x04, 0x08, 0xF2, 0x09, 0x04}, // 0xDD Ý
{0x81, 0xFF, 0x24, 0x24, 0x18}, // 0xDE Þ
{0x80, 0x7C, 0x92, 0x92, 0x6C}, // 0xDF ß
{0x40, 0xA9, 0xAA, 0xA8, 0xF0}, // 0xE0 à
{0x40, 0xA8, 0xAA, 0xA9, 0xF0}, // 0xE1 á
{0x40, 0xAA, 0xA9, 0xAA, 0xF0}, // 0xE2 â
{0x42, 0xA9, 0xA9, 0xAA, 0xF1}, // 0xE3 ã
{0x40, 0xAA, 0xA8, 0xAA, 0xF0}, // 0xE4 ä
{0x40, 0xAA, 0xAD, 0xAA, 0xF0}, // 0xE5 å
{0x64, 0x94, 0x78, 0x94, 0x58}, // 0xE6 æ
{0x18, 0x24, 0xA4, 0xE4, 0x10}, // 0xE7 ç
{0x70, 0xA9, 0xAA, 0xA8, 0x30}, // 0xE8 è
{0x70, 0xA8, 0xAA, 0xA9, 0x30}, // 0xE9 é
{0x70, 0xAA, 0xA9, 0xAA, 0x30}, // 0xEA ê
{0x70, 0xAA, 0xA8, 0xAA, 0x30}, // 0xEB ë
{0x00, 0x91, 0xFA, 0x80, 0x00}, // 0xEC ì
{0x00, 0x90, 0xFA, 0x81, 0x00}, // 0xED í
{0x00, 0x92, 0xF9, 0x82, 0x00}, // 0xEE î
{0x00, 0x92, 0xF8, 0x82, 0x00}, // 0xEF ï
{0x4A, 0xA4, 0xAA, 0xB0, 0x60}, // 0xF0 ð
{0xFA, 0x11, 0x09, 0x0A, 0xF1}, // 0xF1 ñ
{0x70, 0x89, 0x8A, 0x88, 0x70}, // 0xF2 ò
{0x70, 0x88, 0x8A, 0x89, 0x70}, // 0xF3 ó
{0x60, 0x94, 0x92, 0x94, 0x60}, // 0xF4 ô
{0x64, 0x92, 0x92, 0x94, 0x62}, // 0xF5 õ
{0x70, 0x8A, 0x88, 0x8A, 0x70}, // 0xF6 ö
{0x10, 0x10, 0x54, 0x10, 0x10}, // 0xF7 ÷
{0x10, 0xA8, 0x7C, 0x2A, 0x10}, // 0xF8 ø
{0x78, 0x81, 0x82, 0x40, 0xF8}, // 0xF9 ù
{0x78, 0x80, 0x82, 0x41, 0xF8}, // 0xFA ú
{0x78, 0x82, 0x81, 0x42, 0xF8}, // 0xFB û
{0x78, 0x82, 0x80, 0x42, 0xF8}, // 0xFC ü
{0x18, 0xA0, 0xA4, 0xA2, 0x78}, // 0xFD v
{0x00, 0x82, 0xFE, 0xA8, 0x10}, // 0xFE þ
{0x18, 0xA2, 0xA0, 0xA2, 0x78} // 0xFF ÿ
};

View File

@ -1,60 +0,0 @@
#ifndef G13_H
#define G13_H
#include <boost/log/trivial.hpp>
#include <string>
namespace G13 {
#define G13_LOG(level, message) BOOST_LOG_TRIVIAL(level) << message
#define G13_OUT(message) BOOST_LOG_TRIVIAL(info) << message
const size_t G13_INTERFACE = 0;
const size_t G13_KEY_ENDPOINT = 1;
const size_t G13_LCD_ENDPOINT = 2;
const size_t G13_KEY_READ_TIMEOUT = 0;
const size_t G13_VENDOR_ID = 0x046d;
const size_t G13_PRODUCT_ID = 0xc21c;
const size_t G13_REPORT_SIZE = 8;
const size_t G13_LCD_BUFFER_SIZE = 0x3c0;
const size_t G13_NUM_KEYS = 40;
const size_t G13_LCD_COLUMNS = 160;
const size_t G13_LCD_ROWS = 48;
const size_t G13_LCD_BYTES_PER_ROW = G13_LCD_COLUMNS / 8;
const size_t G13_LCD_BUF_SIZE = G13_LCD_ROWS * G13_LCD_BYTES_PER_ROW;
const size_t G13_LCD_TEXT_CHEIGHT = 8;
const size_t G13_LCD_TEXT_ROWS = 160 / G13_LCD_TEXT_CHEIGHT;
enum stick_mode_t {
STICK_ABSOLUTE,
STICK_RELATIVE,
STICK_KEYS,
STICK_CALCENTER,
STICK_CALBOUNDS,
STICK_CALNORTH
};
typedef int linux_keyvalue;
const linux_keyvalue BAD_KEY_VALUE = -1;
typedef int g13_keyindex;
class CommandException : public std::exception {
public:
CommandException(const std::string &reason) : _reason(reason) {
}
virtual ~CommandException() throw() {
}
virtual const char *what() const throw() {
return _reason.c_str();
}
std::string _reason;
};
} // namespace G13
#endif // G13_H

View File

@ -1,80 +0,0 @@
/*
* helper.hpp
*
* Miscellaneous helpful little tidbits...
*/
/*
* Copyright (c) 2015, James Fowler
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef HELPER_HPP
#define HELPER_HPP
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq.hpp>
#include <boost/shared_ptr.hpp>
#include <exception>
#include <iomanip>
#include <iostream>
#include <map>
#include <string>
#include <vector>
namespace Helper {
template <class MAP_T>
struct _map_keys_out {
_map_keys_out(const MAP_T &c, const std::string &s) : container(c), sep(s) {
}
const MAP_T &container;
std::string sep;
};
template <class STREAM_T, class MAP_T>
STREAM_T &operator<<(STREAM_T &o, const _map_keys_out<MAP_T> &_mko) {
bool first = true;
for (auto i = _mko.container.begin(); i != _mko.container.end(); i++) {
if (first) {
first = false;
o << i->first;
} else {
o << _mko.sep << i->first;
}
}
return o;
};
template <class MAP_T>
_map_keys_out<MAP_T> map_keys_out(const MAP_T &c,
const std::string &sep = " ") {
return _map_keys_out<MAP_T>(c, sep);
};
}; // namespace Helper
#endif // HELPER_HPP

View File

@ -1,160 +0,0 @@
/*
pixels are mapped rather strangely for G13 buffer...
byte 0 contains column 0 / row 0 - 7
byte 1 contains column 1 / row 0 - 7
so the masks for each pixel are laid out as below
(ByteOffset.PixelMask)
00.01 01.01 02.01 ...
00.02 01.02 02.02 ...
00.04 01.04 02.04 ...
00.08 01.08 02.08 ...
00.10 01.10 02.10 ...
00.20 01.20 02.20 ...
00.40 01.40 02.40 ...
00.80 01.80 02.80 ...
A0.01 A1.01 A2.01 ...
*/
#include "lcd.h"
#include <fstream>
#include <iostream>
#include "device.h"
namespace G13 {
void G13_LCD::image(unsigned char *data, int size) {
_keypad.write_lcd(data, size);
}
G13_LCD::G13_LCD(Device &keypad) : _keypad(keypad) {
cursor_col = 0;
cursor_row = 0;
text_mode = 0;
}
void G13_LCD::image_setpixel(unsigned row, unsigned col) {
unsigned offset =
image_byte_offset(row, col); // col + (row /8 ) * BYTES_PER_ROW * 8;
unsigned char mask = 1 << ((row)&7);
if (offset >= G13_LCD_BUF_SIZE) {
G13_LOG(error,
"bad offset " << offset << " for " << (row) << " x " << (col));
return;
}
image_buf[offset] |= mask;
}
void G13_LCD::image_clearpixel(unsigned row, unsigned col) {
unsigned offset =
image_byte_offset(row, col); // col + (row /8 ) * BYTES_PER_ROW * 8;
unsigned char mask = 1 << ((row)&7);
if (offset >= G13_LCD_BUF_SIZE) {
G13_LOG(error,
"bad offset " << offset << " for " << (row) << " x " << (col));
return;
}
image_buf[offset] &= ~mask;
}
void G13_LCD::write_pos(int row, int col) {
cursor_row = row;
cursor_col = col;
if (cursor_col >= G13_LCD_COLUMNS) {
cursor_col = 0;
}
if (cursor_row >= G13_LCD_TEXT_ROWS) {
cursor_row = 0;
}
}
void G13_LCD::write_char(char c, int row, int col) {
if (row == -1) {
row = cursor_row;
col = cursor_col;
cursor_col += _keypad.current_font().width();
if (cursor_col >= G13_LCD_COLUMNS) {
cursor_col = 0;
if (++cursor_row >= G13_LCD_TEXT_ROWS) {
cursor_row = 0;
}
}
}
unsigned offset = image_byte_offset(row * G13_LCD_TEXT_CHEIGHT,
col); //*_keypad._current_font->_width );
if (text_mode) {
memcpy(&image_buf[offset],
&_keypad.current_font().char_data(c).bits_inverted,
_keypad.current_font().width());
} else {
memcpy(&image_buf[offset],
&_keypad.current_font().char_data(c).bits_regular,
_keypad.current_font().width());
}
}
void G13_LCD::write_string(const char *str) {
G13_LOG(info, "writing \"" << str << "\"");
while (*str) {
if (*str == '\n') {
cursor_col = 0;
if (++cursor_row >= G13_LCD_TEXT_ROWS) {
cursor_row = 0;
}
} else if (*str == '\t') {
cursor_col += 4 - (cursor_col % 4);
if (++cursor_col >= G13_LCD_COLUMNS) {
cursor_col = 0;
if (++cursor_row >= G13_LCD_TEXT_ROWS) {
cursor_row = 0;
}
}
} else {
write_char(*str);
}
++str;
}
image_send();
}
void G13_LCD::image_test(int x, int y) {
unsigned int row = 0, col = 0;
if (y >= 0) {
image_setpixel(x, y);
} else {
image_clear();
switch (x) {
case 1:
for (row = 0; row < G13_LCD_ROWS; ++row) {
col = row;
image_setpixel(row, col);
image_setpixel(row, G13_LCD_COLUMNS - col);
}
break;
case 2:
default:
for (row = 0; row < G13_LCD_ROWS; ++row) {
col = row;
image_setpixel(row, 8);
image_setpixel(row, G13_LCD_COLUMNS - 8);
image_setpixel(row, G13_LCD_COLUMNS / 2);
image_setpixel(row, col);
image_setpixel(row, G13_LCD_COLUMNS - col);
}
break;
}
}
image_send();
}
} // namespace G13

View File

@ -1,46 +0,0 @@
#ifndef LCD_H
#define LCD_H
#include <memory.h>
#include "g13.h"
namespace G13 {
class Device;
class G13_LCD {
public:
G13_LCD(Device &keypad);
Device &_keypad;
unsigned char image_buf[G13_LCD_BUF_SIZE + 8];
unsigned cursor_row;
unsigned cursor_col;
int text_mode;
void image(unsigned char *data, int size);
void image_send() {
image(image_buf, G13_LCD_BUF_SIZE);
}
void image_test(int x, int y);
void image_clear() {
memset(image_buf, 0, G13_LCD_BUF_SIZE);
}
unsigned image_byte_offset(unsigned row, unsigned col) {
return col + (row / 8) * G13_LCD_BYTES_PER_ROW * 8;
}
void image_setpixel(unsigned row, unsigned col);
void image_clearpixel(unsigned row, unsigned col);
void write_char(char c, int row = -1, int col = -1);
void write_string(const char *str);
void write_pos(int row, int col);
};
} // namespace G13
#endif // LCD_H

View File

@ -1,86 +0,0 @@
#ifndef G13_LOGO_H
#define G13_LOGO_H
static unsigned char g13_logo[160 * 48 / 8] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf8, 0x78, 0x78, 0x7c, 0x3c, 0x3c, 0x3e,
0x3e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xdf, 0xdf, 0x9f, 0x9f,
0x9f, 0xbe, 0x3e, 0x7e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x90,
0xe8, 0x70, 0x94, 0x28, 0x0a, 0x0c, 0x12, 0x04, 0x06, 0x10, 0x14, 0x10,
0x10, 0x48, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00,
0x48, 0x10, 0x0c, 0x10, 0x18, 0x04, 0x18, 0x08, 0x28, 0x5c, 0x30, 0xe8,
0x90, 0x20, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xf0, 0xf8, 0x7c, 0x3e,
0x1e, 0x0f, 0x0f, 0x07, 0x03, 0x83, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00,
0xe0, 0xe0, 0x80, 0x00, 0xe0, 0xe0, 0x00, 0x18, 0x38, 0xf0, 0xf0, 0xf8,
0x8b, 0x07, 0x04, 0x04, 0x07, 0x0f, 0x0f, 0x1f, 0x1e, 0x3e, 0x7c, 0xf8,
0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
0xf0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc, 0x7c, 0x7c, 0x3c, 0x3c, 0x3c, 0x3c,
0x7c, 0x7c, 0x78, 0xf8, 0xfc, 0xfc, 0xfc, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xf8, 0x38,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf8, 0xf8, 0x78,
0x3c, 0x3c, 0x7c, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xe0, 0x00, 0x00, 0x00,
0x00, 0xb0, 0x00, 0x1f, 0xff, 0xe4, 0x80, 0x80, 0x80, 0xe0, 0xd0, 0x28,
0x34, 0x18, 0x1d, 0x1e, 0xcf, 0x0f, 0x6f, 0x0f, 0x0f, 0x87, 0x2e, 0x01,
0x01, 0x65, 0x03, 0xcf, 0x4f, 0x0f, 0x1e, 0x1d, 0x38, 0x60, 0xd0, 0xe0,
0x80, 0xe0, 0xcb, 0xfd, 0x3f, 0x80, 0x35, 0x00, 0xf0, 0xfe, 0xff, 0x0f,
0x03, 0x01, 0x3e, 0xfe, 0xfe, 0x00, 0x08, 0xfb, 0xfb, 0x00, 0xff, 0xff,
0x03, 0x1f, 0xff, 0xfe, 0x0f, 0x1f, 0x1f, 0x1c, 0x1f, 0x3f, 0x98, 0x80,
0x4f, 0xe7, 0x61, 0x01, 0x83, 0xc2, 0xfc, 0xfc, 0xfc, 0x80, 0xf0, 0xf0,
0xd0, 0xf0, 0x30, 0x00, 0x03, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00,
0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
0x00, 0x40, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf3, 0xf3, 0xf0,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x18, 0x18, 0x38, 0x3e, 0xff, 0xff, 0xff, 0xf7, 0xe7,
0xc1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x01, 0x09, 0xc3,
0x3f, 0x03, 0x00, 0x00, 0x80, 0x80, 0x40, 0x10, 0x44, 0x00, 0x00, 0x02,
0x02, 0x03, 0x00, 0xc0, 0x01, 0x00, 0x40, 0x03, 0x06, 0x17, 0x30, 0x40,
0x20, 0x80, 0x21, 0x03, 0x4b, 0x23, 0x01, 0x04, 0x02, 0x00, 0x00, 0x00,
0x07, 0x7f, 0xfe, 0xe0, 0x80, 0x00, 0x00, 0x3f, 0x3f, 0x00, 0x00, 0x07,
0x03, 0x00, 0xf4, 0xfe, 0xf4, 0x7c, 0xfc, 0xfc, 0x18, 0xfc, 0xfc, 0xf0,
0x1e, 0xbf, 0xf7, 0xe3, 0x1f, 0xff, 0xff, 0x3e, 0x7f, 0x77, 0x39, 0x7f,
0x7f, 0x03, 0x0f, 0x0f, 0x0c, 0x0e, 0x86, 0xe0, 0xf8, 0x7f, 0x1f, 0x03,
0x00, 0x00, 0x00, 0x00, 0x03, 0x0f, 0x1f, 0x7f, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xfe, 0xf8, 0xf0, 0xe0, 0xe0, 0xe0, 0xf0, 0xff, 0xff, 0xff, 0xff,
0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xf0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xc0, 0xc0, 0x80, 0x00,
0x00, 0x00, 0x18, 0x78, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0xfc, 0xff,
0xff, 0xff, 0xff, 0x7f, 0x3f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x02, 0x02, 0x0d, 0xe1, 0x00, 0x00, 0x07, 0x10, 0x20,
0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x21, 0x00, 0x41, 0x41, 0x00,
0x40, 0x00, 0x40, 0x48, 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0f, 0x1e, 0x3e, 0x7c,
0x78, 0xf0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc7, 0x8f, 0x8f, 0x80, 0x87, 0x07,
0x00, 0x00, 0x07, 0x07, 0x83, 0x83, 0x83, 0x81, 0x80, 0x80, 0xc0, 0xc0,
0xc0, 0xe0, 0xe0, 0xf0, 0x70, 0x78, 0x3c, 0x1c, 0x0e, 0x0f, 0x07, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x04, 0x08, 0x00, 0x00, 0x01, 0x01, 0x0e, 0x58, 0x3c, 0x38, 0xe0, 0xc0,
0xc0, 0xe2, 0xe2, 0xa2, 0x9a, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03,
0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03,
0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif // G13_LOGO_H

View File

@ -1,66 +0,0 @@
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>
#include <iostream>
#include "g13.h"
#include "manager.h"
namespace po = boost::program_options;
extern "C" {
int main(int argc, char *argv[]) {
G13::Manager manager;
manager.set_log_level("info");
// Declare the supported options.
po::options_description desc("Allowed options");
desc.add_options()("help", "produce help message");
std::vector<std::string> sopt_names;
auto add_string_option = [&sopt_names, &desc](const char *name,
const char *description) {
desc.add_options()(name, po::value<std::string>(), description);
sopt_names.push_back(name);
};
add_string_option("logo", "set logo from file");
add_string_option("config", "load config commands from file");
add_string_option("pipe_in", "specify name for input pipe");
add_string_option("pipe_out", "specify name for output pipe");
add_string_option("log_level", "logging level");
// add_string_option( "logfile", "write log to logfile" );
po::positional_options_description p;
p.add("logo", -1);
po::variables_map vm;
po::store(
po::command_line_parser(argc, argv).options(desc).positional(p).run(),
vm);
po::notify(vm);
if (vm.count("help")) {
std::cout << argv[0] << " : user space G13 driver" << std::endl
<< desc << "\n";
return 1;
}
BOOST_FOREACH (const std::string &tag, sopt_names) {
if (vm.count(tag)) {
manager.set_string_config_value(tag, vm[tag].as<std::string>());
}
}
if (vm.count("logo")) {
manager.set_logo(vm["logo"].as<std::string>());
}
if (vm.count("log_level")) {
manager.set_log_level(manager.string_config_value("log_level"));
}
manager.run();
return 0;
}
}

View File

@ -1,279 +0,0 @@
#include "manager.h"
#include <signal.h>
#include <boost/foreach.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/expressions/formatters/stream.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <fstream>
#include <vector>
#include "device.h"
#include "find_or_throw.h"
#include "helper.h"
#include "repr.h"
namespace G13 {
void Manager::discover_g13s(libusb_device **devs, ssize_t count,
std::vector<Device *> &g13s) {
for (int i = 0; i < count; i++) {
libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(devs[i], &desc);
if (r < 0) {
G13_LOG(error, "Failed to get device descriptor");
return;
}
if (desc.idVendor == G13_VENDOR_ID && desc.idProduct == G13_PRODUCT_ID) {
libusb_device_handle *handle;
int r = libusb_open(devs[i], &handle);
if (r != 0) {
G13_LOG(error, "Error opening G13 device");
return;
}
if (libusb_kernel_driver_active(handle, 0) == 1)
if (libusb_detach_kernel_driver(handle, 0) == 0)
G13_LOG(info, "Kernel driver detached");
r = libusb_claim_interface(handle, 0);
if (r < 0) {
G13_LOG(error, "Cannot Claim Interface");
return;
}
g13s.push_back(new Device(*this, handle, g13s.size()));
}
}
}
void Manager::set_log_level(::boost::log::trivial::severity_level lvl) {
boost::log::core::get()->set_filter(::boost::log::trivial::severity >= lvl);
G13_OUT("set log level to " << lvl);
}
void Manager::set_log_level(const std::string &level) {
#define CHECK_LEVEL(L) \
if (level == BOOST_PP_STRINGIZE(L)) { \
set_log_level(::boost::log::trivial::L); \
return; \
}
CHECK_LEVEL(trace);
CHECK_LEVEL(debug);
CHECK_LEVEL(info);
CHECK_LEVEL(warning);
CHECK_LEVEL(error);
CHECK_LEVEL(fatal);
G13_LOG(error, "unknown log level" << level);
}
void Manager::cleanup() {
G13_LOG(info, "cleaning up");
for (auto device : g13s) {
device->cleanup();
delete device;
}
libusb_exit(ctx);
}
Manager::Manager() : devs(0), ctx(0) {
}
bool Manager::running = true;
void Manager::set_stop(int) {
running = false;
}
std::string Manager::string_config_value(const std::string &name) const {
try {
return find_or_throw(_string_config_values, name);
} catch (...) {
return "";
}
}
void Manager::set_string_config_value(const std::string &name,
const std::string &value) {
G13_LOG(info, "set_string_config_value " << name << " = " << repr(value));
_string_config_values[name] = value;
}
#define CONTROL_DIR std::string("/tmp/")
std::string Manager::make_pipe_name(Device *d, bool is_input) {
if (is_input) {
std::string config_base = string_config_value("pipe_in");
if (config_base.size()) {
if (d->id_within_manager() == 0) {
return config_base;
} else {
return config_base + "-" +
boost::lexical_cast<std::string>(d->id_within_manager());
}
}
return CONTROL_DIR + "g13-" +
boost::lexical_cast<std::string>(d->id_within_manager());
} else {
std::string config_base = string_config_value("pipe_out");
if (config_base.size()) {
if (d->id_within_manager() == 0) {
return config_base;
} else {
return config_base + "-" +
boost::lexical_cast<std::string>(d->id_within_manager());
}
}
return CONTROL_DIR + "g13-" +
boost::lexical_cast<std::string>(d->id_within_manager()) + "_out";
}
}
int Manager::run() {
init_keynames();
display_keys();
ssize_t cnt;
int ret;
ret = libusb_init(&ctx);
if (ret < 0) {
G13_LOG(error, "Initialization error: " << ret);
return 1;
}
libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, 3);
cnt = libusb_get_device_list(ctx, &devs);
if (cnt < 0) {
G13_LOG(error, "Error while getting device list");
return 1;
}
discover_g13s(devs, cnt, g13s);
libusb_free_device_list(devs, 1);
G13_LOG(info, "Found " << g13s.size() << " G13s");
if (g13s.size() == 0) {
return 1;
}
for (auto device : g13s) {
device->register_context(ctx);
}
signal(SIGINT, set_stop);
if (g13s.size() > 0 && logo_filename.size()) {
g13s[0]->write_lcd_file(logo_filename);
}
G13_LOG(info, "Active Stick zones ");
g13s[0]->stick().dump(std::cout);
std::string config_fn = string_config_value("config");
if (config_fn.size()) {
G13_LOG(info, "config_fn = " << config_fn);
g13s[0]->read_config_file(config_fn);
}
do {
if (g13s.size() > 0)
for (auto device : g13s) {
int status = device->read_keys();
device->read_commands();
if (status < 0) {
running = false;
}
}
} while (running && (g13s.size() > 0));
cleanup();
return 0;
}
// setup maps to let us convert between strings and G13 key names
#define ADD_G13_KEY_MAPPING(r, data, elem) \
{ \
std::string name = BOOST_PP_STRINGIZE(elem); \
g13_key_to_name[key_index] = name; \
g13_name_to_key[name] = key_index; \
key_index++; \
}
// setup maps to let us convert between strings and linux key names
#define ADD_KB_KEY_MAPPING(r, data, elem) \
{ \
std::string name = BOOST_PP_STRINGIZE(elem); \
int keyval = BOOST_PP_CAT(KEY_, elem); \
input_key_to_name[keyval] = name; \
input_name_to_key[name] = keyval; \
}
void Manager::init_keynames() {
int key_index = 0;
BOOST_PP_SEQ_FOR_EACH(ADD_G13_KEY_MAPPING, _, G13_KEY_SEQ);
BOOST_PP_SEQ_FOR_EACH(ADD_KB_KEY_MAPPING, _, KB_INPUT_KEY_SEQ);
}
linux_keyvalue
Manager::find_g13_key_value(const std::string &keyname) const {
auto i = g13_name_to_key.find(keyname);
if (i == g13_name_to_key.end()) {
return BAD_KEY_VALUE;
}
return i->second;
}
linux_keyvalue
Manager::find_input_key_value(const std::string &keyname) const {
// if there is a KEY_ prefix, strip it off
if (!strncmp(keyname.c_str(), "KEY_", 4)) {
return find_input_key_value(keyname.c_str() + 4);
}
auto i = input_name_to_key.find(keyname);
if (i == input_name_to_key.end()) {
return BAD_KEY_VALUE;
}
return i->second;
}
std::string Manager::find_input_key_name(linux_keyvalue v) const {
try {
return find_or_throw(input_key_to_name, v);
} catch (...) {
return "(unknown linux key)";
}
}
std::string Manager::find_g13_key_name(g13_keyindex v) const {
try {
return find_or_throw(g13_key_to_name, v);
} catch (...) {
return "(unknown G13 key)";
}
}
void Manager::display_keys() {
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));
}
} // namespace G13

View File

@ -1,79 +0,0 @@
#ifndef MANAGER_H
#define MANAGER_H
#include <map>
#include <string>
#include <vector>
#include "action.h"
#include "device.h"
namespace G13 {
/*!
* top level class, holds what would otherwise be in global variables
*/
class Manager {
public:
Manager();
g13_keyindex find_g13_key_value(const std::string &keyname) const;
std::string find_g13_key_name(g13_keyindex) const;
linux_keyvalue find_input_key_value(const std::string &keyname) const;
std::string find_input_key_name(linux_keyvalue) const;
void set_logo(const std::string &fn) {
logo_filename = fn;
}
int run();
std::string string_config_value(const std::string &name) const;
void set_string_config_value(const std::string &name, const std::string &val);
std::string make_pipe_name(Device *d, bool is_input);
void set_log_level(::boost::log::trivial::severity_level lvl);
void set_log_level(const std::string &);
protected:
void init_keynames();
void display_keys();
void discover_g13s(libusb_device **devs, ssize_t count,
std::vector<Device *> &g13s);
void cleanup();
std::string logo_filename;
libusb_device **devs;
libusb_context *ctx;
std::vector<Device *> g13s;
std::map<g13_keyindex, std::string> g13_key_to_name;
std::map<std::string, g13_keyindex> g13_name_to_key;
std::map<linux_keyvalue, std::string> input_key_to_name;
std::map<std::string, linux_keyvalue> input_name_to_key;
std::map<std::string, std::string> _string_config_values;
static bool running;
static void set_stop(int);
};
// inlines
inline Manager &Action::manager() {
return _keypad.manager();
}
inline const Manager &Action::manager() const {
return _keypad.manager();
}
inline const Manager &Profile::manager() const {
return _keypad.manager();
}
} // namespace G13
#endif // MANAGER_H

View File

@ -1,55 +0,0 @@
#include <string.h>
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
// convert a .pbm raw file to our custom .lpbm format
int main(int argc, char *argv[]) {
unsigned char c;
const int LEN = 256;
char s[LEN];
cin.getline(s, LEN);
if (strncmp(s, "P4", 2)) {
cerr << "input file is not .pbm (P4)" << endl;
return -1;
}
cin.getline(s, LEN);
while (s[0] == '#' || s[0] == ' ')
cin.getline(s, LEN);
unsigned int w = 0, h = 0;
if (std::sscanf(s, "%d %d", &w, &h) != 2) {
cerr << "height and width not found" << endl;
return -1;
}
if (w != 160 || h != 43) {
cerr << "incorrect width / height, mandated: 160x43, found: " << w << "x"
<< h << endl;
return -1;
}
cin >> noskipws;
int i = 0, row = -1;
unsigned char buf[160 * 48];
memset(buf, 0, 160 * 43);
while (cin >> c) {
if (i % 20 == 0) row++;
if (row == 8) row = 0;
buf[7 + (i % 20) * 8 + i / 160 * 160] |= ((c >> 0) & 0x01) << row;
buf[6 + (i % 20) * 8 + i / 160 * 160] |= ((c >> 1) & 0x01) << row;
buf[5 + (i % 20) * 8 + i / 160 * 160] |= ((c >> 2) & 0x01) << row;
buf[4 + (i % 20) * 8 + i / 160 * 160] |= ((c >> 3) & 0x01) << row;
buf[3 + (i % 20) * 8 + i / 160 * 160] |= ((c >> 4) & 0x01) << row;
buf[2 + (i % 20) * 8 + i / 160 * 160] |= ((c >> 5) & 0x01) << row;
buf[1 + (i % 20) * 8 + i / 160 * 160] |= ((c >> 6) & 0x01) << row;
buf[0 + (i % 20) * 8 + i / 160 * 160] |= ((c >> 7) & 0x01) << row;
i++;
}
if (i != 160 * 43 / 8) {
cerr << "wrong number of bytes, expected " << 160 * 43 / 8 << ", got " << i
<< endl;
}
for (int i = 0; i < 160 * 48 / 8; i++) {
cout << hex << (char)buf[i];
}
}

View File

@ -1,91 +0,0 @@
/* This file contains code for managing keys an profiles
*
*/
#include "profile.h"
#include <boost/foreach.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include "find_or_throw.h"
#include "helper.h"
#include "manager.h"
#include "repr.h"
namespace G13 {
void Key::dump(std::ostream &o) const {
o << manager().find_g13_key_name(index()) << "(" << index() << ") : ";
if (action()) {
action()->dump(o);
} else {
o << "(no action)";
}
}
void Key::parse_key(unsigned char *byte, Device *g13) {
bool key_is_down = byte[_index.offset] & _index.mask;
bool key_state_changed = g13->update(_index.index, key_is_down);
if (key_state_changed && _action) {
_action->act(*g13, key_is_down);
}
}
void Profile::_init_keys() {
int key_index = 0;
// create a Key entry for every key in G13_KEY_SEQ
#define INIT_KEY(r, data, elem) \
{ \
Key key(*this, BOOST_PP_STRINGIZE(elem), key_index++); \
_keys.push_back(key); \
}
BOOST_PP_SEQ_FOR_EACH(INIT_KEY, _, G13_KEY_SEQ)
assert(_keys.size() == G13_NUM_KEYS);
// now disable testing for keys in G13_NONPARSED_KEY_SEQ
#define MARK_NON_PARSED_KEY(r, data, elem) \
{ \
Key *key = find_key(BOOST_PP_STRINGIZE(elem)); \
assert(key); \
key->_should_parse = false; \
}
BOOST_PP_SEQ_FOR_EACH(MARK_NON_PARSED_KEY, _, G13_NONPARSED_KEY_SEQ)
}
void Profile::dump(std::ostream &o) const {
o << "Profile " << repr(name()) << std::endl;
BOOST_FOREACH (const Key &key, _keys) {
if (key.action()) {
o << " ";
key.dump(o);
o << std::endl;
}
}
}
void Profile::parse_keys(unsigned char *buf) {
buf += 3;
for (size_t i = 0; i < _keys.size(); i++) {
if (_keys[i]._should_parse) {
_keys[i].parse_key(buf, &_keypad);
}
}
}
Key *Profile::find_key(const std::string &keyname) {
auto key = _keypad.manager().find_g13_key_value(keyname);
// TODO(jtgans): Check this is the proper type
if (key >= 0 && key < static_cast<int>(_keys.size())) {
return &_keys[key];
}
return 0;
}
} // namespace G13

View File

@ -1,135 +0,0 @@
#ifndef PROFILE_H
#define PROFILE_H
#include <memory>
#include <ostream>
#include "action.h"
/*! G13_KEY_SEQ is a Boost Preprocessor sequence containing the
* G13 keys. The order is very specific, with the position of each
* item corresponding to a specific bit in the G13's USB message
* format. Do NOT remove or insert items in this list.
*/
#define G13_KEY_SEQ \
/* byte 3 */ (G1)(G2)(G3)(G4)(G5)(G6)(G7)(G8) /* byte 4 */ \
(G9)(G10)(G11)(G12)(G13)(G14)(G15)(G16) /* byte 5 */ (G17)(G18)(G19)( \
G20)(G21)(G22)(UNDEF1)(LIGHT_STATE) /* byte 6 */ \
(BD)(L1)(L2)(L3)(L4)(M1)(M2)(M3) /* byte 7 */ (MR)(LEFT)(DOWN)(TOP)( \
UNDEF3)(LIGHT)(LIGHT2)(MISC_TOGGLE)
/*! G13_NONPARSED_KEY_SEQ is a Boost Preprocessor sequence containing the
* G13 keys that shouldn't be tested input. These aren't actually keys,
* but they are in the bitmap defined by G13_KEY_SEQ.
*/
#define G13_NONPARSED_KEY_SEQ \
(UNDEF1)(LIGHT_STATE)(UNDEF3)(LIGHT)(LIGHT2)(UNDEF3)(MISC_TOGGLE)
/*! KB_INPUT_KEY_SEQ is a Boost Preprocessor sequence containing the
* names of keyboard keys we can send through binding actions.
* These correspond to KEY_xxx value definitions in <linux/input.h>,
* i.e. ESC is KEY_ESC, 1 is KEY_1, etc.
*/
#define KB_INPUT_KEY_SEQ \
(ESC)(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)(MINUS)(EQUAL)(BACKSPACE)(TAB)(Q)(W)(E)( \
R)(T)(Y)(U)(I)(O)(P)(LEFTBRACE)(RIGHTBRACE)(ENTER)(LEFTCTRL)(RIGHTCTRL)( \
A)(S)(D)(F)(G)(H)(J)(K)(L)(SEMICOLON)(APOSTROPHE)(GRAVE)(LEFTSHIFT)( \
BACKSLASH)(Z)(X)(C)(V)(B)(N)(M)(COMMA)(DOT)(SLASH)(RIGHTSHIFT)( \
KPASTERISK)(LEFTALT)(RIGHTALT)(SPACE)(CAPSLOCK)(F1)(F2)(F3)(F4)(F5)(F6)( \
F7)(F8)(F9)(F10)(F11)(F12)(NUMLOCK)(SCROLLLOCK)(KP7)(KP8)(KP9)(KPMINUS)( \
KP4)(KP5)(KP6)(KPPLUS)(KP1)(KP2)(KP3)(KP0)(KPDOT)(LEFT)(RIGHT)(UP)( \
DOWN)(PAGEUP)(PAGEDOWN)(HOME)(END)(INSERT)(DELETE)
namespace G13 {
class Device;
class Key;
class Profile;
/*! manages the bindings for a G13 key
*
*/
class Key : public Actionable<Profile> {
public:
void dump(std::ostream &o) const;
g13_keyindex index() const {
return _index.index;
}
void parse_key(unsigned char *byte, Device *g13);
protected:
struct KeyIndex {
KeyIndex(int key) : index(key), offset(key / 8), mask(1 << (key % 8)) {
}
int index;
unsigned char offset;
unsigned char mask;
};
// Profile is the only class able to instantiate Keys
friend class Profile;
Key(Profile &mode, const std::string &name, int index)
: Actionable<Profile>(mode, name),
_index(index),
_should_parse(true) {
}
Key(Profile &mode, const Key &key)
: Actionable<Profile>(mode, key.name()),
_index(key._index),
_should_parse(key._should_parse) {
set_action(key.action());
}
KeyIndex _index;
bool _should_parse;
};
/*!
* Represents a set of configured key mappings
*
* This allows a keypad to have multiple configured
* profiles and switch between them easily
*/
class Profile {
public:
Profile(Device &keypad, const std::string &name_arg)
: _keypad(keypad),
_name(name_arg) {
_init_keys();
}
Profile(const Profile &other, const std::string &name_arg)
: _keypad(other._keypad),
_name(name_arg),
_keys(other._keys) {
}
// search key by G13 keyname
Key *find_key(const std::string &keyname);
void dump(std::ostream &o) const;
void parse_keys(unsigned char *buf);
const std::string &name() const {
return _name;
}
const Manager &manager() const;
protected:
Device &_keypad;
std::string _name;
std::vector<Key> _keys;
void _init_keys();
};
typedef std::shared_ptr<Profile> ProfilePtr;
} // namespace G13
#endif // PROFILE_H

View File

@ -1,55 +0,0 @@
#include "repr.h"
#include <ostream>
namespace G13 {
void string_repr_out::write_on(std::ostream &o) const {
const char *cp = s.c_str();
const char *end = cp + s.size();
o << "\"";
while (cp < end) {
switch (*cp) {
case '\n':
o << "\\n";
break;
case '\r':
o << "\\r";
break;
case '\0':
o << "\\0";
break;
case '\t':
o << "\\t";
break;
case '\\':
case '\'':
case '\"':
o << "\\" << *cp;
break;
default: {
char c = *cp;
if (c < 32) {
char hi = '0' + (c & 0x0f);
char lo = '0' + ((c >> 4) & 0x0f);
o << "\\x" << hi << lo;
} else {
o << c;
}
}
}
cp++;
}
o << "\"";
};
} // namespace G13

View File

@ -1,37 +0,0 @@
#ifndef REPR_H
#define REPR_H
#include <ostream>
#include <string>
namespace G13 {
struct string_repr_out {
string_repr_out(const std::string &str) : s(str) {
}
void write_on(std::ostream &) const;
std::string s;
};
inline std::ostream &operator<<(std::ostream &o, const string_repr_out &sro) {
sro.write_on(o);
return o;
}
template <class T>
inline const T &repr(const T &v) {
return v;
}
inline string_repr_out repr(const char *s) {
return string_repr_out(s);
}
inline string_repr_out repr(const std::string &s) {
return string_repr_out(s);
}
} // namespace G13
#endif // REPR_H

View File

@ -1,173 +0,0 @@
/* This file contains code for managing keys and profiles
*
*/
#include <boost/foreach.hpp>
#include <iomanip>
#include <iostream>
#include "device.h"
namespace G13 {
Stick::Stick(Device &keypad)
: _keypad(keypad),
_bounds(0, 0, 255, 255),
_center_pos(127, 127),
_north_pos(127, 0) {
_stick_mode = STICK_KEYS;
auto add_zone = [this, &keypad](const std::string &name, double x1, double y1,
double x2, double y2) {
_zones.push_back(StickZone(
*this, "STICK_" + name, ZoneBounds(x1, y1, x2, y2),
ActionPtr(new Action_Keys(keypad, "KEY_" + name))));
};
add_zone("UP", 0.0, 0.1, 1.0, 0.3);
add_zone("DOWN", 0.0, 0.7, 1.0, 0.9);
add_zone("LEFT", 0.0, 0.0, 0.2, 1.0);
add_zone("RIGHT", 0.8, 0.0, 1.0, 1.0);
add_zone("PAGEUP", 0.0, 0.0, 1.0, 0.1);
add_zone("PAGEDOWN", 0.0, 0.9, 1.0, 1.0);
}
StickZone *Stick::zone(const std::string &name, bool create) {
BOOST_FOREACH (StickZone &zone, _zones) {
if (zone.name() == name) {
return &zone;
}
}
if (create) {
_zones.push_back(
StickZone(*this, name, ZoneBounds(0.0, 0.0, 0.0, 0.0)));
return zone(name);
}
return 0;
}
void Stick::set_mode(stick_mode_t m) {
if (m == _stick_mode) {
return;
}
if (_stick_mode == STICK_CALCENTER || _stick_mode == STICK_CALBOUNDS ||
_stick_mode == STICK_CALNORTH) {
_recalc_calibrated();
}
_stick_mode = m;
if (_stick_mode == STICK_CALBOUNDS) {
_bounds.tl = StickCoord(255, 255);
_bounds.br = StickCoord(0, 0);
}
}
void Stick::_recalc_calibrated() {
}
void Stick::remove_zone(const StickZone &zone) {
StickZone target(zone);
_zones.erase(std::remove(_zones.begin(), _zones.end(), target), _zones.end());
}
void Stick::dump(std::ostream &out) const {
BOOST_FOREACH (const StickZone &zone, _zones) {
zone.dump(out);
out << std::endl;
}
}
void StickZone::dump(std::ostream &out) const {
out << " " << std::setw(20) << name() << " " << _bounds << " ";
if (action()) {
action()->dump(out);
} else {
out << " (no action)";
}
}
void StickZone::test(const ZoneCoord &loc) {
if (!_action) return;
bool prior_active = _active;
_active = _bounds.contains(loc);
if (!_active) {
if (prior_active) {
_action->act(false);
}
} else {
_action->act(true);
}
}
StickZone::StickZone(Stick &stick, const std::string &name,
const ZoneBounds &b, ActionPtr action)
: Actionable<Stick>(stick, name),
_active(false),
_bounds(b) {
set_action(action);
}
void Stick::parse_joystick(unsigned char *buf) {
_current_pos.x = buf[1];
_current_pos.y = buf[2];
// update targets if we're in calibration mode
switch (_stick_mode) {
case STICK_CALCENTER:
_center_pos = _current_pos;
return;
case STICK_CALNORTH:
_north_pos = _current_pos;
return;
case STICK_CALBOUNDS:
_bounds.expand(_current_pos);
return;
default:
break;
};
// determine our normalized position
double dx = 0.5;
if (_current_pos.x <= _center_pos.x) {
dx = _current_pos.x - _bounds.tl.x;
dx /= (_center_pos.x - _bounds.tl.x) * 2;
} else {
dx = _bounds.br.x - _current_pos.x;
dx /= (_bounds.br.x - _center_pos.x) * 2;
dx = 1.0 - dx;
}
double dy = 0.5;
if (_current_pos.y <= _center_pos.y) {
dy = _current_pos.y - _bounds.tl.y;
dy /= (_center_pos.y - _bounds.tl.y) * 2;
} else {
dy = _bounds.br.y - _current_pos.y;
dy /= (_bounds.br.y - _center_pos.y) * 2;
dy = 1.0 - dy;
}
G13_LOG(trace, "x=" << _current_pos.x << " y=" << _current_pos.y
<< " dx=" << dx << " dy=" << dy);
ZoneCoord jpos(dx, dy);
if (_stick_mode == STICK_ABSOLUTE) {
_keypad.send_event(EV_ABS, ABS_X, _current_pos.x);
_keypad.send_event(EV_ABS, ABS_Y, _current_pos.y);
} else if (_stick_mode == STICK_KEYS) {
BOOST_FOREACH (StickZone &zone, _zones) { zone.test(jpos); }
return;
}
}
} // namespace G13

View File

@ -1,74 +0,0 @@
#ifndef STICK_H
#define STICK_H
#include "action.h"
#include "bounds.h"
#include "coord.h"
namespace G13 {
class Stick;
typedef Coord<int> StickCoord;
typedef Bounds<int> StickBounds;
typedef Coord<double> ZoneCoord;
typedef Bounds<double> ZoneBounds;
class StickZone : public Actionable<Stick> {
public:
StickZone(Stick &, const std::string &name, const ZoneBounds &,
ActionPtr = 0);
bool operator==(const StickZone &other) const {
return _name == other._name;
}
void dump(std::ostream &) const;
void parse_key(unsigned char *byte, Device *g13);
void test(const ZoneCoord &loc);
void set_bounds(const ZoneBounds &bounds) {
_bounds = bounds;
}
protected:
bool _active;
ZoneBounds _bounds;
};
typedef boost::shared_ptr<StickZone> StickZonePtr;
class Stick {
public:
Stick(Device &keypad);
void parse_joystick(unsigned char *buf);
void set_mode(stick_mode_t);
StickZone *zone(const std::string &, bool create = false);
void remove_zone(const StickZone &zone);
const std::vector<StickZone> &zones() const {
return _zones;
}
void dump(std::ostream &) const;
protected:
void _recalc_calibrated();
Device &_keypad;
std::vector<StickZone> _zones;
StickBounds _bounds;
StickCoord _center_pos;
StickCoord _north_pos;
StickCoord _current_pos;
stick_mode_t _stick_mode;
};
} // namespace G13
#endif // STICK_H

View File

@ -1,98 +0,0 @@
#!/usr/bin/python3
import gi
import os
import os.path
import threading
import time
import traceback
import xdg.BaseDirectory as basedir
import json
from g13gui.model import PreferencesStore
from g13gui.common import PROFILES_CONFIG_PATH
from g13gui.common import VERSION
gi.require_version('Gtk', '3.0')
from gi.repository import GObject
class UploadTask():
def __init__(self, commands):
self._commands = str.encode(commands)
def run(self, outfp, infp, callback):
bytes_written = 0
while bytes_written < len(self._commands):
result = os.write(outfp, self._commands[bytes_written:])
if result > 0:
bytes_written = result + bytes_written
callback(bytes_written / len(self._commands))
callback(1.0)
class SaveTask():
def __init__(self, prefs):
self._prefs = prefs
def run(self, outfp, infp, callback):
PreferencesStore.storePrefs(self._prefs)
G13D_IN_FIFO = "/run/g13d/in"
G13D_OUT_FIFO = "/run/g13d/out"
class G13DWorker(threading.Thread):
def __init__(self, q, window):
threading.Thread.__init__(self, daemon=True)
self._mainWindow = window
self._queue = q
self._connected = False
def _connect(self):
try:
self._outfp = os.open(G13D_IN_FIFO, os.O_WRONLY)
self._infp = os.open(G13D_OUT_FIFO, os.O_RDONLY)
except FileNotFoundError:
self._outfp = None
self._infp = None
self._connected = False
self._mainWindow.emit("daemon-connection-changed", False)
time.sleep(10)
except Exception as err:
self._outfp = None
self._infp = None
self._connected = False
print("Unknown exception occurred: %s %s" % (type(err), err))
self._mainWindow.emit("daemon-connection-changed", False)
time.sleep(10)
else:
self._mainWindow.emit("daemon-connection-changed", True)
self._connected = True
def run(self):
while True:
while not self._connected:
self._connect()
item = self._queue.get()
try:
item.run(self._outfp, self._infp, self.callback)
except BrokenPipeError as err:
print("g13d connection broken: %s" % (err))
self._connected = False
except Exception as err:
traceback.print_exc()
finally:
self._queue.task_done()
def callback(self, percentage):
self._mainWindow.emit("uploading", percentage)
def getQueue(self):
return self._queue