Signed-off-by: Ping Cheng <pingc@xxxxxxxxx> --- drivers/input/tablet/wacom_sys.c | 26 ++++++------ drivers/input/tablet/wacom_wac.c | 82 +++++++++++++++++++++++++++++++++++++- drivers/input/tablet/wacom_wac.h | 8 ++++ 3 files changed, 101 insertions(+), 15 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index b9736fb..eee06ef 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -297,6 +297,10 @@ static int wacom_parse_hid(struct usb_interface *intf, features->pktlen = WACOM_PKGLEN_TPC2FG; features->touch_max = 2; } + + if (features->type == MTSCREEN) + features->pktlen = WACOM_PKGLEN_MTOUCH; + if (features->type == BAMBOO_PT) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_BBTOUCH; @@ -331,18 +335,15 @@ static int wacom_parse_hid(struct usb_interface *intf, case HID_USAGE_Y: if (usage == WCM_DESKTOP) { if (finger) { - features->device_type = BTN_TOOL_FINGER; - if (features->type == TABLETPC2FG) { - /* need to reset back */ - features->pktlen = WACOM_PKGLEN_TPC2FG; + int type = features->type; + + if (type == TABLETPC2FG || type == MTSCREEN) { features->y_max = get_unaligned_le16(&report[i + 3]); features->y_phy = get_unaligned_le16(&report[i + 6]); i += 7; - } else if (features->type == BAMBOO_PT) { - /* need to reset back */ - features->pktlen = WACOM_PKGLEN_BBTOUCH; + } else if (type == BAMBOO_PT) { features->y_phy = get_unaligned_le16(&report[i + 3]); features->y_max = @@ -356,10 +357,6 @@ static int wacom_parse_hid(struct usb_interface *intf, i += 4; } } else if (pen) { - /* penabled only accepts exact bytes of data */ - if (features->type == TABLETPC2FG) - features->pktlen = WACOM_PKGLEN_GRAPHIRE; - features->device_type = BTN_TOOL_PEN; features->y_max = get_unaligned_le16(&report[i + 3]); i += 4; @@ -432,7 +429,8 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat /* ask to report tablet data if it is MT Tablet PC or * not a Tablet PC */ - if (features->type == TABLETPC2FG) { + if (((features->type == TABLETPC2FG) || (features->type == MTSCREEN)) + && features->device_type != BTN_TOOL_PEN) { do { rep_data[0] = 3; rep_data[1] = 4; @@ -479,9 +477,9 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, features->pressure_fuzz = 0; features->distance_fuzz = 0; - /* only Tablet PCs and Bamboo P&T need to retrieve the info */ + /* only devices that support touch need to retrieve the info */ if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && - (features->type != BAMBOO_PT)) + (features->type != BAMBOO_PT) && (features->type != MTSCREEN)) goto out; if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 8dc185d..1a887a1 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -729,6 +729,73 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) return 1; } +static int wacom_mt_touch(struct wacom_wac *wacom) +{ + struct wacom_features *features = &wacom->features; + struct input_dev *input = wacom->input; + char *data = wacom->data; + struct input_mt_slot *mt; + int i, id = -1, j = 0, k = 4; + int x = 0, y = 0; + int current_num_contacts = data[2]; + int contacts_to_send = 0; + bool touch = false; + + /* reset the counter by the first packet */ + if (current_num_contacts) { + features->num_contacts = current_num_contacts; + features->num_contacts_left = current_num_contacts; + } + + /* There are at most 5 contacts per packet */ + contacts_to_send = min(5, (int)features->num_contacts_left); + + for (i = 0; i < contacts_to_send; i++) { + id = le16_to_cpup((__le16 *)&data[k]); + + /* is there an existing slot for this contact? */ + for (j = 0; j < features->touch_max; j++) { + mt = &input->mt[j]; + if (input_mt_get_value(mt, ABS_MT_TRACKING_ID) == id ) + break; + } + + /* no. then find an unused slot to fill */ + if (j >= features->touch_max) { + for (j = 0; j < features->touch_max; j++) { + mt = &input->mt[j]; + if (input_mt_get_value(mt, ABS_MT_TRACKING_ID) == -1 ) + break; + } + } + + touch = data[k - 1] & 0x1; + input_mt_slot(input, j); + if (touch) { + x = le16_to_cpup((__le16 *)&data[k + 6]); + y = le16_to_cpup((__le16 *)&data[k + 8]); + + input_report_abs(input, ABS_MT_POSITION_X, x); + input_report_abs(input, ABS_MT_POSITION_Y, y); + } else + id = -1; + + /* keep the id from firmware since we need + * it to process future events + */ + input_report_abs(input, ABS_MT_TRACKING_ID, id); + + k += WACOM_BYTES_PER_MT_PACKET; + } + + input_mt_report_pointer_emulation(input, true); + + features->num_contacts_left -= contacts_to_send; + if (features->num_contacts_left < 0) + features->num_contacts_left = 0; + return 1; +} + static int wacom_tpc_mt_touch(struct wacom_wac *wacom) { struct input_dev *input = wacom->input; @@ -767,6 +834,10 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) bool prox; int x = 0, y = 0; + if ((wacom->features.touch_max > 1) || + (len > WACOM_PKGLEN_TPC2FG)) + return 0; + if (!wacom->shared->stylus_in_proximity) { if (len == WACOM_PKGLEN_TPC1FG) { prox = data[0] & 0x01; @@ -847,6 +918,9 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) case WACOM_REPORT_TPCST: return wacom_tpc_single_touch(wacom, len); + case WACOM_REPORT_TPCMT: + return wacom_mt_touch(wacom); + case WACOM_REPORT_PENABLED: return wacom_tpc_pen(wacom); } @@ -1088,6 +1162,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) case TABLETPC: case TABLETPC2FG: + case MTSCREEN: sync = wacom_tpc_irq(wacom_wac, len); break; @@ -1156,7 +1231,7 @@ void wacom_setup_device_quirks(struct wacom_features *features) /* these device have multiple inputs */ if (features->type == TABLETPC || features->type == TABLETPC2FG || - features->type == BAMBOO_PT) + features->type == BAMBOO_PT || features->type == MTSCREEN) features->quirks |= WACOM_QUIRK_MULTI_INPUT; /* quirk for bamboo touch with 2 low res touches */ @@ -1330,6 +1405,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, break; case TABLETPC2FG: + case MTSCREEN: if (features->device_type == BTN_TOOL_FINGER) { input_mt_init_slots(input_dev, features->touch_max); @@ -1629,6 +1705,9 @@ static const struct wacom_features wacom_features_0xE2 = static const struct wacom_features wacom_features_0xE3 = { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xE5 = + { "Wacom ISDv4 E5", WACOM_PKGLEN_MTOUCH, 26202, 16325, 255, + 0, MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xE6 = { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -1784,6 +1863,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x9F) }, { USB_DEVICE_WACOM(0xE2) }, { USB_DEVICE_WACOM(0xE3) }, + { USB_DEVICE_WACOM(0xE5) }, { USB_DEVICE_WACOM(0xE6) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 1c9dc3e..265b09f 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -24,6 +24,10 @@ #define WACOM_PKGLEN_BBTOUCH 20 #define WACOM_PKGLEN_BBTOUCH3 64 #define WACOM_PKGLEN_BBPEN 10 +#define WACOM_PKGLEN_MTOUCH 62 + +/* wacom data size per MT contact */ +#define WACOM_BYTES_PER_MT_PACKET 11 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -39,6 +43,7 @@ #define WACOM_REPORT_INTUOSPAD 12 #define WACOM_REPORT_TPC1FG 6 #define WACOM_REPORT_TPC2FG 13 +#define WACOM_REPORT_TPCMT 13 #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 @@ -68,6 +73,7 @@ enum { WACOM_MO, TABLETPC, TABLETPC2FG, + MTSCREEN, MAX_TYPE }; @@ -92,6 +98,8 @@ struct wacom_features { int distance_fuzz; unsigned quirks; unsigned touch_max; + unsigned num_contacts; + unsigned num_contacts_left; }; struct wacom_shared { -- 1.7.6.4 -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html