diff options
author | Benjamin Tissoires <benjamin.tissoires@enac.fr> | 2011-03-22 12:34:01 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-03-24 07:44:45 -0400 |
commit | f786bba4499cf3de20da345ce090457ebcef03b0 (patch) | |
tree | 8b26ca5808f3c711f9da708f89dba8a3c8ea82e5 /drivers/hid/hid-multitouch.c | |
parent | 1e648a13720ef5de51f132501acf3e443d1a36d4 (diff) |
HID: hid-multitouch: migrate 3M PCT touch screens to hid-multitouch
This patch merges the hid-3m-pct driver into hid-multitouch.
To keep devices working the same way they used to with hid-3m-pct,
we need to add two signal/noise ratios for width and height.
We also need to work on width/height to send proper
ABS_MT_ORIENTATION flag.
Importing 3M into hid-multitouch also solved the bug in which
devices handling width and height in their report descriptors
did not show ABS_MT_TOUCH_MAJOR and ABS_MT_TOUCH_MINOR.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Reviewed-by: Stéphane Chatty <chatty@enac.fr>
Reviewed-and-tested-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-multitouch.c')
-rw-r--r-- | drivers/hid/hid-multitouch.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index d31301e85c56..0175f8583095 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -11,6 +11,12 @@ | |||
11 | * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se> | 11 | * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se> |
12 | * Copyright (c) 2010 Canonical, Ltd. | 12 | * Copyright (c) 2010 Canonical, Ltd. |
13 | * | 13 | * |
14 | * This code is partly based on hid-3m-pct.c: | ||
15 | * | ||
16 | * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> | ||
17 | * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se> | ||
18 | * Copyright (c) 2010 Canonical, Ltd. | ||
19 | * | ||
14 | */ | 20 | */ |
15 | 21 | ||
16 | /* | 22 | /* |
@@ -69,6 +75,8 @@ struct mt_class { | |||
69 | __s32 name; /* MT_CLS */ | 75 | __s32 name; /* MT_CLS */ |
70 | __s32 quirks; | 76 | __s32 quirks; |
71 | __s32 sn_move; /* Signal/noise ratio for move events */ | 77 | __s32 sn_move; /* Signal/noise ratio for move events */ |
78 | __s32 sn_width; /* Signal/noise ratio for width events */ | ||
79 | __s32 sn_height; /* Signal/noise ratio for height events */ | ||
72 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ | 80 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ |
73 | __u8 maxcontacts; | 81 | __u8 maxcontacts; |
74 | }; | 82 | }; |
@@ -80,6 +88,7 @@ struct mt_class { | |||
80 | #define MT_CLS_CYPRESS 4 | 88 | #define MT_CLS_CYPRESS 4 |
81 | #define MT_CLS_EGALAX 5 | 89 | #define MT_CLS_EGALAX 5 |
82 | #define MT_CLS_STANTUM 6 | 90 | #define MT_CLS_STANTUM 6 |
91 | #define MT_CLS_3M 7 | ||
83 | 92 | ||
84 | #define MT_DEFAULT_MAXCONTACT 10 | 93 | #define MT_DEFAULT_MAXCONTACT 10 |
85 | 94 | ||
@@ -141,6 +150,12 @@ struct mt_class mt_classes[] = { | |||
141 | }, | 150 | }, |
142 | { .name = MT_CLS_STANTUM, | 151 | { .name = MT_CLS_STANTUM, |
143 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, | 152 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, |
153 | { .name = MT_CLS_3M, | ||
154 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | | ||
155 | MT_QUIRK_SLOT_IS_CONTACTID, | ||
156 | .sn_move = 2048, | ||
157 | .sn_width = 128, | ||
158 | .sn_height = 128 }, | ||
144 | 159 | ||
145 | { } | 160 | { } |
146 | }; | 161 | }; |
@@ -230,11 +245,15 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
230 | case HID_DG_WIDTH: | 245 | case HID_DG_WIDTH: |
231 | hid_map_usage(hi, usage, bit, max, | 246 | hid_map_usage(hi, usage, bit, max, |
232 | EV_ABS, ABS_MT_TOUCH_MAJOR); | 247 | EV_ABS, ABS_MT_TOUCH_MAJOR); |
248 | set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, | ||
249 | cls->sn_width); | ||
233 | td->last_slot_field = usage->hid; | 250 | td->last_slot_field = usage->hid; |
234 | return 1; | 251 | return 1; |
235 | case HID_DG_HEIGHT: | 252 | case HID_DG_HEIGHT: |
236 | hid_map_usage(hi, usage, bit, max, | 253 | hid_map_usage(hi, usage, bit, max, |
237 | EV_ABS, ABS_MT_TOUCH_MINOR); | 254 | EV_ABS, ABS_MT_TOUCH_MINOR); |
255 | set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, | ||
256 | cls->sn_height); | ||
238 | input_set_abs_params(hi->input, | 257 | input_set_abs_params(hi->input, |
239 | ABS_MT_ORIENTATION, 0, 1, 0, 0); | 258 | ABS_MT_ORIENTATION, 0, 1, 0, 0); |
240 | td->last_slot_field = usage->hid; | 259 | td->last_slot_field = usage->hid; |
@@ -332,11 +351,18 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input) | |||
332 | input_mt_report_slot_state(input, MT_TOOL_FINGER, | 351 | input_mt_report_slot_state(input, MT_TOOL_FINGER, |
333 | s->touch_state); | 352 | s->touch_state); |
334 | if (s->touch_state) { | 353 | if (s->touch_state) { |
354 | /* this finger is on the screen */ | ||
355 | int wide = (s->w > s->h); | ||
356 | /* divided by two to match visual scale of touch */ | ||
357 | int major = max(s->w, s->h) >> 1; | ||
358 | int minor = min(s->w, s->h) >> 1; | ||
359 | |||
335 | input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); | 360 | input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); |
336 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); | 361 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); |
362 | input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); | ||
337 | input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); | 363 | input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); |
338 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w); | 364 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); |
339 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h); | 365 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); |
340 | } | 366 | } |
341 | s->seen_in_this_frame = false; | 367 | s->seen_in_this_frame = false; |
342 | 368 | ||
@@ -398,6 +424,15 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, | |||
398 | break; | 424 | break; |
399 | 425 | ||
400 | default: | 426 | default: |
427 | if (td->last_field_index | ||
428 | && field->index == td->last_field_index) | ||
429 | /* we reach here when the last field in the | ||
430 | * report is not related to multitouch. | ||
431 | * This is not good. As a temporary solution, | ||
432 | * we trigger our mt event completion and | ||
433 | * ignore the field. | ||
434 | */ | ||
435 | break; | ||
401 | /* fallback to the generic hidinput handling */ | 436 | /* fallback to the generic hidinput handling */ |
402 | return 0; | 437 | return 0; |
403 | } | 438 | } |
@@ -513,6 +548,14 @@ static void mt_remove(struct hid_device *hdev) | |||
513 | 548 | ||
514 | static const struct hid_device_id mt_devices[] = { | 549 | static const struct hid_device_id mt_devices[] = { |
515 | 550 | ||
551 | /* 3M panels */ | ||
552 | { .driver_data = MT_CLS_3M, | ||
553 | HID_USB_DEVICE(USB_VENDOR_ID_3M, | ||
554 | USB_DEVICE_ID_3M1968) }, | ||
555 | { .driver_data = MT_CLS_3M, | ||
556 | HID_USB_DEVICE(USB_VENDOR_ID_3M, | ||
557 | USB_DEVICE_ID_3M2256) }, | ||
558 | |||
516 | /* Cando panels */ | 559 | /* Cando panels */ |
517 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, | 560 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, |
518 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 561 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |