/* kbd_cmd.c - aeb, 940505 */ /* * This program must have write permission to /dev/port - probably that * means that it has to be suid root. * * Without arguments: enable keyboard. * * With a single argument "sane": enable keyboard and set default scancodes. * * [These are useful commands, but when the keyboard is in some obscure * state they probably cannot be typed. Under X you can have them as a * menu item. Otherwise you might use "sleep 300; kbd_cmd sane" before * doing something dangerous, like playing with this program.] * * With a sequence of two-character hexadecimal values or symbolic commands: * send these values to the keyboard. * An argument W or w means wait. * * e.g., "kbd_cmd LED 7" will set the LEDs behind the kernel's back - * use the program "setleds" if you want the lights to mean anything. * * "kbd_cmd f0 1; showkey -s; kbd_cmd f0 2" will enable you to study the * scancodes produced in a different scancode mode. * * "kbd_cmd W f0 1 f0 0 W f0 2 & showkey -s" will enable you to find the * identifications of the various scancode sets, and similarly * "kbd_cmd W f2 & showkey -s" yields the keyboard identification. * * Playing with these things is dangerous! It is very easy to get into a * state in which the keyboard cannot be used anymore. Set up an escape * (as suggested above). * These commands work on my keyboard. For other keyboards the results * may be unpredictible. */ #include #include #include struct { unsigned char cmd; int argct, resct; char *name; } commands[] = { 0xed, 1, 0, "LED", /* arg 0-7: 1 ScrollLock, 2 NumLock, 4 CapsLock */ 0xee, 0, 1, "echo", /* result: ee */ 0xf0, 1, 1, "get_scancodes", /* arg: 0, result: 43, 41 or 3f */ 0xf0, 1, 0, "set_scancodes", /* arg: 1-3 */ 0xf2, 0, 2, "identify_keyboard", /* result: ab 41 */ 0xf3, 1, 0, "set_repeat_rate", 0xf4, 0, 0, "enable", 0xf5, 0, 0, "reset_and_disable", 0xf6, 0, 0, "reset_and_enable", 0xfe, 0, 1, "resend", 0xff, 0, 1, "reset_and_selftest" /* result: aa (OK) / fc (error) */ }; int fd; int args_expected; send_cmd(unsigned char x) { char z; int i; do { lseek( fd, 0x64, 0 ); read( fd, &z, 1 ); } while ((z & 2) == 2 ); /* wait */ lseek( fd, 0x60, 0 ); write( fd, &x, 1 ); if (args_expected) args_expected--; else { for(i=0; i 2) { for (j=0; j < sizeof(commands)/sizeof(commands[0]); j++) if(!strcmp(commands[j].name, argv[i])) { send_cmd(commands[j].cmd); goto fnd; } fprintf(stderr, "kbd_cmd: unrecognized command %s\n", argv[i]); leave(1); fnd:; } else send_cmd(tohex(argv[i])); } leave(0); } leave(int n) { /* prevent frozen keyboards, waiting for command arguments */ while(args_expected) send_cmd(0); exit(n); }