diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-06-01 03:39:53 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-06-01 03:39:53 -0400 |
commit | 905ab9d13694d0f75d1cb8c076ff2027538312ce (patch) | |
tree | d1747ada83e657a814aa045cfdddeb1b00e25d95 /drivers | |
parent | c611763d048990de5cdf848d97af6392f8fa7430 (diff) |
Input: cleanup ps2_command() timeout handling in libps2.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/serio/libps2.c | 90 |
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 | |||
105 | static 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 | |||
125 | static 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 | ||
193 | out: | 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); |