aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-12-15 07:50:34 -0500
committerHenrik Rydberg <rydberg@euromail.se>2010-12-16 04:41:38 -0500
commitc5f4dec1ceb6ab773bbbefbe64a7c990c7d6b17f (patch)
treefdc8b67537b73474bd34b65d0d1c5bc7a9de3c7a /drivers/input
parent8cde81001626c4c60b26ef2eb5fc522885ed9fd0 (diff)
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 <pingc@wacom.com> Acked-by: Jiri Kosina <jkosina@suse.cz> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/input-mt.c115
-rw-r--r--drivers/input/tablet/wacom_wac.c23
-rw-r--r--drivers/input/tablet/wacom_wac.h4
-rw-r--r--drivers/input/touchscreen/wacom_w8001.c21
4 files changed, 120 insertions, 43 deletions
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 @@
11#include <linux/input/mt.h> 11#include <linux/input/mt.h>
12#include <linux/slab.h> 12#include <linux/slab.h>
13 13
14#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
15
14/** 16/**
15 * input_mt_init_slots() - initialize MT input slots 17 * input_mt_init_slots() - initialize MT input slots
16 * @dev: input device supporting MT events and finger tracking 18 * @dev: input device supporting MT events and finger tracking
17 * @num_slots: number of slots used by the device 19 * @num_slots: number of slots used by the device
18 * 20 *
19 * This function allocates all necessary memory for MT slot handling 21 * This function allocates all necessary memory for MT slot handling
20 * in the input device, adds ABS_MT_SLOT to the device capabilities 22 * in the input device, prepares the ABS_MT_SLOT and
21 * and sets up appropriate event buffers. All slots are initially 23 * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
22 * marked as unused by setting ABS_MT_TRACKING_ID to -1. May be called 24 * May be called repeatedly. Returns -EINVAL if attempting to
23 * repeatedly. Returns -EINVAL if attempting to reinitialize with a 25 * reinitialize with a different number of slots.
24 * different number of slots.
25 */ 26 */
26int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) 27int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
27{ 28{
@@ -38,6 +39,7 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
38 39
39 dev->mtsize = num_slots; 40 dev->mtsize = num_slots;
40 input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); 41 input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
42 input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
41 input_set_events_per_packet(dev, 6 * num_slots); 43 input_set_events_per_packet(dev, 6 * num_slots);
42 44
43 /* Mark slots as 'unused' */ 45 /* Mark slots as 'unused' */
@@ -61,5 +63,108 @@ void input_mt_destroy_slots(struct input_dev *dev)
61 dev->mt = NULL; 63 dev->mt = NULL;
62 dev->mtsize = 0; 64 dev->mtsize = 0;
63 dev->slot = 0; 65 dev->slot = 0;
66 dev->trkid = 0;
64} 67}
65EXPORT_SYMBOL(input_mt_destroy_slots); 68EXPORT_SYMBOL(input_mt_destroy_slots);
69
70/**
71 * input_mt_report_slot_state() - report contact state
72 * @dev: input device with allocated MT slots
73 * @tool_type: the tool type to use in this slot
74 * @active: true if contact is active, false otherwise
75 *
76 * Reports a contact via ABS_MT_TRACKING_ID, and optionally
77 * ABS_MT_TOOL_TYPE. If active is true and the slot is currently
78 * inactive, or if the tool type is changed, a new tracking id is
79 * assigned to the slot. The tool type is only reported if the
80 * corresponding absbit field is set.
81 */
82void input_mt_report_slot_state(struct input_dev *dev,
83 unsigned int tool_type, bool active)
84{
85 struct input_mt_slot *mt;
86 int id;
87
88 if (!dev->mt || !active) {
89 input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
90 return;
91 }
92
93 mt = &dev->mt[dev->slot];
94 id = input_mt_get_value(mt, ABS_MT_TRACKING_ID);
95 if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type)
96 id = input_mt_new_trkid(dev);
97
98 input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
99 input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
100}
101EXPORT_SYMBOL(input_mt_report_slot_state);
102
103/**
104 * input_mt_report_finger_count() - report contact count
105 * @dev: input device with allocated MT slots
106 * @count: the number of contacts
107 *
108 * Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,
109 * BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP.
110 *
111 * The input core ensures only the KEY events already setup for
112 * this device will produce output.
113 */
114void input_mt_report_finger_count(struct input_dev *dev, int count)
115{
116 input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1);
117 input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
118 input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
119 input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4);
120}
121EXPORT_SYMBOL(input_mt_report_finger_count);
122
123/**
124 * input_mt_report_pointer_emulation() - common pointer emulation
125 * @dev: input device with allocated MT slots
126 * @use_count: report number of active contacts as finger count
127 *
128 * Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and
129 * ABS_PRESSURE. Touchpad finger count is emulated if use_count is true.
130 *
131 * The input core ensures only the KEY and ABS axes already setup for
132 * this device will produce output.
133 */
134void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
135{
136 struct input_mt_slot *oldest = 0;
137 int oldid = dev->trkid;
138 int count = 0;
139 int i;
140
141 for (i = 0; i < dev->mtsize; ++i) {
142 struct input_mt_slot *ps = &dev->mt[i];
143 int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
144
145 if (id < 0)
146 continue;
147 if ((id - oldid) & TRKID_SGN) {
148 oldest = ps;
149 oldid = id;
150 }
151 count++;
152 }
153
154 input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
155 if (use_count)
156 input_mt_report_finger_count(dev, count);
157
158 if (oldest) {
159 int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
160 int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
161 int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
162
163 input_event(dev, EV_ABS, ABS_X, x);
164 input_event(dev, EV_ABS, ABS_Y, y);
165 input_event(dev, EV_ABS, ABS_PRESSURE, p);
166 } else {
167 input_event(dev, EV_ABS, ABS_PRESSURE, 0);
168 }
169}
170EXPORT_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)
863 struct wacom_features *features = &wacom->features; 863 struct wacom_features *features = &wacom->features;
864 struct input_dev *input = wacom->input; 864 struct input_dev *input = wacom->input;
865 unsigned char *data = wacom->data; 865 unsigned char *data = wacom->data;
866 int sp = 0, sx = 0, sy = 0, count = 0;
867 int i; 866 int i;
868 867
869 for (i = 0; i < 2; i++) { 868 for (i = 0; i < 2; i++) {
870 int p = data[9 * i + 2]; 869 int p = data[9 * i + 2];
870 bool touch = p && !wacom->shared->stylus_in_proximity;
871
871 input_mt_slot(input, i); 872 input_mt_slot(input, i);
873 input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
872 /* 874 /*
873 * Touch events need to be disabled while stylus is 875 * Touch events need to be disabled while stylus is
874 * in proximity because user's hand is resting on touchpad 876 * in proximity because user's hand is resting on touchpad
875 * and sending unwanted events. User expects tablet buttons 877 * and sending unwanted events. User expects tablet buttons
876 * to continue working though. 878 * to continue working though.
877 */ 879 */
878 if (p && !wacom->shared->stylus_in_proximity) { 880 if (touch) {
879 int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff; 881 int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff;
880 int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff; 882 int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff;
881 if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) { 883 if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) {
@@ -885,23 +887,10 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
885 input_report_abs(input, ABS_MT_PRESSURE, p); 887 input_report_abs(input, ABS_MT_PRESSURE, p);
886 input_report_abs(input, ABS_MT_POSITION_X, x); 888 input_report_abs(input, ABS_MT_POSITION_X, x);
887 input_report_abs(input, ABS_MT_POSITION_Y, y); 889 input_report_abs(input, ABS_MT_POSITION_Y, y);
888 if (wacom->id[i] < 0)
889 wacom->id[i] = wacom->trk_id++ & MAX_TRACKING_ID;
890 if (!count++)
891 sp = p, sx = x, sy = y;
892 } else {
893 wacom->id[i] = -1;
894 } 890 }
895 input_report_abs(input, ABS_MT_TRACKING_ID, wacom->id[i]);
896 } 891 }
897 892
898 input_report_key(input, BTN_TOUCH, count > 0); 893 input_mt_report_pointer_emulation(input, true);
899 input_report_key(input, BTN_TOOL_FINGER, count == 1);
900 input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2);
901
902 input_report_abs(input, ABS_PRESSURE, sp);
903 input_report_abs(input, ABS_X, sx);
904 input_report_abs(input, ABS_Y, sy);
905 894
906 input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); 895 input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
907 input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); 896 input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
@@ -1283,8 +1272,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
1283 input_set_abs_params(input_dev, ABS_MT_PRESSURE, 1272 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
1284 0, features->pressure_max, 1273 0, features->pressure_max,
1285 features->pressure_fuzz, 0); 1274 features->pressure_fuzz, 0);
1286 input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
1287 MAX_TRACKING_ID, 0, 0);
1288 } else if (features->device_type == BTN_TOOL_PEN) { 1275 } else if (features->device_type == BTN_TOOL_PEN) {
1289 __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); 1276 __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
1290 __set_bit(BTN_TOOL_PEN, input_dev->keybit); 1277 __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 @@
42#define WACOM_QUIRK_MULTI_INPUT 0x0001 42#define WACOM_QUIRK_MULTI_INPUT 0x0001
43#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002 43#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002
44 44
45/* largest reported tracking id */
46#define MAX_TRACKING_ID 0xfff
47
48enum { 45enum {
49 PENPARTNER = 0, 46 PENPARTNER = 0,
50 GRAPHIRE, 47 GRAPHIRE,
@@ -100,7 +97,6 @@ struct wacom_wac {
100 int id[3]; 97 int id[3];
101 __u32 serial[2]; 98 __u32 serial[2];
102 int last_finger; 99 int last_finger;
103 int trk_id;
104 struct wacom_features features; 100 struct wacom_features features;
105 struct wacom_shared *shared; 101 struct wacom_shared *shared;
106 struct input_dev *input; 102 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");
48#define W8001_PKTLEN_TPCCTL 11 /* control packet */ 48#define W8001_PKTLEN_TPCCTL 11 /* control packet */
49#define W8001_PKTLEN_TOUCH2FG 13 49#define W8001_PKTLEN_TOUCH2FG 13
50 50
51#define MAX_TRACKING_ID 0xFF /* arbitrarily chosen */
52
53struct w8001_coord { 51struct w8001_coord {
54 u8 rdy; 52 u8 rdy;
55 u8 tsw; 53 u8 tsw;
@@ -87,7 +85,6 @@ struct w8001 {
87 char phys[32]; 85 char phys[32];
88 int type; 86 int type;
89 unsigned int pktlen; 87 unsigned int pktlen;
90 int trkid[2];
91}; 88};
92 89
93static void parse_data(u8 *data, struct w8001_coord *coord) 90static void parse_data(u8 *data, struct w8001_coord *coord)
@@ -116,28 +113,23 @@ static void parse_data(u8 *data, struct w8001_coord *coord)
116 113
117static void parse_touch(struct w8001 *w8001) 114static void parse_touch(struct w8001 *w8001)
118{ 115{
119 static int trkid;
120 struct input_dev *dev = w8001->dev; 116 struct input_dev *dev = w8001->dev;
121 unsigned char *data = w8001->data; 117 unsigned char *data = w8001->data;
122 int i; 118 int i;
123 119
124 for (i = 0; i < 2; i++) { 120 for (i = 0; i < 2; i++) {
125 input_mt_slot(dev, i); 121 bool touch = data[0] & (1 << i);
126 122
127 if (data[0] & (1 << i)) { 123 input_mt_slot(dev, i);
124 input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch);
125 if (touch) {
128 int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]); 126 int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]);
129 int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]); 127 int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]);
130 /* data[5,6] and [11,12] is finger capacity */ 128 /* data[5,6] and [11,12] is finger capacity */
131 129
132 input_report_abs(dev, ABS_MT_POSITION_X, x); 130 input_report_abs(dev, ABS_MT_POSITION_X, x);
133 input_report_abs(dev, ABS_MT_POSITION_Y, y); 131 input_report_abs(dev, ABS_MT_POSITION_Y, y);
134 input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
135 if (w8001->trkid[i] < 0)
136 w8001->trkid[i] = trkid++ & MAX_TRACKING_ID;
137 } else {
138 w8001->trkid[i] = -1;
139 } 132 }
140 input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]);
141 } 133 }
142 134
143 input_sync(dev); 135 input_sync(dev);
@@ -319,14 +311,12 @@ static int w8001_setup(struct w8001 *w8001)
319 w8001->pktlen = W8001_PKTLEN_TOUCH2FG; 311 w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
320 312
321 input_mt_init_slots(dev, 2); 313 input_mt_init_slots(dev, 2);
322 input_set_abs_params(dev, ABS_MT_TRACKING_ID,
323 0, MAX_TRACKING_ID, 0, 0);
324 input_set_abs_params(dev, ABS_MT_POSITION_X, 314 input_set_abs_params(dev, ABS_MT_POSITION_X,
325 0, touch.x, 0, 0); 315 0, touch.x, 0, 0);
326 input_set_abs_params(dev, ABS_MT_POSITION_Y, 316 input_set_abs_params(dev, ABS_MT_POSITION_Y,
327 0, touch.y, 0, 0); 317 0, touch.y, 0, 0);
328 input_set_abs_params(dev, ABS_MT_TOOL_TYPE, 318 input_set_abs_params(dev, ABS_MT_TOOL_TYPE,
329 0, 0, 0, 0); 319 0, MT_TOOL_MAX, 0, 0);
330 break; 320 break;
331 } 321 }
332 } 322 }
@@ -372,7 +362,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
372 w8001->serio = serio; 362 w8001->serio = serio;
373 w8001->id = serio->id.id; 363 w8001->id = serio->id.id;
374 w8001->dev = input_dev; 364 w8001->dev = input_dev;
375 w8001->trkid[0] = w8001->trkid[1] = -1;
376 init_completion(&w8001->cmd_done); 365 init_completion(&w8001->cmd_done);
377 snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); 366 snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
378 367