/trunk/uspace/srv/kbd/ctl/pc.c |
---|
39,6 → 39,7 |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <kbd_ctl.h> |
#include <gsp.h> |
enum dec_state { |
ds_s, |
45,7 → 46,7 |
ds_e |
}; |
static enum dec_state ds = ds_s; |
static enum dec_state ds; |
static int scanmap_simple[] = { |
179,6 → 180,11 |
[0x1c] = KC_NENTER |
}; |
int kbd_ctl_init(void) |
{ |
ds = ds_s; |
return 0; |
} |
void kbd_ctl_parse_scancode(int scancode) |
{ |
/trunk/uspace/srv/kbd/ctl/stty.c |
---|
39,291 → 39,191 |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <kbd_ctl.h> |
#include <gsp.h> |
#include <stroke.h> |
static void parse_ds_start(int scancode); |
static void parse_ds_e(int scancode); |
static void parse_ds_e1(int scancode); |
static void parse_ds_e2(int scancode); |
static void parse_ds_e2a(int scancode); |
static void parse_ds_e2b(int scancode); |
/** Scancode parser */ |
static gsp_t sp; |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length); |
/** Current parser state */ |
static int ds; |
enum dec_state { |
ds_start, |
ds_e, |
ds_e1, |
ds_e2, |
ds_e2a, |
ds_e2b |
}; |
#include <stdio.h> |
static int map_start[][2] = { |
int seq_defs[] = { |
/* Not shifted */ |
[0x60] = { 0, KC_BACKTICK }, |
0, KC_BACKTICK, 0x60, GSP_END, |
[0x31] = { 0, KC_1 }, |
[0x32] = { 0, KC_2 }, |
[0x33] = { 0, KC_3 }, |
[0x34] = { 0, KC_4 }, |
[0x35] = { 0, KC_5 }, |
[0x36] = { 0, KC_6 }, |
[0x37] = { 0, KC_7 }, |
[0x38] = { 0, KC_8 }, |
[0x39] = { 0, KC_9 }, |
[0x30] = { 0, KC_0 }, |
0, KC_1, 0x31, GSP_END, |
0, KC_2, 0x32, GSP_END, |
0, KC_3, 0x33, GSP_END, |
0, KC_4, 0x34, GSP_END, |
0, KC_5, 0x35, GSP_END, |
0, KC_6, 0x36, GSP_END, |
0, KC_7, 0x37, GSP_END, |
0, KC_8, 0x38, GSP_END, |
0, KC_9, 0x39, GSP_END, |
0, KC_0, 0x30, GSP_END, |
[0x2d] = { 0, KC_MINUS }, |
[0x3d] = { 0, KC_EQUALS }, |
[0x08] = { 0, KC_BACKSPACE }, |
0, KC_MINUS, 0x2d, GSP_END, |
0, KC_EQUALS, 0x3d, GSP_END, |
0, KC_BACKSPACE, 0x08, GSP_END, |
[0x0f] = { 0, KC_TAB }, |
0, KC_TAB, 0x09, GSP_END, |
[0x71] = { 0, KC_Q }, |
[0x77] = { 0, KC_W }, |
[0x65] = { 0, KC_E }, |
[0x72] = { 0, KC_R }, |
[0x74] = { 0, KC_T }, |
[0x79] = { 0, KC_Y }, |
[0x75] = { 0, KC_U }, |
[0x69] = { 0, KC_I }, |
[0x6f] = { 0, KC_O }, |
[0x70] = { 0, KC_P }, |
0, KC_Q, 0x71, GSP_END, |
0, KC_W, 0x77, GSP_END, |
0, KC_E, 0x65, GSP_END, |
0, KC_R, 0x72, GSP_END, |
0, KC_T, 0x74, GSP_END, |
0, KC_Y, 0x79, GSP_END, |
0, KC_U, 0x75, GSP_END, |
0, KC_I, 0x69, GSP_END, |
0, KC_O, 0x6f, GSP_END, |
0, KC_P, 0x70, GSP_END, |
[0x5b] = { 0, KC_LBRACKET }, |
[0x5d] = { 0, KC_RBRACKET }, |
0, KC_LBRACKET, 0x5b, GSP_END, |
0, KC_RBRACKET, 0x5d, GSP_END, |
[0x61] = { 0, KC_A }, |
[0x73] = { 0, KC_S }, |
[0x64] = { 0, KC_D }, |
[0x66] = { 0, KC_F }, |
[0x67] = { 0, KC_G }, |
[0x68] = { 0, KC_H }, |
[0x6a] = { 0, KC_J }, |
[0x6b] = { 0, KC_K }, |
[0x6c] = { 0, KC_L }, |
0, KC_A, 0x61, GSP_END, |
0, KC_S, 0x73, GSP_END, |
0, KC_D, 0x64, GSP_END, |
0, KC_F, 0x66, GSP_END, |
0, KC_G, 0x67, GSP_END, |
0, KC_H, 0x68, GSP_END, |
0, KC_J, 0x6a, GSP_END, |
0, KC_K, 0x6b, GSP_END, |
0, KC_L, 0x6c, GSP_END, |
[0x3b] = { 0, KC_SEMICOLON }, |
[0x27] = { 0, KC_QUOTE }, |
[0x5c] = { 0, KC_BACKSLASH }, |
0, KC_SEMICOLON, 0x3b, GSP_END, |
0, KC_QUOTE, 0x27, GSP_END, |
0, KC_BACKSLASH, 0x5c, GSP_END, |
[0x7a] = { 0, KC_Z }, |
[0x78] = { 0, KC_X }, |
[0x63] = { 0, KC_C }, |
[0x76] = { 0, KC_V }, |
[0x62] = { 0, KC_B }, |
[0x6e] = { 0, KC_N }, |
[0x6d] = { 0, KC_M }, |
0, KC_Z, 0x7a, GSP_END, |
0, KC_X, 0x78, GSP_END, |
0, KC_C, 0x63, GSP_END, |
0, KC_V, 0x76, GSP_END, |
0, KC_B, 0x62, GSP_END, |
0, KC_N, 0x6e, GSP_END, |
0, KC_M, 0x6d, GSP_END, |
[0x2c] = { 0, KC_COMMA }, |
[0x2e] = { 0, KC_PERIOD }, |
[0x2f] = { 0, KC_SLASH }, |
0, KC_COMMA, 0x2c, GSP_END, |
0, KC_PERIOD, 0x2e, GSP_END, |
0, KC_SLASH, 0x2f, GSP_END, |
[0x20] = { 0, KC_SPACE }, |
/* Shifted */ |
[0x1b] = { 0, KC_ESCAPE }, |
KM_SHIFT, KC_BACKTICK, 0x7e, GSP_END, |
[0x0a] = { 0, KC_ENTER }, |
[0x0d] = { 0, KC_ENTER }, |
KM_SHIFT, KC_1, 0x21, GSP_END, |
KM_SHIFT, KC_2, 0x40, GSP_END, |
KM_SHIFT, KC_3, 0x23, GSP_END, |
KM_SHIFT, KC_4, 0x24, GSP_END, |
KM_SHIFT, KC_5, 0x25, GSP_END, |
KM_SHIFT, KC_6, 0x5e, GSP_END, |
KM_SHIFT, KC_7, 0x26, GSP_END, |
KM_SHIFT, KC_8, 0x2a, GSP_END, |
KM_SHIFT, KC_9, 0x28, GSP_END, |
KM_SHIFT, KC_0, 0x29, GSP_END, |
/* with Shift pressed */ |
KM_SHIFT, KC_MINUS, 0x5f, GSP_END, |
KM_SHIFT, KC_EQUALS, 0x2b, GSP_END, |
[0x7e] = { KM_LSHIFT, KC_BACKTICK }, |
KM_SHIFT, KC_Q, 0x51, GSP_END, |
KM_SHIFT, KC_W, 0x57, GSP_END, |
KM_SHIFT, KC_E, 0x45, GSP_END, |
KM_SHIFT, KC_R, 0x52, GSP_END, |
KM_SHIFT, KC_T, 0x54, GSP_END, |
KM_SHIFT, KC_Y, 0x59, GSP_END, |
KM_SHIFT, KC_U, 0x55, GSP_END, |
KM_SHIFT, KC_I, 0x49, GSP_END, |
KM_SHIFT, KC_O, 0x4f, GSP_END, |
KM_SHIFT, KC_P, 0x50, GSP_END, |
[0x21] = { KM_LSHIFT, KC_1 }, |
[0x40] = { KM_LSHIFT, KC_2 }, |
[0x23] = { KM_LSHIFT, KC_3 }, |
[0x24] = { KM_LSHIFT, KC_4 }, |
[0x25] = { KM_LSHIFT, KC_5 }, |
[0x5e] = { KM_LSHIFT, KC_6 }, |
[0x26] = { KM_LSHIFT, KC_7 }, |
[0x2a] = { KM_LSHIFT, KC_8 }, |
[0x28] = { KM_LSHIFT, KC_9 }, |
[0x29] = { KM_LSHIFT, KC_0 }, |
KM_SHIFT, KC_LBRACKET, 0x7b, GSP_END, |
KM_SHIFT, KC_RBRACKET, 0x7d, GSP_END, |
[0x5f] = { KM_LSHIFT, KC_MINUS }, |
[0x2b] = { KM_LSHIFT, KC_EQUALS }, |
KM_SHIFT, KC_A, 0x41, GSP_END, |
KM_SHIFT, KC_S, 0x53, GSP_END, |
KM_SHIFT, KC_D, 0x44, GSP_END, |
KM_SHIFT, KC_F, 0x46, GSP_END, |
KM_SHIFT, KC_G, 0x47, GSP_END, |
KM_SHIFT, KC_H, 0x48, GSP_END, |
KM_SHIFT, KC_J, 0x4a, GSP_END, |
KM_SHIFT, KC_K, 0x4b, GSP_END, |
KM_SHIFT, KC_L, 0x4c, GSP_END, |
[0x51] = { KM_LSHIFT, KC_Q }, |
[0x57] = { KM_LSHIFT, KC_W }, |
[0x45] = { KM_LSHIFT, KC_E }, |
[0x52] = { KM_LSHIFT, KC_R }, |
[0x54] = { KM_LSHIFT, KC_T }, |
[0x59] = { KM_LSHIFT, KC_Y }, |
[0x55] = { KM_LSHIFT, KC_U }, |
[0x49] = { KM_LSHIFT, KC_I }, |
[0x4f] = { KM_LSHIFT, KC_O }, |
[0x50] = { KM_LSHIFT, KC_P }, |
KM_SHIFT, KC_SEMICOLON, 0x3a, GSP_END, |
KM_SHIFT, KC_QUOTE, 0x22, GSP_END, |
KM_SHIFT, KC_BACKSLASH, 0x7c, GSP_END, |
[0x7b] = { KM_LSHIFT, KC_LBRACKET }, |
[0x7d] = { KM_LSHIFT, KC_RBRACKET }, |
KM_SHIFT, KC_Z, 0x5a, GSP_END, |
KM_SHIFT, KC_X, 0x58, GSP_END, |
KM_SHIFT, KC_C, 0x43, GSP_END, |
KM_SHIFT, KC_V, 0x56, GSP_END, |
KM_SHIFT, KC_B, 0x42, GSP_END, |
KM_SHIFT, KC_N, 0x4e, GSP_END, |
KM_SHIFT, KC_M, 0x4d, GSP_END, |
[0x41] = { KM_LSHIFT, KC_A }, |
[0x53] = { KM_LSHIFT, KC_S }, |
[0x44] = { KM_LSHIFT, KC_D }, |
[0x46] = { KM_LSHIFT, KC_F }, |
[0x47] = { KM_LSHIFT, KC_G }, |
[0x48] = { KM_LSHIFT, KC_H }, |
[0x4a] = { KM_LSHIFT, KC_J }, |
[0x4b] = { KM_LSHIFT, KC_K }, |
[0x4c] = { KM_LSHIFT, KC_L }, |
KM_SHIFT, KC_COMMA, 0x3c, GSP_END, |
KM_SHIFT, KC_PERIOD, 0x3e, GSP_END, |
KM_SHIFT, KC_SLASH, 0x3f, GSP_END, |
[0x3a] = { KM_LSHIFT, KC_SEMICOLON }, |
[0x22] = { KM_LSHIFT, KC_QUOTE }, |
[0x7c] = { KM_LSHIFT, KC_BACKSLASH }, |
/* ... */ |
[0x5a] = { KM_LSHIFT, KC_Z }, |
[0x58] = { KM_LSHIFT, KC_X }, |
[0x43] = { KM_LSHIFT, KC_C }, |
[0x56] = { KM_LSHIFT, KC_V }, |
[0x42] = { KM_LSHIFT, KC_B }, |
[0x4e] = { KM_LSHIFT, KC_N }, |
[0x4d] = { KM_LSHIFT, KC_M }, |
0, KC_SPACE, 0x20, GSP_END, |
0, KC_ENTER, 0x0a, GSP_END, |
0, KC_ENTER, 0x0d, GSP_END, |
[0x3c] = { KM_LSHIFT, KC_COMMA }, |
[0x3e] = { KM_LSHIFT, KC_PERIOD }, |
[0x3f] = { KM_LSHIFT, KC_SLASH } |
}; |
0, KC_ESCAPE, 0x1b, 0x1b, GSP_END, |
static int map_e1[][2] = |
{ |
[0x50] = { 0, KC_F1 }, |
[0x51] = { 0, KC_F2 }, |
[0x52] = { 0, KC_F3 }, |
[0x53] = { 0, KC_F4 }, |
}; |
0, KC_F1, 0x1b, 0x4f, 0x50, GSP_END, |
0, KC_F2, 0x1b, 0x4f, 0x51, GSP_END, |
0, KC_F3, 0x1b, 0x4f, 0x52, GSP_END, |
0, KC_F4, 0x1b, 0x4f, 0x53, GSP_END, |
0, KC_F5, 0x1b, 0x5b, 0x31, 0x35, 0x7e, GSP_END, |
0, KC_F6, 0x1b, 0x5b, 0x31, 0x37, 0x7e, GSP_END, |
0, KC_F7, 0x1b, 0x5b, 0x31, 0x38, 0x7e, GSP_END, |
0, KC_F8, 0x1b, 0x5b, 0x31, 0x39, 0x7e, GSP_END, |
0, KC_F9, 0x1b, 0x5b, 0x32, 0x30, 0x7e, GSP_END, |
0, KC_F10, 0x1b, 0x5b, 0x32, 0x31, 0x7e, GSP_END, |
0, KC_F11, 0x1b, 0x5b, 0x32, 0x33, 0x7e, GSP_END, |
0, KC_F12, 0x1b, 0x5b, 0x32, 0x34, 0x7e, GSP_END, |
static int map_e2[][2] = |
{ |
[0x41] = { 0, KC_UP }, |
[0x42] = { 0, KC_DOWN }, |
[0x44] = { 0, KC_LEFT }, |
[0x43] = { 0, KC_RIGHT }, |
}; |
0, KC_INSERT, 0x1b, 0x5b, 0x32, 0x7e, GSP_END, |
0, KC_HOME, 0x1b, 0x5b, 0x48, GSP_END, |
0, KC_PAGE_UP, 0x1b, 0x5b, 0x35, 0x7e, GSP_END, |
0, KC_DELETE, 0x1b, 0x5b, 0x33, 0x7e, GSP_END, |
0, KC_END, 0x1b, 0x5b, 0x46, GSP_END, |
0, KC_PAGE_DOWN, 0x1b, 0x5b, 0x36, 0x7e, GSP_END, |
static int map_e2a[][2] = |
{ |
[0x35] = { 0, KC_F5 }, |
[0x37] = { 0, KC_F6 }, |
[0x38] = { 0, KC_F7 }, |
[0x39] = { 0, KC_F8 }, |
}; |
0, KC_UP, 0x1b, 0x5b, 0x41, GSP_END, |
0, KC_LEFT, 0x1b, 0x5b, 0x44, GSP_END, |
0, KC_DOWN, 0x1b, 0x5b, 0x42, GSP_END, |
0, KC_RIGHT, 0x1b, 0x5b, 0x43, GSP_END, |
static int map_e2b[][2] = |
{ |
[0x30] = { 0, KC_F9 }, |
[0x31] = { 0, KC_F10 }, |
[0x32] = { 0, KC_F11 }, |
[0x33] = { 0, KC_F12 }, |
0, 0 |
}; |
static unsigned int mods_keys[][2] = { |
{ KM_LSHIFT, KC_LSHIFT }, |
{ 0, 0 } |
}; |
static enum dec_state ds; |
void kbd_ctl_parse_scancode(int scancode) |
int kbd_ctl_init(void) |
{ |
switch (ds) { |
case ds_start: parse_ds_start(scancode); break; |
case ds_e: parse_ds_e(scancode); break; |
case ds_e1: parse_ds_e1(scancode); break; |
case ds_e2: parse_ds_e2(scancode); break; |
case ds_e2a: parse_ds_e2a(scancode); break; |
case ds_e2b: parse_ds_e2b(scancode); break; |
} |
} |
ds = 0; |
static void parse_ds_start(int scancode) |
{ |
if (scancode == 0x1b) { |
ds = ds_e; |
return; |
gsp_init(&sp); |
return gsp_insert_defs(&sp, seq_defs); |
} |
parse_leaf(scancode, map_start, sizeof(map_start) / (2 * sizeof(int))); |
} |
static void parse_ds_e(int scancode) |
void kbd_ctl_parse_scancode(int scancode) |
{ |
if (scancode < 0 || scancode >= 0x80) return; |
unsigned mods, key; |
switch (scancode) { |
case 0x4f: ds = ds_e1; return; |
case 0x5b: ds = ds_e2; return; |
case 0x1b: ds = ds_start; break; |
default: ds = ds_start; return; |
} |
kbd_push_ev(KE_PRESS, KC_ESCAPE); |
} |
static void parse_ds_e1(int scancode) |
{ |
parse_leaf(scancode, map_e1, sizeof(map_e1) / (2 * sizeof(int))); |
} |
static void parse_ds_e2(int scancode) |
{ |
switch (scancode) { |
case 0x31: ds = ds_e2a; break; |
case 0x32: ds = ds_e2b; break; |
default: ds = ds_start; break; |
} |
parse_leaf(scancode, map_e2, sizeof(map_e2) / (2 * sizeof(int))); |
} |
static void parse_ds_e2a(int scancode) |
{ |
parse_leaf(scancode, map_e2a, sizeof(map_e2a) / (2 * sizeof(int))); |
} |
static void parse_ds_e2b(int scancode) |
{ |
parse_leaf(scancode, map_e2b, sizeof(map_e2b) / (2 * sizeof(int))); |
} |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length) |
{ |
unsigned int key, mod; |
int i; |
ds = ds_start; |
if (scancode < 0 || scancode >= map_length) |
return; |
mod = map[scancode][0]; |
key = map[scancode][1]; |
/* Simulate modifier pressing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_PRESS, mods_keys[i][1]); |
} |
++i; |
} |
ds = gsp_step(&sp, ds, scancode, &mods, &key); |
if (key != 0) { |
kbd_push_ev(KE_PRESS, key); |
kbd_push_ev(KE_RELEASE, key); |
stroke_sim(mods, key); |
} |
/* Simulate modifier releasing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_RELEASE, mods_keys[i][1]); |
} |
++i; |
} |
} |
/** |
* @} |
*/ |
/trunk/uspace/srv/kbd/ctl/sun.c |
---|
45,6 → 45,11 |
static int scanmap_simple[]; |
int kbd_ctl_init(void) |
{ |
return 0; |
} |
void kbd_ctl_parse_scancode(int scancode) |
{ |
kbd_ev_type_t type; |
/trunk/uspace/srv/kbd/ctl/gxe_fb.c |
---|
39,283 → 39,190 |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <kbd_ctl.h> |
#include <gsp.h> |
#include <stroke.h> |
static void parse_ds_start(int scancode); |
static void parse_ds_e(int scancode); |
static void parse_ds_e1(int scancode); |
static void parse_ds_e1a(int scancode); |
static void parse_ds_e1b(int scancode); |
static void parse_ds_e1c(int scancode); |
/** Scancode parser */ |
static gsp_t sp; |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length); |
/** Current parser state */ |
static int ds; |
enum dec_state { |
ds_start, |
ds_e, |
ds_e1, |
ds_e1a, |
ds_e1b, |
ds_e1c |
}; |
#include <stdio.h> |
static int map_start[][2] = { |
int seq_defs[] = { |
/* Not shifted */ |
[0x60] = { 0, KC_BACKTICK }, |
0, KC_BACKTICK, 0x60, GSP_END, |
[0x31] = { 0, KC_1 }, |
[0x32] = { 0, KC_2 }, |
[0x33] = { 0, KC_3 }, |
[0x34] = { 0, KC_4 }, |
[0x35] = { 0, KC_5 }, |
[0x36] = { 0, KC_6 }, |
[0x37] = { 0, KC_7 }, |
[0x38] = { 0, KC_8 }, |
[0x39] = { 0, KC_9 }, |
[0x30] = { 0, KC_0 }, |
0, KC_1, 0x31, GSP_END, |
0, KC_2, 0x32, GSP_END, |
0, KC_3, 0x33, GSP_END, |
0, KC_4, 0x34, GSP_END, |
0, KC_5, 0x35, GSP_END, |
0, KC_6, 0x36, GSP_END, |
0, KC_7, 0x37, GSP_END, |
0, KC_8, 0x38, GSP_END, |
0, KC_9, 0x39, GSP_END, |
0, KC_0, 0x30, GSP_END, |
[0x2d] = { 0, KC_MINUS }, |
[0x3d] = { 0, KC_EQUALS }, |
[0x08] = { 0, KC_BACKSPACE }, |
0, KC_MINUS, 0x2d, GSP_END, |
0, KC_EQUALS, 0x3d, GSP_END, |
0, KC_BACKSPACE, 0x08, GSP_END, |
[0x0f] = { 0, KC_TAB }, |
0, KC_TAB, 0x09, GSP_END, |
[0x71] = { 0, KC_Q }, |
[0x77] = { 0, KC_W }, |
[0x65] = { 0, KC_E }, |
[0x72] = { 0, KC_R }, |
[0x74] = { 0, KC_T }, |
[0x79] = { 0, KC_Y }, |
[0x75] = { 0, KC_U }, |
[0x69] = { 0, KC_I }, |
[0x6f] = { 0, KC_O }, |
[0x70] = { 0, KC_P }, |
0, KC_Q, 0x71, GSP_END, |
0, KC_W, 0x77, GSP_END, |
0, KC_E, 0x65, GSP_END, |
0, KC_R, 0x72, GSP_END, |
0, KC_T, 0x74, GSP_END, |
0, KC_Y, 0x79, GSP_END, |
0, KC_U, 0x75, GSP_END, |
0, KC_I, 0x69, GSP_END, |
0, KC_O, 0x6f, GSP_END, |
0, KC_P, 0x70, GSP_END, |
[0x5b] = { 0, KC_LBRACKET }, |
[0x5d] = { 0, KC_RBRACKET }, |
0, KC_LBRACKET, 0x5b, GSP_END, |
0, KC_RBRACKET, 0x5d, GSP_END, |
[0x61] = { 0, KC_A }, |
[0x73] = { 0, KC_S }, |
[0x64] = { 0, KC_D }, |
[0x66] = { 0, KC_F }, |
[0x67] = { 0, KC_G }, |
[0x68] = { 0, KC_H }, |
[0x6a] = { 0, KC_J }, |
[0x6b] = { 0, KC_K }, |
[0x6c] = { 0, KC_L }, |
0, KC_A, 0x61, GSP_END, |
0, KC_S, 0x73, GSP_END, |
0, KC_D, 0x64, GSP_END, |
0, KC_F, 0x66, GSP_END, |
0, KC_G, 0x67, GSP_END, |
0, KC_H, 0x68, GSP_END, |
0, KC_J, 0x6a, GSP_END, |
0, KC_K, 0x6b, GSP_END, |
0, KC_L, 0x6c, GSP_END, |
[0x3b] = { 0, KC_SEMICOLON }, |
[0x27] = { 0, KC_QUOTE }, |
[0x5c] = { 0, KC_BACKSLASH }, |
0, KC_SEMICOLON, 0x3b, GSP_END, |
0, KC_QUOTE, 0x27, GSP_END, |
0, KC_BACKSLASH, 0x5c, GSP_END, |
[0x7a] = { 0, KC_Z }, |
[0x78] = { 0, KC_X }, |
[0x63] = { 0, KC_C }, |
[0x76] = { 0, KC_V }, |
[0x62] = { 0, KC_B }, |
[0x6e] = { 0, KC_N }, |
[0x6d] = { 0, KC_M }, |
0, KC_Z, 0x7a, GSP_END, |
0, KC_X, 0x78, GSP_END, |
0, KC_C, 0x63, GSP_END, |
0, KC_V, 0x76, GSP_END, |
0, KC_B, 0x62, GSP_END, |
0, KC_N, 0x6e, GSP_END, |
0, KC_M, 0x6d, GSP_END, |
[0x2c] = { 0, KC_COMMA }, |
[0x2e] = { 0, KC_PERIOD }, |
[0x2f] = { 0, KC_SLASH }, |
0, KC_COMMA, 0x2c, GSP_END, |
0, KC_PERIOD, 0x2e, GSP_END, |
0, KC_SLASH, 0x2f, GSP_END, |
[0x20] = { 0, KC_SPACE }, |
/* Shifted */ |
[0x1b] = { 0, KC_ESCAPE }, |
KM_SHIFT, KC_BACKTICK, 0x7e, GSP_END, |
[0x0a] = { 0, KC_ENTER }, |
[0x0d] = { 0, KC_ENTER }, |
KM_SHIFT, KC_1, 0x21, GSP_END, |
KM_SHIFT, KC_2, 0x40, GSP_END, |
KM_SHIFT, KC_3, 0x23, GSP_END, |
KM_SHIFT, KC_4, 0x24, GSP_END, |
KM_SHIFT, KC_5, 0x25, GSP_END, |
KM_SHIFT, KC_6, 0x5e, GSP_END, |
KM_SHIFT, KC_7, 0x26, GSP_END, |
KM_SHIFT, KC_8, 0x2a, GSP_END, |
KM_SHIFT, KC_9, 0x28, GSP_END, |
KM_SHIFT, KC_0, 0x29, GSP_END, |
/* with Shift pressed */ |
KM_SHIFT, KC_MINUS, 0x5f, GSP_END, |
KM_SHIFT, KC_EQUALS, 0x2b, GSP_END, |
[0x7e] = { KM_LSHIFT, KC_BACKTICK }, |
KM_SHIFT, KC_Q, 0x51, GSP_END, |
KM_SHIFT, KC_W, 0x57, GSP_END, |
KM_SHIFT, KC_E, 0x45, GSP_END, |
KM_SHIFT, KC_R, 0x52, GSP_END, |
KM_SHIFT, KC_T, 0x54, GSP_END, |
KM_SHIFT, KC_Y, 0x59, GSP_END, |
KM_SHIFT, KC_U, 0x55, GSP_END, |
KM_SHIFT, KC_I, 0x49, GSP_END, |
KM_SHIFT, KC_O, 0x4f, GSP_END, |
KM_SHIFT, KC_P, 0x50, GSP_END, |
[0x21] = { KM_LSHIFT, KC_1 }, |
[0x40] = { KM_LSHIFT, KC_2 }, |
[0x23] = { KM_LSHIFT, KC_3 }, |
[0x24] = { KM_LSHIFT, KC_4 }, |
[0x25] = { KM_LSHIFT, KC_5 }, |
[0x5e] = { KM_LSHIFT, KC_6 }, |
[0x26] = { KM_LSHIFT, KC_7 }, |
[0x2a] = { KM_LSHIFT, KC_8 }, |
[0x28] = { KM_LSHIFT, KC_9 }, |
[0x29] = { KM_LSHIFT, KC_0 }, |
KM_SHIFT, KC_LBRACKET, 0x7b, GSP_END, |
KM_SHIFT, KC_RBRACKET, 0x7d, GSP_END, |
[0x5f] = { KM_LSHIFT, KC_MINUS }, |
[0x2b] = { KM_LSHIFT, KC_EQUALS }, |
KM_SHIFT, KC_A, 0x41, GSP_END, |
KM_SHIFT, KC_S, 0x53, GSP_END, |
KM_SHIFT, KC_D, 0x44, GSP_END, |
KM_SHIFT, KC_F, 0x46, GSP_END, |
KM_SHIFT, KC_G, 0x47, GSP_END, |
KM_SHIFT, KC_H, 0x48, GSP_END, |
KM_SHIFT, KC_J, 0x4a, GSP_END, |
KM_SHIFT, KC_K, 0x4b, GSP_END, |
KM_SHIFT, KC_L, 0x4c, GSP_END, |
[0x51] = { KM_LSHIFT, KC_Q }, |
[0x57] = { KM_LSHIFT, KC_W }, |
[0x45] = { KM_LSHIFT, KC_E }, |
[0x52] = { KM_LSHIFT, KC_R }, |
[0x54] = { KM_LSHIFT, KC_T }, |
[0x59] = { KM_LSHIFT, KC_Y }, |
[0x55] = { KM_LSHIFT, KC_U }, |
[0x49] = { KM_LSHIFT, KC_I }, |
[0x4f] = { KM_LSHIFT, KC_O }, |
[0x50] = { KM_LSHIFT, KC_P }, |
KM_SHIFT, KC_SEMICOLON, 0x3a, GSP_END, |
KM_SHIFT, KC_QUOTE, 0x22, GSP_END, |
KM_SHIFT, KC_BACKSLASH, 0x7c, GSP_END, |
[0x7b] = { KM_LSHIFT, KC_LBRACKET }, |
[0x7d] = { KM_LSHIFT, KC_RBRACKET }, |
KM_SHIFT, KC_Z, 0x5a, GSP_END, |
KM_SHIFT, KC_X, 0x58, GSP_END, |
KM_SHIFT, KC_C, 0x43, GSP_END, |
KM_SHIFT, KC_V, 0x56, GSP_END, |
KM_SHIFT, KC_B, 0x42, GSP_END, |
KM_SHIFT, KC_N, 0x4e, GSP_END, |
KM_SHIFT, KC_M, 0x4d, GSP_END, |
[0x41] = { KM_LSHIFT, KC_A }, |
[0x53] = { KM_LSHIFT, KC_S }, |
[0x44] = { KM_LSHIFT, KC_D }, |
[0x46] = { KM_LSHIFT, KC_F }, |
[0x47] = { KM_LSHIFT, KC_G }, |
[0x48] = { KM_LSHIFT, KC_H }, |
[0x4a] = { KM_LSHIFT, KC_J }, |
[0x4b] = { KM_LSHIFT, KC_K }, |
[0x4c] = { KM_LSHIFT, KC_L }, |
KM_SHIFT, KC_COMMA, 0x3c, GSP_END, |
KM_SHIFT, KC_PERIOD, 0x3e, GSP_END, |
KM_SHIFT, KC_SLASH, 0x3f, GSP_END, |
[0x3a] = { KM_LSHIFT, KC_SEMICOLON }, |
[0x22] = { KM_LSHIFT, KC_QUOTE }, |
[0x7c] = { KM_LSHIFT, KC_BACKSLASH }, |
/* ... */ |
[0x5a] = { KM_LSHIFT, KC_Z }, |
[0x58] = { KM_LSHIFT, KC_X }, |
[0x43] = { KM_LSHIFT, KC_C }, |
[0x56] = { KM_LSHIFT, KC_V }, |
[0x42] = { KM_LSHIFT, KC_B }, |
[0x4e] = { KM_LSHIFT, KC_N }, |
[0x4d] = { KM_LSHIFT, KC_M }, |
0, KC_SPACE, 0x20, GSP_END, |
0, KC_ENTER, 0x0a, GSP_END, |
0, KC_ENTER, 0x0d, GSP_END, |
[0x3c] = { KM_LSHIFT, KC_COMMA }, |
[0x3e] = { KM_LSHIFT, KC_PERIOD }, |
[0x3f] = { KM_LSHIFT, KC_SLASH } |
}; |
0, KC_ESCAPE, 0x1b, 0x1b, GSP_END, |
static int map_e1[][2] = |
{ |
}; |
0, KC_F1, 0x1b, 0x5b, 0x4f, 0x50, GSP_END, |
0, KC_F2, 0x1b, 0x5b, 0x4f, 0x51, GSP_END, |
0, KC_F3, 0x1b, 0x5b, 0x4f, 0x52, GSP_END, |
0, KC_F4, 0x1b, 0x5b, 0x4f, 0x53, GSP_END, |
0, KC_F5, 0x1b, 0x5b, 0x31, 0x35, GSP_END, |
0, KC_F6, 0x1b, 0x5b, 0x31, 0x37, GSP_END, |
0, KC_F7, 0x1b, 0x5b, 0x31, 0x38, GSP_END, |
0, KC_F8, 0x1b, 0x5b, 0x31, 0x39, GSP_END, |
0, KC_F9, 0x1b, 0x5b, 0x32, 0x38, GSP_END, |
0, KC_F10, 0x1b, 0x5b, 0x32, 0x39, GSP_END, |
0, KC_F11, 0x1b, 0x5b, 0x32, 0x33, GSP_END, |
0, KC_F12, 0x1b, 0x5b, 0x32, 0x34, GSP_END, |
static int map_e1a[][2] = |
{ |
[0x50] = { 0, KC_F1 }, |
[0x51] = { 0, KC_F2 }, |
[0x52] = { 0, KC_F3 }, |
[0x53] = { 0, KC_F4 }, |
}; |
0, KC_INSERT, 0x1b, 0x5b, 0x32, 0x7e, GSP_END, |
0, KC_HOME, 0x1b, 0x5b, 0x48, GSP_END, |
0, KC_PAGE_UP, 0x1b, 0x5b, 0x35, 0x7e, GSP_END, |
0, KC_DELETE, 0x1b, 0x5b, 0x33, 0x7e, GSP_END, |
0, KC_END, 0x1b, 0x5b, 0x46, GSP_END, |
0, KC_PAGE_DOWN, 0x1b, 0x5b, 0x36, 0x7e, GSP_END, |
static int map_e1b[][2] = |
{ |
[0x33] = { 0, KC_F5 }, |
[0x37] = { 0, KC_F6 }, |
[0x38] = { 0, KC_F7 }, |
[0x39] = { 0, KC_F8 }, |
}; |
0, KC_UP, 0x1b, 0x5b, 0x41, GSP_END, |
0, KC_LEFT, 0x1b, 0x5b, 0x44, GSP_END, |
0, KC_DOWN, 0x1b, 0x5b, 0x42, GSP_END, |
0, KC_RIGHT, 0x1b, 0x5b, 0x43, GSP_END, |
static int map_e1c[][2] = |
{ |
[0x38] = { 0, KC_F9 }, |
[0x39] = { 0, KC_F10 }, |
[0x33] = { 0, KC_F11 }, |
[0x34] = { 0, KC_F12 }, |
0, 0 |
}; |
static unsigned int mods_keys[][2] = { |
{ KM_LSHIFT, KC_LSHIFT }, |
{ 0, 0 } |
}; |
static enum dec_state ds = ds_start; |
void kbd_ctl_parse_scancode(int scancode) |
int kbd_ctl_init(void) |
{ |
switch (ds) { |
case ds_start: parse_ds_start(scancode); break; |
case ds_e: parse_ds_e(scancode); break; |
case ds_e1: parse_ds_e1(scancode); break; |
case ds_e1a: parse_ds_e1a(scancode); break; |
case ds_e1b: parse_ds_e1b(scancode); break; |
case ds_e1c: parse_ds_e1c(scancode); break; |
} |
} |
ds = 0; |
static void parse_ds_start(int scancode) |
{ |
if (scancode == 0x1b) { |
ds = ds_e; |
return; |
gsp_init(&sp); |
return gsp_insert_defs(&sp, seq_defs); |
} |
parse_leaf(scancode, map_start, sizeof(map_start) / (2 * sizeof(int))); |
} |
static void parse_ds_e(int scancode) |
void kbd_ctl_parse_scancode(int scancode) |
{ |
switch (scancode) { |
case 0x5b: ds = ds_e1; return; |
case 0x1b: ds = ds_start; break; |
default: ds = ds_start; return; |
} |
unsigned mods, key; |
kbd_push_ev(KE_PRESS, KC_ESCAPE); |
} |
static void parse_ds_e1(int scancode) |
{ |
switch (scancode) { |
case 0x4f: ds = ds_e1a; return; |
case 0x31: ds = ds_e1b; return; |
case 0x32: ds = ds_e1c; return; |
default: ds = ds_start; break; |
} |
parse_leaf(scancode, map_e1, sizeof(map_e1) / (2 * sizeof(int))); |
} |
static void parse_ds_e1a(int scancode) |
{ |
parse_leaf(scancode, map_e1a, sizeof(map_e1a) / (2 * sizeof(int))); |
} |
static void parse_ds_e1b(int scancode) |
{ |
parse_leaf(scancode, map_e1b, sizeof(map_e1b) / (2 * sizeof(int))); |
} |
static void parse_ds_e1c(int scancode) |
{ |
parse_leaf(scancode, map_e1c, sizeof(map_e1c) / (2 * sizeof(int))); |
} |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length) |
{ |
unsigned int key, mod; |
int i; |
ds = ds_start; |
if (scancode < 0 || scancode >= map_length) |
return; |
mod = map[scancode][0]; |
key = map[scancode][1]; |
/* Simulate modifier pressing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_PRESS, mods_keys[i][1]); |
} |
++i; |
} |
ds = gsp_step(&sp, ds, scancode, &mods, &key); |
if (key != 0) { |
kbd_push_ev(KE_PRESS, key); |
kbd_push_ev(KE_RELEASE, key); |
stroke_sim(mods, key); |
} |
/* Simulate modifier releasing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_RELEASE, mods_keys[i][1]); |
} |
++i; |
} |
} |
/** |
* @} |
/trunk/uspace/srv/kbd/include/gsp.h |
---|
0,0 → 1,78 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbdgen generic |
* @brief Generic scancode parser. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_GSP_H_ |
#define KBD_GSP_H_ |
#include <libadt/hash_table.h> |
enum { |
GSP_END = -1, |
GSP_DEFAULT = -2 |
}; |
typedef struct { |
/** Transition table, (state, input) -> (state, output). */ |
hash_table_t trans; |
/** Current number of states. */ |
int states; |
} gsp_t; |
typedef struct { |
link_t link; |
int old_state; |
int input; |
int new_state; |
unsigned out_mods; |
unsigned out_key; |
} gsp_trans_t; |
extern void gsp_init(gsp_t *); |
extern int gsp_insert_defs(gsp_t *, const int *); |
extern int gsp_insert_seq(gsp_t *, const int *, unsigned, unsigned); |
extern int gsp_step(gsp_t *, int, int, unsigned *, unsigned *); |
#endif |
/** |
* @} |
*/ |
/trunk/uspace/srv/kbd/include/kbd_ctl.h |
---|
38,7 → 38,9 |
#define KBD_CTL_H_ |
extern void kbd_ctl_parse_scancode(int); |
extern int kbd_ctl_init(void); |
#endif |
/** |
/trunk/uspace/srv/kbd/include/stroke.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbdgen generic |
* @brief Generic scancode parser. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_STROKE_H_ |
#define KBD_STROKE_H_ |
extern void stroke_sim(unsigned, unsigned); |
#endif |
/** |
* @} |
*/ |
/trunk/uspace/srv/kbd/genarch/stroke.c |
---|
0,0 → 1,84 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief Stroke simulator. |
* |
* When simulating a keyboard using a serial TTY we need to convert the |
* recognized strokes (such as Shift-A) to sequences of key presses and |
* releases (such as 'press Shift, press A, release A, release Shift'). |
*/ |
#include <stroke.h> |
#include <kbd.h> |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
/** Correspondence between modifers and the modifier keycodes. */ |
static unsigned int mods_keys[][2] = { |
{ KM_LSHIFT, KC_LSHIFT }, |
{ 0, 0 } |
}; |
/** Simulate keystroke using sequences of key presses and releases. */ |
void stroke_sim(unsigned mod, unsigned key) |
{ |
int i; |
/* Simulate modifier presses. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_PRESS, mods_keys[i][1]); |
} |
++i; |
} |
/* Simulate key press and release. */ |
if (key != 0) { |
kbd_push_ev(KE_PRESS, key); |
kbd_push_ev(KE_RELEASE, key); |
} |
/* Simulate modifier releases. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_RELEASE, mods_keys[i][1]); |
} |
++i; |
} |
} |
/** |
* @} |
*/ |
/trunk/uspace/srv/kbd/genarch/gsp.c |
---|
0,0 → 1,288 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** |
* @addtogroup kbdgen generic |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief Generic scancode parser. |
* |
* The scancode parser is a simple finite state machine. It is described |
* using sequences of input symbols (scancodes) and the corresponding output |
* value (mods, key pair). When the parser recognizes a sequence, |
* it outputs the value and restarts. If a transition is undefined, |
* the parser restarts, too. |
* |
* Apart from precise values, GSP_DEFAULT allows to catch general cases. |
* I.e. if we knew that after 0x1b 0x4f there always follow two more |
* scancodes, we can define (0x1b, 0x4f, GSP_DEFAULT, GSP_DEFAULT, GSP_END) |
* with null output. This will force the parser to read the entire sequence, |
* not leaving garbage on the input if it does not recognize the specific |
* sequence. |
*/ |
#include <gsp.h> |
#include <libadt/hash_table.h> |
#include <stdlib.h> |
#include <stdio.h> |
#define TRANS_TABLE_CHAINS 256 |
/* |
* Hash table operations for the transition function. |
*/ |
static hash_index_t trans_op_hash(unsigned long key[]); |
static int trans_op_compare(unsigned long key[], hash_count_t keys, |
link_t *item); |
static void trans_op_remove_callback(link_t *item); |
static hash_table_operations_t trans_ops = { |
.hash = trans_op_hash, |
.compare = trans_op_compare, |
.remove_callback = trans_op_remove_callback |
}; |
static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input); |
static void trans_insert(gsp_t *p, gsp_trans_t *t); |
static gsp_trans_t *trans_new(void); |
/** Initialise scancode parser. */ |
void gsp_init(gsp_t *p) |
{ |
p->states = 1; |
hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops); |
} |
/** Insert a series of definitions into the parser. |
* |
* @param p The parser. |
* @param defs Definition list. Each definition starts with two output values |
* (mods, key) and continues with a sequence of input values |
* terminated with GSP_END. The definition list is terminated |
* with two zeroes (0, 0) for output values. |
*/ |
int gsp_insert_defs(gsp_t *p, const int *defs) |
{ |
unsigned mods, key; |
const int *dp; |
int rc; |
dp = defs; |
while (1) { |
/* Read the output values. */ |
mods = *dp++; |
key = *dp++; |
if (key == 0) break; |
/* Insert one sequence. */ |
rc = gsp_insert_seq(p, dp, mods, key); |
if (rc != 0) |
return rc; |
/* Skip to the next definition. */ |
while (*dp != GSP_END) |
++dp; |
++dp; |
} |
return 0; |
} |
/** Insert one sequence into the parser. |
* |
* @param p The parser. |
* @param seq Sequence of input values terminated with GSP_END. |
* @param mods Corresponsing output value. |
* @param key Corresponsing output value. |
*/ |
int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key) |
{ |
int state; |
gsp_trans_t *t; |
state = 0; |
t = NULL; |
/* Input sequence must be non-empty. */ |
if (*seq == GSP_END) |
return -1; |
while (*(seq + 1) != GSP_END) { |
t = trans_lookup(p, state, *seq); |
if (t == NULL) { |
/* Create new state. */ |
t = trans_new(); |
t->old_state = state; |
t->input = *seq; |
t->new_state = p->states++; |
t->out_mods = 0; |
t->out_key = 0; |
trans_insert(p, t); |
} |
state = t->new_state; |
++seq; |
} |
/* Process the last transition. */ |
t = trans_lookup(p, state, *seq); |
if (t != NULL) { |
exit(1); |
return -1; /* Conflicting definition. */ |
} |
t = trans_new(); |
t->old_state = state; |
t->input = *seq; |
t->new_state = 0; |
t->out_mods = mods; |
t->out_key = key; |
trans_insert(p, t); |
return 0; |
} |
/** Compute one parser step. |
* |
* Computes the next state and output values for a given state and input. |
* This handles everything including restarts and default branches. |
* |
* @param p The parser. |
* @param state Old state. |
* @param input Input symbol (scancode). |
* @param mods Output value (modifier). |
* @param key Output value (key). |
* @return New state. |
*/ |
int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key) |
{ |
gsp_trans_t *t; |
t = trans_lookup(p, state, input); |
if (t == NULL) { |
t = trans_lookup(p, state, GSP_DEFAULT); |
} |
if (t == NULL) { |
printf("gsp_step: not found\n"); |
*mods = NULL; |
*key = NULL; |
return 0; |
} |
*mods = t->out_mods; |
*key = t->out_key; |
return t->new_state; |
} |
/** Transition function lookup. |
* |
* Returns the value of the transition function for the given state |
* and input. Note that the transition must be specified precisely, |
* to obtain the default branch use input = GSP_DEFAULT. |
* |
* @param p Parser. |
* @param state Current state. |
* @param input Input value. |
* @return The transition or @c NULL if not defined. |
*/ |
static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input) |
{ |
link_t *item; |
unsigned long key[2]; |
key[0] = state; |
key[1] = input; |
item = hash_table_find(&p->trans, key); |
if (item == NULL) return NULL; |
return hash_table_get_instance(item, gsp_trans_t, link); |
} |
/** Define a new transition. |
* |
* @param p The parser. |
* @param t Transition with all fields defined. |
*/ |
static void trans_insert(gsp_t *p, gsp_trans_t *t) |
{ |
unsigned long key[2]; |
key[0] = t->old_state; |
key[1] = t->input; |
hash_table_insert(&p->trans, &key, &t->link); |
} |
/** Allocate transition structure. */ |
static gsp_trans_t *trans_new(void) |
{ |
gsp_trans_t *t; |
t = malloc(sizeof(gsp_trans_t)); |
if (t == NULL) { |
printf("Memory allocation failed.\n"); |
exit(1); |
} |
return t; |
} |
/* |
* Transition function hash table operations. |
*/ |
static hash_index_t trans_op_hash(unsigned long key[]) |
{ |
return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS; |
} |
static int trans_op_compare(unsigned long key[], hash_count_t keys, |
link_t *item) |
{ |
gsp_trans_t *t; |
t = hash_table_get_instance(item, gsp_trans_t, link); |
return (key[0] == t->old_state && key[1] == t->input); |
} |
static void trans_op_remove_callback(link_t *item) |
{ |
} |
/** |
* @} |
*/ |
/trunk/uspace/srv/kbd/generic/kbd.c |
---|
189,9 → 189,13 |
} |
/* Initialize port driver. */ |
if (kbd_port_init()) |
if (kbd_port_init() != 0) |
return -1; |
/* Initialize controller driver. */ |
if (kbd_ctl_init() != 0) |
return -1; |
/* Initialize key buffer */ |
keybuffer_init(&keybuffer); |
/trunk/uspace/srv/kbd/Makefile |
---|
44,6 → 44,8 |
OUTPUT = kbd |
GENERIC_SOURCES = \ |
generic/kbd.c \ |
genarch/gsp.c \ |
genarch/stroke.c \ |
generic/key_buffer.c |
ARCH_SOURCES = |