Messages in this thread Patch in this message | | | Date | Wed, 4 Nov 1998 14:52:59 +1100 | From | Paul Mackerras <> | Subject | for comment: multi-keyboard patch |
| |
I'm working with Inaky Gonzalez on USB keyboard support. The current keyboard driver in linux really only allows one keyboard, or at best one type of keyboard. I have hacked the keyboard driver to allow multiple keyboards of different types (patch at the end of this message). I have added register_keyboard() and unregister_keyboard() functions which are used to create new keyboard instances and specify sets of low-level keyboard operations to be used with them.
I have also hacked the PC and mac low-level keyboard drivers to work with the new scheme. Other low-level keyboard drivers should still work using some compatibility stuff I put in keyboard.c.
At present input from all keyboards goes to the current foreground VC. Ultimately it would be nice to be able to bind a keyboard, screen and mouse together into a "console" which would have its own set of VCs.
Comments, anyone?
Paul.
diff -ur linux/Documentation/Configure.help linux-pmac/Documentation/Configure.help --- linux/Documentation/Configure.help Tue Oct 27 16:32:16 1998 +++ linux-pmac/Documentation/Configure.help Wed Oct 28 15:32:07 1998 @@ -9064,12 +9064,14 @@ Support for PowerMac keyboard CONFIG_MAC_KEYBOARD This option allows you to use an ADB keyboard attached to your - machine. Note that this disables any other (ie. PS/2) keyboard - support, even if your machine is physically capable of using both - at the same time. - - If you use an ADB keyboard (4 pin connector), say Y here. - If you use a PS/2 keyboard (6 pin connector), say N here. + machine. Say Y if you have a Power Macintosh or a CHRP machine + with an ADB keyboard. + +Support for PC-style keyboard +CONFIG_PC_KEYBOARD + This option allows you to use a PC-style or PS/2-style keyboard + attached to your machine. PReP and some CHRP machines have this + style of keyboard; say Y if you have such a machine. Support for PowerMac floppy CONFIG_MAC_FLOPPY diff -ur linux/arch/ppc/config.in linux-pmac/arch/ppc/config.in --- linux/arch/ppc/config.in Tue Oct 20 11:07:47 1998 +++ linux-pmac/arch/ppc/config.in Sat Oct 24 18:11:24 1998 @@ -61,6 +61,7 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA +bool 'PC-style keyboard support' CONFIG_PC_KEYBOARD tristate 'Parallel port support' CONFIG_PARPORT if [ "$CONFIG_PARPORT" != "n" ]; then dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT diff -ur linux/drivers/char/Makefile linux-pmac/drivers/char/Makefile --- linux/drivers/char/Makefile Tue Oct 27 16:44:51 1998 +++ linux-pmac/drivers/char/Makefile Tue Nov 3 15:49:37 1998 @@ -42,7 +42,7 @@ ifndef CONFIG_SUN_KEYBOARD ifdef CONFIG_VT -L_OBJS += keyboard.o +LX_OBJS += keyboard.o endif ifneq ($(ARCH),m68k) ifndef CONFIG_MBX @@ -51,7 +51,8 @@ endif else ifdef CONFIG_PCI -L_OBJS += defkeymap.o keyboard.o +L_OBJS += defkeymap.o +LX_OBJS += keyboard.o endif endif diff -ur linux/drivers/char/keyboard.c linux-pmac/drivers/char/keyboard.c --- linux/drivers/char/keyboard.c Thu Oct 1 22:36:47 1998 +++ linux-pmac/drivers/char/keyboard.c Tue Nov 3 15:48:30 1998 @@ -31,6 +31,7 @@ #include <linux/string.h> #include <linux/random.h> #include <linux/init.h> +#include <linux/malloc.h> #include <asm/keyboard.h> #include <asm/bitops.h> @@ -71,35 +72,56 @@ } /* - * global state includes the following, and various static variables - * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next. - * (last_console is now a global variable) + * Per-keyboard state. + * At present all keyboards are connected to the current fg_console - + * this needs to be generalized a bit. */ +struct keyboard_state { + struct keyboard_state *next; + struct kbd_ll_operations *k_op; + void *devid; + ushort **key_maps; + struct kbd_struct *kbd; + struct tty_struct *tty; + int last_scancode; + struct timer_list repeat_timer; + int repeat_timer_running; + int dead_key_next; + int shift_state; + int npadch; /* -1 or number assembled on pad */ +#ifdef CONFIG_MAGIC_SYSRQ + int sysrq_pressed; +#endif + char rep; /* flag telling character repeat */ + unsigned char diacr; + unsigned char k_down[NR_SHIFT]; /* shift state counters.. */ + unsigned long key_down[256/BITS_PER_LONG]; /* keyboard key bitmap */ +}; -/* shift state counters.. */ -static unsigned char k_down[NR_SHIFT] = {0, }; -/* keyboard key bitmap */ -static unsigned long key_down[256/BITS_PER_LONG] = { 0, }; +/* + * List of all keyboards (and a spinlock for it). + */ +static struct keyboard_state *all_kbds; +static spinlock_t all_kbds_lock = SPIN_LOCK_UNLOCKED; -static int dead_key_next = 0; /* * In order to retrieve the shift_state (for the mouse server), either * the variable must be global, or a new procedure must be created to * return the value. I chose the former way. + * This now reflects the shift_state of the last keyboard + * whose shift_state changed - paulus. */ int shift_state = 0; -static int npadch = -1; /* -1 or number assembled on pad */ -static unsigned char diacr = 0; -static char rep = 0; /* flag telling character repeat */ + struct kbd_struct kbd_table[MAX_NR_CONSOLES]; static struct tty_struct **ttytab; -static struct kbd_struct * kbd = kbd_table; -static struct tty_struct * tty = NULL; -void compute_shiftstate(void); +void kbd_compute_shiftstate(struct keyboard_state *); -typedef void (*k_hand)(unsigned char value, char up_flag); -typedef void (k_handfn)(unsigned char value, char up_flag); +typedef void (*k_hand)(struct keyboard_state *, unsigned char value, + char up_flag); +typedef void (k_handfn)(struct keyboard_state *, unsigned char value, + char up_flag); static k_handfn do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, @@ -116,16 +138,17 @@ #define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT)) -typedef void (*void_fnp)(void); -typedef void (void_fn)(void); +typedef void (*void_fnp)(struct keyboard_state *); +typedef void (void_fn)(struct keyboard_state *); static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle, num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, - SAK, decr_console, incr_console, spawn_console, bare_num; + SAK, decr_console, incr_console, spawn_console, bare_num, + do_show_mem, do_show_state; static void_fnp spec_fn_table[] = { - do_null, enter, show_ptregs, show_mem, - show_state, send_intr, lastcons, caps_toggle, + do_null, enter, show_ptregs, do_show_mem, + do_show_state, send_intr, lastcons, caps_toggle, num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, SAK, decr_console, incr_console, spawn_console, bare_num @@ -143,33 +166,28 @@ const int NR_TYPES = SIZE(max_vals); -/* N.B. drivers/macintosh/mac_keyb.c needs to call put_queue */ -void put_queue(int); -static unsigned char handle_diacr(unsigned char); +static void put_queue(struct tty_struct *, int); +static unsigned char handle_diacr(struct keyboard_state *, unsigned char); /* kbd_pt_regs - set by keyboard_interrupt(), used by show_ptregs() */ struct pt_regs * kbd_pt_regs; -#ifdef CONFIG_MAGIC_SYSRQ -static int sysrq_pressed; -#endif - /* * Many other routines do put_queue, but I think either * they produce ASCII, or they produce some user-assigned * string, and in both cases we might assume that it is * in utf-8 already. */ -void to_utf8(ushort c) { +void to_utf8(struct tty_struct *tty, ushort c) { if (c < 0x80) - put_queue(c); /* 0******* */ + put_queue(tty, c); /* 0******* */ else if (c < 0x800) { - put_queue(0xc0 | (c >> 6)); /* 110***** 10****** */ - put_queue(0x80 | (c & 0x3f)); + put_queue(tty, 0xc0 | (c >> 6)); /* 110***** 10****** */ + put_queue(tty, 0x80 | (c & 0x3f)); } else { - put_queue(0xe0 | (c >> 12)); /* 1110**** 10****** 10****** */ - put_queue(0x80 | ((c >> 6) & 0x3f)); - put_queue(0x80 | (c & 0x3f)); + put_queue(tty, 0xe0 | (c >> 12)); /* 1110**** 10****** 10****** */ + put_queue(tty, 0x80 | ((c >> 6) & 0x3f)); + put_queue(tty, 0x80 | (c & 0x3f)); } /* UTF-8 is defined for words of up to 31 bits, but we need only 16 bits here */ @@ -178,76 +196,123 @@ /* * Translation of escaped scancodes to keycodes. * This is now user-settable (for machines were it makes sense). + * (XXX It doesn't make much sense with multiple keyboards :-() */ int setkeycode(unsigned int scancode, unsigned int keycode) { - return kbd_setkeycode(scancode, keycode); + struct keyboard_state *ks; + int err = 0; + + spin_lock(&all_kbds_lock); + for (ks = all_kbds; ks != NULL && err == 0; ks = ks->next) + if (ks->key_maps == key_maps) + err = ks->k_op->setkeycode(ks->devid, scancode, keycode); + spin_unlock(&all_kbds_lock); + return err; } +/* XXX and this makes even less sense... :-* */ int getkeycode(unsigned int scancode) { - return kbd_getkeycode(scancode); + struct keyboard_state *ks = all_kbds; + + if (ks == NULL) + return -ENODEV; + return ks->k_op->getkeycode(ks->devid, scancode); } -void handle_scancode(unsigned char scancode) +static void kbd_repeat(unsigned long devid) +{ + struct keyboard_state *ks = (struct keyboard_state *) devid; + unsigned long flags; + + save_flags(flags); + cli(); + ks->repeat_timer_running = 0; + kbd_handle_scancode((void *)ks, ks->last_scancode); + restore_flags(flags); +} + +void kbd_handle_scancode(void *kbdid, int scancode) { + struct keyboard_state *ks = (struct keyboard_state *) kbdid; unsigned char keycode; char up_flag; /* 0 or 0200 */ - char raw_mode; + char raw_mode, rep; + struct kbd_struct *kbd; + struct tty_struct *tty; do_poke_blanked_console = 1; mark_bh(CONSOLE_BH); add_keyboard_randomness(scancode); - tty = ttytab? ttytab[fg_console]: NULL; - kbd = kbd_table + fg_console; + if (ks->repeat_timer_running) { + del_timer(&ks->repeat_timer); + ks->repeat_timer_running = 0; + } + + ks->tty = tty = ttytab? ttytab[fg_console]: NULL; + ks->kbd = kbd = kbd_table + fg_console; if ((raw_mode = (kbd->kbdmode == VC_RAW))) { - put_queue(scancode); + put_queue(tty, scancode); /* we do not return yet, because we want to maintain the key_down array, so that we have the correct values when finishing RAW mode or when changing VT's */ } - if (!kbd_pretranslate(scancode, raw_mode)) - return; + if (!ks->k_op->pretranslate(ks->devid, scancode, raw_mode)) + return; + /* * Convert scancode to keycode */ up_flag = (scancode & 0200); scancode &= 0x7f; - if (!kbd_translate(scancode, &keycode, raw_mode)) - return; + if (!ks->k_op->translate(ks->devid, scancode, &keycode, raw_mode)) + return; /* * At this point the variable `keycode' contains the keycode. - * Note: the keycode must not be 0 (++Geert: on m68k 0 is valid). * We keep track of the up/down status of the key, and * return the keycode if in MEDIUMRAW mode. */ if (up_flag) { rep = 0; - if(!test_and_clear_bit(keycode, key_down)) - up_flag = kbd_unexpected_up(keycode); + if (!test_and_clear_bit(keycode, ks->key_down)) + up_flag = ks->k_op->unexpected_up(ks->devid, keycode); } else - rep = test_and_set_bit(keycode, key_down); + rep = test_and_set_bit(keycode, ks->key_down); + ks->rep = rep; + + if (!raw_mode && !up_flag + && ks->k_op->dont_repeat && !ks->k_op->dont_repeat[keycode]) { + ks->last_scancode = scancode; + ks->repeat_timer.function = kbd_repeat; + ks->repeat_timer.data = (unsigned long) ks; + ks->repeat_timer.expires = jiffies + + (rep? ks->k_op->repeat_delay: ks->k_op->repeat_initial); + add_timer(&ks->repeat_timer); + ks->repeat_timer_running = 1; + } #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ - if (keycode == SYSRQ_KEY) { - sysrq_pressed = !up_flag; + if (keycode == ks->k_op->sysrq_key) { + ks->sysrq_pressed = !up_flag; return; - } else if (sysrq_pressed) { + } else if (ks->sysrq_pressed) { if (!up_flag) - handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, kbd, tty); + handle_sysrq(ks->k_op->sysrq_xlate[keycode], + kbd_pt_regs, kbd, tty); return; } #endif if (kbd->kbdmode == VC_MEDIUMRAW) { /* soon keycodes will require more than one byte */ - put_queue(keycode + up_flag); + put_queue(tty, keycode + up_flag); raw_mode = 1; /* Most key classes will be ignored */ } @@ -271,8 +336,8 @@ u_char type; /* the XOR below used to be an OR */ - int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate; - ushort *key_map = key_maps[shift_final]; + int shift_final = ks->shift_state ^ kbd->lockstate ^ kbd->slockstate; + ushort *key_map = ks->key_maps[shift_final]; if (key_map != NULL) { keysym = key_map[keycode]; @@ -285,36 +350,36 @@ if (type == KT_LETTER) { type = KT_LATIN; if (vc_kbd_led(kbd, VC_CAPSLOCK)) { - key_map = key_maps[shift_final ^ (1<<KG_SHIFT)]; + key_map = ks->key_maps[shift_final ^ (1<<KG_SHIFT)]; if (key_map) keysym = key_map[keycode]; } } - (*key_handler[type])(keysym & 0xff, up_flag); + (*key_handler[type])(ks, keysym & 0xff, up_flag); if (type != KT_SLOCK) kbd->slockstate = 0; } else { /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */ if (!up_flag && !raw_mode) - to_utf8(keysym); + to_utf8(tty, keysym); } } else { /* maybe beep? */ /* we have at least to update shift_state */ #if 1 /* how? two almost equivalent choices follow */ - compute_shiftstate(); + kbd_compute_shiftstate(ks); #else - keysym = U(plain_map[keycode]); + keysym = U(ks->key_maps[0][keycode]); type = KTYP(keysym); if (type == KT_SHIFT) - (*key_handler[type])(keysym & 0xff, up_flag); + (*key_handler[type])(ks, keysym & 0xff, up_flag); #endif } } } -void put_queue(int ch) +static void put_queue(struct tty_struct *tty, int ch) { wake_up(&keypress_wait); if (tty) { @@ -323,7 +388,7 @@ } } -static void puts_queue(char *cp) +static void puts_queue(struct tty_struct *tty, char *cp) { wake_up(&keypress_wait); if (!tty) @@ -336,49 +401,61 @@ con_schedule_flip(tty); } -static void applkey(int key, char mode) +static void applkey(struct tty_struct *tty, int key, char mode) { static char buf[] = { 0x1b, 'O', 0x00, 0x00 }; buf[1] = (mode ? 'O' : '['); buf[2] = key; - puts_queue(buf); + puts_queue(tty, buf); } -static void enter(void) +static void enter(struct keyboard_state *ks) { - if (diacr) { - put_queue(diacr); - diacr = 0; + if (ks->diacr) { + put_queue(ks->tty, ks->diacr); + ks->diacr = 0; } - put_queue(13); - if (vc_kbd_mode(kbd,VC_CRLF)) - put_queue(10); + put_queue(ks->tty, 13); + if (vc_kbd_mode(ks->kbd, VC_CRLF)) + put_queue(ks->tty, 10); } -static void caps_toggle(void) +static void caps_toggle(struct keyboard_state *ks) { - if (rep) + if (ks->rep) return; - chg_vc_kbd_led(kbd, VC_CAPSLOCK); + chg_vc_kbd_led(ks->kbd, VC_CAPSLOCK); } -static void caps_on(void) +static void caps_on(struct keyboard_state *ks) { - if (rep) + if (ks->rep) return; - set_vc_kbd_led(kbd, VC_CAPSLOCK); + set_vc_kbd_led(ks->kbd, VC_CAPSLOCK); } -static void show_ptregs(void) +static void show_ptregs(struct keyboard_state *ks) { if (kbd_pt_regs) show_regs(kbd_pt_regs); } -static void hold(void) +static void do_show_mem(struct keyboard_state *ks) +{ + show_mem(); +} + +static void do_show_state(struct keyboard_state *ks) { - if (rep || !tty) + show_state(); +} + +static void hold(struct keyboard_state *ks) +{ + struct tty_struct *tty = ks->tty; + + if (ks->rep || !tty) return; /* @@ -392,12 +469,12 @@ stop_tty(tty); } -static void num(void) +static void num(struct keyboard_state *ks) { - if (vc_kbd_mode(kbd,VC_APPLIC)) - applkey('P', 1); + if (vc_kbd_mode(ks->kbd, VC_APPLIC)) + applkey(ks->tty, 'P', 1); else - bare_num(); + bare_num(ks); } /* @@ -406,19 +483,19 @@ * Bind this to NumLock if you prefer that the NumLock key always * changes the NumLock flag. */ -static void bare_num(void) +static void bare_num(struct keyboard_state *ks) { - if (!rep) - chg_vc_kbd_led(kbd,VC_NUMLOCK); + if (!ks->rep) + chg_vc_kbd_led(ks->kbd, VC_NUMLOCK); } -static void lastcons(void) +static void lastcons(struct keyboard_state *ks) { /* switch to the last used console, ChN */ set_console(last_console); } -static void decr_console(void) +static void decr_console(struct keyboard_state *ks) { int i; @@ -431,7 +508,7 @@ set_console(i); } -static void incr_console(void) +static void incr_console(struct keyboard_state *ks) { int i; @@ -444,45 +521,49 @@ set_console(i); } -static void send_intr(void) +static void send_intr(struct keyboard_state *ks) { + struct tty_struct *tty = ks->tty; + if (!tty) return; tty_insert_flip_char(tty, 0, TTY_BREAK); con_schedule_flip(tty); } -static void scroll_forw(void) +static void scroll_forw(struct keyboard_state *ks) { scrollfront(0); } -static void scroll_back(void) +static void scroll_back(struct keyboard_state *ks) { scrollback(0); } -static void boot_it(void) +static void boot_it(struct keyboard_state *ks) { ctrl_alt_del(); } -static void compose(void) +static void compose(struct keyboard_state *ks) { - dead_key_next = 1; + ks->dead_key_next = 1; } int spawnpid, spawnsig; -static void spawn_console(void) +static void spawn_console(struct keyboard_state *ks) { if (spawnpid) if(kill_proc(spawnpid, spawnsig, 1)) spawnpid = 0; } -static void SAK(void) +static void SAK(struct keyboard_state *ks) { + struct tty_struct *tty = ks->tty; + /* * SAK should also work in all raw modes and reset * them properly. @@ -495,17 +576,19 @@ #endif } -static void do_ignore(unsigned char value, char up_flag) +static void do_ignore(struct keyboard_state *ks, unsigned char value, char up_flag) { } -static void do_null() +static void do_null(struct keyboard_state *ks) { - compute_shiftstate(); + kbd_compute_shiftstate(ks); } -static void do_spec(unsigned char value, char up_flag) +static void do_spec(struct keyboard_state *ks, unsigned char value, char up_flag) { + struct kbd_struct *kbd = ks->kbd; + if (up_flag) return; if (value >= SIZE(spec_fn_table)) @@ -513,29 +596,29 @@ if ((kbd->kbdmode == VC_RAW || kbd->kbdmode == VC_MEDIUMRAW) && !(SPECIALS_ALLOWED_IN_RAW_MODE & (1 << value))) return; - spec_fn_table[value](); + spec_fn_table[value](ks); } -static void do_lowercase(unsigned char value, char up_flag) +static void do_lowercase(struct keyboard_state *ks, unsigned char value, char up_flag) { printk(KERN_ERR "keyboard.c: do_lowercase was called - impossible\n"); } -static void do_self(unsigned char value, char up_flag) +static void do_self(struct keyboard_state *ks, unsigned char value, char up_flag) { if (up_flag) return; /* no action, if this is a key release */ - if (diacr) - value = handle_diacr(value); + if (ks->diacr) + value = handle_diacr(ks, value); - if (dead_key_next) { - dead_key_next = 0; - diacr = value; + if (ks->dead_key_next) { + ks->dead_key_next = 0; + ks->diacr = value; return; } - put_queue(value); + put_queue(ks->tty, value); } #define A_GRAVE '`' @@ -548,10 +631,10 @@ {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL }; /* Obsolete - for backwards compatibility only */ -static void do_dead(unsigned char value, char up_flag) +static void do_dead(struct keyboard_state *ks, unsigned char value, char up_flag) { value = ret_diacr[value]; - do_dead2(value,up_flag); + do_dead2(ks, value, up_flag); } /* @@ -559,12 +642,12 @@ * dead keys modifying the same character. Very useful * for Vietnamese. */ -static void do_dead2(unsigned char value, char up_flag) +static void do_dead2(struct keyboard_state *ks, unsigned char value, char up_flag) { if (up_flag) return; - diacr = (diacr ? handle_diacr(value) : value); + ks->diacr = (ks->diacr ? handle_diacr(ks, value) : value); } @@ -575,12 +658,12 @@ * Otherwise, conclude that DIACR was not combining after all, * queue it and return CH. */ -unsigned char handle_diacr(unsigned char ch) +unsigned char handle_diacr(struct keyboard_state *ks, unsigned char ch) { - int d = diacr; + int d = ks->diacr; int i; - diacr = 0; + ks->diacr = 0; for (i = 0; i < accent_table_size; i++) { if (accent_table[i].diacr == d && accent_table[i].base == ch) @@ -590,30 +673,31 @@ if (ch == ' ' || ch == d) return d; - put_queue(d); + put_queue(ks->tty, d); return ch; } -static void do_cons(unsigned char value, char up_flag) +static void do_cons(struct keyboard_state *ks, unsigned char value, char up_flag) { if (up_flag) return; set_console(value); } -static void do_fn(unsigned char value, char up_flag) +static void do_fn(struct keyboard_state *ks, unsigned char value, char up_flag) { if (up_flag) return; if (value < SIZE(func_table)) { if (func_table[value]) - puts_queue(func_table[value]); + puts_queue(ks->tty, func_table[value]); } else printk(KERN_ERR "do_fn called with value=%d\n", value); } -static void do_pad(unsigned char value, char up_flag) +static void do_pad(struct keyboard_state *ks, unsigned char value, char up_flag) { + struct kbd_struct *kbd = ks->kbd; static const char *pad_chars = "0123456789+-*/\015,.?()"; static const char *app_map = "pqrstuvwxylSRQMnnmPQ"; @@ -621,8 +705,8 @@ return; /* no action, if this is a key release */ /* kludge... shift forces cursor/number keys */ - if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) { - applkey(app_map[value], 1); + if (vc_kbd_mode(kbd,VC_APPLIC) && !ks->k_down[KG_SHIFT]) { + applkey(ks->tty, app_map[value], 1); return; } @@ -630,59 +714,60 @@ switch (value) { case KVAL(K_PCOMMA): case KVAL(K_PDOT): - do_fn(KVAL(K_REMOVE), 0); + do_fn(ks, KVAL(K_REMOVE), 0); return; case KVAL(K_P0): - do_fn(KVAL(K_INSERT), 0); + do_fn(ks, KVAL(K_INSERT), 0); return; case KVAL(K_P1): - do_fn(KVAL(K_SELECT), 0); + do_fn(ks, KVAL(K_SELECT), 0); return; case KVAL(K_P2): - do_cur(KVAL(K_DOWN), 0); + do_cur(ks, KVAL(K_DOWN), 0); return; case KVAL(K_P3): - do_fn(KVAL(K_PGDN), 0); + do_fn(ks, KVAL(K_PGDN), 0); return; case KVAL(K_P4): - do_cur(KVAL(K_LEFT), 0); + do_cur(ks, KVAL(K_LEFT), 0); return; case KVAL(K_P6): - do_cur(KVAL(K_RIGHT), 0); + do_cur(ks, KVAL(K_RIGHT), 0); return; case KVAL(K_P7): - do_fn(KVAL(K_FIND), 0); + do_fn(ks, KVAL(K_FIND), 0); return; case KVAL(K_P8): - do_cur(KVAL(K_UP), 0); + do_cur(ks, KVAL(K_UP), 0); return; case KVAL(K_P9): - do_fn(KVAL(K_PGUP), 0); + do_fn(ks, KVAL(K_PGUP), 0); return; case KVAL(K_P5): - applkey('G', vc_kbd_mode(kbd, VC_APPLIC)); + applkey(ks->tty, 'G', vc_kbd_mode(kbd, VC_APPLIC)); return; } - put_queue(pad_chars[value]); + put_queue(ks->tty, pad_chars[value]); if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF)) - put_queue(10); + put_queue(ks->tty, 10); } -static void do_cur(unsigned char value, char up_flag) +static void do_cur(struct keyboard_state *ks, unsigned char value, char up_flag) { static const char *cur_chars = "BDCA"; if (up_flag) return; - applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE)); + applkey(ks->tty, cur_chars[value], vc_kbd_mode(ks->kbd,VC_CKMODE)); } -static void do_shift(unsigned char value, char up_flag) +static void do_shift(struct keyboard_state *ks, unsigned char value, char up_flag) { - int old_state = shift_state; + struct kbd_struct *kbd = ks->kbd; + int old_state = ks->shift_state; - if (rep) + if (ks->rep) return; /* Mimic typewriter: @@ -696,23 +781,23 @@ if (up_flag) { /* handle the case that two shift or control keys are depressed simultaneously */ - if (k_down[value]) - k_down[value]--; + if (ks->k_down[value]) + ks->k_down[value]--; } else - k_down[value]++; + ks->k_down[value]++; - if (k_down[value]) - shift_state |= (1 << value); + if (ks->k_down[value]) + ks->shift_state |= (1 << value); else - shift_state &= ~ (1 << value); + ks->shift_state &= ~ (1 << value); /* kludge */ - if (up_flag && shift_state != old_state && npadch != -1) { + if (up_flag && ks->shift_state != old_state && ks->npadch != -1) { if (kbd->kbdmode == VC_UNICODE) - to_utf8(npadch & 0xffff); + to_utf8(ks->tty, ks->npadch & 0xffff); else - put_queue(npadch & 0xff); - npadch = -1; + put_queue(ks->tty, ks->npadch & 0xff); + ks->npadch = -1; } } @@ -721,42 +806,55 @@ /* maybe called when keymap is undefined, so that shiftkey release is seen */ void compute_shiftstate(void) { + struct keyboard_state *ks; + + spin_lock(&all_kbds_lock); + for (ks = all_kbds; ks != NULL; ks = ks->next) + kbd_compute_shiftstate(ks); + spin_unlock(&all_kbds_lock); +} + +void kbd_compute_shiftstate(struct keyboard_state *ks) +{ int i, j, k, sym, val; - shift_state = 0; - for(i=0; i < SIZE(k_down); i++) - k_down[i] = 0; - - for(i=0; i < SIZE(key_down); i++) - if(key_down[i]) { /* skip this word if not a single bit on */ - k = i*BITS_PER_LONG; - for(j=0; j<BITS_PER_LONG; j++,k++) - if(test_bit(k, key_down)) { - sym = U(plain_map[k]); - if(KTYP(sym) == KT_SHIFT) { - val = KVAL(sym); - if (val == KVAL(K_CAPSSHIFT)) - val = KVAL(K_SHIFT); - k_down[val]++; - shift_state |= (1<<val); + ks->shift_state = 0; + for (i = 0; i < SIZE(ks->k_down); i++) + ks->k_down[i] = 0; + + for (i = 0; i < SIZE(ks->key_down); i++) { + if (ks->key_down[i] == 0) + continue; /* skip this word if not a single bit on */ + k = i * BITS_PER_LONG; + for (j = 0; j < BITS_PER_LONG; j++, k++) { + if (test_bit(k, ks->key_down) == 0) + continue; + sym = U(ks->key_maps[0][k]); + if (KTYP(sym) == KT_SHIFT) { + val = KVAL(sym); + if (val == KVAL(K_CAPSSHIFT)) + val = KVAL(K_SHIFT); + ks->k_down[val]++; + ks->shift_state |= (1<<val); + } } - } - } + } + shift_state = ks->shift_state; /* XXX */ } -static void do_meta(unsigned char value, char up_flag) +static void do_meta(struct keyboard_state *ks, unsigned char value, char up_flag) { if (up_flag) return; - if (vc_kbd_mode(kbd, VC_META)) { - put_queue('\033'); - put_queue(value); + if (vc_kbd_mode(ks->kbd, VC_META)) { + put_queue(ks->tty, '\033'); + put_queue(ks->tty, value); } else - put_queue(value | 0x80); + put_queue(ks->tty, value | 0x80); } -static void do_ascii(unsigned char value, char up_flag) +static void do_ascii(struct keyboard_state *ks, unsigned char value, char up_flag) { int base; @@ -764,30 +862,30 @@ return; if (value < 10) /* decimal input of code, while Alt depressed */ - base = 10; + base = 10; else { /* hexadecimal input of code, while AltGr depressed */ - value -= 10; - base = 16; + value -= 10; + base = 16; } - if (npadch == -1) - npadch = value; + if (ks->npadch == -1) + ks->npadch = value; else - npadch = npadch * base + value; + ks->npadch = ks->npadch * base + value; } -static void do_lock(unsigned char value, char up_flag) +static void do_lock(struct keyboard_state *ks, unsigned char value, char up_flag) { - if (up_flag || rep) + if (up_flag || ks->rep) return; - chg_vc_kbd_lock(kbd, value); + chg_vc_kbd_lock(ks->kbd, value); } -static void do_slock(unsigned char value, char up_flag) +static void do_slock(struct keyboard_state *ks, unsigned char value, char up_flag) { - if (up_flag || rep) + if (up_flag || ks->rep) return; - chg_vc_kbd_slock(kbd, value); + chg_vc_kbd_slock(ks->kbd, value); } /* @@ -799,8 +897,8 @@ static unsigned char ledstate = 0xff; /* undefined */ static unsigned char ledioctl; -unsigned char getledstate(void) { - return ledstate; +unsigned char getledstate() { + return ledstate; } void setledstate(struct kbd_struct *kbd, unsigned int led) { @@ -876,13 +974,74 @@ static void kbd_bh(void) { unsigned char leds = getleds(); + struct keyboard_state *ks; if (leds != ledstate) { ledstate = leds; - kbd_leds(leds); + spin_lock(&all_kbds_lock); + for (ks = all_kbds; ks != NULL; ks = ks->next) + ks->k_op->leds(ks, leds); + spin_unlock(&all_kbds_lock); } } +#ifndef NEW_STYLE_KEYBOARD +int oldkbd_setkeycode(void *devid, unsigned int scancode, unsigned int keycode) +{ + return kbd_setkeycode(scancode, keycode); +} + +int oldkbd_getkeycode(void *devid, unsigned int scancode) +{ + return kbd_getkeycode(scancode); +} + +int oldkbd_pretranslate(void *devid, unsigned char scancode, char raw_mode) +{ + return kbd_pretranslate(scancode, raw_mode); +} + +int oldkbd_translate(void *devid, unsigned char scancode, + unsigned char *keycode, char raw_mode) +{ + return kbd_translate(scancode, keycode, raw_mode); +} + +int oldkbd_unexpected_up(void *devid, unsigned char keycode) +{ + return kbd_unexpected_up(keycode); +} + +void oldkbd_leds(void *devid, unsigned char leds) +{ + return kbd_leds(leds); +} + +struct kbd_ll_operations oldkbd_operations = { + oldkbd_setkeycode, + oldkbd_getkeycode, + oldkbd_pretranslate, + oldkbd_translate, + oldkbd_unexpected_up, + oldkbd_leds, +#ifdef CONFIG_MAGIC_SYSRQ + SYSRQ_KEY, + kbd_sysrq_xlate, +#else + -1, NULL, +#endif + 0, 0, NULL +}; + +void *old_kbdid; + +void handle_scancode(unsigned char scancode) +{ + if (old_kbdid) + kbd_handle_scancode(old_kbdid, scancode); +} +#endif /* NEW_STYLE_KEYBOARD */ + __initfunc(int kbd_init(void)) { int i; @@ -902,7 +1061,54 @@ ttytab = console_driver.table; kbd_init_hw(); + +#ifndef NEW_STYLE_KEYBOARD + old_kbdid = register_keyboard(oldkbd_operations, NULL, key_maps); +#endif /* NEW_STYLE_KEYBOARD */ + init_bh(KEYBOARD_BH, kbd_bh); mark_bh(KEYBOARD_BH); return 0; } + +void *register_keyboard(struct kbd_ll_operations *ops, void *devid, + ushort **key_maps) +{ + struct keyboard_state *ks, **ksp; + + ks = (struct keyboard_state *) kmalloc(sizeof(*ks), GFP_KERNEL); + if (ks == 0) + return NULL; + memset(ks, 0, sizeof(*ks)); + + ks->next = NULL; + ks->k_op = ops; + ks->devid = devid; + ks->key_maps = key_maps; + ks->npadch = -1; + + spin_lock(&all_kbds_lock); + for (ksp = &all_kbds; *ksp != NULL; ksp = &(*ksp)->next) + ; + *ksp = ks; + spin_unlock(&all_kbds_lock); + + return (void *) ks; +} + +void unregister_keyboard(void *kbdid) +{ + struct keyboard_state **ksp; + + spin_lock(&all_kbds_lock); + for (ksp = &all_kbds; *ksp != NULL; ksp = &(*ksp)->next) { + if (*ksp == kbdid) { + *ksp = (*ksp)->next; + kfree(kbdid); + break; + } + } +} + +EXPORT_SYMBOL (register_keyboard); +EXPORT_SYMBOL (unregister_keyboard); diff -ur linux/drivers/char/pc_keyb.c linux-pmac/drivers/char/pc_keyb.c --- linux/drivers/char/pc_keyb.c Tue Oct 27 16:45:38 1998 +++ linux-pmac/drivers/char/pc_keyb.c Wed Oct 28 15:38:11 1998 @@ -24,6 +24,7 @@ #include <linux/init.h> #include <linux/kbd_ll.h> #include <linux/delay.h> +#include <linux/keyboard.h> #include <linux/random.h> #include <linux/poll.h> #include <linux/miscdevice.h> @@ -52,6 +53,8 @@ "\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 */ +#else +#define pckbd_sysrq_xlate NULL #endif static void kbd_write(int address, int data); @@ -85,6 +88,30 @@ #endif #endif /* CONFIG_PSMOUSE */ +extern int pckbd_setkeycode(void *, unsigned int scancode, + unsigned int keycode); +extern int pckbd_getkeycode(void *, unsigned int scancode); +extern int pckbd_pretranslate(void *, unsigned char scancode, char raw_mode); +extern int pckbd_translate(void *, unsigned char scancode, + unsigned char *keycode, char raw_mode); +extern char pckbd_unexpected_up(void *, unsigned char keycode); +extern void pckbd_leds(void *, unsigned char leds); +#define SYSRQ_KEY 0x54 + +struct kbd_ll_operations pckbd_operations = { + pckbd_setkeycode, + pckbd_getkeycode, + pckbd_pretranslate, + pckbd_translate, + pckbd_unexpected_up, + pckbd_leds, + SYSRQ_KEY, + pckbd_sysrq_xlate, + 0, 0, NULL +}; + +static void *pckbd_id; + /* * Wait for keyboard controller input buffer is empty. * @@ -237,7 +264,7 @@ static unsigned int prev_scancode = 0; /* remember E0, E1 */ -int pckbd_setkeycode(unsigned int scancode, unsigned int keycode) +int pckbd_setkeycode(void *devid, unsigned int scancode, unsigned int keycode) { if (scancode < SC_LIM || scancode > 255 || keycode > 127) return -EINVAL; @@ -248,7 +275,7 @@ return 0; } -int pckbd_getkeycode(unsigned int scancode) +int pckbd_getkeycode(void *devid, unsigned int scancode) { return (scancode < SC_LIM || scancode > 255) ? -EINVAL : @@ -308,7 +335,7 @@ return 1; } -int pckbd_pretranslate(unsigned char scancode, char raw_mode) +int pckbd_pretranslate(void *devid, unsigned char scancode, char raw_mode) { if (scancode == 0xff) { /* in scancode mode 1, my ESC key generates 0xff */ @@ -330,8 +357,8 @@ return 1; } -int pckbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode) +int pckbd_translate(void *devid, unsigned char scancode, + unsigned char *keycode, char raw_mode) { if (prev_scancode) { /* @@ -409,7 +436,7 @@ return 1; } -char pckbd_unexpected_up(unsigned char keycode) +char pckbd_unexpected_up(void *devid, unsigned char keycode) { /* unexpected, but this can happen: maybe this was a key release for a FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */ @@ -452,7 +479,7 @@ #endif } else { if (do_acknowledge(scancode)) - handle_scancode(scancode); + kbd_handle_scancode(pckbd_id, scancode); mark_bh(KEYBOARD_BH); } @@ -501,7 +528,7 @@ return 0; } -void pckbd_leds(unsigned char leds) +void pckbd_leds(void *devid, unsigned char leds) { if (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds)) send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */ @@ -713,6 +740,10 @@ /* Ok, finally allocate the IRQ, and off we go.. */ request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL); + + pckbd_id = register_keyboard(&pckbd_operations, NULL, key_maps); + if (pckbd_id == NULL) + printk(KERN_ERR "Couldn't register PC keyboard!\n"); } #if defined CONFIG_PSMOUSE diff -ur linux/drivers/macintosh/mac_keyb.c linux-pmac/drivers/macintosh/mac_keyb.c --- linux/drivers/macintosh/mac_keyb.c Mon Oct 12 10:32:52 1998 +++ linux-pmac/drivers/macintosh/mac_keyb.c Sun Oct 25 16:13:14 1998 @@ -31,7 +31,27 @@ #define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */ #define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */ -static u_short macplain_map[NR_KEYS] __initdata = { +int mackbd_setkeycode(void *devid, unsigned int scancode, unsigned int keycode); +int mackbd_getkeycode(void *devid, unsigned int scancode); +int mackbd_pretranslate(void *devid, unsigned char scancode, char raw_mode); +int mackbd_translate(void *devid, unsigned char scancode, + unsigned char *keycode, char raw_mode); +char mackbd_unexpected_up(void *devid, unsigned char keycode); +void mackbd_leds(void *devid, unsigned char leds); + +/* this map indicates which keys shouldn't autorepeat. */ +static unsigned char dont_repeat[128] = { + 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, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* esc...option */ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* num lock */ + 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, 1, 0, 0, 0, 0, /* scroll lock */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static u_short plain_map[NR_KEYS] = { 0xfb61, 0xfb73, 0xfb64, 0xfb66, 0xfb68, 0xfb67, 0xfb7a, 0xfb78, 0xfb63, 0xfb76, 0xf200, 0xfb62, 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb79, 0xfb74, 0xf031, 0xf032, 0xf033, 0xf034, 0xf036, 0xf035, @@ -50,7 +70,7 @@ 0xf101, 0xf119, 0xf100, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200, }; -static u_short macshift_map[NR_KEYS] __initdata = { +static u_short shift_map[NR_KEYS] = { 0xfb41, 0xfb53, 0xfb44, 0xfb46, 0xfb48, 0xfb47, 0xfb5a, 0xfb58, 0xfb43, 0xfb56, 0xf200, 0xfb42, 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb59, 0xfb54, 0xf021, 0xf040, 0xf023, 0xf024, 0xf05e, 0xf025, @@ -69,7 +89,7 @@ 0xf10b, 0xf20a, 0xf10a, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200, }; -static u_short macaltgr_map[NR_KEYS] __initdata = { +static u_short altgr_map[NR_KEYS] = { 0xf914, 0xfb73, 0xf917, 0xf919, 0xfb68, 0xfb67, 0xfb7a, 0xfb78, 0xf916, 0xfb76, 0xf200, 0xf915, 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb79, 0xfb74, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, @@ -88,7 +108,7 @@ 0xf50d, 0xf119, 0xf50c, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200, }; -static u_short macctrl_map[NR_KEYS] __initdata = { +static u_short ctrl_map[NR_KEYS] = { 0xf001, 0xf013, 0xf004, 0xf006, 0xf008, 0xf007, 0xf01a, 0xf018, 0xf003, 0xf016, 0xf200, 0xf002, 0xf011, 0xf017, 0xf005, 0xf012, 0xf019, 0xf014, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01e, 0xf01d, @@ -107,7 +127,7 @@ 0xf101, 0xf119, 0xf100, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200, }; -static u_short macshift_ctrl_map[NR_KEYS] __initdata = { +static u_short shift_ctrl_map[NR_KEYS] = { 0xf001, 0xf013, 0xf004, 0xf006, 0xf008, 0xf007, 0xf01a, 0xf018, 0xf003, 0xf016, 0xf200, 0xf002, 0xf011, 0xf017, 0xf005, 0xf012, 0xf019, 0xf014, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200, @@ -126,7 +146,7 @@ 0xf200, 0xf119, 0xf200, 0xf700, 0xf701, 0xf702, 0xf200, 0xf20c, }; -static u_short macalt_map[NR_KEYS] __initdata = { +static u_short alt_map[NR_KEYS] = { 0xf861, 0xf873, 0xf864, 0xf866, 0xf868, 0xf867, 0xf87a, 0xf878, 0xf863, 0xf876, 0xf200, 0xf862, 0xf871, 0xf877, 0xf865, 0xf872, 0xf879, 0xf874, 0xf831, 0xf832, 0xf833, 0xf834, 0xf836, 0xf835, @@ -145,7 +165,7 @@ 0xf501, 0xf119, 0xf500, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200, }; -static u_short macctrl_alt_map[NR_KEYS] __initdata = { +static u_short ctrl_alt_map[NR_KEYS] = { 0xf801, 0xf813, 0xf804, 0xf806, 0xf808, 0xf807, 0xf81a, 0xf818, 0xf803, 0xf816, 0xf200, 0xf802, 0xf811, 0xf817, 0xf805, 0xf812, 0xf819, 0xf814, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, @@ -164,13 +184,28 @@ 0xf501, 0xf119, 0xf500, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200, }; +static ushort *mackey_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; -static void kbd_repeat(unsigned long); -static struct timer_list repeat_timer = { NULL, NULL, 0, 0, kbd_repeat }; -static int last_keycode; +struct kbd_ll_operations mackbd_operations = { + mackbd_setkeycode, + mackbd_getkeycode, + mackbd_pretranslate, + mackbd_translate, + mackbd_unexpected_up, + mackbd_leds, + -1, /* no SysRq key */ + NULL, + HZ/2, HZ/15, + dont_repeat +}; static void keyboard_input(unsigned char *, int, struct pt_regs *, int); -static void input_keycode(int, int); +static void input_keycode(void *, int); static void leds_done(struct adb_request *); static void mac_put_queue(int); @@ -185,44 +220,39 @@ extern int console_loglevel; extern struct kbd_struct kbd_table[]; -extern struct wait_queue * keypress_wait; - -extern void handle_scancode(unsigned char); +extern struct wait_queue *keypress_wait; static struct adb_ids keyboard_ids; static struct adb_ids mouse_ids; -/* this map indicates which keys shouldn't autorepeat. */ -static unsigned char dont_repeat[128] = { - 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, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* esc...option */ - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* num lock */ - 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, 1, 0, 0, 0, 0, /* scroll lock */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +struct mackbd_state { + int adb_id; + void *kbd_id; + struct adb_request led_request; + int leds_pending; }; +struct mackbd_state mackbd_states[16]; + __openfirmware -int mackbd_setkeycode(unsigned int scancode, unsigned int keycode) +int mackbd_setkeycode(void *devid, unsigned int scancode, unsigned int keycode) { return -EINVAL; } -int mackbd_getkeycode(unsigned int scancode) +int mackbd_getkeycode(void *devid, unsigned int scancode) { return -EINVAL; } -int mackbd_pretranslate(unsigned char scancode, char raw_mode) +int mackbd_pretranslate(void *devid, unsigned char scancode, char raw_mode) { return 1; } -int mackbd_translate(unsigned char keycode, unsigned char *keycodep, - char raw_mode) +int mackbd_translate(void *devid, unsigned char keycode, + unsigned char *keycodep, char raw_mode) { if (!raw_mode) { /* @@ -238,7 +268,7 @@ return 1; } -int mackbd_unexpected_up(unsigned char keycode) +char mackbd_unexpected_up(void *devid, unsigned char keycode) { return 0x80; } @@ -246,17 +276,22 @@ static void keyboard_input(unsigned char *data, int nb, struct pt_regs *regs, int apoll) { + void *kbd_id; + /* first check this is from register 0 */ if (nb != 3 || (data[0] & 3) != KEYB_KEYREG) return; /* ignore it */ + kbd_id = mackbd_states[data[0] >> 4].kbd_id; + if (kbd_id == NULL) + return; kbd_pt_regs = regs; - input_keycode(data[1], 0); + input_keycode(kbd_id, data[1]); if (!(data[2] == 0xff || (data[2] == 0x7f && data[1] == 0x7f))) - input_keycode(data[2], 0); + input_keycode(kbd_id, data[2]); } static void -input_keycode(int keycode, int repeat) +input_keycode(void *kbdid, int keycode) { struct kbd_struct *kbd; int up_flag; @@ -269,9 +304,6 @@ if (keycode == 0x7e) keycode = 0x7f; - if (!repeat) - del_timer(&repeat_timer); - #ifdef CONFIG_ADBMOUSE /* * XXX: Add mouse button 2+3 fake codes here if mouse open. @@ -305,12 +337,6 @@ #endif /* CONFIG_ADBMOUSE */ if (kbd->kbdmode != VC_RAW) { - if (!up_flag && !dont_repeat[keycode]) { - last_keycode = keycode; - repeat_timer.expires = jiffies + (repeat? HZ/15: HZ/2); - add_timer(&repeat_timer); - } - /* * adb kludge!! Imitate pc caps lock behaviour by * generating an up/down event for each time caps @@ -320,8 +346,8 @@ switch (keycode) { /*case 0xb9:*/ case 0x39: - handle_scancode(0x39); - handle_scancode(0xb9); + kbd_handle_scancode(kbdid, 0x39); + kbd_handle_scancode(kbdid, 0xb9); mark_bh(KEYBOARD_BH); return; case 0x47: @@ -331,18 +357,7 @@ } } - handle_scancode(keycode + up_flag); -} - -static void -kbd_repeat(unsigned long xxx) -{ - unsigned long flags; - - save_flags(flags); - cli(); - input_keycode(last_keycode, 1); - restore_flags(flags); + kbd_handle_scancode(kbdid, keycode + up_flag); } static void mac_put_queue(int ch) @@ -479,132 +494,120 @@ 7, /* caps + num + scroll lock */ }; -static struct adb_request led_request; -static int leds_pending[16]; -static int pending_devs[16]; -static int pending_led_start=0; -static int pending_led_end=0; - -static void real_mackbd_leds(unsigned char leds, int device) -{ - - if (led_request.complete) { - adb_request(&led_request, leds_done, 0, 3, - ADB_WRITEREG(device, KEYB_LEDREG), 0xff, - ~mac_ledmap[leds]); - } else { - if (!(leds_pending[device] & 0x100)) { - pending_devs[pending_led_end] = device; - pending_led_end++; - pending_led_end = (pending_led_end < 16) ? pending_led_end : 0; - } - leds_pending[device] = leds | 0x100; - } -} - -void mackbd_leds(unsigned char leds) +void mackbd_leds(void *devid, unsigned char leds) { - int i; + struct mackbd_state *ms = (struct mackbd_state *) devid; - for(i = 0; i < keyboard_ids.nids; i++) - real_mackbd_leds(leds,keyboard_ids.id[i]); + if (ms->led_request.complete) { + ms->led_request.arg = devid; + adb_request(&ms->led_request, leds_done, 0, 3, + ADB_WRITEREG(ms->adb_id, KEYB_LEDREG), 0xff, + ~mac_ledmap[leds]); + } else { + ms->leds_pending = leds | 0x100; + } } static void leds_done(struct adb_request *req) { - int leds,device; - - if (pending_led_start != pending_led_end) { - device = pending_devs[pending_led_start]; - leds = leds_pending[device] & 0xff; - leds_pending[device] = 0; - pending_led_start++; - pending_led_start = (pending_led_start < 16) ? pending_led_start : 0; - real_mackbd_leds(leds,device); - } + struct mackbd_state *ms = (struct mackbd_state *) req->arg; + int leds; + if (ms->leds_pending) { + leds = ms->leds_pending & 0xff; + ms->leds_pending = 0; + mackbd_leds(ms, leds); + } } -__initfunc(void mackbd_init_hw(void)) +__initfunc(static void init_mouse(int id)) { struct adb_request req; - int i; - - if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) - return; - - /* setup key map */ - memcpy(key_maps[0], macplain_map, sizeof(plain_map)); - memcpy(key_maps[1], macshift_map, sizeof(plain_map)); - memcpy(key_maps[2], macaltgr_map, sizeof(plain_map)); - memcpy(key_maps[4], macctrl_map, sizeof(plain_map)); - memcpy(key_maps[5], macshift_ctrl_map, sizeof(plain_map)); - memcpy(key_maps[8], macalt_map, sizeof(plain_map)); - memcpy(key_maps[12], macctrl_alt_map, sizeof(plain_map)); - -#ifdef CONFIG_ADBMOUSE - /* initialize mouse interrupt hook */ - adb_mouse_interrupt_hook = NULL; - - adb_register(ADB_MOUSE, 1, &mouse_ids, mouse_input); -#endif /* CONFIG_ADBMOUSE */ - - adb_register(ADB_KEYBOARD, 5, &keyboard_ids, keyboard_input); - - for(i = 0; i < keyboard_ids.nids; i++) { - /* turn off all leds */ - adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(keyboard_ids.id[i], KEYB_LEDREG), 0xff, 0xff); - } - /* get the keyboard to send separate codes for - left and right shift, control, option keys. */ - for(i = 0;i < keyboard_ids.nids; i++) { - /* get the keyboard to send separate codes for - left and right shift, control, option keys. */ - adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(keyboard_ids.id[i], 3), 0, 3); - } + adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, + ADB_READREG(id, 1)); - led_request.complete = 1; + if ((req.reply_len) && + (req.reply[1] == 0x9a) && (req.reply[2] == 0x21)) { + printk("aha, trackball found at %d\n", id); - /* Try to switch the mouse (id 3) to handler 4, for three-button - mode. (0x20 is Service Request Enable, 0x03 is Device ID). */ - for(i = 0; i < mouse_ids.nids; i++) { - adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, - ADB_READREG(mouse_ids.id[i], 1)); - - if ((req.reply_len) && - (req.reply[1] == 0x9a) && (req.reply[2] == 0x21)) { + adb_request(&req, NULL, ADBREQ_SYNC, 3, + ADB_WRITEREG(id, 3), 0x63, 4 ); - printk("aha, trackball found at %d\n", mouse_ids.id[i]); + adb_request(&req, NULL, ADBREQ_SYNC, 3, + ADB_WRITEREG(id,1), 00,0x81); adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(mouse_ids.id[i], 3), 0x63, 4 ); + ADB_WRITEREG(id,1), 01,0x81); adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(mouse_ids.id[i],1), 00,0x81); + ADB_WRITEREG(id,1), 02,0x81); adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(mouse_ids.id[i],1), 01,0x81); + ADB_WRITEREG(id,1), 03,0x38); adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(mouse_ids.id[i],1), 02,0x81); + ADB_WRITEREG(id,1), 00,0x81); adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(mouse_ids.id[i],1), 03,0x38); + ADB_WRITEREG(id,1), 01,0x81); adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(mouse_ids.id[i],1), 00,0x81); + ADB_WRITEREG(id,1), 02,0x81); adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(mouse_ids.id[i],1), 01,0x81); + ADB_WRITEREG(id,1), 03,0x38); + } +} +__initfunc(void mackbd_init_hw(void)) +{ + int i; + + if ((_machine != _MACH_chrp) && (_machine != _MACH_Pmac)) + return; + +#ifdef CONFIG_ADBMOUSE + /* initialize mouse interrupt hook */ + adb_mouse_interrupt_hook = NULL; + + adb_register(ADB_MOUSE, 1, &mouse_ids, mouse_input); + + /* Try to switch the mouse (id 3) to handler 4, for three-button + mode. (0x20 is Service Request Enable, 0x03 is Device ID). */ + for (i = 0; i < mouse_ids.nids; i++) { + init_mouse(mouse_ids.id[i]); + } +#endif /* CONFIG_ADBMOUSE */ + + adb_register(ADB_KEYBOARD, 5, &keyboard_ids, keyboard_input); + if (keyboard_ids.nids == 0) + return; + + for (i = 0; i < keyboard_ids.nids; i++) { + int id = keyboard_ids.id[i]; + struct mackbd_state *ms = &mackbd_states[id]; + struct adb_request req; + + memset(ms, 0, sizeof(*ms)); + ms->adb_id = id; + ms->led_request.complete = 1; + ms->kbd_id = register_keyboard(&mackbd_operations, ms, + mackey_maps); + if (ms->kbd_id == NULL) + printk(KERN_ERR "Couldn't register ADB keyboard %d\n", + id); + + /* turn off all leds */ adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(mouse_ids.id[i],1), 02,0x81); + ADB_WRITEREG(id, KEYB_LEDREG), 0xff, 0xff); + /* get the keyboard to send separate codes for + left and right shift, control, option keys. */ adb_request(&req, NULL, ADBREQ_SYNC, 3, - ADB_WRITEREG(mouse_ids.id[i],1), 03,0x38); - } + ADB_WRITEREG(id, 3), 0, 3); } + + /* setup default key map */ + memcpy(key_maps, mackey_maps, sizeof(mackey_maps)); } diff -ur linux/include/asm-i386/keyboard.h linux-pmac/include/asm-i386/keyboard.h --- linux/include/asm-i386/keyboard.h Mon Jul 21 18:16:55 1997 +++ linux-pmac/include/asm-i386/keyboard.h Sun Oct 25 15:56:37 1998 @@ -15,27 +15,11 @@ #define KEYBOARD_IRQ 1 #define DISABLE_KBD_DURING_INTERRUPTS 0 +#define NEW_STYLE_KEYBOARD -extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); -extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern char pckbd_unexpected_up(unsigned char keycode); -extern void pckbd_leds(unsigned char leds); extern void pckbd_init_hw(void); -extern unsigned char pckbd_sysrq_xlate[128]; -#define kbd_setkeycode pckbd_setkeycode -#define kbd_getkeycode pckbd_getkeycode -#define kbd_pretranslate pckbd_pretranslate -#define kbd_translate pckbd_translate -#define kbd_unexpected_up pckbd_unexpected_up -#define kbd_leds pckbd_leds #define kbd_init_hw pckbd_init_hw -#define kbd_sysrq_xlate pckbd_sysrq_xlate - -#define SYSRQ_KEY 0x54 #endif /* __KERNEL__ */ diff -ur linux/include/asm-ppc/keyboard.h linux-pmac/include/asm-ppc/keyboard.h --- linux/include/asm-ppc/keyboard.h Thu Oct 22 16:31:01 1998 +++ linux-pmac/include/asm-ppc/keyboard.h Wed Oct 28 15:45:57 1998 @@ -16,7 +16,7 @@ #ifdef __KERNEL__ #include <linux/config.h> -#include <asm/adb.h> +#include <asm/processor.h> #ifdef CONFIG_APUS #include <asm-m68k/keyboard.h> @@ -24,152 +24,22 @@ #define KEYBOARD_IRQ 1 #define DISABLE_KBD_DURING_INTERRUPTS 0 -#define INIT_KBD +#define NEW_STYLE_KEYBOARD -extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int mackbd_getkeycode(unsigned int scancode); -extern int mackbd_pretranslate(unsigned char scancode, char raw_mode); -extern int mackbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern int mackbd_unexpected_up(unsigned char keycode); -extern void mackbd_leds(unsigned char leds); extern void mackbd_init_hw(void); -extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); -extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern char pckbd_unexpected_up(unsigned char keycode); -extern void pckbd_leds(unsigned char leds); extern void pckbd_init_hw(void); -static inline int kbd_setkeycode(unsigned int scancode, unsigned int keycode) -{ - if ( is_prep ) - return pckbd_setkeycode(scancode,keycode); - else if ( is_chrp ) -#ifndef CONFIG_MAC_KEYBOARD - return pckbd_setkeycode(scancode,keycode); -#else - /* I'm not actually sure if it's legal to have a CHRP machine - * without an ADB controller. In any case, this should really - * be changed to be a test to see if an ADB _keyboard_ exists - * (not just a controller), but that's another story for - * another night. - */ - if ( adb_hardware == ADB_NONE ) - return pckbd_setkeycode(scancode,keycode); - else - return mackbd_setkeycode(scancode,keycode); -#endif - else - return mackbd_setkeycode(scancode,keycode); -} - -static inline int kbd_getkeycode(unsigned int x) -{ - if ( is_prep ) - return pckbd_getkeycode(x); - else if ( is_chrp ) -#ifndef CONFIG_MAC_KEYBOARD - return pckbd_getkeycode(x); -#else - if ( adb_hardware == ADB_NONE ) - return pckbd_getkeycode(x); - else - return mackbd_getkeycode(x); -#endif - else - return mackbd_getkeycode(x); -} - -static inline int kbd_pretranslate(unsigned char x,char y) -{ - if ( is_prep ) - return pckbd_pretranslate(x,y); - else if ( is_chrp ) -#ifndef CONFIG_MAC_KEYBOARD - return pckbd_pretranslate(x,y); -#else - if ( adb_hardware == ADB_NONE ) - return pckbd_pretranslate(x,y); - else - return mackbd_pretranslate(x,y); -#endif - else - return mackbd_pretranslate(x,y); -} - -static inline int kbd_translate(unsigned char keycode, unsigned char *keycodep, - char raw_mode) -{ - if ( is_prep ) - return pckbd_translate(keycode,keycodep,raw_mode); - else if ( is_chrp ) -#ifndef CONFIG_MAC_KEYBOARD - return pckbd_translate(keycode,keycodep,raw_mode); -#else - if ( adb_hardware == ADB_NONE ) - return pckbd_translate(keycode,keycodep,raw_mode); - else - return mackbd_translate(keycode,keycodep,raw_mode); -#endif - else - return mackbd_translate(keycode,keycodep,raw_mode); - -} - -static inline int kbd_unexpected_up(unsigned char keycode) -{ - if ( is_prep ) - return pckbd_unexpected_up(keycode); - else if ( is_chrp ) -#ifndef CONFIG_MAC_KEYBOARD - return pckbd_unexpected_up(keycode); -#else - if ( adb_hardware == ADB_NONE ) - return pckbd_unexpected_up(keycode); - else - return mackbd_unexpected_up(keycode); -#endif - else - return mackbd_unexpected_up(keycode); - -} - -static inline void kbd_leds(unsigned char leds) -{ - if ( is_prep ) - pckbd_leds(leds); - else if ( is_chrp ) -#ifndef CONFIG_MAC_KEYBOARD - pckbd_leds(leds); -#else - if ( adb_hardware == ADB_NONE ) - pckbd_leds(leds); - else - mackbd_leds(leds); -#endif - else - mackbd_leds(leds); -} - static inline void kbd_init_hw(void) { - if ( is_prep ) - pckbd_init_hw(); - else if ( is_chrp ) -#ifndef CONFIG_MAC_KEYBOARD +#ifdef CONFIG_MAC_KEYBOARD + if (!is_prep) + mackbd_init_hw(); +#endif +#ifdef CONFIG_PC_KEYBOARD + if (is_prep || is_chrp) pckbd_init_hw(); -#else - if ( adb_hardware == ADB_NONE ) - pckbd_init_hw(); - else - mackbd_init_hw(); #endif - else - mackbd_init_hw(); } #endif /* CONFIG_APUS */ diff -ur linux/include/linux/kbd_ll.h linux-pmac/include/linux/kbd_ll.h --- linux/include/linux/kbd_ll.h Mon Jul 21 18:44:40 1997 +++ linux-pmac/include/linux/kbd_ll.h Sat Oct 24 21:12:14 1998 @@ -5,8 +5,35 @@ #ifndef _KBD_LL_H #define _KBD_LL_H +/* + * The kbd_operations struct contains pointers to the procedures + * which are supplied by the low-level keyboard driver and used + * by the keymapper (drivers/char/keyboard.c). + */ +struct kbd_ll_operations { + int (*setkeycode)(void *devid, unsigned int scancode, + unsigned int keycode); + int (*getkeycode)(void *devid, unsigned int scancode); + int (*pretranslate)(void *devid, unsigned char scancode, + char raw_mode); + int (*translate)(void *devid, unsigned char scancode, + unsigned char *keycode, char raw_mode); + char (*unexpected_up)(void *devid, unsigned char keycode); + void (*leds)(void *devid, unsigned char leds); + int sysrq_key; + unsigned char *sysrq_xlate; + int repeat_initial; /* initial delay for soft auto-repeat */ + int repeat_delay; /* delay between auto-repeats */ + unsigned char *dont_repeat; /* keys which don't auto-repeat */ +}; + extern struct pt_regs *kbd_pt_regs; void handle_scancode(unsigned char scancode); + +void *register_keyboard(struct kbd_ll_operations *ops, void *devid, + ushort **key_maps); /* returns kbd id */ +void unregister_keyboard(void *kbdid); +void kbd_handle_scancode(void *kbdid, int scancode); #endif /* _KBD_LL_H */ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |