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
dcfe2282
Commit
dcfe2282
authored
Jun 24, 2004
by
Vojtech Pavlik
Browse files
Options
Browse Files
Download
Plain Diff
Merge suse.cz:/data/bk/linus into suse.cz:/data/bk/input
parents
5e1c40de
f163d52f
Changes
23
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
886 additions
and
449 deletions
+886
-449
Documentation/input/joystick-parport.txt
Documentation/input/joystick-parport.txt
+11
-2
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
+25
-8
drivers/input/gameport/emu10k1-gp.c
drivers/input/gameport/emu10k1-gp.c
+3
-0
drivers/input/joystick/gamecon.c
drivers/input/joystick/gamecon.c
+102
-92
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
+80
-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
+21
-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/hid-tmff.c
drivers/usb/input/hid-tmff.c
+1
-1
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/input/joystick-parport.txt
View file @
dcfe2282
...
...
@@ -335,6 +335,7 @@ controller (compatible with DirectPadPro):
* Analog PSX Pad (red mode)
* Analog PSX Pad (green mode)
* PSX Rumble Pad
* PSX DDR Pad
2.4 Sega
~~~~~~~~
...
...
@@ -452,14 +453,22 @@ uses the following kernel/module command line:
5 | Multisystem 2-button joystick
6 | N64 pad
7 | Sony PSX controller
8 | Sony PSX DDR controller
The exact type of the PSX controller type is autoprobed
, so you must have
your controller plugged in before initializing
.
The exact type of the PSX controller type is autoprobed
when used so
hot swapping should work (but is not recomended)
.
Should you want to use more than one of parallel ports at once, you can use
gamecon.map2 and gamecon.map3 as additional command line parameters for two
more parallel ports.
There are two options specific to PSX driver portion. gamecon.psx_delay sets
the command delay when talking to the controllers. The default of 25 should
work but you can try lowering it for better performace. If your pads don't
respond try raising it untill they work. Setting the type to 8 allows the
driver to be used with Dance Dance Revolution or similar games. Arrow keys are
registered as key presses instead of X and Y axes.
3.2 db9.c
~~~~~~~~~
Apart from making an interface, there is nothing difficult on using the
...
...
Documentation/kernel-parameters.txt
View file @
dcfe2282
...
...
@@ -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 @
dcfe2282
...
...
@@ -16,6 +16,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
;
...
...
@@ -354,6 +357,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).
...
...
@@ -828,6 +842,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 @
dcfe2282
...
...
@@ -123,7 +123,7 @@ int shift_state = 0;
*/
static
struct
input_handler
kbd_handler
;
static
unsigned
long
key_down
[
256
/
BITS_PER_LONG
];
/* keyboard key bitmap */
static
unsigned
long
key_down
[
NBITS
(
KEY_MAX
)];
/* keyboard key bitmap */
static
unsigned
char
shift_down
[
NR_SHIFT
];
/* shift state counters.. */
static
int
dead_key_next
;
static
int
npadch
=
-
1
;
/* -1 or number assembled on pad */
...
...
@@ -142,7 +142,7 @@ static struct ledptr {
/* Simple translation table for the SysRq keys */
#ifdef CONFIG_MAGIC_SYSRQ
unsigned
char
kbd_sysrq_xlate
[
128
]
=
unsigned
char
kbd_sysrq_xlate
[
KEY_MAX
]
=
"
\000\033
1234567890-=
\177\t
"
/* 0x00 - 0x0f */
"qwertyuiop[]
\r\000
as"
/* 0x10 - 0x1f */
"dfghjkl;'`
\000\\
zxcv"
/* 0x20 - 0x2f */
...
...
@@ -941,6 +941,9 @@ void kbd_refresh_leds(struct input_handle *handle)
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_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
,
...
...
@@ -1007,6 +1010,8 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
#else
#define HW_RAW(dev) 0
#warning "Cannot generate rawmode keyboard for your architecture yet."
static
int
emulate_raw
(
struct
vc_data
*
vc
,
unsigned
int
keycode
,
unsigned
char
up_flag
)
...
...
@@ -1019,7 +1024,15 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u
}
#endif
void
kbd_keycode
(
unsigned
int
keycode
,
int
down
,
struct
pt_regs
*
regs
)
void
kbd_rawcode
(
unsigned
char
data
)
{
struct
vc_data
*
vc
=
vc_cons
[
fg_console
].
d
;
kbd
=
kbd_table
+
fg_console
;
if
(
kbd
->
kbdmode
==
VC_RAW
)
put_queue
(
vc
,
data
);
}
void
kbd_keycode
(
unsigned
int
keycode
,
int
down
,
int
hw_raw
,
struct
pt_regs
*
regs
)
{
struct
vc_data
*
vc
=
vc_cons
[
fg_console
].
d
;
unsigned
short
keysym
,
*
key_map
;
...
...
@@ -1053,7 +1066,7 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
return
;
#endif
/* CONFIG_MAC_EMUMOUSEBTN */
if
((
raw_mode
=
(
kbd
->
kbdmode
==
VC_RAW
)))
if
((
raw_mode
=
(
kbd
->
kbdmode
==
VC_RAW
))
&&
!
hw_raw
)
if
(
emulate_raw
(
vc
,
keycode
,
!
down
<<
7
))
if
(
keycode
<
BTN_MISC
)
printk
(
KERN_WARNING
"keyboard.c: can't emulate rawmode for keycode %d
\n
"
,
keycode
);
...
...
@@ -1119,6 +1132,9 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
return
;
}
if
(
keycode
>
NR_KEYS
)
return
;
keysym
=
key_map
[
keycode
];
type
=
KTYP
(
keysym
);
...
...
@@ -1148,11 +1164,12 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
}
static
void
kbd_event
(
struct
input_handle
*
handle
,
unsigned
int
event_type
,
unsigned
int
keycode
,
int
down
)
unsigned
int
event_code
,
int
value
)
{
if
(
event_type
!=
EV_KEY
)
return
;
kbd_keycode
(
keycode
,
down
,
handle
->
dev
->
regs
);
if
(
event_type
==
EV_MSC
&&
event_code
==
MSC_RAW
&&
HW_RAW
(
handle
->
dev
))
kbd_rawcode
(
value
);
if
(
event_type
==
EV_KEY
)
kbd_keycode
(
event_code
,
value
,
HW_RAW
(
handle
->
dev
),
handle
->
dev
->
regs
);
tasklet_schedule
(
&
keyboard_tasklet
);
do_poke_blanked_console
=
1
;
schedule_console_callback
();
...
...
drivers/input/gameport/emu10k1-gp.c
View file @
dcfe2282
...
...
@@ -50,8 +50,11 @@ struct emu {
};
static
struct
pci_device_id
emu_tbl
[]
=
{
{
0x1102
,
0x7002
,
PCI_ANY_ID
,
PCI_ANY_ID
},
/* SB Live gameport */
{
0x1102
,
0x7003
,
PCI_ANY_ID
,
PCI_ANY_ID
},
/* Audigy gameport */
{
0x1102
,
0x7004
,
PCI_ANY_ID
,
PCI_ANY_ID
},
/* Dell SB Live */
{
0x1102
,
0x7005
,
PCI_ANY_ID
,
PCI_ANY_ID
},
/* Audigy LS gameport */
{
0
,
}
};
...
...
drivers/input/joystick/gamecon.c
View file @
dcfe2282
/*
*
$Id: gamecon.c,v 1.22 2002/07/01 15:42:25 vojtech Exp $
*
NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
*
* Copyright (c) 1999-2001 Vojtech Pavlik
* Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2004 Peter Nelson <pnelson@andrew.cmu.edu>
*
* Based on the work of:
* Andree Borrmann John Dahlstrom
* David Kuder Nathan Hand
*/
/*
* NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -72,8 +69,9 @@ __obsolete_setup("gc_3=");
#define GC_MULTI2 5
#define GC_N64 6
#define GC_PSX 7
#define GC_DDR 8
#define GC_MAX
7
#define GC_MAX
8
#define GC_REFRESH_TIME HZ/100
...
...
@@ -91,7 +89,8 @@ static struct gc *gc_base[3];
static
int
gc_status_bit
[]
=
{
0x40
,
0x80
,
0x20
,
0x10
,
0x08
};
static
char
*
gc_names
[]
=
{
NULL
,
"SNES pad"
,
"NES pad"
,
"NES FourPort"
,
"Multisystem joystick"
,
"Multisystem 2-button joystick"
,
"N64 controller"
,
"PSX controller"
};
"Multisystem 2-button joystick"
,
"N64 controller"
,
"PSX controller"
"PSX DDR controller"
};
/*
* N64 support.
*/
...
...
@@ -237,7 +236,7 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
#define GC_PSX_RUMBLE 7
/* Rumble in Red mode */
#define GC_PSX_CLOCK 0x04
/* Pin 4 */
#define GC_PSX_COMMAND 0x01
/* Pin
1
*/
#define GC_PSX_COMMAND 0x01
/* Pin
2
*/
#define GC_PSX_POWER 0xf8
/* Pins 5-9 */
#define GC_PSX_SELECT 0x02
/* Pin 3 */
...
...
@@ -253,25 +252,29 @@ __obsolete_setup("gc_psx_delay=");
static
short
gc_psx_abs
[]
=
{
ABS_X
,
ABS_Y
,
ABS_RX
,
ABS_RY
,
ABS_HAT0X
,
ABS_HAT0Y
};
static
short
gc_psx_btn
[]
=
{
BTN_TL
,
BTN_TR
,
BTN_TL2
,
BTN_TR2
,
BTN_A
,
BTN_B
,
BTN_X
,
BTN_Y
,
BTN_START
,
BTN_SELECT
,
BTN_THUMBL
,
BTN_THUMBR
};
static
short
gc_psx_ddr_btn
[]
=
{
BTN_0
,
BTN_1
,
BTN_2
,
BTN_3
};
/*
* gc_psx_command() writes 8bit command and reads 8bit data from
* the psx pad.
*/
static
int
gc_psx_command
(
struct
gc
*
gc
,
int
b
)
static
void
gc_psx_command
(
struct
gc
*
gc
,
int
b
,
unsigned
char
data
[
GC_PSX_LENGTH
]
)
{
int
i
,
cmd
,
data
=
0
;
int
i
,
j
,
cmd
,
read
;
for
(
i
=
0
;
i
<
5
;
i
++
)
data
[
i
]
=
0
;
for
(
i
=
0
;
i
<
8
;
i
++
,
b
>>=
1
)
{
cmd
=
(
b
&
1
)
?
GC_PSX_COMMAND
:
0
;
parport_write_data
(
gc
->
pd
->
port
,
cmd
|
GC_PSX_POWER
);
udelay
(
gc_psx_delay
);
data
|=
((
parport_read_status
(
gc
->
pd
->
port
)
^
0x80
)
&
gc
->
pads
[
GC_PSX
])
?
(
1
<<
i
)
:
0
;
read
=
parport_read_status
(
gc
->
pd
->
port
)
^
0x80
;
for
(
j
=
0
;
j
<
5
;
j
++
)
data
[
j
]
|=
(
read
&
gc_status_bit
[
j
]
&
gc
->
pads
[
GC_PSX
])
?
(
1
<<
i
)
:
0
;
parport_write_data
(
gc
->
pd
->
port
,
cmd
|
GC_PSX_CLOCK
|
GC_PSX_POWER
);
udelay
(
gc_psx_delay
);
}
return
data
;
}
/*
...
...
@@ -279,30 +282,39 @@ static int gc_psx_command(struct gc *gc, int b)
* device identifier code.
*/
static
int
gc_psx_read_packet
(
struct
gc
*
gc
,
unsigned
char
*
data
)
static
void
gc_psx_read_packet
(
struct
gc
*
gc
,
unsigned
char
data
[
5
][
GC_PSX_LENGTH
],
unsigned
char
id
[
5
]
)
{
int
i
,
id
;
int
i
,
j
,
max_len
=
0
;
unsigned
long
flags
;
unsigned
char
data2
[
5
];
parport_write_data
(
gc
->
pd
->
port
,
GC_PSX_CLOCK
|
GC_PSX_SELECT
|
GC_PSX_POWER
);
/* Select pad */
udelay
(
gc_psx_delay
*
2
);
udelay
(
gc_psx_delay
);
parport_write_data
(
gc
->
pd
->
port
,
GC_PSX_CLOCK
|
GC_PSX_POWER
);
/* Deselect, begin command */
udelay
(
gc_psx_delay
*
2
);
udelay
(
gc_psx_delay
);
local_irq_save
(
flags
);
gc_psx_command
(
gc
,
0x01
);
/* Access pad */
id
=
gc_psx_command
(
gc
,
0x42
);
/* Get device id */
if
(
gc_psx_command
(
gc
,
0
)
==
0x5a
)
{
/* Okay? */
for
(
i
=
0
;
i
<
GC_PSX_LEN
(
id
)
*
2
;
i
++
)
data
[
i
]
=
gc_psx_command
(
gc
,
0
);
}
else
id
=
0
;
gc_psx_command
(
gc
,
0x01
,
data2
);
/* Access pad */
gc_psx_command
(
gc
,
0x42
,
id
);
/* Get device ids */
gc_psx_command
(
gc
,
0
,
data2
);
/* Dump status */
for
(
i
=
0
;
i
<
5
;
i
++
)
/* Find the longest pad */
if
((
gc_status_bit
[
i
]
&
gc
->
pads
[
GC_PSX
])
&&
(
GC_PSX_LEN
(
id
[
i
])
>
max_len
))
max_len
=
GC_PSX_LEN
(
id
[
i
]);
for
(
i
=
0
;
i
<
max_len
*
2
;
i
++
)
{
/* Read in all the data */
gc_psx_command
(
gc
,
0
,
data2
);
for
(
j
=
0
;
j
<
5
;
j
++
)
data
[
j
][
i
]
=
data2
[
j
];
}
local_irq_restore
(
flags
);
parport_write_data
(
gc
->
pd
->
port
,
GC_PSX_CLOCK
|
GC_PSX_SELECT
|
GC_PSX_POWER
);
return
GC_PSX_ID
(
id
);
for
(
i
=
0
;
i
<
5
;
i
++
)
/* Set id's to the real value */
id
[
i
]
=
GC_PSX_ID
(
id
[
i
]);
}
/*
...
...
@@ -316,6 +328,7 @@ static void gc_timer(unsigned long private)
struct
gc
*
gc
=
(
void
*
)
private
;
struct
input_dev
*
dev
=
gc
->
dev
;
unsigned
char
data
[
GC_MAX_LENGTH
];
unsigned
char
data_psx
[
5
][
GC_PSX_LENGTH
];
int
i
,
j
,
s
;
/*
...
...
@@ -412,53 +425,72 @@ static void gc_timer(unsigned long private)
* PSX controllers
*/
if
(
gc
->
pads
[
GC_PSX
])
{
if
(
gc
->
pads
[
GC_PSX
]
||
gc
->
pads
[
GC_DDR
]
)
{
for
(
i
=
0
;
i
<
5
;
i
++
)
if
(
gc
->
pads
[
GC_PSX
]
&
gc_status_bit
[
i
])
break
;
gc_psx_read_packet
(
gc
,
data_psx
,
data
);
switch
(
gc_psx_read_packet
(
gc
,
data
))
{
for
(
i
=
0
;
i
<
5
;
i
++
)
{
switch
(
data
[
i
])
{
case
GC_PSX_RUMBLE
:
case
GC_PSX_RUMBLE
:
input_report_key
(
dev
+
i
,
BTN_THUMBL
,
~
data
[
0
]
&
0x04
);
input_report_key
(
dev
+
i
,
BTN_THUMBR
,
~
data
[
0
]
&
0x02
);
input_sync
(
dev
+
i
);
input_report_key
(
dev
+
i
,
BTN_THUMBL
,
~
data_psx
[
i
][
0
]
&
0x04
);
input_report_key
(
dev
+
i
,
BTN_THUMBR
,
~
data_psx
[
i
][
0
]
&
0x02
);
case
GC_PSX_NEGCON
:
case
GC_PSX_ANALOG
:
case
GC_PSX_NEGCON
:
case
GC_PSX_ANALOG
:
for
(
j
=
0
;
j
<
4
;
j
++
)
input_report_abs
(
dev
+
i
,
gc_psx_abs
[
j
],
data
[
j
+
2
]);
if
(
gc
->
pads
[
GC_DDR
]
&
gc_status_bit
[
i
])
{
for
(
j
=
0
;
j
<
4
;
j
++
)
input_report_key
(
dev
+
i
,
gc_psx_ddr_btn
[
j
],
~
data_psx
[
i
][
0
]
&
(
0x10
<<
j
));
}
else
{
for
(
j
=
0
;
j
<
4
;
j
++
)
input_report_abs
(
dev
+
i
,
gc_psx_abs
[
j
+
2
],
data_psx
[
i
][
j
+
2
]);
input_report_abs
(
dev
+
i
,
ABS_HAT0X
,
!
(
data
[
0
]
&
0x20
)
-
!
(
data
[
0
]
&
0x80
));
input_report_abs
(
dev
+
i
,
ABS_HAT0Y
,
!
(
data
[
0
]
&
0x40
)
-
!
(
data
[
0
]
&
0x10
));
input_report_abs
(
dev
+
i
,
ABS_X
,
128
+
!
(
data_psx
[
i
][
0
]
&
0x20
)
*
127
-
!
(
data_psx
[
i
][
0
]
&
0x80
)
*
128
);
input_report_abs
(
dev
+
i
,
ABS_Y
,
128
+
!
(
data_psx
[
i
][
0
]
&
0x40
)
*
127
-
!
(
data_psx
[
i
][
0
]
&
0x10
)
*
128
);
}
for
(
j
=
0
;
j
<
8
;
j
++
)
input_report_key
(
dev
+
i
,
gc_psx_btn
[
j
],
~
data
[
1
]
&
(
1
<<
j
));
for
(
j
=
0
;
j
<
8
;
j
++
)
input_report_key
(
dev
+
i
,
gc_psx_btn
[
j
],
~
data_psx
[
i
]
[
1
]
&
(
1
<<
j
));
input_report_key
(
dev
+
i
,
BTN_START
,
~
data
[
0
]
&
0x08
);
input_report_key
(
dev
+
i
,
BTN_SELECT
,
~
data
[
0
]
&
0x01
);
input_report_key
(
dev
+
i
,
BTN_START
,
~
data_psx
[
i
]
[
0
]
&
0x08
);
input_report_key
(
dev
+
i
,
BTN_SELECT
,
~
data_psx
[
i
]
[
0
]
&
0x01
);
input_sync
(
dev
+
i
);
input_sync
(
dev
+
i
);
break
;
break
;
case
GC_PSX_NORMAL
:
case
GC_PSX_NORMAL
:
if
(
gc
->
pads
[
GC_DDR
]
&
gc_status_bit
[
i
])
{
for
(
j
=
0
;
j
<
4
;
j
++
)
input_report_key
(
dev
+
i
,
gc_psx_ddr_btn
[
j
],
~
data_psx
[
i
][
0
]
&
(
0x10
<<
j
));
}
else
{
input_report_abs
(
dev
+
i
,
ABS_X
,
128
+
!
(
data_psx
[
i
][
0
]
&
0x20
)
*
127
-
!
(
data_psx
[
i
][
0
]
&
0x80
)
*
128
);
input_report_abs
(
dev
+
i
,
ABS_Y
,
128
+
!
(
data_psx
[
i
][
0
]
&
0x40
)
*
127
-
!
(
data_psx
[
i
][
0
]
&
0x10
)
*
128
);
input_report_abs
(
dev
+
i
,
ABS_X
,
128
+
!
(
data
[
0
]
&
0x20
)
*
127
-
!
(
data
[
0
]
&
0x80
)
*
128
);
input_report_abs
(
dev
+
i
,
ABS_Y
,
128
+
!
(
data
[
0
]
&
0x40
)
*
127
-
!
(
data
[
0
]
&
0x10
)
*
128
);
/* for some reason if the extra axes are left unset they drift */
/* for (j = 0; j < 4; j++)
input_report_abs(dev + i, gc_psx_abs[j+2], 128);
* This needs to be debugged properly,
* maybe fuzz processing needs to be done in input_sync()
* --vojtech
*/
}
for
(
j
=
0
;
j
<
8
;
j
++
)
input_report_key
(
dev
+
i
,
gc_psx_btn
[
j
],
~
data
[
1
]
&
(
1
<<
j
));
for
(
j
=
0
;
j
<
8
;
j
++
)
input_report_key
(
dev
+
i
,
gc_psx_btn
[
j
],
~
data_psx
[
i
]
[
1
]
&
(
1
<<
j
));
input_report_key
(
dev
+
i
,
BTN_START
,
~
data
[
0
]
&
0x08
);
input_report_key
(
dev
+
i
,
BTN_SELECT
,
~
data
[
0
]
&
0x01
);
input_report_key
(
dev
+
i
,
BTN_START
,
~
data_psx
[
i
]
[
0
]
&
0x08
);
input_report_key
(
dev
+
i
,
BTN_SELECT
,
~
data_psx
[
i
]
[
0
]
&
0x01
);
input_sync
(
dev
+
i
);
input_sync
(
dev
+
i
);
break
;
break
;
case
0
:
/* not a pad, ignore */
break
;
}
}
}
...
...
@@ -490,8 +522,7 @@ static struct gc __init *gc_probe(int *config, int nargs)
{
struct
gc
*
gc
;
struct
parport
*
pp
;
int
i
,
j
,
psx
;
unsigned
char
data
[
32
];
int
i
,
j
;
if
(
config
[
0
]
<
0
)
return
NULL
;
...
...
@@ -588,43 +619,22 @@ static struct gc __init *gc_probe(int *config, int nargs)
break
;
case
GC_PSX
:
psx
=
gc_psx_read_packet
(
gc
,
data
);
switch
(
psx
)
{
case
GC_PSX_NEGCON
:
case
GC_PSX_NORMAL
:
case
GC_PSX_ANALOG
:
case
GC_PSX_RUMBLE
:
for
(
j
=
0
;
j
<
6
;
j
++
)
{
psx
=
gc_psx_abs
[
j
];
set_bit
(
psx
,
gc
->
dev
[
i
].
absbit
);
if
(
j
<
4
)
{
gc
->
dev
[
i
].
absmin
[
psx
]
=
4
;
gc
->
dev
[
i
].
absmax
[
psx
]
=
252
;
gc
->
dev
[
i
].
absflat
[
psx
]
=
2
;
}
else
{
gc
->
dev
[
i
].
absmin
[
psx
]
=
-
1
;
gc
->
dev
[
i
].
absmax
[
psx
]
=
1
;
}
}
for
(
j
=
0
;
j
<
12
;
j
++
)
set_bit
(
gc_psx_btn
[
j
],
gc
->
dev
[
i
].
keybit
);
break
;
case
0
:
gc
->
pads
[
GC_PSX
]
&=
~
gc_status_bit
[
i
];
printk
(
KERN_ERR
"gamecon.c: No PSX controller found.
\n
"
);
break
;
default:
gc
->
pads
[
GC_PSX
]
&=
~
gc_status_bit
[
i
];
printk
(
KERN_WARNING
"gamecon.c: Unsupported PSX controller %#x,"
" please report to <vojtech@ucw.cz>.
\n
"
,
psx
);
case
GC_DDR
:
if
(
config
[
i
+
1
]
==
GC_DDR
)
{
for
(
j
=
0
;
j
<
4
;
j
++
)
set_bit
(
gc_psx_ddr_btn
[
j
],
gc
->
dev
[
i
].
keybit
);
}
else
{
for
(
j
=
0
;
j
<
6
;
j
++
)
{
set_bit
(
gc_psx_abs
[
j
],
gc
->
dev
[
i
].
absbit
);
gc
->
dev
[
i
].
absmin
[
gc_psx_abs
[
j
]]
=
4
;
gc
->
dev
[
i
].
absmax
[
gc_psx_abs
[
j
]]
=
252
;
gc
->
dev
[
i
].
absflat
[
gc_psx_abs
[
j
]]
=
2
;
}
}
for
(
j
=
0
;
j
<
12
;
j
++
)
set_bit
(
gc_psx_btn
[
j
],
gc
->
dev
[
i
].
keybit
);
break
;
}
...
...
drivers/input/keyboard/atkbd.c
View file @
dcfe2282
...
...
@@ -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 @
dcfe2282
...
...
@@ -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 @
dcfe2282
...
...
@@ -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 @
dcfe2282
...
...
@@ -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 @
dcfe2282
...
...
@@ -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
(
test_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
)
&&
timeout
--
)
udelay
(
1
);
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
while
(
!
psmouse
->
ack
&&
timeout
--
)
udelay
(
10
);
return
-
(
psmouse
->
ack
<=
0
);
return
-
psmouse
->
nak
;
}
/*
...
...
@@ -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
...
...
@@ -394,6 +418,8 @@ static int im_explorer_detect(struct psmouse *psmouse)
{
unsigned
char
param
[
2
];
intellimouse_detect
(
psmouse
);
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
200
;
...
...
@@ -735,7 +761,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 @
dcfe2282
...
...
@@ -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 @
dcfe2282
...
...
@@ -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 @
dcfe2282
/*
* 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,11 @@ 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"
);
#ifdef __i386__
extern
unsigned
int
i8042_dmi_noloop
;
#endif
static
unsigned
int
i8042_noloop
;
__obsolete_setup
(
"i8042_noaux"
);
__obsolete_setup
(
"i8042_nomux"
);
__obsolete_setup
(
"i8042_unlock"
);
...
...
@@ -95,6 +100,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 +160,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 +483,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 +677,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 +724,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 +967,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 @
dcfe2282
/*
* $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 @
dcfe2282
...
...
@@ -3,9 +3,17 @@
*
* Copyright (c) 2001 "Crazy" james Simmons
*
* Input driver to Touchscreen device driver module.
* Compaq touchscreen protocol driver. The protocol emulated by this driver
* is obsolete; for new programs use the tslib library which can read directly
* from evdev and perform dejittering, variance filtering and calibration -
* all in user space, not at kernel level. The meaning of this driver is
* to allow usage of newer input drivers with old applications that use the
* old /dev/h3600_ts and /dev/h3600_tsraw devices.
*
* Sponsored by Transvirtual Technology
* 09-Apr-2004: Andrew Zabolotny <zap@homelink.ru>
* Fixed to actually work, not just output random numbers.
* Added support for both h3600_ts and h3600_tsraw protocol
* emulation.
*/
/*
...
...
@@ -24,11 +32,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <jsimmons@
transvirtual.com
>.
* e-mail - mail your message to <jsimmons@
infradead.org
>.
*/
#define TSDEV_MINOR_BASE 128
#define TSDEV_MINORS 32
/* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */
#define TSDEV_MINOR_MASK 15
#define TSDEV_BUFFER_SIZE 64
#include <linux/slab.h>
...
...
@@ -52,48 +62,84 @@
#define CONFIG_INPUT_TSDEV_SCREEN_Y 320
#endif
/* This driver emulates both protocols of the old h3600_ts and h3600_tsraw
* devices. The first one must output X/Y data in 'cooked' format, e.g.
* filtered, dejittered and calibrated. Second device just outputs raw
* data received from the hardware.
*
* This driver doesn't support filtering and dejittering; it supports only
* calibration. Filtering and dejittering must be done in the low-level
* driver, if needed, because it may gain additional benefits from knowing
* the low-level details, the nature of noise and so on.
*
* The driver precomputes a calibration matrix given the initial xres and
* yres values (quite innacurate for most touchscreens) that will result
* in a more or less expected range of output values. The driver supports
* the TS_SET_CAL ioctl, which will replace the calibration matrix with a
* new one, supposedly generated from the values taken from the raw device.
*/
MODULE_AUTHOR
(
"James Simmons <jsimmons@transvirtual.com>"
);
MODULE_DESCRIPTION
(
"Input driver to touchscreen converter"
);
MODULE_LICENSE
(
"GPL"
);
static
int
xres
=
CONFIG_INPUT_TSDEV_SCREEN_X
;
module_param
(
xres
,
uint
,
0
);
MODULE_PARM_DESC
(
xres
,
"Horizontal screen resolution"
);
MODULE_PARM_DESC
(
xres
,
"Horizontal screen resolution
(can be negative for X-mirror)
"
);
static
int
yres
=
CONFIG_INPUT_TSDEV_SCREEN_Y
;
module_param
(
yres
,
uint
,
0
);
MODULE_PARM_DESC
(
yres
,
"Vertical screen resolution"
);
MODULE_PARM_DESC
(
yres
,
"Vertical screen resolution (can be negative for Y-mirror)"
);
/* From Compaq's Touch Screen Specification version 0.2 (draft) */
struct
ts_event
{
short
pressure
;
short
x
;
short
y
;
short
millisecs
;
};
struct
ts_calibration
{
int
xscale
;
int
xtrans
;
int
yscale
;
int
ytrans
;
int
xyswap
;
};
struct
tsdev
{
int
exist
;
int
open
;
int
minor
;
char
name
[
16
];
char
name
[
8
];
wait_queue_head_t
wait
;
struct
list_head
list
;
struct
input_handle
handle
;
int
x
,
y
,
pressure
;
struct
ts_calibration
cal
;
};
/* From Compaq's Touch Screen Specification version 0.2 (draft) */
typedef
struct
{
short
pressure
;
short
x
;
short
y
;
short
millisecs
;
}
TS_EVENT
;
struct
tsdev_list
{
struct
fasync_struct
*
fasync
;
struct
list_head
node
;
struct
tsdev
*
tsdev
;
int
head
,
tail
;
int
oldx
,
oldy
,
pendown
;
TS_EVENT
event
[
TSDEV_BUFFER_SIZE
]
;
struct
ts_event
event
[
TSDEV_BUFFER_SIZE
]
;
int
raw
;
};
/* The following ioctl codes are defined ONLY for backward compatibility.
* Don't use tsdev for new developement; use the tslib library instead.
* Touchscreen calibration is a fully userspace task.
*/
/* Use 'f' as magic number */
#define IOC_H3600_TS_MAGIC 'f'
#define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration)
#define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration)
static
struct
input_handler
tsdev_handler
;
static
struct
tsdev
*
tsdev_table
[
TSDEV_MINORS
];
static
struct
tsdev
*
tsdev_table
[
TSDEV_MINORS
/
2
];
static
int
tsdev_fasync
(
int
fd
,
struct
file
*
file
,
int
on
)
{
...
...
@@ -109,13 +155,16 @@ static int tsdev_open(struct inode *inode, struct file *file)
int
i
=
iminor
(
inode
)
-
TSDEV_MINOR_BASE
;
struct
tsdev_list
*
list
;
if
(
i
>=
TSDEV_MINORS
||
!
tsdev_table
[
i
])
if
(
i
>=
TSDEV_MINORS
||
!
tsdev_table
[
i
&
TSDEV_MINOR_MASK
])
return
-
ENODEV
;
if
(
!
(
list
=
kmalloc
(
sizeof
(
struct
tsdev_list
),
GFP_KERNEL
)))
return
-
ENOMEM
;
memset
(
list
,
0
,
sizeof
(
struct
tsdev_list
));
list
->
raw
=
(
i
>=
TSDEV_MINORS
/
2
)
?
1
:
0
;
i
&=
TSDEV_MINOR_MASK
;
list
->
tsdev
=
tsdev_table
[
i
];
list_add_tail
(
&
list
->
node
,
&
tsdev_table
[
i
]
->
list
);
file
->
private_data
=
list
;
...
...
@@ -169,11 +218,13 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
if
(
!
list
->
tsdev
->
exist
)
return
-
ENODEV
;
while
(
list
->
head
!=
list
->
tail
&&
retval
+
sizeof
(
TS_EVENT
)
<=
count
)
{
if
(
copy_to_user
(
buffer
+
retval
,
list
->
event
+
list
->
tail
,
sizeof
(
TS_EVENT
)))
while
(
list
->
head
!=
list
->
tail
&&
retval
+
sizeof
(
struct
ts_event
)
<=
count
)
{
if
(
copy_to_user
(
buffer
+
retval
,
list
->
event
+
list
->
tail
,
sizeof
(
struct
ts_event
)))
return
-
EFAULT
;
list
->
tail
=
(
list
->
tail
+
1
)
&
(
TSDEV_BUFFER_SIZE
-
1
);
retval
+=
sizeof
(
TS_EVENT
);
retval
+=
sizeof
(
struct
ts_event
);
}
return
retval
;
...
...
@@ -193,22 +244,27 @@ static unsigned int tsdev_poll(struct file *file, poll_table * wait)
static
int
tsdev_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
/*
struct
tsdev_list
*
list
=
file
->
private_data
;
struct tsdev *evdev = list->tsdev;
struct input_dev *dev = tsdev->handle.dev;
int retval;
struct
tsdev
*
tsdev
=
list
->
tsdev
;
int
retval
=
0
;
switch
(
cmd
)
{
case HHEHE:
return 0;
case hjff:
return 0;
default:
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:
retval
=
-
EINVAL
;
break
;
}
*/
return
-
EINVAL
;
return
retval
;
}
struct
file_operations
tsdev_fops
=
{
...
...
@@ -227,82 +283,85 @@ 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
]));
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
]));
break
;
case
ABS_PRESSURE
:
list
->
pendown
=
((
value
>
handle
->
dev
->
absmin
[
ABS_PRESSURE
]))
?
value
-
handle
->
dev
->
absmin
[
ABS_PRESSURE
]
:
0
;
break
;
}
switch
(
type
)
{
case
EV_ABS
:
switch
(
code
)
{
case
ABS_X
:
tsdev
->
x
=
value
;
break
;
case
ABS_Y
:
tsdev
->
y
=
value
;
break
;
case
ABS_PRESSURE
:
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
;
case
EV_REL
:
switch
(
code
)
{
case
REL_X
:
tsdev
->
x
+=
value
;
if
(
tsdev
->
x
<
0
)
tsdev
->
x
=
0
;
else
if
(
tsdev
->
x
>
xres
)
tsdev
->
x
=
xres
;
break
;
case
REL_Y
:
tsdev
->
y
+=
value
;
if
(
tsdev
->
y
<
0
)
tsdev
->
y
=
0
;
else
if
(
tsdev
->
y
>
yres
)
tsdev
->
y
=
yres
;
break
;
}
break
;
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
;
case
EV_KEY
:
if
(
code
==
BTN_TOUCH
||
code
==
BTN_MOUSE
)
{
switch
(
value
)
{
case
0
:
tsdev
->
pressure
=
0
;
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
;
case
1
:
if
(
!
tsdev
->
pressure
)
tsdev
->
pressure
=
1
;
break
;
}
break
;
case
EV_KEY
:
if
(
code
==
BTN_TOUCH
||
code
==
BTN_MOUSE
)
{
switch
(
value
)
{
case
0
:
list
->
pendown
=
0
;
break
;
case
1
:
if
(
!
list
->
pendown
)
list
->
pendown
=
1
;
break
;
case
2
:
return
;
}
}
else
return
;
break
;
}
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/hid-tmff.c
View file @
dcfe2282
...
...
@@ -110,7 +110,7 @@ int hid_tmff_init(struct hid_device *hid)
{
struct
tmff_device
*
private
;
struct
list_head
*
pos
;
struct
hid_input
*
hidinput
=
list_entry
(
&
hid
->
inputs
,
struct
hid_input
,
list
);
struct
hid_input
*
hidinput
=
list_entry
(
hid
->
inputs
.
next
,
struct
hid_input
,
list
);
private
=
kmalloc
(
sizeof
(
struct
tmff_device
),
GFP_KERNEL
);
if
(
!
private
)
...
...
drivers/usb/input/hiddev.c
View file @
dcfe2282
...
...
@@ -639,16 +639,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 @
dcfe2282
...
...
@@ -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 @
dcfe2282
...
...
@@ -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 @
dcfe2282
...
...
@@ -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 @
dcfe2282
...
...
@@ -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 @
dcfe2282
...
...
@@ -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