aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/input.c156
1 files changed, 133 insertions, 23 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ceaed631d49f..57fbfd907157 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -434,6 +434,23 @@ static void input_call_hotplug(char *verb, struct input_dev *dev)
434 434
435#endif 435#endif
436 436
437static int input_print_bitmap(char *buf, unsigned long *bitmap, int max)
438{
439 int i;
440 int len = 0;
441
442 for (i = NBITS(max) - 1; i > 0; i--)
443 if (bitmap[i])
444 break;
445
446 for (; i >= 0; i--)
447 len += sprintf(buf + len, "%lx%s", bitmap[i], i > 0 ? " " : "");
448
449 len += sprintf(buf + len, "\n");
450
451 return len;
452}
453
437#ifdef CONFIG_PROC_FS 454#ifdef CONFIG_PROC_FS
438 455
439static struct proc_dir_entry *proc_bus_input_dir; 456static struct proc_dir_entry *proc_bus_input_dir;
@@ -455,20 +472,17 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait)
455 return 0; 472 return 0;
456} 473}
457 474
458#define SPRINTF_BIT_B(bit, name, max) \ 475#define SPRINTF_BIT_B(ev, bm) \
459 do { \ 476 do { \
460 len += sprintf(buf + len, "B: %s", name); \ 477 len += sprintf(buf + len, "B: %s=", #ev); \
461 for (i = NBITS(max) - 1; i >= 0; i--) \ 478 len += input_print_bitmap(buf + len, \
462 if (dev->bit[i]) break; \ 479 dev->bm##bit, ev##_MAX); \
463 for (; i >= 0; i--) \
464 len += sprintf(buf + len, "%lx ", dev->bit[i]); \
465 len += sprintf(buf + len, "\n"); \
466 } while (0) 480 } while (0)
467 481
468#define SPRINTF_BIT_B2(bit, name, max, ev) \ 482#define SPRINTF_BIT_B2(ev, bm) \
469 do { \ 483 do { \
470 if (test_bit(ev, dev->evbit)) \ 484 if (test_bit(EV_##ev, dev->evbit)) \
471 SPRINTF_BIT_B(bit, name, max); \ 485 SPRINTF_BIT_B(ev, bm); \
472 } while (0) 486 } while (0)
473 487
474static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) 488static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
@@ -478,7 +492,7 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int
478 const char *path; 492 const char *path;
479 493
480 off_t at = 0; 494 off_t at = 0;
481 int i, len, cnt = 0; 495 int len, cnt = 0;
482 496
483 list_for_each_entry(dev, &input_dev_list, node) { 497 list_for_each_entry(dev, &input_dev_list, node) {
484 498
@@ -497,15 +511,15 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int
497 511
498 len += sprintf(buf + len, "\n"); 512 len += sprintf(buf + len, "\n");
499 513
500 SPRINTF_BIT_B(evbit, "EV=", EV_MAX); 514 SPRINTF_BIT_B(EV, ev);
501 SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY); 515 SPRINTF_BIT_B2(KEY, key);
502 SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL); 516 SPRINTF_BIT_B2(REL, rel);
503 SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS); 517 SPRINTF_BIT_B2(ABS, abs);
504 SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC); 518 SPRINTF_BIT_B2(MSC, msc);
505 SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED); 519 SPRINTF_BIT_B2(LED, led);
506 SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND); 520 SPRINTF_BIT_B2(SND, snd);
507 SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF); 521 SPRINTF_BIT_B2(FF, ff);
508 SPRINTF_BIT_B2(swbit, "SW=", SW_MAX, EV_SW); 522 SPRINTF_BIT_B2(SW, sw);
509 523
510 len += sprintf(buf + len, "\n"); 524 len += sprintf(buf + len, "\n");
511 525
@@ -612,6 +626,96 @@ static inline int input_proc_init(void) { return 0; }
612static inline void input_proc_exit(void) { } 626static inline void input_proc_exit(void) { }
613#endif 627#endif
614 628
629#define INPUT_DEV_STRING_ATTR_SHOW(name) \
630static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
631{ \
632 struct input_dev *input_dev = to_input_dev(dev); \
633 int retval; \
634 \
635 retval = down_interruptible(&input_dev->sem); \
636 if (retval) \
637 return retval; \
638 \
639 retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : ""); \
640 \
641 up(&input_dev->sem); \
642 \
643 return retval; \
644}
645
646INPUT_DEV_STRING_ATTR_SHOW(name);
647INPUT_DEV_STRING_ATTR_SHOW(phys);
648INPUT_DEV_STRING_ATTR_SHOW(uniq);
649
650static struct class_device_attribute input_dev_attrs[] = {
651 __ATTR(name, S_IRUGO, input_dev_show_name, NULL),
652 __ATTR(phys, S_IRUGO, input_dev_show_phys, NULL),
653 __ATTR(uniq, S_IRUGO, input_dev_show_uniq, NULL),
654 __ATTR_NULL
655};
656
657#define INPUT_DEV_ID_ATTR(name) \
658static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \
659{ \
660 struct input_dev *input_dev = to_input_dev(dev); \
661 return sprintf(buf, "%04x\n", input_dev->id.name); \
662} \
663static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
664
665INPUT_DEV_ID_ATTR(bustype);
666INPUT_DEV_ID_ATTR(vendor);
667INPUT_DEV_ID_ATTR(product);
668INPUT_DEV_ID_ATTR(version);
669
670static struct attribute *input_dev_id_attrs[] = {
671 &class_device_attr_bustype.attr,
672 &class_device_attr_vendor.attr,
673 &class_device_attr_product.attr,
674 &class_device_attr_version.attr,
675 NULL
676};
677
678static struct attribute_group input_dev_id_attr_group = {
679 .name = "id",
680 .attrs = input_dev_id_attrs,
681};
682
683#define INPUT_DEV_CAP_ATTR(ev, bm) \
684static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \
685{ \
686 struct input_dev *input_dev = to_input_dev(dev); \
687 return input_print_bitmap(buf, input_dev->bm##bit, ev##_MAX); \
688} \
689static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
690
691INPUT_DEV_CAP_ATTR(EV, ev);
692INPUT_DEV_CAP_ATTR(KEY, key);
693INPUT_DEV_CAP_ATTR(REL, rel);
694INPUT_DEV_CAP_ATTR(ABS, abs);
695INPUT_DEV_CAP_ATTR(MSC, msc);
696INPUT_DEV_CAP_ATTR(LED, led);
697INPUT_DEV_CAP_ATTR(SND, snd);
698INPUT_DEV_CAP_ATTR(FF, ff);
699INPUT_DEV_CAP_ATTR(SW, sw);
700
701static struct attribute *input_dev_caps_attrs[] = {
702 &class_device_attr_ev.attr,
703 &class_device_attr_key.attr,
704 &class_device_attr_rel.attr,
705 &class_device_attr_abs.attr,
706 &class_device_attr_msc.attr,
707 &class_device_attr_led.attr,
708 &class_device_attr_snd.attr,
709 &class_device_attr_ff.attr,
710 &class_device_attr_sw.attr,
711 NULL
712};
713
714static struct attribute_group input_dev_caps_attr_group = {
715 .name = "capabilities",
716 .attrs = input_dev_caps_attrs,
717};
718
615static void input_dev_release(struct class_device *class_dev) 719static void input_dev_release(struct class_device *class_dev)
616{ 720{
617 struct input_dev *dev = to_input_dev(class_dev); 721 struct input_dev *dev = to_input_dev(class_dev);
@@ -623,6 +727,7 @@ static void input_dev_release(struct class_device *class_dev)
623static struct class input_dev_class = { 727static struct class input_dev_class = {
624 .name = "input_dev", 728 .name = "input_dev",
625 .release = input_dev_release, 729 .release = input_dev_release,
730 .class_dev_attrs = input_dev_attrs,
626}; 731};
627 732
628struct input_dev *input_allocate_device(void) 733struct input_dev *input_allocate_device(void)
@@ -660,6 +765,8 @@ static void input_register_classdevice(struct input_dev *dev)
660 kfree(path); 765 kfree(path);
661 766
662 class_device_add(&dev->cdev); 767 class_device_add(&dev->cdev);
768 sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
769 sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
663} 770}
664 771
665void input_register_device(struct input_dev *dev) 772void input_register_device(struct input_dev *dev)
@@ -726,8 +833,11 @@ void input_unregister_device(struct input_dev *dev)
726 833
727 list_del_init(&dev->node); 834 list_del_init(&dev->node);
728 835
729 if (dev->dynalloc) 836 if (dev->dynalloc) {
837 sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
838 sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
730 class_device_unregister(&dev->cdev); 839 class_device_unregister(&dev->cdev);
840 }
731 841
732 input_wakeup_procfs_readers(); 842 input_wakeup_procfs_readers();
733} 843}