]> Pileus Git - ~andy/linux/commitdiff
HID: multitouch: support T and C for win8 devices
authorBenjamin Tissoires <benjamin.tissoires@gmail.com>
Wed, 14 Nov 2012 15:59:19 +0000 (16:59 +0100)
committerJiri Kosina <jkosina@suse.cz>
Thu, 15 Nov 2012 09:09:12 +0000 (10:09 +0100)
Win8 input specification clarifies the X and Y sent by devices.
It distincts the position where the user wants to Touch (T) from
the center of the ellipsoide (C). This patch enable supports for this
distinction in hid-multitouch.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Reviewed-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/hid-multitouch.c

index 9c7415ff4aafdb7cdb8b31a0dace8c494d7a7dd3..a2963b238fde1d25fd9f10b3cd00974992ff900d 100644 (file)
@@ -54,7 +54,7 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_NO_AREA               (1 << 9)
 
 struct mt_slot {
-       __s32 x, y, p, w, h;
+       __s32 x, y, cx, cy, p, w, h;
        __s32 contactid;        /* the device ContactID assigned to this slot */
        bool touch_state;       /* is the touch valid? */
 };
@@ -322,6 +322,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        struct mt_device *td = hid_get_drvdata(hdev);
        struct mt_class *cls = &td->mtclass;
        int code;
+       struct hid_usage *prev_usage = NULL;
 
        /* Only map fields from TouchScreen or TouchPad collections.
        * We need to ignore fields that belong to other collections
@@ -344,23 +345,42 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        if (field->physical == HID_DG_STYLUS)
                return -1;
 
+       if (usage->usage_index)
+               prev_usage = &field->usage[usage->usage_index - 1];
+
        switch (usage->hid & HID_USAGE_PAGE) {
 
        case HID_UP_GENDESK:
                switch (usage->hid) {
                case HID_GD_X:
-                       hid_map_usage(hi, usage, bit, max,
+                       if (prev_usage && (prev_usage->hid == usage->hid)) {
+                               hid_map_usage(hi, usage, bit, max,
+                                       EV_ABS, ABS_MT_TOOL_X);
+                               set_abs(hi->input, ABS_MT_TOOL_X, field,
+                                       cls->sn_move);
+                       } else {
+                               hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_POSITION_X);
-                       set_abs(hi->input, ABS_MT_POSITION_X, field,
-                               cls->sn_move);
+                               set_abs(hi->input, ABS_MT_POSITION_X, field,
+                                       cls->sn_move);
+                       }
+
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        return 1;
                case HID_GD_Y:
-                       hid_map_usage(hi, usage, bit, max,
+                       if (prev_usage && (prev_usage->hid == usage->hid)) {
+                               hid_map_usage(hi, usage, bit, max,
+                                       EV_ABS, ABS_MT_TOOL_Y);
+                               set_abs(hi->input, ABS_MT_TOOL_Y, field,
+                                       cls->sn_move);
+                       } else {
+                               hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_POSITION_Y);
-                       set_abs(hi->input, ABS_MT_POSITION_Y, field,
-                               cls->sn_move);
+                               set_abs(hi->input, ABS_MT_POSITION_Y, field,
+                                       cls->sn_move);
+                       }
+
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        return 1;
@@ -501,6 +521,8 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 
                        input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
                        input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
+                       input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
+                       input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
                        input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
                        input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
                        input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
@@ -552,10 +574,16 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
                        td->curdata.p = value;
                        break;
                case HID_GD_X:
-                       td->curdata.x = value;
+                       if (usage->code == ABS_MT_TOOL_X)
+                               td->curdata.cx = value;
+                       else
+                               td->curdata.x = value;
                        break;
                case HID_GD_Y:
-                       td->curdata.y = value;
+                       if (usage->code == ABS_MT_TOOL_Y)
+                               td->curdata.cy = value;
+                       else
+                               td->curdata.y = value;
                        break;
                case HID_DG_WIDTH:
                        td->curdata.w = value;