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
5562dd00
Commit
5562dd00
authored
Jun 13, 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
992d6a32
214b7805
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
761 additions
and
352 deletions
+761
-352
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+6
-0
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/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+101
-46
drivers/input/misc/uinput.c
drivers/input/misc/uinput.c
+3
-0
drivers/input/mouse/Kconfig
drivers/input/mouse/Kconfig
+0
-2
drivers/input/mouse/logips2pp.c
drivers/input/mouse/logips2pp.c
+1
-1
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse-base.c
+78
-49
drivers/input/mouse/psmouse.h
drivers/input/mouse/psmouse.h
+7
-2
drivers/input/mousedev.c
drivers/input/mousedev.c
+135
-55
drivers/input/serio/i8042.c
drivers/input/serio/i8042.c
+20
-11
drivers/input/serio/serio.c
drivers/input/serio/serio.c
+128
-66
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
+2
-0
include/linux/serio.h
include/linux/serio.h
+4
-1
No files found.
Documentation/kernel-parameters.txt
View file @
5562dd00
...
...
@@ -652,6 +652,12 @@ running once the system is up.
mga= [HW,DRM]
mousedev.tap_time=
[MOUSE] Maximum time between finger touching and
leaving touchpad surface for touch to be considered
a tap and be reported as a left button click (for
touchpads working in absolute mode only).
Format: <msecs>
mousedev.xres= [MOUSE] Horizontal screen resolution, used for devices
reporting absolute coordinates, such as tablets
mousedev.yres= [MOUSE] Vertical screen resolution, used for devices
...
...
arch/i386/kernel/dmi_scan.c
View file @
5562dd00
...
...
@@ -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).
...
...
@@ -876,6 +890,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 @
5562dd00
...
...
@@ -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/keyboard/atkbd.c
View file @
5562dd00
...
...
@@ -47,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"
);
...
...
@@ -164,34 +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
;
/* Written only during init */
char
name
[
64
];
char
phys
[
32
];
unsigned
short
id
;
struct
serio
*
serio
;
struct
input_dev
dev
;
unsigned
char
set
;
unsigned
int
translated
:
1
;
unsigned
int
extra
:
1
;
unsigned
int
write
:
1
;
unsigned
short
id
;
unsigned
char
keycode
[
512
];
unsigned
char
translated
;
unsigned
char
extra
;
unsigned
char
write
;
/* Protected by FLAG_ACK */
unsigned
char
nak
;
/* Protected by FLAG_CMD */
unsigned
char
cmdbuf
[
4
];
unsigned
char
cmdcnt
;
volatile
signed
char
ack
;
unsigned
char
emul
;
unsigned
int
resend
:
1
;
unsigned
int
release
:
1
;
unsigned
int
bat_xl
:
1
;
unsigned
int
enabled
:
1
;
/* Accessed only from interrupt */
unsigned
char
emul
;
unsigned
char
resend
;
unsigned
char
release
;
unsigned
char
bat_xl
;
unsigned
int
last
;
unsigned
long
time
;
/* Flags */
unsigned
long
flags
;
};
static
void
atkbd_report_key
(
struct
input_dev
*
dev
,
struct
pt_regs
*
regs
,
int
code
,
int
value
)
...
...
@@ -224,7 +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
;
...
...
@@ -234,24 +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
(
!
atkbd
->
enabled
)
if
(
!
test_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
)
)
goto
out
;
input_event
(
&
atkbd
->
dev
,
EV_MSC
,
MSC_RAW
,
code
);
if
(
atkbd
->
translated
)
{
if
(
atkbd
->
emul
||
...
...
@@ -270,6 +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
:
...
...
@@ -300,6 +340,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
code
|=
(
atkbd
->
set
!=
3
)
?
0x80
:
0x100
;
}
if
(
atkbd
->
keycode
[
code
]
!=
ATKBD_KEY_NULL
)
input_event
(
&
atkbd
->
dev
,
EV_MSC
,
MSC_SCAN
,
code
);
switch
(
atkbd
->
keycode
[
code
])
{
case
ATKBD_KEY_NULL
:
break
;
...
...
@@ -376,18 +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
;
}
/*
...
...
@@ -405,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
++
)
...
...
@@ -413,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
(
atkbd
->
cmdcnt
&&
timeout
--
)
{
while
(
test_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
)
&&
timeout
--
)
{
if
(
atkbd
->
cmdcnt
==
1
&&
command
==
ATKBD_CMD_RESET_BAT
&&
timeout
>
100000
)
timeout
=
100000
;
if
(
!
test_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
))
{
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
)
{
atkbd
->
cmdcnt
=
0
;
break
;
if
(
command
==
ATKBD_CMD_GETID
&&
!
test_bit
(
ATKBD_FLAG_ID
,
&
atkbd
->
flags
))
{
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
atkbd
->
cmdcnt
=
0
;
break
;
}
}
udelay
(
1
);
}
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
if
(
param
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
param
[
i
]
=
atkbd
->
cmdbuf
[(
receive
-
1
)
-
i
];
if
(
command
==
ATKBD_CMD_RESET_BAT
&&
atkbd
->
cmdcnt
==
1
)
atkbd
->
cmdcnt
=
0
;
return
0
;
if
(
atkbd
->
cmdcnt
)
{
atkbd
->
cmdcnt
=
0
;
if
(
atkbd
->
cmdcnt
)
return
-
1
;
}
return
0
;
}
...
...
@@ -672,6 +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
);
...
...
@@ -709,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
);
...
...
@@ -754,8 +807,6 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd
->
id
=
0xab00
;
}
atkbd
->
enabled
=
1
;
if
(
atkbd
->
extra
)
{
atkbd
->
dev
.
ledbit
[
0
]
|=
BIT
(
LED_COMPOSE
)
|
BIT
(
LED_SUSPEND
)
|
BIT
(
LED_SLEEP
)
|
BIT
(
LED_MUTE
)
|
BIT
(
LED_MISC
);
sprintf
(
atkbd
->
name
,
"AT Set 2 Extra keyboard"
);
...
...
@@ -797,6 +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
);
}
...
...
@@ -832,6 +885,8 @@ static int atkbd_reconnect(struct serio *serio)
return
-
1
;
}
set_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
);
return
0
;
}
...
...
drivers/input/misc/uinput.c
View file @
5562dd00
...
...
@@ -279,6 +279,9 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait)
{
struct
uinput_device
*
udev
=
file
->
private_data
;
if
(
!
test_bit
(
UIST_CREATED
,
&
(
udev
->
state
)))
return
0
;
poll_wait
(
file
,
&
udev
->
waitq
,
wait
);
if
(
udev
->
head
!=
udev
->
tail
)
...
...
drivers/input/mouse/Kconfig
View file @
5562dd00
...
...
@@ -30,8 +30,6 @@ config MOUSE_PS2
and a new verion of GPM at:
http://www.geocities.com/dt_or/gpm/gpm.html
to take advantage of the advanced features of the touchpad.
If you do not want install specialized drivers but want tapping
working please use option psmouse.proto=imps.
If unsure, say Y.
...
...
drivers/input/mouse/logips2pp.c
View file @
5562dd00
...
...
@@ -277,7 +277,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
protocol
=
PSMOUSE_PS2TPP
;
}
}
else
if
(
get_model_info
(
model
)
!=
NULL
)
{
}
else
if
(
model_info
!=
NULL
)
{
param
[
0
]
=
param
[
1
]
=
param
[
2
]
=
0
;
ps2pp_cmd
(
psmouse
,
param
,
0x39
);
/* Magic knock */
...
...
drivers/input/mouse/psmouse-base.c
View file @
5562dd00
...
...
@@ -142,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
->
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
;
}
psmouse
->
acking
=
0
;
goto
out
;
}
if
(
psmouse
->
cmdcnt
)
{
psmouse
->
cmdbuf
[
--
psmouse
->
cmdcnt
]
=
data
;
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
)
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
goto
out
;
}
...
...
@@ -242,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
;
}
/*
...
...
@@ -271,46 +279,62 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
psmouse
->
cmdcnt
=
receive
;
if
(
command
==
PSMOUSE_CMD_RESET_BAT
)
timeout
=
4000000
;
/* 4 sec */
timeout
=
4000000
;
/* 4 sec */
/* initialize cmdbuf with preset values from param */
if
(
receive
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
psmouse
->
cmdbuf
[(
receive
-
1
)
-
i
]
=
param
[
i
];
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
(
command
==
PSMOUSE_CMD_RESET_BAT
&&
timeout
>
100000
)
timeout
=
100000
;
if
(
psmouse
->
cmdcnt
==
1
&&
command
==
PSMOUSE_CMD_GETID
&&
psmouse
->
cmdbuf
[
1
]
!=
0xab
&&
psmouse
->
cmdbuf
[
1
]
!=
0xac
)
{
psmouse
->
cmdcnt
=
0
;
break
;
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
);
}
for
(
i
=
0
;
i
<
receive
;
i
++
)
param
[
i
]
=
psmouse
->
cmdbuf
[(
receive
-
1
)
-
i
];
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
...
...
@@ -735,7 +759,12 @@ static int psmouse_reconnect(struct serio *serio)
}
psmouse
->
state
=
PSMOUSE_CMD_MODE
;
psmouse
->
acking
=
psmouse
->
cmdcnt
=
psmouse
->
pktcnt
=
psmouse
->
out_of_sync
=
0
;
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
psmouse
->
pktcnt
=
psmouse
->
out_of_sync
=
0
;
if
(
psmouse
->
reconnect
)
{
if
(
psmouse
->
reconnect
(
psmouse
))
return
-
1
;
...
...
drivers/input/mouse/psmouse.h
View file @
5562dd00
...
...
@@ -22,6 +22,11 @@
#define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2
#define PSMOUSE_FLAG_ACK 0
/* Waiting for ACK/NAK */
#define PSMOUSE_FLAG_CMD 1
/* Waiting for command to finish */
#define PSMOUSE_FLAG_CMD1 2
/* First byte of command response */
#define PSMOUSE_FLAG_ID 3
/* First byte is not keyboard ID */
/* psmouse protocol handler return codes */
typedef
enum
{
PSMOUSE_BAD_DATA
,
...
...
@@ -54,11 +59,11 @@ struct psmouse {
unsigned
long
last
;
unsigned
long
out_of_sync
;
unsigned
char
state
;
char
acking
;
volatile
char
ack
;
unsigned
char
nak
;
char
error
;
char
devname
[
64
];
char
phys
[
32
];
unsigned
long
flags
;
psmouse_ret_t
(
*
protocol_handler
)(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
);
int
(
*
reconnect
)(
struct
psmouse
*
psmouse
);
...
...
drivers/input/mousedev.c
View file @
5562dd00
...
...
@@ -48,8 +48,13 @@ static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
module_param
(
yres
,
uint
,
0
);
MODULE_PARM_DESC
(
yres
,
"Vertical screen resolution"
);
static
unsigned
tap_time
=
200
;
module_param
(
tap_time
,
uint
,
0
);
MODULE_PARM_DESC
(
tap_time
,
"Tap time for touchpads in absolute mode (msecs)"
);
struct
mousedev_motion
{
int
dx
,
dy
,
dz
;
unsigned
long
buttons
;
};
struct
mousedev
{
...
...
@@ -62,21 +67,31 @@ struct mousedev {
struct
input_handle
handle
;
struct
mousedev_motion
packet
;
unsigned
long
buttons
;
unsigned
int
pkt_count
;
int
old_x
[
4
],
old_y
[
4
];
unsigned
int
touch
;
unsigned
long
touch
;
};
enum
mousedev_emul
{
MOUSEDEV_EMUL_PS2
,
MOUSEDEV_EMUL_IMPS
,
MOUSEDEV_EMUL_EXPS
}
__attribute__
((
packed
));
#define PACKET_QUEUE_LEN 16
struct
mousedev_list
{
struct
fasync_struct
*
fasync
;
struct
mousedev
*
mousedev
;
struct
list_head
node
;
int
dx
,
dy
,
dz
;
unsigned
long
buttons
;
struct
mousedev_motion
packets
[
PACKET_QUEUE_LEN
];
unsigned
int
head
,
tail
;
spinlock_t
packet_lock
;
signed
char
ps2
[
6
];
unsigned
char
ready
,
buffer
,
bufsiz
;
unsigned
char
mode
,
imexseq
,
impsseq
;
unsigned
char
imexseq
,
impsseq
;
enum
mousedev_emul
mode
;
};
#define MOUSEDEV_SEQ_LEN 6
...
...
@@ -165,30 +180,70 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
}
if
(
value
)
{
set_bit
(
index
,
&
mousedev
->
buttons
);
set_bit
(
index
,
&
mousedev_mix
.
buttons
);
set_bit
(
index
,
&
mousedev
->
packet
.
buttons
);
set_bit
(
index
,
&
mousedev_mix
.
packet
.
buttons
);
}
else
{
clear_bit
(
index
,
&
mousedev
->
buttons
);
clear_bit
(
index
,
&
mousedev_mix
.
buttons
);
clear_bit
(
index
,
&
mousedev
->
packet
.
buttons
);
clear_bit
(
index
,
&
mousedev_mix
.
packet
.
buttons
);
}
}
static
void
mousedev_notify_readers
(
struct
mousedev
*
mousedev
,
struct
mousedev_motion
*
packet
)
{
struct
mousedev_list
*
list
;
struct
mousedev_motion
*
p
;
unsigned
long
flags
;
list_for_each_entry
(
list
,
&
mousedev
->
list
,
node
)
{
list
->
dx
+=
packet
->
dx
;
list
->
dy
+=
packet
->
dy
;
list
->
dz
+=
packet
->
dz
;
list
->
buttons
=
mousedev
->
buttons
;
spin_lock_irqsave
(
&
list
->
packet_lock
,
flags
);
p
=
&
list
->
packets
[
list
->
head
];
if
(
list
->
ready
&&
p
->
buttons
!=
packet
->
buttons
)
{
unsigned
int
new_head
=
(
list
->
head
+
1
)
%
PACKET_QUEUE_LEN
;
if
(
new_head
!=
list
->
tail
)
{
p
=
&
list
->
packets
[
list
->
head
=
new_head
];
memset
(
p
,
0
,
sizeof
(
struct
mousedev_motion
));
}
}
p
->
dx
+=
packet
->
dx
;
p
->
dy
+=
packet
->
dy
;
p
->
dz
+=
packet
->
dz
;
p
->
buttons
=
mousedev
->
packet
.
buttons
;
list
->
ready
=
1
;
spin_unlock_irqrestore
(
&
list
->
packet_lock
,
flags
);
kill_fasync
(
&
list
->
fasync
,
SIGIO
,
POLL_IN
);
}
wake_up_interruptible
(
&
mousedev
->
wait
);
}
static
void
mousedev_touchpad_touch
(
struct
mousedev
*
mousedev
,
int
value
)
{
if
(
!
value
)
{
if
(
mousedev
->
touch
&&
!
time_after
(
jiffies
,
mousedev
->
touch
+
msecs_to_jiffies
(
tap_time
)))
{
/*
* Toggle left button to emulate tap.
* We rely on the fact that mousedev_mix always has 0
* motion packet so we won't mess current position.
*/
set_bit
(
0
,
&
mousedev
->
packet
.
buttons
);
set_bit
(
0
,
&
mousedev_mix
.
packet
.
buttons
);
mousedev_notify_readers
(
mousedev
,
&
mousedev_mix
.
packet
);
mousedev_notify_readers
(
&
mousedev_mix
,
&
mousedev_mix
.
packet
);
clear_bit
(
0
,
&
mousedev
->
packet
.
buttons
);
clear_bit
(
0
,
&
mousedev_mix
.
packet
.
buttons
);
}
mousedev
->
touch
=
mousedev
->
pkt_count
=
0
;
}
else
if
(
!
mousedev
->
touch
)
mousedev
->
touch
=
jiffies
;
}
static
void
mousedev_event
(
struct
input_handle
*
handle
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
struct
mousedev
*
mousedev
=
handle
->
private
;
...
...
@@ -212,12 +267,8 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
case
EV_KEY
:
if
(
value
!=
2
)
{
if
(
code
==
BTN_TOUCH
&&
test_bit
(
BTN_TOOL_FINGER
,
handle
->
dev
->
keybit
))
{
/* Handle touchpad data */
mousedev
->
touch
=
value
;
if
(
!
mousedev
->
touch
)
mousedev
->
pkt_count
=
0
;
}
if
(
code
==
BTN_TOUCH
&&
test_bit
(
BTN_TOOL_FINGER
,
handle
->
dev
->
keybit
))
mousedev_touchpad_touch
(
mousedev
,
value
);
else
mousedev_key_event
(
mousedev
,
code
,
value
);
}
...
...
@@ -237,7 +288,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
mousedev_notify_readers
(
mousedev
,
&
mousedev
->
packet
);
mousedev_notify_readers
(
&
mousedev_mix
,
&
mousedev
->
packet
);
m
emset
(
&
mousedev
->
packet
,
0
,
sizeof
(
struct
mousedev_motion
))
;
m
ousedev
->
packet
.
dx
=
mousedev
->
packet
.
dy
=
mousedev
->
packet
.
dz
=
0
;
}
break
;
}
...
...
@@ -322,6 +373,7 @@ static int mousedev_open(struct inode * inode, struct file * file)
return
-
ENOMEM
;
memset
(
list
,
0
,
sizeof
(
struct
mousedev_list
));
spin_lock_init
(
&
list
->
packet_lock
);
list
->
mousedev
=
mousedev_table
[
i
];
list_add_tail
(
&
list
->
node
,
&
mousedev_table
[
i
]
->
list
);
file
->
private_data
=
list
;
...
...
@@ -341,32 +393,56 @@ static int mousedev_open(struct inode * inode, struct file * file)
return
0
;
}
static
void
mousedev_packet
(
struct
mousedev_list
*
list
,
unsigned
char
off
)
static
inline
int
mousedev_limit_delta
(
int
delta
,
int
limit
)
{
list
->
ps2
[
off
]
=
0x08
|
((
list
->
dx
<
0
)
<<
4
)
|
((
list
->
dy
<
0
)
<<
5
)
|
(
list
->
buttons
&
0x07
);
list
->
ps2
[
off
+
1
]
=
(
list
->
dx
>
127
?
127
:
(
list
->
dx
<
-
127
?
-
127
:
list
->
dx
));
list
->
ps2
[
off
+
2
]
=
(
list
->
dy
>
127
?
127
:
(
list
->
dy
<
-
127
?
-
127
:
list
->
dy
));
list
->
dx
-=
list
->
ps2
[
off
+
1
];
list
->
dy
-=
list
->
ps2
[
off
+
2
];
list
->
bufsiz
=
off
+
3
;
if
(
list
->
mode
==
2
)
{
list
->
ps2
[
off
+
3
]
=
(
list
->
dz
>
7
?
7
:
(
list
->
dz
<
-
7
?
-
7
:
list
->
dz
));
list
->
dz
-=
list
->
ps2
[
off
+
3
];
list
->
ps2
[
off
+
3
]
=
(
list
->
ps2
[
off
+
3
]
&
0x0f
)
|
((
list
->
buttons
&
0x18
)
<<
1
);
list
->
bufsiz
++
;
}
else
{
list
->
ps2
[
off
]
|=
((
list
->
buttons
&
0x10
)
>>
3
)
|
((
list
->
buttons
&
0x08
)
>>
1
);
return
delta
>
limit
?
limit
:
(
delta
<
-
limit
?
-
limit
:
delta
);
}
static
void
mousedev_packet
(
struct
mousedev_list
*
list
,
signed
char
*
ps2_data
)
{
struct
mousedev_motion
*
p
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
list
->
packet_lock
,
flags
);
p
=
&
list
->
packets
[
list
->
tail
];
ps2_data
[
0
]
=
0x08
|
((
p
->
dx
<
0
)
<<
4
)
|
((
p
->
dy
<
0
)
<<
5
)
|
(
p
->
buttons
&
0x07
);
ps2_data
[
1
]
=
mousedev_limit_delta
(
p
->
dx
,
127
);
ps2_data
[
2
]
=
mousedev_limit_delta
(
p
->
dy
,
127
);
p
->
dx
-=
ps2_data
[
1
];
p
->
dy
-=
ps2_data
[
2
];
switch
(
list
->
mode
)
{
case
MOUSEDEV_EMUL_EXPS
:
ps2_data
[
3
]
=
mousedev_limit_delta
(
p
->
dz
,
127
);
p
->
dz
-=
ps2_data
[
3
];
ps2_data
[
3
]
=
(
ps2_data
[
3
]
&
0x0f
)
|
((
p
->
buttons
&
0x18
)
<<
1
);
list
->
bufsiz
=
4
;
break
;
case
MOUSEDEV_EMUL_IMPS
:
ps2_data
[
0
]
|=
((
p
->
buttons
&
0x10
)
>>
3
)
|
((
p
->
buttons
&
0x08
)
>>
1
);
ps2_data
[
3
]
=
mousedev_limit_delta
(
p
->
dz
,
127
);
p
->
dz
-=
ps2_data
[
3
];
list
->
bufsiz
=
4
;
break
;
case
MOUSEDEV_EMUL_PS2
:
default:
ps2_data
[
0
]
|=
((
p
->
buttons
&
0x10
)
>>
3
)
|
((
p
->
buttons
&
0x08
)
>>
1
);
p
->
dz
=
0
;
list
->
bufsiz
=
3
;
break
;
}
if
(
list
->
mode
==
1
)
{
list
->
ps2
[
off
+
3
]
=
(
list
->
dz
>
127
?
127
:
(
list
->
dz
<
-
127
?
-
127
:
list
->
dz
));
list
->
dz
-=
list
->
ps2
[
off
+
3
];
list
->
bufsiz
++
;
if
(
!
p
->
dx
&&
!
p
->
dy
&&
!
p
->
dz
)
{
if
(
list
->
tail
!=
list
->
head
)
list
->
tail
=
(
list
->
tail
+
1
)
%
PACKET_QUEUE_LEN
;
if
(
list
->
tail
==
list
->
head
)
list
->
ready
=
0
;
}
if
(
!
list
->
dx
&&
!
list
->
dy
&&
(
!
list
->
mode
||
!
list
->
dz
))
list
->
ready
=
0
;
list
->
buffer
=
list
->
bufsiz
;
spin_unlock_irqrestore
(
&
list
->
packet_lock
,
flags
);
}
...
...
@@ -384,31 +460,31 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si
if
(
c
==
mousedev_imex_seq
[
list
->
imexseq
])
{
if
(
++
list
->
imexseq
==
MOUSEDEV_SEQ_LEN
)
{
list
->
imexseq
=
0
;
list
->
mode
=
2
;
list
->
mode
=
MOUSEDEV_EMUL_EXPS
;
}
}
else
list
->
imexseq
=
0
;
if
(
c
==
mousedev_imps_seq
[
list
->
impsseq
])
{
if
(
++
list
->
impsseq
==
MOUSEDEV_SEQ_LEN
)
{
list
->
impsseq
=
0
;
list
->
mode
=
1
;
list
->
mode
=
MOUSEDEV_EMUL_IMPS
;
}
}
else
list
->
impsseq
=
0
;
list
->
ps2
[
0
]
=
0xfa
;
list
->
bufsiz
=
1
;
switch
(
c
)
{
case
0xeb
:
/* Poll */
mousedev_packet
(
list
,
1
);
mousedev_packet
(
list
,
&
list
->
ps2
[
1
]);
list
->
bufsiz
++
;
/* account for leading ACK */
break
;
case
0xf2
:
/* Get ID */
switch
(
list
->
mode
)
{
case
0
:
list
->
ps2
[
1
]
=
0
;
break
;
case
1
:
list
->
ps2
[
1
]
=
3
;
break
;
case
2
:
list
->
ps2
[
1
]
=
4
;
break
;
case
MOUSEDEV_EMUL_PS2
:
list
->
ps2
[
1
]
=
0
;
break
;
case
MOUSEDEV_EMUL_IMPS
:
list
->
ps2
[
1
]
=
3
;
break
;
case
MOUSEDEV_EMUL_EXPS
:
list
->
ps2
[
1
]
=
4
;
break
;
}
list
->
bufsiz
=
2
;
break
;
...
...
@@ -419,13 +495,15 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si
break
;
case
0xff
:
/* Reset */
list
->
impsseq
=
0
;
list
->
imexseq
=
0
;
list
->
mode
=
0
;
list
->
ps2
[
1
]
=
0xaa
;
list
->
ps2
[
2
]
=
0x00
;
list
->
impsseq
=
list
->
imexseq
=
0
;
list
->
mode
=
MOUSEDEV_EMUL_PS2
;
list
->
ps2
[
1
]
=
0xaa
;
list
->
ps2
[
2
]
=
0x00
;
list
->
bufsiz
=
3
;
break
;
default:
list
->
bufsiz
=
1
;
break
;
}
list
->
buffer
=
list
->
bufsiz
;
...
...
@@ -451,8 +529,10 @@ static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t co
if
(
retval
)
return
retval
;
if
(
!
list
->
buffer
&&
list
->
ready
)
mousedev_packet
(
list
,
0
);
if
(
!
list
->
buffer
&&
list
->
ready
)
{
mousedev_packet
(
list
,
list
->
ps2
);
list
->
buffer
=
list
->
bufsiz
;
}
if
(
count
>
list
->
buffer
)
count
=
list
->
buffer
;
...
...
drivers/input/serio/i8042.c
View file @
5562dd00
/*
* i8042 keyboard and mouse controller driver for Linux
*
* Copyright (c) 1999-200
2
Vojtech Pavlik
* Copyright (c) 1999-200
4
Vojtech Pavlik
*/
/*
...
...
@@ -52,6 +52,10 @@ static unsigned int i8042_dumbkbd;
module_param_named
(
dumbkbd
,
i8042_dumbkbd
,
bool
,
0
);
MODULE_PARM_DESC
(
dumbkbd
,
"Pretend that controller can only read data from keyboard"
);
extern
unsigned
int
i8042_dmi_noloop
;
static
unsigned
int
i8042_noloop
;
extern
unsigned
int
i8042_dmi_noloop
;
__obsolete_setup
(
"i8042_noaux"
);
__obsolete_setup
(
"i8042_nomux"
);
__obsolete_setup
(
"i8042_unlock"
);
...
...
@@ -95,6 +99,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 +159,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,17 +482,8 @@ static int i8042_enable_mux_mode(struct i8042_values *values, unsigned char *mux
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
!=
0xa9
)
return
-
1
;
param
=
0xa4
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
==
0x5b
)
{
/*
* Do another loop test with the 0x5a value. Doing anything else upsets
* Profusion/ServerWorks OSB4 chipsets.
*/
param
=
0x5a
;
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
);
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
==
0x5b
)
return
-
1
;
}
if
(
mux_version
)
*
mux_version
=
~
param
;
...
...
@@ -677,6 +676,7 @@ static void i8042_timer_func(unsigned long data)
static
int
i8042_controller_init
(
void
)
{
unsigned
long
flags
;
/*
* Test the i8042. We need to know if it thinks it's working correctly
...
...
@@ -723,12 +723,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
...
...
@@ -964,6 +966,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
++
)
{
...
...
drivers/input/serio/serio.c
View file @
5562dd00
/*
* $Id: serio.c,v 1.15 2002/01/22 21:12:03 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* The Serio abstraction module
*
* Copyright (c) 1999-2004 Vojtech Pavlik
* Copyright (c) 2004 Dmitry Torokhov
* Copyright (c) 2003 Daniele Bellucci
*/
/*
...
...
@@ -26,10 +24,6 @@
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*
* Changes:
* 20 Jul. 2003 Daniele Bellucci <bellucda@tiscali.it>
* Minor cleanups.
*/
#include <linux/stddef.h>
...
...
@@ -61,17 +55,11 @@ EXPORT_SYMBOL(serio_close);
EXPORT_SYMBOL
(
serio_rescan
);
EXPORT_SYMBOL
(
serio_reconnect
);
struct
serio_event
{
int
type
;
struct
serio
*
serio
;
struct
list_head
node
;
};
static
DECLARE_MUTEX
(
serio_sem
);
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
)
{
...
...
@@ -85,34 +73,76 @@ static void serio_find_dev(struct serio *serio)
}
}
#define SERIO_RESCAN 1
#define SERIO_RECONNECT 2
#define SERIO_REGISTER_PORT 3
#define SERIO_UNREGISTER_PORT 4
/*
* Serio event processing.
*/
struct
serio_event
{
int
type
;
struct
serio
*
serio
;
struct
list_head
node
;
};
enum
serio_event_type
{
SERIO_RESCAN
,
SERIO_RECONNECT
,
SERIO_REGISTER_PORT
,
SERIO_UNREGISTER_PORT
,
};
static
spinlock_t
serio_event_lock
=
SPIN_LOCK_UNLOCKED
;
/* protects serio_event_list */
static
LIST_HEAD
(
serio_event_list
);
static
DECLARE_WAIT_QUEUE_HEAD
(
serio_wait
);
static
DECLARE_COMPLETION
(
serio_exited
);
static
int
serio_pid
;
static
void
serio_
invalidate_pending_events
(
struct
serio
*
serio
)
static
void
serio_
queue_event
(
struct
serio
*
serio
,
int
event_type
)
{
unsigned
long
flags
;
struct
serio_event
*
event
;
list_for_each_entry
(
event
,
&
serio_event_list
,
node
)
if
(
event
->
serio
==
serio
)
event
->
serio
=
NULL
;
spin_lock_irqsave
(
&
serio_event_lock
,
flags
);
if
((
event
=
kmalloc
(
sizeof
(
struct
serio_event
),
GFP_ATOMIC
)))
{
event
->
type
=
event_type
;
event
->
serio
=
serio
;
list_add_tail
(
&
event
->
node
,
&
serio_event_list
);
wake_up
(
&
serio_wait
);
}
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
}
void
serio_handle_events
(
void
)
static
struct
serio_event
*
serio_get_event
(
void
)
{
struct
list_head
*
node
,
*
next
;
struct
serio_event
*
event
;
struct
list_head
*
node
;
unsigned
long
flags
;
list_for_each_safe
(
node
,
next
,
&
serio_event_list
)
{
event
=
container_of
(
node
,
struct
serio_event
,
node
);
spin_lock_irqsave
(
&
serio_event_lock
,
flags
);
if
(
list_empty
(
&
serio_event_list
))
{
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
return
NULL
;
}
node
=
serio_event_list
.
next
;
event
=
container_of
(
node
,
struct
serio_event
,
node
);
list_del_init
(
node
);
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
return
event
;
}
static
void
serio_handle_events
(
void
)
{
struct
serio_event
*
event
;
while
((
event
=
serio_get_event
()))
{
down
(
&
serio_sem
);
if
(
event
->
serio
==
NULL
)
goto
event_done
;
switch
(
event
->
type
)
{
case
SERIO_REGISTER_PORT
:
...
...
@@ -137,13 +167,32 @@ void serio_handle_events(void)
default:
break
;
}
event_done:
up
(
&
serio_sem
);
list_del_init
(
node
);
kfree
(
event
);
}
}
static
void
serio_remove_pending_events
(
struct
serio
*
serio
)
{
struct
list_head
*
node
,
*
next
;
struct
serio_event
*
event
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
serio_event_lock
,
flags
);
list_for_each_safe
(
node
,
next
,
&
serio_event_list
)
{
event
=
container_of
(
node
,
struct
serio_event
,
node
);
if
(
event
->
serio
==
serio
)
{
list_del_init
(
node
);
kfree
(
event
);
}
}
spin_unlock_irqrestore
(
&
serio_event_lock
,
flags
);
}
static
int
serio_thread
(
void
*
nothing
)
{
lock_kernel
();
...
...
@@ -163,18 +212,10 @@ static int serio_thread(void *nothing)
complete_and_exit
(
&
serio_exited
,
0
);
}
static
void
serio_queue_event
(
struct
serio
*
serio
,
int
event_type
)
{
struct
serio_event
*
event
;
if
((
event
=
kmalloc
(
sizeof
(
struct
serio_event
),
GFP_ATOMIC
)))
{
event
->
type
=
event_type
;
event
->
serio
=
serio
;
list_add_tail
(
&
event
->
node
,
&
serio_event_list
);
wake_up
(
&
serio_wait
);
}
}
/*
* Serio port operations
*/
void
serio_rescan
(
struct
serio
*
serio
)
{
...
...
@@ -186,25 +227,6 @@ void serio_reconnect(struct serio *serio)
serio_queue_event
(
serio
,
SERIO_RECONNECT
);
}
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
)
{
irqreturn_t
ret
=
IRQ_NONE
;
if
(
serio
->
dev
&&
serio
->
dev
->
interrupt
)
{
ret
=
serio
->
dev
->
interrupt
(
serio
,
data
,
flags
,
regs
);
}
else
{
if
(
!
flags
)
{
if
((
serio
->
type
==
SERIO_8042
||
serio
->
type
==
SERIO_8042_XL
)
&&
(
data
!=
0xaa
))
return
ret
;
serio_rescan
(
serio
);
ret
=
IRQ_HANDLED
;
}
}
return
ret
;
}
void
serio_register_port
(
struct
serio
*
serio
)
{
down
(
&
serio_sem
);
...
...
@@ -229,6 +251,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
);
}
...
...
@@ -257,12 +280,16 @@ void serio_unregister_port_delayed(struct serio *serio)
*/
void
__serio_unregister_port
(
struct
serio
*
serio
)
{
serio_
invalidat
e_pending_events
(
serio
);
serio_
remov
e_pending_events
(
serio
);
list_del_init
(
&
serio
->
node
);
if
(
serio
->
dev
&&
serio
->
dev
->
disconnect
)
serio
->
dev
->
disconnect
(
serio
);
}
/*
* Serio device operations
*/
void
serio_register_device
(
struct
serio_dev
*
dev
)
{
struct
serio
*
serio
;
...
...
@@ -292,9 +319,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
;
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,9 +336,38 @@ 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
);
}
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
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
(
likely
(
serio
->
dev
))
{
ret
=
serio
->
dev
->
interrupt
(
serio
,
data
,
dfl
,
regs
);
}
else
{
if
(
!
dfl
)
{
if
((
serio
->
type
!=
SERIO_8042
&&
serio
->
type
!=
SERIO_8042_XL
)
||
(
data
==
0xaa
))
{
serio_rescan
(
serio
);
ret
=
IRQ_HANDLED
;
}
}
}
spin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
return
ret
;
}
static
int
__init
serio_init
(
void
)
...
...
drivers/input/tsdev.c
View file @
5562dd00
This diff is collapsed.
Click to expand it.
drivers/usb/input/hiddev.c
View file @
5562dd00
...
...
@@ -638,16 +638,22 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
goto
inval
;
field
=
report
->
field
[
uref
->
field_index
];
if
(
uref
->
usage_index
>=
field
->
maxusage
)
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
)
if
(
cmd
==
HIDIOCGCOLLECTIONINDEX
)
{
if
(
uref
->
usage_index
>=
field
->
maxusage
)
goto
inval
;
}
else
if
(
uref
->
usage_index
>=
field
->
report_count
)
goto
inval
;
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
)
{
case
HIDIOCGUSAGE
:
...
...
fs/compat_ioctl.c
View file @
5562dd00
...
...
@@ -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 @
5562dd00
...
...
@@ -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 @
5562dd00
...
...
@@ -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 @
5562dd00
...
...
@@ -527,6 +527,8 @@ struct input_absinfo {
#define MSC_SERIAL 0x00
#define MSC_PULSELED 0x01
#define MSC_GESTURE 0x02
#define MSC_RAW 0x03
#define MSC_SCAN 0x04
#define MSC_MAX 0x07
/*
...
...
include/linux/serio.h
View file @
5562dd00
...
...
@@ -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