aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@enac.fr>2011-06-12 02:22:08 -0400
committerJiri Kosina <jkosina@suse.cz>2011-06-12 17:59:23 -0400
commitb84bd27fe70206f9253c395958134e4e4b7e55f0 (patch)
treea9f04e1f620a5bed4605bdde9ac6b30480bb0801 /drivers
parentc2f019713df67e09d32e1b3c12f147a83a579d25 (diff)
HID: hid-multitouch: fix broken eGalax
Since the inclusion of eGalax devices in 2.6.39, I've got some bug reports for 480d and other devices. The problem lies in the reports descriptors: eGalax supports both pen and fingers, and so the reports descriptors contained both. But hid-multitouch relies on them to detect the last item in each field to send the multitouch events. In 480d, the last item is not Y as it should but Pressure. That means that the fields are not aligned and X,Y are at 0,0 (the other touch coordinates of the report). With this patch, the detection is made only when the field ContactID has been detected inside the collection. There is still a problem with the detections of the range as stylus and fingers may not have the same min/max, but it's a start. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr> Reviewed-by: Henrik Rydberg <rydberg@euromail.se> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hid/hid-multitouch.c57
1 files changed, 39 insertions, 18 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 8bc32a0fa00e..0b2dcd0ee591 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -64,6 +64,7 @@ struct mt_device {
64 struct mt_class *mtclass; /* our mt device class */ 64 struct mt_class *mtclass; /* our mt device class */
65 unsigned last_field_index; /* last field index of the report */ 65 unsigned last_field_index; /* last field index of the report */
66 unsigned last_slot_field; /* the last field of a slot */ 66 unsigned last_slot_field; /* the last field of a slot */
67 int last_mt_collection; /* last known mt-related collection */
67 __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ 68 __s8 inputmode; /* InputMode HID feature, -1 if non-existent */
68 __u8 num_received; /* how many contacts we received */ 69 __u8 num_received; /* how many contacts we received */
69 __u8 num_expected; /* expected last contact index */ 70 __u8 num_expected; /* expected last contact index */
@@ -225,8 +226,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
225 cls->sn_move); 226 cls->sn_move);
226 /* touchscreen emulation */ 227 /* touchscreen emulation */
227 set_abs(hi->input, ABS_X, field, cls->sn_move); 228 set_abs(hi->input, ABS_X, field, cls->sn_move);
228 td->last_slot_field = usage->hid; 229 if (td->last_mt_collection == usage->collection_index) {
229 td->last_field_index = field->index; 230 td->last_slot_field = usage->hid;
231 td->last_field_index = field->index;
232 }
230 return 1; 233 return 1;
231 case HID_GD_Y: 234 case HID_GD_Y:
232 if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) 235 if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
@@ -237,8 +240,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
237 cls->sn_move); 240 cls->sn_move);
238 /* touchscreen emulation */ 241 /* touchscreen emulation */
239 set_abs(hi->input, ABS_Y, field, cls->sn_move); 242 set_abs(hi->input, ABS_Y, field, cls->sn_move);
240 td->last_slot_field = usage->hid; 243 if (td->last_mt_collection == usage->collection_index) {
241 td->last_field_index = field->index; 244 td->last_slot_field = usage->hid;
245 td->last_field_index = field->index;
246 }
242 return 1; 247 return 1;
243 } 248 }
244 return 0; 249 return 0;
@@ -246,31 +251,40 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
246 case HID_UP_DIGITIZER: 251 case HID_UP_DIGITIZER:
247 switch (usage->hid) { 252 switch (usage->hid) {
248 case HID_DG_INRANGE: 253 case HID_DG_INRANGE:
249 td->last_slot_field = usage->hid; 254 if (td->last_mt_collection == usage->collection_index) {
250 td->last_field_index = field->index; 255 td->last_slot_field = usage->hid;
256 td->last_field_index = field->index;
257 }
251 return 1; 258 return 1;
252 case HID_DG_CONFIDENCE: 259 case HID_DG_CONFIDENCE:
253 td->last_slot_field = usage->hid; 260 if (td->last_mt_collection == usage->collection_index) {
254 td->last_field_index = field->index; 261 td->last_slot_field = usage->hid;
262 td->last_field_index = field->index;
263 }
255 return 1; 264 return 1;
256 case HID_DG_TIPSWITCH: 265 case HID_DG_TIPSWITCH:
257 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); 266 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
258 input_set_capability(hi->input, EV_KEY, BTN_TOUCH); 267 input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
259 td->last_slot_field = usage->hid; 268 if (td->last_mt_collection == usage->collection_index) {
260 td->last_field_index = field->index; 269 td->last_slot_field = usage->hid;
270 td->last_field_index = field->index;
271 }
261 return 1; 272 return 1;
262 case HID_DG_CONTACTID: 273 case HID_DG_CONTACTID:
263 input_mt_init_slots(hi->input, td->maxcontacts); 274 input_mt_init_slots(hi->input, td->maxcontacts);
264 td->last_slot_field = usage->hid; 275 td->last_slot_field = usage->hid;
265 td->last_field_index = field->index; 276 td->last_field_index = field->index;
277 td->last_mt_collection = usage->collection_index;
266 return 1; 278 return 1;
267 case HID_DG_WIDTH: 279 case HID_DG_WIDTH:
268 hid_map_usage(hi, usage, bit, max, 280 hid_map_usage(hi, usage, bit, max,
269 EV_ABS, ABS_MT_TOUCH_MAJOR); 281 EV_ABS, ABS_MT_TOUCH_MAJOR);
270 set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, 282 set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
271 cls->sn_width); 283 cls->sn_width);
272 td->last_slot_field = usage->hid; 284 if (td->last_mt_collection == usage->collection_index) {
273 td->last_field_index = field->index; 285 td->last_slot_field = usage->hid;
286 td->last_field_index = field->index;
287 }
274 return 1; 288 return 1;
275 case HID_DG_HEIGHT: 289 case HID_DG_HEIGHT:
276 hid_map_usage(hi, usage, bit, max, 290 hid_map_usage(hi, usage, bit, max,
@@ -279,8 +293,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
279 cls->sn_height); 293 cls->sn_height);
280 input_set_abs_params(hi->input, 294 input_set_abs_params(hi->input,
281 ABS_MT_ORIENTATION, 0, 1, 0, 0); 295 ABS_MT_ORIENTATION, 0, 1, 0, 0);
282 td->last_slot_field = usage->hid; 296 if (td->last_mt_collection == usage->collection_index) {
283 td->last_field_index = field->index; 297 td->last_slot_field = usage->hid;
298 td->last_field_index = field->index;
299 }
284 return 1; 300 return 1;
285 case HID_DG_TIPPRESSURE: 301 case HID_DG_TIPPRESSURE:
286 if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) 302 if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
@@ -292,16 +308,20 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
292 /* touchscreen emulation */ 308 /* touchscreen emulation */
293 set_abs(hi->input, ABS_PRESSURE, field, 309 set_abs(hi->input, ABS_PRESSURE, field,
294 cls->sn_pressure); 310 cls->sn_pressure);
295 td->last_slot_field = usage->hid; 311 if (td->last_mt_collection == usage->collection_index) {
296 td->last_field_index = field->index; 312 td->last_slot_field = usage->hid;
313 td->last_field_index = field->index;
314 }
297 return 1; 315 return 1;
298 case HID_DG_CONTACTCOUNT: 316 case HID_DG_CONTACTCOUNT:
299 td->last_field_index = field->index; 317 if (td->last_mt_collection == usage->collection_index)
318 td->last_field_index = field->index;
300 return 1; 319 return 1;
301 case HID_DG_CONTACTMAX: 320 case HID_DG_CONTACTMAX:
302 /* we don't set td->last_slot_field as contactcount and 321 /* we don't set td->last_slot_field as contactcount and
303 * contact max are global to the report */ 322 * contact max are global to the report */
304 td->last_field_index = field->index; 323 if (td->last_mt_collection == usage->collection_index)
324 td->last_field_index = field->index;
305 return -1; 325 return -1;
306 } 326 }
307 /* let hid-input decide for the others */ 327 /* let hid-input decide for the others */
@@ -516,6 +536,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
516 } 536 }
517 td->mtclass = mtclass; 537 td->mtclass = mtclass;
518 td->inputmode = -1; 538 td->inputmode = -1;
539 td->last_mt_collection = -1;
519 hid_set_drvdata(hdev, td); 540 hid_set_drvdata(hdev, td);
520 541
521 ret = hid_parse(hdev); 542 ret = hid_parse(hdev);