aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorMarvin Raaijmakers <marvin_raaijmakers@linux-box.nl>2007-03-14 22:50:42 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-03-14 22:50:42 -0400
commitc8e4c77277ca5db0c4ddbfb4bc628b8abad585b0 (patch)
tree07bebb34767c8c3bd0902d6c2be3f4819b30a7bf /drivers/input
parent55e3d9224b60df0fd2dc36bff9b538ce40fd9586 (diff)
Input: add getkeycode and setkeycode methods
Allow drivers to implement their own get and set keycode methods. This will allow drivers to change their keymaps without allocating huge tables covering entire range of possible scancodes. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/evdev.c29
-rw-r--r--drivers/input/input.c87
2 files changed, 96 insertions, 20 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 6439f378f6cc..64b47de052bb 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -434,32 +434,21 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
434 case EVIOCGKEYCODE: 434 case EVIOCGKEYCODE:
435 if (get_user(t, ip)) 435 if (get_user(t, ip))
436 return -EFAULT; 436 return -EFAULT;
437 if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) 437
438 return -EINVAL; 438 error = dev->getkeycode(dev, t, &v);
439 if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) 439 if (error)
440 return error;
441
442 if (put_user(v, ip + 1))
440 return -EFAULT; 443 return -EFAULT;
444
441 return 0; 445 return 0;
442 446
443 case EVIOCSKEYCODE: 447 case EVIOCSKEYCODE:
444 if (get_user(t, ip)) 448 if (get_user(t, ip) || get_user(v, ip + 1))
445 return -EFAULT;
446 if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
447 return -EINVAL;
448 if (get_user(v, ip + 1))
449 return -EFAULT; 449 return -EFAULT;
450 if (v < 0 || v > KEY_MAX)
451 return -EINVAL;
452 if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8)))
453 return -EINVAL;
454
455 u = SET_INPUT_KEYCODE(dev, t, v);
456 clear_bit(u, dev->keybit);
457 set_bit(v, dev->keybit);
458 for (i = 0; i < dev->keycodemax; i++)
459 if (INPUT_KEYCODE(dev, i) == u)
460 set_bit(u, dev->keybit);
461 450
462 return 0; 451 return dev->setkeycode(dev, t, v);
463 452
464 case EVIOCSFF: 453 case EVIOCSFF:
465 if (copy_from_user(&effect, p, sizeof(effect))) 454 if (copy_from_user(&effect, p, sizeof(effect)))
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 4486402fbf5d..26393a606e6f 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -299,6 +299,87 @@ void input_close_device(struct input_handle *handle)
299} 299}
300EXPORT_SYMBOL(input_close_device); 300EXPORT_SYMBOL(input_close_device);
301 301
302static int input_fetch_keycode(struct input_dev *dev, int scancode)
303{
304 switch (dev->keycodesize) {
305 case 1:
306 return ((u8 *)dev->keycode)[scancode];
307
308 case 2:
309 return ((u16 *)dev->keycode)[scancode];
310
311 default:
312 return ((u32 *)dev->keycode)[scancode];
313 }
314}
315
316static int input_default_getkeycode(struct input_dev *dev,
317 int scancode, int *keycode)
318{
319 if (!dev->keycodesize)
320 return -EINVAL;
321
322 if (scancode < 0 || scancode >= dev->keycodemax)
323 return -EINVAL;
324
325 *keycode = input_fetch_keycode(dev, scancode);
326
327 return 0;
328}
329
330static int input_default_setkeycode(struct input_dev *dev,
331 int scancode, int keycode)
332{
333 int old_keycode;
334 int i;
335
336 if (scancode < 0 || scancode >= dev->keycodemax)
337 return -EINVAL;
338
339 if (keycode < 0 || keycode > KEY_MAX)
340 return -EINVAL;
341
342 if (!dev->keycodesize)
343 return -EINVAL;
344
345 if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
346 return -EINVAL;
347
348 switch (dev->keycodesize) {
349 case 1: {
350 u8 *k = (u8 *)dev->keycode;
351 old_keycode = k[scancode];
352 k[scancode] = keycode;
353 break;
354 }
355 case 2: {
356 u16 *k = (u16 *)dev->keycode;
357 old_keycode = k[scancode];
358 k[scancode] = keycode;
359 break;
360 }
361 default: {
362 u32 *k = (u32 *)dev->keycode;
363 old_keycode = k[scancode];
364 k[scancode] = keycode;
365 break;
366 }
367 }
368
369 clear_bit(old_keycode, dev->keybit);
370 set_bit(keycode, dev->keybit);
371
372 for (i = 0; i < dev->keycodemax; i++) {
373 if (input_fetch_keycode(dev, i) == old_keycode) {
374 set_bit(old_keycode, dev->keybit);
375 break; /* Setting the bit twice is useless, so break */
376 }
377 }
378
379 return 0;
380}
381
382
302static void input_link_handle(struct input_handle *handle) 383static void input_link_handle(struct input_handle *handle)
303{ 384{
304 list_add_tail(&handle->d_node, &handle->dev->h_list); 385 list_add_tail(&handle->d_node, &handle->dev->h_list);
@@ -978,6 +1059,12 @@ int input_register_device(struct input_dev *dev)
978 dev->rep[REP_PERIOD] = 33; 1059 dev->rep[REP_PERIOD] = 33;
979 } 1060 }
980 1061
1062 if (!dev->getkeycode)
1063 dev->getkeycode = input_default_getkeycode;
1064
1065 if (!dev->setkeycode)
1066 dev->setkeycode = input_default_setkeycode;
1067
981 list_add_tail(&dev->node, &input_dev_list); 1068 list_add_tail(&dev->node, &input_dev_list);
982 1069
983 snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id), 1070 snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),