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
a76a8a35
Commit
a76a8a35
authored
Dec 29, 2003
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge redhat.com:/spare/repo/linux-2.5
into redhat.com:/spare/repo/libata-2.5
parents
d75f0d82
dbf8623b
Changes
24
Show whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
1007 additions
and
664 deletions
+1007
-664
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+2
-1
arch/i386/kernel/irq.c
arch/i386/kernel/irq.c
+14
-0
arch/i386/lib/usercopy.c
arch/i386/lib/usercopy.c
+3
-1
arch/i386/pci/irq.c
arch/i386/pci/irq.c
+1
-9
drivers/block/ll_rw_blk.c
drivers/block/ll_rw_blk.c
+1
-1
drivers/char/keyboard.c
drivers/char/keyboard.c
+21
-14
drivers/input/input.c
drivers/input/input.c
+8
-6
drivers/input/joydev.c
drivers/input/joydev.c
+10
-4
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+162
-88
drivers/input/mouse/Kconfig
drivers/input/mouse/Kconfig
+7
-16
drivers/input/mouse/logips2pp.c
drivers/input/mouse/logips2pp.c
+21
-1
drivers/input/mouse/logips2pp.h
drivers/input/mouse/logips2pp.h
+1
-1
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse-base.c
+180
-155
drivers/input/mouse/psmouse.h
drivers/input/mouse/psmouse.h
+13
-0
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.c
+121
-111
drivers/input/mouse/synaptics.h
drivers/input/mouse/synaptics.h
+1
-5
drivers/input/serio/i8042.c
drivers/input/serio/i8042.c
+331
-204
drivers/input/serio/serio.c
drivers/input/serio/serio.c
+83
-23
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+3
-0
include/asm-i386/irq.h
include/asm-i386/irq.h
+1
-0
include/linux/input.h
include/linux/input.h
+1
-0
include/linux/keyboard.h
include/linux/keyboard.h
+1
-2
include/linux/serio.h
include/linux/serio.h
+6
-2
kernel/sched.c
kernel/sched.c
+15
-20
No files found.
Documentation/kernel-parameters.txt
View file @
a76a8a35
...
...
@@ -790,7 +790,8 @@ running once the system is up.
before loading.
See Documentation/ramdisk.txt.
psmouse_noext [HW,MOUSE] Disable probing for PS2 mouse protocol extensions
psmouse_proto= [HW,MOUSE] Highest PS2 mouse protocol extension to
probe for (bare|imps|exps).
psmouse_resetafter=
[HW,MOUSE] Try to reset Synaptics Touchpad after so many
...
...
arch/i386/kernel/irq.c
View file @
a76a8a35
...
...
@@ -505,6 +505,20 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
return
1
;
}
int
can_request_irq
(
unsigned
int
irq
,
unsigned
long
irqflags
)
{
struct
irqaction
*
action
;
if
(
irq
>=
NR_IRQS
)
return
0
;
action
=
irq_desc
[
irq
].
action
;
if
(
action
)
{
if
(
irqflags
&
action
->
flags
&
SA_SHIRQ
)
action
=
NULL
;
}
return
!
action
;
}
/**
* request_irq - allocate an interrupt line
* @irq: Interrupt line to allocate
...
...
arch/i386/lib/usercopy.c
View file @
a76a8a35
...
...
@@ -541,8 +541,10 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long
goto
survive
;
}
if
(
retval
!=
1
)
if
(
retval
!=
1
)
{
up_read
(
&
current
->
mm
->
mmap_sem
);
break
;
}
maddr
=
kmap_atomic
(
pg
,
KM_USER0
);
memcpy
(
maddr
+
offset
,
from
,
len
);
...
...
arch/i386/pci/irq.c
View file @
a76a8a35
...
...
@@ -695,11 +695,6 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev)
return
NULL
;
}
static
irqreturn_t
pcibios_test_irq_handler
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
return
IRQ_NONE
;
}
static
int
pcibios_lookup_irq
(
struct
pci_dev
*
dev
,
int
assign
)
{
u8
pin
;
...
...
@@ -761,13 +756,10 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
for
(
i
=
0
;
i
<
16
;
i
++
)
{
if
(
!
(
mask
&
(
1
<<
i
)))
continue
;
if
(
pirq_penalty
[
i
]
<
pirq_penalty
[
newirq
]
&&
!
request_irq
(
i
,
pcibios_test_irq_handler
,
SA_SHIRQ
,
"pci-test"
,
dev
))
{
free_irq
(
i
,
dev
);
if
(
pirq_penalty
[
i
]
<
pirq_penalty
[
newirq
]
&&
can_request_irq
(
i
,
SA_SHIRQ
))
newirq
=
i
;
}
}
}
DBG
(
" -> newirq=%d"
,
newirq
);
/* Check if it is hardcoded */
...
...
drivers/block/ll_rw_blk.c
View file @
a76a8a35
...
...
@@ -2460,7 +2460,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
if
(
!
uptodate
)
{
error
=
-
EIO
;
if
(
!
(
req
->
flags
&
REQ_QUIET
))
if
(
blk_fs_request
(
req
)
&&
!
(
req
->
flags
&
REQ_QUIET
))
printk
(
"end_request: I/O error, dev %s, sector %llu
\n
"
,
req
->
rq_disk
?
req
->
rq_disk
->
disk_name
:
"?"
,
(
unsigned
long
long
)
req
->
sector
);
...
...
drivers/char/keyboard.c
View file @
a76a8a35
...
...
@@ -941,16 +941,16 @@ static unsigned short x86_keycodes[256] =
32
,
33
,
34
,
35
,
36
,
37
,
38
,
39
,
40
,
41
,
42
,
43
,
44
,
45
,
46
,
47
,
48
,
49
,
50
,
51
,
52
,
53
,
54
,
55
,
56
,
57
,
58
,
59
,
60
,
61
,
62
,
63
,
64
,
65
,
66
,
67
,
68
,
69
,
70
,
71
,
72
,
73
,
74
,
75
,
76
,
77
,
78
,
79
,
80
,
81
,
82
,
83
,
43
,
85
,
86
,
87
,
88
,
115
,
119
,
120
,
121
,
375
,
123
,
90
,
284
,
285
,
309
,
298
,
312
,
91
,
327
,
328
,
329
,
331
,
333
,
335
,
336
,
337
,
338
,
339
,
367
,
288
,
302
,
304
,
350
,
92
,
334
,
512
,
116
,
377
,
109
,
111
,
373
,
347
,
348
,
349
,
360
,
93
,
94
,
95
,
98
,
376
,
100
,
101
,
321
,
316
,
354
,
286
,
289
,
102
,
351
,
355
,
80
,
81
,
82
,
83
,
84
,
93
,
86
,
87
,
88
,
94
,
95
,
85
,
259
,
375
,
260
,
90
,
284
,
285
,
309
,
311
,
312
,
91
,
327
,
328
,
329
,
331
,
333
,
335
,
336
,
337
,
338
,
339
,
367
,
288
,
302
,
304
,
350
,
89
,
334
,
326
,
116
,
377
,
109
,
111
,
126
,
347
,
348
,
349
,
360
,
261
,
262
,
263
,
298
,
376
,
100
,
101
,
321
,
316
,
373
,
286
,
289
,
102
,
351
,
355
,
103
,
104
,
105
,
275
,
287
,
279
,
306
,
106
,
274
,
107
,
294
,
364
,
358
,
363
,
362
,
361
,
291
,
108
,
381
,
281
,
290
,
272
,
292
,
305
,
280
,
99
,
112
,
257
,
258
,
359
,
270
,
114
,
118
,
117
,
125
,
374
,
379
,
115
,
112
,
125
,
121
,
123
,
264
,
265
,
266
,
267
,
268
,
269
,
271
,
273
,
276
,
277
,
278
,
282
,
283
,
295
,
296
,
297
,
299
,
300
,
301
,
293
,
303
,
307
,
308
,
310
,
313
,
314
,
315
,
317
,
318
,
319
,
320
,
357
,
322
,
323
,
324
,
325
,
32
6
,
330
,
332
,
340
,
365
,
342
,
343
,
344
,
345
,
346
,
356
,
113
,
341
,
368
,
369
,
370
,
371
,
372
};
291
,
108
,
381
,
281
,
290
,
272
,
292
,
305
,
280
,
99
,
112
,
257
,
258
,
359
,
113
,
114
,
264
,
117
,
271
,
374
,
379
,
115
,
125
,
273
,
121
,
123
,
92
,
265
,
266
,
267
,
268
,
269
,
120
,
119
,
118
,
277
,
278
,
282
,
283
,
295
,
296
,
297
,
299
,
300
,
301
,
293
,
303
,
307
,
308
,
310
,
313
,
314
,
315
,
317
,
318
,
319
,
320
,
357
,
322
,
323
,
324
,
325
,
27
6
,
330
,
332
,
340
,
365
,
342
,
343
,
344
,
345
,
346
,
356
,
270
,
341
,
368
,
369
,
370
,
371
,
372
};
#ifdef CONFIG_MAC_EMUMOUSEBTN
extern
int
mac_hid_mouse_emulate_buttons
(
int
,
int
,
int
);
...
...
@@ -972,11 +972,18 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
if
(
keycode
>
255
||
!
x86_keycodes
[
keycode
])
return
-
1
;
if
(
keycode
==
KEY_PAUSE
)
{
switch
(
keycode
)
{
case
KEY_PAUSE
:
put_queue
(
vc
,
0xe1
);
put_queue
(
vc
,
0x1d
|
up_flag
);
put_queue
(
vc
,
0x45
|
up_flag
);
return
0
;
case
KEY_LANG1
:
if
(
!
up_flag
)
put_queue
(
vc
,
0xf1
);
return
0
;
case
KEY_LANG2
:
if
(
!
up_flag
)
put_queue
(
vc
,
0xf2
);
return
0
;
}
if
(
keycode
==
KEY_SYSRQ
&&
sysrq_alt
)
{
...
...
drivers/input/input.c
View file @
a76a8a35
...
...
@@ -447,6 +447,7 @@ void input_register_device(struct input_dev *dev)
list_add_tail
(
&
dev
->
node
,
&
input_dev_list
);
list_for_each_entry
(
handler
,
&
input_handler_list
,
node
)
if
(
!
handler
->
blacklist
||
!
input_match_device
(
handler
->
blacklist
,
dev
))
if
((
id
=
input_match_device
(
handler
->
id_table
,
dev
)))
if
((
handle
=
handler
->
connect
(
handler
,
dev
,
id
)))
input_link_handle
(
handle
);
...
...
@@ -507,6 +508,7 @@ void input_register_handler(struct input_handler *handler)
list_add_tail
(
&
handler
->
node
,
&
input_handler_list
);
list_for_each_entry
(
dev
,
&
input_dev_list
,
node
)
if
(
!
handler
->
blacklist
||
!
input_match_device
(
handler
->
blacklist
,
dev
))
if
((
id
=
input_match_device
(
handler
->
id_table
,
dev
)))
if
((
handle
=
handler
->
connect
(
handler
,
dev
,
id
)))
input_link_handle
(
handle
);
...
...
drivers/input/joydev.c
View file @
a76a8a35
...
...
@@ -380,10 +380,6 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
struct
joydev
*
joydev
;
int
i
,
j
,
t
,
minor
;
/* Avoid tablets */
if
(
test_bit
(
EV_KEY
,
dev
->
evbit
)
&&
test_bit
(
BTN_TOUCH
,
dev
->
keybit
))
return
NULL
;
for
(
minor
=
0
;
minor
<
JOYDEV_MINORS
&&
joydev_table
[
minor
];
minor
++
);
if
(
minor
==
JOYDEV_MINORS
)
{
printk
(
KERN_ERR
"joydev: no more free joydev devices
\n
"
);
...
...
@@ -464,6 +460,15 @@ static void joydev_disconnect(struct input_handle *handle)
joydev_free
(
joydev
);
}
static
struct
input_device_id
joydev_blacklist
[]
=
{
{
.
flags
=
INPUT_DEVICE_ID_MATCH_EVBIT
|
INPUT_DEVICE_ID_MATCH_KEYBIT
,
.
evbit
=
{
BIT
(
EV_KEY
)
},
.
keybit
=
{
[
LONG
(
BTN_TOUCH
)]
=
BIT
(
BTN_TOUCH
)
},
},
/* Avoid itouchpads, touchscreens and tablets */
{
},
/* Terminating entry */
};
static
struct
input_device_id
joydev_ids
[]
=
{
{
.
flags
=
INPUT_DEVICE_ID_MATCH_EVBIT
|
INPUT_DEVICE_ID_MATCH_ABSBIT
,
...
...
@@ -493,6 +498,7 @@ static struct input_handler joydev_handler = {
.
minor
=
JOYDEV_MINOR_BASE
,
.
name
=
"joydev"
,
.
id_table
=
joydev_ids
,
.
blacklist
=
joydev_blacklist
,
};
static
int
__init
joydev_init
(
void
)
...
...
drivers/input/keyboard/atkbd.c
View file @
a76a8a35
...
...
@@ -48,33 +48,30 @@ static int atkbd_softrepeat;
*/
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
,
90
,
57
,
47
,
33
,
20
,
19
,
6
,
0
,
91
,
49
,
48
,
35
,
34
,
21
,
7
,
0
,
0
,
0
,
50
,
36
,
22
,
8
,
9
,
0
,
0
,
67
,
65
,
63
,
61
,
59
,
60
,
88
,
0
,
68
,
66
,
64
,
62
,
15
,
41
,
117
,
0
,
56
,
42
,
182
,
29
,
16
,
2
,
0
,
0
,
0
,
44
,
31
,
30
,
17
,
3
,
0
,
0
,
46
,
45
,
32
,
18
,
5
,
4
,
186
,
0
,
57
,
47
,
33
,
20
,
19
,
6
,
85
,
0
,
49
,
48
,
35
,
34
,
21
,
7
,
89
,
0
,
0
,
50
,
36
,
22
,
8
,
9
,
90
,
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
,
0
,
181
,
40
,
0
,
26
,
13
,
0
,
0
,
58
,
54
,
28
,
27
,
0
,
43
,
0
,
194
,
0
,
86
,
193
,
192
,
184
,
0
,
14
,
185
,
0
,
79
,
182
,
75
,
71
,
124
,
0
,
0
,
82
,
83
,
80
,
76
,
77
,
72
,
1
,
69
,
87
,
78
,
81
,
74
,
55
,
73
,
70
,
99
,
0
,
0
,
0
,
65
,
99
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
25
5
,
0
,
0
,
92
,
90
,
85
,
0
,
137
,
0
,
0
,
0
,
0
,
91
,
89
,
144
,
115
,
0
,
217
,
100
,
255
,
0
,
97
,
165
,
164
,
0
,
156
,
0
,
0
,
140
,
115
,
0
,
0
,
125
,
1
73
,
114
,
0
,
113
,
152
,
163
,
151
,
126
,
128
,
166
,
0
,
140
,
0
,
147
,
0
,
127
,
159
,
167
,
115
,
160
,
164
,
0
,
0
,
116
,
158
,
0
,
150
,
166
,
0
,
0
,
0
,
142
,
157
,
0
,
114
,
166
,
168
,
0
,
0
,
213
,
155
,
0
,
98
,
113
,
0
,
163
,
0
,
138
,
226
,
0
,
0
,
0
,
0
,
0
,
153
,
140
,
0
,
255
,
96
,
0
,
0
,
0
,
143
,
0
,
133
,
0
,
116
,
0
,
143
,
0
,
174
,
133
,
0
,
107
,
0
,
105
,
102
,
0
,
0
,
112
,
110
,
111
,
108
,
112
,
106
,
103
,
0
,
119
,
0
,
118
,
109
,
0
,
99
,
104
,
119
217
,
100
,
255
,
0
,
97
,
165
,
0
,
0
,
156
,
0
,
0
,
0
,
0
,
0
,
0
,
12
5
,
173
,
114
,
0
,
113
,
0
,
0
,
0
,
126
,
128
,
0
,
0
,
140
,
0
,
0
,
0
,
127
,
159
,
0
,
115
,
0
,
164
,
0
,
0
,
116
,
158
,
0
,
150
,
166
,
0
,
0
,
0
,
142
,
1
57
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
155
,
0
,
98
,
0
,
0
,
163
,
0
,
0
,
226
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
255
,
96
,
0
,
0
,
0
,
143
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
107
,
0
,
105
,
102
,
0
,
0
,
112
,
110
,
111
,
108
,
112
,
106
,
103
,
0
,
119
,
0
,
118
,
109
,
0
,
99
,
104
,
119
,
0
,
0
,
0
,
0
,
65
,
99
,
};
static
unsigned
char
atkbd_set3_keycode
[
512
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
59
,
1
,
138
,
128
,
129
,
130
,
15
,
41
,
60
,
131
,
29
,
42
,
86
,
58
,
16
,
2
,
61
,
133
,
56
,
44
,
31
,
30
,
17
,
3
,
62
,
134
,
46
,
45
,
32
,
18
,
5
,
4
,
63
,
135
,
57
,
47
,
33
,
20
,
19
,
6
,
64
,
...
...
@@ -83,14 +80,10 @@ static unsigned char atkbd_set3_keycode[512] = {
113
,
114
,
40
,
84
,
26
,
13
,
87
,
99
,
97
,
54
,
28
,
27
,
43
,
84
,
88
,
70
,
108
,
105
,
119
,
103
,
111
,
107
,
14
,
110
,
0
,
79
,
106
,
75
,
71
,
109
,
102
,
104
,
82
,
83
,
80
,
76
,
77
,
72
,
69
,
98
,
0
,
96
,
81
,
0
,
78
,
73
,
55
,
85
,
89
,
90
,
91
,
92
,
74
,
185
,
184
,
182
,
0
,
0
,
0
,
125
,
126
,
127
,
112
,
0
,
0
,
139
,
150
,
163
,
165
,
115
,
152
,
150
,
166
,
140
,
160
,
154
,
113
,
114
,
167
,
168
,
148
,
149
,
147
,
140
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
255
148
,
149
,
147
,
140
};
static
unsigned
char
atkbd_unxlate_table
[
128
]
=
{
...
...
@@ -125,6 +118,9 @@ static unsigned char atkbd_unxlate_table[128] = {
#define ATKBD_RET_EMULX 0x80
#define ATKBD_RET_EMUL1 0xe1
#define ATKBD_RET_RELEASE 0xf0
#define ATKBD_RET_HANGUEL 0xf1
#define ATKBD_RET_HANJA 0xf2
#define ATKBD_RET_ERR 0xff
#define ATKBD_KEY_UNKNOWN 0
#define ATKBD_KEY_NULL 255
...
...
@@ -156,6 +152,17 @@ struct atkbd {
unsigned
long
time
;
};
static
void
atkbd_report_key
(
struct
input_dev
*
dev
,
struct
pt_regs
*
regs
,
int
code
,
int
value
)
{
input_regs
(
dev
,
regs
);
if
(
value
==
3
)
{
input_report_key
(
dev
,
code
,
1
);
input_report_key
(
dev
,
code
,
0
);
}
else
input_event
(
dev
,
EV_KEY
,
code
,
value
);
input_sync
(
dev
);
}
/*
* atkbd_interrupt(). Here takes place processing of data received from
* the keyboard into events.
...
...
@@ -184,6 +191,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd
->
resend
=
0
;
#endif
if
(
!
atkbd
->
ack
)
switch
(
code
)
{
case
ATKBD_RET_ACK
:
atkbd
->
ack
=
1
;
...
...
@@ -193,36 +201,25 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
goto
out
;
}
if
(
atkbd
->
translated
)
do
{
if
(
atkbd
->
emul
!=
1
)
{
if
(
code
==
ATKBD_RET_EMUL0
||
code
==
ATKBD_RET_EMUL1
)
break
;
if
(
code
==
ATKBD_RET_BAT
)
{
if
(
!
atkbd
->
bat_xl
)
break
;
atkbd
->
bat_xl
=
0
;
}
if
(
code
==
(
ATKBD_RET_BAT
&
0x7f
))
atkbd
->
bat_xl
=
1
;
}
if
(
code
<
0x80
)
{
code
=
atkbd_unxlate_table
[
code
];
break
;
if
(
atkbd
->
cmdcnt
)
{
atkbd
->
cmdbuf
[
--
atkbd
->
cmdcnt
]
=
code
;
goto
out
;
}
if
(
atkbd
->
cmdcnt
)
break
;
if
(
atkbd
->
translated
)
{
code
=
atkbd_unxlate_table
[
code
&
0x7f
];
atkbd
->
release
=
1
;
}
while
(
0
);
if
(
atkbd
->
emul
||
!
(
code
==
ATKBD_RET_EMUL0
||
code
==
ATKBD_RET_EMUL1
||
code
==
ATKBD_RET_HANGUEL
||
code
==
ATKBD_RET_HANJA
||
code
==
ATKBD_RET_ERR
||
(
code
==
ATKBD_RET_BAT
&&
!
atkbd
->
bat_xl
)))
{
atkbd
->
release
=
code
>>
7
;
code
&=
0x7f
;
}
if
(
atkbd
->
cmdcnt
)
{
atkbd
->
cmdbuf
[
--
atkbd
->
cmdcnt
]
=
code
;
goto
out
;
if
(
!
atkbd
->
emul
&&
(
code
&
0x7f
)
==
(
ATKBD_RET_BAT
&
0x7f
))
atkbd
->
bat_xl
=
!
atkbd
->
release
;
}
switch
(
code
)
{
...
...
@@ -238,22 +235,33 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
case
ATKBD_RET_RELEASE
:
atkbd
->
release
=
1
;
goto
out
;
case
ATKBD_RET_HANGUEL
:
atkbd_report_key
(
&
atkbd
->
dev
,
regs
,
KEY_LANG1
,
3
);
goto
out
;
case
ATKBD_RET_HANJA
:
atkbd_report_key
(
&
atkbd
->
dev
,
regs
,
KEY_LANG2
,
3
);
goto
out
;
case
ATKBD_RET_ERR
:
printk
(
KERN_WARNING
"atkbd.c: Keyboard on %s reports too many keys pressed.
\n
"
,
serio
->
phys
);
goto
out
;
}
if
(
atkbd
->
set
!=
3
)
code
=
(
code
&
0x7f
)
|
((
code
&
0x80
)
<<
1
);
if
(
atkbd
->
emul
)
{
if
(
--
atkbd
->
emul
)
goto
out
;
code
|=
0x100
;
code
|=
(
atkbd
->
set
!=
3
)
?
0x80
:
0x100
;
}
switch
(
atkbd
->
keycode
[
code
])
{
case
ATKBD_KEY_NULL
:
break
;
case
ATKBD_KEY_UNKNOWN
:
printk
(
KERN_WARNING
"atkbd.c: Unknown key %s (%s set %d, code %#x
, data %#x,
on %s).
\n
"
,
printk
(
KERN_WARNING
"atkbd.c: Unknown key %s (%s set %d, code %#x on %s).
\n
"
,
atkbd
->
release
?
"released"
:
"pressed"
,
atkbd
->
translated
?
"translated"
:
"raw"
,
atkbd
->
set
,
code
,
data
,
serio
->
phys
);
atkbd
->
set
,
code
,
serio
->
phys
);
break
;
default:
value
=
atkbd
->
release
?
0
:
...
...
@@ -273,9 +281,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break
;
}
input_regs
(
&
atkbd
->
dev
,
regs
);
input_event
(
&
atkbd
->
dev
,
EV_KEY
,
atkbd
->
keycode
[
code
],
value
);
input_sync
(
&
atkbd
->
dev
);
atkbd_report_key
(
&
atkbd
->
dev
,
regs
,
atkbd
->
keycode
[
code
],
value
);
}
atkbd
->
release
=
0
;
...
...
@@ -369,10 +375,11 @@ static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command)
static
int
atkbd_event
(
struct
input_dev
*
dev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
struct
atkbd
*
atkbd
=
dev
->
private
;
struct
{
int
p
;
u8
v
;
}
period
[]
=
{
{
30
,
0x00
},
{
25
,
0x02
},
{
20
,
0x04
},
{
15
,
0x08
},
{
10
,
0x0c
},
{
7
,
0x10
},
{
5
,
0x14
},
{
0
,
0x14
}
};
struct
{
int
d
;
u8
v
;
}
delay
[]
=
{
{
1000
,
0x60
},
{
750
,
0x40
},
{
500
,
0x20
},
{
250
,
0x00
},
{
0
,
0x00
}
};
const
short
period
[
32
]
=
{
33
,
37
,
42
,
46
,
50
,
54
,
58
,
63
,
67
,
75
,
83
,
92
,
100
,
109
,
116
,
125
,
133
,
149
,
167
,
182
,
200
,
217
,
232
,
250
,
270
,
303
,
333
,
370
,
400
,
435
,
470
,
500
};
const
short
delay
[
4
]
=
{
250
,
500
,
750
,
1000
};
char
param
[
2
];
int
i
,
j
;
...
...
@@ -406,11 +413,11 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
if
(
atkbd_softrepeat
)
return
0
;
i
=
j
=
0
;
while
(
period
[
i
].
p
>
dev
->
rep
[
REP_PERIOD
])
i
++
;
while
(
delay
[
j
].
d
>
dev
->
rep
[
REP_DELAY
])
j
++
;
dev
->
rep
[
REP_PERIOD
]
=
period
[
i
]
.
p
;
dev
->
rep
[
REP_DELAY
]
=
delay
[
j
]
.
d
;
param
[
0
]
=
period
[
i
].
v
|
delay
[
j
].
v
;
while
(
i
<
32
&&
period
[
i
]
<
dev
->
rep
[
REP_PERIOD
])
i
++
;
while
(
j
<
4
&&
delay
[
j
]
<
dev
->
rep
[
REP_DELAY
])
j
++
;
dev
->
rep
[
REP_PERIOD
]
=
period
[
i
];
dev
->
rep
[
REP_DELAY
]
=
delay
[
j
];
param
[
0
]
=
i
|
(
j
<<
5
)
;
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETREP
);
return
0
;
...
...
@@ -623,6 +630,7 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd
->
dev
.
rep
[
REP_PERIOD
]
=
33
;
}
atkbd
->
ack
=
1
;
atkbd
->
serio
=
serio
;
init_input_dev
(
&
atkbd
->
dev
);
...
...
@@ -665,16 +673,22 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
sprintf
(
atkbd
->
phys
,
"%s/input0"
,
serio
->
phys
);
if
(
atkbd
->
set
==
3
)
memcpy
(
atkbd
->
keycode
,
atkbd_set3_keycode
,
sizeof
(
atkbd
->
keycode
));
else
if
(
atkbd
->
translated
)
{
for
(
i
=
0
;
i
<
128
;
i
++
)
{
atkbd
->
keycode
[
i
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]];
atkbd
->
keycode
[
i
|
0x80
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]
|
0x80
];
}
}
else
if
(
atkbd
->
set
==
2
)
{
memcpy
(
atkbd
->
keycode
,
atkbd_set2_keycode
,
sizeof
(
atkbd
->
keycode
));
}
else
{
memcpy
(
atkbd
->
keycode
,
atkbd_set3_keycode
,
sizeof
(
atkbd
->
keycode
));
}
atkbd
->
dev
.
name
=
atkbd
->
name
;
atkbd
->
dev
.
phys
=
atkbd
->
phys
;
atkbd
->
dev
.
id
.
bustype
=
BUS_I8042
;
atkbd
->
dev
.
id
.
vendor
=
0x0001
;
atkbd
->
dev
.
id
.
product
=
atkbd
->
set
;
atkbd
->
dev
.
id
.
product
=
atkbd
->
translated
?
1
:
atkbd
->
set
;
atkbd
->
dev
.
id
.
version
=
atkbd
->
id
;
for
(
i
=
0
;
i
<
512
;
i
++
)
...
...
@@ -686,10 +700,62 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
atkbd
->
name
,
serio
->
phys
);
}
/*
* atkbd_reconnect() tries to restore keyboard into a sane state and is
* most likely called on resume.
*/
static
int
atkbd_reconnect
(
struct
serio
*
serio
)
{
struct
atkbd
*
atkbd
=
serio
->
private
;
struct
serio_dev
*
dev
=
serio
->
dev
;
int
i
;
if
(
!
dev
)
{
printk
(
KERN_DEBUG
"atkbd: reconnect request, but serio is disconnected, ignoring...
\n
"
);
return
-
1
;
}
if
(
atkbd
->
write
)
{
if
(
atkbd_probe
(
atkbd
))
return
-
1
;
atkbd
->
set
=
atkbd_set_3
(
atkbd
);
atkbd_enable
(
atkbd
);
}
else
{
atkbd
->
set
=
2
;
atkbd
->
id
=
0xab00
;
}
/*
* Here we probably should check if the keyboard has the same set that
* it had before and bail out if it's different. But this will most likely
* cause new keyboard device be created... and for the user it will look
* like keyboard is lost
*/
if
(
atkbd
->
translated
)
{
for
(
i
=
0
;
i
<
128
;
i
++
)
{
atkbd
->
keycode
[
i
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]];
atkbd
->
keycode
[
i
|
0x80
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]
|
0x80
];
}
}
else
if
(
atkbd
->
set
==
2
)
{
memcpy
(
atkbd
->
keycode
,
atkbd_set2_keycode
,
sizeof
(
atkbd
->
keycode
));
}
else
{
memcpy
(
atkbd
->
keycode
,
atkbd_set3_keycode
,
sizeof
(
atkbd
->
keycode
));
}
for
(
i
=
0
;
i
<
512
;
i
++
)
if
(
atkbd
->
keycode
[
i
]
&&
atkbd
->
keycode
[
i
]
<
255
)
set_bit
(
atkbd
->
keycode
[
i
],
atkbd
->
dev
.
keybit
);
return
0
;
}
static
struct
serio_dev
atkbd_dev
=
{
.
interrupt
=
atkbd_interrupt
,
.
connect
=
atkbd_connect
,
.
reconnect
=
atkbd_reconnect
,
.
disconnect
=
atkbd_disconnect
,
.
cleanup
=
atkbd_cleanup
,
};
...
...
@@ -709,9 +775,17 @@ static int __init atkbd_setup_reset(char *str)
if
(
ints
[
0
]
>
0
)
atkbd_reset
=
ints
[
1
];
return
1
;
}
static
int
__init
atkbd_setup_softrepeat
(
char
*
str
)
{
int
ints
[
4
];
str
=
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
if
(
ints
[
0
]
>
0
)
atkbd_softrepeat
=
ints
[
1
];
return
1
;
}
__setup
(
"atkbd_set="
,
atkbd_setup_set
);
__setup
(
"atkbd_reset"
,
atkbd_setup_reset
);
__setup
(
"atkbd_softrepeat="
,
atkbd_setup_softrepeat
);
#endif
int
__init
atkbd_init
(
void
)
...
...
drivers/input/mouse/Kconfig
View file @
a76a8a35
...
...
@@ -23,27 +23,18 @@ config MOUSE_PS2
mice with wheels and extra buttons, Microsoft, Logitech or Genius
compatible.
Synaptics TouchPad users might be interested in a specialized
XFree86 driver at:
http://w1.894.telia.com/~u89404340/touchpad/index.html
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 unsure, say Y.
To compile this driver as a module, choose M here: the
module will be called psmouse.
config MOUSE_PS2_SYNAPTICS
bool "Synaptics TouchPad"
default n
depends on INPUT && INPUT_MOUSE && 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
...
...
drivers/input/mouse/logips2pp.c
View file @
a76a8a35
...
...
@@ -10,6 +10,7 @@
*/
#include <linux/input.h>
#include <linux/serio.h>
#include "psmouse.h"
#include "logips2pp.h"
...
...
@@ -142,7 +143,7 @@ void ps2pp_set_800dpi(struct psmouse *psmouse)
* touchpad.
*/
int
ps2pp_detect_model
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
)
static
int
ps2pp_detect_model
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
)
{
int
i
;
static
int
logitech_4btn
[]
=
{
12
,
40
,
41
,
42
,
43
,
52
,
73
,
80
,
-
1
};
...
...
@@ -226,3 +227,22 @@ int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
return
0
;
}
/*
* Logitech magic init.
*/
int
ps2pp_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
param
[
1
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
return
param
[
1
]
!=
0
?
ps2pp_detect_model
(
psmouse
,
param
)
:
0
;
}
drivers/input/mouse/logips2pp.h
View file @
a76a8a35
...
...
@@ -13,5 +13,5 @@
struct
psmouse
;
void
ps2pp_process_packet
(
struct
psmouse
*
psmouse
);
void
ps2pp_set_800dpi
(
struct
psmouse
*
psmouse
);
int
ps2pp_detect
_model
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
);
int
ps2pp_detect
(
struct
psmouse
*
psmouse
);
#endif
drivers/input/mouse/psmouse-base.c
View file @
a76a8a35
...
...
@@ -12,35 +12,44 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#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"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@suse.cz>"
);
MODULE_DESCRIPTION
(
"PS/2 mouse driver"
);
MODULE_PARM
(
psmouse_noext
,
"1i"
);
MODULE_PARM_DESC
(
psmouse_noext
,
"Disable any protocol extensions. Useful for KVM switches."
);
MODULE_PARM
(
psmouse_resolution
,
"i"
);
MODULE_PARM_DESC
(
psmouse_resolution
,
"Resolution, in dpi."
);
MODULE_PARM
(
psmouse_rate
,
"i"
);
MODULE_PARM_DESC
(
psmouse_rate
,
"Report rate, in reports per second."
);
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"
);
static
int
psmouse_noext
;
module_param
(
psmouse_noext
,
int
,
0
);
MODULE_PARM_DESC
(
psmouse_noext
,
"[DEPRECATED] Disable any protocol extensions. Useful for KVM switches."
);
static
char
*
psmouse_proto
;
static
unsigned
int
psmouse_max_proto
=
-
1UL
;
module_param
(
psmouse_proto
,
charp
,
0
);
MODULE_PARM_DESC
(
psmouse_proto
,
"Highest protocol extension to probe (bare, imps, exps). Useful for KVM switches."
);
int
psmouse_resolution
=
200
;
module_param
(
psmouse_resolution
,
uint
,
0
);
MODULE_PARM_DESC
(
psmouse_resolution
,
"Resolution, in dpi."
);
unsigned
int
psmouse_rate
=
100
;
module_param
(
psmouse_rate
,
uint
,
0
);
MODULE_PARM_DESC
(
psmouse_rate
,
"Report rate, in reports per second."
);
int
psmouse_smartscroll
=
1
;
module_param
(
psmouse_smartscroll
,
bool
,
0
);
MODULE_PARM_DESC
(
psmouse_smartscroll
,
"Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."
);
unsigned
int
psmouse_resetafter
;
module_param
(
psmouse_resetafter
,
uint
,
0
);
MODULE_PARM_DESC
(
psmouse_resetafter
,
"Reset Synaptics Touchpad after so many bad packets (0 = never)."
);
static
char
*
psmouse_protocols
[]
=
{
"None"
,
"PS/2"
,
"PS2++"
,
"PS2T++"
,
"GenPS/2"
,
"ImPS/2"
,
"ImExPS/2"
,
"SynPS/2"
};
...
...
@@ -139,7 +148,8 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
goto
out
;
}
if
(
psmouse
->
pktcnt
&&
time_after
(
jiffies
,
psmouse
->
last
+
HZ
/
2
))
{
if
(
psmouse
->
state
==
PSMOUSE_ACTIVATED
&&
psmouse
->
pktcnt
&&
time_after
(
jiffies
,
psmouse
->
last
+
HZ
/
2
))
{
printk
(
KERN_WARNING
"psmouse.c: %s at %s lost synchronization, throwing %d bytes away.
\n
"
,
psmouse
->
name
,
psmouse
->
phys
,
psmouse
->
pktcnt
);
psmouse
->
pktcnt
=
0
;
...
...
@@ -257,46 +267,12 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
}
/*
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
* the mouse may have.
* Genius NetMouse magic init.
*/
static
int
psmouse_extensions
(
struct
psmouse
*
psmouse
)
static
int
genius_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
param
[
0
]
=
0
;
psmouse
->
vendor
=
"Generic"
;
psmouse
->
name
=
"Mouse"
;
psmouse
->
model
=
0
;
if
(
psmouse_noext
)
return
PSMOUSE_PS2
;
/*
* Try Synaptics TouchPad magic ID
*/
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
if
(
param
[
1
]
==
0x47
)
{
psmouse
->
vendor
=
"Synaptics"
;
psmouse
->
name
=
"TouchPad"
;
if
(
!
synaptics_init
(
psmouse
))
return
PSMOUSE_SYNAPTICS
;
else
return
PSMOUSE_PS2
;
}
/*
* Try Genius NetMouse magic init.
*/
param
[
0
]
=
3
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
...
...
@@ -304,38 +280,15 @@ static int psmouse_extensions(struct psmouse *psmouse)
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
if
(
param
[
0
]
==
0x00
&&
param
[
1
]
==
0x33
&&
param
[
2
]
==
0x55
)
{
set_bit
(
BTN_EXTRA
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_SIDE
,
psmouse
->
dev
.
keybit
);
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
psmouse
->
vendor
=
"Genius"
;
psmouse
->
name
=
"Wheel Mouse"
;
return
PSMOUSE_GENPS
;
}
/*
* Try Logitech magic ID.
*/
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
param
[
1
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
if
(
param
[
1
])
{
int
type
=
ps2pp_detect_model
(
psmouse
,
param
);
if
(
type
)
return
type
;
}
return
param
[
0
]
==
0x00
&&
param
[
1
]
==
0x33
&&
param
[
2
]
==
0x55
;
}
/*
*
Try
IntelliMouse magic init.
* IntelliMouse magic init.
*/
static
int
intellimouse_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
2
];
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
...
...
@@ -345,13 +298,15 @@ static int psmouse_extensions(struct psmouse *psmouse)
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETID
);
if
(
param
[
0
]
==
3
)
{
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
return
param
[
0
]
==
3
;
}
/*
* Try IntelliMouse/Explorer magic init.
*/
static
int
im_explorer_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
2
];
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
...
...
@@ -361,8 +316,63 @@ static int psmouse_extensions(struct psmouse *psmouse)
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETID
);
if
(
param
[
0
]
==
4
)
{
return
param
[
0
]
==
4
;
}
/*
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
* the mouse may have.
*/
static
int
psmouse_extensions
(
struct
psmouse
*
psmouse
)
{
int
synaptics_hardware
=
0
;
psmouse
->
vendor
=
"Generic"
;
psmouse
->
name
=
"Mouse"
;
psmouse
->
model
=
0
;
/*
* Try Synaptics TouchPad
*/
if
(
psmouse_max_proto
>
PSMOUSE_PS2
&&
synaptics_detect
(
psmouse
))
{
synaptics_hardware
=
1
;
psmouse
->
vendor
=
"Synaptics"
;
psmouse
->
name
=
"TouchPad"
;
if
(
psmouse_max_proto
>
PSMOUSE_IMEX
)
{
if
(
synaptics_init
(
psmouse
)
==
0
)
return
PSMOUSE_SYNAPTICS
;
/*
* Some Synaptics touchpads can emulate extended protocols (like IMPS/2).
* Unfortunately Logitech/Genius probes confuse some firmware versions so
* we'll have to skip them.
*/
psmouse_max_proto
=
PSMOUSE_IMEX
;
}
}
if
(
psmouse_max_proto
>
PSMOUSE_IMEX
&&
genius_detect
(
psmouse
))
{
set_bit
(
BTN_EXTRA
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_SIDE
,
psmouse
->
dev
.
keybit
);
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
psmouse
->
vendor
=
"Genius"
;
psmouse
->
name
=
"Wheel Mouse"
;
return
PSMOUSE_GENPS
;
}
if
(
psmouse_max_proto
>
PSMOUSE_IMEX
)
{
int
type
=
ps2pp_detect
(
psmouse
);
if
(
type
)
return
type
;
}
if
(
psmouse_max_proto
>=
PSMOUSE_IMPS
&&
intellimouse_detect
(
psmouse
))
{
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
if
(
psmouse_max_proto
>=
PSMOUSE_IMEX
&&
im_explorer_detect
(
psmouse
))
{
set_bit
(
BTN_SIDE
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_EXTRA
,
psmouse
->
dev
.
keybit
);
...
...
@@ -378,6 +388,15 @@ static int psmouse_extensions(struct psmouse *psmouse)
* Okay, all failed, we have a standard mouse here. The number of the buttons
* is still a question, though. We assume 3.
*/
if
(
synaptics_hardware
)
{
/*
* We detected Synaptics hardware but it did not respond to IMPS/2 probes.
* We need to reset the touchpad because if there is a track point on the
* pass through port it could get disabled while probing for protocol
* extensions.
*/
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_RESET_DIS
);
}
return
PSMOUSE_PS2
;
}
...
...
@@ -468,7 +487,7 @@ static void psmouse_initialize(struct psmouse *psmouse)
* We set the mouse report rate, resolution and scaling.
*/
if
(
!
psmouse_noext
)
{
if
(
psmouse_max_proto
!=
PSMOUSE_PS2
)
{
psmouse_set_rate
(
psmouse
);
psmouse_set_resolution
(
psmouse
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
...
...
@@ -513,45 +532,30 @@ 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
);
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
);
if
(
psmouse
->
ptport
)
{
if
(
psmouse
->
ptport
->
deactivate
)
psmouse
->
ptport
->
deactivate
(
psmouse
);
__serio_unregister_port
(
&
psmouse
->
ptport
->
serio
);
/* we have serio_sem */
kfree
(
psmouse
->
ptport
);
psmouse
->
ptport
=
NULL
;
}
/* We need to reopen the serio port to reinitialize the i8042 controller */
serio_close
(
psmouse
->
serio
);
serio_open
(
psmouse
->
serio
,
ser_dev
);
if
(
psmouse
->
disconnect
)
psmouse
->
disconnect
(
psmouse
);
/* Probe and re-initialize the mouse */
psmouse_probe
(
psmouse
);
psmouse_initialize
(
psmouse
);
synaptics_pt_init
(
psmouse
);
psmouse_activate
(
psmouse
);
return
0
;
input_unregister_device
(
&
psmouse
->
dev
);
serio_close
(
serio
);
kfree
(
psmouse
);
}
/*
* psmouse_connect() is a callback from the serio module when
* an unhandled serio port is found.
*/
static
void
psmouse_connect
(
struct
serio
*
serio
,
struct
serio_dev
*
dev
)
{
struct
psmouse
*
psmouse
;
struct
pm_dev
*
pmdev
;
if
((
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_8042
&&
(
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_PS_PSTHRU
)
...
...
@@ -572,7 +576,6 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse
->
dev
.
private
=
psmouse
;
serio
->
private
=
psmouse
;
if
(
serio_open
(
serio
,
dev
))
{
kfree
(
psmouse
);
return
;
...
...
@@ -584,12 +587,6 @@ 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"
,
...
...
@@ -608,59 +605,87 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse_initialize
(
psmouse
);
synaptics_pt_init
(
psmouse
);
if
(
psmouse
->
ptport
)
{
printk
(
KERN_INFO
"serio: %s port at %s
\n
"
,
psmouse
->
ptport
->
serio
.
name
,
psmouse
->
phys
);
__serio_register_port
(
&
psmouse
->
ptport
->
serio
);
/* we have serio_sem */
if
(
psmouse
->
ptport
->
activate
)
psmouse
->
ptport
->
activate
(
psmouse
);
}
psmouse_activate
(
psmouse
);
}
static
int
psmouse_reconnect
(
struct
serio
*
serio
)
{
struct
psmouse
*
psmouse
=
serio
->
private
;
struct
serio_dev
*
dev
=
serio
->
dev
;
int
old_type
=
psmouse
->
type
;
if
(
!
dev
)
{
printk
(
KERN_DEBUG
"psmouse: reconnect request, but serio is disconnected, ignoring...
\n
"
);
return
-
1
;
}
psmouse
->
state
=
PSMOUSE_NEW_DEVICE
;
psmouse
->
type
=
psmouse
->
acking
=
psmouse
->
cmdcnt
=
psmouse
->
pktcnt
=
0
;
if
(
psmouse
->
reconnect
)
{
if
(
psmouse
->
reconnect
(
psmouse
))
return
-
1
;
}
else
if
(
psmouse_probe
(
psmouse
)
!=
old_type
)
return
-
1
;
/* ok, the device type (and capabilities) match the old one,
* we can continue using it, complete intialization
*/
psmouse
->
type
=
old_type
;
psmouse_initialize
(
psmouse
);
if
(
psmouse
->
ptport
)
{
if
(
psmouse_reconnect
(
&
psmouse
->
ptport
->
serio
))
{
__serio_unregister_port
(
&
psmouse
->
ptport
->
serio
);
__serio_register_port
(
&
psmouse
->
ptport
->
serio
);
if
(
psmouse
->
ptport
->
activate
)
psmouse
->
ptport
->
activate
(
psmouse
);
}
}
psmouse_activate
(
psmouse
);
return
0
;
}
static
struct
serio_dev
psmouse_dev
=
{
.
interrupt
=
psmouse_interrupt
,
.
connect
=
psmouse_connect
,
.
reconnect
=
psmouse_reconnect
,
.
disconnect
=
psmouse_disconnect
,
.
cleanup
=
psmouse_cleanup
,
};
#ifndef MODULE
static
int
__init
psmouse_noext_setup
(
char
*
str
)
{
psmouse_noext
=
1
;
return
1
;
}
static
int
__init
psmouse_resolution_setup
(
char
*
str
)
{
get_option
(
&
str
,
&
psmouse_resolution
);
return
1
;
}
static
int
__init
psmouse_smartscroll_setup
(
char
*
str
)
{
get_option
(
&
str
,
&
psmouse_smartscroll
);
return
1
;
}
static
int
__init
psmouse_resetafter_setup
(
char
*
str
)
static
inline
void
psmouse_parse_proto
(
void
)
{
get_option
(
&
str
,
&
psmouse_resetafter
);
return
1
;
}
if
(
psmouse_noext
)
{
printk
(
KERN_WARNING
"psmouse: 'psmouse_noext' option is deprecated, please use 'psmouse_proto'
\n
"
);
psmouse_max_proto
=
PSMOUSE_PS2
;
}
static
int
__init
psmouse_rate_setup
(
char
*
str
)
{
get_option
(
&
str
,
&
psmouse_rate
);
return
1
;
/* even is psmouse_noext is present psmouse_proto overrides it */
if
(
psmouse_proto
)
{
if
(
!
strcmp
(
psmouse_proto
,
"bare"
))
psmouse_max_proto
=
PSMOUSE_PS2
;
else
if
(
!
strcmp
(
psmouse_proto
,
"imps"
))
psmouse_max_proto
=
PSMOUSE_IMPS
;
else
if
(
!
strcmp
(
psmouse_proto
,
"exps"
))
psmouse_max_proto
=
PSMOUSE_IMEX
;
else
printk
(
KERN_ERR
"psmouse: unknown protocol type '%s'
\n
"
,
psmouse_proto
);
}
}
__setup
(
"psmouse_noext"
,
psmouse_noext_setup
);
__setup
(
"psmouse_resolution="
,
psmouse_resolution_setup
);
__setup
(
"psmouse_smartscroll="
,
psmouse_smartscroll_setup
);
__setup
(
"psmouse_resetafter="
,
psmouse_resetafter_setup
);
__setup
(
"psmouse_rate="
,
psmouse_rate_setup
);
#endif
int
__init
psmouse_init
(
void
)
{
psmouse_parse_proto
();
serio_register_device
(
&
psmouse_dev
);
return
0
;
}
...
...
drivers/input/mouse/psmouse.h
View file @
a76a8a35
...
...
@@ -22,10 +22,20 @@
#define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2
struct
psmouse
;
struct
psmouse_ptport
{
struct
serio
serio
;
void
(
*
activate
)(
struct
psmouse
*
parent
);
void
(
*
deactivate
)(
struct
psmouse
*
parent
);
};
struct
psmouse
{
void
*
private
;
struct
input_dev
dev
;
struct
serio
*
serio
;
struct
psmouse_ptport
*
ptport
;
char
*
vendor
;
char
*
name
;
unsigned
char
cmdbuf
[
8
];
...
...
@@ -41,6 +51,9 @@ struct psmouse {
char
error
;
char
devname
[
64
];
char
phys
[
32
];
int
(
*
reconnect
)(
struct
psmouse
*
psmouse
);
void
(
*
disconnect
)(
struct
psmouse
*
psmouse
);
};
#define PSMOUSE_PS2 1
...
...
drivers/input/mouse/synaptics.c
View file @
a76a8a35
...
...
@@ -2,7 +2,8 @@
* Synaptics TouchPad PS/2 mouse driver
*
* 2003 Dmitry Torokhov <dtor@mail.ru>
* Added support for pass-through port
* Added support for pass-through port. Special thanks to Peter Berg Larsen
* for explaining various Synaptics quirks.
*
* 2003 Peter Osterlund <petero2@telia.com>
* Ported to 2.5 input device infrastructure.
...
...
@@ -194,9 +195,7 @@ static void print_ident(struct synaptics_data *priv)
static
int
synaptics_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
"
);
...
...
@@ -208,7 +207,14 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
if
(
synaptics_capability
(
psmouse
))
return
-
1
;
mode
=
SYN_BIT_ABSOLUTE_MODE
|
SYN_BIT_HIGH_RATE
;
return
0
;
}
static
int
synaptics_set_mode
(
struct
psmouse
*
psmouse
,
int
mode
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
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
))
...
...
@@ -265,49 +271,38 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
}
}
int
synaptics_pt_init
(
struct
psmouse
*
psmouse
)
static
void
synaptics_pt_activate
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
struct
serio
*
port
;
struct
psmouse
*
child
;
struct
psmouse
*
child
=
psmouse
->
ptport
->
serio
.
private
;
if
(
psmouse
->
type
!=
PSMOUSE_SYNAPTICS
)
return
-
1
;
if
(
!
SYN_CAP_EXTENDED
(
priv
->
capabilities
))
return
-
1
;
if
(
!
SYN_CAP_PASS_THROUGH
(
priv
->
capabilities
))
return
-
1
;
/* adjust the touchpad to child's choice of protocol */
if
(
child
&&
child
->
type
>=
PSMOUSE_GENPS
)
{
if
(
synaptics_set_mode
(
psmouse
,
SYN_BIT_FOUR_BYTE_CLIENT
))
printk
(
KERN_INFO
"synaptics: failed to enable 4-byte guest protocol
\n
"
);
}
}
static
void
synaptics_pt_create
(
struct
psmouse
*
psmouse
)
{
struct
psmouse_ptport
*
port
;
p
riv
->
ptport
=
port
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
p
smouse
->
ptport
=
port
=
kmalloc
(
sizeof
(
struct
psmouse_ptport
),
GFP_KERNEL
);
if
(
!
port
)
{
printk
(
KERN_ERR
"synaptics: not enough memory to allocate
serio
port
\n
"
);
return
-
1
;
printk
(
KERN_ERR
"synaptics: not enough memory to allocate
pass-through
port
\n
"
);
return
;
}
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
;
memset
(
port
,
0
,
sizeof
(
struct
psmouse_ptport
));
printk
(
KERN_INFO
"serio: %s port at %s
\n
"
,
port
->
name
,
psmouse
->
phys
);
serio_register_slave_port
(
port
);
port
->
serio
.
type
=
SERIO_PS_PSTHRU
;
port
->
serio
.
name
=
"Synaptics pass-through"
;
port
->
serio
.
phys
=
"synaptics-pt/serio0"
;
port
->
serio
.
write
=
synaptics_pt_write
;
port
->
serio
.
open
=
synaptics_pt_open
;
port
->
serio
.
close
=
synaptics_pt_close
;
port
->
serio
.
driver
=
psmouse
;
/* adjust the touchpad to child's choice of protocol */
child
=
port
->
private
;
if
(
child
&&
child
->
type
>=
PSMOUSE_GENPS
)
{
if
(
synaptics_mode_cmd
(
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
;
port
->
activate
=
synaptics_pt_activate
;
}
/*****************************************************************************
...
...
@@ -371,13 +366,57 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
clear_bit
(
REL_Y
,
dev
->
relbit
);
}
int
synaptics_ini
t
(
struct
psmouse
*
psmouse
)
static
void
synaptics_disconnec
t
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
;
synaptics_mode_cmd
(
psmouse
,
0
);
kfree
(
psmouse
->
private
);
}
#ifndef CONFIG_MOUSE_PS2_SYNAPTICS
static
int
synaptics_reconnect
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
struct
synaptics_data
old_priv
=
*
priv
;
if
(
!
synaptics_detect
(
psmouse
))
return
-
1
;
if
(
synaptics_query_hardware
(
psmouse
))
{
printk
(
KERN_ERR
"Unable to query Synaptics hardware.
\n
"
);
return
-
1
;
#endif
}
if
(
old_priv
.
identity
!=
priv
->
identity
||
old_priv
.
model_id
!=
priv
->
model_id
||
old_priv
.
capabilities
!=
priv
->
capabilities
||
old_priv
.
ext_cap
!=
priv
->
ext_cap
)
return
-
1
;
if
(
synaptics_set_mode
(
psmouse
,
0
))
{
printk
(
KERN_ERR
"Unable to initialize Synaptics hardware.
\n
"
);
return
-
1
;
}
return
0
;
}
int
synaptics_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
return
param
[
1
]
==
0x47
;
}
int
synaptics_init
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
;
psmouse
->
private
=
priv
=
kmalloc
(
sizeof
(
struct
synaptics_data
),
GFP_KERNEL
);
if
(
!
priv
)
...
...
@@ -385,13 +424,24 @@ int synaptics_init(struct psmouse *psmouse)
memset
(
priv
,
0
,
sizeof
(
struct
synaptics_data
));
if
(
synaptics_query_hardware
(
psmouse
))
{
printk
(
KERN_ERR
"Unable to query/initialize Synaptics hardware.
\n
"
);
printk
(
KERN_ERR
"Unable to query Synaptics hardware.
\n
"
);
goto
init_fail
;
}
if
(
synaptics_set_mode
(
psmouse
,
0
))
{
printk
(
KERN_ERR
"Unable to initialize Synaptics hardware.
\n
"
);
goto
init_fail
;
}
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
)
&&
SYN_CAP_PASS_THROUGH
(
priv
->
capabilities
))
synaptics_pt_create
(
psmouse
);
print_ident
(
priv
);
set_input_params
(
&
psmouse
->
dev
,
priv
);
psmouse
->
disconnect
=
synaptics_disconnect
;
psmouse
->
reconnect
=
synaptics_reconnect
;
return
0
;
init_fail:
...
...
@@ -399,36 +449,13 @@ int synaptics_init(struct psmouse *psmouse)
return
-
1
;
}
void
synaptics_disconnect
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
if
(
psmouse
->
type
==
PSMOUSE_SYNAPTICS
&&
priv
)
{
synaptics_mode_cmd
(
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
(
unsigned
char
buf
[],
struct
synaptics_data
*
priv
,
struct
synaptics_hw_state
*
hw
)
{
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
;
memset
(
hw
,
0
,
sizeof
(
struct
synaptics_hw_state
));
if
(
SYN_MODEL_NEWABS
(
priv
->
model_id
))
{
hw
->
x
=
(((
buf
[
3
]
&
0x10
)
<<
8
)
|
...
...
@@ -570,64 +597,47 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_sync
(
dev
);
}
static
int
synaptics_validate_byte
(
struct
psmouse
*
psmouse
)
{
static
unsigned
char
newabs_mask
[]
=
{
0xC0
,
0x00
,
0x00
,
0xC0
,
0x00
};
static
unsigned
char
newabs_rslt
[]
=
{
0x80
,
0x00
,
0x00
,
0xC0
,
0x00
};
static
unsigned
char
oldabs_mask
[]
=
{
0xC0
,
0x60
,
0x00
,
0xC0
,
0x60
};
static
unsigned
char
oldabs_rslt
[]
=
{
0xC0
,
0x00
,
0x00
,
0x80
,
0x00
};
struct
synaptics_data
*
priv
=
psmouse
->
private
;
int
idx
=
psmouse
->
pktcnt
-
1
;
if
(
SYN_MODEL_NEWABS
(
priv
->
model_id
))
return
(
psmouse
->
packet
[
idx
]
&
newabs_mask
[
idx
])
==
newabs_rslt
[
idx
];
else
return
(
psmouse
->
packet
[
idx
]
&
oldabs_mask
[
idx
])
==
oldabs_rslt
[
idx
];
}
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
data
=
psmouse
->
packet
[
psmouse
->
pktcnt
-
1
];
int
newabs
=
SYN_MODEL_NEWABS
(
priv
->
model_id
);
input_regs
(
dev
,
regs
);
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
)
break
;
/* Wait for full packet */
if
(
psmouse
->
pktcnt
>=
6
)
{
/* Full packet received */
if
(
priv
->
out_of_sync
)
{
priv
->
out_of_sync
=
0
;
printk
(
KERN_NOTICE
"Synaptics driver resynced.
\n
"
);
}
if
(
p
riv
->
ptport
&&
synaptics_is_pt_packet
(
psmouse
->
packet
))
synaptics_pass_pt_packet
(
priv
->
ptport
,
psmouse
->
packet
);
if
(
p
smouse
->
ptport
&&
psmouse
->
ptport
->
serio
.
dev
&&
synaptics_is_pt_packet
(
psmouse
->
packet
))
synaptics_pass_pt_packet
(
&
psmouse
->
ptport
->
serio
,
psmouse
->
packet
);
else
synaptics_process_packet
(
psmouse
);
psmouse
->
pktcnt
=
0
;
break
;
}
return
;
bad_sync:
priv
->
out_of_sync
++
;
}
else
if
(
psmouse
->
pktcnt
&&
!
synaptics_validate_byte
(
psmouse
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at byte %d
\n
"
,
psmouse
->
pktcnt
)
;
psmouse
->
pktcnt
=
0
;
if
(
psmouse_resetafter
>
0
&&
priv
->
out_of_sync
==
psmouse_resetafter
)
{
if
(
++
priv
->
out_of_sync
==
psmouse_resetafter
)
{
psmouse
->
state
=
PSMOUSE_IGNORE
;
serio_rescan
(
psmouse
->
serio
);
printk
(
KERN_NOTICE
"synaptics: issuing reconnect request
\n
"
);
serio_reconnect
(
psmouse
->
serio
);
}
}
}
drivers/input/mouse/synaptics.h
View file @
a76a8a35
...
...
@@ -9,11 +9,9 @@
#ifndef _SYNAPTICS_H
#define _SYNAPTICS_H
extern
void
synaptics_process_byte
(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
);
extern
int
synaptics_detect
(
struct
psmouse
*
psmouse
);
extern
int
synaptics_init
(
struct
psmouse
*
psmouse
);
extern
int
synaptics_pt_init
(
struct
psmouse
*
psmouse
);
extern
void
synaptics_disconnect
(
struct
psmouse
*
psmouse
);
/* synaptics queries */
#define SYN_QUE_IDENTIFY 0x00
...
...
@@ -105,8 +103,6 @@ struct synaptics_data {
/* Data for normal processing */
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/i8042.c
View file @
a76a8a35
...
...
@@ -12,11 +12,14 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/config.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/sysdev.h>
#include <linux/pm.h>
#include <linux/serio.h>
#include <asm/io.h>
...
...
@@ -25,19 +28,23 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION
(
"i8042 keyboard and mouse controller driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
i8042_noaux
,
"1i"
);
MODULE_PARM
(
i8042_nomux
,
"1i"
);
MODULE_PARM
(
i8042_unlock
,
"1i"
);
MODULE_PARM
(
i8042_reset
,
"1i"
);
MODULE_PARM
(
i8042_direct
,
"1i"
);
MODULE_PARM
(
i8042_dumbkbd
,
"1i"
);
static
unsigned
int
i8042_noaux
;
module_param
(
i8042_noaux
,
bool
,
0
);
static
int
i8042_reset
;
static
int
i8042_noaux
;
static
int
i8042_nomux
;
static
int
i8042_unlock
;
static
int
i8042_direct
;
static
int
i8042_dumbkbd
;
static
unsigned
int
i8042_nomux
;
module_param
(
i8042_nomux
,
bool
,
0
);
static
unsigned
int
i8042_unlock
;
module_param
(
i8042_unlock
,
bool
,
0
);
static
unsigned
int
i8042_reset
;
module_param
(
i8042_reset
,
bool
,
0
);
static
unsigned
int
i8042_direct
;
module_param
(
i8042_direct
,
bool
,
0
);
static
unsigned
int
i8042_dumbkbd
;
module_param
(
i8042_dumbkbd
,
bool
,
0
);
#undef DEBUG
#include "i8042.h"
...
...
@@ -59,6 +66,9 @@ static struct serio i8042_aux_port;
static
unsigned
char
i8042_initial_ctr
;
static
unsigned
char
i8042_ctr
;
static
unsigned
char
i8042_mux_open
;
static
unsigned
char
i8042_mux_present
;
static
unsigned
char
i8042_sysdev_initialized
;
static
struct
pm_dev
*
i8042_pm_dev
;
struct
timer_list
i8042_timer
;
/*
...
...
@@ -214,16 +224,41 @@ static int i8042_aux_write(struct serio *port, unsigned char c)
}
/*
* i8042_open() is called when a port is open by the higher layer.
* It allocates the interrupt and enables it in the chip.
* i8042_activate_port() enables port on a chip.
*/
static
int
i8042_
open
(
struct
serio
*
port
)
static
int
i8042_
activate_port
(
struct
serio
*
port
)
{
struct
i8042_values
*
values
=
port
->
driver
;
i8042_flush
();
/*
* Enable port again here because it is disabled if we are
* resuming (normally it is enabled already).
*/
i8042_ctr
&=
~
values
->
disable
;
i8042_ctr
|=
values
->
irqen
;
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
{
i8042_ctr
&=
~
values
->
irqen
;
return
-
1
;
}
return
0
;
}
/*
* i8042_open() is called when a port is open by the higher layer.
* It allocates the interrupt and calls i8042_enable_port.
*/
static
int
i8042_open
(
struct
serio
*
port
)
{
struct
i8042_values
*
values
=
port
->
driver
;
if
(
values
->
mux
!=
-
1
)
if
(
i8042_mux_open
++
)
return
0
;
...
...
@@ -231,21 +266,26 @@ static int i8042_open(struct serio *port)
if
(
request_irq
(
values
->
irq
,
i8042_interrupt
,
SA_SHIRQ
,
"i8042"
,
i8042_request_irq_cookie
))
{
printk
(
KERN_ERR
"i8042.c: Can't get irq %d for %s, unregistering the port.
\n
"
,
values
->
irq
,
values
->
name
);
values
->
exists
=
0
;
serio_unregister_port
(
port
);
return
-
1
;
goto
irq_fail
;
}
i8042_ctr
|=
values
->
irqen
;
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
{
printk
(
KERN_ERR
"i8042.c: Can't write CTR while opening %s.
\n
"
,
values
->
name
);
return
-
1
;
if
(
i8042_activate_port
(
port
))
{
printk
(
KERN_ERR
"i8042.c: Can't activate %s, unregistering the port
\n
"
,
values
->
name
);
goto
activate_fail
;
}
i8042_interrupt
(
0
,
NULL
,
NULL
);
return
0
;
activate_fail:
free_irq
(
values
->
irq
,
i8042_request_irq_cookie
);
irq_fail:
values
->
exists
=
0
;
serio_unregister_port_delayed
(
port
);
return
-
1
;
}
/*
...
...
@@ -393,145 +433,78 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
/*
* i8042_
controller init initializes the i8042 controller, and,
* m
ost importantly, sets it into non-xlated mode if that's
*
desired
.
* i8042_
enable_mux_mode checks whether the controller has an active
* m
ultiplexor and puts the chip into Multiplexed (as opposed to
*
Legacy) mode
.
*/
static
int
__init
i8042_controller_init
(
void
)
static
int
i8042_enable_mux_mode
(
struct
i8042_values
*
values
,
unsigned
char
*
mux_version
)
{
unsigned
char
param
;
/*
* Test the i8042. We need to know if it thinks it's working correctly
* before doing anything else.
* Get rid of bytes in the queue.
*/
i8042_flush
();
if
(
i8042_reset
)
{
unsigned
char
param
;
if
(
i8042_command
(
&
param
,
I8042_CMD_CTL_TEST
))
{
printk
(
KERN_ERR
"i8042.c: i8042 controller self test timeout.
\n
"
);
return
-
1
;
}
if
(
param
!=
I8042_RET_CTL_TEST
)
{
printk
(
KERN_ERR
"i8042.c: i8042 controller selftest failed. (%#x != %#x)
\n
"
,
param
,
I8042_RET_CTL_TEST
);
return
-
1
;
}
}
/*
* Save the CTR for restoral on unload / reboot.
* Internal loopback test - send three bytes, they should come back from the
* mouse interface, the last should be version. Note that we negate mouseport
* command responses for the i8042_check_aux() routine.
*/
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_RCTR
))
{
printk
(
KERN_ERR
"i8042.c: Can't read CTR while initializing i8042.
\n
"
);
param
=
0xf0
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
!=
0x0f
)
return
-
1
;
}
i8042_initial_ctr
=
i8042_ctr
;
/*
* Disable the keyboard interface and interrupt.
*/
i8042_ctr
|=
I8042_CTR_KBDDIS
;
i8042_ctr
&=
~
I8042_CTR_KBDINT
;
/*
* Handle keylock.
*/
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
"
);
}
/*
* If the chip is configured into nontranslated mode by the BIOS, don't
* bother enabling translating and be happy.
*/
if
(
~
i8042_ctr
&
I8042_CTR_XLATE
)
i8042_direct
=
1
;
/*
* Set nontranslated mode for the kbd interface if requested by an option.
* After this the kbd interface becomes a simple serial in/out, like the aux
* interface is. We don't do this by default, since it can confuse notebook
* BIOSes.
*/
if
(
i8042_direct
)
{
i8042_ctr
&=
~
I8042_CTR_XLATE
;
i8042_kbd_port
.
type
=
SERIO_8042
;
}
/*
* Write CTR back.
*/
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
{
printk
(
KERN_ERR
"i8042.c: Can't write CTR while initializing i8042.
\n
"
);
param
=
0x56
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
!=
0xa9
)
return
-
1
;
}
param
=
0xa4
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
==
0x5b
)
return
-
1
;
if
(
mux_version
)
*
mux_version
=
~
param
;
return
0
;
}
/*
*
Here we try to reset everything back to a state in which the BIOS will be
*
able to talk to the hardware when rebooting.
*
i8042_enable_mux_ports enables 4 individual AUX ports after
*
the controller has been switched into Multiplexed mode
*/
void
i8042_controller_cleanup
(
void
)
static
int
i8042_enable_mux_ports
(
struct
i8042_values
*
values
)
{
unsigned
char
param
;
int
i
;
i8042_flush
();
/*
* Reset anything that is connected to the ports.
*/
if
(
i8042_kbd_values
.
exists
)
serio_cleanup
(
&
i8042_kbd_port
);
if
(
i8042_aux_values
.
exists
)
serio_cleanup
(
&
i8042_aux_port
);
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
)
serio_cleanup
(
i8042_mux_port
+
i
);
/*
* Reset the controller.
* Disable all muxed ports by disabling AUX.
*/
i
f
(
i8042_reset
)
{
unsigned
char
param
;
i
8042_ctr
|=
I8042_CTR_AUXDIS
;
i8042_ctr
&=
~
I8042_CTR_AUXINT
;
if
(
i8042_command
(
&
param
,
I8042_CMD_CTL_TEST
))
printk
(
KERN_ERR
"i8042.c: i8042 controller reset timeout.
\n
"
);
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
{
printk
(
KERN_ERR
"i8042.c: Failed to disable AUX port, can't use MUX.
\n
"
);
return
-
1
;
}
/*
*
Restore the original control register setting
.
*
Enable all muxed ports
.
*/
i8042_ctr
=
i8042_initial_ctr
;
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
printk
(
KERN_WARNING
"i8042.c: Can't restore CTR.
\n
"
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
i8042_command
(
&
param
,
I8042_CMD_MUX_PFX
+
i
);
i8042_command
(
&
param
,
I8042_CMD_AUX_ENABLE
);
}
return
0
;
}
/*
* i8042_check_mux() checks whether the controller supports the PS/2 Active
* Multiplexing specification by Synaptics, Phoenix, Insyde and
...
...
@@ -540,66 +513,31 @@ void i8042_controller_cleanup(void)
static
int
__init
i8042_check_mux
(
struct
i8042_values
*
values
)
{
unsigned
char
param
;
static
int
i8042_check_mux_cookie
;
int
i
;
unsigned
char
mux_version
;
/*
* Check if AUX irq is available.
*/
if
(
request_irq
(
values
->
irq
,
i8042_interrupt
,
SA_SHIRQ
,
"i8042"
,
&
i8042_check_mux_cookie
))
return
-
1
;
free_irq
(
values
->
irq
,
&
i8042_check_mux_cookie
);
/*
* Get rid of bytes in the queue.
*/
i8042_flush
();
/*
* Internal loopback test - send three bytes, they should come back from the
* mouse interface, the last should be version. Note that we negate mouseport
* command responses for the i8042_check_aux() routine.
*/
param
=
0xf0
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
!=
0x0f
)
return
-
1
;
param
=
0x56
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
!=
0xa9
)
return
-
1
;
param
=
0xa4
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
==
0x5b
)
if
(
i8042_enable_mux_mode
(
values
,
&
mux_version
))
return
-
1
;
printk
(
KERN_INFO
"i8042.c: Detected active multiplexing controller, rev %d.%d.
\n
"
,
(
~
param
>>
4
)
&
0xf
,
~
param
&
0xf
);
/*
* Disable all muxed ports by disabling AUX.
*/
i8042_ctr
|=
I8042_CTR_AUXDIS
;
i8042_ctr
&=
~
I8042_CTR_AUXINT
;
(
mux_version
>>
4
)
&
0xf
,
mux_version
&
0xf
);
if
(
i8042_
command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
if
(
i8042_
enable_mux_ports
(
values
))
return
-
1
;
/*
* Enable all muxed ports.
*/
for
(
i
=
0
;
i
<
4
;
i
++
)
{
i8042_command
(
&
param
,
I8042_CMD_MUX_PFX
+
i
);
i8042_command
(
&
param
,
I8042_CMD_AUX_ENABLE
);
}
i8042_mux_present
=
1
;
return
0
;
}
/*
* i8042_check_aux() applies as much paranoia as it can at detecting
* the presence of an AUX interface.
...
...
@@ -675,6 +613,7 @@ static int __init i8042_check_aux(struct i8042_values *values)
return
0
;
}
/*
* i8042_port_register() marks the device as existing,
* registers it, and reports to the user.
...
...
@@ -691,63 +630,205 @@ static int __init i8042_port_register(struct i8042_values *values, struct serio
return
-
1
;
}
serio_register_port
(
port
);
printk
(
KERN_INFO
"serio: i8042 %s port at %#lx,%#lx irq %d
\n
"
,
values
->
name
,
(
unsigned
long
)
I8042_DATA_REG
,
(
unsigned
long
)
I8042_COMMAND_REG
,
values
->
irq
);
serio_register_port
(
port
);
return
0
;
}
static
void
i8042_timer_func
(
unsigned
long
data
)
{
i8042_interrupt
(
0
,
NULL
,
NULL
);
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
}
#ifndef MODULE
static
int
__init
i8042_setup_reset
(
char
*
str
)
{
i8042_reset
=
1
;
return
1
;
}
static
int
__init
i8042_setup_noaux
(
char
*
str
)
{
i8042_noaux
=
1
;
i8042_nomux
=
1
;
return
1
;
}
static
int
__init
i8042_setup_nomux
(
char
*
str
)
/*
* i8042_controller init initializes the i8042 controller, and,
* most importantly, sets it into non-xlated mode if that's
* desired.
*/
static
int
i8042_controller_init
(
void
)
{
if
(
i8042_noaux
)
i8042_nomux
=
1
;
return
1
;
}
static
int
__init
i8042_setup_unlock
(
char
*
str
)
{
i8042_unlock
=
1
;
return
1
;
/*
* Test the i8042. We need to know if it thinks it's working correctly
* before doing anything else.
*/
i8042_flush
();
if
(
i8042_reset
)
{
unsigned
char
param
;
if
(
i8042_command
(
&
param
,
I8042_CMD_CTL_TEST
))
{
printk
(
KERN_ERR
"i8042.c: i8042 controller self test timeout.
\n
"
);
return
-
1
;
}
if
(
param
!=
I8042_RET_CTL_TEST
)
{
printk
(
KERN_ERR
"i8042.c: i8042 controller selftest failed. (%#x != %#x)
\n
"
,
param
,
I8042_RET_CTL_TEST
);
return
-
1
;
}
}
/*
* Save the CTR for restoral on unload / reboot.
*/
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_RCTR
))
{
printk
(
KERN_ERR
"i8042.c: Can't read CTR while initializing i8042.
\n
"
);
return
-
1
;
}
i8042_initial_ctr
=
i8042_ctr
;
/*
* Disable the keyboard interface and interrupt.
*/
i8042_ctr
|=
I8042_CTR_KBDDIS
;
i8042_ctr
&=
~
I8042_CTR_KBDINT
;
/*
* Handle keylock.
*/
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
"
);
}
/*
* If the chip is configured into nontranslated mode by the BIOS, don't
* bother enabling translating and be happy.
*/
if
(
~
i8042_ctr
&
I8042_CTR_XLATE
)
i8042_direct
=
1
;
/*
* Set nontranslated mode for the kbd interface if requested by an option.
* After this the kbd interface becomes a simple serial in/out, like the aux
* interface is. We don't do this by default, since it can confuse notebook
* BIOSes.
*/
if
(
i8042_direct
)
{
i8042_ctr
&=
~
I8042_CTR_XLATE
;
i8042_kbd_port
.
type
=
SERIO_8042
;
}
/*
* Write CTR back.
*/
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
{
printk
(
KERN_ERR
"i8042.c: Can't write CTR while initializing i8042.
\n
"
);
return
-
1
;
}
return
0
;
}
static
int
__init
i8042_setup_direct
(
char
*
str
)
/*
* Here we try to reset everything back to a state in which the BIOS will be
* able to talk to the hardware when rebooting.
*/
void
i8042_controller_cleanup
(
void
)
{
i8042_direct
=
1
;
return
1
;
int
i
;
i8042_flush
();
/*
* Reset anything that is connected to the ports.
*/
if
(
i8042_kbd_values
.
exists
)
serio_cleanup
(
&
i8042_kbd_port
);
if
(
i8042_aux_values
.
exists
)
serio_cleanup
(
&
i8042_aux_port
);
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
)
serio_cleanup
(
i8042_mux_port
+
i
);
/*
* Reset the controller.
*/
if
(
i8042_reset
)
{
unsigned
char
param
;
if
(
i8042_command
(
&
param
,
I8042_CMD_CTL_TEST
))
printk
(
KERN_ERR
"i8042.c: i8042 controller reset timeout.
\n
"
);
}
/*
* Restore the original control register setting.
*/
i8042_ctr
=
i8042_initial_ctr
;
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
printk
(
KERN_WARNING
"i8042.c: Can't restore CTR.
\n
"
);
}
static
int
__init
i8042_setup_dumbkbd
(
char
*
str
)
/*
* Here we try to reset everything back to a state in which suspended
*/
static
int
i8042_controller_resume
(
void
)
{
i8042_dumbkbd
=
1
;
return
1
;
int
i
;
if
(
i8042_controller_init
())
{
printk
(
KERN_ERR
"i8042: resume failed
\n
"
);
return
-
1
;
}
if
(
i8042_mux_present
)
if
(
i8042_enable_mux_mode
(
&
i8042_aux_values
,
NULL
)
||
i8042_enable_mux_ports
(
&
i8042_aux_values
))
{
printk
(
KERN_WARNING
"i8042: failed to resume active multiplexor, mouse won't wotk.
\n
"
);
}
/*
* Reconnect anything that was connected to the ports.
*/
if
(
i8042_kbd_values
.
exists
&&
i8042_activate_port
(
&
i8042_kbd_port
)
==
0
)
serio_reconnect
(
&
i8042_kbd_port
);
if
(
i8042_aux_values
.
exists
&&
i8042_activate_port
(
&
i8042_aux_port
)
==
0
)
serio_reconnect
(
&
i8042_aux_port
);
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
&&
i8042_activate_port
(
i8042_mux_port
+
i
)
==
0
)
serio_reconnect
(
i8042_mux_port
+
i
);
return
0
;
}
__setup
(
"i8042_reset"
,
i8042_setup_reset
);
__setup
(
"i8042_noaux"
,
i8042_setup_noaux
);
__setup
(
"i8042_nomux"
,
i8042_setup_nomux
);
__setup
(
"i8042_unlock"
,
i8042_setup_unlock
);
__setup
(
"i8042_direct"
,
i8042_setup_direct
);
__setup
(
"i8042_dumbkbd"
,
i8042_setup_dumbkbd
);
#endif
/*
* We need to reset the 8042 back to original mode on system shutdown,
...
...
@@ -769,6 +850,35 @@ static struct notifier_block i8042_notifier=
0
};
/*
* Resume handler for the new PM scheme (driver model)
*/
static
int
i8042_resume
(
struct
sys_device
*
dev
)
{
return
i8042_controller_resume
();
}
static
struct
sysdev_class
kbc_sysclass
=
{
set_kset_name
(
"i8042"
),
.
resume
=
i8042_resume
,
};
static
struct
sys_device
device_i8042
=
{
.
id
=
0
,
.
cls
=
&
kbc_sysclass
,
};
/*
* Resume handler for the old PM scheme (APM)
*/
static
int
i8042_pm_callback
(
struct
pm_dev
*
dev
,
pm_request_t
request
,
void
*
dummy
)
{
if
(
request
==
PM_RESUME
)
return
i8042_controller_resume
();
return
0
;
}
static
void
__init
i8042_init_mux_values
(
struct
i8042_values
*
values
,
struct
serio
*
port
,
int
index
)
{
memcpy
(
port
,
&
i8042_aux_port
,
sizeof
(
struct
serio
));
...
...
@@ -817,6 +927,15 @@ int __init i8042_init(void)
i8042_timer
.
function
=
i8042_timer_func
;
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
if
(
sysdev_class_register
(
&
kbc_sysclass
)
==
0
)
{
if
(
sys_device_register
(
&
device_i8042
)
==
0
)
i8042_sysdev_initialized
=
1
;
else
sysdev_class_unregister
(
&
kbc_sysclass
);
}
i8042_pm_dev
=
pm_register
(
PM_SYS_DEV
,
PM_SYS_UNKNOWN
,
i8042_pm_callback
);
register_reboot_notifier
(
&
i8042_notifier
);
return
0
;
...
...
@@ -828,6 +947,14 @@ void __exit i8042_exit(void)
unregister_reboot_notifier
(
&
i8042_notifier
);
if
(
i8042_pm_dev
)
pm_unregister
(
i8042_pm_dev
);
if
(
i8042_sysdev_initialized
)
{
sys_device_unregister
(
&
device_i8042
);
sysdev_class_unregister
(
&
kbc_sysclass
);
}
del_timer
(
&
i8042_timer
);
i8042_controller_cleanup
();
...
...
drivers/input/serio/serio.c
View file @
a76a8a35
...
...
@@ -49,14 +49,17 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL
(
serio_interrupt
);
EXPORT_SYMBOL
(
serio_register_port
);
EXPORT_SYMBOL
(
serio_register_slave_port
);
EXPORT_SYMBOL
(
serio_register_port_delayed
);
EXPORT_SYMBOL
(
__serio_register_port
);
EXPORT_SYMBOL
(
serio_unregister_port
);
EXPORT_SYMBOL
(
serio_unregister_slave_port
);
EXPORT_SYMBOL
(
serio_unregister_port_delayed
);
EXPORT_SYMBOL
(
__serio_unregister_port
);
EXPORT_SYMBOL
(
serio_register_device
);
EXPORT_SYMBOL
(
serio_unregister_device
);
EXPORT_SYMBOL
(
serio_open
);
EXPORT_SYMBOL
(
serio_close
);
EXPORT_SYMBOL
(
serio_rescan
);
EXPORT_SYMBOL
(
serio_reconnect
);
struct
serio_event
{
int
type
;
...
...
@@ -83,10 +86,22 @@ 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
static
DECLARE_WAIT_QUEUE_HEAD
(
serio_wait
);
static
DECLARE_COMPLETION
(
serio_exited
);
static
void
serio_invalidate_pending_events
(
struct
serio
*
serio
)
{
struct
serio_event
*
event
;
list_for_each_entry
(
event
,
&
serio_event_list
,
node
)
if
(
event
->
serio
==
serio
)
event
->
serio
=
NULL
;
}
void
serio_handle_events
(
void
)
{
struct
list_head
*
node
,
*
next
;
...
...
@@ -95,17 +110,35 @@ void serio_handle_events(void)
list_for_each_safe
(
node
,
next
,
&
serio_event_list
)
{
event
=
container_of
(
node
,
struct
serio_event
,
node
);
down
(
&
serio_sem
);
if
(
event
->
serio
==
NULL
)
goto
event_done
;
switch
(
event
->
type
)
{
case
SERIO_REGISTER_PORT
:
__serio_register_port
(
event
->
serio
);
break
;
case
SERIO_UNREGISTER_PORT
:
__serio_unregister_port
(
event
->
serio
);
break
;
case
SERIO_RECONNECT
:
if
(
event
->
serio
->
dev
&&
event
->
serio
->
dev
->
reconnect
)
if
(
event
->
serio
->
dev
->
reconnect
(
event
->
serio
)
==
0
)
break
;
/* reconnect failed - fall through to rescan */
case
SERIO_RESCAN
:
down
(
&
serio_sem
);
if
(
event
->
serio
->
dev
&&
event
->
serio
->
dev
->
disconnect
)
event
->
serio
->
dev
->
disconnect
(
event
->
serio
);
serio_find_dev
(
event
->
serio
);
up
(
&
serio_sem
);
break
;
default:
break
;
}
event_done:
up
(
&
serio_sem
);
list_del_init
(
node
);
kfree
(
event
);
}
...
...
@@ -130,18 +163,27 @@ static int serio_thread(void *nothing)
complete_and_exit
(
&
serio_exited
,
0
);
}
void
serio_rescan
(
struct
serio
*
serio
)
static
void
serio_queue_event
(
struct
serio
*
serio
,
int
event_type
)
{
struct
serio_event
*
event
;
if
(
!
(
event
=
kmalloc
(
sizeof
(
struct
serio_event
),
GFP_ATOMIC
)))
return
;
event
->
type
=
SERIO_RESCAN
;
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
);
}
}
void
serio_rescan
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_RESCAN
);
}
void
serio_reconnect
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_RECONNECT
);
}
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
...
...
@@ -163,17 +205,26 @@ irqreturn_t serio_interrupt(struct serio *serio,
void
serio_register_port
(
struct
serio
*
serio
)
{
down
(
&
serio_sem
);
list_add_tail
(
&
serio
->
node
,
&
serio_list
);
serio_find_dev
(
serio
);
__serio_register_port
(
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
* Submits register request to kseriod for subsequent execution.
* Can be used when it is not obvious whether the serio_sem is
* taken or not and when delayed execution is feasible.
*/
void
serio_register_port_delayed
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_REGISTER_PORT
);
}
/*
* Should only be called directly if serio_sem has already been taken,
* for example when unregistering a serio from other input device's
* connect() function.
*/
void
serio_register_slave
_port
(
struct
serio
*
serio
)
void
__serio_register
_port
(
struct
serio
*
serio
)
{
list_add_tail
(
&
serio
->
node
,
&
serio_list
);
serio_find_dev
(
serio
);
...
...
@@ -182,19 +233,28 @@ void serio_register_slave_port(struct serio *serio)
void
serio_unregister_port
(
struct
serio
*
serio
)
{
down
(
&
serio_sem
);
list_del_init
(
&
serio
->
node
);
if
(
serio
->
dev
&&
serio
->
dev
->
disconnect
)
serio
->
dev
->
disconnect
(
serio
);
__serio_unregister_port
(
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
* Submits unregister request to kseriod for subsequent execution.
* Can be used when it is not obvious whether the serio_sem is
* taken or not and when delayed execution is feasible.
*/
void
serio_unregister_port_delayed
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_UNREGISTER_PORT
);
}
/*
* Should only be called directly if serio_sem has already been taken,
* for example when unregistering a serio from other input device's
* disconnect() function.
*/
void
serio_unregister_slave
_port
(
struct
serio
*
serio
)
void
__serio_unregister
_port
(
struct
serio
*
serio
)
{
serio_invalidate_pending_events
(
serio
);
list_del_init
(
&
serio
->
node
);
if
(
serio
->
dev
&&
serio
->
dev
->
disconnect
)
serio
->
dev
->
disconnect
(
serio
);
...
...
drivers/usb/host/uhci-hcd.c
View file @
a76a8a35
...
...
@@ -2182,6 +2182,9 @@ static int uhci_reset(struct usb_hcd *hcd)
uhci
->
io_addr
=
(
unsigned
long
)
hcd
->
regs
;
/* Turn off all interrupts */
outw
(
0
,
uhci
->
io_addr
+
USBINTR
);
/* Maybe kick BIOS off this hardware. Then reset, so we won't get
* interrupts from any previous setup.
*/
...
...
include/asm-i386/irq.h
View file @
a76a8a35
...
...
@@ -24,6 +24,7 @@ extern void disable_irq(unsigned int);
extern
void
disable_irq_nosync
(
unsigned
int
);
extern
void
enable_irq
(
unsigned
int
);
extern
void
release_x86_irqs
(
struct
task_struct
*
);
extern
int
can_request_irq
(
unsigned
int
,
unsigned
long
flags
);
#ifdef CONFIG_X86_LOCAL_APIC
#define ARCH_HAS_NMI_WATCHDOG
/* See include/linux/nmi.h */
...
...
include/linux/input.h
View file @
a76a8a35
...
...
@@ -870,6 +870,7 @@ struct input_handler {
char
*
name
;
struct
input_device_id
*
id_table
;
struct
input_device_id
*
blacklist
;
struct
list_head
h_list
;
struct
list_head
node
;
...
...
include/linux/keyboard.h
View file @
a76a8a35
...
...
@@ -2,7 +2,6 @@
#define __LINUX_KEYBOARD_H
#include <linux/wait.h>
#include <linux/input.h>
#define KG_SHIFT 0
#define KG_CTRL 2
...
...
@@ -17,7 +16,7 @@
#define NR_SHIFT 9
#define NR_KEYS
(KEY_MAX+1)
#define NR_KEYS
255
#define MAX_NR_KEYMAPS 256
/* This means 128Kb if all keymaps are allocated. Only the superuser
may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
...
...
include/linux/serio.h
View file @
a76a8a35
...
...
@@ -49,6 +49,7 @@ struct serio_dev {
irqreturn_t
(
*
interrupt
)(
struct
serio
*
,
unsigned
char
,
unsigned
int
,
struct
pt_regs
*
);
void
(
*
connect
)(
struct
serio
*
,
struct
serio_dev
*
dev
);
int
(
*
reconnect
)(
struct
serio
*
);
void
(
*
disconnect
)(
struct
serio
*
);
void
(
*
cleanup
)(
struct
serio
*
);
...
...
@@ -58,12 +59,15 @@ struct serio_dev {
int
serio_open
(
struct
serio
*
serio
,
struct
serio_dev
*
dev
);
void
serio_close
(
struct
serio
*
serio
);
void
serio_rescan
(
struct
serio
*
serio
);
void
serio_reconnect
(
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_register_port_delayed
(
struct
serio
*
serio
);
void
__serio_register_port
(
struct
serio
*
serio
);
void
serio_unregister_port
(
struct
serio
*
serio
);
void
serio_unregister_slave_port
(
struct
serio
*
serio
);
void
serio_unregister_port_delayed
(
struct
serio
*
serio
);
void
__serio_unregister_port
(
struct
serio
*
serio
);
void
serio_register_device
(
struct
serio_dev
*
dev
);
void
serio_unregister_device
(
struct
serio_dev
*
dev
);
...
...
kernel/sched.c
View file @
a76a8a35
...
...
@@ -1470,6 +1470,7 @@ void scheduling_functions_start_here(void) { }
*/
asmlinkage
void
schedule
(
void
)
{
long
*
switch_count
;
task_t
*
prev
,
*
next
;
runqueue_t
*
rq
;
prio_array_t
*
array
;
...
...
@@ -1516,33 +1517,26 @@ asmlinkage void schedule(void)
* if entering off of a kernel preemption go straight
* to picking the next task.
*/
if
(
unlikely
(
preempt_count
()
&
PREEMPT_ACTIVE
))
goto
pick_next_task
;
switch
(
prev
->
state
)
{
case
TASK_INTERRUPTIBLE
:
if
(
unlikely
(
signal_pending
(
prev
)))
{
switch_count
=
&
prev
->
nivcsw
;
if
(
prev
->
state
&&
!
(
preempt_count
()
&
PREEMPT_ACTIVE
))
{
switch_count
=
&
prev
->
nvcsw
;
if
(
unlikely
((
prev
->
state
&
TASK_INTERRUPTIBLE
)
&&
unlikely
(
signal_pending
(
prev
))))
prev
->
state
=
TASK_RUNNING
;
break
;
}
default:
else
deactivate_task
(
prev
,
rq
);
prev
->
nvcsw
++
;
break
;
case
TASK_RUNNING
:
prev
->
nivcsw
++
;
}
pick_next_task:
if
(
unlikely
(
!
rq
->
nr_running
))
{
#ifdef CONFIG_SMP
load_balance
(
rq
,
1
,
cpu_to_node_mask
(
smp_processor_id
()));
if
(
rq
->
nr_running
)
goto
pick_next_task
;
#endif
if
(
!
rq
->
nr_running
)
{
next
=
rq
->
idle
;
rq
->
expired_timestamp
=
0
;
goto
switch_tasks
;
}
}
array
=
rq
->
active
;
if
(
unlikely
(
!
array
->
nr_active
))
{
...
...
@@ -1588,6 +1582,7 @@ asmlinkage void schedule(void)
next
->
timestamp
=
now
;
rq
->
nr_switches
++
;
rq
->
curr
=
next
;
++*
switch_count
;
prepare_arch_switch
(
rq
,
next
);
prev
=
context_switch
(
rq
,
prev
,
next
);
...
...
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