aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-multitouch.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@gmail.com>2012-11-14 10:59:24 -0500
committerJiri Kosina <jkosina@suse.cz>2012-11-15 04:17:52 -0500
commit9b3bb9b8b6b221ab5ec96defedb15e4c99e26372 (patch)
treed6ca3a48afc059a0046c20304d047ef980c4c2e1 /drivers/hid/hid-multitouch.c
parent2872839904848a43c5222f284bc1168ec3f998e7 (diff)
HID: multitouch: support for hovering devices
Win8 devices supporting hovering must provides InRange HID field. The information that the finger is here but is not touching the surface is sent to the user space through ABS_MT_DISTANCE as required by the multitouch protocol. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com> Reviewed-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.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index e86fbf4be639..0a0489309905 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -53,11 +53,13 @@ MODULE_LICENSE("GPL");
53#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) 53#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8)
54#define MT_QUIRK_NO_AREA (1 << 9) 54#define MT_QUIRK_NO_AREA (1 << 9)
55#define MT_QUIRK_IGNORE_DUPLICATES (1 << 10) 55#define MT_QUIRK_IGNORE_DUPLICATES (1 << 10)
56#define MT_QUIRK_HOVERING (1 << 11)
56 57
57struct mt_slot { 58struct mt_slot {
58 __s32 x, y, cx, cy, p, w, h; 59 __s32 x, y, cx, cy, p, w, h;
59 __s32 contactid; /* the device ContactID assigned to this slot */ 60 __s32 contactid; /* the device ContactID assigned to this slot */
60 bool touch_state; /* is the touch valid? */ 61 bool touch_state; /* is the touch valid? */
62 bool inrange_state; /* is the finger in proximity of the sensor? */
61}; 63};
62 64
63struct mt_class { 65struct mt_class {
@@ -391,6 +393,12 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
391 case HID_UP_DIGITIZER: 393 case HID_UP_DIGITIZER:
392 switch (usage->hid) { 394 switch (usage->hid) {
393 case HID_DG_INRANGE: 395 case HID_DG_INRANGE:
396 if (cls->quirks & MT_QUIRK_HOVERING) {
397 hid_map_usage(hi, usage, bit, max,
398 EV_ABS, ABS_MT_DISTANCE);
399 input_set_abs_params(hi->input,
400 ABS_MT_DISTANCE, 0, 1, 0, 0);
401 }
394 mt_store_field(usage, td, hi); 402 mt_store_field(usage, td, hi);
395 td->last_field_index = field->index; 403 td->last_field_index = field->index;
396 return 1; 404 return 1;
@@ -520,9 +528,9 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
520 528
521 input_mt_slot(input, slotnum); 529 input_mt_slot(input, slotnum);
522 input_mt_report_slot_state(input, MT_TOOL_FINGER, 530 input_mt_report_slot_state(input, MT_TOOL_FINGER,
523 s->touch_state); 531 s->touch_state || s->inrange_state);
524 if (s->touch_state) { 532 if (s->touch_state || s->inrange_state) {
525 /* this finger is on the screen */ 533 /* this finger is in proximity of the sensor */
526 int wide = (s->w > s->h); 534 int wide = (s->w > s->h);
527 /* divided by two to match visual scale of touch */ 535 /* divided by two to match visual scale of touch */
528 int major = max(s->w, s->h) >> 1; 536 int major = max(s->w, s->h) >> 1;
@@ -532,6 +540,8 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
532 input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); 540 input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
533 input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx); 541 input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
534 input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy); 542 input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
543 input_event(input, EV_ABS, ABS_MT_DISTANCE,
544 !s->touch_state);
535 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); 545 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
536 input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); 546 input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
537 input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); 547 input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
@@ -564,6 +574,8 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
564 case HID_DG_INRANGE: 574 case HID_DG_INRANGE:
565 if (quirks & MT_QUIRK_VALID_IS_INRANGE) 575 if (quirks & MT_QUIRK_VALID_IS_INRANGE)
566 td->curvalid = value; 576 td->curvalid = value;
577 if (quirks & MT_QUIRK_HOVERING)
578 td->curdata.inrange_state = value;
567 break; 579 break;
568 case HID_DG_TIPSWITCH: 580 case HID_DG_TIPSWITCH:
569 if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) 581 if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)