Commit c5f4dec1ceb6ab773bbbefbe64a7c990c7d6b17f

Authored by Henrik Rydberg
1 parent 8cde810016

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>

Showing 7 changed files with 138 additions and 71 deletions Side-by-side Diff

drivers/hid/hid-3m-pct.c
... ... @@ -28,7 +28,6 @@
28 28 #include "hid-ids.h"
29 29  
30 30 #define MAX_SLOTS 60
31   -#define MAX_TRKID USHRT_MAX
32 31  
33 32 /* estimated signal-to-noise ratios */
34 33 #define SN_MOVE 2048
35 34  
... ... @@ -36,14 +35,11 @@
36 35  
37 36 struct mmm_finger {
38 37 __s32 x, y, w, h;
39   - __u16 id;
40   - bool prev_touch;
41 38 bool touch, valid;
42 39 };
43 40  
44 41 struct mmm_data {
45 42 struct mmm_finger f[MAX_SLOTS];
46   - __u16 id;
47 43 __u8 curid;
48 44 __u8 nexp, nreal;
49 45 bool touch, valid;
... ... @@ -117,11 +113,6 @@
117 113 0, 1, 0, 0);
118 114 return 1;
119 115 case HID_DG_CONTACTID:
120   - field->logical_maximum = MAX_TRKID;
121   - hid_map_usage(hi, usage, bit, max,
122   - EV_ABS, ABS_MT_TRACKING_ID);
123   - input_set_abs_params(hi->input, ABS_MT_TRACKING_ID,
124   - 0, MAX_TRKID, 0, 0);
125 116 input_mt_init_slots(hi->input, MAX_SLOTS);
126 117 return 1;
127 118 }
... ... @@ -152,7 +143,6 @@
152 143 */
153 144 static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
154 145 {
155   - struct mmm_finger *oldest = 0;
156 146 int i;
157 147 for (i = 0; i < MAX_SLOTS; ++i) {
158 148 struct mmm_finger *f = &md->f[i];
... ... @@ -161,6 +151,7 @@
161 151 continue;
162 152 }
163 153 input_mt_slot(input, i);
  154 + input_mt_report_slot_state(input, MT_TOOL_FINGER, f->touch);
164 155 if (f->touch) {
165 156 /* this finger is on the screen */
166 157 int wide = (f->w > f->h);
167 158  
168 159  
169 160  
... ... @@ -168,33 +159,16 @@
168 159 int major = max(f->w, f->h) >> 1;
169 160 int minor = min(f->w, f->h) >> 1;
170 161  
171   - if (!f->prev_touch)
172   - f->id = md->id++;
173   - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id);
174 162 input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
175 163 input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
176 164 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
177 165 input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
178 166 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
179   - /* touchscreen emulation: pick the oldest contact */
180   - if (!oldest || ((f->id - oldest->id) & (SHRT_MAX + 1)))
181   - oldest = f;
182   - } else {
183   - /* this finger took off the screen */
184   - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1);
185 167 }
186   - f->prev_touch = f->touch;
187 168 f->valid = 0;
188 169 }
189 170  
190   - /* touchscreen emulation */
191   - if (oldest) {
192   - input_event(input, EV_KEY, BTN_TOUCH, 1);
193   - input_event(input, EV_ABS, ABS_X, oldest->x);
194   - input_event(input, EV_ABS, ABS_Y, oldest->y);
195   - } else {
196   - input_event(input, EV_KEY, BTN_TOUCH, 0);
197   - }
  171 + input_mt_report_pointer_emulation(input, true);
198 172 input_sync(input);
199 173 }
200 174  
drivers/input/input-mt.c
... ... @@ -11,17 +11,18 @@
11 11 #include <linux/input/mt.h>
12 12 #include <linux/slab.h>
13 13  
  14 +#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
  15 +
