aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio/libps2.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-27 17:47:31 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-27 17:47:31 -0400
commit3e0777b8fa96f7073ed5d13d3bc1d573b766bef9 (patch)
tree3849e8457dd8f038ab7da025c708e275b43ea9c1 /drivers/input/serio/libps2.c
parenta94130e00038ebeb2f66901a4a4a9e05a03051c1 (diff)
parente5119885f00874453e837e3407014b73de2f4741 (diff)
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/dtor/input.git manually
Some manual fixups required due to clashes with the PF_FREEZE cleanups.
Diffstat (limited to 'drivers/input/serio/libps2.c')
-rw-r--r--drivers/input/serio/libps2.c136
1 files changed, 100 insertions, 36 deletions
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index c978657068c5..d4c990f7c85e 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -29,6 +29,7 @@ MODULE_LICENSE("GPL");
29 29
30EXPORT_SYMBOL(ps2_init); 30EXPORT_SYMBOL(ps2_init);
31EXPORT_SYMBOL(ps2_sendbyte); 31EXPORT_SYMBOL(ps2_sendbyte);
32EXPORT_SYMBOL(ps2_drain);
32EXPORT_SYMBOL(ps2_command); 33EXPORT_SYMBOL(ps2_command);
33EXPORT_SYMBOL(ps2_schedule_command); 34EXPORT_SYMBOL(ps2_schedule_command);
34EXPORT_SYMBOL(ps2_handle_ack); 35EXPORT_SYMBOL(ps2_handle_ack);
@@ -45,11 +46,11 @@ struct ps2work {
45 46
46 47
47/* 48/*
48 * ps2_sendbyte() sends a byte to the mouse, and waits for acknowledge. 49 * ps2_sendbyte() sends a byte to the device and waits for acknowledge.
49 * It doesn't handle retransmission, though it could - because when there would 50 * It doesn't handle retransmission, though it could - because if there
50 * be need for retransmissions, the mouse has to be replaced anyway. 51 * is a need for retransmissions device has to be replaced anyway.
51 * 52 *
52 * ps2_sendbyte() can only be called from a process context 53 * ps2_sendbyte() can only be called from a process context.
53 */ 54 */
54 55
55int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) 56int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout)
@@ -72,6 +73,91 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout)
72} 73}
73 74
74/* 75/*
76 * ps2_drain() waits for device to transmit requested number of bytes
77 * and discards them.
78 */
79
80void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
81{
82 if (maxbytes > sizeof(ps2dev->cmdbuf)) {
83 WARN_ON(1);
84 maxbytes = sizeof(ps2dev->cmdbuf);
85 }
86
87 down(&ps2dev->cmd_sem);
88
89 serio_pause_rx(ps2dev->serio);
90 ps2dev->flags = PS2_FLAG_CMD;
91 ps2dev->cmdcnt = maxbytes;
92 serio_continue_rx(ps2dev->serio);
93
94 wait_event_timeout(ps2dev->wait,
95 !(ps2dev->flags & PS2_FLAG_CMD),
96 msecs_to_jiffies(timeout));
97 up(&ps2dev->cmd_sem);
98}
99
100/*
101 * ps2_is_keyboard_id() checks received ID byte against the list of
102 * known keyboard IDs.
103 */
104
105static inline int ps2_is_keyboard_id(char id_byte)
106{
107 static char keyboard_ids[] = {
108 0xab, /* Regular keyboards */
109 0xac, /* NCD Sun keyboard */
110 0x2b, /* Trust keyboard, translated */
111 0x5d, /* Trust keyboard */
112 0x60, /* NMB SGI keyboard, translated */
113 0x47, /* NMB SGI keyboard */
114 };
115
116 return memchr(keyboard_ids, id_byte, sizeof(keyboard_ids)) != NULL;
117}
118
119/*
120 * ps2_adjust_timeout() is called after receiving 1st byte of command
121 * response and tries to reduce remaining timeout to speed up command
122 * completion.
123 */
124
125static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout)
126{
127 switch (command) {
128 case PS2_CMD_RESET_BAT:
129 /*
130 * Device has sent the first response byte after
131 * reset command, reset is thus done, so we can
132 * shorten the timeout.
133 * The next byte will come soon (keyboard) or not
134 * at all (mouse).
135 */
136 if (timeout > msecs_to_jiffies(100))
137 timeout = msecs_to_jiffies(100);
138 break;
139
140 case PS2_CMD_GETID:
141 /*
142 * If device behind the port is not a keyboard there
143 * won't be 2nd byte of ID response.
144 */
145 if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) {
146 serio_pause_rx(ps2dev->serio);
147 ps2dev->flags = ps2dev->cmdcnt = 0;
148 serio_continue_rx(ps2dev->serio);
149 timeout = 0;
150 }
151 break;
152
153 default:
154 break;
155 }
156
157 return timeout;
158}
159
160/*
75 * ps2_command() sends a command and its parameters to the mouse, 161 * ps2_command() sends a command and its parameters to the mouse,
76 * then waits for the response and puts it in the param array. 162 * then waits for the response and puts it in the param array.
77 * 163 *
@@ -86,6 +172,11 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
86 int rc = -1; 172 int rc = -1;
87 int i; 173 int i;
88 174
175 if (receive > sizeof(ps2dev->cmdbuf)) {
176 WARN_ON(1);
177 return -1;
178 }
179
89 down(&ps2dev->cmd_sem); 180 down(&ps2dev->cmd_sem);
90 181
91 serio_pause_rx(ps2dev->serio); 182 serio_pause_rx(ps2dev->serio);
@@ -101,10 +192,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
101 * ACKing the reset command, and so it can take a long 192 * ACKing the reset command, and so it can take a long
102 * time before the ACK arrrives. 193 * time before the ACK arrrives.
103 */ 194 */
104 if (command & 0xff) 195 if (ps2_sendbyte(ps2dev, command & 0xff,
105 if (ps2_sendbyte(ps2dev, command & 0xff, 196 command == PS2_CMD_RESET_BAT ? 1000 : 200))
106 command == PS2_CMD_RESET_BAT ? 1000 : 200)) 197 goto out;
107 goto out;
108 198
109 for (i = 0; i < send; i++) 199 for (i = 0; i < send; i++)
110 if (ps2_sendbyte(ps2dev, param[i], 200)) 200 if (ps2_sendbyte(ps2dev, param[i], 200))
@@ -120,33 +210,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
120 210
121 if (ps2dev->cmdcnt && timeout > 0) { 211 if (ps2dev->cmdcnt && timeout > 0) {
122 212
123 if (command == PS2_CMD_RESET_BAT && timeout > msecs_to_jiffies(100)) { 213 timeout = ps2_adjust_timeout(ps2dev, command, timeout);
124 /*
125 * Device has sent the first response byte
126 * after a reset command, reset is thus done,
127 * shorten the timeout. The next byte will come
128 * soon (keyboard) or not at all (mouse).
129 */
130 timeout = msecs_to_jiffies(100);
131 }
132
133 if (command == PS2_CMD_GETID &&
134 ps2dev->cmdbuf[receive - 1] != 0xab && /* Regular keyboards */
135 ps2dev->cmdbuf[receive - 1] != 0xac && /* NCD Sun keyboard */
136 ps2dev->cmdbuf[receive - 1] != 0x2b && /* Trust keyboard, translated */
137 ps2dev->cmdbuf[receive - 1] != 0x5d && /* Trust keyboard */
138 ps2dev->cmdbuf[receive - 1] != 0x60 && /* NMB SGI keyboard, translated */
139 ps2dev->cmdbuf[receive - 1] != 0x47) { /* NMB SGI keyboard */
140 /*
141 * Device behind the port is not a keyboard
142 * so we don't need to wait for the 2nd byte
143 * of ID response.
144 */
145 serio_pause_rx(ps2dev->serio);
146 ps2dev->flags = ps2dev->cmdcnt = 0;
147 serio_continue_rx(ps2dev->serio);
148 }
149
150 wait_event_timeout(ps2dev->wait, 214 wait_event_timeout(ps2dev->wait,
151 !(ps2dev->flags & PS2_FLAG_CMD), timeout); 215 !(ps2dev->flags & PS2_FLAG_CMD), timeout);
152 } 216 }
@@ -160,7 +224,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
160 224
161 rc = 0; 225 rc = 0;
162 226
163out: 227 out:
164 serio_pause_rx(ps2dev->serio); 228 serio_pause_rx(ps2dev->serio);
165 ps2dev->flags = 0; 229 ps2dev->flags = 0;
166 serio_continue_rx(ps2dev->serio); 230 serio_continue_rx(ps2dev->serio);