diff --git a/g13d/CMakeLists.txt b/g13d/CMakeLists.txt index 5908d9d..8538535 100644 --- a/g13d/CMakeLists.txt +++ b/g13d/CMakeLists.txt @@ -11,14 +11,15 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror") add_executable(pbm2lpbm pbm2lpbm.cc) add_executable(g13d + device.cc g13.cc g13_fonts.cc g13_keys.cc g13_lcd.cc - g13_log.cc g13_main.cc g13_stick.cc helper.cc + manager.cc ) target_compile_definitions(g13d PRIVATE BOOST_LOG_DYN_LINK=1) diff --git a/g13d/action.h b/g13d/action.h new file mode 100644 index 0000000..c175192 --- /dev/null +++ b/g13d/action.h @@ -0,0 +1,111 @@ +#ifndef ACTION_H +#define ACTION_H + +#include +#include +#include + +#include "g13.h" + +namespace G13 { + +class G13_Device; +class G13_Manager; + +/*! holds potential actions which can be bound to G13 activity + * + */ +class G13_Action { +public: + G13_Action(G13_Device &keypad) : _keypad(keypad) {} + virtual ~G13_Action(); + + virtual void act(G13_Device &, bool is_down) = 0; + virtual void dump(std::ostream &) const = 0; + + void act(bool is_down) { act(keypad(), is_down); } + + G13_Device &keypad() { return _keypad; } + const G13_Device &keypad() const { return _keypad; } + + G13_Manager &manager(); + const G13_Manager &manager() const; + +private: + G13_Device &_keypad; +}; + +/*! + * action to send one or more keystrokes + */ +class G13_Action_Keys : public G13_Action { +public: + G13_Action_Keys(G13_Device &keypad, const std::string &keys); + virtual ~G13_Action_Keys(); + + virtual void act(G13_Device &, bool is_down); + virtual void dump(std::ostream &) const; + + std::vector _keys; +}; + +/*! + * action to send a string to the output pipe + */ +class G13_Action_PipeOut : public G13_Action { +public: + G13_Action_PipeOut(G13_Device &keypad, const std::string &out); + virtual ~G13_Action_PipeOut(); + + virtual void act(G13_Device &, bool is_down); + virtual void dump(std::ostream &) const; + + std::string _out; +}; + +/*! + * action to send a command to the g13 + */ +class G13_Action_Command : public G13_Action { +public: + G13_Action_Command(G13_Device &keypad, const std::string &cmd); + virtual ~G13_Action_Command(); + + virtual void act(G13_Device &, bool is_down); + virtual void dump(std::ostream &) const; + + std::string _cmd; +}; + +typedef std::shared_ptr G13_ActionPtr; + +template class G13_Actionable { +public: + G13_Actionable(PARENT_T &parent_arg, const std::string &name) + : _name(name), _parent_ptr(&parent_arg) { + } + + virtual ~G13_Actionable() { + _parent_ptr = 0; + } + + G13_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; } + G13_Manager &manager() { return _parent_ptr->manager(); } + const G13_Manager &manager() const { return _parent_ptr->manager(); } + + virtual void set_action(const G13_ActionPtr &action) { _action = action; } + +protected: + std::string _name; + G13_ActionPtr _action; + +private: + PARENT_T *_parent_ptr; +}; + +} // namespace G13 + +#endif // ACTION_H diff --git a/g13d/bounds.h b/g13d/bounds.h new file mode 100644 index 0000000..a61bbba --- /dev/null +++ b/g13d/bounds.h @@ -0,0 +1,51 @@ +#ifndef BOUNDS_H +#define BOUNDS_H + +#include + +#include "coord.h" + +namespace G13 { + +template class Bounds { +public: + Bounds(const Coord &_tl, const Coord &_br) + : tl(_tl), br(_br) { + } + + Bounds(T x1, T y1, T x2, T y2) : tl(x1, y1), br(x2, y2) { + } + + bool contains(const Coord &pos) const { + return tl.x <= pos.x && tl.y <= pos.y && pos.x <= br.x && pos.y <= br.y; + } + + void expand(const Coord &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 tl; + Coord br; +}; + +template +std::ostream &operator<<(std::ostream &o, const Bounds &b) { + o << "{ " + << b.tl.x << " x " << b.tl.y + << " / " + << b.br.x << " x " << b.br.y + << " }"; + + return o; +}; + +} // namespace G13 + +#endif // BOUNDS_H diff --git a/g13d/coord.h b/g13d/coord.h new file mode 100644 index 0000000..e143fd8 --- /dev/null +++ b/g13d/coord.h @@ -0,0 +1,28 @@ +#ifndef COORD_H +#define COORD_H + +namespace G13 { + +template class Coord { +public: + Coord() + : x(), y() { + } + + Coord(T _x, T _y) + : x(_x), y(_y) { + } + + T x; + T y; +}; + +template +std::ostream &operator<<(std::ostream &o, const Coord &c) { + o << "{ " << c.x << " x " << c.y << " }"; + return o; +}; + +} // namespace G13 + +#endif // COORD_H diff --git a/g13d/device.cc b/g13d/device.cc new file mode 100644 index 0000000..8acc4d3 --- /dev/null +++ b/g13d/device.cc @@ -0,0 +1,60 @@ + + +#include "device.h" + +namespace G13 { + +void G13_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 G13_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 G13_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 G13_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; + } +} + +} // namespace G13 diff --git a/g13d/device.h b/g13d/device.h new file mode 100644 index 0000000..5e310fa --- /dev/null +++ b/g13d/device.h @@ -0,0 +1,117 @@ +#ifndef DEVICE_H +#define DEVICE_H + +#include +#include + +#include +#include +#include + +#include "lcd.h" +#include "stick.h" +#include "font.h" +#include "profile.h" + +namespace G13 { + +class G13_Manager; + +class G13_Device { +public: + G13_Device(G13_Manager &manager, libusb_device_handle *handle, int id); + + G13_Manager &manager() { return _manager; } + const G13_Manager &manager() const { return _manager; } + + G13_LCD &lcd() { return _lcd; } + const G13_LCD &lcd() const { return _lcd; } + G13_Stick &stick() { return _stick; } + const G13_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); + + G13_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 G13_Manager + void cleanup(); + void register_context(libusb_context *ctx); + void write_lcd_file(const std::string &filename); + + G13_Font ¤t_font() { return *_current_font; } + G13_Profile ¤t_profile() { return *_current_profile; } + + int id_within_manager() const { return _id_within_manager; } + + typedef std::function COMMAND_FUNCTION; + typedef std::map CommandFunctionTable; + +protected: + void _init_fonts(); + void init_lcd(); + void _init_commands(); + + // typedef void (COMMAND_FUNCTION)( G13_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 _fonts; + FontPtr _current_font; + std::map _profiles; + ProfilePtr _current_profile; + + G13_Manager &_manager; + G13_LCD _lcd; + G13_Stick _stick; + + bool keys[G13_NUM_KEYS]; +}; + +inline bool G13_Device::is_set(int key) { + return keys[key]; +} + +inline bool G13_Device::update(int key, bool v) { + bool old = keys[key]; + keys[key] = v; + return old != v; +} + +} // namespace G13 + +#endif // DEVICE_H diff --git a/g13d/find_or_throw.h b/g13d/find_or_throw.h new file mode 100644 index 0000000..1c886b3 --- /dev/null +++ b/g13d/find_or_throw.h @@ -0,0 +1,38 @@ +#ifndef FIND_OR_THROW_H +#define FIND_OR_THROW_H + +#include + +namespace G13 { + +class NotFoundException : public std::exception { +public: + const char *what() throw(); +}; + +template +inline const V_T &find_or_throw(const std::map &m, + const K_T &target) { + auto i = m.find(target); + + if (i == m.end()) { + throw NotFoundException(); + } + + return i->second; +}; + +template +inline V_T &find_or_throw(std::map &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 diff --git a/g13d/font.h b/g13d/font.h new file mode 100644 index 0000000..08c271c --- /dev/null +++ b/g13d/font.h @@ -0,0 +1,51 @@ +#ifndef FONT_H +#define FONT_H + +#include + +#include + +namespace G13 { + +class G13_FontChar { +public: + static const int CHAR_BUF_SIZE = 8; + enum FONT_FLAGS { FF_ROTATE = 0x01 }; + + G13_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 G13_Font { +public: + G13_Font(); + G13_Font(const std::string &name, unsigned int width = 8); + + void set_character(unsigned int c, unsigned char *data); + + template + 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 G13_FontChar &char_data(unsigned int x) { return _chars[x]; } + +protected: + std::string _name; + unsigned int _width; + + G13_FontChar _chars[256]; +}; + +typedef std::shared_ptr FontPtr; + +} // namespace G13 + +#endif // FONT_H diff --git a/g13d/g13.cc b/g13d/g13.cc index 4e86d6a..b3fbd3d 100644 --- a/g13d/g13.cc +++ b/g13d/g13.cc @@ -1,129 +1,39 @@ +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "device.h" #include "g13.h" #include "logo.h" -#include - -#if 0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -using namespace std; - -// ************************************************************************* +#include "manager.h" +#include "repr.h" +#include "find_or_throw.h" #define CONTROL_DIR std::string("/tmp/") namespace G13 { -// ************************************************************************* - -void G13_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 G13_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 G13_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 G13_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 G13_Manager::discover_g13s(libusb_device **devs, ssize_t count, - vector &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 G13_Device(*this, handle, g13s.size())); - } - } -} - -// ************************************************************************* - int g13_create_fifo(const char *fifo_name) { - - // mkfifo(g13->fifo_name(), 0777); - didn't work mkfifo(fifo_name, 0666); - chmod(fifo_name, 0777); - + chmod(fifo_name, 0660); return open(fifo_name, O_RDWR | O_NONBLOCK); } -// ************************************************************************* - -int g13_create_uinput(G13_Device *g13) { +int g13_create_uinput(void) { struct uinput_user_dev uinp; const char *dev_uinput_fname = access("/dev/input/uinput", F_OK) == 0 @@ -197,7 +107,7 @@ void G13_Device::register_context(libusb_context *_ctx) { write_lcd(g13_logo, sizeof(g13_logo)); - _uinput_fid = g13_create_uinput(this); + _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()); @@ -238,7 +148,6 @@ static std::string describe_libusb_error_code(int code) { 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)( @@ -468,15 +377,17 @@ G13_ActionPtr G13_Device::make_action(const std::string &action) { // ************************************************************************* void G13_Device::dump(std::ostream &o, int detail) { - o << "G13 id=" << id_within_manager() << endl; - o << " input_pipe_name=" << repr(_input_pipe_name) << endl; - o << " output_pipe_name=" << repr(_output_pipe_name) << endl; - o << " current_profile=" << _current_profile->name() << endl; - o << " current_font=" << _current_font->name() << std::endl; + 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 { @@ -513,11 +424,24 @@ struct command_adder { BOOST_PP_STRINGIZE(name)); \ BOOST_PP_CAT(add_, name) += [this](const char *remainder) +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; +}; + void G13_Device::_init_commands() { - - using Helper::advance_ws; - - G13_DEVICE_COMMAND(out) { lcd().write_string(remainder); } + G13_DEVICE_COMMAND(out) { + lcd().write_string(remainder); + } G13_DEVICE_COMMAND(pos) { int row, col; @@ -548,7 +472,6 @@ void G13_Device::_init_commands() { } 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); } @@ -562,15 +485,15 @@ void G13_Device::_init_commands() { } } - G13_DEVICE_COMMAND(stickmode) { - - std::string mode = 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)) { @@ -594,9 +517,11 @@ void G13_Device::_init_commands() { 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 G13_CommandException("bad bounds format"); } + zone->set_bounds(G13_ZoneBounds(x1, y1, x2, y2)); } else if (operation == "del") { _stick.remove_zone(*zone); @@ -626,22 +551,20 @@ void G13_Device::_init_commands() { manager().set_log_level(level); } - G13_DEVICE_COMMAND(refresh) { lcd().image_send(); } + G13_DEVICE_COMMAND(refresh) { + lcd().image_send(); + } G13_DEVICE_COMMAND(clear) { lcd().image_clear(); lcd().image_send(); - } - - ; + }; } void G13_Device::command(char const *str) { const char *remainder = str; try { - using Helper::advance_ws; - std::string cmd; advance_ws(remainder, cmd); @@ -649,15 +572,19 @@ void G13_Device::command(char const *str) { 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()); } } -G13_Manager::G13_Manager() : devs(0), ctx(0) {} +G13_Manager::G13_Manager() + : devs(0), ctx(0) { +} // ************************************************************************* @@ -671,6 +598,7 @@ std::string G13_Manager::string_config_value(const std::string &name) const { return ""; } } + void G13_Manager::set_string_config_value(const std::string &name, const std::string &value) { G13_LOG(info, "set_string_config_value " << name << " = " << repr(value)); @@ -707,7 +635,6 @@ std::string G13_Manager::make_pipe_name(G13_Device *d, bool is_input) { } int G13_Manager::run() { - init_keynames(); display_keys(); @@ -769,4 +696,5 @@ int G13_Manager::run() { return 0; } + } // namespace G13 diff --git a/g13d/g13.h b/g13d/g13.h index 7e3bfa7..1d0bf6a 100644 --- a/g13d/g13.h +++ b/g13d/g13.h @@ -1,22 +1,9 @@ -#ifndef __G13_H__ -#define __G13_H__ - -#include "helper.h" +#ifndef G13_H +#define G13_H #include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -// ************************************************************************* +#include namespace G13 { @@ -54,20 +41,6 @@ const LINUX_KEY_VALUE BAD_KEY_VALUE = -1; typedef int G13_KEY_INDEX; -// ************************************************************************* - -using Helper::find_or_throw; -using Helper::repr; - -// ************************************************************************* - -class G13_Action; -class G13_Stick; -class G13_LCD; -class G13_Profile; -class G13_Device; -class G13_Manager; - class G13_CommandException : public std::exception { public: G13_CommandException(const std::string &reason) : _reason(reason) {} @@ -77,462 +50,6 @@ public: std::string _reason; }; -// ************************************************************************* - -/*! holds potential actions which can be bound to G13 activity - * - */ -class G13_Action { -public: - G13_Action(G13_Device &keypad) : _keypad(keypad) {} - virtual ~G13_Action(); - - virtual void act(G13_Device &, bool is_down) = 0; - virtual void dump(std::ostream &) const = 0; - - void act(bool is_down) { act(keypad(), is_down); } - - G13_Device &keypad() { return _keypad; } - const G13_Device &keypad() const { return _keypad; } - - G13_Manager &manager(); - const G13_Manager &manager() const; - -private: - G13_Device &_keypad; -}; - -/*! - * action to send one or more keystrokes - */ -class G13_Action_Keys : public G13_Action { -public: - G13_Action_Keys(G13_Device &keypad, const std::string &keys); - virtual ~G13_Action_Keys(); - - virtual void act(G13_Device &, bool is_down); - virtual void dump(std::ostream &) const; - - std::vector _keys; -}; - -/*! - * action to send a string to the output pipe - */ -class G13_Action_PipeOut : public G13_Action { -public: - G13_Action_PipeOut(G13_Device &keypad, const std::string &out); - virtual ~G13_Action_PipeOut(); - - virtual void act(G13_Device &, bool is_down); - virtual void dump(std::ostream &) const; - - std::string _out; -}; - -/*! - * action to send a command to the g13 - */ -class G13_Action_Command : public G13_Action { -public: - G13_Action_Command(G13_Device &keypad, const std::string &cmd); - virtual ~G13_Action_Command(); - - virtual void act(G13_Device &, bool is_down); - virtual void dump(std::ostream &) const; - - std::string _cmd; -}; - -typedef boost::shared_ptr G13_ActionPtr; - -// ************************************************************************* -template class G13_Actionable { -public: - G13_Actionable(PARENT_T &parent_arg, const std::string &name) - : _name(name), _parent_ptr(&parent_arg) {} - virtual ~G13_Actionable() { _parent_ptr = 0; } - - G13_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; } - G13_Manager &manager() { return _parent_ptr->manager(); } - const G13_Manager &manager() const { return _parent_ptr->manager(); } - - virtual void set_action(const G13_ActionPtr &action) { _action = action; } - -protected: - std::string _name; - G13_ActionPtr _action; - -private: - PARENT_T *_parent_ptr; -}; - -// ************************************************************************* -/*! manages the bindings for a G13 key - * - */ -class G13_Key : public G13_Actionable { -public: - void dump(std::ostream &o) const; - G13_KEY_INDEX index() const { return _index.index; } - - void parse_key(unsigned char *byte, G13_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; - }; - - // G13_Profile is the only class able to instantiate G13_Keys - friend class G13_Profile; - - G13_Key(G13_Profile &mode, const std::string &name, int index) - : G13_Actionable(mode, name), _index(index), - _should_parse(true) {} - - G13_Key(G13_Profile &mode, const G13_Key &key) - : G13_Actionable(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 G13_Profile { -public: - G13_Profile(G13_Device &keypad, const std::string &name_arg) - : _keypad(keypad), _name(name_arg) { - _init_keys(); - } - G13_Profile(const G13_Profile &other, const std::string &name_arg) - : _keypad(other._keypad), _name(name_arg), _keys(other._keys) {} - - // search key by G13 keyname - G13_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 G13_Manager &manager() const; - -protected: - G13_Device &_keypad; - std::string _name; - std::vector _keys; - - void _init_keys(); -}; - -typedef boost::shared_ptr ProfilePtr; - -class G13_FontChar { -public: - static const int CHAR_BUF_SIZE = 8; - enum FONT_FLAGS { FF_ROTATE = 0x01 }; - - G13_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 G13_Font { -public: - G13_Font(); - G13_Font(const std::string &name, unsigned int width = 8); - - void set_character(unsigned int c, unsigned char *data); - - template - 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 G13_FontChar &char_data(unsigned int x) { return _chars[x]; } - -protected: - std::string _name; - unsigned int _width; - - G13_FontChar _chars[256]; - - // unsigned char font_basic[256][8]; - // unsigned char font_inverted[256][8]; -}; -typedef boost::shared_ptr FontPtr; - -class G13_LCD { -public: - G13_LCD(G13_Device &keypad); - - G13_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); -}; -using Helper::repr; - -typedef Helper::Coord G13_StickCoord; -typedef Helper::Bounds G13_StickBounds; -typedef Helper::Coord G13_ZoneCoord; -typedef Helper::Bounds G13_ZoneBounds; - -// ************************************************************************* - -class G13_StickZone : public G13_Actionable { -public: - G13_StickZone(G13_Stick &, const std::string &name, const G13_ZoneBounds &, - G13_ActionPtr = 0); - - bool operator==(const G13_StickZone &other) const { - return _name == other._name; - } - - void dump(std::ostream &) const; - - void parse_key(unsigned char *byte, G13_Device *g13); - void test(const G13_ZoneCoord &loc); - void set_bounds(const G13_ZoneBounds &bounds) { _bounds = bounds; } - -protected: - bool _active; - G13_ZoneBounds _bounds; -}; - -typedef boost::shared_ptr G13_StickZonePtr; - -// ************************************************************************* - -class G13_Stick { -public: - G13_Stick(G13_Device &keypad); - - void parse_joystick(unsigned char *buf); - - void set_mode(stick_mode_t); - G13_StickZone *zone(const std::string &, bool create = false); - void remove_zone(const G13_StickZone &zone); - - const std::vector &zones() const { return _zones; } - - void dump(std::ostream &) const; - -protected: - void _recalc_calibrated(); - - G13_Device &_keypad; - std::vector _zones; - - G13_StickBounds _bounds; - G13_StickCoord _center_pos; - G13_StickCoord _north_pos; - - G13_StickCoord _current_pos; - - stick_mode_t _stick_mode; -}; - -// ************************************************************************* - -class G13_Device { -public: - G13_Device(G13_Manager &manager, libusb_device_handle *handle, int id); - - G13_Manager &manager() { return _manager; } - const G13_Manager &manager() const { return _manager; } - - G13_LCD &lcd() { return _lcd; } - const G13_LCD &lcd() const { return _lcd; } - G13_Stick &stick() { return _stick; } - const G13_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); - - G13_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 G13_Manager - void cleanup(); - void register_context(libusb_context *ctx); - void write_lcd_file(const std::string &filename); - - G13_Font ¤t_font() { return *_current_font; } - G13_Profile ¤t_profile() { return *_current_profile; } - - int id_within_manager() const { return _id_within_manager; } - - typedef boost::function COMMAND_FUNCTION; - typedef std::map CommandFunctionTable; - -protected: - void _init_fonts(); - void init_lcd(); - void _init_commands(); - - // typedef void (COMMAND_FUNCTION)( G13_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 _fonts; - FontPtr _current_font; - std::map _profiles; - ProfilePtr _current_profile; - - G13_Manager &_manager; - G13_LCD _lcd; - G13_Stick _stick; - - bool keys[G13_NUM_KEYS]; -}; - -// ************************************************************************* - -/*! - * top level class, holds what would otherwise be in global variables - */ - -class G13_Manager { -public: - G13_Manager(); - - G13_KEY_INDEX find_g13_key_value(const std::string &keyname) const; - std::string find_g13_key_name(G13_KEY_INDEX) const; - - LINUX_KEY_VALUE find_input_key_value(const std::string &keyname) const; - std::string find_input_key_name(LINUX_KEY_VALUE) 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(G13_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 &g13s); - void cleanup(); - - std::string logo_filename; - libusb_device **devs; - - libusb_context *ctx; - std::vector g13s; - - std::map g13_key_to_name; - std::map g13_name_to_key; - std::map input_key_to_name; - std::map input_name_to_key; - - std::map _string_config_values; - - static bool running; - static void set_stop(int); -}; - -// ************************************************************************* - -// inlines - -inline G13_Manager &G13_Action::manager() { return _keypad.manager(); } - -inline const G13_Manager &G13_Action::manager() const { - return _keypad.manager(); -} - -inline bool G13_Device::is_set(int key) { return keys[key]; } - -inline bool G13_Device::update(int key, bool v) { - bool old = keys[key]; - keys[key] = v; - return old != v; -} - -inline const G13_Manager &G13_Profile::manager() const { - return _keypad.manager(); -} - -// ************************************************************************* - } // namespace G13 #endif // __G13_H__ diff --git a/g13d/g13_fonts.cc b/g13d/g13_fonts.cc index 1871a75..34b6dad 100644 --- a/g13d/g13_fonts.cc +++ b/g13d/g13_fonts.cc @@ -1,4 +1,5 @@ -#include "g13.h" +#include "device.h" +#include "font.h" using namespace std; diff --git a/g13d/g13_keys.cc b/g13d/g13_keys.cc index 77842d1..0168c8e 100644 --- a/g13d/g13_keys.cc +++ b/g13d/g13_keys.cc @@ -1,9 +1,15 @@ /* This file contains code for managing keys an profiles * */ -#include "g13.h" -using namespace std; +#include +#include + +#include "profile.h" +#include "manager.h" +#include "repr.h" +#include "find_or_throw.h" +#include "helper.h" namespace G13 { diff --git a/g13d/g13_lcd.cc b/g13d/g13_lcd.cc index 3fa6864..07dc629 100644 --- a/g13d/g13_lcd.cc +++ b/g13d/g13_lcd.cc @@ -18,9 +18,11 @@ A0.01 A1.01 A2.01 ... */ -#include "g13.h" +#include +#include -using namespace std; +#include "lcd.h" +#include "device.h" namespace G13 { @@ -51,16 +53,16 @@ void G13_Device::write_lcd(unsigned char *data, size_t size) { << error << ", " << bytes_written << " bytes written"); } -void G13_Device::write_lcd_file(const string &filename) { - filebuf *pbuf; - ifstream filestr; +void G13_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, ios::end, ios::in); - pbuf->pubseekpos(0, ios::in); + size = pbuf->pubseekoff(0, std::ios::end, std::ios::in); + pbuf->pubseekpos(0, std::ios::in); char buffer[size]; diff --git a/g13d/g13_main.cc b/g13d/g13_main.cc index 4f7813f..0ac2891 100644 --- a/g13d/g13_main.cc +++ b/g13d/g13_main.cc @@ -1,35 +1,30 @@ -#include "g13.h" +#include #include -#if 0 -#include -#include -#include -#include -#include -#include -#include -#include -#endif +#include + +#include "g13.h" +#include "manager.h" -using namespace std; -using namespace G13; namespace po = boost::program_options; -int main(int argc, char *argv[]) { +extern "C" { - G13_Manager manager; +int main(int argc, char *argv[]) { + G13::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 sopt_names; + auto add_string_option = [&sopt_names, &desc](const char *name, const char *description) { desc.add_options()(name, po::value(), 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"); @@ -46,8 +41,8 @@ int main(int argc, char *argv[]) { po::notify(vm); if (vm.count("help")) { - cout << argv[0] << " : user space G13 driver" << endl; - cout << desc << "\n"; + std::cout << argv[0] << " : user space G13 driver" << std::endl + << desc << "\n"; return 1; } @@ -66,4 +61,8 @@ int main(int argc, char *argv[]) { } manager.run(); + + return 0; +} + } diff --git a/g13d/g13_stick.cc b/g13d/g13_stick.cc index 93269ad..f3d0c38 100644 --- a/g13d/g13_stick.cc +++ b/g13d/g13_stick.cc @@ -1,9 +1,13 @@ /* This file contains code for managing keys and profiles * */ -#include "g13.h" -using namespace std; +#include +#include + +#include + +#include "device.h" namespace G13 { @@ -67,21 +71,23 @@ void G13_Stick::set_mode(stick_mode_t m) { } } -void G13_Stick::_recalc_calibrated() {} +void G13_Stick::_recalc_calibrated() { +} void G13_Stick::remove_zone(const G13_StickZone &zone) { G13_StickZone target(zone); _zones.erase(std::remove(_zones.begin(), _zones.end(), target), _zones.end()); } + void G13_Stick::dump(std::ostream &out) const { BOOST_FOREACH (const G13_StickZone &zone, _zones) { zone.dump(out); - out << endl; + out << std::endl; } } void G13_StickZone::dump(std::ostream &out) const { - out << " " << setw(20) << name() << " " << _bounds << " "; + out << " " << std::setw(20) << name() << " " << _bounds << " "; if (action()) { action()->dump(out); } else { diff --git a/g13d/helper.cc b/g13d/helper.cc index e693901..8ecdbd3 100644 --- a/g13d/helper.cc +++ b/g13d/helper.cc @@ -26,11 +26,11 @@ * */ -#include "helper.h" +#include "repr.h" // ************************************************************************* -namespace Helper { +namespace G13 { void string_repr_out::write_on(std::ostream &o) const { diff --git a/g13d/helper.h b/g13d/helper.h index 143fd22..8f3c091 100644 --- a/g13d/helper.h +++ b/g13d/helper.h @@ -51,115 +51,13 @@ namespace Helper { -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 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); } - -// ************************************************************************* - -class NotFoundException : public std::exception { -public: - const char *what() throw(); -}; - -template -inline const VAL_T &find_or_throw(const std::map &m, - const KEY_T &target) { - auto i = m.find(target); - if (i == m.end()) { - throw NotFoundException(); - } - return i->second; -}; - -template -inline VAL_T &find_or_throw(std::map &m, const KEY_T &target) { - auto i = m.find(target); - if (i == m.end()) { - throw NotFoundException(); - } - return i->second; -}; - -// ************************************************************************* - -template class Coord { -public: - Coord() : x(), y() {} - Coord(T _x, T _y) : x(_x), y(_y) {} - T x; - T y; -}; - -template -std::ostream &operator<<(std::ostream &o, const Coord &c) { - o << "{ " << c.x << " x " << c.y << " }"; - return o; -}; - -template class Bounds { -public: - typedef Coord CT; - Bounds(const CT &_tl, const CT &_br) : tl(_tl), br(_br) {} - Bounds(T x1, T y1, T x2, T y2) : tl(x1, y1), br(x2, y2) {} - - bool contains(const CT &pos) const { - return tl.x <= pos.x && tl.y <= pos.y && pos.x <= br.x && pos.y <= br.y; - } - - void expand(const CT &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; - } - CT tl; - CT br; -}; - -template -std::ostream &operator<<(std::ostream &o, const Bounds &b) { - o << "{ " << b.tl.x << " x " << b.tl.y << " / " << b.br.x << " x " << b.br.y - << " }"; - return o; -}; - -// ************************************************************************* - -typedef const char *CCP; -inline const char *advance_ws(CCP &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; -}; - // ************************************************************************* template struct _map_keys_out { - _map_keys_out(const MAP_T &c, const std::string &s) : container(c), sep(s) {} + _map_keys_out(const MAP_T &c, const std::string &s) + : container(c), sep(s) { + } + const MAP_T &container; std::string sep; }; diff --git a/g13d/lcd.h b/g13d/lcd.h new file mode 100644 index 0000000..85ae242 --- /dev/null +++ b/g13d/lcd.h @@ -0,0 +1,42 @@ +#ifndef LCD_H +#define LCD_H + +#include "g13.h" + +#include + +namespace G13 { + +class G13_Device; + +class G13_LCD { +public: + G13_LCD(G13_Device &keypad); + + G13_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 diff --git a/g13d/g13_log.cc b/g13d/manager.cc similarity index 54% rename from g13d/g13_log.cc rename to g13d/manager.cc index d8a6e56..66a7e48 100644 --- a/g13d/g13_log.cc +++ b/g13d/manager.cc @@ -1,6 +1,3 @@ -#include "g13.h" -#include - #include #include #include @@ -12,10 +9,44 @@ #include #include -using namespace std; +#include +#include + +#include "device.h" +#include "manager.h" namespace G13 { +void G13_Manager::discover_g13s(libusb_device **devs, ssize_t count, + std::vector &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 G13_Device(*this, handle, g13s.size())); + } + } +} + void G13_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); @@ -38,5 +69,4 @@ void G13_Manager::set_log_level(const std::string &level) { G13_LOG(error, "unknown log level" << level); } - } // namespace G13 diff --git a/g13d/manager.h b/g13d/manager.h new file mode 100644 index 0000000..0b5d433 --- /dev/null +++ b/g13d/manager.h @@ -0,0 +1,79 @@ +#ifndef MANAGER_H +#define MANAGER_H + +#include +#include +#include + +#include "action.h" +#include "device.h" + +namespace G13 { + +/*! + * top level class, holds what would otherwise be in global variables + */ +class G13_Manager { +public: + G13_Manager(); + + G13_KEY_INDEX find_g13_key_value(const std::string &keyname) const; + std::string find_g13_key_name(G13_KEY_INDEX) const; + + LINUX_KEY_VALUE find_input_key_value(const std::string &keyname) const; + std::string find_input_key_name(LINUX_KEY_VALUE) 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(G13_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 &g13s); + void cleanup(); + + std::string logo_filename; + libusb_device **devs; + + libusb_context *ctx; + std::vector g13s; + + std::map g13_key_to_name; + std::map g13_name_to_key; + std::map input_key_to_name; + std::map input_name_to_key; + + std::map _string_config_values; + + static bool running; + static void set_stop(int); +}; + +// ************************************************************************* + +// inlines + +inline G13_Manager &G13_Action::manager() { + return _keypad.manager(); +} + +inline const G13_Manager &G13_Action::manager() const { + return _keypad.manager(); +} + +inline const G13_Manager &G13_Profile::manager() const { + return _keypad.manager(); +} + +} // namespace G13 + +#endif // MANAGER_H diff --git a/g13d/profile.h b/g13d/profile.h new file mode 100644 index 0000000..40cfa73 --- /dev/null +++ b/g13d/profile.h @@ -0,0 +1,91 @@ +#ifndef PROFILE_H +#define PROFILE_H + +#include +#include + +#include "action.h" + +namespace G13 { + +class G13_Device; +class G13_Key; +class G13_Profile; + +/*! manages the bindings for a G13 key + * + */ +class G13_Key : public G13_Actionable { +public: + void dump(std::ostream &o) const; + G13_KEY_INDEX index() const { return _index.index; } + + void parse_key(unsigned char *byte, G13_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; + }; + + // G13_Profile is the only class able to instantiate G13_Keys + friend class G13_Profile; + + G13_Key(G13_Profile &mode, const std::string &name, int index) + : G13_Actionable(mode, name), _index(index), + _should_parse(true) { + } + + G13_Key(G13_Profile &mode, const G13_Key &key) + : G13_Actionable(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 G13_Profile { +public: + G13_Profile(G13_Device &keypad, const std::string &name_arg) + : _keypad(keypad), _name(name_arg) { + _init_keys(); + } + + G13_Profile(const G13_Profile &other, const std::string &name_arg) + : _keypad(other._keypad), _name(name_arg), _keys(other._keys) { + } + + // search key by G13 keyname + G13_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 G13_Manager &manager() const; + +protected: + G13_Device &_keypad; + std::string _name; + std::vector _keys; + + void _init_keys(); +}; + +typedef std::shared_ptr ProfilePtr; + +} // namespace G13 + +#endif // PROFILE_H diff --git a/g13d/repr.h b/g13d/repr.h new file mode 100644 index 0000000..b184ac9 --- /dev/null +++ b/g13d/repr.h @@ -0,0 +1,35 @@ +#ifndef REPR_H +#define REPR_H + +#include +#include + +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 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); +} + +} + +#endif // REPR_H diff --git a/g13d/stick.h b/g13d/stick.h new file mode 100644 index 0000000..6dc4aec --- /dev/null +++ b/g13d/stick.h @@ -0,0 +1,70 @@ +#ifndef STICK_H +#define STICK_H + +#include "coord.h" +#include "bounds.h" +#include "action.h" + +namespace G13 { + +class G13_Stick; + +typedef Coord G13_StickCoord; +typedef Bounds G13_StickBounds; +typedef Coord G13_ZoneCoord; +typedef Bounds G13_ZoneBounds; + +class G13_StickZone : public G13_Actionable { +public: + G13_StickZone(G13_Stick &, const std::string &name, const G13_ZoneBounds &, + G13_ActionPtr = 0); + + bool operator==(const G13_StickZone &other) const { + return _name == other._name; + } + + void dump(std::ostream &) const; + + void parse_key(unsigned char *byte, G13_Device *g13); + void test(const G13_ZoneCoord &loc); + void set_bounds(const G13_ZoneBounds &bounds) { _bounds = bounds; } + +protected: + bool _active; + G13_ZoneBounds _bounds; +}; + +typedef boost::shared_ptr G13_StickZonePtr; + +class G13_Stick { +public: + G13_Stick(G13_Device &keypad); + + void parse_joystick(unsigned char *buf); + + void set_mode(stick_mode_t); + G13_StickZone *zone(const std::string &, bool create = false); + void remove_zone(const G13_StickZone &zone); + + const std::vector &zones() const { return _zones; } + + void dump(std::ostream &) const; + +protected: + void _recalc_calibrated(); + + G13_Device &_keypad; + std::vector _zones; + + G13_StickBounds _bounds; + G13_StickCoord _center_pos; + G13_StickCoord _north_pos; + + G13_StickCoord _current_pos; + + stick_mode_t _stick_mode; +}; + +} // namespace G13 + +#endif // STICK_H