14 16 /**
15 17 * input_mt_init_slots() - initialize MT input slots
16 18 * @dev: input device supporting MT events and finger tracking
17 19 * @num_slots: number of slots used by the device
18 20 *
19 21 * This function allocates all necessary memory for MT slot handling
20   - * in the input device, adds ABS_MT_SLOT to the device capabilities
21   - * and sets up appropriate event buffers. All slots are initially
22   - * marked as unused by setting ABS_MT_TRACKING_ID to -1. May be called
23   - * repeatedly. Returns -EINVAL if attempting to reinitialize with a
24   - * different number of slots.
  22 + * in the input device, prepares the ABS_MT_SLOT and
  23 + * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
  24 + * May be called repeatedly. Returns -EINVAL if attempting to
  25 + * reinitialize with a different number of slots.
25 26 */
26 27 int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
27 28 {
... ... @@ -38,6 +39,7 @@
38 39  
39 40 dev->mtsize = num_slots;
40 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 43 input_set_events_per_packet(dev, 6 * num_slots);
42 44  
43 45 /* Mark slots as 'unused' */
44 46  
... ... @@ -61,6 +63,109 @@
61 63 dev->mt = NULL;
62 64 dev->mtsize = 0;
63 65 dev->slot = 0;
  66 + dev->trkid = 0;
64 67 }
65 68 EXPORT_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 + */
  82 +void 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 +}
  101 +EXPORT_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 + */
  114 +void 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 +}
  121 +EXPORT_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 + */
  134 +void 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 +}
  170 +EXPORT_SYMBOL(input_mt_report_pointer_emulation);
drivers/input/tablet/wacom_wac.c
... ... @@ -863,19 +863,21 @@
863 863 struct wacom_features *features = &wacom->features;
864 864 struct input_dev *input = wacom->input;
865 865 unsigned char *data = wacom->data;
866   - int sp = 0, sx = 0, sy = 0, count = 0;
867 866 int i;
868 867  
869 868 for (i = 0; i < 2; i++) {
870 869 int p = data[9 * i + 2];
  870 + bool touch = p && !wacom->shared->stylus_in_proximity;
  871 +
871 872 input_mt_slot(input, i);
  873 + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
872 874 /*
873 875 * Touch events need to be disabled while stylus is
874 876 * in proximity because user's hand is resting on touchpad
875 877 * and sending unwanted events. User expects tablet buttons
876 878 * to continue working though.
877 879 */
878   - if (p && !wacom->shared->stylus_in_proximity) {
  880 + if (touch) {
879 881 int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff;
880 882 int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff;
881 883 if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) {
882 884  
883 885  
884 886  
... ... @@ -885,24 +887,11 @@
885 887 input_report_abs(input, ABS_MT_PRESSURE, p);
886 888 input_report_abs(input, ABS_MT_POSITION_X, x);
887 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);
899   - input_report_key(input, BTN_TOOL_FINGER, count == 1);
900   - input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2);
  893 + input_mt_report_pointer_emulation(input, true);
901 894  
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   -
906 895 input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
907 896 input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
908 897 input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
... ... @@ -1283,8 +1272,6 @@
1283 1272 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
1284 1273 0, features->pressure_max,
1285 1274 features->pressure_fuzz, 0);
1286   - input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
1287   - MAX_TRACKING_ID, 0, 0);
1288 1275 } else if (features->device_type == BTN_TOOL_PEN) {
1289 1276 __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
1290 1277 __set_bit(BTN_TOOL_PEN, input_dev->keybit);
drivers/input/tablet/wacom_wac.h
... ... @@ -42,9 +42,6 @@
42 42 #define WACOM_QUIRK_MULTI_INPUT 0x0001
43 43 #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002
44 44  
45   -/* largest reported tracking id */
46   -#define MAX_TRACKING_ID 0xfff
47   -
48 45 enum {
49 46 PENPARTNER = 0,
50 47 GRAPHIRE,
... ... @@ -100,7 +97,6 @@
100 97 int id[3];
101 98 __u32 serial[2];
102 99 int last_finger;
103   - int trk_id;
104 100 struct wacom_features features;
105 101 struct wacom_shared *shared;
106 102 struct input_dev *input;
drivers/input/touchscreen/wacom_w8001.c
... ... @@ -48,8 +48,6 @@
48 48 #define W8001_PKTLEN_TPCCTL 11 /* control packet */
49 49 #define W8001_PKTLEN_TOUCH2FG 13
50 50  
51   -#define MAX_TRACKING_ID 0xFF /* arbitrarily chosen */
52   -
53 51 struct w8001_coord {
54 52 u8 rdy;
55 53 u8 tsw;
... ... @@ -87,7 +85,6 @@
87 85 char phys[32];
88 86 int type;
89 87 unsigned int pktlen;
90   - int trkid[2];
91 88 };
92 89  
93 90 static void parse_data(u8 *data, struct w8001_coord *coord)
94 91  
95 92  
96 93  
97 94  
... ... @@ -116,28 +113,23 @@
116 113  
117 114 static void parse_touch(struct w8001 *w8001)
118 115 {
119   - static int trkid;
120 116 struct input_dev *dev = w8001->dev;
121 117 unsigned char *data = w8001->data;
122 118 int i;
123 119  
124 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 126 int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]);
129 127 int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]);
130 128 /* data[5,6] and [11,12] is finger capacity */
131 129  
132 130 input_report_abs(dev, ABS_MT_POSITION_X, x);
133 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 135 input_sync(dev);
144 136  
... ... @@ -319,14 +311,12 @@
319 311 w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
320 312  
321 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 314 input_set_abs_params(dev, ABS_MT_POSITION_X,
325 315 0, touch.x, 0, 0);
326 316 input_set_abs_params(dev, ABS_MT_POSITION_Y,
327 317 0, touch.y, 0, 0);
328 318 input_set_abs_params(dev, ABS_MT_TOOL_TYPE,
329   - 0, 0, 0, 0);
  319 + 0, MT_TOOL_MAX, 0, 0);
