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
Kirill Smelkov
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
Hide 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,11 +756,8 @@ 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
);
...
...
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
)
{
put_queue
(
vc
,
0xe1
);
put_queue
(
vc
,
0x1d
|
up_flag
);
put_queue
(
vc
,
0x45
|
up_flag
);
return
0
;
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,9 +447,10 @@ 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
((
id
=
input_match_device
(
handler
->
id_table
,
dev
)))
if
((
handle
=
handler
->
connect
(
handler
,
dev
,
id
)))
input_link_handle
(
handle
);
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
);
#ifdef CONFIG_HOTPLUG
input_call_hotplug
(
"add"
,
dev
);
...
...
@@ -507,9 +508,10 @@ 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
((
id
=
input_match_device
(
handler
->
id_table
,
dev
)))
if
((
handle
=
handler
->
connect
(
handler
,
dev
,
id
)))
input_link_handle
(
handle
);
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
);
#ifdef CONFIG_PROC_FS
input_devices_state
++
;
...
...
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,25 +80,21 @@ 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
]
=
{
0
,
118
,
22
,
30
,
38
,
37
,
46
,
54
,
61
,
62
,
70
,
69
,
78
,
85
,
102
,
13
,
21
,
29
,
36
,
45
,
44
,
53
,
60
,
67
,
68
,
77
,
84
,
91
,
90
,
20
,
28
,
27
,
35
,
43
,
52
,
51
,
59
,
66
,
75
,
76
,
82
,
14
,
18
,
93
,
26
,
34
,
33
,
42
,
50
,
49
,
58
,
65
,
73
,
74
,
89
,
124
,
17
,
41
,
88
,
5
,
6
,
4
,
12
,
3
,
11
,
2
,
10
,
1
,
9
,
119
,
126
,
108
,
117
,
125
,
123
,
107
,
115
,
116
,
121
,
105
,
114
,
122
,
112
,
113
,
127
,
96
,
97
,
120
,
7
,
15
,
23
,
31
,
39
,
47
,
55
,
63
,
71
,
79
,
86
,
94
,
8
,
16
,
24
,
32
,
40
,
48
,
56
,
64
,
72
,
80
,
87
,
111
,
19
,
25
,
57
,
81
,
83
,
92
,
95
,
98
,
99
,
100
,
101
,
103
,
104
,
106
,
109
,
110
0
,
118
,
22
,
30
,
38
,
37
,
46
,
54
,
61
,
62
,
70
,
69
,
78
,
85
,
102
,
13
,
21
,
29
,
36
,
45
,
44
,
53
,
60
,
67
,
68
,
77
,
84
,
91
,
90
,
20
,
28
,
27
,
35
,
43
,
52
,
51
,
59
,
66
,
75
,
76
,
82
,
14
,
18
,
93
,
26
,
34
,
33
,
42
,
50
,
49
,
58
,
65
,
73
,
74
,
89
,
124
,
17
,
41
,
88
,
5
,
6
,
4
,
12
,
3
,
11
,
2
,
10
,
1
,
9
,
119
,
126
,
108
,
117
,
125
,
123
,
107
,
115
,
116
,
121
,
105
,
114
,
122
,
112
,
113
,
127
,
96
,
97
,
120
,
7
,
15
,
23
,
31
,
39
,
47
,
55
,
63
,
71
,
79
,
86
,
94
,
8
,
16
,
24
,
32
,
40
,
48
,
56
,
64
,
72
,
80
,
87
,
111
,
19
,
25
,
57
,
81
,
83
,
92
,
95
,
98
,
99
,
100
,
101
,
103
,
104
,
106
,
109
,
110
};
#define ATKBD_CMD_SETLEDS 0x10ed
...
...
@@ -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,47 +191,37 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd
->
resend
=
0
;
#endif
switch
(
code
)
{
case
ATKBD_RET_ACK
:
atkbd
->
ack
=
1
;
goto
out
;
case
ATKBD_RET_NAK
:
atkbd
->
ack
=
-
1
;
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
(
!
atkbd
->
ack
)
switch
(
code
)
{
case
ATKBD_RET_ACK
:
atkbd
->
ack
=
1
;
goto
out
;
case
ATKBD_RET_NAK
:
atkbd
->
ack
=
-
1
;
goto
out
;
}
if
(
code
<
0x80
)
{
code
=
atkbd_unxlate_table
[
code
];
break
;
}
if
(
atkbd
->
cmdcnt
)
break
;
code
=
atkbd_unxlate_table
[
code
&
0x7f
];
atkbd
->
release
=
1
;
}
while
(
0
);
if
(
atkbd
->
cmdcnt
)
{
atkbd
->
cmdbuf
[
--
atkbd
->
cmdcnt
]
=
code
;
goto
out
;
}
if
(
atkbd
->
translated
)
{
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
->
emul
&&
(
code
&
0x7f
)
==
(
ATKBD_RET_BAT
&
0x7f
))
atkbd
->
bat_xl
=
!
atkbd
->
release
;
}
switch
(
code
)
{
case
ATKBD_RET_BAT
:
serio_rescan
(
atkbd
->
serio
);
...
...
@@ -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
;
...
...
@@ -256,6 +266,59 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
return
0
;
}
/*
* Genius NetMouse magic init.
*/
static
int
genius_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
param
[
0
]
=
3
;
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
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
return
param
[
0
]
==
0x00
&&
param
[
1
]
==
0x33
&&
param
[
2
]
==
0x55
;
}
/*
* IntelliMouse magic init.
*/
static
int
intellimouse_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
2
];
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
100
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
80
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETID
);
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
);
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
80
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETID
);
return
param
[
0
]
==
4
;
}
/*
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
* the mouse may have.
...
...
@@ -263,49 +326,33 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
static
int
psmouse_extensions
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
]
;
int
synaptics_hardware
=
0
;
param
[
0
]
=
0
;
psmouse
->
vendor
=
"Generic"
;
psmouse
->
name
=
"Mouse"
;
psmouse
->
model
=
0
;
if
(
psmouse_noext
)
return
PSMOUSE_PS2
;
/*
* Try Synaptics TouchPad
magic ID
* Try Synaptics TouchPad
*/
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
)
{
if
(
psmouse_max_proto
>
PSMOUSE_PS2
&&
synaptics_detect
(
psmouse
))
{
synaptics_hardware
=
1
;
psmouse
->
vendor
=
"Synaptics"
;
psmouse
->
name
=
"TouchPad"
;
if
(
!
synaptics_init
(
psmouse
))
return
PSMOUSE_SYNAPTICS
;
else
return
PSMOUSE_PS2
;
}
if
(
psmouse_max_proto
>
PSMOUSE_IMEX
)
{
if
(
synaptics_init
(
psmouse
)
==
0
)
return
PSMOUSE_SYNAPTICS
;
/*
* Try Genius NetMouse magic init.
* 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
;
}
}
param
[
0
]
=
3
;
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
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
if
(
param
[
0
]
==
0x00
&&
param
[
1
]
==
0x33
&&
param
[
2
]
==
0x55
)
{
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
);
...
...
@@ -315,54 +362,17 @@ static int psmouse_extensions(struct psmouse *psmouse)
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
(
psmouse_max_proto
>
PSMOUSE_IMEX
)
{
int
type
=
ps2pp_detect
(
psmouse
);
if
(
type
)
return
type
;
}
/*
* Try IntelliMouse magic init.
*/
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
100
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
80
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETID
);
if
(
param
[
0
]
==
3
)
{
if
(
psmouse_max_proto
>=
PSMOUSE_IMPS
&&
intellimouse_detect
(
psmouse
))
{
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
/*
* Try IntelliMouse/Explorer magic init.
*/
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
80
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETID
);
if
(
param
[
0
]
==
4
)
{
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
);
/* We need to reopen the serio port to reinitialize the i8042 controller */
serio_close
(
psmouse
->
serio
);
serio_open
(
psmouse
->
serio
,
ser_dev
);
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
;
}
/* Probe and re-initialize the mouse */
psmouse_probe
(
psmouse
);
psmouse_initialize
(
psmouse
);
synaptics_pt_init
(
psmouse
);
psmouse_activate
(
psmouse
);
if
(
psmouse
->
disconnect
)
psmouse
->
disconnect
(
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
)
static
inline
void
psmouse_parse_proto
(
void
)
{
get_option
(
&
str
,
&
psmouse_smartscroll
);
return
1
;
}
static
int
__init
psmouse_resetafter_setup
(
char
*
str
)
{
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,27 +366,82 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
clear_bit
(
REL_Y
,
dev
->
relbit
);
}
static
void
synaptics_disconnect
(
struct
psmouse
*
psmouse
)
{
synaptics_mode_cmd
(
psmouse
,
0
);
kfree
(
psmouse
->
private
);
}
static
int
synaptics_reconnect
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
struct
synaptics_data
old_priv
=
*
priv
;
if
(
!
synaptics_detect
(
psmouse
))
return
-
1
;
if
(
synaptics_query_hardware
(
psmouse
))
{
printk
(
KERN_ERR
"Unable to query Synaptics hardware.
\n
"
);
return
-
1
;
}
if
(
old_priv
.
identity
!=
priv
->
identity
||
old_priv
.
model_id
!=
priv
->
model_id
||
old_priv
.
capabilities
!=
priv
->
capabilities
||
old_priv
.
ext_cap
!=
priv
->
ext_cap
)
return
-
1
;
if
(
synaptics_set_mode
(
psmouse
,
0
))
{
printk
(
KERN_ERR
"Unable to initialize Synaptics hardware.
\n
"
);
return
-
1
;
}
return
0
;
}
int
synaptics_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
return
param
[
1
]
==
0x47
;
}
int
synaptics_init
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
;
#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
));
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
;
}
else
if
(
psmouse
->
pktcnt
&&
!
synaptics_validate_byte
(
psmouse
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at byte %d
\n
"
,
psmouse
->
pktcnt
);
psmouse
->
pktcnt
=
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
);
if
(
++
priv
->
out_of_sync
==
psmouse_resetafter
)
{
psmouse
->
state
=
PSMOUSE_IGNORE
;
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_nomux
=
1
;
return
1
;
}
static
int
__init
i8042_setup_unlock
(
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
)
{
i8042_unlock
=
1
;
return
1
;
if
(
i8042_noaux
)
i8042_nomux
=
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
;
...
...
@@ -82,11 +85,23 @@ static void serio_find_dev(struct serio *serio)
}
}
#define SERIO_RESCAN 1
#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
;
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
);
}
}
event
->
type
=
SERIO_RESCAN
;
event
->
serio
=
serio
;
void
serio_rescan
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_RESCAN
);
}
list_add_tail
(
&
event
->
node
,
&
serio_event_list
);
wake_up
(
&
serio_wait
);
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,32 +1517,25 @@ 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:
deactivate_task
(
prev
,
rq
);
prev
->
nvcsw
++
;
break
;
case
TASK_RUNNING
:
prev
->
nivcsw
++
;
else
deactivate_task
(
prev
,
rq
);
}
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
next
=
rq
->
idle
;
rq
->
expired_timestamp
=
0
;
goto
switch_tasks
;
if
(
!
rq
->
nr_running
)
{
next
=
rq
->
idle
;
rq
->
expired_timestamp
=
0
;
goto
switch_tasks
;
}
}
array
=
rq
->
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