Commit 66562390 authored by Vojtech Pavlik's avatar Vojtech Pavlik

This is the last and most important step in the input core conversion.

It removes pc_keyb and keybdev, connecting keyboard.c straight into
the input core. No arch specific keyboard.c code anymore - every
keyboard driver is now expected to be an input driver.
parent ea675330
......@@ -7,7 +7,6 @@
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/pm.h>
#include <asm/keyboard.h>
#include <asm/system.h>
#include <linux/bootmem.h>
......@@ -393,21 +392,13 @@ static __init int init_ints_after_s1(struct dmi_blacklist *d)
}
/*
* Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it
* was disabled before the suspend. Linux gets terribly confused by that.
* Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it was
* disabled before the suspend. Linux used to get terribly confused by that.
*/
typedef void (pm_kbd_func) (void);
static __init int broken_ps2_resume(struct dmi_blacklist *d)
{
#ifdef CONFIG_VT
if (pm_kbd_request_override == NULL)
{
pm_kbd_request_override = pckbd_pm_resume;
printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround enabled.\n", d->ident);
}
#endif
printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround hopefully not needed.\n", d->ident);
return 0;
}
......
......@@ -633,25 +633,6 @@ CONFIG_BUSMOUSE
The module will be called busmouse.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_PSMOUSE
The PS/2 mouse connects to a special mouse port that looks much like
the keyboard port (small circular connector with 6 pins). This way,
the mouse does not use any serial ports. This port can also be used
for other input devices like light pens, tablets, keypads. Compaq,
AST and IBM all use this as their mouse port on currently shipping
machines. The trackballs of some laptops are PS/2 mice also. In
particular, the C&T 82C710 mouse on TI Travelmates is a PS/2 mouse.
Although PS/2 mice are not technically bus mice, they are explained
in detail in the Busmouse-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>.
When using a PS/2 mouse, you can get problems if you want to use the
mouse both on the Linux console and under X. Using the "-R" option
of the Linux mouse managing program gpm (available from
<ftp://gnu.systemy.it/pub/gpm/>) solves this problem, or you can get
the "mconv2" utility from <ftp://ibiblio.org/pub/Linux/system/mouse/>.
CONFIG_QIC02_TAPE
If you have a non-SCSI tape drive like that, say Y. Or, if you want
to compile this driver as a module ( = code which can be inserted in
......
......@@ -58,8 +58,6 @@ if [ "$CONFIG_IT8712" = "y" ]; then
if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then
define_bool CONFIG_IT8172_CIR y
else
bool ' Enable PS2 Keyboard Support' CONFIG_PC_KEYB
fi
bool 'Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0
bool 'Enable Smart Card Reader 1 Support ' CONFIG_IT8172_SCR1
fi
......@@ -89,7 +87,6 @@ source drivers/i2c/Config.in
mainmenu_option next_comment
comment 'Mice'
tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
endmenu
tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE
......
......@@ -17,115 +17,27 @@ export-objs := busmouse.o console.o keyboard.o sysrq.o \
sonypi.o tty_io.o tty_ioctl.o generic_serial.o rtc.o \
ip2main.o
KEYMAP =defkeymap.o
KEYBD =pc_keyb.o
CONSOLE =console.o
ifeq ($(ARCH),s390)
KEYMAP =
KEYBD =
CONSOLE =
endif
ifeq ($(ARCH),mips)
ifneq ($(CONFIG_PC_KEYB),y)
KEYBD =
endif
endif
ifeq ($(ARCH),s390x)
KEYMAP =
KEYBD =
CONSOLE =
endif
ifeq ($(ARCH),m68k)
ifdef CONFIG_AMIGA
KEYBD = amikeyb.o
else
KEYBD =
endif
ifneq ($(ARCH),s390)
ifneq ($(ARCH),s390x)
ifneq ($(ARCH),um)
KEYMAP =defkeymap.o
CONSOLE =console.o
endif
endif
endif
ifdef CONFIG_Q40
KEYBD += q40_keyb.o
SERIAL = serial.o
endif
ifdef CONFIG_APOLLO
KEYBD += dn_keyb.o
endif
ifeq ($(ARCH),arm)
ifneq ($(CONFIG_PC_KEYMAP),y)
KEYMAP =
endif
ifneq ($(CONFIG_PC_KEYB),y)
KEYBD =
endif
endif
ifeq ($(ARCH),um)
KEYMAP =
KEYBD =
CONSOLE =
endif
ifeq ($(ARCH),sh)
KEYMAP =
KEYBD =
CONSOLE =
ifeq ($(CONFIG_SH_HP600),y)
KEYMAP = defkeymap.o
KEYBD = scan_keyb.o hp600_keyb.o
CONSOLE = console.o
endif
ifeq ($(CONFIG_SH_DMIDA),y)
# DMIDA does not connect the HD64465 PS/2 keyboard port
# but we allow for USB keyboards to be plugged in.
KEYMAP = defkeymap.o
KEYBD = # hd64465_keyb.o pc_keyb.o
CONSOLE = console.o
endif
ifeq ($(CONFIG_SH_EC3104),y)
KEYMAP = defkeymap.o
KEYBD = ec3104_keyb.o
CONSOLE = console.o
endif
ifeq ($(CONFIG_SH_DREAMCAST),y)
KEYMAP = defkeymap.o
KEYBD =
CONSOLE = console.o
endif
endif
ifeq ($(CONFIG_DECSTATION),y)
KEYMAP =
KEYBD =
SERIAL = decserial.o
endif
ifeq ($(CONFIG_BAGET_MIPS),y)
KEYBD =
endif
ifeq ($(CONFIG_QTRONIX_KEYBOARD),y)
KEYBD = qtronix.o
KEYMAP = qtronixmap.o
endif
ifeq ($(CONFIG_SPARC32),y)
KEYBD =
endif
ifeq ($(CONFIG_SPARC64),y)
KEYBD =
endif
obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
#obj-$(CONFIG_SERIAL) += $(SERIAL) # Fix for decserial.o
obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD)
obj-$(CONFIG_VT) += keyboard.o $(KEYMAP)
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
......
......@@ -21,6 +21,7 @@
*
* 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
* 30-07-98: Dead keys redone, aeb@cwi.nl.
* 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
*/
#include <linux/config.h>
......@@ -32,63 +33,35 @@
#include <linux/string.h>
#include <linux/random.h>
#include <linux/init.h>
#include <asm/keyboard.h>
#include <asm/bitops.h>
#include <linux/slab.h>
#include <linux/console_struct.h>
#include <linux/kbd_kern.h>
#include <linux/kbd_diacr.h>
#include <linux/vt_kern.h>
#include <linux/kbd_ll.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);
#define SIZE(x) (sizeof(x)/sizeof((x)[0]))
/*
* Exported functions/variables
*/
#ifndef KBD_DEFMODE
#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
#endif
#ifndef KBD_DEFLEDS
/*
* Some laptops take the 789uiojklm,. keys as number pad when NumLock
* is on. This seems a good reason to start with NumLock off.
*/
#define KBD_DEFLEDS 0
#endif
#ifndef KBD_DEFLOCK
#define KBD_DEFLOCK 0
#endif
void (*kbd_ledfunc)(unsigned int led);
EXPORT_SYMBOL(handle_scancode);
EXPORT_SYMBOL(kbd_ledfunc);
/* kbd_pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
struct pt_regs * kbd_pt_regs;
struct pt_regs *kbd_pt_regs;
void compute_shiftstate(void);
/*
* Handler Tables.
*/
/* Key types processed even in raw modes */
#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT))
#define SPECIALS_ALLOWED_IN_RAW_MODE (1 << KVAL(K_SAK))
#define K_HANDLERS\
k_self, k_fn, k_spec, k_pad,\
k_dead, k_cons, k_cur, k_shift,\
k_meta, k_ascii, k_lock, k_lowercase,\
k_slock, k_dead2, k_ignore, k_ignore
k_slock, k_dead2, k_ignore, k_ignore
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
char up_flag);
......@@ -107,74 +80,70 @@ static fn_handler_fn FN_HANDLERS;
static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
/*
* Variables/functions exported for vt.c
* Variables/functions exported for vt_ioctl.c
*/
/* maximum values each key_handler can handle */
const int max_vals[] = {
255, SIZE(func_table) - 1, SIZE(fn_handler) - 1, NR_PAD - 1,
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, NR_LOCK - 1, 255
};
const int NR_TYPES = SIZE(max_vals);
const int NR_TYPES = ARRAY_SIZE(max_vals);
struct kbd_struct kbd_table[MAX_NR_CONSOLES];
static struct kbd_struct *kbd = kbd_table;
int spawnpid, spawnsig;
/*
* Translation of escaped scancodes to keycodes.
* This is now user-settable (for machines were it makes sense).
* Translation of scancodes to keycodes.
*/
int getkeycode(unsigned int scancode)
{
return kbd_getkeycode(scancode);
return 0; /* FIXME */
}
int setkeycode(unsigned int scancode, unsigned int keycode)
{
return kbd_setkeycode(scancode, keycode);
return 0; /* FIXME */
}
/*
* Variables/function exported for console.c
* Variables/function exported for vt.c
*/
int shift_state = 0;
/*
* Internal Data.
*/
static unsigned long key_down[256/BITS_PER_LONG]; /* keyboard key bitmap */
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
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 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 {
unsigned int *addr;
unsigned int mask;
unsigned char valid:1;
unsigned int *addr;
unsigned int mask;
unsigned char valid:1;
} ledptrs[3];
struct kbd_struct kbd_table[MAX_NR_CONSOLES];
static struct kbd_struct *kbd = kbd_table;
#ifdef CONFIG_MAGIC_SYSRQ
static int sysrq_pressed;
#endif
/*
* Helper Functions.
*/
void put_queue(struct vc_data *vc, int ch)
static void put_queue(struct vc_data *vc, int ch)
{
struct tty_struct *tty = vc->vc_tty;
struct tty_struct *tty = vc->vc_tty;
if (tty) {
tty_insert_flip_char(tty, ch, 0);
......@@ -215,23 +184,25 @@ static void applkey(struct vc_data *vc, int key, char mode)
void to_utf8(struct vc_data *vc, ushort c)
{
if (c < 0x80)
/* 0******* */
/* 0******* */
put_queue(vc, c);
else if (c < 0x800) {
/* 110***** 10****** */
/* 110***** 10****** */
put_queue(vc, 0xc0 | (c >> 6));
put_queue(vc, 0x80 | (c & 0x3f));
} else {
/* 1110**** 10****** 10*******/
/* 1110**** 10****** 10****** */
put_queue(vc, 0xe0 | (c >> 12));
put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
put_queue(vc, 0x80 | (c & 0x3f));
}
}
/* 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)
{
int i, j, k, sym, val;
......@@ -239,28 +210,28 @@ void compute_shiftstate(void)
shift_state = 0;
memset(shift_down, 0, sizeof(shift_down));
for (i = 0; i < SIZE(key_down); i++) {
for (i = 0; i < ARRAY_SIZE(key_down); i++) {
if (!key_down[i])
continue;
continue;
k = i*BITS_PER_LONG;
for (j = 0; j < BITS_PER_LONG; j++, k++) {
if (!test_bit(k, key_down))
continue;
sym = U(plain_map[k]);
if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
continue;
val = KVAL(sym);
if (val == KVAL(K_CAPSSHIFT))
val = KVAL(K_SHIFT);
val = KVAL(sym);
if (val == KVAL(K_CAPSSHIFT))
val = KVAL(K_SHIFT);
shift_down[val]++;
shift_state |= (1<<val);
shift_state |= (1 << val);
}
}
}
......@@ -360,7 +331,7 @@ static void fn_num(struct vc_data *vc)
static void fn_bare_num(struct vc_data *vc)
{
if (!rep)
chg_vc_kbd_led(kbd,VC_NUMLOCK);
chg_vc_kbd_led(kbd, VC_NUMLOCK);
}
static void fn_lastcons(struct vc_data *vc)
......@@ -453,9 +424,6 @@ static void fn_SAK(struct vc_data *vc)
if (tty)
do_SAK(tty);
reset_vc(fg_console);
#if 0
do_unblank_screen(); /* not in interrupt routine? */
#endif
}
static void fn_null(struct vc_data *vc)
......@@ -474,17 +442,18 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
{
if (up_flag)
return;
if (value >= SIZE(fn_handler))
return;
if ((kbd->kbdmode == VC_RAW || kbd->kbdmode == VC_MEDIUMRAW) &&
!(SPECIALS_ALLOWED_IN_RAW_MODE & (1 << value)))
if (value >= ARRAY_SIZE(fn_handler))
return;
if ((kbd->kbdmode == VC_RAW ||
kbd->kbdmode == VC_MEDIUMRAW) &&
value != K_SAK)
return; /* SAK is allowed even in raw mode */
fn_handler[value](vc);
}
static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
{
printk(KERN_ERR "keyboard.c: do_lowercase was called - impossible\n");
printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
}
static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
......@@ -503,22 +472,6 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
put_queue(vc, value);
}
#define A_GRAVE '`'
#define A_ACUTE '\''
#define A_CFLEX '^'
#define A_TILDE '~'
#define A_DIAER '"'
#define A_CEDIL ','
static unsigned char ret_diacr[NR_DEAD] =
{A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL };
/* Obsolete - for backwards compatibility only */
static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
{
value = ret_diacr[value];
k_dead2(vc, value,up_flag);
}
/*
* Handle dead key. Note that we now may have several
* dead keys modifying the same character. Very useful
......@@ -528,10 +481,19 @@ static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
{
if (up_flag)
return;
diacr = (diacr ? handle_diacr(vc, value) : value);
}
/*
* Obsolete - for backwards compatibility only
*/
static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
{
static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
value = ret_diacr[value];
k_dead2(vc, value, up_flag);
}
static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
{
if (up_flag)
......@@ -543,13 +505,22 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
{
if (up_flag)
return;
if (value < SIZE(func_table)) {
if (value < ARRAY_SIZE(func_table)) {
if (func_table[value])
puts_queue(vc, func_table[value]);
} else
printk(KERN_ERR "k_fn called with value=%d\n", value);
}
static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
{
static const char *cur_chars = "BDCA";
if (up_flag)
return;
applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
}
static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
{
static const char *pad_chars = "0123456789+-*/\015,.?()";
......@@ -559,12 +530,12 @@ static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
return; /* no action, if this is a key release */
/* kludge... shift forces cursor/number keys */
if (vc_kbd_mode(kbd,VC_APPLIC) && !shift_down[KG_SHIFT]) {
if (vc_kbd_mode(kbd, VC_APPLIC) && !shift_down[KG_SHIFT]) {
applkey(vc, app_map[value], 1);
return;
}
if (!vc_kbd_led(kbd,VC_NUMLOCK))
if (!vc_kbd_led(kbd, VC_NUMLOCK))
switch (value) {
case KVAL(K_PCOMMA):
case KVAL(K_PDOT):
......@@ -607,24 +578,16 @@ static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
put_queue(vc, 10);
}
static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
{
static const char *cur_chars = "BDCA";
if (up_flag)
return;
applkey(vc, cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
}
static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
{
int old_state = shift_state;
if (rep)
return;
/* Mimic typewriter:
a CapsShift key acts like Shift but undoes CapsLock */
/*
* Mimic typewriter:
* a CapsShift key acts like Shift but undoes CapsLock
*/
if (value == KVAL(K_CAPSSHIFT)) {
value = KVAL(K_SHIFT);
if (!up_flag)
......@@ -632,8 +595,10 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
}
if (up_flag) {
/* handle the case that two shift or control
keys are depressed simultaneously */
/*
* handle the case that two shift or control
* keys are depressed simultaneously
*/
if (shift_down[value])
shift_down[value]--;
} else
......@@ -642,14 +607,14 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
if (shift_down[value])
shift_state |= (1 << value);
else
shift_state &= ~ (1 << value);
shift_state &= ~(1 << value);
/* kludge */
if (up_flag && shift_state != old_state && npadch != -1) {
if (kbd->kbdmode == VC_UNICODE)
to_utf8(vc, npadch & 0xffff);
to_utf8(vc, npadch & 0xffff);
else
put_queue(vc, npadch & 0xff);
put_queue(vc, npadch & 0xff);
npadch = -1;
}
}
......@@ -673,17 +638,19 @@ static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
if (up_flag)
return;
if (value < 10) /* decimal input of code, while Alt depressed */
base = 10;
else { /* hexadecimal input of code, while AltGr depressed */
value -= 10;
base = 16;
if (value < 10) {
/* decimal input of code, while Alt depressed */
base = 10;
} else {
/* hexadecimal input of code, while AltGr depressed */
value -= 10;
base = 16;
}
if (npadch == -1)
npadch = value;
npadch = value;
else
npadch = npadch * base + value;
npadch = npadch * base + value;
}
static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
......@@ -695,7 +662,7 @@ static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
{
k_shift(vc, value,up_flag);
k_shift(vc, value, up_flag);
if (up_flag || rep)
return;
chg_vc_kbd_slock(kbd, value);
......@@ -711,59 +678,54 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
* or (ii) whatever pattern of lights people want to show using KDSETLED,
* or (iii) specified bits of specified words in kernel memory.
*/
unsigned char getledstate(void) {
return ledstate;
}
void setledstate(struct kbd_struct *kbd, unsigned int led) {
if (!(led & ~7)) {
ledioctl = led;
kbd->ledmode = LED_SHOW_IOCTL;
} else
kbd->ledmode = LED_SHOW_FLAGS;
set_leds();
}
void register_leds(int console, unsigned int led,
unsigned int *addr, unsigned int mask) {
struct kbd_struct *kbd = kbd_table + console;
if (led < 3) {
ledptrs[led].addr = addr;
ledptrs[led].mask = mask;
ledptrs[led].valid = 1;
kbd->ledmode = LED_SHOW_MEM;
} else
kbd->ledmode = LED_SHOW_FLAGS;
}
static inline unsigned char getleds(void){
struct kbd_struct *kbd = kbd_table + fg_console;
unsigned char leds;
if (kbd->ledmode == LED_SHOW_IOCTL)
return ledioctl;
leds = kbd->ledflagstate;
if (kbd->ledmode == LED_SHOW_MEM) {
if (ledptrs[0].valid) {
if (*ledptrs[0].addr & ledptrs[0].mask)
leds |= 1;
else
leds &= ~1;
}
if (ledptrs[1].valid) {
if (*ledptrs[1].addr & ledptrs[1].mask)
leds |= 2;
else
leds &= ~2;
}
if (ledptrs[2].valid) {
if (*ledptrs[2].addr & ledptrs[2].mask)
leds |= 4;
else
leds &= ~4;
unsigned char getledstate(void)
{
return ledstate;
}
void setledstate(struct kbd_struct *kbd, unsigned int led)
{
if (!(led & ~7)) {
ledioctl = led;
kbd->ledmode = LED_SHOW_IOCTL;
} else
kbd->ledmode = LED_SHOW_FLAGS;
set_leds();
}
void register_leds(struct kbd_struct *kbd, unsigned int led,
unsigned int *addr, unsigned int mask)
{
if (led < 3) {
ledptrs[led].addr = addr;
ledptrs[led].mask = mask;
ledptrs[led].valid = 1;
kbd->ledmode = LED_SHOW_MEM;
} else
kbd->ledmode = LED_SHOW_FLAGS;
}
static inline unsigned char getleds(void)
{
struct kbd_struct *kbd = kbd_table + fg_console;
unsigned char leds;
int i;
if (kbd->ledmode == LED_SHOW_IOCTL)
return ledioctl;
leds = kbd->ledflagstate;
if (kbd->ledmode == LED_SHOW_MEM) {
for (i = 0; i < 3; i++)
if (ledptrs[i].valid) {
if (*ledptrs[i].addr & ledptrs[i].mask)
leds |= (1 << i);
else
leds &= ~(1 << i);
}
}
}
return leds;
return leds;
}
/*
......@@ -782,175 +744,270 @@ static inline unsigned char getleds(void){
static void kbd_bh(unsigned long dummy)
{
struct input_handle *handle;
unsigned char leds = getleds();
if (leds != ledstate) {
ledstate = leds;
kbd_leds(leds);
if (kbd_ledfunc) kbd_ledfunc(leds);
for (handle = kbd_handler.handle; handle; handle = handle->hnext) {
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;
}
EXPORT_SYMBOL(keyboard_tasklet);
DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
void handle_scancode(unsigned char scancode, int down)
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC)
static int x86_sysrq_alt = 0;
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,373,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,115,112,125,121,123,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 };
#ifdef CONFIG_MAC_EMUMOUSEBTN
extern int mac_hid_mouse_emulate_buttons(int, int, int);
#endif /* CONFIG_MAC_EMUMOUSEBTN */
static int emulate_raw(struct vc_data *vc, unsigned int keycode,
unsigned char up_flag)
{
#ifdef CONFIG_MAC_EMUMOUSEBTN
if (mac_hid_mouse_emulate_buttons(1, keycode, !up_flag))
return 0;
#endif /* CONFIG_MAC_EMUMOUSEBTN */
if (keycode > 255 || !x86_keycodes[keycode])
return -1;
if (keycode == KEY_PAUSE) {
put_queue(vc, 0xe1);
put_queue(vc, 0x1d | up_flag);
put_queue(vc, 0x45 | up_flag);
return 0;
}
if (keycode == KEY_SYSRQ && x86_sysrq_alt) {
put_queue(vc, 0x54 | up_flag);
return 0;
}
if (x86_keycodes[keycode] & 0x100)
put_queue(vc, 0xe0);
put_queue(vc, (x86_keycodes[keycode] & 0x7f) | up_flag);
if (keycode == KEY_SYSRQ) {
put_queue(vc, 0xe0);
put_queue(vc, 0x37 | up_flag);
}
if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
x86_sysrq_alt = !up_flag;
return 0;
}
#else
#warning "Cannot generate rawmode keyboard for your architecture yet."
static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
{
if (keycode > 127)
return -1;
put_queue(vc, keycode | up_flag);
return 0;
}
#endif
void kbd_keycode(unsigned int keycode, int down)
{
struct vc_data *vc = vc_cons[fg_console].d;
char up_flag = down ? 0 : 0200;
unsigned short keysym, *key_map;
unsigned char type, raw_mode;
struct tty_struct *tty;
unsigned char keycode;
char raw_mode;
int shift_final;
pm_access(pm_kbd);
add_keyboard_randomness(scancode | up_flag);
if (down != 2)
add_keyboard_randomness((keycode << 1) ^ down);
tty = vc->vc_tty;
if (tty && (!tty->driver_data)) {
/*
* We touch the tty structure via the ttytab array
* without knowing whether or not tty is open, which
* is inherently dangerous. We currently rely on that
* fact that console_open sets tty->driver_data when
* it opens it, and clears it when it closes it.
*/
tty = NULL;
/* No driver data? Strange. Okay we fix it then. */
tty->driver_data = vc;
}
kbd = kbd_table + fg_console;
if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
put_queue(vc, scancode | up_flag);
/* 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 ((raw_mode = (kbd->kbdmode == VC_RAW)))
if (emulate_raw(vc, keycode, !down << 7))
printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
if (kbd->kbdmode == VC_MEDIUMRAW) {
/*
* This is extended medium raw mode, with keys above 127
* encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
* the 'up' flag if needed. 0 is reserved, so this shouldn't
* interfere with anything else. The two bytes after 0 will
* always have the up flag set not to interfere with older
* applications. This allows for 16384 different keycodes,
* which should be enough.
*/
if (keycode < 128) {
put_queue(vc, keycode | (!down << 7));
} else {
put_queue(vc, !down << 7);
put_queue(vc, (keycode >> 7) | 0x80);
put_queue(vc, keycode | 0x80);
}
raw_mode = 1;
}
/*
* Convert scancode to keycode
*/
if (!kbd_translate(scancode, &keycode, raw_mode))
goto out;
rep = (down == 2);
/*
* 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 (rep && (!vc_kbd_mode(kbd, 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
* characters get aren't echoed locally. This makes key repeat
* usable with slow applications and under heavy loads.
*/
return;
}
if (up_flag) {
rep = 0;
if(!test_and_clear_bit(keycode, key_down))
up_flag = kbd_unexpected_up(keycode);
} else
rep = test_and_set_bit(keycode, key_down);
#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
if (keycode == SYSRQ_KEY) {
sysrq_pressed = !up_flag;
goto out;
} else if (sysrq_pressed) {
if (!up_flag) {
handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, tty);
goto out;
}
shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
key_map = key_maps[shift_final];
if (!key_map) {
compute_shiftstate();
kbd->slockstate = 0;
return;
}
#endif
if (kbd->kbdmode == VC_MEDIUMRAW) {
/* soon keycodes will require more than one byte */
put_queue(vc, keycode + up_flag);
raw_mode = 1; /* Most key classes will be ignored */
keysym = key_map[keycode];
type = KTYP(keysym);
if (type < 0xf0) {
if (down && !raw_mode) to_utf8(vc, keysym);
return;
}
/*
* Small change in philosophy: earlier we defined repetition by
* rep = keycode == prev_keycode;
* prev_keycode = keycode;
* but now by the fact that the depressed key was down already.
* Does this ever make a difference? Yes.
*/
type -= 0xf0;
/*
* Repeat a key only if the input buffers are empty or the
* characters get echoed locally. This makes key repeat usable
* with slow applications and under heavy loads.
*/
if (!rep ||
(vc_kbd_mode(kbd,VC_REPEAT) && tty &&
(L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
u_short keysym;
u_char type;
/* the XOR below used to be an OR */
int shift_final = (shift_state | kbd->slockstate) ^
kbd->lockstate;
ushort *key_map = key_maps[shift_final];
if (key_map != NULL) {
keysym = key_map[keycode];
type = KTYP(keysym);
if (type >= 0xf0) {
type -= 0xf0;
if (raw_mode && ! (TYPES_ALLOWED_IN_RAW_MODE & (1 << type)))
goto out;
if (type == KT_LETTER) {
type = KT_LATIN;
if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
if (key_map)
keysym = key_map[keycode];
}
}
(*k_handler[type])(vc, 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(vc, keysym);
}
} else {
/* maybe beep? */
/* we have at least to update shift_state */
#if 1 /* how? two almost equivalent choices follow */
compute_shiftstate();
kbd->slockstate = 0; /* play it safe */
#else
keysym = U(plain_map[keycode]);
type = KTYP(keysym);
if (type == KT_SHIFT)
(*key_handler[type])(keysym & 0xff, up_flag);
#endif
if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
return;
if (type == KT_LETTER) {
type = KT_LATIN;
if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
key_map = key_maps[shift_final ^ (1 << KG_SHIFT)];
if (key_map)
keysym = key_map[keycode];
}
}
out:
do_poke_blanked_console = 1;
schedule_console_callback();
(*k_handler[type])(vc, keysym & 0xff, !down);
if (type != KT_SLOCK)
kbd->slockstate = 0;
}
int __init kbd_init(void)
static void kbd_event(struct input_handle *handle, unsigned int event_type,
unsigned int keycode, int down)
{
if (event_type != EV_KEY)
return;
kbd_keycode(keycode, down);
tasklet_schedule(&keyboard_tasklet);
}
static char kbd_name[] = "kbd";
/*
* When a keyboard (or other input device) is found, the kbd_connect
* function is called. The function then looks at the device, and if it
* likes it, it can open it and get events from it. In this (kbd_connect)
* function, we should decide which VT to bind that keyboard to initially.
*/
static struct input_handle *kbd_connect(struct input_handler *handler,
struct input_dev *dev,
struct input_device_id *id)
{
struct input_handle *handle;
int i;
struct kbd_struct kbd0;
kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
kbd0.ledmode = LED_SHOW_FLAGS;
kbd0.lockstate = KBD_DEFLOCK;
kbd0.slockstate = 0;
kbd0.modeflags = KBD_DEFMODE;
kbd0.kbdmode = VC_XLATE;
for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
kbd_table[i] = kbd0;
kbd_init_hw();
for (i = KEY_RESERVED; i < BTN_MISC; i++)
if (test_bit(i, dev->keybit)) break;
tasklet_enable(&keyboard_tasklet);
tasklet_schedule(&keyboard_tasklet);
if ((i == BTN_MISC) && !test_bit(EV_SND, dev->evbit))
return NULL;
if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL;
memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
handle->name = kbd_name;
input_open_device(handle);
return handle;
}
static void kbd_disconnect(struct input_handle *handle)
{
input_close_device(handle);
kfree(handle);
}
static struct input_device_id kbd_ids[] = {
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT,
evbit: { BIT(EV_KEY) },
},
pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_kbd_request_override);
{
flags: INPUT_DEVICE_ID_MATCH_EVBIT,
evbit: { BIT(EV_SND) },
},
{ }, /* Terminating entry */
};
MODULE_DEVICE_TABLE(input, kbd_ids);
static struct input_handler kbd_handler = {
event: kbd_event,
connect: kbd_connect,
disconnect: kbd_disconnect,
name: "kbd",
id_table: kbd_ids,
};
int __init kbd_init(void)
{
tasklet_enable(&keyboard_tasklet);
tasklet_schedule(&keyboard_tasklet);
input_register_handler(&kbd_handler);
return 0;
}
/*
* linux/drivers/char/pc_keyb.c
*
* Separation of the PC low-level part by Geert Uytterhoeven, May 1997
* See keyboard.c for the whole history.
*
* Major cleanup by Martin Mares, May 1997
*
* Combined the keyboard and PS/2 mouse handling into one file,
* because they share the same hardware.
* Johan Myreen <jem@iki.fi> 1998-10-08.
*
* Code fixes to handle mouse ACKs properly.
* C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
*
*/
#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/vt_kern.h>
#include <linux/smp_lock.h>
#include <linux/kd.h>
#include <linux/pm.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>
/* Some configuration switches are present in the include file... */
#include <linux/pc_keyb.h>
/* Simple translation table for the SysRq keys */
#ifdef CONFIG_MAGIC_SYSRQ
unsigned char pckbd_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 */
#endif
static void kbd_write_command_w(int data);
static void kbd_write_output_w(int data);
#ifdef CONFIG_PSMOUSE
static void aux_write_ack(int val);
static void __aux_write_ack(int val);
static int aux_reconnect = 0;
#endif
static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
static unsigned char handle_kbd_event(void);
/* used only by send_data - set by keyboard_interrupt */
static volatile unsigned char reply_expected;
static volatile unsigned char acknowledge;
static volatile unsigned char resend;
#if defined CONFIG_PSMOUSE
/*
* PS/2 Auxiliary Device
*/
static int __init psaux_init(void);
#define AUX_RECONNECT1 0xaa /* scancode1 when ps2 device is plugged (back) in */
#define AUX_RECONNECT2 0x00 /* scancode2 when ps2 device is plugged (back) in */
static struct aux_queue *queue; /* Mouse data buffer. */
static int aux_count;
static spinlock_t aux_count_lock = SPIN_LOCK_UNLOCKED;
/* used when we send commands to the mouse that expect an ACK. */
static unsigned char mouse_reply_expected;
#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
#define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
#define MAX_RETRIES 60 /* some aux operations take long time*/
#endif /* CONFIG_PSMOUSE */
/*
* Wait for keyboard controller input buffer to drain.
*
* Don't use 'jiffies' so that we don't depend on
* interrupts..
*
* Quote from PS/2 System Reference Manual:
*
* "Address hex 0060 and address hex 0064 should be written only when
* the input-buffer-full bit and output-buffer-full bit in the
* Controller Status register are set 0."
*/
static void kb_wait(void)
{
unsigned long timeout = KBC_TIMEOUT;
do {
/*
* "handle_kbd_event()" will handle any incoming events
* while we wait - keypresses or mouse movement.
*/
unsigned char status = handle_kbd_event();
if (! (status & KBD_STAT_IBF))
return;
mdelay(1);
timeout--;
} while (timeout);
#ifdef KBD_REPORT_TIMEOUTS
printk(KERN_WARNING "Keyboard timed out[1]\n");
#endif
}
/*
* Translation of escaped scancodes to keycodes.
* This is now user-settable.
* The keycodes 1-88,96-111,119 are fairly standard, and
* should probably not be changed - changing might confuse X.
* X also interprets scancode 0x5d (KEY_Begin).
*
* For 1-88 keycode equals scancode.
*/
#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
/*
* The keycodes below are randomly located in 89-95,112-118,120-127.
* They could be thrown away (and all occurrences below replaced by 0),
* but that would force many users to use the `setkeycodes' utility, where
* they needed not before. It does not matter that there are duplicates, as
* long as no duplication occurs for any single keyboard.
*/
#define SC_LIM 89
#define FOCUS_PF1 85 /* actual code! */
#define FOCUS_PF2 89
#define FOCUS_PF3 90
#define FOCUS_PF4 91
#define FOCUS_PF5 92
#define FOCUS_PF6 93
#define FOCUS_PF7 94
#define FOCUS_PF8 95
#define FOCUS_PF9 120
#define FOCUS_PF10 121
#define FOCUS_PF11 122
#define FOCUS_PF12 123
#define JAP_86 124
/* tfj@olivia.ping.dk:
* The four keys are located over the numeric keypad, and are
* labelled A1-A4. It's an rc930 keyboard, from
* Regnecentralen/RC International, Now ICL.
* Scancodes: 59, 5a, 5b, 5c.
*/
#define RGN1 124
#define RGN2 125
#define RGN3 126
#define RGN4 127
static unsigned char high_keys[128 - SC_LIM] = {
RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
};
/* BTC */
#define E0_MACRO 112
/* LK450 */
#define E0_F13 113
#define E0_F14 114
#define E0_HELP 115
#define E0_DO 116
#define E0_F17 117
#define E0_KPMINPLUS 118
/*
* My OmniKey generates e0 4c for the "OMNI" key and the
* right alt key does nada. [kkoller@nyx10.cs.du.edu]
*/
#define E0_OK 124
/*
* New microsoft keyboard is rumoured to have
* e0 5b (left window button), e0 5c (right window button),
* e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
* [or: Windows_L, Windows_R, TaskMan]
*/
#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 */
};
int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
{
if (scancode < SC_LIM || scancode > 255 || keycode > 127)
return -EINVAL;
if (scancode < 128)
high_keys[scancode - SC_LIM] = keycode;
else
e0_keys[scancode - 128] = keycode;
return 0;
}
int pckbd_getkeycode(unsigned int scancode)
{
return
(scancode < SC_LIM || scancode > 255) ? -EINVAL :
(scancode < 128) ? high_keys[scancode - SC_LIM] :
e0_keys[scancode - 128];
}
static int do_acknowledge(unsigned char scancode)
{
if (reply_expected) {
/* Unfortunately, we must recognise these codes only if we know they
* are known to be valid (i.e., after sending a command), because there
* are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
* keys with such codes :(
*/
if (scancode == KBD_REPLY_ACK) {
acknowledge = 1;
reply_expected = 0;
return 0;
} else if (scancode == KBD_REPLY_RESEND) {
resend = 1;
reply_expected = 0;
return 0;
}
/* Should not happen... */
#if 0
printk(KERN_DEBUG "keyboard reply expected - got %02x\n",
scancode);
#endif
}
return 1;
}
int pckbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode)
{
static int prev_scancode;
/* special prefix scancodes.. */
if (scancode == 0xe0 || scancode == 0xe1) {
prev_scancode = scancode;
return 0;
}
/* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
if (scancode == 0x00 || scancode == 0xff) {
prev_scancode = 0;
return 0;
}
scancode &= 0x7f;
if (prev_scancode) {
/*
* usually it will be 0xe0, but a Pause key generates
* e1 1d 45 e1 9d c5 when pressed, and nothing when released
*/
if (prev_scancode != 0xe0) {
if (prev_scancode == 0xe1 && scancode == 0x1d) {
prev_scancode = 0x100;
return 0;
} else if (prev_scancode == 0x100 && scancode == 0x45) {
*keycode = E1_PAUSE;
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;
/*
* The keyboard maintains its own internal caps lock and
* num lock statuses. In caps lock mode E0 AA precedes make
* code and E0 2A follows break code. In num lock mode,
* E0 2A precedes make code and E0 AA follows break code.
* We do our own book-keeping, so we will just ignore these.
*/
/*
* For my keyboard there is no caps lock mode, but there are
* both Shift-L and Shift-R modes. The former mode generates
* E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
* So, we should also ignore the latter. - aeb@cwi.nl
*/
if (scancode == 0x2a || scancode == 0x36)
return 0;
if (e0_keys[scancode])
*keycode = e0_keys[scancode];
else {
#ifdef KBD_REPORT_UNKN
if (!raw_mode)
printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
scancode);
#endif
return 0;
}
}
} else if (scancode >= SC_LIM) {
/* This happens with the FOCUS 9000 keyboard
Its keys PF1..PF12 are reported to generate
55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
Moreover, unless repeated, they do not generate
key-down events, so we have to zero up_flag below */
/* Also, Japanese 86/106 keyboards are reported to
generate 0x73 and 0x7d for \ - and \ | respectively. */
/* Also, some Brazilian keyboard is reported to produce
0x73 and 0x7e for \ ? and KP-dot, respectively. */
*keycode = high_keys[scancode - SC_LIM];
if (!*keycode) {
if (!raw_mode) {
#ifdef KBD_REPORT_UNKN
printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
" - ignored\n", scancode);
#endif
}
return 0;
}
} else
*keycode = scancode;
return 1;
}
char pckbd_unexpected_up(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 */
if (keycode >= SC_LIM || keycode == 85)
return 0;
else
return 0200;
}
int pckbd_pm_resume(struct pm_dev *dev, pm_request_t rqst, void *data)
{
#if defined CONFIG_PSMOUSE
unsigned long flags;
if (rqst == PM_RESUME) {
if (queue) { /* Aux port detected */
spin_lock_irqsave(&aux_count_lock, flags);
if ( aux_count == 0) { /* Mouse not in use */
spin_lock(&kbd_controller_lock);
/*
* Dell Lat. C600 A06 enables mouse after resume.
* When user touches the pad, it posts IRQ 12
* (which we do not process), thus holding keyboard.
*/
kbd_write_command(KBD_CCMD_MOUSE_DISABLE);
/* kbd_write_cmd(AUX_INTS_OFF); */ /* Config & lock */
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_MODE);
kb_wait();
kbd_write_output(AUX_INTS_OFF);
spin_unlock(&kbd_controller_lock);
}
spin_unlock_irqrestore(&aux_count_lock, flags);
}
}
#endif
return 0;
}
static inline void handle_mouse_event(unsigned char scancode)
{
#ifdef CONFIG_PSMOUSE
unsigned long flags;
static unsigned char prev_code;
if (mouse_reply_expected) {
if (scancode == AUX_ACK) {
mouse_reply_expected--;
return;
}
mouse_reply_expected = 0;
}
else if(scancode == AUX_RECONNECT2 && prev_code == AUX_RECONNECT1
&& aux_reconnect) {
printk (KERN_INFO "PS/2 mouse reconnect detected\n");
queue->head = queue->tail = 0; /* Flush input queue */
__aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */
return;
}
prev_code = scancode;
add_mouse_randomness(scancode);
spin_lock_irqsave(&aux_count_lock, flags);
if ( aux_count ) {
int head = queue->head;
queue->buf[head] = scancode;
head = (head + 1) & (AUX_BUF_SIZE-1);
if (head != queue->tail) {
queue->head = head;
kill_fasync(&queue->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&queue->proc_list);
}
}
spin_unlock_irqrestore(&aux_count_lock, flags);
#endif
}
static unsigned char kbd_exists = 1;
static inline void handle_keyboard_event(unsigned char scancode)
{
#ifdef CONFIG_VT
kbd_exists = 1;
if (do_acknowledge(scancode))
handle_scancode(scancode, !(scancode & 0x80));
#endif
tasklet_schedule(&keyboard_tasklet);
}
/*
* This reads the keyboard status port, and does the
* appropriate action.
*
* It requires that we hold the keyboard controller
* spinlock.
*/
static unsigned char handle_kbd_event(void)
{
unsigned char status = kbd_read_status();
unsigned int work = 10000;
while ((--work > 0) && (status & KBD_STAT_OBF)) {
unsigned char scancode;
scancode = kbd_read_input();
/* Error bytes must be ignored to make the
Synaptics touchpads compaq use work */
#if 1
/* Ignore error bytes */
if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR)))
#endif
{
if (status & KBD_STAT_MOUSE_OBF)
handle_mouse_event(scancode);
else
handle_keyboard_event(scancode);
}
status = kbd_read_status();
}
if (!work)
printk(KERN_ERR "pc_keyb: controller jammed (0x%02X).\n", status);
return status;
}
static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
#ifdef CONFIG_VT
kbd_pt_regs = regs;
#endif
spin_lock_irq(&kbd_controller_lock);
handle_kbd_event();
spin_unlock_irq(&kbd_controller_lock);
}
/*
* send_data sends a character to the keyboard and waits
* for an acknowledge, possibly retrying if asked to. Returns
* the success status.
*
* Don't use 'jiffies', so that we don't depend on interrupts
*/
static int send_data(unsigned char data)
{
int retries = 3;
do {
unsigned long timeout = KBD_TIMEOUT;
acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */
resend = 0;
reply_expected = 1;
kbd_write_output_w(data);
for (;;) {
if (acknowledge)
return 1;
if (resend)
break;
mdelay(1);
if (!--timeout) {
#ifdef KBD_REPORT_TIMEOUTS
printk(KERN_WARNING "keyboard: Timeout - AT keyboard not present?(%02x)\n", data);
#endif
return 0;
}
}
} while (retries-- > 0);
#ifdef KBD_REPORT_TIMEOUTS
printk(KERN_WARNING "keyboard: Too many NACKs -- noisy kbd cable?\n");
#endif
return 0;
}
void pckbd_leds(unsigned char leds)
{
if (kbd_exists && (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))) {
send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */
kbd_exists = 0;
}
}
#define DEFAULT_KEYB_REP_DELAY 250
#define DEFAULT_KEYB_REP_RATE 30 /* cps */
static struct kbd_repeat kbdrate={
DEFAULT_KEYB_REP_DELAY,
DEFAULT_KEYB_REP_RATE
};
static unsigned char parse_kbd_rate(struct kbd_repeat *r)
{
static struct r2v{
int rate;
unsigned char val;
} kbd_rates[]={ {5,0x14},
{7,0x10},
{10,0x0c},
{15,0x08},
{20,0x04},
{25,0x02},
{30,0x00}
};
static struct d2v{
int delay;
unsigned char val;
} kbd_delays[]={{250,0},
{500,1},
{750,2},
{1000,3}
};
int rate=0,delay=0;
if (r != NULL){
int i,new_rate=30,new_delay=250;
if (r->rate <= 0)
r->rate=kbdrate.rate;
if (r->delay <= 0)
r->delay=kbdrate.delay;
for (i=0; i < sizeof(kbd_rates)/sizeof(struct r2v); i++)
if (kbd_rates[i].rate == r->rate){
new_rate=kbd_rates[i].rate;
rate=kbd_rates[i].val;
break;
}
for (i=0; i < sizeof(kbd_delays)/sizeof(struct d2v); i++)
if (kbd_delays[i].delay == r->delay){
new_delay=kbd_delays[i].delay;
delay=kbd_delays[i].val;
break;
}
r->rate=new_rate;
r->delay=new_delay;
}
return (delay << 5) | rate;
}
static int write_kbd_rate(unsigned char r)
{
if (!send_data(KBD_CMD_SET_RATE) || !send_data(r)){
send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */
return 0;
}else
return 1;
}
static int pckbd_rate(struct kbd_repeat *rep)
{
if (rep == NULL)
return -EINVAL;
else{
unsigned char r=parse_kbd_rate(rep);
struct kbd_repeat old_rep;
memcpy(&old_rep,&kbdrate,sizeof(struct kbd_repeat));
if (write_kbd_rate(r)){
memcpy(&kbdrate,rep,sizeof(struct kbd_repeat));
memcpy(rep,&old_rep,sizeof(struct kbd_repeat));
return 0;
}
}
return -EIO;
}
/*
* In case we run on a non-x86 hardware we need to initialize both the
* keyboard controller and the keyboard. On a x86, the BIOS will
* already have initialized them.
*
* Some x86 BIOSes do not correctly initialize the keyboard, so the
* "kbd-reset" command line options can be given to force a reset.
* [Ranger]
*/
#ifdef __i386__
int kbd_startup_reset __initdata = 0;
#else
int kbd_startup_reset __initdata = 1;
#endif
/* for "kbd-reset" cmdline param */
static int __init kbd_reset_setup(char *str)
{
kbd_startup_reset = 1;
return 1;
}
__setup("kbd-reset", kbd_reset_setup);
#define KBD_NO_DATA (-1) /* No data */
#define KBD_BAD_DATA (-2) /* Parity or other error */
static int __init kbd_read_data(void)
{
int retval = KBD_NO_DATA;
unsigned char status;
status = kbd_read_status();
if (status & KBD_STAT_OBF) {
unsigned char data = kbd_read_input();
retval = data;
if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
retval = KBD_BAD_DATA;
}
return retval;
}
static void __init kbd_clear_input(void)
{
int maxread = 100; /* Random number */
do {
if (kbd_read_data() == KBD_NO_DATA)
break;
} while (--maxread);
}
static int __init kbd_wait_for_input(void)
{
long timeout = KBD_INIT_TIMEOUT;
do {
int retval = kbd_read_data();
if (retval >= 0)
return retval;
mdelay(1);
} while (--timeout);
return -1;
}
static void kbd_write_command_w(int data)
{
unsigned long flags;
spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_command(data);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}
static void kbd_write_output_w(int data)
{
unsigned long flags;
spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_output(data);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}
#if defined(__alpha__)
/*
* Some Alphas cannot mask some/all interrupts, so we have to
* make sure not to allow interrupts AT ALL when polling for
* specific return values from the keyboard.
*
* I think this should work on any architecture, but for now, only Alpha.
*/
static int kbd_write_command_w_and_wait(int data)
{
unsigned long flags;
int input;
spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_command(data);
input = kbd_wait_for_input();
spin_unlock_irqrestore(&kbd_controller_lock, flags);
return input;
}
static int kbd_write_output_w_and_wait(int data)
{
unsigned long flags;
int input;
spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_output(data);
input = kbd_wait_for_input();
spin_unlock_irqrestore(&kbd_controller_lock, flags);
return input;
}
#else
static int kbd_write_command_w_and_wait(int data)
{
kbd_write_command_w(data);
return kbd_wait_for_input();
}
static int kbd_write_output_w_and_wait(int data)
{
kbd_write_output_w(data);
return kbd_wait_for_input();
}
#endif /* __alpha__ */
#if defined CONFIG_PSMOUSE
static void kbd_write_cmd(int cmd)
{
unsigned long flags;
spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_MODE);
kb_wait();
kbd_write_output(cmd);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}
#endif /* CONFIG_PSMOUSE */
static char * __init initialize_kbd(void)
{
int status;
#ifdef CONFIG_IA64
/*
* This is not really IA-64 specific. Probably ought to be done on all platforms
* that are (potentially) legacy-free.
*/
if (kbd_read_status() == 0xff && kbd_read_input() == 0xff) {
kbd_exists = 0;
return "No keyboard controller preset";
}
#endif
/*
* Test the keyboard interface.
* This seems to be the only way to get it going.
* If the test is successful a x55 is placed in the input buffer.
*/
kbd_write_command_w(KBD_CCMD_SELF_TEST);
if (kbd_wait_for_input() != 0x55)
return "Keyboard failed self test";
/*
* Perform a keyboard interface test. This causes the controller
* to test the keyboard clock and data lines. The results of the
* test are placed in the input buffer.
*/
kbd_write_command_w(KBD_CCMD_KBD_TEST);
if (kbd_wait_for_input() != 0x00)
return "Keyboard interface failed self test";
/*
* Enable the keyboard by allowing the keyboard clock to run.
*/
kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
/*
* Reset keyboard. If the read times out
* then the assumption is that no keyboard is
* plugged into the machine.
* This defaults the keyboard to scan-code set 2.
*
* Set up to try again if the keyboard asks for RESEND.
*/
do {
kbd_write_output_w(KBD_CMD_RESET);
status = kbd_wait_for_input();
if (status == KBD_REPLY_ACK)
break;
if (status != KBD_REPLY_RESEND)
return "Keyboard reset failed, no ACK";
} while (1);
if (kbd_wait_for_input() != KBD_REPLY_POR)
return "Keyboard reset failed, no POR";
/*
* Set keyboard controller mode. During this, the keyboard should be
* in the disabled state.
*
* Set up to try again if the keyboard asks for RESEND.
*/
do {
kbd_write_output_w(KBD_CMD_DISABLE);
status = kbd_wait_for_input();
if (status == KBD_REPLY_ACK)
break;
if (status != KBD_REPLY_RESEND)
return "Disable keyboard: no ACK";
} while (1);
kbd_write_command_w(KBD_CCMD_WRITE_MODE);
kbd_write_output_w(KBD_MODE_KBD_INT
| KBD_MODE_SYS
| KBD_MODE_DISABLE_MOUSE
| KBD_MODE_KCC);
/* ibm powerpc portables need this to use scan-code set 1 -- Cort */
if (!(kbd_write_command_w_and_wait(KBD_CCMD_READ_MODE) & KBD_MODE_KCC))
{
/*
* If the controller does not support conversion,
* Set the keyboard to scan-code set 1.
*/
kbd_write_output_w(0xF0);
kbd_wait_for_input();
kbd_write_output_w(0x01);
kbd_wait_for_input();
}
if (kbd_write_output_w_and_wait(KBD_CMD_ENABLE) != KBD_REPLY_ACK)
return "Enable keyboard: no ACK";
/*
* Finally, set the typematic rate to maximum.
*/
if (kbd_write_output_w_and_wait(KBD_CMD_SET_RATE) != KBD_REPLY_ACK)
return "Set rate: no ACK";
if (kbd_write_output_w_and_wait(0x00) != KBD_REPLY_ACK)
return "Set rate: no 2nd ACK";
return NULL;
}
void __init pckbd_init_hw(void)
{
#ifndef CONFIG_SERIO_I8042
kbd_request_region();
/* Flush any pending input. */
kbd_clear_input();
if (kbd_startup_reset) {
char *msg = initialize_kbd();
if (msg)
printk(KERN_WARNING "initialize_kbd: %s\n", msg);
#ifdef CONFIG_IA64
if (!kbd_exists)
return;
#endif
}
#if defined CONFIG_PSMOUSE
psaux_init();
#endif
kbd_rate = pckbd_rate;
/* Ok, finally allocate the IRQ, and off we go.. */
kbd_request_irq(keyboard_interrupt);
#endif
}
#if defined CONFIG_PSMOUSE
static int __init aux_reconnect_setup (char *str)
{
aux_reconnect = 1;
return 1;
}
__setup("psaux-reconnect", aux_reconnect_setup);
/*
* Check if this is a dual port controller.
*/
static int __init detect_auxiliary_port(void)
{
unsigned long flags;
int loops = 10;
int retval = 0;
/* Check if the BIOS detected a device on the auxiliary port. */
if (aux_device_present == 0xaa)
return 1;
spin_lock_irqsave(&kbd_controller_lock, flags);
/* Put the value 0x5A in the output buffer using the "Write
* Auxiliary Device Output Buffer" command (0xD3). Poll the
* Status Register for a while to see if the value really
* turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
* bit is also set to 1 in the Status Register, we assume this
* controller has an Auxiliary Port (a.k.a. Mouse Port).
*/
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
kb_wait();
kbd_write_output(0x5a); /* 0x5a is a random dummy value. */
do {
unsigned char status = kbd_read_status();
if (status & KBD_STAT_OBF) {
(void) kbd_read_input();
if (status & KBD_STAT_MOUSE_OBF) {
printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
retval = 1;
}
break;
}
mdelay(1);
} while (--loops);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
return retval;
}
/*
* Send a byte to the mouse.
*/
static void aux_write_dev(int val)
{
unsigned long flags;
spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_MOUSE);
kb_wait();
kbd_write_output(val);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}
/*
* Send a byte to the mouse & handle returned ack
*/
static void __aux_write_ack(int val)
{
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_MOUSE);
kb_wait();
kbd_write_output(val);
/* we expect an ACK in response. */
mouse_reply_expected++;
kb_wait();
}
static void aux_write_ack(int val)
{
unsigned long flags;
spin_lock_irqsave(&kbd_controller_lock, flags);
__aux_write_ack(val);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}
static unsigned char get_from_queue(void)
{
unsigned char result;
unsigned long flags;
spin_lock_irqsave(&kbd_controller_lock, flags);
result = queue->buf[queue->tail];
queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
return result;
}
static inline int queue_empty(void)
{
return queue->head == queue->tail;
}
static int fasync_aux(int fd, struct file *filp, int on)
{
int retval;
retval = fasync_helper(fd, filp, on, &queue->fasync);
if (retval < 0)
return retval;
return 0;
}
/*
* Random magic cookie for the aux device
*/
#define AUX_DEV ((void *)queue)
static int release_aux(struct inode * inode, struct file * file)
{
unsigned long flags;
fasync_aux(-1, file, 0);
spin_lock_irqsave(&aux_count_lock, flags);
if ( --aux_count ) {
spin_unlock_irqrestore(&aux_count_lock, flags);
return 0;
}
spin_unlock_irqrestore(&aux_count_lock, flags);
kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */
kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
aux_free_irq(AUX_DEV);
return 0;
}
/*
* Install interrupt handler.
* Enable auxiliary device.
*/
static int open_aux(struct inode * inode, struct file * file)
{
unsigned long flags;
int ret;
spin_lock_irqsave(&aux_count_lock, flags);
if ( aux_count++ ) {
spin_unlock_irqrestore(&aux_count_lock, flags);
return 0;
}
queue->head = queue->tail = 0; /* Flush input queue */
spin_unlock_irqrestore(&aux_count_lock, flags);
ret = aux_request_irq(keyboard_interrupt, AUX_DEV);
spin_lock_irqsave(&aux_count_lock, flags);
if (ret) {
aux_count--;
spin_unlock_irqrestore(&aux_count_lock, flags);
return -EBUSY;
}
spin_unlock_irqrestore(&aux_count_lock, flags);
kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable the
auxiliary port on
controller. */
aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
mdelay(2); /* Ensure we follow the kbc access delay rules.. */
send_data(KBD_CMD_ENABLE); /* try to workaround toshiba4030cdt problem */
return 0;
}
/*
* Put bytes from input queue to buffer.
*/
static ssize_t read_aux(struct file * file, char * buffer,
size_t count, loff_t *ppos)
{
DECLARE_WAITQUEUE(wait, current);
ssize_t i = count;
unsigned char c;
if (queue_empty()) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
add_wait_queue(&queue->proc_list, &wait);
repeat:
set_current_state(TASK_INTERRUPTIBLE);
if (queue_empty() && !signal_pending(current)) {
schedule();
goto repeat;
}
current->state = TASK_RUNNING;
remove_wait_queue(&queue->proc_list, &wait);
}
while (i > 0 && !queue_empty()) {
c = get_from_queue();
put_user(c, buffer++);
i--;
}
if (count-i) {
file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return count-i;
}
if (signal_pending(current))
return -ERESTARTSYS;
return 0;
}
/*
* Write to the aux device.
*/
static ssize_t write_aux(struct file * file, const char * buffer,
size_t count, loff_t *ppos)
{
ssize_t retval = 0;
if (count) {
ssize_t written = 0;
if (count > 32)
count = 32; /* Limit to 32 bytes. */
do {
char c;
get_user(c, buffer++);
aux_write_dev(c);
written++;
} while (--count);
retval = -EIO;
if (written) {
retval = written;
file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
}
}
return retval;
}
/* No kernel lock held - fine */
static unsigned int aux_poll(struct file *file, poll_table * wait)
{
poll_wait(file, &queue->proc_list, wait);
if (!queue_empty())
return POLLIN | POLLRDNORM;
return 0;
}
struct file_operations psaux_fops = {
read: read_aux,
write: write_aux,
poll: aux_poll,
open: open_aux,
release: release_aux,
fasync: fasync_aux,
};
/*
* Initialize driver.
*/
static struct miscdevice psaux_mouse = {
PSMOUSE_MINOR, "psaux", &psaux_fops
};
static int __init psaux_init(void)
{
#ifndef CONFIG_SERIO_I8042
int retval;
if (!detect_auxiliary_port())
return -EIO;
if ((retval = misc_register(&psaux_mouse)))
return retval;
queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
if (queue == NULL) {
printk(KERN_ERR "psaux_init(): out of memory\n");
misc_deregister(&psaux_mouse);
return -ENOMEM;
}
memset(queue, 0, sizeof(*queue));
queue->head = queue->tail = 0;
init_waitqueue_head(&queue->proc_list);
#ifdef INITIALIZE_MOUSE
kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
aux_write_ack(AUX_SET_SAMPLE);
aux_write_ack(100); /* 100 samples/sec */
aux_write_ack(AUX_SET_RES);
aux_write_ack(3); /* 8 counts per mm */
aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
#endif /* INITIALIZE_MOUSE */
kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
#endif
return 0;
}
#endif /* CONFIG_PSMOUSE */
......@@ -15,16 +15,6 @@ CONFIG_INPUT
The module will be called input.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_INPUT_KEYBDEV
Say Y here if you want your keyboard to be able to serve as a system
keyboard. This is needed in most cases. The only exceptions are
headless and embedded systems.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called keybdev.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_INPUT_MOUSEDEV
Say Y here if you want your mouse to be accessible as char devices
13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice as an
......
......@@ -8,7 +8,6 @@ comment 'Input device support'
tristate 'Input core support' CONFIG_INPUT
comment 'Userland interfaces'
dep_tristate ' Keyboard interface' CONFIG_INPUT_KEYBDEV $CONFIG_INPUT
dep_tristate ' Mouse interface' CONFIG_INPUT_MOUSEDEV $CONFIG_INPUT
dep_mbool ' Provide legacy /dev/psaux device' CONFIG_INPUT_MOUSEDEV_PSAUX $CONFIG_INPUT
if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then
......
......@@ -9,7 +9,6 @@ export-objs := input.o
# Each configuration option enables a list of files.
obj-$(CONFIG_INPUT) += input.o
obj-$(CONFIG_INPUT_KEYBDEV) += keybdev.o
obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
obj-$(CONFIG_INPUT_EVDEV) += evdev.o
......
/*
* $Id: keybdev.c,v 1.19 2002/03/13 10:09:20 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Input core to console keyboard binding.
*/
/*
* 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.
*
* 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.
*
* 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
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/config.h>
#include <linux/kbd_ll.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/kbd_kern.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Input core to console keyboard binding");
MODULE_LICENSE("GPL");
char keybdev_name[] = "keyboard";
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || \
defined(__mips__) || defined(CONFIG_SPARC64) || defined(CONFIG_SUPERH) || \
defined(CONFIG_PPC) || defined(__mc68000__) || defined(__hppa__) || \
defined(__arm__) || defined(__x86_64__)
static int x86_sysrq_alt = 0;
#ifdef CONFIG_SPARC64
static int sparc_l1_a_state = 0;
#endif
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,373,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,115,112,125,121,123,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 };
#ifdef CONFIG_MAC_EMUMOUSEBTN
extern int mac_hid_mouse_emulate_buttons(int, int, int);
#endif /* CONFIG_MAC_EMUMOUSEBTN */
static int emulate_raw(unsigned int keycode, int down)
{
#ifdef CONFIG_MAC_EMUMOUSEBTN
if (mac_hid_mouse_emulate_buttons(1, keycode, down))
return 0;
#endif /* CONFIG_MAC_EMUMOUSEBTN */
if (keycode > 255 || !x86_keycodes[keycode])
return -1;
if (keycode == KEY_PAUSE) {
handle_scancode(0xe1, 1);
handle_scancode(0x1d, down);
handle_scancode(0x45, down);
return 0;
}
if (keycode == KEY_SYSRQ && x86_sysrq_alt) {
handle_scancode(0x54, down);
return 0;
}
#ifdef CONFIG_SPARC64
if (keycode == KEY_A && sparc_l1_a_state) {
sparc_l1_a_state = 0;
sun_do_break();
}
#endif
if (x86_keycodes[keycode] & 0x100)
handle_scancode(0xe0, 1);
handle_scancode(x86_keycodes[keycode] & 0x7f, down);
if (keycode == KEY_SYSRQ) {
handle_scancode(0xe0, 1);
handle_scancode(0x37, down);
}
if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
x86_sysrq_alt = down;
#ifdef CONFIG_SPARC64
if (keycode == KEY_STOP)
sparc_l1_a_state = down;
#endif
return 0;
}
#endif /* CONFIG_X86 || CONFIG_IA64 || __alpha__ || __mips__ || CONFIG_PPC */
static struct input_handler keybdev_handler;
void keybdev_ledfunc(unsigned int led)
{
struct input_handle *handle;
for (handle = keybdev_handler.handle; handle; handle = handle->hnext) {
input_event(handle->dev, EV_LED, LED_SCROLLL, !!(led & 0x01));
input_event(handle->dev, EV_LED, LED_NUML, !!(led & 0x02));
input_event(handle->dev, EV_LED, LED_CAPSL, !!(led & 0x04));
input_sync(handle->dev);
}
}
/* Tell the user who may be running in X and not see the console that we have
panic'ed. This is to distingush panics from "real" lockups.
Could in theory send the panic message as morse, but that is left as an
exercise for the reader. */
void panic_blink(void)
{
static unsigned long last_jiffie;
static char led;
/* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is different. */
if (time_after(jiffies, last_jiffie + HZ/2)) {
led ^= 0x01 | 0x04;
keybdev_ledfunc(led);
last_jiffie = jiffies;
}
}
void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int down)
{
if (type != EV_KEY) return;
emulate_raw(code, down);
tasklet_schedule(&keyboard_tasklet);
}
static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct input_handle *handle;
int i;
for (i = KEY_ESC; i < BTN_MISC; i++)
if (test_bit(i, dev->keybit))
break;
if (i == BTN_MISC)
return NULL;
if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL;
memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->name = keybdev_name;
handle->handler = handler;
input_open_device(handle);
return handle;
}
static void keybdev_disconnect(struct input_handle *handle)
{
input_close_device(handle);
kfree(handle);
}
static struct input_device_id keybdev_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
.evbit = { BIT(EV_KEY) },
},
{ }, /* Terminating entry */
};
MODULE_DEVICE_TABLE(input, keybdev_ids);
static struct input_handler keybdev_handler = {
.event = keybdev_event,
.connect = keybdev_connect,
.disconnect = keybdev_disconnect,
.name = "keybdev",
.id_table = keybdev_ids,
};
static int __init keybdev_init(void)
{
input_register_handler(&keybdev_handler);
kbd_ledfunc = keybdev_ledfunc;
return 0;
}
static void __exit keybdev_exit(void)
{
kbd_ledfunc = NULL;
input_unregister_handler(&keybdev_handler);
}
module_init(keybdev_init);
module_exit(keybdev_exit);
/*
* linux/include/asm-alpha/keyboard.h
*
* Created 3 Nov 1996 by Geert Uytterhoeven
*/
/*
* This file contains the alpha architecture specific keyboard definitions
*/
#ifndef _ALPHA_KEYBOARD_H
#define _ALPHA_KEYBOARD_H
#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/kd.h>
#include <asm/io.h>
#define KEYBOARD_IRQ 1
#define DISABLE_KBD_DURING_INTERRUPTS 0
extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pckbd_getkeycode(unsigned int scancode);
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_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 INIT_KBD
#define SYSRQ_KEY 0x54
/* resource allocation */
#define kbd_request_region()
#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
"keyboard", NULL)
/* How to access the keyboard macros on this platform. */
#define kbd_read_input() inb(KBD_DATA_REG)
#define kbd_read_status() inb(KBD_STATUS_REG)
#define kbd_write_output(val) outb(val, KBD_DATA_REG)
#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
/* Some stoneage hardware needs delays after some operations. */
#define kbd_pause() do { } while(0)
/*
* Machine specific bits for the PS/2 driver
*/
/* Jensen puts this at 9, everyone else at the standard 12. */
#define AUX_IRQ (RTC_PORT(0) == 0x170 ? 9 : 12)
#define aux_request_irq(hand, dev_id) \
request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
#endif /* __KERNEL__ */
#endif /* __ASMalpha_KEYBOARD_H */
/*
* linux/include/asm-arm/keyboard.h
*
* Copyright (C) 1998 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Keyboard driver definitions for ARM
*/
#ifndef __ASM_ARM_KEYBOARD_H
#define __ASM_ARM_KEYBOARD_H
#include <linux/kd.h>
#include <linux/pm.h>
/*
* We provide a unified keyboard interface when in VC_MEDIUMRAW
* mode. This means that all keycodes must be common between
* all supported keyboards. This unfortunately puts us at odds
* with the PC keyboard interface chip... but we can't do anything
* about that now.
*/
#ifdef __KERNEL__
extern int (*k_setkeycode)(unsigned int, unsigned int);
extern int (*k_getkeycode)(unsigned int);
extern int (*k_translate)(unsigned char, unsigned char *, char);
extern char (*k_unexpected_up)(unsigned char);
extern void (*k_leds)(unsigned char);
static inline int kbd_setkeycode(unsigned int sc, unsigned int kc)
{
int ret = -EINVAL;
if (k_setkeycode)
ret = k_setkeycode(sc, kc);
return ret;
}
static inline int kbd_getkeycode(unsigned int sc)
{
int ret = -EINVAL;
if (k_getkeycode)
ret = k_getkeycode(sc);
return ret;
}
static inline void kbd_leds(unsigned char leds)
{
if (k_leds)
k_leds(leds);
}
extern int k_sysrq_key;
extern unsigned char *k_sysrq_xlate;
#define SYSRQ_KEY k_sysrq_key
#define kbd_sysrq_xlate k_sysrq_xlate
#define kbd_translate k_translate
#define kbd_unexpected_up k_unexpected_up
#include <asm/arch/keyboard.h>
#endif /* __KERNEL__ */
#endif /* __ASM_ARM_KEYBOARD_H */
/*
* linux/include/asm-i386/keyboard.h
*
* Created 3 Nov 1996 by Geert Uytterhoeven
*/
/*
* This file contains the i386 architecture specific keyboard definitions
*/
#ifndef _I386_KEYBOARD_H
#define _I386_KEYBOARD_H
#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/kd.h>
#include <linux/pm.h>
#include <asm/io.h>
#define KEYBOARD_IRQ 1
#define DISABLE_KBD_DURING_INTERRUPTS 0
extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pckbd_getkeycode(unsigned int scancode);
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 int pckbd_pm_resume(struct pm_dev *, pm_request_t, void *);
extern pm_callback pm_kbd_request_override;
extern unsigned char pckbd_sysrq_xlate[128];
#define kbd_setkeycode pckbd_setkeycode
#define kbd_getkeycode pckbd_getkeycode
#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
/* resource allocation */
#define kbd_request_region()
#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
"keyboard", NULL)
/* How to access the keyboard macros on this platform. */
#define kbd_read_input() inb(KBD_DATA_REG)
#define kbd_read_status() inb(KBD_STATUS_REG)
#define kbd_write_output(val) outb(val, KBD_DATA_REG)
#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
/* Some stoneage hardware needs delays after some operations. */
#define kbd_pause() do { } while(0)
/*
* Machine specific bits for the PS/2 driver
*/
#define AUX_IRQ 12
#define aux_request_irq(hand, dev_id) \
request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
#endif /* __KERNEL__ */
#endif /* _I386_KEYBOARD_H */
#ifndef _ASM_IA64_KEYBOARD_H
#define _ASM_IA64_KEYBOARD_H
/*
* This file contains the ia64 architecture specific keyboard definitions.
*
* Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
* Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
*/
# ifdef __KERNEL__
#include <linux/irq.h>
#include <linux/kd.h>
#define KEYBOARD_IRQ isa_irq_to_vector(1)
#define DISABLE_KBD_DURING_INTERRUPTS 0
extern unsigned char acpi_kbd_controller_present;
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_controller_present() acpi_kbd_controller_present
#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 INIT_KBD
#define SYSRQ_KEY 0x54
#define E1_PAUSE 119 /* PAUSE key */
/* resource allocation */
#define kbd_request_region()
#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL)
/* How to access the keyboard macros on this platform. */
#define kbd_read_input() inb(KBD_DATA_REG)
#define kbd_read_status() inb(KBD_STATUS_REG)
#define kbd_write_output(val) outb(val, KBD_DATA_REG)
#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
/* Some stoneage hardware needs delays after some operations. */
#define kbd_pause() do { } while(0)
/*
* Machine specific bits for the PS/2 driver
*/
#define AUX_IRQ isa_irq_to_vector(12)
#define aux_request_irq(hand, dev_id) \
request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
# endif /* __KERNEL__ */
#endif /* _ASM_IA64_KEYBOARD_H */
/*
* linux/include/asm-m68k/keyboard.h
*
* Created 3 Nov 1996 by Geert Uytterhoeven
*/
/*
* This file contains the m68k architecture specific keyboard definitions
*/
#ifndef __M68K_KEYBOARD_H
#define __M68K_KEYBOARD_H
#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/kd.h>
#include <asm/machdep.h>
#ifdef CONFIG_Q40
#include <asm/q40_keyboard.h>
#endif
static __inline__ int kbd_setkeycode(unsigned int scancode,
unsigned int keycode)
{
#ifdef CONFIG_Q40
if (MACH_IS_Q40)
return q40kbd_setkeycode(scancode,keycode);
#endif
return -EOPNOTSUPP;
}
static __inline__ int kbd_getkeycode(unsigned int scancode)
{
#ifdef CONFIG_Q40
if (MACH_IS_Q40)
return q40kbd_getkeycode(scancode);
#endif
return scancode > 127 ? -EINVAL : scancode;
}
static __inline__ char kbd_unexpected_up(unsigned char keycode)
{
#ifdef CONFIG_Q40
if (MACH_IS_Q40)
return q40kbd_unexpected_up(keycode);
#endif
return 0200;
}
static __inline__ void kbd_leds(unsigned char leds)
{
if (mach_kbd_leds)
mach_kbd_leds(leds);
}
#define kbd_init_hw mach_keyb_init
#define kbd_translate mach_kbd_translate
#define kbd_rate mach_kbdrate
#define kbd_sysrq_xlate mach_sysrq_xlate
/* resource allocation */
#define kbd_request_region()
#define kbd_request_irq(handler)
extern unsigned int SYSRQ_KEY;
#endif /* __KERNEL__ */
#endif /* __M68K_KEYBOARD_H */
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1994 - 1999, 2001 Ralf Baechle
* Copyright (C) 2001 MIPS Technologies, Inc.
*/
#ifndef _ASM_KEYBOARD_H
#define _ASM_KEYBOARD_H
#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/kd.h>
#include <asm/bootinfo.h>
#define DISABLE_KBD_DURING_INTERRUPTS 0
#ifdef CONFIG_PC_KEYB
extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pckbd_getkeycode(unsigned int scancode);
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 int pckbd_rate(struct kbd_repeat *rep);
extern void pckbd_init_hw(void);
extern unsigned char pckbd_sysrq_xlate[128];
extern void kbd_forward_char (int ch);
#define kbd_setkeycode pckbd_setkeycode
#define kbd_getkeycode pckbd_getkeycode
#define kbd_translate pckbd_translate
#define kbd_unexpected_up pckbd_unexpected_up
#define kbd_leds pckbd_leds
#define kbd_rate pckbd_rate
#define kbd_init_hw pckbd_init_hw
#define kbd_sysrq_xlate pckbd_sysrq_xlate
#else
extern int kbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int kbd_getkeycode(unsigned int scancode);
extern int kbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode);
extern char kbd_unexpected_up(unsigned char keycode);
extern void kbd_leds(unsigned char leds);
extern void kbd_init_hw(void);
extern unsigned char *kbd_sysrq_xlate;
#endif
#define SYSRQ_KEY 0x54
/* Some stoneage hardware needs delays after some operations. */
#define kbd_pause() do { } while(0)
struct kbd_ops {
/* Keyboard driver resource allocation */
void (*kbd_request_region)(void);
int (*kbd_request_irq)(void (*handler)(int, void *, struct pt_regs *));
/* PSaux driver resource management */
int (*aux_request_irq)(void (*handler)(int, void *, struct pt_regs *));
void (*aux_free_irq)(void);
/* Methods to access the keyboard processor's I/O registers */
unsigned char (*kbd_read_input)(void);
void (*kbd_write_output)(unsigned char val);
void (*kbd_write_command)(unsigned char val);
unsigned char (*kbd_read_status)(void);
};
extern struct kbd_ops *kbd_ops;
/* Do the actual calls via kbd_ops vector */
#define kbd_request_region() kbd_ops->kbd_request_region()
#define kbd_request_irq(handler) kbd_ops->kbd_request_irq(handler)
#define aux_request_irq(hand, dev_id) kbd_ops->aux_request_irq(hand)
#define aux_free_irq(dev_id) kbd_ops->aux_free_irq()
#define kbd_read_input() kbd_ops->kbd_read_input()
#define kbd_write_output(val) kbd_ops->kbd_write_output(val)
#define kbd_write_command(val) kbd_ops->kbd_write_command(val)
#define kbd_read_status() kbd_ops->kbd_read_status()
#endif /* __KERNEL */
#endif /* _ASM_KEYBOARD_H */
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1994 - 1999, 2001 Ralf Baechle
* Copyright (C) 2001 MIPS Technologies, Inc.
*/
#ifndef _ASM_KEYBOARD_H
#define _ASM_KEYBOARD_H
#ifdef __KERNEL__
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/kd.h>
#include <asm/bootinfo.h>
#define DISABLE_KBD_DURING_INTERRUPTS 0
extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pckbd_getkeycode(unsigned int scancode);
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 int pckbd_rate(struct kbd_repeat *rep);
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_translate pckbd_translate
#define kbd_unexpected_up pckbd_unexpected_up
#define kbd_leds pckbd_leds
#define kbd_rate pckbd_rate
#define kbd_init_hw pckbd_init_hw
#define kbd_sysrq_xlate pckbd_sysrq_xlate
#define SYSRQ_KEY 0x54
/* Some stoneage hardware needs delays after some operations. */
#define kbd_pause() do { } while(0)
struct kbd_ops {
/* Keyboard driver resource allocation */
void (*kbd_request_region)(void);
int (*kbd_request_irq)(void (*handler)(int, void *, struct pt_regs *));
/* PSaux driver resource management */
int (*aux_request_irq)(void (*handler)(int, void *, struct pt_regs *));
void (*aux_free_irq)(void);
/* Methods to access the keyboard processor's I/O registers */
unsigned char (*kbd_read_input)(void);
void (*kbd_write_output)(unsigned char val);
void (*kbd_write_command)(unsigned char val);
unsigned char (*kbd_read_status)(void);
};
extern struct kbd_ops *kbd_ops;
/* Do the actual calls via kbd_ops vector */
#define kbd_request_region() kbd_ops->kbd_request_region()
#define kbd_request_irq(handler) kbd_ops->kbd_request_irq(handler)
#define aux_request_irq(hand, dev_id) kbd_ops->aux_request_irq(hand)
#define aux_free_irq(dev_id) kbd_ops->aux_free_irq()
#define kbd_read_input() kbd_ops->kbd_read_input()
#define kbd_write_output(val) kbd_ops->kbd_write_output(val)
#define kbd_write_command(val) kbd_ops->kbd_write_command(val)
#define kbd_read_status() kbd_ops->kbd_read_status()
#endif /* __KERNEL */
#endif /* _ASM_KEYBOARD_H */
/*
* linux/include/asm-parisc/keyboard.h
*
* Original by Geert Uytterhoeven
* updates by Alex deVries <adevries@thepuffingroup.com>
* portions copyright (1999) The Puffin Group
* mostly rewritten by Philipp Rumpf <prumpf@tux.org>,
* Copyright 2000 Philipp Rumpf
*/
/*
* We try to keep the amount of generic code as low as possible -
* we want to support all HIL, PS/2, and untranslated USB keyboards
*/
#ifndef _PARISC_KEYBOARD_H
#define _PARISC_KEYBOARD_H
#include <linux/config.h>
#ifdef __KERNEL__
#ifdef CONFIG_VT
/* These are basically the generic functions / variables. The only
* unexpected detail is the initialization sequence for the keyboard
* driver is something like this:
*
* detect keyboard port
* detect keyboard
* call register_kbd_ops
* wait for init_hw
*
* only after init_hw has been called you're allowed to call
* handle_scancode. This means you either have to be extremely
* careful or use a global flag or something - I strongly suggest
* the latter. prumpf */
extern struct kbd_ops {
int (*setkeycode)(unsigned int, unsigned int);
int (*getkeycode)(unsigned int);
int (*translate)(unsigned char, unsigned char *, char);
char (*unexpected_up)(unsigned char);
void (*leds)(unsigned char);
void (*init_hw)(void);
unsigned char sysrq_key;
unsigned char *sysrq_xlate;
} *kbd_ops;
#define kbd_setkeycode (*kbd_ops->setkeycode)
#define kbd_getkeycode (*kbd_ops->getkeycode)
#define kbd_translate (*kbd_ops->translate)
#define kbd_unexpected_up (*kbd_ops->unexpected_up)
#define kbd_leds (*kbd_ops->leds)
#define kbd_init_hw (*kbd_ops->init_hw)
#define SYSRQ_KEY (kbd_ops->sysrq_key)
#define kbd_sysrq_xlate (kbd_ops->sysrq_xlate)
extern unsigned char hp_ps2kbd_sysrq_xlate[128]; /* from drivers/char/hp_keyb.c */
extern void register_kbd_ops(struct kbd_ops *ops);
#endif /* CONFIG_VT */
#endif /* __KERNEL__ */
#endif /* __ASMPARISC_KEYBOARD_H */
/*
* BK Id: %F% %I% %G% %U% %#%
*/
/*
* linux/include/asm-ppc/keyboard.h
*
* Created 3 Nov 1996 by Geert Uytterhoeven
* Modified for Power Macintosh by Paul Mackerras
*/
/*
* This file contains the ppc architecture specific keyboard definitions -
* like the intel pc for prep systems, different for power macs.
*/
#ifndef __ASM_KEYBOARD_H__
#define __ASM_KEYBOARD_H__
#ifdef __KERNEL__
#include <linux/adb.h>
#include <asm/machdep.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/kd.h>
#include <asm/io.h>
#ifndef KEYBOARD_IRQ
#define KEYBOARD_IRQ 1
#endif
#define DISABLE_KBD_DURING_INTERRUPTS 0
#define INIT_KBD
extern int mac_hid_kbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode);
extern char mac_hid_kbd_unexpected_up(unsigned char keycode);
extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode);
extern char pckbd_unexpected_up(unsigned char keycode);
extern unsigned char pckbd_sysrq_xlate[128];
static inline int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
{
return 0;
}
static inline int kbd_getkeycode(unsigned int scancode)
{
return 0;
}
static inline int kbd_translate(unsigned char keycode, unsigned char *keycodep,
char raw_mode)
{
if ( ppc_md.kbd_translate )
return ppc_md.kbd_translate(keycode, keycodep, raw_mode);
else
return pckbd_translate(keycode, keycodep, raw_mode);
}
static inline int kbd_unexpected_up(unsigned char keycode)
{
if ( ppc_md.kbd_unexpected_up )
return ppc_md.kbd_unexpected_up(keycode);
else
return pckbd_unexpected_up(keycode);
}
static inline void kbd_leds(unsigned char leds)
{
}
static inline void kbd_init_hw(void)
{
}
#define kbd_sysrq_xlate pckbd_sysrq_xlate
extern unsigned long SYSRQ_KEY;
/* resource allocation */
#define kbd_request_region()
#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
"keyboard", NULL)
/* How to access the keyboard macros on this platform. */
#ifndef kbd_read_input
#define kbd_read_input() inb(KBD_DATA_REG)
#define kbd_read_status() inb(KBD_STATUS_REG)
#define kbd_write_output(val) outb(val, KBD_DATA_REG)
#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
#endif
/* Some stoneage hardware needs delays after some operations. */
#define kbd_pause() do { } while(0)
/*
* Machine specific bits for the PS/2 driver
*/
#ifndef AUX_IRQ
#define AUX_IRQ 12
#endif
#define aux_request_irq(hand, dev_id) \
request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
#endif /* __KERNEL__ */
#endif /* __ASM_KEYBOARD_H__ */
/*
* linux/include/asm-ppc/keyboard.h
*
* Created 3 Nov 1996 by Geert Uytterhoeven
* Modified for Power Macintosh by Paul Mackerras
*
* 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.
*/
/*
* This file contains the ppc architecture specific keyboard definitions -
* like the intel pc for prep systems, different for power macs.
*/
#ifndef __ASMPPC64_KEYBOARD_H
#define __ASMPPC64_KEYBOARD_H
#ifdef __KERNEL__
#include <linux/adb.h>
#include <asm/machdep.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/kd.h>
#include <asm/io.h>
#define KEYBOARD_IRQ 1
#define DISABLE_KBD_DURING_INTERRUPTS 0
#define INIT_KBD
static inline int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
{
if ( ppc_md.kbd_setkeycode )
return ppc_md.kbd_setkeycode(scancode, keycode);
else
return 0;
}
static inline int kbd_getkeycode(unsigned int scancode)
{
if ( ppc_md.kbd_getkeycode )
return ppc_md.kbd_getkeycode(scancode);
else
return 0;
}
static inline int kbd_translate(unsigned char keycode, unsigned char *keycodep,
char raw_mode)
{
if ( ppc_md.kbd_translate )
return ppc_md.kbd_translate(keycode, keycodep, raw_mode);
else
return 0;
}
static inline int kbd_unexpected_up(unsigned char keycode)
{
if ( ppc_md.kbd_unexpected_up )
return ppc_md.kbd_unexpected_up(keycode);
else
return 0;
}
static inline void kbd_leds(unsigned char leds)
{
if ( ppc_md.kbd_leds )
ppc_md.kbd_leds(leds);
}
static inline void kbd_init_hw(void)
{
if ( ppc_md.kbd_init_hw )
ppc_md.kbd_init_hw();
}
#define kbd_sysrq_xlate (ppc_md.ppc_kbd_sysrq_xlate)
extern unsigned long SYSRQ_KEY;
#define E1_PAUSE 119 /* PAUSE key */
/* resource allocation */
#define kbd_request_region()
#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
"keyboard", NULL)
/* How to access the keyboard macros on this platform. */
#define kbd_read_input() inb(KBD_DATA_REG)
static inline int kbd_read_status(void) {
int ret = inb(0x64);
return (ret == 0xff) ? 0 : ret; /* translate float to bad status. */
}
#define kbd_write_output(val) outb(val, KBD_DATA_REG)
#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
/* Some stoneage hardware needs delays after some operations. */
#define kbd_pause() do { } while(0)
/*
* Machine specific bits for the PS/2 driver
*/
#define AUX_IRQ 12
#define aux_request_irq(hand, dev_id) \
request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
#endif /* __KERNEL__ */
#endif /* __ASMPPC64_KEYBOARD_H */
#ifndef __ASM_SH_KEYBOARD_H
#define __ASM_SH_KEYBOARD_H
/*
* $Id: keyboard.h,v 1.12 2001/09/06 04:01:41 gniibe Exp $
*/
#include <linux/kd.h>
#include <linux/config.h>
#include <asm/machvec.h>
#ifdef CONFIG_SH_EC3104
#include <asm/keyboard-ec3104.h>
#else
static __inline__ int kbd_setkeycode(unsigned int scancode,
unsigned int keycode)
{
return -EOPNOTSUPP;
}
static __inline__ int kbd_getkeycode(unsigned int scancode)
{
return scancode > 127 ? -EINVAL : scancode;
}
#ifdef CONFIG_SH_DREAMCAST
extern int kbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode);
#else
static __inline__ int kbd_translate(unsigned char scancode,
unsigned char *keycode, char raw_mode)
{
*keycode = scancode;
return 1;
}
#endif
static __inline__ char kbd_unexpected_up(unsigned char keycode)
{
return 0200;
}
static __inline__ void kbd_leds(unsigned char leds)
{
}
extern void hp600_kbd_init_hw(void);
extern void dreamcast_kbd_init_hw(void);
static __inline__ void kbd_init_hw(void)
{
if (MACH_HP600) {
hp600_kbd_init_hw();
}
}
#endif
#endif
/* $Id: keyboard.h,v 1.8 2002/01/08 16:00:20 davem Exp $
* linux/include/asm-sparc/keyboard.h
*
* sparc64 Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be)
*/
/*
* This file contains the Ultra/PCI architecture specific keyboard definitions
*/
#ifndef _SPARC_KEYBOARD_H
#define _SPARC_KEYBOARD_H 1
#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/ioport.h>
#include <linux/kd.h>
#include <asm/io.h>
#define KEYBOARD_IRQ 13
#define DISABLE_KBD_DURING_INTERRUPTS 0
extern int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pcikbd_getkeycode(unsigned int scancode);
extern int pcikbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode);
extern char pcikbd_unexpected_up(unsigned char keycode);
extern void pcikbd_leds(unsigned char leds);
extern void pcikbd_init_hw(void);
extern unsigned char pcikbd_sysrq_xlate[128];
#define kbd_setkeycode pcikbd_setkeycode
#define kbd_getkeycode pcikbd_getkeycode
#define kbd_translate pcikbd_translate
#define kbd_unexpected_up pcikbd_unexpected_up
#define kbd_leds pcikbd_leds
#define kbd_init_hw pcikbd_init_hw
#define kbd_sysrq_xlate pcikbd_sysrq_xlate
#define kbd_init pcikbd_init
#define compute_shiftstate pci_compute_shiftstate
#define getkeycode pci_getkeycode
#define setkeycode pci_setkeycode
#define getledstate pci_getledstate
#define setledstate pci_setledstate
#define register_leds pci_register_leds
/* #define SYSRQ_KEY 0x54 */ /* sparc64 */
#define SYSRQ_KEY 0x63 /* sparc */
/* resource allocation */
#define kbd_request_region() request_region(0x60, 16, "keyboard")
#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
"keyboard", NULL)
/* How to access the keyboard macros on this platform. */
#define kbd_read_input() inb(KBD_DATA_REG)
#define kbd_read_status() inb(KBD_STATUS_REG)
#define kbd_write_output(val) outb(val, KBD_DATA_REG)
#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
/* Some stoneage hardware needs delays after some operations. */
#define kbd_pause() do { } while(0)
/*
* Machine specific bits for the PS/2 driver
*/
#define AUX_IRQ 12
#define aux_request_irq(hand, dev_id) \
request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
#endif /* __KERNEL__ */
#endif /* !(_SPARC_KEYBOARD_H) */
/* $Id: keyboard.h,v 1.6 2002/01/08 16:00:20 davem Exp $
* linux/include/asm-sparc64/keyboard.h
*
* Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be)
*/
/*
* This file contains the Ultra/PCI architecture specific keyboard definitions
*/
#ifndef _SPARC64_KEYBOARD_H
#define _SPARC64_KEYBOARD_H 1
#ifdef __KERNEL__
/* We use the generic input layer for keyboard handling, thus
* some of this stuff should never be invoked.
*/
#define kbd_setkeycode(scancode, keycode) (BUG(), 0)
#define kbd_getkeycode(scancode) (BUG(), 0)
#define kbd_translate(keycode, keycodep, raw_mode) \
({ *(keycodep) = scancode; 1; })
#define kbd_unexpected_up(keycode) (0200)
#define kbd_leds(leds) do { } while (0)
#define kbd_init_hw() do { } while (0)
#define SYSRQ_KEY 0x54
extern unsigned char kbd_sysrq_xlate[128];
#endif /* __KERNEL__ */
#endif /* !(_SPARC64_KEYBOARD_H) */
/*
* linux/include/asm-x8664/keyboard.h
*
* Created 3 Nov 1996 by Geert Uytterhoeven
*/
/*
* This file contains the x8664 architecture specific keyboard definitions
*/
#ifndef _X8664_KEYBOARD_H
#define _X8664_KEYBOARD_H
#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/kd.h>
#include <linux/pm.h>
#include <asm/io.h>
#define KEYBOARD_IRQ 1
#define DISABLE_KBD_DURING_INTERRUPTS 0
extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pckbd_getkeycode(unsigned int scancode);
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 int pckbd_pm_resume(struct pm_dev *dev, pm_request_t rqst, void *data);
extern unsigned char pckbd_sysrq_xlate[128];
#define kbd_setkeycode pckbd_setkeycode
#define kbd_getkeycode pckbd_getkeycode
#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
/* resource allocation */
#define kbd_request_region()
#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
"keyboard", NULL)
/* How to access the keyboard macros on this platform. */
#define kbd_read_input() inb(KBD_DATA_REG)
#define kbd_read_status() inb(KBD_STATUS_REG)
#define kbd_write_output(val) outb(val, KBD_DATA_REG)
#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
/* Some stoneage hardware needs delays after some operations. */
#define kbd_pause() do { } while(0)
/*
* Machine specific bits for the PS/2 driver
*/
#define AUX_IRQ 12
#define aux_request_irq(hand, dev_id) \
request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
#endif /* __KERNEL__ */
#endif /* _X8664_KEYBOARD_H */
/*
* Interface between the low-level keyboard driver and the keymapper
*/
#ifndef _KBD_LL_H
#define _KBD_LL_H
extern struct pt_regs *kbd_pt_regs;
void handle_scancode(unsigned char scancode, int down);
#endif /* _KBD_LL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment