From: James S. <jsi...@us...> - 2002-10-30 18:17:24
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/char In directory usw-pr-cvs1:/tmp/cvs-serv17869 Modified Files: keyboard.c Log Message: Synced up. Index: keyboard.c =================================================================== RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/char/keyboard.c,v retrieving revision 1.77 retrieving revision 1.78 diff -u -d -r1.77 -r1.78 --- keyboard.c 2 Aug 2002 14:58:50 -0000 1.77 +++ keyboard.c 30 Oct 2002 18:17:20 -0000 1.78 @@ -1,39 +1,27 @@ /* - * $Id$ + * linux/drivers/char/keyboard.c * - * Copyright (c) 2000 Vojtech Pavlik + * Written for linux by Johan Myreen as a translation from + * the assembly version by Linus (with diacriticals added) * - * Based on the work of: - * Linus Torvalds Johan Myreen - * Christoph Niemann Risto Kankkunen - * Andries Brouwer Martin Mares - * Hamish MacDonald Geert Uytterhoeven + * Some additional features added by Christoph Niemann (ChN), March 1993 * - * Sponsored by SuSE - */ - -/* - * Keyboard input for VT's - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Loadable keymaps by Risto Kankkunen, May 1993 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Diacriticals redone & other small changes, ae...@cw..., June 1993 + * Added decr/incr_console, dynamic keymaps, Unicode support, + * dynamic function/string keys, led setting, Sept 1994 + * `Sticky' modifier keys, 951006. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * 11-11-96: SAK should now work in the raw mode (Martin Mares) + * + * Modified to provide 'generic' keyboard support by Hamish Macdonald + * Merge with the m68k keyboard driver and split-off of the PC low-level + * parts by Geert Uytterhoeven, May 1997 * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vo...@uc...>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic + * 27-05-97: Added support for the Magic SysRq Key (Martin Mares) + * 30-07-98: Dead keys redone, ae...@cw.... + * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik) */ #include <linux/config.h> @@ -47,23 +35,16 @@ #include <linux/init.h> #include <linux/slab.h> -#include <linux/kbd_kern.h> #include <linux/kbd_diacr.h> #include <linux/vt_kern.h> -#include <linux/consolemap.h> #include <linux/sysrq.h> -#include <linux/pm.h> #include <linux/input.h> static void kbd_disconnect(struct input_handle *handle); extern void ctrl_alt_del(void); - -/* - * Exported functions/variables - */ - -struct pt_regs *kbd_pt_regs; void compute_shiftstate(void); +struct pt_regs *kbd_pt_regs; +EXPORT_SYMBOL(kbd_pt_regs); /* * Handler Tables. @@ -81,48 +62,32 @@ static k_handler_fn *k_handler[16] = { K_HANDLERS }; #define FN_HANDLERS\ - fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\ - fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\ - fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\ - fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\ - fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num + fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\ + fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\ + fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\ + fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\ + fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num typedef void (fn_handler_fn)(struct vc_data *vc); static fn_handler_fn FN_HANDLERS; static fn_handler_fn *fn_handler[] = { FN_HANDLERS }; /* - * Variables/functions exported for vt_ioctl.c + * Variables exported for vt_ioctl.c */ /* maximum values each key_handler can handle */ const int max_vals[] = { 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1, NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, - 255, 2*NR_LOCK - 1, 255 + 255, NR_LOCK - 1, 255 }; -const int NR_TYPES = ARRAY_SIZE(max_vals); +const int NR_TYPES = ARRAY_SIZE(max_vals); int spawnpid, spawnsig; -int getkeycode(struct input_handle *handle, unsigned int scancode) -{ - unsigned char *keycode = handle->dev->keycode; - - return keycode[scancode & handle->dev->keycodemax]; -} - -int setkeycode(struct input_handle *handle, unsigned int scancode, unsigned int keycode) -{ - unsigned char *key_code = handle->dev->keycode; - - if (keycode <= handle->dev->keycodemax) - key_code[scancode & handle->dev->keycodemax] = keycode; - return 0; -} - /* - * Variables/function exported for vt.c + * Variables exported for vt.c */ int shift_state = 0; @@ -131,17 +96,14 @@ */ static struct input_handler kbd_handler; -static unsigned long key_down[256/BITS_PER_LONG]; /* keyboard key bitmap */ -static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ +static unsigned long key_down[256/BITS_PER_LONG]; /* keyboard key bitmap */ +static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ static int dead_key_next; -static int npadch = -1; /* -1 or number assembled on pad */ +static int npadch = -1; /* -1 or number assembled on pad */ static unsigned char diacr; -static char rep; /* flag telling character repeat */ -pm_callback pm_kbd_request_override = NULL; -typedef void (pm_kbd_func) (void); -static struct pm_dev *pm_kbd; +static char rep; /* flag telling character repeat */ -static unsigned char ledstate = 0xff; /* undefined */ +static unsigned char ledstate = 0xff; /* undefined */ static unsigned char ledioctl; static struct ledptr { @@ -150,6 +112,128 @@ unsigned char valid:1; } ledptrs[3]; +/* Simple translation table for the SysRq keys */ + +#ifdef CONFIG_MAGIC_SYSRQ +unsigned char kbd_sysrq_xlate[128] = + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/"; /* 0x60 - 0x6f */ +static int sysrq_down; +#endif +static int sysrq_alt; + +/* + * Translation of scancodes to keycodes. We set them on only the first attached + * keyboard - for per-keyboard setting, /dev/input/event is more useful. + */ +int getkeycode(struct input_handle *handle, unsigned int scancode) +{ + struct input_dev *dev = handle->dev; + + if (!dev) + return -ENODEV; + + if (!dev->keycodesize || (scancode < 0 || scancode >= dev->keycodemax)) + return -EINVAL; + + return INPUT_KEYCODE(dev, scancode); +} + +int setkeycode(struct input_handle *handle, unsigned int scancode, unsigned int keycode) +{ + struct input_dev *dev = handle->dev; + int i, oldkey; + + if (!dev) + return -ENODEV; + + if (!dev->keycodesize || (scancode < 0 || scancode >= dev->keycodemax)) + return -EINVAL; + + oldkey = INPUT_KEYCODE(dev, scancode); + INPUT_KEYCODE(dev, scancode) = keycode; + + for (i = 0; i < dev->keycodemax; i++) + if (INPUT_KEYCODE(dev, scancode) == oldkey) + break; + if (i == dev->keycodemax) + clear_bit(oldkey, dev->keybit); + set_bit(keycode, dev->keybit); + return 0; +} + +/* + * Making beeps and bells. + */ +void kd_nosound(unsigned long private) +{ + struct input_handle *handle = (struct input_handle *) private; + + if (test_bit(EV_SND, handle->dev->evbit)) { + if (test_bit(SND_TONE, handle->dev->sndbit)) + input_event(handle->dev, EV_SND, SND_TONE, 0); + if (test_bit(SND_BELL, handle->dev->sndbit)) + input_event(handle->dev, EV_SND, SND_BELL, 0); + } +} + +void kd_mksound(struct input_handle *handle, unsigned int hz, unsigned int ticks) +{ +/* + struct vt_struct *vt = vt_cons; + + if (vt) { + del_timer(&vt->beep); + + if (hz) { + if (test_bit(EV_SND, handle->dev->evbit)) { + if (test_bit(SND_TONE, handle->dev->sndbit)) + input_event(handle->dev, EV_SND, SND_TONE, hz); + if (test_bit(SND_BELL, handle->dev->sndbit)) + input_event(handle->dev, EV_SND, SND_BELL, 1); + } + if (ticks) + mod_timer(&vt->beep, jiffies + ticks); + } else + kd_nosound((long) handle); + } +*/ +} + +/* + * Setting the keyboard rate. + */ +static inline unsigned int ms_to_jiffies(unsigned int ms) { + unsigned int j; + + j = (ms * HZ + 500) / 1000; + return (j > 0) ? j : 1; +} + +int kbd_rate(struct input_handle *handle, struct kbd_repeat *rep) +{ + struct input_dev *dev = handle->dev; + unsigned int d = 0; + unsigned int p = 0; + + if (test_bit(EV_REP, dev->evbit)) { + if (rep->delay > 0) + dev->rep[REP_DELAY] = ms_to_jiffies(rep->delay); + if (rep->period > 0) + dev->rep[REP_PERIOD] = ms_to_jiffies(rep->period); + d = dev->rep[REP_DELAY] * 1000 / HZ; + p = dev->rep[REP_PERIOD] * 1000 / HZ; + } + rep->delay = d; + rep->period = p; + return 0; +} + /* * Helper Functions. */ @@ -159,11 +243,11 @@ if (tty) { tty_insert_flip_char(tty, ch, 0); - tty_schedule_flip(tty); + schedule_work(&tty->flip.work); } } -static void puts_queue(struct vc_data *vc, char *cp) +void puts_queue(struct vc_data *vc, char *cp) { struct tty_struct *tty = vc->vc_tty; @@ -174,7 +258,7 @@ tty_insert_flip_char(tty, *cp, 0); cp++; } - tty_schedule_flip(tty); + schedule_work(&tty->flip.work); } static void applkey(struct vc_data *vc, int key, char mode) @@ -224,50 +308,50 @@ * in utf-8 already. UTF-8 is defined for words of up to 31 bits, * but we need only 16 bits here */ -void to_utf8(struct vc_data *vc, ushort c) +void to_utf8(struct vc_data *vc, ushort c) { if (c < 0x80) /* 0******* */ put_queue(vc, c); - else if (c < 0x800) { + else if (c < 0x800) { /* 110***** 10****** */ - put_queue(vc, 0xc0 | (c >> 6)); + put_queue(vc, 0xc0 | (c >> 6)); put_queue(vc, 0x80 | (c & 0x3f)); - } else { + } else { /* 1110**** 10****** 10****** */ put_queue(vc, 0xe0 | (c >> 12)); put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); put_queue(vc, 0x80 | (c & 0x3f)); - } + } } void put_unicode(struct vc_data *vc, u16 uc) { - if (vc->kbd_table.kbdmode == VC_UNICODE) - to_utf8(vc, uc); - else if ((uc & ~0x9f) == 0 || uc == 127) - /* Don't translate control chars */ - put_queue(vc, uc); - else { - unsigned char c; - c = inverse_translate(vc->display_fg->fg_console->vc_translate, uc); - if (c) put_queue(vc, c); - } + if (vc->kbd_table.kbdmode == VC_UNICODE) + to_utf8(vc, uc); + else if ((uc & ~0x9f) == 0 || uc == 127) + /* Don't translate control chars */ + put_queue(vc, uc); + else { + unsigned char c; + c = inverse_translate(vc->display_fg->fg_console->vc_translate, uc); + if (c) put_queue(vc, c); + } } static void put_8bit(struct vc_data *vc, u8 c) { - if (vc->kbd_table.kbdmode != VC_UNICODE || - c < 32 || c == 127) /* Don't translate control chars */ - put_queue(vc, c); - else - to_utf8(vc, get_acm(vc->display_fg->fg_console->vc_translate)[c]); + /* Don't translate control chars */ + if (vc->kbd_table.kbdmode != VC_UNICODE || c < 32 || c == 127) + put_queue(vc, c); + else + to_utf8(vc, get_acm(vc->display_fg->fg_console->vc_translate)[c]); } -/* - * called after returning from RAW mode or when changing consoles - - * recompute shift_down[] and shift_state from key_down[] - * maybe called when keymap is undefined, so that shiftkey release is seen +/* + * Called after returning from RAW mode or when changing consoles - recompute + * shift_down[] and shift_state from key_down[] maybe called when keymap is + * undefined, so that shiftkey release is seen */ void compute_shiftstate(void) { @@ -281,7 +365,7 @@ if (!key_down[i]) continue; - k = i*BITS_PER_LONG; + k = i * BITS_PER_LONG; for (j = 0; j < BITS_PER_LONG; j++, k++) { @@ -338,7 +422,7 @@ diacr = 0; } put_queue(vc, 13); - if (get_kbd_mode(&vc->kbd_table, VC_CRLF)) + if (get_kbd_mode(vc->kbd_table, VC_CRLF)) put_queue(vc, 10); } @@ -346,14 +430,14 @@ { if (rep) return; - chg_kbd_led(&vc->kbd_table, VC_CAPSLOCK); + chg_kbd_led(vc->kbd_table, VC_CAPSLOCK); } static void fn_caps_on(struct vc_data *vc) { if (rep) return; - set_kbd_led(&vc->kbd_table, VC_CAPSLOCK); + set_kbd_led(vc->kbd_table, VC_CAPSLOCK); } static void fn_show_ptregs(struct vc_data *vc) @@ -382,7 +466,7 @@ static void fn_num(struct vc_data *vc) { - if (get_kbd_mode(&vc->kbd_table, VC_APPLIC)) + if (get_kbd_mode(vc->kbd_table, VC_APPLIC)) applkey(vc, 'P', 1); else fn_bare_num(vc); @@ -397,40 +481,44 @@ static void fn_bare_num(struct vc_data *vc) { if (!rep) - chg_kbd_led(&vc->kbd_table, VC_NUMLOCK); + chg_kbd_led(vc->kbd_table, VC_NUMLOCK); } static void fn_lastcons(struct vc_data *vc) { - set_console(vc->display_fg->last_console); + set_console(vc->display_fg->last_console); } static void fn_dec_console(struct vc_data *vc) { - int i, j = vc->display_fg->fg_console->vc_num; - - for (i = j-1; i != j; i--) { - if (i < vc->display_fg->first_vc) - i = vc->display_fg->first_vc + MAX_NR_USER_CONSOLES-1; - vc = find_vc(i); - if (vc) + struct vt_struct *vt = vc->display_fg; + int i, j = vt->fg_console->vc_num - vt->first_vc; + struct vc_data *tmp = NULL; + + for (i = j-1; i != j; i--) { + if (i == -1) + i = MAX_NR_USER_CONSOLES-1; + tmp = vt->vc_cons[i]; + if (tmp) break; - } - set_console(vc); + } + set_console(tmp); } static void fn_inc_console(struct vc_data *vc) { - int i, j = vc->display_fg->fg_console->vc_num; + struct vt_struct *vt = vc->display_fg; + int i, j = vt->fg_console->vc_num - vt->first_vc; + struct vc_data *tmp = NULL; - for (i = j+1; i != j; i++) { - if (i == vc->display_fg->first_vc + MAX_NR_USER_CONSOLES) - i = vc->display_fg->first_vc; - vc = find_vc(i); - if (vc) - break; - } - set_console(vc); + for (i = j+1; i != j; i++) { + if (i == MAX_NR_USER_CONSOLES) + i = 0; + tmp = vt->vc_cons[i]; + if (tmp) + break; + } + set_console(tmp); } static void fn_send_intr(struct vc_data *vc) @@ -440,27 +528,29 @@ if (!tty) return; tty_insert_flip_char(tty, 0, TTY_BREAK); - tty_schedule_flip(tty); + schedule_work(&tty->flip.work); } static void fn_scroll_forw(struct vc_data *vc) { + //scroll_down(vc, 0); if (vc->vc_visible_origin < vc->vc_origin) { vc->vc_visible_origin =+ vc->vc_screensize; - do_update_region(vc, vc->vc_visible_origin, vc->vc_screensize); -// scroll_up(vc, vc->vc_rows/2); + do_update_region(vc, vc->vc_visible_origin, vc->vc_screensize); +// scroll_down(vc, vc->vc_rows/2); } } static void fn_scroll_back(struct vc_data *vc) { + //scroll_up(vc, 0); unsigned short *p = (unsigned short *) vc->vc_visible_origin - vc->vc_screensize; unsigned long q = (unsigned long) p; if (q >= ((unsigned long) vc->vc_screenbuf)) { vc->vc_visible_origin = q; - do_update_region(vc, vc->vc_visible_origin, vc->vc_screensize); -// scroll_down(vc, vc->vc_rows/2); + do_update_region(vc, vc->vc_visible_origin, vc->vc_screensize); +// scroll_up(vc, vc->vc_rows/2); } } @@ -476,35 +566,29 @@ static void fn_boot_it(struct vc_data *vc) { - struct input_handle *handle; - - if (vc && (vc->display_fg == admin_vt)) { - /* Stop other key events from coming */ - for (handle = kbd_handler.handle; handle; - handle = handle->hnext) { - kbd_disconnect(handle); - } - ctrl_alt_del(); - } + ctrl_alt_del(); } static void fn_compose(struct vc_data *vc) { - /* ???? */ dead_key_next = 1; } static void fn_spawn_con(struct vc_data *vc) { - if (spawnpid) - if (kill_proc(spawnpid, spawnsig, 1)) - spawnpid = 0; + if (spawnpid) + if(kill_proc(spawnpid, spawnsig, 1)) + spawnpid = 0; } static void fn_SAK(struct vc_data *vc) { struct tty_struct *tty = vc->vc_tty; + /* + * SAK should also work in all raw modes and reset + * them properly. + */ if (tty) do_SAK(tty); reset_vc(vc); @@ -583,7 +667,7 @@ struct vc_data *tmp = find_vc(value + vc->display_fg->first_vc); if (up_flag || !tmp) - return; + return; set_console(tmp); } @@ -604,7 +688,7 @@ if (up_flag) return; - applkey(vc, cur_chars[value], get_kbd_mode(&vc->kbd_table, VC_CKMODE)); + applkey(vc, cur_chars[value], get_kbd_mode(vc->kbd_table, VC_CKMODE)); } static void k_pad(struct vc_data *vc, unsigned char value, char up_flag) @@ -616,12 +700,12 @@ return; /* no action, if this is a key release */ /* kludge... shift forces cursor/number keys */ - if (get_kbd_mode(&vc->kbd_table, VC_APPLIC) && !shift_down[KG_SHIFT]) { + if (get_kbd_mode(vc->kbd_table, VC_APPLIC) && !shift_down[KG_SHIFT]) { applkey(vc, app_map[value], 1); return; } - if (!get_kbd_led(&vc->kbd_table, VC_NUMLOCK)) + if (!get_kbd_led(vc->kbd_table, VC_NUMLOCK)) switch (value) { case KVAL(K_PCOMMA): case KVAL(K_PDOT): @@ -655,13 +739,12 @@ k_fn(vc, KVAL(K_PGUP), 0); return; case KVAL(K_P5): - applkey(vc, 'G', get_kbd_mode(&vc->kbd_table, - VC_APPLIC)); + applkey(vc, 'G', get_kbd_mode(vc->kbd_table, VC_APPLIC)); return; } put_8bit(vc, pad_chars[value]); - if (value == KVAL(K_PENTER) && get_kbd_mode(&vc->kbd_table, VC_CRLF)) + if (value == KVAL(K_PENTER) && get_kbd_mode(vc->kbd_table, VC_CRLF)) put_queue(vc, 10); } @@ -678,7 +761,7 @@ if (value == KVAL(K_CAPSSHIFT)) { value = KVAL(K_SHIFT); if (!up_flag) - clr_kbd_led(&vc->kbd_table, VC_CAPSLOCK); + clr_kbd_led(vc->kbd_table, VC_CAPSLOCK); } if (up_flag) { @@ -711,7 +794,7 @@ if (up_flag) return; - if (get_kbd_mode(&vc->kbd_table, VC_META)) { + if (get_kbd_mode(vc->kbd_table, VC_META)) { put_queue(vc, '\033'); put_queue(vc, value); } else @@ -744,11 +827,12 @@ { if (up_flag || rep) return; +/* if (value >= NR_LOCK) { - /* + * * Change the lock state and - * set the CapsLock LED to the new state - */ + * set the CapsLock LED to the new state + * unsigned char mask; mask = 1 << (value -= NR_LOCK); @@ -757,9 +841,8 @@ else clr_kbd_led(&vc->kbd_table, VC_CAPSLOCK); } else { - /* Just change the lock state */ - chg_kbd_lock(&vc->kbd_table, value); - } + * Just change the lock state */ + chg_kbd_lock(vc->kbd_table, value); } static void k_slock(struct vc_data *vc, unsigned char value, char up_flag) @@ -767,11 +850,11 @@ k_shift(vc, value, up_flag); if (up_flag || rep) return; - chg_kbd_slock(&vc->kbd_table, value); + chg_kbd_slock(vc->kbd_table, value); /* try to make Alt, oops, AltGr and such work */ if (!key_maps[vc->kbd_table.lockstate ^ vc->kbd_table.slockstate]) { vc->kbd_table.slockstate = 0; - chg_kbd_slock(&vc->kbd_table, value); + chg_kbd_slock(vc->kbd_table, value); } } @@ -807,18 +890,17 @@ kbd->ledmode = LED_SHOW_FLAGS; } -static inline unsigned char getleds(struct vt_struct *vt) +static inline unsigned char getleds(struct vc_data *vc) { - struct kbd_struct *kbd = &vt->fg_console->kbd_table; unsigned char leds; int i; - if (kbd->ledmode == LED_SHOW_IOCTL) + if (vc->kbd_table.ledmode == LED_SHOW_IOCTL) return ledioctl; - leds = kbd->ledflagstate; + leds = vc->kbd_table.ledflagstate; - if (kbd->ledmode == LED_SHOW_MEM) { + if (vc->kbd_table.ledmode == LED_SHOW_MEM) { for (i = 0; i < 3; i++) if (ledptrs[i].valid) { if (*ledptrs[i].addr & ledptrs[i].mask) @@ -846,50 +928,57 @@ static void kbd_bh(unsigned long dummy) { - struct input_handle *handle; + struct list_head * node; unsigned char leds; - for (handle = kbd_handler.handle; handle; handle = handle->hnext) { - if (handle->private) { - leds = getleds(handle->private); + list_for_each(node, &kbd_handler.h_list) { + struct input_handle *handle = to_handle_h(node); + struct vt_struct *vt = vt_cons; + + if (vt) { + leds = getleds(vt->fg_console); + if (leds != ledstate) { - ledstate = leds; input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); + + ledstate = leds; } - } + } } } DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); -#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) - -static int x86_sysrq_alt = 0; +#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) -static unsigned short x86_keycodes[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +static unsigned short x86_keycodes[256] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 43, 85, 86, 87, 88,115,119,120,121,375,123, 90, 284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339, - 367,294,293,286,350, 92,334,512,116,377,109,111,259,347,348,349, - 360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355, - 103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361, - 291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114, - 118,117,125,374,379,125,260,261,262,263,264,265,266,267,268,269, - 271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307, - 308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330, - 332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 -}; + 367,288,302,304,350, 92,334,512,116,377,109,111,373,347,348,349, + 360, 93, 94, 95, 98,376,100,101,321,316,354,286,289,102,351,355, + 103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361, + 291,108,381,281,290,272,292,305,280, 99,112,257,258,359,270,114, + 118,117,125,374,379,115,112,125,121,123,264,265,266,267,268,269, + 271,273,276,277,278,282,283,295,296,297,299,300,301,293,303,307, + 308,310,313,314,315,317,318,319,320,357,322,323,324,325,326,330, + 332,340,365,342,343,344,345,346,356,113,341,368,369,370,371,372 }; #ifdef CONFIG_MAC_EMUMOUSEBTN extern int mac_hid_mouse_emulate_buttons(int, int, int); #endif /* CONFIG_MAC_EMUMOUSEBTN */ +#if defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) +static int sparc_l1_a_state = 0; +extern void sun_do_break(void); +#endif + static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag) { @@ -908,7 +997,7 @@ return 0; } - if (keycode == KEY_SYSRQ && x86_sysrq_alt) { + if (keycode == KEY_SYSRQ && sysrq_alt) { put_queue(vc, 0x54 | up_flag); return 0; } @@ -923,9 +1012,6 @@ put_queue(vc, 0x37 | up_flag); } - if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT) - x86_sysrq_alt = !up_flag; - return 0; } @@ -951,8 +1037,6 @@ struct tty_struct *tty; int shift_final; - pm_access(pm_kbd); - if (down != 2) add_keyboard_randomness((keycode << 1) ^ down); @@ -963,14 +1047,36 @@ tty->driver_data = vc; } - /* If the console is blanked unblank it */ - vt->want_vc = vc; - schedule_task(&vt->vt_tq); + if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT) + sysrq_alt = down; +#if defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) + if (keycode == KEY_STOP) + sparc_l1_a_state = down; +#endif + + rep = (down == 2); if ((raw_mode = (vc->kbd_table.kbdmode == VC_RAW))) if (emulate_raw(vc, keycode, !down << 7)) printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); +#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ + if (keycode == KEY_SYSRQ && !rep) { + sysrq_down = sysrq_alt && down; + return; + } + if (sysrq_down && down && !rep) { + handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, tty); + return; + } +#endif +#if defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) + if (keycode == KEY_A && sparc_l1_a_state) { + sparc_l1_a_state = 0; + sun_do_break(); + } +#endif + if (vc->kbd_table.kbdmode == VC_MEDIUMRAW) { /* * This is extended medium raw mode, with keys above 127 @@ -991,9 +1097,12 @@ raw_mode = 1; } - rep = (down == 2); + if (down) + set_bit(keycode, key_down); + else + clear_bit(keycode, key_down); - if (rep && (!get_kbd_mode(&vc->kbd_table, VC_REPEAT) || (tty && + if (rep && (!get_kbd_mode(vc->kbd_table, VC_REPEAT) || (tty && (!L_ECHO(tty) && tty->driver.chars_in_buffer(tty))))) { /* * Don't repeat a key if the input buffers are not empty and the @@ -1027,13 +1136,15 @@ if (type == KT_LETTER) { type = KT_LATIN; - if (get_kbd_led(&vc->kbd_table, VC_CAPSLOCK)) { + if (get_kbd_led(vc->kbd_table, VC_CAPSLOCK)) { key_map = key_maps[shift_final ^ (1 << KG_SHIFT)]; if (key_map) keysym = key_map[keycode]; } } - (*k_handler[type])(vc, keysym & 0xff, !(down << 7)); + + (*k_handler[type])(vc, keysym & 0xff, !down); + if (type != KT_SLOCK) vc->kbd_table.slockstate = 0; } @@ -1047,6 +1158,7 @@ return; kbd_keycode(vt, keycode, down); tasklet_schedule(&keyboard_tasklet); + schedule_work(&vt->vt_work); } static char kbd_name[] = "kbd"; @@ -1062,9 +1174,8 @@ struct input_dev *dev, struct input_device_id *id) { - struct input_handle *handle; struct vt_struct *vt = vt_cons; - struct vc_data *vc; + struct input_handle *handle; int i; for (i = KEY_RESERVED; i < BTN_MISC; i++) @@ -1077,6 +1188,14 @@ return NULL; memset(handle, 0, sizeof(struct input_handle)); + /* + * If we have more keyboards than VTs we still register the handler. + * It is possible someone might add a graphics card thus needing the + * keyboard later + */ + handle->dev = dev; + handle->handler = handler; + handle->name = kbd_name; if (!first_time) { first_time = 1; @@ -1084,26 +1203,19 @@ } while (vt) { - if (!vt->keyboard) { - vt->keyboard = handle; + if (!vt->keyboard) { + vt->keyboard = handle; handle->private = vt; vt_map_input(vt); /* enable receieving key events for each VC */ for (i = 0; i < MAX_NR_USER_CONSOLES; i++) { vc = find_vc(vt->first_vc + i); - if (vc) vc->vc_kam = 1; + if (vc) vc->vc_kam = 1; } break; - } else + } else vt = vt->next; - } - - /* If we have more keyboards than VTs we still register the handler. - * It is possible someone might add a graphics card thus needing the - * keyboard later */ - handle->dev = dev; - handle->handler = handler; - handle->name = kbd_name; /* FIXME, should be vt0, vt1, etc, or similar */ + } input_open_device(handle); return handle; } @@ -1112,18 +1224,17 @@ { struct vt_struct *vt = handle->private; struct vc_data *vc; - int i; + int i; if (vt && vt->keyboard == handle) { /* disable receieving key events for each VC */ for (i = 0; i < MAX_NR_USER_CONSOLES; i++) { vc = find_vc(vt->first_vc + i); - if (vc) vc->vc_kam = 1; + if (vc) vc->vc_kam = 1; } vt->keyboard = NULL; handle->private = NULL; - } - + } input_close_device(handle); kfree(handle); } @@ -1154,11 +1265,8 @@ int __init kbd_init(void) { + input_register_handler(&kbd_handler); tasklet_enable(&keyboard_tasklet); tasklet_schedule(&keyboard_tasklet); - - pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_kbd_request_override); - - input_register_handler(&kbd_handler); return 0; } |