aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor_core@ameritech.net>2005-06-01 03:39:53 -0400
committerDmitry Torokhov <dtor_core@ameritech.net>2005-06-01 03:39:53 -0400
commit905ab9d13694d0f75d1cb8c076ff2027538312ce (patch)
treed1747ada83e657a814aa045cfdddeb1b00e25d95 /drivers/input
parentc611763d048990de5cdf848d97af6392f8fa7430 (diff)
Input: cleanup ps2_command() timeout handling in libps2.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/serio/libps2.c90
1 files changed, 62 insertions, 28 deletions
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 92b92ee03791..d4c990f7c85e 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -98,6 +98,66 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
98} 98}
99 99
100/* 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/*
101 * ps2_command() sends a command and its parameters to the mouse, 161 * ps2_command() sends a command and its parameters to the mouse,
102 * 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.
103 * 163 *
@@ -150,33 +210,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
150 210
151 if (ps2dev->cmdcnt && timeout > 0) { 211 if (ps2dev->cmdcnt && timeout > 0) {
152 212
153 if (command == PS2_CMD_RESET_BAT && timeout > msecs_to_jiffies(100)) { 213 timeout = ps2_adjust_timeout(ps2dev, command, timeout);
154 /*
155 * Device has sent the first response byte
156 * after a reset command, reset is thus done,
157 * shorten the timeout. The next byte will come
158 * soon (keyboard) or not at all (mouse).
159 */
160 timeout = msecs_to_jiffies(100);
161 }
162
163 if (command == PS2_CMD_GETID &&
164 ps2dev->cmdbuf[receive - 1] != 0xab && /* Regular keyboards */
165 ps2dev->cmdbuf[receive - 1] != 0xac && /* NCD Sun keyboard */
166 ps2dev->cmdbuf[receive - 1] != 0x2b && /* Trust keyboard, translated */
167 ps2dev->cmdbuf[receive - 1] != 0x5d && /* Trust keyboard */
168 ps2dev->cmdbuf[receive - 1] != 0x60 && /* NMB SGI keyboard, translated */
169 ps2dev->cmdbuf[receive - 1] != 0x47) { /* NMB SGI keyboard */
170 /*
171 * Device behind the port is not a keyboard
172 * so we don't need to wait for the 2nd byte
173 * of ID response.
174 */
175 serio_pause_rx(ps2dev->serio);
176 ps2dev->flags = ps2dev->cmdcnt = 0;
177 serio_continue_rx(ps2dev->serio);
178 }
179
180 wait_event_timeout(ps2dev->wait, 214 wait_event_timeout(ps2dev->wait,
181 !(ps2dev->flags & PS2_FLAG_CMD), timeout); 215 !(ps2dev->flags & PS2_FLAG_CMD), timeout);
182 } 216 }
@@ -190,7 +224,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
190 224
191 rc = 0; 225 rc = 0;
192 226
193out: 227 out:
194 serio_pause_rx(ps2dev->serio); 228 serio_pause_rx(ps2dev->serio);
195 ps2dev->flags = 0; 229 ps2dev->flags = 0;
196 serio_continue_rx(ps2dev->serio); 230 serio_continue_rx(ps2dev->serio);