Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
e832882d
Commit
e832882d
authored
Feb 03, 2004
by
Vojtech Pavlik
Browse files
Options
Browse Files
Download
Plain Diff
Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
parents
862e3994
afa1823e
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
854 additions
and
964 deletions
+854
-964
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+10
-3
Documentation/usb/acm.txt
Documentation/usb/acm.txt
+4
-4
drivers/input/gameport/ns558.c
drivers/input/gameport/ns558.c
+24
-11
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Kconfig
+1
-0
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+81
-51
drivers/input/keyboard/hpps2atkbd.h
drivers/input/keyboard/hpps2atkbd.h
+91
-83
drivers/input/keyboard/sunkbd.c
drivers/input/keyboard/sunkbd.c
+11
-11
drivers/input/misc/Kconfig
drivers/input/misc/Kconfig
+0
-9
drivers/input/misc/Makefile
drivers/input/misc/Makefile
+0
-1
drivers/input/misc/gsc_ps2.c
drivers/input/misc/gsc_ps2.c
+0
-712
drivers/input/mouse/Kconfig
drivers/input/mouse/Kconfig
+1
-0
drivers/input/serio/Kconfig
drivers/input/serio/Kconfig
+16
-0
drivers/input/serio/Makefile
drivers/input/serio/Makefile
+1
-0
drivers/input/serio/gscps2.c
drivers/input/serio/gscps2.c
+470
-0
drivers/usb/input/hid-core.c
drivers/usb/input/hid-core.c
+42
-21
drivers/usb/input/hid-input.c
drivers/usb/input/hid-input.c
+4
-3
drivers/usb/input/hiddev.c
drivers/usb/input/hiddev.c
+55
-24
include/linux/hiddev.h
include/linux/hiddev.h
+43
-31
No files found.
Documentation/kernel-parameters.txt
View file @
e832882d
...
...
@@ -174,11 +174,18 @@ running once the system is up.
atascsi= [HW,SCSI] Atari SCSI
atkbd.extra= [HW] Enable extra LEDs and keys on IBM RapidAccess, EzKey
and similar keyboards
atkbd.reset= [HW] Reset keyboard during initialization
atkbd.set= [HW] Select keyboard code set
Format: <int>
Format: <int> (2 = AT (default) 3 = PS/2)
atkbd.scroll= [HW] Enable scroll wheel on MS Office and similar keyboards
atkbd.softrepeat=
[HW] Use software keyboard repeat
atkbd.reset= [HW] Reset keyboard during initialization
autotest [IA64]
...
...
Documentation/usb/acm.txt
View file @
e832882d
...
...
@@ -28,7 +28,7 @@ in the package: See the file COPYING.
1. Usage
~~~~~~~~
The drivers/usb/acm.c drivers works with USB modems and USB ISDN terminal
The drivers/usb/
class/cdc-
acm.c drivers works with USB modems and USB ISDN terminal
adapters that conform to the Universal Serial Bus Communication Device Class
Abstract Control Model (USB CDC ACM) specification.
...
...
@@ -65,9 +65,9 @@ minor/major numbers anywhere you want, but either the above location or
To use the modems you need these modules loaded:
usbcore.o
u
sb-[uo]hci.o or uhci.
o
acm.
o
usbcore.
k
o
u
hci-hcd.ko ohci-hcd.ko or ehci-hcd.k
o
cdc-acm.k
o
After that, the modem[s] should be accessible. You should be able to use
minicom, ppp and mgetty with them.
...
...
drivers/input/gameport/ns558.c
View file @
e832882d
...
...
@@ -77,7 +77,7 @@ static void ns558_isa_probe(int io)
* No one should be using this address.
*/
if
(
check_region
(
io
,
1
))
if
(
!
request_region
(
io
,
1
,
"ns558-isa"
))
return
;
/*
...
...
@@ -89,7 +89,8 @@ static void ns558_isa_probe(int io)
outb
(
~
c
&
~
3
,
io
);
if
(
~
(
u
=
v
=
inb
(
io
))
&
3
)
{
outb
(
c
,
io
);
return
;
i
=
0
;
goto
out
;
}
/*
* After a trigger, there must be at least some bits changing.
...
...
@@ -99,7 +100,8 @@ static void ns558_isa_probe(int io)
if
(
u
==
v
)
{
outb
(
c
,
io
);
return
;
i
=
0
;
goto
out
;
}
wait_ms
(
3
);
/*
...
...
@@ -110,7 +112,8 @@ static void ns558_isa_probe(int io)
for
(
i
=
0
;
i
<
1000
;
i
++
)
if
((
u
^
inb
(
io
))
&
0xf
)
{
outb
(
c
,
io
);
return
;
i
=
0
;
goto
out
;
}
/*
* And now find the number of mirrors of the port.
...
...
@@ -118,7 +121,9 @@ static void ns558_isa_probe(int io)
for
(
i
=
1
;
i
<
5
;
i
++
)
{
if
(
check_region
(
io
&
(
-
1
<<
i
),
(
1
<<
i
)))
/* Don't disturb anyone */
release_region
(
io
&
(
-
1
<<
(
i
-
1
)),
(
1
<<
(
i
-
1
)));
if
(
!
request_region
(
io
&
(
-
1
<<
i
),
(
1
<<
i
),
"ns558-isa"
))
/* Don't disturb anyone */
break
;
outb
(
0xff
,
io
&
(
-
1
<<
i
));
...
...
@@ -126,15 +131,22 @@ static void ns558_isa_probe(int io)
if
(
inb
(
io
&
(
-
1
<<
i
))
!=
inb
((
io
&
(
-
1
<<
i
))
+
(
1
<<
i
)
-
1
))
b
++
;
wait_ms
(
3
);
if
(
b
>
300
)
/* We allow 30% difference */
if
(
b
>
300
)
{
/* We allow 30% difference */
release_region
(
io
&
(
-
1
<<
i
),
(
1
<<
i
));
break
;
}
}
i
--
;
if
(
i
!=
4
)
{
if
(
!
request_region
(
io
&
(
-
1
<<
i
),
(
1
<<
i
),
"ns558-isa"
))
return
;
}
if
(
!
(
port
=
kmalloc
(
sizeof
(
struct
ns558
),
GFP_KERNEL
)))
{
printk
(
KERN_ERR
"ns558: Memory allocation failed.
\n
"
);
return
;
goto
out
;
}
memset
(
port
,
0
,
sizeof
(
struct
ns558
));
...
...
@@ -148,8 +160,6 @@ static void ns558_isa_probe(int io)
sprintf
(
port
->
phys
,
"isa%04x/gameport0"
,
io
&
(
-
1
<<
i
));
sprintf
(
port
->
name
,
"NS558 ISA"
);
request_region
(
io
&
(
-
1
<<
i
),
(
1
<<
i
),
"ns558-isa"
);
gameport_register_port
(
&
port
->
gameport
);
printk
(
KERN_INFO
"gameport: NS558 ISA at %#x"
,
port
->
gameport
.
io
);
...
...
@@ -157,6 +167,9 @@ static void ns558_isa_probe(int io)
printk
(
" speed %d kHz
\n
"
,
port
->
gameport
.
speed
);
list_add
(
&
port
->
node
,
&
ns558_list
);
return
;
out:
release_region
(
io
&
(
-
1
<<
i
),
(
1
<<
i
));
}
#ifdef CONFIG_PNP
...
...
drivers/input/keyboard/Kconfig
View file @
e832882d
...
...
@@ -17,6 +17,7 @@ config KEYBOARD_ATKBD
depends on INPUT && INPUT_KEYBOARD
select SERIO
select SERIO_I8042 if PC
select SERIO_GSCPS2 if GSC
help
Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
you'll need this, unless you have a different type keyboard (USB, ADB
...
...
drivers/input/keyboard/atkbd.c
View file @
e832882d
...
...
@@ -37,14 +37,13 @@ MODULE_LICENSE("GPL");
static
int
atkbd_set
=
2
;
module_param_named
(
set
,
atkbd_set
,
int
,
0
);
MODULE_PARM_DESC
(
set
,
"Select keyboard code set (2 = default, 3, 4)"
);
MODULE_PARM_DESC
(
set
,
"Select keyboard code set (2 = default, 3 = PS/2 native)"
);
#if defined(__i386__) || defined(__x86_64__) || defined(__hppa__)
static
int
atkbd_reset
;
#else
static
int
atkbd_reset
=
1
;
#endif
static
int
atkbd_softrepeat
;
module_param_named
(
reset
,
atkbd_reset
,
bool
,
0
);
MODULE_PARM_DESC
(
reset
,
"Reset keyboard during initialization"
);
...
...
@@ -52,6 +51,14 @@ static int atkbd_softrepeat;
module_param_named
(
softrepeat
,
atkbd_softrepeat
,
bool
,
0
);
MODULE_PARM_DESC
(
softrepeat
,
"Use software keyboard repeat"
);
static
int
atkbd_scroll
;
module_param_named
(
scroll
,
atkbd_scroll
,
bool
,
0
);
MODULE_PARM_DESC
(
scroll
,
"Enable scroll-wheel on MS Office and similar keyboards"
);
static
int
atkbd_extra
;
module_param_named
(
extra
,
atkbd_extra
,
bool
,
0
);
MODULE_PARM_DESC
(
extra
,
"Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards"
);
/*
* Scancode to keycode tables. These are just the default setting, and
* are loadable via an userland utility.
...
...
@@ -127,11 +134,11 @@ static unsigned char atkbd_unxlate_table[128] = {
#define ATKBD_CMD_EX_SETLEDS 0x20eb
#define ATKBD_CMD_OK_GETID 0x02e8
#define ATKBD_RET_ACK 0xfa
#define ATKBD_RET_NAK 0xfe
#define ATKBD_RET_BAT 0xaa
#define ATKBD_RET_EMUL0 0xe0
#define ATKBD_RET_EMULX 0x80
#define ATKBD_RET_EMUL1 0xe1
#define ATKBD_RET_RELEASE 0xf0
#define ATKBD_RET_HANGUEL 0xf1
...
...
@@ -141,6 +148,22 @@ static unsigned char atkbd_unxlate_table[128] = {
#define ATKBD_KEY_UNKNOWN 0
#define ATKBD_KEY_NULL 255
#define ATKBD_SCR_1 254
#define ATKBD_SCR_2 253
#define ATKBD_SCR_4 252
#define ATKBD_SCR_8 251
#define ATKBD_SCR_CLICK 250
#define ATKBD_SPECIAL 250
static
unsigned
char
atkbd_scroll_keys
[
5
][
2
]
=
{
{
ATKBD_SCR_1
,
0x45
},
{
ATKBD_SCR_2
,
0x29
},
{
ATKBD_SCR_4
,
0x36
},
{
ATKBD_SCR_8
,
0x27
},
{
ATKBD_SCR_CLICK
,
0x60
},
};
/*
* The atkbd control structure
*/
...
...
@@ -155,6 +178,7 @@ struct atkbd {
unsigned
char
cmdbuf
[
4
];
unsigned
char
cmdcnt
;
unsigned
char
set
;
unsigned
char
extra
;
unsigned
char
release
;
int
lastkey
;
volatile
signed
char
ack
;
...
...
@@ -189,6 +213,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
{
struct
atkbd
*
atkbd
=
serio
->
private
;
unsigned
int
code
=
data
;
int
scroll
=
0
,
click
=
-
1
;
int
value
;
#ifdef ATKBD_DEBUG
...
...
@@ -284,6 +309,21 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
else
printk
(
KERN_WARNING
"atkbd.c: Use 'setkeycodes %s%02x <keycode>' to make it known.
\n
"
,
code
&
0x80
?
"e0"
:
""
,
code
&
0x7f
);
break
;
case
ATKBD_SCR_1
:
scroll
=
1
-
atkbd
->
release
*
2
;
break
;
case
ATKBD_SCR_2
:
scroll
=
2
-
atkbd
->
release
*
4
;
break
;
case
ATKBD_SCR_4
:
scroll
=
4
-
atkbd
->
release
*
8
;
break
;
case
ATKBD_SCR_8
:
scroll
=
8
-
atkbd
->
release
*
16
;
break
;
case
ATKBD_SCR_CLICK
:
click
=
!
atkbd
->
release
;
break
;
default:
value
=
atkbd
->
release
?
0
:
(
1
+
(
!
atkbd_softrepeat
&&
test_bit
(
atkbd
->
keycode
[
code
],
atkbd
->
dev
.
key
)));
...
...
@@ -305,6 +345,13 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd_report_key
(
&
atkbd
->
dev
,
regs
,
atkbd
->
keycode
[
code
],
value
);
}
if
(
scroll
||
click
!=
-
1
)
{
input_regs
(
&
atkbd
->
dev
,
regs
);
input_report_key
(
&
atkbd
->
dev
,
BTN_MIDDLE
,
click
);
input_report_rel
(
&
atkbd
->
dev
,
REL_WHEEL
,
scroll
);
input_sync
(
&
atkbd
->
dev
);
}
atkbd
->
release
=
0
;
out:
return
IRQ_HANDLED
;
...
...
@@ -420,7 +467,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
|
(
test_bit
(
LED_CAPSL
,
dev
->
led
)
?
4
:
0
);
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETLEDS
);
if
(
atkbd
->
set
==
4
)
{
if
(
atkbd
->
extra
)
{
param
[
0
]
=
0
;
param
[
1
]
=
(
test_bit
(
LED_COMPOSE
,
dev
->
led
)
?
0x01
:
0
)
|
(
test_bit
(
LED_SLEEP
,
dev
->
led
)
?
0x02
:
0
)
...
...
@@ -529,21 +576,22 @@ static int atkbd_set_3(struct atkbd *atkbd)
return
3
;
}
if
(
atkbd_set
!=
2
)
if
(
!
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_OK_GETID
))
{
atkbd
->
id
=
param
[
0
]
<<
8
|
param
[
1
];
if
(
atkbd_extra
)
{
param
[
0
]
=
0x71
;
if
(
!
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_EX_ENABLE
))
{
atkbd
->
extra
=
1
;
return
2
;
}
if
(
atkbd_set
==
4
)
{
param
[
0
]
=
0x71
;
if
(
!
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_EX_ENABLE
))
return
4
;
}
if
(
atkbd_set
!=
3
)
return
2
;
if
(
!
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_OK_GETID
))
{
atkbd
->
id
=
param
[
0
]
<<
8
|
param
[
1
];
return
2
;
}
param
[
0
]
=
3
;
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SSCANSET
))
return
2
;
...
...
@@ -696,24 +744,32 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd
->
id
=
0xab00
;
}
if
(
atkbd
->
set
==
4
)
{
if
(
atkbd
->
extra
)
{
atkbd
->
dev
.
ledbit
[
0
]
|=
BIT
(
LED_COMPOSE
)
|
BIT
(
LED_SUSPEND
)
|
BIT
(
LED_SLEEP
)
|
BIT
(
LED_MUTE
)
|
BIT
(
LED_MISC
);
sprintf
(
atkbd
->
name
,
"AT Set 2 Ext
ended
keyboard"
);
sprintf
(
atkbd
->
name
,
"AT Set 2 Ext
ra
keyboard"
);
}
else
sprintf
(
atkbd
->
name
,
"AT %s Set %d keyboard"
,
atkbd
->
translated
?
"Translated"
:
"Raw"
,
atkbd
->
set
);
sprintf
(
atkbd
->
phys
,
"%s/input0"
,
serio
->
phys
);
if
(
atkbd_scroll
)
{
for
(
i
=
0
;
i
<
5
;
i
++
)
atkbd_set2_keycode
[
atkbd_scroll_keys
[
i
][
1
]]
=
atkbd_scroll_keys
[
i
][
0
];
atkbd
->
dev
.
evbit
[
0
]
|=
BIT
(
EV_REL
);
atkbd
->
dev
.
relbit
[
0
]
=
BIT
(
REL_WHEEL
);
set_bit
(
BTN_MIDDLE
,
atkbd
->
dev
.
keybit
);
}
if
(
atkbd
->
translated
)
{
for
(
i
=
0
;
i
<
128
;
i
++
)
{
atkbd
->
keycode
[
i
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]];
atkbd
->
keycode
[
i
|
0x80
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]
|
0x80
];
}
}
else
if
(
atkbd
->
set
==
2
)
{
memcpy
(
atkbd
->
keycode
,
atkbd_set2_keycode
,
sizeof
(
atkbd
->
keycode
));
}
else
{
}
else
if
(
atkbd
->
set
==
3
)
{
memcpy
(
atkbd
->
keycode
,
atkbd_set3_keycode
,
sizeof
(
atkbd
->
keycode
));
}
else
{
memcpy
(
atkbd
->
keycode
,
atkbd_set2_keycode
,
sizeof
(
atkbd
->
keycode
));
}
atkbd
->
dev
.
name
=
atkbd
->
name
;
...
...
@@ -724,7 +780,7 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd
->
dev
.
id
.
version
=
atkbd
->
id
;
for
(
i
=
0
;
i
<
512
;
i
++
)
if
(
atkbd
->
keycode
[
i
]
&&
atkbd
->
keycode
[
i
]
<
255
)
if
(
atkbd
->
keycode
[
i
]
&&
atkbd
->
keycode
[
i
]
<
ATKBD_SPECIAL
)
set_bit
(
atkbd
->
keycode
[
i
],
atkbd
->
dev
.
keybit
);
input_register_device
(
&
atkbd
->
dev
);
...
...
@@ -741,7 +797,6 @@ static int atkbd_reconnect(struct serio *serio)
{
struct
atkbd
*
atkbd
=
serio
->
private
;
struct
serio_dev
*
dev
=
serio
->
dev
;
int
i
;
if
(
!
dev
)
{
printk
(
KERN_DEBUG
"atkbd: reconnect request, but serio is disconnected, ignoring...
\n
"
);
...
...
@@ -751,36 +806,11 @@ static int atkbd_reconnect(struct serio *serio)
if
(
atkbd
->
write
)
{
if
(
atkbd_probe
(
atkbd
))
return
-
1
;
atkbd
->
set
=
atkbd_set_3
(
atkbd
)
;
if
(
atkbd
->
set
!=
atkbd_set_3
(
atkbd
))
return
-
1
;
atkbd_enable
(
atkbd
);
}
else
{
atkbd
->
set
=
2
;
atkbd
->
id
=
0xab00
;
}
/*
* Here we probably should check if the keyboard has the same set that
* it had before and bail out if it's different. But this will most likely
* cause new keyboard device be created... and for the user it will look
* like keyboard is lost
*/
if
(
atkbd
->
translated
)
{
for
(
i
=
0
;
i
<
128
;
i
++
)
{
atkbd
->
keycode
[
i
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]];
atkbd
->
keycode
[
i
|
0x80
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]
|
0x80
];
}
}
else
if
(
atkbd
->
set
==
2
)
{
memcpy
(
atkbd
->
keycode
,
atkbd_set2_keycode
,
sizeof
(
atkbd
->
keycode
));
}
else
{
memcpy
(
atkbd
->
keycode
,
atkbd_set3_keycode
,
sizeof
(
atkbd
->
keycode
));
}
for
(
i
=
0
;
i
<
512
;
i
++
)
if
(
atkbd
->
keycode
[
i
]
&&
atkbd
->
keycode
[
i
]
<
255
)
set_bit
(
atkbd
->
keycode
[
i
],
atkbd
->
dev
.
keybit
);
return
0
;
}
...
...
drivers/input/keyboard/hpps2atkbd.h
View file @
e832882d
...
...
@@ -4,14 +4,9 @@
* Copyright (c) 2004 Helge Deller <deller@gmx.de>
* Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
* Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
*
* based on linux-2.4's hp_mouse.c & hp_keyb.c
* Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
* Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
* Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
* Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
*
* HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations
* HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations
& Laptops
*
* 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
...
...
@@ -19,87 +14,100 @@
*/
#define KBD_UNKNOWN 0
/* Raw SET 2 scancode table */
/* undefine if you have a RDI PRECISIONBOOK */
#define STANDARD_KEYBOARD
#if 0
/* conflicting keys between a RDI Precisionbook keyboard and a normal HP keyboard */
keytable[0x07] = KEY_F1; /* KEY_F12 */
keytable[0x11] = KEY_LEFTCTRL; /* KEY_LEFTALT */
keytable[0x14] = KEY_CAPSLOCK; /* KEY_LEFTCTRL */
keytable[0x61] = KEY_LEFT; /* KEY_102ND */
#if defined(STANDARD_KEYBOARD)
# define CONFLICT(x,y) x
#else
# define CONFLICT(x,y) y
#endif
/* sadly RDI (Tadpole) decided to ship a different keyboard layout
than HP for their PS/2 laptop keyboard which leads to conflicting
keycodes between a normal HP PS/2 keyboard and a RDI Precisionbook.
HP: RDI: */
#define C_07 CONFLICT( KEY_F12, KEY_F1 )
#define C_11 CONFLICT( KEY_LEFTALT, KEY_LEFTCTRL )
#define C_14 CONFLICT( KEY_LEFTCTRL, KEY_CAPSLOCK )
#define C_58 CONFLICT( KEY_CAPSLOCK, KEY_RIGHTCTRL )
#define C_61 CONFLICT( KEY_102ND, KEY_LEFT )
/* Raw SET 2 scancode table */
static
unsigned
char
atkbd_set2_keycode
[
512
]
=
{
/* 00 */
KEY_RESERVED
,
KEY_F9
,
KEY_RESERVED
,
KEY_F5
,
KEY_F3
,
KEY_F1
,
KEY_F2
,
C_07
,
/* 08 */
KEY_ESC
,
KEY_F10
,
KEY_F8
,
KEY_F6
,
KEY_F4
,
KEY_TAB
,
KEY_GRAVE
,
KEY_F2
,
/* 10 */
KEY_RESERVED
,
C_11
,
KEY_LEFTSHIFT
,
KEY_RESERVED
,
C_14
,
KEY_Q
,
KEY_1
,
KEY_F3
,
/* 18 */
KEY_RESERVED
,
KEY_LEFTALT
,
KEY_Z
,
KEY_S
,
KEY_A
,
KEY_W
,
KEY_2
,
KEY_F4
,
/* 20 */
KEY_RESERVED
,
KEY_C
,
KEY_X
,
KEY_D
,
KEY_E
,
KEY_4
,
KEY_3
,
KEY_F5
,
/* 28 */
KEY_RESERVED
,
KEY_SPACE
,
KEY_V
,
KEY_F
,
KEY_T
,
KEY_R
,
KEY_5
,
KEY_F6
,
/* 30 */
KEY_RESERVED
,
KEY_N
,
KEY_B
,
KEY_H
,
KEY_G
,
KEY_Y
,
KEY_6
,
KEY_F7
,
/* 38 */
KEY_RESERVED
,
KEY_RIGHTALT
,
KEY_M
,
KEY_J
,
KEY_U
,
KEY_7
,
KEY_8
,
KEY_F8
,
/* 40 */
KEY_RESERVED
,
KEY_COMMA
,
KEY_K
,
KEY_I
,
KEY_O
,
KEY_0
,
KEY_9
,
KEY_F9
,
/* 48 */
KEY_RESERVED
,
KEY_DOT
,
KEY_SLASH
,
KEY_L
,
KEY_SEMICOLON
,
KEY_P
,
KEY_MINUS
,
KEY_F10
,
/* 50 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_APOSTROPHE
,
KEY_RESERVED
,
KEY_LEFTBRACE
,
KEY_EQUAL
,
KEY_F11
,
KEY_SYSRQ
,
/* 58 */
C_58
,
KEY_RIGHTSHIFT
,
KEY_ENTER
,
KEY_RIGHTBRACE
,
KEY_BACKSLASH
,
KEY_BACKSLASH
,
KEY_F12
,
KEY_SCROLLLOCK
,
/* 60 */
KEY_DOWN
,
C_61
,
KEY_PAUSE
,
KEY_UP
,
KEY_DELETE
,
KEY_END
,
KEY_BACKSPACE
,
KEY_INSERT
,
/* 68 */
KEY_RESERVED
,
KEY_KP1
,
KEY_RIGHT
,
KEY_KP4
,
KEY_KP7
,
KEY_PAGEDOWN
,
KEY_HOME
,
KEY_PAGEUP
,
/* 70 */
KEY_KP0
,
KEY_KPDOT
,
KEY_KP2
,
KEY_KP5
,
KEY_KP6
,
KEY_KP8
,
KEY_ESC
,
KEY_NUMLOCK
,
/* 78 */
KEY_F11
,
KEY_KPPLUS
,
KEY_KP3
,
KEY_KPMINUS
,
KEY_KPASTERISK
,
KEY_KP9
,
KEY_SCROLLLOCK
,
KEY_103RD
,
/* 80 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 88 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 90 */
KEY_RESERVED
,
KEY_RIGHTALT
,
KEY_SYSRQ
,
KEY_RESERVED
,
KEY_RIGHTCTRL
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 98 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_CAPSLOCK
,
KEY_RESERVED
,
KEY_LEFTMETA
,
/* a0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RIGHTMETA
,
/* a8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_COMPOSE
,
/* b0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* b8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* c0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* c8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_KPSLASH
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* d0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* d8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_KPENTER
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* e0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* e8 */
KEY_RESERVED
,
KEY_END
,
KEY_RESERVED
,
KEY_LEFT
,
KEY_HOME
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* f0 */
KEY_INSERT
,
KEY_DELETE
,
KEY_DOWN
,
KEY_RESERVED
,
KEY_RIGHT
,
KEY_UP
,
KEY_RESERVED
,
KEY_PAUSE
,
/* f8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_PAGEDOWN
,
KEY_RESERVED
,
KEY_SYSRQ
,
KEY_PAGEUP
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 00 */
KBD_UNKNOWN
,
KEY_F9
,
KBD_UNKNOWN
,
KEY_F5
,
KEY_F3
,
KEY_F1
,
KEY_F2
,
KEY_F1
,
/* 08 */
KEY_ESC
,
KEY_F10
,
KEY_F8
,
KEY_F6
,
KEY_F4
,
KEY_TAB
,
KEY_GRAVE
,
KEY_F2
,
/* 10 */
KBD_UNKNOWN
,
KEY_LEFTCTRL
,
KEY_LEFTSHIFT
,
KBD_UNKNOWN
,
KEY_CAPSLOCK
,
KEY_Q
,
KEY_1
,
KEY_F3
,
/* 18 */
KBD_UNKNOWN
,
KEY_LEFTALT
,
KEY_Z
,
KEY_S
,
KEY_A
,
KEY_W
,
KEY_2
,
KEY_F4
,
/* 20 */
KBD_UNKNOWN
,
KEY_C
,
KEY_X
,
KEY_D
,
KEY_E
,
KEY_4
,
KEY_3
,
KEY_F5
,
/* 28 */
KBD_UNKNOWN
,
KEY_SPACE
,
KEY_V
,
KEY_F
,
KEY_T
,
KEY_R
,
KEY_5
,
KEY_F6
,
/* 30 */
KBD_UNKNOWN
,
KEY_N
,
KEY_B
,
KEY_H
,
KEY_G
,
KEY_Y
,
KEY_6
,
KEY_F7
,
/* 38 */
KBD_UNKNOWN
,
KEY_RIGHTALT
,
KEY_M
,
KEY_J
,
KEY_U
,
KEY_7
,
KEY_8
,
KEY_F8
,
/* 40 */
KBD_UNKNOWN
,
KEY_COMMA
,
KEY_K
,
KEY_I
,
KEY_O
,
KEY_0
,
KEY_9
,
KEY_F9
,
/* 48 */
KBD_UNKNOWN
,
KEY_DOT
,
KEY_SLASH
,
KEY_L
,
KEY_SEMICOLON
,
KEY_P
,
KEY_MINUS
,
KEY_F10
,
/* 50 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_APOSTROPHE
,
KBD_UNKNOWN
,
KEY_LEFTBRACE
,
KEY_EQUAL
,
KEY_F11
,
KEY_SYSRQ
,
/* 58 */
KEY_CAPSLOCK
,
KEY_RIGHTSHIFT
,
KEY_ENTER
,
KEY_RIGHTBRACE
,
KEY_BACKSLASH
,
KEY_BACKSLASH
,
KEY_F12
,
KEY_SCROLLLOCK
,
/* 60 */
KEY_DOWN
,
KEY_LEFT
,
KEY_PAUSE
,
KEY_UP
,
KEY_DELETE
,
KEY_END
,
KEY_BACKSPACE
,
KEY_INSERT
,
/* 68 */
KBD_UNKNOWN
,
KEY_KP1
,
KEY_RIGHT
,
KEY_KP4
,
KEY_KP7
,
KEY_PAGEDOWN
,
KEY_HOME
,
KEY_PAGEUP
,
/* 70 */
KEY_KP0
,
KEY_KPDOT
,
KEY_KP2
,
KEY_KP5
,
KEY_KP6
,
KEY_KP8
,
KEY_ESC
,
KEY_NUMLOCK
,
/* 78 */
KEY_F11
,
KEY_KPPLUS
,
KEY_KP3
,
KEY_KPMINUS
,
KEY_KPASTERISK
,
KEY_KP9
,
KEY_SCROLLLOCK
,
KEY_103RD
,
/* 80 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 88 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 90 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 98 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* a0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* a8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* b0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* b8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* c0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* c8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* d0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* d8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* e0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* e8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* f0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* f8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* These are offset for escaped keycodes: */
/* These are offset for escaped keycodes: */
/* 00 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_F7
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 08 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_LEFTMETA
,
KEY_RIGHTMETA
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 10 */
KEY_RESERVED
,
KEY_RIGHTALT
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RIGHTCTRL
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 18 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 20 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 28 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 30 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 38 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 40 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 48 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 50 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 58 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 60 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 68 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 70 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 78 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 80 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 88 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 90 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* 98 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* a0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* a8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* b0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* b8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* c0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* c8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* d0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* d8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* e0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* e8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* f0 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
/* f8 */
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
,
KEY_RESERVED
/* 00 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_F7
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 08 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_LEFTMETA
,
KEY_RIGHTMETA
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 10 */
KBD_UNKNOWN
,
KEY_RIGHTALT
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_RIGHTCTRL
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 18 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 20 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 28 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 30 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 38 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 40 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 48 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_KPSLASH
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 50 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 58 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_KPENTER
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 60 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 68 */
KBD_UNKNOWN
,
KEY_END
,
KBD_UNKNOWN
,
KEY_LEFT
,
KEY_HOME
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 70 */
KEY_INSERT
,
KEY_DELETE
,
KEY_DOWN
,
KBD_UNKNOWN
,
KEY_RIGHT
,
KEY_UP
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 78 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_PAGEDOWN
,
KBD_UNKNOWN
,
KEY_SYSRQ
,
KEY_PAGEUP
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 80 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 88 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 90 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 98 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* a0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* a8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* b0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* b8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* c0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* c8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* d0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* d8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* e0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* e8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* f0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* f8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
#undef STANDARD_KEYBOARD
#undef CONFLICT
#undef C_07
#undef C_11
#undef C_14
#undef C_58
#undef C_61
};
drivers/input/keyboard/sunkbd.c
View file @
e832882d
...
...
@@ -77,6 +77,7 @@ struct sunkbd {
struct
input_dev
dev
;
struct
serio
*
serio
;
struct
work_struct
tq
;
wait_queue_head_t
wait
;
char
name
[
64
];
char
phys
[
32
];
char
type
;
...
...
@@ -96,11 +97,13 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
if
(
sunkbd
->
reset
<=
-
1
)
{
/* If cp[i] is 0xff, sunkbd->reset will stay -1. */
sunkbd
->
reset
=
data
;
/* The keyboard sends 0xff 0xff 0xID on powerup */
wake_up_interruptible
(
&
sunkbd
->
wait
);
goto
out
;
}
if
(
sunkbd
->
layout
==
-
1
)
{
sunkbd
->
layout
=
data
;
wake_up_interruptible
(
&
sunkbd
->
wait
);
goto
out
;
}
...
...
@@ -176,22 +179,19 @@ static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int c
static
int
sunkbd_initialize
(
struct
sunkbd
*
sunkbd
)
{
int
t
;
t
=
1000
;
sunkbd
->
reset
=
-
2
;
sunkbd
->
serio
->
write
(
sunkbd
->
serio
,
SUNKBD_CMD_RESET
);
while
(
sunkbd
->
reset
<
0
&&
--
t
)
mdelay
(
1
);
if
(
!
t
)
return
-
1
;
wait_event_interruptible_timeout
(
sunkbd
->
wait
,
sunkbd
->
reset
>=
0
,
HZ
);
if
(
sunkbd
->
reset
<
0
)
return
-
1
;
sunkbd
->
type
=
sunkbd
->
reset
;
if
(
sunkbd
->
type
==
4
)
{
/* Type 4 keyboard */
t
=
250
;
sunkbd
->
layout
=
-
2
;
sunkbd
->
serio
->
write
(
sunkbd
->
serio
,
SUNKBD_CMD_LAYOUT
);
w
hile
(
sunkbd
->
layout
<
0
&&
--
t
)
mdelay
(
1
);
if
(
!
t
)
return
-
1
;
w
ait_event_interruptible_timeout
(
sunkbd
->
wait
,
sunkbd
->
layout
>=
0
,
HZ
/
4
);
if
(
sunkbd
->
layout
<
0
)
return
-
1
;
if
(
sunkbd
->
layout
&
SUNKBD_LAYOUT_5_MASK
)
sunkbd
->
type
=
5
;
}
...
...
@@ -206,9 +206,8 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
static
void
sunkbd_reinit
(
void
*
data
)
{
struct
sunkbd
*
sunkbd
=
data
;
int
t
=
1000
;
w
hile
(
sunkbd
->
reset
<
0
&&
--
t
)
mdelay
(
1
);
w
ait_event_interruptible_timeout
(
sunkbd
->
wait
,
sunkbd
->
reset
>=
0
,
HZ
);
sunkbd
->
serio
->
write
(
sunkbd
->
serio
,
SUNKBD_CMD_SETLED
);
sunkbd
->
serio
->
write
(
sunkbd
->
serio
,
...
...
@@ -239,6 +238,7 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
memset
(
sunkbd
,
0
,
sizeof
(
struct
sunkbd
));
init_input_dev
(
&
sunkbd
->
dev
);
init_waitqueue_head
(
&
sunkbd
->
wait
);
sunkbd
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_LED
)
|
BIT
(
EV_SND
)
|
BIT
(
EV_REP
);
sunkbd
->
dev
.
ledbit
[
0
]
=
BIT
(
LED_CAPSL
)
|
BIT
(
LED_COMPOSE
)
|
BIT
(
LED_SCROLLL
)
|
BIT
(
LED_NUML
);
...
...
@@ -275,7 +275,7 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
set_bit
(
sunkbd
->
keycode
[
i
],
sunkbd
->
dev
.
keybit
);
clear_bit
(
0
,
sunkbd
->
dev
.
keybit
);
sprintf
(
sunkbd
->
name
,
"%s/input
"
,
serio
->
phys
);
sprintf
(
sunkbd
->
phys
,
"%s/input0
"
,
serio
->
phys
);
sunkbd
->
dev
.
name
=
sunkbd
->
name
;
sunkbd
->
dev
.
phys
=
sunkbd
->
phys
;
...
...
drivers/input/misc/Kconfig
View file @
e832882d
...
...
@@ -54,12 +54,3 @@ config INPUT_UINPUT
To compile this driver as a module, choose M here: the
module will be called uinput.
config INPUT_GSC
tristate "PA-RISC GSC PS/2 keyboard/mouse support"
depends on GSC && INPUT && INPUT_MISC
help
Say Y here if you have a PS/2 keyboard and/or mouse attached
to your PA-RISC box. HP run the keyboard in AT mode rather than
XT mode like everyone else, so we need our own driver.
Furthermore, the GSC PS/2 controller shares IRQ between mouse and
keyboard.
drivers/input/misc/Makefile
View file @
e832882d
...
...
@@ -9,4 +9,3 @@ obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_M68K_BEEP)
+=
m68kspkr.o
obj-$(CONFIG_INPUT_98SPKR)
+=
98spkr.o
obj-$(CONFIG_INPUT_UINPUT)
+=
uinput.o
obj-$(CONFIG_INPUT_GSC)
+=
gsc_ps2.o
drivers/input/misc/gsc_ps2.c
deleted
100644 → 0
View file @
862e3994
/*
* drivers/input/misc/gsc_ps2.c
*
* Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
* Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
*
* Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
* Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
* Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
* Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
* Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
*
* HP PS/2 Keyboard, found in PA/RISC Workstations
* very similar to AT keyboards, but without i8042
*
* 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* STATUS:
* 11/09: lc: Only basic keyboard is supported, mouse still needs to be done.
* 11/12: tv: switching iomapping; cleaning code; improving module stuff.
* 11/13: lc & tv: leds aren't working. auto_repeat/meta are. Generaly good behavior.
* 11/15: tv: 2AM: leds ARE working !
* 11/16: tv: 3AM: escaped keycodes emulation *handled*, some keycodes are
* still deliberately ignored (18), what are they used for ?
* 11/21: lc: mouse is now working
* 11/29: tv: first try for error handling in init sequence
*
* TODO:
* Error handling in init sequence
* SysRq handling
* Pause key handling
* Intellimouse & other rodents handling (at least send an error when
* such a mouse is plugged : it will totally fault)
* Mouse: set scaling / Dino testing
* Bug chasing...
*
*/
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ptrace.h>
/* interrupt.h wants struct pt_regs defined */
#include <linux/interrupt.h>
#include <linux/sched.h>
/* for request_irq/free_irq */
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/kd.h>
#include <linux/pci_ids.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/parisc-device.h>
/* Debugging stuff */
#undef KBD_DEBUG
#ifdef KBD_DEBUG
#define DPRINTK(fmt,args...) printk(KERN_DEBUG __FILE__ ":" fmt, ##args)
#else
#define DPRINTK(x,...)
#endif
/*
* Driver constants
*/
/* PS/2 keyboard and mouse constants */
#define AUX_RECONNECT 0xAA
/* PS/2 Mouse end of test successful */
#define AUX_REPLY_ACK 0xFA
#define AUX_ENABLE_DEV 0xF4
/* Enables aux device */
/* Order of the mouse bytes coming to the host */
#define PACKET_X 1
#define PACKET_Y 2
#define PACKET_CTRL 0
#define GSC_MOUSE_OFFSET 0x0100
/* offset from keyboard to mouse port */
#define GSC_DINO_OFFSET 0x800
/* offset for DINO controller versus LASI one */
#define GSC_ID 0x00
/* ID and reset port offsets */
#define GSC_RESET 0x00
#define GSC_RCVDATA 0x04
/* receive and transmit port offsets */
#define GSC_XMTDATA 0x04
#define GSC_CONTROL 0x08
/* see: control register bits */
#define GSC_STATUS 0x0C
/* see: status register bits */
/* Control register bits */
#define GSC_CTRL_ENBL 0x01
/* enable interface */
#define GSC_CTRL_LPBXR 0x02
/* loopback operation */
#define GSC_CTRL_DIAG 0x20
/* directly control clock/data line */
#define GSC_CTRL_DATDIR 0x40
/* data line direct control */
#define GSC_CTRL_CLKDIR 0x80
/* clock line direct control */
/* Status register bits */
#define GSC_STAT_RBNE 0x01
/* Receive Buffer Not Empty */
#define GSC_STAT_TBNE 0x02
/* Transmit Buffer Not Empty */
#define GSC_STAT_TERR 0x04
/* Timeout Error */
#define GSC_STAT_PERR 0x08
/* Parity Error */
#define GSC_STAT_CMPINTR 0x10
/* Composite Interrupt */
#define GSC_STAT_DATSHD 0x40
/* Data Line Shadow */
#define GSC_STAT_CLKSHD 0x80
/* Clock Line Shadow */
/* Keycode map */
#define KBD_ESCAPE0 0xe0
#define KBD_ESCAPE1 0xe1
#define KBD_RELEASE 0xf0
#define KBD_ACK 0xfa
#define KBD_RESEND 0xfe
#define KBD_UNKNOWN 0
#define KBD_TBLSIZE 512
/* Mouse */
#define MOUSE_LEFTBTN 0x1
#define MOUSE_MIDBTN 0x4
#define MOUSE_RIGHTBTN 0x2
#define MOUSE_ALWAYS1 0x8
#define MOUSE_XSIGN 0x10
#define MOUSE_YSIGN 0x20
#define MOUSE_XOVFLOW 0x40
#define MOUSE_YOVFLOW 0x80
/* Remnant of pc_keyb.h */
#define KBD_CMD_SET_LEDS 0xED
/* Sets keyboard leds */
#define KBD_CMD_SET_RATE 0xF3
/* Sets typematic rate */
#define KBD_CMD_ENABLE 0xF4
/* Enables scanning */
#define KBD_CMD_DISABLE 0xF5
#define KBD_CMD_RESET 0xFF
static
unsigned
char
hpkeyb_keycode
[
KBD_TBLSIZE
]
=
{
/* 00 */
KBD_UNKNOWN
,
KEY_F9
,
KBD_UNKNOWN
,
KEY_F5
,
KEY_F3
,
KEY_F1
,
KEY_F2
,
KEY_F12
,
/* 08 */
KBD_UNKNOWN
,
KEY_F10
,
KEY_F8
,
KEY_F6
,
KEY_F4
,
KEY_TAB
,
KEY_GRAVE
,
KBD_UNKNOWN
,
/* 10 */
KBD_UNKNOWN
,
KEY_LEFTALT
,
KEY_LEFTSHIFT
,
KBD_UNKNOWN
,
KEY_LEFTCTRL
,
KEY_Q
,
KEY_1
,
KBD_UNKNOWN
,
/* 18 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_Z
,
KEY_S
,
KEY_A
,
KEY_W
,
KEY_2
,
KBD_UNKNOWN
,
/* 20 */
KBD_UNKNOWN
,
KEY_C
,
KEY_X
,
KEY_D
,
KEY_E
,
KEY_4
,
KEY_3
,
KBD_UNKNOWN
,
/* 28 */
KBD_UNKNOWN
,
KEY_SPACE
,
KEY_V
,
KEY_F
,
KEY_T
,
KEY_R
,
KEY_5
,
KBD_UNKNOWN
,
/* 30 */
KBD_UNKNOWN
,
KEY_N
,
KEY_B
,
KEY_H
,
KEY_G
,
KEY_Y
,
KEY_6
,
KBD_UNKNOWN
,
/* 38 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_M
,
KEY_J
,
KEY_U
,
KEY_7
,
KEY_8
,
KBD_UNKNOWN
,
/* 40 */
KBD_UNKNOWN
,
KEY_COMMA
,
KEY_K
,
KEY_I
,
KEY_O
,
KEY_0
,
KEY_9
,
KBD_UNKNOWN
,
/* 48 */
KBD_UNKNOWN
,
KEY_DOT
,
KEY_SLASH
,
KEY_L
,
KEY_SEMICOLON
,
KEY_P
,
KEY_MINUS
,
KBD_UNKNOWN
,
/* 50 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_APOSTROPHE
,
KBD_UNKNOWN
,
KEY_LEFTBRACE
,
KEY_EQUAL
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 58 */
KEY_CAPSLOCK
,
KEY_RIGHTSHIFT
,
KEY_ENTER
,
KEY_RIGHTBRACE
,
KBD_UNKNOWN
,
KEY_BACKSLASH
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 60 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_BACKSPACE
,
KBD_UNKNOWN
,
/* 68 */
KBD_UNKNOWN
,
KEY_KP1
,
KBD_UNKNOWN
,
KEY_KP4
,
KEY_KP7
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 70 */
KEY_KP0
,
KEY_KPDOT
,
KEY_KP2
,
KEY_KP5
,
KEY_KP6
,
KEY_KP8
,
KEY_ESC
,
KEY_NUMLOCK
,
/* 78 */
KEY_F11
,
KEY_KPPLUS
,
KEY_KP3
,
KEY_KPMINUS
,
KEY_KPASTERISK
,
KEY_KP9
,
KEY_SCROLLLOCK
,
KEY_103RD
,
/* 80 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_F7
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 88 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 90 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 98 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* a0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* a8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* b0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* b8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* c0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* c8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* d0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* d8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* e0 */
KBD_ESCAPE0
,
KBD_ESCAPE1
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* e8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* f0 */
KBD_RELEASE
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* f8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_ACK
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_RESEND
,
KBD_UNKNOWN
,
/* These are offset for escaped keycodes */
/* 00 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 08 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 10 */
KBD_UNKNOWN
,
KEY_RIGHTALT
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_RIGHTCTRL
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 18 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 20 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 28 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 30 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 38 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 40 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 48 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_KPSLASH
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 50 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 58 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_KPENTER
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 60 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 68 */
KBD_UNKNOWN
,
KEY_END
,
KBD_UNKNOWN
,
KEY_LEFT
,
KEY_HOME
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 70 */
KEY_INSERT
,
KEY_DELETE
,
KEY_DOWN
,
KBD_UNKNOWN
,
KEY_RIGHT
,
KEY_UP
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 78 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KEY_PAGEDOWN
,
KBD_UNKNOWN
,
KEY_SYSRQ
,
KEY_PAGEUP
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 80 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 88 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 90 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* 98 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* a0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* a8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* b0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* b8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* c0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* c8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* d0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* d8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* e0 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* e8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* f0 */
KBD_RELEASE
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
/* f8 */
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
,
KBD_UNKNOWN
};
/* Keyboard struct */
static
struct
{
struct
input_dev
dev
;
char
*
addr
;
unsigned
int
irq
;
unsigned
int
scancode
;
unsigned
int
escaped
;
unsigned
int
released
;
unsigned
int
initialized
;
}
hpkeyb
=
{
.
escaped
=
0
,
.
released
=
0
,
.
initialized
=
0
};
/* Mouse struct */
static
struct
{
struct
input_dev
dev
;
char
*
addr
;
unsigned
long
irq
;
unsigned
long
initialized
;
int
nbread
;
unsigned
char
bytes
[
3
];
unsigned
long
last
;
}
hpmouse
=
{
.
initialized
=
0
,
.
nbread
=
0
};
static
spinlock_t
gscps2_lock
=
SPIN_LOCK_UNLOCKED
;
/*
* Various HW level routines
*/
#define gscps2_readb_input(x) readb(x+GSC_RCVDATA)
#define gscps2_readb_control(x) readb(x+GSC_CONTROL)
#define gscps2_readb_status(x) readb(x+GSC_STATUS)
#define gscps2_writeb_control(x, y) writeb(x, y+GSC_CONTROL)
static
inline
void
gscps2_writeb_output
(
u8
val
,
char
*
addr
)
{
int
wait
=
250
;
/* Keyboard is expected to react within 250ms */
while
(
gscps2_readb_status
(
addr
)
&
GSC_STAT_TBNE
)
{
if
(
!--
wait
)
return
;
/* This should not happen */
mdelay
(
1
);
}
writeb
(
val
,
addr
+
GSC_XMTDATA
);
}
static
inline
unsigned
char
gscps2_wait_input
(
char
*
addr
)
{
int
wait
=
250
;
/* Keyboard is expected to react within 250ms */
while
(
!
(
gscps2_readb_status
(
addr
)
&
GSC_STAT_RBNE
))
{
if
(
!--
wait
)
return
0
;
/* This should not happen */
mdelay
(
1
);
}
return
gscps2_readb_input
(
addr
);
}
static
int
gscps2_writeb_safe_output
(
u8
val
)
{
/* This function waits for keyboard's ACK */
u8
scanread
=
KBD_UNKNOWN
;
int
loop
=
5
;
while
(
hpkeyb_keycode
[
scanread
]
!=
KBD_ACK
&&
--
loop
>
0
)
{
gscps2_writeb_output
(
val
,
hpkeyb
.
addr
);
mdelay
(
5
);
scanread
=
gscps2_wait_input
(
hpkeyb
.
addr
);
}
if
(
loop
<=
0
)
return
-
1
;
return
0
;
}
/* Reset the PS2 port */
static
void
__init
gscps2_reset
(
char
*
addr
)
{
/* reset the interface */
writeb
(
0xff
,
addr
+
GSC_RESET
);
writeb
(
0x0
,
addr
+
GSC_RESET
);
/* enable it */
gscps2_writeb_control
(
gscps2_readb_control
(
addr
)
|
GSC_CTRL_ENBL
,
addr
);
}
/**
* gscps2_kbd_docode() - PS2 Keyboard basic handler
*
* Receives a keyboard scancode, analyses it and sends it to the input layer.
*/
static
void
gscps2_kbd_docode
(
struct
pt_regs
*
regs
)
{
int
scancode
=
gscps2_readb_input
(
hpkeyb
.
addr
);
DPRINTK
(
"rel=%d scancode=%d, esc=%d "
,
hpkeyb
.
released
,
scancode
,
hpkeyb
.
escaped
);
/* Handle previously escaped scancodes */
if
(
hpkeyb
.
escaped
==
KBD_ESCAPE0
)
scancode
|=
0x100
;
/* jump to the next 256 chars of the table */
switch
(
hpkeyb_keycode
[
scancode
])
{
case
KBD_RELEASE
:
DPRINTK
(
"release
\n
"
);
hpkeyb
.
released
=
1
;
break
;
case
KBD_RESEND
:
DPRINTK
(
"resend request
\n
"
);
break
;
case
KBD_ACK
:
DPRINTK
(
"ACK
\n
"
);
break
;
case
KBD_ESCAPE0
:
case
KBD_ESCAPE1
:
DPRINTK
(
"escape code %d
\n
"
,
hpkeyb_keycode
[
scancode
]);
hpkeyb
.
escaped
=
hpkeyb_keycode
[
scancode
];
break
;
case
KBD_UNKNOWN
:
DPRINTK
(
"received unknown scancode %d, escape %d.
\n
"
,
scancode
,
hpkeyb
.
escaped
);
/* This is a DPRINTK atm since we do not handle escaped scancodes cleanly */
if
(
hpkeyb
.
escaped
)
hpkeyb
.
escaped
=
0
;
if
(
hpkeyb
.
released
)
hpkeyb
.
released
=
0
;
return
;
default:
hpkeyb
.
scancode
=
scancode
;
DPRINTK
(
"sent=%d, rel=%d
\n
"
,
hpkeyb
.
scancode
,
hpkeyb
.
released
);
/*input_regs(regs);*/
input_report_key
(
&
hpkeyb
.
dev
,
hpkeyb_keycode
[
hpkeyb
.
scancode
],
!
hpkeyb
.
released
);
input_sync
(
&
hpkeyb
.
dev
);
if
(
hpkeyb
.
escaped
)
hpkeyb
.
escaped
=
0
;
if
(
hpkeyb
.
released
)
hpkeyb
.
released
=
0
;
break
;
}
}
/**
* gscps2_mouse_docode() - PS2 Mouse basic handler
*
* Receives mouse codes, processes them by packets of three, and sends
* correct events to the input layer.
*/
static
void
gscps2_mouse_docode
(
struct
pt_regs
*
regs
)
{
int
xrel
,
yrel
;
/* process BAT (end of basic tests) command */
if
((
hpmouse
.
nbread
==
1
)
&&
(
hpmouse
.
bytes
[
0
]
==
AUX_RECONNECT
))
hpmouse
.
nbread
--
;
/* stolen from psmouse.c */
if
(
hpmouse
.
nbread
&&
time_after
(
jiffies
,
hpmouse
.
last
+
HZ
/
2
))
{
printk
(
KERN_DEBUG
"%s:%d : Lost mouse synchronization, throwing %d bytes away.
\n
"
,
__FILE__
,
__LINE__
,
hpmouse
.
nbread
);
hpmouse
.
nbread
=
0
;
}
hpmouse
.
last
=
jiffies
;
hpmouse
.
bytes
[
hpmouse
.
nbread
++
]
=
gscps2_readb_input
(
hpmouse
.
addr
);
/* process packet */
if
(
hpmouse
.
nbread
==
3
)
{
if
(
!
(
hpmouse
.
bytes
[
PACKET_CTRL
]
&
MOUSE_ALWAYS1
))
DPRINTK
(
"Mouse: error on packet always1 bit checking
\n
"
);
/* XXX should exit now, bad data on the line! */
if
((
hpmouse
.
bytes
[
PACKET_CTRL
]
&
(
MOUSE_XOVFLOW
|
MOUSE_YOVFLOW
)))
DPRINTK
(
"Mouse: position overflow
\n
"
);
/*input_regs(regs);*/
input_report_key
(
&
hpmouse
.
dev
,
BTN_LEFT
,
hpmouse
.
bytes
[
PACKET_CTRL
]
&
MOUSE_LEFTBTN
);
input_report_key
(
&
hpmouse
.
dev
,
BTN_MIDDLE
,
hpmouse
.
bytes
[
PACKET_CTRL
]
&
MOUSE_MIDBTN
);
input_report_key
(
&
hpmouse
.
dev
,
BTN_RIGHT
,
hpmouse
.
bytes
[
PACKET_CTRL
]
&
MOUSE_RIGHTBTN
);
xrel
=
hpmouse
.
bytes
[
PACKET_X
];
yrel
=
hpmouse
.
bytes
[
PACKET_Y
];
/* Data sent by mouse are 9-bit signed, the sign bit is in the control packet */
if
(
xrel
&&
(
hpmouse
.
bytes
[
PACKET_CTRL
]
&
MOUSE_XSIGN
))
xrel
=
xrel
-
0x100
;
if
(
yrel
&&
(
hpmouse
.
bytes
[
PACKET_CTRL
]
&
MOUSE_YSIGN
))
yrel
=
yrel
-
0x100
;
input_report_rel
(
&
hpmouse
.
dev
,
REL_X
,
xrel
);
input_report_rel
(
&
hpmouse
.
dev
,
REL_Y
,
-
yrel
);
/* Y axis is received upside-down */
input_sync
(
&
hpmouse
.
dev
);
hpmouse
.
nbread
=
0
;
}
}
/**
* gscps2_interrupt() - Interruption service routine
*
* This processes the list of scancodes queued and sends appropriate
* key value to the system.
*/
static
irqreturn_t
gscps2_interrupt
(
int
irq
,
void
*
dev
,
struct
pt_regs
*
reg
)
{
/* process mouse actions */
while
(
gscps2_readb_status
(
hpmouse
.
addr
)
&
GSC_STAT_RBNE
)
gscps2_mouse_docode
(
reg
);
/* process keyboard scancode */
while
(
gscps2_readb_status
(
hpkeyb
.
addr
)
&
GSC_STAT_RBNE
)
gscps2_kbd_docode
(
reg
);
return
IRQ_HANDLED
;
}
/**
* gscps2_hpkeyb_event() - Event handler
* @return: success/error report
*
* Currently only updates leds on keyboard
*/
int
gscps2_hpkeyb_event
(
struct
input_dev
*
dev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
DPRINTK
(
"Calling %s, type=%d, code=%d, value=%d
\n
"
,
__FUNCTION__
,
type
,
code
,
value
);
if
(
!
hpkeyb
.
initialized
)
return
-
1
;
if
(
type
==
EV_LED
)
{
u8
leds
[
2
];
if
(
gscps2_writeb_safe_output
(
KBD_CMD_SET_LEDS
))
{
printk
(
KERN_ERR
"gsckbd_leds: timeout
\n
"
);
return
-
1
;
}
DPRINTK
(
"KBD_CMD_SET_LEDS
\n
"
);
*
leds
=
(
test_bit
(
LED_SCROLLL
,
dev
->
led
)
?
LED_SCR
:
0
)
|
(
test_bit
(
LED_NUML
,
dev
->
led
)
?
LED_NUM
:
0
)
|
(
test_bit
(
LED_CAPSL
,
dev
->
led
)
?
LED_CAP
:
0
);
DPRINTK
(
"Sending leds=%x
\n
"
,
*
leds
);
if
(
gscps2_writeb_safe_output
(
*
leds
))
{
printk
(
KERN_ERR
"gsckbd_leds: timeout
\n
"
);
return
-
1
;
}
DPRINTK
(
"leds sent
\n
"
);
if
(
gscps2_writeb_safe_output
(
KBD_CMD_ENABLE
))
{
printk
(
KERN_ERR
"gsckbd_leds: timeout
\n
"
);
return
-
1
;
}
DPRINTK
(
"End
\n
"
);
return
0
;
}
return
-
1
;
}
/**
* gscps2_kbd_probe() - Probes keyboard device and init input_dev structure
* @return: number of device initialized (1, 0 on error)
*/
static
int
__init
gscps2_kbd_probe
(
void
)
{
int
i
,
res
=
0
;
unsigned
long
flags
;
if
(
hpkeyb
.
initialized
)
{
printk
(
KERN_ERR
"GSC PS/2 keyboard driver already registered
\n
"
);
return
0
;
}
spin_lock_irqsave
(
&
gscps2_lock
,
flags
);
if
(
!
gscps2_writeb_safe_output
(
KBD_CMD_SET_LEDS
)
&&
!
gscps2_writeb_safe_output
(
0
)
&&
!
gscps2_writeb_safe_output
(
KBD_CMD_ENABLE
))
res
=
1
;
spin_unlock_irqrestore
(
&
gscps2_lock
,
flags
);
if
(
!
res
)
printk
(
KERN_ERR
"Keyboard initialization sequence failled
\n
"
);
init_input_dev
(
&
hpkeyb
.
dev
);
for
(
i
=
0
;
i
<
KBD_TBLSIZE
;
i
++
)
if
(
hpkeyb_keycode
[
i
]
!=
KBD_UNKNOWN
)
set_bit
(
hpkeyb_keycode
[
i
],
hpkeyb
.
dev
.
keybit
);
hpkeyb
.
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_LED
)
|
BIT
(
EV_REP
);
hpkeyb
.
dev
.
ledbit
[
0
]
=
BIT
(
LED_NUML
)
|
BIT
(
LED_CAPSL
)
|
BIT
(
LED_SCROLLL
);
hpkeyb
.
dev
.
keycode
=
hpkeyb_keycode
;
hpkeyb
.
dev
.
keycodesize
=
sizeof
(
unsigned
char
);
hpkeyb
.
dev
.
keycodemax
=
KBD_TBLSIZE
;
hpkeyb
.
dev
.
name
=
"GSC Keyboard"
;
hpkeyb
.
dev
.
phys
=
"hpkbd/input0"
;
hpkeyb
.
dev
.
event
=
gscps2_hpkeyb_event
;
/* TODO These need some adjustement, are they really useful ? */
hpkeyb
.
dev
.
id
.
bustype
=
BUS_GSC
;
hpkeyb
.
dev
.
id
.
vendor
=
PCI_VENDOR_ID_HP
;
hpkeyb
.
dev
.
id
.
product
=
0x0001
;
hpkeyb
.
dev
.
id
.
version
=
0x0010
;
hpkeyb
.
initialized
=
1
;
return
1
;
}
/**
* gscps2_mouse_probe() - Probes mouse device and init input_dev structure
* @return: number of device initialized (1, 0 on error)
*
* Currently no check on initialization is performed
*/
static
int
__init
gscps2_mouse_probe
(
void
)
{
if
(
hpmouse
.
initialized
)
{
printk
(
KERN_ERR
"GSC PS/2 Mouse driver already registered
\n
"
);
return
0
;
}
init_input_dev
(
&
hpmouse
.
dev
);
hpmouse
.
dev
.
name
=
"GSC Mouse"
;
hpmouse
.
dev
.
phys
=
"hpmouse/input0"
;
hpmouse
.
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_REL
);
hpmouse
.
dev
.
keybit
[
LONG
(
BTN_MOUSE
)]
=
BIT
(
BTN_LEFT
)
|
BIT
(
BTN_MIDDLE
)
|
BIT
(
BTN_RIGHT
);
hpmouse
.
dev
.
relbit
[
0
]
=
BIT
(
REL_X
)
|
BIT
(
REL_Y
);
hpmouse
.
last
=
0
;
gscps2_writeb_output
(
AUX_ENABLE_DEV
,
hpmouse
.
addr
);
/* Try it a second time, this will give status if the device is available */
gscps2_writeb_output
(
AUX_ENABLE_DEV
,
hpmouse
.
addr
);
/* TODO These need some adjustement, are they really useful ? */
hpmouse
.
dev
.
id
.
bustype
=
BUS_GSC
;
hpmouse
.
dev
.
id
.
vendor
=
0x0001
;
hpmouse
.
dev
.
id
.
product
=
0x0001
;
hpmouse
.
dev
.
id
.
version
=
0x0010
;
hpmouse
.
initialized
=
1
;
return
1
;
/* XXX: we don't check if initialization failed */
}
/**
* gscps2_probe() - Probes PS2 devices
* @return: success/error report
*/
static
int
__init
gscps2_probe
(
struct
parisc_device
*
dev
)
{
u8
id
;
char
*
addr
,
*
name
;
int
ret
=
0
,
device_found
=
0
;
unsigned
long
hpa
=
dev
->
hpa
;
if
(
!
dev
->
irq
)
goto
fail_pitifully
;
/* Offset for DINO PS/2. Works with LASI even */
if
(
dev
->
id
.
sversion
==
0x96
)
hpa
+=
GSC_DINO_OFFSET
;
addr
=
ioremap
(
hpa
,
256
);
if
(
!
hpmouse
.
initialized
||
!
hpkeyb
.
initialized
)
gscps2_reset
(
addr
);
ret
=
-
EINVAL
;
id
=
readb
(
addr
+
GSC_ID
)
&
0x0f
;
switch
(
id
)
{
case
0
:
/* keyboard */
hpkeyb
.
addr
=
addr
;
name
=
"keyboard"
;
device_found
=
gscps2_kbd_probe
();
break
;
case
1
:
/* mouse */
hpmouse
.
addr
=
addr
;
name
=
"mouse"
;
device_found
=
gscps2_mouse_probe
();
break
;
default:
printk
(
KERN_WARNING
"%s: Unsupported PS/2 port (id=%d) ignored
\n
"
,
__FUNCTION__
,
id
);
goto
fail_miserably
;
}
/* No valid device found */
ret
=
-
ENODEV
;
if
(
!
device_found
)
goto
fail_miserably
;
/* Here we claim only if we have a device attached */
/* Allocate the irq and memory region for that device */
ret
=
-
EBUSY
;
if
(
request_irq
(
dev
->
irq
,
gscps2_interrupt
,
0
,
name
,
NULL
))
goto
fail_miserably
;
if
(
!
request_mem_region
(
hpa
,
GSC_STATUS
+
4
,
name
))
goto
fail_request_mem
;
/* Finalize input struct and register it */
switch
(
id
)
{
case
0
:
/* keyboard */
hpkeyb
.
irq
=
dev
->
irq
;
input_register_device
(
&
hpkeyb
.
dev
);
break
;
case
1
:
/* mouse */
hpmouse
.
irq
=
dev
->
irq
;
input_register_device
(
&
hpmouse
.
dev
);
break
;
default:
break
;
}
printk
(
KERN_INFO
"input: PS/2 %s port at 0x%08lx (irq %d) found and attached
\n
"
,
name
,
hpa
,
dev
->
irq
);
return
0
;
fail_request_mem:
free_irq
(
dev
->
irq
,
NULL
);
fail_miserably:
iounmap
(
addr
);
fail_pitifully:
return
ret
;
}
static
struct
parisc_device_id
gscps2_device_tbl
[]
=
{
{
HPHW_FIO
,
HVERSION_REV_ANY_ID
,
HVERSION_ANY_ID
,
0x00084
},
/* LASI PS/2 */
/* { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, DINO PS/2 (XXX Not yet tested) */
{
0
,
}
/* 0 terminated list */
};
static
struct
parisc_driver
gscps2_driver
=
{
.
name
=
"GSC PS2"
,
.
id_table
=
gscps2_device_tbl
,
.
probe
=
gscps2_probe
,
};
static
int
__init
gscps2_init
(
void
)
{
if
(
register_parisc_driver
(
&
gscps2_driver
))
return
-
EBUSY
;
return
0
;
}
static
void
__exit
gscps2_exit
(
void
)
{
/* TODO this is probably not very good and needs to be checked */
if
(
hpkeyb
.
initialized
)
{
free_irq
(
hpkeyb
.
irq
,
gscps2_interrupt
);
iounmap
(
hpkeyb
.
addr
);
hpkeyb
.
initialized
=
0
;
input_unregister_device
(
&
hpkeyb
.
dev
);
}
if
(
hpmouse
.
initialized
)
{
free_irq
(
hpmouse
.
irq
,
gscps2_interrupt
);
iounmap
(
hpmouse
.
addr
);
hpmouse
.
initialized
=
0
;
input_unregister_device
(
&
hpmouse
.
dev
);
}
unregister_parisc_driver
(
&
gscps2_driver
);
}
MODULE_AUTHOR
(
"Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>"
);
MODULE_DESCRIPTION
(
"GSC PS/2 keyboard/mouse driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DEVICE_TABLE
(
parisc
,
gscps2_device_tbl
);
module_init
(
gscps2_init
);
module_exit
(
gscps2_exit
);
drivers/input/mouse/Kconfig
View file @
e832882d
...
...
@@ -17,6 +17,7 @@ config MOUSE_PS2
depends on INPUT && INPUT_MOUSE
select SERIO
select SERIO_I8042 if PC
select SERIO_GSCPS2 if GSC
---help---
Say Y here if you have a PS/2 mouse connected to your system. This
includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
...
...
drivers/input/serio/Kconfig
View file @
e832882d
...
...
@@ -20,6 +20,7 @@ config SERIO_I8042
tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
default y
select SERIO
depends on !PARISC
---help---
i8042 is the chip over which the standard AT keyboard and PS/2
mouse are connected to the computer. If you use these devices,
...
...
@@ -48,6 +49,7 @@ config SERIO_SERPORT
config SERIO_CT82C710
tristate "ct82c710 Aux port controller"
depends on SERIO
depends on !PARISC
---help---
Say Y here if you have a Texas Instruments TravelMate notebook
equipped with the ct82c710 chip and want to use a mouse connected
...
...
@@ -105,6 +107,20 @@ config SERIO_98KBD
To compile this driver as a module, choose M here: the
module will be called 98kbd-io.
config SERIO_GSCPS2
tristate "HP GSC PS/2 keyboard and PS/2 mouse controller"
depends on GSC && SERIO
default y
help
This driver provides support for the PS/2 ports on PA-RISC machines
over which HP PS/2 keyboards and PS/2 mice may be connected.
If you use these devices, you'll need to say Y here.
It's safe to enable this driver, so if unsure, say Y.
To compile this driver as a module, choose M here: the
module will be called gscps2.
config SERIO_PCIPS2
tristate "PCI PS/2 keyboard and PS/2 mouse controller"
depends on PCI && SERIO
...
...
drivers/input/serio/Makefile
View file @
e832882d
...
...
@@ -14,4 +14,5 @@ obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o
obj-$(CONFIG_SERIO_AMBAKMI)
+=
ambakmi.o
obj-$(CONFIG_SERIO_Q40KBD)
+=
q40kbd.o
obj-$(CONFIG_SERIO_98KBD)
+=
98kbd-io.o
obj-$(CONFIG_SERIO_GSCPS2)
+=
gscps2.o
obj-$(CONFIG_SERIO_PCIPS2)
+=
pcips2.o
drivers/input/serio/gscps2.c
0 → 100644
View file @
e832882d
/*
* drivers/input/serio/gscps2.c
*
* Copyright (c) 2004 Helge Deller <deller@gmx.de>
* Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
* Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
*
* Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
* Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
* Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
* Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
* Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
*
* HP GSC PS/2 port driver, found in PA/RISC Workstations
*
* 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.
*
* TODO:
* - Dino testing (did HP ever shipped a machine on which this port
* was usable/enabled ?)
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/serio.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/pci_ids.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/parisc-device.h>
MODULE_AUTHOR
(
"Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>, Helge Deller <deller@gmx.de>"
);
MODULE_DESCRIPTION
(
"HP GSC PS/2 port driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DEVICE_TABLE
(
parisc
,
gscps2_device_tbl
);
#define PFX "gscps2.c: "
/*
* Driver constants
*/
/* various constants */
#define ENABLE 1
#define DISABLE 0
#define GSC_DINO_OFFSET 0x0800
/* offset for DINO controller versus LASI one */
/* PS/2 IO port offsets */
#define GSC_ID 0x00
/* device ID offset (see: GSC_ID_XXX) */
#define GSC_RESET 0x00
/* reset port offset */
#define GSC_RCVDATA 0x04
/* receive port offset */
#define GSC_XMTDATA 0x04
/* transmit port offset */
#define GSC_CONTROL 0x08
/* see: Control register bits */
#define GSC_STATUS 0x0C
/* see: Status register bits */
/* Control register bits */
#define GSC_CTRL_ENBL 0x01
/* enable interface */
#define GSC_CTRL_LPBXR 0x02
/* loopback operation */
#define GSC_CTRL_DIAG 0x20
/* directly control clock/data line */
#define GSC_CTRL_DATDIR 0x40
/* data line direct control */
#define GSC_CTRL_CLKDIR 0x80
/* clock line direct control */
/* Status register bits */
#define GSC_STAT_RBNE 0x01
/* Receive Buffer Not Empty */
#define GSC_STAT_TBNE 0x02
/* Transmit Buffer Not Empty */
#define GSC_STAT_TERR 0x04
/* Timeout Error */
#define GSC_STAT_PERR 0x08
/* Parity Error */
#define GSC_STAT_CMPINTR 0x10
/* Composite Interrupt = irq on any port */
#define GSC_STAT_DATSHD 0x40
/* Data Line Shadow */
#define GSC_STAT_CLKSHD 0x80
/* Clock Line Shadow */
/* IDs returned by GSC_ID port register */
#define GSC_ID_KEYBOARD 0
/* device ID values */
#define GSC_ID_MOUSE 1
static
irqreturn_t
gscps2_interrupt
(
int
irq
,
void
*
dev
,
struct
pt_regs
*
regs
);
#define BUFFER_SIZE 0x0f
/* GSC PS/2 port device struct */
struct
gscps2port
{
struct
list_head
node
;
struct
parisc_device
*
padev
;
struct
serio
port
;
spinlock_t
lock
;
char
*
addr
;
u8
act
,
append
;
/* position in buffer[] */
struct
{
u8
data
;
u8
str
;
}
buffer
[
BUFFER_SIZE
+
1
];
int
id
;
char
name
[
32
];
};
/*
* Various HW level routines
*/
#define gscps2_readb_input(x) readb((x)+GSC_RCVDATA)
#define gscps2_readb_control(x) readb((x)+GSC_CONTROL)
#define gscps2_readb_status(x) readb((x)+GSC_STATUS)
#define gscps2_writeb_control(x, y) writeb((x), (y)+GSC_CONTROL)
/*
* wait_TBE() - wait for Transmit Buffer Empty
*/
static
int
wait_TBE
(
char
*
addr
)
{
int
timeout
=
25000
;
/* device is expected to react within 250 msec */
while
(
gscps2_readb_status
(
addr
)
&
GSC_STAT_TBNE
)
{
if
(
!--
timeout
)
return
0
;
/* This should not happen */
udelay
(
10
);
}
return
1
;
}
/*
* gscps2_flush() - flush the receive buffer
*/
static
void
gscps2_flush
(
struct
gscps2port
*
ps2port
)
{
while
(
gscps2_readb_status
(
ps2port
->
addr
)
&
GSC_STAT_RBNE
)
gscps2_readb_input
(
ps2port
->
addr
);
ps2port
->
act
=
ps2port
->
append
=
0
;
}
/*
* gscps2_writeb_output() - write a byte to the port
*
* returns 1 on sucess, 0 on error
*/
static
inline
int
gscps2_writeb_output
(
struct
gscps2port
*
ps2port
,
u8
data
)
{
unsigned
long
flags
;
char
*
addr
=
ps2port
->
addr
;
if
(
!
wait_TBE
(
addr
))
{
printk
(
KERN_DEBUG
PFX
"timeout - could not write byte %#x
\n
"
,
data
);
return
0
;
}
while
(
gscps2_readb_status
(
ps2port
->
addr
)
&
GSC_STAT_RBNE
)
/* wait */
;
spin_lock_irqsave
(
&
ps2port
->
lock
,
flags
);
writeb
(
data
,
addr
+
GSC_XMTDATA
);
spin_unlock_irqrestore
(
&
ps2port
->
lock
,
flags
);
/* this is ugly, but due to timing of the port it seems to be necessary. */
mdelay
(
6
);
/* make sure any received data is returned as fast as possible */
/* this is important e.g. when we set the LEDs on the keyboard */
gscps2_interrupt
(
0
,
NULL
,
NULL
);
return
1
;
}
/*
* gscps2_enable() - enables or disables the port
*/
static
void
gscps2_enable
(
struct
gscps2port
*
ps2port
,
int
enable
)
{
unsigned
long
flags
;
u8
data
;
/* now enable/disable the port */
spin_lock_irqsave
(
&
ps2port
->
lock
,
flags
);
gscps2_flush
(
ps2port
);
data
=
gscps2_readb_control
(
ps2port
->
addr
);
if
(
enable
)
data
|=
GSC_CTRL_ENBL
;
else
data
&=
~
GSC_CTRL_ENBL
;
gscps2_writeb_control
(
data
,
ps2port
->
addr
);
spin_unlock_irqrestore
(
&
ps2port
->
lock
,
flags
);
wait_TBE
(
ps2port
->
addr
);
gscps2_flush
(
ps2port
);
}
/*
* gscps2_reset() - resets the PS/2 port
*/
static
void
gscps2_reset
(
struct
gscps2port
*
ps2port
)
{
char
*
addr
=
ps2port
->
addr
;
unsigned
long
flags
;
/* reset the interface */
spin_lock_irqsave
(
&
ps2port
->
lock
,
flags
);
gscps2_flush
(
ps2port
);
writeb
(
0xff
,
addr
+
GSC_RESET
);
gscps2_flush
(
ps2port
);
spin_unlock_irqrestore
(
&
ps2port
->
lock
,
flags
);
/* enable it */
gscps2_enable
(
ps2port
,
ENABLE
);
}
static
LIST_HEAD
(
ps2port_list
);
/**
* gscps2_interrupt() - Interruption service routine
*
* This function reads received PS/2 bytes and processes them on
* all interfaces.
* The problematic part here is, that the keyboard and mouse PS/2 port
* share the same interrupt and it's not possible to send data if any
* one of them holds input data. To solve this problem we try to receive
* the data as fast as possible and handle the reporting to the upper layer
* later.
*/
static
irqreturn_t
gscps2_interrupt
(
int
irq
,
void
*
dev
,
struct
pt_regs
*
regs
)
{
struct
gscps2port
*
ps2port
;
list_for_each_entry
(
ps2port
,
&
ps2port_list
,
node
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
ps2port
->
lock
,
flags
);
while
(
(
ps2port
->
buffer
[
ps2port
->
append
].
str
=
gscps2_readb_status
(
ps2port
->
addr
))
&
GSC_STAT_RBNE
)
{
ps2port
->
buffer
[
ps2port
->
append
].
data
=
gscps2_readb_input
(
ps2port
->
addr
);
ps2port
->
append
=
((
ps2port
->
append
+
1
)
&
BUFFER_SIZE
);
}
spin_unlock_irqrestore
(
&
ps2port
->
lock
,
flags
);
}
/* list_for_each_entry */
/* all data was read from the ports - now report the data to upper layer */
list_for_each_entry
(
ps2port
,
&
ps2port_list
,
node
)
{
while
(
ps2port
->
act
!=
ps2port
->
append
)
{
unsigned
int
rxflags
;
u8
data
,
status
;
/* Did new data arrived while we read existing data ?
If yes, exit now and let the new irq handler start over again */
if
(
gscps2_readb_status
(
ps2port
->
addr
)
&
GSC_STAT_CMPINTR
)
return
IRQ_HANDLED
;
status
=
ps2port
->
buffer
[
ps2port
->
act
].
str
;
data
=
ps2port
->
buffer
[
ps2port
->
act
].
data
;
ps2port
->
act
=
((
ps2port
->
act
+
1
)
&
BUFFER_SIZE
);
rxflags
=
((
status
&
GSC_STAT_TERR
)
?
SERIO_TIMEOUT
:
0
)
|
((
status
&
GSC_STAT_PERR
)
?
SERIO_PARITY
:
0
);
serio_interrupt
(
&
ps2port
->
port
,
data
,
rxflags
,
regs
);
}
/* while() */
}
/* list_for_each_entry */
return
IRQ_HANDLED
;
}
/*
* gscps2_write() - send a byte out through the aux interface.
*/
static
int
gscps2_write
(
struct
serio
*
port
,
unsigned
char
data
)
{
struct
gscps2port
*
ps2port
=
port
->
driver
;
if
(
!
gscps2_writeb_output
(
ps2port
,
data
))
{
printk
(
KERN_DEBUG
PFX
"sending byte %#x failed.
\n
"
,
data
);
return
-
1
;
}
return
0
;
}
/*
* gscps2_open() is called when a port is opened by the higher layer.
* It resets and enables the port.
*/
static
int
gscps2_open
(
struct
serio
*
port
)
{
struct
gscps2port
*
ps2port
=
port
->
driver
;
gscps2_reset
(
ps2port
);
gscps2_interrupt
(
0
,
NULL
,
NULL
);
return
0
;
}
/*
* gscps2_close() disables the port
*/
static
void
gscps2_close
(
struct
serio
*
port
)
{
struct
gscps2port
*
ps2port
=
port
->
driver
;
gscps2_enable
(
ps2port
,
DISABLE
);
}
static
struct
serio
gscps2_serio_port
=
{
.
name
=
"GSC PS/2"
,
.
idbus
=
BUS_GSC
,
.
idvendor
=
PCI_VENDOR_ID_HP
,
.
idproduct
=
0x0001
,
.
idversion
=
0x0010
,
.
type
=
SERIO_8042
,
.
write
=
gscps2_write
,
.
open
=
gscps2_open
,
.
close
=
gscps2_close
,
};
/**
* gscps2_probe() - Probes PS2 devices
* @return: success/error report
*/
static
int
__init
gscps2_probe
(
struct
parisc_device
*
dev
)
{
struct
gscps2port
*
ps2port
;
unsigned
long
hpa
=
dev
->
hpa
;
int
ret
;
if
(
!
dev
->
irq
)
return
-
ENODEV
;
/* Offset for DINO PS/2. Works with LASI even */
if
(
dev
->
id
.
sversion
==
0x96
)
hpa
+=
GSC_DINO_OFFSET
;
ps2port
=
kmalloc
(
sizeof
(
struct
gscps2port
),
GFP_KERNEL
);
if
(
!
ps2port
)
return
-
ENOMEM
;
dev_set_drvdata
(
&
dev
->
dev
,
ps2port
);
memset
(
ps2port
,
0
,
sizeof
(
struct
gscps2port
));
ps2port
->
padev
=
dev
;
ps2port
->
addr
=
ioremap
(
hpa
,
GSC_STATUS
+
4
);
spin_lock_init
(
&
ps2port
->
lock
);
gscps2_reset
(
ps2port
);
ps2port
->
id
=
readb
(
ps2port
->
addr
+
GSC_ID
)
&
0x0f
;
snprintf
(
ps2port
->
name
,
sizeof
(
ps2port
->
name
)
-
1
,
"%s %s"
,
gscps2_serio_port
.
name
,
(
ps2port
->
id
==
GSC_ID_KEYBOARD
)
?
"keyboard"
:
"mouse"
);
memcpy
(
&
ps2port
->
port
,
&
gscps2_serio_port
,
sizeof
(
gscps2_serio_port
));
ps2port
->
port
.
driver
=
ps2port
;
ps2port
->
port
.
name
=
ps2port
->
name
;
ps2port
->
port
.
phys
=
dev
->
dev
.
bus_id
;
list_add_tail
(
&
ps2port
->
node
,
&
ps2port_list
);
ret
=
-
EBUSY
;
if
(
request_irq
(
dev
->
irq
,
gscps2_interrupt
,
SA_SHIRQ
,
ps2port
->
name
,
ps2port
))
goto
fail_miserably
;
if
(
(
ps2port
->
id
!=
GSC_ID_KEYBOARD
)
&&
(
ps2port
->
id
!=
GSC_ID_MOUSE
)
)
{
printk
(
KERN_WARNING
PFX
"Unsupported PS/2 port at 0x%08lx (id=%d) ignored
\n
"
,
hpa
,
ps2port
->
id
);
ret
=
-
ENODEV
;
goto
fail
;
}
#if 0
if (!request_mem_region(hpa, GSC_STATUS + 4, ps2port->port.name))
goto fail;
#endif
printk
(
KERN_INFO
"serio: %s port at 0x%p irq %d @ %s
\n
"
,
ps2port
->
name
,
ps2port
->
addr
,
ps2port
->
padev
->
irq
,
ps2port
->
port
.
phys
);
serio_register_port
(
&
ps2port
->
port
);
return
0
;
fail:
free_irq
(
dev
->
irq
,
ps2port
);
fail_miserably:
list_del
(
&
ps2port
->
node
);
iounmap
(
ps2port
->
addr
);
release_mem_region
(
dev
->
hpa
,
GSC_STATUS
+
4
);
kfree
(
ps2port
);
return
ret
;
}
/**
* gscps2_remove() - Removes PS2 devices
* @return: success/error report
*/
static
int
__devexit
gscps2_remove
(
struct
parisc_device
*
dev
)
{
struct
gscps2port
*
ps2port
=
dev_get_drvdata
(
&
dev
->
dev
);
serio_unregister_port
(
&
ps2port
->
port
);
free_irq
(
dev
->
irq
,
ps2port
);
gscps2_flush
(
ps2port
);
list_del
(
&
ps2port
->
node
);
iounmap
(
ps2port
->
addr
);
#if 0
release_mem_region(dev->hpa, GSC_STATUS + 4);
#endif
dev_set_drvdata
(
&
dev
->
dev
,
NULL
);
kfree
(
ps2port
);
return
0
;
}
static
struct
parisc_device_id
gscps2_device_tbl
[]
=
{
{
HPHW_FIO
,
HVERSION_REV_ANY_ID
,
HVERSION_ANY_ID
,
0x00084
},
/* LASI PS/2 */
#ifdef DINO_TESTED
{
HPHW_FIO
,
HVERSION_REV_ANY_ID
,
HVERSION_ANY_ID
,
0x00096
},
/* DINO PS/2 */
#endif
{
0
,
}
/* 0 terminated list */
};
static
struct
parisc_driver
parisc_ps2_driver
=
{
.
name
=
"GSC PS/2"
,
.
id_table
=
gscps2_device_tbl
,
.
probe
=
gscps2_probe
,
.
remove
=
gscps2_remove
,
};
static
int
__init
gscps2_init
(
void
)
{
register_parisc_driver
(
&
parisc_ps2_driver
);
return
0
;
}
static
void
__exit
gscps2_exit
(
void
)
{
unregister_parisc_driver
(
&
parisc_ps2_driver
);
}
module_init
(
gscps2_init
);
module_exit
(
gscps2_exit
);
drivers/usb/input/hid-core.c
View file @
e832882d
...
...
@@ -224,6 +224,9 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
offset
=
report
->
size
;
report
->
size
+=
parser
->
global
.
report_size
*
parser
->
global
.
report_count
;
if
(
usages
<
parser
->
global
.
report_count
)
usages
=
parser
->
global
.
report_count
;
if
(
usages
==
0
)
return
0
;
/* ignore padding fields */
...
...
@@ -235,9 +238,13 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
field
->
application
=
hid_lookup_collection
(
parser
,
HID_COLLECTION_APPLICATION
);
for
(
i
=
0
;
i
<
usages
;
i
++
)
{
field
->
usage
[
i
].
hid
=
parser
->
local
.
usage
[
i
];
int
j
=
i
;
/* Duplicate the last usage we parsed if we have excess values */
if
(
i
>=
parser
->
local
.
usage_index
)
j
=
parser
->
local
.
usage_index
-
1
;
field
->
usage
[
i
].
hid
=
parser
->
local
.
usage
[
j
];
field
->
usage
[
i
].
collection_index
=
parser
->
local
.
collection_index
[
i
];
parser
->
local
.
collection_index
[
j
];
}
field
->
maxusage
=
usages
;
...
...
@@ -1315,7 +1322,6 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_KBGEAR 0x084e
#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
#define USB_VENDOR_ID_AIPTEK 0x08ca
#define USB_DEVICE_ID_AIPTEK_6000 0x0020
...
...
@@ -1354,17 +1360,40 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_A4TECH 0x09DA
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
#define USB_VENDOR_ID_CYPRESS 0x04b4
#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001
#define USB_VENDOR_ID_BERKSHIRE 0x0c98
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
#define USB_VENDOR_ID_ALPS 0x0433
#define USB_DEVICE_ID_IBM_GAMEPAD 0x1101
#define USB_VENDOR_ID_SAITEK 0x06a3
#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
struct
hid_blacklist
{
__u16
idVendor
;
__u16
idProduct
;
unsigned
quirks
;
}
hid_blacklist
[]
=
{
{
USB_VENDOR_ID_AIPTEK
,
USB_DEVICE_ID_AIPTEK_6000
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_BERKSHIRE
,
USB_DEVICE_ID_BERKSHIRE_PCWD
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ESSENTIAL_REALITY
,
USB_DEVICE_ID_ESSENTIAL_REALITY_P5
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_KBGEAR
,
USB_DEVICE_ID_KBGEAR_JAMSTUDIO
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_GRIFFIN
,
USB_DEVICE_ID_POWERMATE
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_GRIFFIN
,
USB_DEVICE_ID_SOUNDKNOB
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_MGE
,
USB_DEVICE_ID_MGE_UPS
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_MGE
,
USB_DEVICE_ID_MGE_UPS1
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
100
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
200
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
300
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
400
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
500
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_PENPARTNER
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_GRAPHIRE
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_GRAPHIRE
+
1
,
HID_QUIRK_IGNORE
},
...
...
@@ -1386,32 +1415,24 @@ struct hid_blacklist {
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_INTUOS2
+
2
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_INTUOS2
+
3
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_INTUOS2
+
4
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_KBGEAR
,
USB_DEVICE_ID_KBGEAR_JAMSTUDIO
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_AIPTEK
,
USB_DEVICE_ID_AIPTEK_6000
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_GRIFFIN
,
USB_DEVICE_ID_POWERMATE
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_GRIFFIN
,
USB_DEVICE_ID_SOUNDKNOB
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ATEN
,
USB_DEVICE_ID_ATEN_UC100KM
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_ATEN
,
USB_DEVICE_ID_ATEN_CS124U
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_ATEN
,
USB_DEVICE_ID_ATEN_2PORTKVM
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_ATEN
,
USB_DEVICE_ID_ATEN_4PORTKVM
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_ATEN
,
USB_DEVICE_ID_ATEN_4PORTKVMC
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_MGE
,
USB_DEVICE_ID_MGE_UPS
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_MGE
,
USB_DEVICE_ID_MGE_UPS1
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_TOPMAX
,
USB_DEVICE_ID_TOPMAX_COBRAPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_DRIVING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_FLYING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_FIGHTING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
100
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
200
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
300
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
400
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
500
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_TANGTOP
,
USB_DEVICE_ID_TANGTOP_USBPS2
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_ESSENTIAL_REALITY
,
USB_DEVICE_ID_ESSENTIAL_REALITY_P5
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_A4TECH
,
USB_DEVICE_ID_A4TECH_WCP32PU
,
HID_QUIRK_2WHEEL_MOUSE_HACK
},
{
USB_VENDOR_ID_BERKSHIRE
,
USB_DEVICE_ID_BERKSHIRE_PCWD
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_CYPRESS
,
USB_DEVICE_ID_CYPRESS_MOUSE
,
HID_QUIRK_2WHEEL_MOUSE_HACK
},
{
USB_VENDOR_ID_ALPS
,
USB_DEVICE_ID_IBM_GAMEPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_DRIVING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_FLYING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_FIGHTING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_SAITEK
,
USB_DEVICE_ID_SAITEK_RUMBLEPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_TOPMAX
,
USB_DEVICE_ID_TOPMAX_COBRAPAD
,
HID_QUIRK_BADPAD
},
{
0
,
0
}
};
...
...
drivers/usb/input/hid-input.c
View file @
e832882d
...
...
@@ -432,20 +432,21 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
input_regs
(
input
,
regs
);
if
((
hid
->
quirks
&
HID_QUIRK_2WHEEL_MOUSE_HACK
)
&&
(
usage
->
code
==
BTN_BACK
))
{
&&
(
usage
->
code
==
BTN_BACK
||
usage
->
code
==
BTN_EXTRA
))
{
if
(
value
)
hid
->
quirks
|=
HID_QUIRK_2WHEEL_MOUSE_HACK_ON
;
else
hid
->
quirks
&=
~
HID_QUIRK_2WHEEL_MOUSE_HACK_ON
;
return
;
}
if
((
hid
->
quirks
&
HID_QUIRK_2WHEEL_MOUSE_HACK_ON
)
&&
(
usage
->
code
==
REL_WHEEL
))
{
input_event
(
input
,
usage
->
type
,
REL_HWHEEL
,
value
);
return
;
}
if
(
usage
->
hat_min
!=
usage
->
hat_max
)
{
if
(
usage
->
hat_min
!=
usage
->
hat_max
)
{
/* FIXME: hat_max can be 0 and hat_min 1 */
value
=
(
value
-
usage
->
hat_min
)
*
8
/
(
usage
->
hat_max
-
usage
->
hat_min
+
1
)
+
1
;
if
(
value
<
0
||
value
>
8
)
value
=
0
;
input_event
(
input
,
usage
->
type
,
usage
->
code
,
hid_hat_to_axis
[
value
].
x
);
...
...
@@ -484,7 +485,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return
;
}
if
((
usage
->
type
==
EV_KEY
)
&&
(
usage
->
code
==
0
))
/* Key 0 is "unassigned", not KEY_UKNOWN */
if
((
usage
->
type
==
EV_KEY
)
&&
(
usage
->
code
==
0
))
/* Key 0 is "unassigned", not KEY_U
N
KNOWN */
return
;
input_event
(
input
,
usage
->
type
,
usage
->
code
,
value
);
...
...
drivers/usb/input/hiddev.c
View file @
e832882d
...
...
@@ -403,7 +403,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct
hiddev_collection_info
cinfo
;
struct
hiddev_report_info
rinfo
;
struct
hiddev_field_info
finfo
;
struct
hiddev_usage_ref
uref
;
struct
hiddev_usage_ref_multi
uref_multi
;
struct
hiddev_usage_ref
*
uref
=
&
uref_multi
.
uref
;
struct
hiddev_devinfo
dinfo
;
struct
hid_report
*
report
;
struct
hid_field
*
field
;
...
...
@@ -575,68 +576,98 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return
0
;
case
HIDIOCGUCODE
:
if
(
copy_from_user
(
&
uref
,
(
void
*
)
arg
,
sizeof
(
uref
)))
if
(
copy_from_user
(
uref
,
(
void
*
)
arg
,
sizeof
(
*
uref
)))
return
-
EFAULT
;
rinfo
.
report_type
=
uref
.
report_type
;
rinfo
.
report_id
=
uref
.
report_id
;
rinfo
.
report_type
=
uref
->
report_type
;
rinfo
.
report_id
=
uref
->
report_id
;
if
((
report
=
hiddev_lookup_report
(
hid
,
&
rinfo
))
==
NULL
)
return
-
EINVAL
;
if
(
uref
.
field_index
>=
report
->
maxfield
)
if
(
uref
->
field_index
>=
report
->
maxfield
)
return
-
EINVAL
;
field
=
report
->
field
[
uref
.
field_index
];
if
(
uref
.
usage_index
>=
field
->
maxusage
)
field
=
report
->
field
[
uref
->
field_index
];
if
(
uref
->
usage_index
>=
field
->
maxusage
)
return
-
EINVAL
;
uref
.
usage_code
=
field
->
usage
[
uref
.
usage_index
].
hid
;
uref
->
usage_code
=
field
->
usage
[
uref
->
usage_index
].
hid
;
if
(
copy_to_user
((
void
*
)
arg
,
&
uref
,
sizeof
(
uref
)))
if
(
copy_to_user
((
void
*
)
arg
,
uref
,
sizeof
(
*
uref
)))
return
-
EFAULT
;
return
0
;
case
HIDIOCGUSAGE
:
case
HIDIOCSUSAGE
:
case
HIDIOCGUSAGES
:
case
HIDIOCSUSAGES
:
case
HIDIOCGCOLLECTIONINDEX
:
if
(
copy_from_user
(
&
uref
,
(
void
*
)
arg
,
sizeof
(
uref
)))
if
(
cmd
==
HIDIOCGUSAGES
||
cmd
==
HIDIOCSUSAGES
)
{
if
(
copy_from_user
(
&
uref_multi
,
(
void
*
)
arg
,
sizeof
(
uref_multi
)))
return
-
EFAULT
;
}
else
{
if
(
copy_from_user
(
uref
,
(
void
*
)
arg
,
sizeof
(
*
uref
)))
return
-
EFAULT
;
}
if
(
cmd
!=
HIDIOCGUSAGE
&&
uref
.
report_type
==
HID_REPORT_TYPE_INPUT
)
if
(
cmd
!=
HIDIOCGUSAGE
&&
cmd
!=
HIDIOCGUSAGES
&&
uref
->
report_type
==
HID_REPORT_TYPE_INPUT
)
return
-
EINVAL
;
if
(
uref
.
report_id
==
HID_REPORT_ID_UNKNOWN
)
{
field
=
hiddev_lookup_usage
(
hid
,
&
uref
);
if
(
uref
->
report_id
==
HID_REPORT_ID_UNKNOWN
)
{
field
=
hiddev_lookup_usage
(
hid
,
uref
);
if
(
field
==
NULL
)
return
-
EINVAL
;
}
else
{
rinfo
.
report_type
=
uref
.
report_type
;
rinfo
.
report_id
=
uref
.
report_id
;
rinfo
.
report_type
=
uref
->
report_type
;
rinfo
.
report_id
=
uref
->
report_id
;
if
((
report
=
hiddev_lookup_report
(
hid
,
&
rinfo
))
==
NULL
)
return
-
EINVAL
;
if
(
uref
.
field_index
>=
report
->
maxfield
)
if
(
uref
->
field_index
>=
report
->
maxfield
)
return
-
EINVAL
;
field
=
report
->
field
[
uref
->
field_index
];
if
(
uref
->
usage_index
>=
field
->
maxusage
)
return
-
EINVAL
;
field
=
report
->
field
[
uref
.
field_index
];
if
(
uref
.
usage_index
>=
field
->
maxusage
)
if
(
cmd
==
HIDIOCGUSAGES
||
cmd
==
HIDIOCSUSAGES
)
{
if
(
uref_multi
.
num_values
>=
HID_MAX_USAGES
||
uref
->
usage_index
>=
field
->
maxusage
||
(
uref
->
usage_index
+
uref_multi
.
num_values
)
>=
field
->
maxusage
)
return
-
EINVAL
;
}
}
switch
(
cmd
)
{
case
HIDIOCGUSAGE
:
uref
.
value
=
field
->
value
[
uref
.
usage_index
];
if
(
copy_to_user
((
void
*
)
arg
,
&
uref
,
sizeof
(
uref
)))
uref
->
value
=
field
->
value
[
uref
->
usage_index
];
if
(
copy_to_user
((
void
*
)
arg
,
uref
,
sizeof
(
*
uref
)))
return
-
EFAULT
;
return
0
;
case
HIDIOCSUSAGE
:
field
->
value
[
uref
.
usage_index
]
=
uref
.
value
;
field
->
value
[
uref
->
usage_index
]
=
uref
->
value
;
return
0
;
case
HIDIOCGCOLLECTIONINDEX
:
return
field
->
usage
[
uref
.
usage_index
].
collection_index
;
return
field
->
usage
[
uref
->
usage_index
].
collection_index
;
case
HIDIOCGUSAGES
:
for
(
i
=
0
;
i
<
uref_multi
.
num_values
;
i
++
)
uref_multi
.
values
[
i
]
=
field
->
value
[
uref
->
usage_index
+
i
];
if
(
copy_to_user
((
void
*
)
arg
,
&
uref_multi
,
sizeof
(
uref_multi
)))
return
-
EFAULT
;
return
0
;
case
HIDIOCSUSAGES
:
for
(
i
=
0
;
i
<
uref_multi
.
num_values
;
i
++
)
field
->
value
[
uref
->
usage_index
+
i
]
=
uref_multi
.
values
[
i
];
return
0
;
}
return
0
;
...
...
include/linux/hiddev.h
View file @
e832882d
...
...
@@ -39,33 +39,33 @@ struct hiddev_event {
};
struct
hiddev_devinfo
{
unsigned
int
bustype
;
unsigned
int
busnum
;
unsigned
int
devnum
;
unsigned
int
ifnum
;
short
vendor
;
short
product
;
short
version
;
unsigned
num_applications
;
__u32
bustype
;
__u32
busnum
;
__u32
devnum
;
__u32
ifnum
;
__s16
vendor
;
__s16
product
;
__s16
version
;
__u32
num_applications
;
};
struct
hiddev_collection_info
{
unsigned
index
;
unsigned
type
;
unsigned
usage
;
unsigned
level
;
__u32
index
;
__u32
type
;
__u32
usage
;
__u32
level
;
};
#define HID_STRING_SIZE 256
struct
hiddev_string_descriptor
{
int
index
;
__s32
index
;
char
value
[
HID_STRING_SIZE
];
};
struct
hiddev_report_info
{
unsigned
report_type
;
unsigned
report_id
;
unsigned
num_fields
;
__u32
report_type
;
__u32
report_id
;
__u32
num_fields
;
};
/* To do a GUSAGE/SUSAGE, fill in at least usage_code, report_type and
...
...
@@ -88,20 +88,20 @@ struct hiddev_report_info {
#define HID_REPORT_TYPE_MAX 3
struct
hiddev_field_info
{
unsigned
report_type
;
unsigned
report_id
;
unsigned
field_index
;
unsigned
maxusage
;
unsigned
flags
;
unsigned
physical
;
/* physical usage for this field */
unsigned
logical
;
/* logical usage for this field */
unsigned
application
;
/* application usage for this field */
__u32
report_type
;
__u32
report_id
;
__u32
field_index
;
__u32
maxusage
;
__u32
flags
;
__u32
physical
;
/* physical usage for this field */
__u32
logical
;
/* logical usage for this field */
__u32
application
;
/* application usage for this field */
__s32
logical_minimum
;
__s32
logical_maximum
;
__s32
physical_minimum
;
__s32
physical_maximum
;
unsigned
unit_exponent
;
unsigned
unit
;
__u32
unit_exponent
;
__u32
unit
;
};
/* Fill in report_type, report_id and field_index to get the information on a
...
...
@@ -118,14 +118,22 @@ struct hiddev_field_info {
#define HID_FIELD_BUFFERED_BYTE 0x100
struct
hiddev_usage_ref
{
unsigned
report_type
;
unsigned
report_id
;
unsigned
field_index
;
unsigned
usage_index
;
unsigned
usage_code
;
__u32
report_type
;
__u32
report_id
;
__u32
field_index
;
__u32
usage_index
;
__u32
usage_code
;
__s32
value
;
};
/* hiddev_usage_ref_multi is used for sending multiple bytes to a control.
* It really manifests itself as setting the value of consecutive usages */
struct
hiddev_usage_ref_multi
{
struct
hiddev_usage_ref
uref
;
__u32
num_values
;
__s32
values
[
HID_MAX_USAGES
];
};
/* FIELD_INDEX_NONE is returned in read() data from the kernel when flags
* is set to (HIDDEV_FLAG_UREF | HIDDEV_FLAG_REPORT) and a new report has
* been sent by the device
...
...
@@ -161,6 +169,10 @@ struct hiddev_usage_ref {
#define HIDIOCGCOLLECTIONINFO _IOWR('H', 0x11, struct hiddev_collection_info)
#define HIDIOCGPHYS(len) _IOC(_IOC_READ, 'H', 0x12, len)
/* For writing/reading to multiple/consecutive usages */
#define HIDIOCGUSAGES _IOWR('H', 0x13, struct hiddev_usage_ref_multi)
#define HIDIOCSUSAGES _IOW('H', 0x14, struct hiddev_usage_ref_multi)
/*
* Flags to be used in HIDIOCSFLAG
*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment