Skip to content

Commit 1d8f430

Browse files
rustyrussellgregkh
authored andcommitted
[PATCH] Input: add modalias support
Here's the patch for modalias support for input classes. It uses comma-separated numbers, and doesn't describe all the potential keys (no module currently cares, and that would make the strings huge). The changes to input.h are to move the definitions needed by file2alias outside __KERNEL__. I chose not to move those definitions to mod_devicetable.h, because there are so many that it might break compile of something else in the kernel. The rest is fairly straightforward. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> CC: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
1 parent 263756e commit 1d8f430

File tree

3 files changed

+141
-39
lines changed

3 files changed

+141
-39
lines changed

drivers/input/input.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,10 +528,49 @@ INPUT_DEV_STRING_ATTR_SHOW(name);
528528
INPUT_DEV_STRING_ATTR_SHOW(phys);
529529
INPUT_DEV_STRING_ATTR_SHOW(uniq);
530530

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+
531569
static struct attribute *input_dev_attrs[] = {
532570
&class_device_attr_name.attr,
533571
&class_device_attr_phys.attr,
534572
&class_device_attr_uniq.attr,
573+
&class_device_attr_modalias.attr,
535574
NULL
536575
};
537576

include/linux/input.h

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <sys/ioctl.h>
1919
#include <asm/types.h>
2020
#endif
21+
#include <linux/mod_devicetable.h>
2122

2223
/*
2324
* The event structure itself
@@ -511,6 +512,8 @@ struct input_absinfo {
511512
#define KEY_FN_S 0x1e3
512513
#define KEY_FN_B 0x1e4
513514

515+
/* We avoid low common keys in module aliases so they don't get huge. */
516+
#define KEY_MIN_INTERESTING KEY_MUTE
514517
#define KEY_MAX 0x1ff
515518

516519
/*
@@ -793,6 +796,44 @@ struct ff_effect {
793796

794797
#define FF_MAX 0x7f
795798

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+
796837
#ifdef __KERNEL__
797838

798839
/*
@@ -901,49 +942,11 @@ struct input_dev {
901942
};
902943
#define to_input_dev(d) container_of(d, struct input_dev, cdev)
903944

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-
923945
#define INPUT_DEVICE_ID_MATCH_DEVICE\
924946
(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
925947
#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
926948
(INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
927949

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-
947950
struct input_handle;
948951

949952
struct input_handler {

scripts/mod/file2alias.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
* use either stdint.h or inttypes.h for the rest. */
1717
#if KERNEL_ELFCLASS == ELFCLASS32
1818
typedef Elf32_Addr kernel_ulong_t;
19+
#define BITS_PER_LONG 32
1920
#else
2021
typedef Elf64_Addr kernel_ulong_t;
22+
#define BITS_PER_LONG 64
2123
#endif
2224
#ifdef __sun__
2325
#include <inttypes.h>
@@ -35,6 +37,7 @@ typedef unsigned char __u8;
3537
* even potentially has different endianness and word sizes, since
3638
* we handle those differences explicitly below */
3739
#include "../../include/linux/mod_devicetable.h"
40+
#include "../../include/linux/input.h"
3841

3942
#define ADD(str, sep, cond, field) \
4043
do { \
@@ -366,6 +369,61 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *i2c, char *a
366369
return 1;
367370
}
368371

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+
369427
/* Ignore any prefix, eg. v850 prepends _ */
370428
static inline int sym_is(const char *symbol, const char *name)
371429
{
@@ -453,7 +511,9 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
453511
else if (sym_is(symname, "__mod_i2c_device_table"))
454512
do_table(symval, sym->st_size, sizeof(struct i2c_device_id),
455513
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);
457517
}
458518

459519
/* Now add out buffered information to the generated C source */

0 commit comments

Comments
 (0)