aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/keyboard.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2010-09-10 00:54:22 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-09-10 01:00:50 -0400
commit8613e4c2872a87cc309a42de2c7091744dc54d0e (patch)
tree75b6513268aca8b614f3b2a55421c7a07b4a9899 /drivers/char/keyboard.c
parenta4e6aad64735702256e4feaa4724eb776ca4e637 (diff)
Input: add support for large scancodes
Several devices use a high number of bits for scancodes. One important group is the Remote Controllers. Some new protocols like RC-6 define a scancode space of 64 bits. The current EVIO[CS]GKEYCODE ioctls allow replace the scancode/keycode translation tables, but it is limited to up to 32 bits for scancode. Also, if userspace wants to clean the existing table, replacing it by a new one, it needs to run a loop calling the ioctls over the entire sparse scancode space. To solve those problems, this patch extends the ioctls to allow drivers handle scancodes up to 32 bytes long (the length could be extended in the future should such need arise) and allow userspace to query and set scancode to keycode mappings not only by scancode but also by index. Compatibility code were also added to handle the old format of EVIO[CS]GKEYCODE ioctls. Folded fixes by: - Dan Carpenter: locking fixes for the original implementation - Jarod Wilson: fix crash when setting keycode and wiring up get/set handlers in original implementation. - Dmitry Torokhov: rework to consolidate old and new scancode handling, provide options to act either by index or scancode. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Dan Carpenter <error27@gmail.com> Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/char/keyboard.c')
-rw-r--r--drivers/char/keyboard.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index a7ca75212bfe..e95d7876ca6b 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -175,8 +175,7 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
175 */ 175 */
176 176
177struct getset_keycode_data { 177struct getset_keycode_data {
178 unsigned int scancode; 178 struct input_keymap_entry ke;
179 unsigned int keycode;
180 int error; 179 int error;
181}; 180};
182 181
@@ -184,32 +183,50 @@ static int getkeycode_helper(struct input_handle *handle, void *data)
184{ 183{
185 struct getset_keycode_data *d = data; 184 struct getset_keycode_data *d = data;
186 185
187 d->error = input_get_keycode(handle->dev, d->scancode, &d->keycode); 186 d->error = input_get_keycode(handle->dev, &d->ke);
188 187
189 return d->error == 0; /* stop as soon as we successfully get one */ 188 return d->error == 0; /* stop as soon as we successfully get one */
190} 189}
191 190
192int getkeycode(unsigned int scancode) 191int getkeycode(unsigned int scancode)
193{ 192{
194 struct getset_keycode_data d = { scancode, 0, -ENODEV }; 193 struct getset_keycode_data d = {
194 .ke = {
195 .flags = 0,
196 .len = sizeof(scancode),
197 .keycode = 0,
198 },
199 .error = -ENODEV,
200 };
201
202 memcpy(d.ke.scancode, &scancode, sizeof(scancode));
195 203
196 input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper); 204 input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
197 205
198 return d.error ?: d.keycode; 206 return d.error ?: d.ke.keycode;
199} 207}
200 208
201static int setkeycode_helper(struct input_handle *handle, void *data) 209static int setkeycode_helper(struct input_handle *handle, void *data)
202{ 210{
203 struct getset_keycode_data *d = data; 211 struct getset_keycode_data *d = data;
204 212
205 d->error = input_set_keycode(handle->dev, d->scancode, d->keycode); 213 d->error = input_set_keycode(handle->dev, &d->ke);
206 214
207 return d->error == 0; /* stop as soon as we successfully set one */ 215 return d->error == 0; /* stop as soon as we successfully set one */
208} 216}
209 217
210int setkeycode(unsigned int scancode, unsigned int keycode) 218int setkeycode(unsigned int scancode, unsigned int keycode)
211{ 219{
212 struct getset_keycode_data d = { scancode, keycode, -ENODEV }; 220 struct getset_keycode_data d = {
221 .ke = {
222 .flags = 0,
223 .len = sizeof(scancode),
224 .keycode = keycode,
225 },
226 .error = -ENODEV,
227 };
228
229 memcpy(d.ke.scancode, &scancode, sizeof(scancode));
213 230
214 input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper); 231 input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
215 232