aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-multitouch.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-multitouch.c')
-rw-r--r--drivers/hid/hid-multitouch.c47
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
514static const struct hid_device_id mt_devices[] = { 549static 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,