/* kbd.c: Copyright (c) 1989, 1990 William Jolitz. All rights reserved.
* Written by William Jolitz 9/89
* Redistribution and use in source and binary forms are freely permitted
* provided that the above copyright notice and attribution and date of work
* and this paragraph are duplicated in all such forms.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* Standalone driver for IBM PC keyboards.
*/
#define L 0x001 /* locking function */
#define SHF 0x002 /* keyboard shift */
#define ALT 0x004 /* alternate shift -- alternate chars */
#define NUM 0x008 /* numeric shift cursors vs. numeric */
#define CTL 0x010 /* control shift -- allows ctl function */
#define CPS 0x020 /* caps shift -- swaps case of letter */
#define ASCII 0x040 /* ascii code for this key */
#define STP 0x080 /* stop output */
#define BREAK 0x100 /* key breaking contact */
typedef unsigned char u_char;
u_char inb();
u_char action[] = {
0, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 0- 7 */
ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 8-15 */
ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 16-23 */
ASCII, ASCII, ASCII, ASCII, ASCII, CTL, ASCII, ASCII, /* scan 24-31 */
ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 32-39 */
ASCII, ASCII, SHF , ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 40-47 */
ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, SHF, ASCII, /* scan 48-55 */
ALT, ASCII, CPS|L, 0, 0, ASCII, 0, 0, /* scan 56-63 */
0, 0, 0, 0, 0, NUM|L, STP|L, ASCII, /* scan 64-71 */
ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 72-79 */
ASCII, ASCII, ASCII, ASCII, 0, 0, 0, 0, /* scan 80-87 */
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
u_char unshift[] = { /* no shift */
0, 033 , '1' , '2' , '3' , '4' , '5' , '6' , /* scan 0- 7 */
'7' , '8' , '9' , '0' , '-' , '=' , 0177 ,'\t' , /* scan 8-15 */
'q' , 'w' , 'e' , 'r' , 't' , 'y' , 'u' , 'i' , /* scan 16-23 */
'o' , 'p' , '[' , ']' , '\r' , CTL , 'a' , 's' , /* scan 24-31 */
'd' , 'f' , 'g' , 'h' , 'j' , 'k' , 'l' , ';' , /* scan 32-39 */
'\'' , '`' , SHF , '\\' , 'z' , 'x' , 'c' , 'v' , /* scan 40-47 */
'b' , 'n' , 'm' , ',' , '.' , '/' , SHF , '*', /* scan 48-55 */
ALT , ' ' , CPS|L, 0, 0, ' ' , 0, 0, /* scan 56-63 */
0, 0, 0, 0, 0, NUM|L, STP|L, '7', /* scan 64-71 */
'8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */
'2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
u_char shift[] = { /* shift shift */
0, 033 , '!' , '@' , '#' , '$' , '%' , '^' , /* scan 0- 7 */
'&' , '*' , '(' , ')' , '_' , '+' , 0177 ,'\t' , /* scan 8-15 */
'Q' , 'W' , 'E' , 'R' , 'T' , 'Y' , 'U' , 'I' , /* scan 16-23 */
'O' , 'P' , '[' , ']' , '\r' , CTL , 'A' , 'S' , /* scan 24-31 */
'D' , 'F' , 'G' , 'H' , 'J' , 'K' , 'L' , ':' , /* scan 32-39 */
'"' , '~' , SHF , '|' , 'Z' , 'X' , 'C' , 'V' , /* scan 40-47 */
'B' , 'N' , 'M' , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */
ALT , ' ' , CPS|L, 0, 0, ' ' , 0, 0, /* scan 56-63 */
0, 0, 0, 0, 0, NUM|L, STP|L, '7', /* scan 64-71 */
'8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */
'2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
u_char ctl[] = { /* CTL shift */
0, 033 , '!' , 000 , '#' , '$' , '%' , 036 , /* scan 0- 7 */
'&' , '*' , '(' , ')' , 037 , '+' , 034 ,'\177', /* scan 8-15 */
021 , 027 , 005 , 022 , 024 , 031 , 025 , 011 , /* scan 16-23 */
017 , 020 , 033 , 035 , '\r' , CTL , 001 , 013 , /* scan 24-31 */
004 , 006 , 007 , 010 , 012 , 013 , 014 , ';' , /* scan 32-39 */
'\'' , '`' , SHF , 034 , 032 , 030 , 003 , 026 , /* scan 40-47 */
002 , 016 , 015 , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */
ALT , ' ' , CPS|L, 0, 0, ' ' , 0, 0, /* scan 56-63 */
CPS|L, 0, 0, 0, 0, 0, 0, 0, /* scan 64-71 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 72-79 */
0, 0, 0, 0, 0, 0, 0, 0, /* scan 80-87 */
0, 0, 033, '7' , '4' , '1' , 0, NUM|L, /* scan 88-95 */
'8' , '5' , '2' , 0, STP|L, '9' , '6' , '3' , /*scan 96-103*/
'.' , 0, '*' , '-' , '+' , 0, 0, 0, /*scan 104-111*/
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
#define KBSTATP 0x64 /* kbd status port */
#define KBS_RDY 0x02 /* kbd char ready */
#define KBDATAP 0x60 /* kbd data port */
#define KBSTATUSPORT 0x61 /* kbd status */
#define KBD_BRK 0x80 /* key is breaking contact, not making contact */
#define KBD_KEY(s) ((s) & 0x7f) /* key that has changed */
/* Return an ASCII character from the keyboard. */
u_char kbd() {
u_char dt, act;
static u_char odt, shfts, ctls, alts, caps, num, stp;
do {
do {
while (inb(KBSTATP)&KBS_RDY) ;
dt = inb(KBDATAP);
} while (dt == odt);
odt = dt;
dt = KBD_KEY(dt);
act = action[dt];
if (odt & KBD_BRK) act |= BREAK;
/* kinds of shift keys */
if (act&SHF) actl (act, &shfts);
if (act&ALT) actl (act, &alts);
if (act&NUM) actl (act, &num);
if (act&CTL) actl (act, &ctls);
if (act&CPS) actl (act, &caps);
if (act&STP) actl (act, &stp);
if (act&(ASCII|BREAK) == ASCII) {
u_char chr;
if (shfts)
chr = shift[dt] ;
else {
if (ctls) chr = ctl[dt] ;
else chr = unshift[dt] ;
}
if (caps && (chr >= 'a' && chr <= 'z'))
chr -= 'a' - 'A' ;
return(chr);
}
} while (1);
}
/* Handle shift key actions */
actl(act, v, brk) char *v; {
/* are we locking ... */
if (act&L) {
if((act&BREAK) == 0) *v ^= 1;
/* ... or single - action ? */
} else
if(act&BREAK) *v = 0; else *v = 1;
}