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
Kirill Smelkov
linux
Commits
be7b8193
Commit
be7b8193
authored
Mar 16, 2004
by
Vojtech Pavlik
Browse files
Options
Browse Files
Download
Plain Diff
Merge suse.cz:/data/bk/linus into suse.cz:/data/bk/input
parents
d3fdc9ac
bf9b7f73
Changes
52
Show whitespace changes
Inline
Side-by-side
Showing
52 changed files
with
2588 additions
and
1300 deletions
+2588
-1300
Documentation/input/joystick-parport.txt
Documentation/input/joystick-parport.txt
+8
-8
Documentation/input/joystick.txt
Documentation/input/joystick.txt
+3
-3
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+39
-20
Documentation/usb/acm.txt
Documentation/usb/acm.txt
+4
-4
arch/arm26/Kconfig
arch/arm26/Kconfig
+0
-5
drivers/char/Kconfig
drivers/char/Kconfig
+0
-24
drivers/char/Makefile
drivers/char/Makefile
+0
-1
drivers/input/evdev.c
drivers/input/evdev.c
+4
-1
drivers/input/gameport/ns558.c
drivers/input/gameport/ns558.c
+25
-11
drivers/input/joystick/amijoy.c
drivers/input/joystick/amijoy.c
+7
-12
drivers/input/joystick/analog.c
drivers/input/joystick/analog.c
+7
-21
drivers/input/joystick/db9.c
drivers/input/joystick/db9.c
+29
-38
drivers/input/joystick/gamecon.c
drivers/input/joystick/gamecon.c
+36
-46
drivers/input/joystick/turbografx.c
drivers/input/joystick/turbografx.c
+29
-39
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Kconfig
+14
-0
drivers/input/keyboard/Makefile
drivers/input/keyboard/Makefile
+1
-0
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+102
-62
drivers/input/keyboard/hpps2atkbd.h
drivers/input/keyboard/hpps2atkbd.h
+91
-83
drivers/input/keyboard/lkkbd.c
drivers/input/keyboard/lkkbd.c
+625
-0
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/98busmouse.c
drivers/input/mouse/98busmouse.c
+2
-0
drivers/input/mouse/Kconfig
drivers/input/mouse/Kconfig
+14
-0
drivers/input/mouse/Makefile
drivers/input/mouse/Makefile
+1
-0
drivers/input/mouse/inport.c
drivers/input/mouse/inport.c
+2
-0
drivers/input/mouse/logibm.c
drivers/input/mouse/logibm.c
+2
-0
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse-base.c
+18
-10
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.c
+41
-12
drivers/input/mouse/synaptics.h
drivers/input/mouse/synaptics.h
+7
-0
drivers/input/mouse/vsxxxaa.c
drivers/input/mouse/vsxxxaa.c
+550
-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/input/serio/i8042-io.h
drivers/input/serio/i8042-io.h
+3
-0
drivers/input/serio/i8042.c
drivers/input/serio/i8042.c
+14
-9
drivers/input/serio/serio.c
drivers/input/serio/serio.c
+3
-0
drivers/usb/input/hid-core.c
drivers/usb/input/hid-core.c
+105
-35
drivers/usb/input/hid-ff.c
drivers/usb/input/hid-ff.c
+1
-1
drivers/usb/input/hid-input.c
drivers/usb/input/hid-input.c
+10
-6
drivers/usb/input/hid.h
drivers/usb/input/hid.h
+11
-10
drivers/usb/input/hiddev.c
drivers/usb/input/hiddev.c
+55
-24
drivers/usb/input/wacom.c
drivers/usb/input/wacom.c
+150
-37
include/asm-arm/arch-ebsa285/irqs.h
include/asm-arm/arch-ebsa285/irqs.h
+2
-2
include/asm-arm/arch-shark/irqs.h
include/asm-arm/arch-shark/irqs.h
+2
-1
include/linux/hiddev.h
include/linux/hiddev.h
+43
-31
include/linux/init.h
include/linux/init.h
+17
-5
include/linux/miscdevice.h
include/linux/miscdevice.h
+0
-1
include/linux/moduleparam.h
include/linux/moduleparam.h
+6
-3
include/linux/serio.h
include/linux/serio.h
+2
-0
init/main.c
init/main.c
+5
-2
No files found.
Documentation/input/joystick-parport.txt
View file @
be7b8193
...
...
@@ -434,7 +434,7 @@ Here are described their command lines:
Using gamecon.c you can connect up to five devices to one parallel port. It
uses the following kernel/module command line:
g
c
=port,pad1,pad2,pad3,pad4,pad5
g
amecon.map
=port,pad1,pad2,pad3,pad4,pad5
Where 'port' the number of the parport interface (eg. 0 for parport0).
...
...
@@ -457,15 +457,15 @@ uses the following kernel/module command line:
your controller plugged in before initializing.
Should you want to use more than one of parallel ports at once, you can use
g
c_2 and gc_3 as additional command line parameters for two more parallel
ports.
g
amecon.map2 and gamecon.map3 as additional command line parameters for two
more parallel
ports.
3.2 db9.c
~~~~~~~~~
Apart from making an interface, there is nothing difficult on using the
db9.c driver. It uses the following kernel/module command line:
db9=port,type
db9
.dev
=port,type
Where 'port' is the number of the parport interface (eg. 0 for parport0).
...
...
@@ -489,14 +489,14 @@ Old parallel ports may not have this feature.
10 | Amiga CD32 pad
Should you want to use more than one of these joysticks/pads at once, you
can use db9
_2 and db9_
3 as additional command line parameters for two
can use db9
.dev2 and db9.dev
3 as additional command line parameters for two
more joysticks/pads.
3.3 turbografx.c
~~~~~~~~~~~~~~~~
The turbografx.c driver uses a very simple kernel/module command line:
t
gfx
=port,js1,js2,js3,js4,js5,js6,js7
t
urbografx.map
=port,js1,js2,js3,js4,js5,js6,js7
Where 'port' is the number of the parport interface (eg. 0 for parport0).
...
...
@@ -504,8 +504,8 @@ more joysticks/pads.
interface ports 1-7 have. For a standard multisystem joystick, this is 1.
Should you want to use more than one of these interfaces at once, you can
use t
gfx_2 and tgfx_3 as additional command line parameters for two more
interfaces.
use t
urbografx.map2 and turbografx.map3 as additional command line parameters
for two more
interfaces.
3.4 PC parallel port pinout
~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
...
Documentation/input/joystick.txt
View file @
be7b8193
...
...
@@ -111,7 +111,7 @@ your needs:
alias tty-ldisc-2 serport
alias char-major-13 input
above input joydev ns558 analog
options analog
js=gamepad
options analog
map=gamepad,none,2btn
2.5 Verifying that it works
~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
...
@@ -185,7 +185,7 @@ you'll need to specify the types either on the kernel command line or on the
module command line, when inserting analog.o into the kernel. The
parameters are:
js=type,type,type
,....
analog.map=<type1>,<type2>,<type3>
,....
'type' is type of the joystick from the table below, defining joysticks
present on gameports in the system, starting with gameport0, second 'type'
...
...
@@ -419,7 +419,7 @@ card.
Amiga joysticks, connected to an Amiga, are supported by the amijoy.c
driver. Since they can't be autodetected, the driver has a command line.
amijoy
=a,b
amijoy
.map=<a>,<b>
a and b define the joysticks connected to the JOY0DAT and JOY1DAT ports of
the Amiga.
...
...
Documentation/kernel-parameters.txt
View file @
be7b8193
...
...
@@ -158,7 +158,15 @@ running once the system is up.
Format: <host-scsi-id>,<target-scsi-id>,<max-rate>,<max-offset>
See also header of drivers/scsi/AM53C974.c.
amijoy= [HW,JOY] Amiga joystick support
amijoy.map= [HW,JOY] Amiga joystick support
Map of devices attached to JOY0DAT and JOY1DAT
Format: <a>,<b>
See also Documentation/kernel/input/joystick.txt
analog.map= [HW,JOY] Analog joystick and gamepad support
Specifies type or capabilities of an analog joystick
connected to one of 16 gameports
Format: <type1>,<type2>,..<type16>
apc= [HW,SPARC] Power management functions (SPARCstation-4/5 + deriv.)
Format: noidle
...
...
@@ -181,11 +189,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]
...
...
@@ -287,9 +302,10 @@ running once the system is up.
dasd= [HW,NET]
See header of drivers/s390/block/dasd_devmap.c.
db9= [HW,JOY]
db9_2=
db9_3=
db9.dev[2|3]= [HW,JOY] Multisystem joystick support via parallel port
(one device per port)
Format: <port#>,<type>
See also Documentation/input/joystick-parport.txt
debug [KNL] Enable kernel debugging (events log level).
...
...
@@ -384,11 +400,13 @@ running once the system is up.
ftape= [HW] Floppy Tape subsystem debugging options.
See Documentation/ftape.txt.
gamma= [HW,DRM]
gamecon.map[2|3]=
[HW,JOY] Multisystem joystick and NES/SNES/PSX pad
support via parallel port (up to 5 devices per port)
Format: <port#>,<pad1>,<pad2>,<pad3>,<pad4>,<pad5>
See also Documentation/input/joystick-parport.txt
gc= [HW,JOY]
gc_2= See Documentation/input/joystick-parport.txt.
gc_3=
gamma= [HW,DRM]
gdth= [HW,SCSI]
See header of drivers/scsi/gdth.c.
...
...
@@ -616,9 +634,9 @@ running once the system is up.
mga= [HW,DRM]
mousedev.xres [MOUSE] Horizontal screen resolution, used for devices
mousedev.xres
=
[MOUSE] Horizontal screen resolution, used for devices
reporting absolute coordinates, such as tablets
mousedev.yres [MOUSE] Vertical screen resolution, used for devices
mousedev.yres
=
[MOUSE] Vertical screen resolution, used for devices
reporting absolute coordinates, such as tablets
mpu401= [HW,OSS]
...
...
@@ -1164,10 +1182,6 @@ running once the system is up.
tdfx= [HW,DRM]
tgfx= [HW,JOY] TurboGraFX parallel port interface
tgfx_2= See Documentation/input/joystick-parport.txt.
tgfx_3=
thash_entries= [KNL,NET]
Set number of hash buckets for TCP connection
...
...
@@ -1189,8 +1203,13 @@ running once the system is up.
trix= [HW,OSS] MediaTrix AudioTrix Pro
Format: <io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
tsdev.xres [TS] Horizontal screen resolution.
tsdev.yres [TS] Vertical screen resolution.
tsdev.xres= [TS] Horizontal screen resolution.
tsdev.yres= [TS] Vertical screen resolution.
turbografx.map[2|3]=
[HW,JOY] TurboGraFX parallel port interface
Format: <port#>,<js1>,<js2>,<js3>,<js4>,<js5>,<js6>,<js7>
See also Documentation/input/joystick-parport.txt
u14-34f= [HW,SCSI] UltraStor 14F/34F SCSI host adapter
See header of drivers/scsi/u14-34f.c.
...
...
Documentation/usb/acm.txt
View file @
be7b8193
...
...
@@ -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.
...
...
arch/arm26/Kconfig
View file @
be7b8193
...
...
@@ -198,11 +198,6 @@ source "drivers/input/Kconfig"
source "drivers/char/Kconfig"
config KBDMOUSE
bool
depends on ARCH_ACORN && BUSMOUSE=y
default y
source "drivers/media/Kconfig"
source "fs/Kconfig"
...
...
drivers/char/Kconfig
View file @
be7b8193
...
...
@@ -599,30 +599,6 @@ config PC9800_OLDLP_CONSOLE
bool "Support for console on line printer"
depends on PC9800_OLDLP
menu "Mice"
config BUSMOUSE
tristate "Bus Mouse Support"
---help---
Say Y here if your machine has a bus mouse as opposed to a serial
mouse. Most people have a regular serial MouseSystem or
Microsoft mouse (made by Logitech) that plugs into a COM port
(rectangular with 9 or 25 pins). These people say N here.
If you have a laptop, you either have to check the documentation or
experiment a bit to find out whether the trackball is a serial mouse
or not; it's best to say Y here for you.
This is the generic bus mouse driver code. If you have a bus mouse,
you will have to say Y here and also to the specific driver for your
mouse below.
To compile this driver as a module, choose M here: the
module will be called busmouse.
endmenu
config QIC02_TAPE
tristate "QIC-02 tape support"
help
...
...
drivers/char/Makefile
View file @
be7b8193
...
...
@@ -49,7 +49,6 @@ obj-$(CONFIG_PRINTER) += lp.o
obj-$(CONFIG_TIPAR)
+=
tipar.o
obj-$(CONFIG_PC9800_OLDLP)
+=
lp_old98.o
obj-$(CONFIG_BUSMOUSE)
+=
busmouse.o
obj-$(CONFIG_DTLK)
+=
dtlk.o
obj-$(CONFIG_R3964)
+=
n_r3964.o
obj-$(CONFIG_APPLICOM)
+=
applicom.o
...
...
drivers/input/evdev.c
View file @
be7b8193
...
...
@@ -209,7 +209,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct
evdev
*
evdev
=
list
->
evdev
;
struct
input_dev
*
dev
=
evdev
->
handle
.
dev
;
struct
input_absinfo
abs
;
int
t
,
u
,
v
;
int
i
,
t
,
u
,
v
;
if
(
!
evdev
->
exist
)
return
-
ENODEV
;
...
...
@@ -234,6 +234,9 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
u
=
SET_INPUT_KEYCODE
(
dev
,
t
,
v
);
clear_bit
(
u
,
dev
->
keybit
);
set_bit
(
v
,
dev
->
keybit
);
for
(
i
=
0
;
i
<
dev
->
keycodemax
;
i
++
)
if
(
INPUT_KEYCODE
(
dev
,
i
)
==
u
)
set_bit
(
u
,
dev
->
keybit
);
return
0
;
case
EVIOCSFF
:
...
...
drivers/input/gameport/ns558.c
View file @
be7b8193
...
...
@@ -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
...
...
@@ -276,6 +289,7 @@ void __exit ns558_exit(void)
#endif
case
NS558_ISA
:
release_region
(
port
->
gameport
.
io
&
~
(
port
->
size
-
1
),
port
->
size
);
kfree
(
port
);
break
;
default:
...
...
drivers/input/joystick/amijoy.c
View file @
be7b8193
...
...
@@ -32,6 +32,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
...
...
@@ -42,10 +43,15 @@
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"Driver for Amiga joysticks"
);
MODULE_PARM
(
amijoy
,
"1-2i"
);
MODULE_LICENSE
(
"GPL"
);
static
int
amijoy
[
2
]
=
{
0
,
1
};
static
int
amijoy_nargs
;
module_param_array_named
(
map
,
amijoy
,
uint
,
amijoy_nargs
,
0
);
MODULE_PARM_DESC
(
map
,
"Map of attached joysticks in form of <a>,<b> (default is 0,1)"
);
__obsolete_setup
(
"amijoy="
);
static
int
amijoy_used
[
2
]
=
{
0
,
0
};
static
struct
input_dev
amijoy_dev
[
2
];
static
char
*
amijoy_phys
[
2
]
=
{
"amijoy/input0"
,
"amijoy/input1"
};
...
...
@@ -101,17 +107,6 @@ static void amijoy_close(struct input_dev *dev)
free_irq
(
IRQ_AMIGA_VERTB
,
amijoy_interrupt
);
}
static
int
__init
amijoy_setup
(
char
*
str
)
{
int
i
;
int
ints
[
4
];
str
=
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
for
(
i
=
0
;
i
<=
ints
[
0
]
&&
i
<
2
;
i
++
)
amijoy
[
i
]
=
ints
[
i
+
1
];
return
1
;
}
__setup
(
"amijoy="
,
amijoy_setup
);
static
int
__init
amijoy_init
(
void
)
{
int
i
,
j
;
...
...
drivers/input/joystick/analog.c
View file @
be7b8193
...
...
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/init.h>
...
...
@@ -50,9 +51,12 @@ MODULE_LICENSE("GPL");
#define ANALOG_PORTS 16
static
char
*
js
[
ANALOG_PORTS
];
static
int
js_nargs
;
static
int
analog_options
[
ANALOG_PORTS
];
MODULE_PARM
(
js
,
"1-"
__MODULE_STRING
(
ANALOG_PORTS
)
"s"
);
MODULE_PARM_DESC
(
js
,
"Analog joystick options"
);
module_param_array_named
(
map
,
js
,
charp
,
js_nargs
,
0
);
MODULE_PARM_DESC
(
map
,
"Describes analog joysticks type/capabilities"
);
__obsolete_setup
(
"js="
);
/*
* Times, feature definitions.
...
...
@@ -711,7 +715,7 @@ static void analog_parse_options(void)
int
i
,
j
;
char
*
end
;
for
(
i
=
0
;
i
<
ANALOG_PORTS
&&
js
[
i
]
;
i
++
)
{
for
(
i
=
0
;
i
<
js_nargs
;
i
++
)
{
for
(
j
=
0
;
analog_types
[
j
].
name
;
j
++
)
if
(
!
strcmp
(
analog_types
[
j
].
name
,
js
[
i
]))
{
...
...
@@ -742,24 +746,6 @@ static struct gameport_dev analog_dev = {
.
disconnect
=
analog_disconnect
,
};
#ifndef MODULE
static
int
__init
analog_setup
(
char
*
str
)
{
char
*
s
=
str
;
int
i
=
0
;
if
(
!
str
||
!*
str
)
return
0
;
while
((
str
=
s
)
&&
(
i
<
ANALOG_PORTS
))
{
if
((
s
=
strchr
(
str
,
','
)))
*
s
++
=
0
;
js
[
i
++
]
=
str
;
}
return
1
;
}
__setup
(
"js="
,
analog_setup
);
#endif
int
__init
analog_init
(
void
)
{
analog_parse_options
();
...
...
drivers/input/joystick/db9.c
View file @
be7b8193
...
...
@@ -33,6 +33,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/parport.h>
...
...
@@ -42,9 +43,24 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION
(
"Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
db9
,
"2i"
);
MODULE_PARM
(
db9_2
,
"2i"
);
MODULE_PARM
(
db9_3
,
"2i"
);
static
int
db9
[]
__initdata
=
{
-
1
,
0
};
static
int
db9_nargs
__initdata
=
0
;
module_param_array_named
(
dev
,
db9
,
int
,
db9_nargs
,
0
);
MODULE_PARM_DESC
(
dev
,
"Describes first attached device (<parport#>,<type>)"
);
static
int
db9_2
[]
__initdata
=
{
-
1
,
0
};
static
int
db9_nargs_2
__initdata
=
0
;
module_param_array_named
(
dev2
,
db9_2
,
int
,
db9_nargs_2
,
0
);
MODULE_PARM_DESC
(
dev2
,
"Describes second attached device (<parport#>,<type>)"
);
static
int
db9_3
[]
__initdata
=
{
-
1
,
0
};
static
int
db9_nargs_3
__initdata
=
0
;
module_param_array_named
(
dev3
,
db9_3
,
int
,
db9_nargs_3
,
0
);
MODULE_PARM_DESC
(
dev3
,
"Describes third attached device (<parport#>,<type>)"
);
__obsolete_setup
(
"db9="
);
__obsolete_setup
(
"db9_2="
);
__obsolete_setup
(
"db9_3="
);
#define DB9_MULTI_STICK 0x01
#define DB9_MULTI2_STICK 0x02
...
...
@@ -76,10 +92,6 @@ MODULE_PARM(db9_3, "2i");
#define DB9_GENESIS6_DELAY 14
#define DB9_REFRESH_TIME HZ/100
static
int
db9
[]
__initdata
=
{
-
1
,
0
};
static
int
db9_2
[]
__initdata
=
{
-
1
,
0
};
static
int
db9_3
[]
__initdata
=
{
-
1
,
0
};
struct
db9
{
struct
input_dev
dev
[
DB9_MAX_DEVICES
];
struct
timer_list
timer
;
...
...
@@ -518,7 +530,7 @@ static void db9_close(struct input_dev *dev)
}
}
static
struct
db9
__init
*
db9_probe
(
int
*
config
)
static
struct
db9
__init
*
db9_probe
(
int
*
config
,
int
nargs
)
{
struct
db9
*
db9
;
struct
parport
*
pp
;
...
...
@@ -526,6 +538,12 @@ static struct db9 __init *db9_probe(int *config)
if
(
config
[
0
]
<
0
)
return
NULL
;
if
(
nargs
<
2
)
{
printk
(
KERN_ERR
"db9.c: Device type must be specified.
\n
"
);
return
NULL
;
}
if
(
config
[
1
]
<
1
||
config
[
1
]
>=
DB9_MAX_PAD
||
!
db9_buttons
[
config
[
1
]])
{
printk
(
KERN_ERR
"db9.c: bad config
\n
"
);
return
NULL
;
...
...
@@ -601,38 +619,11 @@ static struct db9 __init *db9_probe(int *config)
return
db9
;
}
#ifndef MODULE
static
int
__init
db9_setup
(
char
*
str
)
{
int
i
,
ints
[
3
];
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
for
(
i
=
0
;
i
<=
ints
[
0
]
&&
i
<
2
;
i
++
)
db9
[
i
]
=
ints
[
i
+
1
];
return
1
;
}
static
int
__init
db9_setup_2
(
char
*
str
)
{
int
i
,
ints
[
3
];
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
for
(
i
=
0
;
i
<=
ints
[
0
]
&&
i
<
2
;
i
++
)
db9_2
[
i
]
=
ints
[
i
+
1
];
return
1
;
}
static
int
__init
db9_setup_3
(
char
*
str
)
{
int
i
,
ints
[
3
];
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
for
(
i
=
0
;
i
<=
ints
[
0
]
&&
i
<
2
;
i
++
)
db9_3
[
i
]
=
ints
[
i
+
1
];
return
1
;
}
__setup
(
"db9="
,
db9_setup
);
__setup
(
"db9_2="
,
db9_setup_2
);
__setup
(
"db9_3="
,
db9_setup_3
);
#endif
int
__init
db9_init
(
void
)
{
db9_base
[
0
]
=
db9_probe
(
db9
);
db9_base
[
1
]
=
db9_probe
(
db9_2
);
db9_base
[
2
]
=
db9_probe
(
db9_3
);
db9_base
[
0
]
=
db9_probe
(
db9
,
db9_nargs
);
db9_base
[
1
]
=
db9_probe
(
db9_2
,
db9_nargs_2
);
db9_base
[
2
]
=
db9_probe
(
db9_3
,
db9_nargs_3
);
if
(
db9_base
[
0
]
||
db9_base
[
1
]
||
db9_base
[
2
])
return
0
;
...
...
drivers/input/joystick/gamecon.c
View file @
be7b8193
...
...
@@ -35,6 +35,7 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/parport.h>
#include <linux/input.h>
...
...
@@ -43,10 +44,26 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION
(
"NES, SNES, N64, MultiSystem, PSX gamepad driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
gc
,
"2-6i"
);
MODULE_PARM
(
gc_2
,
"2-6i"
);
MODULE_PARM
(
gc_3
,
"2-6i"
);
MODULE_PARM
(
gc_psx_delay
,
"i"
);
static
int
gc
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
};
static
int
gc_nargs
__initdata
=
0
;
module_param_array_named
(
map
,
gc
,
int
,
gc_nargs
,
0
);
MODULE_PARM_DESC
(
map
,
"Describers first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)"
);
static
int
gc_2
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
};
static
int
gc_nargs_2
__initdata
=
0
;
module_param_array_named
(
map2
,
gc_2
,
int
,
gc_nargs_2
,
0
);
MODULE_PARM_DESC
(
map2
,
"Describers second set of devices"
);
static
int
gc_3
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
};
static
int
gc_nargs_3
__initdata
=
0
;
module_param_array_named
(
map3
,
gc_3
,
int
,
gc_nargs_3
,
0
);
MODULE_PARM_DESC
(
map3
,
"Describers third set of devices"
);
__obsolete_setup
(
"gc="
);
__obsolete_setup
(
"gc_2="
);
__obsolete_setup
(
"gc_3="
);
/* see also gs_psx_delay parameter in PSX support section */
#define GC_SNES 1
#define GC_NES 2
...
...
@@ -71,10 +88,6 @@ struct gc {
static
struct
gc
*
gc_base
[
3
];
static
int
gc
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
};
static
int
gc_2
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
};
static
int
gc_3
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
};
static
int
gc_status_bit
[]
=
{
0x40
,
0x80
,
0x20
,
0x10
,
0x08
};
static
char
*
gc_names
[]
=
{
NULL
,
"SNES pad"
,
"NES pad"
,
"NES FourPort"
,
"Multisystem joystick"
,
...
...
@@ -232,6 +245,11 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
#define GC_PSX_LEN(x) ((x) & 0xf)
/* Low nibble is length in words */
static
int
gc_psx_delay
=
GC_PSX_DELAY
;
module_param_named
(
psx_delay
,
gc_psx_delay
,
uint
,
0
);
MODULE_PARM_DESC
(
psx_delay
,
"Delay when accessing Sony PSX controller (usecs)"
);
__obsolete_setup
(
"gc_psx_delay="
);
static
short
gc_psx_abs
[]
=
{
ABS_X
,
ABS_Y
,
ABS_RX
,
ABS_RY
,
ABS_HAT0X
,
ABS_HAT0Y
};
static
short
gc_psx_btn
[]
=
{
BTN_TL
,
BTN_TR
,
BTN_TL2
,
BTN_TR2
,
BTN_A
,
BTN_B
,
BTN_X
,
BTN_Y
,
BTN_START
,
BTN_SELECT
,
BTN_THUMBL
,
BTN_THUMBR
};
...
...
@@ -468,7 +486,7 @@ static void gc_close(struct input_dev *dev)
}
}
static
struct
gc
__init
*
gc_probe
(
int
*
config
)
static
struct
gc
__init
*
gc_probe
(
int
*
config
,
int
nargs
)
{
struct
gc
*
gc
;
struct
parport
*
pp
;
...
...
@@ -478,6 +496,11 @@ static struct gc __init *gc_probe(int *config)
if
(
config
[
0
]
<
0
)
return
NULL
;
if
(
nargs
<
2
)
{
printk
(
KERN_ERR
"gamecon.c: at least one device must be specified
\n
"
);
return
NULL
;
}
pp
=
parport_find_number
(
config
[
0
]);
if
(
!
pp
)
{
...
...
@@ -507,7 +530,7 @@ static struct gc __init *gc_probe(int *config)
gc
->
timer
.
data
=
(
long
)
gc
;
gc
->
timer
.
function
=
gc_timer
;
for
(
i
=
0
;
i
<
5
;
i
++
)
{
for
(
i
=
0
;
i
<
nargs
-
1
;
i
++
)
{
if
(
!
config
[
i
+
1
])
continue
;
...
...
@@ -632,44 +655,11 @@ static struct gc __init *gc_probe(int *config)
return
gc
;
}
#ifndef MODULE
static
int
__init
gc_setup
(
char
*
str
)
{
int
i
,
ints
[
7
];
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
for
(
i
=
0
;
i
<=
ints
[
0
]
&&
i
<
6
;
i
++
)
gc
[
i
]
=
ints
[
i
+
1
];
return
1
;
}
static
int
__init
gc_setup_2
(
char
*
str
)
{
int
i
,
ints
[
7
];
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
for
(
i
=
0
;
i
<=
ints
[
0
]
&&
i
<
6
;
i
++
)
gc_2
[
i
]
=
ints
[
i
+
1
];
return
1
;
}
static
int
__init
gc_setup_3
(
char
*
str
)
{
int
i
,
ints
[
7
];
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
for
(
i
=
0
;
i
<=
ints
[
0
]
&&
i
<
6
;
i
++
)
gc_3
[
i
]
=
ints
[
i
+
1
];
return
1
;
}
static
int
__init
gc_psx_setup
(
char
*
str
)
{
get_option
(
&
str
,
&
gc_psx_delay
);
return
1
;
}
__setup
(
"gc="
,
gc_setup
);
__setup
(
"gc_2="
,
gc_setup_2
);
__setup
(
"gc_3="
,
gc_setup_3
);
__setup
(
"gc_psx_delay="
,
gc_psx_setup
);
#endif
int
__init
gc_init
(
void
)
{
gc_base
[
0
]
=
gc_probe
(
gc
);
gc_base
[
1
]
=
gc_probe
(
gc_2
);
gc_base
[
2
]
=
gc_probe
(
gc_3
);
gc_base
[
0
]
=
gc_probe
(
gc
,
gc_nargs
);
gc_base
[
1
]
=
gc_probe
(
gc_2
,
gc_nargs_2
);
gc_base
[
2
]
=
gc_probe
(
gc_3
,
gc_nargs_3
);
if
(
gc_base
[
0
]
||
gc_base
[
1
]
||
gc_base
[
2
])
return
0
;
...
...
drivers/input/joystick/turbografx.c
View file @
be7b8193
...
...
@@ -35,15 +35,31 @@
#include <linux/parport.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"TurboGraFX parallel port interface driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
tgfx
,
"2-8i"
);
MODULE_PARM
(
tgfx_2
,
"2-8i"
);
MODULE_PARM
(
tgfx_3
,
"2-8i"
);
static
int
tgfx
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
int
tgfx_nargs
__initdata
=
0
;
module_param_array_named
(
map
,
tgfx
,
int
,
tgfx_nargs
,
0
);
MODULE_PARM_DESC
(
map
,
"Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>"
);
static
int
tgfx_2
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
int
tgfx_nargs_2
__initdata
=
0
;
module_param_array_named
(
map2
,
tgfx_2
,
int
,
tgfx_nargs_2
,
0
);
MODULE_PARM_DESC
(
map2
,
"Describes second set of devices"
);
static
int
tgfx_3
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
int
tgfx_nargs_3
__initdata
=
0
;
module_param_array_named
(
map3
,
tgfx_3
,
int
,
tgfx_nargs_3
,
0
);
MODULE_PARM_DESC
(
map3
,
"Describes third set of devices"
);
__obsolete_setup
(
"tgfx="
);
__obsolete_setup
(
"tgfx_2="
);
__obsolete_setup
(
"tgfx_3="
);
#define TGFX_REFRESH_TIME HZ/100
/* 10 ms */
...
...
@@ -58,10 +74,6 @@ MODULE_PARM(tgfx_3, "2-8i");
#define TGFX_TOP 0x01
#define TGFX_TOP2 0x08
static
int
tgfx
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
int
tgfx_2
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
int
tgfx_3
[]
__initdata
=
{
-
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
int
tgfx_buttons
[]
=
{
BTN_TRIGGER
,
BTN_THUMB
,
BTN_THUMB2
,
BTN_TOP
,
BTN_TOP2
};
static
char
*
tgfx_name
=
"TurboGraFX Multisystem joystick"
;
...
...
@@ -133,7 +145,7 @@ static void tgfx_close(struct input_dev *dev)
* tgfx_probe() probes for tg gamepads.
*/
static
struct
tgfx
__init
*
tgfx_probe
(
int
*
config
)
static
struct
tgfx
__init
*
tgfx_probe
(
int
*
config
,
int
nargs
)
{
struct
tgfx
*
tgfx
;
struct
parport
*
pp
;
...
...
@@ -142,6 +154,11 @@ static struct tgfx __init *tgfx_probe(int *config)
if
(
config
[
0
]
<
0
)
return
NULL
;
if
(
nargs
<
2
)
{
printk
(
KERN_ERR
"turbografx.c: at least one joystick must be specified
\n
"
);
return
NULL
;
}
pp
=
parport_find_number
(
config
[
0
]);
if
(
!
pp
)
{
...
...
@@ -171,7 +188,7 @@ static struct tgfx __init *tgfx_probe(int *config)
tgfx
->
sticks
=
0
;
for
(
i
=
0
;
i
<
7
;
i
++
)
for
(
i
=
0
;
i
<
nargs
-
1
;
i
++
)
if
(
config
[
i
+
1
]
>
0
&&
config
[
i
+
1
]
<
6
)
{
tgfx
->
sticks
|=
(
1
<<
i
);
...
...
@@ -212,38 +229,11 @@ static struct tgfx __init *tgfx_probe(int *config)
return
tgfx
;
}
#ifndef MODULE
static
int
__init
tgfx_setup
(
char
*
str
)
{
int
i
,
ints
[
9
];
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
for
(
i
=
0
;
i
<=
ints
[
0
]
&&
i
<
8
;
i
++
)
tgfx
[
i
]
=
ints
[
i
+
1
];
return
1
;
}
static
int
__init
tgfx_setup_2
(
char
*
str
)
{
int
i
,
ints
[
9
];
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
for
(
i
=
0
;
i
<=
ints
[
0
]
&&
i
<
8
;
i
++
)
tgfx_2
[
i
]
=
ints
[
i
+
1
];
return
1
;
}
static
int
__init
tgfx_setup_3
(
char
*
str
)
{
int
i
,
ints
[
9
];
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
for
(
i
=
0
;
i
<=
ints
[
0
]
&&
i
<
8
;
i
++
)
tgfx_3
[
i
]
=
ints
[
i
+
1
];
return
1
;
}
__setup
(
"tgfx="
,
tgfx_setup
);
__setup
(
"tgfx_2="
,
tgfx_setup_2
);
__setup
(
"tgfx_3="
,
tgfx_setup_3
);
#endif
int
__init
tgfx_init
(
void
)
{
tgfx_base
[
0
]
=
tgfx_probe
(
tgfx
);
tgfx_base
[
1
]
=
tgfx_probe
(
tgfx_2
);
tgfx_base
[
2
]
=
tgfx_probe
(
tgfx_3
);
tgfx_base
[
0
]
=
tgfx_probe
(
tgfx
,
tgfx_nargs
);
tgfx_base
[
1
]
=
tgfx_probe
(
tgfx_2
,
tgfx_nargs_2
);
tgfx_base
[
2
]
=
tgfx_probe
(
tgfx_3
,
tgfx_nargs_3
);
if
(
tgfx_base
[
0
]
||
tgfx_base
[
1
]
||
tgfx_base
[
2
])
return
0
;
...
...
drivers/input/keyboard/Kconfig
View file @
be7b8193
...
...
@@ -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
...
...
@@ -40,6 +41,19 @@ config KEYBOARD_SUNKBD
To compile this driver as a module, choose M here: the
module will be called sunkbd.
config KEYBOARD_LKKBD
tristate "DECstation/VAXstation LK201/LK401 keyboard support"
depends on INPUT && INPUT_KEYBOARD
select SERIO
help
Say Y here if you want to use a LK201 or LK401 style serial
keyboard. This keyboard is also useable on PCs if you attach
it with the inputattach program. The connector pinout is
described within lkkbd.c.
To compile this driver as a module, choose M here: the
module will be called lkkbd.
config KEYBOARD_XTKBD
tristate "XT Keyboard support"
depends on INPUT && INPUT_KEYBOARD
...
...
drivers/input/keyboard/Makefile
View file @
be7b8193
...
...
@@ -7,6 +7,7 @@
obj-$(CONFIG_KEYBOARD_ATKBD)
+=
atkbd.o
obj-$(CONFIG_KEYBOARD_MAPLE)
+=
maple_keyb.o
obj-$(CONFIG_KEYBOARD_SUNKBD)
+=
sunkbd.o
obj-$(CONFIG_KEYBOARD_LKKBD)
+=
lkkbd.o
obj-$(CONFIG_KEYBOARD_XTKBD)
+=
xtkbd.o
obj-$(CONFIG_KEYBOARD_AMIGA)
+=
amikbd.o
obj-$(CONFIG_KEYBOARD_NEWTON)
+=
newtonkbd.o
...
...
drivers/input/keyboard/atkbd.c
View file @
be7b8193
...
...
@@ -30,21 +30,17 @@
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@suse.cz>"
);
MODULE_DESCRIPTION
(
"AT and PS/2 keyboard driver"
);
MODULE_PARM
(
atkbd_set
,
"1i"
);
MODULE_PARM
(
atkbd_reset
,
"1i"
);
MODULE_PARM
(
atkbd_softrepeat
,
"1i"
);
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 +48,18 @@ 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"
);
__obsolete_setup
(
"atkbd_set="
);
__obsolete_setup
(
"atkbd_reset"
);
__obsolete_setup
(
"atkbd_softrepeat="
);
/*
* Scancode to keycode tables. These are just the default setting, and
* are loadable via an userland utility.
...
...
@@ -127,11 +135,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 +149,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 +179,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 +214,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 +310,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 +346,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 +468,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 +577,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 +745,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 +781,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 +798,7 @@ static int atkbd_reconnect(struct serio *serio)
{
struct
atkbd
*
atkbd
=
serio
->
private
;
struct
serio_dev
*
dev
=
serio
->
dev
;
int
i
;
unsigned
char
param
[
1
]
;
if
(
!
dev
)
{
printk
(
KERN_DEBUG
"atkbd: reconnect request, but serio is disconnected, ignoring...
\n
"
);
...
...
@@ -749,38 +806,21 @@ static int atkbd_reconnect(struct serio *serio)
}
if
(
atkbd
->
write
)
{
param
[
0
]
=
(
test_bit
(
LED_SCROLLL
,
atkbd
->
dev
.
led
)
?
1
:
0
)
|
(
test_bit
(
LED_NUML
,
atkbd
->
dev
.
led
)
?
2
:
0
)
|
(
test_bit
(
LED_CAPSL
,
atkbd
->
dev
.
led
)
?
4
:
0
);
if
(
atkbd_probe
(
atkbd
))
return
-
1
;
if
(
atkbd
->
set
!=
atkbd_set_3
(
atkbd
))
return
-
1
;
atkbd
->
set
=
atkbd_set_3
(
atkbd
);
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
));
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETLEDS
))
return
-
1
;
}
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 @
be7b8193
...
...
@@ -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/lkkbd.c
0 → 100644
View file @
be7b8193
/*
* Copyright (C) 2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
*/
/*
* LK keyboard driver for Linux, based on sunkbd.c (C) by Vojtech Pavlik
*/
/*
* DEC LK201 and LK401 keyboard driver for Linux (primary for DECstations
* and VAXstations, but can also be used on any standard RS232 with an
* adaptor).
*
* DISCLAUNER: This works for _me_. If you break anything by using the
* information given below, I will _not_ be lieable!
*
* RJ11 pinout: To DB9: Or DB25:
* 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD)
* 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND)
* 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD)
* 3 - +12V (from HDD drive connector), DON'T connect to DB9 or DB25!!!
*
* Pin numbers for DB9 and DB25 are noted on the plug (quite small:). For
* RJ11, it's like this:
*
* __=__ Hold the plug in front of you, cable downwards,
* /___/| nose is hidden behind the plug. Now, pin 1 is at
* |1234|| the left side, pin 4 at the right and 2 and 3 are
* |IIII|| in between, of course:)
* | ||
* |____|/
* || So the adaptor consists of three connected cables
* || for data transmission (RxD and TxD) and signal ground.
* Additionally, you have to get +12V from somewhere.
* Most easily, you'll get that from a floppy or HDD power connector.
* It's the yellow cable there (black is ground and red is +5V).
*/
/*
* 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
* email or by paper mail:
* Jan-Benedict Glaw, Lilienstrae 16, 33790 Hrste (near Halle/Westf.),
* Germany.
*/
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/workqueue.h>
MODULE_AUTHOR
(
"Jan-Benedict Glaw <jblaw@lug-owl.de>"
);
MODULE_DESCRIPTION
(
"LK keyboard driver"
);
MODULE_LICENSE
(
"GPL"
);
/*
* Known parameters:
* bell_volume
* keyclick_volume
* ctrlclick_volume
*
* Please notice that there's not yet an API to set these at runtime.
*/
static
int
bell_volume
=
100
;
/* % */
module_param
(
bell_volume
,
int
,
0
);
MODULE_PARM_DESC
(
bell_volume
,
"Bell volume (in %). default is 100%"
);
static
int
keyclick_volume
=
100
;
/* % */
module_param
(
keyclick_volume
,
int
,
0
);
MODULE_PARM_DESC
(
keyclick_volume
,
"Keyclick volume (in %), default is 100%"
);
static
int
ctrlclick_volume
=
100
;
/* % */
module_param
(
ctrlclick_volume
,
int
,
0
);
MODULE_PARM_DESC
(
ctrlclick_volume
,
"Ctrlclick volume (in %), default is 100%"
);
#undef LKKBD_DEBUG
#ifdef LKKBD_DEBUG
#define DBG(x...) printk (x)
#else
#define DBG(x...) do {} while (0)
#endif
/* LED control */
#define LK_LED_WAIT 0x81
#define LK_LED_COMPOSE 0x82
#define LK_LED_SHIFTLOCK 0x84
#define LK_LED_SCROLLLOCK 0x88
#define LK_CMD_LED_ON 0x13
#define LK_CMD_LED_OFF 0x11
/* Mode control */
#define LK_MODE_DOWN 0x80
#define LK_MODE_AUTODOWN 0x82
#define LK_MODE_UPDOWN 0x86
#define LK_CMD_SET_MODE(mode,div) ((mode) | ((div) << 3))
/* Misc commands */
#define LK_CMD_ENABLE_KEYCLICK 0x1b
#define LK_CMD_DISABLE_KEYCLICK 0x99
#define LK_CMD_DISABLE_BELL 0xa1
#define LK_CMD_SOUND_BELL 0xa7
#define LK_CMD_ENABLE_BELL 0x23
#define LK_CMD_DISABLE_CTRCLICK 0xb9
#define LK_CMD_ENABLE_CTRCLICK 0xbb
#define LK_CMD_SET_DEFAULTS 0xd3
#define LK_CMD_POWERCYCLE_RESET 0xfd
#define LK_CMD_ENABLE_LK401 0xe9
/* Misc responses from keyboard */
#define LK_ALL_KEYS_UP 0xb3
#define LK_METRONOME 0xb4
#define LK_OUTPUT_ERROR 0xb5
#define LK_INPUT_ERROR 0xb6
#define LK_KBD_LOCKED 0xb7
#define LK_KBD_TEST_MODE_ACK 0xb8
#define LK_PREFIX_KEY_DOWN 0xb9
#define LK_MODE_CHANGE_ACK 0xba
#define LK_RESPONSE_RESERVED 0xbb
#define LK_NUM_KEYCODES 256
typedef
u_int16_t
lk_keycode_t
;
static
lk_keycode_t
lkkbd_keycode
[
LK_NUM_KEYCODES
]
=
{
[
0x56
]
=
KEY_F1
,
[
0x57
]
=
KEY_F2
,
[
0x58
]
=
KEY_F3
,
[
0x59
]
=
KEY_F4
,
[
0x5a
]
=
KEY_F5
,
[
0x64
]
=
KEY_F6
,
[
0x65
]
=
KEY_F7
,
[
0x66
]
=
KEY_F8
,
[
0x67
]
=
KEY_F9
,
[
0x68
]
=
KEY_F10
,
[
0x71
]
=
KEY_F11
,
[
0x72
]
=
KEY_F12
,
[
0x73
]
=
KEY_F13
,
[
0x74
]
=
KEY_F14
,
[
0x7c
]
=
KEY_F15
,
[
0x7d
]
=
KEY_F16
,
[
0x80
]
=
KEY_F17
,
[
0x81
]
=
KEY_F18
,
[
0x82
]
=
KEY_F19
,
[
0x83
]
=
KEY_F20
,
[
0x8a
]
=
KEY_FIND
,
[
0x8b
]
=
KEY_INSERT
,
[
0x8c
]
=
KEY_DELETE
,
[
0x8d
]
=
KEY_SELECT
,
[
0x8e
]
=
KEY_PAGEUP
,
[
0x8f
]
=
KEY_PAGEDOWN
,
[
0x92
]
=
KEY_KP0
,
[
0x94
]
=
KEY_KPDOT
,
[
0x95
]
=
KEY_KPENTER
,
[
0x96
]
=
KEY_KP1
,
[
0x97
]
=
KEY_KP2
,
[
0x98
]
=
KEY_KP3
,
[
0x99
]
=
KEY_KP4
,
[
0x9a
]
=
KEY_KP5
,
[
0x9b
]
=
KEY_KP6
,
[
0x9c
]
=
KEY_KPCOMMA
,
[
0x9d
]
=
KEY_KP7
,
[
0x9e
]
=
KEY_KP8
,
[
0x9f
]
=
KEY_KP9
,
[
0xa0
]
=
KEY_KPMINUS
,
[
0xa1
]
=
KEY_PROG1
,
[
0xa2
]
=
KEY_PROG2
,
[
0xa3
]
=
KEY_PROG3
,
[
0xa4
]
=
KEY_PROG4
,
[
0xa7
]
=
KEY_LEFT
,
[
0xa8
]
=
KEY_RIGHT
,
[
0xa9
]
=
KEY_DOWN
,
[
0xaa
]
=
KEY_UP
,
[
0xab
]
=
KEY_RIGHTSHIFT
,
[
0xac
]
=
KEY_LEFTALT
,
[
0xad
]
=
KEY_COMPOSE
,
/* Right Compose, that is. */
[
0xae
]
=
KEY_LEFTSHIFT
,
/* Same as KEY_RIGHTSHIFT on LK201 */
[
0xaf
]
=
KEY_LEFTCTRL
,
[
0xb0
]
=
KEY_CAPSLOCK
,
[
0xb1
]
=
KEY_COMPOSE
,
/* Left Compose, that is. */
[
0xb2
]
=
KEY_RIGHTALT
,
[
0xbc
]
=
KEY_BACKSPACE
,
[
0xbd
]
=
KEY_ENTER
,
[
0xbe
]
=
KEY_TAB
,
[
0xbf
]
=
KEY_ESC
,
[
0xc0
]
=
KEY_1
,
[
0xc1
]
=
KEY_Q
,
[
0xc2
]
=
KEY_A
,
[
0xc3
]
=
KEY_Z
,
[
0xc5
]
=
KEY_2
,
[
0xc6
]
=
KEY_W
,
[
0xc7
]
=
KEY_S
,
[
0xc8
]
=
KEY_X
,
[
0xc9
]
=
KEY_102ND
,
[
0xcb
]
=
KEY_3
,
[
0xcc
]
=
KEY_E
,
[
0xcd
]
=
KEY_D
,
[
0xce
]
=
KEY_C
,
[
0xd0
]
=
KEY_4
,
[
0xd1
]
=
KEY_R
,
[
0xd2
]
=
KEY_F
,
[
0xd3
]
=
KEY_V
,
[
0xd4
]
=
KEY_SPACE
,
[
0xd6
]
=
KEY_5
,
[
0xd7
]
=
KEY_T
,
[
0xd8
]
=
KEY_G
,
[
0xd9
]
=
KEY_B
,
[
0xdb
]
=
KEY_6
,
[
0xdc
]
=
KEY_Y
,
[
0xdd
]
=
KEY_H
,
[
0xde
]
=
KEY_N
,
[
0xe0
]
=
KEY_7
,
[
0xe1
]
=
KEY_U
,
[
0xe2
]
=
KEY_J
,
[
0xe3
]
=
KEY_M
,
[
0xe5
]
=
KEY_8
,
[
0xe6
]
=
KEY_I
,
[
0xe7
]
=
KEY_K
,
[
0xe8
]
=
KEY_COMMA
,
[
0xea
]
=
KEY_9
,
[
0xeb
]
=
KEY_O
,
[
0xec
]
=
KEY_L
,
[
0xed
]
=
KEY_DOT
,
[
0xef
]
=
KEY_0
,
[
0xf0
]
=
KEY_P
,
[
0xf2
]
=
KEY_SEMICOLON
,
[
0xf3
]
=
KEY_SLASH
,
[
0xf5
]
=
KEY_EQUAL
,
[
0xf6
]
=
KEY_RIGHTBRACE
,
[
0xf7
]
=
KEY_BACKSLASH
,
[
0xf9
]
=
KEY_MINUS
,
[
0xfa
]
=
KEY_LEFTBRACE
,
[
0xfb
]
=
KEY_APOSTROPHE
,
};
#define CHECK_LED(LED, BITS) do { \
if (test_bit (LED, lk->dev.led)) \
leds_on |= BITS; \
else \
leds_off |= BITS; \
} while (0)
/*
* Per-keyboard data
*/
struct
lkkbd
{
lk_keycode_t
keycode
[
LK_NUM_KEYCODES
];
int
ignore_bytes
;
struct
input_dev
dev
;
struct
serio
*
serio
;
struct
work_struct
tq
;
char
name
[
64
];
char
phys
[
32
];
char
type
;
int
bell_volume
;
int
keyclick_volume
;
int
ctrlclick_volume
;
};
/*
* Calculate volume parameter byte for a given volume.
*/
static
unsigned
char
volume_to_hw
(
int
volume_percent
)
{
unsigned
char
ret
=
0
;
if
(
volume_percent
<
0
)
volume_percent
=
0
;
if
(
volume_percent
>
100
)
volume_percent
=
100
;
if
(
volume_percent
>=
0
)
ret
=
7
;
if
(
volume_percent
>=
13
)
/* 12.5 */
ret
=
6
;
if
(
volume_percent
>=
25
)
ret
=
5
;
if
(
volume_percent
>=
38
)
/* 37.5 */
ret
=
4
;
if
(
volume_percent
>=
50
)
ret
=
3
;
if
(
volume_percent
>=
63
)
/* 62.5 */
ret
=
2
;
/* This is the default volume */
if
(
volume_percent
>=
75
)
ret
=
1
;
if
(
volume_percent
>=
88
)
/* 87.5 */
ret
=
0
;
ret
|=
0x80
;
return
ret
;
}
/*
* lkkbd_interrupt() is called by the low level driver when a character
* is received.
*/
static
irqreturn_t
lkkbd_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
)
{
struct
lkkbd
*
lk
=
serio
->
private
;
int
i
;
DBG
(
KERN_INFO
"Got byte 0x%02x
\n
"
,
data
);
if
(
lk
->
ignore_bytes
>
0
)
{
DBG
(
KERN_INFO
"Ignoring a byte on %s
\n
"
,
lk
->
name
);
lk
->
ignore_bytes
--
;
return
IRQ_HANDLED
;
}
switch
(
data
)
{
case
LK_ALL_KEYS_UP
:
input_regs
(
&
lk
->
dev
,
regs
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
lkkbd_keycode
);
i
++
)
if
(
lk
->
keycode
[
i
]
!=
KEY_RESERVED
)
input_report_key
(
&
lk
->
dev
,
lk
->
keycode
[
i
],
0
);
input_sync
(
&
lk
->
dev
);
break
;
case
LK_METRONOME
:
DBG
(
KERN_INFO
"Got LK_METRONOME and don't "
"know how to handle...
\n
"
);
break
;
case
LK_OUTPUT_ERROR
:
DBG
(
KERN_INFO
"Got LK_OUTPUT_ERROR and don't "
"know how to handle...
\n
"
);
break
;
case
LK_INPUT_ERROR
:
DBG
(
KERN_INFO
"Got LK_INPUT_ERROR and don't "
"know how to handle...
\n
"
);
break
;
case
LK_KBD_LOCKED
:
DBG
(
KERN_INFO
"Got LK_KBD_LOCKED and don't "
"know how to handle...
\n
"
);
break
;
case
LK_KBD_TEST_MODE_ACK
:
DBG
(
KERN_INFO
"Got LK_KBD_TEST_MODE_ACK and don't "
"know how to handle...
\n
"
);
break
;
case
LK_PREFIX_KEY_DOWN
:
DBG
(
KERN_INFO
"Got LK_PREFIX_KEY_DOWN and don't "
"know how to handle...
\n
"
);
break
;
case
LK_MODE_CHANGE_ACK
:
DBG
(
KERN_INFO
"Got LK_MODE_CHANGE_ACK and ignored "
"it properly...
\n
"
);
break
;
case
LK_RESPONSE_RESERVED
:
DBG
(
KERN_INFO
"Got LK_RESPONSE_RESERVED and don't "
"know how to handle...
\n
"
);
break
;
case
0x01
:
DBG
(
KERN_INFO
"Got 0x01, scheduling re-initialization
\n
"
);
lk
->
ignore_bytes
=
3
;
schedule_work
(
&
lk
->
tq
);
break
;
default:
if
(
lk
->
keycode
[
data
]
!=
KEY_RESERVED
)
{
input_regs
(
&
lk
->
dev
,
regs
);
if
(
!
test_bit
(
lk
->
keycode
[
data
],
lk
->
dev
.
key
))
input_report_key
(
&
lk
->
dev
,
lk
->
keycode
[
data
],
1
);
else
input_report_key
(
&
lk
->
dev
,
lk
->
keycode
[
data
],
0
);
input_sync
(
&
lk
->
dev
);
}
else
printk
(
KERN_WARNING
"%s: Unknown key with "
"scancode %02x on %s.
\n
"
,
__FILE__
,
data
,
lk
->
name
);
}
return
IRQ_HANDLED
;
}
/*
* lkkbd_event() handles events from the input module.
*/
static
int
lkkbd_event
(
struct
input_dev
*
dev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
struct
lkkbd
*
lk
=
dev
->
private
;
unsigned
char
leds_on
=
0
;
unsigned
char
leds_off
=
0
;
switch
(
type
)
{
case
EV_LED
:
CHECK_LED
(
LED_CAPSL
,
LK_LED_SHIFTLOCK
);
CHECK_LED
(
LED_COMPOSE
,
LK_LED_COMPOSE
);
CHECK_LED
(
LED_SCROLLL
,
LK_LED_SCROLLLOCK
);
CHECK_LED
(
LED_SLEEP
,
LK_LED_WAIT
);
if
(
leds_on
!=
0
)
{
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_LED_ON
);
lk
->
serio
->
write
(
lk
->
serio
,
leds_on
);
}
if
(
leds_off
!=
0
)
{
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_LED_OFF
);
lk
->
serio
->
write
(
lk
->
serio
,
leds_off
);
}
return
0
;
case
EV_SND
:
switch
(
code
)
{
case
SND_CLICK
:
if
(
value
==
0
)
{
DBG
(
"%s: Deactivating key clicks
\n
"
,
__FUNCTION__
);
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_DISABLE_KEYCLICK
);
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_DISABLE_CTRCLICK
);
}
else
{
DBG
(
"%s: Activating key clicks
\n
"
,
__FUNCTION__
);
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_ENABLE_KEYCLICK
);
lk
->
serio
->
write
(
lk
->
serio
,
volume_to_hw
(
lk
->
keyclick_volume
));
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_ENABLE_CTRCLICK
);
lk
->
serio
->
write
(
lk
->
serio
,
volume_to_hw
(
lk
->
ctrlclick_volume
));
}
return
0
;
case
SND_BELL
:
if
(
value
!=
0
)
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_SOUND_BELL
);
return
0
;
}
break
;
default:
printk
(
KERN_ERR
"%s (): Got unknown type %d, code %d, value %d
\n
"
,
__FUNCTION__
,
type
,
code
,
value
);
}
return
-
1
;
}
/*
* lkkbd_reinit() sets leds and beeps to a state the computer remembers they
* were in.
*/
static
void
lkkbd_reinit
(
void
*
data
)
{
struct
lkkbd
*
lk
=
data
;
int
division
;
unsigned
char
leds_on
=
0
;
unsigned
char
leds_off
=
0
;
/* Reset parameters */
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_SET_DEFAULTS
);
/* Set LEDs */
CHECK_LED
(
LED_CAPSL
,
LK_LED_SHIFTLOCK
);
CHECK_LED
(
LED_COMPOSE
,
LK_LED_COMPOSE
);
CHECK_LED
(
LED_SCROLLL
,
LK_LED_SCROLLLOCK
);
CHECK_LED
(
LED_SLEEP
,
LK_LED_WAIT
);
if
(
leds_on
!=
0
)
{
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_LED_ON
);
lk
->
serio
->
write
(
lk
->
serio
,
leds_on
);
}
if
(
leds_off
!=
0
)
{
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_LED_OFF
);
lk
->
serio
->
write
(
lk
->
serio
,
leds_off
);
}
/*
* Try to activate extended LK401 mode. This command will
* only work with a LK401 keyboard and grants access to
* LAlt, RAlt, RCompose and RShift.
*/
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_ENABLE_LK401
);
/* Set all keys to UPDOWN mode */
for
(
division
=
1
;
division
<=
14
;
division
++
)
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_SET_MODE
(
LK_MODE_UPDOWN
,
division
));
/* Enable bell and set volume */
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_ENABLE_BELL
);
lk
->
serio
->
write
(
lk
->
serio
,
volume_to_hw
(
lk
->
bell_volume
));
/* Enable/disable keyclick (and possibly set volume) */
if
(
test_bit
(
SND_CLICK
,
lk
->
dev
.
snd
))
{
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_ENABLE_KEYCLICK
);
lk
->
serio
->
write
(
lk
->
serio
,
volume_to_hw
(
lk
->
keyclick_volume
));
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_ENABLE_CTRCLICK
);
lk
->
serio
->
write
(
lk
->
serio
,
volume_to_hw
(
lk
->
ctrlclick_volume
));
}
else
{
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_DISABLE_KEYCLICK
);
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_DISABLE_CTRCLICK
);
}
/* Sound the bell if needed */
if
(
test_bit
(
SND_BELL
,
lk
->
dev
.
snd
))
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_SOUND_BELL
);
}
/*
* lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
*/
static
void
lkkbd_connect
(
struct
serio
*
serio
,
struct
serio_dev
*
dev
)
{
struct
lkkbd
*
lk
;
int
i
;
if
((
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_RS232
)
return
;
if
(
!
(
serio
->
type
&
SERIO_PROTO
))
return
;
if
((
serio
->
type
&
SERIO_PROTO
)
&&
(
serio
->
type
&
SERIO_PROTO
)
!=
SERIO_LKKBD
)
return
;
if
(
!
(
lk
=
kmalloc
(
sizeof
(
struct
lkkbd
),
GFP_KERNEL
)))
return
;
memset
(
lk
,
0
,
sizeof
(
struct
lkkbd
));
init_input_dev
(
&
lk
->
dev
);
lk
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_LED
)
|
BIT
(
EV_SND
)
|
BIT
(
EV_REP
);
lk
->
dev
.
ledbit
[
0
]
=
BIT
(
LED_CAPSL
)
|
BIT
(
LED_COMPOSE
)
|
BIT
(
LED_SCROLLL
)
|
BIT
(
LED_SLEEP
);
lk
->
dev
.
sndbit
[
0
]
=
BIT
(
SND_CLICK
)
|
BIT
(
SND_BELL
);
lk
->
serio
=
serio
;
INIT_WORK
(
&
lk
->
tq
,
lkkbd_reinit
,
lk
);
lk
->
bell_volume
=
bell_volume
;
lk
->
keyclick_volume
=
keyclick_volume
;
lk
->
ctrlclick_volume
=
ctrlclick_volume
;
lk
->
dev
.
keycode
=
lk
->
keycode
;
lk
->
dev
.
keycodesize
=
sizeof
(
lk_keycode_t
);
lk
->
dev
.
keycodemax
=
LK_NUM_KEYCODES
;
lk
->
dev
.
event
=
lkkbd_event
;
lk
->
dev
.
private
=
lk
;
serio
->
private
=
lk
;
if
(
serio_open
(
serio
,
dev
))
{
kfree
(
lk
);
return
;
}
sprintf
(
lk
->
name
,
"LK keyboard"
);
memcpy
(
lk
->
keycode
,
lkkbd_keycode
,
sizeof
(
lk_keycode_t
)
*
LK_NUM_KEYCODES
);
for
(
i
=
0
;
i
<
LK_NUM_KEYCODES
;
i
++
)
set_bit
(
lk
->
keycode
[
i
],
lk
->
dev
.
keybit
);
sprintf
(
lk
->
name
,
"%s/input0"
,
serio
->
phys
);
lk
->
dev
.
name
=
lk
->
name
;
lk
->
dev
.
phys
=
lk
->
phys
;
lk
->
dev
.
id
.
bustype
=
BUS_RS232
;
lk
->
dev
.
id
.
vendor
=
SERIO_LKKBD
;
lk
->
dev
.
id
.
product
=
0
;
lk
->
dev
.
id
.
version
=
0x0100
;
input_register_device
(
&
lk
->
dev
);
printk
(
KERN_INFO
"input: %s on %s, initiating reset
\n
"
,
lk
->
name
,
serio
->
phys
);
lk
->
serio
->
write
(
lk
->
serio
,
LK_CMD_POWERCYCLE_RESET
);
}
/*
* lkkbd_disconnect() unregisters and closes behind us.
*/
static
void
lkkbd_disconnect
(
struct
serio
*
serio
)
{
struct
lkkbd
*
lk
=
serio
->
private
;
input_unregister_device
(
&
lk
->
dev
);
serio_close
(
serio
);
kfree
(
lk
);
}
static
struct
serio_dev
lkkbd_dev
=
{
.
interrupt
=
lkkbd_interrupt
,
.
connect
=
lkkbd_connect
,
.
disconnect
=
lkkbd_disconnect
,
};
/*
* The functions for insering/removing us as a module.
*/
int
__init
lkkbd_init
(
void
)
{
serio_register_device
(
&
lkkbd_dev
);
return
0
;
}
void
__exit
lkkbd_exit
(
void
)
{
serio_unregister_device
(
&
lkkbd_dev
);
}
module_init
(
lkkbd_init
);
module_exit
(
lkkbd_exit
);
drivers/input/keyboard/sunkbd.c
View file @
be7b8193
...
...
@@ -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 @
be7b8193
...
...
@@ -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 @
be7b8193
...
...
@@ -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 @
d3fdc9ac
/*
* 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/98busmouse.c
View file @
be7b8193
...
...
@@ -74,6 +74,8 @@ static int pc98bm_irq = PC98BM_IRQ;
module_param_named
(
irq
,
pc98bm_irq
,
uint
,
0
);
MODULE_PARM_DESC
(
irq
,
"IRQ number (13=default)"
);
__obsolete_setup
(
"pc98bm_irq="
);
static
int
pc98bm_used
=
0
;
static
irqreturn_t
pc98bm_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
...
...
drivers/input/mouse/Kconfig
View file @
be7b8193
...
...
@@ -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
...
...
@@ -117,6 +118,19 @@ config MOUSE_RISCPC
To compile this driver as a module, choose M here: the
module will be called rpcmouse.
config MOUSE_VSXXXAA
tristate "DEC VSXXX-AA/GA mouse and tablet"
depends on INPUT && INPUT_MOUSE
select SERIO
help
Say Y (or M) if you want to use a DEC VSXXX-AA (hockey
puck) or a VSXXX-GA (rectangular) mouse. Theses mice are
typically used on DECstations or VAXstations, but can also
be used on any box capable of RS232 (with some adaptor
described in the source file). This driver should, in theory,
also work with the digitizer DEC produced, but it isn't tested
with that (I don't have the hardware yet).
config MOUSE_PC9800
tristate "NEC PC-9800 busmouse"
depends on X86_PC9800 && INPUT && INPUT_MOUSE && ISA
...
...
drivers/input/mouse/Makefile
View file @
be7b8193
...
...
@@ -13,5 +13,6 @@ obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
obj-$(CONFIG_MOUSE_PC9800)
+=
98busmouse.o
obj-$(CONFIG_MOUSE_PS2)
+=
psmouse.o
obj-$(CONFIG_MOUSE_SERIAL)
+=
sermouse.o
obj-$(CONFIG_MOUSE_VSXXXAA)
+=
vsxxxaa.o
psmouse-objs
:=
psmouse-base.o logips2pp.o synaptics.o
drivers/input/mouse/inport.c
View file @
be7b8193
...
...
@@ -85,6 +85,8 @@ static int inport_irq = INPORT_IRQ;
module_param_named
(
irq
,
inport_irq
,
uint
,
0
);
MODULE_PARM_DESC
(
irq
,
"IRQ number (5=default)"
);
__obsolete_setup
(
"inport_irq="
);
static
int
inport_used
;
static
irqreturn_t
inport_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
...
...
drivers/input/mouse/logibm.c
View file @
be7b8193
...
...
@@ -75,6 +75,8 @@ static int logibm_irq = LOGIBM_IRQ;
module_param_named
(
irq
,
logibm_irq
,
uint
,
0
);
MODULE_PARM_DESC
(
irq
,
"IRQ number (5=default)"
);
__obsolete_setup
(
"logibm_irq="
);
static
int
logibm_used
=
0
;
static
irqreturn_t
logibm_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
...
...
drivers/input/mouse/psmouse-base.c
View file @
be7b8193
...
...
@@ -47,6 +47,12 @@ unsigned int psmouse_resetafter;
module_param_named
(
resetafter
,
psmouse_resetafter
,
uint
,
0
);
MODULE_PARM_DESC
(
resetafter
,
"Reset Synaptics Touchpad after so many bad packets (0 = never)."
);
__obsolete_setup
(
"psmouse_noext"
);
__obsolete_setup
(
"psmouse_resolution="
);
__obsolete_setup
(
"psmouse_smartscroll="
);
__obsolete_setup
(
"psmouse_resetafter="
);
__obsolete_setup
(
"psmouse_rate="
);
static
char
*
psmouse_protocols
[]
=
{
"None"
,
"PS/2"
,
"PS2++"
,
"PS2T++"
,
"GenPS/2"
,
"ImPS/2"
,
"ImExPS/2"
,
"SynPS/2"
};
/*
...
...
@@ -442,7 +448,7 @@ static int psmouse_probe(struct psmouse *psmouse)
*/
if
(
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_RESET_DIS
))
return
-
1
;
printk
(
KERN_WARNING
"psmouse.c: Failed to reset mouse on %s
\n
"
,
psmouse
->
serio
->
phys
)
;
/*
* And here we try to determine if it has any extensions over the
...
...
@@ -637,13 +643,15 @@ static int psmouse_reconnect(struct serio *serio)
{
struct
psmouse
*
psmouse
=
serio
->
private
;
struct
serio_dev
*
dev
=
serio
->
dev
;
int
old_type
=
psmouse
->
type
;
int
old_type
;
if
(
!
dev
)
{
if
(
!
dev
||
!
psmouse
)
{
printk
(
KERN_DEBUG
"psmouse: reconnect request, but serio is disconnected, ignoring...
\n
"
);
return
-
1
;
}
old_type
=
psmouse
->
type
;
psmouse
->
state
=
PSMOUSE_NEW_DEVICE
;
psmouse
->
type
=
psmouse
->
acking
=
psmouse
->
cmdcnt
=
psmouse
->
pktcnt
=
0
;
if
(
psmouse
->
reconnect
)
{
...
...
drivers/input/mouse/synaptics.c
View file @
be7b8193
...
...
@@ -435,6 +435,8 @@ int synaptics_init(struct psmouse *psmouse)
goto
init_fail
;
}
priv
->
pkt_type
=
SYN_MODEL_NEWABS
(
priv
->
model_id
)
?
SYN_NEWABS
:
SYN_OLDABS
;
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
)
&&
SYN_CAP_PASS_THROUGH
(
priv
->
capabilities
))
synaptics_pt_create
(
psmouse
);
...
...
@@ -602,19 +604,42 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_sync
(
dev
);
}
static
int
synaptics_validate_byte
(
struct
psmouse
*
psmous
e
)
static
int
synaptics_validate_byte
(
unsigned
char
packet
[],
int
idx
,
unsigned
char
pkt_typ
e
)
{
static
unsigned
char
newabs_mask
[]
=
{
0xC0
,
0x00
,
0x00
,
0xC0
,
0x00
};
static
unsigned
char
newabs_mask
[]
=
{
0xC8
,
0x00
,
0x00
,
0xC8
,
0x00
};
static
unsigned
char
newabs_rel_mask
[]
=
{
0xC0
,
0x00
,
0x00
,
0xC0
,
0x00
};
static
unsigned
char
newabs_rslt
[]
=
{
0x80
,
0x00
,
0x00
,
0xC0
,
0x00
};
static
unsigned
char
oldabs_mask
[]
=
{
0xC0
,
0x60
,
0x00
,
0xC0
,
0x60
};
static
unsigned
char
oldabs_rslt
[]
=
{
0xC0
,
0x00
,
0x00
,
0x80
,
0x00
};
struct
synaptics_data
*
priv
=
psmouse
->
private
;
int
idx
=
psmouse
->
pktcnt
-
1
;
if
(
SYN_MODEL_NEWABS
(
priv
->
model_id
))
return
(
psmouse
->
packet
[
idx
]
&
newabs_mask
[
idx
])
==
newabs_rslt
[
idx
];
else
return
(
psmouse
->
packet
[
idx
]
&
oldabs_mask
[
idx
])
==
oldabs_rslt
[
idx
];
switch
(
pkt_type
)
{
case
SYN_NEWABS
:
case
SYN_NEWABS_RELAXED
:
return
(
packet
[
idx
]
&
newabs_rel_mask
[
idx
])
==
newabs_rslt
[
idx
];
case
SYN_NEWABS_STRICT
:
return
(
packet
[
idx
]
&
newabs_mask
[
idx
])
==
newabs_rslt
[
idx
];
case
SYN_OLDABS
:
return
(
packet
[
idx
]
&
oldabs_mask
[
idx
])
==
oldabs_rslt
[
idx
];
default:
printk
(
KERN_ERR
"synaptics: unknown packet type %d
\n
"
,
pkt_type
);
return
0
;
}
}
static
unsigned
char
synaptics_detect_pkt_type
(
struct
psmouse
*
psmouse
)
{
int
i
;
for
(
i
=
0
;
i
<
5
;
i
++
)
if
(
!
synaptics_validate_byte
(
psmouse
->
packet
,
i
,
SYN_NEWABS_STRICT
))
{
printk
(
KERN_INFO
"synaptics: using relaxed packet validation
\n
"
);
return
SYN_NEWABS_RELAXED
;
}
return
SYN_NEWABS_STRICT
;
}
void
synaptics_process_byte
(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
)
...
...
@@ -630,13 +655,17 @@ void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
printk
(
KERN_NOTICE
"Synaptics driver resynced.
\n
"
);
}
if
(
unlikely
(
priv
->
pkt_type
==
SYN_NEWABS
))
priv
->
pkt_type
=
synaptics_detect_pkt_type
(
psmouse
);
if
(
psmouse
->
ptport
&&
psmouse
->
ptport
->
serio
.
dev
&&
synaptics_is_pt_packet
(
psmouse
->
packet
))
synaptics_pass_pt_packet
(
&
psmouse
->
ptport
->
serio
,
psmouse
->
packet
);
else
synaptics_process_packet
(
psmouse
);
psmouse
->
pktcnt
=
0
;
}
else
if
(
psmouse
->
pktcnt
&&
!
synaptics_validate_byte
(
psmouse
))
{
}
else
if
(
psmouse
->
pktcnt
&&
!
synaptics_validate_byte
(
psmouse
->
packet
,
psmouse
->
pktcnt
-
1
,
priv
->
pkt_type
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at byte %d
\n
"
,
psmouse
->
pktcnt
);
psmouse
->
pktcnt
=
0
;
if
(
++
priv
->
out_of_sync
==
psmouse_resetafter
)
{
...
...
drivers/input/mouse/synaptics.h
View file @
be7b8193
...
...
@@ -70,6 +70,12 @@ extern int synaptics_init(struct psmouse *psmouse);
#define SYN_PS_SET_MODE2 0x14
#define SYN_PS_CLIENT_CMD 0x28
/* synaptics packet types */
#define SYN_NEWABS 0
#define SYN_NEWABS_STRICT 1
#define SYN_NEWABS_RELAXED 2
#define SYN_OLDABS 3
/*
* A structure to describe the state of the touchpad hardware (buttons and pad)
*/
...
...
@@ -103,6 +109,7 @@ struct synaptics_data {
/* Data for normal processing */
unsigned
int
out_of_sync
;
/* # of packets out of sync */
int
old_w
;
/* Previous w value */
unsigned
char
pkt_type
;
/* packet type - old, new, etc */
};
#endif
/* _SYNAPTICS_H */
drivers/input/mouse/vsxxxaa.c
0 → 100644
View file @
be7b8193
/*
* DEC VSXXX-AA and VSXXX-GA mouse driver.
*
* Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
*
* The packet format was taken from a patch to GPM which is (C) 2001
* by Karsten Merker <merker@linuxtag.org>
* and Maciej W. Rozycki <macro@ds2.pg.gda.pl>
*/
/*
* 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
*/
/*
* Building an adaptor to DB9 / DB25 RS232
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* DISCLAIMER: Use this description AT YOUR OWN RISK! I'll not pay for
* anything if you break your mouse, your computer or whatever!
*
* In theory, this mouse is a simple RS232 device. In practice, it has got
* a quite uncommon plug and the requirement to additionally get a power
* supply at +5V and -12V.
*
* If you look at the socket/jack (_not_ at the plug), we use this pin
* numbering:
* _______
* / 7 6 5 \
* | 4 --- 3 |
* \ 2 1 /
* -------
*
* DEC socket DB9 DB25 Note
* 1 (GND) 5 7 -
* 2 (RxD) 3 3 -
* 3 (TxD) 2 2 -
* 4 (-12V) - - Somewhere from the PSU. At ATX, it's
* the blue wire at pin 12 of the ATX
* power connector. Please note that the
* docs say this should be +12V! However,
* I measured -12V...
* 5 (+5V) - - PSU (red wire of ATX power connector
* on pin 4, 6, 19 or 20) or HDD power
* connector (also red wire)
* 6 (not conn.) - - -
* 7 (dev. avail.) - - The mouse shorts this one to pin 1.
* This way, the host computer can detect
* the mouse. To use it with the adaptor,
* simply don't connect this pin.
*
* So to get a working adaptor, you need to connect the mouse with three
* wires to a RS232 port and two additional wires for +5V and -12V to the
* PSU.
*
* Flow specification for the link is 4800, 8o1.
*/
/*
* TODO list:
* - Automatically attach to a given serial port (no need for inputattach).
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/config.h>
#include <linux/serio.h>
#include <linux/init.h>
MODULE_AUTHOR
(
"Jan-Benedict Glaw <jbglaw@lug-owl.de>"
);
MODULE_DESCRIPTION
(
"Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"
);
MODULE_LICENSE
(
"GPL"
);
#undef VSXXXAA_DEBUG
#ifdef VSXXXAA_DEBUG
#define DBG(x...) printk (x)
#else
#define DBG(x...) do {} while (0)
#endif
#define VSXXXAA_INTRO_MASK 0x80
#define VSXXXAA_INTRO_HEAD 0x80
#define IS_HDR_BYTE(x) (((x) & VSXXXAA_INTRO_MASK) \
== VSXXXAA_INTRO_HEAD)
#define VSXXXAA_PACKET_MASK 0xe0
#define VSXXXAA_PACKET_REL 0x80
#define VSXXXAA_PACKET_ABS 0xc0
#define VSXXXAA_PACKET_POR 0xa0
#define MATCH_PACKET_TYPE(data, type) (((data) & VSXXXAA_PACKET_MASK) == type)
struct
vsxxxaa
{
struct
input_dev
dev
;
struct
serio
*
serio
;
#define BUFLEN 15
/* At least 5 is needed for a full tablet packet */
unsigned
char
buf
[
BUFLEN
];
unsigned
char
count
;
unsigned
char
version
;
unsigned
char
country
;
unsigned
char
type
;
char
phys
[
32
];
};
static
void
vsxxxaa_drop_bytes
(
struct
vsxxxaa
*
mouse
,
int
num
)
{
if
(
num
>=
mouse
->
count
)
mouse
->
count
=
0
;
else
{
memmove
(
mouse
->
buf
,
mouse
->
buf
+
num
-
1
,
BUFLEN
-
num
);
mouse
->
count
-=
num
;
}
}
static
void
vsxxxaa_queue_byte
(
struct
vsxxxaa
*
mouse
,
unsigned
char
byte
)
{
if
(
mouse
->
count
==
BUFLEN
)
{
printk
(
KERN_ERR
"%s on %s: Dropping a byte of full buffer.
\n
"
,
mouse
->
dev
.
name
,
mouse
->
dev
.
phys
);
vsxxxaa_drop_bytes
(
mouse
,
1
);
}
mouse
->
buf
[
mouse
->
count
++
]
=
byte
;
}
static
void
vsxxxaa_report_mouse
(
struct
vsxxxaa
*
mouse
)
{
char
*
devtype
;
switch
(
mouse
->
type
)
{
case
0x02
:
devtype
=
"DEC mouse"
;
break
;
case
0x04
:
devtype
=
"DEC tablet"
;
break
;
default:
devtype
=
"unknown DEC device"
;
break
;
}
printk
(
KERN_INFO
"Found %s version 0x%x from country 0x%x "
"on port %s
\n
"
,
devtype
,
mouse
->
version
,
mouse
->
country
,
mouse
->
dev
.
phys
);
}
/*
* Returns number of bytes to be dropped, 0 if packet is okay.
*/
static
int
vsxxxaa_check_packet
(
struct
vsxxxaa
*
mouse
,
int
packet_len
)
{
int
i
;
/* First byte must be a header byte */
if
(
!
IS_HDR_BYTE
(
mouse
->
buf
[
0
]))
{
DBG
(
"vsck: len=%d, 1st=0x%02x
\n
"
,
packet_len
,
mouse
->
buf
[
0
]);
return
1
;
}
/* Check all following bytes */
if
(
packet_len
>
1
)
{
for
(
i
=
1
;
i
<
packet_len
;
i
++
)
{
if
(
IS_HDR_BYTE
(
mouse
->
buf
[
i
]))
{
printk
(
KERN_ERR
"Need to drop %d bytes "
"of a broken packet.
\n
"
,
i
-
1
);
DBG
(
KERN_INFO
"check: len=%d, b[%d]=0x%02x
\n
"
,
packet_len
,
i
,
mouse
->
buf
[
i
]);
return
i
-
1
;
}
}
}
return
0
;
}
static
__inline__
int
vsxxxaa_smells_like_packet
(
struct
vsxxxaa
*
mouse
,
unsigned
char
type
,
size_t
len
)
{
return
(
mouse
->
count
>=
len
)
&&
MATCH_PACKET_TYPE
(
mouse
->
buf
[
0
],
type
);
}
static
void
vsxxxaa_handle_REL_packet
(
struct
vsxxxaa
*
mouse
,
struct
pt_regs
*
regs
)
{
struct
input_dev
*
dev
=
&
mouse
->
dev
;
unsigned
char
*
buf
=
mouse
->
buf
;
int
left
,
middle
,
right
;
int
dx
,
dy
;
/*
* Check for normal stream packets. This is three bytes,
* with the first byte's 3 MSB set to 100.
*
* [0]: 1 0 0 SignX SignY Left Middle Right
* [1]: 0 dx dx dx dx dx dx dx
* [2]: 0 dy dy dy dy dy dy dy
*/
/*
* Low 7 bit of byte 1 are abs(dx), bit 7 is
* 0, bit 4 of byte 0 is direction.
*/
dx
=
buf
[
1
]
&
0x7f
;
dx
*=
((
buf
[
0
]
>>
4
)
&
0x01
)
?
-
1
:
1
;
/*
* Low 7 bit of byte 2 are abs(dy), bit 7 is
* 0, bit 3 of byte 0 is direction.
*/
dy
=
buf
[
2
]
&
0x7f
;
dy
*=
((
buf
[
0
]
>>
3
)
&
0x01
)
?
-
1
:
1
;
/*
* Get button state. It's the low three bits
* (for three buttons) of byte 0.
*/
left
=
(
buf
[
0
]
&
0x04
)
?
1
:
0
;
middle
=
(
buf
[
0
]
&
0x02
)
?
1
:
0
;
right
=
(
buf
[
0
]
&
0x01
)
?
1
:
0
;
vsxxxaa_drop_bytes
(
mouse
,
3
);
DBG
(
KERN_INFO
"%s on %s: dx=%d, dy=%d, buttons=%s%s%s
\n
"
,
mouse
->
dev
.
name
,
mouse
->
dev
.
phys
,
dx
,
dy
,
left
?
"L"
:
"l"
,
middle
?
"M"
:
"m"
,
right
?
"R"
:
"r"
);
/*
* Report what we've found so far...
*/
input_regs
(
dev
,
regs
);
input_report_key
(
dev
,
BTN_LEFT
,
left
);
input_report_key
(
dev
,
BTN_MIDDLE
,
middle
);
input_report_key
(
dev
,
BTN_RIGHT
,
right
);
input_report_rel
(
dev
,
REL_X
,
dx
);
input_report_rel
(
dev
,
REL_Y
,
dy
);
input_sync
(
dev
);
}
static
void
vsxxxaa_handle_ABS_packet
(
struct
vsxxxaa
*
mouse
,
struct
pt_regs
*
regs
)
{
struct
input_dev
*
dev
=
&
mouse
->
dev
;
unsigned
char
*
buf
=
mouse
->
buf
;
int
left
,
middle
,
right
,
extra
;
int
x
,
y
;
/*
* Tablet position / button packet
*
* [0]: 1 1 0 B4 B3 B2 B1 Pr
* [1]: 0 0 X5 X4 X3 X2 X1 X0
* [2]: 0 0 X11 X10 X9 X8 X7 X6
* [3]: 0 0 Y5 Y4 Y3 Y2 Y1 Y0
* [4]: 0 0 Y11 Y10 Y9 Y8 Y7 Y6
*/
/*
* Get X/Y position
*/
x
=
((
buf
[
2
]
&
0x3f
)
<<
6
)
|
(
buf
[
1
]
&
0x3f
);
y
=
((
buf
[
4
]
&
0x3f
)
<<
6
)
|
(
buf
[
3
]
&
0x3f
);
/*
* Get button state. It's bits <4..1> of byte 0.
*/
left
=
(
buf
[
0
]
&
0x02
)
?
1
:
0
;
middle
=
(
buf
[
0
]
&
0x04
)
?
1
:
0
;
right
=
(
buf
[
0
]
&
0x08
)
?
1
:
0
;
extra
=
(
buf
[
0
]
&
0x10
)
?
1
:
0
;
vsxxxaa_drop_bytes
(
mouse
,
5
);
DBG
(
KERN_INFO
"%s on %s: x=%d, y=%d, buttons=%s%s%s%s
\n
"
,
mouse
->
dev
.
name
,
mouse
->
dev
.
phys
,
x
,
y
,
left
?
"L"
:
"l"
,
middle
?
"M"
:
"m"
,
right
?
"R"
:
"r"
,
extra
?
"E"
:
"e"
);
/*
* Report what we've found so far...
*/
input_regs
(
dev
,
regs
);
input_report_key
(
dev
,
BTN_LEFT
,
left
);
input_report_key
(
dev
,
BTN_MIDDLE
,
middle
);
input_report_key
(
dev
,
BTN_RIGHT
,
right
);
input_report_key
(
dev
,
BTN_EXTRA
,
extra
);
input_report_abs
(
dev
,
ABS_X
,
x
);
input_report_abs
(
dev
,
ABS_Y
,
y
);
input_sync
(
dev
);
}
static
void
vsxxxaa_handle_POR_packet
(
struct
vsxxxaa
*
mouse
,
struct
pt_regs
*
regs
)
{
struct
input_dev
*
dev
=
&
mouse
->
dev
;
unsigned
char
*
buf
=
mouse
->
buf
;
int
left
,
middle
,
right
;
unsigned
char
error
;
/*
* Check for Power-On-Reset packets. These are sent out
* after plugging the mouse in, or when explicitely
* requested by sending 'T'.
*
* [0]: 1 0 1 0 R3 R2 R1 R0
* [1]: 0 M2 M1 M0 D3 D2 D1 D0
* [2]: 0 E6 E5 E4 E3 E2 E1 E0
* [3]: 0 0 0 0 0 Left Middle Right
*
* M: manufacturer location code
* R: revision code
* E: Error code. I'm not sure about these, but gpm's sources,
* which support this mouse, too, tell about them:
* E = [0x00 .. 0x1f]: no error, byte #3 is button state
* E = 0x3d: button error, byte #3 tells which one.
* E = <else>: other error
* D: <0010> == mouse, <0100> == tablet
*
*/
mouse
->
version
=
buf
[
0
]
&
0x0f
;
mouse
->
country
=
(
buf
[
1
]
>>
4
)
&
0x07
;
mouse
->
type
=
buf
[
1
]
&
0x07
;
error
=
buf
[
2
]
&
0x7f
;
/*
* Get button state. It's the low three bits
* (for three buttons) of byte 0. Maybe even the bit <3>
* has some meaning if a tablet is attached.
*/
left
=
(
buf
[
0
]
&
0x04
)
?
1
:
0
;
middle
=
(
buf
[
0
]
&
0x02
)
?
1
:
0
;
right
=
(
buf
[
0
]
&
0x01
)
?
1
:
0
;
vsxxxaa_drop_bytes
(
mouse
,
4
);
vsxxxaa_report_mouse
(
mouse
);
if
(
error
<=
0x1f
)
{
/* No error. Report buttons */
input_regs
(
dev
,
regs
);
input_report_key
(
dev
,
BTN_LEFT
,
left
);
input_report_key
(
dev
,
BTN_MIDDLE
,
middle
);
input_report_key
(
dev
,
BTN_RIGHT
,
right
);
input_sync
(
dev
);
}
else
{
printk
(
KERN_ERR
"Your %s on %s reports an undefined error, "
"please check it...
\n
"
,
mouse
->
dev
.
name
,
mouse
->
dev
.
phys
);
}
/*
* If the mouse was hot-plugged, we need to
* force differential mode now...
*/
printk
(
KERN_NOTICE
"%s on %s: Forceing standard packet format and "
"streaming mode
\n
"
,
mouse
->
dev
.
name
,
mouse
->
dev
.
phys
);
mouse
->
serio
->
write
(
mouse
->
serio
,
'S'
);
mouse
->
serio
->
write
(
mouse
->
serio
,
'R'
);
}
static
void
vsxxxaa_parse_buffer
(
struct
vsxxxaa
*
mouse
,
struct
pt_regs
*
regs
)
{
unsigned
char
*
buf
=
mouse
->
buf
;
int
stray_bytes
;
/*
* Parse buffer to death...
*/
do
{
/*
* Out of sync? Throw away what we don't understand. Each
* packet starts with a byte whose bit 7 is set. Unhandled
* packets (ie. which we don't know about or simply b0rk3d
* data...) will get shifted out of the buffer after some
* activity on the mouse.
*/
while
(
mouse
->
count
>
0
&&
!
IS_HDR_BYTE
(
buf
[
0
]))
{
printk
(
KERN_ERR
"%s on %s: Dropping a byte to regain "
"sync with mouse data stream...
\n
"
,
mouse
->
dev
.
name
,
mouse
->
dev
.
phys
);
vsxxxaa_drop_bytes
(
mouse
,
1
);
}
/*
* Check for packets we know about.
*/
if
(
vsxxxaa_smells_like_packet
(
mouse
,
VSXXXAA_PACKET_REL
,
3
))
{
/* Check for broken packet */
stray_bytes
=
vsxxxaa_check_packet
(
mouse
,
3
);
if
(
stray_bytes
>
0
)
{
printk
(
KERN_ERR
"Dropping %d bytes now...
\n
"
,
stray_bytes
);
vsxxxaa_drop_bytes
(
mouse
,
stray_bytes
);
continue
;
}
vsxxxaa_handle_REL_packet
(
mouse
,
regs
);
continue
;
/* More to parse? */
}
if
(
vsxxxaa_smells_like_packet
(
mouse
,
VSXXXAA_PACKET_ABS
,
5
))
{
/* Check for broken packet */
stray_bytes
=
vsxxxaa_check_packet
(
mouse
,
5
);
if
(
stray_bytes
>
0
)
{
printk
(
KERN_ERR
"Dropping %d bytes now...
\n
"
,
stray_bytes
);
vsxxxaa_drop_bytes
(
mouse
,
stray_bytes
);
continue
;
}
vsxxxaa_handle_ABS_packet
(
mouse
,
regs
);
continue
;
/* More to parse? */
}
if
(
vsxxxaa_smells_like_packet
(
mouse
,
VSXXXAA_PACKET_POR
,
4
))
{
/* Check for broken packet */
stray_bytes
=
vsxxxaa_check_packet
(
mouse
,
4
);
if
(
stray_bytes
>
0
)
{
printk
(
KERN_ERR
"Dropping %d bytes now...
\n
"
,
stray_bytes
);
vsxxxaa_drop_bytes
(
mouse
,
stray_bytes
);
continue
;
}
vsxxxaa_handle_POR_packet
(
mouse
,
regs
);
continue
;
/* More to parse? */
}
break
;
/* No REL, ABS or POR packet found */
}
while
(
1
);
}
static
irqreturn_t
vsxxxaa_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
)
{
struct
vsxxxaa
*
mouse
=
serio
->
private
;
vsxxxaa_queue_byte
(
mouse
,
data
);
vsxxxaa_parse_buffer
(
mouse
,
regs
);
return
IRQ_HANDLED
;
}
static
void
vsxxxaa_disconnect
(
struct
serio
*
serio
)
{
struct
vsxxxaa
*
mouse
=
serio
->
private
;
input_unregister_device
(
&
mouse
->
dev
);
serio_close
(
serio
);
kfree
(
mouse
);
}
static
void
vsxxxaa_connect
(
struct
serio
*
serio
,
struct
serio_dev
*
dev
)
{
struct
vsxxxaa
*
mouse
;
if
((
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_RS232
)
return
;
if
((
serio
->
type
&
SERIO_PROTO
)
!=
SERIO_VSXXXAA
)
return
;
if
(
!
(
mouse
=
kmalloc
(
sizeof
(
struct
vsxxxaa
),
GFP_KERNEL
)))
return
;
memset
(
mouse
,
0
,
sizeof
(
struct
vsxxxaa
));
init_input_dev
(
&
mouse
->
dev
);
set_bit
(
EV_KEY
,
mouse
->
dev
.
evbit
);
/* We have buttons */
set_bit
(
EV_REL
,
mouse
->
dev
.
evbit
);
/* We can move */
set_bit
(
BTN_LEFT
,
mouse
->
dev
.
keybit
);
/* We have 3 buttons */
set_bit
(
BTN_MIDDLE
,
mouse
->
dev
.
keybit
);
set_bit
(
BTN_RIGHT
,
mouse
->
dev
.
keybit
);
set_bit
(
BTN_EXTRA
,
mouse
->
dev
.
keybit
);
/* ...and Tablet */
set_bit
(
REL_X
,
mouse
->
dev
.
relbit
);
/* We can move in */
set_bit
(
REL_Y
,
mouse
->
dev
.
relbit
);
/* two dimensions */
set_bit
(
ABS_X
,
mouse
->
dev
.
absbit
);
/* DEC tablet support */
set_bit
(
ABS_Y
,
mouse
->
dev
.
absbit
);
mouse
->
dev
.
absmin
[
ABS_X
]
=
0
;
mouse
->
dev
.
absmax
[
ABS_X
]
=
1023
;
mouse
->
dev
.
absmin
[
ABS_Y
]
=
0
;
mouse
->
dev
.
absmax
[
ABS_Y
]
=
1023
;
mouse
->
dev
.
private
=
mouse
;
serio
->
private
=
mouse
;
sprintf
(
mouse
->
phys
,
"%s/input0"
,
serio
->
phys
);
mouse
->
dev
.
phys
=
mouse
->
phys
;
mouse
->
dev
.
name
=
"DEC VSXXX-AA/GA mouse or DEC tablet"
;
mouse
->
dev
.
id
.
bustype
=
BUS_RS232
;
mouse
->
serio
=
serio
;
if
(
serio_open
(
serio
,
dev
))
{
kfree
(
mouse
);
return
;
}
/*
* Request selftest and differential stream mode.
*/
mouse
->
serio
->
write
(
mouse
->
serio
,
'T'
);
/* Test */
mouse
->
serio
->
write
(
mouse
->
serio
,
'R'
);
/* Differential stream */
input_register_device
(
&
mouse
->
dev
);
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
mouse
->
dev
.
name
,
serio
->
phys
);
}
static
struct
serio_dev
vsxxxaa_dev
=
{
.
interrupt
=
vsxxxaa_interrupt
,
.
connect
=
vsxxxaa_connect
,
.
disconnect
=
vsxxxaa_disconnect
};
int
__init
vsxxxaa_init
(
void
)
{
serio_register_device
(
&
vsxxxaa_dev
);
return
0
;
}
void
__exit
vsxxxaa_exit
(
void
)
{
serio_unregister_device
(
&
vsxxxaa_dev
);
}
module_init
(
vsxxxaa_init
);
module_exit
(
vsxxxaa_exit
);
drivers/input/serio/Kconfig
View file @
be7b8193
...
...
@@ -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 @
be7b8193
...
...
@@ -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 @
be7b8193
/*
* 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/input/serio/i8042-io.h
View file @
be7b8193
...
...
@@ -25,6 +25,9 @@
#elif defined(__ia64__)
# define I8042_KBD_IRQ isa_irq_to_vector(1)
# define I8042_AUX_IRQ isa_irq_to_vector(12)
#elif defined(__arm__)
/* defined in include/asm-arm/arch-xxx/irqs.h */
#include <asm/irq.h>
#else
# define I8042_KBD_IRQ 1
# define I8042_AUX_IRQ 12
...
...
drivers/input/serio/i8042.c
View file @
be7b8193
...
...
@@ -52,6 +52,13 @@ static unsigned int i8042_dumbkbd;
module_param_named
(
dumbkbd
,
i8042_dumbkbd
,
bool
,
0
);
MODULE_PARM_DESC
(
dumbkbd
,
"Pretend that controller can only read data from keyboard"
);
__obsolete_setup
(
"i8042_noaux"
);
__obsolete_setup
(
"i8042_nomux"
);
__obsolete_setup
(
"i8042_unlock"
);
__obsolete_setup
(
"i8042_reset"
);
__obsolete_setup
(
"i8042_direct"
);
__obsolete_setup
(
"i8042_dumbkbd"
);
#undef DEBUG
#include "i8042.h"
...
...
@@ -379,6 +386,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned
int
dfl
;
int
ret
;
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
spin_lock_irqsave
(
&
i8042_lock
,
flags
);
str
=
i8042_read_status
();
if
(
str
&
I8042_STR_OBF
)
...
...
@@ -433,7 +442,6 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
irq_ret:
ret
=
1
;
out:
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
return
IRQ_RETVAL
(
ret
);
}
...
...
@@ -523,6 +531,11 @@ static int __init i8042_check_mux(struct i8042_values *values)
if
(
i8042_enable_mux_mode
(
values
,
&
mux_version
))
return
-
1
;
/* Workaround for broken chips which seem to support MUX, but in reality don't. */
/* They all report version 12.10 */
if
(
mux_version
==
0xCA
)
return
-
1
;
printk
(
KERN_INFO
"i8042.c: Detected active multiplexing controller, rev %d.%d.
\n
"
,
(
mux_version
>>
4
)
&
0xf
,
mux_version
&
0xf
);
...
...
@@ -708,14 +721,6 @@ static int i8042_controller_init(void)
printk
(
KERN_WARNING
"i8042.c: Warning: Keylock active.
\n
"
);
}
/*
* If the chip is configured into nontranslated mode by the BIOS, don't
* bother enabling translating and be happy.
*/
if
(
~
i8042_ctr
&
I8042_CTR_XLATE
)
i8042_direct
=
1
;
/*
* Set nontranslated mode for the kbd interface if requested by an option.
* After this the kbd interface becomes a simple serial in/out, like the aux
...
...
drivers/input/serio/serio.c
View file @
be7b8193
...
...
@@ -195,6 +195,9 @@ irqreturn_t serio_interrupt(struct serio *serio,
ret
=
serio
->
dev
->
interrupt
(
serio
,
data
,
flags
,
regs
);
}
else
{
if
(
!
flags
)
{
if
((
serio
->
type
==
SERIO_8042
||
serio
->
type
==
SERIO_8042_XL
)
&&
(
data
!=
0xaa
))
return
ret
;
serio_rescan
(
serio
);
ret
=
IRQ_HANDLED
;
}
...
...
drivers/usb/input/hid-core.c
View file @
be7b8193
...
...
@@ -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
;
...
...
@@ -1069,24 +1076,41 @@ static int hid_submit_ctrl(struct hid_device *hid)
{
struct
hid_report
*
report
;
unsigned
char
dir
;
int
len
;
report
=
hid
->
ctrl
[
hid
->
ctrltail
].
report
;
dir
=
hid
->
ctrl
[
hid
->
ctrltail
].
dir
;
if
(
dir
==
USB_DIR_OUT
)
len
=
((
report
->
size
-
1
)
>>
3
)
+
1
+
(
report
->
id
>
0
);
if
(
dir
==
USB_DIR_OUT
)
{
hid_output_report
(
report
,
hid
->
ctrlbuf
);
hid
->
urbctrl
->
transfer_buffer_length
=
((
report
->
size
-
1
)
>>
3
)
+
1
+
(
report
->
id
>
0
);
hid
->
urbctrl
->
pipe
=
(
dir
==
USB_DIR_OUT
)
?
usb_sndctrlpipe
(
hid
->
dev
,
0
)
:
usb_rcvctrlpipe
(
hid
->
dev
,
0
);
hid
->
urbctrl
->
pipe
=
usb_sndctrlpipe
(
hid
->
dev
,
0
);
hid
->
urbctrl
->
transfer_buffer_length
=
len
;
}
else
{
int
maxpacket
,
padlen
;
hid
->
urbctrl
->
pipe
=
usb_rcvctrlpipe
(
hid
->
dev
,
0
);
maxpacket
=
usb_maxpacket
(
hid
->
dev
,
hid
->
urbctrl
->
pipe
,
0
);
if
(
maxpacket
>
0
)
{
padlen
=
(
len
+
maxpacket
-
1
)
/
maxpacket
;
padlen
*=
maxpacket
;
if
(
padlen
>
HID_BUFFER_SIZE
)
padlen
=
HID_BUFFER_SIZE
;
}
else
padlen
=
0
;
hid
->
urbctrl
->
transfer_buffer_length
=
padlen
;
}
hid
->
urbctrl
->
dev
=
hid
->
dev
;
hid
->
cr
->
bRequestType
=
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
|
dir
;
hid
->
cr
->
bRequest
=
(
dir
==
USB_DIR_OUT
)
?
HID_REQ_SET_REPORT
:
HID_REQ_GET_REPORT
;
hid
->
cr
->
wValue
=
cpu_to_le16
(((
report
->
type
+
1
)
<<
8
)
|
report
->
id
);
hid
->
cr
->
wIndex
=
cpu_to_le16
(
hid
->
ifnum
);
hid
->
cr
->
wLength
=
cpu_to_le16
(
hid
->
urbctrl
->
transfer_buffer_length
);
hid
->
cr
->
wLength
=
cpu_to_le16
(
len
);
dbg
(
"submitting ctrl urb"
);
dbg
(
"submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u"
,
hid
->
cr
->
bRequest
==
HID_REQ_SET_REPORT
?
"Set_Report"
:
"Get_Report"
,
hid
->
cr
->
wValue
,
hid
->
cr
->
wIndex
,
hid
->
cr
->
wLength
);
if
(
usb_submit_urb
(
hid
->
urbctrl
,
GFP_ATOMIC
))
{
err
(
"usb_submit_urb(ctrl) failed"
);
...
...
@@ -1262,9 +1286,25 @@ void hid_init_reports(struct hid_device *hid)
struct
hid_report_enum
*
report_enum
;
struct
hid_report
*
report
;
struct
list_head
*
list
;
int
len
;
int
err
,
ret
;
/*
* The Set_Idle request is supposed to affect only the
* "Interrupt In" pipe. Unfortunately, buggy devices such as
* the BTC keyboard (ID 046e:5303) the request also affects
* Get_Report requests on the control pipe. In the worst
* case, if the device was put on idle for an indefinite
* amount of time (as we do below) and there are no input
* events to report, the Get_Report requests will just hang
* until we get a USB timeout. To avoid this, we temporarily
* establish a minimal idle time of 1ms. This shouldn't hurt
* bugfree devices and will cause a worst-case extra delay of
* 1ms for buggy ones.
*/
usb_control_msg
(
hid
->
dev
,
usb_sndctrlpipe
(
hid
->
dev
,
0
),
HID_REQ_SET_IDLE
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
(
1
<<
8
),
hid
->
ifnum
,
NULL
,
0
,
HZ
*
USB_CTRL_SET_TIMEOUT
);
report_enum
=
hid
->
report_enum
+
HID_INPUT_REPORT
;
list
=
report_enum
->
report_list
.
next
;
while
(
list
!=
&
report_enum
->
report_list
)
{
...
...
@@ -1297,11 +1337,8 @@ void hid_init_reports(struct hid_device *hid)
list
=
report_enum
->
report_list
.
next
;
while
(
list
!=
&
report_enum
->
report_list
)
{
report
=
(
struct
hid_report
*
)
list
;
len
=
((
report
->
size
-
1
)
>>
3
)
+
1
+
report_enum
->
numbered
;
if
(
len
>
hid
->
urbin
->
transfer_buffer_length
)
hid
->
urbin
->
transfer_buffer_length
=
len
<
HID_BUFFER_SIZE
?
len
:
HID_BUFFER_SIZE
;
usb_control_msg
(
hid
->
dev
,
usb_sndctrlpipe
(
hid
->
dev
,
0
),
0x0a
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
report
->
id
,
HID_REQ_SET_IDLE
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
report
->
id
,
hid
->
ifnum
,
NULL
,
0
,
HZ
*
USB_CTRL_SET_TIMEOUT
);
list
=
list
->
next
;
}
...
...
@@ -1313,11 +1350,12 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_WACOM_INTUOS 0x0020
#define USB_DEVICE_ID_WACOM_PL 0x0030
#define USB_DEVICE_ID_WACOM_INTUOS2 0x0040
#define USB_DEVICE_ID_WACOM_VOLITO 0x0060
#define USB_DEVICE_ID_WACOM_PTU 0x0003
#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
...
...
@@ -1356,22 +1394,52 @@ 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
#define USB_VENDOR_ID_NEC 0x073e
#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
#define USB_VENDOR_ID_CHIC 0x05fe
#define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014
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
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_GRAPHIRE
+
2
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_GRAPHIRE
+
3
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_GRAPHIRE
+
4
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_INTUOS
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_INTUOS
+
1
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_INTUOS
+
2
,
HID_QUIRK_IGNORE
},
...
...
@@ -1383,37 +1451,34 @@ struct hid_blacklist {
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_PL
+
3
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_PL
+
4
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_PL
+
5
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_INTUOS2
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_INTUOS2
+
1
,
HID_QUIRK_IGNORE
},
{
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_WACOM
,
USB_DEVICE_ID_WACOM_INTUOS2
+
5
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_INTUOS2
+
7
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_VOLITO
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_WACOM
,
USB_DEVICE_ID_WACOM_PTU
,
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_A4TECH
,
USB_DEVICE_ID_A4TECH_WCP32PU
,
HID_QUIRK_2WHEEL_MOUSE_HACK_BACK
},
{
USB_VENDOR_ID_CYPRESS
,
USB_DEVICE_ID_CYPRESS_MOUSE
,
HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA
},
{
USB_VENDOR_ID_ALPS
,
USB_DEVICE_ID_IBM_GAMEPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_CHIC
,
USB_DEVICE_ID_CHIC_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_NEC
,
USB_DEVICE_ID_NEC_USB_GAME_PAD
,
HID_QUIRK_BADPAD
},
{
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
}
};
...
...
@@ -1518,12 +1583,17 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
continue
;
if
(
endpoint
->
bEndpointAddress
&
USB_DIR_IN
)
{
int
len
;
if
(
hid
->
urbin
)
continue
;
if
(
!
(
hid
->
urbin
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
goto
fail
;
pipe
=
usb_rcvintpipe
(
dev
,
endpoint
->
bEndpointAddress
);
usb_fill_int_urb
(
hid
->
urbin
,
dev
,
pipe
,
hid
->
inbuf
,
0
,
len
=
usb_maxpacket
(
dev
,
pipe
,
0
);
if
(
len
>
HID_BUFFER_SIZE
)
len
=
HID_BUFFER_SIZE
;
usb_fill_int_urb
(
hid
->
urbin
,
dev
,
pipe
,
hid
->
inbuf
,
len
,
hid_irq_in
,
hid
,
endpoint
->
bInterval
);
hid
->
urbin
->
transfer_dma
=
hid
->
inbuf_dma
;
hid
->
urbin
->
transfer_flags
|=
URB_NO_TRANSFER_DMA_MAP
;
...
...
drivers/usb/input/hid-ff.c
View file @
be7b8193
...
...
@@ -29,7 +29,7 @@
#include <linux/input.h>
#
define
DEBUG
#
undef
DEBUG
#include <linux/usb.h>
#include "hid.h"
...
...
drivers/usb/input/hid-input.c
View file @
be7b8193
...
...
@@ -377,7 +377,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
set_bit
(
usage
->
type
,
input
->
evbit
);
if
((
usage
->
type
==
EV_REL
)
&&
(
device
->
quirks
&
HID_QUIRK_2WHEEL_MOUSE_HACK
)
&&
(
device
->
quirks
&
(
HID_QUIRK_2WHEEL_MOUSE_HACK_BACK
|
HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA
))
&&
(
usage
->
code
==
REL_WHEEL
))
{
set_bit
(
REL_HWHEEL
,
bit
);
}
...
...
@@ -431,21 +432,22 @@ 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
))
{
if
((
(
hid
->
quirks
&
HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA
)
&&
(
usage
->
code
==
BTN_EXTRA
)
)
||
((
hid
->
quirks
&
HID_QUIRK_2WHEEL_MOUSE_HACK_BACK
)
&&
(
usage
->
code
==
BTN_BACK
)
))
{
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 +486,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
);
...
...
@@ -567,8 +569,10 @@ int hidinput_connect(struct hid_device *hid)
while
(
list
!=
&
report_enum
->
report_list
)
{
report
=
(
struct
hid_report
*
)
list
;
if
(
!
report
->
maxfield
)
if
(
!
report
->
maxfield
)
{
list
=
list
->
next
;
continue
;
}
if
(
!
hidinput
)
{
hidinput
=
kmalloc
(
sizeof
(
*
hidinput
),
GFP_KERNEL
);
...
...
drivers/usb/input/hid.h
View file @
be7b8193
...
...
@@ -208,8 +208,9 @@ struct hid_item {
#define HID_QUIRK_HIDDEV 0x010
#define HID_QUIRK_BADPAD 0x020
#define HID_QUIRK_MULTI_INPUT 0x040
#define HID_QUIRK_2WHEEL_MOUSE_HACK 0x080
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_BACK 0x080
#define HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA 0x100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200
/*
* This is the global environment of the parser. This information is
...
...
@@ -309,7 +310,7 @@ struct hid_report_enum {
#define HID_REPORT_TYPES 3
#define HID_BUFFER_SIZE
32
#define HID_BUFFER_SIZE
64
/* use 64 for compatibility with all possible packetlen */
#define HID_CONTROL_FIFO_SIZE 256
/* to init devices with >100 reports */
#define HID_OUTPUT_FIFO_SIZE 64
...
...
drivers/usb/input/hiddev.c
View file @
be7b8193
...
...
@@ -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
;
...
...
drivers/usb/input/wacom.c
View file @
be7b8193
/*
* USB Wacom Graphire and Wacom Intuos tablet support
*
* Copyright (c) 2000-200
2
Vojtech Pavlik <vojtech@ucw.cz>
* Copyright (c) 2000-200
4
Vojtech Pavlik <vojtech@ucw.cz>
* Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk>
* Copyright (c) 2000 Clifford Wolf <clifford@clifford.at>
* Copyright (c) 2000 Sam Mosel <sam.mosel@computer.org>
* Copyright (c) 2000 James E. Blair <corvus@gnu.org>
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2002 Ping Cheng <pingc@wacom.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
* Copyright (c) 2002-2004 Ping Cheng <pingc@wacom.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
...
...
@@ -48,6 +49,8 @@
* v1.30 (vp) - Merge 2.4 and 2.5 drivers
* - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
* - Cleanups here and there
* v1.30.1 (pi) - Added Graphire3 support
* v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
*/
/*
...
...
@@ -137,14 +140,12 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
}
if
(
data
[
0
]
!=
2
)
dbg
(
"received unknown report #%d"
,
data
[
0
]);
dbg
(
"
wacom_pl_irq:
received unknown report #%d"
,
data
[
0
]);
prox
=
data
[
1
]
&
0x40
;
input_regs
(
dev
,
regs
);
input_report_key
(
dev
,
BTN_TOOL_PEN
,
prox
);
if
(
prox
)
{
pressure
=
(
signed
char
)((
data
[
7
]
<<
1
)
|
((
data
[
4
]
>>
2
)
&
1
));
...
...
@@ -152,15 +153,103 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
pressure
=
(
pressure
<<
1
)
|
((
data
[
4
]
>>
6
)
&
1
);
pressure
+=
(
wacom
->
features
->
pressure_max
+
1
)
/
2
;
/*
* if going from out of proximity into proximity select between the eraser
* and the pen based on the state of the stylus2 button, choose eraser if
* pressed else choose pen. if not a proximity change from out to in, send
* an out of proximity for previous tool then a in for new tool.
*/
if
(
!
wacom
->
tool
[
0
])
{
/* Going into proximity select tool */
wacom
->
tool
[
1
]
=
(
data
[
4
]
&
0x20
)
?
BTN_TOOL_RUBBER
:
BTN_TOOL_PEN
;
}
else
{
/* was entered with stylus2 pressed */
if
(
wacom
->
tool
[
1
]
==
BTN_TOOL_RUBBER
&&
!
(
data
[
4
]
&
0x20
)
)
{
/* report out proximity for previous tool */
input_report_key
(
dev
,
wacom
->
tool
[
1
],
0
);
input_sync
(
dev
);
wacom
->
tool
[
1
]
=
BTN_TOOL_PEN
;
goto
exit
;
}
}
if
(
wacom
->
tool
[
1
]
!=
BTN_TOOL_RUBBER
)
{
/* Unknown tool selected default to pen tool */
wacom
->
tool
[
1
]
=
BTN_TOOL_PEN
;
}
input_report_key
(
dev
,
wacom
->
tool
[
1
],
prox
);
/* report in proximity for tool */
input_report_abs
(
dev
,
ABS_X
,
data
[
3
]
|
((
__u32
)
data
[
2
]
<<
7
)
|
((
__u32
)(
data
[
1
]
&
0x03
)
<<
14
));
input_report_abs
(
dev
,
ABS_Y
,
data
[
6
]
|
((
__u32
)
data
[
5
]
<<
7
)
|
((
__u32
)(
data
[
4
]
&
0x03
)
<<
14
));
input_report_abs
(
dev
,
ABS_PRESSURE
,
pressure
);
input_report_key
(
dev
,
BTN_TOUCH
,
data
[
4
]
&
0x08
);
input_report_key
(
dev
,
BTN_STYLUS
,
data
[
4
]
&
0x10
);
input_report_key
(
dev
,
BTN_STYLUS2
,
data
[
4
]
&
0x20
);
/* Only allow the stylus2 button to be reported for the pen tool. */
input_report_key
(
dev
,
BTN_STYLUS2
,
(
wacom
->
tool
[
1
]
==
BTN_TOOL_PEN
)
&&
(
data
[
4
]
&
0x20
));
}
else
{
/* report proximity-out of a (valid) tool */
if
(
wacom
->
tool
[
1
]
!=
BTN_TOOL_RUBBER
)
{
/* Unknown tool selected default to pen tool */
wacom
->
tool
[
1
]
=
BTN_TOOL_PEN
;
}
input_report_key
(
dev
,
wacom
->
tool
[
1
],
prox
);
}
wacom
->
tool
[
0
]
=
prox
;
/* Save proximity state */
input_sync
(
dev
);
exit:
retval
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
if
(
retval
)
err
(
"%s - usb_submit_urb failed with result %d"
,
__FUNCTION__
,
retval
);
}
static
void
wacom_ptu_irq
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
struct
wacom
*
wacom
=
urb
->
context
;
unsigned
char
*
data
=
wacom
->
data
;
struct
input_dev
*
dev
=
&
wacom
->
dev
;
int
retval
;
switch
(
urb
->
status
)
{
case
0
:
/* success */
break
;
case
-
ECONNRESET
:
case
-
ENOENT
:
case
-
ESHUTDOWN
:
/* this urb is terminated, clean up */
dbg
(
"%s - urb shutting down with status: %d"
,
__FUNCTION__
,
urb
->
status
);
return
;
default:
dbg
(
"%s - nonzero urb status received: %d"
,
__FUNCTION__
,
urb
->
status
);
goto
exit
;
}
if
(
data
[
0
]
!=
2
)
{
printk
(
KERN_INFO
"wacom_ptu_irq: received unknown report #%d
\n
"
,
data
[
0
]);
}
input_regs
(
dev
,
regs
);
if
(
data
[
1
]
&
0x04
)
{
input_report_key
(
dev
,
BTN_TOOL_RUBBER
,
data
[
1
]
&
0x20
);
input_report_key
(
dev
,
BTN_TOUCH
,
data
[
1
]
&
0x08
);
}
else
{
input_report_key
(
dev
,
BTN_TOOL_PEN
,
data
[
1
]
&
0x20
);
input_report_key
(
dev
,
BTN_TOUCH
,
data
[
1
]
&
0x01
);
}
input_report_abs
(
dev
,
ABS_X
,
data
[
3
]
<<
8
|
data
[
2
]);
input_report_abs
(
dev
,
ABS_Y
,
data
[
5
]
<<
8
|
data
[
4
]);
input_report_abs
(
dev
,
ABS_PRESSURE
,
(
data
[
6
]
|
data
[
7
]
<<
8
));
input_report_key
(
dev
,
BTN_STYLUS
,
data
[
1
]
&
0x02
);
input_report_key
(
dev
,
BTN_STYLUS2
,
data
[
1
]
&
0x10
);
input_sync
(
dev
);
exit:
...
...
@@ -231,8 +320,12 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
goto
exit
;
}
/* check if we can handle the data */
if
(
data
[
0
]
==
99
)
goto
exit
;
if
(
data
[
0
]
!=
2
)
dbg
(
"received unknown report #%d"
,
data
[
0
]);
dbg
(
"
wacom_graphire_irq:
received unknown report #%d"
,
data
[
0
]);
x
=
data
[
2
]
|
((
__u32
)
data
[
3
]
<<
8
);
y
=
data
[
4
]
|
((
__u32
)
data
[
5
]
<<
8
);
...
...
@@ -249,13 +342,16 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
input_report_key
(
dev
,
BTN_TOOL_RUBBER
,
data
[
1
]
&
0x80
);
break
;
case
2
:
/* Mouse */
case
2
:
/* Mouse with wheel */
input_report_key
(
dev
,
BTN_MIDDLE
,
data
[
1
]
&
0x04
);
input_report_rel
(
dev
,
REL_WHEEL
,
(
signed
char
)
data
[
6
]);
/* fall through */
case
3
:
/* Mouse without wheel */
input_report_key
(
dev
,
BTN_TOOL_MOUSE
,
data
[
7
]
>
24
);
input_report_key
(
dev
,
BTN_LEFT
,
data
[
1
]
&
0x01
);
input_report_key
(
dev
,
BTN_RIGHT
,
data
[
1
]
&
0x02
);
input_report_key
(
dev
,
BTN_MIDDLE
,
data
[
1
]
&
0x04
);
input_report_abs
(
dev
,
ABS_DISTANCE
,
data
[
7
]);
input_report_rel
(
dev
,
REL_WHEEL
,
(
signed
char
)
data
[
6
]);
input_report_abs
(
dev
,
ABS_X
,
x
);
input_report_abs
(
dev
,
ABS_Y
,
y
);
...
...
@@ -308,7 +404,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
}
if
(
data
[
0
]
!=
2
)
dbg
(
"received unknown report #%d"
,
data
[
0
]);
dbg
(
"
wacom_intuos_irq:
received unknown report #%d"
,
data
[
0
]);
input_regs
(
dev
,
regs
);
...
...
@@ -317,18 +413,18 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
if
((
data
[
1
]
&
0xfc
)
==
0xc0
)
{
/* Enter report */
wacom
->
serial
[
idx
]
=
((
__u32
)(
data
[
3
]
&
0x0f
)
<<
4
)
+
/* serial number of the tool */
((
__u32
)
data
[
4
]
<<
16
)
+
((
__u32
)
data
[
5
]
<<
12
)
+
wacom
->
serial
[
idx
]
=
((
__u32
)(
data
[
3
]
&
0x0f
)
<<
28
)
+
/* serial number of the tool */
((
__u32
)
data
[
4
]
<<
20
)
+
((
__u32
)
data
[
5
]
<<
12
)
+
((
__u32
)
data
[
6
]
<<
4
)
+
(
data
[
7
]
>>
4
);
switch
(((
__u32
)
data
[
2
]
<<
4
)
|
(
data
[
3
]
>>
4
))
{
case
0x8
3
2
:
case
0x8
1
2
:
case
0x012
:
wacom
->
tool
[
idx
]
=
BTN_TOOL_PENCIL
;
break
;
/* Inking pen */
case
0x822
:
case
0x842
:
case
0x852
:
case
0x022
:
wacom
->
tool
[
idx
]
=
BTN_TOOL_PEN
;
break
;
/* Pen */
case
0x8
1
2
:
case
0x8
3
2
:
case
0x032
:
wacom
->
tool
[
idx
]
=
BTN_TOOL_BRUSH
;
break
;
/* Stroke pen */
case
0x007
:
case
0x09c
:
...
...
@@ -337,7 +433,10 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
case
0x82a
:
case
0x85a
:
case
0x91a
:
case
0xd1a
:
case
0x0fa
:
wacom
->
tool
[
idx
]
=
BTN_TOOL_RUBBER
;
break
;
/* Eraser */
case
0xd12
:
case
0x912
:
case
0x112
:
wacom
->
tool
[
idx
]
=
BTN_TOOL_AIRBRUSH
;
break
;
/* Airbrush */
default:
wacom
->
tool
[
idx
]
=
BTN_TOOL_PEN
;
break
;
/* Unknown tool */
}
...
...
@@ -350,13 +449,14 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
if
((
data
[
1
]
&
0xfe
)
==
0x80
)
{
/* Exit report */
input_report_key
(
dev
,
wacom
->
tool
[
idx
],
0
);
input_event
(
dev
,
EV_MSC
,
MSC_SERIAL
,
wacom
->
serial
[
idx
]);
input_sync
(
dev
);
goto
exit
;
}
input_report_abs
(
dev
,
ABS_X
,
((
__u32
)
data
[
2
]
<<
8
)
|
data
[
3
]);
input_report_abs
(
dev
,
ABS_Y
,
((
__u32
)
data
[
4
]
<<
8
)
|
data
[
5
]);
input_report_abs
(
dev
,
ABS_DISTANCE
,
data
[
9
]
>>
4
);
input_report_abs
(
dev
,
ABS_DISTANCE
,
data
[
9
]);
if
((
data
[
1
]
&
0xb8
)
==
0xa0
)
{
/* general pen packet */
input_report_abs
(
dev
,
ABS_PRESSURE
,
t
=
((
__u32
)
data
[
6
]
<<
2
)
|
((
data
[
7
]
>>
6
)
&
3
));
...
...
@@ -378,8 +478,8 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
if
(
data
[
1
]
&
0x02
)
{
/* Rotation packet */
input_report_abs
(
dev
,
ABS_RZ
,
(
data
[
7
]
&
0x20
)
?
((
__u32
)
data
[
6
]
<<
2
)
|
((
data
[
7
]
>>
6
)
&
3
)
:
(
-
(((
__u32
)
data
[
6
]
<<
2
)
|
((
data
[
7
]
>>
6
)
&
3
)))
-
1
);
((
__u32
)
data
[
6
]
<<
3
)
|
((
data
[
7
]
>>
5
)
&
7
)
:
(
-
(((
__u32
)
data
[
6
]
<<
3
)
|
((
data
[
7
]
>>
5
)
&
7
)))
-
1
);
}
else
{
...
...
@@ -391,17 +491,17 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
input_report_key
(
dev
,
BTN_SIDE
,
data
[
8
]
&
0x20
);
input_report_key
(
dev
,
BTN_EXTRA
,
data
[
8
]
&
0x10
);
input_report_abs
(
dev
,
ABS_THROTTLE
,
(
data
[
8
]
&
0x08
)
?
input_report_abs
(
dev
,
ABS_THROTTLE
,
-
(
(
data
[
8
]
&
0x08
)
?
((
__u32
)
data
[
6
]
<<
2
)
|
((
data
[
7
]
>>
6
)
&
3
)
:
-
((
__u32
)
data
[
6
]
<<
2
)
|
((
data
[
7
]
>>
6
)
&
3
));
-
((
__u32
)
data
[
6
]
<<
2
)
|
((
data
[
7
]
>>
6
)
&
3
))
)
;
}
else
{
if
(
wacom
->
tool
[
idx
]
==
BTN_TOOL_MOUSE
)
{
/* 2D mouse packets */
input_report_key
(
dev
,
BTN_LEFT
,
data
[
8
]
&
0x04
);
input_report_key
(
dev
,
BTN_MIDDLE
,
data
[
8
]
&
0x08
);
input_report_key
(
dev
,
BTN_RIGHT
,
data
[
8
]
&
0x10
);
input_report_
abs
(
dev
,
REL_WHEEL
,
(
(
__u32
)(
data
[
8
]
&
0x01
)
-
(
__u32
)((
data
[
8
]
&
0x02
)
>>
1
)));
input_report_
rel
(
dev
,
REL_WHEEL
,
(
-
(
__u32
)(
data
[
8
]
&
0x01
)
+
(
__u32
)((
data
[
8
]
&
0x02
)
>>
1
)));
}
else
{
/* Lens cursor packets */
input_report_key
(
dev
,
BTN_LEFT
,
data
[
8
]
&
0x01
);
...
...
@@ -414,6 +514,8 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
}
}
input_report_key
(
dev
,
wacom
->
tool
[
idx
],
1
);
input_event
(
dev
,
EV_MSC
,
MSC_SERIAL
,
wacom
->
serial
[
idx
]);
input_sync
(
dev
);
exit:
...
...
@@ -429,22 +531,26 @@ struct wacom_features wacom_features[] = {
{
"Wacom Graphire2 4x5"
,
8
,
10206
,
7422
,
511
,
32
,
1
,
wacom_graphire_irq
},
{
"Wacom Graphire2 5x7"
,
8
,
13918
,
10206
,
511
,
32
,
1
,
wacom_graphire_irq
},
{
"Wacom Graphire3"
,
8
,
10208
,
7424
,
511
,
32
,
1
,
wacom_graphire_irq
},
{
"Wacom Intuos 4x5"
,
10
,
12700
,
10360
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos 6x8"
,
10
,
20600
,
16450
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos 9x12"
,
10
,
30670
,
24130
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos 12x12"
,
10
,
30670
,
31040
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos 12x18"
,
10
,
45860
,
31040
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Graphire3 6x8"
,
8
,
16704
,
12064
,
511
,
32
,
1
,
wacom_graphire_irq
},
{
"Wacom Intuos 4x5"
,
10
,
12700
,
10600
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos 6x8"
,
10
,
20320
,
16240
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos 9x12"
,
10
,
30480
,
24060
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos 12x12"
,
10
,
30480
,
31680
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos 12x18"
,
10
,
45720
,
31680
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom PL400"
,
8
,
5408
,
4056
,
255
,
32
,
3
,
wacom_pl_irq
},
{
"Wacom PL500"
,
8
,
6144
,
4608
,
255
,
32
,
3
,
wacom_pl_irq
},
{
"Wacom PL600"
,
8
,
6126
,
4604
,
255
,
32
,
3
,
wacom_pl_irq
},
{
"Wacom PL600SX"
,
8
,
6260
,
5016
,
255
,
32
,
3
,
wacom_pl_irq
},
{
"Wacom PL550"
,
8
,
6144
,
4608
,
511
,
32
,
3
,
wacom_pl_irq
},
{
"Wacom PL800"
,
8
,
7220
,
5780
,
511
,
32
,
3
,
wacom_pl_irq
},
{
"Wacom Intuos2 4x5"
,
10
,
12700
,
10360
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos2 6x8"
,
10
,
20600
,
16450
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos2 9x12"
,
10
,
30670
,
24130
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos2 12x12"
,
10
,
30670
,
31040
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos2 12x18"
,
10
,
45860
,
31040
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos2 4x5"
,
10
,
12700
,
10600
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos2 6x8"
,
10
,
20320
,
16240
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos2 9x12"
,
10
,
30480
,
24060
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos2 12x12"
,
10
,
30480
,
31680
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Intuos2 12x18"
,
10
,
45720
,
31680
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
"Wacom Volito"
,
8
,
5104
,
3712
,
511
,
32
,
1
,
wacom_graphire_irq
},
{
"Wacom Cintiq Partner"
,
8
,
20480
,
15360
,
511
,
32
,
3
,
wacom_ptu_irq
},
{
"Wacom Intuos2 6x8"
,
10
,
20320
,
16240
,
1023
,
15
,
2
,
wacom_intuos_irq
},
{
}
};
...
...
@@ -454,6 +560,7 @@ struct usb_device_id wacom_ids[] = {
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x11
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x12
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x13
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x14
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x20
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x21
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x22
)
},
...
...
@@ -470,6 +577,9 @@ struct usb_device_id wacom_ids[] = {
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x43
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x44
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x45
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x60
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x03
)
},
{
USB_DEVICE
(
USB_VENDOR_ID_WACOM
,
0x47
)
},
{
}
};
...
...
@@ -483,8 +593,10 @@ static int wacom_open(struct input_dev *dev)
return
0
;
wacom
->
irq
->
dev
=
wacom
->
usbdev
;
if
(
usb_submit_urb
(
wacom
->
irq
,
GFP_KERNEL
))
if
(
usb_submit_urb
(
wacom
->
irq
,
GFP_KERNEL
))
{
wacom
->
open
--
;
return
-
EIO
;
}
return
0
;
}
...
...
@@ -509,7 +621,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
return
-
ENOMEM
;
memset
(
wacom
,
0
,
sizeof
(
struct
wacom
));
wacom
->
data
=
usb_buffer_alloc
(
dev
,
10
,
SLAB_ATOMIC
,
&
wacom
->
data_dma
);
wacom
->
data
=
usb_buffer_alloc
(
dev
,
10
,
GFP_KERNEL
,
&
wacom
->
data_dma
);
if
(
!
wacom
->
data
)
{
kfree
(
wacom
);
return
-
ENOMEM
;
...
...
@@ -538,8 +650,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
break
;
case
2
:
wacom
->
dev
.
evbit
[
0
]
|=
BIT
(
EV_MSC
);
wacom
->
dev
.
evbit
[
0
]
|=
BIT
(
EV_MSC
)
|
BIT
(
EV_REL
)
;
wacom
->
dev
.
mscbit
[
0
]
|=
BIT
(
MSC_SERIAL
);
wacom
->
dev
.
relbit
[
0
]
|=
BIT
(
REL_WHEEL
);
wacom
->
dev
.
keybit
[
LONG
(
BTN_LEFT
)]
|=
BIT
(
BTN_LEFT
)
|
BIT
(
BTN_RIGHT
)
|
BIT
(
BTN_MIDDLE
)
|
BIT
(
BTN_SIDE
)
|
BIT
(
BTN_EXTRA
);
wacom
->
dev
.
keybit
[
LONG
(
BTN_DIGI
)]
|=
BIT
(
BTN_TOOL_RUBBER
)
|
BIT
(
BTN_TOOL_MOUSE
)
|
BIT
(
BTN_TOOL_BRUSH
)
|
BIT
(
BTN_TOOL_PENCIL
)
|
BIT
(
BTN_TOOL_AIRBRUSH
)
|
BIT
(
BTN_TOOL_LENS
)
|
BIT
(
BTN_STYLUS2
);
...
...
include/asm-arm/arch-ebsa285/irqs.h
View file @
be7b8193
...
...
@@ -91,8 +91,8 @@
#undef RTC_IRQ
#define RTC_IRQ IRQ_ISA_RTC_ALARM
#
undef AUX_IRQ
#define
AUX_IRQ
(machine_is_netwinder() ? IRQ_NETWINDER_PS2MOUSE : IRQ_ISA_PS2MOUSE)
#
define I8042_KBD_IRQ IRQ_ISA_KEYBOARD
#define
I8042_AUX_IRQ
(machine_is_netwinder() ? IRQ_NETWINDER_PS2MOUSE : IRQ_ISA_PS2MOUSE)
#define IRQ_FLOPPYDISK IRQ_ISA_FLOPPY
#define irq_canonicalize(_i) (((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA_2 : _i)
include/asm-arm/arch-shark/irqs.h
View file @
be7b8193
...
...
@@ -8,5 +8,6 @@
#define IRQ_ISA_KEYBOARD 1
#define RTC_IRQ 8
#define AUX_IRQ 12
#define I8042_KBD_IRQ 1
#define I8042_AUX_IRQ 12
#define IRQ_HARDDISK 14
include/linux/hiddev.h
View file @
be7b8193
...
...
@@ -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
*/
...
...
include/linux/init.h
View file @
be7b8193
...
...
@@ -110,12 +110,21 @@ struct obs_kernel_param {
};
/* OBSOLETE: see moduleparam.h for the right way. */
#define __setup
(str, fn)
\
static char __setup_str_##
fn
[] __initdata = str; \
static struct obs_kernel_param __setup_##
fn
\
#define __setup
_param(str, unique_id, fn)
\
static char __setup_str_##
unique_id
[] __initdata = str; \
static struct obs_kernel_param __setup_##
unique_id
\
__attribute_used__ \
__attribute__((__section__(".init.setup"))) \
= { __setup_str_##fn, fn }
= { __setup_str_##unique_id, fn }
#define __setup_null_param(str, unique_id) \
__setup_param(str, unique_id, NULL)
#define __setup(str, fn) \
__setup_param(str, fn, fn)
#define __obsolete_setup(str) \
__setup_null_param(str, __LINE__)
#endif
/* __ASSEMBLY__ */
...
...
@@ -172,7 +181,10 @@ struct obs_kernel_param {
{ return exitfn; } \
void cleanup_module(void) __attribute__((alias(#exitfn)));
#define __setup(str,func)
/* nothing */
#define __setup_param(str, unique_id, fn)
/* nothing */
#define __setup_null_param(str, unique_id)
/* nothing */
#define __setup(str, func)
/* nothing */
#define __obsolete_setup(str)
/* nothing */
#endif
/* Data marked not to be saved by software_suspend() */
...
...
include/linux/miscdevice.h
View file @
be7b8193
...
...
@@ -3,7 +3,6 @@
#include <linux/module.h>
#include <linux/major.h>
#define BUSMOUSE_MINOR 0
#define PSMOUSE_MINOR 1
#define MS_BUSMOUSE_MINOR 2
#define ATIXL_BUSMOUSE_MINOR 3
...
...
include/linux/moduleparam.h
View file @
be7b8193
...
...
@@ -126,13 +126,16 @@ extern int param_get_invbool(char *buffer, struct kernel_param *kp);
#define param_check_invbool(name, p) __param_check(name, p, int)
/* Comma-separated array: num is set to number they actually specified. */
#define module_param_array
(name, type, num, perm)
\
#define module_param_array
_named(name, array, type, num, perm)
\
static struct kparam_array __param_arr_##name \
= { ARRAY_SIZE(
name), &num, param_set_##type, param_get_##type,
\
sizeof(
name[0]), name
}; \
= { ARRAY_SIZE(
array), &num, param_set_##type, param_get_##type,
\
sizeof(
array[0]), array
}; \
module_param_call(name, param_array_set, param_array_get, \
&__param_arr_##name, perm)
#define module_param_array(name, type, num, perm) \
module_param_array_named(name, name, type, num, perm)
extern
int
param_array_set
(
const
char
*
val
,
struct
kernel_param
*
kp
);
extern
int
param_array_get
(
char
*
buffer
,
struct
kernel_param
*
kp
);
...
...
include/linux/serio.h
View file @
be7b8193
...
...
@@ -117,6 +117,7 @@ static __inline__ void serio_cleanup(struct serio *serio)
#define SERIO_MZ 0x05
#define SERIO_MZP 0x06
#define SERIO_MZPP 0x07
#define SERIO_VSXXXAA 0x08
#define SERIO_SUNKBD 0x10
#define SERIO_WARRIOR 0x18
#define SERIO_SPACEORB 0x19
...
...
@@ -134,6 +135,7 @@ static __inline__ void serio_cleanup(struct serio *serio)
#define SERIO_HIL 0x25
#define SERIO_SNES232 0x26
#define SERIO_SEMTECH 0x27
#define SERIO_LKKBD 0x28
#define SERIO_ID 0xff00UL
#define SERIO_EXTRA 0xff0000UL
...
...
init/main.c
View file @
be7b8193
...
...
@@ -156,8 +156,11 @@ static int __init obsolete_checksetup(char *line)
p
=
&
__setup_start
;
do
{
int
n
=
strlen
(
p
->
str
);
if
(
!
strncmp
(
line
,
p
->
str
,
n
))
{
if
(
p
->
setup_func
(
line
+
n
))
if
(
!
strncmp
(
line
,
p
->
str
,
n
))
{
if
(
!
p
->
setup_func
)
{
printk
(
KERN_WARNING
"Parameter %s is obsolete, ignored
\n
"
,
p
->
str
);
return
1
;
}
else
if
(
p
->
setup_func
(
line
+
n
))
return
1
;
}
p
++
;
...
...
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