diff -Nru g110d-0.1/Makefile.am g110d-0.2/Makefile.am --- g110d-0.1/Makefile.am 2014-01-14 19:38:28.000000000 +0000 +++ g110d-0.2/Makefile.am 2014-01-23 19:50:57.000000000 +0000 @@ -16,11 +16,14 @@ g110d_SOURCES = \ main.c \ suinput.c \ - suinput.h + suinput.h \ + utilities.c \ + utilities.h g110d_LDFLAGS = -g110d_LDADD = $(G110D_LIBS) +g110d_LDADD = $(G110D_LIBS) \ + -lpthread dist_config_DATA = files/g110d.conf diff -Nru g110d-0.1/Makefile.in g110d-0.2/Makefile.in --- g110d-0.1/Makefile.in 2014-01-14 19:40:43.000000000 +0000 +++ g110d-0.2/Makefile.in 2014-01-23 20:02:18.000000000 +0000 @@ -102,7 +102,8 @@ "$(DESTDIR)$(sleepdir)" "$(DESTDIR)$(configdir)" \ "$(DESTDIR)$(udevruledir)" PROGRAMS = $(install_PROGRAMS) -am_g110d_OBJECTS = main.$(OBJEXT) suinput.$(OBJEXT) +am_g110d_OBJECTS = main.$(OBJEXT) suinput.$(OBJEXT) \ + utilities.$(OBJEXT) g110d_OBJECTS = $(am_g110d_OBJECTS) am__DEPENDENCIES_1 = g110d_DEPENDENCIES = $(am__DEPENDENCIES_1) @@ -353,10 +354,14 @@ g110d_SOURCES = \ main.c \ suinput.c \ - suinput.h + suinput.h \ + utilities.c \ + utilities.h g110d_LDFLAGS = -g110d_LDADD = $(G110D_LIBS) +g110d_LDADD = $(G110D_LIBS) \ + -lpthread + dist_config_DATA = files/g110d.conf configdir = /etc dist_init_SCRIPTS = files/init/g110d @@ -551,6 +556,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/suinput.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utilities.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff -Nru g110d-0.1/configure g110d-0.2/configure --- g110d-0.1/configure 2014-01-14 17:30:58.000000000 +0000 +++ g110d-0.2/configure 2014-01-23 20:02:18.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for g110d 0.1. +# Generated by GNU Autoconf 2.69 for g110d 0.2. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ # Identity of this package. PACKAGE_NAME='g110d' PACKAGE_TARNAME='g110d' -PACKAGE_VERSION='0.1' -PACKAGE_STRING='g110d 0.1' +PACKAGE_VERSION='0.2' +PACKAGE_STRING='g110d 0.2' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1316,7 +1316,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures g110d 0.1 to adapt to many kinds of systems. +\`configure' configures g110d 0.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1386,7 +1386,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of g110d 0.1:";; + short | recursive ) echo "Configuration of g110d 0.2:";; esac cat <<\_ACEOF @@ -1499,7 +1499,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -g110d configure 0.1 +g110d configure 0.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1777,7 +1777,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by g110d $as_me 0.1, which was +It was created by g110d $as_me 0.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2644,7 +2644,7 @@ # Define the identity of the package. PACKAGE='g110d' - VERSION='0.1' + VERSION='0.2' cat >>confdefs.h <<_ACEOF @@ -12055,7 +12055,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by g110d $as_me 0.1, which was +This file was extended by g110d $as_me 0.2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12121,7 +12121,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -g110d config.status 0.1 +g110d config.status 0.2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru g110d-0.1/configure.ac g110d-0.2/configure.ac --- g110d-0.1/configure.ac 2014-01-14 17:17:46.000000000 +0000 +++ g110d-0.2/configure.ac 2014-01-23 19:42:51.000000000 +0000 @@ -1,7 +1,7 @@ dnl Process this file with autoconf to produce a configure script. dnl Created by Anjuta application wizard. -AC_INIT(g110d, 0.1) +AC_INIT(g110d, 0.2) AC_CONFIG_HEADERS([config.h]) diff -Nru g110d-0.1/debian/bzr-builder.manifest g110d-0.2/debian/bzr-builder.manifest --- g110d-0.1/debian/bzr-builder.manifest 2014-01-23 22:09:35.000000000 +0000 +++ g110d-0.2/debian/bzr-builder.manifest 2014-01-23 22:09:35.000000000 +0000 @@ -1,2 +1,2 @@ -# bzr-builder format 0.3 deb-version {debupstream}-0ubuntu4 -lp:~behda/+junk/g110d revid:pauvitk@gmail.com-20140119165036-bgrvrskt0y0qdtil +# bzr-builder format 0.3 deb-version {debupstream}-0ubuntu1 +lp:~behda/+junk/g110d revid:pauvitk@gmail.com-20140123220026-ji0lupdhxtvcgdyv diff -Nru g110d-0.1/debian/changelog g110d-0.2/debian/changelog --- g110d-0.1/debian/changelog 2014-01-23 22:09:35.000000000 +0000 +++ g110d-0.2/debian/changelog 2014-01-23 22:09:35.000000000 +0000 @@ -1,11 +1,11 @@ -g110d (0.1-0ubuntu4~ubuntu14.04.1) trusty; urgency=low +g110d (0.2-0ubuntu1~ubuntu14.04.1) trusty; urgency=low * Auto build. - -- Paulius Vitkus Sun, 19 Jan 2014 16:54:46 +0000 + -- Paulius Vitkus Thu, 23 Jan 2014 22:07:33 +0000 -g110d (0.1-0ubuntu1) saucy; urgency=low +g110d (0.2-0ubuntu1) saucy; urgency=low - * Initial release + * Added built-in macro support. - -- Paulius Vitkus Tue, 14 Jan 2014 23:58:56 +0200 + -- Paulius Vitkus Thu, 23 Jan 2014 23:44:28 +0200 diff -Nru g110d-0.1/debian/control g110d-0.2/debian/control --- g110d-0.1/debian/control 2014-01-23 22:09:35.000000000 +0000 +++ g110d-0.2/debian/control 2014-01-23 22:09:35.000000000 +0000 @@ -10,4 +10,4 @@ Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libusb-1.0-0 Description: Logitech G110 keyboard G-keys driver - Daemon that acts as Logitech G110 keyboard G-keys driver. + Daemon that acts as Logitech G110 keyboard G-keys driver. \ No newline at end of file diff -Nru g110d-0.1/debian/copyright g110d-0.2/debian/copyright --- g110d-0.1/debian/copyright 2014-01-23 22:09:35.000000000 +0000 +++ g110d-0.2/debian/copyright 2014-01-23 22:09:35.000000000 +0000 @@ -15,4 +15,4 @@ along with this program. If not, see . On Debian systems, the complete text of the GNU General - Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". + Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". \ No newline at end of file diff -Nru g110d-0.1/files/g110d.conf g110d-0.2/files/g110d.conf --- g110d-0.1/files/g110d.conf 2014-01-23 22:09:35.000000000 +0000 +++ g110d-0.2/files/g110d.conf 2014-01-23 21:29:28.000000000 +0000 @@ -19,19 +19,21 @@ brightness_3 = 14 brightness_4 = 14 -# key and button settings are interpreted as device key values -# if assigned strings are equal to defined names of keys and buttons in /usr/include/linux/input.h -# if assigned to any other string that string is interpreted as executable shell command -# if assigned string has spaces then it must be quoted +# If assigned strings are equal to defined names of keys and buttons in /usr/include/linux/input.h +# then key settings are interpreted as device key values. -# macros can be run executing as command a program called xte -# to be able to use xte you need to install xautomation: sudo apt-get install xautomation +# If assigned string starts with "macro " then it is interpreted as macro. +# Macro commands must be in pairs. Macro command types are "key", "keydown", "keyup" and "msleep". +# Macro command type must be followed by key name or sleep interval in miliseconds. -# if u want to execute a commant that uses X display server (eg. gui application and xte) -# you need to add to command string "DISPLAY=:0" and also run once in terminal: sudo xhost +local:root +# If assigned to any other string that string is interpreted as executable shell command. +# If assigned string has spaces then it must be quoted. -# example of binding a macro to key_1_1 that simulates key press of KEY_1 two times: -# key_1_1 = "DISPLAY=:0 xte 'key 1' 'key 1'" +# If you want to execute a commant that uses X display server (eg. gui application) +# you need to add to command string "DISPLAY=:0" and also run in terminal: xhost +local:root + +# Example of binding a macro to key_1_1 that simulates key press of KEY_1 two times with one second interval: +# key_1_1 = "macro key KEY_1 msleep 1000 key KEY_1" key_1_1 = KEY_F1 key_1_2 = KEY_F2 diff -Nru g110d-0.1/main.c g110d-0.2/main.c --- g110d-0.1/main.c 2014-01-23 22:09:35.000000000 +0000 +++ g110d-0.2/main.c 2014-01-23 21:12:35.000000000 +0000 @@ -29,14 +29,16 @@ #include #include #include +#include #include "suinput.h" +#include "utilities.h" #ifndef CONFFILENAME #define CONFFILENAME "g110d.conf" #endif -#define G110_SHELL_PATH "/bin/dash" +#define G110_WORK_DIR "/etc" #define G110_DEV_NAME "Logitech G110 G-keys (behda)" @@ -85,8 +87,6 @@ #define G110_COLOR_MIN 0x01 #define G110_BRIGHTNESS_MIN 0x00 -#define NAME_ELEMENT(element) [element] = #element - typedef struct { unsigned char color; unsigned char brightness; @@ -94,6 +94,8 @@ typedef struct { uint16_t code; + int macro_len; + My_macro *macro; char *cmd; } Dev_button; @@ -110,37 +112,12 @@ static Dev_setting dev_setting[G110_GROUP_COUNT]; static Dev_button dev_button[G110_GROUP_COUNT][G110_BTN_COUNT]; static int button_down_group[G110_BTN_COUNT]; +static pthread_mutex_t mutex_uinput; +static pthread_attr_t detached_thread_attr; static struct timeval libusb_timeout = { 0, 100000 }; -static int uinput_dev_fd; -static int stdin_copy_fd = STDIN_FILENO; -static int stdout_copy_fd = STDOUT_FILENO; -static int stderr_copy_fd = STDERR_FILENO; - -static void g110_execute_command(const char *cmd) { - pid_t pid; - - pid = fork(); - if (pid == 0) { - dup2(stdin_copy_fd, STDIN_FILENO); - dup2(stdout_copy_fd, STDOUT_FILENO); - dup2(stderr_copy_fd, STDERR_FILENO); - execl(G110_SHELL_PATH, G110_SHELL_PATH, "-c", cmd, NULL); - exit(EXIT_SUCCESS); - } -} - -static uint16_t g110_get_keycode(const char **key_names, const char *kstr) { - uint16_t i; - const char *name; - - for (i = 0; i <= KEY_MAX; i++) { - name = key_names[i]; - if ((name != NULL) && (strcmp(name, kstr) == 0)) - return i; - } - - return UINT16_MAX; -} +static int uinput_dev_fd = -1; +static int kernel_driver = 0; +static int interface_claimed = 0; static void g110_set_default_settings(void) { int i; @@ -154,39 +131,51 @@ dev_button[i][0].code = KEY_F1; dev_button[i][0].cmd = NULL; + dev_button[i][0].macro = NULL; dev_button[i][1].code = KEY_F2; dev_button[i][1].cmd = NULL; + dev_button[i][1].macro = NULL; dev_button[i][2].code = KEY_F3; dev_button[i][2].cmd = NULL; + dev_button[i][2].macro = NULL; dev_button[i][3].code = KEY_F4; dev_button[i][3].cmd = NULL; + dev_button[i][3].macro = NULL; dev_button[i][4].code = KEY_F5; dev_button[i][4].cmd = NULL; + dev_button[i][4].macro = NULL; dev_button[i][5].code = KEY_F6; dev_button[i][5].cmd = NULL; + dev_button[i][5].macro = NULL; dev_button[i][6].code = KEY_F7; dev_button[i][6].cmd = NULL; + dev_button[i][6].macro = NULL; dev_button[i][7].code = KEY_F8; dev_button[i][7].cmd = NULL; + dev_button[i][7].macro = NULL; dev_button[i][8].code = KEY_F9; dev_button[i][8].cmd = NULL; + dev_button[i][8].macro = NULL; dev_button[i][9].code = KEY_F10; dev_button[i][9].cmd = NULL; + dev_button[i][9].macro = NULL; dev_button[i][10].code = KEY_F11; dev_button[i][10].cmd = NULL; + dev_button[i][10].macro = NULL; dev_button[i][11].code = KEY_F12; dev_button[i][11].cmd = NULL; + dev_button[i][11].macro = NULL; } } @@ -194,25 +183,30 @@ int i, j; for (i = 0; i < G110_GROUP_COUNT; i++) - for (j = 0; j < G110_BTN_COUNT; j++) + for (j = 0; j < G110_BTN_COUNT; j++) { if (dev_button[i][j].cmd != NULL) free(dev_button[i][j].cmd); + if (dev_button[i][j].macro != NULL) + free(dev_button[i][j].macro); + } } static void g110_release_all_buttons(void) { int old_group, i; uint16_t mask; + pthread_mutex_lock(&mutex_uinput); for (i = 0; i < G110_BTN_COUNT; i++) { mask = 1 << i; if ((button_state_old & mask) == mask) { /*key up*/ old_group = button_down_group[i]; - if (dev_button[old_group][i].cmd == NULL) { + if ((dev_button[old_group][i].cmd == NULL) && (dev_button[old_group][i].macro == NULL)) { suinput_emit(uinput_dev_fd, EV_KEY, dev_button[old_group][i].code, 0); suinput_syn(uinput_dev_fd); } } } + pthread_mutex_unlock(&mutex_uinput); } static void g110_read_config(void) { @@ -288,273 +282,6 @@ CFG_SIMPLE_STR("key_4_12", &key_val[3][11]), CFG_END() }; - static const char *key_names[KEY_MAX + 1] = { - [0 ... KEY_MAX] = NULL, - NAME_ELEMENT(KEY_RESERVED), NAME_ELEMENT(KEY_ESC), - NAME_ELEMENT(KEY_1), NAME_ELEMENT(KEY_2), - NAME_ELEMENT(KEY_3), NAME_ELEMENT(KEY_4), - NAME_ELEMENT(KEY_5), NAME_ELEMENT(KEY_6), - NAME_ELEMENT(KEY_7), NAME_ELEMENT(KEY_8), - NAME_ELEMENT(KEY_9), NAME_ELEMENT(KEY_0), - NAME_ELEMENT(KEY_MINUS), NAME_ELEMENT(KEY_EQUAL), - NAME_ELEMENT(KEY_BACKSPACE), NAME_ELEMENT(KEY_TAB), - NAME_ELEMENT(KEY_Q), NAME_ELEMENT(KEY_W), - NAME_ELEMENT(KEY_E), NAME_ELEMENT(KEY_R), - NAME_ELEMENT(KEY_T), NAME_ELEMENT(KEY_Y), - NAME_ELEMENT(KEY_U), NAME_ELEMENT(KEY_I), - NAME_ELEMENT(KEY_O), NAME_ELEMENT(KEY_P), - NAME_ELEMENT(KEY_LEFTBRACE), NAME_ELEMENT(KEY_RIGHTBRACE), - NAME_ELEMENT(KEY_ENTER), NAME_ELEMENT(KEY_LEFTCTRL), - NAME_ELEMENT(KEY_A), NAME_ELEMENT(KEY_S), - NAME_ELEMENT(KEY_D), NAME_ELEMENT(KEY_F), - NAME_ELEMENT(KEY_G), NAME_ELEMENT(KEY_H), - NAME_ELEMENT(KEY_J), NAME_ELEMENT(KEY_K), - NAME_ELEMENT(KEY_L), NAME_ELEMENT(KEY_SEMICOLON), - NAME_ELEMENT(KEY_APOSTROPHE), NAME_ELEMENT(KEY_GRAVE), - NAME_ELEMENT(KEY_LEFTSHIFT), NAME_ELEMENT(KEY_BACKSLASH), - NAME_ELEMENT(KEY_Z), NAME_ELEMENT(KEY_X), - NAME_ELEMENT(KEY_C), NAME_ELEMENT(KEY_V), - NAME_ELEMENT(KEY_B), NAME_ELEMENT(KEY_N), - NAME_ELEMENT(KEY_M), NAME_ELEMENT(KEY_COMMA), - NAME_ELEMENT(KEY_DOT), NAME_ELEMENT(KEY_SLASH), - NAME_ELEMENT(KEY_RIGHTSHIFT), NAME_ELEMENT(KEY_KPASTERISK), - NAME_ELEMENT(KEY_LEFTALT), NAME_ELEMENT(KEY_SPACE), - NAME_ELEMENT(KEY_CAPSLOCK), NAME_ELEMENT(KEY_F1), - NAME_ELEMENT(KEY_F2), NAME_ELEMENT(KEY_F3), - NAME_ELEMENT(KEY_F4), NAME_ELEMENT(KEY_F5), - NAME_ELEMENT(KEY_F6), NAME_ELEMENT(KEY_F7), - NAME_ELEMENT(KEY_F8), NAME_ELEMENT(KEY_F9), - NAME_ELEMENT(KEY_F10), NAME_ELEMENT(KEY_NUMLOCK), - NAME_ELEMENT(KEY_SCROLLLOCK), NAME_ELEMENT(KEY_KP7), - NAME_ELEMENT(KEY_KP8), NAME_ELEMENT(KEY_KP9), - NAME_ELEMENT(KEY_KPMINUS), NAME_ELEMENT(KEY_KP4), - NAME_ELEMENT(KEY_KP5), NAME_ELEMENT(KEY_KP6), - NAME_ELEMENT(KEY_KPPLUS), NAME_ELEMENT(KEY_KP1), - NAME_ELEMENT(KEY_KP2), NAME_ELEMENT(KEY_KP3), - NAME_ELEMENT(KEY_KP0), NAME_ELEMENT(KEY_KPDOT), - NAME_ELEMENT(KEY_ZENKAKUHANKAKU), NAME_ELEMENT(KEY_102ND), - NAME_ELEMENT(KEY_F11), NAME_ELEMENT(KEY_F12), - NAME_ELEMENT(KEY_RO), NAME_ELEMENT(KEY_KATAKANA), - NAME_ELEMENT(KEY_HIRAGANA), NAME_ELEMENT(KEY_HENKAN), - NAME_ELEMENT(KEY_KATAKANAHIRAGANA), NAME_ELEMENT(KEY_MUHENKAN), - NAME_ELEMENT(KEY_KPJPCOMMA), NAME_ELEMENT(KEY_KPENTER), - NAME_ELEMENT(KEY_RIGHTCTRL), NAME_ELEMENT(KEY_KPSLASH), - NAME_ELEMENT(KEY_SYSRQ), NAME_ELEMENT(KEY_RIGHTALT), - NAME_ELEMENT(KEY_LINEFEED), NAME_ELEMENT(KEY_HOME), - NAME_ELEMENT(KEY_UP), NAME_ELEMENT(KEY_PAGEUP), - NAME_ELEMENT(KEY_LEFT), NAME_ELEMENT(KEY_RIGHT), - NAME_ELEMENT(KEY_END), NAME_ELEMENT(KEY_DOWN), - NAME_ELEMENT(KEY_PAGEDOWN), NAME_ELEMENT(KEY_INSERT), - NAME_ELEMENT(KEY_DELETE), NAME_ELEMENT(KEY_MACRO), - NAME_ELEMENT(KEY_MUTE), NAME_ELEMENT(KEY_VOLUMEDOWN), - NAME_ELEMENT(KEY_VOLUMEUP), NAME_ELEMENT(KEY_POWER), - NAME_ELEMENT(KEY_KPEQUAL), NAME_ELEMENT(KEY_KPPLUSMINUS), - NAME_ELEMENT(KEY_PAUSE), NAME_ELEMENT(KEY_KPCOMMA), - NAME_ELEMENT(KEY_HANGUEL), NAME_ELEMENT(KEY_HANJA), - NAME_ELEMENT(KEY_YEN), NAME_ELEMENT(KEY_LEFTMETA), - NAME_ELEMENT(KEY_RIGHTMETA), NAME_ELEMENT(KEY_COMPOSE), - NAME_ELEMENT(KEY_STOP), NAME_ELEMENT(KEY_AGAIN), - NAME_ELEMENT(KEY_PROPS), NAME_ELEMENT(KEY_UNDO), - NAME_ELEMENT(KEY_FRONT), NAME_ELEMENT(KEY_COPY), - NAME_ELEMENT(KEY_OPEN), NAME_ELEMENT(KEY_PASTE), - NAME_ELEMENT(KEY_FIND), NAME_ELEMENT(KEY_CUT), - NAME_ELEMENT(KEY_HELP), NAME_ELEMENT(KEY_MENU), - NAME_ELEMENT(KEY_CALC), NAME_ELEMENT(KEY_SETUP), - NAME_ELEMENT(KEY_SLEEP), NAME_ELEMENT(KEY_WAKEUP), - NAME_ELEMENT(KEY_FILE), NAME_ELEMENT(KEY_SENDFILE), - NAME_ELEMENT(KEY_DELETEFILE), NAME_ELEMENT(KEY_XFER), - NAME_ELEMENT(KEY_PROG1), NAME_ELEMENT(KEY_PROG2), - NAME_ELEMENT(KEY_WWW), NAME_ELEMENT(KEY_MSDOS), - NAME_ELEMENT(KEY_COFFEE), NAME_ELEMENT(KEY_DIRECTION), - NAME_ELEMENT(KEY_CYCLEWINDOWS), NAME_ELEMENT(KEY_MAIL), - NAME_ELEMENT(KEY_BOOKMARKS), NAME_ELEMENT(KEY_COMPUTER), - NAME_ELEMENT(KEY_BACK), NAME_ELEMENT(KEY_FORWARD), - NAME_ELEMENT(KEY_CLOSECD), NAME_ELEMENT(KEY_EJECTCD), - NAME_ELEMENT(KEY_EJECTCLOSECD), NAME_ELEMENT(KEY_NEXTSONG), - NAME_ELEMENT(KEY_PLAYPAUSE), NAME_ELEMENT(KEY_PREVIOUSSONG), - NAME_ELEMENT(KEY_STOPCD), NAME_ELEMENT(KEY_RECORD), - NAME_ELEMENT(KEY_REWIND), NAME_ELEMENT(KEY_PHONE), - NAME_ELEMENT(KEY_ISO), NAME_ELEMENT(KEY_CONFIG), - NAME_ELEMENT(KEY_HOMEPAGE), NAME_ELEMENT(KEY_REFRESH), - NAME_ELEMENT(KEY_EXIT), NAME_ELEMENT(KEY_MOVE), - NAME_ELEMENT(KEY_EDIT), NAME_ELEMENT(KEY_SCROLLUP), - NAME_ELEMENT(KEY_SCROLLDOWN), NAME_ELEMENT(KEY_KPLEFTPAREN), - NAME_ELEMENT(KEY_KPRIGHTPAREN), NAME_ELEMENT(KEY_F13), - NAME_ELEMENT(KEY_F14), NAME_ELEMENT(KEY_F15), - NAME_ELEMENT(KEY_F16), NAME_ELEMENT(KEY_F17), - NAME_ELEMENT(KEY_F18), NAME_ELEMENT(KEY_F19), - NAME_ELEMENT(KEY_F20), NAME_ELEMENT(KEY_F21), - NAME_ELEMENT(KEY_F22), NAME_ELEMENT(KEY_F23), - NAME_ELEMENT(KEY_F24), NAME_ELEMENT(KEY_PLAYCD), - NAME_ELEMENT(KEY_PAUSECD), NAME_ELEMENT(KEY_PROG3), - NAME_ELEMENT(KEY_PROG4), NAME_ELEMENT(KEY_SUSPEND), - NAME_ELEMENT(KEY_CLOSE), NAME_ELEMENT(KEY_PLAY), - NAME_ELEMENT(KEY_FASTFORWARD), NAME_ELEMENT(KEY_BASSBOOST), - NAME_ELEMENT(KEY_PRINT), NAME_ELEMENT(KEY_HP), - NAME_ELEMENT(KEY_CAMERA), NAME_ELEMENT(KEY_SOUND), - NAME_ELEMENT(KEY_QUESTION), NAME_ELEMENT(KEY_EMAIL), - NAME_ELEMENT(KEY_CHAT), NAME_ELEMENT(KEY_SEARCH), - NAME_ELEMENT(KEY_CONNECT), NAME_ELEMENT(KEY_FINANCE), - NAME_ELEMENT(KEY_SPORT), NAME_ELEMENT(KEY_SHOP), - NAME_ELEMENT(KEY_ALTERASE), NAME_ELEMENT(KEY_CANCEL), - NAME_ELEMENT(KEY_BRIGHTNESSDOWN), NAME_ELEMENT(KEY_BRIGHTNESSUP), - NAME_ELEMENT(KEY_MEDIA), NAME_ELEMENT(KEY_UNKNOWN), - NAME_ELEMENT(KEY_OK), - NAME_ELEMENT(KEY_SELECT), NAME_ELEMENT(KEY_GOTO), - NAME_ELEMENT(KEY_CLEAR), NAME_ELEMENT(KEY_POWER2), - NAME_ELEMENT(KEY_OPTION), NAME_ELEMENT(KEY_INFO), - NAME_ELEMENT(KEY_TIME), NAME_ELEMENT(KEY_VENDOR), - NAME_ELEMENT(KEY_ARCHIVE), NAME_ELEMENT(KEY_PROGRAM), - NAME_ELEMENT(KEY_CHANNEL), NAME_ELEMENT(KEY_FAVORITES), - NAME_ELEMENT(KEY_EPG), NAME_ELEMENT(KEY_PVR), - NAME_ELEMENT(KEY_MHP), NAME_ELEMENT(KEY_LANGUAGE), - NAME_ELEMENT(KEY_TITLE), NAME_ELEMENT(KEY_SUBTITLE), - NAME_ELEMENT(KEY_ANGLE), NAME_ELEMENT(KEY_ZOOM), - NAME_ELEMENT(KEY_MODE), NAME_ELEMENT(KEY_KEYBOARD), - NAME_ELEMENT(KEY_SCREEN), NAME_ELEMENT(KEY_PC), - NAME_ELEMENT(KEY_TV), NAME_ELEMENT(KEY_TV2), - NAME_ELEMENT(KEY_VCR), NAME_ELEMENT(KEY_VCR2), - NAME_ELEMENT(KEY_SAT), NAME_ELEMENT(KEY_SAT2), - NAME_ELEMENT(KEY_CD), NAME_ELEMENT(KEY_TAPE), - NAME_ELEMENT(KEY_RADIO), NAME_ELEMENT(KEY_TUNER), - NAME_ELEMENT(KEY_PLAYER), NAME_ELEMENT(KEY_TEXT), - NAME_ELEMENT(KEY_DVD), NAME_ELEMENT(KEY_AUX), - NAME_ELEMENT(KEY_MP3), NAME_ELEMENT(KEY_AUDIO), - NAME_ELEMENT(KEY_VIDEO), NAME_ELEMENT(KEY_DIRECTORY), - NAME_ELEMENT(KEY_LIST), NAME_ELEMENT(KEY_MEMO), - NAME_ELEMENT(KEY_CALENDAR), NAME_ELEMENT(KEY_RED), - NAME_ELEMENT(KEY_GREEN), NAME_ELEMENT(KEY_YELLOW), - NAME_ELEMENT(KEY_BLUE), NAME_ELEMENT(KEY_CHANNELUP), - NAME_ELEMENT(KEY_CHANNELDOWN), NAME_ELEMENT(KEY_FIRST), - NAME_ELEMENT(KEY_LAST), NAME_ELEMENT(KEY_AB), - NAME_ELEMENT(KEY_NEXT), NAME_ELEMENT(KEY_RESTART), - NAME_ELEMENT(KEY_SLOW), NAME_ELEMENT(KEY_SHUFFLE), - NAME_ELEMENT(KEY_BREAK), NAME_ELEMENT(KEY_PREVIOUS), - NAME_ELEMENT(KEY_DIGITS), NAME_ELEMENT(KEY_TEEN), - NAME_ELEMENT(KEY_TWEN), NAME_ELEMENT(KEY_DEL_EOL), - NAME_ELEMENT(KEY_DEL_EOS), NAME_ELEMENT(KEY_INS_LINE), - NAME_ELEMENT(KEY_DEL_LINE), - NAME_ELEMENT(KEY_VIDEOPHONE), NAME_ELEMENT(KEY_GAMES), - NAME_ELEMENT(KEY_ZOOMIN), NAME_ELEMENT(KEY_ZOOMOUT), - NAME_ELEMENT(KEY_ZOOMRESET), NAME_ELEMENT(KEY_WORDPROCESSOR), - NAME_ELEMENT(KEY_EDITOR), NAME_ELEMENT(KEY_SPREADSHEET), - NAME_ELEMENT(KEY_GRAPHICSEDITOR), NAME_ELEMENT(KEY_PRESENTATION), - NAME_ELEMENT(KEY_DATABASE), NAME_ELEMENT(KEY_NEWS), - NAME_ELEMENT(KEY_VOICEMAIL), NAME_ELEMENT(KEY_ADDRESSBOOK), - NAME_ELEMENT(KEY_MESSENGER), NAME_ELEMENT(KEY_DISPLAYTOGGLE), - NAME_ELEMENT(KEY_SPELLCHECK), NAME_ELEMENT(KEY_LOGOFF), - NAME_ELEMENT(KEY_DOLLAR), NAME_ELEMENT(KEY_EURO), - NAME_ELEMENT(KEY_FRAMEBACK), NAME_ELEMENT(KEY_FRAMEFORWARD), - NAME_ELEMENT(KEY_CONTEXT_MENU), NAME_ELEMENT(KEY_MEDIA_REPEAT), - NAME_ELEMENT(KEY_DEL_EOL), NAME_ELEMENT(KEY_DEL_EOS), - NAME_ELEMENT(KEY_INS_LINE), NAME_ELEMENT(KEY_DEL_LINE), - NAME_ELEMENT(KEY_FN), NAME_ELEMENT(KEY_FN_ESC), - NAME_ELEMENT(KEY_FN_F1), NAME_ELEMENT(KEY_FN_F2), - NAME_ELEMENT(KEY_FN_F3), NAME_ELEMENT(KEY_FN_F4), - NAME_ELEMENT(KEY_FN_F5), NAME_ELEMENT(KEY_FN_F6), - NAME_ELEMENT(KEY_FN_F7), NAME_ELEMENT(KEY_FN_F8), - NAME_ELEMENT(KEY_FN_F9), NAME_ELEMENT(KEY_FN_F10), - NAME_ELEMENT(KEY_FN_F11), NAME_ELEMENT(KEY_FN_F12), - NAME_ELEMENT(KEY_FN_1), NAME_ELEMENT(KEY_FN_2), - NAME_ELEMENT(KEY_FN_D), NAME_ELEMENT(KEY_FN_E), - NAME_ELEMENT(KEY_FN_F), NAME_ELEMENT(KEY_FN_S), - NAME_ELEMENT(KEY_FN_B), - NAME_ELEMENT(KEY_BRL_DOT1), NAME_ELEMENT(KEY_BRL_DOT2), - NAME_ELEMENT(KEY_BRL_DOT3), NAME_ELEMENT(KEY_BRL_DOT4), - NAME_ELEMENT(KEY_BRL_DOT5), NAME_ELEMENT(KEY_BRL_DOT6), - NAME_ELEMENT(KEY_BRL_DOT7), NAME_ELEMENT(KEY_BRL_DOT8), - NAME_ELEMENT(KEY_BRL_DOT9), NAME_ELEMENT(KEY_BRL_DOT10), - NAME_ELEMENT(KEY_NUMERIC_0), NAME_ELEMENT(KEY_NUMERIC_1), - NAME_ELEMENT(KEY_NUMERIC_2), NAME_ELEMENT(KEY_NUMERIC_3), - NAME_ELEMENT(KEY_NUMERIC_4), NAME_ELEMENT(KEY_NUMERIC_5), - NAME_ELEMENT(KEY_NUMERIC_6), NAME_ELEMENT(KEY_NUMERIC_7), - NAME_ELEMENT(KEY_NUMERIC_8), NAME_ELEMENT(KEY_NUMERIC_9), - NAME_ELEMENT(KEY_NUMERIC_STAR), NAME_ELEMENT(KEY_NUMERIC_POUND), - NAME_ELEMENT(KEY_BATTERY), - NAME_ELEMENT(KEY_BLUETOOTH), NAME_ELEMENT(KEY_BRIGHTNESS_CYCLE), - NAME_ELEMENT(KEY_BRIGHTNESS_ZERO), NAME_ELEMENT(KEY_DASHBOARD), - NAME_ELEMENT(KEY_DISPLAY_OFF), NAME_ELEMENT(KEY_DOCUMENTS), - NAME_ELEMENT(KEY_FORWARDMAIL), NAME_ELEMENT(KEY_NEW), - NAME_ELEMENT(KEY_KBDILLUMDOWN), NAME_ELEMENT(KEY_KBDILLUMUP), - NAME_ELEMENT(KEY_KBDILLUMTOGGLE), NAME_ELEMENT(KEY_REDO), - NAME_ELEMENT(KEY_REPLY), NAME_ELEMENT(KEY_SAVE), - NAME_ELEMENT(KEY_SCALE), NAME_ELEMENT(KEY_SEND), - NAME_ELEMENT(KEY_SCREENLOCK), NAME_ELEMENT(KEY_SWITCHVIDEOMODE), - NAME_ELEMENT(KEY_UWB), NAME_ELEMENT(KEY_VIDEO_NEXT), - NAME_ELEMENT(KEY_VIDEO_PREV), NAME_ELEMENT(KEY_WIMAX), - NAME_ELEMENT(KEY_WLAN), -#ifdef KEY_RFKILL - NAME_ELEMENT(KEY_RFKILL), -#endif -#ifdef KEY_WPS_BUTTON - NAME_ELEMENT(KEY_WPS_BUTTON), -#endif -#ifdef KEY_TOUCHPAD_TOGGLE - NAME_ELEMENT(KEY_TOUCHPAD_TOGGLE), - NAME_ELEMENT(KEY_TOUCHPAD_ON), - NAME_ELEMENT(KEY_TOUCHPAD_OFF), -#endif - - NAME_ELEMENT(BTN_0), NAME_ELEMENT(BTN_1), - NAME_ELEMENT(BTN_2), NAME_ELEMENT(BTN_3), - NAME_ELEMENT(BTN_4), NAME_ELEMENT(BTN_5), - NAME_ELEMENT(BTN_6), NAME_ELEMENT(BTN_7), - NAME_ELEMENT(BTN_8), NAME_ELEMENT(BTN_9), - NAME_ELEMENT(BTN_LEFT), NAME_ELEMENT(BTN_RIGHT), - NAME_ELEMENT(BTN_MIDDLE), NAME_ELEMENT(BTN_SIDE), - NAME_ELEMENT(BTN_EXTRA), NAME_ELEMENT(BTN_FORWARD), - NAME_ELEMENT(BTN_BACK), NAME_ELEMENT(BTN_TASK), - NAME_ELEMENT(BTN_TRIGGER), NAME_ELEMENT(BTN_THUMB), - NAME_ELEMENT(BTN_THUMB2), NAME_ELEMENT(BTN_TOP), - NAME_ELEMENT(BTN_TOP2), NAME_ELEMENT(BTN_PINKIE), - NAME_ELEMENT(BTN_BASE), NAME_ELEMENT(BTN_BASE2), - NAME_ELEMENT(BTN_BASE3), NAME_ELEMENT(BTN_BASE4), - NAME_ELEMENT(BTN_BASE5), NAME_ELEMENT(BTN_BASE6), - NAME_ELEMENT(BTN_DEAD), NAME_ELEMENT(BTN_A), - NAME_ELEMENT(BTN_B), NAME_ELEMENT(BTN_C), - NAME_ELEMENT(BTN_X), NAME_ELEMENT(BTN_Y), - NAME_ELEMENT(BTN_Z), NAME_ELEMENT(BTN_TL), - NAME_ELEMENT(BTN_TR), NAME_ELEMENT(BTN_TL2), - NAME_ELEMENT(BTN_TR2), NAME_ELEMENT(BTN_SELECT), - NAME_ELEMENT(BTN_START), NAME_ELEMENT(BTN_MODE), - NAME_ELEMENT(BTN_THUMBL), NAME_ELEMENT(BTN_THUMBR), - NAME_ELEMENT(BTN_TOOL_PEN), NAME_ELEMENT(BTN_TOOL_RUBBER), - NAME_ELEMENT(BTN_TOOL_BRUSH), NAME_ELEMENT(BTN_TOOL_PENCIL), - NAME_ELEMENT(BTN_TOOL_AIRBRUSH), NAME_ELEMENT(BTN_TOOL_FINGER), - NAME_ELEMENT(BTN_TOOL_MOUSE), NAME_ELEMENT(BTN_TOOL_LENS), - NAME_ELEMENT(BTN_TOUCH), NAME_ELEMENT(BTN_STYLUS), - NAME_ELEMENT(BTN_STYLUS2), NAME_ELEMENT(BTN_TOOL_DOUBLETAP), - NAME_ELEMENT(BTN_TOOL_TRIPLETAP), NAME_ELEMENT(BTN_TOOL_QUADTAP), - NAME_ELEMENT(BTN_GEAR_DOWN), - NAME_ELEMENT(BTN_GEAR_UP), - -#ifdef BTN_TRIGGER_HAPPY - NAME_ELEMENT(BTN_TRIGGER_HAPPY1), NAME_ELEMENT(BTN_TRIGGER_HAPPY11), - NAME_ELEMENT(BTN_TRIGGER_HAPPY2), NAME_ELEMENT(BTN_TRIGGER_HAPPY12), - NAME_ELEMENT(BTN_TRIGGER_HAPPY3), NAME_ELEMENT(BTN_TRIGGER_HAPPY13), - NAME_ELEMENT(BTN_TRIGGER_HAPPY4), NAME_ELEMENT(BTN_TRIGGER_HAPPY14), - NAME_ELEMENT(BTN_TRIGGER_HAPPY5), NAME_ELEMENT(BTN_TRIGGER_HAPPY15), - NAME_ELEMENT(BTN_TRIGGER_HAPPY6), NAME_ELEMENT(BTN_TRIGGER_HAPPY16), - NAME_ELEMENT(BTN_TRIGGER_HAPPY7), NAME_ELEMENT(BTN_TRIGGER_HAPPY17), - NAME_ELEMENT(BTN_TRIGGER_HAPPY8), NAME_ELEMENT(BTN_TRIGGER_HAPPY18), - NAME_ELEMENT(BTN_TRIGGER_HAPPY9), NAME_ELEMENT(BTN_TRIGGER_HAPPY19), - NAME_ELEMENT(BTN_TRIGGER_HAPPY10), NAME_ELEMENT(BTN_TRIGGER_HAPPY20), - - NAME_ELEMENT(BTN_TRIGGER_HAPPY21), NAME_ELEMENT(BTN_TRIGGER_HAPPY31), - NAME_ELEMENT(BTN_TRIGGER_HAPPY22), NAME_ELEMENT(BTN_TRIGGER_HAPPY32), - NAME_ELEMENT(BTN_TRIGGER_HAPPY23), NAME_ELEMENT(BTN_TRIGGER_HAPPY33), - NAME_ELEMENT(BTN_TRIGGER_HAPPY24), NAME_ELEMENT(BTN_TRIGGER_HAPPY34), - NAME_ELEMENT(BTN_TRIGGER_HAPPY25), NAME_ELEMENT(BTN_TRIGGER_HAPPY35), - NAME_ELEMENT(BTN_TRIGGER_HAPPY26), NAME_ELEMENT(BTN_TRIGGER_HAPPY36), - NAME_ELEMENT(BTN_TRIGGER_HAPPY27), NAME_ELEMENT(BTN_TRIGGER_HAPPY37), - NAME_ELEMENT(BTN_TRIGGER_HAPPY28), NAME_ELEMENT(BTN_TRIGGER_HAPPY38), - NAME_ELEMENT(BTN_TRIGGER_HAPPY29), NAME_ELEMENT(BTN_TRIGGER_HAPPY39), - NAME_ELEMENT(BTN_TRIGGER_HAPPY30), NAME_ELEMENT(BTN_TRIGGER_HAPPY40), -#endif -#ifdef BTN_TOOL_QUINTTAP - NAME_ELEMENT(BTN_TOOL_QUINTTAP), -#endif - }; cfg_t *cfg = NULL; @@ -595,16 +322,15 @@ for (i = 0; i < G110_GROUP_COUNT; i++) for (j = 0; j < G110_BTN_COUNT; j++) if (key_val[i][j] != NULL) { - key_code = g110_get_keycode(key_names, key_val[i][j]); - if (key_code == UINT16_MAX) { - dev_button[i][j].cmd = malloc(strlen(key_val[i][j]) + 1); - if (dev_button[i][j].cmd != NULL) - strcpy(dev_button[i][j].cmd, key_val[i][j]); - } - else + key_code = my_get_keycode(key_val[i][j]); + if (key_code != KEY_CNT) dev_button[i][j].code = key_code; + else if (strncmp(key_val[i][j], "macro ", 6) == 0) + dev_button[i][j].macro = my_macro_parse(key_val[i][j] + 6, &dev_button[i][j].macro_len); + else + dev_button[i][j].cmd = strdup(key_val[i][j]); } - + error: if (cfg != NULL) cfg_free(cfg); @@ -640,9 +366,50 @@ return 0; } +static void * g110_pthread_process_macro(void *arg) { + Dev_button *key = arg; + struct timespec sleep_time; + int i; + + for (i = 0; i < key->macro_len; i++) { + switch (key->macro[i].type) { + case MACRO_KEYPRESS: + pthread_mutex_lock(&mutex_uinput); + suinput_emit(uinput_dev_fd, EV_KEY, key->macro[i].value, 1); + suinput_syn(uinput_dev_fd); + suinput_emit(uinput_dev_fd, EV_KEY, key->macro[i].value, 0); + suinput_syn(uinput_dev_fd); + pthread_mutex_unlock(&mutex_uinput); + break; + case MACRO_KEYDOWN: + pthread_mutex_lock(&mutex_uinput); + suinput_emit(uinput_dev_fd, EV_KEY, key->macro[i].value, 1); + suinput_syn(uinput_dev_fd); + pthread_mutex_unlock(&mutex_uinput); + break; + case MACRO_KEYUP: + pthread_mutex_lock(&mutex_uinput); + suinput_emit(uinput_dev_fd, EV_KEY, key->macro[i].value, 0); + suinput_syn(uinput_dev_fd); + pthread_mutex_unlock(&mutex_uinput); + break; + case MACRO_MSLEEP: + sleep_time.tv_sec = key->macro[i].value / 1000; + sleep_time.tv_nsec = (key->macro[i].value % 1000) * 1000000; + nanosleep(&sleep_time, NULL); + break; + default: + break; + } + } + + pthread_exit(NULL); +} + static void g110_data_transfer_cb(struct libusb_transfer *transfer) { int old_group, temp_group, i; uint16_t mask; + pthread_t thread_id; if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { do_exit = 1; @@ -659,55 +426,59 @@ #ifdef BIG_ENDIAN_HOST button_state_new = bswap_16(button_state_new); #endif + pthread_mutex_lock(&mutex_uinput); for (i = 0; i < G110_BTN_COUNT; i++) { mask = 1 << i; if (((button_state_old & mask) == 0) && ((button_state_new & mask) == mask)) { /*key down*/ button_down_group[i] = temp_group; - if (dev_button[temp_group][i].cmd == NULL) { - suinput_emit(uinput_dev_fd, EV_KEY, dev_button[temp_group][i].code, 1); - suinput_syn(uinput_dev_fd); + if (dev_button[temp_group][i].macro != NULL) { + pthread_create(&thread_id, &detached_thread_attr, g110_pthread_process_macro, &dev_button[temp_group][i]); + } + else if (dev_button[temp_group][i].cmd != NULL) { + my_execute_command(dev_button[temp_group][i].cmd); } else { - g110_execute_command(dev_button[temp_group][i].cmd); + suinput_emit(uinput_dev_fd, EV_KEY, dev_button[temp_group][i].code, 1); + suinput_syn(uinput_dev_fd); } } else if (((button_state_old & mask) == mask) && ((button_state_new & mask) == 0)) { /*key up*/ old_group = button_down_group[i]; - if (dev_button[old_group][i].cmd == NULL) { + if ((dev_button[old_group][i].cmd == NULL) && (dev_button[old_group][i].macro == NULL)) { suinput_emit(uinput_dev_fd, EV_KEY, dev_button[old_group][i].code, 0); suinput_syn(uinput_dev_fd); } } } + pthread_mutex_unlock(&mutex_uinput); - /*M1*/ - if (((button_state_old & G110_KEY_M1) == 0) && ((button_state_new & G110_KEY_M1) == G110_KEY_M1)) { /*key down*/ - if (active_group != 0) { - active_group = 0; - change_group = 1; - } - } - /*M2*/ - if (((button_state_old & G110_KEY_M2) == 0) && ((button_state_new & G110_KEY_M2) == G110_KEY_M2)) { /*key down*/ - if (active_group != 1) { - active_group = 1; - change_group = 1; - } - } - /*M3*/ - if (((button_state_old & G110_KEY_M3) == 0) && ((button_state_new & G110_KEY_M3) == G110_KEY_M3)) { /*key down*/ - if (active_group != 2) { - active_group = 2; - change_group = 1; + for (i = 0; i < G110_GROUP_COUNT; i++) { + switch (i) { + case 0: + mask = G110_KEY_M1; + break; + case 1: + mask = G110_KEY_M2; + break; + case 2: + mask = G110_KEY_M3; + break; + case 3: + mask = G110_KEY_MR; + break; + default: + mask = 0; + break; } - } - /*MR*/ - if (((button_state_old & G110_KEY_MR) == 0) && ((button_state_new & G110_KEY_MR) == G110_KEY_MR)) { /*key down*/ - if (active_group != 3) { - active_group = 3; - change_group = 1; + + if (((button_state_old & mask) == 0) && ((button_state_new & mask) == mask)) { /*key down*/ + if (active_group != i) { + active_group = i; + change_group = 1; + } } } + button_state_old = button_state_new; } @@ -721,18 +492,6 @@ data_transfer = NULL; } -static int g110_start_data_capture(void) { - data_transfer = libusb_alloc_transfer(0); - if (data_transfer == NULL) - return -1; - libusb_fill_interrupt_transfer(data_transfer, dev_handle, - G110_EP_DATA_IN, dev_data, G110_DEV_DATA_LEN, - g110_data_transfer_cb, NULL, G110_DATA_TIMEOUT); - if (libusb_submit_transfer(data_transfer) != 0) - return -1; - return 0; -} - static int g110_initial_setup(void) { int transfared; unsigned char init_data[G110_DEV_INIT_LEN] = {4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -766,67 +525,63 @@ return 0; } -static void g110_daemonize(void) { - pid_t pid, sid; +static int g110_init_pthread(void) { + if (pthread_attr_init(&detached_thread_attr) != 0) + goto error; - stdin_copy_fd = dup(STDIN_FILENO); - if (stdin_copy_fd == -1) - exit(EXIT_FAILURE); - stdout_copy_fd = dup(STDOUT_FILENO); - if (stdout_copy_fd == -1) - exit(EXIT_FAILURE); - stderr_copy_fd = dup(STDERR_FILENO); - if (stderr_copy_fd == -1) - exit(EXIT_FAILURE); - - pid = fork(); - if (pid < 0) - exit(EXIT_FAILURE); - if (pid > 0) - exit(EXIT_SUCCESS); - sid = setsid(); - if (sid < 0) - exit(EXIT_FAILURE); - pid = fork(); - if (pid < 0) - exit(EXIT_FAILURE); - if (pid > 0) - exit(EXIT_SUCCESS); - umask(0); - if (chdir("/etc") < 0) - exit(EXIT_FAILURE); - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - if (open("/dev/null", O_RDONLY) != 0) - exit(EXIT_FAILURE); - if (open("/dev/null", O_RDWR) != 1) - exit(EXIT_FAILURE); - if (open("/dev/null", O_RDWR) != 2) - exit(EXIT_FAILURE); -} + if (pthread_attr_setdetachstate(&detached_thread_attr, PTHREAD_CREATE_DETACHED) != 0) + goto error; -int main(void) { - int i, j, ret; - int return_value = 1; - int kernel_driver = 0; - int interface_claimed = 0; - struct uinput_user_dev user_dev; + if (pthread_mutex_init(&mutex_uinput, NULL) != 0) + goto error; - g110_daemonize(); + return 0; +error: + return -1; +} - g110_set_default_settings(); - g110_read_config(); +static void g110_destroy_ptread(void) { + pthread_mutex_destroy(&mutex_uinput); + pthread_attr_destroy(&detached_thread_attr); +} +static int g110_create_uinput_device(void) { + int i, j, k; + struct uinput_user_dev user_dev; + memset(&user_dev, 0, sizeof(struct uinput_user_dev)); strcpy(user_dev.name, G110_DEV_NAME); uinput_dev_fd = suinput_open(); + + if (uinput_dev_fd == -1) + goto error; + for (i = 0; i < G110_GROUP_COUNT; i++) - for (j = 0; j < G110_BTN_COUNT; j++) - if (dev_button[i][j].cmd == NULL) - suinput_enable_event(uinput_dev_fd, EV_KEY, dev_button[i][j].code); - suinput_create(uinput_dev_fd, &user_dev); + for (j = 0; j < G110_BTN_COUNT; j++) { + if (dev_button[i][j].macro != NULL) { + for (k = 0; k < dev_button[i][j].macro_len; k++) { + if (dev_button[i][j].macro[k].type != MACRO_MSLEEP) + if (suinput_enable_event(uinput_dev_fd, EV_KEY, dev_button[i][j].macro[k].value) == -1) + goto error; + } + } else if (dev_button[i][j].cmd == NULL) + if (suinput_enable_event(uinput_dev_fd, EV_KEY, dev_button[i][j].code) == -1) + goto error; + } + + if (suinput_create(uinput_dev_fd, &user_dev) == -1) + goto error; + + return 0; +error: + return -1; +} +static void g110_destroy_uinput_device(void) { + suinput_destroy(uinput_dev_fd); +} + +static int g110_init_usb_device(void) { if (libusb_init(&dev_ctx) != 0) goto error; @@ -847,42 +602,55 @@ goto error; interface_claimed = 1; + data_transfer = libusb_alloc_transfer(0); + if (data_transfer == NULL) + goto error; + libusb_fill_interrupt_transfer(data_transfer, dev_handle, + G110_EP_DATA_IN, dev_data, G110_DEV_DATA_LEN, + g110_data_transfer_cb, NULL, G110_DATA_TIMEOUT); + if (g110_initial_setup() != 0) goto error; - if (g110_start_data_capture() != 0) - goto error; + return 0; +error: + return -1; +} - if (g110_sighandler_setup() != 0) - goto error; +static void g110_process_device(void) { + int ret; + + if (libusb_submit_transfer(data_transfer) != 0) + return ; while (!do_exit) { ret = libusb_handle_events_timeout_completed(dev_ctx, &libusb_timeout, NULL); if (ret == LIBUSB_ERROR_INTERRUPTED) continue; if (ret != 0) - goto error; + break; if (change_group == 1) { change_group = 0; if (g110_activate_group(active_group) != 0) do_exit = 2; } } - +} + +static void g110_cancel_usb_transfer(void) { if (data_transfer != NULL) - ret = libusb_cancel_transfer(data_transfer); + libusb_cancel_transfer(data_transfer); while (data_transfer != NULL) { if (libusb_handle_events_completed(dev_ctx, NULL) != 0) - goto error; + break; } +} + +static int g110_free_usb_device(void) { + int ret; + int return_value = 0; - if (do_exit == 1) - return_value = 0; - -error: - g110_release_all_buttons(); - suinput_destroy(uinput_dev_fd); libusb_free_transfer(data_transfer); if (interface_claimed == 1) { ret = libusb_release_interface(dev_handle, G110_DATA_INTERFACE); @@ -897,6 +665,44 @@ if (dev_handle != NULL) libusb_close(dev_handle); libusb_exit(dev_ctx); + + return return_value; +} + +int main(void) { + int ret; + int return_value = 1; + + my_daemonize(G110_WORK_DIR); + + g110_set_default_settings(); + + g110_read_config(); + + if (g110_create_uinput_device() == -1) + goto error; + + if (g110_init_usb_device() == -1) + goto error; + + if (g110_sighandler_setup() != 0) + goto error; + + if (g110_init_pthread() == -1) + goto error; + + g110_process_device(); + +error: + g110_release_all_buttons(); + g110_cancel_usb_transfer(); + if (do_exit == 1) + return_value = 0; + ret = g110_free_usb_device(); + if (ret != 0) + return_value = ret; + g110_destroy_uinput_device(); + g110_destroy_ptread(); g110_free_settings(); return return_value; } \ No newline at end of file diff -Nru g110d-0.1/utilities.c g110d-0.2/utilities.c --- g110d-0.1/utilities.c 1970-01-01 00:00:00.000000000 +0000 +++ g110d-0.2/utilities.c 2014-01-22 20:50:39.000000000 +0000 @@ -0,0 +1,486 @@ +/* + * utilities.c + * Copyright (C) 2014 Paulius Vitkus + * + * nagad is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * nagad is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "utilities.h" + +#define NAME_ELEMENT(element) [element] = #element + +static const char *key_names[KEY_CNT] = { + [0 ... KEY_MAX] = NULL, + NAME_ELEMENT(KEY_RESERVED), NAME_ELEMENT(KEY_ESC), + NAME_ELEMENT(KEY_1), NAME_ELEMENT(KEY_2), + NAME_ELEMENT(KEY_3), NAME_ELEMENT(KEY_4), + NAME_ELEMENT(KEY_5), NAME_ELEMENT(KEY_6), + NAME_ELEMENT(KEY_7), NAME_ELEMENT(KEY_8), + NAME_ELEMENT(KEY_9), NAME_ELEMENT(KEY_0), + NAME_ELEMENT(KEY_MINUS), NAME_ELEMENT(KEY_EQUAL), + NAME_ELEMENT(KEY_BACKSPACE), NAME_ELEMENT(KEY_TAB), + NAME_ELEMENT(KEY_Q), NAME_ELEMENT(KEY_W), + NAME_ELEMENT(KEY_E), NAME_ELEMENT(KEY_R), + NAME_ELEMENT(KEY_T), NAME_ELEMENT(KEY_Y), + NAME_ELEMENT(KEY_U), NAME_ELEMENT(KEY_I), + NAME_ELEMENT(KEY_O), NAME_ELEMENT(KEY_P), + NAME_ELEMENT(KEY_LEFTBRACE), NAME_ELEMENT(KEY_RIGHTBRACE), + NAME_ELEMENT(KEY_ENTER), NAME_ELEMENT(KEY_LEFTCTRL), + NAME_ELEMENT(KEY_A), NAME_ELEMENT(KEY_S), + NAME_ELEMENT(KEY_D), NAME_ELEMENT(KEY_F), + NAME_ELEMENT(KEY_G), NAME_ELEMENT(KEY_H), + NAME_ELEMENT(KEY_J), NAME_ELEMENT(KEY_K), + NAME_ELEMENT(KEY_L), NAME_ELEMENT(KEY_SEMICOLON), + NAME_ELEMENT(KEY_APOSTROPHE), NAME_ELEMENT(KEY_GRAVE), + NAME_ELEMENT(KEY_LEFTSHIFT), NAME_ELEMENT(KEY_BACKSLASH), + NAME_ELEMENT(KEY_Z), NAME_ELEMENT(KEY_X), + NAME_ELEMENT(KEY_C), NAME_ELEMENT(KEY_V), + NAME_ELEMENT(KEY_B), NAME_ELEMENT(KEY_N), + NAME_ELEMENT(KEY_M), NAME_ELEMENT(KEY_COMMA), + NAME_ELEMENT(KEY_DOT), NAME_ELEMENT(KEY_SLASH), + NAME_ELEMENT(KEY_RIGHTSHIFT), NAME_ELEMENT(KEY_KPASTERISK), + NAME_ELEMENT(KEY_LEFTALT), NAME_ELEMENT(KEY_SPACE), + NAME_ELEMENT(KEY_CAPSLOCK), NAME_ELEMENT(KEY_F1), + NAME_ELEMENT(KEY_F2), NAME_ELEMENT(KEY_F3), + NAME_ELEMENT(KEY_F4), NAME_ELEMENT(KEY_F5), + NAME_ELEMENT(KEY_F6), NAME_ELEMENT(KEY_F7), + NAME_ELEMENT(KEY_F8), NAME_ELEMENT(KEY_F9), + NAME_ELEMENT(KEY_F10), NAME_ELEMENT(KEY_NUMLOCK), + NAME_ELEMENT(KEY_SCROLLLOCK), NAME_ELEMENT(KEY_KP7), + NAME_ELEMENT(KEY_KP8), NAME_ELEMENT(KEY_KP9), + NAME_ELEMENT(KEY_KPMINUS), NAME_ELEMENT(KEY_KP4), + NAME_ELEMENT(KEY_KP5), NAME_ELEMENT(KEY_KP6), + NAME_ELEMENT(KEY_KPPLUS), NAME_ELEMENT(KEY_KP1), + NAME_ELEMENT(KEY_KP2), NAME_ELEMENT(KEY_KP3), + NAME_ELEMENT(KEY_KP0), NAME_ELEMENT(KEY_KPDOT), + NAME_ELEMENT(KEY_ZENKAKUHANKAKU), NAME_ELEMENT(KEY_102ND), + NAME_ELEMENT(KEY_F11), NAME_ELEMENT(KEY_F12), + NAME_ELEMENT(KEY_RO), NAME_ELEMENT(KEY_KATAKANA), + NAME_ELEMENT(KEY_HIRAGANA), NAME_ELEMENT(KEY_HENKAN), + NAME_ELEMENT(KEY_KATAKANAHIRAGANA), NAME_ELEMENT(KEY_MUHENKAN), + NAME_ELEMENT(KEY_KPJPCOMMA), NAME_ELEMENT(KEY_KPENTER), + NAME_ELEMENT(KEY_RIGHTCTRL), NAME_ELEMENT(KEY_KPSLASH), + NAME_ELEMENT(KEY_SYSRQ), NAME_ELEMENT(KEY_RIGHTALT), + NAME_ELEMENT(KEY_LINEFEED), NAME_ELEMENT(KEY_HOME), + NAME_ELEMENT(KEY_UP), NAME_ELEMENT(KEY_PAGEUP), + NAME_ELEMENT(KEY_LEFT), NAME_ELEMENT(KEY_RIGHT), + NAME_ELEMENT(KEY_END), NAME_ELEMENT(KEY_DOWN), + NAME_ELEMENT(KEY_PAGEDOWN), NAME_ELEMENT(KEY_INSERT), + NAME_ELEMENT(KEY_DELETE), NAME_ELEMENT(KEY_MACRO), + NAME_ELEMENT(KEY_MUTE), NAME_ELEMENT(KEY_VOLUMEDOWN), + NAME_ELEMENT(KEY_VOLUMEUP), NAME_ELEMENT(KEY_POWER), + NAME_ELEMENT(KEY_KPEQUAL), NAME_ELEMENT(KEY_KPPLUSMINUS), + NAME_ELEMENT(KEY_PAUSE), NAME_ELEMENT(KEY_KPCOMMA), + NAME_ELEMENT(KEY_HANGUEL), NAME_ELEMENT(KEY_HANJA), + NAME_ELEMENT(KEY_YEN), NAME_ELEMENT(KEY_LEFTMETA), + NAME_ELEMENT(KEY_RIGHTMETA), NAME_ELEMENT(KEY_COMPOSE), + NAME_ELEMENT(KEY_STOP), NAME_ELEMENT(KEY_AGAIN), + NAME_ELEMENT(KEY_PROPS), NAME_ELEMENT(KEY_UNDO), + NAME_ELEMENT(KEY_FRONT), NAME_ELEMENT(KEY_COPY), + NAME_ELEMENT(KEY_OPEN), NAME_ELEMENT(KEY_PASTE), + NAME_ELEMENT(KEY_FIND), NAME_ELEMENT(KEY_CUT), + NAME_ELEMENT(KEY_HELP), NAME_ELEMENT(KEY_MENU), + NAME_ELEMENT(KEY_CALC), NAME_ELEMENT(KEY_SETUP), + NAME_ELEMENT(KEY_SLEEP), NAME_ELEMENT(KEY_WAKEUP), + NAME_ELEMENT(KEY_FILE), NAME_ELEMENT(KEY_SENDFILE), + NAME_ELEMENT(KEY_DELETEFILE), NAME_ELEMENT(KEY_XFER), + NAME_ELEMENT(KEY_PROG1), NAME_ELEMENT(KEY_PROG2), + NAME_ELEMENT(KEY_WWW), NAME_ELEMENT(KEY_MSDOS), + NAME_ELEMENT(KEY_COFFEE), NAME_ELEMENT(KEY_DIRECTION), + NAME_ELEMENT(KEY_CYCLEWINDOWS), NAME_ELEMENT(KEY_MAIL), + NAME_ELEMENT(KEY_BOOKMARKS), NAME_ELEMENT(KEY_COMPUTER), + NAME_ELEMENT(KEY_BACK), NAME_ELEMENT(KEY_FORWARD), + NAME_ELEMENT(KEY_CLOSECD), NAME_ELEMENT(KEY_EJECTCD), + NAME_ELEMENT(KEY_EJECTCLOSECD), NAME_ELEMENT(KEY_NEXTSONG), + NAME_ELEMENT(KEY_PLAYPAUSE), NAME_ELEMENT(KEY_PREVIOUSSONG), + NAME_ELEMENT(KEY_STOPCD), NAME_ELEMENT(KEY_RECORD), + NAME_ELEMENT(KEY_REWIND), NAME_ELEMENT(KEY_PHONE), + NAME_ELEMENT(KEY_ISO), NAME_ELEMENT(KEY_CONFIG), + NAME_ELEMENT(KEY_HOMEPAGE), NAME_ELEMENT(KEY_REFRESH), + NAME_ELEMENT(KEY_EXIT), NAME_ELEMENT(KEY_MOVE), + NAME_ELEMENT(KEY_EDIT), NAME_ELEMENT(KEY_SCROLLUP), + NAME_ELEMENT(KEY_SCROLLDOWN), NAME_ELEMENT(KEY_KPLEFTPAREN), + NAME_ELEMENT(KEY_KPRIGHTPAREN), NAME_ELEMENT(KEY_F13), + NAME_ELEMENT(KEY_F14), NAME_ELEMENT(KEY_F15), + NAME_ELEMENT(KEY_F16), NAME_ELEMENT(KEY_F17), + NAME_ELEMENT(KEY_F18), NAME_ELEMENT(KEY_F19), + NAME_ELEMENT(KEY_F20), NAME_ELEMENT(KEY_F21), + NAME_ELEMENT(KEY_F22), NAME_ELEMENT(KEY_F23), + NAME_ELEMENT(KEY_F24), NAME_ELEMENT(KEY_PLAYCD), + NAME_ELEMENT(KEY_PAUSECD), NAME_ELEMENT(KEY_PROG3), + NAME_ELEMENT(KEY_PROG4), NAME_ELEMENT(KEY_SUSPEND), + NAME_ELEMENT(KEY_CLOSE), NAME_ELEMENT(KEY_PLAY), + NAME_ELEMENT(KEY_FASTFORWARD), NAME_ELEMENT(KEY_BASSBOOST), + NAME_ELEMENT(KEY_PRINT), NAME_ELEMENT(KEY_HP), + NAME_ELEMENT(KEY_CAMERA), NAME_ELEMENT(KEY_SOUND), + NAME_ELEMENT(KEY_QUESTION), NAME_ELEMENT(KEY_EMAIL), + NAME_ELEMENT(KEY_CHAT), NAME_ELEMENT(KEY_SEARCH), + NAME_ELEMENT(KEY_CONNECT), NAME_ELEMENT(KEY_FINANCE), + NAME_ELEMENT(KEY_SPORT), NAME_ELEMENT(KEY_SHOP), + NAME_ELEMENT(KEY_ALTERASE), NAME_ELEMENT(KEY_CANCEL), + NAME_ELEMENT(KEY_BRIGHTNESSDOWN), NAME_ELEMENT(KEY_BRIGHTNESSUP), + NAME_ELEMENT(KEY_MEDIA), NAME_ELEMENT(KEY_UNKNOWN), + NAME_ELEMENT(KEY_OK), + NAME_ELEMENT(KEY_SELECT), NAME_ELEMENT(KEY_GOTO), + NAME_ELEMENT(KEY_CLEAR), NAME_ELEMENT(KEY_POWER2), + NAME_ELEMENT(KEY_OPTION), NAME_ELEMENT(KEY_INFO), + NAME_ELEMENT(KEY_TIME), NAME_ELEMENT(KEY_VENDOR), + NAME_ELEMENT(KEY_ARCHIVE), NAME_ELEMENT(KEY_PROGRAM), + NAME_ELEMENT(KEY_CHANNEL), NAME_ELEMENT(KEY_FAVORITES), + NAME_ELEMENT(KEY_EPG), NAME_ELEMENT(KEY_PVR), + NAME_ELEMENT(KEY_MHP), NAME_ELEMENT(KEY_LANGUAGE), + NAME_ELEMENT(KEY_TITLE), NAME_ELEMENT(KEY_SUBTITLE), + NAME_ELEMENT(KEY_ANGLE), NAME_ELEMENT(KEY_ZOOM), + NAME_ELEMENT(KEY_MODE), NAME_ELEMENT(KEY_KEYBOARD), + NAME_ELEMENT(KEY_SCREEN), NAME_ELEMENT(KEY_PC), + NAME_ELEMENT(KEY_TV), NAME_ELEMENT(KEY_TV2), + NAME_ELEMENT(KEY_VCR), NAME_ELEMENT(KEY_VCR2), + NAME_ELEMENT(KEY_SAT), NAME_ELEMENT(KEY_SAT2), + NAME_ELEMENT(KEY_CD), NAME_ELEMENT(KEY_TAPE), + NAME_ELEMENT(KEY_RADIO), NAME_ELEMENT(KEY_TUNER), + NAME_ELEMENT(KEY_PLAYER), NAME_ELEMENT(KEY_TEXT), + NAME_ELEMENT(KEY_DVD), NAME_ELEMENT(KEY_AUX), + NAME_ELEMENT(KEY_MP3), NAME_ELEMENT(KEY_AUDIO), + NAME_ELEMENT(KEY_VIDEO), NAME_ELEMENT(KEY_DIRECTORY), + NAME_ELEMENT(KEY_LIST), NAME_ELEMENT(KEY_MEMO), + NAME_ELEMENT(KEY_CALENDAR), NAME_ELEMENT(KEY_RED), + NAME_ELEMENT(KEY_GREEN), NAME_ELEMENT(KEY_YELLOW), + NAME_ELEMENT(KEY_BLUE), NAME_ELEMENT(KEY_CHANNELUP), + NAME_ELEMENT(KEY_CHANNELDOWN), NAME_ELEMENT(KEY_FIRST), + NAME_ELEMENT(KEY_LAST), NAME_ELEMENT(KEY_AB), + NAME_ELEMENT(KEY_NEXT), NAME_ELEMENT(KEY_RESTART), + NAME_ELEMENT(KEY_SLOW), NAME_ELEMENT(KEY_SHUFFLE), + NAME_ELEMENT(KEY_BREAK), NAME_ELEMENT(KEY_PREVIOUS), + NAME_ELEMENT(KEY_DIGITS), NAME_ELEMENT(KEY_TEEN), + NAME_ELEMENT(KEY_TWEN), NAME_ELEMENT(KEY_DEL_EOL), + NAME_ELEMENT(KEY_DEL_EOS), NAME_ELEMENT(KEY_INS_LINE), + NAME_ELEMENT(KEY_DEL_LINE), + NAME_ELEMENT(KEY_VIDEOPHONE), NAME_ELEMENT(KEY_GAMES), + NAME_ELEMENT(KEY_ZOOMIN), NAME_ELEMENT(KEY_ZOOMOUT), + NAME_ELEMENT(KEY_ZOOMRESET), NAME_ELEMENT(KEY_WORDPROCESSOR), + NAME_ELEMENT(KEY_EDITOR), NAME_ELEMENT(KEY_SPREADSHEET), + NAME_ELEMENT(KEY_GRAPHICSEDITOR), NAME_ELEMENT(KEY_PRESENTATION), + NAME_ELEMENT(KEY_DATABASE), NAME_ELEMENT(KEY_NEWS), + NAME_ELEMENT(KEY_VOICEMAIL), NAME_ELEMENT(KEY_ADDRESSBOOK), + NAME_ELEMENT(KEY_MESSENGER), NAME_ELEMENT(KEY_DISPLAYTOGGLE), + NAME_ELEMENT(KEY_SPELLCHECK), NAME_ELEMENT(KEY_LOGOFF), + NAME_ELEMENT(KEY_DOLLAR), NAME_ELEMENT(KEY_EURO), + NAME_ELEMENT(KEY_FRAMEBACK), NAME_ELEMENT(KEY_FRAMEFORWARD), + NAME_ELEMENT(KEY_CONTEXT_MENU), NAME_ELEMENT(KEY_MEDIA_REPEAT), + NAME_ELEMENT(KEY_DEL_EOL), NAME_ELEMENT(KEY_DEL_EOS), + NAME_ELEMENT(KEY_INS_LINE), NAME_ELEMENT(KEY_DEL_LINE), + NAME_ELEMENT(KEY_FN), NAME_ELEMENT(KEY_FN_ESC), + NAME_ELEMENT(KEY_FN_F1), NAME_ELEMENT(KEY_FN_F2), + NAME_ELEMENT(KEY_FN_F3), NAME_ELEMENT(KEY_FN_F4), + NAME_ELEMENT(KEY_FN_F5), NAME_ELEMENT(KEY_FN_F6), + NAME_ELEMENT(KEY_FN_F7), NAME_ELEMENT(KEY_FN_F8), + NAME_ELEMENT(KEY_FN_F9), NAME_ELEMENT(KEY_FN_F10), + NAME_ELEMENT(KEY_FN_F11), NAME_ELEMENT(KEY_FN_F12), + NAME_ELEMENT(KEY_FN_1), NAME_ELEMENT(KEY_FN_2), + NAME_ELEMENT(KEY_FN_D), NAME_ELEMENT(KEY_FN_E), + NAME_ELEMENT(KEY_FN_F), NAME_ELEMENT(KEY_FN_S), + NAME_ELEMENT(KEY_FN_B), + NAME_ELEMENT(KEY_BRL_DOT1), NAME_ELEMENT(KEY_BRL_DOT2), + NAME_ELEMENT(KEY_BRL_DOT3), NAME_ELEMENT(KEY_BRL_DOT4), + NAME_ELEMENT(KEY_BRL_DOT5), NAME_ELEMENT(KEY_BRL_DOT6), + NAME_ELEMENT(KEY_BRL_DOT7), NAME_ELEMENT(KEY_BRL_DOT8), + NAME_ELEMENT(KEY_BRL_DOT9), NAME_ELEMENT(KEY_BRL_DOT10), + NAME_ELEMENT(KEY_NUMERIC_0), NAME_ELEMENT(KEY_NUMERIC_1), + NAME_ELEMENT(KEY_NUMERIC_2), NAME_ELEMENT(KEY_NUMERIC_3), + NAME_ELEMENT(KEY_NUMERIC_4), NAME_ELEMENT(KEY_NUMERIC_5), + NAME_ELEMENT(KEY_NUMERIC_6), NAME_ELEMENT(KEY_NUMERIC_7), + NAME_ELEMENT(KEY_NUMERIC_8), NAME_ELEMENT(KEY_NUMERIC_9), + NAME_ELEMENT(KEY_NUMERIC_STAR), NAME_ELEMENT(KEY_NUMERIC_POUND), + NAME_ELEMENT(KEY_BATTERY), + NAME_ELEMENT(KEY_BLUETOOTH), NAME_ELEMENT(KEY_BRIGHTNESS_CYCLE), + NAME_ELEMENT(KEY_BRIGHTNESS_ZERO), NAME_ELEMENT(KEY_DASHBOARD), + NAME_ELEMENT(KEY_DISPLAY_OFF), NAME_ELEMENT(KEY_DOCUMENTS), + NAME_ELEMENT(KEY_FORWARDMAIL), NAME_ELEMENT(KEY_NEW), + NAME_ELEMENT(KEY_KBDILLUMDOWN), NAME_ELEMENT(KEY_KBDILLUMUP), + NAME_ELEMENT(KEY_KBDILLUMTOGGLE), NAME_ELEMENT(KEY_REDO), + NAME_ELEMENT(KEY_REPLY), NAME_ELEMENT(KEY_SAVE), + NAME_ELEMENT(KEY_SCALE), NAME_ELEMENT(KEY_SEND), + NAME_ELEMENT(KEY_SCREENLOCK), NAME_ELEMENT(KEY_SWITCHVIDEOMODE), + NAME_ELEMENT(KEY_UWB), NAME_ELEMENT(KEY_VIDEO_NEXT), + NAME_ELEMENT(KEY_VIDEO_PREV), NAME_ELEMENT(KEY_WIMAX), + NAME_ELEMENT(KEY_WLAN), +#ifdef KEY_RFKILL + NAME_ELEMENT(KEY_RFKILL), +#endif +#ifdef KEY_WPS_BUTTON + NAME_ELEMENT(KEY_WPS_BUTTON), +#endif +#ifdef KEY_TOUCHPAD_TOGGLE + NAME_ELEMENT(KEY_TOUCHPAD_TOGGLE), + NAME_ELEMENT(KEY_TOUCHPAD_ON), + NAME_ELEMENT(KEY_TOUCHPAD_OFF), +#endif + + NAME_ELEMENT(BTN_0), NAME_ELEMENT(BTN_1), + NAME_ELEMENT(BTN_2), NAME_ELEMENT(BTN_3), + NAME_ELEMENT(BTN_4), NAME_ELEMENT(BTN_5), + NAME_ELEMENT(BTN_6), NAME_ELEMENT(BTN_7), + NAME_ELEMENT(BTN_8), NAME_ELEMENT(BTN_9), + NAME_ELEMENT(BTN_LEFT), NAME_ELEMENT(BTN_RIGHT), + NAME_ELEMENT(BTN_MIDDLE), NAME_ELEMENT(BTN_SIDE), + NAME_ELEMENT(BTN_EXTRA), NAME_ELEMENT(BTN_FORWARD), + NAME_ELEMENT(BTN_BACK), NAME_ELEMENT(BTN_TASK), + NAME_ELEMENT(BTN_TRIGGER), NAME_ELEMENT(BTN_THUMB), + NAME_ELEMENT(BTN_THUMB2), NAME_ELEMENT(BTN_TOP), + NAME_ELEMENT(BTN_TOP2), NAME_ELEMENT(BTN_PINKIE), + NAME_ELEMENT(BTN_BASE), NAME_ELEMENT(BTN_BASE2), + NAME_ELEMENT(BTN_BASE3), NAME_ELEMENT(BTN_BASE4), + NAME_ELEMENT(BTN_BASE5), NAME_ELEMENT(BTN_BASE6), + NAME_ELEMENT(BTN_DEAD), NAME_ELEMENT(BTN_A), + NAME_ELEMENT(BTN_B), NAME_ELEMENT(BTN_C), + NAME_ELEMENT(BTN_X), NAME_ELEMENT(BTN_Y), + NAME_ELEMENT(BTN_Z), NAME_ELEMENT(BTN_TL), + NAME_ELEMENT(BTN_TR), NAME_ELEMENT(BTN_TL2), + NAME_ELEMENT(BTN_TR2), NAME_ELEMENT(BTN_SELECT), + NAME_ELEMENT(BTN_START), NAME_ELEMENT(BTN_MODE), + NAME_ELEMENT(BTN_THUMBL), NAME_ELEMENT(BTN_THUMBR), + NAME_ELEMENT(BTN_TOOL_PEN), NAME_ELEMENT(BTN_TOOL_RUBBER), + NAME_ELEMENT(BTN_TOOL_BRUSH), NAME_ELEMENT(BTN_TOOL_PENCIL), + NAME_ELEMENT(BTN_TOOL_AIRBRUSH), NAME_ELEMENT(BTN_TOOL_FINGER), + NAME_ELEMENT(BTN_TOOL_MOUSE), NAME_ELEMENT(BTN_TOOL_LENS), + NAME_ELEMENT(BTN_TOUCH), NAME_ELEMENT(BTN_STYLUS), + NAME_ELEMENT(BTN_STYLUS2), NAME_ELEMENT(BTN_TOOL_DOUBLETAP), + NAME_ELEMENT(BTN_TOOL_TRIPLETAP), NAME_ELEMENT(BTN_TOOL_QUADTAP), + NAME_ELEMENT(BTN_GEAR_DOWN), + NAME_ELEMENT(BTN_GEAR_UP), + +#ifdef BTN_TRIGGER_HAPPY + NAME_ELEMENT(BTN_TRIGGER_HAPPY1), NAME_ELEMENT(BTN_TRIGGER_HAPPY11), + NAME_ELEMENT(BTN_TRIGGER_HAPPY2), NAME_ELEMENT(BTN_TRIGGER_HAPPY12), + NAME_ELEMENT(BTN_TRIGGER_HAPPY3), NAME_ELEMENT(BTN_TRIGGER_HAPPY13), + NAME_ELEMENT(BTN_TRIGGER_HAPPY4), NAME_ELEMENT(BTN_TRIGGER_HAPPY14), + NAME_ELEMENT(BTN_TRIGGER_HAPPY5), NAME_ELEMENT(BTN_TRIGGER_HAPPY15), + NAME_ELEMENT(BTN_TRIGGER_HAPPY6), NAME_ELEMENT(BTN_TRIGGER_HAPPY16), + NAME_ELEMENT(BTN_TRIGGER_HAPPY7), NAME_ELEMENT(BTN_TRIGGER_HAPPY17), + NAME_ELEMENT(BTN_TRIGGER_HAPPY8), NAME_ELEMENT(BTN_TRIGGER_HAPPY18), + NAME_ELEMENT(BTN_TRIGGER_HAPPY9), NAME_ELEMENT(BTN_TRIGGER_HAPPY19), + NAME_ELEMENT(BTN_TRIGGER_HAPPY10), NAME_ELEMENT(BTN_TRIGGER_HAPPY20), + + NAME_ELEMENT(BTN_TRIGGER_HAPPY21), NAME_ELEMENT(BTN_TRIGGER_HAPPY31), + NAME_ELEMENT(BTN_TRIGGER_HAPPY22), NAME_ELEMENT(BTN_TRIGGER_HAPPY32), + NAME_ELEMENT(BTN_TRIGGER_HAPPY23), NAME_ELEMENT(BTN_TRIGGER_HAPPY33), + NAME_ELEMENT(BTN_TRIGGER_HAPPY24), NAME_ELEMENT(BTN_TRIGGER_HAPPY34), + NAME_ELEMENT(BTN_TRIGGER_HAPPY25), NAME_ELEMENT(BTN_TRIGGER_HAPPY35), + NAME_ELEMENT(BTN_TRIGGER_HAPPY26), NAME_ELEMENT(BTN_TRIGGER_HAPPY36), + NAME_ELEMENT(BTN_TRIGGER_HAPPY27), NAME_ELEMENT(BTN_TRIGGER_HAPPY37), + NAME_ELEMENT(BTN_TRIGGER_HAPPY28), NAME_ELEMENT(BTN_TRIGGER_HAPPY38), + NAME_ELEMENT(BTN_TRIGGER_HAPPY29), NAME_ELEMENT(BTN_TRIGGER_HAPPY39), + NAME_ELEMENT(BTN_TRIGGER_HAPPY30), NAME_ELEMENT(BTN_TRIGGER_HAPPY40), +#endif +#ifdef BTN_TOOL_QUINTTAP + NAME_ELEMENT(BTN_TOOL_QUINTTAP), +#endif +}; + +static const char *macro_command_names[] = { + [0 ... MACRO_MAX] = NULL, + [MACRO_KEYPRESS] = "key", + [MACRO_KEYDOWN] = "keydown", + [MACRO_KEYUP] = "keyup", + [MACRO_MSLEEP] = "msleep", +}; + +static int stdin_copy_fd = STDIN_FILENO; +static int stdout_copy_fd = STDOUT_FILENO; +static int stderr_copy_fd = STDERR_FILENO; + +void my_execute_command(const char *cmd) { + pid_t pid; + + pid = fork(); + if (pid == 0) { + dup2(stdin_copy_fd, STDIN_FILENO); + dup2(stdout_copy_fd, STDOUT_FILENO); + dup2(stderr_copy_fd, STDERR_FILENO); + execl(MY_SHELL_PATH, MY_SHELL_PATH, "-c", cmd, NULL); + exit(EXIT_SUCCESS); + } +} + +uint16_t my_get_keycode(const char *str) { + uint16_t i; + const char *name; + + for (i = 0; i <= KEY_MAX; i++) { + name = key_names[i]; + if ((name != NULL) && (strcmp(name, str) == 0)) + return i; + } + + return KEY_CNT; +} + +static int my_get_macro_command_code(const char *str) { + int i; + const char *name; + + for (i = 0; i <= MACRO_MAX; i++) { + name = macro_command_names[i]; + if ((name != NULL) && (strcmp(name, str) == 0)) + return i; + } + + return MACRO_CNT; +} + +void my_daemonize(const char *dir) { + pid_t pid, sid; + + stdin_copy_fd = dup(STDIN_FILENO); + if (stdin_copy_fd == -1) + exit(EXIT_FAILURE); + stdout_copy_fd = dup(STDOUT_FILENO); + if (stdout_copy_fd == -1) + exit(EXIT_FAILURE); + stderr_copy_fd = dup(STDERR_FILENO); + if (stderr_copy_fd == -1) + exit(EXIT_FAILURE); + + pid = fork(); + if (pid < 0) + exit(EXIT_FAILURE); + if (pid > 0) + exit(EXIT_SUCCESS); + sid = setsid(); + if (sid < 0) + exit(EXIT_FAILURE); + + pid = fork(); + if (pid < 0) + exit(EXIT_FAILURE); + if (pid > 0) + exit(EXIT_SUCCESS); + + umask(0); + if (chdir(dir) < 0) + exit(EXIT_FAILURE); + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + if (open("/dev/null", O_RDONLY) != 0) + exit(EXIT_FAILURE); + if (open("/dev/null", O_RDWR) != 1) + exit(EXIT_FAILURE); + if (open("/dev/null", O_RDWR) != 2) + exit(EXIT_FAILURE); +} + +static char **my_tokenize(const char *input) { + char *str = strdup(input); + int count = 0; + int capacity = 10; + char **result = malloc(capacity * sizeof(*result)); + char **temp = NULL; + char *tok = NULL; + int i; + + if ((result == NULL) || (str == NULL)) + goto error; + + tok = strtok(str, " "); + + while(1) + { + if (count >= capacity) { + temp = realloc(result, (capacity *= 2) * sizeof(*result)); + if (temp == NULL) + goto error; + } + + result[count++] = tok ? strdup(tok) : NULL; + + if ((tok != NULL) && (result[count - 1] == NULL)) + goto error; + + if (tok == NULL) + break; + + tok = strtok(NULL, " "); + } + + free(str); + return result; +error: + free(str); + if (result != NULL) { + for (i = 0; i < count; i++) { + if (result[i] != NULL) + free(result[i]); + } + free(result); + } + return NULL; +} + +My_macro *my_macro_parse(const char *str, int *macro_len) { + char **tok = my_tokenize (str); + int tok_count = 0; + int len = 0; + My_macro *macro = NULL; + int i, j; + + if (tok == NULL) + goto error; + + while (tok[tok_count] != NULL) + tok_count++; + + if ((tok_count == 0) || ((tok_count & 1) == 1)) + goto error; + + len = tok_count >> 1; + + macro = malloc(len * sizeof(My_macro)); + if (macro == NULL) + goto error; + + for (i = 0; i < len; i++) { + j = i << 1; + macro[i].type = my_get_macro_command_code(tok[j]); + if (macro[i].type == MACRO_CNT) + goto error; + + if (macro[i].type == MACRO_MSLEEP) { + errno = 0; + macro[i].value = strtol(tok[j + 1], NULL, 0); + if ((errno != 0) || (macro[i].value <= 0)) + goto error; + } + else { + macro[i].value = my_get_keycode(tok[j + 1]); + if (macro[i].value == KEY_CNT) + goto error; + } + } + + *macro_len = len; + return macro; + +error: + if (tok != NULL) { + for (i = 0; i < tok_count; i++) + free(tok[i]); + free(tok); + } + if (macro != NULL) + free(macro); + *macro_len = 0; + return NULL; +} \ No newline at end of file diff -Nru g110d-0.1/utilities.h g110d-0.2/utilities.h --- g110d-0.1/utilities.h 1970-01-01 00:00:00.000000000 +0000 +++ g110d-0.2/utilities.h 2014-01-22 20:49:54.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * utilities.h + * Copyright (C) 2014 Paulius Vitkus + * + * nagad is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * nagad is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef UTILITIES_H +#define UTILITIES_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MY_SHELL_PATH "/bin/bash" + +#define MACRO_KEYPRESS 0 +#define MACRO_KEYDOWN 1 +#define MACRO_KEYUP 2 +#define MACRO_MSLEEP 3 + +#define MACRO_MAX 3 +#define MACRO_CNT (MACRO_MAX + 1) + +typedef struct { + int type; + int value; +} My_macro; + +void my_execute_command(const char *cmd) ; + +uint16_t my_get_keycode(const char *str); + +void my_daemonize(const char *dir); + +My_macro *my_macro_parse(const char *str, int *macro_len); + +#endif /* UTILITIES_H */ \ No newline at end of file