From 0417596f66dd6621f4fd46563c7c56a95311dbe8 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 29 Nov 2010 23:33:05 -0800 Subject: Input: add keycodes for touchpad on/off keys Some laptops will have a "touchpad toggle" soft button, which expects user-space to turn off the touchpad themselves, some other devices will do this in hardware, but send key events telling us that the touchpad has been turned off/on. KEY_TOUCHPAD_ON/KEY_TOUCHPAD_OFF will be used by user-space to show a popup with the status of the touchpad. Signed-off-by: Bastien Nocera Signed-off-by: Dmitry Torokhov --- include/linux/input.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux/input.h') diff --git a/include/linux/input.h b/include/linux/input.h index 6ef44465db8d..a50046f15372 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -624,6 +624,10 @@ struct input_keymap_entry { #define KEY_CAMERA_FOCUS 0x210 #define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */ +#define KEY_TOUCHPAD_TOGGLE 0x212 /* Request switch touchpad on or off */ +#define KEY_TOUCHPAD_ON 0x213 +#define KEY_TOUCHPAD_OFF 0x214 + #define BTN_TRIGGER_HAPPY 0x2c0 #define BTN_TRIGGER_HAPPY1 0x2c0 #define BTN_TRIGGER_HAPPY2 0x2c1 -- cgit v1.2.3 From 86b17f76f462db460d6d916e105a4c44cb353e36 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 29 Nov 2010 23:33:04 -0800 Subject: Input: document struct input_absinfo Add documentation for struct input_absinfo that is used in EVIOCGABS and EVIOCSABS ioctl and specify units of measure used for reporting resolution for an axis. Acked-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- include/linux/input.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'include/linux/input.h') diff --git a/include/linux/input.h b/include/linux/input.h index a50046f15372..a8af21d42bc1 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -47,6 +47,25 @@ struct input_id { __u16 version; }; +/** + * struct input_absinfo - used by EVIOCGABS/EVIOCSABS ioctls + * @value: latest reported value for the axis. + * @minimum: specifies minimum value for the axis. + * @maximum: specifies maximum value for the axis. + * @fuzz: specifies fuzz value that is used to filter noise from + * the event stream. + * @flat: values that are within this value will be discarded by + * joydev interface and reported as 0 instead. + * @resolution: specifies resolution for the values reported for + * the axis. + * + * Note that input core does not clamp reported values to the + * [minimum, maximum] limits, such task is left to userspace. + * + * Resolution for main axes (ABS_X, ABS_Y, ABS_Z) is reported in + * units per millimeter (units/mm), resolution for rotational axes + * (ABS_RX, ABS_RY, ABS_RZ) is reported in units per radian. + */ struct input_absinfo { __s32 value; __s32 minimum; @@ -1134,7 +1153,7 @@ struct input_mt_slot { * of tracked contacts * @mtsize: number of MT slots the device uses * @slot: MT slot currently being transmitted - * @absinfo: array of &struct absinfo elements holding information + * @absinfo: array of &struct input_absinfo elements holding information * about absolute axes (current value, min, max, flat, fuzz, * resolution) * @key: reflects current state of device's keys/buttons -- cgit v1.2.3 From ab4e0192196b8d4e43a3945742d4996da934a86f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 14 Dec 2010 23:53:21 -0800 Subject: Input: define separate EVIOCGKEYCODE_V2/EVIOCSKEYCODE_V2 The desire to keep old names for the EVIOCGKEYCODE/EVIOCSKEYCODE while extending them to support large scancodes was a mistake. While we tried to keep ABI intact (and we succeeded in doing that, programs compiled on older kernels will work on newer ones) there is still a problem with recompiling existing software with newer kernel headers. New kernel headers will supply updated ioctl numbers and kernel will expect that userspace will use struct input_keymap_entry to set and retrieve keymap data. But since the names of ioctls are still the same userspace will happily compile even if not adjusted to make use of the new structure and will start miraculously fail in the field. To avoid this issue let's revert EVIOCGKEYCODE/EVIOCSKEYCODE definitions and add EVIOCGKEYCODE_V2/EVIOCSKEYCODE_V2 so that userspace can explicitly select the style of ioctls it wants to employ. Reviewed-by: Henrik Rydberg Acked-by: Jarod Wilson Acked-by: Mauro Carvalho Chehab Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 113 ++++++++++++++++++++++++++------------------------ include/linux/input.h | 6 ++- 2 files changed, 62 insertions(+), 57 deletions(-) (limited to 'include/linux/input.h') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e3f7fc6f9565..68f09a868434 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -534,76 +534,73 @@ static int handle_eviocgbit(struct input_dev *dev, } #undef OLD_KEY_MAX -static int evdev_handle_get_keycode(struct input_dev *dev, - void __user *p, size_t size) +static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p) { - struct input_keymap_entry ke; + struct input_keymap_entry ke = { + .len = sizeof(unsigned int), + .flags = 0, + }; + int __user *ip = (int __user *)p; int error; - memset(&ke, 0, sizeof(ke)); - - if (size == sizeof(unsigned int[2])) { - /* legacy case */ - int __user *ip = (int __user *)p; + /* legacy case */ + if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) + return -EFAULT; - if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) - return -EFAULT; + error = input_get_keycode(dev, &ke); + if (error) + return error; - ke.len = sizeof(unsigned int); - ke.flags = 0; + if (put_user(ke.keycode, ip + 1)) + return -EFAULT; - error = input_get_keycode(dev, &ke); - if (error) - return error; + return 0; +} - if (put_user(ke.keycode, ip + 1)) - return -EFAULT; +static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p) +{ + struct input_keymap_entry ke; + int error; - } else { - size = min(size, sizeof(ke)); + if (copy_from_user(&ke, p, sizeof(ke))) + return -EFAULT; - if (copy_from_user(&ke, p, size)) - return -EFAULT; + error = input_get_keycode(dev, &ke); + if (error) + return error; - error = input_get_keycode(dev, &ke); - if (error) - return error; + if (copy_to_user(p, &ke, sizeof(ke))) + return -EFAULT; - if (copy_to_user(p, &ke, size)) - return -EFAULT; - } return 0; } -static int evdev_handle_set_keycode(struct input_dev *dev, - void __user *p, size_t size) +static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p) { - struct input_keymap_entry ke; - - memset(&ke, 0, sizeof(ke)); + struct input_keymap_entry ke = { + .len = sizeof(unsigned int), + .flags = 0, + }; + int __user *ip = (int __user *)p; - if (size == sizeof(unsigned int[2])) { - /* legacy case */ - int __user *ip = (int __user *)p; + if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) + return -EFAULT; - if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) - return -EFAULT; + if (get_user(ke.keycode, ip + 1)) + return -EFAULT; - if (get_user(ke.keycode, ip + 1)) - return -EFAULT; + return input_set_keycode(dev, &ke); +} - ke.len = sizeof(unsigned int); - ke.flags = 0; +static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) +{ + struct input_keymap_entry ke; - } else { - size = min(size, sizeof(ke)); + if (copy_from_user(&ke, p, sizeof(ke))) + return -EFAULT; - if (copy_from_user(&ke, p, size)) - return -EFAULT; - - if (ke.len > sizeof(ke.scancode)) - return -EINVAL; - } + if (ke.len > sizeof(ke.scancode)) + return -EINVAL; return input_set_keycode(dev, &ke); } @@ -669,6 +666,18 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return evdev_grab(evdev, client); else return evdev_ungrab(evdev, client); + + case EVIOCGKEYCODE: + return evdev_handle_get_keycode(dev, p); + + case EVIOCSKEYCODE: + return evdev_handle_set_keycode(dev, p); + + case EVIOCGKEYCODE_V2: + return evdev_handle_get_keycode_v2(dev, p); + + case EVIOCSKEYCODE_V2: + return evdev_handle_set_keycode_v2(dev, p); } size = _IOC_SIZE(cmd); @@ -708,12 +717,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return -EFAULT; return error; - - case EVIOC_MASK_SIZE(EVIOCGKEYCODE): - return evdev_handle_get_keycode(dev, p, size); - - case EVIOC_MASK_SIZE(EVIOCSKEYCODE): - return evdev_handle_set_keycode(dev, p, size); } /* Multi-number variable-length handlers */ diff --git a/include/linux/input.h b/include/linux/input.h index a8af21d42bc1..9777668883be 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -104,8 +104,10 @@ struct input_keymap_entry { #define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */ #define EVIOCSREP _IOW('E', 0x03, unsigned int[2]) /* set repeat settings */ -#define EVIOCGKEYCODE _IOR('E', 0x04, struct input_keymap_entry) /* get keycode */ -#define EVIOCSKEYCODE _IOW('E', 0x04, struct input_keymap_entry) /* set keycode */ +#define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2]) /* get keycode */ +#define EVIOCGKEYCODE_V2 _IOR('E', 0x04, struct input_keymap_entry) +#define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2]) /* set keycode */ +#define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry) #define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ #define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */ -- cgit v1.2.3 From 47c78e891323513e9909729b44033e2c6649e2b7 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 27 Nov 2010 09:16:48 +0100 Subject: input: mt: Break out slots handling In preparation for common code to handle a larger set of MT slots devices, move the slots handling over to a separate file. Signed-off-by: Henrik Rydberg --- drivers/hid/hid-3m-pct.c | 1 + drivers/input/Makefile | 2 +- drivers/input/input-mt.c | 58 +++++++++++++++++++++++++++++++++ drivers/input/input.c | 48 +-------------------------- drivers/input/misc/uinput.c | 1 + drivers/input/tablet/wacom_wac.c | 1 + drivers/input/touchscreen/wacom_w8001.c | 2 +- include/linux/input.h | 16 --------- include/linux/input/mt.h | 44 +++++++++++++++++++++++++ 9 files changed, 108 insertions(+), 65 deletions(-) create mode 100644 drivers/input/input-mt.c create mode 100644 include/linux/input/mt.h (limited to 'include/linux/input.h') diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c index 02d8cd3b1b1b..18575a4e0d63 100644 --- a/drivers/hid/hid-3m-pct.c +++ b/drivers/hid/hid-3m-pct.c @@ -19,6 +19,7 @@ #include #include #include +#include MODULE_AUTHOR("Stephane Chatty "); MODULE_DESCRIPTION("3M PCT multitouch panels"); diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 7ad212d31f99..569938b3cc04 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -5,7 +5,7 @@ # Each configuration option enables a list of files. obj-$(CONFIG_INPUT) += input-core.o -input-core-objs := input.o input-compat.o ff-core.o +input-core-objs := input.o input-compat.o ff-core.o input-mt.o obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c new file mode 100644 index 000000000000..463a4d7d54f2 --- /dev/null +++ b/drivers/input/input-mt.c @@ -0,0 +1,58 @@ +/* + * Input Multitouch Library + * + * Copyright (c) 2008-2010 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include +#include + +/** + * input_mt_create_slots() - create MT input slots + * @dev: input device supporting MT events and finger tracking + * @num_slots: number of slots used by the device + * + * This function allocates all necessary memory for MT slot handling in the + * input device, and adds ABS_MT_SLOT to the device capabilities. All slots + * are initially marked as unused by setting ABS_MT_TRACKING_ID to -1. + */ +int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots) +{ + int i; + + if (!num_slots) + return 0; + + dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL); + if (!dev->mt) + return -ENOMEM; + + dev->mtsize = num_slots; + input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); + + /* Mark slots as 'unused' */ + for (i = 0; i < num_slots; i++) + input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1); + + return 0; +} +EXPORT_SYMBOL(input_mt_create_slots); + +/** + * input_mt_destroy_slots() - frees the MT slots of the input device + * @dev: input device with allocated MT slots + * + * This function is only needed in error path as the input core will + * automatically free the MT slots when the device is destroyed. + */ +void input_mt_destroy_slots(struct input_dev *dev) +{ + kfree(dev->mt); + dev->mt = NULL; + dev->mtsize = 0; +} +EXPORT_SYMBOL(input_mt_destroy_slots); diff --git a/drivers/input/input.c b/drivers/input/input.c index d092ef9291da..37708d1d86ec 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -1690,52 +1690,6 @@ void input_free_device(struct input_dev *dev) } EXPORT_SYMBOL(input_free_device); -/** - * input_mt_create_slots() - create MT input slots - * @dev: input device supporting MT events and finger tracking - * @num_slots: number of slots used by the device - * - * This function allocates all necessary memory for MT slot handling in the - * input device, and adds ABS_MT_SLOT to the device capabilities. All slots - * are initially marked as unused by setting ABS_MT_TRACKING_ID to -1. - */ -int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots) -{ - int i; - - if (!num_slots) - return 0; - - dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL); - if (!dev->mt) - return -ENOMEM; - - dev->mtsize = num_slots; - input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); - - /* Mark slots as 'unused' */ - for (i = 0; i < num_slots; i++) - dev->mt[i].abs[ABS_MT_TRACKING_ID - ABS_MT_FIRST] = -1; - - return 0; -} -EXPORT_SYMBOL(input_mt_create_slots); - -/** - * input_mt_destroy_slots() - frees the MT slots of the input device - * @dev: input device with allocated MT slots - * - * This function is only needed in error path as the input core will - * automatically free the MT slots when the device is destroyed. - */ -void input_mt_destroy_slots(struct input_dev *dev) -{ - kfree(dev->mt); - dev->mt = NULL; - dev->mtsize = 0; -} -EXPORT_SYMBOL(input_mt_destroy_slots); - /** * input_set_capability - mark device as capable of a certain event * @dev: device that is capable of emitting or accepting event diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index b9410784e6a1..8f374143190e 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "../input-compat.h" static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index b3252ef1e279..bde612c6d36d 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -14,6 +14,7 @@ #include "wacom_wac.h" #include "wacom.h" +#include static int wacom_penpartner_irq(struct wacom_wac *wacom) { diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 9ae4c7b16ba7..5d4f50e52a28 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/linux/input.h b/include/linux/input.h index 51af441f3a21..99e2a52c0509 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1082,14 +1082,6 @@ struct ff_effect { #include #include -/** - * struct input_mt_slot - represents the state of an input MT slot - * @abs: holds current values of ABS_MT axes for this slot - */ -struct input_mt_slot { - int abs[ABS_MT_LAST - ABS_MT_FIRST + 1]; -}; - /** * struct input_dev - represents an input device * @name: name of the device @@ -1461,11 +1453,6 @@ static inline void input_mt_sync(struct input_dev *dev) input_event(dev, EV_SYN, SYN_MT_REPORT, 0); } -static inline void input_mt_slot(struct input_dev *dev, int slot) -{ - input_event(dev, EV_ABS, ABS_MT_SLOT, slot); -} - void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code); /** @@ -1578,8 +1565,5 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file); int input_ff_create_memless(struct input_dev *dev, void *data, int (*play_effect)(struct input_dev *, void *, struct ff_effect *)); -int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots); -void input_mt_destroy_slots(struct input_dev *dev); - #endif #endif diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h new file mode 100644 index 000000000000..4f5e9d0e2eae --- /dev/null +++ b/include/linux/input/mt.h @@ -0,0 +1,44 @@ +#ifndef _INPUT_MT_H +#define _INPUT_MT_H + +/* + * Input Multitouch Library + * + * Copyright (c) 2010 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include + +/** + * struct input_mt_slot - represents the state of an input MT slot + * @abs: holds current values of ABS_MT axes for this slot + */ +struct input_mt_slot { + int abs[ABS_MT_LAST - ABS_MT_FIRST + 1]; +}; + +static inline void input_mt_set_value(struct input_mt_slot *slot, + unsigned code, int value) +{ + slot->abs[code - ABS_MT_FIRST] = value; +} + +static inline int input_mt_get_value(const struct input_mt_slot *slot, + unsigned code) +{ + return slot->abs[code - ABS_MT_FIRST]; +} + +int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots); +void input_mt_destroy_slots(struct input_dev *dev); + +static inline void input_mt_slot(struct input_dev *dev, int slot) +{ + input_event(dev, EV_ABS, ABS_MT_SLOT, slot); +} + +#endif -- cgit v1.2.3 From c5f4dec1ceb6ab773bbbefbe64a7c990c7d6b17f Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Wed, 15 Dec 2010 13:50:34 +0100 Subject: input: mt: Move tracking and pointer emulation to input-mt The drivers using the type B protocol all report tracking information the same way. The contact id is semantically equivalent to ABS_MT_SLOT, and the handling of ABS_MT_TRACKING_ID only complicates the driver. The situation can be improved upon by providing a common pointer emulation code, thereby removing the need for the tracking id in the driver. This patch moves all tracking event handling over to the input core, simplifying both the existing drivers and the ones currently in preparation. Acked-by: Ping Cheng Acked-by: Jiri Kosina Signed-off-by: Henrik Rydberg --- drivers/hid/hid-3m-pct.c | 30 +-------- drivers/input/input-mt.c | 115 ++++++++++++++++++++++++++++++-- drivers/input/tablet/wacom_wac.c | 23 ++----- drivers/input/tablet/wacom_wac.h | 4 -- drivers/input/touchscreen/wacom_w8001.c | 21 ++---- include/linux/input.h | 3 + include/linux/input/mt.h | 13 ++++ 7 files changed, 138 insertions(+), 71 deletions(-) (limited to 'include/linux/input.h') diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c index ea475964d05a..4fb7c7528d16 100644 --- a/drivers/hid/hid-3m-pct.c +++ b/drivers/hid/hid-3m-pct.c @@ -28,7 +28,6 @@ MODULE_LICENSE("GPL"); #include "hid-ids.h" #define MAX_SLOTS 60 -#define MAX_TRKID USHRT_MAX /* estimated signal-to-noise ratios */ #define SN_MOVE 2048 @@ -36,14 +35,11 @@ MODULE_LICENSE("GPL"); struct mmm_finger { __s32 x, y, w, h; - __u16 id; - bool prev_touch; bool touch, valid; }; struct mmm_data { struct mmm_finger f[MAX_SLOTS]; - __u16 id; __u8 curid; __u8 nexp, nreal; bool touch, valid; @@ -117,11 +113,6 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, 0, 1, 0, 0); return 1; case HID_DG_CONTACTID: - field->logical_maximum = MAX_TRKID; - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TRACKING_ID); - input_set_abs_params(hi->input, ABS_MT_TRACKING_ID, - 0, MAX_TRKID, 0, 0); input_mt_init_slots(hi->input, MAX_SLOTS); return 1; } @@ -152,7 +143,6 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi, */ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) { - struct mmm_finger *oldest = 0; int i; for (i = 0; i < MAX_SLOTS; ++i) { struct mmm_finger *f = &md->f[i]; @@ -161,6 +151,7 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) continue; } input_mt_slot(input, i); + input_mt_report_slot_state(input, MT_TOOL_FINGER, f->touch); if (f->touch) { /* this finger is on the screen */ int wide = (f->w > f->h); @@ -168,33 +159,16 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) int major = max(f->w, f->h) >> 1; int minor = min(f->w, f->h) >> 1; - if (!f->prev_touch) - f->id = md->id++; - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id); input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); - /* touchscreen emulation: pick the oldest contact */ - if (!oldest || ((f->id - oldest->id) & (SHRT_MAX + 1))) - oldest = f; - } else { - /* this finger took off the screen */ - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1); } - f->prev_touch = f->touch; f->valid = 0; } - /* touchscreen emulation */ - if (oldest) { - input_event(input, EV_KEY, BTN_TOUCH, 1); - input_event(input, EV_ABS, ABS_X, oldest->x); - input_event(input, EV_ABS, ABS_Y, oldest->y); - } else { - input_event(input, EV_KEY, BTN_TOUCH, 0); - } + input_mt_report_pointer_emulation(input, true); input_sync(input); } diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index f400e47092c4..c48c81f0308d 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -11,17 +11,18 @@ #include #include +#define TRKID_SGN ((TRKID_MAX + 1) >> 1) + /** * input_mt_init_slots() - initialize MT input slots * @dev: input device supporting MT events and finger tracking * @num_slots: number of slots used by the device * * This function allocates all necessary memory for MT slot handling - * in the input device, adds ABS_MT_SLOT to the device capabilities - * and sets up appropriate event buffers. All slots are initially - * marked as unused by setting ABS_MT_TRACKING_ID to -1. May be called - * repeatedly. Returns -EINVAL if attempting to reinitialize with a - * different number of slots. + * in the input device, prepares the ABS_MT_SLOT and + * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers. + * May be called repeatedly. Returns -EINVAL if attempting to + * reinitialize with a different number of slots. */ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) { @@ -38,6 +39,7 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) dev->mtsize = num_slots; input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); + input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0); input_set_events_per_packet(dev, 6 * num_slots); /* Mark slots as 'unused' */ @@ -61,5 +63,108 @@ void input_mt_destroy_slots(struct input_dev *dev) dev->mt = NULL; dev->mtsize = 0; dev->slot = 0; + dev->trkid = 0; } EXPORT_SYMBOL(input_mt_destroy_slots); + +/** + * input_mt_report_slot_state() - report contact state + * @dev: input device with allocated MT slots + * @tool_type: the tool type to use in this slot + * @active: true if contact is active, false otherwise + * + * Reports a contact via ABS_MT_TRACKING_ID, and optionally + * ABS_MT_TOOL_TYPE. If active is true and the slot is currently + * inactive, or if the tool type is changed, a new tracking id is + * assigned to the slot. The tool type is only reported if the + * corresponding absbit field is set. + */ +void input_mt_report_slot_state(struct input_dev *dev, + unsigned int tool_type, bool active) +{ + struct input_mt_slot *mt; + int id; + + if (!dev->mt || !active) { + input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); + return; + } + + mt = &dev->mt[dev->slot]; + id = input_mt_get_value(mt, ABS_MT_TRACKING_ID); + if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type) + id = input_mt_new_trkid(dev); + + input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id); + input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type); +} +EXPORT_SYMBOL(input_mt_report_slot_state); + +/** + * input_mt_report_finger_count() - report contact count + * @dev: input device with allocated MT slots + * @count: the number of contacts + * + * Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, + * BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP. + * + * The input core ensures only the KEY events already setup for + * this device will produce output. + */ +void input_mt_report_finger_count(struct input_dev *dev, int count) +{ + input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1); + input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2); + input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3); + input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4); +} +EXPORT_SYMBOL(input_mt_report_finger_count); + +/** + * input_mt_report_pointer_emulation() - common pointer emulation + * @dev: input device with allocated MT slots + * @use_count: report number of active contacts as finger count + * + * Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and + * ABS_PRESSURE. Touchpad finger count is emulated if use_count is true. + * + * The input core ensures only the KEY and ABS axes already setup for + * this device will produce output. + */ +void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) +{ + struct input_mt_slot *oldest = 0; + int oldid = dev->trkid; + int count = 0; + int i; + + for (i = 0; i < dev->mtsize; ++i) { + struct input_mt_slot *ps = &dev->mt[i]; + int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID); + + if (id < 0) + continue; + if ((id - oldid) & TRKID_SGN) { + oldest = ps; + oldid = id; + } + count++; + } + + input_event(dev, EV_KEY, BTN_TOUCH, count > 0); + if (use_count) + input_mt_report_finger_count(dev, count); + + if (oldest) { + int x = input_mt_get_value(oldest, ABS_MT_POSITION_X); + int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y); + int p = input_mt_get_value(oldest, ABS_MT_PRESSURE); + + input_event(dev, EV_ABS, ABS_X, x); + input_event(dev, EV_ABS, ABS_Y, y); + input_event(dev, EV_ABS, ABS_PRESSURE, p); + } else { + input_event(dev, EV_ABS, ABS_PRESSURE, 0); + } +} +EXPORT_SYMBOL(input_mt_report_pointer_emulation); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index f26e2238f6ca..0b0525486711 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -863,19 +863,21 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) struct wacom_features *features = &wacom->features; struct input_dev *input = wacom->input; unsigned char *data = wacom->data; - int sp = 0, sx = 0, sy = 0, count = 0; int i; for (i = 0; i < 2; i++) { int p = data[9 * i + 2]; + bool touch = p && !wacom->shared->stylus_in_proximity; + input_mt_slot(input, i); + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); /* * Touch events need to be disabled while stylus is * in proximity because user's hand is resting on touchpad * and sending unwanted events. User expects tablet buttons * to continue working though. */ - if (p && !wacom->shared->stylus_in_proximity) { + if (touch) { int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff; int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff; if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) { @@ -885,23 +887,10 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) input_report_abs(input, ABS_MT_PRESSURE, p); input_report_abs(input, ABS_MT_POSITION_X, x); input_report_abs(input, ABS_MT_POSITION_Y, y); - if (wacom->id[i] < 0) - wacom->id[i] = wacom->trk_id++ & MAX_TRACKING_ID; - if (!count++) - sp = p, sx = x, sy = y; - } else { - wacom->id[i] = -1; } - input_report_abs(input, ABS_MT_TRACKING_ID, wacom->id[i]); } - input_report_key(input, BTN_TOUCH, count > 0); - input_report_key(input, BTN_TOOL_FINGER, count == 1); - input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2); - - input_report_abs(input, ABS_PRESSURE, sp); - input_report_abs(input, ABS_X, sx); - input_report_abs(input, ABS_Y, sy); + input_mt_report_pointer_emulation(input, true); input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); @@ -1283,8 +1272,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, features->pressure_max, features->pressure_fuzz, 0); - input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, - MAX_TRACKING_ID, 0, 0); } else if (features->device_type == BTN_TOOL_PEN) { __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_TOOL_PEN, input_dev->keybit); diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 00ca01541d89..b1310ec9720c 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -42,9 +42,6 @@ #define WACOM_QUIRK_MULTI_INPUT 0x0001 #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002 -/* largest reported tracking id */ -#define MAX_TRACKING_ID 0xfff - enum { PENPARTNER = 0, GRAPHIRE, @@ -100,7 +97,6 @@ struct wacom_wac { int id[3]; __u32 serial[2]; int last_finger; - int trk_id; struct wacom_features features; struct wacom_shared *shared; struct input_dev *input; diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 4a2e8cf4c8ef..2a0bec12d12a 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -48,8 +48,6 @@ MODULE_LICENSE("GPL"); #define W8001_PKTLEN_TPCCTL 11 /* control packet */ #define W8001_PKTLEN_TOUCH2FG 13 -#define MAX_TRACKING_ID 0xFF /* arbitrarily chosen */ - struct w8001_coord { u8 rdy; u8 tsw; @@ -87,7 +85,6 @@ struct w8001 { char phys[32]; int type; unsigned int pktlen; - int trkid[2]; }; static void parse_data(u8 *data, struct w8001_coord *coord) @@ -116,28 +113,23 @@ static void parse_data(u8 *data, struct w8001_coord *coord) static void parse_touch(struct w8001 *w8001) { - static int trkid; struct input_dev *dev = w8001->dev; unsigned char *data = w8001->data; int i; for (i = 0; i < 2; i++) { - input_mt_slot(dev, i); + bool touch = data[0] & (1 << i); - if (data[0] & (1 << i)) { + input_mt_slot(dev, i); + input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch); + if (touch) { int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]); int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]); /* data[5,6] and [11,12] is finger capacity */ input_report_abs(dev, ABS_MT_POSITION_X, x); input_report_abs(dev, ABS_MT_POSITION_Y, y); - input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER); - if (w8001->trkid[i] < 0) - w8001->trkid[i] = trkid++ & MAX_TRACKING_ID; - } else { - w8001->trkid[i] = -1; } - input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]); } input_sync(dev); @@ -319,14 +311,12 @@ static int w8001_setup(struct w8001 *w8001) w8001->pktlen = W8001_PKTLEN_TOUCH2FG; input_mt_init_slots(dev, 2); - input_set_abs_params(dev, ABS_MT_TRACKING_ID, - 0, MAX_TRACKING_ID, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_X, 0, touch.x, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, touch.y, 0, 0); input_set_abs_params(dev, ABS_MT_TOOL_TYPE, - 0, 0, 0, 0); + 0, MT_TOOL_MAX, 0, 0); break; } } @@ -372,7 +362,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) w8001->serio = serio; w8001->id = serio->id.id; w8001->dev = input_dev; - w8001->trkid[0] = w8001->trkid[1] = -1; init_completion(&w8001->cmd_done); snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); diff --git a/include/linux/input.h b/include/linux/input.h index 99e2a52c0509..6de145df4c1c 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -848,6 +848,7 @@ struct input_keymap_entry { */ #define MT_TOOL_FINGER 0 #define MT_TOOL_PEN 1 +#define MT_TOOL_MAX 1 /* * Values describing the status of a force-feedback effect @@ -1122,6 +1123,7 @@ struct ff_effect { * of tracked contacts * @mtsize: number of MT slots the device uses * @slot: MT slot currently being transmitted + * @trkid: stores MT tracking ID for the current contact * @absinfo: array of &struct absinfo elements holding information * about absolute axes (current value, min, max, flat, fuzz, * resolution) @@ -1206,6 +1208,7 @@ struct input_dev { struct input_mt_slot *mt; int mtsize; int slot; + int trkid; struct input_absinfo *absinfo; diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h index d7f6518e3222..b3ac06a4435d 100644 --- a/include/linux/input/mt.h +++ b/include/linux/input/mt.h @@ -13,6 +13,8 @@ #include +#define TRKID_MAX 0xffff + /** * struct input_mt_slot - represents the state of an input MT slot * @abs: holds current values of ABS_MT axes for this slot @@ -36,9 +38,20 @@ static inline int input_mt_get_value(const struct input_mt_slot *slot, int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots); void input_mt_destroy_slots(struct input_dev *dev); +static inline int input_mt_new_trkid(struct input_dev *dev) +{ + return dev->trkid++ & TRKID_MAX; +} + static inline void input_mt_slot(struct input_dev *dev, int slot) { input_event(dev, EV_ABS, ABS_MT_SLOT, slot); } +void input_mt_report_slot_state(struct input_dev *dev, + unsigned int tool_type, bool active); + +void input_mt_report_finger_count(struct input_dev *dev, int count); +void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count); + #endif -- cgit v1.2.3 From e42a98b520bb22535687ead3120e80edc268279a Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Mon, 6 Dec 2010 10:05:43 +0100 Subject: input: mt: Add hovering distance axis Touch devices capable of hovering, i.e., fingers detected a distance from the surface, are not supported by the current input MT protocol. This patch adds ABS_MT_DISTANCE, which may be used to indicate the distance between the contact and the surface. Signed-off-by: Henrik Rydberg --- Documentation/input/multi-touch-protocol.txt | 9 ++++++++- include/linux/input.h | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'include/linux/input.h') diff --git a/Documentation/input/multi-touch-protocol.txt b/Documentation/input/multi-touch-protocol.txt index bdcba154b83e..07215fa0c588 100644 --- a/Documentation/input/multi-touch-protocol.txt +++ b/Documentation/input/multi-touch-protocol.txt @@ -161,7 +161,8 @@ against the glass. The inner region will increase, and in general, the ratio ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR, which is always smaller than unity, is related to the contact pressure. For pressure-based devices, ABS_MT_PRESSURE may be used to provide the pressure on the contact area -instead. +instead. Devices capable of contact hovering can use ABS_MT_DISTANCE to +indicate the distance between the contact and the surface. In addition to the MAJOR parameters, the oval shape of the contact can be described by adding the MINOR parameters, such that MAJOR and MINOR are the @@ -213,6 +214,12 @@ The pressure, in arbitrary units, on the contact area. May be used instead of TOUCH and WIDTH for pressure-based devices or any device with a spatial signal intensity distribution. +ABS_MT_DISTANCE + +The distance, in surface units, between the contact and the surface. Zero +distance means the contact is touching the surface. A positive number means +the contact is hovering above the surface. + ABS_MT_ORIENTATION The orientation of the ellipse. The value should describe a signed quarter diff --git a/include/linux/input.h b/include/linux/input.h index 6de145df4c1c..b3a1e02080c0 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -733,11 +733,12 @@ struct input_keymap_entry { #define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */ #define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */ #define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */ +#define ABS_MT_DISTANCE 0x3b /* Contact hover distance */ #ifdef __KERNEL__ /* Implementation details, userspace should not care about these */ #define ABS_MT_FIRST ABS_MT_TOUCH_MAJOR -#define ABS_MT_LAST ABS_MT_PRESSURE +#define ABS_MT_LAST ABS_MT_DISTANCE #endif #define ABS_MAX 0x3f -- cgit v1.2.3 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 ++++ include/linux/input.h | 16 ++++++++++++++++ include/linux/uinput.h | 1 + 5 files changed, 44 insertions(+) (limited to 'include/linux/input.h') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e3f7fc6f9565..0cd97e8f0c9a 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 37708d1d86ec..9ea713f4192b 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 bea89722c4e9..82542a1c1098 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; diff --git a/include/linux/input.h b/include/linux/input.h index b3a1e02080c0..8d9c76cd3c43 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -91,6 +91,7 @@ struct input_keymap_entry { #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 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 EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */ @@ -107,6 +108,18 @@ struct input_keymap_entry { #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 */ @@ -1090,6 +1103,7 @@ struct ff_effect { * @phys: physical path to the device in the system hierarchy * @uniq: unique identification code for the device (if device has it) * @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, * EV_REL, etc.) * @keybit: bitmap of keys/buttons this device has @@ -1173,6 +1187,8 @@ struct input_dev { const char *uniq; struct input_id id; + unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)]; + unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; diff --git a/include/linux/uinput.h b/include/linux/uinput.h index 05f7fed2b173..d28c726ede4f 100644 --- a/include/linux/uinput.h +++ b/include/linux/uinput.h @@ -104,6 +104,7 @@ struct uinput_ff_erase { #define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int) #define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*) #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_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload) -- cgit v1.2.3 From eac8ae087ac66b21de94fee3e920210b43d43076 Mon Sep 17 00:00:00 2001 From: Mariusz Białończyk Date: Mon, 15 Nov 2010 15:50:13 -0300 Subject: [media] Fix rc-tbs-nec table after converting the cx88 driver to ir-core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The patch fixes the rc-tbs-nec table after converting drivers/media/video/cx88 to ir-core (commit ba7e90c9f878e0ac3c0614a5446fe5c62ccc33ec). It is also adds two missing buttons (10- and 10+) with its definition (KEY_10CHANNELSUP and KEY_10CHANNELSDOWN). [mchehab@redhat.com: move keycode numbers to 0x1b8/0x1b9 as requested by the input Maintainer] Signed-off-by: Mariusz Białończyk Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/rc-tbs-nec.c | 66 ++++++++++++++++++----------------- include/linux/input.h | 2 ++ 2 files changed, 36 insertions(+), 32 deletions(-) (limited to 'include/linux/input.h') diff --git a/drivers/media/rc/keymaps/rc-tbs-nec.c b/drivers/media/rc/keymaps/rc-tbs-nec.c index 15b9a9b80767..7242ee66f6e0 100644 --- a/drivers/media/rc/keymaps/rc-tbs-nec.c +++ b/drivers/media/rc/keymaps/rc-tbs-nec.c @@ -13,38 +13,40 @@ #include static struct rc_map_table tbs_nec[] = { - { 0x04, KEY_POWER2}, /*power*/ - { 0x14, KEY_MUTE}, /*mute*/ - { 0x07, KEY_1}, - { 0x06, KEY_2}, - { 0x05, KEY_3}, - { 0x0b, KEY_4}, - { 0x0a, KEY_5}, - { 0x09, KEY_6}, - { 0x0f, KEY_7}, - { 0x0e, KEY_8}, - { 0x0d, KEY_9}, - { 0x12, KEY_0}, - { 0x16, KEY_CHANNELUP}, /*ch+*/ - { 0x11, KEY_CHANNELDOWN},/*ch-*/ - { 0x13, KEY_VOLUMEUP}, /*vol+*/ - { 0x0c, KEY_VOLUMEDOWN},/*vol-*/ - { 0x03, KEY_RECORD}, /*rec*/ - { 0x18, KEY_PAUSE}, /*pause*/ - { 0x19, KEY_OK}, /*ok*/ - { 0x1a, KEY_CAMERA}, /* snapshot */ - { 0x01, KEY_UP}, - { 0x10, KEY_LEFT}, - { 0x02, KEY_RIGHT}, - { 0x08, KEY_DOWN}, - { 0x15, KEY_FAVORITES}, - { 0x17, KEY_SUBTITLE}, - { 0x1d, KEY_ZOOM}, - { 0x1f, KEY_EXIT}, - { 0x1e, KEY_MENU}, - { 0x1c, KEY_EPG}, - { 0x00, KEY_PREVIOUS}, - { 0x1b, KEY_MODE}, + { 0x84, KEY_POWER2}, /* power */ + { 0x94, KEY_MUTE}, /* mute */ + { 0x87, KEY_1}, + { 0x86, KEY_2}, + { 0x85, KEY_3}, + { 0x8b, KEY_4}, + { 0x8a, KEY_5}, + { 0x89, KEY_6}, + { 0x8f, KEY_7}, + { 0x8e, KEY_8}, + { 0x8d, KEY_9}, + { 0x92, KEY_0}, + { 0xc0, KEY_10CHANNELSUP}, /* 10+ */ + { 0xd0, KEY_10CHANNELSDOWN}, /* 10- */ + { 0x96, KEY_CHANNELUP}, /* ch+ */ + { 0x91, KEY_CHANNELDOWN}, /* ch- */ + { 0x93, KEY_VOLUMEUP}, /* vol+ */ + { 0x8c, KEY_VOLUMEDOWN}, /* vol- */ + { 0x83, KEY_RECORD}, /* rec */ + { 0x98, KEY_PAUSE}, /* pause, yellow */ + { 0x99, KEY_OK}, /* ok */ + { 0x9a, KEY_CAMERA}, /* snapshot */ + { 0x81, KEY_UP}, + { 0x90, KEY_LEFT}, + { 0x82, KEY_RIGHT}, + { 0x88, KEY_DOWN}, + { 0x95, KEY_FAVORITES}, /* blue */ + { 0x97, KEY_SUBTITLE}, /* green */ + { 0x9d, KEY_ZOOM}, + { 0x9f, KEY_EXIT}, + { 0x9e, KEY_MENU}, + { 0x9c, KEY_EPG}, + { 0x80, KEY_PREVIOUS}, /* red */ + { 0x9b, KEY_MODE}, }; static struct rc_map_list tbs_nec_map = { diff --git a/include/linux/input.h b/include/linux/input.h index 9777668883be..f7a6e1966df3 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -590,6 +590,8 @@ struct input_keymap_entry { #define KEY_FRAMEFORWARD 0x1b5 #define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */ #define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */ +#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ +#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ #define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOS 0x1c1 -- cgit v1.2.3 From 50a88cb7eddb971077ae7dff76b116747c12c371 Mon Sep 17 00:00:00 2001 From: Jekyll Lai Date: Tue, 11 Jan 2011 21:53:55 -0800 Subject: Input: add SW_ROTATE_LOCK switch type This switch is used to signal that user want to disable screen transitions from portrait to landscape mode and back. Signed-off-by: Jekyll Lai Signed-off-by: Alan Cox Signed-off-by: Dmitry Torokhov --- include/linux/input.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/input.h') diff --git a/include/linux/input.h b/include/linux/input.h index 6c407e553a40..4bdacada8d2a 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -775,6 +775,7 @@ struct input_keymap_entry { #define SW_CAMERA_LENS_COVER 0x09 /* set = lens covered */ #define SW_KEYPAD_SLIDE 0x0a /* set = keypad slide out */ #define SW_FRONT_PROXIMITY 0x0b /* set = front proximity sensor active */ +#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */ #define SW_MAX 0x0f #define SW_CNT (SW_MAX+1) -- cgit v1.2.3 From aebd636bd60e2dda0ebc907dd5f7f4a45174411c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 31 Jan 2011 21:06:39 -0800 Subject: Input: switch completely over to the new versions of get/setkeycode All users of old style get/setkeycode methids have been converted so it is time to retire them. Acked-by: Mauro Carvalho Chehab Acked-by: Jiri Kosina Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-input.c | 4 +-- drivers/input/input.c | 55 ++++-------------------------- drivers/input/misc/ati_remote2.c | 4 +-- drivers/input/sparse-keymap.c | 4 +-- drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 4 +-- drivers/media/rc/rc-main.c | 4 +-- include/linux/input.h | 12 ++----- 7 files changed, 20 insertions(+), 67 deletions(-) (limited to 'include/linux/input.h') diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 7f552bfad32c..ba2aeea2cbf9 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -888,8 +888,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) hid->ll_driver->hidinput_input_event; input_dev->open = hidinput_open; input_dev->close = hidinput_close; - input_dev->setkeycode_new = hidinput_setkeycode; - input_dev->getkeycode_new = hidinput_getkeycode; + input_dev->setkeycode = hidinput_setkeycode; + input_dev->getkeycode = hidinput_getkeycode; input_dev->name = hid->name; input_dev->phys = hid->phys; diff --git a/drivers/input/input.c b/drivers/input/input.c index 7985114beac7..ee2959bd322c 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -806,22 +806,9 @@ int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke) int retval; spin_lock_irqsave(&dev->event_lock, flags); - - if (dev->getkeycode) { - /* - * Support for legacy drivers, that don't implement the new - * ioctls - */ - u32 scancode = ke->index; - - memcpy(ke->scancode, &scancode, sizeof(scancode)); - ke->len = sizeof(scancode); - retval = dev->getkeycode(dev, scancode, &ke->keycode); - } else { - retval = dev->getkeycode_new(dev, ke); - } - + retval = dev->getkeycode(dev, ke); spin_unlock_irqrestore(&dev->event_lock, flags); + return retval; } EXPORT_SYMBOL(input_get_keycode); @@ -846,35 +833,7 @@ int input_set_keycode(struct input_dev *dev, spin_lock_irqsave(&dev->event_lock, flags); - if (dev->setkeycode) { - /* - * Support for legacy drivers, that don't implement the new - * ioctls - */ - unsigned int scancode; - - retval = input_scancode_to_scalar(ke, &scancode); - if (retval) - goto out; - - /* - * We need to know the old scancode, in order to generate a - * keyup effect, if the set operation happens successfully - */ - if (!dev->getkeycode) { - retval = -EINVAL; - goto out; - } - - retval = dev->getkeycode(dev, scancode, &old_keycode); - if (retval) - goto out; - - retval = dev->setkeycode(dev, scancode, ke->keycode); - } else { - retval = dev->setkeycode_new(dev, ke, &old_keycode); - } - + retval = dev->setkeycode(dev, ke, &old_keycode); if (retval) goto out; @@ -1861,11 +1820,11 @@ int input_register_device(struct input_dev *dev) dev->rep[REP_PERIOD] = 33; } - if (!dev->getkeycode && !dev->getkeycode_new) - dev->getkeycode_new = input_default_getkeycode; + if (!dev->getkeycode) + dev->getkeycode = input_default_getkeycode; - if (!dev->setkeycode && !dev->setkeycode_new) - dev->setkeycode_new = input_default_setkeycode; + if (!dev->setkeycode) + dev->setkeycode = input_default_setkeycode; dev_set_name(&dev->dev, "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 0b0e9be63542..9ccdb82d869a 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -612,8 +612,8 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) idev->open = ati_remote2_open; idev->close = ati_remote2_close; - idev->getkeycode_new = ati_remote2_getkeycode; - idev->setkeycode_new = ati_remote2_setkeycode; + idev->getkeycode = ati_remote2_getkeycode; + idev->setkeycode = ati_remote2_setkeycode; idev->name = ar2->name; idev->phys = ar2->phys; diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index 7729e547ba65..337bf51bc984 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -210,8 +210,8 @@ int sparse_keymap_setup(struct input_dev *dev, dev->keycode = map; dev->keycodemax = map_size; - dev->getkeycode_new = sparse_keymap_getkeycode; - dev->setkeycode_new = sparse_keymap_setkeycode; + dev->getkeycode = sparse_keymap_getkeycode; + dev->setkeycode = sparse_keymap_setkeycode; return 0; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 347fbd4e2d56..b2b9415d874d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -198,8 +198,8 @@ static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d) d->input_dev = input_dev; d->rc_dev = NULL; - input_dev->getkeycode_new = legacy_dvb_usb_getkeycode; - input_dev->setkeycode_new = legacy_dvb_usb_setkeycode; + input_dev->getkeycode = legacy_dvb_usb_getkeycode; + input_dev->setkeycode = legacy_dvb_usb_setkeycode; /* set the bits for the keys */ deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size); diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 512a2f4ada0e..c3769283936f 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -966,8 +966,8 @@ struct rc_dev *rc_allocate_device(void) return NULL; } - dev->input_dev->getkeycode_new = ir_getkeycode; - dev->input_dev->setkeycode_new = ir_setkeycode; + dev->input_dev->getkeycode = ir_getkeycode; + dev->input_dev->setkeycode = ir_setkeycode; input_set_drvdata(dev->input_dev, dev); spin_lock_init(&dev->rc_map.lock); diff --git a/include/linux/input.h b/include/linux/input.h index e428382ca28a..056ae8a5bd9b 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1154,8 +1154,6 @@ struct ff_effect { * sparse keymaps. If not supplied default mechanism will be used. * The method is being called while holding event_lock and thus must * not sleep - * @getkeycode_new: transition method - * @setkeycode_new: transition method * @ff: force feedback structure associated with the device if device * supports force feedback effects * @repeat_key: stores key code of the last key pressed; used to implement @@ -1234,14 +1232,10 @@ struct input_dev { void *keycode; int (*setkeycode)(struct input_dev *dev, - unsigned int scancode, unsigned int keycode); + const struct input_keymap_entry *ke, + unsigned int *old_keycode); int (*getkeycode)(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode); - int (*setkeycode_new)(struct input_dev *dev, - const struct input_keymap_entry *ke, - unsigned int *old_keycode); - int (*getkeycode_new)(struct input_dev *dev, - struct input_keymap_entry *ke); + struct input_keymap_entry *ke); struct ff_device *ff; -- cgit v1.2.3 From e2d3d44b9a6efe4f3968252d4b680397a9640268 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 6 Feb 2011 13:30:47 +0100 Subject: eeepc-wmi: add camera keys These keys are supposed to be handled by any software using the camera (like webKam or cheese...). They can also be used to actually move the camera when possible. Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/eeepc-wmi.c | 7 +++++++ include/linux/input.h | 7 +++++++ 2 files changed, 14 insertions(+) (limited to 'include/linux/input.h') diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index eea8c942653b..d3997757e790 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c @@ -114,11 +114,18 @@ static const struct key_entry eeepc_wmi_keymap[] = { { KE_KEY, 0x5c, { KEY_F15 } }, /* Power Gear key */ { KE_KEY, 0x5d, { KEY_WLAN } }, { KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */ + { KE_KEY, 0x82, { KEY_CAMERA } }, + { KE_KEY, 0x83, { KEY_CAMERA_ZOOMIN } }, { KE_KEY, 0x88, { KEY_WLAN } }, { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } }, { KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */ { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */ { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } }, + { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } }, + { KE_KEY, 0xec, { KEY_CAMERA_UP } }, + { KE_KEY, 0xed, { KEY_CAMERA_DOWN } }, + { KE_KEY, 0xee, { KEY_CAMERA_LEFT } }, + { KE_KEY, 0xef, { KEY_CAMERA_RIGHT } }, { KE_END, 0}, }; diff --git a/include/linux/input.h b/include/linux/input.h index 056ae8a5bd9b..f3a7794a18c4 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -664,6 +664,13 @@ struct input_keymap_entry { #define KEY_TOUCHPAD_ON 0x213 #define KEY_TOUCHPAD_OFF 0x214 +#define KEY_CAMERA_ZOOMIN 0x215 +#define KEY_CAMERA_ZOOMOUT 0x216 +#define KEY_CAMERA_UP 0x217 +#define KEY_CAMERA_DOWN 0x218 +#define KEY_CAMERA_LEFT 0x219 +#define KEY_CAMERA_RIGHT 0x21a + #define BTN_TRIGGER_HAPPY 0x2c0 #define BTN_TRIGGER_HAPPY1 0x2c0 #define BTN_TRIGGER_HAPPY2 0x2c1 -- cgit v1.2.3 From ba6a078b77e0dc1309d7e6e2ee034b92ab91f88c Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Tue, 12 Apr 2011 23:13:08 -0700 Subject: Input: add KEY_IMAGES specifically for AL Image Browser Many media center remotes have buttons intended for jumping straight to one type of media browser or another -- commonly, images/photos/pictures, audio/music, television, and movies. At present, remotes with an images or photos or pictures button use any number of different keycodes which sort of maybe fit. I've seen at least KEY_MEDIA, KEY_CAMERA, KEY_GRAPHICSEDITOR and KEY_PRESENTATION. None of those seem quite right. In my mind, KEY_MEDIA should be something more like a media center application launcher (and I'd like to standardize on that for things like the windows media center button on the mce remotes). KEY_CAMERA is used in a lot of webcams, and typically means "take a picture now". KEY_GRAPHICSEDITOR implies an editor, not a browser. KEY_PRESENTATION might be the closest fit here, if you think "photo slide show", but it may well be more intended for "run application in full-screen presentation mode" or to launch something like magicpoint, I dunno. And thus, I'd like to have a KEY_IMAGES, which matches the HID Usage AL Image Browser, the meaning of which I think is crystal-clear. I believe AL Audio Browser is already covered by KEY_AUDIO, and AL Movie Browser by KEY_VIDEO, so I'm also adding appropriate comments next to those keys. Signed-off-by: Jarod Wilson Signed-off-by: Dmitry Torokhov --- include/linux/input.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'include/linux/input.h') diff --git a/include/linux/input.h b/include/linux/input.h index 056ae8a5bd9b..0cc25e4ce2ab 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -553,8 +553,8 @@ struct input_keymap_entry { #define KEY_DVD 0x185 /* Media Select DVD */ #define KEY_AUX 0x186 #define KEY_MP3 0x187 -#define KEY_AUDIO 0x188 -#define KEY_VIDEO 0x189 +#define KEY_AUDIO 0x188 /* AL Audio Browser */ +#define KEY_VIDEO 0x189 /* AL Movie Browser */ #define KEY_DIRECTORY 0x18a #define KEY_LIST 0x18b #define KEY_MEMO 0x18c /* Media Select Messages */ @@ -603,8 +603,9 @@ struct input_keymap_entry { #define KEY_FRAMEFORWARD 0x1b5 #define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */ #define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */ -#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ -#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ +#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ +#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ +#define KEY_IMAGES 0x1ba /* AL Image Browser */ #define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOS 0x1c1 -- cgit v1.2.3 From 9fb0f14e31b6101a0cc69a333b43541044f9b0a6 Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Tue, 12 Apr 2011 23:29:38 -0700 Subject: Input: evdev - indicate buffer overrun with SYN_DROPPED Add a new EV_SYN code, SYN_DROPPED, to inform the client when input events have been dropped from the evdev input buffer due to a buffer overrun. The client should use this event as a hint to reset its state or ignore all following events until the next packet begins. Signed-off-by: Jeff Brown [dtor@mail.ru: Implement Henrik's suggestion and drop old events in case of overflow.] Signed-off-by: Dmitry Torokhov --- Documentation/input/event-codes.txt | 6 ++++++ drivers/input/evdev.c | 33 +++++++++++++++++++++------------ include/linux/input.h | 1 + 3 files changed, 28 insertions(+), 12 deletions(-) (limited to 'include/linux/input.h') diff --git a/Documentation/input/event-codes.txt b/Documentation/input/event-codes.txt index f13aee550409..23fcb05175be 100644 --- a/Documentation/input/event-codes.txt +++ b/Documentation/input/event-codes.txt @@ -85,6 +85,12 @@ sent in the evdev event stream. - Used to synchronize and separate touch events. See the multi-touch-protocol.txt document for more information. +* SYN_DROPPED: + - Used to indicate buffer overrun in the evdev client's event queue. + Client should ignore all events up to and including next SYN_REPORT + event and query the device (using EVIOCG* ioctls) to obtain its + current state. + EV_KEY: ---------- EV_KEY events take the form KEY_ or BTN_. For example, KEY_A is used diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 7f42d3a454d2..88d8e4cb419a 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -39,13 +39,13 @@ struct evdev { }; struct evdev_client { - int head; - int tail; + unsigned int head; + unsigned int tail; spinlock_t buffer_lock; /* protects access to buffer, head and tail */ struct fasync_struct *fasync; struct evdev *evdev; struct list_head node; - int bufsize; + unsigned int bufsize; struct input_event buffer[]; }; @@ -55,16 +55,25 @@ static DEFINE_MUTEX(evdev_table_mutex); static void evdev_pass_event(struct evdev_client *client, struct input_event *event) { - /* - * Interrupts are disabled, just acquire the lock. - * Make sure we don't leave with the client buffer - * "empty" by having client->head == client->tail. - */ + /* Interrupts are disabled, just acquire the lock. */ spin_lock(&client->buffer_lock); - do { - client->buffer[client->head++] = *event; - client->head &= client->bufsize - 1; - } while (client->head == client->tail); + + client->buffer[client->head++] = *event; + client->head &= client->bufsize - 1; + + if (unlikely(client->head == client->tail)) { + /* + * This effectively "drops" all unconsumed events, leaving + * EV_SYN/SYN_DROPPED plus the newest event in the queue. + */ + client->tail = (client->head - 2) & (client->bufsize - 1); + + client->buffer[client->tail].time = event->time; + client->buffer[client->tail].type = EV_SYN; + client->buffer[client->tail].code = SYN_DROPPED; + client->buffer[client->tail].value = 0; + } + spin_unlock(&client->buffer_lock); if (event->type == EV_SYN) diff --git a/include/linux/input.h b/include/linux/input.h index 0cc25e4ce2ab..73a8c6ee595b 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -167,6 +167,7 @@ struct input_keymap_entry { #define SYN_REPORT 0 #define SYN_CONFIG 1 #define SYN_MT_REPORT 2 +#define SYN_DROPPED 3 /* * Keys and buttons -- cgit v1.2.3