aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-09-21 17:22:39 -0400
committerJiri Kosina <jkosina@suse.cz>2010-09-21 17:22:39 -0400
commit1d958c83c8d77ad4977ae963017e87cec8cca9b5 (patch)
tree71ff2c0c756cb973d6d46dd0556138d05b78af4d /drivers/hid
parent1f01a1fe167f588c8b6b449fde2f5427ca940423 (diff)
HID: 3m: Correct touchscreen emulation
The current code sometimes misses to report the last BTN_TOUCH event when multiple fingers are lifted simultaneously. With the introduction of MT slots, the tracking id is available to determine the oldest active contact. Use this information to simplify and correct the touchscreen emulation logic. Signed-off-by: Henrik Rydberg <rydberg@euromail.se> Acked-by: Stéphane Chatty <chatty@enac.fr> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-3m-pct.c41
1 files changed, 5 insertions, 36 deletions
diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c
index 3c380e1c5b60..39628e02a428 100644
--- a/drivers/hid/hid-3m-pct.c
+++ b/drivers/hid/hid-3m-pct.c
@@ -37,7 +37,6 @@ MODULE_LICENSE("GPL");
37struct mmm_finger { 37struct mmm_finger {
38 __s32 x, y, w, h; 38 __s32 x, y, w, h;
39 __u16 id; 39 __u16 id;
40 __u8 rank;
41 bool prev_touch; 40 bool prev_touch;
42 bool touch, valid; 41 bool touch, valid;
43}; 42};
@@ -45,7 +44,7 @@ struct mmm_finger {
45struct mmm_data { 44struct mmm_data {
46 struct mmm_finger f[MAX_SLOTS]; 45 struct mmm_finger f[MAX_SLOTS];
47 __u16 id; 46 __u16 id;
48 __u8 curid, num; 47 __u8 curid;
49 __u8 nexp, nreal; 48 __u8 nexp, nreal;
50 bool touch, valid; 49 bool touch, valid;
51}; 50};
@@ -156,13 +155,7 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
156static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) 155static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
157{ 156{
158 struct mmm_finger *oldest = 0; 157 struct mmm_finger *oldest = 0;
159 bool pressed = false, released = false;
160 int i; 158 int i;
161
162 /*
163 * we need to iterate on all fingers to decide if we have a press
164 * or a release event in our touchscreen emulation.
165 */
166 for (i = 0; i < MAX_SLOTS; ++i) { 159 for (i = 0; i < MAX_SLOTS; ++i) {
167 struct mmm_finger *f = &md->f[i]; 160 struct mmm_finger *f = &md->f[i];
168 if (!f->valid) { 161 if (!f->valid) {
@@ -183,34 +176,11 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
183 wide ? f->w : f->h); 176 wide ? f->w : f->h);
184 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, 177 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR,
185 wide ? f->h : f->w); 178 wide ? f->h : f->w);
186 /* 179 /* touchscreen emulation: pick the oldest contact */
187 * touchscreen emulation: maintain the age rank 180 if (!oldest || ((f->id - oldest->id) & (SHRT_MAX + 1)))
188 * of this finger, decide if we have a press
189 */
190 if (f->rank == 0) {
191 f->rank = ++(md->num);
192 if (f->rank == 1)
193 pressed = true;
194 }
195 if (f->rank == 1)
196 oldest = f; 181 oldest = f;
197 } else { 182 } else {
198 /* this finger took off the screen */ 183 /* this finger took off the screen */
199 /* touchscreen emulation: maintain age rank of others */
200 int j;
201
202 for (j = 0; j < 10; ++j) {
203 struct mmm_finger *g = &md->f[j];
204 if (g->rank > f->rank) {
205 g->rank--;
206 if (g->rank == 1)
207 oldest = g;
208 }
209 }
210 f->rank = 0;
211 --(md->num);
212 if (md->num == 0)
213 released = true;
214 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1); 184 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1);
215 } 185 }
216 f->prev_touch = f->touch; 186 f->prev_touch = f->touch;
@@ -219,11 +189,10 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
219 189
220 /* touchscreen emulation */ 190 /* touchscreen emulation */
221 if (oldest) { 191 if (oldest) {
222 if (pressed) 192 input_event(input, EV_KEY, BTN_TOUCH, 1);
223 input_event(input, EV_KEY, BTN_TOUCH, 1);
224 input_event(input, EV_ABS, ABS_X, oldest->x); 193 input_event(input, EV_ABS, ABS_X, oldest->x);
225 input_event(input, EV_ABS, ABS_Y, oldest->y); 194 input_event(input, EV_ABS, ABS_Y, oldest->y);
226 } else if (released) { 195 } else {
227 input_event(input, EV_KEY, BTN_TOUCH, 0); 196 input_event(input, EV_KEY, BTN_TOUCH, 0);
228 } 197 }
229 input_sync(input); 198 input_sync(input);