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
037d476f
Commit
037d476f
authored
Jul 07, 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
afb7238d
b9f2597e
Changes
59
Show whitespace changes
Inline
Side-by-side
Showing
59 changed files
with
2484 additions
and
1116 deletions
+2484
-1116
Documentation/input/joystick-parport.txt
Documentation/input/joystick-parport.txt
+11
-2
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+6
-0
drivers/Makefile
drivers/Makefile
+1
-1
drivers/char/keyboard.c
drivers/char/keyboard.c
+25
-8
drivers/input/gameport/emu10k1-gp.c
drivers/input/gameport/emu10k1-gp.c
+3
-0
drivers/input/joystick/Kconfig
drivers/input/joystick/Kconfig
+1
-1
drivers/input/joystick/gamecon.c
drivers/input/joystick/gamecon.c
+102
-92
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-main.c
+2
-2
drivers/input/joystick/iforce/iforce-serio.c
drivers/input/joystick/iforce/iforce-serio.c
+11
-7
drivers/input/joystick/iforce/iforce.h
drivers/input/joystick/iforce/iforce.h
+1
-1
drivers/input/joystick/magellan.c
drivers/input/joystick/magellan.c
+15
-9
drivers/input/joystick/spaceball.c
drivers/input/joystick/spaceball.c
+15
-9
drivers/input/joystick/spaceorb.c
drivers/input/joystick/spaceorb.c
+15
-9
drivers/input/joystick/stinger.c
drivers/input/joystick/stinger.c
+15
-9
drivers/input/joystick/twidjoy.c
drivers/input/joystick/twidjoy.c
+12
-8
drivers/input/joystick/warrior.c
drivers/input/joystick/warrior.c
+15
-9
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+120
-59
drivers/input/keyboard/lkkbd.c
drivers/input/keyboard/lkkbd.c
+15
-9
drivers/input/keyboard/newtonkbd.c
drivers/input/keyboard/newtonkbd.c
+15
-9
drivers/input/keyboard/sunkbd.c
drivers/input/keyboard/sunkbd.c
+15
-9
drivers/input/keyboard/xtkbd.c
drivers/input/keyboard/xtkbd.c
+15
-9
drivers/input/misc/uinput.c
drivers/input/misc/uinput.c
+3
-0
drivers/input/mouse/Kconfig
drivers/input/mouse/Kconfig
+0
-2
drivers/input/mouse/logips2pp.c
drivers/input/mouse/logips2pp.c
+1
-1
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse-base.c
+147
-89
drivers/input/mouse/psmouse.h
drivers/input/mouse/psmouse.h
+11
-13
drivers/input/mouse/sermouse.c
drivers/input/mouse/sermouse.c
+15
-9
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.c
+17
-15
drivers/input/mouse/vsxxxaa.c
drivers/input/mouse/vsxxxaa.c
+15
-9
drivers/input/mousedev.c
drivers/input/mousedev.c
+135
-55
drivers/input/serio/Kconfig
drivers/input/serio/Kconfig
+16
-0
drivers/input/serio/Makefile
drivers/input/serio/Makefile
+1
-0
drivers/input/serio/ambakmi.c
drivers/input/serio/ambakmi.c
+25
-19
drivers/input/serio/ct82c710.c
drivers/input/serio/ct82c710.c
+35
-27
drivers/input/serio/gscps2.c
drivers/input/serio/gscps2.c
+38
-24
drivers/input/serio/i8042-io.h
drivers/input/serio/i8042-io.h
+31
-0
drivers/input/serio/i8042.c
drivers/input/serio/i8042.c
+132
-108
drivers/input/serio/i8042.h
drivers/input/serio/i8042.h
+7
-0
drivers/input/serio/maceps2.c
drivers/input/serio/maceps2.c
+42
-35
drivers/input/serio/parkbd.c
drivers/input/serio/parkbd.c
+30
-17
drivers/input/serio/pcips2.c
drivers/input/serio/pcips2.c
+23
-16
drivers/input/serio/q40kbd.c
drivers/input/serio/q40kbd.c
+80
-29
drivers/input/serio/rpckbd.c
drivers/input/serio/rpckbd.c
+28
-10
drivers/input/serio/sa1111ps2.c
drivers/input/serio/sa1111ps2.c
+24
-17
drivers/input/serio/serio.c
drivers/input/serio/serio.c
+400
-119
drivers/input/serio/serio_raw.c
drivers/input/serio/serio_raw.c
+390
-0
drivers/input/serio/serport.c
drivers/input/serio/serport.c
+25
-24
drivers/input/touchscreen/gunze.c
drivers/input/touchscreen/gunze.c
+15
-9
drivers/input/touchscreen/h3600_ts_input.c
drivers/input/touchscreen/h3600_ts_input.c
+15
-9
drivers/input/tsdev.c
drivers/input/tsdev.c
+186
-105
drivers/serial/sunsu.c
drivers/serial/sunsu.c
+49
-40
drivers/serial/sunzilog.c
drivers/serial/sunzilog.c
+40
-26
drivers/usb/input/hid-core.c
drivers/usb/input/hid-core.c
+7
-2
drivers/usb/input/hiddev.c
drivers/usb/input/hiddev.c
+13
-7
fs/compat_ioctl.c
fs/compat_ioctl.c
+2
-0
include/linux/compat_ioctl.h
include/linux/compat_ioctl.h
+17
-0
include/linux/hiddev.h
include/linux/hiddev.h
+7
-1
include/linux/input.h
include/linux/input.h
+2
-0
include/linux/serio.h
include/linux/serio.h
+30
-17
No files found.
Documentation/input/joystick-parport.txt
View file @
037d476f
...
...
@@ -335,6 +335,7 @@ controller (compatible with DirectPadPro):
* Analog PSX Pad (red mode)
* Analog PSX Pad (green mode)
* PSX Rumble Pad
* PSX DDR Pad
2.4 Sega
~~~~~~~~
...
...
@@ -452,14 +453,22 @@ uses the following kernel/module command line:
5 | Multisystem 2-button joystick
6 | N64 pad
7 | Sony PSX controller
8 | Sony PSX DDR controller
The exact type of the PSX controller type is autoprobed
, so you must have
your controller plugged in before initializing
.
The exact type of the PSX controller type is autoprobed
when used so
hot swapping should work (but is not recomended)
.
Should you want to use more than one of parallel ports at once, you can use
gamecon.map2 and gamecon.map3 as additional command line parameters for two
more parallel ports.
There are two options specific to PSX driver portion. gamecon.psx_delay sets
the command delay when talking to the controllers. The default of 25 should
work but you can try lowering it for better performace. If your pads don't
respond try raising it untill they work. Setting the type to 8 allows the
driver to be used with Dance Dance Revolution or similar games. Arrow keys are
registered as key presses instead of X and Y axes.
3.2 db9.c
~~~~~~~~~
Apart from making an interface, there is nothing difficult on using the
...
...
Documentation/kernel-parameters.txt
View file @
037d476f
...
...
@@ -650,6 +650,12 @@ running once the system is up.
mga= [HW,DRM]
mousedev.tap_time=
[MOUSE] Maximum time between finger touching and
leaving touchpad surface for touch to be considered
a tap and be reported as a left button click (for
touchpads working in absolute mode only).
Format: <msecs>
mousedev.xres= [MOUSE] Horizontal screen resolution, used for devices
reporting absolute coordinates, such as tablets
mousedev.yres= [MOUSE] Vertical screen resolution, used for devices
...
...
drivers/Makefile
View file @
037d476f
...
...
@@ -37,9 +37,9 @@ obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC)
+=
tc/
obj-$(CONFIG_USB)
+=
usb/
obj-$(CONFIG_USB_GADGET)
+=
usb/gadget/
obj-$(CONFIG_SERIO)
+=
input/serio/
obj-$(CONFIG_INPUT)
+=
input/
obj-$(CONFIG_GAMEPORT)
+=
input/gameport/
obj-$(CONFIG_SERIO)
+=
input/serio/
obj-$(CONFIG_I2O)
+=
message/
obj-$(CONFIG_I2C)
+=
i2c/
obj-$(CONFIG_PHONE)
+=
telephony/
...
...
drivers/char/keyboard.c
View file @
037d476f
...
...
@@ -123,7 +123,7 @@ int shift_state = 0;
*/
static
struct
input_handler
kbd_handler
;
static
unsigned
long
key_down
[
256
/
BITS_PER_LONG
];
/* keyboard key bitmap */
static
unsigned
long
key_down
[
NBITS
(
KEY_MAX
)];
/* keyboard key bitmap */
static
unsigned
char
shift_down
[
NR_SHIFT
];
/* shift state counters.. */
static
int
dead_key_next
;
static
int
npadch
=
-
1
;
/* -1 or number assembled on pad */
...
...
@@ -142,7 +142,7 @@ static struct ledptr {
/* Simple translation table for the SysRq keys */
#ifdef CONFIG_MAGIC_SYSRQ
unsigned
char
kbd_sysrq_xlate
[
128
]
=
unsigned
char
kbd_sysrq_xlate
[
KEY_MAX
]
=
"
\000\033
1234567890-=
\177\t
"
/* 0x00 - 0x0f */
"qwertyuiop[]
\r\000
as"
/* 0x10 - 0x1f */
"dfghjkl;'`
\000\\
zxcv"
/* 0x20 - 0x2f */
...
...
@@ -941,6 +941,9 @@ void kbd_refresh_leds(struct input_handle *handle)
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH)
#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
static
unsigned
short
x86_keycodes
[
256
]
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
,
14
,
15
,
16
,
17
,
18
,
19
,
20
,
21
,
22
,
23
,
24
,
25
,
26
,
27
,
28
,
29
,
30
,
31
,
...
...
@@ -1007,6 +1010,8 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
#else
#define HW_RAW(dev) 0
#warning "Cannot generate rawmode keyboard for your architecture yet."
static
int
emulate_raw
(
struct
vc_data
*
vc
,
unsigned
int
keycode
,
unsigned
char
up_flag
)
...
...
@@ -1019,7 +1024,15 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u
}
#endif
void
kbd_keycode
(
unsigned
int
keycode
,
int
down
,
struct
pt_regs
*
regs
)
void
kbd_rawcode
(
unsigned
char
data
)
{
struct
vc_data
*
vc
=
vc_cons
[
fg_console
].
d
;
kbd
=
kbd_table
+
fg_console
;
if
(
kbd
->
kbdmode
==
VC_RAW
)
put_queue
(
vc
,
data
);
}
void
kbd_keycode
(
unsigned
int
keycode
,
int
down
,
int
hw_raw
,
struct
pt_regs
*
regs
)
{
struct
vc_data
*
vc
=
vc_cons
[
fg_console
].
d
;
unsigned
short
keysym
,
*
key_map
;
...
...
@@ -1053,7 +1066,7 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
return
;
#endif
/* CONFIG_MAC_EMUMOUSEBTN */
if
((
raw_mode
=
(
kbd
->
kbdmode
==
VC_RAW
)))
if
((
raw_mode
=
(
kbd
->
kbdmode
==
VC_RAW
))
&&
!
hw_raw
)
if
(
emulate_raw
(
vc
,
keycode
,
!
down
<<
7
))
if
(
keycode
<
BTN_MISC
)
printk
(
KERN_WARNING
"keyboard.c: can't emulate rawmode for keycode %d
\n
"
,
keycode
);
...
...
@@ -1119,6 +1132,9 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
return
;
}
if
(
keycode
>
NR_KEYS
)
return
;
keysym
=
key_map
[
keycode
];
type
=
KTYP
(
keysym
);
...
...
@@ -1148,11 +1164,12 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
}
static
void
kbd_event
(
struct
input_handle
*
handle
,
unsigned
int
event_type
,
unsigned
int
keycode
,
int
down
)
unsigned
int
event_code
,
int
value
)
{
if
(
event_type
!=
EV_KEY
)
return
;
kbd_keycode
(
keycode
,
down
,
handle
->
dev
->
regs
);
if
(
event_type
==
EV_MSC
&&
event_code
==
MSC_RAW
&&
HW_RAW
(
handle
->
dev
))
kbd_rawcode
(
value
);
if
(
event_type
==
EV_KEY
)
kbd_keycode
(
event_code
,
value
,
HW_RAW
(
handle
->
dev
),
handle
->
dev
->
regs
);
tasklet_schedule
(
&
keyboard_tasklet
);
do_poke_blanked_console
=
1
;
schedule_console_callback
();
...
...
drivers/input/gameport/emu10k1-gp.c
View file @
037d476f
...
...
@@ -50,8 +50,11 @@ struct emu {
};
static
struct
pci_device_id
emu_tbl
[]
=
{
{
0x1102
,
0x7002
,
PCI_ANY_ID
,
PCI_ANY_ID
},
/* SB Live gameport */
{
0x1102
,
0x7003
,
PCI_ANY_ID
,
PCI_ANY_ID
},
/* Audigy gameport */
{
0x1102
,
0x7004
,
PCI_ANY_ID
,
PCI_ANY_ID
},
/* Dell SB Live */
{
0x1102
,
0x7005
,
PCI_ANY_ID
,
PCI_ANY_ID
},
/* Audigy LS gameport */
{
0
,
}
};
...
...
drivers/input/joystick/Kconfig
View file @
037d476f
...
...
@@ -247,7 +247,7 @@ config JOYSTICK_AMIGA
To compile this driver as a module, choose M here: the
module will be called amijoy.
config
INPUT
_JOYDUMP
config
JOYSTICK
_JOYDUMP
tristate "Gameport data dumper"
depends on INPUT && INPUT_JOYSTICK
help
...
...
drivers/input/joystick/gamecon.c
View file @
037d476f
/*
*
$Id: gamecon.c,v 1.22 2002/07/01 15:42:25 vojtech Exp $
*
NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
*
* Copyright (c) 1999-2001 Vojtech Pavlik
* Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org>
*
* Based on the work of:
* Andree Borrmann John Dahlstrom
* David Kuder Nathan Hand
*/
/*
* NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
*/
/*
* 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
...
...
@@ -72,8 +69,9 @@ __obsolete_setup("gc_3=");
#define GC_MULTI2 5
#define GC_N64 6
#define GC_PSX 7
#define GC_DDR 8
#define GC_MAX
7
#define GC_MAX
8
#define GC_REFRESH_TIME HZ/100
...
...
@@ -91,7 +89,8 @@ static struct gc *gc_base[3];
static
int
gc_status_bit
[]
=
{
0x40
,
0x80
,
0x20
,
0x10
,
0x08
};
static
char
*
gc_names
[]
=
{
NULL
,
"SNES pad"
,
"NES pad"
,
"NES FourPort"
,
"Multisystem joystick"
,
"Multisystem 2-button joystick"
,
"N64 controller"
,
"PSX controller"
};
"Multisystem 2-button joystick"
,
"N64 controller"
,
"PSX controller"
"PSX DDR controller"
};
/*
* N64 support.
*/
...
...
@@ -237,7 +236,7 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
#define GC_PSX_RUMBLE 7
/* Rumble in Red mode */
#define GC_PSX_CLOCK 0x04
/* Pin 4 */
#define GC_PSX_COMMAND 0x01
/* Pin
1
*/
#define GC_PSX_COMMAND 0x01
/* Pin
2
*/
#define GC_PSX_POWER 0xf8
/* Pins 5-9 */
#define GC_PSX_SELECT 0x02
/* Pin 3 */
...
...
@@ -253,25 +252,29 @@ __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
};
static
short
gc_psx_ddr_btn
[]
=
{
BTN_0
,
BTN_1
,
BTN_2
,
BTN_3
};
/*
* gc_psx_command() writes 8bit command and reads 8bit data from
* the psx pad.
*/
static
int
gc_psx_command
(
struct
gc
*
gc
,
int
b
)
static
void
gc_psx_command
(
struct
gc
*
gc
,
int
b
,
unsigned
char
data
[
GC_PSX_LENGTH
]
)
{
int
i
,
cmd
,
data
=
0
;
int
i
,
j
,
cmd
,
read
;
for
(
i
=
0
;
i
<
5
;
i
++
)
data
[
i
]
=
0
;
for
(
i
=
0
;
i
<
8
;
i
++
,
b
>>=
1
)
{
cmd
=
(
b
&
1
)
?
GC_PSX_COMMAND
:
0
;
parport_write_data
(
gc
->
pd
->
port
,
cmd
|
GC_PSX_POWER
);
udelay
(
gc_psx_delay
);
data
|=
((
parport_read_status
(
gc
->
pd
->
port
)
^
0x80
)
&
gc
->
pads
[
GC_PSX
])
?
(
1
<<
i
)
:
0
;
read
=
parport_read_status
(
gc
->
pd
->
port
)
^
0x80
;
for
(
j
=
0
;
j
<
5
;
j
++
)
data
[
j
]
|=
(
read
&
gc_status_bit
[
j
]
&
gc
->
pads
[
GC_PSX
])
?
(
1
<<
i
)
:
0
;
parport_write_data
(
gc
->
pd
->
port
,
cmd
|
GC_PSX_CLOCK
|
GC_PSX_POWER
);
udelay
(
gc_psx_delay
);
}
return
data
;
}
/*
...
...
@@ -279,30 +282,39 @@ static int gc_psx_command(struct gc *gc, int b)
* device identifier code.
*/
static
int
gc_psx_read_packet
(
struct
gc
*
gc
,
unsigned
char
*
data
)
static
void
gc_psx_read_packet
(
struct
gc
*
gc
,
unsigned
char
data
[
5
][
GC_PSX_LENGTH
],
unsigned
char
id
[
5
]
)
{
int
i
,
id
;
int
i
,
j
,
max_len
=
0
;
unsigned
long
flags
;
unsigned
char
data2
[
5
];
parport_write_data
(
gc
->
pd
->
port
,
GC_PSX_CLOCK
|
GC_PSX_SELECT
|
GC_PSX_POWER
);
/* Select pad */
udelay
(
gc_psx_delay
*
2
);
udelay
(
gc_psx_delay
);
parport_write_data
(
gc
->
pd
->
port
,
GC_PSX_CLOCK
|
GC_PSX_POWER
);
/* Deselect, begin command */
udelay
(
gc_psx_delay
*
2
);
udelay
(
gc_psx_delay
);
local_irq_save
(
flags
);
gc_psx_command
(
gc
,
0x01
);
/* Access pad */
id
=
gc_psx_command
(
gc
,
0x42
);
/* Get device id */
if
(
gc_psx_command
(
gc
,
0
)
==
0x5a
)
{
/* Okay? */
for
(
i
=
0
;
i
<
GC_PSX_LEN
(
id
)
*
2
;
i
++
)
data
[
i
]
=
gc_psx_command
(
gc
,
0
);
}
else
id
=
0
;
gc_psx_command
(
gc
,
0x01
,
data2
);
/* Access pad */
gc_psx_command
(
gc
,
0x42
,
id
);
/* Get device ids */
gc_psx_command
(
gc
,
0
,
data2
);
/* Dump status */
for
(
i
=
0
;
i
<
5
;
i
++
)
/* Find the longest pad */
if
((
gc_status_bit
[
i
]
&
gc
->
pads
[
GC_PSX
])
&&
(
GC_PSX_LEN
(
id
[
i
])
>
max_len
))
max_len
=
GC_PSX_LEN
(
id
[
i
]);
for
(
i
=
0
;
i
<
max_len
*
2
;
i
++
)
{
/* Read in all the data */
gc_psx_command
(
gc
,
0
,
data2
);
for
(
j
=
0
;
j
<
5
;
j
++
)
data
[
j
][
i
]
=
data2
[
j
];
}
local_irq_restore
(
flags
);
parport_write_data
(
gc
->
pd
->
port
,
GC_PSX_CLOCK
|
GC_PSX_SELECT
|
GC_PSX_POWER
);
return
GC_PSX_ID
(
id
);
for
(
i
=
0
;
i
<
5
;
i
++
)
/* Set id's to the real value */
id
[
i
]
=
GC_PSX_ID
(
id
[
i
]);
}
/*
...
...
@@ -316,6 +328,7 @@ static void gc_timer(unsigned long private)
struct
gc
*
gc
=
(
void
*
)
private
;
struct
input_dev
*
dev
=
gc
->
dev
;
unsigned
char
data
[
GC_MAX_LENGTH
];
unsigned
char
data_psx
[
5
][
GC_PSX_LENGTH
];
int
i
,
j
,
s
;
/*
...
...
@@ -412,53 +425,72 @@ static void gc_timer(unsigned long private)
* PSX controllers
*/
if
(
gc
->
pads
[
GC_PSX
])
{
if
(
gc
->
pads
[
GC_PSX
]
||
gc
->
pads
[
GC_DDR
]
)
{
for
(
i
=
0
;
i
<
5
;
i
++
)
if
(
gc
->
pads
[
GC_PSX
]
&
gc_status_bit
[
i
])
break
;
gc_psx_read_packet
(
gc
,
data_psx
,
data
);
switch
(
gc_psx_read_packet
(
gc
,
data
))
{
for
(
i
=
0
;
i
<
5
;
i
++
)
{
switch
(
data
[
i
])
{
case
GC_PSX_RUMBLE
:
input_report_key
(
dev
+
i
,
BTN_THUMBL
,
~
data
[
0
]
&
0x04
);
input_report_key
(
dev
+
i
,
BTN_THUMBR
,
~
data
[
0
]
&
0x02
);
input_sync
(
dev
+
i
);
input_report_key
(
dev
+
i
,
BTN_THUMBL
,
~
data_psx
[
i
][
0
]
&
0x04
);
input_report_key
(
dev
+
i
,
BTN_THUMBR
,
~
data_psx
[
i
][
0
]
&
0x02
);
case
GC_PSX_NEGCON
:
case
GC_PSX_ANALOG
:
if
(
gc
->
pads
[
GC_DDR
]
&
gc_status_bit
[
i
])
{
for
(
j
=
0
;
j
<
4
;
j
++
)
input_report_key
(
dev
+
i
,
gc_psx_ddr_btn
[
j
],
~
data_psx
[
i
][
0
]
&
(
0x10
<<
j
));
}
else
{
for
(
j
=
0
;
j
<
4
;
j
++
)
input_report_abs
(
dev
+
i
,
gc_psx_abs
[
j
],
data
[
j
+
2
]);
input_report_abs
(
dev
+
i
,
gc_psx_abs
[
j
+
2
],
data_psx
[
i
]
[
j
+
2
]);
input_report_abs
(
dev
+
i
,
ABS_HAT0X
,
!
(
data
[
0
]
&
0x20
)
-
!
(
data
[
0
]
&
0x80
));
input_report_abs
(
dev
+
i
,
ABS_HAT0Y
,
!
(
data
[
0
]
&
0x40
)
-
!
(
data
[
0
]
&
0x10
));
input_report_abs
(
dev
+
i
,
ABS_X
,
128
+
!
(
data_psx
[
i
][
0
]
&
0x20
)
*
127
-
!
(
data_psx
[
i
][
0
]
&
0x80
)
*
128
);
input_report_abs
(
dev
+
i
,
ABS_Y
,
128
+
!
(
data_psx
[
i
][
0
]
&
0x40
)
*
127
-
!
(
data_psx
[
i
][
0
]
&
0x10
)
*
128
);
}
for
(
j
=
0
;
j
<
8
;
j
++
)
input_report_key
(
dev
+
i
,
gc_psx_btn
[
j
],
~
data
[
1
]
&
(
1
<<
j
));
input_report_key
(
dev
+
i
,
gc_psx_btn
[
j
],
~
data_psx
[
i
]
[
1
]
&
(
1
<<
j
));
input_report_key
(
dev
+
i
,
BTN_START
,
~
data
[
0
]
&
0x08
);
input_report_key
(
dev
+
i
,
BTN_SELECT
,
~
data
[
0
]
&
0x01
);
input_report_key
(
dev
+
i
,
BTN_START
,
~
data_psx
[
i
]
[
0
]
&
0x08
);
input_report_key
(
dev
+
i
,
BTN_SELECT
,
~
data_psx
[
i
]
[
0
]
&
0x01
);
input_sync
(
dev
+
i
);
break
;
case
GC_PSX_NORMAL
:
input_report_abs
(
dev
+
i
,
ABS_X
,
128
+
!
(
data
[
0
]
&
0x20
)
*
127
-
!
(
data
[
0
]
&
0x80
)
*
128
);
input_report_abs
(
dev
+
i
,
ABS_Y
,
128
+
!
(
data
[
0
]
&
0x40
)
*
127
-
!
(
data
[
0
]
&
0x10
)
*
128
);
if
(
gc
->
pads
[
GC_DDR
]
&
gc_status_bit
[
i
])
{
for
(
j
=
0
;
j
<
4
;
j
++
)
input_report_key
(
dev
+
i
,
gc_psx_ddr_btn
[
j
],
~
data_psx
[
i
][
0
]
&
(
0x10
<<
j
));
}
else
{
input_report_abs
(
dev
+
i
,
ABS_X
,
128
+
!
(
data_psx
[
i
][
0
]
&
0x20
)
*
127
-
!
(
data_psx
[
i
][
0
]
&
0x80
)
*
128
);
input_report_abs
(
dev
+
i
,
ABS_Y
,
128
+
!
(
data_psx
[
i
][
0
]
&
0x40
)
*
127
-
!
(
data_psx
[
i
][
0
]
&
0x10
)
*
128
);
/* for some reason if the extra axes are left unset they drift */
/* for (j = 0; j < 4; j++)
input_report_abs(dev + i, gc_psx_abs[j+2], 128);
* This needs to be debugged properly,
* maybe fuzz processing needs to be done in input_sync()
* --vojtech
*/
}
for
(
j
=
0
;
j
<
8
;
j
++
)
input_report_key
(
dev
+
i
,
gc_psx_btn
[
j
],
~
data
[
1
]
&
(
1
<<
j
));
input_report_key
(
dev
+
i
,
gc_psx_btn
[
j
],
~
data_psx
[
i
]
[
1
]
&
(
1
<<
j
));
input_report_key
(
dev
+
i
,
BTN_START
,
~
data
[
0
]
&
0x08
);
input_report_key
(
dev
+
i
,
BTN_SELECT
,
~
data
[
0
]
&
0x01
);
input_report_key
(
dev
+
i
,
BTN_START
,
~
data_psx
[
i
]
[
0
]
&
0x08
);
input_report_key
(
dev
+
i
,
BTN_SELECT
,
~
data_psx
[
i
]
[
0
]
&
0x01
);
input_sync
(
dev
+
i
);
break
;
case
0
:
/* not a pad, ignore */
break
;
}
}
}
...
...
@@ -490,8 +522,7 @@ static struct gc __init *gc_probe(int *config, int nargs)
{
struct
gc
*
gc
;
struct
parport
*
pp
;
int
i
,
j
,
psx
;
unsigned
char
data
[
32
];
int
i
,
j
;
if
(
config
[
0
]
<
0
)
return
NULL
;
...
...
@@ -588,25 +619,16 @@ static struct gc __init *gc_probe(int *config, int nargs)
break
;
case
GC_PSX
:
psx
=
gc_psx_read_packet
(
gc
,
data
);
switch
(
psx
)
{
case
GC_PSX_NEGCON
:
case
GC_PSX_NORMAL
:
case
GC_PSX_ANALOG
:
case
GC_PSX_RUMBLE
:
for
(
j
=
0
;
j
<
6
;
j
++
)
{
psx
=
gc_psx_abs
[
j
];
set_bit
(
psx
,
gc
->
dev
[
i
].
absbit
);
if
(
j
<
4
)
{
gc
->
dev
[
i
].
absmin
[
psx
]
=
4
;
gc
->
dev
[
i
].
absmax
[
psx
]
=
252
;
gc
->
dev
[
i
].
absflat
[
psx
]
=
2
;
case
GC_DDR
:
if
(
config
[
i
+
1
]
==
GC_DDR
)
{
for
(
j
=
0
;
j
<
4
;
j
++
)
set_bit
(
gc_psx_ddr_btn
[
j
],
gc
->
dev
[
i
].
keybit
);
}
else
{
gc
->
dev
[
i
].
absmin
[
psx
]
=
-
1
;
gc
->
dev
[
i
].
absmax
[
psx
]
=
1
;
for
(
j
=
0
;
j
<
6
;
j
++
)
{
set_bit
(
gc_psx_abs
[
j
],
gc
->
dev
[
i
].
absbit
);
gc
->
dev
[
i
].
absmin
[
gc_psx_abs
[
j
]]
=
4
;
gc
->
dev
[
i
].
absmax
[
gc_psx_abs
[
j
]]
=
252
;
gc
->
dev
[
i
].
absflat
[
gc_psx_abs
[
j
]]
=
2
;
}
}
...
...
@@ -614,18 +636,6 @@ static struct gc __init *gc_probe(int *config, int nargs)
set_bit
(
gc_psx_btn
[
j
],
gc
->
dev
[
i
].
keybit
);
break
;
case
0
:
gc
->
pads
[
GC_PSX
]
&=
~
gc_status_bit
[
i
];
printk
(
KERN_ERR
"gamecon.c: No PSX controller found.
\n
"
);
break
;
default:
gc
->
pads
[
GC_PSX
]
&=
~
gc_status_bit
[
i
];
printk
(
KERN_WARNING
"gamecon.c: Unsupported PSX controller %#x,"
" please report to <vojtech@ucw.cz>.
\n
"
,
psx
);
}
break
;
}
sprintf
(
gc
->
phys
[
i
],
"%s/input%d"
,
gc
->
pd
->
port
->
name
,
i
);
...
...
drivers/input/joystick/iforce/iforce-main.c
View file @
037d476f
...
...
@@ -524,7 +524,7 @@ static int __init iforce_init(void)
usb_register
(
&
iforce_usb_driver
);
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
serio_register_d
evice
(
&
iforce_serio_de
v
);
serio_register_d
river
(
&
iforce_serio_dr
v
);
#endif
return
0
;
}
...
...
@@ -535,7 +535,7 @@ static void __exit iforce_exit(void)
usb_deregister
(
&
iforce_usb_driver
);
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
serio_unregister_d
evice
(
&
iforce_serio_de
v
);
serio_unregister_d
river
(
&
iforce_serio_dr
v
);
#endif
}
...
...
drivers/input/joystick/iforce/iforce-serio.c
View file @
037d476f
...
...
@@ -124,7 +124,7 @@ static irqreturn_t iforce_serio_irq(struct serio *serio,
return
IRQ_HANDLED
;
}
static
void
iforce_serio_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
iforce_serio_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
iforce
*
iforce
;
if
(
serio
->
type
!=
(
SERIO_RS232
|
SERIO_IFORCE
))
...
...
@@ -137,7 +137,7 @@ static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
iforce
->
serio
=
serio
;
serio
->
private
=
iforce
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
iforce
);
return
;
}
...
...
@@ -158,7 +158,11 @@ static void iforce_serio_disconnect(struct serio *serio)
kfree
(
iforce
);
}
struct
serio_dev
iforce_serio_dev
=
{
struct
serio_driver
iforce_serio_drv
=
{
.
driver
=
{
.
name
=
"iforce"
,
},
.
description
=
"RS232 I-Force joysticks and wheels driver"
,
.
write_wakeup
=
iforce_serio_write_wakeup
,
.
interrupt
=
iforce_serio_irq
,
.
connect
=
iforce_serio_connect
,
...
...
drivers/input/joystick/iforce/iforce.h
View file @
037d476f
...
...
@@ -187,5 +187,5 @@ int iforce_upload_constant(struct iforce*, struct ff_effect*, int is_update);
int
iforce_upload_condition
(
struct
iforce
*
,
struct
ff_effect
*
,
int
is_update
);
/* Public variables */
extern
struct
serio_d
ev
iforce_serio_de
v
;
extern
struct
serio_d
river
iforce_serio_dr
v
;
extern
struct
usb_driver
iforce_usb_driver
;
drivers/input/joystick/magellan.c
View file @
037d476f
...
...
@@ -35,8 +35,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Magellan and SpaceMouse 6dof controller driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"Magellan and SpaceMouse 6dof controller driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
/*
...
...
@@ -146,7 +148,7 @@ static void magellan_disconnect(struct serio *serio)
* it as an input device.
*/
static
void
magellan_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
magellan_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
magellan
*
magellan
;
int
i
,
t
;
...
...
@@ -184,7 +186,7 @@ static void magellan_connect(struct serio *serio, struct serio_dev *dev)
serio
->
private
=
magellan
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
magellan
);
return
;
}
...
...
@@ -199,7 +201,11 @@ static void magellan_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static
struct
serio_dev
magellan_dev
=
{
static
struct
serio_driver
magellan_drv
=
{
.
driver
=
{
.
name
=
"magellan"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
magellan_interrupt
,
.
connect
=
magellan_connect
,
.
disconnect
=
magellan_disconnect
,
...
...
@@ -211,13 +217,13 @@ static struct serio_dev magellan_dev = {
int
__init
magellan_init
(
void
)
{
serio_register_d
evice
(
&
magellan_de
v
);
serio_register_d
river
(
&
magellan_dr
v
);
return
0
;
}
void
__exit
magellan_exit
(
void
)
{
serio_unregister_d
evice
(
&
magellan_de
v
);
serio_unregister_d
river
(
&
magellan_dr
v
);
}
module_init
(
magellan_init
);
...
...
drivers/input/joystick/spaceball.c
View file @
037d476f
...
...
@@ -39,8 +39,10 @@
#include <linux/input.h>
#include <linux/serio.h>
#define DRIVER_DESC "SpaceTec SpaceBall 2003/3003/4000 FLX driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"SpaceTec SpaceBall 2003/3003/4000 FLX driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
/*
...
...
@@ -201,7 +203,7 @@ static void spaceball_disconnect(struct serio *serio)
* it as an input device.
*/
static
void
spaceball_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
spaceball_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
spaceball
*
spaceball
;
int
i
,
t
,
id
;
...
...
@@ -254,7 +256,7 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
serio
->
private
=
spaceball
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
spaceball
);
return
;
}
...
...
@@ -269,7 +271,11 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static
struct
serio_dev
spaceball_dev
=
{
static
struct
serio_driver
spaceball_drv
=
{
.
driver
=
{
.
name
=
"spaceball"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
spaceball_interrupt
,
.
connect
=
spaceball_connect
,
.
disconnect
=
spaceball_disconnect
,
...
...
@@ -281,13 +287,13 @@ static struct serio_dev spaceball_dev = {
int
__init
spaceball_init
(
void
)
{
serio_register_d
evice
(
&
spaceball_de
v
);
serio_register_d
river
(
&
spaceball_dr
v
);
return
0
;
}
void
__exit
spaceball_exit
(
void
)
{
serio_unregister_d
evice
(
&
spaceball_de
v
);
serio_unregister_d
river
(
&
spaceball_dr
v
);
}
module_init
(
spaceball_init
);
...
...
drivers/input/joystick/spaceorb.c
View file @
037d476f
...
...
@@ -38,8 +38,10 @@
#include <linux/input.h>
#include <linux/serio.h>
#define DRIVER_DESC "SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
/*
...
...
@@ -162,7 +164,7 @@ static void spaceorb_disconnect(struct serio *serio)
* it as an input device.
*/
static
void
spaceorb_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
spaceorb_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
spaceorb
*
spaceorb
;
int
i
,
t
;
...
...
@@ -201,7 +203,7 @@ static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
serio
->
private
=
spaceorb
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
spaceorb
);
return
;
}
...
...
@@ -213,7 +215,11 @@ static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static
struct
serio_dev
spaceorb_dev
=
{
static
struct
serio_driver
spaceorb_drv
=
{
.
driver
=
{
.
name
=
"spaceorb"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
spaceorb_interrupt
,
.
connect
=
spaceorb_connect
,
.
disconnect
=
spaceorb_disconnect
,
...
...
@@ -225,13 +231,13 @@ static struct serio_dev spaceorb_dev = {
int
__init
spaceorb_init
(
void
)
{
serio_register_d
evice
(
&
spaceorb_de
v
);
serio_register_d
river
(
&
spaceorb_dr
v
);
return
0
;
}
void
__exit
spaceorb_exit
(
void
)
{
serio_unregister_d
evice
(
&
spaceorb_de
v
);
serio_unregister_d
river
(
&
spaceorb_dr
v
);
}
module_init
(
spaceorb_init
);
...
...
drivers/input/joystick/stinger.c
View file @
037d476f
...
...
@@ -36,8 +36,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Gravis Stinger gamepad driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"Gravis Stinger gamepad driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
/*
...
...
@@ -134,7 +136,7 @@ static void stinger_disconnect(struct serio *serio)
* it as an input device.
*/
static
void
stinger_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
stinger_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
stinger
*
stinger
;
int
i
;
...
...
@@ -172,7 +174,7 @@ static void stinger_connect(struct serio *serio, struct serio_dev *dev)
stinger
->
dev
.
private
=
stinger
;
serio
->
private
=
stinger
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
stinger
);
return
;
}
...
...
@@ -187,7 +189,11 @@ static void stinger_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static
struct
serio_dev
stinger_dev
=
{
static
struct
serio_driver
stinger_drv
=
{
.
driver
=
{
.
name
=
"stinger"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
stinger_interrupt
,
.
connect
=
stinger_connect
,
.
disconnect
=
stinger_disconnect
,
...
...
@@ -199,13 +205,13 @@ static struct serio_dev stinger_dev = {
int
__init
stinger_init
(
void
)
{
serio_register_d
evice
(
&
stinger_de
v
);
serio_register_d
river
(
&
stinger_dr
v
);
return
0
;
}
void
__exit
stinger_exit
(
void
)
{
serio_unregister_d
evice
(
&
stinger_de
v
);
serio_unregister_d
river
(
&
stinger_dr
v
);
}
module_init
(
stinger_init
);
...
...
drivers/input/joystick/twidjoy.c
View file @
037d476f
...
...
@@ -187,7 +187,7 @@ static void twidjoy_disconnect(struct serio *serio)
* it as an input device.
*/
static
void
twidjoy_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
twidjoy_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
twidjoy_button_spec
*
bp
;
struct
twidjoy
*
twidjoy
;
...
...
@@ -232,7 +232,7 @@ static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
twidjoy
->
dev
.
private
=
twidjoy
;
serio
->
private
=
twidjoy
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
twidjoy
);
return
;
}
...
...
@@ -246,7 +246,11 @@ static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static
struct
serio_dev
twidjoy_dev
=
{
static
struct
serio_driver
twidjoy_drv
=
{
.
driver
=
{
.
name
=
"twidjoy"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
twidjoy_interrupt
,
.
connect
=
twidjoy_connect
,
.
disconnect
=
twidjoy_disconnect
,
...
...
@@ -258,13 +262,13 @@ static struct serio_dev twidjoy_dev = {
int
__init
twidjoy_init
(
void
)
{
serio_register_d
evice
(
&
twidjoy_de
v
);
serio_register_d
river
(
&
twidjoy_dr
v
);
return
0
;
}
void
__exit
twidjoy_exit
(
void
)
{
serio_unregister_d
evice
(
&
twidjoy_de
v
);
serio_unregister_d
river
(
&
twidjoy_dr
v
);
}
module_init
(
twidjoy_init
);
...
...
drivers/input/joystick/warrior.c
View file @
037d476f
...
...
@@ -35,8 +35,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Logitech WingMan Warrior joystick driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"Logitech WingMan Warrior joystick driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
/*
...
...
@@ -139,7 +141,7 @@ static void warrior_disconnect(struct serio *serio)
* it as an input device.
*/
static
void
warrior_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
warrior_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
warrior
*
warrior
;
int
i
;
...
...
@@ -185,7 +187,7 @@ static void warrior_connect(struct serio *serio, struct serio_dev *dev)
serio
->
private
=
warrior
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
warrior
);
return
;
}
...
...
@@ -199,7 +201,11 @@ static void warrior_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static
struct
serio_dev
warrior_dev
=
{
static
struct
serio_driver
warrior_drv
=
{
.
driver
=
{
.
name
=
"warrior"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
warrior_interrupt
,
.
connect
=
warrior_connect
,
.
disconnect
=
warrior_disconnect
,
...
...
@@ -211,13 +217,13 @@ static struct serio_dev warrior_dev = {
int
__init
warrior_init
(
void
)
{
serio_register_d
evice
(
&
warrior_de
v
);
serio_register_d
river
(
&
warrior_dr
v
);
return
0
;
}
void
__exit
warrior_exit
(
void
)
{
serio_unregister_d
evice
(
&
warrior_de
v
);
serio_unregister_d
river
(
&
warrior_dr
v
);
}
module_init
(
warrior_init
);
...
...
drivers/input/keyboard/atkbd.c
View file @
037d476f
...
...
@@ -27,8 +27,10 @@
#include <linux/serio.h>
#include <linux/workqueue.h>
#define DRIVER_DESC "AT and PS/2 keyboard driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@suse.cz>"
);
MODULE_DESCRIPTION
(
"AT and PS/2 keyboard driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
static
int
atkbd_set
=
2
;
...
...
@@ -47,6 +49,10 @@ static int atkbd_softrepeat;
module_param_named
(
softrepeat
,
atkbd_softrepeat
,
bool
,
0
);
MODULE_PARM_DESC
(
softrepeat
,
"Use software keyboard repeat"
);
static
int
atkbd_softraw
=
1
;
module_param_named
(
softraw
,
atkbd_softraw
,
bool
,
0
);
MODULE_PARM_DESC
(
softraw
,
"Use software generated rawmode"
);
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"
);
...
...
@@ -164,34 +170,48 @@ static unsigned char atkbd_scroll_keys[5][2] = {
{
ATKBD_SCR_CLICK
,
0x60
},
};
#define ATKBD_FLAG_ACK 0
/* Waiting for ACK/NAK */
#define ATKBD_FLAG_CMD 1
/* Waiting for command to finish */
#define ATKBD_FLAG_CMD1 2
/* First byte of command response */
#define ATKBD_FLAG_ID 3
/* First byte is not keyboard ID */
#define ATKBD_FLAG_ENABLED 4
/* Waining for init to finish */
/*
* The atkbd control structure
*/
struct
atkbd
{
unsigned
char
keycode
[
512
];
struct
input_dev
dev
;
struct
serio
*
serio
;
/* Written only during init */
char
name
[
64
];
char
phys
[
32
];
unsigned
short
id
;
struct
serio
*
serio
;
struct
input_dev
dev
;
unsigned
char
set
;
unsigned
int
translated
:
1
;
unsigned
int
extra
:
1
;
unsigned
int
write
:
1
;
unsigned
short
id
;
unsigned
char
keycode
[
512
];
unsigned
char
translated
;
unsigned
char
extra
;
unsigned
char
write
;
/* Protected by FLAG_ACK */
unsigned
char
nak
;
/* Protected by FLAG_CMD */
unsigned
char
cmdbuf
[
4
];
unsigned
char
cmdcnt
;
volatile
signed
char
ack
;
unsigned
char
emul
;
unsigned
int
resend
:
1
;
unsigned
int
release
:
1
;
unsigned
int
bat_xl
:
1
;
unsigned
int
enabled
:
1
;
/* Accessed only from interrupt */
unsigned
char
emul
;
unsigned
char
resend
;
unsigned
char
release
;
unsigned
char
bat_xl
;
unsigned
int
last
;
unsigned
long
time
;
/* Flags */
unsigned
long
flags
;
};
static
void
atkbd_report_key
(
struct
input_dev
*
dev
,
struct
pt_regs
*
regs
,
int
code
,
int
value
)
...
...
@@ -224,7 +244,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
#if !defined(__i386__) && !defined (__x86_64__)
if
((
flags
&
(
SERIO_FRAME
|
SERIO_PARITY
))
&&
(
~
flags
&
SERIO_TIMEOUT
)
&&
!
atkbd
->
resend
&&
atkbd
->
write
)
{
printk
(
"atkbd.c: frame/parity error: %02x
\n
"
,
flags
);
printk
(
KERN_WARNING
"atkbd.c: frame/parity error: %02x
\n
"
,
flags
);
serio_write
(
serio
,
ATKBD_CMD_RESEND
);
atkbd
->
resend
=
1
;
goto
out
;
...
...
@@ -234,24 +254,45 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd
->
resend
=
0
;
#endif
if
(
!
atkbd
->
ack
)
if
(
test_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
)
)
switch
(
code
)
{
case
ATKBD_RET_ACK
:
atkbd
->
ack
=
1
;
atkbd
->
nak
=
0
;
if
(
atkbd
->
cmdcnt
)
{
set_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
set_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
);
set_bit
(
ATKBD_FLAG_ID
,
&
atkbd
->
flags
);
}
clear_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
goto
out
;
case
ATKBD_RET_NAK
:
atkbd
->
ack
=
-
1
;
atkbd
->
nak
=
1
;
clear_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
goto
out
;
}
if
(
atkbd
->
cmdcnt
)
{
atkbd
->
cmdbuf
[
--
atkbd
->
cmdcnt
]
=
code
;
if
(
test_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
))
{
atkbd
->
cmdcnt
--
;
atkbd
->
cmdbuf
[
atkbd
->
cmdcnt
]
=
code
;
if
(
atkbd
->
cmdcnt
==
1
)
{
if
(
code
!=
0xab
&&
code
!=
0xac
)
clear_bit
(
ATKBD_FLAG_ID
,
&
atkbd
->
flags
);
clear_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
);
}
if
(
!
atkbd
->
cmdcnt
)
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
goto
out
;
}
if
(
!
atkbd
->
enabled
)
if
(
!
test_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
)
)
goto
out
;
input_event
(
&
atkbd
->
dev
,
EV_MSC
,
MSC_RAW
,
code
);
if
(
atkbd
->
translated
)
{
if
(
atkbd
->
emul
||
...
...
@@ -270,6 +311,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
switch
(
code
)
{
case
ATKBD_RET_BAT
:
clear_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
);
serio_rescan
(
atkbd
->
serio
);
goto
out
;
case
ATKBD_RET_EMUL0
:
...
...
@@ -300,6 +342,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
code
|=
(
atkbd
->
set
!=
3
)
?
0x80
:
0x100
;
}
if
(
atkbd
->
keycode
[
code
]
!=
ATKBD_KEY_NULL
)
input_event
(
&
atkbd
->
dev
,
EV_MSC
,
MSC_SCAN
,
code
);
switch
(
atkbd
->
keycode
[
code
])
{
case
ATKBD_KEY_NULL
:
break
;
...
...
@@ -376,18 +421,20 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
static
int
atkbd_sendbyte
(
struct
atkbd
*
atkbd
,
unsigned
char
byte
)
{
int
timeout
=
20000
;
/* 200 msec */
atkbd
->
ack
=
0
;
int
timeout
=
200000
;
/* 200 msec */
#ifdef ATKBD_DEBUG
printk
(
KERN_DEBUG
"atkbd.c: Sent: %02x
\n
"
,
byte
);
#endif
set_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
if
(
serio_write
(
atkbd
->
serio
,
byte
))
return
-
1
;
while
(
test_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
)
&&
timeout
--
)
udelay
(
1
);
clear_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
while
(
!
atkbd
->
ack
&&
timeout
--
)
udelay
(
10
);
return
-
(
atkbd
->
ack
<=
0
);
return
-
atkbd
->
nak
;
}
/*
...
...
@@ -405,7 +452,7 @@ static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command)
atkbd
->
cmdcnt
=
receive
;
if
(
command
==
ATKBD_CMD_RESET_BAT
)
timeout
=
2000000
;
/* 2
sec */
timeout
=
4000000
;
/* 4
sec */
if
(
receive
&&
param
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
...
...
@@ -413,38 +460,40 @@ static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command)
if
(
command
&
0xff
)
if
(
atkbd_sendbyte
(
atkbd
,
command
&
0xff
))
return
(
atkbd
->
cmdcnt
=
0
)
-
1
;
return
-
1
;
for
(
i
=
0
;
i
<
send
;
i
++
)
if
(
atkbd_sendbyte
(
atkbd
,
param
[
i
]))
return
(
atkbd
->
cmdcnt
=
0
)
-
1
;
return
-
1
;
while
(
test_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
)
&&
timeout
--
)
{
while
(
atkbd
->
cmdcnt
&&
timeout
--
)
{
if
(
!
test_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
)
)
{
if
(
atkbd
->
cmdcnt
==
1
&&
command
==
ATKBD_CMD_RESET_BAT
&&
timeout
>
100000
)
if
(
command
==
ATKBD_CMD_RESET_BAT
&&
timeout
>
100000
)
timeout
=
100000
;
if
(
atkbd
->
cmdcnt
==
1
&&
command
==
ATKBD_CMD_GETID
&&
atkbd
->
cmdbuf
[
1
]
!=
0xab
&&
atkbd
->
cmdbuf
[
1
]
!=
0xac
)
{
if
(
command
==
ATKBD_CMD_GETID
&&
!
test_bit
(
ATKBD_FLAG_ID
,
&
atkbd
->
flags
))
{
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
atkbd
->
cmdcnt
=
0
;
break
;
}
}
udelay
(
1
);
}
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
if
(
param
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
param
[
i
]
=
atkbd
->
cmdbuf
[(
receive
-
1
)
-
i
];
if
(
command
==
ATKBD_CMD_RESET_BAT
&&
atkbd
->
cmdcnt
==
1
)
atkbd
->
cmdcnt
=
0
;
return
0
;
if
(
atkbd
->
cmdcnt
)
{
atkbd
->
cmdcnt
=
0
;
if
(
atkbd
->
cmdcnt
)
return
-
1
;
}
return
0
;
}
...
...
@@ -672,6 +721,7 @@ static void atkbd_cleanup(struct serio *serio)
static
void
atkbd_disconnect
(
struct
serio
*
serio
)
{
struct
atkbd
*
atkbd
=
serio
->
private
;
clear_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
);
input_unregister_device
(
&
atkbd
->
dev
);
serio_close
(
serio
);
kfree
(
atkbd
);
...
...
@@ -684,7 +734,7 @@ static void atkbd_disconnect(struct serio *serio)
* to the input module.
*/
static
void
atkbd_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
atkbd_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
atkbd
*
atkbd
;
int
i
;
...
...
@@ -709,17 +759,22 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
return
;
}
if
(
!
atkbd
->
write
)
atkbd_softrepeat
=
1
;
if
(
atkbd_softrepeat
)
atkbd_softraw
=
1
;
if
(
atkbd
->
write
)
{
atkbd
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_LED
)
|
BIT
(
EV_REP
);
atkbd
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_LED
)
|
BIT
(
EV_REP
)
|
BIT
(
EV_MSC
)
;
atkbd
->
dev
.
ledbit
[
0
]
=
BIT
(
LED_NUML
)
|
BIT
(
LED_CAPSL
)
|
BIT
(
LED_SCROLLL
);
}
else
atkbd
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_REP
);
}
else
atkbd
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_REP
)
|
BIT
(
EV_MSC
);
atkbd
->
dev
.
mscbit
[
0
]
=
atkbd_softraw
?
BIT
(
MSC_SCAN
)
:
BIT
(
MSC_RAW
)
|
BIT
(
MSC_SCAN
);
if
(
!
atkbd_softrepeat
)
{
atkbd
->
dev
.
rep
[
REP_DELAY
]
=
250
;
atkbd
->
dev
.
rep
[
REP_PERIOD
]
=
33
;
}
}
else
atkbd_softraw
=
1
;
atkbd
->
ack
=
1
;
atkbd
->
serio
=
serio
;
init_input_dev
(
&
atkbd
->
dev
);
...
...
@@ -732,7 +787,7 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
serio
->
private
=
atkbd
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
atkbd
);
return
;
}
...
...
@@ -754,8 +809,6 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd
->
id
=
0xab00
;
}
atkbd
->
enabled
=
1
;
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 Extra keyboard"
);
...
...
@@ -797,6 +850,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
input_register_device
(
&
atkbd
->
dev
);
set_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
);
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
atkbd
->
name
,
serio
->
phys
);
}
...
...
@@ -808,10 +863,10 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
static
int
atkbd_reconnect
(
struct
serio
*
serio
)
{
struct
atkbd
*
atkbd
=
serio
->
private
;
struct
serio_d
ev
*
dev
=
serio
->
de
v
;
struct
serio_d
river
*
drv
=
serio
->
dr
v
;
unsigned
char
param
[
1
];
if
(
!
d
e
v
)
{
if
(
!
d
r
v
)
{
printk
(
KERN_DEBUG
"atkbd: reconnect request, but serio is disconnected, ignoring...
\n
"
);
return
-
1
;
}
...
...
@@ -832,10 +887,16 @@ static int atkbd_reconnect(struct serio *serio)
return
-
1
;
}
set_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
);
return
0
;
}
static
struct
serio_dev
atkbd_dev
=
{
static
struct
serio_driver
atkbd_drv
=
{
.
driver
=
{
.
name
=
"atkbd"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
atkbd_interrupt
,
.
connect
=
atkbd_connect
,
.
reconnect
=
atkbd_reconnect
,
...
...
@@ -845,13 +906,13 @@ static struct serio_dev atkbd_dev = {
int
__init
atkbd_init
(
void
)
{
serio_register_d
evice
(
&
atkbd_de
v
);
serio_register_d
river
(
&
atkbd_dr
v
);
return
0
;
}
void
__exit
atkbd_exit
(
void
)
{
serio_unregister_d
evice
(
&
atkbd_de
v
);
serio_unregister_d
river
(
&
atkbd_dr
v
);
}
module_init
(
atkbd_init
);
...
...
drivers/input/keyboard/lkkbd.c
View file @
037d476f
...
...
@@ -76,8 +76,10 @@
#include <linux/serio.h>
#include <linux/workqueue.h>
#define DRIVER_DESC "LK keyboard driver"
MODULE_AUTHOR
(
"Jan-Benedict Glaw <jbglaw@lug-owl.de>"
);
MODULE_DESCRIPTION
(
"LK keyboard driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
/*
...
...
@@ -622,7 +624,7 @@ lkkbd_reinit (void *data)
* lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
*/
static
void
lkkbd_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
lkkbd_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
lkkbd
*
lk
;
int
i
;
...
...
@@ -665,7 +667,7 @@ lkkbd_connect (struct serio *serio, struct serio_dev *dev)
serio
->
private
=
lk
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
lk
);
return
;
}
...
...
@@ -703,7 +705,11 @@ lkkbd_disconnect (struct serio *serio)
kfree
(
lk
);
}
static
struct
serio_dev
lkkbd_dev
=
{
static
struct
serio_driver
lkkbd_drv
=
{
.
driver
=
{
.
name
=
"lkkbd"
,
},
.
description
=
DRIVER_DESC
,
.
connect
=
lkkbd_connect
,
.
disconnect
=
lkkbd_disconnect
,
.
interrupt
=
lkkbd_interrupt
,
...
...
@@ -715,14 +721,14 @@ static struct serio_dev lkkbd_dev = {
int
__init
lkkbd_init
(
void
)
{
serio_register_d
evice
(
&
lkkbd_de
v
);
serio_register_d
river
(
&
lkkbd_dr
v
);
return
0
;
}
void
__exit
lkkbd_exit
(
void
)
{
serio_unregister_d
evice
(
&
lkkbd_de
v
);
serio_unregister_d
river
(
&
lkkbd_dr
v
);
}
module_init
(
lkkbd_init
);
...
...
drivers/input/keyboard/newtonkbd.c
View file @
037d476f
...
...
@@ -32,8 +32,10 @@
#include <linux/init.h>
#include <linux/serio.h>
#define DRIVER_DESC "Newton keyboard driver"
MODULE_AUTHOR
(
"Justin Cormack <j.cormack@doc.ic.ac.uk>"
);
MODULE_DESCRIPTION
(
"Newton keyboard driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
#define NKBD_KEY 0x7f
...
...
@@ -82,7 +84,7 @@ irqreturn_t nkbd_interrupt(struct serio *serio,
}
void
nkbd_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
void
nkbd_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
nkbd
*
nkbd
;
int
i
;
...
...
@@ -106,7 +108,7 @@ void nkbd_connect(struct serio *serio, struct serio_dev *dev)
nkbd
->
dev
.
private
=
nkbd
;
serio
->
private
=
nkbd
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
nkbd
);
return
;
}
...
...
@@ -138,21 +140,25 @@ void nkbd_disconnect(struct serio *serio)
kfree
(
nkbd
);
}
struct
serio_dev
nkbd_dev
=
{
struct
serio_driver
nkbd_drv
=
{
.
driver
=
{
.
name
=
"newtonkbd"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
nkbd_interrupt
,
.
connect
=
nkbd_connect
,
.
disconnect
=
nkbd_disconnect
.
disconnect
=
nkbd_disconnect
,
};
int
__init
nkbd_init
(
void
)
{
serio_register_d
evice
(
&
nkbd_de
v
);
serio_register_d
river
(
&
nkbd_dr
v
);
return
0
;
}
void
__exit
nkbd_exit
(
void
)
{
serio_unregister_d
evice
(
&
nkbd_de
v
);
serio_unregister_d
river
(
&
nkbd_dr
v
);
}
module_init
(
nkbd_init
);
...
...
drivers/input/keyboard/sunkbd.c
View file @
037d476f
...
...
@@ -37,8 +37,10 @@
#include <linux/serio.h>
#include <linux/workqueue.h>
#define DRIVER_DESC "Sun keyboard driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"Sun keyboard driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
static
unsigned
char
sunkbd_keycode
[
128
]
=
{
...
...
@@ -221,7 +223,7 @@ static void sunkbd_reinit(void *data)
* sunkbd_connect() probes for a Sun keyboard and fills the necessary structures.
*/
static
void
sunkbd_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
sunkbd_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
sunkbd
*
sunkbd
;
int
i
;
...
...
@@ -257,7 +259,7 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
serio
->
private
=
sunkbd
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
sunkbd
);
return
;
}
...
...
@@ -301,10 +303,14 @@ static void sunkbd_disconnect(struct serio *serio)
kfree
(
sunkbd
);
}
static
struct
serio_dev
sunkbd_dev
=
{
static
struct
serio_driver
sunkbd_drv
=
{
.
driver
=
{
.
name
=
"sunkbd"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
sunkbd_interrupt
,
.
connect
=
sunkbd_connect
,
.
disconnect
=
sunkbd_disconnect
.
disconnect
=
sunkbd_disconnect
,
};
/*
...
...
@@ -313,13 +319,13 @@ static struct serio_dev sunkbd_dev = {
int
__init
sunkbd_init
(
void
)
{
serio_register_d
evice
(
&
sunkbd_de
v
);
serio_register_d
river
(
&
sunkbd_dr
v
);
return
0
;
}
void
__exit
sunkbd_exit
(
void
)
{
serio_unregister_d
evice
(
&
sunkbd_de
v
);
serio_unregister_d
river
(
&
sunkbd_dr
v
);
}
module_init
(
sunkbd_init
);
...
...
drivers/input/keyboard/xtkbd.c
View file @
037d476f
...
...
@@ -34,8 +34,10 @@
#include <linux/init.h>
#include <linux/serio.h>
#define DRIVER_DESC "XT keyboard driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"XT keyboard driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
#define XTKBD_EMUL0 0xe0
...
...
@@ -86,7 +88,7 @@ irqreturn_t xtkbd_interrupt(struct serio *serio,
return
IRQ_HANDLED
;
}
void
xtkbd_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
void
xtkbd_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
xtkbd
*
xtkbd
;
int
i
;
...
...
@@ -111,7 +113,7 @@ void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
serio
->
private
=
xtkbd
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
xtkbd
);
return
;
}
...
...
@@ -143,21 +145,25 @@ void xtkbd_disconnect(struct serio *serio)
kfree
(
xtkbd
);
}
struct
serio_dev
xtkbd_dev
=
{
struct
serio_driver
xtkbd_drv
=
{
.
driver
=
{
.
name
=
"xtkbd"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
xtkbd_interrupt
,
.
connect
=
xtkbd_connect
,
.
disconnect
=
xtkbd_disconnect
.
disconnect
=
xtkbd_disconnect
,
};
int
__init
xtkbd_init
(
void
)
{
serio_register_d
evice
(
&
xtkbd_de
v
);
serio_register_d
river
(
&
xtkbd_dr
v
);
return
0
;
}
void
__exit
xtkbd_exit
(
void
)
{
serio_unregister_d
evice
(
&
xtkbd_de
v
);
serio_unregister_d
river
(
&
xtkbd_dr
v
);
}
module_init
(
xtkbd_init
);
...
...
drivers/input/misc/uinput.c
View file @
037d476f
...
...
@@ -279,6 +279,9 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait)
{
struct
uinput_device
*
udev
=
file
->
private_data
;
if
(
!
test_bit
(
UIST_CREATED
,
&
(
udev
->
state
)))
return
0
;
poll_wait
(
file
,
&
udev
->
waitq
,
wait
);
if
(
udev
->
head
!=
udev
->
tail
)
...
...
drivers/input/mouse/Kconfig
View file @
037d476f
...
...
@@ -30,8 +30,6 @@ config MOUSE_PS2
and a new verion of GPM at:
http://www.geocities.com/dt_or/gpm/gpm.html
to take advantage of the advanced features of the touchpad.
If you do not want install specialized drivers but want tapping
working please use option psmouse.proto=imps.
If unsure, say Y.
...
...
drivers/input/mouse/logips2pp.c
View file @
037d476f
...
...
@@ -277,7 +277,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
protocol
=
PSMOUSE_PS2TPP
;
}
}
else
if
(
get_model_info
(
model
)
!=
NULL
)
{
}
else
if
(
model_info
!=
NULL
)
{
param
[
0
]
=
param
[
1
]
=
param
[
2
]
=
0
;
ps2pp_cmd
(
psmouse
,
param
,
0x39
);
/* Magic knock */
...
...
drivers/input/mouse/psmouse-base.c
View file @
037d476f
...
...
@@ -22,8 +22,10 @@
#include "synaptics.h"
#include "logips2pp.h"
#define DRIVER_DESC "PS/2 mouse driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@suse.cz>"
);
MODULE_DESCRIPTION
(
"PS/2 mouse driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
static
char
*
psmouse_proto
;
...
...
@@ -142,34 +144,45 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
printk
(
KERN_WARNING
"psmouse.c: bad data from KBC -%s%s
\n
"
,
flags
&
SERIO_TIMEOUT
?
" timeout"
:
""
,
flags
&
SERIO_PARITY
?
" bad parity"
:
""
);
if
(
psmouse
->
acking
)
{
psmouse
->
ack
=
-
1
;
psmouse
->
acking
=
0
;
}
psmouse
->
pktcnt
=
0
;
psmouse
->
nak
=
1
;
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
goto
out
;
}
if
(
psmouse
->
acking
)
{
if
(
test_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
))
switch
(
data
)
{
case
PSMOUSE_RET_ACK
:
psmouse
->
ack
=
1
;
psmouse
->
nak
=
0
;
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
goto
out
;
break
;
case
PSMOUSE_RET_NAK
:
psmouse
->
ack
=
-
1
;
break
;
psmouse
->
nak
=
1
;
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
goto
out
;
default:
psmouse
->
ack
=
1
;
/* Workaround for mice which don't ACK the Get ID command */
if
(
psmouse
->
cmdcnt
)
psmouse
->
cmdbuf
[
--
psmouse
->
cmdcnt
]
=
data
;
break
;
}
psmouse
->
acking
=
0
;
psmouse
->
nak
=
0
;
/* Workaround for mice which don't ACK the Get ID command */
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
if
(
!
test_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
))
goto
out
;
}
if
(
test_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
))
{
psmouse
->
cmdcnt
--
;
psmouse
->
cmdbuf
[
psmouse
->
cmdcnt
]
=
data
;
if
(
psmouse
->
cmdcnt
==
1
)
{
if
(
data
!=
0xab
&&
data
!=
0xac
)
clear_bit
(
PSMOUSE_FLAG_ID
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
);
}
if
(
psmouse
->
cmdcnt
)
{
psmouse
->
cmdbuf
[
--
psmouse
->
cmdcnt
]
=
data
;
if
(
!
psmouse
->
cmdcnt
)
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
goto
out
;
}
...
...
@@ -242,18 +255,15 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
static
int
psmouse_sendbyte
(
struct
psmouse
*
psmouse
,
unsigned
char
byte
)
{
int
timeout
=
10000
;
/* 100 msec */
psmouse
->
ack
=
0
;
psmouse
->
acking
=
1
;
int
timeout
=
200000
;
/* 200 msec */
if
(
serio_write
(
psmouse
->
serio
,
byte
))
{
psmouse
->
acking
=
0
;
set_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
if
(
serio_write
(
psmouse
->
serio
,
byte
))
return
-
1
;
}
while
(
test_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
)
&&
timeout
--
)
udelay
(
1
);
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
while
(
!
psmouse
->
ack
&&
timeout
--
)
udelay
(
10
);
return
-
(
psmouse
->
ack
<=
0
);
return
-
psmouse
->
nak
;
}
/*
...
...
@@ -273,44 +283,60 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
if
(
command
==
PSMOUSE_CMD_RESET_BAT
)
timeout
=
4000000
;
/* 4 sec */
/* initialize cmdbuf with preset values from param */
if
(
receive
)
if
(
receive
&&
param
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
psmouse
->
cmdbuf
[(
receive
-
1
)
-
i
]
=
param
[
i
];
if
(
receive
)
{
set_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
set_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
);
set_bit
(
PSMOUSE_FLAG_ID
,
&
psmouse
->
flags
);
}
if
(
command
&
0xff
)
if
(
psmouse_sendbyte
(
psmouse
,
command
&
0xff
))
return
(
psmouse
->
cmdcnt
=
0
)
-
1
;
if
(
psmouse_sendbyte
(
psmouse
,
command
&
0xff
))
{
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
return
-
1
;
}
for
(
i
=
0
;
i
<
send
;
i
++
)
if
(
psmouse_sendbyte
(
psmouse
,
param
[
i
]))
return
(
psmouse
->
cmdcnt
=
0
)
-
1
;
if
(
psmouse_sendbyte
(
psmouse
,
param
[
i
]))
{
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
return
-
1
;
}
while
(
test_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
)
&&
timeout
--
)
{
while
(
psmouse
->
cmdcnt
&&
timeout
--
)
{
if
(
!
test_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
)
)
{
if
(
psmouse
->
cmdcnt
==
1
&&
command
==
PSMOUSE_CMD_RESET_BAT
&&
timeout
>
100000
)
/* do not run in a endless loop */
timeout
=
100000
;
/* 1 sec */
if
(
command
==
PSMOUSE_CMD_RESET_BAT
&&
timeout
>
100000
)
timeout
=
100000
;
if
(
psmouse
->
cmdcnt
==
1
&&
command
==
PSMOUSE_CMD_GETID
&&
psmouse
->
cmdbuf
[
1
]
!=
0xab
&&
psmouse
->
cmdbuf
[
1
]
!=
0xac
)
{
if
(
command
==
PSMOUSE_CMD_GETID
&&
!
test_bit
(
PSMOUSE_FLAG_ID
,
&
psmouse
->
flags
))
{
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
psmouse
->
cmdcnt
=
0
;
break
;
}
}
udelay
(
1
);
}
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
if
(
param
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
param
[
i
]
=
psmouse
->
cmdbuf
[(
receive
-
1
)
-
i
];
if
(
command
==
PSMOUSE_CMD_RESET_BAT
&&
psmouse
->
cmdcnt
==
1
)
return
0
;
if
(
psmouse
->
cmdcnt
)
return
(
psmouse
->
cmdcnt
=
0
)
-
1
;
return
-
1
;
return
0
;
}
/*
* psmouse_sliced_command() sends an extended PS/2 command to the mouse
* using sliced syntax, understood by advanced devices, such as Logitech
...
...
@@ -394,6 +420,8 @@ static int im_explorer_detect(struct psmouse *psmouse)
{
unsigned
char
param
[
2
];
intellimouse_detect
(
psmouse
);
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
200
;
...
...
@@ -626,16 +654,15 @@ static void psmouse_cleanup(struct serio *serio)
static
void
psmouse_disconnect
(
struct
serio
*
serio
)
{
struct
psmouse
*
psmouse
=
serio
->
private
;
struct
psmouse
*
psmouse
,
*
parent
;
psmouse
=
serio
->
private
;
psmouse
->
state
=
PSMOUSE_CMD_MODE
;
if
(
psmouse
->
ptport
)
{
if
(
psmouse
->
ptport
->
deactivate
)
psmouse
->
ptport
->
deactivate
(
psmouse
);
__serio_unregister_port
(
&
psmouse
->
ptport
->
serio
);
/* we have serio_sem */
kfree
(
psmouse
->
ptport
);
psmouse
->
ptport
=
NULL
;
if
(
serio
->
parent
&&
(
serio
->
type
&
SERIO_TYPE
)
==
SERIO_PS_PSTHRU
)
{
parent
=
serio
->
parent
->
private
;
if
(
parent
->
pt_deactivate
)
parent
->
pt_deactivate
(
parent
);
}
if
(
psmouse
->
disconnect
)
...
...
@@ -652,16 +679,19 @@ static void psmouse_disconnect(struct serio *serio)
* psmouse_connect() is a callback from the serio module when
* an unhandled serio port is found.
*/
static
void
psmouse_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
psmouse_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
psmouse
*
psmouse
;
struct
psmouse
*
psmouse
,
*
parent
=
NULL
;
if
((
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_8042
&&
(
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_PS_PSTHRU
)
return
;
if
(
serio
->
parent
&&
(
serio
->
type
&
SERIO_TYPE
)
==
SERIO_PS_PSTHRU
)
parent
=
serio
->
parent
->
private
;
if
(
!
(
psmouse
=
kmalloc
(
sizeof
(
struct
psmouse
),
GFP_KERNEL
)))
return
;
goto
out
;
memset
(
psmouse
,
0
,
sizeof
(
struct
psmouse
));
...
...
@@ -674,17 +704,17 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse
->
dev
.
private
=
psmouse
;
serio
->
private
=
psmouse
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
psmouse
);
serio
->
private
=
NULL
;
return
;
goto
out
;
}
if
(
psmouse_probe
(
psmouse
)
<
0
)
{
serio_close
(
serio
);
kfree
(
psmouse
);
serio
->
private
=
NULL
;
return
;
goto
out
;
}
psmouse
->
type
=
psmouse_extensions
(
psmouse
,
psmouse_max_proto
,
1
);
...
...
@@ -713,29 +743,50 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse_initialize
(
psmouse
);
if
(
psmouse
->
ptport
)
{
printk
(
KERN_INFO
"serio: %s port at %s
\n
"
,
psmouse
->
ptport
->
serio
.
name
,
psmouse
->
phys
);
__serio_register_port
(
&
psmouse
->
ptport
->
serio
);
/* we have serio_sem */
if
(
psmouse
->
ptport
->
activate
)
psmouse
->
ptport
->
activate
(
psmouse
);
}
if
(
parent
&&
parent
->
pt_activate
)
parent
->
pt_activate
(
parent
);
/*
* OK, the device is ready, we just need to activate it (turn the
* stream mode on). But if mouse has a pass-through port we don't
* want to do it yet to not disturb child detection.
* The child will activate this port when it's ready.
*/
if
(
serio
->
child
)
{
/*
* Nothing to be done here, serio core will detect that
* the driver set serio->child and will register it for us.
*/
printk
(
KERN_INFO
"serio: %s port at %s
\n
"
,
serio
->
child
->
name
,
psmouse
->
phys
);
}
else
psmouse_activate
(
psmouse
);
out:
/* If this is a pass-through port the parent awaits to be activated */
if
(
parent
)
psmouse_activate
(
parent
);
}
static
int
psmouse_reconnect
(
struct
serio
*
serio
)
{
struct
psmouse
*
psmouse
=
serio
->
private
;
struct
serio_dev
*
dev
=
serio
->
dev
;
struct
psmouse
*
parent
=
NULL
;
struct
serio_driver
*
drv
=
serio
->
drv
;
if
(
!
d
e
v
||
!
psmouse
)
{
if
(
!
d
r
v
||
!
psmouse
)
{
printk
(
KERN_DEBUG
"psmouse: reconnect request, but serio is disconnected, ignoring...
\n
"
);
return
-
1
;
}
psmouse
->
state
=
PSMOUSE_CMD_MODE
;
psmouse
->
acking
=
psmouse
->
cmdcnt
=
psmouse
->
pktcnt
=
psmouse
->
out_of_sync
=
0
;
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
psmouse
->
pktcnt
=
psmouse
->
out_of_sync
=
0
;
if
(
psmouse
->
reconnect
)
{
if
(
psmouse
->
reconnect
(
psmouse
))
return
-
1
;
...
...
@@ -748,21 +799,28 @@ static int psmouse_reconnect(struct serio *serio)
*/
psmouse_initialize
(
psmouse
);
if
(
psmouse
->
ptport
)
{
if
(
psmouse_reconnect
(
&
psmouse
->
ptport
->
serio
))
{
__serio_unregister_port
(
&
psmouse
->
ptport
->
serio
);
__serio_register_port
(
&
psmouse
->
ptport
->
serio
);
if
(
psmouse
->
ptport
->
activate
)
psmouse
->
ptport
->
activate
(
psmouse
);
}
}
if
(
serio
->
parent
&&
(
serio
->
type
&
SERIO_TYPE
)
==
SERIO_PS_PSTHRU
)
parent
=
serio
->
parent
->
private
;
if
(
parent
&&
parent
->
pt_activate
)
parent
->
pt_activate
(
parent
);
if
(
!
serio
->
child
)
psmouse_activate
(
psmouse
);
/* If this is a pass-through port the parent waits to be activated */
if
(
parent
)
psmouse_activate
(
parent
);
return
0
;
}
static
struct
serio_dev
psmouse_dev
=
{
static
struct
serio_driver
psmouse_drv
=
{
.
driver
=
{
.
name
=
"psmouse"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
psmouse_interrupt
,
.
connect
=
psmouse_connect
,
.
reconnect
=
psmouse_reconnect
,
...
...
@@ -787,13 +845,13 @@ static inline void psmouse_parse_proto(void)
int
__init
psmouse_init
(
void
)
{
psmouse_parse_proto
();
serio_register_d
evice
(
&
psmouse_de
v
);
serio_register_d
river
(
&
psmouse_dr
v
);
return
0
;
}
void
__exit
psmouse_exit
(
void
)
{
serio_unregister_d
evice
(
&
psmouse_de
v
);
serio_unregister_d
river
(
&
psmouse_dr
v
);
}
module_init
(
psmouse_init
);
...
...
drivers/input/mouse/psmouse.h
View file @
037d476f
...
...
@@ -22,6 +22,11 @@
#define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2
#define PSMOUSE_FLAG_ACK 0
/* Waiting for ACK/NAK */
#define PSMOUSE_FLAG_CMD 1
/* Waiting for command to finish */
#define PSMOUSE_FLAG_CMD1 2
/* First byte of command response */
#define PSMOUSE_FLAG_ID 3
/* First byte is not keyboard ID */
/* psmouse protocol handler return codes */
typedef
enum
{
PSMOUSE_BAD_DATA
,
...
...
@@ -29,20 +34,10 @@ typedef enum {
PSMOUSE_FULL_PACKET
}
psmouse_ret_t
;
struct
psmouse
;
struct
psmouse_ptport
{
struct
serio
serio
;
void
(
*
activate
)(
struct
psmouse
*
parent
);
void
(
*
deactivate
)(
struct
psmouse
*
parent
);
};
struct
psmouse
{
void
*
private
;
struct
input_dev
dev
;
struct
serio
*
serio
;
struct
psmouse_ptport
*
ptport
;
char
*
vendor
;
char
*
name
;
unsigned
char
cmdbuf
[
8
];
...
...
@@ -54,15 +49,18 @@ struct psmouse {
unsigned
long
last
;
unsigned
long
out_of_sync
;
unsigned
char
state
;
char
acking
;
volatile
char
ack
;
unsigned
char
nak
;
char
error
;
char
devname
[
64
];
char
phys
[
32
];
unsigned
long
flags
;
psmouse_ret_t
(
*
protocol_handler
)(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
);
int
(
*
reconnect
)(
struct
psmouse
*
psmouse
);
void
(
*
disconnect
)(
struct
psmouse
*
psmouse
);
void
(
*
pt_activate
)(
struct
psmouse
*
psmouse
);
void
(
*
pt_deactivate
)(
struct
psmouse
*
psmouse
);
};
#define PSMOUSE_PS2 1
...
...
drivers/input/mouse/sermouse.c
View file @
037d476f
...
...
@@ -37,8 +37,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Serial mouse driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"Serial mouse driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
static
char
*
sermouse_protocols
[]
=
{
"None"
,
"Mouse Systems Mouse"
,
"Sun Mouse"
,
"Microsoft Mouse"
,
...
...
@@ -237,7 +239,7 @@ static void sermouse_disconnect(struct serio *serio)
* an unhandled serio port is found.
*/
static
void
sermouse_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
sermouse_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
sermouse
*
sermouse
;
unsigned
char
c
;
...
...
@@ -279,7 +281,7 @@ static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
sermouse
->
dev
.
id
.
product
=
c
;
sermouse
->
dev
.
id
.
version
=
0x0100
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
sermouse
);
return
;
}
...
...
@@ -289,21 +291,25 @@ static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
sermouse_protocols
[
sermouse
->
type
],
serio
->
phys
);
}
static
struct
serio_dev
sermouse_dev
=
{
static
struct
serio_driver
sermouse_drv
=
{
.
driver
=
{
.
name
=
"sermouse"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
sermouse_interrupt
,
.
connect
=
sermouse_connect
,
.
disconnect
=
sermouse_disconnect
.
disconnect
=
sermouse_disconnect
,
};
int
__init
sermouse_init
(
void
)
{
serio_register_d
evice
(
&
sermouse_de
v
);
serio_register_d
river
(
&
sermouse_dr
v
);
return
0
;
}
void
__exit
sermouse_exit
(
void
)
{
serio_unregister_d
evice
(
&
sermouse_de
v
);
serio_unregister_d
river
(
&
sermouse_dr
v
);
}
module_init
(
sermouse_init
);
...
...
drivers/input/mouse/synaptics.c
View file @
037d476f
...
...
@@ -212,9 +212,9 @@ static int synaptics_set_mode(struct psmouse *psmouse, int mode)
/*****************************************************************************
* Synaptics pass-through PS/2 port support
****************************************************************************/
static
int
synaptics_pt_write
(
struct
serio
*
port
,
unsigned
char
c
)
static
int
synaptics_pt_write
(
struct
serio
*
serio
,
unsigned
char
c
)
{
struct
psmouse
*
parent
=
port
->
driver
;
struct
psmouse
*
parent
=
serio
->
parent
->
private
;
char
rate_param
=
SYN_PS_CLIENT_CMD
;
/* indicates that we want pass-through port */
if
(
psmouse_sliced_command
(
parent
,
c
))
...
...
@@ -248,7 +248,7 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
static
void
synaptics_pt_activate
(
struct
psmouse
*
psmouse
)
{
struct
psmouse
*
child
=
psmouse
->
ptport
->
serio
.
private
;
struct
psmouse
*
child
=
psmouse
->
serio
->
child
->
private
;
/* adjust the touchpad to child's choice of protocol */
if
(
child
&&
child
->
type
>=
PSMOUSE_GENPS
)
{
...
...
@@ -259,23 +259,25 @@ static void synaptics_pt_activate(struct psmouse *psmouse)
static
void
synaptics_pt_create
(
struct
psmouse
*
psmouse
)
{
struct
psmouse_ptport
*
port
;
struct
serio
*
serio
;
psmouse
->
ptport
=
port
=
kmalloc
(
sizeof
(
struct
psmouse_ptport
),
GFP_KERNEL
);
if
(
!
port
)
{
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
!
serio
)
{
printk
(
KERN_ERR
"synaptics: not enough memory to allocate pass-through port
\n
"
);
return
;
}
memset
(
port
,
0
,
sizeof
(
struct
psmouse_ptport
));
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
port
->
serio
.
type
=
SERIO_PS_PSTHRU
;
port
->
serio
.
name
=
"Synaptics pass-through"
;
port
->
serio
.
phys
=
"synaptics-pt/serio0"
;
port
->
serio
.
write
=
synaptics_pt_write
;
port
->
serio
.
driver
=
psmouse
;
serio
->
type
=
SERIO_PS_PSTHRU
;
strlcpy
(
serio
->
name
,
"Synaptics pass-through"
,
sizeof
(
serio
->
name
))
;
strlcpy
(
serio
->
phys
,
"synaptics-pt/serio0"
,
sizeof
(
serio
->
name
))
;
serio
->
write
=
synaptics_pt_write
;
serio
->
parent
=
psmouse
->
serio
;
port
->
activate
=
synaptics_pt_activate
;
psmouse
->
pt_activate
=
synaptics_pt_activate
;
psmouse
->
serio
->
child
=
serio
;
}
/*****************************************************************************
...
...
@@ -470,8 +472,8 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_r
if
(
unlikely
(
priv
->
pkt_type
==
SYN_NEWABS
))
priv
->
pkt_type
=
synaptics_detect_pkt_type
(
psmouse
);
if
(
psmouse
->
ptport
&&
psmouse
->
ptport
->
serio
.
de
v
&&
synaptics_is_pt_packet
(
psmouse
->
packet
))
synaptics_pass_pt_packet
(
&
psmouse
->
ptport
->
serio
,
psmouse
->
packet
);
if
(
psmouse
->
serio
->
child
&&
psmouse
->
serio
->
child
->
dr
v
&&
synaptics_is_pt_packet
(
psmouse
->
packet
))
synaptics_pass_pt_packet
(
psmouse
->
serio
->
child
,
psmouse
->
packet
);
else
synaptics_process_packet
(
psmouse
);
...
...
drivers/input/mouse/vsxxxaa.c
View file @
037d476f
...
...
@@ -82,8 +82,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"
MODULE_AUTHOR
(
"Jan-Benedict Glaw <jbglaw@lug-owl.de>"
);
MODULE_DESCRIPTION
(
"Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
#undef VSXXXAA_DEBUG
...
...
@@ -482,7 +484,7 @@ vsxxxaa_disconnect (struct serio *serio)
}
static
void
vsxxxaa_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
vsxxxaa_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
vsxxxaa
*
mouse
;
...
...
@@ -524,7 +526,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
mouse
->
dev
.
id
.
bustype
=
BUS_RS232
;
mouse
->
serio
=
serio
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
mouse
);
return
;
}
...
...
@@ -540,7 +542,11 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
mouse
->
name
,
mouse
->
phys
);
}
static
struct
serio_dev
vsxxxaa_dev
=
{
static
struct
serio_driver
vsxxxaa_drv
=
{
.
driver
=
{
.
name
=
"vsxxxaa"
,
},
.
description
=
DRIVER_DESC
,
.
connect
=
vsxxxaa_connect
,
.
interrupt
=
vsxxxaa_interrupt
,
.
disconnect
=
vsxxxaa_disconnect
,
...
...
@@ -549,14 +555,14 @@ static struct serio_dev vsxxxaa_dev = {
int
__init
vsxxxaa_init
(
void
)
{
serio_register_d
evice
(
&
vsxxxaa_de
v
);
serio_register_d
river
(
&
vsxxxaa_dr
v
);
return
0
;
}
void
__exit
vsxxxaa_exit
(
void
)
{
serio_unregister_d
evice
(
&
vsxxxaa_de
v
);
serio_unregister_d
river
(
&
vsxxxaa_dr
v
);
}
module_init
(
vsxxxaa_init
);
...
...
drivers/input/mousedev.c
View file @
037d476f
...
...
@@ -48,8 +48,13 @@ static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
module_param
(
yres
,
uint
,
0
);
MODULE_PARM_DESC
(
yres
,
"Vertical screen resolution"
);
static
unsigned
tap_time
=
200
;
module_param
(
tap_time
,
uint
,
0
);
MODULE_PARM_DESC
(
tap_time
,
"Tap time for touchpads in absolute mode (msecs)"
);
struct
mousedev_motion
{
int
dx
,
dy
,
dz
;
unsigned
long
buttons
;
};
struct
mousedev
{
...
...
@@ -62,21 +67,31 @@ struct mousedev {
struct
input_handle
handle
;
struct
mousedev_motion
packet
;
unsigned
long
buttons
;
unsigned
int
pkt_count
;
int
old_x
[
4
],
old_y
[
4
];
unsigned
int
touch
;
unsigned
long
touch
;
};
enum
mousedev_emul
{
MOUSEDEV_EMUL_PS2
,
MOUSEDEV_EMUL_IMPS
,
MOUSEDEV_EMUL_EXPS
}
__attribute__
((
packed
));
#define PACKET_QUEUE_LEN 16
struct
mousedev_list
{
struct
fasync_struct
*
fasync
;
struct
mousedev
*
mousedev
;
struct
list_head
node
;
int
dx
,
dy
,
dz
;
unsigned
long
buttons
;
struct
mousedev_motion
packets
[
PACKET_QUEUE_LEN
];
unsigned
int
head
,
tail
;
spinlock_t
packet_lock
;
signed
char
ps2
[
6
];
unsigned
char
ready
,
buffer
,
bufsiz
;
unsigned
char
mode
,
imexseq
,
impsseq
;
unsigned
char
imexseq
,
impsseq
;
enum
mousedev_emul
mode
;
};
#define MOUSEDEV_SEQ_LEN 6
...
...
@@ -165,30 +180,70 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
}
if
(
value
)
{
set_bit
(
index
,
&
mousedev
->
buttons
);
set_bit
(
index
,
&
mousedev_mix
.
buttons
);
set_bit
(
index
,
&
mousedev
->
packet
.
buttons
);
set_bit
(
index
,
&
mousedev_mix
.
packet
.
buttons
);
}
else
{
clear_bit
(
index
,
&
mousedev
->
buttons
);
clear_bit
(
index
,
&
mousedev_mix
.
buttons
);
clear_bit
(
index
,
&
mousedev
->
packet
.
buttons
);
clear_bit
(
index
,
&
mousedev_mix
.
packet
.
buttons
);
}
}
static
void
mousedev_notify_readers
(
struct
mousedev
*
mousedev
,
struct
mousedev_motion
*
packet
)
{
struct
mousedev_list
*
list
;
struct
mousedev_motion
*
p
;
unsigned
long
flags
;
list_for_each_entry
(
list
,
&
mousedev
->
list
,
node
)
{
list
->
dx
+=
packet
->
dx
;
list
->
dy
+=
packet
->
dy
;
list
->
dz
+=
packet
->
dz
;
list
->
buttons
=
mousedev
->
buttons
;
spin_lock_irqsave
(
&
list
->
packet_lock
,
flags
);
p
=
&
list
->
packets
[
list
->
head
];
if
(
list
->
ready
&&
p
->
buttons
!=
packet
->
buttons
)
{
unsigned
int
new_head
=
(
list
->
head
+
1
)
%
PACKET_QUEUE_LEN
;
if
(
new_head
!=
list
->
tail
)
{
p
=
&
list
->
packets
[
list
->
head
=
new_head
];
memset
(
p
,
0
,
sizeof
(
struct
mousedev_motion
));
}
}
p
->
dx
+=
packet
->
dx
;
p
->
dy
+=
packet
->
dy
;
p
->
dz
+=
packet
->
dz
;
p
->
buttons
=
mousedev
->
packet
.
buttons
;
list
->
ready
=
1
;
spin_unlock_irqrestore
(
&
list
->
packet_lock
,
flags
);
kill_fasync
(
&
list
->
fasync
,
SIGIO
,
POLL_IN
);
}
wake_up_interruptible
(
&
mousedev
->
wait
);
}
static
void
mousedev_touchpad_touch
(
struct
mousedev
*
mousedev
,
int
value
)
{
if
(
!
value
)
{
if
(
mousedev
->
touch
&&
!
time_after
(
jiffies
,
mousedev
->
touch
+
msecs_to_jiffies
(
tap_time
)))
{
/*
* Toggle left button to emulate tap.
* We rely on the fact that mousedev_mix always has 0
* motion packet so we won't mess current position.
*/
set_bit
(
0
,
&
mousedev
->
packet
.
buttons
);
set_bit
(
0
,
&
mousedev_mix
.
packet
.
buttons
);
mousedev_notify_readers
(
mousedev
,
&
mousedev_mix
.
packet
);
mousedev_notify_readers
(
&
mousedev_mix
,
&
mousedev_mix
.
packet
);
clear_bit
(
0
,
&
mousedev
->
packet
.
buttons
);
clear_bit
(
0
,
&
mousedev_mix
.
packet
.
buttons
);
}
mousedev
->
touch
=
mousedev
->
pkt_count
=
0
;
}
else
if
(
!
mousedev
->
touch
)
mousedev
->
touch
=
jiffies
;
}
static
void
mousedev_event
(
struct
input_handle
*
handle
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
struct
mousedev
*
mousedev
=
handle
->
private
;
...
...
@@ -212,12 +267,8 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
case
EV_KEY
:
if
(
value
!=
2
)
{
if
(
code
==
BTN_TOUCH
&&
test_bit
(
BTN_TOOL_FINGER
,
handle
->
dev
->
keybit
))
{
/* Handle touchpad data */
mousedev
->
touch
=
value
;
if
(
!
mousedev
->
touch
)
mousedev
->
pkt_count
=
0
;
}
if
(
code
==
BTN_TOUCH
&&
test_bit
(
BTN_TOOL_FINGER
,
handle
->
dev
->
keybit
))
mousedev_touchpad_touch
(
mousedev
,
value
);
else
mousedev_key_event
(
mousedev
,
code
,
value
);
}
...
...
@@ -237,7 +288,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
mousedev_notify_readers
(
mousedev
,
&
mousedev
->
packet
);
mousedev_notify_readers
(
&
mousedev_mix
,
&
mousedev
->
packet
);
m
emset
(
&
mousedev
->
packet
,
0
,
sizeof
(
struct
mousedev_motion
))
;
m
ousedev
->
packet
.
dx
=
mousedev
->
packet
.
dy
=
mousedev
->
packet
.
dz
=
0
;
}
break
;
}
...
...
@@ -322,6 +373,7 @@ static int mousedev_open(struct inode * inode, struct file * file)
return
-
ENOMEM
;
memset
(
list
,
0
,
sizeof
(
struct
mousedev_list
));
spin_lock_init
(
&
list
->
packet_lock
);
list
->
mousedev
=
mousedev_table
[
i
];
list_add_tail
(
&
list
->
node
,
&
mousedev_table
[
i
]
->
list
);
file
->
private_data
=
list
;
...
...
@@ -341,32 +393,56 @@ static int mousedev_open(struct inode * inode, struct file * file)
return
0
;
}
static
void
mousedev_packet
(
struct
mousedev_list
*
list
,
unsigned
char
off
)
static
inline
int
mousedev_limit_delta
(
int
delta
,
int
limit
)
{
list
->
ps2
[
off
]
=
0x08
|
((
list
->
dx
<
0
)
<<
4
)
|
((
list
->
dy
<
0
)
<<
5
)
|
(
list
->
buttons
&
0x07
);
list
->
ps2
[
off
+
1
]
=
(
list
->
dx
>
127
?
127
:
(
list
->
dx
<
-
127
?
-
127
:
list
->
dx
));
list
->
ps2
[
off
+
2
]
=
(
list
->
dy
>
127
?
127
:
(
list
->
dy
<
-
127
?
-
127
:
list
->
dy
));
list
->
dx
-=
list
->
ps2
[
off
+
1
];
list
->
dy
-=
list
->
ps2
[
off
+
2
];
list
->
bufsiz
=
off
+
3
;
if
(
list
->
mode
==
2
)
{
list
->
ps2
[
off
+
3
]
=
(
list
->
dz
>
7
?
7
:
(
list
->
dz
<
-
7
?
-
7
:
list
->
dz
));
list
->
dz
-=
list
->
ps2
[
off
+
3
];
list
->
ps2
[
off
+
3
]
=
(
list
->
ps2
[
off
+
3
]
&
0x0f
)
|
((
list
->
buttons
&
0x18
)
<<
1
);
list
->
bufsiz
++
;
}
else
{
list
->
ps2
[
off
]
|=
((
list
->
buttons
&
0x10
)
>>
3
)
|
((
list
->
buttons
&
0x08
)
>>
1
);
return
delta
>
limit
?
limit
:
(
delta
<
-
limit
?
-
limit
:
delta
);
}
static
void
mousedev_packet
(
struct
mousedev_list
*
list
,
signed
char
*
ps2_data
)
{
struct
mousedev_motion
*
p
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
list
->
packet_lock
,
flags
);
p
=
&
list
->
packets
[
list
->
tail
];
ps2_data
[
0
]
=
0x08
|
((
p
->
dx
<
0
)
<<
4
)
|
((
p
->
dy
<
0
)
<<
5
)
|
(
p
->
buttons
&
0x07
);
ps2_data
[
1
]
=
mousedev_limit_delta
(
p
->
dx
,
127
);
ps2_data
[
2
]
=
mousedev_limit_delta
(
p
->
dy
,
127
);
p
->
dx
-=
ps2_data
[
1
];
p
->
dy
-=
ps2_data
[
2
];
switch
(
list
->
mode
)
{
case
MOUSEDEV_EMUL_EXPS
:
ps2_data
[
3
]
=
mousedev_limit_delta
(
p
->
dz
,
127
);
p
->
dz
-=
ps2_data
[
3
];
ps2_data
[
3
]
=
(
ps2_data
[
3
]
&
0x0f
)
|
((
p
->
buttons
&
0x18
)
<<
1
);
list
->
bufsiz
=
4
;
break
;
case
MOUSEDEV_EMUL_IMPS
:
ps2_data
[
0
]
|=
((
p
->
buttons
&
0x10
)
>>
3
)
|
((
p
->
buttons
&
0x08
)
>>
1
);
ps2_data
[
3
]
=
mousedev_limit_delta
(
p
->
dz
,
127
);
p
->
dz
-=
ps2_data
[
3
];
list
->
bufsiz
=
4
;
break
;
case
MOUSEDEV_EMUL_PS2
:
default:
ps2_data
[
0
]
|=
((
p
->
buttons
&
0x10
)
>>
3
)
|
((
p
->
buttons
&
0x08
)
>>
1
);
p
->
dz
=
0
;
list
->
bufsiz
=
3
;
break
;
}
if
(
list
->
mode
==
1
)
{
list
->
ps2
[
off
+
3
]
=
(
list
->
dz
>
127
?
127
:
(
list
->
dz
<
-
127
?
-
127
:
list
->
dz
));
list
->
dz
-=
list
->
ps2
[
off
+
3
];
list
->
bufsiz
++
;
if
(
!
p
->
dx
&&
!
p
->
dy
&&
!
p
->
dz
)
{
if
(
list
->
tail
!=
list
->
head
)
list
->
tail
=
(
list
->
tail
+
1
)
%
PACKET_QUEUE_LEN
;
if
(
list
->
tail
==
list
->
head
)
list
->
ready
=
0
;
}
if
(
!
list
->
dx
&&
!
list
->
dy
&&
(
!
list
->
mode
||
!
list
->
dz
))
list
->
ready
=
0
;
list
->
buffer
=
list
->
bufsiz
;
spin_unlock_irqrestore
(
&
list
->
packet_lock
,
flags
);
}
...
...
@@ -384,31 +460,31 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si
if
(
c
==
mousedev_imex_seq
[
list
->
imexseq
])
{
if
(
++
list
->
imexseq
==
MOUSEDEV_SEQ_LEN
)
{
list
->
imexseq
=
0
;
list
->
mode
=
2
;
list
->
mode
=
MOUSEDEV_EMUL_EXPS
;
}
}
else
list
->
imexseq
=
0
;
if
(
c
==
mousedev_imps_seq
[
list
->
impsseq
])
{
if
(
++
list
->
impsseq
==
MOUSEDEV_SEQ_LEN
)
{
list
->
impsseq
=
0
;
list
->
mode
=
1
;
list
->
mode
=
MOUSEDEV_EMUL_IMPS
;
}
}
else
list
->
impsseq
=
0
;
list
->
ps2
[
0
]
=
0xfa
;
list
->
bufsiz
=
1
;
switch
(
c
)
{
case
0xeb
:
/* Poll */
mousedev_packet
(
list
,
1
);
mousedev_packet
(
list
,
&
list
->
ps2
[
1
]);
list
->
bufsiz
++
;
/* account for leading ACK */
break
;
case
0xf2
:
/* Get ID */
switch
(
list
->
mode
)
{
case
0
:
list
->
ps2
[
1
]
=
0
;
break
;
case
1
:
list
->
ps2
[
1
]
=
3
;
break
;
case
2
:
list
->
ps2
[
1
]
=
4
;
break
;
case
MOUSEDEV_EMUL_PS2
:
list
->
ps2
[
1
]
=
0
;
break
;
case
MOUSEDEV_EMUL_IMPS
:
list
->
ps2
[
1
]
=
3
;
break
;
case
MOUSEDEV_EMUL_EXPS
:
list
->
ps2
[
1
]
=
4
;
break
;
}
list
->
bufsiz
=
2
;
break
;
...
...
@@ -419,13 +495,15 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si
break
;
case
0xff
:
/* Reset */
list
->
impsseq
=
0
;
list
->
imexseq
=
0
;
list
->
mode
=
0
;
list
->
ps2
[
1
]
=
0xaa
;
list
->
ps2
[
2
]
=
0x00
;
list
->
impsseq
=
list
->
imexseq
=
0
;
list
->
mode
=
MOUSEDEV_EMUL_PS2
;
list
->
ps2
[
1
]
=
0xaa
;
list
->
ps2
[
2
]
=
0x00
;
list
->
bufsiz
=
3
;
break
;
default:
list
->
bufsiz
=
1
;
break
;
}
list
->
buffer
=
list
->
bufsiz
;
...
...
@@ -451,8 +529,10 @@ static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t co
if
(
retval
)
return
retval
;
if
(
!
list
->
buffer
&&
list
->
ready
)
mousedev_packet
(
list
,
0
);
if
(
!
list
->
buffer
&&
list
->
ready
)
{
mousedev_packet
(
list
,
list
->
ps2
);
list
->
buffer
=
list
->
bufsiz
;
}
if
(
count
>
list
->
buffer
)
count
=
list
->
buffer
;
...
...
drivers/input/serio/Kconfig
View file @
037d476f
...
...
@@ -130,3 +130,19 @@ config SERIO_MACEPS2
To compile this driver as a module, choose M here: the
module will be called maceps2.
config SERIO_RAW
tristate "Raw access to serio ports"
depends on SERIO
help
Say Y here if you want to have raw access to serio ports, such as
AUX ports on i8042 keyboard controller. Each serio port that is
bound to this driver will be accessible via a char device with
major 10 and dynamically allocated minor. The driver will try
allocating minor 1 (that historically corresponds to /dev/psaux)
first. To bind this driver to a serio port use sysfs interface:
echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver
To compile this driver as a module, choose M here: the
module will be called serio_raw.
drivers/input/serio/Makefile
View file @
037d476f
...
...
@@ -17,3 +17,4 @@ obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o
obj-$(CONFIG_SERIO_GSCPS2)
+=
gscps2.o
obj-$(CONFIG_SERIO_PCIPS2)
+=
pcips2.o
obj-$(CONFIG_SERIO_MACEPS2)
+=
maceps2.o
obj-$(CONFIG_SERIO_RAW)
+=
serio_raw.o
drivers/input/serio/ambakmi.c
View file @
037d476f
...
...
@@ -29,7 +29,7 @@
#define KMI_BASE (kmi->base)
struct
amba_kmi_port
{
struct
serio
io
;
struct
serio
*
io
;
struct
clk
*
clk
;
unsigned
char
*
base
;
unsigned
int
irq
;
...
...
@@ -44,7 +44,7 @@ static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
int
handled
=
IRQ_NONE
;
while
(
status
&
KMIIR_RXINTR
)
{
serio_interrupt
(
&
kmi
->
io
,
readb
(
KMIDATA
),
0
,
regs
);
serio_interrupt
(
kmi
->
io
,
readb
(
KMIDATA
),
0
,
regs
);
status
=
readb
(
KMIIR
);
handled
=
IRQ_HANDLED
;
}
...
...
@@ -54,7 +54,7 @@ static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
static
int
amba_kmi_write
(
struct
serio
*
io
,
unsigned
char
val
)
{
struct
amba_kmi_port
*
kmi
=
io
->
driver
;
struct
amba_kmi_port
*
kmi
=
io
->
port_data
;
unsigned
int
timeleft
=
10000
;
/* timeout in 100ms */
while
((
readb
(
KMISTAT
)
&
KMISTAT_TXEMPTY
)
==
0
&&
timeleft
--
)
...
...
@@ -68,7 +68,7 @@ static int amba_kmi_write(struct serio *io, unsigned char val)
static
int
amba_kmi_open
(
struct
serio
*
io
)
{
struct
amba_kmi_port
*
kmi
=
io
->
driver
;
struct
amba_kmi_port
*
kmi
=
io
->
port_data
;
unsigned
int
divisor
;
int
ret
;
...
...
@@ -105,7 +105,7 @@ static int amba_kmi_open(struct serio *io)
static
void
amba_kmi_close
(
struct
serio
*
io
)
{
struct
amba_kmi_port
*
kmi
=
io
->
driver
;
struct
amba_kmi_port
*
kmi
=
io
->
port_data
;
writeb
(
0
,
KMICR
);
...
...
@@ -117,6 +117,7 @@ static void amba_kmi_close(struct serio *io)
static
int
amba_kmi_probe
(
struct
amba_device
*
dev
,
void
*
id
)
{
struct
amba_kmi_port
*
kmi
;
struct
serio
*
io
;
int
ret
;
ret
=
amba_request_regions
(
dev
,
NULL
);
...
...
@@ -124,21 +125,25 @@ static int amba_kmi_probe(struct amba_device *dev, void *id)
return
ret
;
kmi
=
kmalloc
(
sizeof
(
struct
amba_kmi_port
),
GFP_KERNEL
);
if
(
!
kmi
)
{
io
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
!
kmi
||
!
io
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
memset
(
kmi
,
0
,
sizeof
(
struct
amba_kmi_port
));
kmi
->
io
.
type
=
SERIO_8042
;
kmi
->
io
.
write
=
amba_kmi_write
;
kmi
->
io
.
open
=
amba_kmi_open
;
kmi
->
io
.
close
=
amba_kmi_close
;
kmi
->
io
.
name
=
dev
->
dev
.
bus_id
;
kmi
->
io
.
phys
=
dev
->
dev
.
bus_id
;
kmi
->
io
.
driver
=
kmi
;
memset
(
io
,
0
,
sizeof
(
struct
serio
));
io
->
type
=
SERIO_8042
;
io
->
write
=
amba_kmi_write
;
io
->
open
=
amba_kmi_open
;
io
->
close
=
amba_kmi_close
;
strlcpy
(
io
->
name
,
dev
->
dev
.
bus_id
,
sizeof
(
io
->
name
));
strlcpy
(
io
->
phys
,
dev
->
dev
.
bus_id
,
sizeof
(
io
->
phys
));
io
->
port_data
=
kmi
;
io
->
dev
.
parent
=
&
dev
->
dev
;
kmi
->
io
=
io
;
kmi
->
base
=
ioremap
(
dev
->
res
.
start
,
KMI_SIZE
);
if
(
!
kmi
->
base
)
{
ret
=
-
ENOMEM
;
...
...
@@ -154,13 +159,14 @@ static int amba_kmi_probe(struct amba_device *dev, void *id)
kmi
->
irq
=
dev
->
irq
[
0
];
amba_set_drvdata
(
dev
,
kmi
);
serio_register_port
(
&
kmi
->
io
);
serio_register_port
(
kmi
->
io
);
return
0
;
unmap:
iounmap
(
kmi
->
base
);
out:
kfree
(
kmi
);
kfree
(
io
);
amba_release_regions
(
dev
);
return
ret
;
}
...
...
@@ -171,7 +177,7 @@ static int amba_kmi_remove(struct amba_device *dev)
amba_set_drvdata
(
dev
,
NULL
);
serio_unregister_port
(
&
kmi
->
io
);
serio_unregister_port
(
kmi
->
io
);
clk_put
(
kmi
->
clk
);
iounmap
(
kmi
->
base
);
kfree
(
kmi
);
...
...
@@ -184,7 +190,7 @@ static int amba_kmi_resume(struct amba_device *dev)
struct
amba_kmi_port
*
kmi
=
amba_get_drvdata
(
dev
);
/* kick the serio layer to rescan this port */
serio_re
scan
(
&
kmi
->
io
);
serio_re
connect
(
kmi
->
io
);
return
0
;
}
...
...
@@ -214,7 +220,7 @@ static int __init amba_kmi_init(void)
static
void
__exit
amba_kmi_exit
(
void
)
{
return
amba_driver_unregister
(
&
ambakmi_driver
);
amba_driver_unregister
(
&
ambakmi_driver
);
}
module_init
(
amba_kmi_init
);
...
...
drivers/input/serio/ct82c710.c
View file @
037d476f
...
...
@@ -43,9 +43,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION
(
"82C710 C&T mouse port chip driver"
);
MODULE_LICENSE
(
"GPL"
);
static
char
ct82c710_name
[]
=
"C&T 82c710 mouse port"
;
static
char
ct82c710_phys
[
16
];
/*
* ct82c710 interface
*/
...
...
@@ -61,10 +58,20 @@ static char ct82c710_phys[16];
#define CT82C710_IRQ 12
static
struct
serio
*
ct82c710_port
;
static
int
ct82c710_data
;
static
int
ct82c710_status
;
static
irqreturn_t
ct82c710_interrupt
(
int
cpl
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
/*
* Interrupt handler for the 82C710 mouse port. A character
* is waiting in the 82C710.
*/
static
irqreturn_t
ct82c710_interrupt
(
int
cpl
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
return
serio_interrupt
(
ct82c710_port
,
inb
(
ct82c710_data
),
0
,
regs
);
}
/*
* Wait for device to send output char and flush any input char.
...
...
@@ -139,26 +146,6 @@ static int ct82c710_write(struct serio *port, unsigned char c)
return
0
;
}
static
struct
serio
ct82c710_port
=
{
.
type
=
SERIO_8042
,
.
name
=
ct82c710_name
,
.
phys
=
ct82c710_phys
,
.
write
=
ct82c710_write
,
.
open
=
ct82c710_open
,
.
close
=
ct82c710_close
,
};
/*
* Interrupt handler for the 82C710 mouse port. A character
* is waiting in the 82C710.
*/
static
irqreturn_t
ct82c710_interrupt
(
int
cpl
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
return
serio_interrupt
(
&
ct82c710_port
,
inb
(
ct82c710_data
),
0
,
regs
);
}
/*
* See if we can find a 82C710 device. Read mouse address.
*/
...
...
@@ -183,6 +170,24 @@ static int __init ct82c710_probe(void)
return
0
;
}
static
struct
serio
*
__init
ct82c710_allocate_port
(
void
)
{
struct
serio
*
serio
;
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
open
=
ct82c710_open
;
serio
->
close
=
ct82c710_close
;
serio
->
write
=
ct82c710_write
;
strlcpy
(
serio
->
name
,
"C&T 82c710 mouse port"
,
sizeof
(
serio
->
name
));
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
"isa%04x/serio0"
,
ct82c710_data
);
}
return
serio
;
}
int
__init
ct82c710_init
(
void
)
{
if
(
ct82c710_probe
())
...
...
@@ -191,9 +196,12 @@ int __init ct82c710_init(void)
if
(
request_region
(
ct82c710_data
,
2
,
"ct82c710"
))
return
-
EBUSY
;
sprintf
(
ct82c710_phys
,
"isa%04x/serio0"
,
ct82c710_data
);
if
(
!
(
ct82c710_port
=
ct82c710_allocate_port
()))
{
release_region
(
ct82c710_data
,
2
);
return
-
ENOMEM
;
}
serio_register_port
(
&
ct82c710_port
);
serio_register_port
(
ct82c710_port
);
printk
(
KERN_INFO
"serio: C&T 82c710 mouse port at %#x irq %d
\n
"
,
ct82c710_data
,
CT82C710_IRQ
);
...
...
@@ -203,7 +211,7 @@ int __init ct82c710_init(void)
void
__exit
ct82c710_exit
(
void
)
{
serio_unregister_port
(
&
ct82c710_port
);
serio_unregister_port
(
ct82c710_port
);
release_region
(
ct82c710_data
,
2
);
}
...
...
drivers/input/serio/gscps2.c
View file @
037d476f
...
...
@@ -91,7 +91,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs);
struct
gscps2port
{
struct
list_head
node
;
struct
parisc_device
*
padev
;
struct
serio
port
;
struct
serio
*
port
;
spinlock_t
lock
;
char
*
addr
;
u8
act
,
append
;
/* position in buffer[] */
...
...
@@ -100,7 +100,6 @@ struct gscps2port {
u8
str
;
}
buffer
[
BUFFER_SIZE
+
1
];
int
id
;
char
name
[
32
];
};
/*
...
...
@@ -272,7 +271,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
rxflags
=
((
status
&
GSC_STAT_TERR
)
?
SERIO_TIMEOUT
:
0
)
|
((
status
&
GSC_STAT_PERR
)
?
SERIO_PARITY
:
0
);
serio_interrupt
(
&
ps2port
->
port
,
data
,
rxflags
,
regs
);
serio_interrupt
(
ps2port
->
port
,
data
,
rxflags
,
regs
);
}
/* while() */
...
...
@@ -288,7 +287,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
static
int
gscps2_write
(
struct
serio
*
port
,
unsigned
char
data
)
{
struct
gscps2port
*
ps2port
=
port
->
driver
;
struct
gscps2port
*
ps2port
=
port
->
port_data
;
if
(
!
gscps2_writeb_output
(
ps2port
,
data
))
{
printk
(
KERN_DEBUG
PFX
"sending byte %#x failed.
\n
"
,
data
);
...
...
@@ -304,7 +303,7 @@ static int gscps2_write(struct serio *port, unsigned char data)
static
int
gscps2_open
(
struct
serio
*
port
)
{
struct
gscps2port
*
ps2port
=
port
->
driver
;
struct
gscps2port
*
ps2port
=
port
->
port_data
;
gscps2_reset
(
ps2port
);
...
...
@@ -319,7 +318,7 @@ static int gscps2_open(struct serio *port)
static
void
gscps2_close
(
struct
serio
*
port
)
{
struct
gscps2port
*
ps2port
=
port
->
driver
;
struct
gscps2port
*
ps2port
=
port
->
port_data
;
gscps2_enable
(
ps2port
,
DISABLE
);
}
...
...
@@ -344,6 +343,7 @@ static struct serio gscps2_serio_port =
static
int
__init
gscps2_probe
(
struct
parisc_device
*
dev
)
{
struct
gscps2port
*
ps2port
;
struct
serio
*
serio
;
unsigned
long
hpa
=
dev
->
hpa
;
int
ret
;
...
...
@@ -355,34 +355,45 @@ static int __init gscps2_probe(struct parisc_device *dev)
hpa
+=
GSC_DINO_OFFSET
;
ps2port
=
kmalloc
(
sizeof
(
struct
gscps2port
),
GFP_KERNEL
);
if
(
!
ps2port
)
return
-
ENOMEM
;
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
!
ps2port
||
!
serio
)
{
ret
=
-
ENOMEM
;
goto
fail_nomem
;
}
dev_set_drvdata
(
&
dev
->
dev
,
ps2port
);
memset
(
ps2port
,
0
,
sizeof
(
struct
gscps2port
));
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
ps2port
->
port
=
serio
;
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
;
ps2port
->
id
=
readb
(
ps2port
->
addr
+
GSC_ID
)
&
0x0f
;
snprintf
(
serio
->
name
,
sizeof
(
serio
->
name
),
"GSC PS/2 %s"
,
(
ps2port
->
id
==
GSC_ID_KEYBOARD
)
?
"keyboard"
:
"mouse"
);
strlcpy
(
serio
->
phys
,
dev
->
dev
.
bus_id
,
sizeof
(
serio
->
phys
));
serio
->
idbus
=
BUS_GSC
;
serio
->
idvendor
=
PCI_VENDOR_ID_HP
;
serio
->
idproduct
=
0x0001
;
serio
->
idversion
=
0x0010
;
serio
->
type
=
SERIO_8042
;
serio
->
write
=
gscps2_write
;
serio
->
open
=
gscps2_open
;
serio
->
close
=
gscps2_close
;
serio
->
port_data
=
ps2port
;
serio
->
dev
.
parent
=
&
dev
->
dev
;
list_add_tail
(
&
ps2port
->
node
,
&
ps2port_list
);
ret
=
-
EBUSY
;
if
(
request_irq
(
dev
->
irq
,
gscps2_interrupt
,
SA_SHIRQ
,
ps2port
->
name
,
ps2port
))
if
(
request_irq
(
dev
->
irq
,
gscps2_interrupt
,
SA_SHIRQ
,
ps2port
->
port
->
name
,
ps2port
))
goto
fail_miserably
;
if
(
(
ps2port
->
id
!=
GSC_ID_KEYBOARD
)
&&
(
ps2port
->
id
!=
GSC_ID_MOUSE
)
)
{
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
;
...
...
@@ -395,12 +406,12 @@ static int __init gscps2_probe(struct parisc_device *dev)
#endif
printk
(
KERN_INFO
"serio: %s port at 0x%p irq %d @ %s
\n
"
,
ps2port
->
name
,
ps2port
->
port
->
name
,
ps2port
->
addr
,
ps2port
->
padev
->
irq
,
ps2port
->
port
.
phys
);
ps2port
->
port
->
phys
);
serio_register_port
(
&
ps2port
->
port
);
serio_register_port
(
ps2port
->
port
);
return
0
;
...
...
@@ -411,7 +422,10 @@ static int __init gscps2_probe(struct parisc_device *dev)
list_del
(
&
ps2port
->
node
);
iounmap
(
ps2port
->
addr
);
release_mem_region
(
dev
->
hpa
,
GSC_STATUS
+
4
);
fail_nomem:
kfree
(
ps2port
);
kfree
(
serio
);
return
ret
;
}
...
...
@@ -424,7 +438,7 @@ static int __devexit gscps2_remove(struct parisc_device *dev)
{
struct
gscps2port
*
ps2port
=
dev_get_drvdata
(
&
dev
->
dev
);
serio_unregister_port
(
&
ps2port
->
port
);
serio_unregister_port
(
ps2port
->
port
);
free_irq
(
dev
->
irq
,
ps2port
);
gscps2_flush
(
ps2port
);
list_del
(
&
ps2port
->
node
);
...
...
drivers/input/serio/i8042-io.h
View file @
037d476f
...
...
@@ -65,6 +65,31 @@ static inline void i8042_write_command(int val)
return
;
}
#if defined(__i386__)
#include <linux/dmi.h>
static
struct
dmi_system_id
__initdata
i8042_dmi_table
[]
=
{
{
.
ident
=
"Compaq Proliant 8500"
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Compaq"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"ProLiant"
),
DMI_MATCH
(
DMI_PRODUCT_VERSION
,
"8500"
),
},
},
{
.
ident
=
"Compaq Proliant DL760"
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Compaq"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"ProLiant"
),
DMI_MATCH
(
DMI_PRODUCT_VERSION
,
"DL760"
),
},
},
{
}
};
#endif
static
inline
int
i8042_platform_init
(
void
)
{
/*
...
...
@@ -79,6 +104,12 @@ static inline int i8042_platform_init(void)
#if !defined(__i386__) && !defined(__x86_64__)
i8042_reset
=
1
;
#endif
#if defined(__i386__)
if
(
dmi_check_system
(
i8042_dmi_table
))
i8042_noloop
=
1
;
#endif
return
0
;
}
...
...
drivers/input/serio/i8042.c
View file @
037d476f
/*
* i8042 keyboard and mouse controller driver for Linux
*
* Copyright (c) 1999-200
2
Vojtech Pavlik
* Copyright (c) 1999-200
4
Vojtech Pavlik
*/
/*
...
...
@@ -52,6 +52,10 @@ 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"
);
static
unsigned
int
i8042_noloop
;
module_param_named
(
noloop
,
i8042_noloop
,
bool
,
0
);
MODULE_PARM_DESC
(
dumbkbd
,
"Disable the AUX Loopback command while probing for the AUX port"
);
__obsolete_setup
(
"i8042_noaux"
);
__obsolete_setup
(
"i8042_nomux"
);
__obsolete_setup
(
"i8042_unlock"
);
...
...
@@ -70,19 +74,35 @@ struct i8042_values {
unsigned
char
irqen
;
unsigned
char
exists
;
signed
char
mux
;
unsigned
char
*
name
;
unsigned
char
*
phys
;
char
name
[
8
];
};
static
struct
i8042_values
i8042_kbd_values
=
{
.
disable
=
I8042_CTR_KBDDIS
,
.
irqen
=
I8042_CTR_KBDINT
,
.
mux
=
-
1
,
.
name
=
"KBD"
,
};
static
struct
i8042_values
i8042_aux_values
=
{
.
disable
=
I8042_CTR_AUXDIS
,
.
irqen
=
I8042_CTR_AUXINT
,
.
mux
=
-
1
,
.
name
=
"AUX"
,
};
static
struct
serio
i8042_kbd_port
;
static
struct
serio
i8042_aux_port
;
static
struct
i8042_values
i8042_mux_values
[
I8042_NUM_MUX_PORTS
];
static
struct
serio
*
i8042_kbd_port
;
static
struct
serio
*
i8042_aux_port
;
static
struct
serio
*
i8042_mux_port
[
I8042_NUM_MUX_PORTS
];
static
unsigned
char
i8042_initial_ctr
;
static
unsigned
char
i8042_ctr
;
static
unsigned
char
i8042_mux_open
;
static
unsigned
char
i8042_mux_present
;
static
unsigned
char
i8042_sysdev_initialized
;
static
struct
pm_dev
*
i8042_pm_dev
;
struct
timer_list
i8042_timer
;
st
atic
st
ruct
timer_list
i8042_timer
;
/*
* Shared IRQ's require a device pointer, but this driver doesn't support
...
...
@@ -95,6 +115,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/*
* The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to
* be ready for reading values from it / writing values to it.
* Called always with i8042_lock held.
*/
static
int
i8042_wait_read
(
void
)
...
...
@@ -154,6 +175,9 @@ static int i8042_command(unsigned char *param, int command)
unsigned
long
flags
;
int
retval
=
0
,
i
=
0
;
if
(
i8042_noloop
&&
command
==
I8042_CMD_AUX_LOOP
)
return
-
1
;
spin_lock_irqsave
(
&
i8042_lock
,
flags
);
retval
=
i8042_wait_write
();
...
...
@@ -214,7 +238,7 @@ static int i8042_kbd_write(struct serio *port, unsigned char c)
static
int
i8042_aux_write
(
struct
serio
*
port
,
unsigned
char
c
)
{
struct
i8042_values
*
values
=
port
->
driver
;
struct
i8042_values
*
values
=
port
->
port_data
;
int
retval
;
/*
...
...
@@ -242,7 +266,7 @@ static int i8042_aux_write(struct serio *port, unsigned char c)
static
int
i8042_activate_port
(
struct
serio
*
port
)
{
struct
i8042_values
*
values
=
port
->
driver
;
struct
i8042_values
*
values
=
port
->
port_data
;
i8042_flush
();
...
...
@@ -270,7 +294,7 @@ static int i8042_activate_port(struct serio *port)
static
int
i8042_open
(
struct
serio
*
port
)
{
struct
i8042_values
*
values
=
port
->
driver
;
struct
i8042_values
*
values
=
port
->
port_data
;
if
(
values
->
mux
!=
-
1
)
if
(
i8042_mux_open
++
)
...
...
@@ -309,7 +333,7 @@ static int i8042_open(struct serio *port)
static
void
i8042_close
(
struct
serio
*
port
)
{
struct
i8042_values
*
values
=
port
->
driver
;
struct
i8042_values
*
values
=
port
->
port_data
;
if
(
values
->
mux
!=
-
1
)
if
(
--
i8042_mux_open
)
...
...
@@ -327,52 +351,6 @@ static void i8042_close(struct serio *port)
i8042_flush
();
}
/*
* Structures for registering the devices in the serio.c module.
*/
static
struct
i8042_values
i8042_kbd_values
=
{
.
irqen
=
I8042_CTR_KBDINT
,
.
disable
=
I8042_CTR_KBDDIS
,
.
name
=
"KBD"
,
.
mux
=
-
1
,
};
static
struct
serio
i8042_kbd_port
=
{
.
type
=
SERIO_8042_XL
,
.
write
=
i8042_kbd_write
,
.
open
=
i8042_open
,
.
close
=
i8042_close
,
.
driver
=
&
i8042_kbd_values
,
.
name
=
"i8042 Kbd Port"
,
.
phys
=
I8042_KBD_PHYS_DESC
,
};
static
struct
i8042_values
i8042_aux_values
=
{
.
irqen
=
I8042_CTR_AUXINT
,
.
disable
=
I8042_CTR_AUXDIS
,
.
name
=
"AUX"
,
.
mux
=
-
1
,
};
static
struct
serio
i8042_aux_port
=
{
.
type
=
SERIO_8042
,
.
write
=
i8042_aux_write
,
.
open
=
i8042_open
,
.
close
=
i8042_close
,
.
driver
=
&
i8042_aux_values
,
.
name
=
"i8042 Aux Port"
,
.
phys
=
I8042_AUX_PHYS_DESC
,
};
static
struct
i8042_values
i8042_mux_values
[
4
];
static
struct
serio
i8042_mux_port
[
4
];
static
char
i8042_mux_names
[
4
][
32
];
static
char
i8042_mux_short
[
4
][
16
];
static
char
i8042_mux_phys
[
4
][
32
];
/*
* i8042_interrupt() is the most important function in this driver -
* it handles the interrupts from the i8042, and sends incoming bytes
...
...
@@ -419,7 +397,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dfl
&
SERIO_PARITY
?
", bad parity"
:
""
,
dfl
&
SERIO_TIMEOUT
?
", timeout"
:
""
);
serio_interrupt
(
i8042_mux_port
+
((
str
>>
6
)
&
3
)
,
data
,
dfl
,
regs
);
serio_interrupt
(
i8042_mux_port
[(
str
>>
6
)
&
3
]
,
data
,
dfl
,
regs
);
goto
irq_ret
;
}
...
...
@@ -430,14 +408,14 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dfl
&
SERIO_TIMEOUT
?
", timeout"
:
""
);
if
(
i8042_aux_values
.
exists
&&
(
str
&
I8042_STR_AUXDATA
))
{
serio_interrupt
(
&
i8042_aux_port
,
data
,
dfl
,
regs
);
serio_interrupt
(
i8042_aux_port
,
data
,
dfl
,
regs
);
goto
irq_ret
;
}
if
(
!
i8042_kbd_values
.
exists
)
goto
irq_ret
;
serio_interrupt
(
&
i8042_kbd_port
,
data
,
dfl
,
regs
);
serio_interrupt
(
i8042_kbd_port
,
data
,
dfl
,
regs
);
irq_ret:
ret
=
1
;
...
...
@@ -474,17 +452,8 @@ static int i8042_enable_mux_mode(struct i8042_values *values, unsigned char *mux
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
!=
0xa9
)
return
-
1
;
param
=
0xa4
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
==
0x5b
)
{
/*
* Do another loop test with the 0x5a value. Doing anything else upsets
* Profusion/ServerWorks OSB4 chipsets.
*/
param
=
0x5a
;
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
);
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
==
0x5b
)
return
-
1
;
}
if
(
mux_version
)
*
mux_version
=
~
param
;
...
...
@@ -639,8 +608,10 @@ static int __init i8042_check_aux(struct i8042_values *values)
* registers it, and reports to the user.
*/
static
int
__init
i8042_port_register
(
struct
i8042_values
*
values
,
struct
serio
*
port
)
static
int
__init
i8042_port_register
(
struct
serio
*
port
)
{
struct
i8042_values
*
values
=
port
->
port_data
;
values
->
exists
=
1
;
i8042_ctr
&=
~
values
->
disable
;
...
...
@@ -677,6 +648,7 @@ static void i8042_timer_func(unsigned long data)
static
int
i8042_controller_init
(
void
)
{
unsigned
long
flags
;
/*
* Test the i8042. We need to know if it thinks it's working correctly
...
...
@@ -723,12 +695,14 @@ static int i8042_controller_init(void)
* Handle keylock.
*/
spin_lock_irqsave
(
&
i8042_lock
,
flags
);
if
(
~
i8042_read_status
()
&
I8042_STR_KEYLOCK
)
{
if
(
i8042_unlock
)
i8042_ctr
|=
I8042_CTR_IGNKEYLOCK
;
else
printk
(
KERN_WARNING
"i8042.c: Warning: Keylock active.
\n
"
);
}
spin_unlock_irqrestore
(
&
i8042_lock
,
flags
);
/*
* If the chip is configured into nontranslated mode by the BIOS, don't
...
...
@@ -745,10 +719,8 @@ static int i8042_controller_init(void)
* BIOSes.
*/
if
(
i8042_direct
)
{
if
(
i8042_direct
)
i8042_ctr
&=
~
I8042_CTR_XLATE
;
i8042_kbd_port
.
type
=
SERIO_8042
;
}
/*
* Write CTR back.
...
...
@@ -802,14 +774,14 @@ void i8042_controller_cleanup(void)
*/
if
(
i8042_kbd_values
.
exists
)
serio_cleanup
(
&
i8042_kbd_port
);
serio_cleanup
(
i8042_kbd_port
);
if
(
i8042_aux_values
.
exists
)
serio_cleanup
(
&
i8042_aux_port
);
serio_cleanup
(
i8042_aux_port
);
for
(
i
=
0
;
i
<
4
;
i
++
)
for
(
i
=
0
;
i
<
I8042_NUM_MUX_PORTS
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
)
serio_cleanup
(
i8042_mux_port
+
i
);
serio_cleanup
(
i8042_mux_port
[
i
]
);
i8042_controller_reset
();
}
...
...
@@ -851,15 +823,15 @@ static int i8042_controller_resume(void)
* Reconnect anything that was connected to the ports.
*/
if
(
i8042_kbd_values
.
exists
&&
i8042_activate_port
(
&
i8042_kbd_port
)
==
0
)
serio_reconnect
(
&
i8042_kbd_port
);
if
(
i8042_kbd_values
.
exists
&&
i8042_activate_port
(
i8042_kbd_port
)
==
0
)
serio_reconnect
(
i8042_kbd_port
);
if
(
i8042_aux_values
.
exists
&&
i8042_activate_port
(
&
i8042_aux_port
)
==
0
)
serio_reconnect
(
&
i8042_aux_port
);
if
(
i8042_aux_values
.
exists
&&
i8042_activate_port
(
i8042_aux_port
)
==
0
)
serio_reconnect
(
i8042_aux_port
);
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
&&
i8042_activate_port
(
i8042_mux_port
+
i
)
==
0
)
serio_reconnect
(
i8042_mux_port
+
i
);
for
(
i
=
0
;
i
<
I8042_NUM_MUX_PORTS
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
&&
i8042_activate_port
(
i8042_mux_port
[
i
]
)
==
0
)
serio_reconnect
(
i8042_mux_port
[
i
]
);
/*
* Restart timer (for polling "stuck" data)
*/
...
...
@@ -929,18 +901,66 @@ static int i8042_pm_callback(struct pm_dev *dev, pm_request_t request, void *dum
return
0
;
}
static
void
__init
i8042_init_mux_values
(
struct
i8042_values
*
values
,
struct
serio
*
port
,
int
index
)
static
struct
serio
*
__init
i8042_allocate_kbd_port
(
void
)
{
struct
serio
*
serio
;
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
i8042_direct
?
SERIO_8042
:
SERIO_8042_XL
,
serio
->
write
=
i8042_dumbkbd
?
NULL
:
i8042_kbd_write
,
serio
->
open
=
i8042_open
,
serio
->
close
=
i8042_close
,
serio
->
port_data
=
&
i8042_kbd_values
,
strlcpy
(
serio
->
name
,
"i8042 Kbd Port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
I8042_KBD_PHYS_DESC
,
sizeof
(
serio
->
phys
));
}
return
serio
;
}
static
struct
serio
*
__init
i8042_allocate_aux_port
(
void
)
{
struct
serio
*
serio
;
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
write
=
i8042_aux_write
;
serio
->
open
=
i8042_open
;
serio
->
close
=
i8042_close
;
serio
->
port_data
=
&
i8042_aux_values
,
strlcpy
(
serio
->
name
,
"i8042 Aux Port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
I8042_AUX_PHYS_DESC
,
sizeof
(
serio
->
phys
));
}
return
serio
;
}
static
struct
serio
*
__init
i8042_allocate_mux_port
(
int
index
)
{
memcpy
(
port
,
&
i8042_aux_port
,
sizeof
(
struct
serio
));
memcpy
(
values
,
&
i8042_aux_values
,
sizeof
(
struct
i8042_values
));
sprintf
(
i8042_mux_names
[
index
],
"i8042 Aux-%d Port"
,
index
);
sprintf
(
i8042_mux_phys
[
index
],
I8042_MUX_PHYS_DESC
,
index
+
1
);
sprintf
(
i8042_mux_short
[
index
],
"AUX%d"
,
index
);
port
->
name
=
i8042_mux_names
[
index
];
port
->
phys
=
i8042_mux_phys
[
index
];
port
->
driver
=
values
;
values
->
name
=
i8042_mux_short
[
index
];
struct
serio
*
serio
;
struct
i8042_values
*
values
=
&
i8042_mux_values
[
index
];
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
*
values
=
i8042_aux_values
;
snprintf
(
values
->
name
,
sizeof
(
values
->
name
),
"AUX%d"
,
index
);
values
->
mux
=
index
;
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
write
=
i8042_aux_write
;
serio
->
open
=
i8042_open
;
serio
->
close
=
i8042_close
;
serio
->
port_data
=
values
;
snprintf
(
serio
->
name
,
sizeof
(
serio
->
name
),
"i8042 Aux-%d Port"
,
index
);
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
I8042_MUX_PHYS_DESC
,
index
+
1
);
}
return
serio
;
}
int
__init
i8042_init
(
void
)
...
...
@@ -961,20 +981,23 @@ int __init i8042_init(void)
if
(
i8042_controller_init
())
return
-
ENODEV
;
if
(
i8042_dumbkbd
)
i8042_kbd_port
.
write
=
NULL
;
if
(
!
i8042_noaux
&&
!
i8042_check_aux
(
&
i8042_aux_values
))
{
if
(
!
i8042_nomux
&&
!
i8042_check_mux
(
&
i8042_aux_values
))
for
(
i
=
0
;
i
<
4
;
i
++
)
{
i8042_init_mux_values
(
i8042_mux_values
+
i
,
i8042_mux_port
+
i
,
i
);
i8042_port_register
(
i8042_mux_values
+
i
,
i8042_mux_port
+
i
);
for
(
i
=
0
;
i
<
I8042_NUM_MUX_PORTS
;
i
++
)
{
i8042_mux_port
[
i
]
=
i8042_allocate_mux_port
(
i
);
if
(
i8042_mux_port
[
i
])
i8042_port_register
(
i8042_mux_port
[
i
]);
}
else
{
i8042_aux_port
=
i8042_allocate_aux_port
();
if
(
i8042_aux_port
)
i8042_port_register
(
i8042_aux_port
);
}
else
i8042_port_register
(
&
i8042_aux_values
,
&
i8042_aux_port
);
}
i8042_port_register
(
&
i8042_kbd_values
,
&
i8042_kbd_port
);
i8042_kbd_port
=
i8042_allocate_kbd_port
();
if
(
i8042_kbd_port
)
i8042_port_register
(
i8042_kbd_port
);
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
...
...
@@ -1009,14 +1032,15 @@ void __exit i8042_exit(void)
i8042_controller_cleanup
();
if
(
i8042_kbd_values
.
exists
)
serio_unregister_port
(
&
i8042_kbd_port
);
serio_unregister_port
(
i8042_kbd_port
);
if
(
i8042_aux_values
.
exists
)
serio_unregister_port
(
&
i8042_aux_port
);
serio_unregister_port
(
i8042_aux_port
);
for
(
i
=
0
;
i
<
4
;
i
++
)
for
(
i
=
0
;
i
<
I8042_NUM_MUX_PORTS
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
)
serio_unregister_port
(
i8042_mux_port
+
i
);
serio_unregister_port
(
i8042_mux_port
[
i
]);
del_timer_sync
(
&
i8042_timer
);
i8042_platform_exit
();
...
...
drivers/input/serio/i8042.h
View file @
037d476f
...
...
@@ -103,6 +103,13 @@
#define I8042_BUFFER_SIZE 32
/*
* Number of AUX ports on controllers supporting active multiplexing
* specification
*/
#define I8042_NUM_MUX_PORTS 4
/*
* Debug.
*/
...
...
drivers/input/serio/maceps2.c
View file @
037d476f
...
...
@@ -46,15 +46,17 @@ MODULE_LICENSE("GPL");
#define PS2_CONTROL_RX_CLOCK_ENABLE BIT(4)
/* pause reception if set to 0 */
#define PS2_CONTROL_RESET BIT(5)
/* reset */
struct
maceps2_data
{
struct
mace_ps2port
*
port
;
int
irq
;
};
static
struct
maceps2_data
port_data
[
2
];
static
struct
serio
*
maceps2_port
[
2
];
static
int
maceps2_write
(
struct
serio
*
dev
,
unsigned
char
val
)
{
struct
mace_ps2port
*
port
=
((
struct
maceps2_data
*
)
dev
->
driver
)
->
port
;
struct
mace_ps2port
*
port
=
((
struct
maceps2_data
*
)
dev
->
port_data
)
->
port
;
unsigned
int
timeout
=
MACE_PS2_TIMEOUT
;
do
{
...
...
@@ -68,11 +70,10 @@ static int maceps2_write(struct serio *dev, unsigned char val)
return
-
1
;
}
static
irqreturn_t
maceps2_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
maceps2_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
serio
*
dev
=
dev_id
;
struct
mace_ps2port
*
port
=
((
struct
maceps2_data
*
)
dev
->
driver
)
->
port
;
struct
mace_ps2port
*
port
=
((
struct
maceps2_data
*
)
dev
->
port_data
)
->
port
;
unsigned
int
byte
;
if
(
mace_read
(
port
->
status
)
&
PS2_STATUS_RX_FULL
)
{
...
...
@@ -85,7 +86,7 @@ static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
static
int
maceps2_open
(
struct
serio
*
dev
)
{
struct
maceps2_data
*
data
=
(
struct
maceps2_data
*
)
dev
->
driver
;
struct
maceps2_data
*
data
=
(
struct
maceps2_data
*
)
dev
->
port_data
;
if
(
request_irq
(
data
->
irq
,
maceps2_interrupt
,
0
,
"PS/2 port"
,
dev
))
{
printk
(
KERN_ERR
"Could not allocate PS/2 IRQ
\n
"
);
...
...
@@ -106,7 +107,7 @@ static int maceps2_open(struct serio *dev)
static
void
maceps2_close
(
struct
serio
*
dev
)
{
struct
maceps2_data
*
data
=
(
struct
maceps2_data
*
)
dev
->
driver
;
struct
maceps2_data
*
data
=
(
struct
maceps2_data
*
)
dev
->
port_data
;
mace_write
(
PS2_CONTROL_TX_CLOCK_DISABLE
|
PS2_CONTROL_RESET
,
data
->
port
->
control
);
...
...
@@ -114,46 +115,52 @@ static void maceps2_close(struct serio *dev)
free_irq
(
data
->
irq
,
dev
);
}
static
struct
maceps2_data
port0_data
,
port1_data
;
static
struct
serio
maceps2_port0
=
static
struct
serio
*
__init
maceps2_allocate_port
(
int
idx
)
{
.
type
=
SERIO_8042
,
.
open
=
maceps2_open
,
.
close
=
maceps2_close
,
.
write
=
maceps2_write
,
.
name
=
"MACE PS/2 port0"
,
.
phys
=
"mace/serio0"
,
.
driver
=
&
port0_data
,
};
struct
serio
*
serio
;
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
write
=
maceps2_write
;
serio
->
open
=
maceps2_open
;
serio
->
close
=
maceps2_close
;
snprintf
(
serio
->
name
,
sizeof
(
serio
->
name
),
"MACE PS/2 port%d"
,
idx
);
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
"mace/serio%d"
,
idx
);
serio
->
port_data
=
&
port_data
[
idx
];
}
return
serio
;
}
static
struct
serio
maceps2_port1
=
{
.
type
=
SERIO_8042
,
.
open
=
maceps2_open
,
.
close
=
maceps2_close
,
.
write
=
maceps2_write
,
.
name
=
"MACE PS/2 port1"
,
.
phys
=
"mace/serio1"
,
.
driver
=
&
port1_data
,
};
static
int
__init
maceps2_init
(
void
)
{
port0_data
.
port
=
&
mace
->
perif
.
ps2
.
keyb
;
port0_data
.
irq
=
MACEISA_KEYB_IRQ
;
port1_data
.
port
=
&
mace
->
perif
.
ps2
.
mouse
;
port1_data
.
irq
=
MACEISA_MOUSE_IRQ
;
serio_register_port
(
&
maceps2_port0
);
serio_register_port
(
&
maceps2_port1
);
port_data
[
0
].
port
=
&
mace
->
perif
.
ps2
.
keyb
;
port_data
[
0
].
irq
=
MACEISA_KEYB_IRQ
;
port_data
[
1
].
port
=
&
mace
->
perif
.
ps2
.
mouse
;
port_data
[
1
].
irq
=
MACEISA_MOUSE_IRQ
;
maceps2_port
[
0
]
=
maceps2_allocate_port
(
0
);
maceps2_port
[
1
]
=
maceps2_allocate_port
(
1
);
if
(
!
maceps2_port
[
0
]
||
!
maceps2_port
[
1
])
{
kfree
(
maceps2_port
[
0
]);
kfree
(
maceps2_port
[
1
]);
return
-
ENOMEM
;
}
serio_register_port
(
maceps2_port
[
0
]);
serio_register_port
(
maceps2_port
[
1
]);
return
0
;
}
static
void
__exit
maceps2_exit
(
void
)
{
serio_unregister_port
(
&
maceps2_port0
);
serio_unregister_port
(
&
maceps2_port1
);
serio_unregister_port
(
maceps2_port
[
0
]
);
serio_unregister_port
(
maceps2_port
[
1
]
);
}
module_init
(
maceps2_init
);
...
...
drivers/input/serio/parkbd.c
View file @
037d476f
...
...
@@ -53,9 +53,7 @@ static int parkbd_writing;
static
unsigned
long
parkbd_start
;
static
struct
pardevice
*
parkbd_dev
;
static
char
parkbd_name
[]
=
"PARKBD AT/XT keyboard adapter"
;
static
char
parkbd_phys
[
32
];
static
struct
serio
*
parkbd_port
;
static
int
parkbd_readlines
(
void
)
{
...
...
@@ -86,13 +84,6 @@ static int parkbd_write(struct serio *port, unsigned char c)
return
0
;
}
static
struct
serio
parkbd_port
=
{
.
write
=
parkbd_write
,
.
name
=
parkbd_name
,
.
phys
=
parkbd_phys
,
};
static
void
parkbd_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
...
...
@@ -125,7 +116,7 @@ static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
parkbd_buffer
|=
(
parkbd_readlines
()
>>
1
)
<<
parkbd_counter
++
;
if
(
parkbd_counter
==
parkbd_mode
+
10
)
serio_interrupt
(
&
parkbd_port
,
(
parkbd_buffer
>>
(
2
-
parkbd_mode
))
&
0xff
,
0
,
regs
);
serio_interrupt
(
parkbd_port
,
(
parkbd_buffer
>>
(
2
-
parkbd_mode
))
&
0xff
,
0
,
regs
);
}
parkbd_last
=
jiffies
;
...
...
@@ -163,16 +154,38 @@ static int parkbd_getport(void)
return
0
;
}
static
struct
serio
*
__init
parkbd_allocate_serio
(
void
)
{
struct
serio
*
serio
;
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
serio
->
type
=
parkbd_mode
;
serio
->
write
=
parkbd_write
,
strlcpy
(
serio
->
name
,
"PARKBD AT/XT keyboard adapter"
,
sizeof
(
serio
->
name
));
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
"%s/serio0"
,
parkbd_dev
->
port
->
name
);
}
return
serio
;
}
int
__init
parkbd_init
(
void
)
{
if
(
parkbd_getport
())
return
-
1
;
parkbd_writelines
(
3
);
parkbd_port
.
type
=
parkbd_mode
;
int
err
;
err
=
parkbd_getport
();
if
(
err
)
return
err
;
parkbd_port
=
parkbd_allocate_serio
();
if
(
!
parkbd_port
)
{
parport_release
(
parkbd_dev
);
return
-
ENOMEM
;
}
sprintf
(
parkbd_phys
,
"%s/serio0"
,
parkbd_dev
->
port
->
name
);
parkbd_writelines
(
3
);
serio_register_port
(
&
parkbd_port
);
serio_register_port
(
parkbd_port
);
printk
(
KERN_INFO
"serio: PARKBD %s adapter on %s
\n
"
,
parkbd_mode
?
"AT"
:
"XT"
,
parkbd_dev
->
port
->
name
);
...
...
@@ -183,7 +196,7 @@ int __init parkbd_init(void)
void
__exit
parkbd_exit
(
void
)
{
parport_release
(
parkbd_dev
);
serio_unregister_port
(
&
parkbd_port
);
serio_unregister_port
(
parkbd_port
);
parport_unregister_device
(
parkbd_dev
);
}
...
...
drivers/input/serio/pcips2.c
View file @
037d476f
...
...
@@ -38,14 +38,14 @@
#define PS2_STAT_TXEMPTY (1<<7)
struct
pcips2_data
{
struct
serio
io
;
struct
serio
*
io
;
unsigned
int
base
;
struct
pci_dev
*
dev
;
};
static
int
pcips2_write
(
struct
serio
*
io
,
unsigned
char
val
)
{
struct
pcips2_data
*
ps2if
=
io
->
driver
;
struct
pcips2_data
*
ps2if
=
io
->
port_data
;
unsigned
int
stat
;
do
{
...
...
@@ -80,7 +80,7 @@ static irqreturn_t pcips2_interrupt(int irq, void *devid, struct pt_regs *regs)
if
(
hweight8
(
scancode
)
&
1
)
flag
^=
SERIO_PARITY
;
serio_interrupt
(
&
ps2if
->
io
,
scancode
,
flag
,
regs
);
serio_interrupt
(
ps2if
->
io
,
scancode
,
flag
,
regs
);
}
while
(
1
);
return
IRQ_RETVAL
(
handled
);
}
...
...
@@ -101,7 +101,7 @@ static void pcips2_flush_input(struct pcips2_data *ps2if)
static
int
pcips2_open
(
struct
serio
*
io
)
{
struct
pcips2_data
*
ps2if
=
io
->
driver
;
struct
pcips2_data
*
ps2if
=
io
->
port_data
;
int
ret
,
val
=
0
;
outb
(
PS2_CTRL_ENABLE
,
ps2if
->
base
);
...
...
@@ -119,7 +119,7 @@ static int pcips2_open(struct serio *io)
static
void
pcips2_close
(
struct
serio
*
io
)
{
struct
pcips2_data
*
ps2if
=
io
->
driver
;
struct
pcips2_data
*
ps2if
=
io
->
port_data
;
outb
(
0
,
ps2if
->
base
);
...
...
@@ -129,6 +129,7 @@ static void pcips2_close(struct serio *io)
static
int
__devinit
pcips2_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
id
)
{
struct
pcips2_data
*
ps2if
;
struct
serio
*
serio
;
int
ret
;
ret
=
pci_enable_device
(
dev
);
...
...
@@ -142,29 +143,35 @@ static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_i
}
ps2if
=
kmalloc
(
sizeof
(
struct
pcips2_data
),
GFP_KERNEL
);
if
(
!
ps2if
)
{
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
!
ps2if
||
!
serio
)
{
ret
=
-
ENOMEM
;
goto
release
;
}
memset
(
ps2if
,
0
,
sizeof
(
struct
pcips2_data
));
ps2if
->
io
.
type
=
SERIO_8042
;
ps2if
->
io
.
write
=
pcips2_write
;
ps2if
->
io
.
open
=
pcips2_open
;
ps2if
->
io
.
close
=
pcips2_close
;
ps2if
->
io
.
name
=
pci_name
(
dev
);
ps2if
->
io
.
phys
=
dev
->
dev
.
bus_id
;
ps2if
->
io
.
driver
=
ps2if
;
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
write
=
pcips2_write
;
serio
->
open
=
pcips2_open
;
serio
->
close
=
pcips2_close
;
strlcpy
(
serio
->
name
,
pci_name
(
dev
),
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
dev
->
dev
.
bus_id
,
sizeof
(
serio
->
phys
));
serio
->
port_data
=
ps2if
;
serio
->
dev
.
parent
=
&
dev
->
dev
;
ps2if
->
io
=
serio
;
ps2if
->
dev
=
dev
;
ps2if
->
base
=
pci_resource_start
(
dev
,
0
);
pci_set_drvdata
(
dev
,
ps2if
);
serio_register_port
(
&
ps2if
->
io
);
serio_register_port
(
ps2if
->
io
);
return
0
;
release:
kfree
(
ps2if
);
kfree
(
serio
);
release_region
(
pci_resource_start
(
dev
,
0
),
pci_resource_len
(
dev
,
0
));
disable:
...
...
@@ -176,7 +183,7 @@ static void __devexit pcips2_remove(struct pci_dev *dev)
{
struct
pcips2_data
*
ps2if
=
pci_get_drvdata
(
dev
);
serio_unregister_port
(
&
ps2if
->
io
);
serio_unregister_port
(
ps2if
->
io
);
release_region
(
pci_resource_start
(
dev
,
0
),
pci_resource_len
(
dev
,
0
));
pci_set_drvdata
(
dev
,
NULL
);
...
...
drivers/input/serio/q40kbd.c
View file @
037d476f
...
...
@@ -47,43 +47,98 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION
(
"Q40 PS/2 keyboard controller driver"
);
MODULE_LICENSE
(
"GPL"
);
static
struct
serio
q40kbd_port
=
{
.
type
=
SERIO_8042
,
.
name
=
"Q40 kbd port"
,
.
phys
=
"Q40"
,
.
write
=
NULL
,
};
static
irqreturn_t
q40kbd_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
spinlock_t
q40kbd_lock
=
SPIN_LOCK_UNLOCKED
;
static
struct
serio
*
q40kbd_port
;
static
irqreturn_t
q40kbd_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
q40kbd_lock
,
flags
);
if
(
Q40_IRQ_KEYB_MASK
&
master_inb
(
INTERRUPT_REG
))
serio_interrupt
(
&
q40kbd_port
,
master_inb
(
KEYCODE_REG
),
0
,
regs
);
serio_interrupt
(
q40kbd_port
,
master_inb
(
KEYCODE_REG
),
0
,
regs
);
master_outb
(
-
1
,
KEYBOARD_UNLOCK_REG
);
spin_unlock_irqrestore
(
&
q40kbd_lock
,
flags
);
return
IRQ_HANDLED
;
}
static
int
__init
q40kbd_init
(
void
)
/*
* q40kbd_flush() flushes all data that may be in the keyboard buffers
*/
static
void
q40kbd_flush
(
void
)
{
int
maxread
=
100
;
unsigned
long
flags
;
if
(
!
MACH_IS_Q40
)
return
-
EIO
;
/* allocate the IRQ */
request_irq
(
Q40_IRQ_KEYBOARD
,
q40kbd_interrupt
,
0
,
"q40kbd"
,
NULL
);
spin_lock_irqsave
(
&
q40kbd_lock
,
flags
);
/* flush any pending input */
while
(
maxread
--
&&
(
Q40_IRQ_KEYB_MASK
&
master_inb
(
INTERRUPT_REG
)))
master_inb
(
KEYCODE_REG
);
spin_unlock_irqrestore
(
&
q40kbd_lock
,
flags
);
}
/*
* q40kbd_open() is called when a port is open by the higher layer.
* It allocates the interrupt and enables in in the chip.
*/
static
int
q40kbd_open
(
struct
serio
*
port
)
{
q40kbd_flush
();
if
(
request_irq
(
Q40_IRQ_KEYBOARD
,
q40kbd_interrupt
,
0
,
"q40kbd"
,
NULL
))
{
printk
(
KERN_ERR
"q40kbd.c: Can't get irq %d.
\n
"
,
Q40_IRQ_KEYBOARD
);
return
-
1
;
}
/* off we go */
master_outb
(
-
1
,
KEYBOARD_UNLOCK_REG
);
master_outb
(
1
,
KEY_IRQ_ENABLE_REG
);
master_outb
(
-
1
,
KEYBOARD_UNLOCK_REG
);
master_outb
(
1
,
KEY_IRQ_ENABLE_REG
);
return
0
;
}
serio_register_port
(
&
q40kbd_port
);
static
void
q40kbd_close
(
struct
serio
*
port
)
{
master_outb
(
0
,
KEY_IRQ_ENABLE_REG
);
master_outb
(
-
1
,
KEYBOARD_UNLOCK_REG
);
free_irq
(
Q40_IRQ_KEYBOARD
,
NULL
);
q40kbd_flush
();
}
static
struct
serio
*
__init
q40kbd_allocate_port
(
void
)
{
struct
serio
*
serio
;
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
open
=
q40kbd_open
;
serio
->
close
=
q40kbd_close
;
strlcpy
(
serio
->
name
,
"Q40 Kbd Port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
"Q40"
,
sizeof
(
serio
->
phys
));
}
return
serio
;
}
static
int
__init
q40kbd_init
(
void
)
{
if
(
!
MACH_IS_Q40
)
return
-
EIO
;
if
(
!
(
q40kbd_port
=
q40kbd_allocate_port
()))
return
-
ENOMEM
;
serio_register_port
(
q40kbd_port
);
printk
(
KERN_INFO
"serio: Q40 kbd registered
\n
"
);
return
0
;
...
...
@@ -91,11 +146,7 @@ static int __init q40kbd_init(void)
static
void
__exit
q40kbd_exit
(
void
)
{
master_outb
(
0
,
KEY_IRQ_ENABLE_REG
);
master_outb
(
-
1
,
KEYBOARD_UNLOCK_REG
);
serio_unregister_port
(
&
q40kbd_port
);
free_irq
(
Q40_IRQ_KEYBOARD
,
NULL
);
serio_unregister_port
(
q40kbd_port
);
}
module_init
(
q40kbd_init
);
...
...
drivers/input/serio/rpckbd.c
View file @
037d476f
...
...
@@ -44,6 +44,8 @@ MODULE_AUTHOR("Vojtech Pavlik, Russell King");
MODULE_DESCRIPTION
(
"Acorn RiscPC PS/2 keyboard controller driver"
);
MODULE_LICENSE
(
"GPL"
);
static
struct
serio
*
rpckbd_port
;
static
int
rpckbd_write
(
struct
serio
*
port
,
unsigned
char
val
)
{
while
(
!
(
iomd_readb
(
IOMD_KCTRL
)
&
(
1
<<
7
)))
...
...
@@ -101,25 +103,41 @@ static void rpckbd_close(struct serio *port)
free_irq
(
IRQ_KEYBOARDTX
,
port
);
}
static
struct
serio
rpckbd_port
=
/*
* Allocate and initialize serio structure for subsequent registration
* with serio core.
*/
static
struct
serio
*
__init
rpckbd_allocate_port
(
void
)
{
.
type
=
SERIO_8042
,
.
open
=
rpckbd_open
,
.
close
=
rpckbd_close
,
.
write
=
rpckbd_write
,
.
name
=
"RiscPC PS/2 kbd port"
,
.
phys
=
"rpckbd/serio0"
,
};
struct
serio
*
serio
;
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
write
=
rpckbd_write
;
serio
->
open
=
rpckbd_open
;
serio
->
close
=
rpckbd_close
;
strlcpy
(
serio
->
name
,
"RiscPC PS/2 kbd port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
"rpckbd/serio0"
,
sizeof
(
serio
->
phys
));
}
return
serio
;
}
static
int
__init
rpckbd_init
(
void
)
{
serio_register_port
(
&
rpckbd_port
);
if
(
!
(
rpckbd_port
=
rpckbd_allocate_port
()))
return
-
ENOMEM
;
serio_register_port
(
rpckbd_port
);
return
0
;
}
static
void
__exit
rpckbd_exit
(
void
)
{
serio_unregister_port
(
&
rpckbd_port
);
serio_unregister_port
(
rpckbd_port
);
}
module_init
(
rpckbd_init
);
...
...
drivers/input/serio/sa1111ps2.c
View file @
037d476f
...
...
@@ -26,7 +26,7 @@
#include <asm/hardware/sa1111.h>
struct
ps2if
{
struct
serio
io
;
struct
serio
*
io
;
struct
sa1111_dev
*
dev
;
unsigned
long
base
;
unsigned
int
open
;
...
...
@@ -59,7 +59,7 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
if
(
hweight8
(
scancode
)
&
1
)
flag
^=
SERIO_PARITY
;
serio_interrupt
(
&
ps2if
->
io
,
scancode
,
flag
,
regs
);
serio_interrupt
(
ps2if
->
io
,
scancode
,
flag
,
regs
);
status
=
sa1111_readl
(
ps2if
->
base
+
SA1111_PS2STAT
);
}
...
...
@@ -95,7 +95,7 @@ static irqreturn_t ps2_txint(int irq, void *dev_id, struct pt_regs *regs)
*/
static
int
ps2_write
(
struct
serio
*
io
,
unsigned
char
val
)
{
struct
ps2if
*
ps2if
=
io
->
driver
;
struct
ps2if
*
ps2if
=
io
->
port_data
;
unsigned
long
flags
;
unsigned
int
head
;
...
...
@@ -122,7 +122,7 @@ static int ps2_write(struct serio *io, unsigned char val)
static
int
ps2_open
(
struct
serio
*
io
)
{
struct
ps2if
*
ps2if
=
io
->
driver
;
struct
ps2if
*
ps2if
=
io
->
port_data
;
int
ret
;
sa1111_enable_device
(
ps2if
->
dev
);
...
...
@@ -154,7 +154,7 @@ static int ps2_open(struct serio *io)
static
void
ps2_close
(
struct
serio
*
io
)
{
struct
ps2if
*
ps2if
=
io
->
driver
;
struct
ps2if
*
ps2if
=
io
->
port_data
;
sa1111_writel
(
0
,
ps2if
->
base
+
SA1111_PS2CR
);
...
...
@@ -232,22 +232,28 @@ static int __init ps2_test(struct ps2if *ps2if)
static
int
ps2_probe
(
struct
sa1111_dev
*
dev
)
{
struct
ps2if
*
ps2if
;
struct
serio
*
serio
;
int
ret
;
ps2if
=
kmalloc
(
sizeof
(
struct
ps2if
),
GFP_KERNEL
);
if
(
!
ps2if
)
{
return
-
ENOMEM
;
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
!
ps2if
||
!
serio
)
{
ret
=
-
ENOMEM
;
goto
free
;
}
memset
(
ps2if
,
0
,
sizeof
(
struct
ps2if
));
ps2if
->
io
.
type
=
SERIO_8042
;
ps2if
->
io
.
write
=
ps2_write
;
ps2if
->
io
.
open
=
ps2_open
;
ps2if
->
io
.
close
=
ps2_close
;
ps2if
->
io
.
name
=
dev
->
dev
.
bus_id
;
ps2if
->
io
.
phys
=
dev
->
dev
.
bus_id
;
ps2if
->
io
.
driver
=
ps2if
;
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
write
=
ps2_write
;
serio
->
open
=
ps2_open
;
serio
->
close
=
ps2_close
;
strlcpy
(
serio
->
name
,
dev
->
dev
.
bus_id
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
dev
->
dev
.
bus_id
,
sizeof
(
serio
->
phys
));
serio
->
port_data
=
ps2if
;
serio
->
dev
.
parent
=
&
dev
->
dev
;
ps2if
->
io
=
serio
;
ps2if
->
dev
=
dev
;
sa1111_set_drvdata
(
dev
,
ps2if
);
...
...
@@ -292,7 +298,7 @@ static int ps2_probe(struct sa1111_dev *dev)
ps2_clear_input
(
ps2if
);
sa1111_disable_device
(
ps2if
->
dev
);
serio_register_port
(
&
ps2if
->
io
);
serio_register_port
(
ps2if
->
io
);
return
0
;
out:
...
...
@@ -302,6 +308,7 @@ static int ps2_probe(struct sa1111_dev *dev)
free:
sa1111_set_drvdata
(
dev
,
NULL
);
kfree
(
ps2if
);
kfree
(
serio
);
return
ret
;
}
...
...
@@ -312,7 +319,7 @@ static int ps2_remove(struct sa1111_dev *dev)
{
struct
ps2if
*
ps2if
=
sa1111_get_drvdata
(
dev
);
serio_unregister_port
(
&
ps2if
->
io
);
serio_unregister_port
(
ps2if
->
io
);
release_mem_region
(
dev
->
res
.
start
,
dev
->
res
.
end
-
dev
->
res
.
start
+
1
);
sa1111_set_drvdata
(
dev
,
NULL
);
...
...
drivers/input/serio/serio.c
View file @
037d476f
/*
* $Id: serio.c,v 1.15 2002/01/22 21:12:03 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* The Serio abstraction module
*
* Copyright (c) 1999-2004 Vojtech Pavlik
* Copyright (c) 2004 Dmitry Torokhov
* Copyright (c) 2003 Daniele Bellucci
*/
/*
...
...
@@ -26,10 +24,6 @@
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*
* Changes:
* 20 Jul. 2003 Daniele Bellucci <bellucda@tiscali.it>
* Minor cleanups.
*/
#include <linux/stddef.h>
...
...
@@ -50,100 +44,178 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL
(
serio_interrupt
);
EXPORT_SYMBOL
(
serio_register_port
);
EXPORT_SYMBOL
(
serio_register_port_delayed
);
EXPORT_SYMBOL
(
__serio_register_port
);
EXPORT_SYMBOL
(
serio_unregister_port
);
EXPORT_SYMBOL
(
serio_unregister_port_delayed
);
EXPORT_SYMBOL
(
__serio_unregister_port
);
EXPORT_SYMBOL
(
serio_register_device
);
EXPORT_SYMBOL
(
serio_unregister_device
);
EXPORT_SYMBOL
(
serio_register_driver
);
EXPORT_SYMBOL
(
serio_unregister_driver
);
EXPORT_SYMBOL
(
serio_open
);
EXPORT_SYMBOL
(
serio_close
);
EXPORT_SYMBOL
(
serio_rescan
);
EXPORT_SYMBOL
(
serio_reconnect
);
static
DECLARE_MUTEX
(
serio_sem
);
/* protects serio_list and serio_diriver_list */
static
LIST_HEAD
(
serio_list
);
static
LIST_HEAD
(
serio_driver_list
);
static
unsigned
int
serio_no
;
struct
bus_type
serio_bus
=
{
.
name
=
"serio"
,
};
static
void
serio_find_driver
(
struct
serio
*
serio
);
static
void
serio_create_port
(
struct
serio
*
serio
);
static
void
serio_destroy_port
(
struct
serio
*
serio
);
static
void
serio_connect_port
(
struct
serio
*
serio
,
struct
serio_driver
*
drv
);
static
void
serio_reconnect_port
(
struct
serio
*
serio
);
static
void
serio_disconnect_port
(
struct
serio
*
serio
);
static
int
serio_bind_driver
(
struct
serio
*
serio
,
struct
serio_driver
*
drv
)
{
get_driver
(
&
drv
->
driver
);
drv
->
connect
(
serio
,
drv
);
if
(
serio
->
drv
)
{
down_write
(
&
serio_bus
.
subsys
.
rwsem
);
serio
->
dev
.
driver
=
&
drv
->
driver
;
device_bind_driver
(
&
serio
->
dev
);
up_write
(
&
serio_bus
.
subsys
.
rwsem
);
return
1
;
}
put_driver
(
&
drv
->
driver
);
return
0
;
}
/* serio_find_driver() must be called with serio_sem down. */
static
void
serio_find_driver
(
struct
serio
*
serio
)
{
struct
serio_driver
*
drv
;
list_for_each_entry
(
drv
,
&
serio_driver_list
,
node
)
if
(
!
drv
->
manual_bind
)
if
(
serio_bind_driver
(
serio
,
drv
))
break
;
}
/*
* Serio event processing.
*/
struct
serio_event
{
int
type
;
struct
serio
*
serio
;
struct
list_head
node
;
};
static
DECLARE_MUTEX
(
serio_sem
);
static
LIST_HEAD
(
serio_list
);
static
LIST_HEAD
(
serio_dev_list
);
enum
serio_event_type
{
SERIO_RESCAN
,
SERIO_RECONNECT
,
SERIO_REGISTER_PORT
,
SERIO_UNREGISTER_PORT
,
};
static
spinlock_t
serio_event_lock
=
SPIN_LOCK_UNLOCKED
;
/* protects serio_event_list */
static
LIST_HEAD
(
serio_event_list
);
static
DECLARE_WAIT_QUEUE_HEAD
(
serio_wait
);
static
DECLARE_COMPLETION
(
serio_exited
);
static
int
serio_pid
;
static
void
serio_
find_dev
(
struct
serio
*
serio
)
static
void
serio_
queue_event
(
struct
serio
*
serio
,
int
event_type
)
{
struct
serio_dev
*
dev
;
unsigned
long
flags
;
struct
serio_event
*
event
;
list_for_each_entry
(
dev
,
&
serio_dev_list
,
node
)
{
if
(
serio
->
dev
)
break
;
if
(
dev
->
connect
)
dev
->
connect
(
serio
,
dev
);
}
}
spin_lock_irqsave
(
&
serio_event_lock
,
flags
);
if
((
event
=
kmalloc
(
sizeof
(
struct
serio_event
),
GFP_ATOMIC
)))
{
event
->
type
=
event_type
;
event
->
serio
=
serio
;
#define SERIO_RESCAN 1
#define SERIO_RECONNECT 2
#define SERIO_REGISTER_PORT 3
#define SERIO_UNREGISTER_PORT 4
list_add_tail
(
&
event
->
node
,
&
serio_event_list
);
wake_up
(
&
serio_wait
);
}
static
DECLARE_WAIT_QUEUE_HEAD
(
serio_wait
);
static
DECLARE_COMPLETION
(
serio_exited
);
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
}
static
void
serio_invalidate_pending_events
(
struct
serio
*
serio
)
static
struct
serio_event
*
serio_get_event
(
void
)
{
struct
serio_event
*
event
;
struct
list_head
*
node
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
serio_event_lock
,
flags
);
list_for_each_entry
(
event
,
&
serio_event_list
,
node
)
if
(
event
->
serio
==
serio
)
event
->
serio
=
NULL
;
if
(
list_empty
(
&
serio_event_list
))
{
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
return
NULL
;
}
node
=
serio_event_list
.
next
;
event
=
container_of
(
node
,
struct
serio_event
,
node
);
list_del_init
(
node
);
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
return
event
;
}
void
serio_handle_events
(
void
)
static
void
serio_handle_events
(
void
)
{
struct
list_head
*
node
,
*
next
;
struct
serio_event
*
event
;
list_for_each_safe
(
node
,
next
,
&
serio_event_list
)
{
event
=
container_of
(
node
,
struct
serio_event
,
node
);
while
((
event
=
serio_get_event
()))
{
down
(
&
serio_sem
);
if
(
event
->
serio
==
NULL
)
goto
event_done
;
switch
(
event
->
type
)
{
case
SERIO_REGISTER_PORT
:
__serio_register_port
(
event
->
serio
);
serio_create_port
(
event
->
serio
);
serio_connect_port
(
event
->
serio
,
NULL
);
break
;
case
SERIO_UNREGISTER_PORT
:
__serio_unregister_port
(
event
->
serio
);
serio_disconnect_port
(
event
->
serio
);
serio_destroy_port
(
event
->
serio
);
break
;
case
SERIO_RECONNECT
:
if
(
event
->
serio
->
dev
&&
event
->
serio
->
dev
->
reconnect
)
if
(
event
->
serio
->
dev
->
reconnect
(
event
->
serio
)
==
0
)
serio_reconnect_port
(
event
->
serio
);
break
;
/* reconnect failed - fall through to rescan */
case
SERIO_RESCAN
:
if
(
event
->
serio
->
dev
&&
event
->
serio
->
dev
->
disconnect
)
event
->
serio
->
dev
->
disconnect
(
event
->
serio
);
serio_find_dev
(
event
->
serio
);
serio_disconnect_port
(
event
->
serio
);
serio_connect_port
(
event
->
serio
,
NULL
);
break
;
default:
break
;
}
event_done:
up
(
&
serio_sem
);
kfree
(
event
);
}
}
static
void
serio_remove_pending_events
(
struct
serio
*
serio
)
{
struct
list_head
*
node
,
*
next
;
struct
serio_event
*
event
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
serio_event_lock
,
flags
);
list_for_each_safe
(
node
,
next
,
&
serio_event_list
)
{
event
=
container_of
(
node
,
struct
serio_event
,
node
);
if
(
event
->
serio
==
serio
)
{
list_del_init
(
node
);
kfree
(
event
);
}
}
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
}
static
int
serio_thread
(
void
*
nothing
)
{
lock_kernel
();
...
...
@@ -163,52 +235,211 @@ static int serio_thread(void *nothing)
complete_and_exit
(
&
serio_exited
,
0
);
}
static
void
serio_queue_event
(
struct
serio
*
serio
,
int
event_type
)
/*
* Serio port operations
*/
static
ssize_t
serio_show_description
(
struct
device
*
dev
,
char
*
buf
)
{
struct
serio_event
*
event
;
struct
serio
*
serio
=
to_serio_port
(
dev
);
return
sprintf
(
buf
,
"%s
\n
"
,
serio
->
name
);
}
static
DEVICE_ATTR
(
description
,
S_IRUGO
,
serio_show_description
,
NULL
);
if
((
event
=
kmalloc
(
sizeof
(
struct
serio_event
),
GFP_ATOMIC
)))
{
event
->
type
=
event_type
;
event
->
serio
=
serio
;
static
ssize_t
serio_show_driver
(
struct
device
*
dev
,
char
*
buf
)
{
return
sprintf
(
buf
,
"%s
\n
"
,
dev
->
driver
?
dev
->
driver
->
name
:
"(none)"
);
}
list_add_tail
(
&
event
->
node
,
&
serio_event_list
);
wake_up
(
&
serio_wait
);
static
ssize_t
serio_rebind_driver
(
struct
device
*
dev
,
const
char
*
buf
,
size_t
count
)
{
struct
serio
*
serio
=
to_serio_port
(
dev
);
struct
device_driver
*
drv
;
struct
kobject
*
k
;
int
retval
;
retval
=
down_interruptible
(
&
serio_sem
);
if
(
retval
)
return
retval
;
retval
=
count
;
if
(
!
strncmp
(
buf
,
"none"
,
count
))
{
serio_disconnect_port
(
serio
);
}
else
if
(
!
strncmp
(
buf
,
"reconnect"
,
count
))
{
serio_reconnect_port
(
serio
);
}
else
if
(
!
strncmp
(
buf
,
"rescan"
,
count
))
{
serio_disconnect_port
(
serio
);
serio_connect_port
(
serio
,
NULL
);
}
else
if
((
k
=
kset_find_obj
(
&
serio_bus
.
drivers
,
buf
))
!=
NULL
)
{
drv
=
container_of
(
k
,
struct
device_driver
,
kobj
);
serio_disconnect_port
(
serio
);
serio_connect_port
(
serio
,
to_serio_driver
(
drv
));
}
else
{
retval
=
-
EINVAL
;
}
up
(
&
serio_sem
);
return
retval
;
}
static
DEVICE_ATTR
(
driver
,
S_IWUSR
|
S_IRUGO
,
serio_show_driver
,
serio_rebind_driver
);
void
serio_rescan
(
struct
serio
*
serio
)
static
void
serio_release_port
(
struct
device
*
dev
)
{
serio_queue_event
(
serio
,
SERIO_RESCAN
);
struct
serio
*
serio
=
to_serio_port
(
dev
);
kfree
(
serio
);
module_put
(
THIS_MODULE
);
}
void
serio_reconnec
t
(
struct
serio
*
serio
)
static
void
serio_create_por
t
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_RECONNECT
);
try_module_get
(
THIS_MODULE
);
spin_lock_init
(
&
serio
->
lock
);
list_add_tail
(
&
serio
->
node
,
&
serio_list
);
snprintf
(
serio
->
dev
.
bus_id
,
sizeof
(
serio
->
dev
.
bus_id
),
"serio%d"
,
serio_no
++
);
serio
->
dev
.
bus
=
&
serio_bus
;
serio
->
dev
.
release
=
serio_release_port
;
if
(
serio
->
parent
)
serio
->
dev
.
parent
=
&
serio
->
parent
->
dev
;
device_register
(
&
serio
->
dev
);
device_create_file
(
&
serio
->
dev
,
&
dev_attr_description
);
device_create_file
(
&
serio
->
dev
,
&
dev_attr_driver
);
}
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
)
/*
* serio_destroy_port() completes deregistration process and removes
* port from the system
*/
static
void
serio_destroy_port
(
struct
serio
*
serio
)
{
irqreturn_t
ret
=
IRQ_NONE
;
struct
serio_driver
*
drv
=
serio
->
drv
;
unsigned
long
flags
;
if
(
serio
->
dev
&&
serio
->
dev
->
interrupt
)
{
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
;
serio_remove_pending_events
(
serio
);
list_del_init
(
&
serio
->
node
);
if
(
drv
)
{
drv
->
disconnect
(
serio
);
down_write
(
&
serio_bus
.
subsys
.
rwsem
);
device_release_driver
(
&
serio
->
dev
)
;
up_write
(
&
serio_bus
.
subsys
.
rwsem
);
put_driver
(
&
drv
->
driver
)
;
}
if
(
serio
->
parent
)
{
spin_lock_irqsave
(
&
serio
->
parent
->
lock
,
flags
);
serio
->
parent
->
child
=
NULL
;
spin_unlock_irqrestore
(
&
serio
->
parent
->
lock
,
flags
);
}
return
ret
;
device_unregister
(
&
serio
->
dev
);
}
/*
* serio_connect_port() tries to bind the port and possible all its
* children to appropriate drivers. If driver passed in the function will not
* try otehr drivers when binding parent port.
*/
static
void
serio_connect_port
(
struct
serio
*
serio
,
struct
serio_driver
*
drv
)
{
WARN_ON
(
serio
->
drv
);
WARN_ON
(
serio
->
child
);
if
(
drv
)
serio_bind_driver
(
serio
,
drv
);
else
serio_find_driver
(
serio
);
/* Ok, now bind children, if any */
while
(
serio
->
child
)
{
serio
=
serio
->
child
;
WARN_ON
(
serio
->
drv
);
WARN_ON
(
serio
->
child
);
serio_create_port
(
serio
);
/*
* With children we just _prefer_ passed in driver,
* but we will try other options in case preferred
* is not the one
*/
if
(
!
drv
||
!
serio_bind_driver
(
serio
,
drv
))
serio_find_driver
(
serio
);
}
}
/*
*
*/
static
void
serio_reconnect_port
(
struct
serio
*
serio
)
{
do
{
if
(
!
serio
->
drv
||
!
serio
->
drv
->
reconnect
||
serio
->
drv
->
reconnect
(
serio
))
{
serio_disconnect_port
(
serio
);
serio_connect_port
(
serio
,
NULL
);
/* Ok, old children are now gone, we are done */
break
;
}
serio
=
serio
->
child
;
}
while
(
serio
);
}
/*
* serio_disconnect_port() unbinds a port from its driver. As a side effect
* all child ports are unbound and destroyed.
*/
static
void
serio_disconnect_port
(
struct
serio
*
serio
)
{
struct
serio_driver
*
drv
=
serio
->
drv
;
struct
serio
*
s
;
if
(
serio
->
child
)
{
/*
* Children ports should be disconnected and destroyed
* first, staring with the leaf one, since we don't want
* to do recursion
*/
do
{
s
=
serio
->
child
;
}
while
(
s
->
child
);
while
(
s
!=
serio
)
{
s
=
s
->
parent
;
serio_destroy_port
(
s
->
child
);
}
}
/*
* Ok, no children left, now disconnect this port
*/
if
(
drv
)
{
drv
->
disconnect
(
serio
);
down_write
(
&
serio_bus
.
subsys
.
rwsem
);
device_release_driver
(
&
serio
->
dev
);
up_write
(
&
serio_bus
.
subsys
.
rwsem
);
put_driver
(
&
drv
->
driver
);
}
}
void
serio_rescan
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_RESCAN
);
}
void
serio_reconnect
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_RECONNECT
);
}
void
serio_register_port
(
struct
serio
*
serio
)
{
down
(
&
serio_sem
);
__serio_register_port
(
serio
);
serio_create_port
(
serio
);
serio_connect_port
(
serio
,
NULL
);
up
(
&
serio_sem
);
}
...
...
@@ -222,21 +453,11 @@ void serio_register_port_delayed(struct serio *serio)
serio_queue_event
(
serio
,
SERIO_REGISTER_PORT
);
}
/*
* Should only be called directly if serio_sem has already been taken,
* for example when unregistering a serio from other input device's
* connect() function.
*/
void
__serio_register_port
(
struct
serio
*
serio
)
{
list_add_tail
(
&
serio
->
node
,
&
serio_list
);
serio_find_dev
(
serio
);
}
void
serio_unregister_port
(
struct
serio
*
serio
)
{
down
(
&
serio_sem
);
__serio_unregister_port
(
serio
);
serio_disconnect_port
(
serio
);
serio_destroy_port
(
serio
);
up
(
&
serio_sem
);
}
...
...
@@ -250,82 +471,142 @@ void serio_unregister_port_delayed(struct serio *serio)
serio_queue_event
(
serio
,
SERIO_UNREGISTER_PORT
);
}
/*
* Should only be called directly if serio_sem has already been taken,
* for example when unregistering a serio from other input device's
* disconnect() function.
* Serio driver operations
*/
void
__serio_unregister_port
(
struct
serio
*
serio
)
static
ssize_t
serio_driver_show_description
(
struct
device_driver
*
drv
,
char
*
buf
)
{
serio_invalidate_pending_events
(
serio
);
list_del_init
(
&
serio
->
node
);
if
(
serio
->
dev
&&
serio
->
dev
->
disconnect
)
serio
->
dev
->
disconnect
(
serio
);
struct
serio_driver
*
driver
=
to_serio_driver
(
drv
);
return
sprintf
(
buf
,
"%s
\n
"
,
driver
->
description
?
driver
->
description
:
"(none)"
);
}
static
DRIVER_ATTR
(
description
,
S_IRUGO
,
serio_driver_show_description
,
NULL
);
void
serio_register_d
evice
(
struct
serio_dev
*
de
v
)
void
serio_register_d
river
(
struct
serio_driver
*
dr
v
)
{
struct
serio
*
serio
;
down
(
&
serio_sem
);
list_add_tail
(
&
dev
->
node
,
&
serio_dev_list
);
list_for_each_entry
(
serio
,
&
serio_list
,
node
)
if
(
!
serio
->
dev
&&
dev
->
connect
)
dev
->
connect
(
serio
,
dev
);
list_add_tail
(
&
drv
->
node
,
&
serio_driver_list
);
drv
->
driver
.
bus
=
&
serio_bus
;
driver_register
(
&
drv
->
driver
);
driver_create_file
(
&
drv
->
driver
,
&
driver_attr_description
);
if
(
drv
->
manual_bind
)
goto
out
;
start_over:
list_for_each_entry
(
serio
,
&
serio_list
,
node
)
{
if
(
!
serio
->
drv
)
{
serio_connect_port
(
serio
,
drv
);
/*
* if new child appeared then the list is changed,
* we need to start over
*/
if
(
serio
->
child
)
goto
start_over
;
}
}
out:
up
(
&
serio_sem
);
}
void
serio_unregister_d
evice
(
struct
serio_dev
*
de
v
)
void
serio_unregister_d
river
(
struct
serio_driver
*
dr
v
)
{
struct
serio
*
serio
;
down
(
&
serio_sem
);
list_del_init
(
&
dev
->
node
);
list_del_init
(
&
drv
->
node
);
start_over:
list_for_each_entry
(
serio
,
&
serio_list
,
node
)
{
if
(
serio
->
dev
==
dev
&&
dev
->
disconnect
)
dev
->
disconnect
(
serio
);
serio_find_dev
(
serio
);
if
(
serio
->
drv
==
drv
)
{
serio_disconnect_port
(
serio
);
serio_connect_port
(
serio
,
NULL
);
/* we could've deleted some ports, restart */
goto
start_over
;
}
}
driver_unregister
(
&
drv
->
driver
);
up
(
&
serio_sem
);
}
/* called from serio_d
ev
->connect/disconnect methods under serio_sem */
int
serio_open
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
/* called from serio_d
river
->connect/disconnect methods under serio_sem */
int
serio_open
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
serio
->
dev
=
dev
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
serio
->
lock
,
flags
);
serio
->
drv
=
drv
;
spin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
if
(
serio
->
open
&&
serio
->
open
(
serio
))
{
serio
->
dev
=
NULL
;
spin_lock_irqsave
(
&
serio
->
lock
,
flags
);
serio
->
drv
=
NULL
;
spin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
return
-
1
;
}
return
0
;
}
/* called from serio_d
ev
->connect/disconnect methods under serio_sem */
/* called from serio_d
river
->connect/disconnect methods under serio_sem */
void
serio_close
(
struct
serio
*
serio
)
{
unsigned
long
flags
;
if
(
serio
->
close
)
serio
->
close
(
serio
);
serio
->
dev
=
NULL
;
spin_lock_irqsave
(
&
serio
->
lock
,
flags
);
serio
->
drv
=
NULL
;
spin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
}
static
int
__init
serio_init
(
void
)
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
dfl
,
struct
pt_regs
*
regs
)
{
int
pid
;
unsigned
long
flags
;
irqreturn_t
ret
=
IRQ_NONE
;
spin_lock_irqsave
(
&
serio
->
lock
,
flags
);
pid
=
kernel_thread
(
serio_thread
,
NULL
,
CLONE_KERNEL
);
if
(
likely
(
serio
->
drv
))
{
ret
=
serio
->
drv
->
interrupt
(
serio
,
data
,
dfl
,
regs
);
}
else
{
if
(
!
dfl
)
{
if
((
serio
->
type
!=
SERIO_8042
&&
serio
->
type
!=
SERIO_8042_XL
)
||
(
data
==
0xaa
))
{
serio_rescan
(
serio
);
ret
=
IRQ_HANDLED
;
}
}
}
if
(
!
pid
)
{
spin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
return
ret
;
}
static
int
__init
serio_init
(
void
)
{
if
(
!
(
serio_pid
=
kernel_thread
(
serio_thread
,
NULL
,
CLONE_KERNEL
)))
{
printk
(
KERN_WARNING
"serio: Failed to start kseriod
\n
"
);
return
-
1
;
}
serio_pid
=
pid
;
bus_register
(
&
serio_bus
)
;
return
0
;
}
static
void
__exit
serio_exit
(
void
)
{
bus_unregister
(
&
serio_bus
);
kill_proc
(
serio_pid
,
SIGTERM
,
1
);
wait_for_completion
(
&
serio_exited
);
}
...
...
drivers/input/serio/serio_raw.c
0 → 100644
View file @
037d476f
/*
* Raw serio device providing access to a raw byte stream from underlying
* serio port. Closely emulates behavior of pre-2.6 /dev/psaux device
*
* Copyright (c) 2004 Dmitry Torokhov
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/major.h>
#include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/miscdevice.h>
#include <linux/wait.h>
#define DRIVER_DESC "Raw serio driver"
MODULE_AUTHOR
(
"Dmitry Torokhov <dtor@mail.ru>"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
#define SERIO_RAW_QUEUE_LEN 64
struct
serio_raw
{
unsigned
char
queue
[
SERIO_RAW_QUEUE_LEN
];
unsigned
int
tail
,
head
;
char
name
[
16
];
unsigned
int
refcnt
;
struct
serio
*
serio
;
struct
miscdevice
dev
;
wait_queue_head_t
wait
;
struct
list_head
list
;
struct
list_head
node
;
};
struct
serio_raw_list
{
struct
fasync_struct
*
fasync
;
struct
serio_raw
*
serio_raw
;
struct
list_head
node
;
};
static
DECLARE_MUTEX
(
serio_raw_sem
);
static
LIST_HEAD
(
serio_raw_list
);
static
unsigned
int
serio_raw_no
;
/*********************************************************************
* Interface with userspace (file operations) *
*********************************************************************/
static
int
serio_raw_fasync
(
int
fd
,
struct
file
*
file
,
int
on
)
{
struct
serio_raw_list
*
list
=
file
->
private_data
;
int
retval
;
retval
=
fasync_helper
(
fd
,
file
,
on
,
&
list
->
fasync
);
return
retval
<
0
?
retval
:
0
;
}
static
struct
serio_raw
*
serio_raw_locate
(
int
minor
)
{
struct
serio_raw
*
serio_raw
;
list_for_each_entry
(
serio_raw
,
&
serio_raw_list
,
node
)
{
if
(
serio_raw
->
dev
.
minor
==
minor
)
return
serio_raw
;
}
return
NULL
;
}
static
int
serio_raw_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
serio_raw
*
serio_raw
;
struct
serio_raw_list
*
list
;
int
retval
=
0
;
retval
=
down_interruptible
(
&
serio_raw_sem
);
if
(
retval
)
return
retval
;
if
(
!
(
serio_raw
=
serio_raw_locate
(
iminor
(
inode
))))
{
retval
=
-
ENODEV
;
goto
out
;
}
if
(
!
serio_raw
->
serio
)
{
retval
=
-
ENODEV
;
goto
out
;
}
if
(
!
(
list
=
kmalloc
(
sizeof
(
struct
serio_raw_list
),
GFP_KERNEL
)))
{
retval
=
-
ENOMEM
;
goto
out
;
}
memset
(
list
,
0
,
sizeof
(
struct
serio_raw_list
));
list
->
serio_raw
=
serio_raw
;
file
->
private_data
=
list
;
serio_raw
->
refcnt
++
;
list_add_tail
(
&
list
->
node
,
&
serio_raw
->
list
);
out:
up
(
&
serio_raw_sem
);
return
retval
;
}
static
int
serio_raw_cleanup
(
struct
serio_raw
*
serio_raw
)
{
if
(
--
serio_raw
->
refcnt
==
0
)
{
misc_deregister
(
&
serio_raw
->
dev
);
list_del_init
(
&
serio_raw
->
node
);
kfree
(
serio_raw
);
return
1
;
}
return
0
;
}
static
int
serio_raw_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
serio_raw_list
*
list
=
file
->
private_data
;
struct
serio_raw
*
serio_raw
=
list
->
serio_raw
;
down
(
&
serio_raw_sem
);
serio_raw_fasync
(
-
1
,
file
,
0
);
serio_raw_cleanup
(
serio_raw
);
up
(
&
serio_raw_sem
);
return
0
;
}
static
int
serio_raw_fetch_byte
(
struct
serio_raw
*
serio_raw
,
char
*
c
)
{
unsigned
long
flags
;
int
empty
;
spin_lock_irqsave
(
&
serio_raw
->
serio
->
lock
,
flags
);
empty
=
serio_raw
->
head
==
serio_raw
->
tail
;
if
(
!
empty
)
{
*
c
=
serio_raw
->
queue
[
serio_raw
->
tail
];
serio_raw
->
tail
=
(
serio_raw
->
tail
+
1
)
%
SERIO_RAW_QUEUE_LEN
;
}
spin_unlock_irqrestore
(
&
serio_raw
->
serio
->
lock
,
flags
);
return
!
empty
;
}
static
ssize_t
serio_raw_read
(
struct
file
*
file
,
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
struct
serio_raw_list
*
list
=
file
->
private_data
;
struct
serio_raw
*
serio_raw
=
list
->
serio_raw
;
char
c
;
ssize_t
retval
=
0
;
if
(
!
serio_raw
->
serio
)
return
-
ENODEV
;
if
(
serio_raw
->
head
==
serio_raw
->
tail
&&
(
file
->
f_flags
&
O_NONBLOCK
))
return
-
EAGAIN
;
retval
=
wait_event_interruptible
(
list
->
serio_raw
->
wait
,
serio_raw
->
head
!=
serio_raw
->
tail
||
!
serio_raw
->
serio
);
if
(
retval
)
return
retval
;
if
(
!
serio_raw
->
serio
)
return
-
ENODEV
;
while
(
retval
<
count
&&
serio_raw_fetch_byte
(
serio_raw
,
&
c
))
{
if
(
put_user
(
c
,
buffer
++
))
return
-
EFAULT
;
retval
++
;
}
return
retval
;
}
static
ssize_t
serio_raw_write
(
struct
file
*
file
,
const
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
struct
serio_raw_list
*
list
=
file
->
private_data
;
ssize_t
written
=
0
;
int
retval
;
unsigned
char
c
;
retval
=
down_interruptible
(
&
serio_raw_sem
);
if
(
retval
)
return
retval
;
if
(
!
list
->
serio_raw
->
serio
)
{
retval
=
-
ENODEV
;
goto
out
;
}
if
(
count
>
32
)
count
=
32
;
while
(
count
--
)
{
if
(
get_user
(
c
,
buffer
++
))
{
retval
=
-
EFAULT
;
goto
out
;
}
if
(
serio_write
(
list
->
serio_raw
->
serio
,
c
))
{
retval
=
-
EIO
;
goto
out
;
}
written
++
;
};
out:
up
(
&
serio_raw_sem
);
return
written
;
}
static
unsigned
int
serio_raw_poll
(
struct
file
*
file
,
poll_table
*
wait
)
{
struct
serio_raw_list
*
list
=
file
->
private_data
;
poll_wait
(
file
,
&
list
->
serio_raw
->
wait
,
wait
);
if
(
list
->
serio_raw
->
head
!=
list
->
serio_raw
->
tail
)
return
POLLIN
|
POLLRDNORM
;
return
0
;
}
struct
file_operations
serio_raw_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
serio_raw_open
,
.
release
=
serio_raw_release
,
.
read
=
serio_raw_read
,
.
write
=
serio_raw_write
,
.
poll
=
serio_raw_poll
,
.
fasync
=
serio_raw_fasync
,
};
/*********************************************************************
* Interface with serio port *
*********************************************************************/
static
irqreturn_t
serio_raw_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
dfl
,
struct
pt_regs
*
regs
)
{
struct
serio_raw
*
serio_raw
=
serio
->
private
;
struct
serio_raw_list
*
list
;
unsigned
int
head
=
serio_raw
->
head
;
/* we are holding serio->lock here so we are prootected */
serio_raw
->
queue
[
head
]
=
data
;
head
=
(
head
+
1
)
%
SERIO_RAW_QUEUE_LEN
;
if
(
likely
(
head
!=
serio_raw
->
tail
))
{
serio_raw
->
head
=
head
;
list_for_each_entry
(
list
,
&
serio_raw
->
list
,
node
)
kill_fasync
(
&
list
->
fasync
,
SIGIO
,
POLL_IN
);
wake_up_interruptible
(
&
serio_raw
->
wait
);
}
return
IRQ_HANDLED
;
}
static
void
serio_raw_connect
(
struct
serio
*
serio
,
struct
serio_driver
*
drv
)
{
struct
serio_raw
*
serio_raw
;
int
err
;
if
((
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_8042
)
return
;
if
(
!
(
serio_raw
=
kmalloc
(
sizeof
(
struct
serio_raw
),
GFP_KERNEL
)))
{
printk
(
KERN_ERR
"serio_raw.c: can't allocate memory for a device
\n
"
);
return
;
}
down
(
&
serio_raw_sem
);
memset
(
serio_raw
,
0
,
sizeof
(
struct
serio_raw
));
snprintf
(
serio_raw
->
name
,
sizeof
(
serio_raw
->
name
),
"serio_raw%d"
,
serio_raw_no
++
);
serio_raw
->
refcnt
=
1
;
serio_raw
->
serio
=
serio
;
INIT_LIST_HEAD
(
&
serio_raw
->
list
);
init_waitqueue_head
(
&
serio_raw
->
wait
);
serio
->
private
=
serio_raw
;
if
(
serio_open
(
serio
,
drv
))
goto
out_free
;
list_add_tail
(
&
serio_raw
->
node
,
&
serio_raw_list
);
serio_raw
->
dev
.
minor
=
PSMOUSE_MINOR
;
serio_raw
->
dev
.
name
=
serio_raw
->
name
;
serio_raw
->
dev
.
fops
=
&
serio_raw_fops
;
err
=
misc_register
(
&
serio_raw
->
dev
);
if
(
err
)
{
serio_raw
->
dev
.
minor
=
MISC_DYNAMIC_MINOR
;
err
=
misc_register
(
&
serio_raw
->
dev
);
}
if
(
err
)
{
printk
(
KERN_INFO
"serio_raw: failed to register raw access device for %s
\n
"
,
serio
->
phys
);
goto
out_close
;
}
printk
(
KERN_INFO
"serio_raw: raw access enabled on %s (%s, minor %d)
\n
"
,
serio
->
phys
,
serio_raw
->
name
,
serio_raw
->
dev
.
minor
);
goto
out
;
out_close:
serio_close
(
serio
);
list_del_init
(
&
serio_raw
->
node
);
out_free:
serio
->
private
=
NULL
;
kfree
(
serio_raw
);
out:
up
(
&
serio_raw_sem
);
}
static
int
serio_raw_reconnect
(
struct
serio
*
serio
)
{
struct
serio_raw
*
serio_raw
=
serio
->
private
;
struct
serio_driver
*
drv
=
serio
->
drv
;
if
(
!
drv
||
!
serio_raw
)
{
printk
(
KERN_DEBUG
"serio_raw: reconnect request, but serio is disconnected, ignoring...
\n
"
);
return
-
1
;
}
/*
* Nothing needs to be done here, we just need this method to
* keep the same device.
*/
return
0
;
}
static
void
serio_raw_disconnect
(
struct
serio
*
serio
)
{
struct
serio_raw
*
serio_raw
;
down
(
&
serio_raw_sem
);
serio_raw
=
serio
->
private
;
serio_close
(
serio
);
serio
->
private
=
NULL
;
serio_raw
->
serio
=
NULL
;
if
(
!
serio_raw_cleanup
(
serio_raw
))
wake_up_interruptible
(
&
serio_raw
->
wait
);
up
(
&
serio_raw_sem
);
}
static
struct
serio_driver
serio_raw_drv
=
{
.
driver
=
{
.
name
=
"serio_raw"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
serio_raw_interrupt
,
.
connect
=
serio_raw_connect
,
.
reconnect
=
serio_raw_reconnect
,
.
disconnect
=
serio_raw_disconnect
,
.
manual_bind
=
1
,
};
int
__init
serio_raw_init
(
void
)
{
serio_register_driver
(
&
serio_raw_drv
);
return
0
;
}
void
__exit
serio_raw_exit
(
void
)
{
serio_unregister_driver
(
&
serio_raw_drv
);
}
module_init
(
serio_raw_init
);
module_exit
(
serio_raw_exit
);
drivers/input/serio/serport.c
View file @
037d476f
...
...
@@ -31,28 +31,25 @@ MODULE_ALIAS_LDISC(N_MOUSE);
struct
serport
{
struct
tty_struct
*
tty
;
wait_queue_head_t
wait
;
struct
serio
serio
;
struct
serio
*
serio
;
unsigned
long
flags
;
char
phys
[
32
];
};
char
serport_name
[]
=
"Serial port"
;
/*
* Callback functions from the serio code.
*/
static
int
serport_serio_write
(
struct
serio
*
serio
,
unsigned
char
data
)
{
struct
serport
*
serport
=
serio
->
driver
;
struct
serport
*
serport
=
serio
->
port_data
;
return
-
(
serport
->
tty
->
driver
->
write
(
serport
->
tty
,
0
,
&
data
,
1
)
!=
1
);
}
static
void
serport_serio_close
(
struct
serio
*
serio
)
{
struct
serport
*
serport
=
serio
->
driver
;
struct
serport
*
serport
=
serio
->
port_data
;
serport
->
serio
.
type
=
0
;
serport
->
serio
->
type
=
0
;
wake_up_interruptible
(
&
serport
->
wait
);
}
...
...
@@ -64,26 +61,30 @@ static void serport_serio_close(struct serio *serio)
static
int
serport_ldisc_open
(
struct
tty_struct
*
tty
)
{
struct
serport
*
serport
;
struct
serio
*
serio
;
char
name
[
64
];
serport
=
kmalloc
(
sizeof
(
struct
serport
),
GFP_KERNEL
);
if
(
unlikely
(
!
serport
))
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
unlikely
(
!
serport
||
!
serio
))
{
kfree
(
serport
);
kfree
(
serio
);
return
-
ENOMEM
;
memset
(
serport
,
0
,
sizeof
(
struct
serport
));
}
memset
(
serport
,
0
,
sizeof
(
struct
serport
));
serport
->
serio
=
serio
;
set_bit
(
TTY_DO_WRITE_WAKEUP
,
&
tty
->
flags
);
serport
->
tty
=
tty
;
tty
->
disc_data
=
serport
;
snprintf
(
serport
->
phys
,
sizeof
(
serport
->
phys
),
"%s/serio0"
,
tty_name
(
tty
,
name
));
serport
->
serio
.
name
=
serport_name
;
serport
->
serio
.
phys
=
serport
->
phys
;
serport
->
serio
.
type
=
SERIO_RS232
;
serport
->
serio
.
write
=
serport_serio_write
;
serport
->
serio
.
close
=
serport_serio_close
;
serport
->
serio
.
driver
=
serport
;
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
strlcpy
(
serio
->
name
,
"Serial port"
,
sizeof
(
serio
->
name
));
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
"%s/serio0"
,
tty_name
(
tty
,
name
));
serio
->
type
=
SERIO_RS232
;
serio
->
write
=
serport_serio_write
;
serio
->
close
=
serport_serio_close
;
serio
->
port_data
=
serport
;
init_waitqueue_head
(
&
serport
->
wait
);
...
...
@@ -114,7 +115,7 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c
struct
serport
*
serport
=
(
struct
serport
*
)
tty
->
disc_data
;
int
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
serio_interrupt
(
&
serport
->
serio
,
cp
[
i
],
0
,
NULL
);
serio_interrupt
(
serport
->
serio
,
cp
[
i
],
0
,
NULL
);
}
/*
...
...
@@ -142,10 +143,10 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
if
(
test_and_set_bit
(
SERPORT_BUSY
,
&
serport
->
flags
))
return
-
EBUSY
;
serio_register_port
(
&
serport
->
serio
);
serio_register_port
(
serport
->
serio
);
printk
(
KERN_INFO
"serio: Serial port %s
\n
"
,
tty_name
(
tty
,
name
));
wait_event_interruptible
(
serport
->
wait
,
!
serport
->
serio
.
type
);
serio_unregister_port
(
&
serport
->
serio
);
wait_event_interruptible
(
serport
->
wait
,
!
serport
->
serio
->
type
);
serio_unregister_port
(
serport
->
serio
);
clear_bit
(
SERPORT_BUSY
,
&
serport
->
flags
);
...
...
@@ -161,7 +162,7 @@ static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsi
struct
serport
*
serport
=
(
struct
serport
*
)
tty
->
disc_data
;
if
(
cmd
==
SPIOCSTYPE
)
return
get_user
(
serport
->
serio
.
type
,
(
unsigned
long
__user
*
)
arg
);
return
get_user
(
serport
->
serio
->
type
,
(
unsigned
long
__user
*
)
arg
);
return
-
EINVAL
;
}
...
...
@@ -170,7 +171,7 @@ static void serport_ldisc_write_wakeup(struct tty_struct * tty)
{
struct
serport
*
sp
=
(
struct
serport
*
)
tty
->
disc_data
;
serio_d
ev_write_wakeup
(
&
sp
->
serio
);
serio_d
rv_write_wakeup
(
sp
->
serio
);
}
/*
...
...
drivers/input/touchscreen/gunze.c
View file @
037d476f
...
...
@@ -36,8 +36,10 @@
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "Gunze AHL-51S touchscreen driver"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>"
);
MODULE_DESCRIPTION
(
"Gunze AHL-51S touchscreen driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
/*
...
...
@@ -111,7 +113,7 @@ static void gunze_disconnect(struct serio *serio)
* and if yes, registers it as an input device.
*/
static
void
gunze_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
gunze_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
gunze
*
gunze
;
...
...
@@ -142,7 +144,7 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev)
gunze
->
dev
.
id
.
product
=
0x0051
;
gunze
->
dev
.
id
.
version
=
0x0100
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
kfree
(
gunze
);
return
;
}
...
...
@@ -156,7 +158,11 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev)
* The serio device structure.
*/
static
struct
serio_dev
gunze_dev
=
{
static
struct
serio_driver
gunze_drv
=
{
.
driver
=
{
.
name
=
"gunze"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
gunze_interrupt
,
.
connect
=
gunze_connect
,
.
disconnect
=
gunze_disconnect
,
...
...
@@ -168,13 +174,13 @@ static struct serio_dev gunze_dev = {
int
__init
gunze_init
(
void
)
{
serio_register_d
evice
(
&
gunze_de
v
);
serio_register_d
river
(
&
gunze_dr
v
);
return
0
;
}
void
__exit
gunze_exit
(
void
)
{
serio_unregister_d
evice
(
&
gunze_de
v
);
serio_unregister_d
river
(
&
gunze_dr
v
);
}
module_init
(
gunze_init
);
...
...
drivers/input/touchscreen/h3600_ts_input.c
View file @
037d476f
...
...
@@ -45,8 +45,10 @@
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>
#define DRIVER_DESC "H3600 touchscreen driver"
MODULE_AUTHOR
(
"James Simmons <jsimmons@transvirtual.com>"
);
MODULE_DESCRIPTION
(
"H3600 touchscreen driver"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
/*
...
...
@@ -373,7 +375,7 @@ static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
* new serio device. It looks whether it was registered as a H3600 touchscreen
* and if yes, registers it as an input device.
*/
static
void
h3600ts_connect
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
)
static
void
h3600ts_connect
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
)
{
struct
h3600_dev
*
ts
;
...
...
@@ -441,7 +443,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
ts
->
dev
.
id
.
product
=
0x0666
;
/* FIXME !!! We can ask the hardware */
ts
->
dev
.
id
.
version
=
0x0100
;
if
(
serio_open
(
serio
,
d
e
v
))
{
if
(
serio_open
(
serio
,
d
r
v
))
{
free_irq
(
IRQ_GPIO_BITSY_ACTION_BUTTON
,
ts
);
free_irq
(
IRQ_GPIO_BITSY_NPOWER_BUTTON
,
ts
);
kfree
(
ts
);
...
...
@@ -478,7 +480,11 @@ static void h3600ts_disconnect(struct serio *serio)
* The serio device structure.
*/
static
struct
serio_dev
h3600ts_dev
=
{
static
struct
serio_driver
h3600ts_drv
=
{
.
driver
=
{
.
name
=
"h3600ts"
,
},
.
description
=
DRIVER_DESC
,
.
interrupt
=
h3600ts_interrupt
,
.
connect
=
h3600ts_connect
,
.
disconnect
=
h3600ts_disconnect
,
...
...
@@ -490,13 +496,13 @@ static struct serio_dev h3600ts_dev = {
static
int
__init
h3600ts_init
(
void
)
{
serio_register_d
evice
(
&
h3600ts_de
v
);
serio_register_d
river
(
&
h3600ts_dr
v
);
return
0
;
}
static
void
__exit
h3600ts_exit
(
void
)
{
serio_unregister_d
evice
(
&
h3600ts_de
v
);
serio_unregister_d
river
(
&
h3600ts_dr
v
);
}
module_init
(
h3600ts_init
);
...
...
drivers/input/tsdev.c
View file @
037d476f
...
...
@@ -3,9 +3,17 @@
*
* Copyright (c) 2001 "Crazy" james Simmons
*
* Input driver to Touchscreen device driver module.
* Compaq touchscreen protocol driver. The protocol emulated by this driver
* is obsolete; for new programs use the tslib library which can read directly
* from evdev and perform dejittering, variance filtering and calibration -
* all in user space, not at kernel level. The meaning of this driver is
* to allow usage of newer input drivers with old applications that use the
* old /dev/h3600_ts and /dev/h3600_tsraw devices.
*
* Sponsored by Transvirtual Technology
* 09-Apr-2004: Andrew Zabolotny <zap@homelink.ru>
* Fixed to actually work, not just output random numbers.
* Added support for both h3600_ts and h3600_tsraw protocol
* emulation.
*/
/*
...
...
@@ -24,11 +32,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <jsimmons@
transvirtual.com
>.
* e-mail - mail your message to <jsimmons@
infradead.org
>.
*/
#define TSDEV_MINOR_BASE 128
#define TSDEV_MINORS 32
/* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */
#define TSDEV_MINOR_MASK 15
#define TSDEV_BUFFER_SIZE 64
#include <linux/slab.h>
...
...
@@ -52,48 +62,84 @@
#define CONFIG_INPUT_TSDEV_SCREEN_Y 320
#endif
/* This driver emulates both protocols of the old h3600_ts and h3600_tsraw
* devices. The first one must output X/Y data in 'cooked' format, e.g.
* filtered, dejittered and calibrated. Second device just outputs raw
* data received from the hardware.
*
* This driver doesn't support filtering and dejittering; it supports only
* calibration. Filtering and dejittering must be done in the low-level
* driver, if needed, because it may gain additional benefits from knowing
* the low-level details, the nature of noise and so on.
*
* The driver precomputes a calibration matrix given the initial xres and
* yres values (quite innacurate for most touchscreens) that will result
* in a more or less expected range of output values. The driver supports
* the TS_SET_CAL ioctl, which will replace the calibration matrix with a
* new one, supposedly generated from the values taken from the raw device.
*/
MODULE_AUTHOR
(
"James Simmons <jsimmons@transvirtual.com>"
);
MODULE_DESCRIPTION
(
"Input driver to touchscreen converter"
);
MODULE_LICENSE
(
"GPL"
);
static
int
xres
=
CONFIG_INPUT_TSDEV_SCREEN_X
;
module_param
(
xres
,
uint
,
0
);
MODULE_PARM_DESC
(
xres
,
"Horizontal screen resolution"
);
MODULE_PARM_DESC
(
xres
,
"Horizontal screen resolution
(can be negative for X-mirror)
"
);
static
int
yres
=
CONFIG_INPUT_TSDEV_SCREEN_Y
;
module_param
(
yres
,
uint
,
0
);
MODULE_PARM_DESC
(
yres
,
"Vertical screen resolution"
);
MODULE_PARM_DESC
(
yres
,
"Vertical screen resolution (can be negative for Y-mirror)"
);
/* From Compaq's Touch Screen Specification version 0.2 (draft) */
struct
ts_event
{
short
pressure
;
short
x
;
short
y
;
short
millisecs
;
};
struct
ts_calibration
{
int
xscale
;
int
xtrans
;
int
yscale
;
int
ytrans
;
int
xyswap
;
};
struct
tsdev
{
int
exist
;
int
open
;
int
minor
;
char
name
[
16
];
char
name
[
8
];
wait_queue_head_t
wait
;
struct
list_head
list
;
struct
input_handle
handle
;
int
x
,
y
,
pressure
;
struct
ts_calibration
cal
;
};
/* From Compaq's Touch Screen Specification version 0.2 (draft) */
typedef
struct
{
short
pressure
;
short
x
;
short
y
;
short
millisecs
;
}
TS_EVENT
;
struct
tsdev_list
{
struct
fasync_struct
*
fasync
;
struct
list_head
node
;
struct
tsdev
*
tsdev
;
int
head
,
tail
;
int
oldx
,
oldy
,
pendown
;
TS_EVENT
event
[
TSDEV_BUFFER_SIZE
]
;
struct
ts_event
event
[
TSDEV_BUFFER_SIZE
]
;
int
raw
;
};
/* The following ioctl codes are defined ONLY for backward compatibility.
* Don't use tsdev for new developement; use the tslib library instead.
* Touchscreen calibration is a fully userspace task.
*/
/* Use 'f' as magic number */
#define IOC_H3600_TS_MAGIC 'f'
#define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration)
#define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration)
static
struct
input_handler
tsdev_handler
;
static
struct
tsdev
*
tsdev_table
[
TSDEV_MINORS
];
static
struct
tsdev
*
tsdev_table
[
TSDEV_MINORS
/
2
];
static
int
tsdev_fasync
(
int
fd
,
struct
file
*
file
,
int
on
)
{
...
...
@@ -109,13 +155,16 @@ static int tsdev_open(struct inode *inode, struct file *file)
int
i
=
iminor
(
inode
)
-
TSDEV_MINOR_BASE
;
struct
tsdev_list
*
list
;
if
(
i
>=
TSDEV_MINORS
||
!
tsdev_table
[
i
])
if
(
i
>=
TSDEV_MINORS
||
!
tsdev_table
[
i
&
TSDEV_MINOR_MASK
])
return
-
ENODEV
;
if
(
!
(
list
=
kmalloc
(
sizeof
(
struct
tsdev_list
),
GFP_KERNEL
)))
return
-
ENOMEM
;
memset
(
list
,
0
,
sizeof
(
struct
tsdev_list
));
list
->
raw
=
(
i
>=
TSDEV_MINORS
/
2
)
?
1
:
0
;
i
&=
TSDEV_MINOR_MASK
;
list
->
tsdev
=
tsdev_table
[
i
];
list_add_tail
(
&
list
->
node
,
&
tsdev_table
[
i
]
->
list
);
file
->
private_data
=
list
;
...
...
@@ -169,11 +218,13 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
if
(
!
list
->
tsdev
->
exist
)
return
-
ENODEV
;
while
(
list
->
head
!=
list
->
tail
&&
retval
+
sizeof
(
TS_EVENT
)
<=
count
)
{
if
(
copy_to_user
(
buffer
+
retval
,
list
->
event
+
list
->
tail
,
sizeof
(
TS_EVENT
)))
while
(
list
->
head
!=
list
->
tail
&&
retval
+
sizeof
(
struct
ts_event
)
<=
count
)
{
if
(
copy_to_user
(
buffer
+
retval
,
list
->
event
+
list
->
tail
,
sizeof
(
struct
ts_event
)))
return
-
EFAULT
;
list
->
tail
=
(
list
->
tail
+
1
)
&
(
TSDEV_BUFFER_SIZE
-
1
);
retval
+=
sizeof
(
TS_EVENT
);
retval
+=
sizeof
(
struct
ts_event
);
}
return
retval
;
...
...
@@ -193,22 +244,27 @@ static unsigned int tsdev_poll(struct file *file, poll_table * wait)
static
int
tsdev_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
/*
struct
tsdev_list
*
list
=
file
->
private_data
;
struct tsdev *evdev = list->tsdev;
struct input_dev *dev = tsdev->handle.dev;
int retval;
struct
tsdev
*
tsdev
=
list
->
tsdev
;
int
retval
=
0
;
switch
(
cmd
)
{
case HHEHE:
return 0;
case hjff:
return 0;
case
TS_GET_CAL
:
if
(
copy_to_user
((
void
*
)
arg
,
&
tsdev
->
cal
,
sizeof
(
struct
ts_calibration
)))
retval
=
-
EFAULT
;
break
;
case
TS_SET_CAL
:
if
(
copy_from_user
(
&
tsdev
->
cal
,
(
void
*
)
arg
,
sizeof
(
struct
ts_calibration
)))
retval
=
-
EFAULT
;
break
;
default:
return 0;
retval
=
-
EINVAL
;
break
;
}
*/
return
-
EINVAL
;
return
retval
;
}
struct
file_operations
tsdev_fops
=
{
...
...
@@ -227,33 +283,23 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
struct
tsdev
*
tsdev
=
handle
->
private
;
struct
tsdev_list
*
list
;
struct
timeval
time
;
int
size
;
list_for_each_entry
(
list
,
&
tsdev
->
list
,
node
)
{
switch
(
type
)
{
case
EV_ABS
:
switch
(
code
)
{
case
ABS_X
:
if
(
!
list
->
pendown
)
return
;
size
=
handle
->
dev
->
absmax
[
ABS_X
]
-
handle
->
dev
->
absmin
[
ABS_X
];
if
(
size
>
0
)
list
->
oldx
=
((
value
-
handle
->
dev
->
absmin
[
ABS_X
])
*
xres
/
size
);
else
list
->
oldx
=
((
value
-
handle
->
dev
->
absmin
[
ABS_X
]));
tsdev
->
x
=
value
;
break
;
case
ABS_Y
:
if
(
!
list
->
pendown
)
return
;
size
=
handle
->
dev
->
absmax
[
ABS_Y
]
-
handle
->
dev
->
absmin
[
ABS_Y
];
if
(
size
>
0
)
list
->
oldy
=
((
value
-
handle
->
dev
->
absmin
[
ABS_Y
])
*
yres
/
size
);
else
list
->
oldy
=
((
value
-
handle
->
dev
->
absmin
[
ABS_Y
]));
tsdev
->
y
=
value
;
break
;
case
ABS_PRESSURE
:
list
->
pendown
=
((
value
>
handle
->
dev
->
absmin
[
ABS_PRESSURE
]))
?
value
-
handle
->
dev
->
absmin
[
ABS_PRESSURE
]
:
0
;
if
(
value
>
handle
->
dev
->
absmax
[
ABS_PRESSURE
])
value
=
handle
->
dev
->
absmax
[
ABS_PRESSURE
];
value
-=
handle
->
dev
->
absmin
[
ABS_PRESSURE
];
if
(
value
<
0
)
value
=
0
;
tsdev
->
pressure
=
value
;
break
;
}
break
;
...
...
@@ -261,22 +307,18 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
case
EV_REL
:
switch
(
code
)
{
case
REL_X
:
if
(
!
list
->
pendown
)
return
;
list
->
oldx
+=
value
;
if
(
list
->
oldx
<
0
)
list
->
oldx
=
0
;
else
if
(
list
->
oldx
>
xres
)
list
->
oldx
=
xres
;
tsdev
->
x
+=
value
;
if
(
tsdev
->
x
<
0
)
tsdev
->
x
=
0
;
else
if
(
tsdev
->
x
>
xres
)
tsdev
->
x
=
xres
;
break
;
case
REL_Y
:
if
(
!
list
->
pendown
)
return
;
list
->
oldy
+=
value
;
if
(
list
->
oldy
<
0
)
list
->
oldy
=
0
;
else
if
(
list
->
oldy
>
xres
)
list
->
oldy
=
xres
;
tsdev
->
y
+=
value
;
if
(
tsdev
->
y
<
0
)
tsdev
->
y
=
0
;
else
if
(
tsdev
->
y
>
yres
)
tsdev
->
y
=
yres
;
break
;
}
break
;
...
...
@@ -285,24 +327,41 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
if
(
code
==
BTN_TOUCH
||
code
==
BTN_MOUSE
)
{
switch
(
value
)
{
case
0
:
list
->
pendown
=
0
;
tsdev
->
pressure
=
0
;
break
;
case
1
:
if
(
!
list
->
pendown
)
list
->
pendown
=
1
;
if
(
!
tsdev
->
pressure
)
tsdev
->
pressure
=
1
;
break
;
case
2
:
return
;
}
}
else
return
;
}
break
;
}
if
(
type
!=
EV_SYN
||
code
!=
SYN_REPORT
)
return
;
list_for_each_entry
(
list
,
&
tsdev
->
list
,
node
)
{
int
x
,
y
,
tmp
;
do_gettimeofday
(
&
time
);
list
->
event
[
list
->
head
].
millisecs
=
time
.
tv_usec
/
100
;
list
->
event
[
list
->
head
].
pressure
=
list
->
pendown
;
list
->
event
[
list
->
head
].
x
=
list
->
oldx
;
list
->
event
[
list
->
head
].
y
=
list
->
oldy
;
list
->
event
[
list
->
head
].
pressure
=
tsdev
->
pressure
;
x
=
tsdev
->
x
;
y
=
tsdev
->
y
;
/* Calibration */
if
(
!
list
->
raw
)
{
x
=
((
x
*
tsdev
->
cal
.
xscale
)
>>
8
)
+
tsdev
->
cal
.
xtrans
;
y
=
((
y
*
tsdev
->
cal
.
yscale
)
>>
8
)
+
tsdev
->
cal
.
ytrans
;
if
(
tsdev
->
cal
.
xyswap
)
{
tmp
=
x
;
x
=
y
;
y
=
tmp
;
}
}
list
->
event
[
list
->
head
].
x
=
x
;
list
->
event
[
list
->
head
].
y
=
y
;
list
->
head
=
(
list
->
head
+
1
)
&
(
TSDEV_BUFFER_SIZE
-
1
);
kill_fasync
(
&
list
->
fasync
,
SIGIO
,
POLL_IN
);
}
...
...
@@ -314,11 +373,11 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
struct
input_device_id
*
id
)
{
struct
tsdev
*
tsdev
;
int
minor
;
int
minor
,
delta
;
for
(
minor
=
0
;
minor
<
TSDEV_MINORS
&&
tsdev_table
[
minor
];
for
(
minor
=
0
;
minor
<
TSDEV_MINORS
/
2
&&
tsdev_table
[
minor
];
minor
++
);
if
(
minor
==
TSDEV_MINORS
)
{
if
(
minor
>=
TSDEV_MINORS
/
2
)
{
printk
(
KERN_ERR
"tsdev: You have way too many touchscreens
\n
"
);
return
NULL
;
...
...
@@ -340,10 +399,25 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
tsdev
->
handle
.
handler
=
handler
;
tsdev
->
handle
.
private
=
tsdev
;
/* Precompute the rough calibration matrix */
delta
=
dev
->
absmax
[
ABS_X
]
-
dev
->
absmin
[
ABS_X
]
+
1
;
if
(
delta
==
0
)
delta
=
1
;
tsdev
->
cal
.
xscale
=
(
xres
<<
8
)
/
delta
;
tsdev
->
cal
.
xtrans
=
-
((
dev
->
absmin
[
ABS_X
]
*
tsdev
->
cal
.
xscale
)
>>
8
);
delta
=
dev
->
absmax
[
ABS_Y
]
-
dev
->
absmin
[
ABS_Y
]
+
1
;
if
(
delta
==
0
)
delta
=
1
;
tsdev
->
cal
.
yscale
=
(
yres
<<
8
)
/
delta
;
tsdev
->
cal
.
ytrans
=
-
((
dev
->
absmin
[
ABS_Y
]
*
tsdev
->
cal
.
yscale
)
>>
8
);
tsdev_table
[
minor
]
=
tsdev
;
devfs_mk_cdev
(
MKDEV
(
INPUT_MAJOR
,
TSDEV_MINOR_BASE
+
minor
),
S_IFCHR
|
S_IRUGO
|
S_IWUSR
,
"input/ts%d"
,
minor
);
devfs_mk_cdev
(
MKDEV
(
INPUT_MAJOR
,
TSDEV_MINOR_BASE
+
minor
+
TSDEV_MINORS
/
2
),
S_IFCHR
|
S_IRUGO
|
S_IWUSR
,
"input/tsraw%d"
,
minor
);
class_simple_device_add
(
input_class
,
MKDEV
(
INPUT_MAJOR
,
TSDEV_MINOR_BASE
+
minor
),
dev
->
dev
,
"ts%d"
,
minor
);
...
...
@@ -362,6 +436,7 @@ static void tsdev_disconnect(struct input_handle *handle)
wake_up_interruptible
(
&
tsdev
->
wait
);
}
else
tsdev_free
(
tsdev
);
devfs_remove
(
"input/tsraw%d"
,
tsdev
->
minor
);
}
static
struct
input_device_id
tsdev_ids
[]
=
{
...
...
@@ -379,6 +454,12 @@ static struct input_device_id tsdev_ids[] = {
.
absbit
=
{
BIT
(
ABS_X
)
|
BIT
(
ABS_Y
)
},
},
/* A tablet like device, at least touch detection, two absolute axes */
{
.
flags
=
INPUT_DEVICE_ID_MATCH_EVBIT
|
INPUT_DEVICE_ID_MATCH_ABSBIT
,
.
evbit
=
{
BIT
(
EV_ABS
)
},
.
absbit
=
{
BIT
(
ABS_X
)
|
BIT
(
ABS_Y
)
|
BIT
(
ABS_PRESSURE
)
},
},
/* A tablet like device with several gradations of pressure */
{},
/* Terminating entry */
};
...
...
drivers/serial/sunsu.c
View file @
037d476f
...
...
@@ -98,7 +98,7 @@ struct uart_sunsu_port {
unsigned
int
irq
;
#ifdef CONFIG_SERIO
struct
serio
serio
;
struct
serio
*
serio
;
int
serio_open
;
#endif
};
...
...
@@ -520,7 +520,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
/* Stop-A is handled by drivers/char/keyboard.c now. */
if
(
up
->
su_type
==
SU_PORT_KBD
)
{
#ifdef CONFIG_SERIO
serio_interrupt
(
&
up
->
serio
,
ch
,
0
,
regs
);
serio_interrupt
(
up
->
serio
,
ch
,
0
,
regs
);
#endif
}
else
if
(
up
->
su_type
==
SU_PORT_MS
)
{
int
ret
=
suncore_mouse_baud_detection
(
ch
,
is_break
);
...
...
@@ -534,7 +534,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
case
0
:
#ifdef CONFIG_SERIO
serio_interrupt
(
&
up
->
serio
,
ch
,
0
,
regs
);
serio_interrupt
(
up
->
serio
,
ch
,
0
,
regs
);
#endif
break
;
};
...
...
@@ -994,7 +994,7 @@ static spinlock_t sunsu_serio_lock = SPIN_LOCK_UNLOCKED;
static
int
sunsu_serio_write
(
struct
serio
*
serio
,
unsigned
char
ch
)
{
struct
uart_sunsu_port
*
up
=
serio
->
driver
;
struct
uart_sunsu_port
*
up
=
serio
->
port_data
;
unsigned
long
flags
;
int
lsr
;
...
...
@@ -1014,7 +1014,7 @@ static int sunsu_serio_write(struct serio *serio, unsigned char ch)
static
int
sunsu_serio_open
(
struct
serio
*
serio
)
{
struct
uart_sunsu_port
*
up
=
serio
->
driver
;
struct
uart_sunsu_port
*
up
=
serio
->
port_data
;
unsigned
long
flags
;
int
ret
;
...
...
@@ -1031,7 +1031,7 @@ static int sunsu_serio_open(struct serio *serio)
static
void
sunsu_serio_close
(
struct
serio
*
serio
)
{
struct
uart_sunsu_port
*
up
=
serio
->
driver
;
struct
uart_sunsu_port
*
up
=
serio
->
port_data
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
sunsu_serio_lock
,
flags
);
...
...
@@ -1284,13 +1284,11 @@ static struct uart_driver sunsu_reg = {
.
major
=
TTY_MAJOR
,
};
static
int
__init
sunsu_kbd_ms_init
(
void
)
static
int
__init
sunsu_kbd_ms_init
(
struct
uart_sunsu_port
*
up
,
int
channel
)
{
struct
uart_sunsu_port
*
up
;
int
i
;
struct
serio
*
serio
;
for
(
i
=
0
,
up
=
sunsu_ports
;
i
<
2
;
i
++
,
up
++
)
{
up
->
port
.
line
=
i
;
up
->
port
.
line
=
channel
;
up
->
port
.
type
=
PORT_UNKNOWN
;
up
->
port
.
uartclk
=
(
SU_BASE_BAUD
*
16
);
...
...
@@ -1301,37 +1299,43 @@ static int __init sunsu_kbd_ms_init(void)
sunsu_autoconfig
(
up
);
if
(
up
->
port
.
type
==
PORT_UNKNOWN
)
continue
;
return
-
1
;
printk
(
KERN_INFO
"su%d at 0x%p (irq = %s) is a %s
\n
"
,
i
,
channel
,
up
->
port
.
membase
,
__irq_itoa
(
up
->
irq
),
sunsu_type
(
&
up
->
port
));
#ifdef CONFIG_SERIO
memset
(
&
up
->
serio
,
0
,
sizeof
(
up
->
serio
));
up
->
serio
=
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
serio
));
up
->
serio
.
driver
=
up
;
serio
->
port_data
=
up
;
up
->
serio
.
type
=
SERIO_RS232
;
serio
->
type
=
SERIO_RS232
;
if
(
up
->
su_type
==
SU_PORT_KBD
)
{
up
->
serio
.
type
|=
SERIO_SUNKBD
;
up
->
serio
.
name
=
"sukbd"
;
serio
->
type
|=
SERIO_SUNKBD
;
strlcpy
(
serio
->
name
,
"sukbd"
,
sizeof
(
serio
->
name
))
;
}
else
{
up
->
serio
.
type
|=
(
SERIO_SUN
|
(
1
<<
16
));
up
->
serio
.
name
=
"sums"
;
serio
->
type
|=
(
SERIO_SUN
|
(
1
<<
16
));
strlcpy
(
serio
->
name
,
"sums"
,
sizeof
(
serio
->
name
))
;
}
up
->
serio
.
phys
=
(
i
==
0
?
"su/serio0"
:
"su/serio1"
);
strlcpy
(
serio
->
phys
,
(
channel
==
0
?
"su/serio0"
:
"su/serio1"
),
sizeof
(
serio
->
phys
));
up
->
serio
.
write
=
sunsu_serio_write
;
up
->
serio
.
open
=
sunsu_serio_open
;
up
->
serio
.
close
=
sunsu_serio_close
;
serio
->
write
=
sunsu_serio_write
;
serio
->
open
=
sunsu_serio_open
;
serio
->
close
=
sunsu_serio_close
;
serio_register_port
(
&
up
->
serio
);
serio_register_port
(
serio
);
}
else
{
printk
(
KERN_WARNING
"su%d: not enough memory for serio port
\n
"
,
channel
);
}
#endif
sunsu_startup
(
&
up
->
port
);
}
return
0
;
}
...
...
@@ -1680,10 +1684,12 @@ static int __init sunsu_probe(void)
if
(
scan
.
msx
!=
-
1
&&
scan
.
kbx
!=
-
1
)
{
sunsu_ports
[
0
].
su_type
=
SU_PORT_MS
;
sunsu_ports
[
0
].
port_node
=
scan
.
msnode
;
sunsu_kbd_ms_init
(
&
sunsu_ports
[
0
],
0
);
sunsu_ports
[
1
].
su_type
=
SU_PORT_KBD
;
sunsu_ports
[
1
].
port_node
=
scan
.
kbnode
;
sunsu_kbd_ms_init
(
&
sunsu_ports
[
1
],
1
);
sunsu_kbd_ms_init
();
return
0
;
}
...
...
@@ -1715,7 +1721,10 @@ static void __exit sunsu_exit(void)
if
(
up
->
su_type
==
SU_PORT_MS
||
up
->
su_type
==
SU_PORT_KBD
)
{
#ifdef CONFIG_SERIO
serio_unregister_port
(
&
up
->
serio
);
if
(
up
->
serio
)
{
serio_unregister_port
(
up
->
serio
);
up
->
serio
=
NULL
;
}
#endif
}
else
if
(
up
->
port
.
type
!=
PORT_UNKNOWN
)
{
uart_remove_one_port
(
&
sunsu_reg
,
&
up
->
port
);
...
...
drivers/serial/sunzilog.c
View file @
037d476f
...
...
@@ -107,7 +107,7 @@ struct uart_sunzilog_port {
unsigned
char
prev_status
;
#ifdef CONFIG_SERIO
struct
serio
serio
;
struct
serio
*
serio
;
int
serio_open
;
#endif
};
...
...
@@ -291,7 +291,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
/* Stop-A is handled by drivers/char/keyboard.c now. */
#ifdef CONFIG_SERIO
if
(
up
->
serio_open
)
serio_interrupt
(
&
up
->
serio
,
ch
,
0
,
regs
);
serio_interrupt
(
up
->
serio
,
ch
,
0
,
regs
);
#endif
}
else
if
(
ZS_IS_MOUSE
(
up
))
{
int
ret
=
suncore_mouse_baud_detection
(
ch
,
is_break
);
...
...
@@ -306,7 +306,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
case
0
:
#ifdef CONFIG_SERIO
if
(
up
->
serio_open
)
serio_interrupt
(
&
up
->
serio
,
ch
,
0
,
regs
);
serio_interrupt
(
up
->
serio
,
ch
,
0
,
regs
);
#endif
break
;
};
...
...
@@ -1295,7 +1295,7 @@ static spinlock_t sunzilog_serio_lock = SPIN_LOCK_UNLOCKED;
static
int
sunzilog_serio_write
(
struct
serio
*
serio
,
unsigned
char
ch
)
{
struct
uart_sunzilog_port
*
up
=
serio
->
driver
;
struct
uart_sunzilog_port
*
up
=
serio
->
port_data
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
sunzilog_serio_lock
,
flags
);
...
...
@@ -1309,7 +1309,7 @@ static int sunzilog_serio_write(struct serio *serio, unsigned char ch)
static
int
sunzilog_serio_open
(
struct
serio
*
serio
)
{
struct
uart_sunzilog_port
*
up
=
serio
->
driver
;
struct
uart_sunzilog_port
*
up
=
serio
->
port_data
;
unsigned
long
flags
;
int
ret
;
...
...
@@ -1326,7 +1326,7 @@ static int sunzilog_serio_open(struct serio *serio)
static
void
sunzilog_serio_close
(
struct
serio
*
serio
)
{
struct
uart_sunzilog_port
*
up
=
serio
->
driver
;
struct
uart_sunzilog_port
*
up
=
serio
->
port_data
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
sunzilog_serio_lock
,
flags
);
...
...
@@ -1529,6 +1529,7 @@ static void __init sunzilog_prepare(void)
static
void
__init
sunzilog_init_kbdms
(
struct
uart_sunzilog_port
*
up
,
int
channel
)
{
int
baud
,
brg
;
struct
serio
*
serio
;
if
(
channel
==
KEYBOARD_LINE
)
{
up
->
flags
|=
SUNZILOG_FLAG_CONS_KEYB
;
...
...
@@ -1547,26 +1548,34 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
sunzilog_convert_to_zs
(
up
,
up
->
cflag
,
0
,
brg
);
#ifdef CONFIG_SERIO
memset
(
&
up
->
serio
,
0
,
sizeof
(
up
->
serio
));
up
->
serio
=
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
up
->
serio
.
driver
=
up
;
memset
(
serio
,
0
,
sizeof
(
serio
))
;
up
->
serio
.
type
=
SERIO_RS232
;
serio
->
port_data
=
up
;
serio
->
type
=
SERIO_RS232
;
if
(
channel
==
KEYBOARD_LINE
)
{
up
->
serio
.
type
|=
SERIO_SUNKBD
;
up
->
serio
.
name
=
"zskbd"
;
serio
->
type
|=
SERIO_SUNKBD
;
strlcpy
(
serio
->
name
,
"zskbd"
,
sizeof
(
serio
->
name
))
;
}
else
{
up
->
serio
.
type
|=
(
SERIO_SUN
|
(
1
<<
16
));
up
->
serio
.
name
=
"zsms"
;
serio
->
type
|=
(
SERIO_SUN
|
(
1
<<
16
));
strlcpy
(
serio
->
name
,
"zsms"
,
sizeof
(
serio
->
name
))
;
}
up
->
serio
.
phys
=
(
channel
==
KEYBOARD_LINE
?
"zs/serio0"
:
"zs/serio1"
);
strlcpy
(
serio
->
phys
,
(
channel
==
KEYBOARD_LINE
?
"zs/serio0"
:
"zs/serio1"
),
sizeof
(
serio
->
phys
));
up
->
serio
.
write
=
sunzilog_serio_write
;
up
->
serio
.
open
=
sunzilog_serio_open
;
up
->
serio
.
close
=
sunzilog_serio_close
;
serio
->
write
=
sunzilog_serio_write
;
serio
->
open
=
sunzilog_serio_open
;
serio
->
close
=
sunzilog_serio_close
;
serio_register_port
(
&
up
->
serio
);
serio_register_port
(
serio
);
}
else
{
printk
(
KERN_WARNING
"zs%d: not enough memory for serio port
\n
"
,
channel
);
}
#endif
sunzilog_set_mctrl
(
&
up
->
port
,
TIOCM_DTR
|
TIOCM_RTS
);
...
...
@@ -1732,9 +1741,14 @@ static void __exit sunzilog_exit(void)
for
(
i
=
0
;
i
<
NUM_CHANNELS
;
i
++
)
{
struct
uart_sunzilog_port
*
up
=
&
sunzilog_port_table
[
i
];
if
(
ZS_IS_KEYB
(
up
)
||
ZS_IS_MOUSE
(
up
))
continue
;
if
(
ZS_IS_KEYB
(
up
)
||
ZS_IS_MOUSE
(
up
))
{
#ifdef CONFIG_SERIO
if
(
up
->
serio
)
{
serio_unregister_port
(
up
->
serio
);
up
->
serio
=
NULL
;
}
#endif
}
else
uart_remove_one_port
(
&
sunzilog_reg
,
&
up
->
port
);
}
...
...
drivers/usb/input/hid-core.c
View file @
037d476f
...
...
@@ -1430,6 +1430,11 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101
#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104
#define USB_VENDOR_ID_CODEMERCS 0x07c0
#define USB_DEVICE_ID_CODEMERCS_IOW40 0x1500
#define USB_DEVICE_ID_CODEMERCS_IOW24 0x1501
static
struct
hid_blacklist
{
__u16
idVendor
;
__u16
idProduct
;
...
...
@@ -1444,20 +1449,20 @@ static struct hid_blacklist {
{
USB_VENDOR_ID_AIPTEK
,
USB_DEVICE_ID_AIPTEK_23
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_AIPTEK
,
USB_DEVICE_ID_AIPTEK_24
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_BERKSHIRE
,
USB_DEVICE_ID_BERKSHIRE_PCWD
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_CODEMERCS
,
USB_DEVICE_ID_CODEMERCS_IOW40
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_CODEMERCS
,
USB_DEVICE_ID_CODEMERCS_IOW24
,
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
},
...
...
drivers/usb/input/hiddev.c
View file @
037d476f
...
...
@@ -636,15 +636,21 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
goto
inval
;
field
=
report
->
field
[
uref
->
field_index
];
if
(
cmd
==
HIDIOCGCOLLECTIONINDEX
)
{
if
(
uref
->
usage_index
>=
field
->
maxusage
)
goto
inval
;
}
else
if
(
uref
->
usage_index
>=
field
->
report_count
)
goto
inval
;
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
)
else
if
((
cmd
==
HIDIOCGUSAGES
||
cmd
==
HIDIOCSUSAGES
)
&&
(
uref
->
usage_index
+
uref_multi
->
num_values
>=
field
->
report_count
||
uref
->
usage_index
+
uref_multi
->
num_values
<
uref
->
usage_index
))
goto
inval
;
}
}
switch
(
cmd
)
{
...
...
fs/compat_ioctl.c
View file @
037d476f
...
...
@@ -115,6 +115,8 @@
#include <linux/filter.h>
#include <linux/msdos_fs.h>
#include <linux/hiddev.h>
#undef INCLUDES
#endif
...
...
include/linux/compat_ioctl.h
View file @
037d476f
...
...
@@ -732,3 +732,20 @@ COMPATIBLE_IOCTL(SIOCSIWRETRY)
COMPATIBLE_IOCTL
(
SIOCGIWRETRY
)
COMPATIBLE_IOCTL
(
SIOCSIWPOWER
)
COMPATIBLE_IOCTL
(
SIOCGIWPOWER
)
/* hiddev */
COMPATIBLE_IOCTL
(
HIDIOCGVERSION
)
COMPATIBLE_IOCTL
(
HIDIOCAPPLICATION
)
COMPATIBLE_IOCTL
(
HIDIOCGDEVINFO
)
COMPATIBLE_IOCTL
(
HIDIOCGSTRING
)
COMPATIBLE_IOCTL
(
HIDIOCINITREPORT
)
COMPATIBLE_IOCTL
(
HIDIOCGREPORT
)
COMPATIBLE_IOCTL
(
HIDIOCSREPORT
)
COMPATIBLE_IOCTL
(
HIDIOCGREPORTINFO
)
COMPATIBLE_IOCTL
(
HIDIOCGFIELDINFO
)
COMPATIBLE_IOCTL
(
HIDIOCGUSAGE
)
COMPATIBLE_IOCTL
(
HIDIOCSUSAGE
)
COMPATIBLE_IOCTL
(
HIDIOCGUCODE
)
COMPATIBLE_IOCTL
(
HIDIOCGFLAG
)
COMPATIBLE_IOCTL
(
HIDIOCSFLAG
)
COMPATIBLE_IOCTL
(
HIDIOCGCOLLECTIONINDEX
)
COMPATIBLE_IOCTL
(
HIDIOCGCOLLECTIONINFO
)
include/linux/hiddev.h
View file @
037d476f
...
...
@@ -128,10 +128,11 @@ struct hiddev_usage_ref {
/* hiddev_usage_ref_multi is used for sending multiple bytes to a control.
* It really manifests itself as setting the value of consecutive usages */
#define HID_MAX_MULTI_USAGES 1024
struct
hiddev_usage_ref_multi
{
struct
hiddev_usage_ref
uref
;
__u32
num_values
;
__s32
values
[
HID_MAX_USAGES
];
__s32
values
[
HID_MAX_
MULTI_
USAGES
];
};
/* FIELD_INDEX_NONE is returned in read() data from the kernel when flags
...
...
@@ -212,6 +213,11 @@ struct hiddev_usage_ref_multi {
* In-kernel definitions.
*/
struct
hid_device
;
struct
hid_usage
;
struct
hid_field
;
struct
hid_report
;
#ifdef CONFIG_USB_HIDDEV
int
hiddev_connect
(
struct
hid_device
*
);
void
hiddev_disconnect
(
struct
hid_device
*
);
...
...
include/linux/input.h
View file @
037d476f
...
...
@@ -527,6 +527,8 @@ struct input_absinfo {
#define MSC_SERIAL 0x00
#define MSC_PULSELED 0x01
#define MSC_GESTURE 0x02
#define MSC_RAW 0x03
#define MSC_SCAN 0x04
#define MSC_MAX 0x07
/*
...
...
include/linux/serio.h
View file @
037d476f
...
...
@@ -17,12 +17,15 @@
#ifdef __KERNEL__
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/device.h>
struct
serio
{
void
*
private
;
void
*
driver
;
char
*
name
;
char
*
phys
;
void
*
port_data
;
char
name
[
32
];
char
phys
[
32
];
unsigned
short
idbus
;
unsigned
short
idvendor
;
...
...
@@ -32,31 +35,43 @@ struct serio {
unsigned
long
type
;
unsigned
long
event
;
spinlock_t
lock
;
int
(
*
write
)(
struct
serio
*
,
unsigned
char
);
int
(
*
open
)(
struct
serio
*
);
void
(
*
close
)(
struct
serio
*
);
struct
serio_dev
*
dev
;
struct
serio
*
parent
,
*
child
;
struct
serio_driver
*
drv
;
/* Accessed from interrupt, writes must be protected by serio_lock */
struct
device
dev
;
struct
list_head
node
;
};
#define to_serio_port(d) container_of(d, struct serio, dev)
struct
serio_d
ev
{
struct
serio_d
river
{
void
*
private
;
char
*
name
;
char
*
description
;
int
manual_bind
;
void
(
*
write_wakeup
)(
struct
serio
*
);
irqreturn_t
(
*
interrupt
)(
struct
serio
*
,
unsigned
char
,
unsigned
int
,
struct
pt_regs
*
);
void
(
*
connect
)(
struct
serio
*
,
struct
serio_d
ev
*
de
v
);
void
(
*
connect
)(
struct
serio
*
,
struct
serio_d
river
*
dr
v
);
int
(
*
reconnect
)(
struct
serio
*
);
void
(
*
disconnect
)(
struct
serio
*
);
void
(
*
cleanup
)(
struct
serio
*
);
struct
device_driver
driver
;
struct
list_head
node
;
};
#define to_serio_driver(d) container_of(d, struct serio_driver, driver)
int
serio_open
(
struct
serio
*
serio
,
struct
serio_d
ev
*
de
v
);
int
serio_open
(
struct
serio
*
serio
,
struct
serio_d
river
*
dr
v
);
void
serio_close
(
struct
serio
*
serio
);
void
serio_rescan
(
struct
serio
*
serio
);
void
serio_reconnect
(
struct
serio
*
serio
);
...
...
@@ -64,12 +79,10 @@ irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned in
void
serio_register_port
(
struct
serio
*
serio
);
void
serio_register_port_delayed
(
struct
serio
*
serio
);
void
__serio_register_port
(
struct
serio
*
serio
);
void
serio_unregister_port
(
struct
serio
*
serio
);
void
serio_unregister_port_delayed
(
struct
serio
*
serio
);
void
__serio_unregister_port
(
struct
serio
*
serio
);
void
serio_register_device
(
struct
serio_dev
*
dev
);
void
serio_unregister_device
(
struct
serio_dev
*
dev
);
void
serio_register_driver
(
struct
serio_driver
*
drv
);
void
serio_unregister_driver
(
struct
serio_driver
*
drv
);
static
__inline__
int
serio_write
(
struct
serio
*
serio
,
unsigned
char
data
)
{
...
...
@@ -79,16 +92,16 @@ static __inline__ int serio_write(struct serio *serio, unsigned char data)
return
-
1
;
}
static
__inline__
void
serio_d
e
v_write_wakeup
(
struct
serio
*
serio
)
static
__inline__
void
serio_d
r
v_write_wakeup
(
struct
serio
*
serio
)
{
if
(
serio
->
d
ev
&&
serio
->
de
v
->
write_wakeup
)
serio
->
d
e
v
->
write_wakeup
(
serio
);
if
(
serio
->
d
rv
&&
serio
->
dr
v
->
write_wakeup
)
serio
->
d
r
v
->
write_wakeup
(
serio
);
}
static
__inline__
void
serio_cleanup
(
struct
serio
*
serio
)
{
if
(
serio
->
d
ev
&&
serio
->
de
v
->
cleanup
)
serio
->
d
e
v
->
cleanup
(
serio
);
if
(
serio
->
d
rv
&&
serio
->
dr
v
->
cleanup
)
serio
->
d
r
v
->
cleanup
(
serio
);
}
#endif
...
...
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