mirror of
https://github.com/jtgans/g13gui.git
synced 2025-06-20 08:23:50 -04:00
g13d: Kill off the old daemon
We no longer need this -- g13gui.g13 does everything and more.
This commit is contained in:
parent
8ebe1e2fc2
commit
f4daed3148
@ -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\")
|
|
||||||
")
|
|
@ -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
|
|
139
g13d/action.h
139
g13d/action.h
@ -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
|
|
@ -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
|
|
@ -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
|
|
27
g13d/coord.h
27
g13d/coord.h
@ -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
|
|
625
g13d/device.cc
625
g13d/device.cc
@ -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
|
|
135
g13d/device.h
135
g13d/device.h
@ -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 ¤t_font() {
|
|
||||||
return *_current_font;
|
|
||||||
}
|
|
||||||
Profile ¤t_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
|
|
@ -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
|
|
65
g13d/font.cc
65
g13d/font.cc
@ -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
|
|
57
g13d/font.h
57
g13d/font.h
@ -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
|
|
360
g13d/font8x8.h
360
g13d/font8x8.h
@ -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 ÿ
|
|
||||||
};
|
|
60
g13d/g13.h
60
g13d/g13.h
@ -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
|
|
@ -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
|
|
160
g13d/lcd.cc
160
g13d/lcd.cc
@ -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
|
|
46
g13d/lcd.h
46
g13d/lcd.h
@ -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
|
|
86
g13d/logo.h
86
g13d/logo.h
@ -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
|
|
66
g13d/main.cc
66
g13d/main.cc
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
279
g13d/manager.cc
279
g13d/manager.cc
@ -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
|
|
@ -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
|
|
@ -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];
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
135
g13d/profile.h
135
g13d/profile.h
@ -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
|
|
55
g13d/repr.cc
55
g13d/repr.cc
@ -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
|
|
37
g13d/repr.h
37
g13d/repr.h
@ -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
|
|
173
g13d/stick.cc
173
g13d/stick.cc
@ -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
|
|
74
g13d/stick.h
74
g13d/stick.h
@ -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
|
|
@ -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
|
|
Loading…
Reference in New Issue
Block a user