/* * pk -- pseudo keyboard via ``kbdsim.o'' * * 0.0: Feb. 12, 2004 by Dai ISHIJIMA (alphabet) * 0.1: Feb. 14, 2004 * * usage: * pk string * * see also * kbdsim.c * * how to install kbdsim.o * # mknod /dev/kbdsim c 61 0 * # insmod -f kbdsim.o */ #include #include #include #include #define YES 1 #define NO 0 #define EOS '\0' #define DEVKBDSIM "/dev/kbdsim" #define KEY_PRESS 1 #define KEY_RELEASE 0 #define ASCII 'a' #define HEX 'X' #define DIGIT 'D' #define shift --argc; ++argv char *prog; /* * keycode definitions * see also "kernel/linux24/drivers/char/corgi_keymap.map" * but something wrong... */ /* ALPHABETS (1..26) */ enum { KEY_A = 1, KEY_B, KEY_C, KEY_D, /* 1.. 4 */ KEY_E, KEY_F, KEY_G, KEY_H, /* 5.. 8 */ KEY_I, KEY_J, KEY_K, KEY_L, /* 9..12 */ KEY_M, KEY_N, KEY_O, KEY_P, /* 13..16 */ KEY_Q, KEY_R, KEY_S, KEY_T, /* 17..20 */ KEY_U, KEY_V, KEY_W, KEY_X, /* 21..24 */ KEY_Y, KEY_Z}; /* 25, 26 */ /* MODIFIERS, FUNCTIONS */ enum { KEY_SHIFT = 27, KEY_RET, KEY_MENU, KEY_ALT, /* 27- */ KEY_BS, KEY_KIGOU, KEY_LCDOFF, KEY_CANCEL,/* 31- */ KEY_LEFT, KEY_UP, KEY_DOWN, KEY_RIGHT, /* 35- */ /* ESC [ D ESC [ A ESC [ B ESC [ C */ KEY_OK, KEY_HOME}; /* 39- */ /* NUMBERS */ enum { KEY_ONE = 41, KEY_TWO, KEY_THREE, KEY_FOUR, /* 41- */ KEY_FIVE, KEY_SIX, KEY_SEVEN, KEY_EIGHT, /* 45- */ KEY_NINE, KEY_ZERO}; /* 49- */ /* SYMBOLS */ enum { KEY_USCORE = 51, KEY_DOT, KEY_EQUAL, KEY_YEN, /* 51- */ KEY_SEMI, KEY_COLON, KEY_FN_I}; /* 55- */ /* 」*/ /* SYMBOLS */ enum { KEY_MINUS = 58, KEY_ASTER, KEY_LOCK, KEY_UNDEF, /* 58- */ KEY_BAR, KEY_COMMA, KEY_PERIOD, KEY_TAB, /* 62- */ KEY_X_2, KEY_C_2, KEY_V_2, KEY_PLUS, /* 66- */ KEY_LBRACKET, KEY_LARGE, KEY_CIRCUM, KEY_RBRACKET,/* 70- */ KEY_SMALL, KEY_FN_U, KEY_DARK, KEY_BRITE, /* 74- */ /* 「 */ KEY_UNDEF6, KEY_UNDEF7, KEY_UNDEF8, KEY_UNDEF9,/* 78- */ KEY_Z_2, KEY_UNDEFA, KEY_UNDEFB, KEY_AT, /* 82- */ KEY_LESS, KEY_GRATER, KEY_F9, KEY_SLASH, /* 86- */ /* ESC [ 20 ~ */ KEY_MAIL, KEY_SPACE, KEY_SPACE_2, KEY_UNDEFC,/* 90- */ KEY_UNDEFD, KEY_KANJI}; /* 94- */ /* FUNCTIONS */ enum { KEY_MUSIC = 96, KEY_MUSIC2, KEY_MUSIC3, KEY_MUSIC4,/* 96- */ KEY_MUSIC5, KEY_MUSIC6, KEY_UNDEFE}; /* 100- */ /* MODIFIERS, CONTROLS */ enum { KEY_SHIFT_2 = 103, KEY_CTRL, KEY_CTRL_HAT, KEY_MENUX, /* 103- */ KEY_CTRL_YEN, KEY_LBRACE, KEY_OFF, KEY_MAIL2, /* 107- */ KEY_RBRACE, KEY_KIGOU2, KEY_KRIGHT, KEY_KLEFT, /* 111- */ KEY_PRTSC, KEY_CTRL_US, KEY_SYNC, KEY_YEN2, /* 115- */ KEY_UNDEFI, KEY_LARGE2, KEY_KANAHIRA, KEY_KANJI2, /* 119- */ KEY_OK2, KEY_CANCEL2, KEY_KUP, KEY_KDOWN, /* 123- */ KEY_UNDEFK}; /* 127- */ #define CTRL(ch) ((unsigned char)ch & 0x1f) /* ASCII -> KEYCODE */ int char2key(int ch, unsigned char *keybuf) { if (ch == 0) { keybuf[0] = KEY_CTRL; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_SPACE; keybuf[3] = KEY_PRESS; keybuf[4] = KEY_SPACE; keybuf[5] = KEY_RELEASE; keybuf[6] = KEY_CTRL; keybuf[7] = KEY_RELEASE; return(4); } else if (ch == '\010') { /* BS */ keybuf[0] = KEY_BS; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_BS; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '\r') { keybuf[0] = KEY_RET; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_RET; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '\033') { keybuf[0] = KEY_CANCEL; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_CANCEL; keybuf[3] = KEY_RELEASE; return(2); } else if (ch <= CTRL('z')) { keybuf[0] = KEY_CTRL; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_A + ch - CTRL('a'); keybuf[3] = KEY_PRESS; keybuf[4] = keybuf[2]; keybuf[5] = KEY_RELEASE; keybuf[6] = KEY_CTRL; keybuf[7] = KEY_RELEASE; return(4); } else if (ch == ' ') { keybuf[0] = KEY_SPACE; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_SPACE; keybuf[3] = KEY_RELEASE; return(2); } else if (('!' <= ch) && (ch <= ')')) { keybuf[0] = KEY_SHIFT; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_ONE + ch - '!'; keybuf[3] = KEY_PRESS; keybuf[4] = keybuf[2]; keybuf[5] = KEY_RELEASE; keybuf[6] = KEY_SHIFT; keybuf[7] = KEY_RELEASE; return(4); } else if (ch == '*') { keybuf[0] = KEY_ASTER; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_ASTER; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '+') { keybuf[0] = KEY_PLUS; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_PLUS; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == ',') { keybuf[0] = KEY_COMMA; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_COMMA; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '-') { keybuf[0] = KEY_MINUS; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_MINUS; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '.') { keybuf[0] = KEY_PERIOD; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_PERIOD; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '/') { keybuf[0] = KEY_SLASH; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_SLASH; keybuf[3] = KEY_RELEASE; return(2); } else if (('1' <= ch) && (ch <= '9')) { keybuf[0] = KEY_ONE + ch - '1'; keybuf[1] = KEY_PRESS; keybuf[2] = keybuf[0]; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '0') { keybuf[0] = KEY_ZERO; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_ZERO; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == ':') { keybuf[0] = KEY_COLON; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_COLON; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == ';') { keybuf[0] = KEY_SEMI; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_SEMI; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '<') { keybuf[0] = KEY_LESS; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_LESS; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '=') { keybuf[0] = KEY_EQUAL; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_EQUAL; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '>') { keybuf[0] = KEY_GRATER; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_GRATER; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '?') { keybuf[0] = KEY_SHIFT; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_PERIOD; keybuf[3] = KEY_PRESS; keybuf[4] = KEY_PERIOD; keybuf[5] = KEY_RELEASE; keybuf[6] = KEY_SHIFT; keybuf[7] = KEY_RELEASE; return(4); } else if (ch == '@') { keybuf[0] = KEY_AT; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_AT; keybuf[3] = KEY_RELEASE; return(2); } else if (('A' <= ch) && (ch <= 'Z')) { keybuf[0] = KEY_SHIFT; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_A + ch - 'A'; keybuf[3] = KEY_PRESS; keybuf[4] = keybuf[2]; keybuf[5] = KEY_RELEASE; keybuf[6] = KEY_SHIFT; keybuf[7] = KEY_RELEASE; return(4); } else if (ch == '[') { keybuf[0] = KEY_LBRACKET; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_LBRACKET; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '\134') { keybuf[0] = KEY_YEN; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_YEN; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == ']') { keybuf[0] = KEY_RBRACKET; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_RBRACKET; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '^') { keybuf[0] = KEY_CIRCUM; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_CIRCUM; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '_') { keybuf[0] = KEY_USCORE; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_USCORE; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '`') { keybuf[0] = KEY_ALT; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_SHIFT; keybuf[3] = KEY_PRESS; keybuf[4] = KEY_MINUS; keybuf[5] = KEY_PRESS; keybuf[6] = KEY_MINUS; keybuf[7] = KEY_RELEASE; keybuf[8] = KEY_SHIFT; keybuf[9] = KEY_PRESS; keybuf[10] = KEY_ALT; keybuf[11] = KEY_RELEASE; return(6); } else if (('a' <= ch) && (ch <= 'z')) { keybuf[0] = KEY_A + ch - 'a'; keybuf[1] = KEY_PRESS; keybuf[2] = keybuf[0]; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '{') { keybuf[0] = KEY_LBRACE; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_LBRACE; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '|') { keybuf[0] = KEY_BAR; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_BAR; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '}') { keybuf[0] = KEY_RBRACE; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_RBRACE; keybuf[3] = KEY_RELEASE; return(2); } else if (ch == '~') { keybuf[0] = KEY_SHIFT; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_ZERO; keybuf[3] = KEY_PRESS; keybuf[4] = KEY_ZERO; keybuf[5] = KEY_RELEASE; keybuf[6] = KEY_SHIFT; keybuf[7] = KEY_RELEASE; return(4); } else if (ch == '\177') { keybuf[0] = KEY_ALT; keybuf[1] = KEY_PRESS; keybuf[2] = KEY_BS; keybuf[3] = KEY_PRESS; keybuf[4] = KEY_BS; keybuf[5] = KEY_RELEASE; keybuf[6] = KEY_ALT; keybuf[7] = KEY_RELEASE; return(4); } return(0); } int hexdigit(char ch) { /* ch に応じて 0〜15までの値を返す */ if (('0' <= ch) && (ch <= '9')) { return(ch - '0'); } else if (('A' <= ch) && (ch <= 'F')) { return(ch - 'A' + 10); } else if (('a' <= ch) && (ch <= 'f')) { return(ch - 'a' + 10); } return(-1); /* 16進文字じゃないときは -1 を返す */ } /* 16進文字列をバイナリ化する。「41 54 5a 0d 0a」→「ATZ\r\n」 */ int hexconv(char *to, char *from) { int m, n; int x; m = n = 0; while (from[m] != EOS) { while ((from[m] != EOS) && ((x = hexdigit(from[m])) < 0)) { ++m; } if ((from[m] != EOS) && ((x = hexdigit(from[m])) >= 0)) { to[n] = x; ++m; } if ((from[m] != EOS) && ((x = hexdigit(from[m])) >= 0)) { to[n] = to[n] << 4 | x; ++m; } ++n; if (from[m] == EOS) { break; } } for (m = 0; m < n; m++) { from[m] = to[m]; } from[m] = EOS; return(m); } void sendkey(int fd, unsigned char *s, int verbose) { if (verbose) { fprintf(stderr, "%s: code=%d(%x), ", prog, s[0], s[0]); if (s[1] == KEY_PRESS) { fprintf(stderr, "PRESS\n"); } else if (s[1] == KEY_RELEASE) { fprintf(stderr, "RELEASE\n"); } else { fprintf(stderr, "UNKNOWN(%d)\n", s[1]); } } write(fd, s, 2); } void digitcode(int fd, char sign, unsigned char ch, int verbose) { unsigned char keybuf[2]; if (sign != '-') { keybuf[0] = ch; keybuf[1] = KEY_PRESS; sendkey(fd, keybuf, verbose); } if (sign != '+') { keybuf[0] = ch; keybuf[1] = KEY_RELEASE; sendkey(fd, keybuf, verbose); } } void hexcode(int fd, unsigned char *s, int verbose) { unsigned char codebuf[BUFSIZ]; unsigned char keybuf[2]; int n; int i; if (verbose) { fprintf(stderr, "%s: sending \"%s\"\n", prog, s); } n = hexconv(codebuf, s); for (i = 0; i < n; i++) { keybuf[0] = codebuf[i]; keybuf[1] = KEY_PRESS; sendkey(fd, keybuf, verbose); keybuf[0] = codebuf[i]; keybuf[1] = KEY_RELEASE; sendkey(fd, keybuf, verbose); } } void pseudo_input(int fd, int ch, int verbose) { unsigned char keybuf[BUFSIZ]; int n; int i; n = char2key(ch, keybuf); for (i = 0; i < n; i++) { sendkey(fd, &keybuf[2 * i], verbose); } } int parse(char *to, char *from) { int i; int x; i = 0; while (*from != EOS) { if (*from == '\\') { ++from; if (*from == EOS) { break; } else if (*from == 'r') { to[i] = '\r'; } else if (*from == 'n') { to[i] = '\n'; } else if (*from == 't') { to[i] = '\t'; } else if (*from == '^') { ++from; if (*from == EOS) { break; } else if (*from == '?') { to[i] = 0x7f; } else if (*from == '^') { to[i] = '^'; } else { to[i] = CTRL(*from); } } else if (('0'<= *from) && (*from <= '7')) { while (('0'<= *from) && (*from <= '7')) { to[i] = to[i] * 8 + *from - '0'; ++from; } --from; } else if (*from == 'x') { ++from; if ((*from != EOS) && ((x = hexdigit(*from)) >= 0)) { to[i] = x; ++from; } if ((*from != EOS) && ((x = hexdigit(*from)) >= 0)) { to[i] = to[i] << 4 | x; ++from; } --from; } else { to[i] = *from; } } else { to[i] = *from; } ++from; ++i; } to[i] = EOS; return(i); } void usage() { fprintf(stderr, "Usage: %s string\n", prog); } int main(int argc, char *argv[]) { int fd; int mode; int verbose; int delay; unsigned char string[BUFSIZ]; int i, n; prog = *argv; shift; delay = 0; mode = ASCII; verbose = NO; while ((argc > 0) && (argv[0][0] == '-')) { if (('0' <= argv[0][1]) && (argv[0][1] <= '9')) { delay = -atoi(*argv); } else if (argv[0][1] == 'e') { shift; break; } else if (argv[0][1] == 'v') { verbose = !verbose; } else if (argv[0][1] == 'x') { mode = HEX; } else if (argv[0][1] == 'd') { mode = DIGIT; shift; break; } else { usage(); } shift; } if (delay > 0) { sleep(delay); } if ((fd = open(DEVKBDSIM, O_WRONLY)) <= 0) { fprintf(stderr, "can't open %s\n", DEVKBDSIM); exit(1); } while (argc > 0) { if (mode == HEX) { hexcode(fd, *argv, verbose); } else if (mode == DIGIT) { digitcode(fd, **argv, abs(atoi(*argv)), verbose); } else { n = parse(string, *argv); for (i = 0; i < n; i++) { pseudo_input(fd, string[i], verbose); } } shift; } close(fd); exit(0); }