From 85b7720039fc000b561c20fe2aaa3b54cddae4a7 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 18 Dec 2010 20:51:13 +0100 Subject: Input: introduce device properties Today, userspace sets up an input device based on the data it emits. This is not always enough; a tablet and a touchscreen may emit exactly the same data, for instance, but the former should be set up with a pointer whereas the latter does not need to. Recently, a new type of touchpad has emerged where the buttons are under the pad, which changes logic without changing the emitted data. This patch introduces a new ioctl, EVIOCGPROP, which enables user access to a set of device properties useful during setup. The properties are given as a bitmap in the same fashion as the event types, and are also made available via sysfs, uevent and /proc/bus/input/devices. Acked-by: Ping Cheng Acked-by: Chase Douglas Acked-by: Dmitry Torokhov Signed-off-by: Henrik Rydberg --- drivers/input/evdev.c | 4 ++++ drivers/input/input.c | 19 +++++++++++++++++++ drivers/input/misc/uinput.c | 4 ++++ 3 files changed, 27 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e3f7fc6..0cd97e8 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -677,6 +677,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, #define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) switch (EVIOC_MASK_SIZE(cmd)) { + case EVIOCGPROP(0): + return bits_to_user(dev->propbit, INPUT_PROP_MAX, + size, p, compat_mode); + case EVIOCGKEY(0): return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); diff --git a/drivers/input/input.c b/drivers/input/input.c index 37708d1..9ea713f 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1095,6 +1095,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "%s ", handle->name); seq_putc(seq, '\n'); + input_seq_print_bitmap(seq, "PROP", dev->propbit, INPUT_PROP_MAX); + input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX); if (test_bit(EV_KEY, dev->evbit)) input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX); @@ -1318,11 +1320,26 @@ static ssize_t input_dev_show_modalias(struct device *dev, } static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); +static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, + int max, int add_cr); + +static ssize_t input_dev_show_properties(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct input_dev *input_dev = to_input_dev(dev); + int len = input_print_bitmap(buf, PAGE_SIZE, input_dev->propbit, + INPUT_PROP_MAX, true); + return min_t(int, len, PAGE_SIZE); +} +static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL); + static struct attribute *input_dev_attrs[] = { &dev_attr_name.attr, &dev_attr_phys.attr, &dev_attr_uniq.attr, &dev_attr_modalias.attr, + &dev_attr_properties.attr, NULL }; @@ -1522,6 +1539,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) if (dev->uniq) INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq); + INPUT_ADD_HOTPLUG_BM_VAR("PROP=", dev->propbit, INPUT_PROP_MAX); + INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX); if (test_bit(EV_KEY, dev->evbit)) INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX); diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index bea8972..82542a1 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -680,6 +680,10 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, retval = uinput_set_bit(arg, swbit, SW_MAX); break; + case UI_SET_PROPBIT: + retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); + break; + case UI_SET_PHYS: if (udev->state == UIST_CREATED) { retval = -EINVAL; -- cgit v1.1