Input: add match() method to input hanlders

Get rid of blacklist in input handler structure and instead allow
handlers to define their own match() method to perform fine-grained
filtering of supported devices.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
Dmitry Torokhov 2010-02-02 21:08:26 -08:00
parent 1e87a43080
commit 0b7024ac4d
4 changed files with 40 additions and 35 deletions

View file

@ -1323,6 +1323,21 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,
schedule_console_callback();
}
static bool kbd_match(struct input_handler *handler, struct input_dev *dev)
{
int i;
if (test_bit(EV_SND, dev->evbit))
return true;
if (test_bit(EV_KEY, dev->evbit))
for (i = KEY_RESERVED; i < BTN_MISC; i++)
if (test_bit(i, dev->keybit))
return true;
return false;
}
/*
* When a keyboard (or other input device) is found, the kbd_connect
* function is called. The function then looks at the device, and if it
@ -1334,14 +1349,6 @@ static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
{
struct input_handle *handle;
int error;
int i;
for (i = KEY_RESERVED; i < BTN_MISC; i++)
if (test_bit(i, dev->keybit))
break;
if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
return -ENODEV;
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
if (!handle)
@ -1407,6 +1414,7 @@ MODULE_DEVICE_TABLE(input, kbd_ids);
static struct input_handler kbd_handler = {
.event = kbd_event,
.match = kbd_match,
.connect = kbd_connect,
.disconnect = kbd_disconnect,
.start = kbd_start,

View file

@ -723,12 +723,13 @@ EXPORT_SYMBOL(input_set_keycode);
if (i != BITS_TO_LONGS(max)) \
continue;
static const struct input_device_id *input_match_device(const struct input_device_id *id,
static const struct input_device_id *input_match_device(struct input_handler *handler,
struct input_dev *dev)
{
const struct input_device_id *id;
int i;
for (; id->flags || id->driver_info; id++) {
for (id = handler->id_table; id->flags || id->driver_info; id++) {
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
if (id->bustype != dev->id.bustype)
@ -756,7 +757,8 @@ static const struct input_device_id *input_match_device(const struct input_devic
MATCH_BIT(ffbit, FF_MAX);
MATCH_BIT(swbit, SW_MAX);
return id;
if (!handler->match || handler->match(handler, dev))
return id;
}
return NULL;
@ -767,10 +769,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
const struct input_device_id *id;
int error;
if (handler->blacklist && input_match_device(handler->blacklist, dev))
return -ENODEV;
id = input_match_device(handler->id_table, dev);
id = input_match_device(handler, dev);
if (!id)
return -ENODEV;

View file

@ -775,6 +775,20 @@ static void joydev_cleanup(struct joydev *joydev)
input_close_device(handle);
}
static bool joydev_match(struct input_handler *handler, struct input_dev *dev)
{
/* Avoid touchpads and touchscreens */
if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_TOUCH, dev->keybit))
return false;
/* Avoid tablets, digitisers and similar devices */
if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_DIGI, dev->keybit))
return false;
return true;
}
static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
@ -894,22 +908,6 @@ static void joydev_disconnect(struct input_handle *handle)
put_device(&joydev->dev);
}
static const struct input_device_id joydev_blacklist[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT_MASK(EV_KEY) },
.keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
}, /* Avoid itouchpads and touchscreens */
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT_MASK(EV_KEY) },
.keybit = { [BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_DIGI) },
}, /* Avoid tablets, digitisers and similar devices */
{ } /* Terminating entry */
};
static const struct input_device_id joydev_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
@ -936,13 +934,13 @@ MODULE_DEVICE_TABLE(input, joydev_ids);
static struct input_handler joydev_handler = {
.event = joydev_event,
.match = joydev_match,
.connect = joydev_connect,
.disconnect = joydev_disconnect,
.fops = &joydev_fops,
.minor = JOYDEV_MINOR_BASE,
.name = "joydev",
.id_table = joydev_ids,
.blacklist = joydev_blacklist,
};
static int __init joydev_init(void)

View file

@ -1200,6 +1200,8 @@ struct input_handle;
* it may not sleep
* @filter: similar to @event; separates normal event handlers from
* "filters".
* @match: called after comparing device's id with handler's id_table
* to perform fine-grained matching between device and handler
* @connect: called when attaching a handler to an input device
* @disconnect: disconnects a handler from input device
* @start: starts handler for given handle. This function is called by
@ -1211,8 +1213,6 @@ struct input_handle;
* @name: name of the handler, to be shown in /proc/bus/input/handlers
* @id_table: pointer to a table of input_device_ids this driver can
* handle
* @blacklist: pointer to a table of input_device_ids this driver should
* ignore even if they match @id_table
* @h_list: list of input handles associated with the handler
* @node: for placing the driver onto input_handler_list
*
@ -1235,6 +1235,7 @@ struct input_handler {
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
bool (*match)(struct input_handler *handler, struct input_dev *dev);
int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
void (*start)(struct input_handle *handle);
@ -1244,7 +1245,6 @@ struct input_handler {
const char *name;
const struct input_device_id *id_table;
const struct input_device_id *blacklist;
struct list_head h_list;
struct list_head node;