diff options
-rw-r--r-- | drivers/input/input.c | 39 | ||||
-rw-r--r-- | include/linux/input.h | 79 | ||||
-rw-r--r-- | scripts/mod/file2alias.c | 62 |
3 files changed, 141 insertions, 39 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 2d37b394e384..ef5824c8846b 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -528,10 +528,49 @@ INPUT_DEV_STRING_ATTR_SHOW(name); | |||
528 | INPUT_DEV_STRING_ATTR_SHOW(phys); | 528 | INPUT_DEV_STRING_ATTR_SHOW(phys); |
529 | INPUT_DEV_STRING_ATTR_SHOW(uniq); | 529 | INPUT_DEV_STRING_ATTR_SHOW(uniq); |
530 | 530 | ||
531 | static int print_modalias_bits(char *buf, char prefix, unsigned long *arr, | ||
532 | unsigned int min, unsigned int max) | ||
533 | { | ||
534 | int len, i; | ||
535 | |||
536 | len = sprintf(buf, "%c", prefix); | ||
537 | for (i = min; i < max; i++) | ||
538 | if (arr[LONG(i)] & BIT(i)) | ||
539 | len += sprintf(buf+len, "%X,", i); | ||
540 | return len; | ||
541 | } | ||
542 | |||
543 | static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) | ||
544 | { | ||
545 | struct input_dev *id = to_input_dev(dev); | ||
546 | ssize_t len = 0; | ||
547 | |||
548 | len += sprintf(buf+len, "input:b%04Xv%04Xp%04Xe%04X-", | ||
549 | id->id.bustype, | ||
550 | id->id.vendor, | ||
551 | id->id.product, | ||
552 | id->id.version); | ||
553 | |||
554 | len += print_modalias_bits(buf+len, 'e', id->evbit, 0, EV_MAX); | ||
555 | len += print_modalias_bits(buf+len, 'k', id->keybit, | ||
556 | KEY_MIN_INTERESTING, KEY_MAX); | ||
557 | len += print_modalias_bits(buf+len, 'r', id->relbit, 0, REL_MAX); | ||
558 | len += print_modalias_bits(buf+len, 'a', id->absbit, 0, ABS_MAX); | ||
559 | len += print_modalias_bits(buf+len, 'm', id->mscbit, 0, MSC_MAX); | ||
560 | len += print_modalias_bits(buf+len, 'l', id->ledbit, 0, LED_MAX); | ||
561 | len += print_modalias_bits(buf+len, 's', id->sndbit, 0, SND_MAX); | ||
562 | len += print_modalias_bits(buf+len, 'f', id->ffbit, 0, FF_MAX); | ||
563 | len += print_modalias_bits(buf+len, 'w', id->swbit, 0, SW_MAX); | ||
564 | len += sprintf(buf+len, "\n"); | ||
565 | return len; | ||
566 | } | ||
567 | static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); | ||
568 | |||
531 | static struct attribute *input_dev_attrs[] = { | 569 | static struct attribute *input_dev_attrs[] = { |
532 | &class_device_attr_name.attr, | 570 | &class_device_attr_name.attr, |
533 | &class_device_attr_phys.attr, | 571 | &class_device_attr_phys.attr, |
534 | &class_device_attr_uniq.attr, | 572 | &class_device_attr_uniq.attr, |
573 | &class_device_attr_modalias.attr, | ||
535 | NULL | 574 | NULL |
536 | }; | 575 | }; |
537 | 576 | ||
diff --git a/include/linux/input.h b/include/linux/input.h index 3c5823368ddb..bef08551a33b 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <sys/ioctl.h> | 18 | #include <sys/ioctl.h> |
19 | #include <asm/types.h> | 19 | #include <asm/types.h> |
20 | #endif | 20 | #endif |
21 | #include <linux/mod_devicetable.h> | ||
21 | 22 | ||
22 | /* | 23 | /* |
23 | * The event structure itself | 24 | * The event structure itself |
@@ -511,6 +512,8 @@ struct input_absinfo { | |||
511 | #define KEY_FN_S 0x1e3 | 512 | #define KEY_FN_S 0x1e3 |
512 | #define KEY_FN_B 0x1e4 | 513 | #define KEY_FN_B 0x1e4 |
513 | 514 | ||
515 | /* We avoid low common keys in module aliases so they don't get huge. */ | ||
516 | #define KEY_MIN_INTERESTING KEY_MUTE | ||
514 | #define KEY_MAX 0x1ff | 517 | #define KEY_MAX 0x1ff |
515 | 518 | ||
516 | /* | 519 | /* |
@@ -793,6 +796,44 @@ struct ff_effect { | |||
793 | 796 | ||
794 | #define FF_MAX 0x7f | 797 | #define FF_MAX 0x7f |
795 | 798 | ||
799 | struct input_device_id { | ||
800 | |||
801 | kernel_ulong_t flags; | ||
802 | |||
803 | struct input_id id; | ||
804 | |||
805 | kernel_ulong_t evbit[EV_MAX/BITS_PER_LONG+1]; | ||
806 | kernel_ulong_t keybit[KEY_MAX/BITS_PER_LONG+1]; | ||
807 | kernel_ulong_t relbit[REL_MAX/BITS_PER_LONG+1]; | ||
808 | kernel_ulong_t absbit[ABS_MAX/BITS_PER_LONG+1]; | ||
809 | kernel_ulong_t mscbit[MSC_MAX/BITS_PER_LONG+1]; | ||
810 | kernel_ulong_t ledbit[LED_MAX/BITS_PER_LONG+1]; | ||
811 | kernel_ulong_t sndbit[SND_MAX/BITS_PER_LONG+1]; | ||
812 | kernel_ulong_t ffbit[FF_MAX/BITS_PER_LONG+1]; | ||
813 | kernel_ulong_t swbit[SW_MAX/BITS_PER_LONG+1]; | ||
814 | |||
815 | kernel_ulong_t driver_info; | ||
816 | }; | ||
817 | |||
818 | /* | ||
819 | * Structure for hotplug & device<->driver matching. | ||
820 | */ | ||
821 | |||
822 | #define INPUT_DEVICE_ID_MATCH_BUS 1 | ||
823 | #define INPUT_DEVICE_ID_MATCH_VENDOR 2 | ||
824 | #define INPUT_DEVICE_ID_MATCH_PRODUCT 4 | ||
825 | #define INPUT_DEVICE_ID_MATCH_VERSION 8 | ||
826 | |||
827 | #define INPUT_DEVICE_ID_MATCH_EVBIT 0x010 | ||
828 | #define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020 | ||
829 | #define INPUT_DEVICE_ID_MATCH_RELBIT 0x040 | ||
830 | #define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080 | ||
831 | #define INPUT_DEVICE_ID_MATCH_MSCIT 0x100 | ||
832 | #define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200 | ||
833 | #define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400 | ||
834 | #define INPUT_DEVICE_ID_MATCH_FFBIT 0x800 | ||
835 | #define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000 | ||
836 | |||
796 | #ifdef __KERNEL__ | 837 | #ifdef __KERNEL__ |
797 | 838 | ||
798 | /* | 839 | /* |
@@ -901,49 +942,11 @@ struct input_dev { | |||
901 | }; | 942 | }; |
902 | #define to_input_dev(d) container_of(d, struct input_dev, cdev) | 943 | #define to_input_dev(d) container_of(d, struct input_dev, cdev) |
903 | 944 | ||
904 | /* | ||
905 | * Structure for hotplug & device<->driver matching. | ||
906 | */ | ||
907 | |||
908 | #define INPUT_DEVICE_ID_MATCH_BUS 1 | ||
909 | #define INPUT_DEVICE_ID_MATCH_VENDOR 2 | ||
910 | #define INPUT_DEVICE_ID_MATCH_PRODUCT 4 | ||
911 | #define INPUT_DEVICE_ID_MATCH_VERSION 8 | ||
912 | |||
913 | #define INPUT_DEVICE_ID_MATCH_EVBIT 0x010 | ||
914 | #define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020 | ||
915 | #define INPUT_DEVICE_ID_MATCH_RELBIT 0x040 | ||
916 | #define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080 | ||
917 | #define INPUT_DEVICE_ID_MATCH_MSCIT 0x100 | ||
918 | #define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200 | ||
919 | #define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400 | ||
920 | #define INPUT_DEVICE_ID_MATCH_FFBIT 0x800 | ||
921 | #define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000 | ||
922 | |||
923 | #define INPUT_DEVICE_ID_MATCH_DEVICE\ | 945 | #define INPUT_DEVICE_ID_MATCH_DEVICE\ |
924 | (INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT) | 946 | (INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT) |
925 | #define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\ | 947 | #define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\ |
926 | (INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION) | 948 | (INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION) |
927 | 949 | ||
928 | struct input_device_id { | ||
929 | |||
930 | unsigned long flags; | ||
931 | |||
932 | struct input_id id; | ||
933 | |||
934 | unsigned long evbit[NBITS(EV_MAX)]; | ||
935 | unsigned long keybit[NBITS(KEY_MAX)]; | ||
936 | unsigned long relbit[NBITS(REL_MAX)]; | ||
937 | unsigned long absbit[NBITS(ABS_MAX)]; | ||
938 | unsigned long mscbit[NBITS(MSC_MAX)]; | ||
939 | unsigned long ledbit[NBITS(LED_MAX)]; | ||
940 | unsigned long sndbit[NBITS(SND_MAX)]; | ||
941 | unsigned long ffbit[NBITS(FF_MAX)]; | ||
942 | unsigned long swbit[NBITS(SW_MAX)]; | ||
943 | |||
944 | unsigned long driver_info; | ||
945 | }; | ||
946 | |||
947 | struct input_handle; | 950 | struct input_handle; |
948 | 951 | ||
949 | struct input_handler { | 952 | struct input_handler { |
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index e3d144a3f10b..e0eedffe565b 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -16,8 +16,10 @@ | |||
16 | * use either stdint.h or inttypes.h for the rest. */ | 16 | * use either stdint.h or inttypes.h for the rest. */ |
17 | #if KERNEL_ELFCLASS == ELFCLASS32 | 17 | #if KERNEL_ELFCLASS == ELFCLASS32 |
18 | typedef Elf32_Addr kernel_ulong_t; | 18 | typedef Elf32_Addr kernel_ulong_t; |
19 | #define BITS_PER_LONG 32 | ||
19 | #else | 20 | #else |
20 | typedef Elf64_Addr kernel_ulong_t; | 21 | typedef Elf64_Addr kernel_ulong_t; |
22 | #define BITS_PER_LONG 64 | ||
21 | #endif | 23 | #endif |
22 | #ifdef __sun__ | 24 | #ifdef __sun__ |
23 | #include <inttypes.h> | 25 | #include <inttypes.h> |
@@ -35,6 +37,7 @@ typedef unsigned char __u8; | |||
35 | * even potentially has different endianness and word sizes, since | 37 | * even potentially has different endianness and word sizes, since |
36 | * we handle those differences explicitly below */ | 38 | * we handle those differences explicitly below */ |
37 | #include "../../include/linux/mod_devicetable.h" | 39 | #include "../../include/linux/mod_devicetable.h" |
40 | #include "../../include/linux/input.h" | ||
38 | 41 | ||
39 | #define ADD(str, sep, cond, field) \ | 42 | #define ADD(str, sep, cond, field) \ |
40 | do { \ | 43 | do { \ |
@@ -366,6 +369,61 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *i2c, char *a | |||
366 | return 1; | 369 | return 1; |
367 | } | 370 | } |
368 | 371 | ||
372 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | ||
373 | |||
374 | static void do_input(char *alias, | ||
375 | kernel_ulong_t *arr, unsigned int min, unsigned int max) | ||
376 | { | ||
377 | unsigned int i; | ||
378 | for (i = min; i < max; i++) { | ||
379 | if (arr[i/BITS_PER_LONG] & (1 << (i%BITS_PER_LONG))) | ||
380 | sprintf(alias+strlen(alias), "%X,*", i); | ||
381 | } | ||
382 | } | ||
383 | |||
384 | /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */ | ||
385 | static int do_input_entry(const char *filename, struct input_device_id *id, | ||
386 | char *alias) | ||
387 | { | ||
388 | sprintf(alias, "input:"); | ||
389 | |||
390 | ADD(alias, "b", id->flags&INPUT_DEVICE_ID_MATCH_BUS, id->id.bustype); | ||
391 | ADD(alias, "v", id->flags&INPUT_DEVICE_ID_MATCH_VENDOR, id->id.vendor); | ||
392 | ADD(alias, "p", id->flags&INPUT_DEVICE_ID_MATCH_PRODUCT, | ||
393 | id->id.product); | ||
394 | ADD(alias, "e", id->flags&INPUT_DEVICE_ID_MATCH_VERSION, | ||
395 | id->id.version); | ||
396 | |||
397 | sprintf(alias + strlen(alias), "-e*"); | ||
398 | if (id->flags&INPUT_DEVICE_ID_MATCH_EVBIT) | ||
399 | do_input(alias, id->evbit, 0, EV_MAX); | ||
400 | sprintf(alias + strlen(alias), "k*"); | ||
401 | if (id->flags&INPUT_DEVICE_ID_MATCH_KEYBIT) | ||
402 | do_input(alias, id->keybit, KEY_MIN_INTERESTING, KEY_MAX); | ||
403 | sprintf(alias + strlen(alias), "r*"); | ||
404 | if (id->flags&INPUT_DEVICE_ID_MATCH_RELBIT) | ||
405 | do_input(alias, id->relbit, 0, REL_MAX); | ||
406 | sprintf(alias + strlen(alias), "a*"); | ||
407 | if (id->flags&INPUT_DEVICE_ID_MATCH_ABSBIT) | ||
408 | do_input(alias, id->absbit, 0, ABS_MAX); | ||
409 | sprintf(alias + strlen(alias), "m*"); | ||
410 | if (id->flags&INPUT_DEVICE_ID_MATCH_MSCIT) | ||
411 | do_input(alias, id->mscbit, 0, MSC_MAX); | ||
412 | sprintf(alias + strlen(alias), "l*"); | ||
413 | if (id->flags&INPUT_DEVICE_ID_MATCH_LEDBIT) | ||
414 | do_input(alias, id->ledbit, 0, LED_MAX); | ||
415 | sprintf(alias + strlen(alias), "s*"); | ||
416 | if (id->flags&INPUT_DEVICE_ID_MATCH_SNDBIT) | ||
417 | do_input(alias, id->sndbit, 0, SND_MAX); | ||
418 | sprintf(alias + strlen(alias), "f*"); | ||
419 | if (id->flags&INPUT_DEVICE_ID_MATCH_FFBIT) | ||
420 | do_input(alias, id->ffbit, 0, SND_MAX); | ||
421 | sprintf(alias + strlen(alias), "w*"); | ||
422 | if (id->flags&INPUT_DEVICE_ID_MATCH_SWBIT) | ||
423 | do_input(alias, id->swbit, 0, SW_MAX); | ||
424 | return 1; | ||
425 | } | ||
426 | |||
369 | /* Ignore any prefix, eg. v850 prepends _ */ | 427 | /* Ignore any prefix, eg. v850 prepends _ */ |
370 | static inline int sym_is(const char *symbol, const char *name) | 428 | static inline int sym_is(const char *symbol, const char *name) |
371 | { | 429 | { |
@@ -453,7 +511,9 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
453 | else if (sym_is(symname, "__mod_i2c_device_table")) | 511 | else if (sym_is(symname, "__mod_i2c_device_table")) |
454 | do_table(symval, sym->st_size, sizeof(struct i2c_device_id), | 512 | do_table(symval, sym->st_size, sizeof(struct i2c_device_id), |
455 | do_i2c_entry, mod); | 513 | do_i2c_entry, mod); |
456 | 514 | else if (sym_is(symname, "__mod_input_device_table")) | |
515 | do_table(symval, sym->st_size, sizeof(struct input_device_id), | ||
516 | do_input_entry, mod); | ||
457 | } | 517 | } |
458 | 518 | ||
459 | /* Now add out buffered information to the generated C source */ | 519 | /* Now add out buffered information to the generated C source */ |