From 88a2aea3c2590cdc4583b09661fa2a5bfe9280d7 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 27 Aug 2015 17:49:16 -0400 Subject: [PATCH] etekcity: retrieve and dump the macros Still not hooked up in the library, but re-assigning back a different hard-coded macro works. This also re-introduce the dependency on libevdev for the lib. Signed-off-by: Benjamin Tissoires --- src/Makefile.am | 3 +- src/driver-etekcity.c | 200 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 185 insertions(+), 18 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 73cc782f..b1e48dfe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,10 +21,11 @@ libratbag_la_SOURCES = \ libratbag-private.h \ libratbag-util.h -libratbag_la_LIBADD = $(LIBUDEV_LIBS) +libratbag_la_LIBADD = $(LIBUDEV_LIBS) $(LIBEVDEV_LIBS) libratbag_la_CFLAGS = -I$(top_srcdir)/include \ $(LIBUDEV_CFLAGS) \ + $(LIBEVDEV_CFLAGS) \ $(GCC_CFLAGS) EXTRA_libratbag_la_DEPENDENCIES = $(srcdir)/libratbag.sym diff --git a/src/driver-etekcity.c b/src/driver-etekcity.c index 48c5788c..08db9222 100644 --- a/src/driver-etekcity.c +++ b/src/driver-etekcity.c @@ -24,6 +24,7 @@ #include "config.h" #include #include +#include #include #include #include @@ -40,9 +41,11 @@ #define ETEKCITY_REPORT_ID_PROFILE 5 #define ETEKCITY_REPORT_ID_SETTINGS 6 #define ETEKCITY_REPORT_ID_KEY_MAPPING 7 +#define ETEKCITY_REPORT_ID_MACRO 9 #define ETEKCITY_REPORT_SIZE_PROFILE 50 #define ETEKCITY_REPORT_SIZE_SETTINGS 40 +#define ETEKCITY_REPORT_SIZE_MACRO 130 #define ETEKCITY_CONFIG_SETTINGS 0x10 #define ETEKCITY_CONFIG_KEY_MAPPING 0x20 @@ -65,9 +68,24 @@ struct etekcity_settings_report { uint8_t padding3[5]; } __attribute__((packed)); +struct etekcity_macro { + uint8_t reportID; + uint8_t heightytwo; + uint8_t profile; + uint8_t button_index; + uint8_t one; + char name[24]; + uint8_t length; + struct { + uint8_t keycode; + uint8_t flag; + } keys[50]; +} __attribute__((packed)); + struct etekcity_data { uint8_t profiles[(ETEKCITY_PROFILE_MAX + 1)][ETEKCITY_REPORT_SIZE_PROFILE]; struct etekcity_settings_report settings[(ETEKCITY_PROFILE_MAX + 1)]; + struct etekcity_macro macros[(ETEKCITY_PROFILE_MAX + 1)][(ETEKCITY_BUTTON_MAX + 1)]; }; static char * @@ -293,6 +311,140 @@ etekcity_set_config_profile(struct ratbag_device *device, uint8_t profile, uint8 return ret == sizeof(buf) ? 0 : ret; } +static inline unsigned +etekcity_button_to_index(unsigned button) +{ + return button < 8 ? button : button + 5; +} + +static const struct ratbag_button_action * +etekcity_button_to_action(struct ratbag_profile *profile, + unsigned int button_index) +{ + struct ratbag_device *device = profile->device; + struct etekcity_data *drv_data = ratbag_get_drv_data(device); + uint8_t data; + unsigned raw_index = etekcity_button_to_index(button_index); + + data = drv_data->profiles[profile->index][3 + raw_index * 3]; + log_debug(device->ratbag, + " - button%d: %s (%02x) %s:%d\n", + button_index, print_key(data), data, __FILE__, __LINE__); + return etekcity_raw_to_button_action(data); +} + +static const unsigned int macro_mapping[] = { + [0x00 ... 0x03] = 0, + [0x04] = KEY_A, + [0x05] = KEY_B, + [0x06] = KEY_C, + [0x07] = KEY_D, + [0x08] = KEY_E, + [0x09] = KEY_F, + [0x0a] = KEY_G, + [0x0b] = KEY_H, + [0x0c] = KEY_I, + [0x0d] = KEY_J, + [0x0e] = KEY_K, + [0x0f] = KEY_L, + [0x10] = KEY_M, + [0x11] = KEY_N, + [0x12] = KEY_O, + [0x13] = KEY_P, + [0x14] = KEY_Q, + [0x15] = KEY_R, + [0x16] = KEY_S, + [0x17] = KEY_T, + [0x18] = KEY_U, + [0x19] = KEY_V, + [0x1a] = KEY_W, + [0x1b] = KEY_X, + [0x1c] = KEY_Y, + [0x1d] = KEY_Z, + [0x1e] = KEY_1, + [0x1f] = KEY_2, + [0x20] = KEY_3, + [0x21] = KEY_4, + [0x22] = KEY_5, + [0x23] = KEY_6, + [0x24] = KEY_7, + [0x25] = KEY_8, + [0x26] = KEY_9, + [0x27] = KEY_0, + [0x28] = KEY_ENTER, + [0x29] = KEY_ESC, + [0x2a] = KEY_BACKSPACE, + [0x2b] = KEY_TAB, + [0x2c] = KEY_SPACE, + [0x2d] = KEY_MINUS, + [0x2e] = KEY_EQUAL, + [0x2f] = KEY_LEFTBRACE, + [0x30] = KEY_RIGHTBRACE, + [0x31] = KEY_BACKSLASH, + [0x32] = KEY_BACKSLASH, + [0x33] = KEY_SEMICOLON, + [0x34] = KEY_APOSTROPHE, + [0x35] = KEY_GRAVE, + [0x36] = KEY_COMMA, + [0x37] = KEY_DOT, + [0x38] = KEY_SLASH, + [0x39] = KEY_CAPSLOCK, + [0x3a] = KEY_F1, + [0x3b] = KEY_F2, + [0x3c] = KEY_F3, + [0x3d] = KEY_F4, + [0x3e] = KEY_F5, + [0x3f] = KEY_F6, + [0x40] = KEY_F7, + [0x41] = KEY_F8, + [0x42] = KEY_F9, + [0x43] = KEY_F10, + [0x44] = KEY_F11, + [0x45] = KEY_F12, + [0x46] = KEY_SYSRQ, + [0x47] = KEY_SCROLLLOCK, + [0x48] = KEY_PAUSE, + [0x49] = KEY_INSERT, + [0x4a] = KEY_HOME, + [0x4b] = KEY_PAGEUP, + [0x4c] = KEY_DELETE, + [0x4d] = KEY_END, + [0x4e] = KEY_PAGEDOWN, + [0x4f] = KEY_RIGHT, + [0x50] = KEY_LEFT, + [0x51] = KEY_DOWN, + [0x52] = KEY_UP, + [0x53] = KEY_NUMLOCK, + [0x54] = KEY_KPSLASH, + [0x55] = KEY_KPASTERISK, + [0x56] = KEY_KPMINUS, + [0x57] = KEY_KPPLUS, + [0x58] = KEY_KPENTER, + [0x59] = KEY_KP1, + [0x5a] = KEY_KP2, + [0x5b] = KEY_KP3, + [0x5c] = KEY_KP4, + [0x5d] = KEY_KP5, + [0x5e] = KEY_KP6, + [0x5f] = KEY_KP7, + [0x60] = KEY_KP8, + [0x61] = KEY_KP9, + [0x62] = KEY_KP0, + [0x63] = KEY_KPDOT, + [0x64] = KEY_102ND, + [0x65] = KEY_COMPOSE, + [0x66 ... 0xdf] = 0, + [0xe0] = KEY_LEFTCTRL, + [0xe1] = KEY_LEFTSHIFT, + [0xe2] = KEY_LEFTALT, + [0xe3] = KEY_LEFTMETA, + [0xe4] = KEY_RIGHTCTRL, + [0xe5] = KEY_RIGHTSHIFT, + [0xe6] = KEY_RIGHTALT, + [0xe7] = KEY_RIGHTMETA, + [0xe8 ... 0xff] = 0, +}; + static void etekcity_read_profile(struct ratbag_profile *profile, unsigned int index) { @@ -303,7 +455,7 @@ etekcity_read_profile(struct ratbag_profile *profile, unsigned int index) int rc; uint8_t *buf, *dpi_list; unsigned int report_rate; - unsigned int i; + unsigned int i, j; assert(index <= ETEKCITY_PROFILE_MAX); @@ -367,6 +519,35 @@ etekcity_read_profile(struct ratbag_profile *profile, unsigned int index) msleep(10); + for (i = 0; i < ETEKCITY_BUTTON_MAX; i++) { + const struct ratbag_button_action *action; + struct etekcity_macro *macro; + + action = etekcity_button_to_action(profile, i); + if (action->type != RATBAG_BUTTON_ACTION_TYPE_MACRO) + continue; + + etekcity_set_config_profile(device, index, i); + macro = &drv_data->macros[index][i]; + buf = (uint8_t*)macro; + rc = ratbag_hidraw_raw_request(device, ETEKCITY_REPORT_ID_MACRO, + buf, ETEKCITY_REPORT_SIZE_MACRO, + HID_FEATURE_REPORT, HID_REQ_GET_REPORT); + log_info(device->ratbag, + "macro on button %d of profile %d is named '%s', and contains %d events:\n", + i, profile->index, + macro->name, macro->length); + for (j = 0; j < macro->length; j++) { + log_info(device->ratbag, + " - %s %s\n", + libevdev_event_code_get_name(EV_KEY, macro_mapping[macro->keys[j].keycode]), + macro->keys[j].flag & 0x80 ? "released" : "pressed"); + } + + } + + msleep(10); + if (rc < ETEKCITY_REPORT_SIZE_PROFILE) return; @@ -405,27 +586,12 @@ etekcity_write_profile(struct ratbag_profile *profile) return 0; } -static inline unsigned -etekcity_button_to_index(unsigned button) -{ - return button < 8 ? button : button + 5; -} - static void etekcity_read_button(struct ratbag_button *button) { - struct ratbag_profile *profile = button->profile; - struct ratbag_device *device = profile->device; - struct etekcity_data *drv_data = ratbag_get_drv_data(device); - uint8_t data; - unsigned raw_index = etekcity_button_to_index(button->index); const struct ratbag_button_action *action; - data = drv_data->profiles[profile->index][3 + raw_index * 3]; - log_debug(device->ratbag, - " - button%d: %s (%02x) %s:%d\n", - button->index, print_key(data), data, __FILE__, __LINE__); - action = etekcity_raw_to_button_action(data); + action = etekcity_button_to_action(button->profile, button->index); if (action) button->action = *action; button->type = etekcity_raw_to_button_type(button->index);