From: Vojtech P. <vo...@us...> - 2002-01-24 19:51:29
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/keyboard In directory usw-pr-cvs1:/tmp/cvs-serv2610/linux/drivers/input/keyboard Added Files: arckbd.c cerf_keyb.c Log Message: Moving, updating to latest versions. --- NEW FILE: arckbd.c --- /* * linux/arch/arm/drivers/char1/keyb_arc.c * * Acorn keyboard driver for ARM Linux. * * The Acorn keyboard appears to have a ***very*** buggy reset protocol - * every reset behaves differently. We try to get round this by attempting * a few things... */ #include <linux/config.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/mm.h> #include <linux/slab.h> #include <linux/ptrace.h> #include <linux/signal.h> #include <linux/timer.h> #include <linux/random.h> #include <linux/ctype.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/bitops.h> #include <asm/keyboard.h> #include <asm/irq.h> #include <asm/ioc.h> #include <asm/hardware.h> #include "../../char/busmouse.h" extern void kbd_reset_kdown(void); #define VERSION 108 #define KBD_REPORT_ERR #define KBD_REPORT_UNKN #include <asm/io.h> #include <asm/system.h> static char kbd_txval[4]; static unsigned char kbd_txhead, kbd_txtail; #define KBD_INCTXPTR(ptr) ((ptr) = ((ptr) + 1) & 3) static int kbd_id = -1; static DECLARE_WAIT_QUEUE_HEAD(kbd_waitq); #ifdef CONFIG_KBDMOUSE static int mousedev; #endif /* * Protocol codes to send the keyboard. */ #define HRST 0xff /* reset keyboard */ #define RAK1 0xfe /* reset response */ #define RAK2 0xfd /* reset response */ #define BACK 0x3f /* Ack for first keyboard pair */ #define SMAK 0x33 /* Last data byte ack (key scanning + mouse movement scanning) */ #define MACK 0x32 /* Last data byte ack (mouse movement scanning) */ #define SACK 0x31 /* Last data byte ack (key scanning) */ #define NACK 0x30 /* Last data byte ack (no scanning, mouse data) */ #define RQMP 0x22 /* Request mouse data */ #define PRST 0x21 /* nothing */ #define RQID 0x20 /* Request ID */ #define UP_FLAG 1 #ifdef CONFIG_MAGIC_SYSRQ unsigned char a5kkbd_sysrq_xlate[] = { 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '£', 127, 0, 0, 0, 0, '/', '*', '#', 9, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\', 22, 23, 25, '7', '8', '9', '-', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', 13, '4', '5', '6', '+', 0, 0, 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, 0, '1', '2', '3', 0, 0, ' ', 0, 0, 0, 0, 0, '0', '.', 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; #endif /* * This array converts the scancode that we get from the keyboard to the * real rows/columns on the A5000 keyboard. This might be keyboard specific... * * It is these values that we use to maintain the key down array. That way, we * should pick up on the ghost key presses (which is what happens when you press * three keys, and the keyboard thinks you have pressed four!) * * Row 8 (0x80+c) is actually a column with one key per row. It is isolated from * the other keys, and can't cause these problems (its used for shift, ctrl, alt etc). * * Illegal scancodes are denoted by an 0xff (in other words, we don't know about * them, and can't process them for ghosts). This does however, cause problems with * autorepeat processing... */ static unsigned char scancode_2_colrow[256] = { 0x01, 0x42, 0x32, 0x33, 0x43, 0x56, 0x5a, 0x6c, 0x7c, 0x5c, 0x5b, 0x6b, 0x7b, 0x84, 0x70, 0x60, 0x11, 0x51, 0x62, 0x63, 0x44, 0x54, 0x55, 0x45, 0x46, 0x4a, 0x3c, 0x4b, 0x59, 0x49, 0x69, 0x79, 0x83, 0x40, 0x30, 0x3b, 0x39, 0x38, 0x31, 0x61, 0x72, 0x73, 0x64, 0x74, 0x75, 0x65, 0x66, 0x6a, 0x1c, 0x2c, 0x7a, 0x36, 0x48, 0x68, 0x78, 0x20, 0x2b, 0x29, 0x28, 0x81, 0x71, 0x22, 0x23, 0x34, 0x24, 0x25, 0x35, 0x26, 0x3a, 0x0c, 0x2a, 0x76, 0x10, 0x1b, 0x19, 0x18, 0x82, 0xff, 0x21, 0x12, 0x13, 0x14, 0x04, 0x05, 0x15, 0x16, 0x1a, 0x0a, 0x85, 0x77, 0x00, 0x0b, 0x09, 0x02, 0x80, 0x03, 0x87, 0x86, 0x06, 0x17, 0x27, 0x07, 0x37, 0x08, 0xff, }; #define BITS_PER_SHORT (8*sizeof(unsigned short)) static unsigned short ghost_down[128/BITS_PER_SHORT]; static void a5kkbd_key(unsigned int keycode, unsigned int up_flag) { unsigned int real_keycode; if (keycode > 0x72) { #ifdef KBD_REPORT_UNKN printk ("kbd: unknown scancode 0x%04x\n", keycode); #endif return; } if (keycode >= 0x70) { #ifdef CONFIG_KBDMOUSE if (mousedev >= 0) switch (keycode) { case 0x70: /* Left mouse button */ busmouse_add_buttons(mousedev, 4, up_flag ? 4 : 0); break; case 0x71: /* Middle mouse button */ busmouse_add_buttons(mousedev, 2, up_flag ? 2 : 0); break; case 0x72:/* Right mouse button */ busmouse_add_buttons(mousedev, 1, up_flag ? 1 : 0); break; } #endif return; } /* * We have to work out if we accept this key press as a real key, or * if it is a ghost. IE. If you press three keys, the keyboard will think * that you've pressed a fourth: (@ = key down, # = ghost) * * 0 1 2 3 4 5 6 7 * | | | | | | | | * 0-+-+-+-+-+-+-+-+- * | | | | | | | | * 1-+-@-+-+-+-@-+-+- * | | | | | | | | * 2-+-+-+-+-+-+-+-+- * | | | | | | | | * 3-+-@-+-+-+-#-+-+- * | | | | | | | | * * This is what happens when you have a matrix keyboard... */ real_keycode = scancode_2_colrow[keycode]; if ((real_keycode & 0x80) == 0) { int rr, kc = (real_keycode >> 4) & 7; int cc; unsigned short res, kdownkc; kdownkc = ghost_down[kc] | (1 << (real_keycode & 15)); for (rr = 0; rr < 128/BITS_PER_SHORT; rr++) if (rr != kc && (res = ghost_down[rr] & kdownkc)) { /* * we have found a second row with at least one key pressed in the * same column. */ for (cc = 0; res; res >>= 1) cc += (res & 1); if (cc > 1) return; /* ignore it */ } if (up_flag) clear_bit (real_keycode, ghost_down); else set_bit (real_keycode, ghost_down); } handle_scancode(keycode, !up_flag); } static inline void a5kkbd_sendbyte(unsigned char val) { kbd_txval[kbd_txhead] = val; KBD_INCTXPTR(kbd_txhead); enable_irq(IRQ_KEYBOARDTX); } static inline void a5kkbd_reset(void) { int i; for (i = 0; i < NR_SCANCODES/BITS_PER_SHORT; i++) ghost_down[i] = 0; kbd_reset_kdown(); } void a5kkbd_leds(unsigned char leds) { leds = ((leds & (1<<VC_SCROLLOCK))?4:0) | ((leds & (1<<VC_NUMLOCK))?2:0) | ((leds & (1<<VC_CAPSLOCK))?1:0); a5kkbd_sendbyte(leds); } /* Keyboard states: * 0 initial reset condition, receive HRST, send RRAK1 * 1 Sent RAK1, wait for RAK1, send RRAK2 * 2 Sent RAK2, wait for RAK2, send SMAK or RQID * 3 Sent RQID, expect KBID, send SMAK * 4 Sent SMAK, wait for anything * 5 Wait for second keyboard nibble for key pressed * 6 Wait for second keyboard nibble for key released * 7 Wait for second part of mouse data * * This function returns 1 when we successfully enter the IDLE state * (and hence need to do some keyboard processing). */ #define KBD_INITRST 0 #define KBD_RAK1 1 #define KBD_RAK2 2 #define KBD_ID 3 #define KBD_IDLE 4 #define KBD_KEYDOWN 5 #define KBD_KEYUP 6 #define KBD_MOUSE 7 static int handle_rawcode(unsigned int keyval) { static signed char kbd_mousedx = 0; signed char kbd_mousedy; static unsigned char kbd_state = KBD_INITRST; static unsigned char kbd_keyhigh = 0; if (keyval == HRST && kbd_state != KBD_INITRST && kbd_state != KBD_ID) { a5kkbd_sendbyte (HRST); a5kkbd_reset (); kbd_state = KBD_INITRST; } else switch(kbd_state) { case KBD_INITRST: /* hard reset - sent HRST */ if (keyval == HRST) { a5kkbd_sendbyte (RAK1); kbd_state = KBD_RAK1; } else if (keyval == RAK1) { /* Some A5000 keyboards are very fussy and don't follow Acorn's * specs - this appears to fix them, but them it might stop * them from being initialised. * fix by Philip Blundell */ printk(KERN_DEBUG "keyboard sent early RAK1 -- ignored\n"); } else goto kbd_wontreset; break; case KBD_RAK1: /* sent RAK1 - expect RAK1 and send RAK2 */ if (keyval == RAK1) { a5kkbd_sendbyte (RAK2); kbd_state = KBD_RAK2; } else goto kbd_wontreset; break; case KBD_RAK2: /* Sent RAK2 - expect RAK2 and send either RQID or SMAK */ if (keyval == RAK2) { if (kbd_id == -1) { a5kkbd_sendbyte (NACK); a5kkbd_sendbyte (RQID); kbd_state = KBD_ID; } else { a5kkbd_sendbyte (SMAK); kbd_state = KBD_IDLE; } } else goto kbd_wontreset; break; case KBD_ID: /* Sent RQID - expect KBID */ if (keyval == HRST) { kbd_id = -2; a5kkbd_reset (); a5kkbd_sendbyte (HRST); kbd_state = KBD_INITRST; wake_up (&kbd_waitq); } else if ((keyval & 0xc0) == 0x80) { kbd_id = keyval & 0x3f; a5kkbd_sendbyte (SMAK); kbd_state = KBD_IDLE; wake_up (&kbd_waitq); } break; case KBD_IDLE: /* Send SMAK, ready for any reply */ switch (keyval & 0xf0) { default: /* 0x00 - 0x7f */ kbd_mousedx = keyval & 0x40 ? keyval|0x80 : keyval; kbd_state = KBD_MOUSE; a5kkbd_sendbyte (BACK); break; case 0x80: case 0x90: case 0xa0: case 0xb0: if (kbd_id == -1) kbd_id = keyval & 0x3f; break; case 0xc0: kbd_keyhigh = keyval; kbd_state = KBD_KEYDOWN; a5kkbd_sendbyte (BACK); break; case 0xd0: kbd_keyhigh = keyval; kbd_state = KBD_KEYUP; a5kkbd_sendbyte (BACK); break; case 0xe0: case 0xf0: goto kbd_error; } break; case KBD_KEYDOWN: if ((keyval & 0xf0) != 0xc0) goto kbd_error; else { kbd_state = KBD_IDLE; a5kkbd_sendbyte (SMAK); if (((kbd_keyhigh ^ keyval) & 0xf0) == 0) a5kkbd_key ((keyval & 0x0f) | ((kbd_keyhigh << 4) & 0xf0), 0); } break; case KBD_KEYUP: if ((keyval & 0xf0) != 0xd0) goto kbd_error; else { kbd_state = KBD_IDLE; a5kkbd_sendbyte (SMAK); if (((kbd_keyhigh ^ keyval) & 0xf0) == 0) a5kkbd_key ((keyval & 0x0f) | ((kbd_keyhigh << 4) & 0xf0), UP_FLAG); } break; case KBD_MOUSE: if (keyval & 0x80) goto kbd_error; else { kbd_state = KBD_IDLE; a5kkbd_sendbyte (SMAK); kbd_mousedy = (char)(keyval & 0x40 ? keyval | 0x80 : keyval); #ifdef CONFIG_KBDMOUSE if (mousedev >= 0) busmouse_add_movement(mousedev, (int)kbd_mousedx, (int)kbd_mousedy); #endif } } return kbd_state == KBD_IDLE ? 1 : 0; kbd_wontreset: #ifdef KBD_REPORT_ERR printk ("kbd: keyboard won't reset (kbdstate %d, keyval %02X)\n", kbd_state, keyval); #endif mdelay(1); inb(IOC_KARTRX); a5kkbd_sendbyte (HRST); kbd_state = KBD_INITRST; return 0; kbd_error: #ifdef KBD_REPORT_ERR printk ("kbd: keyboard out of sync - resetting\n"); #endif a5kkbd_sendbyte (HRST); kbd_state = KBD_INITRST; return 0; } static void a5kkbd_rx(int irq, void *dev_id, struct pt_regs *regs) { kbd_pt_regs = regs; if (handle_rawcode(inb(IOC_KARTRX))) mark_bh (KEYBOARD_BH); } static void a5kkbd_tx(int irq, void *dev_id, struct pt_regs *regs) { outb (kbd_txval[kbd_txtail], IOC_KARTTX); KBD_INCTXPTR(kbd_txtail); if (kbd_txtail == kbd_txhead) disable_irq(irq); } #ifdef CONFIG_KBDMOUSE static struct busmouse a5kkbd_mouse = { 6, "kbdmouse", NULL, NULL, 7 }; #endif void __init a5kkbd_init_hw (void) { unsigned long flags; save_flags_cli (flags); if (request_irq (IRQ_KEYBOARDTX, a5kkbd_tx, 0, "keyboard", NULL) != 0) panic("Could not allocate keyboard transmit IRQ!"); disable_irq (IRQ_KEYBOARDTX); if (request_irq (IRQ_KEYBOARDRX, a5kkbd_rx, 0, "keyboard", NULL) != 0) panic("Could not allocate keyboard receive IRQ!"); (void)inb(IOC_KARTRX); restore_flags (flags); a5kkbd_sendbyte (HRST); /* send HRST (expect HRST) */ /* wait 1s for keyboard to initialise */ interruptible_sleep_on_timeout(&kbd_waitq, HZ); #ifdef CONFIG_KBDMOUSE mousedev = register_busmouse(&a5kkbd_mouse); if (mousedev < 0) printk(KERN_ERR "Unable to register mouse driver\n"); #endif printk (KERN_INFO "Keyboard driver v%d.%02d. (", VERSION/100, VERSION%100); if (kbd_id != -1) printk ("id=%d ", kbd_id); printk ("English)\n"); } --- NEW FILE: cerf_keyb.c --- /* cerf_keyb.c: This is the end. Daniel is writing a device driver!!! */ #include <linux/config.h> #include <linux/spinlock.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/tty.h> #include <linux/mm.h> #include <linux/signal.h> #include <linux/init.h> #include <linux/kbd_ll.h> #include <linux/delay.h> #include <linux/random.h> #include <linux/poll.h> #include <linux/miscdevice.h> #include <linux/slab.h> #include <linux/kbd_kern.h> #include <linux/smp_lock.h> #include <linux/timer.h> #include <asm/keyboard.h> #include <asm/bitops.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/system.h> #include <asm/io.h> #define KBD_REPORT_UNKN #define KBD_REPORT_ERR /* Report keyboard errors */ #define KBD_REPORT_UNKN /* Report unknown scan codes */ #define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */ #define KBD_NO_DATA (-1) /* No data */ #define KBD_REPEAT_START (0x20) #define KBD_REPEAT_CONTINUE (0x05) #define KBD_KEY_DOWN_MAX (0x10) #define UINT_LEN (20) #define SC_LIM (69) #define KBD_ROWS (5) #define KBD_COLUMNS (8) #define KBD_KEYUP (0x80) #define KBD_MODESCAN (0x7f) #define KBD_CAPSSCAN (0x3a) #define KBD_SHIFTSCAN (0x2a) #define KBD_NUMCURSCAN (0x7c) #define KBD_CTRLSCAN (0x1d) #define KBD_ALTSCAN (0x38) #define KBD_UP_OFF (0) #define KBD_UP_ON (1) #define KBD_DOWN (2) #define KBD_DOWN_HOLD (3) static unsigned char handle_kbd_event(void); static unsigned char kbd_read_input(void); static void column_set(unsigned int column); static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS]); static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED; static struct timer_list kbd_timer; static short mode_ena = 0; static short numcur_ena = 0; static short shift_ena = 0; #define E0_KPENTER 96 #define E0_RCTRL 97 #define E0_KPSLASH 98 #define E0_PRSCR 99 #define E0_RALT 100 #define E0_BREAK 101 /* (control-pause) */ #define E0_HOME 102 #define E0_UP 103 #define E0_PGUP 104 #define E0_LEFT 105 #define E0_RIGHT 106 #define E0_END 107 #define E0_DOWN 108 #define E0_PGDN 109 #define E0_INS 110 #define E0_DEL 111 #define E1_PAUSE 119 #define E0_MACRO 112 #define E0_F13 113 #define E0_F14 114 #define E0_HELP 115 #define E0_DO 116 #define E0_F17 117 #define E0_KPMINPLUS 118 #define E0_OK 124 #define E0_MSLW 125 #define E0_MSRW 126 #define E0_MSTM 127 static unsigned char e0_keys[128] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */ E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */ E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */ E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */ E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */ 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ }; static unsigned char cerf_normal_map[KBD_ROWS][KBD_COLUMNS] = { {KBD_ALTSCAN, KBD_MODESCAN, 0x1e, 0x30, 0x2e, 0x20, 0x00, 0x00}, {0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x00}, {0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x00}, {0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x00}, {0x2c, KBD_SHIFTSCAN, KBD_CTRLSCAN, 0x39, KBD_NUMCURSCAN, 0x2b, 0x1c, 0x00} }; static unsigned char cerf_mode_map[KBD_ROWS][KBD_COLUMNS] = { {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00}, {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00}, // {0x0d, 0x0c, 0x37, 0x35, 0x0d, 0x48, 0x28, 0x00}, {0x01, 0x33, 0x34, 0x00, 0x4b, 0x27, 0x4d, 0x00}, // {0x0f, 0x00, KBD_CAPSSCAN, 0x0e, 0x00, 0x50, 0x00, 0x00} }; static unsigned char cerf_numcur_map[KBD_ROWS][KBD_COLUMNS] = { {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00}, {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00}, {0x0d, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x4d, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00} }; static void column_set(unsigned int column) { if (column < 0) { CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF); CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF); } else { if(column < 4) { CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_A, 1 << (column % 4), 0xFF); CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF); } else { CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF); CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_B, 1 << (column % 4), 0xFF); } } } static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS]) { int i, j; for(i = 0; i < KBD_COLUMNS; i++) { column_set(i); udelay(50); for(j = 0; j < KBD_ROWS; j++) { if(mode_ena) codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_mode_map[j][i]?cerf_mode_map[j][i]:cerf_normal_map[j][i]):0; else if(numcur_ena) codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_numcur_map[j][i]?cerf_numcur_map[j][i]:cerf_normal_map[j][i]):0; else codeval[j][i] = (GPLR & (1 << (20 + j)))?cerf_normal_map[j][i]:0; } } column_set(-1); return 0; } static unsigned char kbd_read_input(void) { int i, j, k, l; unsigned char prev; static unsigned char count = 0; static unsigned char oldcodes[KBD_ROWS][KBD_COLUMNS]={{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}}; unsigned char inputcode[KBD_ROWS][KBD_COLUMNS]; memset(inputcode, 0, sizeof(unsigned char) * (KBD_ROWS * KBD_COLUMNS)); scancodes(inputcode); for(i = 0; i < KBD_COLUMNS; i++) { for(j = 0; j < KBD_ROWS; j++) { // if(oldcodes[j][i] == 0xe0) // oldcodes[j][i] = if(oldcodes[j][i] != inputcode[j][i]) { // Value of the key before entering this function prev = oldcodes[j][i]; // KEYUP if(inputcode[j][i] == 0 && oldcodes[j][i] != 0 && !(oldcodes[j][i] & KBD_KEYUP)) { oldcodes[j][i] |= KBD_KEYUP; if(mode_ena == KBD_UP_ON) mode_ena = KBD_UP_OFF; if(prev == KBD_MODESCAN) if(mode_ena == KBD_DOWN_HOLD) mode_ena = KBD_UP_OFF; else if(mode_ena == KBD_DOWN) mode_ena = KBD_UP_ON; if(mode_ena == KBD_DOWN) mode_ena = KBD_DOWN_HOLD; } // RESET KEYUP else if(oldcodes[j][i] & KBD_KEYUP) oldcodes[j][i] = 0; // KEY DOWN else { oldcodes[j][i] = inputcode[j][i]; // Parse out mode modifiers before the keyboard interpreter can touch them if(inputcode[j][i] == KBD_MODESCAN) { if(!mode_ena) mode_ena = KBD_DOWN; continue; } if(inputcode[j][i] == KBD_NUMCURSCAN) { numcur_ena = numcur_ena?0:1; continue; } } //printk("Modified: (%#x,%#x), ipv:%#x, To: (%#.2x), From: (%#.2x), Flags:%d,%d,%d\r\n", j, i, inputcode[j][i], oldcodes[j][i], prev, mode_ena, shift_ena, numcur_ena); return oldcodes[j][i]; } } } return (unsigned char)(KBD_NO_DATA); } int cerf_kbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode) { static int prev_scancode; if (scancode == 0xe0 || scancode == 0xe1) { prev_scancode = scancode; return 0; } if (scancode == 0x00 || scancode == 0xff) { prev_scancode = 0; return 0; } scancode &= 0x7f; if (prev_scancode) { if (prev_scancode != 0xe0) { if (prev_scancode == 0xe1 && scancode == 0x1d) { prev_scancode = 0x100; return 0; } else if (prev_scancode == 0x100 && scancode == 0x45) { prev_scancode = 0; } else { #ifdef KBD_REPORT_UNKN if (!raw_mode) printk(KERN_INFO "keyboard: unknown e1 escape sequence\n"); #endif prev_scancode = 0; return 0; } } else { prev_scancode = 0; if (scancode == 0x2a || scancode == 0x36) return 0; else { #ifdef KBD_REPORT_UNKN if (!raw_mode) printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n", scancode); #endif return 0; } } } else *keycode = scancode; return 1; } static inline void handle_keyboard_event(unsigned char scancode) { if(scancode != (unsigned char)(KBD_NO_DATA)) { #ifdef CONFIG_VT handle_scancode(scancode, !(scancode & KBD_KEYUP)); #endif tasklet_schedule(&keyboard_tasklet); } } static unsigned char handle_kbd_event(void) { unsigned char scancode; scancode = kbd_read_input(); handle_keyboard_event(scancode); return 0; } /* Handle the automatic interrupts handled by the timer */ static void keyboard_interrupt(unsigned long foo) { spin_lock_irq(&kbd_controller_lock); handle_kbd_event(); spin_unlock_irq(&kbd_controller_lock); kbd_timer.expires = 8 + jiffies; kbd_timer.data = 0x00000000; kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt; add_timer(&kbd_timer); } void cerf_leds(unsigned char leds) { } char cerf_unexpected_up(unsigned char keycode) { return 0; } int cerf_getkeycode(unsigned int scancode) { return 0; } int cerf_setkeycode(unsigned int scancode, unsigned int keycode) { return 0; } void cerf_kbd_init_hw(void) { printk("Starting Cerf PDA Keyboard Driver... "); k_setkeycode = cerf_setkeycode; k_getkeycode = cerf_getkeycode; k_translate = cerf_kbd_translate; k_unexpected_up = cerf_unexpected_up; k_leds = cerf_leds; GPDR &= ~(GPIO_GPIO(20) | GPIO_GPIO(21) | GPIO_GPIO(22) | GPIO_GPIO(23) | GPIO_GPIO(24)); kbd_timer.expires = 40 + jiffies; kbd_timer.data = 0x00000000; kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt; add_timer(&kbd_timer); printk("Done\r\n"); } |