aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-07-16 02:10:10 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-07-16 02:52:03 -0400
commit40d007e7df1dab17bf1ecf91e718218354d963d7 (patch)
treed8c12e13e71f411b4f66aa44ec9b23935156e49d
parenta8aef622929bbba4d89498fb41dd445c14fae1f7 (diff)
Input: introduce MT event slots
With the rapidly increasing number of intelligent multi-contact and multi-user devices, the need to send digested, filtered information from a set of different sources within the same device is imminent. This patch adds the concept of slots to the MT protocol. The slots enumerate a set of identified sources, such that all MT events can be passed independently and selectively per identified source. The protocol works like this: Instead of sending a SYN_MT_REPORT event immediately after the contact data, one sends an ABS_MT_SLOT event immediately before the contact data. The input core will only emit events for slots with modified MT events. It is assumed that the same slot is used for the duration of an initiated contact. Acked-by: Ping Cheng <pingc@wacom.com> Acked-by: Chase Douglas <chase.douglas@canonical.com> Acked-by: Rafi Rubin <rafi@seas.upenn.edu> Signed-off-by: Henrik Rydberg <rydberg@euromail.se> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/input/evdev.c4
-rw-r--r--drivers/input/input.c135
-rw-r--r--include/linux/input.h33
3 files changed, 129 insertions, 43 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index cd323254ca6f..fc5afbd78625 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -686,6 +686,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
686 sizeof(struct input_absinfo)))) 686 sizeof(struct input_absinfo))))
687 return -EFAULT; 687 return -EFAULT;
688 688
689 /* We can't change number of reserved MT slots */
690 if (t == ABS_MT_SLOT)
691 return -EINVAL;
692
689 /* 693 /*
690 * Take event lock to ensure that we are not 694 * Take event lock to ensure that we are not
691 * changing device parameters in the middle 695 * changing device parameters in the middle
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a3d5485154e7..54109c33e36c 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -33,25 +33,6 @@ MODULE_LICENSE("GPL");
33 33
34#define INPUT_DEVICES 256 34#define INPUT_DEVICES 256
35 35
36/*
37 * EV_ABS events which should not be cached are listed here.
38 */
39static unsigned int input_abs_bypass_init_data[] __initdata = {
40 ABS_MT_TOUCH_MAJOR,
41 ABS_MT_TOUCH_MINOR,
42 ABS_MT_WIDTH_MAJOR,
43 ABS_MT_WIDTH_MINOR,
44 ABS_MT_ORIENTATION,
45 ABS_MT_POSITION_X,
46 ABS_MT_POSITION_Y,
47 ABS_MT_TOOL_TYPE,
48 ABS_MT_BLOB_ID,
49 ABS_MT_TRACKING_ID,
50 ABS_MT_PRESSURE,
51 0
52};
53static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];
54
55static LIST_HEAD(input_dev_list); 36static LIST_HEAD(input_dev_list);
56static LIST_HEAD(input_handler_list); 37static LIST_HEAD(input_handler_list);
57 38
@@ -181,6 +162,56 @@ static void input_stop_autorepeat(struct input_dev *dev)
181#define INPUT_PASS_TO_DEVICE 2 162#define INPUT_PASS_TO_DEVICE 2
182#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) 163#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
183 164
165static int input_handle_abs_event(struct input_dev *dev,
166 unsigned int code, int *pval)
167{
168 bool is_mt_event;
169 int *pold;
170
171 if (code == ABS_MT_SLOT) {
172 /*
173 * "Stage" the event; we'll flush it later, when we
174 * get actiual touch data.
175 */
176 if (*pval >= 0 && *pval < dev->mtsize)
177 dev->slot = *pval;
178
179 return INPUT_IGNORE_EVENT;
180 }
181
182 is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;
183
184 if (!is_mt_event) {
185 pold = &dev->abs[code];
186 } else if (dev->mt) {
187 struct input_mt_slot *mtslot = &dev->mt[dev->slot];
188 pold = &mtslot->abs[code - ABS_MT_FIRST];
189 } else {
190 /*
191 * Bypass filtering for multitouch events when
192 * not employing slots.
193 */
194 pold = NULL;
195 }
196
197 if (pold) {
198 *pval = input_defuzz_abs_event(*pval, *pold,
199 dev->absfuzz[code]);
200 if (*pold == *pval)
201 return INPUT_IGNORE_EVENT;
202
203 *pold = *pval;
204 }
205
206 /* Flush pending "slot" event */
207 if (is_mt_event && dev->slot != dev->abs[ABS_MT_SLOT]) {
208 dev->abs[ABS_MT_SLOT] = dev->slot;
209 input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
210 }
211
212 return INPUT_PASS_TO_HANDLERS;
213}
214
184static void input_handle_event(struct input_dev *dev, 215static void input_handle_event(struct input_dev *dev,
185 unsigned int type, unsigned int code, int value) 216 unsigned int type, unsigned int code, int value)
186{ 217{
@@ -233,21 +264,9 @@ static void input_handle_event(struct input_dev *dev,
233 break; 264 break;
234 265
235 case EV_ABS: 266 case EV_ABS:
236 if (is_event_supported(code, dev->absbit, ABS_MAX)) { 267 if (is_event_supported(code, dev->absbit, ABS_MAX))
237 268 disposition = input_handle_abs_event(dev, code, &value);
238 if (test_bit(code, input_abs_bypass)) {
239 disposition = INPUT_PASS_TO_HANDLERS;
240 break;
241 }
242 269
243 value = input_defuzz_abs_event(value,
244 dev->abs[code], dev->absfuzz[code]);
245
246 if (dev->abs[code] != value) {
247 dev->abs[code] = value;
248 disposition = INPUT_PASS_TO_HANDLERS;
249 }
250 }
251 break; 270 break;
252 271
253 case EV_REL: 272 case EV_REL:
@@ -1288,6 +1307,7 @@ static void input_dev_release(struct device *device)
1288 struct input_dev *dev = to_input_dev(device); 1307 struct input_dev *dev = to_input_dev(device);
1289 1308
1290 input_ff_destroy(dev); 1309 input_ff_destroy(dev);
1310 input_mt_destroy_slots(dev);
1291 kfree(dev); 1311 kfree(dev);
1292 1312
1293 module_put(THIS_MODULE); 1313 module_put(THIS_MODULE);
@@ -1537,6 +1557,45 @@ void input_free_device(struct input_dev *dev)
1537EXPORT_SYMBOL(input_free_device); 1557EXPORT_SYMBOL(input_free_device);
1538 1558
1539/** 1559/**
1560 * input_mt_create_slots() - create MT input slots
1561 * @dev: input device supporting MT events and finger tracking
1562 * @num_slots: number of slots used by the device
1563 *
1564 * This function allocates all necessary memory for MT slot handling
1565 * in the input device, and adds ABS_MT_SLOT to the device capabilities.
1566 */
1567int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
1568{
1569 if (!num_slots)
1570 return 0;
1571
1572 dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
1573 if (!dev->mt)
1574 return -ENOMEM;
1575
1576 dev->mtsize = num_slots;
1577 input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
1578
1579 return 0;
1580}
1581EXPORT_SYMBOL(input_mt_create_slots);
1582
1583/**
1584 * input_mt_destroy_slots() - frees the MT slots of the input device
1585 * @dev: input device with allocated MT slots
1586 *
1587 * This function is only needed in error path as the input core will
1588 * automatically free the MT slots when the device is destroyed.
1589 */
1590void input_mt_destroy_slots(struct input_dev *dev)
1591{
1592 kfree(dev->mt);
1593 dev->mt = NULL;
1594 dev->mtsize = 0;
1595}
1596EXPORT_SYMBOL(input_mt_destroy_slots);
1597
1598/**
1540 * input_set_capability - mark device as capable of a certain event 1599 * input_set_capability - mark device as capable of a certain event
1541 * @dev: device that is capable of emitting or accepting event 1600 * @dev: device that is capable of emitting or accepting event
1542 * @type: type of the event (EV_KEY, EV_REL, etc...) 1601 * @type: type of the event (EV_KEY, EV_REL, etc...)
@@ -1945,20 +2004,10 @@ static const struct file_operations input_fops = {
1945 .open = input_open_file, 2004 .open = input_open_file,
1946}; 2005};
1947 2006
1948static void __init input_init_abs_bypass(void)
1949{
1950 const unsigned int *p;
1951
1952 for (p = input_abs_bypass_init_data; *p; p++)
1953 input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p);
1954}
1955
1956static int __init input_init(void) 2007static int __init input_init(void)
1957{ 2008{
1958 int err; 2009 int err;
1959 2010
1960 input_init_abs_bypass();
1961
1962 err = class_register(&input_class); 2011 err = class_register(&input_class);
1963 if (err) { 2012 if (err) {
1964 printk(KERN_ERR "input: unable to register input_dev class\n"); 2013 printk(KERN_ERR "input: unable to register input_dev class\n");
diff --git a/include/linux/input.h b/include/linux/input.h
index cc524c8b6703..a14de64ed16a 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -691,9 +691,12 @@ struct input_absinfo {
691#define ABS_TILT_X 0x1a 691#define ABS_TILT_X 0x1a
692#define ABS_TILT_Y 0x1b 692#define ABS_TILT_Y 0x1b
693#define ABS_TOOL_WIDTH 0x1c 693#define ABS_TOOL_WIDTH 0x1c
694
694#define ABS_VOLUME 0x20 695#define ABS_VOLUME 0x20
696
695#define ABS_MISC 0x28 697#define ABS_MISC 0x28
696 698
699#define ABS_MT_SLOT 0x2f /* MT slot being modified */
697#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */ 700#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
698#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */ 701#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
699#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */ 702#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
@@ -706,6 +709,12 @@ struct input_absinfo {
706#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */ 709#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
707#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */ 710#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
708 711
712#ifdef __KERNEL__
713/* Implementation details, userspace should not care about these */
714#define ABS_MT_FIRST ABS_MT_TOUCH_MAJOR
715#define ABS_MT_LAST ABS_MT_PRESSURE
716#endif
717
709#define ABS_MAX 0x3f 718#define ABS_MAX 0x3f
710#define ABS_CNT (ABS_MAX+1) 719#define ABS_CNT (ABS_MAX+1)
711 720
@@ -1048,6 +1057,14 @@ struct ff_effect {
1048#include <linux/mod_devicetable.h> 1057#include <linux/mod_devicetable.h>
1049 1058
1050/** 1059/**
1060 * struct input_mt_slot - represents the state of an input MT slot
1061 * @abs: holds current values of ABS_MT axes for this slot
1062 */
1063struct input_mt_slot {
1064 int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
1065};
1066
1067/**
1051 * struct input_dev - represents an input device 1068 * struct input_dev - represents an input device
1052 * @name: name of the device 1069 * @name: name of the device
1053 * @phys: physical path to the device in the system hierarchy 1070 * @phys: physical path to the device in the system hierarchy
@@ -1085,6 +1102,10 @@ struct ff_effect {
1085 * @sync: set to 1 when there were no new events since last EV_SYNC 1102 * @sync: set to 1 when there were no new events since last EV_SYNC
1086 * @abs: current values for reports from absolute axes 1103 * @abs: current values for reports from absolute axes
1087 * @rep: current values for autorepeat parameters (delay, rate) 1104 * @rep: current values for autorepeat parameters (delay, rate)
1105 * @mt: pointer to array of struct input_mt_slot holding current values
1106 * of tracked contacts
1107 * @mtsize: number of MT slots the device uses
1108 * @slot: MT slot currently being transmitted
1088 * @key: reflects current state of device's keys/buttons 1109 * @key: reflects current state of device's keys/buttons
1089 * @led: reflects current state of device's LEDs 1110 * @led: reflects current state of device's LEDs
1090 * @snd: reflects current state of sound effects 1111 * @snd: reflects current state of sound effects
@@ -1164,6 +1185,10 @@ struct input_dev {
1164 int abs[ABS_CNT]; 1185 int abs[ABS_CNT];
1165 int rep[REP_MAX + 1]; 1186 int rep[REP_MAX + 1];
1166 1187
1188 struct input_mt_slot *mt;
1189 int mtsize;
1190 int slot;
1191
1167 unsigned long key[BITS_TO_LONGS(KEY_CNT)]; 1192 unsigned long key[BITS_TO_LONGS(KEY_CNT)];
1168 unsigned long led[BITS_TO_LONGS(LED_CNT)]; 1193 unsigned long led[BITS_TO_LONGS(LED_CNT)];
1169 unsigned long snd[BITS_TO_LONGS(SND_CNT)]; 1194 unsigned long snd[BITS_TO_LONGS(SND_CNT)];
@@ -1412,6 +1437,11 @@ static inline void input_mt_sync(struct input_dev *dev)
1412 input_event(dev, EV_SYN, SYN_MT_REPORT, 0); 1437 input_event(dev, EV_SYN, SYN_MT_REPORT, 0);
1413} 1438}
1414 1439
1440static inline void input_mt_slot(struct input_dev *dev, int slot)
1441{
1442 input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
1443}
1444
1415void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code); 1445void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
1416 1446
1417/** 1447/**
@@ -1506,5 +1536,8 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
1506int input_ff_create_memless(struct input_dev *dev, void *data, 1536int input_ff_create_memless(struct input_dev *dev, void *data,
1507 int (*play_effect)(struct input_dev *, void *, struct ff_effect *)); 1537 int (*play_effect)(struct input_dev *, void *, struct ff_effect *));
1508 1538
1539int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots);
1540void input_mt_destroy_slots(struct input_dev *dev);
1541
1509#endif 1542#endif
1510#endif 1543#endif