diff options
Diffstat (limited to 'chips/lk201.c')
-rw-r--r-- | chips/lk201.c | 695 |
1 files changed, 695 insertions, 0 deletions
diff --git a/chips/lk201.c b/chips/lk201.c new file mode 100644 index 0000000..d11b1e9 --- /dev/null +++ b/chips/lk201.c @@ -0,0 +1,695 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * File: lk201.c + * Author: Alessandro Forin, Carnegie Mellon University + * Date: 9/90 + * + * Routines for the LK201 Keyboard Driver + */ + +#include <lk.h> +#if NLK > 0 +#include <bm.h> + +#include <mach_kdb.h> + +#include <mach/std_types.h> +#include <device/device_types.h> +#include <machine/machspl.h> /* spl definitions */ +#include <sys/ioctl.h> +#include <machine/machspl.h> +#include <chips/lk201.h> +#include <chips/serial_defs.h> +#include <chips/screen_defs.h> + + +/* + * Structures describing the keyboard status + */ +typedef struct { + unsigned short kbd_flags; + unsigned short kbd_previous; + char kbd_gen_shift; + char kbd_ctrl; + char kbd_lock; + char kbd_meta; + char kbd_shift; +} lk201_kbd_state_t; + +#define mapLOCKtoCNTRL 0x1 /* flags */ + +typedef struct { + char led_active; + char led_pattern; + char led_increasing; + char led_lights; + int led_interval; + int led_light_count; +} lk201_led_state_t; + + +/* + * Keyboard state + */ + +struct lk201_softc { + lk201_kbd_state_t kbd; + lk201_led_state_t led; + int sl_unit; +} lk201_softc_data[NLK]; + +typedef struct lk201_softc *lk201_softc_t; + +lk201_softc_t lk201_softc[NLK]; + +/* + * Forward decls + */ +io_return_t +lk201_translation( + int key, + char c, + int tabcode ); + +int +lk201_input( + int unit, + unsigned short data); + + +/* + * Autoconf (sort-of) + */ +lk201_probe( + int unit) +{ + lk201_softc[unit] = &lk201_softc_data[unit]; + return 1; +} + +void lk201_attach( + int unit, + int sl_unit) +{ + lk201_softc[unit]->sl_unit = sl_unit; + lk201_selftest(unit); +} + +/* + * Keyboard initialization + */ + +static unsigned char lk201_reset_string[] = { + LK_CMD_LEDS_ON, LK_PARAM_LED_MASK(0xf), /* show we are resetting */ + LK_CMD_SET_DEFAULTS, + LK_CMD_MODE(LK_MODE_RPT_DOWN,1), + LK_CMD_MODE(LK_MODE_RPT_DOWN,2), + LK_CMD_MODE(LK_MODE_RPT_DOWN,3), + LK_CMD_MODE(LK_MODE_RPT_DOWN,4), + LK_CMD_MODE(LK_MODE_DOWN_UP,5), + LK_CMD_MODE(LK_MODE_DOWN_UP,6), + LK_CMD_MODE(LK_MODE_RPT_DOWN,7), + LK_CMD_MODE(LK_MODE_RPT_DOWN,8), + LK_CMD_MODE(LK_MODE_RPT_DOWN,9), + LK_CMD_MODE(LK_MODE_RPT_DOWN,10), + LK_CMD_MODE(LK_MODE_RPT_DOWN,11), + LK_CMD_MODE(LK_MODE_RPT_DOWN,12), + LK_CMD_MODE(LK_MODE_DOWN,13), + LK_CMD_MODE(LK_MODE_RPT_DOWN,14), + LK_CMD_ENB_RPT, +/* LK_CMD_ENB_KEYCLK, LK_PARAM_VOLUME(4), */ + LK_CMD_DIS_KEYCLK, + LK_CMD_RESUME, + LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4), + LK_CMD_LEDS_OFF, LK_PARAM_LED_MASK(0xf) +}; + +void +lk201_reset( + int unit) +{ + register int i, sl; + register spl_t s; + lk201_softc_t lk; + + lk = lk201_softc[unit]; + sl = lk->sl_unit; + s = spltty(); + for (i = 0; i < sizeof(lk201_reset_string); i++) { + (*console_putc)(sl, + SCREEN_LINE_KEYBOARD, + lk201_reset_string[i]); + delay(100); + } + /* zero any state associated with previous keypresses */ + bzero(lk, sizeof(*lk)); + lk->sl_unit = sl; + splx(s); +} + +lk201_selftest( + int unit) +{ + int messg[4], sl; + spl_t s; + + sl = lk201_softc[unit]->sl_unit; + s = spltty(); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_REQ_ID); + delay(10000);/* arbitrary */ + messg[0] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE); + messg[1] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE); + splx(s); + + printf("( lk201 id %x.%x", messg[0], messg[1]); + + s = spltty(); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_POWER_UP); + + /* cannot do this, waiting too long might cause receiver overruns */ +/* delay(80000);/* spec says 70 msecs or less */ + + messg[0] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE); + messg[1] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE); + messg[2] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE); + messg[3] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE); + splx(s); + + printf(", self-test "); + if (messg[0] != 0x01 || messg[1] || messg[2] || messg[3]) + printf("bad [%x %x %x %x]", + messg[0], messg[1], messg[2], messg[3]); + else + printf("ok )"); + + lk201_reset(unit); +} + +/* + * Tinkerbell + */ +void +lk201_ring_bell( + int unit) +{ + spl_t s = spltty(); + (*console_putc)(lk201_softc[unit]->sl_unit, SCREEN_LINE_KEYBOARD, LK_CMD_BELL); + splx(s); +} + +/* + * Here is your LED toy, Bob + */ +void +lk201_lights( + int unit, + boolean_t on) +{ + unsigned int sl; + spl_t s; + + sl = lk201_softc[unit]->sl_unit; + s = spltty(); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(0xf)); + if (on < 16 && on > 0) { + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_ON); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(on)); + } + splx(s); +} + + +lk201_led( + int unit) +{ + lk201_led_state_t *leds = &lk201_softc[unit]->led; + unsigned int sl; + spl_t s; + + sl = lk201_softc[unit]->sl_unit; + if (leds->led_interval) { /* leds are on */ + if (leds->led_light_count <= 0) { /* hit this lights */ + + if (leds->led_lights <= 0) leds->led_lights= 1; /* sanity */ + if (leds->led_lights > 16) leds->led_lights = 16;/* sanity */ + leds->led_light_count = leds->led_interval; /* reset */ + s = spltty(); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(leds->led_lights)); + switch (leds->led_pattern) { + case LED_OFF: + leds->led_interval = 0; /* since you can now set */ + break; /* the interval even if off */ + case LED_COUNT: + leds->led_lights++; + if (leds->led_lights > 16) leds->led_lights = 1; + break; + case LED_ROTATE: + leds->led_lights <<= 1; + if (leds->led_lights > 8) leds->led_lights = 1; + break; + case LED_CYLON: + if (leds->led_increasing) { + leds->led_lights <<= 1; + if (leds->led_lights > 8) { + leds->led_lights >>= 2; + leds->led_increasing = 0; + } + } else { + leds->led_lights >>= 1; + if (leds->led_lights <= 0) { + leds->led_lights = 2; + leds->led_increasing = 1; + } + } + break; + } + (*console_putc)( sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_ON); + (*console_putc)( sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(leds->led_lights)); + splx(s); + } + leds->led_light_count--; + } else { + if (leds->led_lights) { + s = spltty(); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(0xf)); + leds->led_lights = 0; + splx(s); + } + leds->led_active = 0; +#if NBM > 0 + screen_enable_vretrace(unit, 0); /* interrupts off */ +#endif + } +} + + +/* + * Special user-visible ops + */ +io_return_t +lk201_set_status( + int unit, + dev_flavor_t flavor, + dev_status_t status, + natural_t status_count) +{ + lk201_led_state_t *leds = &lk201_softc[unit]->led; + lk201_kbd_state_t *kbd = &lk201_softc[unit]->kbd; + + switch( flavor ) { + case LK201_SEND_CMD:{ + register lk201_cmd_t *cmd = (lk201_cmd_t*)status; + unsigned int cnt, s, sl; + + if ((status_count < (sizeof(*cmd)/sizeof(int))) || + ((cnt = cmd->len) > 2)) + return D_INVALID_SIZE; + + if (cnt == 0) + cmd->command |= LK_PARAM; + else + cmd->params[cnt-1] |= LK_PARAM; + sl = lk201_softc[unit]->sl_unit; + s = spltty(); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, cmd->command); + if (cnt > 0) + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, cmd->params[0]); + if (cnt > 1) + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, cmd->params[1]); + splx(s); + return D_SUCCESS; + } + case LK201_LED_PATTERN:{ + register int ptn = * (int *) status; + if (ptn != LED_OFF && ptn != LED_COUNT && + ptn != LED_ROTATE && ptn != LED_CYLON ) { + return -1; + } else { + leds->led_pattern = ptn; + } + break; + } + case LK201_LED_INTERVAL:{ + register int lcnt = * (int *) status; + if (lcnt < 0) + lcnt = 1; + leds->led_interval = lcnt; + break; + } + case LK201_mapLOCKtoCNTRL:{ + boolean_t enable = * (boolean_t*) status; + if (enable) + kbd->kbd_flags |= mapLOCKtoCNTRL; + else + kbd->kbd_flags &= ~mapLOCKtoCNTRL; + return D_SUCCESS; + } + case LK201_REMAP_KEY:{ + register KeyMap *k = (KeyMap *) status; + int mode; + + if (status_count < (sizeof(KeyMap)/sizeof(int))) + return D_INVALID_SIZE; + + mode = k->shifted ? 1 : 0; + if (k->meta) mode += 2; + return lk201_translation( k->in_keyval, + k->out_keyval, + mode ); + } + default: + return D_INVALID_OPERATION; + } + leds->led_lights = 1; + leds->led_active = 1; +#if NBM > 0 + screen_enable_vretrace(unit, 1); /* interrupts on */ +#endif + return D_SUCCESS; +} + +/* + * Keycode translation tables + * + * NOTE: these tables have been compressed a little bit + * because the lk201 cannot generate very small codes. + */ + +unsigned char lk201_xlate_key[] = { + /* 86 */ 0 ,0 + /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0 + /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2' + /* 152 */ ,'3','4','5','6',',','7','8','9' + /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 184 */ ,0 ,0 ,0 ,0 ,0x7f,'\r','\t','`' + /* 192 */ ,'1' ,'q' ,'a' ,'z' ,0 ,'2' ,'w' ,'s' + /* 200 */ ,'x' ,'<' ,0 ,'3' ,'e' ,'d' ,'c' ,0 + /* 208 */ ,'4' ,'r' ,'f' ,'v' ,' ' ,0 ,'5' ,'t' + /* 216 */ ,'g' ,'b' ,0 ,'6' ,'y' ,'h' ,'n' ,0 + /* 224 */ ,'7' ,'u' ,'j' ,'m' ,0 ,'8' ,'i' ,'k' + /* 232 */ ,',' ,0 ,'9' ,'o' ,'l' ,'.' ,0 ,'0' + /* 240 */ ,'p' ,0 ,';' ,'/' ,0 ,'=' ,']' ,'\\' + /* 248 */ ,0 ,'-' ,'[' ,'\'' ,0 ,0 ,0 ,0 +}; + +unsigned char lk201_xlate_shifted[] = { + /* 86 */ 0 ,0 + /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0 + /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2' + /* 152 */ ,'3','4','5','6',',','7','8','9' + /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 184 */ ,0 ,0 ,0 ,0 ,0x7f ,'\r' ,'\t' ,'~' + /* 192 */ ,'!' ,'Q' ,'A' ,'Z' ,0 ,'@' ,'W' ,'S' + /* 200 */ ,'X' ,'>' ,0 ,'#' ,'E' ,'D' ,'C' ,0 + /* 208 */ ,'$' ,'R' ,'F' ,'V' ,' ' ,0 ,'%' ,'T' + /* 216 */ ,'G' ,'B' ,0 ,'^' ,'Y' ,'H' ,'N' ,0 + /* 224 */ ,'&' ,'U' ,'J' ,'M' ,0 ,'*' ,'I' ,'K' + /* 232 */ ,'<' ,0 ,'(' ,'O' ,'L' ,'>' ,0 ,')' + /* 240 */ ,'P' ,0 ,':' ,'?' ,0 ,'+' ,'}' ,'|' + /* 248 */ ,0 ,'_' ,'{' ,'"' ,0 ,0 ,0 ,0 +}; + +unsigned char lk201_xlate_meta[] = { + /* 86 */ 0 ,0 + /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0 + /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2' + /* 152 */ ,'3','4','5','6',',','7','8','9' + /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 184 */ ,0 ,0 ,0 ,0 ,0x7f ,'\r' ,'\t' ,'~' + /* 192 */ ,'!' ,'Q' ,'A' ,'Z' ,0 ,'@' ,'W' ,'S' + /* 200 */ ,'X' ,'>' ,0 ,'#' ,'E' ,'D' ,'C' ,0 + /* 208 */ ,'$' ,'R' ,'F' ,'V' ,' ' ,0 ,'%' ,'T' + /* 216 */ ,'G' ,'B' ,0 ,'^' ,'Y' ,'H' ,'N' ,0 + /* 224 */ ,'&' ,'U' ,'J' ,'M' ,0 ,'*' ,'I' ,'K' + /* 232 */ ,'<' ,0 ,'(' ,'O' ,'L' ,'>' ,0 ,')' + /* 240 */ ,'P' ,0 ,':' ,'?' ,0 ,'+' ,'}' ,'|' + /* 248 */ ,0 ,'_' ,'{' ,'"' ,0 ,0 ,0 ,0 +}; + +unsigned char lk201_xlate_shifted_meta[] = { + /* 86 */ 0 ,0 + /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0 + /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2' + /* 152 */ ,'3','4','5','6',',','7','8','9' + /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 + /* 184 */ ,0 ,0 ,0 ,0 ,0x7f ,'\r' ,'\t' ,'~' + /* 192 */ ,'!' ,'Q' ,'A' ,'Z' ,0 ,'@' ,'W' ,'S' + /* 200 */ ,'X' ,'>' ,0 ,'#' ,'E' ,'D' ,'C' ,0 + /* 208 */ ,'$' ,'R' ,'F' ,'V' ,' ' ,0 ,'%' ,'T' + /* 216 */ ,'G' ,'B' ,0 ,'^' ,'Y' ,'H' ,'N' ,0 + /* 224 */ ,'&' ,'U' ,'J' ,'M' ,0 ,'*' ,'I' ,'K' + /* 232 */ ,'<' ,0 ,'(' ,'O' ,'L' ,'>' ,0 ,')' + /* 240 */ ,'P' ,0 ,':' ,'?' ,0 ,'+' ,'}' ,'|' + /* 248 */ ,0 ,'_' ,'{' ,'"' ,0 ,0 ,0 ,0 +}; + + +io_return_t +lk201_translation( + int key, + char c, + int tabcode ) +{ + unsigned char *table; + + if ((key &= 0xff) < LK_MINCODE) + return D_INVALID_OPERATION; + + switch (tabcode) { + case 3: + table = lk201_xlate_shifted_meta; + break; + case 2: + table = lk201_xlate_meta; + break; + case 1: + table = lk201_xlate_shifted; + break; + case 0: + default: + table = lk201_xlate_key; + break; + } + table[key - LK_MINCODE] = c; + return D_SUCCESS; +} + +/* + * Input character processing + */ + +lk201_rint( + int unit, + unsigned short data, + boolean_t handle_shift, + boolean_t from_kernel) +{ + int c; + lk201_kbd_state_t *kbd = &lk201_softc[unit]->kbd; + + /* + * Keyboard touched, clean char to 8 bits. + */ +#if NBM > 0 + ssaver_bump(unit); +#endif + + data &= 0xff; + + /* Translate keycode into ASCII */ + if ((c = lk201_input(unit, data)) == -1) + return -1; + +#if NBM > 0 + /* + * Notify X, unless we are called from inside kernel + */ + if (!from_kernel && + screen_keypress_event(unit, DEV_KEYBD, data, EVT_BUTTON_RAW)) + return -1; +#endif + + /* Handle shifting if need to */ + if (kbd->kbd_gen_shift) + return (handle_shift) ? cngetc() : -1; + + return c; +} + +/* + * Routine to grock a character from LK201 + */ +#if MACH_KDB +int lk201_allow_kdb = 1; +#endif + +int lk201_debug = 0; + +lk201_input( + int unit, + unsigned short data) +{ + int c, sl; + lk201_kbd_state_t *kbd = &lk201_softc[unit]->kbd; + + kbd->kbd_gen_shift = 0; + +#if MACH_KDB + if (lk201_allow_kdb && (data == LK_DO)) { + kdb_kintr(); + return -2; + } +#endif + + /* + * Sanity checks + */ + + if (data == LK_INPUT_ERR || data == LK_OUTPUT_ERR) { + printf(" Keyboard error, code = %x\n",data); + return -1; + } + if (data < LK_MINCODE) + return -1; + + /* + * Check special keys: shifts, ups, .. + */ + + if (data == LK_LOCK && (kbd->kbd_flags&mapLOCKtoCNTRL)) + data = LK_CNTRL; + + switch (data) { + case LK_LOCK: + kbd->kbd_lock ^= 1; + kbd->kbd_gen_shift = 1; + sl = lk201_softc[unit]->sl_unit; + /* called from interrupt, no need for spl */ + if (kbd->kbd_lock) + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_ON); + else + (*console_putc)(sl,SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF); + (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(0x4)); + return 0; + + case LK_ALT: + case LK_L_ALT: + case LK_R_ALT: + case LK_R_COMPOSE: + kbd->kbd_meta ^= 1; + kbd->kbd_gen_shift = 1; + return 0; + + case LK_SHIFT: + case LK_R_SHIFT: + kbd->kbd_shift ^= 1; + kbd->kbd_gen_shift = 1; + return 0; + + case LK_CNTRL: + kbd->kbd_ctrl ^= 1; + kbd->kbd_gen_shift = 1; + return 0; + + case LK_ALLUP: + kbd->kbd_ctrl = 0; + kbd->kbd_shift = 0; + kbd->kbd_meta = 0; + kbd->kbd_gen_shift = 1; + return 0; + + case LK_REPEAT: + c = kbd->kbd_previous; + break; + + default: + + /* + * Do the key translation to ASCII + */ + if (kbd->kbd_ctrl || kbd->kbd_lock || kbd->kbd_shift) { + c = ((kbd->kbd_meta) ? + lk201_xlate_shifted_meta : lk201_xlate_shifted) + [data - LK_MINCODE]; + if (kbd->kbd_ctrl) + c &= 0x1f; + } else + c = ((kbd->kbd_meta) ? + lk201_xlate_meta : lk201_xlate_key) + [data-LK_MINCODE]; + break; + + } + + kbd->kbd_previous = c; + + /* + * DEBUG code DEBUG + */ + if (lk201_debug && (c == 0)) { + printf("lk201: [%x]\n", data); + } + + return c; +} + +#endif /* NLK > 0 */ |