From 900a63785689906491efce19e5c348ab0bc2db30 Mon Sep 17 00:00:00 2001 From: knolax <1339802534.kk@gmail.com> Date: Thu, 28 Dec 2017 23:23:54 -0500 Subject: finished the keymap --- keymap.h | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/keymap.h b/keymap.h index 760eaf9..572ea08 100644 --- a/keymap.h +++ b/keymap.h @@ -3,20 +3,32 @@ #define KEY_NUMBERMAP 25341 #define KEY_SPECIALMAP 133981 #define KEY_STICKYMAP 133982 -unsigned long skey_keymap[3][3][10] = { +#define KEY_MS_2ND 133983 +#define MS_UP 133984 +#define MS_LEFT 133985 +#define MS_RIGHT 133986 +#define MS_DOWN 133987 +#define MS_SCRL_UP 133988 +#define MS_SCRL_DOWN 133989 +unsigned long skey_keymap[4][3][10] = { { {KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P}, {KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_STICKYMAP}, {KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} }, { - {KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P}, - {KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_STICKYMAP}, - {KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} + {KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0}, + {KEY_GRAVE, KEY_LEFTSHIFT, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_MINUS, KEY_EQUAL, KEY_STICKYMAP}, + {KEY_LEFTCTRL, KEY_LEFTMETA, KEY_LEFTALT, KEY_SPACE, KEY_COMMA, KEY_DOT, KEY_SLASH, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} }, { - {KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P}, - {KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_STICKYMAP}, - {KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} + {KEY_ESC, KEY_TAB, BTN_LEFT, MS_UP, BTN_RIGHT, BTN_MIDDLE, MS_SCRL_UP, KEY_INSERT, KEY_DELETE, KEY_BACKSPACE}, + {KEY_CAPSLOCK, KEY_LEFTSHIFT, MS_LEFT, MS_DOWN, MS_RIGHT, KEY_UP, MS_SCRL_DOWN, KEY_MS_2ND, KEY_ENTER, KEY_STICKYMAP}, + {KEY_LEFTCTRL, KEY_LEFTMETA, KEY_LEFTALT, KEY_SPACE, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} + }, + { + {KEY_ESC, KEY_TAB, BTN_LEFT, KEY_PAGEUP, BTN_RIGHT, BTN_MIDDLE, MS_SCRL_UP, KEY_INSERT, KEY_DELETE, KEY_BACKSPACE}, + {KEY_CAPSLOCK, KEY_SHIFT, KEY_HOME, KEY_PAGEDOWN, KEY_END, KEY_UP, MS_SCRL_DOWN, KEY_MS_2ND, KEY_ENTER, KEY_STICKYMAP}, + {KEY_LEFTCTRL, KEY_LEFTMETA, KEY_LEFTALT, KEY_SPACE, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} } }; -- cgit v1.1 From 1966fcd11290656185a428ac41e5205c3f29d9e9 Mon Sep 17 00:00:00 2001 From: knolax <1339802534.kk@gmail.com> Date: Fri, 29 Dec 2017 15:42:27 -0500 Subject: added full functionality to the module. it now sends the correct keypresses to the input subsystem. As a reminder, i'm using git to upload code to the production system so this code hasn't been tested yet. --- skey.c | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 233 insertions(+), 17 deletions(-) diff --git a/skey.c b/skey.c index 917bf6c..55c86b4 100644 --- a/skey.c +++ b/skey.c @@ -50,33 +50,250 @@ static struct task_struct *update_task; */ struct input_dev * skey_dev; /* - * Name and ID + * Name and ID, for use with input.h */ struct input_id skey_id; char * skey_name = "Switch Keyboard for the Omnicom"; /* + * Array to hold the keystate for the board + * a char is assumed to be atleast 8 bits, the bit KEYSTATE_PHYS holds the previous physical + * states for detecting rising and falling edges whereas the other ones hold the previous states + * of the 3 keymaps when stickymode is turned on. + */ +char keystate[3][10]= {0}; +#define KEYSTATE_PHYS 0x1 +#define KEYSTATE_ALPHA 0x2 +#define KEYSTATE_NUMBER 0x4 +#define KEYSTATE_SPECIAL 0x8 +/* + * current keymapping,\ + * 0 - ALPHA + * 1 - NUM + * 2 - SPECIAL + * 3 - SPECIAL with mouse + */ +int current_keymap = 0; +/* + * Stickymode + */ +int stickymode = 0; +//number of pixels mousemove buttons do +#define MOUSE_DIST 5 +//same but for scrollwheel +#define WHEEL_DIST 5 +/* + * clears the state of stickymode keystates, sends a key up event if it was previously pressed + * + */ +void clearkeystate(void) { + int row_index = 0; + int column_index = 0; + int map_index = 0; //range of 0 to 2, which are KEYSTATE_ALPHA to KEYSTATE_SPECIAL + int keystate_mask; // the actual map used + while (map_index < 3) { + //gets mask from map_index + switch(map_index) { + case 0: + keystate_mask = KEYSTATE_ALPHA; + break; + case 1: + keystate_mask = KEYSTATE_NUMBER; + break; + case 2: + keystate_mask = KEYSTATE_SPECIAL; + break; + } + row_index = 0; + while (row_index < 3) { + column_index = 0; + while (column_index < 10) { + //sends a button released event if it is not sticky mode + if (keystate[row_index][column_index] & keystate_mask) { + //reports key up + input_report_key(skey_dev, skey_keymap[map_index][row_index][column_index], 0); + input_sync(skey_dev); + //sets the bit to low. + keystate[row_index][column_index] = (~keystate_mask) & keystate[row_index][column_index]; + } + column_index++; + } + row_index++; + } + map_index++; + } + return; +} +/* + * The keystates are processed as following, the current read value is compared with the + * previous one stored in KEYSTATE_PHYS to detect a rising or falling edge. for regular keys, + * the corresponding keycode from skey_keymap is sent, with the current_keymap. if stickymode + * is on, then it toggles the value stored in KEYSTATE_ALPHA, *NUMBER or *SPECIAL depending on + * current_keymap. special keys that change the keymap and the mouse position are only triggered + * on rising level, when current_keymap is 3, or special map with mouse, the KEYSTATE_SPECIAL + * mask is used. + */ +/* + * This function is called by skey_update_thread every time it reads the keyboard, and + * implements the above. returns -EINVAL if the column and row are out of bouns, but that's + * not going to happen. + */ +int processkey(int row, int column, int state) { + //sanity checks + if ((column < 10) && (column >= 0) && (row < 3) && (row >= 0)) { + } else { + /*if this happens, whatever is calling this function is not expected to handle + * this + */ + printk(KERN_ALERT "skey: keypress data sent to processkey() was invalid\n"); + return -EINVAL; + } + //finds the KEYSTATE_* bitmask to use with the current keymapping + int keystate_bitmask; + switch (current_keymap) { + case 0: + keystate_bitmask = KEYSTATE_ALPHA; + break; + case 1: + keystate_bitmask = KEYSTATE_NUMBER; + break; + case 2: + keystate_bitmask = KEYSTATE_SPECIAL; + break; + case 3: + keystate_bitmask = KEYSTATE_SPECIAL; + break; + //if current_keymap is out of range [0,3] + default: + return -EINVAL; + break; + } + + //falling edge + if ((KEYSTATE_PHYS & keystate[row][column]) && !state) { + //after the previous keystate is checked, it is updated + if (state) { + keystate[row][column] = KEYSTATE_PHYS | keystate[row][column]; + } else { + keystate[row][column] = (~KEYSTATE_PHYS) & keystate[row][column]; + } + + if (!stickymode) { + //reports key up + input_report_key(skey_dev, skey_keymap[current_keymap][row][column], 0); + input_sync(skey_dev); + + } + //rising edge + }else if (!(KEYSTATE_PHYS & keystate[row][column]) && state) { + //after the previous keystate is checked, it is updated + if (state) { + keystate[row][column] = KEYSTATE_PHYS | keystate[row][column]; + } else { + keystate[row][column] = (~KEYSTATE_PHYS) & keystate[row][column]; + } + /* + *handles keys that have special behavior, and to which stickykey do not apply + * if sticky keys don't apply then only the falling edge applies + */ + switch (skey_keymap[current_keymap][row][column]) { + case KEY_ALPHAMAP: + current_keymap = 0; + return 0; + break; + case KEY_NUMBERMAP: + current_keymap = 1; + return 0; + break; + case KEY_SPECIALMAP: + current_keymap = 2; + return 0; + break; + case KEY_STICKYMAP: + stickymode = !stickymode; + if (!stickymode) { + clearkeystate(); + } + return 0; + break; + case KEY_MS_2ND: + if (current_keymap == 2) { + current_keymap = 3; + } else if (current_keymap == 3) { + current_keymap = 2; + } + return 0; + break; + case MS_UP: + input_event(skey_dev, EV_REL, REL_Y, +MOUSE_DIST); + input_sync(skey_dev); + return 0; + break; + case MS_DOWN: + input_event(skey_dev, EV_REL, REL_Y, -MOUSE_DIST); + input_sync(skey_dev); + return 0; + break; + case MS_LEFT: + input_event(skey_dev, EV_REL, REL_X, -MOUSE_DIST); + input_sync(skey_dev); + return 0; + break; + case MS_RIGHT: + input_event(skey_dev, EV_REL, REL_X, +MOUSE_DIST); + input_sync(skey_dev); + return 0; + break; + case MS_SCRL_UP: + input_event(skey_dev, EV_REL, REL_WHEEL, +WHEEL_DIST); + input_sync(skey_dev); + return 0; + break; + case MS_SCRL_DOWN: + input_event(skey_dev, EV_REL, REL_WHEEL, -WHEEL_DIST); + input_sync(skey_dev); + return 0; + break; + } + //if it's stickymode, toggle the state stored and send corresponding vent + if (stickymode) { + //it was high before, so now it's being toggled off + if (keystate[row][column] & keystate_bitmask) { + input_report_key(skey_dev, skey_keymap[current_keymap][row][column], 0); + input_sync(skey_dev); + + keystate[row][column] = (~keystate_bitmask) & keystate[row][column]; + //it was low before, so now it's being toggled on + } else { + input_report_key(skey_dev, skey_keymap[current_keymap][row][column], 1); + input_sync(skey_dev); + keystate[row][column] = keystate_bitmask | keystate[row][column]; + + } + //otherwise just send a key down event + } else { + input_report_key(skey_dev, skey_keymap[current_keymap][row][column], 1); + input_sync(skey_dev); + } + } + return 0; +} + +/* *This function is called every timer-period to actually read the keyboard */ int skey_update_thread (void *data) { printk(KERN_INFO "skey: starting update thread\n"); //thread stuff + //thread priority const struct sched_param PARAM = { .sched_priority = 45}; + //sets the thread to be kinda realtime sched_setscheduler(current, SCHED_FIFO, &PARAM); printk(KERN_INFO "skey: started update thread\n"); if (!USE_GPIO) { printk(KERN_ALERT "skey: currently in test mode with gpio use disabled\n"); } - //a counter for testing prints - int i = 0; - int j = 0; + while (1) { - /*if (!i) { - printk(KERN_INFO "skey: update thread printed to kernel log every 1s\n"); - //reports the a button pressed - input_report_key(skey_dev,KEY_CAPSLOCK,j); - input_sync(skey_dev); - j = !j; - }*/ if (USE_GPIO) { //reads the keyboard int row_index = 0; @@ -90,9 +307,9 @@ int skey_update_thread (void *data) { column_index = 0; while (column_index < 10) { if (gpio_get_value_cansleep(column_pins[column_index])) { - printk(KERN_INFO "skey: key pressed at column %d, row %d\n", column_index, row_index); + processkey(row_index, column_index, 1); } else { - //printk(KERN_INFO "skey: key not pressed at column %d, row %d\n", column_index, row_index); + processkey(row_index, column_index, 0); } column_index++; } @@ -102,10 +319,9 @@ int skey_update_thread (void *data) { row_index++; } } - //sleep 2000us= 2ms = 0.002 seconds - //usleep_range(2000, 2000); - //sleeps = 1000000us = 1000ms = 1s - usleep_range(1000000,1000000); + //sleep 500us= .5ms = 0.0005 seconds + // 1 / 0.0005 = 2000 hz fastest, but it's really 1/0.00052 + usleep_range(500,500); //for when the thread has to stop if (kthread_should_stop()) { break; -- cgit v1.1 From 5284845c53c58f98126ad63c859cbccb730fcf9e Mon Sep 17 00:00:00 2001 From: knolax <1339802534.kk@gmail.com> Date: Fri, 29 Dec 2017 15:43:47 -0500 Subject: added full full keymap --- keymap.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/keymap.h b/keymap.h index 572ea08..69c99e3 100644 --- a/keymap.h +++ b/keymap.h @@ -12,23 +12,23 @@ #define MS_SCRL_DOWN 133989 unsigned long skey_keymap[4][3][10] = { { - {KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P}, - {KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_STICKYMAP}, - {KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} + {KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P}, + {KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_STICKYMAP}, + {KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} }, { - {KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0}, - {KEY_GRAVE, KEY_LEFTSHIFT, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_MINUS, KEY_EQUAL, KEY_STICKYMAP}, - {KEY_LEFTCTRL, KEY_LEFTMETA, KEY_LEFTALT, KEY_SPACE, KEY_COMMA, KEY_DOT, KEY_SLASH, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} + {KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0}, + {KEY_GRAVE, KEY_LEFTSHIFT, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_MINUS, KEY_EQUAL, KEY_STICKYMAP}, + {KEY_LEFTCTRL, KEY_LEFTMETA, KEY_LEFTALT, KEY_SPACE, KEY_COMMA, KEY_DOT, KEY_SLASH, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} }, { - {KEY_ESC, KEY_TAB, BTN_LEFT, MS_UP, BTN_RIGHT, BTN_MIDDLE, MS_SCRL_UP, KEY_INSERT, KEY_DELETE, KEY_BACKSPACE}, - {KEY_CAPSLOCK, KEY_LEFTSHIFT, MS_LEFT, MS_DOWN, MS_RIGHT, KEY_UP, MS_SCRL_DOWN, KEY_MS_2ND, KEY_ENTER, KEY_STICKYMAP}, - {KEY_LEFTCTRL, KEY_LEFTMETA, KEY_LEFTALT, KEY_SPACE, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} + {KEY_ESC, KEY_TAB, BTN_LEFT, KEY_PAGEUP, BTN_RIGHT, BTN_MIDDLE, MS_SCRL_UP, KEY_INSERT, KEY_DELETE, KEY_BACKSPACE}, + {KEY_CAPSLOCK, KEY_LEFTSHIFT, KEY_HOME, KEY_PAGEDOWN, KEY_END, KEY_UP, MS_SCRL_DOWN, KEY_MS_2ND, KEY_ENTER, KEY_STICKYMAP}, + {KEY_LEFTCTRL, KEY_LEFTMETA, KEY_LEFTALT, KEY_SPACE, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} }, { - {KEY_ESC, KEY_TAB, BTN_LEFT, KEY_PAGEUP, BTN_RIGHT, BTN_MIDDLE, MS_SCRL_UP, KEY_INSERT, KEY_DELETE, KEY_BACKSPACE}, - {KEY_CAPSLOCK, KEY_SHIFT, KEY_HOME, KEY_PAGEDOWN, KEY_END, KEY_UP, MS_SCRL_DOWN, KEY_MS_2ND, KEY_ENTER, KEY_STICKYMAP}, - {KEY_LEFTCTRL, KEY_LEFTMETA, KEY_LEFTALT, KEY_SPACE, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} + {KEY_ESC, KEY_TAB, BTN_LEFT, MS_UP, BTN_RIGHT, BTN_MIDDLE, MS_SCRL_UP, KEY_INSERT, KEY_DELETE, KEY_BACKSPACE}, + {KEY_CAPSLOCK, KEY_LEFTSHIFT, MS_LEFT, MS_DOWN, MS_RIGHT, KEY_UP, MS_SCRL_DOWN, KEY_MS_2ND, KEY_ENTER, KEY_STICKYMAP}, + {KEY_LEFTCTRL, KEY_LEFTMETA, KEY_LEFTALT, KEY_SPACE, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_ALPHAMAP, KEY_NUMBERMAP, KEY_SPECIALMAP} } }; -- cgit v1.1 From 42dd37ade1869064b3404ec8e62ca52c8e323985 Mon Sep 17 00:00:00 2001 From: knolax <1339802534.kk@gmail.com> Date: Fri, 29 Dec 2017 15:48:05 -0500 Subject: fixed c90 mixed declaration warnings. --- skey.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/skey.c b/skey.c index 55c86b4..bc94680 100644 --- a/skey.c +++ b/skey.c @@ -138,6 +138,8 @@ void clearkeystate(void) { * not going to happen. */ int processkey(int row, int column, int state) { + //the bitmask to use for the current keymap mode + int keystate_bitmask; //sanity checks if ((column < 10) && (column >= 0) && (row < 3) && (row >= 0)) { } else { @@ -147,8 +149,7 @@ int processkey(int row, int column, int state) { printk(KERN_ALERT "skey: keypress data sent to processkey() was invalid\n"); return -EINVAL; } - //finds the KEYSTATE_* bitmask to use with the current keymapping - int keystate_bitmask; + //finds the KEYSTATE_* bitmask to use with the current keymapping switch (current_keymap) { case 0: keystate_bitmask = KEYSTATE_ALPHA; @@ -282,10 +283,10 @@ int processkey(int row, int column, int state) { *This function is called every timer-period to actually read the keyboard */ int skey_update_thread (void *data) { - printk(KERN_INFO "skey: starting update thread\n"); //thread stuff //thread priority const struct sched_param PARAM = { .sched_priority = 45}; + printk(KERN_INFO "skey: starting update thread\n"); //sets the thread to be kinda realtime sched_setscheduler(current, SCHED_FIFO, &PARAM); printk(KERN_INFO "skey: started update thread\n"); @@ -336,7 +337,9 @@ int skey_update_thread (void *data) { static int __init skey_init (void) { printk(KERN_INFO "skey: module initiating...\n"); if (USE_GPIO) { + //indexes for row and column pin init loops int i = 0; + int j = 0; //claims the column pins while (i < 10) { //checks to see if the gpios are valid @@ -354,8 +357,7 @@ static int __init skey_init (void) { } i++; } - //ditto for row pins - int j = 0; + //ditto for row pins while (j < 3) { //checks to see if the gpios are valid if (!gpio_is_valid(row_pins[j])) { @@ -424,11 +426,11 @@ static void __exit skey_exit (void) { if (USE_GPIO) { //frees column and row pins int i = 0; + int j = 0; while (i < 10) { gpio_free(column_pins[i]); i++; } - int j = 0; while (j < 3) { gpio_free(row_pins[j]); j++; -- cgit v1.1