[RFC/PATCH] Uncap max number of evdev devices [was: Re: need more events]
From: Linas Vepstas
Date: Mon Nov 27 2006 - 13:57:17 EST
On Fri, Nov 24, 2006 at 05:09:52PM -0800, juanslayton@xxxxxxxxxxxxxx wrote:
>
> The object is to poll 20 usb keyboards in an elementary school
> classroom, each of which generates 2
> events (one keyboard and one mouse). The stock kernel maxes out at event
> 31, leaving me 4
> keyboards short.
> I thought to fix this by changing the definition of EVDEV_MINORS
> (line 12, evdev.c) from 32 to 64. It almost worked. The extra
> events showed up in /dev/input/* and /proc/bus/input/devices.
> However, attempting to access the new events in the application
> program only yields a segmentation fault. Obviously I've got to change
> something else.
The problem is in input_register_handler() in drivers/input/input.c
which does things like
if (input_table[handler->minor >> 5])
and
input_table[handler->minor >> 5] = handler;
which implicitly makes 32 the max.
The kernel path below removes this limitation. Does it fix your problem?
--linas
The evdev code is limited to 32 input devices max, because
the generic input layer puts a 32-device cap on the number
of minor device numbers that a device driver can register.
This patch hacks around the 32-device limitation for
the number of evdev drivers. Not clear to me if this
this is the best solution.
Not-even-compile-tested.
Signed-off-by: Linas Vepstas <linas@xxxxxxxxxxxxxx>
----
drivers/input/input.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
Index: linux-2.6.19-rc4-git3/drivers/input/input.c
===================================================================
--- linux-2.6.19-rc4-git3.orig/drivers/input/input.c 2006-11-01 16:15:19.000000000 -0600
+++ linux-2.6.19-rc4-git3/drivers/input/input.c 2006-11-27 12:50:12.000000000 -0600
@@ -28,12 +28,16 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@s
MODULE_DESCRIPTION("Input core");
MODULE_LICENSE("GPL");
-#define INPUT_DEVICES 256
+#define INPUT_MINOR_BITS 8
+#define INPUT_DEVICES (1<<INPUT_MINOR_BITS)
+#define MINOR_RANGE_BITS 6
+#define MINOR_RANGES (1<<(INPUT_MINOR_BITS-MINOR_RANGE_BITS))
+#define TABLE_OFFSET(minor) ((minor)>>MINOR_RANGE_BITS)
static LIST_HEAD(input_dev_list);
static LIST_HEAD(input_handler_list);
-static struct input_handler *input_table[8];
+static struct input_handler *input_table[MINOR_RANGES];
/**
* input_event() - report new input event
@@ -1046,10 +1050,10 @@ int input_register_handler(struct input_
INIT_LIST_HEAD(&handler->h_list);
if (handler->fops != NULL) {
- if (input_table[handler->minor >> 5])
+ if (input_table[TABLE_OFFSET(handler->minor)])
return -EBUSY;
- input_table[handler->minor >> 5] = handler;
+ input_table[TABLE_OFFSET(handler->minor)] = handler;
}
list_add_tail(&handler->node, &input_handler_list);
@@ -1082,7 +1086,7 @@ void input_unregister_handler(struct inp
list_del_init(&handler->node);
if (handler->fops != NULL)
- input_table[handler->minor >> 5] = NULL;
+ input_table[TABLE_OFFSET(handler->minor)] = NULL;
input_wakeup_procfs_readers();
}
@@ -1090,7 +1094,7 @@ EXPORT_SYMBOL(input_unregister_handler);
static int input_open_file(struct inode *inode, struct file *file)
{
- struct input_handler *handler = input_table[iminor(inode) >> 5];
+ struct input_handler *handler = input_table[TABLE_OFFSET(iminor(inode))];
const struct file_operations *old_fops, *new_fops = NULL;
int err;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/