Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
fd58ee61
Commit
fd58ee61
authored
Jun 06, 2004
by
Vojtech Pavlik
Browse files
Options
Browse Files
Download
Plain Diff
Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
parents
99185c20
bc2d9f69
Changes
81
Show whitespace changes
Inline
Side-by-side
Showing
81 changed files
with
1798 additions
and
1356 deletions
+1798
-1356
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+2
-2
arch/i386/kernel/dmi_scan.c
arch/i386/kernel/dmi_scan.c
+31
-0
drivers/char/keyboard.c
drivers/char/keyboard.c
+20
-6
drivers/input/Kconfig
drivers/input/Kconfig
+8
-1
drivers/input/evbug.c
drivers/input/evbug.c
+7
-7
drivers/input/evdev.c
drivers/input/evdev.c
+4
-4
drivers/input/gameport/cs461x.c
drivers/input/gameport/cs461x.c
+15
-15
drivers/input/gameport/emu10k1-gp.c
drivers/input/gameport/emu10k1-gp.c
+6
-6
drivers/input/gameport/fm801-gp.c
drivers/input/gameport/fm801-gp.c
+1
-1
drivers/input/gameport/gameport.c
drivers/input/gameport/gameport.c
+1
-1
drivers/input/gameport/lightning.c
drivers/input/gameport/lightning.c
+8
-8
drivers/input/gameport/ns558.c
drivers/input/gameport/ns558.c
+7
-7
drivers/input/gameport/vortex.c
drivers/input/gameport/vortex.c
+3
-3
drivers/input/input.c
drivers/input/input.c
+20
-20
drivers/input/joydev.c
drivers/input/joydev.c
+8
-8
drivers/input/joystick/Kconfig
drivers/input/joystick/Kconfig
+8
-8
drivers/input/joystick/a3d.c
drivers/input/joystick/a3d.c
+7
-7
drivers/input/joystick/adi.c
drivers/input/joystick/adi.c
+15
-15
drivers/input/joystick/amijoy.c
drivers/input/joystick/amijoy.c
+1
-1
drivers/input/joystick/analog.c
drivers/input/joystick/analog.c
+21
-21
drivers/input/joystick/cobra.c
drivers/input/joystick/cobra.c
+5
-5
drivers/input/joystick/db9.c
drivers/input/joystick/db9.c
+12
-12
drivers/input/joystick/gamecon.c
drivers/input/joystick/gamecon.c
+16
-16
drivers/input/joystick/gf2k.c
drivers/input/joystick/gf2k.c
+6
-6
drivers/input/joystick/grip.c
drivers/input/joystick/grip.c
+3
-3
drivers/input/joystick/grip_mp.c
drivers/input/joystick/grip_mp.c
+22
-22
drivers/input/joystick/guillemot.c
drivers/input/joystick/guillemot.c
+4
-4
drivers/input/joystick/iforce/Kconfig
drivers/input/joystick/iforce/Kconfig
+1
-1
drivers/input/joystick/iforce/Makefile
drivers/input/joystick/iforce/Makefile
+3
-3
drivers/input/joystick/iforce/iforce-ff.c
drivers/input/joystick/iforce/iforce-ff.c
+2
-2
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-main.c
+2
-2
drivers/input/joystick/iforce/iforce-packets.c
drivers/input/joystick/iforce/iforce-packets.c
+2
-2
drivers/input/joystick/iforce/iforce-serio.c
drivers/input/joystick/iforce/iforce-serio.c
+1
-1
drivers/input/joystick/iforce/iforce.h
drivers/input/joystick/iforce/iforce.h
+1
-1
drivers/input/joystick/interact.c
drivers/input/joystick/interact.c
+4
-4
drivers/input/joystick/joydump.c
drivers/input/joystick/joydump.c
+5
-5
drivers/input/joystick/magellan.c
drivers/input/joystick/magellan.c
+6
-6
drivers/input/joystick/sidewinder.c
drivers/input/joystick/sidewinder.c
+10
-10
drivers/input/joystick/spaceball.c
drivers/input/joystick/spaceball.c
+10
-10
drivers/input/joystick/spaceorb.c
drivers/input/joystick/spaceorb.c
+9
-9
drivers/input/joystick/stinger.c
drivers/input/joystick/stinger.c
+3
-3
drivers/input/joystick/tmdc.c
drivers/input/joystick/tmdc.c
+12
-12
drivers/input/joystick/turbografx.c
drivers/input/joystick/turbografx.c
+10
-10
drivers/input/joystick/twidjoy.c
drivers/input/joystick/twidjoy.c
+9
-6
drivers/input/joystick/warrior.c
drivers/input/joystick/warrior.c
+16
-16
drivers/input/keyboard/98kbd.c
drivers/input/keyboard/98kbd.c
+23
-19
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Kconfig
+3
-3
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+120
-54
drivers/input/keyboard/maple_keyb.c
drivers/input/keyboard/maple_keyb.c
+1
-1
drivers/input/keyboard/sunkbd.c
drivers/input/keyboard/sunkbd.c
+8
-8
drivers/input/keyboard/xtkbd.c
drivers/input/keyboard/xtkbd.c
+6
-6
drivers/input/misc/98spkr.c
drivers/input/misc/98spkr.c
+2
-2
drivers/input/misc/pcspkr.c
drivers/input/misc/pcspkr.c
+2
-2
drivers/input/misc/sparcspkr.c
drivers/input/misc/sparcspkr.c
+4
-4
drivers/input/misc/uinput.c
drivers/input/misc/uinput.c
+28
-25
drivers/input/mouse/logips2pp.c
drivers/input/mouse/logips2pp.c
+153
-113
drivers/input/mouse/logips2pp.h
drivers/input/mouse/logips2pp.h
+2
-7
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse-base.c
+192
-106
drivers/input/mouse/psmouse.h
drivers/input/mouse/psmouse.h
+17
-3
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.c
+198
-255
drivers/input/mouse/synaptics.h
drivers/input/mouse/synaptics.h
+8
-15
drivers/input/mousedev.c
drivers/input/mousedev.c
+161
-129
drivers/input/power.c
drivers/input/power.c
+14
-13
drivers/input/serio/98kbd-io.c
drivers/input/serio/98kbd-io.c
+5
-4
drivers/input/serio/ct82c710.c
drivers/input/serio/ct82c710.c
+4
-4
drivers/input/serio/gscps2.c
drivers/input/serio/gscps2.c
+11
-11
drivers/input/serio/i8042.c
drivers/input/serio/i8042.c
+44
-19
drivers/input/serio/parkbd.c
drivers/input/serio/parkbd.c
+6
-17
drivers/input/serio/q40kbd.c
drivers/input/serio/q40kbd.c
+1
-12
drivers/input/serio/rpckbd.c
drivers/input/serio/rpckbd.c
+1
-1
drivers/input/serio/serio.c
drivers/input/serio/serio.c
+69
-21
drivers/input/serio/serport.c
drivers/input/serio/serport.c
+2
-8
drivers/input/touchscreen/gunze.c
drivers/input/touchscreen/gunze.c
+3
-5
drivers/input/touchscreen/h3600_ts_input.c
drivers/input/touchscreen/h3600_ts_input.c
+60
-52
drivers/input/tsdev.c
drivers/input/tsdev.c
+186
-105
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
+54
-11
include/linux/serio.h
include/linux/serio.h
+4
-1
No files found.
Documentation/kernel-parameters.txt
View file @
fd58ee61
...
...
@@ -896,8 +896,8 @@ running once the system is up.
psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports
per second.
psmouse.resetafter=
[HW,MOUSE] Try to reset
Synaptics Touchpad after so many
bad packets
(0 = never).
[HW,MOUSE] Try to reset
the device after so many bad packets
(0 = never).
psmouse.resolution=
[HW,MOUSE] Set desired mouse resolution, in dpi.
psmouse.smartscroll=
...
...
arch/i386/kernel/dmi_scan.c
View file @
fd58ee61
...
...
@@ -15,6 +15,9 @@
unsigned
long
dmi_broken
;
EXPORT_SYMBOL
(
dmi_broken
);
unsigned
int
i8042_dmi_noloop
=
0
;
EXPORT_SYMBOL
(
i8042_dmi_noloop
);
int
is_sony_vaio_laptop
;
int
is_unsafe_smbus
;
int
es7000_plat
=
0
;
...
...
@@ -400,6 +403,17 @@ static __init int sony_vaio_laptop(struct dmi_blacklist *d)
return
0
;
}
/*
* Several HP Proliant (and maybe other OSB4/ProFusion) systems
* shouldn't use the AUX LoopBack command, or they crash or reboot.
*/
static
__init
int
set_8042_noloop
(
struct
dmi_blacklist
*
d
)
{
i8042_dmi_noloop
=
1
;
return
0
;
}
/*
* This bios swaps the APM minute reporting bytes over (Many sony laptops
* have this problem).
...
...
@@ -875,6 +889,23 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={
NO_MATCH
,
NO_MATCH
,
}
},
/*
* Several HP Proliant (and maybe other OSB4/ProFusion) systems
* can't use i8042 in mux mode, or they crash or reboot.
*/
{
set_8042_noloop
,
"Compaq Proliant 8500"
,
{
MATCH
(
DMI_SYS_VENDOR
,
"Compaq"
),
MATCH
(
DMI_PRODUCT_NAME
,
"ProLiant"
),
MATCH
(
DMI_PRODUCT_VERSION
,
"8500"
),
NO_MATCH
}},
{
set_8042_noloop
,
"Compaq Proliant DL760"
,
{
MATCH
(
DMI_SYS_VENDOR
,
"Compaq"
),
MATCH
(
DMI_PRODUCT_NAME
,
"ProLiant"
),
MATCH
(
DMI_PRODUCT_VERSION
,
"DL760"
),
NO_MATCH
}},
#ifdef CONFIG_ACPI_BOOT
/*
* If your system is blacklisted here, but you find that acpi=force
...
...
drivers/char/keyboard.c
View file @
fd58ee61
...
...
@@ -942,6 +942,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_SH_MPC1211)
#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
,
...
...
@@ -1008,6 +1011,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
)
...
...
@@ -1020,7 +1025,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
;
...
...
@@ -1054,7 +1067,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
);
...
...
@@ -1149,11 +1162,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/Kconfig
View file @
fd58ee61
...
...
@@ -41,9 +41,16 @@ config INPUT_MOUSEDEV
module will be called mousedev.
config INPUT_MOUSEDEV_PSAUX
bool "Provide legacy /dev/psaux device"
if EMBEDDED
bool "Provide legacy /dev/psaux device"
default y
depends on INPUT_MOUSEDEV
---help---
Say Y here if you want your mouse also be accessible as char device
10:1 - /dev/psaux. The data available through /dev/psaux is exactly
the same as the data from /dev/input/mice.
If unsure, say Y.
config INPUT_MOUSEDEV_SCREEN_X
int "Horizontal screen resolution"
...
...
drivers/input/evbug.c
View file @
fd58ee61
drivers/input/evdev.c
View file @
fd58ee61
...
...
@@ -126,7 +126,7 @@ static int evdev_open(struct inode * inode, struct file * file)
int
i
=
iminor
(
inode
)
-
EVDEV_MINOR_BASE
;
int
accept_err
;
if
(
i
>=
EVDEV_MINORS
||
!
evdev_table
[
i
])
if
(
i
>=
EVDEV_MINORS
||
!
evdev_table
[
i
]
||
!
evdev_table
[
i
]
->
exist
)
return
-
ENODEV
;
if
((
accept_err
=
input_accept_process
(
&
(
evdev_table
[
i
]
->
handle
),
file
)))
...
...
@@ -175,7 +175,7 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count
return
-
EAGAIN
;
retval
=
wait_event_interruptible
(
list
->
evdev
->
wait
,
list
->
head
!=
list
->
tail
&&
list
->
evdev
->
exist
);
list
->
head
!=
list
->
tail
||
(
!
list
->
evdev
->
exist
)
);
if
(
retval
)
return
retval
;
...
...
drivers/input/gameport/cs461x.c
View file @
fd58ee61
drivers/input/gameport/emu10k1-gp.c
View file @
fd58ee61
drivers/input/gameport/fm801-gp.c
View file @
fd58ee61
drivers/input/gameport/gameport.c
View file @
fd58ee61
drivers/input/gameport/lightning.c
View file @
fd58ee61
drivers/input/gameport/ns558.c
View file @
fd58ee61
drivers/input/gameport/vortex.c
View file @
fd58ee61
drivers/input/input.c
View file @
fd58ee61
drivers/input/joydev.c
View file @
fd58ee61
drivers/input/joystick/Kconfig
View file @
fd58ee61
drivers/input/joystick/a3d.c
View file @
fd58ee61
drivers/input/joystick/adi.c
View file @
fd58ee61
drivers/input/joystick/amijoy.c
View file @
fd58ee61
drivers/input/joystick/analog.c
View file @
fd58ee61
drivers/input/joystick/cobra.c
View file @
fd58ee61
drivers/input/joystick/db9.c
View file @
fd58ee61
drivers/input/joystick/gamecon.c
View file @
fd58ee61
drivers/input/joystick/gf2k.c
View file @
fd58ee61
drivers/input/joystick/grip.c
View file @
fd58ee61
drivers/input/joystick/grip_mp.c
View file @
fd58ee61
drivers/input/joystick/guillemot.c
View file @
fd58ee61
drivers/input/joystick/iforce/Kconfig
View file @
fd58ee61
drivers/input/joystick/iforce/Makefile
View file @
fd58ee61
drivers/input/joystick/iforce/iforce-ff.c
View file @
fd58ee61
drivers/input/joystick/iforce/iforce-main.c
View file @
fd58ee61
drivers/input/joystick/iforce/iforce-packets.c
View file @
fd58ee61
drivers/input/joystick/iforce/iforce-serio.c
View file @
fd58ee61
drivers/input/joystick/iforce/iforce.h
View file @
fd58ee61
drivers/input/joystick/interact.c
View file @
fd58ee61
drivers/input/joystick/joydump.c
View file @
fd58ee61
drivers/input/joystick/magellan.c
View file @
fd58ee61
drivers/input/joystick/sidewinder.c
View file @
fd58ee61
drivers/input/joystick/spaceball.c
View file @
fd58ee61
drivers/input/joystick/spaceorb.c
View file @
fd58ee61
drivers/input/joystick/stinger.c
View file @
fd58ee61
drivers/input/joystick/tmdc.c
View file @
fd58ee61
drivers/input/joystick/turbografx.c
View file @
fd58ee61
drivers/input/joystick/twidjoy.c
View file @
fd58ee61
...
...
@@ -58,6 +58,9 @@
#include <linux/serio.h>
#include <linux/init.h>
MODULE_DESCRIPTION
(
"Handykey Twiddler keyboard as a joystick driver"
);
MODULE_LICENSE
(
"GPL"
);
/*
* Constants.
*/
...
...
@@ -142,7 +145,7 @@ static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs
* packet processing routine.
*/
static
void
twidjoy_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struc
pt_regs
*
regs
)
static
irqreturn_t
twidjoy_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
)
{
struct
twidjoy
*
twidjoy
=
serio
->
private
;
...
...
@@ -153,7 +156,7 @@ static void twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned
if
((
data
&
0x80
)
==
0
)
twidjoy
->
idx
=
0
;
/* this byte starts a new packet */
else
if
(
twidjoy
->
idx
==
0
)
return
;
/* wrong MSB -- ignore this byte */
return
IRQ_HANDLED
;
/* wrong MSB -- ignore this byte */
if
(
twidjoy
->
idx
<
TWIDJOY_MAX_LENGTH
)
twidjoy
->
data
[
twidjoy
->
idx
++
]
=
data
;
...
...
@@ -163,7 +166,7 @@ static void twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned
twidjoy
->
idx
=
0
;
}
return
;
return
IRQ_HANDLED
;
}
/*
...
...
drivers/input/joystick/warrior.c
View file @
fd58ee61
drivers/input/keyboard/98kbd.c
View file @
fd58ee61
...
...
@@ -109,7 +109,7 @@ struct kbd98 {
struct
jis_kbd_conv
jis
[
16
];
};
void
kbd98_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
irqreturn_t
kbd98_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
)
{
struct
kbd98
*
kbd98
=
serio
->
private
;
...
...
@@ -119,15 +119,15 @@ void kbd98_interrupt(struct serio *serio, unsigned char data,
switch
(
data
)
{
case
KBD98_RET_ACK
:
kbd98
->
ack
=
1
;
return
;
goto
out
;
case
KBD98_RET_NAK
:
kbd98
->
ack
=
-
1
;
return
;
goto
out
;
}
if
(
kbd98
->
cmdcnt
)
{
kbd98
->
cmdbuf
[
--
kbd98
->
cmdcnt
]
=
data
;
return
;
goto
out
;
}
scancode
=
data
&
KBD98_KEY
;
...
...
@@ -164,7 +164,7 @@ void kbd98_interrupt(struct serio *serio, unsigned char data,
keycode
=
kbd98
->
jis
[
i
].
emul
[
kbd98
->
shift
].
keycode
;
if
(
keycode
==
KBD98_KEY_NULL
)
return
;
break
;
if
(
press
)
{
kbd98
->
emul
.
scancode
=
scancode
;
...
...
@@ -187,27 +187,31 @@ void kbd98_interrupt(struct serio *serio, unsigned char data,
}
input_sync
(
&
kbd98
->
dev
);
return
;
break
;
case
KEY_CAPSLOCK
:
input_report_key
(
&
kbd98
->
dev
,
keycode
,
1
);
input_sync
(
&
kbd98
->
dev
);
input_report_key
(
&
kbd98
->
dev
,
keycode
,
0
);
input_sync
(
&
kbd98
->
dev
);
return
;
break
;
case
KBD98_KEY_NULL
:
return
;
break
;
case
0
:
printk
(
KERN_WARNING
"kbd98.c: Unknown key (scancode %#x) %s.
\n
"
,
data
&
KBD98_KEY
,
data
&
KBD98_RELEASE
?
"released"
:
"pressed"
);
return
;
break
;
default:
input_report_key
(
&
kbd98
->
dev
,
keycode
,
press
);
input_sync
(
&
kbd98
->
dev
);
break
;
}
out:
return
IRQ_HANDLED
;
}
/*
...
...
drivers/input/keyboard/Kconfig
View file @
fd58ee61
drivers/input/keyboard/atkbd.c
View file @
fd58ee61
...
...
@@ -26,7 +26,6 @@
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@suse.cz>"
);
MODULE_DESCRIPTION
(
"AT and PS/2 keyboard driver"
);
...
...
@@ -48,6 +47,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"
);
...
...
@@ -165,32 +168,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
;
struct
timer_list
timer
;
/* Written only during init */
char
name
[
64
];
char
phys
[
32
];
unsigned
char
cmdbuf
[
4
];
unsigned
char
cmdcnt
;
struct
serio
*
serio
;
struct
input_dev
dev
;
unsigned
char
set
;
unsigned
char
extra
;
unsigned
char
release
;
int
lastkey
;
volatile
signed
char
ack
;
unsigned
char
emul
;
unsigned
short
id
;
unsigned
char
write
;
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
;
/* 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
)
...
...
@@ -223,7 +242,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
;
...
...
@@ -233,21 +252,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
(
!
test_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
))
goto
out
;
input_event
(
&
atkbd
->
dev
,
EV_MSC
,
MSC_RAW
,
code
);
if
(
atkbd
->
translated
)
{
if
(
atkbd
->
emul
||
...
...
@@ -266,6 +309,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
:
...
...
@@ -296,19 +340,27 @@ 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
;
case
ATKBD_KEY_UNKNOWN
:
printk
(
KERN_WARNING
"atkbd.c: Unknown key %s (%s set %d, code %#x on %s).
\n
"
,
if
(
data
==
ATKBD_RET_ACK
||
data
==
ATKBD_RET_NAK
)
{
printk
(
KERN_WARNING
"atkbd.c: Spurious %s on %s. Some program, "
"like XFree86, might be trying access hardware directly.
\n
"
,
data
==
ATKBD_RET_ACK
?
"ACK"
:
"NAK"
,
serio
->
phys
);
}
else
{
printk
(
KERN_WARNING
"atkbd.c: Unknown key %s "
"(%s set %d, code %#x on %s).
\n
"
,
atkbd
->
release
?
"released"
:
"pressed"
,
atkbd
->
translated
?
"translated"
:
"raw"
,
atkbd
->
set
,
code
,
serio
->
phys
);
if
(
atkbd
->
translated
&&
atkbd
->
set
==
2
&&
code
==
0x7a
)
printk
(
KERN_WARNING
"atkbd.c: This is an XFree86 bug. It shouldn't access"
" hardware directly.
\n
"
);
else
printk
(
KERN_WARNING
"atkbd.c: Use 'setkeycodes %s%02x <keycode>' to make it known.
\n
"
,
code
&
0x80
?
"e0"
:
""
,
code
&
0x7f
);
printk
(
KERN_WARNING
"atkbd.c: Use 'setkeycodes %s%02x <keycode>' "
"to make it known.
\n
"
,
code
&
0x80
?
"e0"
:
""
,
code
&
0x7f
);
}
break
;
case
ATKBD_SCR_1
:
scroll
=
1
-
atkbd
->
release
*
2
;
...
...
@@ -367,18 +419,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
;
}
/*
...
...
@@ -396,7 +450,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
++
)
...
...
@@ -404,38 +458,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
;
}
...
...
@@ -663,6 +719,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
);
...
...
@@ -700,17 +757,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
);
...
...
@@ -786,6 +848,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
);
}
...
...
@@ -821,6 +885,8 @@ static int atkbd_reconnect(struct serio *serio)
return
-
1
;
}
set_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
);
return
0
;
}
...
...
drivers/input/keyboard/maple_keyb.c
View file @
fd58ee61
drivers/input/keyboard/sunkbd.c
View file @
fd58ee61
drivers/input/keyboard/xtkbd.c
View file @
fd58ee61
drivers/input/misc/98spkr.c
View file @
fd58ee61
drivers/input/misc/pcspkr.c
View file @
fd58ee61
drivers/input/misc/sparcspkr.c
View file @
fd58ee61
drivers/input/misc/uinput.c
View file @
fd58ee61
...
...
@@ -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/logips2pp.c
View file @
fd58ee61
...
...
@@ -14,6 +14,25 @@
#include "psmouse.h"
#include "logips2pp.h"
/* Logitech mouse types */
#define PS2PP_KIND_WHEEL 1
#define PS2PP_KIND_MX 2
#define PS2PP_KIND_TP3 3
/* Logitech mouse features */
#define PS2PP_WHEEL 0x01
#define PS2PP_HWHEEL 0x02
#define PS2PP_SIDE_BTN 0x04
#define PS2PP_EXTRA_BTN 0x08
#define PS2PP_TASK_BTN 0x10
#define PS2PP_NAV_BTN 0x20
struct
ps2pp_info
{
const
int
model
;
unsigned
const
int
kind
;
unsigned
const
int
features
;
};
/*
* Process a PS2++ or PS2T++ packet.
*/
...
...
@@ -63,7 +82,6 @@ void ps2pp_process_packet(struct psmouse *psmouse)
packet
[
0
]
&=
0x0f
;
packet
[
1
]
=
0
;
packet
[
2
]
=
0
;
}
}
...
...
@@ -76,18 +94,9 @@ void ps2pp_process_packet(struct psmouse *psmouse)
static
int
ps2pp_cmd
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
,
unsigned
char
command
)
{
unsigned
char
d
;
int
i
;
if
(
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
))
if
(
psmouse_sliced_command
(
psmouse
,
command
))
return
-
1
;
for
(
i
=
6
;
i
>=
0
;
i
-=
2
)
{
d
=
(
command
>>
i
)
&
3
;
if
(
psmouse_command
(
psmouse
,
&
d
,
PSMOUSE_CMD_SETRES
))
return
-
1
;
}
if
(
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_POLL
))
return
-
1
;
...
...
@@ -113,14 +122,11 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse)
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
if
(
psmouse_smartscroll
==
1
)
param
[
0
]
=
1
;
else
if
(
psmouse_smartscroll
>
2
)
return
;
/* else leave param[0] == 0 to disable */
if
(
psmouse_smartscroll
<
2
)
{
/* 0 - disabled, 1 - enabled */
param
[
0
]
=
psmouse_smartscroll
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
}
}
/*
...
...
@@ -138,133 +144,167 @@ void ps2pp_set_800dpi(struct psmouse *psmouse)
psmouse_command
(
psmouse
,
&
param
,
PSMOUSE_CMD_SETRES
);
}
/*
* Detect the exact model and features of a PS2++ or PS2T++ Logitech mouse or
* touchpad.
*/
static
int
ps2pp_detect_model
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
)
static
struct
ps2pp_info
*
get_model_info
(
unsigned
char
model
)
{
int
i
;
static
struct
_logips2_list
{
const
int
model
;
unsigned
const
int
features
;
}
logips2pp_list
[]
=
{
{
12
,
PS2PP_4BTN
},
{
13
,
0
},
{
40
,
PS2PP_4BTN
},
{
41
,
PS2PP_4BTN
},
{
42
,
PS2PP_4BTN
},
{
43
,
PS2PP_4BTN
},
{
50
,
0
},
{
51
,
0
},
{
52
,
PS2PP_4BTN
|
PS2PP_WHEEL
},
{
53
,
PS2PP_WHEEL
},
{
61
,
PS2PP_WHEEL
|
PS2PP_MX
},
/* MX700 */
{
73
,
PS2PP_4BTN
},
{
75
,
PS2PP_WHEEL
},
{
76
,
PS2PP_WHEEL
},
{
80
,
PS2PP_4BTN
|
PS2PP_WHEEL
},
{
81
,
PS2PP_WHEEL
},
{
83
,
PS2PP_WHEEL
},
{
88
,
PS2PP_WHEEL
},
{
96
,
0
},
{
97
,
0
},
{
100
,
PS2PP_WHEEL
|
PS2PP_MX
},
/* MX510 */
{
112
,
PS2PP_WHEEL
|
PS2PP_MX
},
/* MX500 */
{
114
,
PS2PP_WHEEL
|
PS2PP_MX
|
PS2PP_MX310
},
/* MX310 */
static
struct
ps2pp_info
ps2pp_list
[]
=
{
{
12
,
0
,
PS2PP_SIDE_BTN
},
{
13
,
0
,
0
},
{
40
,
0
,
PS2PP_SIDE_BTN
},
{
41
,
0
,
PS2PP_SIDE_BTN
},
{
42
,
0
,
PS2PP_SIDE_BTN
},
{
43
,
0
,
PS2PP_SIDE_BTN
},
{
50
,
0
,
0
},
{
51
,
0
,
0
},
{
52
,
PS2PP_KIND_WHEEL
,
PS2PP_SIDE_BTN
|
PS2PP_WHEEL
},
{
53
,
PS2PP_KIND_WHEEL
,
PS2PP_WHEEL
},
{
61
,
PS2PP_KIND_MX
,
PS2PP_WHEEL
|
PS2PP_SIDE_BTN
|
PS2PP_TASK_BTN
|
PS2PP_EXTRA_BTN
|
PS2PP_NAV_BTN
},
/* MX700 */
{
73
,
0
,
PS2PP_SIDE_BTN
},
{
75
,
PS2PP_KIND_WHEEL
,
PS2PP_WHEEL
},
{
76
,
PS2PP_KIND_WHEEL
,
PS2PP_WHEEL
},
{
80
,
PS2PP_KIND_WHEEL
,
PS2PP_SIDE_BTN
|
PS2PP_WHEEL
},
{
81
,
PS2PP_KIND_WHEEL
,
PS2PP_WHEEL
},
{
83
,
PS2PP_KIND_WHEEL
,
PS2PP_WHEEL
},
{
88
,
PS2PP_KIND_WHEEL
,
PS2PP_WHEEL
},
{
96
,
0
,
0
},
{
97
,
PS2PP_KIND_TP3
,
PS2PP_WHEEL
|
PS2PP_HWHEEL
},
{
100
,
PS2PP_KIND_MX
,
PS2PP_WHEEL
|
PS2PP_SIDE_BTN
|
PS2PP_TASK_BTN
|
PS2PP_EXTRA_BTN
|
PS2PP_NAV_BTN
},
/* MX510 */
{
112
,
PS2PP_KIND_MX
,
PS2PP_WHEEL
|
PS2PP_SIDE_BTN
|
PS2PP_TASK_BTN
|
PS2PP_EXTRA_BTN
|
PS2PP_NAV_BTN
},
/* MX500 */
{
114
,
PS2PP_KIND_MX
,
PS2PP_WHEEL
|
PS2PP_SIDE_BTN
|
PS2PP_TASK_BTN
|
PS2PP_EXTRA_BTN
},
/* M310 */
{
}
};
int
i
;
psmouse
->
vendor
=
"Logitech"
;
psmouse
->
model
=
((
param
[
0
]
>>
4
)
&
0x07
)
|
((
param
[
0
]
<<
3
)
&
0x78
);
if
(
param
[
1
]
<
3
)
clear_bit
(
BTN_MIDDLE
,
psmouse
->
dev
.
keybit
);
if
(
param
[
1
]
<
2
)
clear_bit
(
BTN_RIGHT
,
psmouse
->
dev
.
keybit
);
for
(
i
=
0
;
ps2pp_list
[
i
].
model
;
i
++
)
if
(
model
==
ps2pp_list
[
i
].
model
)
return
&
ps2pp_list
[
i
];
return
NULL
;
}
psmouse
->
type
=
PSMOUSE_PS2
;
/*
* Set up input device's properties based on the detected mouse model.
*/
for
(
i
=
0
;
logips2pp_list
[
i
].
model
;
i
++
){
if
(
logips2pp_list
[
i
].
model
==
psmouse
->
model
){
psmouse
->
type
=
PSMOUSE_PS2PP
;
if
(
logips2pp_list
[
i
].
features
&
PS2PP_4BTN
)
static
void
ps2pp_set_model_properties
(
struct
psmouse
*
psmouse
,
struct
ps2pp_info
*
model_info
)
{
if
(
model_info
->
features
&
PS2PP_SIDE_BTN
)
set_bit
(
BTN_SIDE
,
psmouse
->
dev
.
keybit
);
if
(
logips2pp_list
[
i
].
features
&
PS2PP_WHEEL
){
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
psmouse
->
name
=
"Wheel Mouse"
;
}
if
(
logips2pp_list
[
i
].
features
&
PS2PP_MX
)
{
set_bit
(
BTN_SIDE
,
psmouse
->
dev
.
keybit
);
if
(
model_info
->
features
&
PS2PP_EXTRA_BTN
)
set_bit
(
BTN_EXTRA
,
psmouse
->
dev
.
keybit
);
if
(
model_info
->
features
&
PS2PP_TASK_BTN
)
set_bit
(
BTN_TASK
,
psmouse
->
dev
.
keybit
);
if
(
!
(
logips2pp_list
[
i
].
features
&
PS2PP_MX310
)){
set_bit
(
BTN_BACK
,
psmouse
->
dev
.
keybit
);
if
(
model_info
->
features
&
PS2PP_NAV_BTN
)
{
set_bit
(
BTN_FORWARD
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_BACK
,
psmouse
->
dev
.
keybit
);
}
if
(
model_info
->
features
&
PS2PP_WHEEL
)
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
if
(
model_info
->
features
&
PS2PP_HWHEEL
)
set_bit
(
REL_HWHEEL
,
psmouse
->
dev
.
relbit
);
switch
(
model_info
->
kind
)
{
case
PS2PP_KIND_WHEEL
:
psmouse
->
name
=
"Wheel Mouse"
;
break
;
case
PS2PP_KIND_MX
:
psmouse
->
name
=
"MX Mouse"
;
}
break
;
case
PS2PP_KIND_TP3
:
psmouse
->
name
=
"TouchPad 3"
;
break
;
}
}
}
/*
* Do Logitech PS2++ / PS2T++ magic init.
* Logitech magic init. Detect whether the mouse is a Logitech one
* and its exact model and try turning on extended protocol for ones
* that support it.
*/
if
(
psmouse
->
type
==
PSMOUSE_PS2PP
)
{
if
(
psmouse
->
model
==
97
)
{
/* TouchPad 3 */
int
ps2pp_init
(
struct
psmouse
*
psmouse
,
int
set_properties
)
{
unsigned
char
param
[
4
];
unsigned
char
protocol
=
PSMOUSE_PS2
;
unsigned
char
model
,
buttons
;
struct
ps2pp_info
*
model_info
;
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
set_bit
(
REL_HWHEEL
,
psmouse
->
dev
.
relbit
);
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
param
[
1
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
if
(
param
[
1
]
!=
0
)
{
model
=
((
param
[
0
]
>>
4
)
&
0x07
)
|
((
param
[
0
]
<<
3
)
&
0x78
);
buttons
=
param
[
1
];
model_info
=
get_model_info
(
model
);
param
[
0
]
=
0x11
;
param
[
1
]
=
0x04
;
param
[
2
]
=
0x68
;
/* Unprotect RAM */
/*
* Do Logitech PS2++ / PS2T++ magic init.
*/
if
(
model
==
97
)
{
/* Touch Pad 3 */
/* Unprotect RAM */
param
[
0
]
=
0x11
;
param
[
1
]
=
0x04
;
param
[
2
]
=
0x68
;
psmouse_command
(
psmouse
,
param
,
0x30d1
);
param
[
0
]
=
0x11
;
param
[
1
]
=
0x05
;
param
[
2
]
=
0x0b
;
/* Enable features */
/* Enable features */
param
[
0
]
=
0x11
;
param
[
1
]
=
0x05
;
param
[
2
]
=
0x0b
;
psmouse_command
(
psmouse
,
param
,
0x30d1
);
param
[
0
]
=
0x11
;
param
[
1
]
=
0x09
;
param
[
2
]
=
0xc3
;
/* Enable PS2++ */
/* Enable PS2++ */
param
[
0
]
=
0x11
;
param
[
1
]
=
0x09
;
param
[
2
]
=
0xc3
;
psmouse_command
(
psmouse
,
param
,
0x30d1
);
param
[
0
]
=
0
;
if
(
!
psmouse_command
(
psmouse
,
param
,
0x13d1
)
&&
param
[
0
]
==
0x06
&&
param
[
1
]
==
0x00
&&
param
[
2
]
==
0x14
)
{
psmouse
->
name
=
"TouchPad 3"
;
return
PSMOUSE_PS2TPP
;
protocol
=
PSMOUSE_PS2TPP
;
}
}
else
{
}
else
if
(
get_model_info
(
model
)
!=
NULL
)
{
param
[
0
]
=
param
[
1
]
=
param
[
2
]
=
0
;
ps2pp_cmd
(
psmouse
,
param
,
0x39
);
/* Magic knock */
ps2pp_cmd
(
psmouse
,
param
,
0xDB
);
if
((
param
[
0
]
&
0x78
)
==
0x48
&&
(
param
[
1
]
&
0xf3
)
==
0xc2
&&
(
param
[
2
]
&
3
)
==
((
param
[
1
]
>>
2
)
&
3
))
{
if
((
param
[
0
]
&
0x78
)
==
0x48
&&
(
param
[
1
]
&
0xf3
)
==
0xc2
&&
(
param
[
2
]
&
0x03
)
==
((
param
[
1
]
>>
2
)
&
3
))
{
ps2pp_set_smartscroll
(
psmouse
);
return
PSMOUSE_PS2PP
;
}
protocol
=
PSMOUSE_PS2PP
;
}
}
return
0
;
}
if
(
set_properties
)
{
psmouse
->
vendor
=
"Logitech"
;
psmouse
->
model
=
model
;
/*
* Logitech magic init.
*/
int
ps2pp_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
if
(
buttons
<
3
)
clear_bit
(
BTN_MIDDLE
,
psmouse
->
dev
.
keybit
);
if
(
buttons
<
2
)
clear_bit
(
BTN_RIGHT
,
psmouse
->
dev
.
keybit
);
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
param
[
1
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
if
(
model_info
)
ps2pp_set_model_properties
(
psmouse
,
model_info
);
}
}
return
p
aram
[
1
]
!=
0
?
ps2pp_detect_model
(
psmouse
,
param
)
:
0
;
return
p
rotocol
;
}
drivers/input/mouse/logips2pp.h
View file @
fd58ee61
...
...
@@ -11,13 +11,8 @@
#ifndef _LOGIPS2PP_H
#define _LOGIPS2PP_H
#define PS2PP_4BTN 0x01
#define PS2PP_WHEEL 0x02
#define PS2PP_MX 0x04
#define PS2PP_MX310 0x08
struct
psmouse
;
void
ps2pp_process_packet
(
struct
psmouse
*
psmouse
);
void
ps2pp_set_800dpi
(
struct
psmouse
*
psmouse
);
int
ps2pp_detect
(
struct
psmouse
*
psmouse
);
int
ps2pp_init
(
struct
psmouse
*
psmouse
,
int
set_properties
);
#endif
drivers/input/mouse/psmouse-base.c
View file @
fd58ee61
...
...
@@ -43,9 +43,9 @@ int psmouse_smartscroll = 1;
module_param_named
(
smartscroll
,
psmouse_smartscroll
,
bool
,
0
);
MODULE_PARM_DESC
(
smartscroll
,
"Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."
);
unsigned
int
psmouse_resetafter
;
static
unsigned
int
psmouse_resetafter
;
module_param_named
(
resetafter
,
psmouse_resetafter
,
uint
,
0
);
MODULE_PARM_DESC
(
resetafter
,
"Reset
Synaptics Touchpad
after so many bad packets (0 = never)."
);
MODULE_PARM_DESC
(
resetafter
,
"Reset
device
after so many bad packets (0 = never)."
);
__obsolete_setup
(
"psmouse_noext"
);
__obsolete_setup
(
"psmouse_resolution="
);
...
...
@@ -56,15 +56,22 @@ __obsolete_setup("psmouse_rate=");
static
char
*
psmouse_protocols
[]
=
{
"None"
,
"PS/2"
,
"PS2++"
,
"PS2T++"
,
"GenPS/2"
,
"ImPS/2"
,
"ImExPS/2"
,
"SynPS/2"
};
/*
* psmouse_process_
packet() analyzes the PS/2 mouse packet contents and
* re
ports relevant events to the input module
.
* psmouse_process_
byte() analyzes the PS/2 data stream and reports
* re
levant events to the input module once full packet has arrived
.
*/
static
void
psmouse_process_packet
(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
)
static
psmouse_ret_t
psmouse_process_byte
(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
)
{
struct
input_dev
*
dev
=
&
psmouse
->
dev
;
unsigned
char
*
packet
=
psmouse
->
packet
;
if
(
psmouse
->
pktcnt
<
3
+
(
psmouse
->
type
>=
PSMOUSE_GENPS
))
return
PSMOUSE_GOOD_DATA
;
/*
* Full packet accumulated, process it
*/
input_regs
(
dev
,
regs
);
/*
...
...
@@ -112,6 +119,8 @@ static void psmouse_process_packet(struct psmouse *psmouse, struct pt_regs *regs
input_report_rel
(
dev
,
REL_Y
,
packet
[
2
]
?
(
int
)
((
packet
[
0
]
<<
3
)
&
0x100
)
-
(
int
)
packet
[
2
]
:
0
);
input_sync
(
dev
);
return
PSMOUSE_FULL_PACKET
;
}
/*
...
...
@@ -123,6 +132,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
)
{
struct
psmouse
*
psmouse
=
serio
->
private
;
psmouse_ret_t
rc
;
if
(
psmouse
->
state
==
PSMOUSE_IGNORE
)
goto
out
;
...
...
@@ -132,34 +142,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
;
}
...
...
@@ -180,7 +201,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if
(
psmouse
->
pktcnt
==
2
)
{
if
(
psmouse
->
packet
[
1
]
==
PSMOUSE_RET_ID
)
{
psmouse
->
state
=
PSMOUSE_IGNORE
;
serio_re
scan
(
serio
);
serio_re
connect
(
serio
);
goto
out
;
}
if
(
psmouse
->
type
==
PSMOUSE_SYNAPTICS
)
{
...
...
@@ -193,19 +214,32 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
}
}
if
(
psmouse
->
type
==
PSMOUSE_SYNAPTICS
)
{
/*
* The synaptics driver has its own resync logic,
* so it needs to receive all bytes one at a time.
*/
synaptics_process_byte
(
psmouse
,
regs
);
goto
out
;
rc
=
psmouse
->
protocol_handler
(
psmouse
,
regs
);
switch
(
rc
)
{
case
PSMOUSE_BAD_DATA
:
printk
(
KERN_WARNING
"psmouse.c: %s at %s lost sync at byte %d
\n
"
,
psmouse
->
name
,
psmouse
->
phys
,
psmouse
->
pktcnt
);
psmouse
->
pktcnt
=
0
;
if
(
++
psmouse
->
out_of_sync
==
psmouse_resetafter
)
{
psmouse
->
state
=
PSMOUSE_IGNORE
;
printk
(
KERN_NOTICE
"psmouse.c: issuing reconnect request
\n
"
);
serio_reconnect
(
psmouse
->
serio
);
}
break
;
if
(
psmouse
->
pktcnt
==
3
+
(
psmouse
->
type
>=
PSMOUSE_GENPS
))
{
psmouse_process_packet
(
psmouse
,
regs
);
case
PSMOUSE_FULL_PACKET
:
psmouse
->
pktcnt
=
0
;
goto
out
;
if
(
psmouse
->
out_of_sync
)
{
psmouse
->
out_of_sync
=
0
;
printk
(
KERN_NOTICE
"psmouse.c: %s at %s - driver resynched.
\n
"
,
psmouse
->
name
,
psmouse
->
phys
);
}
break
;
case
PSMOUSE_GOOD_DATA
:
break
;
}
out:
return
IRQ_HANDLED
;
...
...
@@ -219,18 +253,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
(
!
psmouse
->
ack
&&
timeout
--
)
udelay
(
10
);
while
(
test_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
)
&&
timeout
--
)
udelay
(
1
);
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
return
-
(
psmouse
->
ack
<=
0
)
;
return
-
psmouse
->
nak
;
}
/*
...
...
@@ -250,39 +281,79 @@ 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
(
psmouse
->
cmdcnt
&&
timeout
--
)
{
while
(
test_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
)
&&
timeout
--
)
{
if
(
psmouse
->
cmdcnt
==
1
&&
command
==
PSMOUSE_CMD_RESET_BAT
&&
timeout
>
100000
)
/* do not run in a endless loop */
timeout
=
100000
;
/* 1 sec */
if
(
!
test_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
))
{
if
(
psmouse
->
cmdcnt
==
1
&&
command
==
PSMOUSE_CMD_GETID
&&
psmouse
->
cmdbuf
[
1
]
!=
0xab
&&
psmouse
->
cmdbuf
[
1
]
!=
0xac
)
{
if
(
command
==
PSMOUSE_CMD_RESET_BAT
&&
timeout
>
100000
)
timeout
=
100000
;
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
* or Synaptics touchpads. The command is encoded as:
* 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
* is the command.
*/
int
psmouse_sliced_command
(
struct
psmouse
*
psmouse
,
unsigned
char
command
)
{
int
i
;
if
(
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
))
return
-
1
;
for
(
i
=
6
;
i
>=
0
;
i
-=
2
)
{
unsigned
char
d
=
(
command
>>
i
)
&
3
;
if
(
psmouse_command
(
psmouse
,
&
d
,
PSMOUSE_CMD_SETRES
))
return
-
1
;
}
return
0
;
}
...
...
@@ -363,31 +434,31 @@ static int im_explorer_detect(struct psmouse *psmouse)
* the mouse may have.
*/
static
int
psmouse_extensions
(
struct
psmouse
*
psmouse
)
static
int
psmouse_extensions
(
struct
psmouse
*
psmouse
,
unsigned
int
max_proto
,
int
set_properties
)
{
int
synaptics_hardware
=
0
;
psmouse
->
vendor
=
"Generic"
;
psmouse
->
name
=
"Mouse"
;
psmouse
->
model
=
0
;
/*
* Try Synaptics TouchPad
*/
if
(
psmouse_
max_proto
>
PSMOUSE_PS2
&&
synaptics_detect
(
psmouse
))
{
if
(
max_proto
>
PSMOUSE_PS2
&&
synaptics_detect
(
psmouse
))
{
synaptics_hardware
=
1
;
if
(
set_properties
)
{
psmouse
->
vendor
=
"Synaptics"
;
psmouse
->
name
=
"TouchPad"
;
}
if
(
psmouse_
max_proto
>
PSMOUSE_IMEX
)
{
if
(
synaptics_init
(
psmouse
)
==
0
)
if
(
max_proto
>
PSMOUSE_IMEX
)
{
if
(
!
set_properties
||
synaptics_init
(
psmouse
)
==
0
)
return
PSMOUSE_SYNAPTICS
;
/*
* Some Synaptics touchpads can emulate extended protocols (like IMPS/2).
* Unfortunately Logitech/Genius probes confuse some firmware versions so
* we'll have to skip them.
*/
psmouse_
max_proto
=
PSMOUSE_IMEX
;
max_proto
=
PSMOUSE_IMEX
;
}
/*
* Make sure that touchpad is in relative mode, gestures (taps) are enabled
...
...
@@ -395,35 +466,46 @@ static int psmouse_extensions(struct psmouse *psmouse)
synaptics_reset
(
psmouse
);
}
if
(
psmouse_max_proto
>
PSMOUSE_IMEX
&&
genius_detect
(
psmouse
))
{
if
(
max_proto
>
PSMOUSE_IMEX
&&
genius_detect
(
psmouse
))
{
if
(
set_properties
)
{
set_bit
(
BTN_EXTRA
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_SIDE
,
psmouse
->
dev
.
keybit
);
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
psmouse
->
vendor
=
"Genius"
;
psmouse
->
name
=
"Wheel Mouse"
;
}
return
PSMOUSE_GENPS
;
}
if
(
psmouse_
max_proto
>
PSMOUSE_IMEX
)
{
int
type
=
ps2pp_
detect
(
psmouse
);
if
(
type
)
if
(
max_proto
>
PSMOUSE_IMEX
)
{
int
type
=
ps2pp_
init
(
psmouse
,
set_properties
);
if
(
type
>
PSMOUSE_PS2
)
return
type
;
}
if
(
psmouse_max_proto
>=
PSMOUSE_IMPS
&&
intellimouse_detect
(
psmouse
))
{
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
if
(
max_proto
>=
PSMOUSE_IMEX
&&
im_explorer_detect
(
psmouse
))
{
if
(
psmouse_max_proto
>=
PSMOUSE_IMEX
&&
im_explorer_detect
(
psmouse
))
{
if
(
set_properties
)
{
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
set_bit
(
BTN_SIDE
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_EXTRA
,
psmouse
->
dev
.
keybit
);
if
(
!
psmouse
->
name
)
psmouse
->
name
=
"Explorer Mouse"
;
}
return
PSMOUSE_IMEX
;
}
if
(
max_proto
>=
PSMOUSE_IMPS
&&
intellimouse_detect
(
psmouse
))
{
if
(
set_properties
)
{
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
if
(
!
psmouse
->
name
)
psmouse
->
name
=
"Wheel Mouse"
;
}
return
PSMOUSE_IMPS
;
}
...
...
@@ -473,12 +555,7 @@ static int psmouse_probe(struct psmouse *psmouse)
if
(
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_RESET_DIS
))
printk
(
KERN_WARNING
"psmouse.c: Failed to reset mouse on %s
\n
"
,
psmouse
->
serio
->
phys
);
/*
* And here we try to determine if it has any extensions over the
* basic PS/2 3-button mouse.
*/
return
psmouse
->
type
=
psmouse_extensions
(
psmouse
);
return
0
;
}
/*
...
...
@@ -616,7 +693,6 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_REL
);
psmouse
->
dev
.
keybit
[
LONG
(
BTN_MOUSE
)]
=
BIT
(
BTN_LEFT
)
|
BIT
(
BTN_MIDDLE
)
|
BIT
(
BTN_RIGHT
);
psmouse
->
dev
.
relbit
[
0
]
=
BIT
(
REL_X
)
|
BIT
(
REL_Y
);
psmouse
->
state
=
PSMOUSE_CMD_MODE
;
psmouse
->
serio
=
serio
;
psmouse
->
dev
.
private
=
psmouse
;
...
...
@@ -628,13 +704,21 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
return
;
}
if
(
psmouse_probe
(
psmouse
)
<
=
0
)
{
if
(
psmouse_probe
(
psmouse
)
<
0
)
{
serio_close
(
serio
);
kfree
(
psmouse
);
serio
->
private
=
NULL
;
return
;
}
psmouse
->
type
=
psmouse_extensions
(
psmouse
,
psmouse_max_proto
,
1
);
if
(
!
psmouse
->
vendor
)
psmouse
->
vendor
=
"Generic"
;
if
(
!
psmouse
->
name
)
psmouse
->
name
=
"Mouse"
;
if
(
!
psmouse
->
protocol_handler
)
psmouse
->
protocol_handler
=
psmouse_process_byte
;
sprintf
(
psmouse
->
devname
,
"%s %s %s"
,
psmouse_protocols
[
psmouse
->
type
],
psmouse
->
vendor
,
psmouse
->
name
);
sprintf
(
psmouse
->
phys
,
"%s/input0"
,
...
...
@@ -668,27 +752,29 @@ static int psmouse_reconnect(struct serio *serio)
{
struct
psmouse
*
psmouse
=
serio
->
private
;
struct
serio_dev
*
dev
=
serio
->
dev
;
int
old_type
;
if
(
!
dev
||
!
psmouse
)
{
printk
(
KERN_DEBUG
"psmouse: reconnect request, but serio is disconnected, ignoring...
\n
"
);
return
-
1
;
}
old_type
=
psmouse
->
type
;
psmouse
->
state
=
PSMOUSE_CMD_MODE
;
psmouse
->
type
=
psmouse
->
acking
=
psmouse
->
cmdcnt
=
psmouse
->
pktcnt
=
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
;
}
else
if
(
psmouse_probe
(
psmouse
)
!=
old_type
)
}
else
if
(
psmouse_probe
(
psmouse
)
<
0
||
psmouse
->
type
!=
psmouse_extensions
(
psmouse
,
psmouse_max_proto
,
0
))
return
-
1
;
/* ok, the device type (and capabilities) match the old one,
* we can continue using it, complete intialization
*/
psmouse
->
type
=
old_type
;
psmouse_initialize
(
psmouse
);
if
(
psmouse
->
ptport
)
{
...
...
drivers/input/mouse/psmouse.h
View file @
fd58ee61
...
...
@@ -22,6 +22,18 @@
#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
,
PSMOUSE_GOOD_DATA
,
PSMOUSE_FULL_PACKET
}
psmouse_ret_t
;
struct
psmouse
;
struct
psmouse_ptport
{
...
...
@@ -45,13 +57,15 @@ struct psmouse {
unsigned
char
type
;
unsigned
char
model
;
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
);
};
...
...
@@ -65,10 +79,10 @@ struct psmouse {
#define PSMOUSE_SYNAPTICS 7
int
psmouse_command
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
,
int
command
);
int
psmouse_sliced_command
(
struct
psmouse
*
psmouse
,
unsigned
char
command
);
int
psmouse_reset
(
struct
psmouse
*
psmouse
);
extern
int
psmouse_smartscroll
;
extern
unsigned
int
psmouse_rate
;
extern
unsigned
int
psmouse_resetafter
;
#endif
/* _PSMOUSE_H */
drivers/input/mouse/synaptics.c
View file @
fd58ee61
...
...
@@ -43,34 +43,12 @@
* Synaptics communications functions
****************************************************************************/
/*
* Use the Synaptics extended ps/2 syntax to write a special command byte.
* special command: 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
* is the command. A 0xF3 or 0xE9 must follow (see synaptics_send_cmd
* and synaptics_mode_cmd)
*/
static
int
synaptics_special_cmd
(
struct
psmouse
*
psmouse
,
unsigned
char
command
)
{
int
i
;
if
(
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
))
return
-
1
;
for
(
i
=
6
;
i
>=
0
;
i
-=
2
)
{
unsigned
char
d
=
(
command
>>
i
)
&
3
;
if
(
psmouse_command
(
psmouse
,
&
d
,
PSMOUSE_CMD_SETRES
))
return
-
1
;
}
return
0
;
}
/*
* Send a command to the synpatics touchpad by special commands
*/
static
int
synaptics_send_cmd
(
struct
psmouse
*
psmouse
,
unsigned
char
c
,
unsigned
char
*
param
)
{
if
(
synaptics_special_cm
d
(
psmouse
,
c
))
if
(
psmouse_sliced_comman
d
(
psmouse
,
c
))
return
-
1
;
if
(
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
))
return
-
1
;
...
...
@@ -84,7 +62,7 @@ static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode)
{
unsigned
char
param
[
1
];
if
(
synaptics_special_cm
d
(
psmouse
,
mode
))
if
(
psmouse_sliced_comman
d
(
psmouse
,
mode
))
return
-
1
;
param
[
0
]
=
SYN_PS_SET_MODE2
;
if
(
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
))
...
...
@@ -118,17 +96,31 @@ static int synaptics_capability(struct psmouse *psmouse)
if
(
synaptics_send_cmd
(
psmouse
,
SYN_QUE_CAPABILITIES
,
cap
))
return
-
1
;
priv
->
capabilities
=
(
cap
[
0
]
<<
16
)
|
(
cap
[
1
]
<<
8
)
|
cap
[
2
];
priv
->
capabilities
=
(
cap
[
0
]
<<
16
)
|
(
cap
[
1
]
<<
8
)
|
cap
[
2
];
priv
->
ext_cap
=
0
;
if
(
!
SYN_CAP_VALID
(
priv
->
capabilities
))
return
-
1
;
if
(
SYN_EXT_CAP_REQUESTS
(
priv
->
capabilities
))
{
/*
* Unless capExtended is set the rest of the flags should be ignored
*/
if
(
!
SYN_CAP_EXTENDED
(
priv
->
capabilities
))
priv
->
capabilities
=
0
;
if
(
SYN_EXT_CAP_REQUESTS
(
priv
->
capabilities
)
>=
1
)
{
if
(
synaptics_send_cmd
(
psmouse
,
SYN_QUE_EXT_CAPAB
,
cap
))
{
printk
(
KERN_ERR
"Synaptics claims to have extended capabilities,"
" but I'm not able to read them."
);
}
else
priv
->
ext_cap
=
(
cap
[
0
]
<<
16
)
|
(
cap
[
1
]
<<
8
)
|
cap
[
2
];
}
else
{
priv
->
ext_cap
=
(
cap
[
0
]
<<
16
)
|
(
cap
[
1
]
<<
8
)
|
cap
[
2
];
/*
* if nExtBtn is greater than 8 it should be considered
* invalid and treated as 0
*/
if
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
>
8
)
priv
->
ext_cap
&=
0xff0fff
;
}
}
return
0
;
}
...
...
@@ -167,11 +159,12 @@ static void print_ident(struct synaptics_data *priv)
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
))
{
printk
(
KERN_INFO
" Touchpad has extended capability bits
\n
"
);
if
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
&&
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
<=
8
)
if
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
))
printk
(
KERN_INFO
" -> %d multi-buttons, i.e. besides standard buttons
\n
"
,
(
int
)(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)));
else
if
(
SYN_CAP_FOUR_BUTTON
(
priv
->
capabilities
))
if
(
SYN_CAP_MIDDLE_BUTTON
(
priv
->
capabilities
))
printk
(
KERN_INFO
" -> middle button
\n
"
);
if
(
SYN_CAP_FOUR_BUTTON
(
priv
->
capabilities
))
printk
(
KERN_INFO
" -> four buttons
\n
"
);
if
(
SYN_CAP_MULTIFINGER
(
priv
->
capabilities
))
printk
(
KERN_INFO
" -> multifinger detection
\n
"
);
...
...
@@ -219,21 +212,12 @@ static int synaptics_set_mode(struct psmouse *psmouse, int mode)
/*****************************************************************************
* Synaptics pass-through PS/2 port support
****************************************************************************/
static
int
synaptics_pt_open
(
struct
serio
*
port
)
{
return
0
;
}
static
void
synaptics_pt_close
(
struct
serio
*
port
)
{
}
static
int
synaptics_pt_write
(
struct
serio
*
port
,
unsigned
char
c
)
{
struct
psmouse
*
parent
=
port
->
driver
;
char
rate_param
=
SYN_PS_CLIENT_CMD
;
/* indicates that we want pass-through port */
if
(
synaptics_special_cm
d
(
parent
,
c
))
if
(
psmouse_sliced_comman
d
(
parent
,
c
))
return
-
1
;
if
(
psmouse_command
(
parent
,
&
rate_param
,
PSMOUSE_CMD_SETRATE
))
return
-
1
;
...
...
@@ -289,165 +273,11 @@ static void synaptics_pt_create(struct psmouse *psmouse)
port
->
serio
.
name
=
"Synaptics pass-through"
;
port
->
serio
.
phys
=
"synaptics-pt/serio0"
;
port
->
serio
.
write
=
synaptics_pt_write
;
port
->
serio
.
open
=
synaptics_pt_open
;
port
->
serio
.
close
=
synaptics_pt_close
;
port
->
serio
.
driver
=
psmouse
;
port
->
activate
=
synaptics_pt_activate
;
}
/*****************************************************************************
* Driver initialization/cleanup functions
****************************************************************************/
static
inline
void
set_abs_params
(
struct
input_dev
*
dev
,
int
axis
,
int
min
,
int
max
,
int
fuzz
,
int
flat
)
{
dev
->
absmin
[
axis
]
=
min
;
dev
->
absmax
[
axis
]
=
max
;
dev
->
absfuzz
[
axis
]
=
fuzz
;
dev
->
absflat
[
axis
]
=
flat
;
set_bit
(
axis
,
dev
->
absbit
);
}
static
void
set_input_params
(
struct
input_dev
*
dev
,
struct
synaptics_data
*
priv
)
{
set_bit
(
EV_ABS
,
dev
->
evbit
);
set_abs_params
(
dev
,
ABS_X
,
XMIN_NOMINAL
,
XMAX_NOMINAL
,
0
,
0
);
set_abs_params
(
dev
,
ABS_Y
,
YMIN_NOMINAL
,
YMAX_NOMINAL
,
0
,
0
);
set_abs_params
(
dev
,
ABS_PRESSURE
,
0
,
255
,
0
,
0
);
set_bit
(
ABS_TOOL_WIDTH
,
dev
->
absbit
);
set_bit
(
EV_KEY
,
dev
->
evbit
);
set_bit
(
BTN_TOUCH
,
dev
->
keybit
);
set_bit
(
BTN_TOOL_FINGER
,
dev
->
keybit
);
set_bit
(
BTN_TOOL_DOUBLETAP
,
dev
->
keybit
);
set_bit
(
BTN_TOOL_TRIPLETAP
,
dev
->
keybit
);
set_bit
(
BTN_LEFT
,
dev
->
keybit
);
set_bit
(
BTN_RIGHT
,
dev
->
keybit
);
set_bit
(
BTN_FORWARD
,
dev
->
keybit
);
set_bit
(
BTN_BACK
,
dev
->
keybit
);
if
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
))
{
switch
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
&
~
0x01
)
{
default:
/*
* if nExtBtn is greater than 8 it should be considered
* invalid and treated as 0
*/
break
;
case
8
:
set_bit
(
BTN_7
,
dev
->
keybit
);
set_bit
(
BTN_6
,
dev
->
keybit
);
case
6
:
set_bit
(
BTN_5
,
dev
->
keybit
);
set_bit
(
BTN_4
,
dev
->
keybit
);
case
4
:
set_bit
(
BTN_3
,
dev
->
keybit
);
set_bit
(
BTN_2
,
dev
->
keybit
);
case
2
:
set_bit
(
BTN_1
,
dev
->
keybit
);
set_bit
(
BTN_0
,
dev
->
keybit
);
break
;
}
}
clear_bit
(
EV_REL
,
dev
->
evbit
);
clear_bit
(
REL_X
,
dev
->
relbit
);
clear_bit
(
REL_Y
,
dev
->
relbit
);
}
void
synaptics_reset
(
struct
psmouse
*
psmouse
)
{
/* reset touchpad back to relative mode, gestures enabled */
synaptics_mode_cmd
(
psmouse
,
0
);
}
static
void
synaptics_disconnect
(
struct
psmouse
*
psmouse
)
{
synaptics_reset
(
psmouse
);
kfree
(
psmouse
->
private
);
}
static
int
synaptics_reconnect
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
struct
synaptics_data
old_priv
=
*
priv
;
if
(
!
synaptics_detect
(
psmouse
))
return
-
1
;
if
(
synaptics_query_hardware
(
psmouse
))
{
printk
(
KERN_ERR
"Unable to query Synaptics hardware.
\n
"
);
return
-
1
;
}
if
(
old_priv
.
identity
!=
priv
->
identity
||
old_priv
.
model_id
!=
priv
->
model_id
||
old_priv
.
capabilities
!=
priv
->
capabilities
||
old_priv
.
ext_cap
!=
priv
->
ext_cap
)
return
-
1
;
if
(
synaptics_set_mode
(
psmouse
,
0
))
{
printk
(
KERN_ERR
"Unable to initialize Synaptics hardware.
\n
"
);
return
-
1
;
}
return
0
;
}
int
synaptics_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
return
param
[
1
]
==
0x47
;
}
int
synaptics_init
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
;
psmouse
->
private
=
priv
=
kmalloc
(
sizeof
(
struct
synaptics_data
),
GFP_KERNEL
);
if
(
!
priv
)
return
-
1
;
memset
(
priv
,
0
,
sizeof
(
struct
synaptics_data
));
if
(
synaptics_query_hardware
(
psmouse
))
{
printk
(
KERN_ERR
"Unable to query Synaptics hardware.
\n
"
);
goto
init_fail
;
}
if
(
synaptics_set_mode
(
psmouse
,
0
))
{
printk
(
KERN_ERR
"Unable to initialize Synaptics hardware.
\n
"
);
goto
init_fail
;
}
priv
->
pkt_type
=
SYN_MODEL_NEWABS
(
priv
->
model_id
)
?
SYN_NEWABS
:
SYN_OLDABS
;
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
)
&&
SYN_CAP_PASS_THROUGH
(
priv
->
capabilities
))
synaptics_pt_create
(
psmouse
);
print_ident
(
priv
);
set_input_params
(
&
psmouse
->
dev
,
priv
);
psmouse
->
disconnect
=
synaptics_disconnect
;
psmouse
->
reconnect
=
synaptics_reconnect
;
return
0
;
init_fail:
kfree
(
priv
);
return
-
1
;
}
/*****************************************************************************
* Functions to interpret the absolute mode packets
****************************************************************************/
...
...
@@ -471,17 +301,17 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
hw
->
left
=
(
buf
[
0
]
&
0x01
)
?
1
:
0
;
hw
->
right
=
(
buf
[
0
]
&
0x02
)
?
1
:
0
;
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
)
&&
(
SYN_CAP_FOUR_BUTTON
(
priv
->
capabilities
)))
{
hw
->
up
=
((
buf
[
3
]
&
0x01
))
?
1
:
0
;
if
(
hw
->
left
)
hw
->
up
=
!
hw
->
up
;
hw
->
down
=
((
buf
[
3
]
&
0x02
))
?
1
:
0
;
if
(
hw
->
right
)
hw
->
down
=
!
hw
->
down
;
if
(
SYN_CAP_MIDDLE_BUTTON
(
priv
->
capabilities
))
hw
->
middle
=
((
buf
[
0
]
^
buf
[
3
])
&
0x01
)
?
1
:
0
;
if
(
SYN_CAP_FOUR_BUTTON
(
priv
->
capabilities
))
{
hw
->
up
=
((
buf
[
0
]
^
buf
[
3
])
&
0x01
)
?
1
:
0
;
hw
->
down
=
((
buf
[
0
]
^
buf
[
3
])
&
0x02
)
?
1
:
0
;
}
if
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
&&
((
buf
[
3
]
&
2
)
?
!
hw
->
right
:
hw
->
right
))
{
((
buf
[
0
]
^
buf
[
3
])
&
0x02
))
{
switch
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
&
~
0x01
)
{
default:
/*
...
...
@@ -490,17 +320,17 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
*/
break
;
case
8
:
hw
->
b7
=
((
buf
[
5
]
&
0x08
))
?
1
:
0
;
hw
->
b6
=
((
buf
[
4
]
&
0x08
))
?
1
:
0
;
hw
->
ext_buttons
|=
((
buf
[
5
]
&
0x08
))
?
0x80
:
0
;
hw
->
ext_buttons
|=
((
buf
[
4
]
&
0x08
))
?
0x40
:
0
;
case
6
:
hw
->
b5
=
((
buf
[
5
]
&
0x04
))
?
1
:
0
;
hw
->
b4
=
((
buf
[
4
]
&
0x04
))
?
1
:
0
;
hw
->
ext_buttons
|=
((
buf
[
5
]
&
0x04
))
?
0x20
:
0
;
hw
->
ext_buttons
|=
((
buf
[
4
]
&
0x04
))
?
0x10
:
0
;
case
4
:
hw
->
b3
=
((
buf
[
5
]
&
0x02
))
?
1
:
0
;
hw
->
b2
=
((
buf
[
4
]
&
0x02
))
?
1
:
0
;
hw
->
ext_buttons
|=
((
buf
[
5
]
&
0x02
))
?
0x08
:
0
;
hw
->
ext_buttons
|=
((
buf
[
4
]
&
0x02
))
?
0x04
:
0
;
case
2
:
hw
->
b1
=
((
buf
[
5
]
&
0x01
))
?
1
:
0
;
hw
->
b0
=
((
buf
[
4
]
&
0x01
))
?
1
:
0
;
hw
->
ext_buttons
|=
((
buf
[
5
]
&
0x01
))
?
0x02
:
0
;
hw
->
ext_buttons
|=
((
buf
[
4
]
&
0x01
))
?
0x0
1
:
0
;
}
}
}
else
{
...
...
@@ -525,6 +355,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
struct
synaptics_hw_state
hw
;
int
num_fingers
;
int
finger_width
;
int
i
;
synaptics_parse_hw_state
(
psmouse
->
packet
,
priv
,
&
hw
);
...
...
@@ -572,30 +403,18 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_report_key
(
dev
,
BTN_LEFT
,
hw
.
left
);
input_report_key
(
dev
,
BTN_RIGHT
,
hw
.
right
);
if
(
SYN_CAP_MIDDLE_BUTTON
(
priv
->
capabilities
))
input_report_key
(
dev
,
BTN_MIDDLE
,
hw
.
middle
);
if
(
SYN_CAP_FOUR_BUTTON
(
priv
->
capabilities
))
{
input_report_key
(
dev
,
BTN_FORWARD
,
hw
.
up
);
input_report_key
(
dev
,
BTN_BACK
,
hw
.
down
);
if
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
))
switch
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
&
~
0x01
)
{
default:
/*
* if nExtBtn is greater than 8 it should be considered
* invalid and treated as 0
*/
break
;
case
8
:
input_report_key
(
dev
,
BTN_7
,
hw
.
b7
);
input_report_key
(
dev
,
BTN_6
,
hw
.
b6
);
case
6
:
input_report_key
(
dev
,
BTN_5
,
hw
.
b5
);
input_report_key
(
dev
,
BTN_4
,
hw
.
b4
);
case
4
:
input_report_key
(
dev
,
BTN_3
,
hw
.
b3
);
input_report_key
(
dev
,
BTN_2
,
hw
.
b2
);
case
2
:
input_report_key
(
dev
,
BTN_1
,
hw
.
b1
);
input_report_key
(
dev
,
BTN_0
,
hw
.
b0
);
break
;
}
for
(
i
=
0
;
i
<
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
);
i
++
)
input_report_key
(
dev
,
BTN_0
+
i
,
hw
.
ext_buttons
&
(
1
<<
i
));
input_sync
(
dev
);
}
...
...
@@ -607,6 +426,9 @@ static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned cha
static
unsigned
char
oldabs_mask
[]
=
{
0xC0
,
0x60
,
0x00
,
0xC0
,
0x60
};
static
unsigned
char
oldabs_rslt
[]
=
{
0xC0
,
0x00
,
0x00
,
0x80
,
0x00
};
if
(
idx
<
0
||
idx
>
4
)
return
0
;
switch
(
pkt_type
)
{
case
SYN_NEWABS
:
case
SYN_NEWABS_RELAXED
:
...
...
@@ -637,7 +459,7 @@ static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
return
SYN_NEWABS_STRICT
;
}
void
synaptics_process_byte
(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
)
static
psmouse_ret_t
synaptics_process_byte
(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
)
{
struct
input_dev
*
dev
=
&
psmouse
->
dev
;
struct
synaptics_data
*
priv
=
psmouse
->
private
;
...
...
@@ -645,11 +467,6 @@ void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
input_regs
(
dev
,
regs
);
if
(
psmouse
->
pktcnt
>=
6
)
{
/* Full packet received */
if
(
priv
->
out_of_sync
)
{
priv
->
out_of_sync
=
0
;
printk
(
KERN_NOTICE
"Synaptics driver resynced.
\n
"
);
}
if
(
unlikely
(
priv
->
pkt_type
==
SYN_NEWABS
))
priv
->
pkt_type
=
synaptics_detect_pkt_type
(
psmouse
);
...
...
@@ -657,16 +474,142 @@ void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
synaptics_pass_pt_packet
(
&
psmouse
->
ptport
->
serio
,
psmouse
->
packet
);
else
synaptics_process_packet
(
psmouse
);
psmouse
->
pktcnt
=
0
;
}
else
if
(
psmouse
->
pktcnt
&&
!
synaptics_validate_byte
(
psmouse
->
packet
,
psmouse
->
pktcnt
-
1
,
priv
->
pkt_type
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at byte %d
\n
"
,
psmouse
->
pktcnt
);
psmouse
->
pktcnt
=
0
;
if
(
++
priv
->
out_of_sync
==
psmouse_resetafter
)
{
psmouse
->
state
=
PSMOUSE_IGNORE
;
printk
(
KERN_NOTICE
"synaptics: issuing reconnect request
\n
"
);
serio_reconnect
(
psmouse
->
serio
);
return
PSMOUSE_FULL_PACKET
;
}
return
synaptics_validate_byte
(
psmouse
->
packet
,
psmouse
->
pktcnt
-
1
,
priv
->
pkt_type
)
?
PSMOUSE_GOOD_DATA
:
PSMOUSE_BAD_DATA
;
}
/*****************************************************************************
* Driver initialization/cleanup functions
****************************************************************************/
static
void
set_input_params
(
struct
input_dev
*
dev
,
struct
synaptics_data
*
priv
)
{
int
i
;
set_bit
(
EV_ABS
,
dev
->
evbit
);
input_set_abs_params
(
dev
,
ABS_X
,
XMIN_NOMINAL
,
XMAX_NOMINAL
,
0
,
0
);
input_set_abs_params
(
dev
,
ABS_Y
,
YMIN_NOMINAL
,
YMAX_NOMINAL
,
0
,
0
);
input_set_abs_params
(
dev
,
ABS_PRESSURE
,
0
,
255
,
0
,
0
);
set_bit
(
ABS_TOOL_WIDTH
,
dev
->
absbit
);
set_bit
(
EV_KEY
,
dev
->
evbit
);
set_bit
(
BTN_TOUCH
,
dev
->
keybit
);
set_bit
(
BTN_TOOL_FINGER
,
dev
->
keybit
);
set_bit
(
BTN_TOOL_DOUBLETAP
,
dev
->
keybit
);
set_bit
(
BTN_TOOL_TRIPLETAP
,
dev
->
keybit
);
set_bit
(
BTN_LEFT
,
dev
->
keybit
);
set_bit
(
BTN_RIGHT
,
dev
->
keybit
);
if
(
SYN_CAP_MIDDLE_BUTTON
(
priv
->
capabilities
))
set_bit
(
BTN_MIDDLE
,
dev
->
keybit
);
if
(
SYN_CAP_FOUR_BUTTON
(
priv
->
capabilities
))
{
set_bit
(
BTN_FORWARD
,
dev
->
keybit
);
set_bit
(
BTN_BACK
,
dev
->
keybit
);
}
for
(
i
=
0
;
i
<
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
);
i
++
)
set_bit
(
BTN_0
+
i
,
dev
->
keybit
);
clear_bit
(
EV_REL
,
dev
->
evbit
);
clear_bit
(
REL_X
,
dev
->
relbit
);
clear_bit
(
REL_Y
,
dev
->
relbit
);
}
void
synaptics_reset
(
struct
psmouse
*
psmouse
)
{
/* reset touchpad back to relative mode, gestures enabled */
synaptics_mode_cmd
(
psmouse
,
0
);
}
static
void
synaptics_disconnect
(
struct
psmouse
*
psmouse
)
{
synaptics_reset
(
psmouse
);
kfree
(
psmouse
->
private
);
}
static
int
synaptics_reconnect
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
struct
synaptics_data
old_priv
=
*
priv
;
if
(
!
synaptics_detect
(
psmouse
))
return
-
1
;
if
(
synaptics_query_hardware
(
psmouse
))
{
printk
(
KERN_ERR
"Unable to query Synaptics hardware.
\n
"
);
return
-
1
;
}
if
(
old_priv
.
identity
!=
priv
->
identity
||
old_priv
.
model_id
!=
priv
->
model_id
||
old_priv
.
capabilities
!=
priv
->
capabilities
||
old_priv
.
ext_cap
!=
priv
->
ext_cap
)
return
-
1
;
if
(
synaptics_set_mode
(
psmouse
,
0
))
{
printk
(
KERN_ERR
"Unable to initialize Synaptics hardware.
\n
"
);
return
-
1
;
}
return
0
;
}
int
synaptics_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
return
param
[
1
]
==
0x47
;
}
int
synaptics_init
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
;
psmouse
->
private
=
priv
=
kmalloc
(
sizeof
(
struct
synaptics_data
),
GFP_KERNEL
);
if
(
!
priv
)
return
-
1
;
memset
(
priv
,
0
,
sizeof
(
struct
synaptics_data
));
if
(
synaptics_query_hardware
(
psmouse
))
{
printk
(
KERN_ERR
"Unable to query Synaptics hardware.
\n
"
);
goto
init_fail
;
}
if
(
synaptics_set_mode
(
psmouse
,
0
))
{
printk
(
KERN_ERR
"Unable to initialize Synaptics hardware.
\n
"
);
goto
init_fail
;
}
priv
->
pkt_type
=
SYN_MODEL_NEWABS
(
priv
->
model_id
)
?
SYN_NEWABS
:
SYN_OLDABS
;
if
(
SYN_CAP_PASS_THROUGH
(
priv
->
capabilities
))
synaptics_pt_create
(
psmouse
);
print_ident
(
priv
);
set_input_params
(
&
psmouse
->
dev
,
priv
);
psmouse
->
protocol_handler
=
synaptics_process_byte
;
psmouse
->
disconnect
=
synaptics_disconnect
;
psmouse
->
reconnect
=
synaptics_reconnect
;
return
0
;
init_fail:
kfree
(
priv
);
return
-
1
;
}
drivers/input/mouse/synaptics.h
View file @
fd58ee61
...
...
@@ -9,7 +9,6 @@
#ifndef _SYNAPTICS_H
#define _SYNAPTICS_H
extern
void
synaptics_process_byte
(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
);
extern
int
synaptics_detect
(
struct
psmouse
*
psmouse
);
extern
int
synaptics_init
(
struct
psmouse
*
psmouse
);
extern
void
synaptics_reset
(
struct
psmouse
*
psmouse
);
...
...
@@ -44,13 +43,14 @@ extern void synaptics_reset(struct psmouse *psmouse);
/* synaptics capability bits */
#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23))
#define SYN_CAP_MIDDLE_BUTTON(c) ((c) & (1 << 18))
#define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7))
#define SYN_CAP_SLEEP(c) ((c) & (1 << 4))
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
#define SYN_EXT_CAP_REQUESTS(c) (((
(c) & 0x700000) >> 20) == 1
)
#define SYN_EXT_CAP_REQUESTS(c) (((
c) & 0x700000) >> 20
)
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
/* synaptics modes query bits */
...
...
@@ -86,18 +86,12 @@ struct synaptics_hw_state {
int
y
;
int
z
;
int
w
;
int
left
;
int
right
;
int
up
;
int
down
;
int
b0
;
int
b1
;
int
b2
;
int
b3
;
int
b4
;
int
b5
;
int
b6
;
int
b7
;
unsigned
int
left
:
1
;
unsigned
int
right
:
1
;
unsigned
int
middle
:
1
;
unsigned
int
up
:
1
;
unsigned
int
down
:
1
;
unsigned
char
ext_buttons
;
};
struct
synaptics_data
{
...
...
@@ -108,7 +102,6 @@ struct synaptics_data {
unsigned
long
int
identity
;
/* Identification */
/* Data for normal processing */
unsigned
int
out_of_sync
;
/* # of packets out of sync */
int
old_w
;
/* Previous w value */
unsigned
char
pkt_type
;
/* packet type - old, new, etc */
};
...
...
drivers/input/mousedev.c
View file @
fd58ee61
...
...
@@ -2,6 +2,7 @@
* Input driver to ExplorerPS/2 device driver module.
*
* Copyright (c) 1999-2002 Vojtech Pavlik
* 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
...
...
@@ -47,15 +48,24 @@ static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
module_param
(
yres
,
uint
,
0
);
MODULE_PARM_DESC
(
yres
,
"Vertical screen resolution"
);
struct
mousedev_motion
{
int
dx
,
dy
,
dz
;
};
struct
mousedev
{
int
exist
;
int
open
;
int
minor
;
int
misc
;
char
name
[
16
];
wait_queue_head_t
wait
;
struct
list_head
list
;
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
;
};
struct
mousedev_list
{
...
...
@@ -63,13 +73,10 @@ struct mousedev_list {
struct
mousedev
*
mousedev
;
struct
list_head
node
;
int
dx
,
dy
,
dz
;
int
old_x
[
4
],
old_y
[
4
];
unsigned
long
buttons
;
signed
char
ps2
[
6
];
unsigned
char
ready
,
buffer
,
bufsiz
;
unsigned
char
mode
,
imexseq
,
impsseq
;
unsigned
int
pkt_count
;
unsigned
char
touch
;
};
#define MOUSEDEV_SEQ_LEN 6
...
...
@@ -82,135 +89,157 @@ static struct input_handler mousedev_handler;
static
struct
mousedev
*
mousedev_table
[
MOUSEDEV_MINORS
];
static
struct
mousedev
mousedev_mix
;
#define fx(i) (
list->old_x[(list
->pkt_count - (i)) & 03])
#define fy(i) (
list->old_y[(list
->pkt_count - (i)) & 03])
#define fx(i) (
mousedev->old_x[(mousedev
->pkt_count - (i)) & 03])
#define fy(i) (
mousedev->old_y[(mousedev
->pkt_count - (i)) & 03])
static
void
mousedev_
abs_event
(
struct
input_handle
*
handle
,
struct
mousedev_list
*
list
,
unsigned
int
code
,
int
value
)
static
void
mousedev_
touchpad_event
(
struct
mousedev
*
mousedev
,
unsigned
int
code
,
int
value
)
{
int
size
;
int
touchpad
;
/* Ignore joysticks */
if
(
test_bit
(
BTN_TRIGGER
,
handle
->
dev
->
keybit
))
return
;
touchpad
=
test_bit
(
BTN_TOOL_FINGER
,
handle
->
dev
->
keybit
);
if
(
mousedev
->
touch
)
{
switch
(
code
)
{
case
ABS_X
:
if
(
touchpad
)
{
if
(
list
->
touch
)
{
fx
(
0
)
=
value
;
if
(
list
->
pkt_count
>=
2
)
list
->
dx
=
((
fx
(
0
)
-
fx
(
1
))
/
2
+
(
fx
(
1
)
-
fx
(
2
))
/
2
)
/
8
;
}
}
else
{
size
=
handle
->
dev
->
absmax
[
ABS_X
]
-
handle
->
dev
->
absmin
[
ABS_X
];
if
(
size
==
0
)
size
=
xres
;
list
->
dx
+=
(
value
*
xres
-
list
->
old_x
[
0
])
/
size
;
list
->
old_x
[
0
]
+=
list
->
dx
*
size
;
}
if
(
mousedev
->
pkt_count
>=
2
)
mousedev
->
packet
.
dx
=
((
fx
(
0
)
-
fx
(
1
))
/
2
+
(
fx
(
1
)
-
fx
(
2
))
/
2
)
/
8
;
break
;
case
ABS_Y
:
if
(
touchpad
)
{
if
(
list
->
touch
)
{
fy
(
0
)
=
value
;
if
(
list
->
pkt_count
>=
2
)
list
->
dy
=
-
((
fy
(
0
)
-
fy
(
1
))
/
2
+
(
fy
(
1
)
-
fy
(
2
))
/
2
)
/
8
;
}
}
else
{
size
=
handle
->
dev
->
absmax
[
ABS_Y
]
-
handle
->
dev
->
absmin
[
ABS_Y
];
if
(
size
==
0
)
size
=
yres
;
list
->
dy
-=
(
value
*
yres
-
list
->
old_y
[
0
])
/
size
;
list
->
old_y
[
0
]
-=
list
->
dy
*
size
;
}
if
(
mousedev
->
pkt_count
>=
2
)
mousedev
->
packet
.
dy
=
-
((
fy
(
0
)
-
fy
(
1
))
/
2
+
(
fy
(
1
)
-
fy
(
2
))
/
2
)
/
8
;
break
;
}
}
}
static
void
mousedev_
event
(
struct
input_handle
*
handle
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
static
void
mousedev_
abs_event
(
struct
input_dev
*
dev
,
struct
mousedev
*
mousedev
,
unsigned
int
code
,
int
value
)
{
struct
mousedev
*
mousedevs
[
3
]
=
{
handle
->
private
,
&
mousedev_mix
,
NULL
};
struct
mousedev
**
mousedev
=
mousedevs
;
struct
mousedev_list
*
list
;
int
index
,
wake
;
while
(
*
mousedev
)
{
int
size
;
wake
=
0
;
switch
(
code
)
{
case
ABS_X
:
size
=
dev
->
absmax
[
ABS_X
]
-
dev
->
absmin
[
ABS_X
];
if
(
size
==
0
)
size
=
xres
;
mousedev
->
packet
.
dx
=
(
value
*
xres
-
mousedev
->
old_x
[
0
])
/
size
;
mousedev
->
old_x
[
0
]
=
mousedev
->
packet
.
dx
*
size
;
break
;
list_for_each_entry
(
list
,
&
(
*
mousedev
)
->
list
,
node
)
switch
(
type
)
{
case
EV_ABS
:
mousedev_abs_event
(
handle
,
list
,
code
,
value
);
case
ABS_Y
:
size
=
dev
->
absmax
[
ABS_Y
]
-
dev
->
absmin
[
ABS_Y
];
if
(
size
==
0
)
size
=
yres
;
mousedev
->
packet
.
dy
=
(
value
*
yres
-
mousedev
->
old_y
[
0
])
/
size
;
mousedev
->
old_y
[
0
]
=
mousedev
->
packet
.
dy
*
size
;
break
;
}
}
case
EV_REL
:
static
void
mousedev_rel_event
(
struct
mousedev
*
mousedev
,
unsigned
int
code
,
int
value
)
{
switch
(
code
)
{
case
REL_X
:
list
->
dx
+=
value
;
break
;
case
REL_Y
:
list
->
dy
-=
value
;
break
;
case
REL_WHEEL
:
if
(
list
->
mode
)
list
->
dz
-=
value
;
break
;
case
REL_X
:
mousedev
->
packet
.
dx
+=
value
;
break
;
case
REL_Y
:
mousedev
->
packet
.
dy
-=
value
;
break
;
case
REL_WHEEL
:
mousedev
->
packet
.
dz
-=
value
;
break
;
}
break
;
}
case
EV_KEY
:
if
(
code
==
BTN_TOUCH
&&
test_bit
(
BTN_TOOL_FINGER
,
handle
->
dev
->
keybit
))
{
/* Handle touchpad data */
list
->
touch
=
value
;
if
(
!
list
->
touch
)
list
->
pkt_count
=
0
;
break
;
}
static
void
mousedev_key_event
(
struct
mousedev
*
mousedev
,
unsigned
int
code
,
int
value
)
{
int
index
;
switch
(
code
)
{
case
BTN_TOUCH
:
case
BTN_0
:
case
BTN_FORWARD
:
case
BTN_LEFT
:
index
=
0
;
break
;
case
BTN_4
:
case
BTN_EXTRA
:
if
(
list
->
mode
==
2
)
{
index
=
4
;
break
;
}
case
BTN_STYLUS
:
case
BTN_1
:
case
BTN_RIGHT
:
index
=
1
;
break
;
case
BTN_3
:
case
BTN_BACK
:
case
BTN_SIDE
:
if
(
list
->
mode
==
2
)
{
index
=
3
;
break
;
}
case
BTN_2
:
case
BTN_STYLUS2
:
case
BTN_MIDDLE
:
index
=
2
;
break
;
case
BTN_3
:
case
BTN_BACK
:
case
BTN_SIDE
:
index
=
3
;
break
;
case
BTN_4
:
case
BTN_EXTRA
:
index
=
4
;
break
;
default:
return
;
}
switch
(
value
)
{
case
0
:
clear_bit
(
index
,
&
list
->
buttons
);
break
;
case
1
:
set_bit
(
index
,
&
list
->
buttons
);
break
;
case
2
:
return
;
}
break
;
case
EV_SYN
:
switch
(
code
)
{
case
SYN_REPORT
:
if
(
list
->
touch
)
{
list
->
pkt_count
++
;
/* Input system eats duplicate events,
* but we need all of them to do correct
* averaging so apply present one forward
*/
fx
(
0
)
=
fx
(
1
);
fy
(
0
)
=
fy
(
1
);
if
(
value
)
{
set_bit
(
index
,
&
mousedev
->
buttons
);
set_bit
(
index
,
&
mousedev_mix
.
buttons
);
}
else
{
clear_bit
(
index
,
&
mousedev
->
buttons
);
clear_bit
(
index
,
&
mousedev_mix
.
buttons
);
}
}
static
void
mousedev_notify_readers
(
struct
mousedev
*
mousedev
,
struct
mousedev_motion
*
packet
)
{
struct
mousedev_list
*
list
;
list_for_each_entry
(
list
,
&
mousedev
->
list
,
node
)
{
list
->
dx
+=
packet
->
dx
;
list
->
dy
+=
packet
->
dy
;
list
->
dz
+=
packet
->
dz
;
list
->
buttons
=
mousedev
->
buttons
;
list
->
ready
=
1
;
kill_fasync
(
&
list
->
fasync
,
SIGIO
,
POLL_IN
);
wake
=
1
;
}
wake_up_interruptible
(
&
mousedev
->
wait
);
}
static
void
mousedev_event
(
struct
input_handle
*
handle
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
struct
mousedev
*
mousedev
=
handle
->
private
;
switch
(
type
)
{
case
EV_ABS
:
/* Ignore joysticks */
if
(
test_bit
(
BTN_TRIGGER
,
handle
->
dev
->
keybit
))
return
;
if
(
test_bit
(
BTN_TOOL_FINGER
,
handle
->
dev
->
keybit
))
mousedev_touchpad_event
(
mousedev
,
code
,
value
);
else
mousedev_abs_event
(
handle
->
dev
,
mousedev
,
code
,
value
);
break
;
case
EV_REL
:
mousedev_rel_event
(
mousedev
,
code
,
value
);
break
;
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
;
}
else
mousedev_key_event
(
mousedev
,
code
,
value
);
}
break
;
case
EV_SYN
:
if
(
code
==
SYN_REPORT
)
{
if
(
mousedev
->
touch
)
{
mousedev
->
pkt_count
++
;
/* Input system eats duplicate events, but we need all of them
* to do correct averaging so apply present one forward
*/
fx
(
0
)
=
fx
(
1
);
fy
(
0
)
=
fy
(
1
);
}
if
(
wake
)
wake_up_interruptible
(
&
((
*
mousedev
)
->
wait
)
);
mousedev_notify_readers
(
mousedev
,
&
mousedev
->
packet
);
mousedev_notify_readers
(
&
mousedev_mix
,
&
mousedev
->
packet
);
mousedev
++
;
memset
(
&
mousedev
->
packet
,
0
,
sizeof
(
struct
mousedev_motion
));
}
break
;
}
}
...
...
@@ -326,6 +355,8 @@ static void mousedev_packet(struct mousedev_list *list, unsigned char off)
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
);
}
if
(
list
->
mode
==
1
)
{
...
...
@@ -391,9 +422,9 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si
list
->
impsseq
=
0
;
list
->
imexseq
=
0
;
list
->
mode
=
0
;
list
->
ps2
[
0
]
=
0xaa
;
list
->
ps2
[
1
]
=
0x00
;
list
->
bufsiz
=
2
;
list
->
ps2
[
1
]
=
0xaa
;
list
->
ps2
[
2
]
=
0x00
;
list
->
bufsiz
=
3
;
break
;
}
...
...
@@ -553,6 +584,7 @@ static struct input_handler mousedev_handler = {
static
struct
miscdevice
psaux_mouse
=
{
PSMOUSE_MINOR
,
"psaux"
,
&
mousedev_fops
};
static
int
psaux_registered
;
#endif
static
int
__init
mousedev_init
(
void
)
...
...
@@ -572,7 +604,7 @@ static int __init mousedev_init(void)
NULL
,
"mice"
);
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
if
(
!
(
mousedev_mix
.
misc
=
!
misc_register
(
&
psaux_mouse
)))
if
(
!
(
psaux_registered
=
!
misc_register
(
&
psaux_mouse
)))
printk
(
KERN_WARNING
"mice: could not misc_register the device
\n
"
);
#endif
...
...
@@ -584,7 +616,7 @@ static int __init mousedev_init(void)
static
void
__exit
mousedev_exit
(
void
)
{
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
if
(
mousedev_mix
.
misc
)
if
(
psaux_registered
)
misc_deregister
(
&
psaux_mouse
);
#endif
devfs_remove
(
"input/mice"
);
...
...
drivers/input/power.c
View file @
fd58ee61
...
...
@@ -172,3 +172,4 @@ module_exit(power_exit);
MODULE_AUTHOR
(
"James Simmons <jsimmons@transvirtual.com>"
);
MODULE_DESCRIPTION
(
"Input Power Management driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/serio/98kbd-io.c
View file @
fd58ee61
...
...
@@ -51,7 +51,7 @@ spinlock_t kbd98io_lock = SPIN_LOCK_UNLOCKED;
static
struct
serio
kbd98_port
;
extern
struct
pt_regs
*
kbd_pt_regs
;
static
void
kbd98io_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
irqreturn_t
kbd98io_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
/*
* kbd98_flush() flushes all data that may be in the keyboard buffers
...
...
@@ -143,7 +143,7 @@ static struct serio kbd98_port =
* to the upper layers.
*/
static
void
kbd98io_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
kbd98io_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
unsigned
long
flags
;
unsigned
char
data
;
...
...
@@ -154,6 +154,7 @@ static void kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock_irqrestore
(
&
kbd98io_lock
,
flags
);
serio_interrupt
(
&
kbd98_port
,
data
,
0
,
regs
);
return
IRQ_HANDLED
;
}
int
__init
kbd98io_init
(
void
)
...
...
drivers/input/serio/ct82c710.c
View file @
fd58ee61
drivers/input/serio/gscps2.c
View file @
fd58ee61
drivers/input/serio/i8042.c
View file @
fd58ee61
/*
* 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,9 @@ 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"
);
extern
unsigned
int
i8042_dmi_noloop
;
static
unsigned
int
i8042_noloop
;
__obsolete_setup
(
"i8042_noaux"
);
__obsolete_setup
(
"i8042_nomux"
);
__obsolete_setup
(
"i8042_unlock"
);
...
...
@@ -95,6 +98,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 +158,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
();
...
...
@@ -474,8 +481,17 @@ 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
)
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
);
return
-
1
;
}
if
(
mux_version
)
*
mux_version
=
~
param
;
...
...
@@ -532,8 +548,8 @@ static int __init i8042_check_mux(struct i8042_values *values)
return
-
1
;
/* Workaround for broken chips which seem to support MUX, but in reality don't. */
/* They all report version 1
2.10
*/
if
(
mux_version
==
0x
CA
)
/* They all report version 1
0.12
*/
if
(
mux_version
==
0x
AC
)
return
-
1
;
printk
(
KERN_INFO
"i8042.c: Detected active multiplexing controller, rev %d.%d.
\n
"
,
...
...
@@ -668,6 +684,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
...
...
@@ -714,12 +731,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
...
...
@@ -868,7 +887,7 @@ static int i8042_controller_resume(void)
static
int
i8042_notify_sys
(
struct
notifier_block
*
this
,
unsigned
long
code
,
void
*
unused
)
{
if
(
code
==
SYS_DOWN
||
code
==
SYS_HALT
)
if
(
code
==
SYS_DOWN
||
code
==
SYS_HALT
)
i8042_controller_cleanup
();
return
NOTIFY_DONE
;
}
...
...
@@ -955,6 +974,13 @@ int __init i8042_init(void)
if
(
i8042_dumbkbd
)
i8042_kbd_port
.
write
=
NULL
;
#ifdef __i386__
if
(
i8042_dmi_noloop
)
{
printk
(
KERN_INFO
"i8042.c: AUX LoopBack command disabled by DMI.
\n
"
);
i8042_noloop
=
1
;
}
#endif
if
(
!
i8042_noaux
&&
!
i8042_check_aux
(
&
i8042_aux_values
))
{
if
(
!
i8042_nomux
&&
!
i8042_check_mux
(
&
i8042_aux_values
))
for
(
i
=
0
;
i
<
4
;
i
++
)
{
...
...
@@ -997,8 +1023,6 @@ void __exit i8042_exit(void)
sysdev_class_unregister
(
&
kbc_sysclass
);
}
del_timer_sync
(
&
i8042_timer
);
i8042_controller_cleanup
();
if
(
i8042_kbd_values
.
exists
)
...
...
@@ -1010,6 +1034,7 @@ void __exit i8042_exit(void)
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
)
serio_unregister_port
(
i8042_mux_port
+
i
);
del_timer_sync
(
&
i8042_timer
);
i8042_platform_exit
();
}
...
...
drivers/input/serio/parkbd.c
View file @
fd58ee61
...
...
@@ -86,20 +86,9 @@ static int parkbd_write(struct serio *port, unsigned char c)
return
0
;
}
static
int
parkbd_open
(
struct
serio
*
port
)
{
return
0
;
}
static
void
parkbd_close
(
struct
serio
*
port
)
{
}
static
struct
serio
parkbd_port
=
{
.
write
=
parkbd_write
,
.
open
=
parkbd_open
,
.
close
=
parkbd_close
,
.
name
=
parkbd_name
,
.
phys
=
parkbd_phys
,
};
...
...
drivers/input/serio/q40kbd.c
View file @
fd58ee61
...
...
@@ -47,23 +47,12 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION
(
"Q40 PS/2 keyboard controller driver"
);
MODULE_LICENSE
(
"GPL"
);
static
int
q40kbd_open
(
struct
serio
*
port
)
{
return
0
;
}
static
void
q40kbd_close
(
struct
serio
*
port
)
{
}
static
struct
serio
q40kbd_port
=
{
.
type
=
SERIO_8042
,
.
name
=
"Q40 kbd port"
,
.
phys
=
"Q40"
,
.
write
=
NULL
,
.
open
=
q40kbd_open
,
.
close
=
q40kbd_close
,
};
static
irqreturn_t
q40kbd_interrupt
(
int
irq
,
void
*
dev_id
,
...
...
drivers/input/serio/rpckbd.c
View file @
fd58ee61
drivers/input/serio/serio.c
View file @
fd58ee61
...
...
@@ -67,12 +67,18 @@ struct serio_event {
struct
list_head
node
;
};
static
DECLARE_MUTEX
(
serio_sem
);
spinlock_t
serio_event_lock
=
SPIN_LOCK_UNLOCKED
;
/* protects serio_event_list */
static
DECLARE_MUTEX
(
serio_sem
);
/* protects serio_list and serio_dev_list */
static
LIST_HEAD
(
serio_list
);
static
LIST_HEAD
(
serio_dev_list
);
static
LIST_HEAD
(
serio_event_list
);
static
int
serio_pid
;
/*
* serio_find_dev() must be called with serio_sem down.
*/
static
void
serio_find_dev
(
struct
serio
*
serio
)
{
struct
serio_dev
*
dev
;
...
...
@@ -96,22 +102,42 @@ static DECLARE_COMPLETION(serio_exited);
static
void
serio_invalidate_pending_events
(
struct
serio
*
serio
)
{
struct
serio_event
*
event
;
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
;
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
}
void
serio_handle_events
(
void
)
{
struct
list_head
*
node
,
*
next
;
struct
list_head
*
node
;
struct
serio_event
*
event
;
unsigned
long
flags
;
list_for_each_safe
(
node
,
next
,
&
serio_event_list
)
{
while
(
1
)
{
spin_lock_irqsave
(
&
serio_event_lock
,
flags
);
if
(
list_empty
(
&
serio_event_list
))
{
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
break
;
}
node
=
serio_event_list
.
next
;
event
=
container_of
(
node
,
struct
serio_event
,
node
);
list_del_init
(
node
);
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
down
(
&
serio_sem
);
if
(
event
->
serio
==
NULL
)
if
(
event
->
serio
==
NULL
)
/*!!!*/
goto
event_done
;
switch
(
event
->
type
)
{
...
...
@@ -139,7 +165,6 @@ void serio_handle_events(void)
}
event_done:
up
(
&
serio_sem
);
list_del_init
(
node
);
kfree
(
event
);
}
}
...
...
@@ -165,8 +190,11 @@ static int serio_thread(void *nothing)
static
void
serio_queue_event
(
struct
serio
*
serio
,
int
event_type
)
{
unsigned
long
flags
;
struct
serio_event
*
event
;
spin_lock_irqsave
(
&
serio_event_lock
,
flags
);
if
((
event
=
kmalloc
(
sizeof
(
struct
serio_event
),
GFP_ATOMIC
)))
{
event
->
type
=
event_type
;
event
->
serio
=
serio
;
...
...
@@ -174,6 +202,8 @@ static void serio_queue_event(struct serio *serio, int event_type)
list_add_tail
(
&
event
->
node
,
&
serio_event_list
);
wake_up
(
&
serio_wait
);
}
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
}
void
serio_rescan
(
struct
serio
*
serio
)
...
...
@@ -187,21 +217,27 @@ void serio_reconnect(struct serio *serio)
}
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
)
unsigned
char
data
,
unsigned
int
dfl
,
struct
pt_regs
*
regs
)
{
unsigned
long
flags
;
irqreturn_t
ret
=
IRQ_NONE
;
spin_lock_irqsave
(
&
serio
->
lock
,
flags
);
if
(
serio
->
dev
&&
serio
->
dev
->
interrupt
)
{
ret
=
serio
->
dev
->
interrupt
(
serio
,
data
,
flags
,
regs
);
ret
=
serio
->
dev
->
interrupt
(
serio
,
data
,
dfl
,
regs
);
}
else
{
if
(
!
flags
)
{
if
((
serio
->
type
==
SERIO_8042
||
serio
->
type
==
SERIO_8042_XL
)
&&
(
data
!=
0xaa
))
return
ret
;
if
(
!
dfl
)
{
if
((
serio
->
type
!=
SERIO_8042
&&
serio
->
type
!=
SERIO_8042_XL
)
||
(
data
==
0xaa
))
{
serio_rescan
(
serio
);
ret
=
IRQ_HANDLED
;
}
}
}
spin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
return
ret
;
}
...
...
@@ -229,6 +265,7 @@ void serio_register_port_delayed(struct serio *serio)
*/
void
__serio_register_port
(
struct
serio
*
serio
)
{
spin_lock_init
(
&
serio
->
lock
);
list_add_tail
(
&
serio
->
node
,
&
serio_list
);
serio_find_dev
(
serio
);
}
...
...
@@ -292,9 +329,15 @@ void serio_unregister_device(struct serio_dev *dev)
/* called from serio_dev->connect/disconnect methods under serio_sem */
int
serio_open
(
struct
serio
*
serio
,
struct
serio_dev
*
dev
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
serio
->
lock
,
flags
);
serio
->
dev
=
dev
;
if
(
serio
->
open
(
serio
))
{
spin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
if
(
serio
->
open
&&
serio
->
open
(
serio
))
{
spin_lock_irqsave
(
&
serio
->
lock
,
flags
);
serio
->
dev
=
NULL
;
spin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
return
-
1
;
}
return
0
;
...
...
@@ -303,8 +346,13 @@ int serio_open(struct serio *serio, struct serio_dev *dev)
/* called from serio_dev->connect/disconnect methods under serio_sem */
void
serio_close
(
struct
serio
*
serio
)
{
unsigned
long
flags
;
if
(
serio
->
close
)
serio
->
close
(
serio
);
spin_lock_irqsave
(
&
serio
->
lock
,
flags
);
serio
->
dev
=
NULL
;
spin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
}
static
int
__init
serio_init
(
void
)
...
...
drivers/input/serio/serport.c
View file @
fd58ee61
...
...
@@ -48,11 +48,6 @@ static int serport_serio_write(struct serio *serio, unsigned char data)
return
-
(
serport
->
tty
->
driver
->
write
(
serport
->
tty
,
0
,
&
data
,
1
)
!=
1
);
}
static
int
serport_serio_open
(
struct
serio
*
serio
)
{
return
0
;
}
static
void
serport_serio_close
(
struct
serio
*
serio
)
{
struct
serport
*
serport
=
serio
->
driver
;
...
...
@@ -87,7 +82,6 @@ static int serport_ldisc_open(struct tty_struct *tty)
serport
->
serio
.
type
=
SERIO_RS232
;
serport
->
serio
.
write
=
serport_serio_write
;
serport
->
serio
.
open
=
serport_serio_open
;
serport
->
serio
.
close
=
serport_serio_close
;
serport
->
serio
.
driver
=
serport
;
...
...
drivers/input/touchscreen/gunze.c
View file @
fd58ee61
...
...
@@ -125,11 +125,9 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev)
init_input_dev
(
&
gunze
->
dev
);
gunze
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_ABS
);
gunze
->
dev
.
absbit
[
0
]
=
BIT
(
ABS_X
)
|
BIT
(
ABS_Y
);
gunze
->
dev
.
keybit
[
LONG
(
BTN_TOUCH
)]
=
BIT
(
BTN_TOUCH
);
gunze
->
dev
.
absmin
[
ABS_X
]
=
96
;
gunze
->
dev
.
absmin
[
ABS_Y
]
=
72
;
gunze
->
dev
.
absmax
[
ABS_X
]
=
4000
;
gunze
->
dev
.
absmax
[
ABS_Y
]
=
3000
;
input_set_abs_params
(
&
gunze
->
dev
,
ABS_X
,
96
,
4000
,
0
,
0
);
input_set_abs_params
(
&
gunze
->
dev
,
ABS_Y
,
72
,
3000
,
0
,
0
);
gunze
->
serio
=
serio
;
serio
->
private
=
gunze
;
...
...
drivers/input/touchscreen/h3600_ts_input.c
View file @
fd58ee61
...
...
@@ -45,6 +45,10 @@
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>
MODULE_AUTHOR
(
"James Simmons <jsimmons@transvirtual.com>"
);
MODULE_DESCRIPTION
(
"H3600 touchscreen driver"
);
MODULE_LICENSE
(
"GPL"
);
/*
* Definitions & global arrays.
*/
...
...
@@ -103,7 +107,7 @@ struct h3600_dev {
char
phys
[
32
];
};
static
void
action_button_handler
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
action_button_handler
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
int
down
=
(
GPLR
&
GPIO_BITSY_ACTION_BUTTON
)
?
0
:
1
;
struct
input_dev
*
dev
=
(
struct
input_dev
*
)
dev_id
;
...
...
@@ -111,9 +115,11 @@ static void action_button_handler(int irq, void *dev_id, struct pt_regs *regs)
input_regs
(
dev
,
regs
);
input_report_key
(
dev
,
KEY_ENTER
,
down
);
input_sync
(
dev
);
return
IRQ_HANDLED
;
}
static
void
npower_button_handler
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
npower_button_handler
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
int
down
=
(
GPLR
&
GPIO_BITSY_NPOWER_BUTTON
)
?
0
:
1
;
struct
input_dev
*
dev
=
(
struct
input_dev
*
)
dev_id
;
...
...
@@ -126,6 +132,8 @@ static void npower_button_handler(int irq, void *dev_id, struct pt_regs *regs)
input_report_key
(
dev
,
KEY_SUSPEND
,
1
);
input_report_key
(
dev
,
KEY_SUSPEND
,
down
);
input_sync
(
dev
);
return
IRQ_HANDLED
;
}
#ifdef CONFIG_PM
...
...
@@ -141,7 +149,7 @@ enum flite_pwr {
* h3600_flite_power: enables or disables power to frontlight, using last bright */
unsigned
int
h3600_flite_power
(
struct
input_dev
*
dev
,
enum
flite_pwr
pwr
)
{
unsigned
char
brightness
=
(
(
pwr
==
FLITE_PWR_OFF
)
?
0
:
flite_brightness
)
;
unsigned
char
brightness
=
(
pwr
==
FLITE_PWR_OFF
)
?
0
:
flite_brightness
;
struct
h3600_dev
*
ts
=
dev
->
private
;
/* Must be in this order */
...
...
@@ -317,8 +325,8 @@ static int state;
#define STATE_DATA 2
/* state where we decode data */
#define STATE_EOF 3
/* state where we decode checksum or EOF */
static
void
h3600ts_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
fla
gs
)
static
irqreturn_t
h3600ts_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
re
gs
)
{
struct
h3600_dev
*
ts
=
serio
->
private
;
...
...
@@ -329,7 +337,7 @@ static void h3600ts_interrupt(struct serio *serio, unsigned char data,
case
STATE_SOF
:
if
(
data
==
CHAR_SOF
)
state
=
STATE_ID
;
return
;
break
;
case
STATE_ID
:
ts
->
event
=
(
data
&
0xf0
)
>>
4
;
ts
->
len
=
(
data
&
0xf
);
...
...
@@ -339,7 +347,7 @@ static void h3600ts_interrupt(struct serio *serio, unsigned char data,
break
;
}
ts
->
chksum
=
data
;
state
=
(
ts
->
len
>
0
)
?
STATE_DATA
:
STATE_EOF
;
state
=
(
ts
->
len
>
0
)
?
STATE_DATA
:
STATE_EOF
;
break
;
case
STATE_DATA
:
ts
->
chksum
+=
data
;
...
...
@@ -349,13 +357,15 @@ static void h3600ts_interrupt(struct serio *serio, unsigned char data,
break
;
case
STATE_EOF
:
state
=
STATE_SOF
;
if
(
data
==
CHAR_EOF
||
data
==
ts
->
chksum
)
h3600ts_process_packet
(
ts
);
if
(
data
==
CHAR_EOF
||
data
==
ts
->
chksum
)
h3600ts_process_packet
(
ts
,
regs
);
break
;
default:
printk
(
"Error3
\n
"
);
break
;
}
return
IRQ_HANDLED
;
}
/*
...
...
@@ -378,8 +388,8 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
init_input_dev
(
&
ts
->
dev
);
/* Device specific stuff */
set_GPIO_IRQ_edge
(
GPIO_BITSY_ACTION_BUTTON
,
GPIO_BOTH_EDGES
);
set_GPIO_IRQ_edge
(
GPIO_BITSY_NPOWER_BUTTON
,
GPIO_RISING_EDGE
);
set_GPIO_IRQ_edge
(
GPIO_BITSY_ACTION_BUTTON
,
GPIO_BOTH_EDGES
);
set_GPIO_IRQ_edge
(
GPIO_BITSY_NPOWER_BUTTON
,
GPIO_RISING_EDGE
);
if
(
request_irq
(
IRQ_GPIO_BITSY_ACTION_BUTTON
,
action_button_handler
,
SA_SHIRQ
|
SA_INTERRUPT
|
SA_SAMPLE_RANDOM
,
...
...
@@ -397,17 +407,12 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
kfree
(
ts
);
return
;
}
/* Now we have things going we setup our input device */
ts
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_ABS
)
|
BIT
(
EV_LED
)
|
BIT
(
EV_PWR
);
ts
->
dev
.
absbit
[
0
]
=
BIT
(
ABS_X
)
|
BIT
(
ABS_Y
);
ts
->
dev
.
ledbit
[
0
]
=
BIT
(
LED_SLEEP
);
ts
->
dev
.
absmin
[
ABS_X
]
=
60
;
ts
->
dev
.
absmin
[
ABS_Y
]
=
35
;
ts
->
dev
.
absmax
[
ABS_X
]
=
985
;
ts
->
dev
.
absmax
[
ABS_Y
]
=
1024
;
ts
->
dev
.
absfuzz
[
ABS_X
]
=
0
;
ts
->
dev
.
absfuzz
[
ABS_Y
]
=
0
;
ts
->
serio
=
serio
;
serio
->
private
=
ts
;
input_set_abs_params
(
&
ts
->
dev
,
ABS_X
,
60
,
985
,
0
,
0
);
input_set_abs_params
(
&
ts
->
dev
,
ABS_Y
,
35
,
1024
,
0
,
0
);
set_bit
(
KEY_RECORD
,
ts
->
dev
.
keybit
);
set_bit
(
KEY_Q
,
ts
->
dev
.
keybit
);
...
...
@@ -422,6 +427,9 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
ts
->
dev
.
keybit
[
LONG
(
BTN_TOUCH
)]
|=
BIT
(
BTN_TOUCH
);
ts
->
dev
.
keybit
[
LONG
(
KEY_SUSPEND
)]
|=
BIT
(
KEY_SUSPEND
);
ts
->
serio
=
serio
;
serio
->
private
=
ts
;
sprintf
(
ts
->
phys
,
"%s/input0"
,
serio
->
phys
);
ts
->
dev
.
event
=
h3600ts_event
;
...
...
drivers/input/tsdev.c
View file @
fd58ee61
...
...
@@ -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 *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/usb/input/hiddev.c
View file @
fd58ee61
...
...
@@ -638,15 +638,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 @
fd58ee61
...
...
@@ -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 @
fd58ee61
...
...
@@ -728,3 +728,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 @
fd58ee61
...
...
@@ -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 @
fd58ee61
...
...
@@ -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
/*
...
...
@@ -749,8 +751,6 @@ struct ff_effect {
#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
((dev->keycodesize == 2) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
#define init_input_dev(dev) do { INIT_LIST_HEAD(&((dev)->h_list)); INIT_LIST_HEAD(&((dev)->node)); } while (0)
#define SET_INPUT_KEYCODE(dev, scancode, val) \
({ unsigned __old; \
switch (dev->keycodesize) { \
...
...
@@ -915,6 +915,12 @@ struct input_handle {
#define to_handle(n) container_of(n,struct input_handle,d_node)
#define to_handle_h(n) container_of(n,struct input_handle,h_node)
static
inline
void
init_input_dev
(
struct
input_dev
*
dev
)
{
INIT_LIST_HEAD
(
&
dev
->
h_list
);
INIT_LIST_HEAD
(
&
dev
->
node
);
}
void
input_register_device
(
struct
input_dev
*
);
void
input_unregister_device
(
struct
input_dev
*
);
...
...
@@ -932,14 +938,51 @@ int input_flush_device(struct input_handle* handle, struct file* file);
void
input_event
(
struct
input_dev
*
dev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
);
#define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c))
#define input_report_rel(a,b,c) input_event(a, EV_REL, b, c)
#define input_report_abs(a,b,c) input_event(a, EV_ABS, b, c)
#define input_report_ff(a,b,c) input_event(a, EV_FF, b, c)
#define input_report_ff_status(a,b,c) input_event(a, EV_FF_STATUS, b, c)
#define input_regs(a,b) do { (a)->regs = (b); } while (0)
#define input_sync(a) do { input_event(a, EV_SYN, SYN_REPORT, 0); (a)->regs = NULL; } while (0)
static
inline
void
input_report_key
(
struct
input_dev
*
dev
,
unsigned
int
code
,
int
value
)
{
input_event
(
dev
,
EV_KEY
,
code
,
!!
value
);
}
static
inline
void
input_report_rel
(
struct
input_dev
*
dev
,
unsigned
int
code
,
int
value
)
{
input_event
(
dev
,
EV_REL
,
code
,
value
);
}
static
inline
void
input_report_abs
(
struct
input_dev
*
dev
,
unsigned
int
code
,
int
value
)
{
input_event
(
dev
,
EV_ABS
,
code
,
value
);
}
static
inline
void
input_report_ff
(
struct
input_dev
*
dev
,
unsigned
int
code
,
int
value
)
{
input_event
(
dev
,
EV_FF
,
code
,
value
);
}
static
inline
void
input_report_ff_status
(
struct
input_dev
*
dev
,
unsigned
int
code
,
int
value
)
{
input_event
(
dev
,
EV_FF_STATUS
,
code
,
value
);
}
static
inline
void
input_regs
(
struct
input_dev
*
dev
,
struct
pt_regs
*
regs
)
{
dev
->
regs
=
regs
;
}
static
inline
void
input_sync
(
struct
input_dev
*
dev
)
{
input_event
(
dev
,
EV_SYN
,
SYN_REPORT
,
0
);
dev
->
regs
=
NULL
;
}
static
inline
void
input_set_abs_params
(
struct
input_dev
*
dev
,
int
axis
,
int
min
,
int
max
,
int
fuzz
,
int
flat
)
{
dev
->
absmin
[
axis
]
=
min
;
dev
->
absmax
[
axis
]
=
max
;
dev
->
absfuzz
[
axis
]
=
fuzz
;
dev
->
absflat
[
axis
]
=
flat
;
dev
->
absbit
[
LONG
(
axis
)]
|=
BIT
(
axis
);
}
extern
struct
class_simple
*
input_class
;
...
...
include/linux/serio.h
View file @
fd58ee61
...
...
@@ -17,6 +17,7 @@
#ifdef __KERNEL__
#include <linux/list.h>
#include <linux/spinlock.h>
struct
serio
{
void
*
private
;
...
...
@@ -32,11 +33,13 @@ 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_dev
*
dev
;
/* Accessed from interrupt, writes must be protected by serio_lock */
struct
list_head
node
;
};
...
...
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