Commit 85b77200 authored by Henrik Rydberg's avatar Henrik Rydberg

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: default avatarPing Cheng <pingc@wacom.com>
Acked-by: default avatarChase Douglas <chase.douglas@canonical.com>
Acked-by: default avatarDmitry Torokhov <dtor@mail.ru>
Signed-off-by: default avatarHenrik Rydberg <rydberg@euromail.se>
parent 4dd295a7
...@@ -677,6 +677,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, ...@@ -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)) #define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
switch (EVIOC_MASK_SIZE(cmd)) { switch (EVIOC_MASK_SIZE(cmd)) {
case EVIOCGPROP(0):
return bits_to_user(dev->propbit, INPUT_PROP_MAX,
size, p, compat_mode);
case EVIOCGKEY(0): case EVIOCGKEY(0):
return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode);
......
...@@ -1095,6 +1095,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v) ...@@ -1095,6 +1095,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "%s ", handle->name); seq_printf(seq, "%s ", handle->name);
seq_putc(seq, '\n'); 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); input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
if (test_bit(EV_KEY, dev->evbit)) if (test_bit(EV_KEY, dev->evbit))
input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX); input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
...@@ -1318,11 +1320,26 @@ static ssize_t input_dev_show_modalias(struct device *dev, ...@@ -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 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[] = { static struct attribute *input_dev_attrs[] = {
&dev_attr_name.attr, &dev_attr_name.attr,
&dev_attr_phys.attr, &dev_attr_phys.attr,
&dev_attr_uniq.attr, &dev_attr_uniq.attr,
&dev_attr_modalias.attr, &dev_attr_modalias.attr,
&dev_attr_properties.attr,
NULL NULL
}; };
...@@ -1522,6 +1539,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) ...@@ -1522,6 +1539,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
if (dev->uniq) if (dev->uniq)
INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", 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); INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
if (test_bit(EV_KEY, dev->evbit)) if (test_bit(EV_KEY, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX); INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
......
...@@ -680,6 +680,10 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, ...@@ -680,6 +680,10 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
retval = uinput_set_bit(arg, swbit, SW_MAX); retval = uinput_set_bit(arg, swbit, SW_MAX);
break; break;
case UI_SET_PROPBIT:
retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
break;
case UI_SET_PHYS: case UI_SET_PHYS:
if (udev->state == UIST_CREATED) { if (udev->state == UIST_CREATED) {
retval = -EINVAL; retval = -EINVAL;
......
...@@ -91,6 +91,7 @@ struct input_keymap_entry { ...@@ -91,6 +91,7 @@ struct input_keymap_entry {
#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ #define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */
#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */ #define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */
#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */ #define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */
#define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len) /* get device properties */
#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global key state */ #define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global key state */
#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */ #define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */
...@@ -107,6 +108,18 @@ struct input_keymap_entry { ...@@ -107,6 +108,18 @@ struct input_keymap_entry {
#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */ #define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
/*
* Device properties and quirks
*/
#define INPUT_PROP_POINTER 0x00 /* needs a pointer */
#define INPUT_PROP_DIRECT 0x01 /* direct input devices */
#define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */
#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */
#define INPUT_PROP_MAX 0x1f
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
/* /*
* Event types * Event types
*/ */
...@@ -1090,6 +1103,7 @@ struct ff_effect { ...@@ -1090,6 +1103,7 @@ struct ff_effect {
* @phys: physical path to the device in the system hierarchy * @phys: physical path to the device in the system hierarchy
* @uniq: unique identification code for the device (if device has it) * @uniq: unique identification code for the device (if device has it)
* @id: id of the device (struct input_id) * @id: id of the device (struct input_id)
* @propbit: bitmap of device properties and quirks
* @evbit: bitmap of types of events supported by the device (EV_KEY, * @evbit: bitmap of types of events supported by the device (EV_KEY,
* EV_REL, etc.) * EV_REL, etc.)
* @keybit: bitmap of keys/buttons this device has * @keybit: bitmap of keys/buttons this device has
...@@ -1173,6 +1187,8 @@ struct input_dev { ...@@ -1173,6 +1187,8 @@ struct input_dev {
const char *uniq; const char *uniq;
struct input_id id; struct input_id id;
unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
......
...@@ -104,6 +104,7 @@ struct uinput_ff_erase { ...@@ -104,6 +104,7 @@ struct uinput_ff_erase {
#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int) #define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int)
#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*) #define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*)
#define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int) #define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int)
#define UI_SET_PROPBIT _IOW(UINPUT_IOCTL_BASE, 110, int)
#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload) #define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload) #define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment