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
aac0e012
Commit
aac0e012
authored
Sep 20, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/vojtech/input
into home.osdl.org:/home/torvalds/v2.5/linux
parents
157e3d70
0736b22a
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
844 additions
and
251 deletions
+844
-251
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+4
-0
drivers/char/keyboard.c
drivers/char/keyboard.c
+1
-1
drivers/input/evdev.c
drivers/input/evdev.c
+5
-7
drivers/input/input.c
drivers/input/input.c
+4
-2
drivers/input/joystick/db9.c
drivers/input/joystick/db9.c
+269
-44
drivers/input/joystick/iforce/iforce-packets.c
drivers/input/joystick/iforce/iforce-packets.c
+2
-3
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/joystick/iforce/iforce-usb.c
+2
-4
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Kconfig
+2
-1
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+95
-78
drivers/input/mouse/Kconfig
drivers/input/mouse/Kconfig
+17
-3
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse-base.c
+88
-15
drivers/input/mouse/psmouse.h
drivers/input/mouse/psmouse.h
+15
-7
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.c
+285
-78
drivers/input/mouse/synaptics.h
drivers/input/mouse/synaptics.h
+22
-5
drivers/input/serio/serio.c
drivers/input/serio/serio.c
+29
-2
include/linux/input.h
include/linux/input.h
+1
-1
include/linux/serio.h
include/linux/serio.h
+3
-0
No files found.
Documentation/kernel-parameters.txt
View file @
aac0e012
...
...
@@ -788,6 +788,10 @@ running once the system is up.
psmouse_noext [HW,MOUSE] Disable probing for PS2 mouse protocol extensions
psmouse_resetafter=
[HW,MOUSE] Try to reset Synaptics Touchpad after so many
bad packets (0 = never).
pss= [HW,OSS] Personal Sound System (ECHO ESC614)
Format: <io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
...
...
drivers/char/keyboard.c
View file @
aac0e012
...
...
@@ -205,7 +205,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
INPUT_KEYCODE
(
dev
,
scancode
)
=
keycode
;
for
(
i
=
0
;
i
<
dev
->
keycodemax
;
i
++
)
if
(
INPUT_KEYCODE
(
dev
,
scancode
)
==
oldkey
)
if
(
keycode
==
oldkey
)
break
;
if
(
i
==
dev
->
keycodemax
)
clear_bit
(
oldkey
,
dev
->
keybit
);
...
...
drivers/input/evdev.c
View file @
aac0e012
...
...
@@ -208,7 +208,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct
evdev
*
evdev
=
list
->
evdev
;
struct
input_dev
*
dev
=
evdev
->
handle
.
dev
;
struct
input_absinfo
abs
;
int
i
,
t
,
u
;
int
i
,
t
,
u
,
v
;
if
(
!
evdev
->
exist
)
return
-
ENODEV
;
...
...
@@ -239,14 +239,12 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case
EVIOCSKEYCODE
:
if
(
get_user
(
t
,
((
int
*
)
arg
)
+
0
))
return
-
EFAULT
;
if
(
t
<
0
||
t
>
dev
->
keycodemax
||
!
dev
->
keycodesize
)
return
-
EINVAL
;
if
(
get_user
(
v
,
((
int
*
)
arg
)
+
1
))
return
-
EFAULT
;
u
=
INPUT_KEYCODE
(
dev
,
t
);
if
(
get_user
(
INPUT_KEYCODE
(
dev
,
t
),
((
int
*
)
arg
)
+
1
))
return
-
EFAULT
;
for
(
i
=
0
;
i
<
dev
->
keycodemax
;
i
++
)
if
(
INPUT_KEYCODE
(
dev
,
t
)
==
u
)
break
;
INPUT_KEYCODE
(
dev
,
t
)
=
v
;
for
(
i
=
0
;
i
<
dev
->
keycodemax
;
i
++
)
if
(
v
==
u
)
break
;
if
(
i
==
dev
->
keycodemax
)
clear_bit
(
u
,
dev
->
keybit
);
set_bit
(
INPUT_KEYCODE
(
dev
,
t
),
dev
->
keybit
);
set_bit
(
v
,
dev
->
keybit
);
return
0
;
case
EVIOCSFF
:
...
...
drivers/input/input.c
View file @
aac0e012
...
...
@@ -426,8 +426,10 @@ void input_register_device(struct input_dev *dev)
init_timer
(
&
dev
->
timer
);
dev
->
timer
.
data
=
(
long
)
dev
;
dev
->
timer
.
function
=
input_repeat_key
;
dev
->
rep
[
REP_DELAY
]
=
HZ
/
4
;
dev
->
rep
[
REP_PERIOD
]
=
HZ
/
33
;
if
(
!
dev
->
rep
[
REP_DELAY
])
dev
->
rep
[
REP_DELAY
]
=
HZ
/
4
;
if
(
!
dev
->
rep
[
REP_PERIOD
])
dev
->
rep
[
REP_PERIOD
]
=
HZ
/
33
;
INIT_LIST_HEAD
(
&
dev
->
h_list
);
list_add_tail
(
&
dev
->
node
,
&
input_dev_list
);
...
...
drivers/input/joystick/db9.c
View file @
aac0e012
...
...
@@ -55,7 +55,9 @@ MODULE_PARM(db9_3, "2i");
#define DB9_MULTI_0802 0x08
#define DB9_MULTI_0802_2 0x09
#define DB9_CD32_PAD 0x0A
#define DB9_MAX_PAD 0x0B
#define DB9_SATURN_DPP 0x0B
#define DB9_SATURN_DPP_2 0x0C
#define DB9_MAX_PAD 0x0D
#define DB9_UP 0x01
#define DB9_DOWN 0x02
...
...
@@ -69,10 +71,7 @@ MODULE_PARM(db9_3, "2i");
#define DB9_NORMAL 0x0a
#define DB9_NOSELECT 0x08
#define DB9_SATURN0 0x00
#define DB9_SATURN1 0x02
#define DB9_SATURN2 0x04
#define DB9_SATURN3 0x06
#define DB9_MAX_DEVICES 2
#define DB9_GENESIS6_DELAY 14
#define DB9_REFRESH_TIME HZ/100
...
...
@@ -82,7 +81,7 @@ static int db9_2[] __initdata = { -1, 0 };
static
int
db9_3
[]
__initdata
=
{
-
1
,
0
};
struct
db9
{
struct
input_dev
dev
[
2
];
struct
input_dev
dev
[
DB9_MAX_DEVICES
];
struct
timer_list
timer
;
struct
pardevice
*
pd
;
int
mode
;
...
...
@@ -96,12 +95,247 @@ static short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
static
short
db9_genesis_btn
[]
=
{
BTN_START
,
BTN_A
,
BTN_B
,
BTN_C
,
BTN_X
,
BTN_Y
,
BTN_Z
,
BTN_MODE
};
static
short
db9_cd32_btn
[]
=
{
BTN_A
,
BTN_B
,
BTN_C
,
BTN_X
,
BTN_Y
,
BTN_Z
,
BTN_TL
,
BTN_TR
,
BTN_START
};
static
char
db9_buttons
[
DB9_MAX_PAD
]
=
{
0
,
1
,
2
,
4
,
0
,
6
,
8
,
8
,
1
,
1
,
7
};
static
char
db9_buttons
[
DB9_MAX_PAD
]
=
{
0
,
1
,
2
,
4
,
0
,
6
,
8
,
9
,
1
,
1
,
7
,
9
,
9
};
static
short
*
db9_btn
[
DB9_MAX_PAD
]
=
{
NULL
,
db9_multi_btn
,
db9_multi_btn
,
db9_genesis_btn
,
NULL
,
db9_genesis_btn
,
db9_genesis_btn
,
db9_cd32_btn
,
db9_multi_btn
,
db9_multi_btn
,
db9_cd32_btn
};
db9_genesis_btn
,
db9_cd32_btn
,
db9_multi_btn
,
db9_multi_btn
,
db9_cd32_btn
,
db9_cd32_btn
,
db9_cd32_btn
};
static
char
*
db9_name
[
DB9_MAX_PAD
]
=
{
NULL
,
"Multisystem joystick"
,
"Multisystem joystick (2 fire)"
,
"Genesis pad"
,
NULL
,
"Genesis 5 pad"
,
"Genesis 6 pad"
,
"Saturn pad"
,
"Multisystem (0.8.0.2) joystick"
,
"Multisystem (0.8.0.2-dual) joystick"
,
"Amiga CD-32 pad"
};
"Multisystem (0.8.0.2-dual) joystick"
,
"Amiga CD-32 pad"
,
"Saturn dpp"
,
"Saturn dpp dual"
};
static
const
int
db9_max_pads
[
DB9_MAX_PAD
]
=
{
0
,
1
,
1
,
1
,
0
,
1
,
1
,
6
,
1
,
2
,
1
,
6
,
12
};
static
const
int
db9_num_axis
[
DB9_MAX_PAD
]
=
{
0
,
2
,
2
,
2
,
0
,
2
,
2
,
7
,
2
,
2
,
2
,
7
,
7
};
static
const
short
db9_abs
[]
=
{
ABS_X
,
ABS_Y
,
ABS_RX
,
ABS_RY
,
ABS_RZ
,
ABS_Z
,
ABS_HAT0X
,
ABS_HAT0Y
,
ABS_HAT1X
,
ABS_HAT1Y
};
static
const
int
db9_bidirectional
[
DB9_MAX_PAD
]
=
{
0
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
0
,
1
,
1
,
0
,
0
};
static
const
int
db9_reverse
[
DB9_MAX_PAD
]
=
{
0
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
};
/*
* Saturn controllers
*/
#define DB9_SATURN_DELAY 300
static
const
int
db9_saturn_byte
[]
=
{
1
,
1
,
1
,
2
,
2
,
2
,
2
,
2
,
1
};
static
const
unsigned
char
db9_saturn_mask
[]
=
{
0x04
,
0x01
,
0x02
,
0x40
,
0x20
,
0x10
,
0x08
,
0x80
,
0x08
};
/*
* db9_saturn_write_sub() writes 2 bit data.
*/
static
void
db9_saturn_write_sub
(
struct
parport
*
port
,
int
type
,
unsigned
char
data
,
int
powered
,
int
pwr_sub
)
{
unsigned
char
c
;
switch
(
type
)
{
case
1
:
/* DPP1 */
c
=
0x80
|
0x30
|
(
powered
?
0x08
:
0
)
|
(
pwr_sub
?
0x04
:
0
)
|
data
;
parport_write_data
(
port
,
c
);
break
;
case
2
:
/* DPP2 */
c
=
0x40
|
data
<<
4
|
(
powered
?
0x08
:
0
)
|
(
pwr_sub
?
0x04
:
0
)
|
0x03
;
parport_write_data
(
port
,
c
);
break
;
case
0
:
/* DB9 */
c
=
((((
data
&
2
)
?
2
:
0
)
|
((
data
&
1
)
?
4
:
0
))
^
0x02
)
|
!
powered
;
parport_write_control
(
port
,
c
);
break
;
}
}
/*
* gc_saturn_read_sub() reads 4 bit data.
*/
static
unsigned
char
db9_saturn_read_sub
(
struct
parport
*
port
,
int
type
)
{
unsigned
char
data
;
if
(
type
)
{
/* DPP */
data
=
parport_read_status
(
port
)
^
0x80
;
return
(
data
&
0x80
?
1
:
0
)
|
(
data
&
0x40
?
2
:
0
)
|
(
data
&
0x20
?
4
:
0
)
|
(
data
&
0x10
?
8
:
0
);
}
else
{
/* DB9 */
data
=
parport_read_data
(
port
)
&
0x0f
;
return
(
data
&
0x8
?
1
:
0
)
|
(
data
&
0x4
?
2
:
0
)
|
(
data
&
0x2
?
4
:
0
)
|
(
data
&
0x1
?
8
:
0
);
}
}
/*
* db9_saturn_read_analog() sends clock and reads 8 bit data.
*/
static
unsigned
char
db9_saturn_read_analog
(
struct
parport
*
port
,
int
type
,
int
powered
)
{
unsigned
char
data
;
db9_saturn_write_sub
(
port
,
type
,
0
,
powered
,
0
);
udelay
(
DB9_SATURN_DELAY
);
data
=
db9_saturn_read_sub
(
port
,
type
)
<<
4
;
db9_saturn_write_sub
(
port
,
type
,
2
,
powered
,
0
);
udelay
(
DB9_SATURN_DELAY
);
data
|=
db9_saturn_read_sub
(
port
,
type
);
return
data
;
}
/*
* db9_saturn_read_packet() reads whole saturn packet at connector
* and returns device identifier code.
*/
static
unsigned
char
db9_saturn_read_packet
(
struct
parport
*
port
,
unsigned
char
*
data
,
int
type
,
int
powered
)
{
int
i
,
j
;
unsigned
char
tmp
;
db9_saturn_write_sub
(
port
,
type
,
3
,
powered
,
0
);
data
[
0
]
=
db9_saturn_read_sub
(
port
,
type
);
switch
(
data
[
0
]
&
0x0f
)
{
case
0xf
:
/* 1111 no pad */
return
data
[
0
]
=
0xff
;
case
0x4
:
case
0x4
|
0x8
:
/* ?100 : digital controller */
db9_saturn_write_sub
(
port
,
type
,
0
,
powered
,
1
);
data
[
2
]
=
db9_saturn_read_sub
(
port
,
type
)
<<
4
;
db9_saturn_write_sub
(
port
,
type
,
2
,
powered
,
1
);
data
[
1
]
=
db9_saturn_read_sub
(
port
,
type
)
<<
4
;
db9_saturn_write_sub
(
port
,
type
,
1
,
powered
,
1
);
data
[
1
]
|=
db9_saturn_read_sub
(
port
,
type
);
db9_saturn_write_sub
(
port
,
type
,
3
,
powered
,
1
);
/* data[2] |= db9_saturn_read_sub(port, type); */
data
[
2
]
|=
data
[
0
];
return
data
[
0
]
=
0x02
;
case
0x1
:
/* 0001 : analog controller or multitap */
db9_saturn_write_sub
(
port
,
type
,
2
,
powered
,
0
);
udelay
(
DB9_SATURN_DELAY
);
data
[
0
]
=
db9_saturn_read_analog
(
port
,
type
,
powered
);
if
(
data
[
0
]
!=
0x41
)
{
/* read analog controller */
for
(
i
=
0
;
i
<
(
data
[
0
]
&
0x0f
);
i
++
)
data
[
i
+
1
]
=
db9_saturn_read_analog
(
port
,
type
,
powered
);
db9_saturn_write_sub
(
port
,
type
,
3
,
powered
,
0
);
return
data
[
0
];
}
else
{
/* read multitap */
if
(
db9_saturn_read_analog
(
port
,
type
,
powered
)
!=
0x60
)
return
data
[
0
]
=
0xff
;
for
(
i
=
0
;
i
<
60
;
i
+=
10
)
{
data
[
i
]
=
db9_saturn_read_analog
(
port
,
type
,
powered
);
if
(
data
[
i
]
!=
0xff
)
/* read each pad */
for
(
j
=
0
;
j
<
(
data
[
i
]
&
0x0f
);
j
++
)
data
[
i
+
j
+
1
]
=
db9_saturn_read_analog
(
port
,
type
,
powered
);
}
db9_saturn_write_sub
(
port
,
type
,
3
,
powered
,
0
);
return
0x41
;
}
case
0x0
:
/* 0000 : mouse */
db9_saturn_write_sub
(
port
,
type
,
2
,
powered
,
0
);
udelay
(
DB9_SATURN_DELAY
);
tmp
=
db9_saturn_read_analog
(
port
,
type
,
powered
);
if
(
tmp
==
0xff
)
{
for
(
i
=
0
;
i
<
3
;
i
++
)
data
[
i
+
1
]
=
db9_saturn_read_analog
(
port
,
type
,
powered
);
db9_saturn_write_sub
(
port
,
type
,
3
,
powered
,
0
);
return
data
[
0
]
=
0xe3
;
}
default:
return
data
[
0
];
}
}
/*
* db9_saturn_report() analyzes packet and reports.
*/
static
int
db9_saturn_report
(
unsigned
char
id
,
unsigned
char
data
[
60
],
struct
input_dev
*
dev
,
int
n
,
int
max_pads
)
{
int
tmp
,
i
,
j
;
tmp
=
(
id
==
0x41
)
?
60
:
10
;
for
(
j
=
0
;
(
j
<
tmp
)
&&
(
n
<
max_pads
);
j
+=
10
,
n
++
)
{
switch
(
data
[
j
])
{
case
0x16
:
/* multi controller (analog 4 axis) */
input_report_abs
(
dev
+
n
,
db9_abs
[
5
],
data
[
j
+
6
]);
case
0x15
:
/* mission stick (analog 3 axis) */
input_report_abs
(
dev
+
n
,
db9_abs
[
3
],
data
[
j
+
4
]);
input_report_abs
(
dev
+
n
,
db9_abs
[
4
],
data
[
j
+
5
]);
case
0x13
:
/* racing controller (analog 1 axis) */
input_report_abs
(
dev
+
n
,
db9_abs
[
2
],
data
[
j
+
3
]);
case
0x34
:
/* saturn keyboard (udlr ZXC ASD QE Esc) */
case
0x02
:
/* digital pad (digital 2 axis + buttons) */
input_report_abs
(
dev
+
n
,
db9_abs
[
0
],
!
(
data
[
j
+
1
]
&
128
)
-
!
(
data
[
j
+
1
]
&
64
));
input_report_abs
(
dev
+
n
,
db9_abs
[
1
],
!
(
data
[
j
+
1
]
&
32
)
-
!
(
data
[
j
+
1
]
&
16
));
for
(
i
=
0
;
i
<
9
;
i
++
)
input_report_key
(
dev
+
n
,
db9_cd32_btn
[
i
],
~
data
[
j
+
db9_saturn_byte
[
i
]]
&
db9_saturn_mask
[
i
]);
break
;
case
0x19
:
/* mission stick x2 (analog 6 axis + buttons) */
input_report_abs
(
dev
+
n
,
db9_abs
[
0
],
!
(
data
[
j
+
1
]
&
128
)
-
!
(
data
[
j
+
1
]
&
64
));
input_report_abs
(
dev
+
n
,
db9_abs
[
1
],
!
(
data
[
j
+
1
]
&
32
)
-
!
(
data
[
j
+
1
]
&
16
));
for
(
i
=
0
;
i
<
9
;
i
++
)
input_report_key
(
dev
+
n
,
db9_cd32_btn
[
i
],
~
data
[
j
+
db9_saturn_byte
[
i
]]
&
db9_saturn_mask
[
i
]);
input_report_abs
(
dev
+
n
,
db9_abs
[
2
],
data
[
j
+
3
]);
input_report_abs
(
dev
+
n
,
db9_abs
[
3
],
data
[
j
+
4
]);
input_report_abs
(
dev
+
n
,
db9_abs
[
4
],
data
[
j
+
5
]);
/*
input_report_abs(dev + n, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1));
input_report_abs(dev + n, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1));
*/
input_report_abs
(
dev
+
n
,
db9_abs
[
6
],
data
[
j
+
7
]);
input_report_abs
(
dev
+
n
,
db9_abs
[
7
],
data
[
j
+
8
]);
input_report_abs
(
dev
+
n
,
db9_abs
[
5
],
data
[
j
+
9
]);
break
;
case
0xd3
:
/* sankyo ff (analog 1 axis + stop btn) */
input_report_key
(
dev
+
n
,
BTN_A
,
data
[
j
+
3
]
&
0x80
);
input_report_abs
(
dev
+
n
,
db9_abs
[
2
],
data
[
j
+
3
]
&
0x7f
);
break
;
case
0xe3
:
/* shuttle mouse (analog 2 axis + buttons. signed value) */
input_report_key
(
dev
+
n
,
BTN_START
,
data
[
j
+
1
]
&
0x08
);
input_report_key
(
dev
+
n
,
BTN_A
,
data
[
j
+
1
]
&
0x04
);
input_report_key
(
dev
+
n
,
BTN_C
,
data
[
j
+
1
]
&
0x02
);
input_report_key
(
dev
+
n
,
BTN_B
,
data
[
j
+
1
]
&
0x01
);
input_report_abs
(
dev
+
n
,
db9_abs
[
2
],
data
[
j
+
2
]
^
0x80
);
input_report_abs
(
dev
+
n
,
db9_abs
[
3
],
(
0xff
-
(
data
[
j
+
3
]
^
0x80
))
+
1
);
/* */
break
;
case
0xff
:
default:
/* no pad */
input_report_abs
(
dev
+
n
,
db9_abs
[
0
],
0
);
input_report_abs
(
dev
+
n
,
db9_abs
[
1
],
0
);
for
(
i
=
0
;
i
<
9
;
i
++
)
input_report_key
(
dev
+
n
,
db9_cd32_btn
[
i
],
0
);
break
;
}
}
return
n
;
}
static
int
db9_saturn
(
int
mode
,
struct
parport
*
port
,
struct
input_dev
*
dev
)
{
unsigned
char
id
,
data
[
60
];
int
type
,
n
,
max_pads
;
int
tmp
,
i
;
switch
(
mode
)
{
case
DB9_SATURN_PAD
:
type
=
0
;
n
=
1
;
break
;
case
DB9_SATURN_DPP
:
type
=
1
;
n
=
1
;
break
;
case
DB9_SATURN_DPP_2
:
type
=
1
;
n
=
2
;
break
;
default:
return
-
1
;
}
max_pads
=
min
(
db9_max_pads
[
mode
],
DB9_MAX_DEVICES
);
for
(
tmp
=
0
,
i
=
0
;
i
<
n
;
i
++
)
{
id
=
db9_saturn_read_packet
(
port
,
data
,
type
+
i
,
1
);
tmp
=
db9_saturn_report
(
id
,
data
,
dev
,
tmp
,
max_pads
);
}
return
0
;
}
static
void
db9_timer
(
unsigned
long
private
)
{
...
...
@@ -222,28 +456,10 @@ static void db9_timer(unsigned long private)
break
;
case
DB9_SATURN_PAD
:
case
DB9_SATURN_DPP
:
case
DB9_SATURN_DPP_2
:
parport_write_control
(
port
,
DB9_SATURN0
);
data
=
parport_read_data
(
port
);
input_report_key
(
dev
,
BTN_Y
,
~
data
&
DB9_LEFT
);
input_report_key
(
dev
,
BTN_Z
,
~
data
&
DB9_DOWN
);
input_report_key
(
dev
,
BTN_TL
,
~
data
&
DB9_UP
);
input_report_key
(
dev
,
BTN_TR
,
~
data
&
DB9_RIGHT
);
parport_write_control
(
port
,
DB9_SATURN2
);
data
=
parport_read_data
(
port
);
input_report_abs
(
dev
,
ABS_X
,
(
data
&
DB9_RIGHT
?
0
:
1
)
-
(
data
&
DB9_LEFT
?
0
:
1
));
input_report_abs
(
dev
,
ABS_Y
,
(
data
&
DB9_DOWN
?
0
:
1
)
-
(
data
&
DB9_UP
?
0
:
1
));
parport_write_control
(
port
,
DB9_NORMAL
);
data
=
parport_read_data
(
port
);
input_report_key
(
dev
,
BTN_A
,
~
data
&
DB9_LEFT
);
input_report_key
(
dev
,
BTN_B
,
~
data
&
DB9_UP
);
input_report_key
(
dev
,
BTN_C
,
~
data
&
DB9_DOWN
);
input_report_key
(
dev
,
BTN_X
,
~
data
&
DB9_RIGHT
);
db9_saturn
(
db9
->
mode
,
port
,
dev
);
break
;
case
DB9_CD32_PAD
:
...
...
@@ -279,8 +495,10 @@ static int db9_open(struct input_dev *dev)
if
(
!
db9
->
used
++
)
{
parport_claim
(
db9
->
pd
);
parport_write_data
(
port
,
0xff
);
parport_data_reverse
(
port
);
parport_write_control
(
port
,
DB9_NORMAL
);
if
(
db9_reverse
[
db9
->
mode
])
{
parport_data_reverse
(
port
);
parport_write_control
(
port
,
DB9_NORMAL
);
}
mod_timer
(
&
db9
->
timer
,
jiffies
+
DB9_REFRESH_TIME
);
}
...
...
@@ -321,11 +539,13 @@ static struct db9 __init *db9_probe(int *config)
return
NULL
;
}
if
(
!
(
pp
->
modes
&
PARPORT_MODE_TRISTATE
)
&&
config
[
1
]
!=
DB9_MULTI_0802
)
{
printk
(
KERN_ERR
"db9.c: specified parport is not bidirectional
\n
"
);
return
NULL
;
if
(
db9_bidirectional
[
config
[
1
]])
{
if
(
!
(
pp
->
modes
&
PARPORT_MODE_TRISTATE
))
{
printk
(
KERN_ERR
"db9.c: specified parport is not bidirectional
\n
"
);
return
NULL
;
}
}
if
(
!
(
db9
=
kmalloc
(
sizeof
(
struct
db9
),
GFP_KERNEL
)))
return
NULL
;
memset
(
db9
,
0
,
sizeof
(
struct
db9
));
...
...
@@ -343,7 +563,7 @@ static struct db9 __init *db9_probe(int *config)
return
NULL
;
}
for
(
i
=
0
;
i
<
1
+
(
db9
->
mode
==
DB9_MULTI_0802_2
);
i
++
)
{
for
(
i
=
0
;
i
<
(
min
(
db9_max_pads
[
db9
->
mode
],
DB9_MAX_DEVICES
)
);
i
++
)
{
sprintf
(
db9
->
phys
[
i
],
"%s/input%d"
,
db9
->
pd
->
port
->
name
,
i
);
...
...
@@ -359,14 +579,19 @@ static struct db9 __init *db9_probe(int *config)
db9
->
dev
[
i
].
id
.
version
=
0x0100
;
db9
->
dev
[
i
].
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_ABS
);
db9
->
dev
[
i
].
absbit
[
0
]
=
BIT
(
ABS_X
)
|
BIT
(
ABS_Y
);
for
(
j
=
0
;
j
<
db9_buttons
[
db9
->
mode
];
j
++
)
set_bit
(
db9_btn
[
db9
->
mode
][
j
],
db9
->
dev
[
i
].
keybit
);
db9
->
dev
[
i
].
absmin
[
ABS_X
]
=
-
1
;
db9
->
dev
[
i
].
absmax
[
ABS_X
]
=
1
;
db9
->
dev
[
i
].
absmin
[
ABS_Y
]
=
-
1
;
db9
->
dev
[
i
].
absmax
[
ABS_Y
]
=
1
;
for
(
j
=
0
;
j
<
db9_num_axis
[
db9
->
mode
];
j
++
)
{
set_bit
(
db9_abs
[
j
],
db9
->
dev
[
i
].
absbit
);
if
(
j
<
2
)
{
db9
->
dev
[
i
].
absmin
[
db9_abs
[
j
]]
=
-
1
;
db9
->
dev
[
i
].
absmax
[
db9_abs
[
j
]]
=
1
;
}
else
{
db9
->
dev
[
i
].
absmin
[
db9_abs
[
j
]]
=
1
;
db9
->
dev
[
i
].
absmax
[
db9_abs
[
j
]]
=
255
;
db9
->
dev
[
i
].
absflat
[
db9_abs
[
j
]]
=
0
;
}
}
input_register_device
(
db9
->
dev
+
i
);
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
db9
->
dev
[
i
].
name
,
db9
->
pd
->
port
->
name
);
}
...
...
@@ -419,7 +644,7 @@ void __exit db9_exit(void)
for
(
i
=
0
;
i
<
3
;
i
++
)
if
(
db9_base
[
i
])
{
for
(
j
=
0
;
j
<
1
+
(
db9_base
[
i
]
->
mode
==
DB9_MULTI_0802_2
);
j
++
)
for
(
j
=
0
;
j
<
min
(
db9_max_pads
[
db9_base
[
i
]
->
mode
],
DB9_MAX_DEVICES
);
j
++
)
input_unregister_device
(
db9_base
[
i
]
->
dev
+
j
);
parport_unregister_device
(
db9_base
[
i
]
->
pd
);
}
...
...
drivers/input/joystick/iforce/iforce-packets.c
View file @
aac0e012
...
...
@@ -166,8 +166,7 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data,
iforce
->
expect_packet
=
0
;
iforce
->
ecmd
=
cmd
;
memcpy
(
iforce
->
edata
,
data
,
IFORCE_MAX_LENGTH
);
if
(
waitqueue_active
(
&
iforce
->
wait
))
wake_up
(
&
iforce
->
wait
);
wake_up
(
&
iforce
->
wait
);
}
#endif
...
...
@@ -264,7 +263,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
set_current_state
(
TASK_INTERRUPTIBLE
);
add_wait_queue
(
&
iforce
->
wait
,
&
wait
);
if
(
usb_submit_urb
(
iforce
->
ctrl
,
GFP_
KERNEL
))
{
if
(
usb_submit_urb
(
iforce
->
ctrl
,
GFP_
ATOMIC
))
{
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
iforce
->
wait
,
&
wait
);
return
-
1
;
...
...
drivers/input/joystick/iforce/iforce-usb.c
View file @
aac0e012
...
...
@@ -116,8 +116,7 @@ static void iforce_usb_out(struct urb *urb, struct pt_regs *regs)
iforce_usb_xmit
(
iforce
);
if
(
waitqueue_active
(
&
iforce
->
wait
))
wake_up
(
&
iforce
->
wait
);
wake_up
(
&
iforce
->
wait
);
}
static
void
iforce_usb_ctrl
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
...
...
@@ -125,8 +124,7 @@ static void iforce_usb_ctrl(struct urb *urb, struct pt_regs *regs)
struct
iforce
*
iforce
=
urb
->
context
;
if
(
urb
->
status
)
return
;
iforce
->
ecmd
=
0xff00
|
urb
->
actual_length
;
if
(
waitqueue_active
(
&
iforce
->
wait
))
wake_up
(
&
iforce
->
wait
);
wake_up
(
&
iforce
->
wait
);
}
static
int
iforce_usb_probe
(
struct
usb_interface
*
intf
,
...
...
drivers/input/keyboard/Kconfig
View file @
aac0e012
...
...
@@ -13,7 +13,8 @@ config INPUT_KEYBOARD
config KEYBOARD_ATKBD
tristate "AT keyboard support" if EMBEDDED || !X86
default y
default y if INPUT=y && INPUT_KEYBOARD=y && SERIO=y
default m
depends on INPUT && INPUT_KEYBOARD && SERIO
help
Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
...
...
drivers/input/keyboard/atkbd.c
View file @
aac0e012
...
...
@@ -18,6 +18,7 @@
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@suse.cz>"
);
MODULE_DESCRIPTION
(
"AT and PS/2 keyboard driver"
);
...
...
@@ -40,8 +41,8 @@ static int atkbd_reset = 1;
static
unsigned
char
atkbd_set2_keycode
[
512
]
=
{
0
,
67
,
65
,
63
,
61
,
59
,
60
,
88
,
0
,
68
,
66
,
64
,
62
,
15
,
41
,
85
,
0
,
56
,
42
,
182
,
29
,
16
,
2
,
89
,
0
,
0
,
44
,
31
,
30
,
17
,
3
,
90
,
0
,
46
,
45
,
32
,
18
,
5
,
4
,
91
,
0
,
57
,
47
,
33
,
20
,
19
,
6
,
0
,
0
,
49
,
48
,
35
,
34
,
21
,
7
,
0
,
0
,
0
,
50
,
36
,
22
,
8
,
9
,
0
,
0
,
46
,
45
,
32
,
18
,
5
,
4
,
91
,
9
0
,
57
,
47
,
33
,
20
,
19
,
6
,
0
,
91
,
49
,
48
,
35
,
34
,
21
,
7
,
0
,
0
,
0
,
50
,
36
,
22
,
8
,
9
,
0
,
0
,
51
,
37
,
23
,
24
,
11
,
10
,
0
,
0
,
52
,
53
,
38
,
39
,
25
,
12
,
0
,
122
,
89
,
40
,
120
,
26
,
13
,
0
,
0
,
58
,
54
,
28
,
27
,
0
,
43
,
0
,
0
,
85
,
86
,
90
,
91
,
92
,
93
,
14
,
94
,
95
,
79
,
183
,
75
,
71
,
121
,
0
,
123
,
...
...
@@ -87,10 +88,10 @@ static unsigned char atkbd_set3_keycode[512] = {
#define ATKBD_CMD_GSCANSET 0x11f0
#define ATKBD_CMD_SSCANSET 0x10f0
#define ATKBD_CMD_GETID 0x02f2
#define ATKBD_CMD_SETREP 0x10f3
#define ATKBD_CMD_ENABLE 0x00f4
#define ATKBD_CMD_RESET_DIS 0x00f5
#define ATKBD_CMD_RESET_BAT 0x02ff
#define ATKBD_CMD_SETALL_MB 0x00f8
#define ATKBD_CMD_RESEND 0x00fe
#define ATKBD_CMD_EX_ENABLE 0x10ea
#define ATKBD_CMD_EX_SETLEDS 0x20eb
...
...
@@ -114,12 +115,14 @@ struct atkbd {
unsigned
char
keycode
[
512
];
struct
input_dev
dev
;
struct
serio
*
serio
;
struct
timer_list
timer
;
char
name
[
64
];
char
phys
[
32
];
unsigned
char
cmdbuf
[
4
];
unsigned
char
cmdcnt
;
unsigned
char
set
;
unsigned
char
release
;
int
lastkey
;
volatile
signed
char
ack
;
unsigned
char
emul
;
unsigned
short
id
;
...
...
@@ -142,6 +145,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
printk
(
KERN_DEBUG
"atkbd.c: Received %02x flags %02x
\n
"
,
data
,
flags
);
#endif
#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
);
serio_write
(
serio
,
ATKBD_CMD_RESEND
);
...
...
@@ -151,6 +155,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if
(
!
flags
)
atkbd
->
resend
=
0
;
#endif
switch
(
code
)
{
case
ATKBD_RET_ACK
:
...
...
@@ -195,6 +200,14 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd
->
set
,
code
,
serio
->
phys
,
atkbd
->
release
?
"released"
:
"pressed"
);
break
;
default:
if
(
!
atkbd
->
release
)
{
mod_timer
(
&
atkbd
->
timer
,
jiffies
+
(
test_bit
(
atkbd
->
keycode
[
code
],
&
atkbd
->
dev
.
key
)
?
HZ
/
33
:
HZ
/
4
)
+
HZ
/
100
);
atkbd
->
lastkey
=
atkbd
->
keycode
[
code
];
}
input_regs
(
&
atkbd
->
dev
,
regs
);
input_report_key
(
&
atkbd
->
dev
,
atkbd
->
keycode
[
code
],
!
atkbd
->
release
);
input_sync
(
&
atkbd
->
dev
);
...
...
@@ -205,6 +218,13 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
return
IRQ_HANDLED
;
}
static
void
atkbd_force_key_up
(
unsigned
long
data
)
{
struct
atkbd
*
atkbd
=
(
void
*
)
data
;
input_report_key
(
&
atkbd
->
dev
,
atkbd
->
lastkey
,
0
);
input_sync
(
&
atkbd
->
dev
);
}
/*
* atkbd_sendbyte() sends a byte to the keyboard, and waits for
* acknowledge. It doesn't handle resends according to the keyboard
...
...
@@ -214,7 +234,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
static
int
atkbd_sendbyte
(
struct
atkbd
*
atkbd
,
unsigned
char
byte
)
{
int
timeout
=
10000
;
/* 1
00 msec */
int
timeout
=
20000
;
/* 2
00 msec */
atkbd
->
ack
=
0
;
#ifdef ATKBD_DEBUG
...
...
@@ -322,13 +342,50 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
}
/*
*
Enable keyboard
.
*
atkbd_probe() probes for an AT keyboard on a serio port
.
*/
static
void
atkbd_enable
(
struct
atkbd
*
atkbd
)
static
int
atkbd_probe
(
struct
atkbd
*
atkbd
)
{
if
(
atkbd_command
(
atkbd
,
NULL
,
ATKBD_CMD_ENABLE
))
printk
(
KERN_ERR
"atkbd.c: Failed to enable keyboard on %s
\n
"
,
atkbd
->
serio
->
phys
);
unsigned
char
param
[
2
];
/*
* Some systems, where the bit-twiddling when testing the io-lines of the
* controller may confuse the keyboard need a full reset of the keyboard. On
* these systems the BIOS also usually doesn't do it for us.
*/
if
(
atkbd_reset
)
if
(
atkbd_command
(
atkbd
,
NULL
,
ATKBD_CMD_RESET_BAT
))
printk
(
KERN_WARNING
"atkbd.c: keyboard reset failed on %s
\n
"
,
atkbd
->
serio
->
phys
);
/*
* Then we check the keyboard ID. We should get 0xab83 under normal conditions.
* Some keyboards report different values, but the first byte is always 0xab or
* 0xac. Some old AT keyboards don't report anything. If a mouse is connected, this
* should make sure we don't try to set the LEDs on it.
*/
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_GETID
))
{
/*
* If the get ID command failed, we check if we can at least set the LEDs on
* the keyboard. This should work on every keyboard out there. It also turns
* the LEDs off, which we want anyway.
*/
param
[
0
]
=
0
;
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETLEDS
))
return
-
1
;
atkbd
->
id
=
0xabba
;
return
0
;
}
if
(
param
[
0
]
!=
0xab
&&
param
[
0
]
!=
0xac
)
return
-
1
;
atkbd
->
id
=
(
param
[
0
]
<<
8
)
|
param
[
1
];
return
0
;
}
/*
...
...
@@ -365,102 +422,56 @@ static int atkbd_set_3(struct atkbd *atkbd)
return
4
;
}
/*
* Try to set the set we want.
*/
if
(
atkbd_set
!=
3
)
return
2
;
param
[
0
]
=
atkbd_set
;
param
[
0
]
=
3
;
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SSCANSET
))
return
2
;
/*
* Read set number. Beware here. Some keyboards always send '2'
* or some other number regardless into what mode they have been
* attempted to be set. Other keyboards treat the '0' command as
* 'set to set 0', and not 'report current set' as they should.
* In that case we time out, and return 2.
*/
param
[
0
]
=
0
;
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_GSCANSET
))
return
2
;
/*
* Here we return the set number the keyboard reports about
* itself.
*/
if
(
param
[
0
]
!=
3
)
return
2
;
return
(
param
[
0
]
==
3
)
?
3
:
2
;
return
3
;
}
/*
* atkbd_probe() probes for an AT keyboard on a serio port.
*/
static
int
atkbd_probe
(
struct
atkbd
*
atkbd
)
static
int
atkbd_enable
(
struct
atkbd
*
atkbd
)
{
unsigned
char
param
[
2
];
/*
* Some systems, where the bit-twiddling when testing the io-lines of the
* controller may confuse the keyboard need a full reset of the keyboard. On
* these systems the BIOS also usually doesn't do it for us.
*/
if
(
atkbd_reset
)
if
(
atkbd_command
(
atkbd
,
NULL
,
ATKBD_CMD_RESET_BAT
))
printk
(
KERN_WARNING
"atkbd.c: keyboard reset failed on %s
\n
"
,
atkbd
->
serio
->
phys
);
unsigned
char
param
[
1
];
/*
* Then we check the keyboard ID. We should get 0xab83 under normal conditions.
* Some keyboards report different values, but the first byte is always 0xab or
* 0xac. Some old AT keyboards don't report anything.
* Set the LEDs to a defined state.
*/
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_GETID
))
{
param
[
0
]
=
0
;
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETLEDS
))
return
-
1
;
/*
* If the get ID command failed, we check if we can at least set the LEDs on
* the keyboard. This should work on every keyboard out there. It also turns
* the LEDs off, which we want anyway.
* Set autorepeat to fastest possible.
*/
param
[
0
]
=
0
;
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETLEDS
))
return
-
1
;
atkbd
->
id
=
0xabba
;
return
0
;
}
if
(
param
[
0
]
!=
0xab
&&
param
[
0
]
!=
0xac
)
param
[
0
]
=
0
;
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETREP
))
return
-
1
;
atkbd
->
id
=
(
param
[
0
]
<<
8
)
|
param
[
1
];
/*
*
Set the LEDs to a defined state
.
*
Enable the keyboard to receive keystrokes
.
*/
param
[
0
]
=
0
;
if
(
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETLEDS
))
if
(
atkbd_command
(
atkbd
,
NULL
,
ATKBD_CMD_ENABLE
))
{
printk
(
KERN_ERR
"atkbd.c: Failed to enable keyboard on %s
\n
"
,
atkbd
->
serio
->
phys
);
return
-
1
;
}
return
0
;
}
/*
* Disable autorepeat. We don't need it, as we do it in software anyway,
* because that way can get faster repeat, and have less system load (less
* accesses to the slow ISA hardware). If this fails, we don't care, and will
* just ignore the repeated keys.
*
* This command is for scancode set 3 only.
*/
static
void
atkbd_disable_autorepeat
(
struct
atkbd
*
atkbd
)
{
atkbd_command
(
atkbd
,
NULL
,
ATKBD_CMD_SETALL_MB
);
}
/*
* atkbd_cleanup() restores the keyboard state so that BIOS is happy after a
* reboot.
...
...
@@ -485,7 +496,7 @@ static void atkbd_disconnect(struct serio *serio)
}
/*
* atkbd_connect() is called when the serio module finds an interface
* atkbd_connect() is called when the serio module finds an
d
interface
* that isn't handled yet by an appropriate device driver. We check if
* there is an AT keyboard out there and if yes, we register ourselves
* to the input module.
...
...
@@ -513,6 +524,9 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd
->
dev
.
ledbit
[
0
]
=
BIT
(
LED_NUML
)
|
BIT
(
LED_CAPSL
)
|
BIT
(
LED_SCROLLL
);
}
else
atkbd
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_REP
);
atkbd
->
dev
.
rep
[
REP_DELAY
]
=
HZ
/
4
+
HZ
/
50
;
atkbd
->
dev
.
rep
[
REP_PERIOD
]
=
HZ
/
33
;
atkbd
->
serio
=
serio
;
init_input_dev
(
&
atkbd
->
dev
);
...
...
@@ -525,6 +539,10 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
serio
->
private
=
atkbd
;
init_timer
(
&
atkbd
->
timer
);
atkbd
->
timer
.
data
=
(
long
)
atkbd
;
atkbd
->
timer
.
function
=
atkbd_force_key_up
;
if
(
serio_open
(
serio
,
dev
))
{
kfree
(
atkbd
);
return
;
...
...
@@ -539,9 +557,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
}
atkbd
->
set
=
atkbd_set_3
(
atkbd
);
if
(
atkbd
->
set
==
3
)
atkbd_disable_autorepeat
(
atkbd
);
atkbd_enable
(
atkbd
);
}
else
{
atkbd
->
set
=
2
;
atkbd
->
id
=
0xab00
;
...
...
drivers/input/mouse/Kconfig
View file @
aac0e012
...
...
@@ -19,9 +19,7 @@ config MOUSE_PS2
Say Y here if you have a PS/2 mouse connected to your system. This
includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
mice with wheels and extra buttons, Microsoft, Logitech or Genius
compatible. Support for Synaptics TouchPads is also included.
For Synaptics TouchPad support in XFree86 you'll need this XFree86
driver: http://w1.894.telia.com/~u89404340/touchpad/index.html
compatible.
If unsure, say Y.
...
...
@@ -30,6 +28,22 @@ config MOUSE_PS2
The module will be called psmouse. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config MOUSE_PS2_SYNAPTICS
bool "Synaptics TouchPad"
default n
depends on INPUT && INPUT_MOUSE && SERIO && MOUSE_PS2
---help---
Say Y here if you have a Synaptics TouchPad connected to your system.
This touchpad is found on many modern laptop computers.
Note that you also need a user space driver to interpret the data
generated by the kernel. A compatible driver for XFree86 is available
from http://w1.894.telia.com/~u89404340/touchpad/index.html
The gpm program is not yet able to interpret the data from this
driver, so if you need to use the touchpad in the console, you have to
say N for now.
config MOUSE_SERIAL
tristate "Serial mouse"
depends on INPUT && INPUT_MOUSE && SERIO
...
...
drivers/input/mouse/psmouse-base.c
View file @
aac0e012
...
...
@@ -17,6 +17,7 @@
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/pm.h>
#include "psmouse.h"
#include "synaptics.h"
#include "logips2pp.h"
...
...
@@ -29,6 +30,8 @@ MODULE_PARM(psmouse_resolution, "i");
MODULE_PARM_DESC
(
psmouse_resolution
,
"Resolution, in dpi."
);
MODULE_PARM
(
psmouse_smartscroll
,
"i"
);
MODULE_PARM_DESC
(
psmouse_smartscroll
,
"Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."
);
MODULE_PARM
(
psmouse_resetafter
,
"i"
);
MODULE_PARM_DESC
(
psmouse_resetafter
,
"Reset Synaptics Touchpad after so many bad packets (0 = never)."
);
MODULE_LICENSE
(
"GPL"
);
#define PSMOUSE_LOGITECH_SMARTSCROLL 1
...
...
@@ -36,11 +39,12 @@ MODULE_LICENSE("GPL");
static
int
psmouse_noext
;
int
psmouse_resolution
;
int
psmouse_smartscroll
=
PSMOUSE_LOGITECH_SMARTSCROLL
;
unsigned
int
psmouse_resetafter
;
static
char
*
psmouse_protocols
[]
=
{
"None"
,
"PS/2"
,
"PS2++"
,
"PS2T++"
,
"GenPS/2"
,
"ImPS/2"
,
"ImExPS/2"
,
"Syn
aptics
"
};
static
char
*
psmouse_protocols
[]
=
{
"None"
,
"PS/2"
,
"PS2++"
,
"PS2T++"
,
"GenPS/2"
,
"ImPS/2"
,
"ImExPS/2"
,
"Syn
PS/2
"
};
/*
* psmouse_process_packet() anlyzes the PS/2 mouse packet contents and
* psmouse_process_packet() an
a
lyzes the PS/2 mouse packet contents and
* reports relevant events to the input module.
*/
...
...
@@ -108,6 +112,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
{
struct
psmouse
*
psmouse
=
serio
->
private
;
if
(
psmouse
->
state
==
PSMOUSE_IGNORE
)
goto
out
;
if
(
psmouse
->
acking
)
{
switch
(
data
)
{
case
PSMOUSE_RET_ACK
:
...
...
@@ -132,20 +139,35 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
}
if
(
psmouse
->
pktcnt
&&
time_after
(
jiffies
,
psmouse
->
last
+
HZ
/
2
))
{
printk
(
KERN_WARNING
"psmouse.c: Lost synchronization, throwing %d bytes away.
\n
"
,
psmouse
->
pktcnt
);
printk
(
KERN_WARNING
"psmouse.c: %s at %s lost synchronization, throwing %d bytes away.
\n
"
,
psmouse
->
name
,
psmouse
->
phys
,
psmouse
->
pktcnt
);
psmouse
->
pktcnt
=
0
;
}
psmouse
->
last
=
jiffies
;
psmouse
->
packet
[
psmouse
->
pktcnt
++
]
=
data
;
if
(
psmouse
->
pktcnt
==
3
+
(
psmouse
->
type
>=
PSMOUSE_GENPS
))
{
psmouse_process_packet
(
psmouse
,
regs
);
psmouse
->
pktcnt
=
0
;
goto
out
;
if
(
psmouse
->
packet
[
0
]
==
PSMOUSE_RET_BAT
)
{
if
(
psmouse
->
pktcnt
==
1
)
goto
out
;
if
(
psmouse
->
pktcnt
==
2
)
{
if
(
psmouse
->
packet
[
1
]
==
PSMOUSE_RET_ID
)
{
psmouse
->
state
=
PSMOUSE_IGNORE
;
serio_rescan
(
serio
);
goto
out
;
}
if
(
psmouse
->
type
==
PSMOUSE_SYNAPTICS
)
{
/* neither 0xAA nor 0x00 are valid first bytes
* for a packet in absolute mode
*/
psmouse
->
pktcnt
=
0
;
goto
out
;
}
}
}
if
(
psmouse
->
pktcnt
==
1
&&
psmouse
->
type
==
PSMOUSE_SYNAPTICS
)
{
if
(
psmouse
->
type
==
PSMOUSE_SYNAPTICS
)
{
/*
* The synaptics driver has its own resync logic,
* so it needs to receive all bytes one at a time.
...
...
@@ -155,8 +177,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
goto
out
;
}
if
(
psmouse
->
pktcnt
==
1
&&
psmouse
->
packet
[
0
]
==
PSMOUSE_RET_BAT
)
{
serio_rescan
(
serio
);
if
(
psmouse
->
pktcnt
==
3
+
(
psmouse
->
type
>=
PSMOUSE_GENPS
))
{
psmouse_process_packet
(
psmouse
,
regs
);
psmouse
->
pktcnt
=
0
;
goto
out
;
}
out:
...
...
@@ -200,7 +223,7 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
psmouse
->
cmdcnt
=
receive
;
if
(
command
==
PSMOUSE_CMD_RESET_BAT
)
timeout
=
2000000
;
/* 2
sec */
timeout
=
4000000
;
/* 4
sec */
if
(
command
&
0xff
)
if
(
psmouse_sendbyte
(
psmouse
,
command
&
0xff
))
...
...
@@ -227,7 +250,7 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
for
(
i
=
0
;
i
<
receive
;
i
++
)
param
[
i
]
=
psmouse
->
cmdbuf
[(
receive
-
1
)
-
i
];
if
(
psmouse
->
cmdcnt
)
if
(
psmouse
->
cmdcnt
)
return
(
psmouse
->
cmdcnt
=
0
)
-
1
;
return
0
;
...
...
@@ -450,14 +473,18 @@ static void psmouse_initialize(struct psmouse *psmouse)
*/
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETSTREAM
);
}
/*
*
Last, we enable the mouse so that we get
reports from it.
*
psmouse_activate() enables the mouse so that we get motion
reports from it.
*/
static
void
psmouse_activate
(
struct
psmouse
*
psmouse
)
{
if
(
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_ENABLE
))
printk
(
KERN_WARNING
"psmouse.c: Failed to enable mouse on %s
\n
"
,
psmouse
->
serio
->
phys
);
psmouse
->
state
=
PSMOUSE_ACTIVATED
;
}
/*
...
...
@@ -478,12 +505,38 @@ static void psmouse_cleanup(struct serio *serio)
static
void
psmouse_disconnect
(
struct
serio
*
serio
)
{
struct
psmouse
*
psmouse
=
serio
->
private
;
psmouse
->
state
=
PSMOUSE_IGNORE
;
synaptics_disconnect
(
psmouse
);
input_unregister_device
(
&
psmouse
->
dev
);
serio_close
(
serio
);
synaptics_disconnect
(
psmouse
);
kfree
(
psmouse
);
}
/*
* Reinitialize mouse hardware after software suspend.
*/
static
int
psmouse_pm_callback
(
struct
pm_dev
*
dev
,
pm_request_t
request
,
void
*
data
)
{
struct
psmouse
*
psmouse
=
dev
->
data
;
struct
serio_dev
*
ser_dev
=
psmouse
->
serio
->
dev
;
synaptics_disconnect
(
psmouse
);
/* We need to reopen the serio port to reinitialize the i8042 controller */
serio_close
(
psmouse
->
serio
);
serio_open
(
psmouse
->
serio
,
ser_dev
);
/* Probe and re-initialize the mouse */
psmouse_probe
(
psmouse
);
psmouse_initialize
(
psmouse
);
synaptics_pt_init
(
psmouse
);
psmouse_activate
(
psmouse
);
return
0
;
}
/*
* psmouse_connect() is a callback from the serio module when
* an unhandled serio port is found.
...
...
@@ -492,8 +545,10 @@ static void psmouse_disconnect(struct serio *serio)
static
void
psmouse_connect
(
struct
serio
*
serio
,
struct
serio_dev
*
dev
)
{
struct
psmouse
*
psmouse
;
struct
pm_dev
*
pmdev
;
if
((
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_8042
)
if
((
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_8042
&&
(
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_PS_PSTHRU
)
return
;
if
(
!
(
psmouse
=
kmalloc
(
sizeof
(
struct
psmouse
),
GFP_KERNEL
)))
...
...
@@ -506,6 +561,7 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse
->
dev
.
keybit
[
LONG
(
BTN_MOUSE
)]
=
BIT
(
BTN_LEFT
)
|
BIT
(
BTN_MIDDLE
)
|
BIT
(
BTN_RIGHT
);
psmouse
->
dev
.
relbit
[
0
]
=
BIT
(
REL_X
)
|
BIT
(
REL_Y
);
psmouse
->
state
=
PSMOUSE_NEW_DEVICE
;
psmouse
->
serio
=
serio
;
psmouse
->
dev
.
private
=
psmouse
;
...
...
@@ -522,6 +578,12 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
return
;
}
pmdev
=
pm_register
(
PM_SYS_DEV
,
PM_SYS_UNKNOWN
,
psmouse_pm_callback
);
if
(
pmdev
)
{
psmouse
->
dev
.
pm_dev
=
pmdev
;
pmdev
->
data
=
psmouse
;
}
sprintf
(
psmouse
->
devname
,
"%s %s %s"
,
psmouse_protocols
[
psmouse
->
type
],
psmouse
->
vendor
,
psmouse
->
name
);
sprintf
(
psmouse
->
phys
,
"%s/input0"
,
...
...
@@ -539,6 +601,10 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
psmouse
->
devname
,
serio
->
phys
);
psmouse_initialize
(
psmouse
);
synaptics_pt_init
(
psmouse
);
psmouse_activate
(
psmouse
);
}
static
struct
serio_dev
psmouse_dev
=
{
...
...
@@ -567,9 +633,16 @@ static int __init psmouse_smartscroll_setup(char *str)
return
1
;
}
static
int
__init
psmouse_resetafter_setup
(
char
*
str
)
{
get_option
(
&
str
,
&
psmouse_resetafter
);
return
1
;
}
__setup
(
"psmouse_noext"
,
psmouse_noext_setup
);
__setup
(
"psmouse_resolution="
,
psmouse_resolution_setup
);
__setup
(
"psmouse_smartscroll="
,
psmouse_smartscroll_setup
);
__setup
(
"psmouse_resetafter="
,
psmouse_resetafter_setup
);
#endif
...
...
drivers/input/mouse/psmouse.h
View file @
aac0e012
...
...
@@ -13,9 +13,15 @@
#define PSMOUSE_CMD_RESET_BAT 0x02ff
#define PSMOUSE_RET_BAT 0xaa
#define PSMOUSE_RET_ID 0x00
#define PSMOUSE_RET_ACK 0xfa
#define PSMOUSE_RET_NAK 0xfe
/* psmouse states */
#define PSMOUSE_NEW_DEVICE 0
#define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2
struct
psmouse
{
void
*
private
;
struct
input_dev
dev
;
...
...
@@ -29,6 +35,7 @@ struct psmouse {
unsigned
char
type
;
unsigned
char
model
;
unsigned
long
last
;
unsigned
char
state
;
char
acking
;
volatile
char
ack
;
char
error
;
...
...
@@ -36,16 +43,17 @@ struct psmouse {
char
phys
[
32
];
};
#define PSMOUSE_PS2 1
#define PSMOUSE_PS2PP 2
#define PSMOUSE_PS2TPP 3
#define PSMOUSE_GENPS 4
#define PSMOUSE_IMPS 5
#define PSMOUSE_IMEX 6
#define PSMOUSE_SYNAPTICS 7
#define PSMOUSE_PS2
1
#define PSMOUSE_PS2PP
2
#define PSMOUSE_PS2TPP
3
#define PSMOUSE_GENPS
4
#define PSMOUSE_IMPS
5
#define PSMOUSE_IMEX
6
#define PSMOUSE_SYNAPTICS
7
int
psmouse_command
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
,
int
command
);
extern
int
psmouse_smartscroll
;
extern
unsigned
int
psmouse_resetafter
;
#endif
/* _PSMOUSE_H */
drivers/input/mouse/synaptics.c
View file @
aac0e012
/*
* Synaptics TouchPad PS/2 mouse driver
*
* 2003 Dmitry Torokhov <dtor@mail.ru>
* Added support for pass-through port
*
* 2003 Peter Osterlund <petero2@telia.com>
* Ported to 2.5 input device infrastructure.
*
...
...
@@ -21,6 +24,7 @@
#include <linux/module.h>
#include <linux/input.h>
#include <linux/serio.h>
#include "psmouse.h"
#include "synaptics.h"
...
...
@@ -71,7 +75,7 @@ static int synaptics_set_mode(struct psmouse *psmouse, unsigned char mode)
if
(
synaptics_special_cmd
(
psmouse
,
mode
))
return
-
1
;
param
[
0
]
=
0x14
;
param
[
0
]
=
SYN_PS_SET_MODE2
;
if
(
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
))
return
-
1
;
return
0
;
...
...
@@ -83,7 +87,7 @@ static int synaptics_reset(struct psmouse *psmouse)
if
(
psmouse_command
(
psmouse
,
r
,
PSMOUSE_CMD_RESET_BAT
))
return
-
1
;
if
(
r
[
0
]
==
0xAA
&&
r
[
1
]
==
0x00
)
if
(
r
[
0
]
==
PSMOUSE_RET_BAT
&&
r
[
1
]
==
PSMOUSE_RET_ID
)
return
0
;
return
-
1
;
}
...
...
@@ -106,16 +110,25 @@ static int synaptics_model_id(struct psmouse *psmouse, unsigned long int *model_
* Read the capability-bits from the touchpad
* see also the SYN_CAP_* macros
*/
static
int
synaptics_capability
(
struct
psmouse
*
psmouse
,
unsigned
long
int
*
capability
)
static
int
synaptics_capability
(
struct
psmouse
*
psmouse
,
unsigned
long
int
*
capability
,
unsigned
long
int
*
ext_cap
)
{
unsigned
char
cap
[
3
];
if
(
synaptics_send_cmd
(
psmouse
,
SYN_QUE_CAPABILITIES
,
cap
))
return
-
1
;
*
capability
=
(
cap
[
0
]
<<
16
)
|
(
cap
[
1
]
<<
8
)
|
cap
[
2
];
if
(
SYN_CAP_VALID
(
*
capability
))
return
0
;
return
-
1
;
*
ext_cap
=
0
;
if
(
!
SYN_CAP_VALID
(
*
capability
))
return
-
1
;
if
(
SYN_EXT_CAP_REQUESTS
(
*
capability
))
{
if
(
synaptics_send_cmd
(
psmouse
,
SYN_QUE_EXT_CAPAB
,
cap
))
{
printk
(
KERN_ERR
"Synaptics claims to have extended capabilities,"
" but I'm not able to read them."
);
}
else
*
ext_cap
=
(
cap
[
0
]
<<
16
)
|
(
cap
[
1
]
<<
8
)
|
cap
[
2
];
}
return
0
;
}
/*
...
...
@@ -134,19 +147,11 @@ static int synaptics_identify(struct psmouse *psmouse, unsigned long int *ident)
return
-
1
;
}
static
int
synaptics_enable_device
(
struct
psmouse
*
psmouse
)
{
if
(
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_ENABLE
))
return
-
1
;
return
0
;
}
static
void
print_ident
(
struct
synaptics_data
*
priv
)
{
printk
(
KERN_INFO
"Synaptics Touchpad, model: %ld
\n
"
,
SYN_ID_MODEL
(
priv
->
identity
));
printk
(
KERN_INFO
" Firware: %ld.%ld
\n
"
,
SYN_ID_MAJOR
(
priv
->
identity
),
printk
(
KERN_INFO
" Fir
m
ware: %ld.%ld
\n
"
,
SYN_ID_MAJOR
(
priv
->
identity
),
SYN_ID_MINOR
(
priv
->
identity
));
if
(
SYN_MODEL_ROT180
(
priv
->
model_id
))
printk
(
KERN_INFO
" 180 degree mounted touchpad
\n
"
);
if
(
SYN_MODEL_PORTRAIT
(
priv
->
model_id
))
...
...
@@ -159,12 +164,17 @@ static void print_ident(struct synaptics_data *priv)
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
))
{
printk
(
KERN_INFO
" Touchpad has extended capability bits
\n
"
);
if
(
SYN_CAP_FOUR_BUTTON
(
priv
->
capabilities
))
if
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
))
printk
(
KERN_INFO
" -> %d multi-buttons, i.e. besides standard buttons
\n
"
,
(
int
)(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)));
else
if
(
SYN_CAP_FOUR_BUTTON
(
priv
->
capabilities
))
printk
(
KERN_INFO
" -> four buttons
\n
"
);
if
(
SYN_CAP_MULTIFINGER
(
priv
->
capabilities
))
printk
(
KERN_INFO
" -> multifinger detection
\n
"
);
if
(
SYN_CAP_PALMDETECT
(
priv
->
capabilities
))
printk
(
KERN_INFO
" -> palm detection
\n
"
);
if
(
SYN_CAP_PASS_THROUGH
(
priv
->
capabilities
))
printk
(
KERN_INFO
" -> pass-through port
\n
"
);
}
}
...
...
@@ -172,6 +182,7 @@ static int query_hardware(struct psmouse *psmouse)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
int
retries
=
0
;
int
mode
;
while
((
retries
++
<
3
)
&&
synaptics_reset
(
psmouse
))
printk
(
KERN_ERR
"synaptics reset failed
\n
"
);
...
...
@@ -180,17 +191,107 @@ static int query_hardware(struct psmouse *psmouse)
return
-
1
;
if
(
synaptics_model_id
(
psmouse
,
&
priv
->
model_id
))
return
-
1
;
if
(
synaptics_capability
(
psmouse
,
&
priv
->
capabilities
))
if
(
synaptics_capability
(
psmouse
,
&
priv
->
capabilities
,
&
priv
->
ext_cap
))
return
-
1
;
if
(
synaptics_set_mode
(
psmouse
,
(
SYN_BIT_ABSOLUTE_MODE
|
SYN_BIT_HIGH_RATE
|
SYN_BIT_DISABLE_GESTURE
|
SYN_BIT_W_MODE
)))
mode
=
SYN_BIT_ABSOLUTE_MODE
|
SYN_BIT_HIGH_RATE
;
if
(
SYN_ID_MAJOR
(
priv
->
identity
)
>=
4
)
mode
|=
SYN_BIT_DISABLE_GESTURE
;
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
))
mode
|=
SYN_BIT_W_MODE
;
if
(
synaptics_set_mode
(
psmouse
,
mode
))
return
-
1
;
synaptics_enable_device
(
psmouse
);
return
0
;
}
print_ident
(
priv
);
/*****************************************************************************
* Synaptics pass-through PS/2 port support
****************************************************************************/
static
int
synaptics_pt_open
(
struct
serio
*
port
)
{
return
0
;
}
static
void
synaptics_pt_close
(
struct
serio
*
port
)
{
}
static
int
synaptics_pt_write
(
struct
serio
*
port
,
unsigned
char
c
)
{
struct
psmouse
*
parent
=
port
->
driver
;
char
rate_param
=
SYN_PS_CLIENT_CMD
;
/* indicates that we want pass-through port */
if
(
synaptics_special_cmd
(
parent
,
c
))
return
-
1
;
if
(
psmouse_command
(
parent
,
&
rate_param
,
PSMOUSE_CMD_SETRATE
))
return
-
1
;
return
0
;
}
static
inline
int
synaptics_is_pt_packet
(
unsigned
char
*
buf
)
{
return
(
buf
[
0
]
&
0xFC
)
==
0x84
&&
(
buf
[
3
]
&
0xCC
)
==
0xC4
;
}
static
void
synaptics_pass_pt_packet
(
struct
serio
*
ptport
,
unsigned
char
*
packet
)
{
struct
psmouse
*
child
=
ptport
->
private
;
if
(
child
)
{
if
(
child
->
state
==
PSMOUSE_ACTIVATED
)
{
serio_interrupt
(
ptport
,
packet
[
1
],
0
,
NULL
);
serio_interrupt
(
ptport
,
packet
[
4
],
0
,
NULL
);
serio_interrupt
(
ptport
,
packet
[
5
],
0
,
NULL
);
if
(
child
->
type
>=
PSMOUSE_GENPS
)
serio_interrupt
(
ptport
,
packet
[
2
],
0
,
NULL
);
}
else
if
(
child
->
state
!=
PSMOUSE_IGNORE
)
{
serio_interrupt
(
ptport
,
packet
[
1
],
0
,
NULL
);
}
}
}
int
synaptics_pt_init
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
struct
serio
*
port
;
struct
psmouse
*
child
;
if
(
psmouse
->
type
!=
PSMOUSE_SYNAPTICS
)
return
-
1
;
if
(
!
SYN_CAP_EXTENDED
(
priv
->
capabilities
))
return
-
1
;
if
(
!
SYN_CAP_PASS_THROUGH
(
priv
->
capabilities
))
return
-
1
;
priv
->
ptport
=
port
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
!
port
)
{
printk
(
KERN_ERR
"synaptics: not enough memory to allocate serio port
\n
"
);
return
-
1
;
}
memset
(
port
,
0
,
sizeof
(
struct
serio
));
port
->
type
=
SERIO_PS_PSTHRU
;
port
->
name
=
"Synaptics pass-through"
;
port
->
phys
=
"synaptics-pt/serio0"
;
port
->
write
=
synaptics_pt_write
;
port
->
open
=
synaptics_pt_open
;
port
->
close
=
synaptics_pt_close
;
port
->
driver
=
psmouse
;
printk
(
KERN_INFO
"serio: %s port at %s
\n
"
,
port
->
name
,
psmouse
->
phys
);
serio_register_slave_port
(
port
);
/* adjust the touchpad to child's choice of protocol */
child
=
port
->
private
;
if
(
child
&&
child
->
type
>=
PSMOUSE_GENPS
)
{
if
(
synaptics_set_mode
(
psmouse
,
(
SYN_BIT_ABSOLUTE_MODE
|
SYN_BIT_HIGH_RATE
|
SYN_BIT_DISABLE_GESTURE
|
SYN_BIT_FOUR_BYTE_CLIENT
|
SYN_BIT_W_MODE
)))
printk
(
KERN_INFO
"synaptics: failed to enable 4-byte guest protocol
\n
"
);
}
return
0
;
}
...
...
@@ -213,22 +314,27 @@ int synaptics_init(struct psmouse *psmouse)
{
struct
synaptics_data
*
priv
;
#ifndef CONFIG_MOUSE_PS2_SYNAPTICS
return
-
1
;
#endif
psmouse
->
private
=
priv
=
kmalloc
(
sizeof
(
struct
synaptics_data
),
GFP_KERNEL
);
if
(
!
priv
)
return
-
1
;
memset
(
priv
,
0
,
sizeof
(
struct
synaptics_data
));
priv
->
inSync
=
1
;
priv
->
out_of_sync
=
0
;
if
(
query_hardware
(
psmouse
))
{
printk
(
KERN_ERR
"Unable to query/initialize Synaptics hardware.
\n
"
);
goto
init_fail
;
}
print_ident
(
priv
);
/*
* The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
* which says that they should be valid regardless of the actual size of
* the sens
e
r.
* the sens
o
r.
*/
set_bit
(
EV_ABS
,
psmouse
->
dev
.
evbit
);
set_abs_params
(
&
psmouse
->
dev
,
ABS_X
,
1472
,
5472
,
0
,
0
);
...
...
@@ -243,7 +349,24 @@ int synaptics_init(struct psmouse *psmouse)
set_bit
(
BTN_RIGHT
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_FORWARD
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_BACK
,
psmouse
->
dev
.
keybit
);
if
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
))
switch
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
&
~
0x01
)
{
default:
printk
(
KERN_ERR
"This touchpad reports more than 8 multi-buttons, don't know how to handle.
\n
"
);
case
8
:
set_bit
(
BTN_7
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_6
,
psmouse
->
dev
.
keybit
);
case
6
:
set_bit
(
BTN_5
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_4
,
psmouse
->
dev
.
keybit
);
case
4
:
set_bit
(
BTN_3
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_2
,
psmouse
->
dev
.
keybit
);
case
2
:
set_bit
(
BTN_1
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_0
,
psmouse
->
dev
.
keybit
);
break
;
}
clear_bit
(
EV_REL
,
psmouse
->
dev
.
evbit
);
clear_bit
(
REL_X
,
psmouse
->
dev
.
relbit
);
clear_bit
(
REL_Y
,
psmouse
->
dev
.
relbit
);
...
...
@@ -259,42 +382,85 @@ void synaptics_disconnect(struct psmouse *psmouse)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
kfree
(
priv
);
if
(
psmouse
->
type
==
PSMOUSE_SYNAPTICS
&&
priv
)
{
synaptics_set_mode
(
psmouse
,
0
);
if
(
priv
->
ptport
)
{
serio_unregister_slave_port
(
priv
->
ptport
);
kfree
(
priv
->
ptport
);
}
kfree
(
priv
);
}
}
/*****************************************************************************
* Functions to interpret the absolute mode packets
****************************************************************************/
static
void
synaptics_parse_hw_state
(
struct
synaptics_data
*
priv
,
struct
synaptics_hw_state
*
hw
)
static
void
synaptics_parse_hw_state
(
unsigned
char
buf
[],
struct
synaptics_data
*
priv
,
struct
synaptics_hw_state
*
hw
)
{
unsigned
char
*
buf
=
priv
->
proto_buf
;
hw
->
x
=
(((
buf
[
3
]
&
0x10
)
<<
8
)
|
((
buf
[
1
]
&
0x0f
)
<<
8
)
|
buf
[
4
]);
hw
->
y
=
(((
buf
[
3
]
&
0x20
)
<<
7
)
|
((
buf
[
1
]
&
0xf0
)
<<
4
)
|
buf
[
5
]);
hw
->
z
=
buf
[
2
];
hw
->
w
=
(((
buf
[
0
]
&
0x30
)
>>
2
)
|
((
buf
[
0
]
&
0x04
)
>>
1
)
|
((
buf
[
3
]
&
0x04
)
>>
2
));
hw
->
left
=
(
buf
[
0
]
&
0x01
)
?
1
:
0
;
hw
->
right
=
(
buf
[
0
]
&
0x2
)
?
1
:
0
;
hw
->
up
=
0
;
hw
->
down
=
0
;
hw
->
b0
=
0
;
hw
->
b1
=
0
;
hw
->
b2
=
0
;
hw
->
b3
=
0
;
hw
->
b4
=
0
;
hw
->
b5
=
0
;
hw
->
b6
=
0
;
hw
->
b7
=
0
;
if
(
SYN_MODEL_NEWABS
(
priv
->
model_id
))
{
hw
->
x
=
(((
buf
[
3
]
&
0x10
)
<<
8
)
|
((
buf
[
1
]
&
0x0f
)
<<
8
)
|
buf
[
4
]);
hw
->
y
=
(((
buf
[
3
]
&
0x20
)
<<
7
)
|
((
buf
[
1
]
&
0xf0
)
<<
4
)
|
buf
[
5
]);
hw
->
z
=
buf
[
2
];
hw
->
w
=
(((
buf
[
0
]
&
0x30
)
>>
2
)
|
((
buf
[
0
]
&
0x04
)
>>
1
)
|
((
buf
[
3
]
&
0x04
)
>>
2
));
hw
->
left
=
(
buf
[
0
]
&
0x01
)
?
1
:
0
;
hw
->
right
=
(
buf
[
0
]
&
0x02
)
?
1
:
0
;
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
)
&&
(
SYN_CAP_FOUR_BUTTON
(
priv
->
capabilities
)))
{
hw
->
up
=
((
buf
[
3
]
&
0x01
))
?
1
:
0
;
if
(
hw
->
left
)
hw
->
up
=
!
hw
->
up
;
hw
->
down
=
((
buf
[
3
]
&
0x02
))
?
1
:
0
;
if
(
hw
->
right
)
hw
->
down
=
!
hw
->
down
;
}
if
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
&&
((
buf
[
3
]
&
2
)
?
!
hw
->
right
:
hw
->
right
))
{
switch
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
&
~
0x01
)
{
default:
;
/* we did comment while initialising... */
case
8
:
hw
->
b7
=
((
buf
[
5
]
&
0x08
))
?
1
:
0
;
hw
->
b6
=
((
buf
[
4
]
&
0x08
))
?
1
:
0
;
case
6
:
hw
->
b5
=
((
buf
[
5
]
&
0x04
))
?
1
:
0
;
hw
->
b4
=
((
buf
[
4
]
&
0x04
))
?
1
:
0
;
case
4
:
hw
->
b3
=
((
buf
[
5
]
&
0x02
))
?
1
:
0
;
hw
->
b2
=
((
buf
[
4
]
&
0x02
))
?
1
:
0
;
case
2
:
hw
->
b1
=
((
buf
[
5
]
&
0x01
))
?
1
:
0
;
hw
->
b0
=
((
buf
[
4
]
&
0x01
))
?
1
:
0
;
}
}
}
else
{
hw
->
x
=
(((
buf
[
1
]
&
0x1f
)
<<
8
)
|
buf
[
2
]);
hw
->
y
=
(((
buf
[
4
]
&
0x1f
)
<<
8
)
|
buf
[
5
]);
hw
->
z
=
(((
buf
[
0
]
&
0x30
)
<<
2
)
|
(
buf
[
3
]
&
0x3F
));
hw
->
w
=
(((
buf
[
1
]
&
0x80
)
>>
4
)
|
((
buf
[
0
]
&
0x04
)
>>
1
));
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
)
&&
(
SYN_CAP_FOUR_BUTTON
(
priv
->
capabilities
)))
{
hw
->
up
=
((
buf
[
3
]
&
0x01
))
?
1
:
0
;
if
(
hw
->
left
)
hw
->
up
=
!
hw
->
up
;
hw
->
down
=
((
buf
[
3
]
&
0x02
))
?
1
:
0
;
if
(
hw
->
right
)
hw
->
down
=
!
hw
->
down
;
hw
->
left
=
(
buf
[
0
]
&
0x01
)
?
1
:
0
;
hw
->
right
=
(
buf
[
0
]
&
0x02
)
?
1
:
0
;
}
}
...
...
@@ -307,7 +473,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
struct
synaptics_data
*
priv
=
psmouse
->
private
;
struct
synaptics_hw_state
hw
;
synaptics_parse_hw_state
(
priv
,
&
hw
);
synaptics_parse_hw_state
(
p
smouse
->
packet
,
p
riv
,
&
hw
);
if
(
hw
.
z
>
0
)
{
int
w_ok
=
0
;
...
...
@@ -347,7 +513,24 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_report_key
(
dev
,
BTN_RIGHT
,
hw
.
right
);
input_report_key
(
dev
,
BTN_FORWARD
,
hw
.
up
);
input_report_key
(
dev
,
BTN_BACK
,
hw
.
down
);
if
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
))
switch
(
SYN_CAP_MULTI_BUTTON_NO
(
priv
->
ext_cap
)
&
~
0x01
)
{
default:
;
/* we did comment while initialising... */
case
8
:
input_report_key
(
dev
,
BTN_7
,
hw
.
b7
);
input_report_key
(
dev
,
BTN_6
,
hw
.
b6
);
case
6
:
input_report_key
(
dev
,
BTN_5
,
hw
.
b5
);
input_report_key
(
dev
,
BTN_4
,
hw
.
b4
);
case
4
:
input_report_key
(
dev
,
BTN_3
,
hw
.
b3
);
input_report_key
(
dev
,
BTN_2
,
hw
.
b2
);
case
2
:
input_report_key
(
dev
,
BTN_1
,
hw
.
b1
);
input_report_key
(
dev
,
BTN_0
,
hw
.
b0
);
break
;
}
input_sync
(
dev
);
}
...
...
@@ -355,35 +538,59 @@ void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
struct
input_dev
*
dev
=
&
psmouse
->
dev
;
struct
synaptics_data
*
priv
=
psmouse
->
private
;
unsigned
char
*
pBuf
=
priv
->
proto_buf
;
unsigned
char
u
=
psmouse
->
packet
[
0
]
;
unsigned
char
data
=
psmouse
->
packet
[
psmouse
->
pktcnt
-
1
]
;
int
newabs
=
SYN_MODEL_NEWABS
(
priv
->
model_id
)
;
input_regs
(
dev
,
regs
);
pBuf
[
priv
->
proto_buf_tail
++
]
=
u
;
/* check first byte */
if
((
priv
->
proto_buf_tail
==
1
)
&&
((
u
&
0xC8
)
!=
0x80
))
{
priv
->
inSync
=
0
;
priv
->
proto_buf_tail
=
0
;
printk
(
KERN_WARNING
"Synaptics driver lost sync at 1st byte
\n
"
);
return
;
}
switch
(
psmouse
->
pktcnt
)
{
case
1
:
if
(
newabs
?
((
data
&
0xC8
)
!=
0x80
)
:
((
data
&
0xC0
)
!=
0xC0
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at 1st byte
\n
"
);
goto
bad_sync
;
}
break
;
case
2
:
if
(
!
newabs
&&
((
data
&
0x60
)
!=
0x00
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at 2nd byte
\n
"
);
goto
bad_sync
;
}
break
;
case
4
:
if
(
newabs
?
((
data
&
0xC8
)
!=
0xC0
)
:
((
data
&
0xC0
)
!=
0x80
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at 4th byte
\n
"
);
goto
bad_sync
;
}
break
;
case
5
:
if
(
!
newabs
&&
((
data
&
0x60
)
!=
0x00
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at 5th byte
\n
"
);
goto
bad_sync
;
}
break
;
default:
if
(
psmouse
->
pktcnt
>=
6
)
{
/* Full packet received */
if
(
priv
->
out_of_sync
)
{
priv
->
out_of_sync
=
0
;
printk
(
KERN_NOTICE
"Synaptics driver resynced.
\n
"
);
}
/* check 4th byte */
if
((
priv
->
proto_buf_tail
==
4
)
&&
((
u
&
0xc8
)
!=
0xc0
))
{
priv
->
inSync
=
0
;
priv
->
proto_buf_tail
=
0
;
printk
(
KERN_WARNING
"Synaptics driver lost sync at 4th byte
\n
"
);
return
;
}
if
(
priv
->
ptport
&&
synaptics_is_pt_packet
(
psmouse
->
packet
))
synaptics_pass_pt_packet
(
priv
->
ptport
,
psmouse
->
packet
);
else
synaptics_process_packet
(
psmouse
);
if
(
priv
->
proto_buf_tail
>=
6
)
{
/* Full packet received */
if
(
!
priv
->
inSync
)
{
priv
->
inSync
=
1
;
printk
(
KERN_NOTICE
"Synaptics driver resynced.
\n
"
);
psmouse
->
pktcnt
=
0
;
}
synaptics_process_packet
(
psmouse
);
priv
->
proto_buf_tail
=
0
;
break
;
}
return
;
bad_sync:
priv
->
out_of_sync
++
;
psmouse
->
pktcnt
=
0
;
if
(
psmouse_resetafter
>
0
&&
priv
->
out_of_sync
==
psmouse_resetafter
)
{
psmouse
->
state
=
PSMOUSE_IGNORE
;
serio_rescan
(
psmouse
->
serio
);
}
}
drivers/input/mouse/synaptics.h
View file @
aac0e012
...
...
@@ -12,6 +12,7 @@
extern
void
synaptics_process_byte
(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
);
extern
int
synaptics_init
(
struct
psmouse
*
psmouse
);
extern
int
synaptics_pt_init
(
struct
psmouse
*
psmouse
);
extern
void
synaptics_disconnect
(
struct
psmouse
*
psmouse
);
/* synaptics queries */
...
...
@@ -22,12 +23,14 @@ extern void synaptics_disconnect(struct psmouse *psmouse);
#define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06
#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07
#define SYN_QUE_RESOLUTION 0x08
#define SYN_QUE_EXT_CAPAB 0x09
/* synatics modes */
#define SYN_BIT_ABSOLUTE_MODE (1 << 7)
#define SYN_BIT_HIGH_RATE (1 << 6)
#define SYN_BIT_SLEEP_MODE (1 << 3)
#define SYN_BIT_DISABLE_GESTURE (1 << 2)
#define SYN_BIT_FOUR_BYTE_CLIENT (1 << 1)
#define SYN_BIT_W_MODE (1 << 0)
/* synaptics model ID bits */
...
...
@@ -42,11 +45,14 @@ extern void synaptics_disconnect(struct psmouse *psmouse);
/* synaptics capability bits */
#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23))
#define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7))
#define SYN_CAP_SLEEP(c) ((c) & (1 << 4))
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
#define SYN_EXT_CAP_REQUESTS(c) ((((c) & 0x700000) >> 20) == 1)
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
/* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
...
...
@@ -62,6 +68,10 @@ extern void synaptics_disconnect(struct psmouse *psmouse);
#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff)
#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47)
/* synaptics special commands */
#define SYN_PS_SET_MODE2 0x14
#define SYN_PS_CLIENT_CMD 0x28
/*
* A structure to describe the state of the touchpad hardware (buttons and pad)
*/
...
...
@@ -75,21 +85,28 @@ struct synaptics_hw_state {
int
right
;
int
up
;
int
down
;
int
b0
;
int
b1
;
int
b2
;
int
b3
;
int
b4
;
int
b5
;
int
b6
;
int
b7
;
};
struct
synaptics_data
{
/* Data read from the touchpad */
unsigned
long
int
model_id
;
/* Model-ID */
unsigned
long
int
capabilities
;
/* Capabilities */
unsigned
long
int
ext_cap
;
/* Extended Capabilities */
unsigned
long
int
identity
;
/* Identification */
/* Data for normal processing */
unsigned
char
proto_buf
[
6
];
/* Buffer for Packet */
unsigned
char
last_byte
;
/* last received byte */
int
inSync
;
/* Packets in sync */
int
proto_buf_tail
;
unsigned
int
out_of_sync
;
/* # of packets out of sync */
int
old_w
;
/* Previous w value */
struct
serio
*
ptport
;
/* pass-through port */
};
#endif
/* _SYNAPTICS_H */
drivers/input/serio/serio.c
View file @
aac0e012
...
...
@@ -49,7 +49,9 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL
(
serio_interrupt
);
EXPORT_SYMBOL
(
serio_register_port
);
EXPORT_SYMBOL
(
serio_register_slave_port
);
EXPORT_SYMBOL
(
serio_unregister_port
);
EXPORT_SYMBOL
(
serio_unregister_slave_port
);
EXPORT_SYMBOL
(
serio_register_device
);
EXPORT_SYMBOL
(
serio_unregister_device
);
EXPORT_SYMBOL
(
serio_open
);
...
...
@@ -166,6 +168,17 @@ void serio_register_port(struct serio *serio)
up
(
&
serio_sem
);
}
/*
* Same as serio_register_port but does not try to acquire serio_sem.
* Should be used when registering a serio from other input device's
* connect() function.
*/
void
serio_register_slave_port
(
struct
serio
*
serio
)
{
list_add_tail
(
&
serio
->
node
,
&
serio_list
);
serio_find_dev
(
serio
);
}
void
serio_unregister_port
(
struct
serio
*
serio
)
{
down
(
&
serio_sem
);
...
...
@@ -175,6 +188,18 @@ void serio_unregister_port(struct serio *serio)
up
(
&
serio_sem
);
}
/*
* Same as serio_unregister_port but does not try to acquire serio_sem.
* Should be used when unregistering a serio from other input device's
* disconnect() function.
*/
void
serio_unregister_slave_port
(
struct
serio
*
serio
)
{
list_del_init
(
&
serio
->
node
);
if
(
serio
->
dev
&&
serio
->
dev
->
disconnect
)
serio
->
dev
->
disconnect
(
serio
);
}
void
serio_register_device
(
struct
serio_dev
*
dev
)
{
struct
serio
*
serio
;
...
...
@@ -204,9 +229,11 @@ 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
)
{
if
(
serio
->
open
(
serio
))
return
-
1
;
serio
->
dev
=
dev
;
if
(
serio
->
open
(
serio
))
{
serio
->
dev
=
NULL
;
return
-
1
;
}
return
0
;
}
...
...
include/linux/input.h
View file @
aac0e012
...
...
@@ -751,7 +751,7 @@ struct ff_effect {
#define LONG(x) ((x)/BITS_PER_LONG)
#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
((dev->keycodesize ==
1
) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
((dev->keycodesize ==
2
) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
#define init_input_dev(dev) do { INIT_LIST_HEAD(&((dev)->h_list)); INIT_LIST_HEAD(&((dev)->node)); } while (0)
...
...
include/linux/serio.h
View file @
aac0e012
...
...
@@ -65,7 +65,9 @@ void serio_rescan(struct serio *serio);
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
);
void
serio_register_port
(
struct
serio
*
serio
);
void
serio_register_slave_port
(
struct
serio
*
serio
);
void
serio_unregister_port
(
struct
serio
*
serio
);
void
serio_unregister_slave_port
(
struct
serio
*
serio
);
void
serio_register_device
(
struct
serio_dev
*
dev
);
void
serio_unregister_device
(
struct
serio_dev
*
dev
);
...
...
@@ -104,6 +106,7 @@ static __inline__ void serio_cleanup(struct serio *serio)
#define SERIO_RS232 0x02000000UL
#define SERIO_HIL_MLC 0x03000000UL
#define SERIO_PC9800 0x04000000UL
#define SERIO_PS_PSTHRU 0x05000000UL
#define SERIO_PROTO 0xFFUL
#define SERIO_MSC 0x01
...
...
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