diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 3626b1ce4609..cfe78597eb68 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include "input-compat.h" @@ -632,6 +632,28 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) return input_set_keycode(dev, &ke); } +static int evdev_handle_mt_request(struct input_dev *dev, + unsigned int size, + int __user *ip) +{ + const struct input_mt_slot *mt = dev->mt; + unsigned int code; + int max_slots; + int i; + + if (get_user(code, &ip[0])) + return -EFAULT; + if (!input_is_mt_value(code)) + return -EINVAL; + + max_slots = (size - sizeof(__u32)) / sizeof(__s32); + for (i = 0; i < dev->mtsize && i < max_slots; i++) + if (put_user(input_mt_get_value(&mt[i], code), &ip[1 + i])) + return -EFAULT; + + return 0; +} + static long evdev_do_ioctl(struct file *file, unsigned int cmd, void __user *p, int compat_mode) { @@ -725,6 +747,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return bits_to_user(dev->propbit, INPUT_PROP_MAX, size, p, compat_mode); + case EVIOCGMTSLOTS(0): + return evdev_handle_mt_request(dev, size, ip); + 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 1f78c957a75a..8921c6180c51 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -180,7 +180,7 @@ static int input_handle_abs_event(struct input_dev *dev, return INPUT_IGNORE_EVENT; } - is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST; + is_mt_event = input_is_mt_value(code); if (!is_mt_event) { pold = &dev->absinfo[code].value; diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 927e479c2649..f9e2758b9f46 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -433,6 +433,7 @@ static void setup_events_to_report(struct input_dev *input_dev, __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); if (cfg->caps & HAS_INTEGRATED_BUTTON) __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); diff --git a/include/linux/input.h b/include/linux/input.h index 177261ea6f52..a81671453575 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -114,6 +114,31 @@ struct input_keymap_entry { #define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */ #define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len) /* get device properties */ +/** + * EVIOCGMTSLOTS(len) - get MT slot values + * + * The ioctl buffer argument should be binary equivalent to + * + * struct input_mt_request_layout { + * __u32 code; + * __s32 values[num_slots]; + * }; + * + * where num_slots is the (arbitrary) number of MT slots to extract. + * + * The ioctl size argument (len) is the size of the buffer, which + * should satisfy len = (num_slots + 1) * sizeof(__s32). If len is + * too small to fit all available slots, the first num_slots are + * returned. + * + * Before the call, code is set to the wanted ABS_MT event type. On + * return, values[] is filled with the slot values for the specified + * ABS_MT code. + * + * If the request code is not an ABS_MT value, -EINVAL is returned. + */ +#define EVIOCGMTSLOTS(len) _IOC(_IOC_READ, 'E', 0x0a, len) + #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 EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */ diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h index 318bb82325a6..f86737586e19 100644 --- a/include/linux/input/mt.h +++ b/include/linux/input/mt.h @@ -48,10 +48,14 @@ static inline void input_mt_slot(struct input_dev *dev, int slot) input_event(dev, EV_ABS, ABS_MT_SLOT, slot); } +static inline bool input_is_mt_value(int axis) +{ + return axis >= ABS_MT_FIRST && axis <= ABS_MT_LAST; +} + static inline bool input_is_mt_axis(int axis) { - return axis == ABS_MT_SLOT || - (axis >= ABS_MT_FIRST && axis <= ABS_MT_LAST); + return axis == ABS_MT_SLOT || input_is_mt_value(axis); } void input_mt_report_slot_state(struct input_dev *dev,