330 320 break;
331 321 }
332 322 }
... ... @@ -372,7 +362,6 @@
372 362 w8001->serio = serio;
373 363 w8001->id = serio->id.id;
374 364 w8001->dev = input_dev;
375   - w8001->trkid[0] = w8001->trkid[1] = -1;
376 365 init_completion(&w8001->cmd_done);
377 366 snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
378 367  
include/linux/input.h
... ... @@ -848,6 +848,7 @@
848 848 */
849 849 #define MT_TOOL_FINGER 0
850 850 #define MT_TOOL_PEN 1
  851 +#define MT_TOOL_MAX 1
851 852  
852 853 /*
853 854 * Values describing the status of a force-feedback effect
... ... @@ -1122,6 +1123,7 @@
1122 1123 * of tracked contacts
1123 1124 * @mtsize: number of MT slots the device uses
1124 1125 * @slot: MT slot currently being transmitted
  1126 + * @trkid: stores MT tracking ID for the current contact
1125 1127 * @absinfo: array of &struct absinfo elements holding information
1126 1128 * about absolute axes (current value, min, max, flat, fuzz,
1127 1129 * resolution)
... ... @@ -1206,6 +1208,7 @@
1206 1208 struct input_mt_slot *mt;
1207 1209 int mtsize;
1208 1210 int slot;
  1211 + int trkid;
1209 1212  
1210 1213 struct input_absinfo *absinfo;
1211 1214  
include/linux/input/mt.h
... ... @@ -13,6 +13,8 @@
13 13  
14 14 #include <linux/input.h>
15 15  
  16 +#define TRKID_MAX 0xffff
  17 +
16 18 /**
17 19 * struct input_mt_slot - represents the state of an input MT slot
18 20 * @abs: holds current values of ABS_MT axes for this slot
19 21  
... ... @@ -36,10 +38,21 @@
36 38 int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots);
37 39 void input_mt_destroy_slots(struct input_dev *dev);
38 40  
  41 +static inline int input_mt_new_trkid(struct input_dev *dev)
  42 +{
  43 + return dev->trkid++ & TRKID_MAX;
  44 +}
  45 +
39 46 static inline void input_mt_slot(struct input_dev *dev, int slot)
40 47 {
41 48 input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
42 49 }
  50 +
  51 +void input_mt_report_slot_state(struct input_dev *dev,
  52 + unsigned int tool_type, bool active);
  53 +
  54 +void input_mt_report_finger_count(struct input_dev *dev, int count);
  55 +void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count);
43 56  
44 57 #endif