From b9e06256932bd462b7ee392d7742a79ade679abe Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 25 Jan 2017 12:08:35 -0800 Subject: HID: wacom: Enable HID_GENERIC codepath for Bluetooth devices There no reason a Bluetooth device with the appropriate HID descriptor couldn't be used through the HID_GENERIC codepath in the future. Ensure that the driver attempts to bind to these devices. Signed-off-by: Jason Gerecke Reviewed-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 0884dc9554fd..a23b736d05d2 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -4121,6 +4121,7 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(HID_ANY_ID) }, { I2C_DEVICE_WACOM(HID_ANY_ID) }, + { BT_DEVICE_WACOM(HID_ANY_ID) }, { } }; MODULE_DEVICE_TABLE(hid, wacom_ids); -- cgit v1.2.3-59-g8ed1b From 4922cd26f03c1c71bf7dd6cbdb638e7e36a4a50b Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 25 Jan 2017 12:08:37 -0800 Subject: HID: wacom: Support 2nd-gen Intuos Pro's Bluetooth classic interface In addition to its USB interface, the second-generation Intuos Pro includes a Bluetooth radio that offers two pairing interfaces: classic and low-energy. The classic interface functions just like the earlier Bluetooth-enabled Intuos4 and Graphire4 tablets, appearing as a HID device that our driver can work with. The low-energy interface is intented to be used by userspace applications that make use of its paper-to-digital capabilities. Despite the USB interface using Wacom's new vendor-defined HID usages, the Bluetooth interface provides us with useless black-box "blob" report descriptors like past devices. We thus have to explicitly add support for the PIDs and reports used. These devices pack a /lot/ of information into a single Bluetooth input report. Each report contains up to seven snapshots of the pen state, four snapshots of the touch state (of five touches each), pad state, and battery data. Thankfully this isn't too hard for the driver to report -- it just takes a fair amount of code to extract! Signed-off-by: Jason Gerecke Reviewed-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 25 ++++++ drivers/hid/wacom_wac.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/hid/wacom_wac.h | 6 +- 3 files changed, 226 insertions(+), 2 deletions(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 4dd7b80ffca4..4a70783e64e1 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -756,6 +756,10 @@ static int wacom_led_control(struct wacom *wacom) report_id = WAC_CMD_WL_LED_CONTROL; buf_size = 13; } + else if (wacom->wacom_wac.features.type == INTUOSP2_BT) { + report_id = WAC_CMD_WL_INTUOSP2; + buf_size = 51; + } buf = kzalloc(buf_size, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -781,6 +785,16 @@ static int wacom_led_control(struct wacom *wacom) } else buf[1] = led_bits; } + else if (wacom->wacom_wac.features.type == INTUOSP2_BT) { + buf[0] = report_id; + buf[4] = 100; // Power Connection LED (ORANGE) + buf[5] = 100; // BT Connection LED (BLUE) + buf[6] = 100; // Paper Mode (RED?) + buf[7] = 100; // Paper Mode (GREEN?) + buf[8] = 100; // Paper Mode (BLUE?) + buf[9] = wacom->led.llv; + buf[10] = wacom->led.groups[0].select & 0x03; + } else { int led = wacom->led.groups[0].select | 0x4; @@ -1409,6 +1423,17 @@ static int wacom_initialize_leds(struct wacom *wacom) &intuos5_led_attr_group); break; + case INTUOSP2_BT: + wacom->led.llv = 50; + wacom->led.max_llv = 100; + error = wacom_leds_alloc_and_register(wacom, 1, 4, false); + if (error) { + hid_err(wacom->hdev, + "cannot create leds err: %d\n", error); + return error; + } + return 0; + case REMOTE: wacom->led.llv = 255; wacom->led.max_llv = 255; diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index a23b736d05d2..ef29f7ad7664 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1190,6 +1190,161 @@ static int wacom_wac_finger_count_touches(struct wacom_wac *wacom) return count; } +static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) +{ + const int pen_frame_len = 14; + const int pen_frames = 7; + + struct input_dev *pen_input = wacom->pen_input; + unsigned char *data = wacom->data; + int i; + + wacom->serial[0] = get_unaligned_le64(&data[99]); + wacom->id[0] = get_unaligned_le16(&data[107]); + if (wacom->serial[0] >> 52 == 1) { + /* Add back in missing bits of ID for non-USI pens */ + wacom->id[0] |= (wacom->serial[0] >> 32) & 0xFFFFF; + } + wacom->tool[0] = wacom_intuos_get_tool_type(wacom_intuos_id_mangle(wacom->id[0])); + + for (i = 0; i < pen_frames; i++) { + unsigned char *frame = &data[i*pen_frame_len + 1]; + + if (!(frame[0] & 0x80)) + continue; + + input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1])); + input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3])); + input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5])); + input_report_abs(pen_input, ABS_TILT_X, frame[7]); + input_report_abs(pen_input, ABS_TILT_Y, frame[8]); + input_report_abs(pen_input, ABS_Z, get_unaligned_le16(&frame[9])); + input_report_abs(pen_input, ABS_WHEEL, get_unaligned_le16(&frame[11])); + input_report_abs(pen_input, ABS_DISTANCE, frame[13]); + + input_report_key(pen_input, BTN_TOUCH, frame[0] & 0x01); + input_report_key(pen_input, BTN_STYLUS, frame[0] & 0x02); + input_report_key(pen_input, BTN_STYLUS2, frame[0] & 0x04); + + input_report_key(pen_input, wacom->tool[0], 1); + input_event(pen_input, EV_MSC, MSC_SERIAL, wacom->serial[0]); + input_report_abs(pen_input, ABS_MISC, + wacom_intuos_id_mangle(wacom->id[0])); /* report tool id */ + + wacom->shared->stylus_in_proximity = frame[0] & 0x40; + + input_sync(pen_input); + } +} + +static void wacom_intuos_pro2_bt_touch(struct wacom_wac *wacom) +{ + const int finger_touch_len = 8; + const int finger_frames = 4; + const int finger_frame_len = 43; + + struct input_dev *touch_input = wacom->touch_input; + unsigned char *data = wacom->data; + int num_contacts_left = 5; + int i, j; + + for (i = 0; i < finger_frames; i++) { + unsigned char *frame = &data[i*finger_frame_len + 109]; + int current_num_contacts = frame[0] & 0x7F; + int contacts_to_send; + + if (!(frame[0] & 0x80)) + continue; + + /* + * First packet resets the counter since only the first + * packet in series will have non-zero current_num_contacts. + */ + if (current_num_contacts) + wacom->num_contacts_left = current_num_contacts; + + contacts_to_send = min(num_contacts_left, wacom->num_contacts_left); + + for (j = 0; j < contacts_to_send; j++) { + unsigned char *touch = &frame[j*finger_touch_len + 1]; + int slot = input_mt_get_slot_by_key(touch_input, touch[0]); + int x = get_unaligned_le16(&touch[2]); + int y = get_unaligned_le16(&touch[4]); + int w = touch[6] * input_abs_get_res(touch_input, ABS_MT_POSITION_X); + int h = touch[7] * input_abs_get_res(touch_input, ABS_MT_POSITION_Y); + + if (slot < 0) + continue; + + input_mt_slot(touch_input, slot); + input_mt_report_slot_state(touch_input, MT_TOOL_FINGER, touch[1] & 0x01); + input_report_abs(touch_input, ABS_MT_POSITION_X, x); + input_report_abs(touch_input, ABS_MT_POSITION_Y, y); + input_report_abs(touch_input, ABS_MT_TOUCH_MAJOR, max(w, h)); + input_report_abs(touch_input, ABS_MT_TOUCH_MINOR, min(w, h)); + input_report_abs(touch_input, ABS_MT_ORIENTATION, w > h); + } + + input_mt_sync_frame(touch_input); + + wacom->num_contacts_left -= contacts_to_send; + if (wacom->num_contacts_left <= 0) { + wacom->num_contacts_left = 0; + wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); + } + } + + input_report_switch(touch_input, SW_MUTE_DEVICE, !(data[281] >> 7)); + input_sync(touch_input); +} + +static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom) +{ + struct input_dev *pad_input = wacom->pad_input; + unsigned char *data = wacom->data; + + int buttons = (data[282] << 1) | ((data[281] >> 6) & 0x01); + int ring = data[285]; + int prox = buttons | (ring & 0x80); + + wacom_report_numbered_buttons(pad_input, 9, buttons); + + input_report_abs(pad_input, ABS_WHEEL, (ring & 0x80) ? (ring & 0x7f) : 0); + + input_report_key(pad_input, wacom->tool[1], prox ? 1 : 0); + input_report_abs(pad_input, ABS_MISC, prox ? PAD_DEVICE_ID : 0); + input_event(pad_input, EV_MSC, MSC_SERIAL, 0xffffffff); + + input_sync(pad_input); +} + +static void wacom_intuos_pro2_bt_battery(struct wacom_wac *wacom) +{ + unsigned char *data = wacom->data; + + bool chg = data[284] & 0x80; + int battery_status = data[284] & 0x7F; + + wacom_notify_battery(wacom, battery_status, chg, 1, chg); +} + +static int wacom_intuos_pro2_bt_irq(struct wacom_wac *wacom, size_t len) +{ + unsigned char *data = wacom->data; + + if (data[0] != 0x80) { + dev_dbg(wacom->pen_input->dev.parent, + "%s: received unknown report #%d\n", __func__, data[0]); + return 0; + } + + wacom_intuos_pro2_bt_pen(wacom); + wacom_intuos_pro2_bt_touch(wacom); + wacom_intuos_pro2_bt_pad(wacom); + wacom_intuos_pro2_bt_battery(wacom); + return 0; +} + static int wacom_24hdt_irq(struct wacom_wac *wacom) { struct input_dev *input = wacom->touch_input; @@ -2667,6 +2822,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_intuos_irq(wacom_wac); break; + case INTUOSP2_BT: + sync = wacom_intuos_pro2_bt_irq(wacom_wac, len); + break; + case TABLETPC: case TABLETPCE: case TABLETPC2FG: @@ -2838,6 +2997,13 @@ void wacom_setup_device_quirks(struct wacom *wacom) if (features->type == REMOTE) features->device_type = WACOM_DEVICETYPE_PAD; + if (features->type == INTUOSP2_BT) { + features->device_type |= WACOM_DEVICETYPE_PEN | + WACOM_DEVICETYPE_PAD | + WACOM_DEVICETYPE_TOUCH; + features->quirks |= WACOM_QUIRK_BATTERY; + } + switch (features->type) { case PL: case DTU: @@ -2984,6 +3150,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, case INTUOSPL: case INTUOS5S: case INTUOSPS: + case INTUOSP2_BT: input_set_abs_params(input_dev, ABS_DISTANCE, 0, features->distance_max, features->distance_fuzz, 0); @@ -3092,6 +3259,27 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, } switch (features->type) { + case INTUOSP2_BT: + input_dev->evbit[0] |= BIT_MASK(EV_SW); + __set_bit(SW_MUTE_DEVICE, input_dev->swbit); + + if (wacom_wac->shared->touch->product == 0x361) { + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, 12440, 4, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + 0, 8640, 4, 0); + } + else if (wacom_wac->shared->touch->product == 0x360) { + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, 8960, 4, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + 0, 5920, 4, 0); + } + input_abs_set_res(input_dev, ABS_MT_POSITION_X, 40); + input_abs_set_res(input_dev, ABS_MT_POSITION_X, 40); + + /* fall through */ + case INTUOS5: case INTUOS5L: case INTUOSPM: @@ -3389,6 +3577,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, case INTUOSPL: case INTUOS5S: case INTUOSPS: + case INTUOSP2_BT: input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); break; @@ -3947,6 +4136,12 @@ static const struct wacom_features wacom_features_0x343 = DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; +static const struct wacom_features wacom_features_0x360 = + { "Wacom Intuos Pro M", 44800, 29600, 8191, 63, + INTUOSP2_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 9, .touch_max = 10 }; +static const struct wacom_features wacom_features_0x361 = + { "Wacom Intuos Pro L", 62200, 43200, 8191, 63, + INTUOSP2_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 9, .touch_max = 10 }; static const struct wacom_features wacom_features_HID_ANY_ID = { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; @@ -4113,6 +4308,8 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x33D) }, { USB_DEVICE_WACOM(0x33E) }, { USB_DEVICE_WACOM(0x343) }, + { BT_DEVICE_WACOM(0x360) }, + { BT_DEVICE_WACOM(0x361) }, { USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x4004) }, { USB_DEVICE_WACOM(0x5000) }, diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 804fda3e192a..d3482debae8a 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -12,8 +12,8 @@ #include #include -/* maximum packet length for USB devices */ -#define WACOM_PKGLEN_MAX 192 +/* maximum packet length for USB/BT devices */ +#define WACOM_PKGLEN_MAX 361 #define WACOM_NAME_MAX 64 #define WACOM_MAX_REMOTES 5 @@ -80,6 +80,7 @@ #define WAC_CMD_ICON_BT_XFER 0x26 #define WAC_CMD_DELETE_PAIRING 0x20 #define WAC_CMD_UNPAIR_ALL 0xFF +#define WAC_CMD_WL_INTUOSP2 0x82 /* device quirks */ #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 @@ -179,6 +180,7 @@ enum { INTUOSPS, INTUOSPM, INTUOSPL, + INTUOSP2_BT, WACOM_21UX2, WACOM_22HD, DTK, -- cgit v1.2.3-59-g8ed1b From 65ef4c1e98b73176a64fb6e9829e4166249392ec Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 25 Jan 2017 12:08:38 -0800 Subject: HID: wacom: generic: remove input_event_flag Input_event_flag duplicates the information we track in wacom_wac->hid_data.inrange_state for the pad. Signed-off-by: Aaron Skomra Reviewed-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 9 +-------- drivers/hid/wacom_wac.h | 1 - 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index ef29f7ad7664..f6825d25a257 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1773,7 +1773,6 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct input_dev *input = wacom_wac->pad_input; - struct wacom_features *features = &wacom_wac->features; unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) { @@ -1785,7 +1784,6 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field break; default: - features->input_event_flag = true; input_event(input, usage->type, usage->code, value); break; } @@ -1823,20 +1821,15 @@ static void wacom_wac_pad_report(struct hid_device *hdev, { struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; - struct wacom_features *features = &wacom_wac->features; struct input_dev *input = wacom_wac->pad_input; bool active = wacom_wac->hid_data.inrange_state != 0; /* report prox for expresskey events */ if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) { - features->input_event_flag = true; input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0); - } - - if (features->input_event_flag) { - features->input_event_flag = false; input_sync(input); } + } static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index d3482debae8a..dac95ba49888 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -243,7 +243,6 @@ struct wacom_features { int pktlen; bool check_for_hid_type; int hid_type; - bool input_event_flag; }; struct wacom_shared { -- cgit v1.2.3-59-g8ed1b From 60a221869803a0864c4b1683395ef574ee15aba6 Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 25 Jan 2017 12:08:39 -0800 Subject: HID: wacom: generic: add support for touchring Add support for the touchring to the generic code path in support of the second generation Intuos Pro. We also add checks for usage->type to ensure that we handle the usage before we report it, or change the inrange_state based on it. Signed-off-by: Aaron Skomra Reviewed-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index f6825d25a257..636c4a1ee958 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1733,6 +1733,10 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); features->device_type |= WACOM_DEVICETYPE_PAD; break; + case WACOM_HID_WD_TOUCHRINGSTATUS: + wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); + features->device_type |= WACOM_DEVICETYPE_PAD; + break; } switch (equivalent_usage & 0xfffffff0) { @@ -1775,12 +1779,22 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field struct input_dev *input = wacom_wac->pad_input; unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); + /* + * Avoid reporting this event and setting inrange_state if this usage + * hasn't been mapped. + */ + if (!usage->type) + return; + if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) { - wacom_wac->hid_data.inrange_state |= value; + if (usage->hid != WACOM_HID_WD_TOUCHRING) + wacom_wac->hid_data.inrange_state |= value; } switch (equivalent_usage) { case WACOM_HID_WD_TOUCHRINGSTATUS: + if (!value) + input_event(input, usage->type, usage->code, 0); break; default: @@ -2288,6 +2302,9 @@ void wacom_wac_event(struct hid_device *hdev, struct hid_field *field, if (wacom->wacom_wac.features.type != HID_GENERIC) return; + if (value > field->logical_maximum || value < field->logical_minimum) + return; + if (WACOM_PAD_FIELD(field)) { wacom_wac_pad_battery_event(hdev, field, usage, value); if (wacom->wacom_wac.pad_input) -- cgit v1.2.3-59-g8ed1b From ac2423c975dbd3e8c2afc6dec53ee25be38f723b Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 25 Jan 2017 12:08:40 -0800 Subject: HID: wacom: generic: add vendor defined touch Add vendor defined touch to support the second generation Intuos Pro. Previously all generic Wacom devices used true HID to report their touch. Signed-off-by: Aaron Skomra Reviewed-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom.h | 1 + drivers/hid/wacom_sys.c | 13 ++++++++++--- drivers/hid/wacom_wac.c | 22 +++++++++++++++++----- drivers/hid/wacom_wac.h | 16 +++++++++++++++- 4 files changed, 43 insertions(+), 9 deletions(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 8d8fe309c872..0e7b840bb80b 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -219,4 +219,5 @@ enum led_brightness wacom_leds_brightness_get(struct wacom_led *led); struct wacom_led *wacom_led_find(struct wacom *wacom, unsigned int group, unsigned int id); struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur); +int wacom_equivalent_usage(int usage); #endif diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 4a70783e64e1..a4884e78b3f8 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -112,11 +112,12 @@ 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; + unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid); u8 *data; int ret; int n; - switch (usage->hid) { + switch (equivalent_usage) { case HID_DG_CONTACTMAX: /* leave touch_max as is if predefined */ if (!features->touch_max) { @@ -325,8 +326,14 @@ static void wacom_post_parse_hid(struct hid_device *hdev, if (features->type == HID_GENERIC) { /* Any last-minute generic device setup */ if (features->touch_max > 1) { - input_mt_init_slots(wacom_wac->touch_input, wacom_wac->features.touch_max, - INPUT_MT_DIRECT); + if (features->device_type & WACOM_DEVICETYPE_DIRECT) + input_mt_init_slots(wacom_wac->touch_input, + wacom_wac->features.touch_max, + INPUT_MT_DIRECT); + else + input_mt_init_slots(wacom_wac->touch_input, + wacom_wac->features.touch_max, + INPUT_MT_POINTER); } } } diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 636c4a1ee958..2eeaa05e2068 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1599,7 +1599,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) return 0; } -static int wacom_equivalent_usage(int usage) +int wacom_equivalent_usage(int usage) { if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) { int subpage = (usage & 0xFF00) << 8; @@ -1626,6 +1626,16 @@ static int wacom_equivalent_usage(int usage) return subpage | subusage; } + if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMTOUCH) { + int subpage = (usage & 0xFF00) << 8; + int subusage = (usage & 0xFF); + + if (subpage == HID_UP_UNDEFINED) + subpage = WACOM_HID_SP_DIGITIZER; + + return subpage | subusage; + } + return usage; } @@ -2218,8 +2228,10 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev, for (j = 0; j < field->maxusage; j++) { struct hid_usage *usage = &field->usage[j]; + unsigned int equivalent_usage = + wacom_equivalent_usage(usage->hid); - switch (usage->hid) { + switch (equivalent_usage) { case HID_GD_X: case HID_GD_Y: case HID_DG_WIDTH: @@ -2228,7 +2240,7 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev, case HID_DG_INRANGE: case HID_DG_INVERT: case HID_DG_TIPSWITCH: - hid_data->last_slot_field = usage->hid; + hid_data->last_slot_field = equivalent_usage; break; case HID_DG_CONTACTCOUNT: hid_data->cc_report = report->id; @@ -2283,8 +2295,8 @@ void wacom_wac_usage_mapping(struct hid_device *hdev, struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct wacom_features *features = &wacom_wac->features; - /* currently, only direct devices have proper hid report descriptors */ - features->device_type |= WACOM_DEVICETYPE_DIRECT; + if (WACOM_DIRECT_DEVICE(field)) + features->device_type |= WACOM_DEVICETYPE_DIRECT; if (WACOM_PAD_FIELD(field)) wacom_wac_pad_usage_mapping(hdev, field, usage); diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index dac95ba49888..da38f7736a7a 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -101,6 +101,7 @@ #define WACOM_HID_SP_DIGITIZER 0x000d0000 #define WACOM_HID_SP_DIGITIZERINFO 0x00100000 #define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) +#define WACOM_HID_WD_PEN (WACOM_HID_UP_WACOMDIGITIZER | 0x02) #define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) #define WACOM_HID_WD_DIGITIZERFNKEYS (WACOM_HID_UP_WACOMDIGITIZER | 0x39) #define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c) @@ -137,6 +138,12 @@ #define WACOM_HID_UP_G11 0xff110000 #define WACOM_HID_G11_PEN (WACOM_HID_UP_G11 | 0x02) #define WACOM_HID_G11_TOUCHSCREEN (WACOM_HID_UP_G11 | 0x11) +#define WACOM_HID_UP_WACOMTOUCH 0xff000000 +#define WACOM_HID_WT_TOUCHSCREEN (WACOM_HID_UP_WACOMTOUCH | 0x04) +#define WACOM_HID_WT_TOUCHPAD (WACOM_HID_UP_WACOMTOUCH | 0x05) +#define WACOM_HID_WT_CONTACTMAX (WACOM_HID_UP_WACOMTOUCH | 0x55) +#define WACOM_HID_WT_X (WACOM_HID_UP_WACOMTOUCH | 0x130) +#define WACOM_HID_WT_Y (WACOM_HID_UP_WACOMTOUCH | 0x131) #define WACOM_PAD_FIELD(f) (((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \ ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \ @@ -154,7 +161,14 @@ ((f)->physical == HID_DG_FINGER) || \ ((f)->application == HID_DG_TOUCHSCREEN) || \ ((f)->application == WACOM_HID_G9_TOUCHSCREEN) || \ - ((f)->application == WACOM_HID_G11_TOUCHSCREEN)) + ((f)->application == WACOM_HID_G11_TOUCHSCREEN) || \ + ((f)->application == WACOM_HID_WT_TOUCHPAD) || \ + ((f)->application == HID_DG_TOUCHPAD)) + +#define WACOM_DIRECT_DEVICE(f) (((f)->application == HID_DG_TOUCHSCREEN) || \ + ((f)->application == WACOM_HID_WT_TOUCHSCREEN) || \ + ((f)->application == HID_DG_PEN) || \ + ((f)->application == WACOM_HID_WD_PEN)) enum { PENPARTNER = 0, -- cgit v1.2.3-59-g8ed1b From d2ec58aee8b1d68d309656a0561c81c12197a987 Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 25 Jan 2017 12:08:41 -0800 Subject: HID: wacom: generic: support generic touch switch The second generation Intuos Pro is the first device in the generic codepath which has a touchswitch. We utilize a flag in wacom_shared in order to report this switch event received from the pad on the touch input. Signed-off-by: Aaron Skomra Reviewed-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 26 +++++++++++++++++++------- drivers/hid/wacom_wac.c | 19 ++++++++++++++++++- drivers/hid/wacom_wac.h | 4 +++- 3 files changed, 40 insertions(+), 9 deletions(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index a4884e78b3f8..a8e68dc2ca99 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -2053,6 +2053,24 @@ static void wacom_release_resources(struct wacom *wacom) wacom->wacom_wac.pad_input = NULL; } +static void wacom_set_shared_values(struct wacom_wac *wacom_wac) +{ + if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) { + wacom_wac->shared->type = wacom_wac->features.type; + wacom_wac->shared->touch_input = wacom_wac->touch_input; + } + + if (wacom_wac->has_mute_touch_switch) + wacom_wac->shared->has_mute_touch_switch = true; + + if (wacom_wac->shared->has_mute_touch_switch && + wacom_wac->shared->touch_input) { + set_bit(EV_SW, wacom_wac->shared->touch_input->evbit); + input_set_capability(wacom_wac->shared->touch_input, EV_SW, + SW_MUTE_DEVICE); + } +} + static int wacom_parse_and_register(struct wacom *wacom, bool wireless) { struct wacom_wac *wacom_wac = &wacom->wacom_wac; @@ -2172,13 +2190,7 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) error = hid_hw_open(hdev); - if ((wacom_wac->features.type == INTUOSHT || - wacom_wac->features.type == INTUOSHT2) && - (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)) { - wacom_wac->shared->type = wacom_wac->features.type; - wacom_wac->shared->touch_input = wacom_wac->touch_input; - } - + wacom_set_shared_values(wacom_wac); devres_close_group(&hdev->dev, wacom); return 0; diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 2eeaa05e2068..06d152a286a0 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1728,7 +1728,17 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, features->device_type |= WACOM_DEVICETYPE_PAD; break; case WACOM_HID_WD_TOUCHONOFF: - wacom_map_usage(input, usage, field, EV_SW, SW_MUTE_DEVICE, 0); + /* + * This usage, which is used to mute touch events, comes + * from the pad packet, but is reported on the touch + * interface. Because the touch interface may not have + * been created yet, we cannot call wacom_map_usage(). In + * order to process this usage when we receive it, we set + * the usage type and code directly. + */ + wacom_wac->has_mute_touch_switch = true; + usage->type = EV_SW; + usage->code = SW_MUTE_DEVICE; features->device_type |= WACOM_DEVICETYPE_PAD; break; case WACOM_HID_WD_TOUCHSTRIP: @@ -1807,6 +1817,13 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field input_event(input, usage->type, usage->code, 0); break; + case WACOM_HID_WD_TOUCHONOFF: + if (wacom_wac->shared->touch_input) { + input_report_switch(wacom_wac->shared->touch_input, + SW_MUTE_DEVICE, !value); + input_sync(wacom_wac->shared->touch_input); + } + break; default: input_event(input, usage->type, usage->code, value); break; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index da38f7736a7a..4feaf94fb08b 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -115,6 +115,7 @@ #define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402) #define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403) #define WACOM_HID_WD_BATTERY_CHARGING (WACOM_HID_UP_WACOMDIGITIZER | 0x0404) +#define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0454) #define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b) #define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) #define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0950) @@ -124,7 +125,6 @@ #define WACOM_HID_WD_BUTTONLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0993) #define WACOM_HID_WD_BUTTONRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0994) #define WACOM_HID_WD_BUTTONCENTER (WACOM_HID_UP_WACOMDIGITIZER | 0x0995) -#define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0996) #define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) #define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30) #define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31) @@ -268,6 +268,7 @@ struct wacom_shared { struct input_dev *touch_input; struct hid_device *pen; struct hid_device *touch; + bool has_mute_touch_switch; }; struct hid_data { @@ -324,6 +325,7 @@ struct wacom_wac { int mode_report; int mode_value; struct hid_data hid_data; + bool has_mute_touch_switch; }; #endif -- cgit v1.2.3-59-g8ed1b From 10c55cacb8b20518fddf92de43fbfb198f288eb2 Mon Sep 17 00:00:00 2001 From: Aaron Armstrong Skomra Date: Wed, 25 Jan 2017 12:08:42 -0800 Subject: HID: wacom: generic: support LEDs Add support for the LEDs around the mode switch to the generic code path in support of the second generation Intuos Pro. Signed-off-by: Aaron Skomra Reviewed-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom.h | 2 ++ drivers/hid/wacom_sys.c | 39 ++++++++++++++++++++++++++++++++++++--- drivers/hid/wacom_wac.c | 14 +++++++++++++- drivers/hid/wacom_wac.h | 1 + 4 files changed, 52 insertions(+), 4 deletions(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 0e7b840bb80b..d0d7dc1572ca 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -168,6 +168,7 @@ struct wacom { struct work_struct remote_work; struct delayed_work init_work; struct wacom_remote *remote; + bool generic_has_leds; struct wacom_leds { struct wacom_group_leds *groups; unsigned int count; @@ -220,4 +221,5 @@ struct wacom_led *wacom_led_find(struct wacom *wacom, unsigned int group, unsigned int id); struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur); int wacom_equivalent_usage(int usage); +int wacom_initialize_leds(struct wacom *wacom); #endif diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index a8e68dc2ca99..3586acbdb467 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -771,8 +771,13 @@ static int wacom_led_control(struct wacom *wacom) if (!buf) return -ENOMEM; - if (wacom->wacom_wac.features.type >= INTUOS5S && - wacom->wacom_wac.features.type <= INTUOSPL) { + if (wacom->wacom_wac.features.type == HID_GENERIC) { + buf[0] = WAC_CMD_LED_CONTROL_GENERIC; + buf[1] = wacom->led.llv; + buf[2] = wacom->led.groups[0].select & 0x03; + + } else if ((wacom->wacom_wac.features.type >= INTUOS5S && + wacom->wacom_wac.features.type <= INTUOSPL)) { /* * Touch Ring and crop mark LED luminance may take on * one of four values: @@ -1042,6 +1047,17 @@ static struct attribute_group intuos5_led_attr_group = { .attrs = intuos5_led_attrs, }; +static struct attribute *generic_led_attrs[] = { + &dev_attr_status0_luminance.attr, + &dev_attr_status_led0_select.attr, + NULL +}; + +static struct attribute_group generic_led_attr_group = { + .name = "wacom_led", + .attrs = generic_led_attrs, +}; + struct wacom_sysfs_group_devres { struct attribute_group *group; struct kobject *root; @@ -1363,7 +1379,7 @@ static int wacom_leds_alloc_and_register(struct wacom *wacom, int group_count, return 0; } -static int wacom_initialize_leds(struct wacom *wacom) +int wacom_initialize_leds(struct wacom *wacom) { int error; @@ -1372,6 +1388,23 @@ static int wacom_initialize_leds(struct wacom *wacom) /* Initialize default values */ switch (wacom->wacom_wac.features.type) { + case HID_GENERIC: + if (!wacom->generic_has_leds) + return 0; + wacom->led.llv = 100; + wacom->led.max_llv = 100; + + error = wacom_leds_alloc_and_register(wacom, 1, 4, false); + if (error) { + hid_err(wacom->hdev, + "cannot create leds err: %d\n", error); + return error; + } + + error = wacom_devm_sysfs_create_group(wacom, + &generic_led_attr_group); + break; + case INTUOS4S: case INTUOS4: case INTUOS4WL: diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 06d152a286a0..0dad786d2135 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -43,6 +43,8 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev, static int wacom_numbered_button_to_key(int n); +static void wacom_update_led(struct wacom *wacom, int button_count, int mask, + int group); /* * Percent of battery capacity for Graphire. * 8th value means AC online and show 100% capacity. @@ -1715,12 +1717,14 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0); features->device_type |= WACOM_DEVICETYPE_PAD; break; + case WACOM_HID_WD_BUTTONCENTER: + wacom->generic_has_leds = true; + /* fall through */ case WACOM_HID_WD_BUTTONHOME: case WACOM_HID_WD_BUTTONUP: case WACOM_HID_WD_BUTTONDOWN: case WACOM_HID_WD_BUTTONLEFT: case WACOM_HID_WD_BUTTONRIGHT: - case WACOM_HID_WD_BUTTONCENTER: wacom_map_usage(input, usage, field, EV_KEY, wacom_numbered_button_to_key(features->numbered_buttons), 0); @@ -1797,7 +1801,9 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct input_dev *input = wacom_wac->pad_input; + struct wacom_features *features = &wacom_wac->features; unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); + int i; /* * Avoid reporting this event and setting inrange_state if this usage @@ -1824,6 +1830,12 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field input_sync(wacom_wac->shared->touch_input); } break; + + case WACOM_HID_WD_BUTTONCENTER: + for (i = 0; i < wacom->led.count; i++) + wacom_update_led(wacom, features->numbered_buttons, + value, i); + /* fall through*/ default: input_event(input, usage->type, usage->code, value); break; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 4feaf94fb08b..857ccee16f38 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -79,6 +79,7 @@ #define WAC_CMD_ICON_XFER 0x23 #define WAC_CMD_ICON_BT_XFER 0x26 #define WAC_CMD_DELETE_PAIRING 0x20 +#define WAC_CMD_LED_CONTROL_GENERIC 0x32 #define WAC_CMD_UNPAIR_ALL 0xFF #define WAC_CMD_WL_INTUOSP2 0x82 -- cgit v1.2.3-59-g8ed1b From e7deb1570a527d3c74be4e21a72b1b459605c501 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Mon, 30 Jan 2017 15:40:49 -0800 Subject: HID: wacom: don't apply generic settings to old devices Non-generic devices have numbered_buttons set for both pen and touch interfaces by default. The actual number of buttons on the interface is normally manually decided later, which is different from what those HID generic devices are processed, where number of buttons are directly retrieved from HID descriptors. This patch adds the missed HID_GENERIC check and moves the statement to wacom_setup_pad_input_capabilities since it's not a quirk anymore. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 0dad786d2135..d51daf581488 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2987,8 +2987,6 @@ void wacom_setup_device_quirks(struct wacom *wacom) struct wacom_features *features = &wacom->wacom_wac.features; /* The pen and pad share the same interface on most devices */ - if (features->numbered_buttons > 0) - features->device_type |= WACOM_DEVICETYPE_PAD; if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 || features->type == DTUS || (features->type >= INTUOS3S && features->type <= WACOM_MO)) { @@ -3527,6 +3525,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, { struct wacom_features *features = &wacom_wac->features; + if ((features->type == HID_GENERIC) && features->numbered_buttons > 0) + features->device_type |= WACOM_DEVICETYPE_PAD; + if (!(features->device_type & WACOM_DEVICETYPE_PAD)) return -ENODEV; -- cgit v1.2.3-59-g8ed1b From a48324de6d4d41dd3974e18ee8cedac4c0dd503a Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Fri, 10 Feb 2017 16:14:07 -0800 Subject: HID: wacom: Bluetooth IRQ for Intuos Pro should handle prox/range The prox/range bits included in the Bluetooth reports from the Intuos Pro were being ignored, leading to two issues. Firstly, the pen would never announce a BTN_TOOL_PEN event with value 0, leaving userspace to believe the pen was always active. Secondly, the driver would continue to send events for data while the packet's "prox" bit was clear. This can lead to sudden incorrect pointer jumps if the pen is slowly moved away from the tablet surface. Signed-off-by: Jason Gerecke Reviewed-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers/hid/wacom_wac.c') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index d51daf581488..1f3bdd16e159 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1211,29 +1211,34 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) for (i = 0; i < pen_frames; i++) { unsigned char *frame = &data[i*pen_frame_len + 1]; + bool valid = frame[0] & 0x80; + bool prox = frame[0] & 0x40; + bool range = frame[0] & 0x20; - if (!(frame[0] & 0x80)) + if (!valid) continue; - input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1])); - input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3])); + if (range) { + input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1])); + input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3])); + input_report_abs(pen_input, ABS_TILT_X, frame[7]); + input_report_abs(pen_input, ABS_TILT_Y, frame[8]); + input_report_abs(pen_input, ABS_Z, get_unaligned_le16(&frame[9])); + input_report_abs(pen_input, ABS_WHEEL, get_unaligned_le16(&frame[11])); + } input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5])); - input_report_abs(pen_input, ABS_TILT_X, frame[7]); - input_report_abs(pen_input, ABS_TILT_Y, frame[8]); - input_report_abs(pen_input, ABS_Z, get_unaligned_le16(&frame[9])); - input_report_abs(pen_input, ABS_WHEEL, get_unaligned_le16(&frame[11])); - input_report_abs(pen_input, ABS_DISTANCE, frame[13]); + input_report_abs(pen_input, ABS_DISTANCE, range ? frame[13] : wacom->features.distance_max); input_report_key(pen_input, BTN_TOUCH, frame[0] & 0x01); input_report_key(pen_input, BTN_STYLUS, frame[0] & 0x02); input_report_key(pen_input, BTN_STYLUS2, frame[0] & 0x04); - input_report_key(pen_input, wacom->tool[0], 1); + input_report_key(pen_input, wacom->tool[0], prox); input_event(pen_input, EV_MSC, MSC_SERIAL, wacom->serial[0]); input_report_abs(pen_input, ABS_MISC, wacom_intuos_id_mangle(wacom->id[0])); /* report tool id */ - wacom->shared->stylus_in_proximity = frame[0] & 0x40; + wacom->shared->stylus_in_proximity = prox; input_sync(pen_input); } -- cgit v1.2.3-59-g8ed1b