From: Benjamin Tissoires <benjamin.tissoi...@redhat.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com> Acked-by: Jason Gerecke <killert...@gmail.com> Signed-off-by: Jiri Kosina <jkos...@suse.cz> --- 3.17/wacom_sys.c | 39 ++++++++++++++++-- 3.17/wacom_wac.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3.17/wacom_wac.h | 8 ++++ 3 files changed, 164 insertions(+), 3 deletions(-)
diff --git a/3.17/wacom_sys.c b/3.17/wacom_sys.c index 03924e1..8ff5875 100644 --- a/3.17/wacom_sys.c +++ b/3.17/wacom_sys.c @@ -109,6 +109,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, { struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_features *features = &wacom->wacom_wac.features; + struct hid_data *hid_data = &wacom->wacom_wac.hid_data; u8 *data; int ret; @@ -128,6 +129,16 @@ static void wacom_feature_mapping(struct hid_device *hdev, kfree(data); } break; + case HID_DG_INPUTMODE: + /* Ignore if value index is out of bounds. */ + if (usage->usage_index >= field->report_count) { + dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n"); + break; + } + + hid_data->inputmode = field->report->id; + hid_data->inputmode_index = usage->usage_index; + break; } } @@ -255,6 +266,25 @@ static void wacom_parse_hid(struct hid_device *hdev, } } +static int wacom_hid_set_device_mode(struct hid_device *hdev) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct hid_data *hid_data = &wacom->wacom_wac.hid_data; + struct hid_report *r; + struct hid_report_enum *re; + + if (hid_data->inputmode < 0) + return 0; + + re = &(hdev->report_enum[HID_FEATURE_REPORT]); + r = re->report_id_hash[hid_data->inputmode]; + if (r) { + r->field[0]->value[hid_data->inputmode_index] = 2; + hid_hw_request(hdev, r, HID_REQ_SET_REPORT); + } + return 0; +} + static int wacom_set_device_mode(struct hid_device *hdev, int report_id, int length, int mode) { @@ -347,6 +377,9 @@ static int wacom_query_tablet_data(struct hid_device *hdev, if (hdev->bus == BUS_BLUETOOTH) return wacom_bt_query_tablet_data(hdev, 1, features); + if (features->type == HID_GENERIC) + return wacom_hid_set_device_mode(hdev); + if (features->device_type == BTN_TOOL_FINGER) { if (features->type > TABLETPC) { /* MT Tablet PC touch */ @@ -1451,9 +1484,6 @@ static int wacom_probe(struct hid_device *hdev, error); } - /* Note that if query fails it is not a hard failure */ - wacom_query_tablet_data(hdev, features); - if (features->type == HID_GENERIC) #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,18,0) hdev->claimed |= 8; /* HID_CLAIMED_DRIVER */ @@ -1468,6 +1498,9 @@ static int wacom_probe(struct hid_device *hdev, goto fail_hw_start; } + /* Note that if query fails it is not a hard failure */ + wacom_query_tablet_data(hdev, features); + if (features->quirks & WACOM_QUIRK_MONITOR) error = hid_hw_open(hdev); diff --git a/3.17/wacom_wac.c b/3.17/wacom_wac.c index db6b517..8ce7fab 100644 --- a/3.17/wacom_wac.c +++ b/3.17/wacom_wac.c @@ -1372,6 +1372,117 @@ static void wacom_wac_pen_report(struct hid_device *hdev, } } +static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, + struct hid_field *field, struct hid_usage *usage) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct input_dev *input = wacom_wac->input; + unsigned touch_max = wacom_wac->features.touch_max; + + switch (usage->hid) { + case HID_GD_X: + if (touch_max == 1) + wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4); + else + wacom_map_usage(wacom, usage, field, EV_ABS, + ABS_MT_POSITION_X, 4); + break; + case HID_GD_Y: + if (touch_max == 1) + wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4); + else + wacom_map_usage(wacom, usage, field, EV_ABS, + ABS_MT_POSITION_Y, 4); + break; + case HID_DG_CONTACTID: + input_mt_init_slots(input, wacom_wac->features.touch_max, + INPUT_MT_DIRECT); + break; + case HID_DG_INRANGE: + break; + case HID_DG_INVERT: + break; + case HID_DG_TIPSWITCH: + wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0); + break; + } +} + +static int wacom_wac_finger_event(struct hid_device *hdev, + struct hid_field *field, struct hid_usage *usage, __s32 value) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + + switch (usage->hid) { + case HID_GD_X: + wacom_wac->hid_data.x = value; + break; + case HID_GD_Y: + wacom_wac->hid_data.y = value; + break; + case HID_DG_CONTACTID: + wacom_wac->hid_data.id = value; + break; + case HID_DG_TIPSWITCH: + wacom_wac->hid_data.tipswitch = value; + break; + } + + + return 0; +} + +static void wacom_wac_finger_mt_report(struct wacom_wac *wacom_wac, + struct input_dev *input, bool touch) +{ + int slot; + struct hid_data *hid_data = &wacom_wac->hid_data; + + slot = input_mt_get_slot_by_key(input, hid_data->id); + + input_mt_slot(input, slot); + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + if (touch) { + input_report_abs(input, ABS_MT_POSITION_X, hid_data->x); + input_report_abs(input, ABS_MT_POSITION_Y, hid_data->y); + } + input_mt_sync_frame(input); +} + +static void wacom_wac_finger_single_touch_report(struct wacom_wac *wacom_wac, + struct input_dev *input, bool touch) +{ + struct hid_data *hid_data = &wacom_wac->hid_data; + + if (touch) { + input_report_abs(input, ABS_X, hid_data->x); + input_report_abs(input, ABS_Y, hid_data->y); + } + input_report_key(input, BTN_TOUCH, touch); +} + +static void wacom_wac_finger_report(struct hid_device *hdev, + struct hid_report *report) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct input_dev *input = wacom_wac->input; + bool touch = wacom_wac->hid_data.tipswitch && + !wacom_wac->shared->stylus_in_proximity; + unsigned touch_max = wacom_wac->features.touch_max; + + if (touch_max > 1) + wacom_wac_finger_mt_report(wacom_wac, input, touch); + else + wacom_wac_finger_single_touch_report(wacom_wac, input, touch); + input_sync(input); + + /* keep touch state for pen event */ + wacom_wac->shared->touch_down = touch; +} + #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS)) #define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \ @@ -1389,6 +1500,9 @@ void wacom_wac_usage_mapping(struct hid_device *hdev, if (WACOM_PEN_FIELD(field)) return wacom_wac_pen_usage_mapping(hdev, field, usage); + + if (WACOM_FINGER_FIELD(field)) + return wacom_wac_finger_usage_mapping(hdev, field, usage); } int wacom_wac_event(struct hid_device *hdev, struct hid_field *field, @@ -1402,6 +1516,9 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field, if (WACOM_PEN_FIELD(field)) return wacom_wac_pen_event(hdev, field, usage, value); + if (WACOM_FINGER_FIELD(field)) + return wacom_wac_finger_event(hdev, field, usage, value); + return 0; } @@ -1416,6 +1533,9 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) if (WACOM_PEN_FIELD(field)) return wacom_wac_pen_report(hdev, report); + + if (WACOM_FINGER_FIELD(field)) + return wacom_wac_finger_report(hdev, report); } static int wacom_bpt_touch(struct wacom_wac *wacom) diff --git a/3.17/wacom_wac.h b/3.17/wacom_wac.h index f472eac..0f0b85e 100644 --- a/3.17/wacom_wac.h +++ b/3.17/wacom_wac.h @@ -156,9 +156,17 @@ struct wacom_shared { }; struct hid_data { + __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ + __s16 inputmode_index; /* InputMode HID feature index in the report */ bool inrange_state; bool invert_state; bool tipswitch; + int x; + int y; + int pressure; + int width; + int height; + int id; }; struct wacom_wac { -- 2.1.3 ------------------------------------------------------------------------------ Dive into the World of Parallel Programming! The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel