--- 2.6.30/wacom_sys.c | 20 +++- 2.6.30/wacom_wac.c | 224 +++++++++++++++++++++++++++++++++++++++++++ 2.6.30/wacom_wac.h | 8 ++ 2.6.36/wacom_sys.c | 20 +++- 2.6.36/wacom_wac.c | 272 +++++++++++++++++++++++++++++++++++++++++++++++++---- 2.6.36/wacom_wac.h | 8 ++ 2.6.38/wacom_sys.c | 9 ++ 2.6.38/wacom_wac.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++ 2.6.38/wacom_wac.h | 8 ++ 3.7/wacom_sys.c | 9 ++ 3.7/wacom_wac.c | 234 +++++++++++++++++++++++++++++++++++++++++++++ 3.7/wacom_wac.h | 8 ++ 12 files changed, 1033 insertions(+), 23 deletions(-)
diff --git a/2.6.30/wacom_sys.c b/2.6.30/wacom_sys.c index 517e293..37c30ec 100644 --- a/2.6.30/wacom_sys.c +++ b/2.6.30/wacom_sys.c @@ -235,11 +235,14 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi features->device_type = BTN_TOOL_DOUBLETAP; if (features->type == TABLETPC2FG || features->type == MTTPC || - features->type == MTTPC_B) { + features->type == MTTPC_B || + features->type == WACOM_MSPROT) { /* need to reset back */ features->pktlen = WACOM_PKGLEN_TPC2FG; if (features->type == MTTPC || features->type == MTTPC_B) features->pktlen = WACOM_PKGLEN_MTTPC; + else if (features->type == WACOM_MSPROT) + features->pktlen = WACOM_PKGLEN_MSPROT; features->device_type = BTN_TOOL_TRIPLETAP; } if (features->type == BAMBOO_PT) { @@ -251,7 +254,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi features->x_max = get_unaligned_le16(&report[i + 8]); i += 15; - } else if (features->type == MTTPC_B) { + } else if (features->type == WACOM_MSPROT || + features->type == MTTPC_B) { features->x_max = get_unaligned_le16(&report[i + 3]); features->x_phy = @@ -291,7 +295,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi features->y_phy = get_unaligned_le16(&report[i + 6]); i += 7; - } else if (features->type == MTTPC_B) { + } else if (features->type == WACOM_MSPROT || + features->type == MTTPC_B) { features->y_max = get_unaligned_le16(&report[i + 3]); features->y_phy = @@ -383,6 +388,15 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat report_id, rep_data, 4, 1); } while ((error < 0 || rep_data[1] != 4) && limit++ < 5); } + else if (features->type == WACOM_MSPROT) { + do { + rep_data[0] = 14; + rep_data[1] = 2; + report_id = 14; + error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, + report_id, rep_data, 2, 1); + } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); + } } else if (features->type <= BAMBOO_PT) { do { rep_data[0] = 2; diff --git a/2.6.30/wacom_wac.c b/2.6.30/wacom_wac.c index f24d7b8..3075f96 100644 --- a/2.6.30/wacom_wac.c +++ b/2.6.30/wacom_wac.c @@ -27,6 +27,8 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev, int button_count, int mask); +static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid); + static int wacom_penpartner_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; @@ -628,6 +630,7 @@ static int wacom_intuos_get_tool_type(int tool_id) break; case 0x82a: /* Eraser */ + case 0x84a: case 0x85a: case 0x91a: case 0xd1a: @@ -1054,6 +1057,73 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) return 0; } +static int wacom_msprot_irq(struct wacom_wac *wacom) +{ + struct input_dev *input = wacom->input; + unsigned char *data = wacom->data; + int i; + int current_num_contacts = data[2]; + int contacts_to_send = 0; + + wacom->tool[1] = BTN_TOOL_DOUBLETAP; + wacom->id[0] = TOUCH_DEVICE_ID; + wacom->tool[2] = BTN_TOOL_TRIPLETAP; + + if (current_num_contacts) + wacom->num_contacts_left = current_num_contacts; + + contacts_to_send = min(5, wacom->num_contacts_left); + + for (i = 0; i < contacts_to_send; i++) { + int offset = WACOM_BYTES_PER_MSPROT_PACKET * i + 3; + bool touch = (data[offset] & 0x1) && !wacom->shared->stylus_in_proximity; + int id = get_unaligned_le16(&data[offset + 1]); + int slot = find_slot_from_contactid(wacom, id); + + if (slot < 0) + continue; + + //input_mt_slot(input, slot); + //input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + if (touch) { + int x = get_unaligned_le16(&data[offset + 3]); + int y = get_unaligned_le16(&data[offset + 5]); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) + if (wacom->last_finger != slot) { + if (x == input->abs[ABS_X]) + x++; + + if (y == input->abs[ABS_Y]) + y++; + } +#endif + + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + } + wacom->slots[slot] = touch ? id : -1; + + input_report_abs(input, ABS_MISC, wacom->id[0]); + input_report_key(input, wacom->tool[slot+1], touch); + wacom->last_finger = slot + 1; + if (!slot) + input_report_key(input, BTN_TOUCH, touch); + input_event(input, EV_MSC, MSC_SERIAL, slot + 1); + input_sync(input); + } + + wacom->num_contacts_left -= contacts_to_send; + if (wacom->num_contacts_left <= 0) { + wacom->num_contacts_left = 0; + wacom->shared->touch_down = test_bit(BTN_TOOL_DOUBLETAP, input->key) || + test_bit(BTN_TOOL_TRIPLETAP, input->key); + } + + //input_mt_sync_frame(input); + return 1; +} + static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len) { struct wacom_features *features = &wacom->features; @@ -1363,6 +1433,136 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) return retval; } +static int wacom_mspro_pad_irq(struct wacom_wac *wacom) +{ + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + int nbuttons = wacom->features.numbered_buttons; + bool prox; + int buttons, ring; + + switch (nbuttons) { + case 11: + buttons = (data[1] >> 1) | (data[3] << 6); + break; + case 13: + buttons = data[1] | (data[3] << 8); + break; + default: + dev_warn(input->dev.parent, "%s: unsupported device #%d\n", __func__, data[0]); + return 0; + } + + ring = le16_to_cpup((__le16 *)&data[4]); + + prox = buttons || ring; + + wacom_report_numbered_buttons(input, nbuttons, buttons); + input_report_abs(input, ABS_WHEEL, (ring & 0x80) ? (ring & 0x7f) : 0); + + input_report_key(input, wacom->tool[1], prox ? 1 : 0); + input_report_abs(input, ABS_MISC, prox ? PAD_DEVICE_ID : 0); + + input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff); + + return 1; +} + +static int wacom_mspro_pen_irq(struct wacom_wac *wacom) +{ + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + bool tip, sw1, sw2, range, proximity; + unsigned int x, y; + unsigned int pressure; + int tilt_x, tilt_y; + int rotation; + unsigned int fingerwheel; + unsigned int height; + u64 tool_uid; + unsigned int tool_type; + + if (wacom->shared->touch_down) + return 1; + + tip = data[1] & 0x01; + sw1 = data[1] & 0x02; + sw2 = data[1] & 0x04; + /* eraser = data[1] & 0x08; */ + /* invert = data[1] & 0x10; */ + range = data[1] & 0x20; + proximity = data[1] & 0x40; + x = le32_to_cpup((__le32 *)&data[2]) & 0xFFFFFF; + y = le32_to_cpup((__le32 *)&data[5]) & 0xFFFFFF; + pressure = le16_to_cpup((__le16 *)&data[8]); + tilt_x = data[10]; + tilt_y = data[11]; + rotation = le16_to_cpup((__le16 *)&data[12]); + fingerwheel = le16_to_cpup((__le16 *)&data[14]); + height = data[16]; + tool_uid = le64_to_cpup((__le64 *)&data[17]); + tool_type = le16_to_cpup((__le16 *)&data[25]); + + wacom->serial[0] = (tool_uid & 0xFFFFFFFF); + wacom->id[0] = (tool_uid >> 32) | tool_type; + if (range) { + wacom->tool[0] = wacom_intuos_get_tool_type(wacom->id[0] & 0xFFFFF); + } + + /* pointer going from fully "in range" to merely "in proximity" */ + if (!range && wacom->tool[0]) { + height = wacom->features.distance_max; + } + + /* + * only report data if there's a tool for userspace to associate + * the events with. + */ + if (wacom->tool[0]) { + input_report_key(input, BTN_TOUCH, tip); + input_report_key(input, BTN_STYLUS, sw1); + input_report_key(input, BTN_STYLUS2, sw2); + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + input_report_abs(input, ABS_PRESSURE, pressure); + input_report_abs(input, ABS_TILT_X, tilt_x); + input_report_abs(input, ABS_TILT_Y, tilt_y); + input_report_abs(input, ABS_Z, rotation); + input_report_abs(input, ABS_WHEEL, fingerwheel); + input_report_abs(input, ABS_DISTANCE, height); + input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[0]); + input_report_abs(input, ABS_MISC, wacom_intuos_id_mangle(wacom->id[0])); + input_report_key(input, wacom->tool[0], range ? 1 : 0); + + if (!range) + wacom->tool[0] = 0; + } + + wacom->shared->stylus_in_proximity = proximity; + + return 1; +} + +static int wacom_mspro_irq(struct wacom_wac *wacom) +{ + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + + switch (data[0]) { + case WACOM_REPORT_MSPRO: + return wacom_mspro_pen_irq(wacom); + case WACOM_REPORT_MSPROPAD: + return wacom_mspro_pad_irq(wacom); + case WACOM_REPORT_MSPRODEVICE: + return 0; + default: + dev_dbg(input->dev.parent, + "%s: received unknown report #%d\n", __func__, data[0]); + break; + } + return 0; +} + void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) { bool sync; @@ -1419,6 +1619,14 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_intuos_irq(wacom_wac); break; + case WACOM_MSPRO: + sync = wacom_mspro_irq(wacom_wac); + break; + + case WACOM_MSPROT: + sync = wacom_msprot_irq(wacom_wac); + break; + case INTUOS5S: case INTUOS5: case INTUOS5L: @@ -1750,6 +1958,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, wacom_setup_cintiq(wacom_wac); break; + case WACOM_MSPRO: case WACOM_13HD: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); wacom_setup_cintiq(wacom_wac); @@ -1813,6 +2022,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, case MTTPC: case MTTPC_B: + case WACOM_MSPROT: if (features->device_type == BTN_TOOL_TRIPLETAP) { for (i = 0; i < 10; i++) wacom_wac->slots[i] = -1; @@ -2129,6 +2339,16 @@ static const struct wacom_features wacom_features_0x47 = { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, 0, TABLETPC }; +static const struct wacom_features wacom_features_0x34A = + { "Wacom MobileStudio Pro 13 Touch", WACOM_PKGLEN_MSPROT, .type = WACOM_MSPROT }; /* Touch */ +static const struct wacom_features wacom_features_0x34B = + { "Wacom MobileStudio Pro 16 Touch", WACOM_PKGLEN_MSPROT, .type = WACOM_MSPROT }; /* Touch */ +static const struct wacom_features wacom_features_0x34D = + { "Wacom MobileStudio Pro 13", WACOM_PKGLEN_MSPRO, 59552, 33848, 8191, 63, + WACOM_MSPRO, 11, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; +static const struct wacom_features wacom_features_0x34E = + { "Wacom MobileStudio Pro 16", WACOM_PKGLEN_MSPRO, 69920, 39680, 8191, 63, + WACOM_MSPRO, 13, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; #define USB_DEVICE_WACOM(prod) \ USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ @@ -2279,6 +2499,10 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x32B) }, { USB_DEVICE_WACOM(0x32F) }, { USB_DEVICE_WACOM(0x343) }, + { USB_DEVICE_WACOM(0x34A) }, + { USB_DEVICE_WACOM(0x34B) }, + { USB_DEVICE_WACOM(0x34D) }, + { USB_DEVICE_WACOM(0x34E) }, { USB_DEVICE_LENOVO(0x6004) }, { } }; diff --git a/2.6.30/wacom_wac.h b/2.6.30/wacom_wac.h index 8e39ff8..8d444fc 100755 --- a/2.6.30/wacom_wac.h +++ b/2.6.30/wacom_wac.h @@ -28,9 +28,12 @@ #define WACOM_PKGLEN_BBPEN 10 #define WACOM_PKGLEN_DTUS 68 #define WACOM_PKGLEN_PENABLED 8 +#define WACOM_PKGLEN_MSPRO 64 +#define WACOM_PKGLEN_MSPROT 50 /* wacom data size per MT contact */ #define WACOM_BYTES_PER_MT_PACKET 11 +#define WACOM_BYTES_PER_MSPROT_PACKET 9 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -51,8 +54,11 @@ #define WACOM_REPORT_TPCMT2 3 #define WACOM_REPORT_DTUS 17 #define WACOM_REPORT_CINTIQ 16 +#define WACOM_REPORT_MSPRO 16 #define WACOM_REPORT_INTUOS_PEN 16 #define WACOM_REPORT_CINTIQPAD 17 +#define WACOM_REPORT_MSPROPAD 17 +#define WACOM_REPORT_MSPRODEVICE 19 /* device quirks */ #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 @@ -86,6 +92,7 @@ enum { WACOM_27QHD, DTK, WACOM_24HD, + WACOM_MSPRO, CINTIQ, WACOM_BEE, WACOM_13HD, @@ -94,6 +101,7 @@ enum { INTUOSHT, INTUOSHT2, BAMBOO_PT, + WACOM_MSPROT, TABLETPC, TABLETPC2FG, MTTPC, diff --git a/2.6.36/wacom_sys.c b/2.6.36/wacom_sys.c index 55e54dc..87990b9 100644 --- a/2.6.36/wacom_sys.c +++ b/2.6.36/wacom_sys.c @@ -227,6 +227,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi if (features->type == MTSCREEN) features->pktlen = WACOM_PKGLEN_MTOUCH; + else if (features->type == WACOM_MSPROT) + features->pktlen = WACOM_PKGLEN_MSPROT; if (features->type == BAMBOO_PT) { features->pktlen = WACOM_PKGLEN_BBTOUCH; @@ -236,6 +238,15 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi features->x_max = get_unaligned_le16(&report[i + 8]); i += 15; + } else if (features->type == WACOM_MSPROT) { + features->touch_max = 10; + features->x_max = + get_unaligned_le16(&report[i + 3]); + features->x_phy = + get_unaligned_le16(&report[i + 6]); + features->unit = report[i - 5]; + features->unitExpo = report[i - 3]; + i += 9; } else { features->touch_max = 1; features->x_max = @@ -271,6 +282,12 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi features->y_max = get_unaligned_le16(&report[i + 6]); i += 12; + } else if (features->type == WACOM_MSPROT) { + features->y_max = + get_unaligned_le16(&report[i + 3]); + features->y_phy = + get_unaligned_le16(&report[i + 6]); + i += 9; } else { features->y_max = features->x_max; @@ -387,7 +404,8 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, /* only devices support touch need to retrieve the info */ if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && - (features->type != BAMBOO_PT) && (features->type != MTSCREEN)) + (features->type != BAMBOO_PT) && (features->type != MTSCREEN) && + (features->type != WACOM_MSPROT)) goto out; if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { diff --git a/2.6.36/wacom_wac.c b/2.6.36/wacom_wac.c index cf8556f..4537c9d 100644 --- a/2.6.36/wacom_wac.c +++ b/2.6.36/wacom_wac.c @@ -420,6 +420,7 @@ static int wacom_intuos_get_tool_type(int tool_id) break; case 0x82a: /* Eraser */ + case 0x84a: case 0x85a: case 0x91a: case 0xd1a: @@ -847,13 +848,38 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) return 0; } +static int find_slot_from_contactid(struct wacom_wac *wacom, int id) +{ + struct wacom_features *features = &wacom->features; + struct input_dev *input = wacom->input; + struct input_mt_slot *mt; + int i; + + /* is there an existing slot for this contact? */ + for (i = 0; i < features->touch_max; i++) { + mt = &input->mt[i]; + if (input_mt_get_value(mt, ABS_MT_TRACKING_ID) == id ) + return i; + } + + /* no. then find an unused slot to fill */ + if (i >= features->touch_max) { + for (i = 0; i < features->touch_max; i++) { + mt = &input->mt[i]; + if (input_mt_get_value(mt, ABS_MT_TRACKING_ID) == -1 ) + return i; + } + } + + return -1; +} + static int wacom_mt_touch(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; struct input_dev *input = wacom->input; unsigned char *data = wacom->data; - struct input_mt_slot *mt; - int i, id = -1, j = 0, k = 4; + int i, id = -1, slot = -1, k = 4; int x = 0, y = 0, sx = 0, sy = 0, st = 0; int current_num_contacts = data[2]; int contacts_to_send = 0; @@ -870,25 +896,10 @@ static int wacom_mt_touch(struct wacom_wac *wacom) for (i = 0; i < contacts_to_send; i++) { id = get_unaligned_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; - } - } + slot = find_slot_from_contactid(wacom, id); touch = (data[k - 1] & 0x1) && !wacom->shared->stylus_in_proximity; - input_mt_slot(input, j); + input_mt_slot(input, slot); if (touch) { x = get_unaligned_le16(&data[k + 6]); y = get_unaligned_le16(&data[k + 8]); @@ -1189,6 +1200,197 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len) return 0; } +static int wacom_msprot_irq(struct wacom_wac *wacom) +{ + struct wacom_features *features = &wacom->features; + struct input_dev *input = wacom->input; + unsigned char *data = wacom->data; + int i; + int current_num_contacts = data[2]; + int contacts_to_send = 0; + int sx = 0, sy = 0; + + if (current_num_contacts) { + features->num_contacts = 0; + features->num_contacts_left = current_num_contacts; + } + + contacts_to_send = min(5, features->num_contacts_left); + + for (i = 0; i < contacts_to_send; i++) { + int offset = WACOM_BYTES_PER_MSPROT_PACKET * i + 3; + bool touch = (data[offset] & 0x1) && !wacom->shared->stylus_in_proximity; + int id = get_unaligned_le16(&data[offset + 1]); + int slot = find_slot_from_contactid(wacom, id); + + if (slot < 0) + continue; + + input_mt_slot(input, slot); + if (touch) { + int x = get_unaligned_le16(&data[offset + 3]); + int y = get_unaligned_le16(&data[offset + 5]); + input_report_abs(input, ABS_MT_POSITION_X, x); + input_report_abs(input, ABS_MT_POSITION_Y, y); + + features->num_contacts++; + if (features->num_contacts == 1) { + sx = x; + sy = y; + } + } + else + id = -1; + + input_report_abs(input, ABS_MT_TRACKING_ID, id); + } + + features->num_contacts_left -= contacts_to_send; + if (features->num_contacts_left <= 0) { + features->num_contacts_left = 0; + wacom->shared->touch_down = features->num_contacts > 0; + } + + if (features->num_contacts <= 1) { + input_report_key(input, BTN_TOUCH, features->num_contacts == 1); + input_report_abs(input, ABS_X, sx); + input_report_abs(input, ABS_Y, sy); + } + + return 1; +} + +static int wacom_mspro_pad_irq(struct wacom_wac *wacom) +{ + struct wacom_features *features = &wacom->features; + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + int nbuttons = features->numbered_buttons; + bool prox; + int buttons, ring; + + switch (nbuttons) { + case 11: + buttons = (data[1] >> 1) | (data[3] << 6); + break; + case 13: + buttons = data[1] | (data[3] << 8); + break; + default: + dev_warn(input->dev.parent, "%s: unsupported device #%d\n", __func__, data[0]); + return 0; + } + + ring = le16_to_cpup((__le16 *)&data[4]); + + prox = buttons || ring; + + wacom_report_numbered_buttons(input, nbuttons, buttons); + input_report_abs(input, ABS_WHEEL, (ring & 0x80) ? (ring & 0x7f) : 0); + + input_report_key(input, wacom->tool[1], prox ? 1 : 0); + input_report_abs(input, ABS_MISC, prox ? PAD_DEVICE_ID : 0); + + input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff); + + return 1; +} + +static int wacom_mspro_pen_irq(struct wacom_wac *wacom) +{ + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + bool tip, sw1, sw2, range, proximity; + unsigned int x, y; + unsigned int pressure; + int tilt_x, tilt_y; + int rotation; + unsigned int fingerwheel; + unsigned int height; + u64 tool_uid; + unsigned int tool_type; + + if (wacom->shared->touch_down) + return 1; + + tip = data[1] & 0x01; + sw1 = data[1] & 0x02; + sw2 = data[1] & 0x04; + /* eraser = data[1] & 0x08; */ + /* invert = data[1] & 0x10; */ + range = data[1] & 0x20; + proximity = data[1] & 0x40; + x = le32_to_cpup((__le32 *)&data[2]) & 0xFFFFFF; + y = le32_to_cpup((__le32 *)&data[5]) & 0xFFFFFF; + pressure = le16_to_cpup((__le16 *)&data[8]); + tilt_x = data[10]; + tilt_y = data[11]; + rotation = le16_to_cpup((__le16 *)&data[12]); + fingerwheel = le16_to_cpup((__le16 *)&data[14]); + height = data[16]; + tool_uid = le64_to_cpup((__le64 *)&data[17]); + tool_type = le16_to_cpup((__le16 *)&data[25]); + + wacom->serial[0] = (tool_uid & 0xFFFFFFFF); + wacom->id[0] = (tool_uid >> 32) | tool_type; + if (range) { + wacom->tool[0] = wacom_intuos_get_tool_type(wacom->id[0] & 0xFFFFF); + } + + /* pointer going from fully "in range" to merely "in proximity" */ + if (!range && wacom->tool[0]) { + height = wacom->features.distance_max; + } + + /* + * only report data if there's a tool for userspace to associate + * the events with. + */ + if (wacom->tool[0]) { + input_report_key(input, BTN_TOUCH, tip); + input_report_key(input, BTN_STYLUS, sw1); + input_report_key(input, BTN_STYLUS2, sw2); + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + input_report_abs(input, ABS_PRESSURE, pressure); + input_report_abs(input, ABS_TILT_X, tilt_x); + input_report_abs(input, ABS_TILT_Y, tilt_y); + input_report_abs(input, ABS_Z, rotation); + input_report_abs(input, ABS_WHEEL, fingerwheel); + input_report_abs(input, ABS_DISTANCE, height); + input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[0]); + input_report_abs(input, ABS_MISC, wacom_intuos_id_mangle(wacom->id[0])); + input_report_key(input, wacom->tool[0], range ? 1 : 0); + + if (!range) + wacom->tool[0] = 0; + } + + wacom->shared->stylus_in_proximity = proximity; + + return 1; +} + +static int wacom_mspro_irq(struct wacom_wac *wacom) +{ + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + + switch (data[0]) { + case WACOM_REPORT_MSPRO: + return wacom_mspro_pen_irq(wacom); + case WACOM_REPORT_MSPROPAD: + return wacom_mspro_pad_irq(wacom); + case WACOM_REPORT_MSPRODEVICE: + return 0; + default: + dev_dbg(input->dev.parent, + "%s: received unknown report #%d\n", __func__, data[0]); + break; + } + return 0; +} + void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) { bool sync; @@ -1244,6 +1446,14 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_intuos_irq(wacom_wac); break; + case WACOM_MSPRO: + sync = wacom_mspro_irq(wacom_wac); + break; + + case WACOM_MSPROT: + sync = wacom_msprot_irq(wacom_wac); + break; + case TABLETPC: case TABLETPCE: case TABLETPC2FG: @@ -1486,6 +1696,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, break; case WACOM_13HD: + case WACOM_MSPRO: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); wacom_setup_cintiq(wacom_wac); break; @@ -1525,6 +1736,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, wacom_setup_intuos(wacom_wac); break; + case WACOM_MSPROT: case TABLETPC2FG: case MTSCREEN: if (features->device_type == BTN_TOOL_FINGER) { @@ -1941,6 +2153,24 @@ static const struct wacom_features wacom_features_0x343 = 0, 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_0x34A = + { "Wacom MobileStudio Pro 13 Touch", WACOM_PKGLEN_MSPROT, .type = WACOM_MSPROT, /* Touch */ + }; +static const struct wacom_features wacom_features_0x34B = + { "Wacom MobileStudio Pro 16 Touch", WACOM_PKGLEN_MSPROT, .type = WACOM_MSPROT, /* Touch */ + }; +static const struct wacom_features wacom_features_0x34D = + { "Wacom MobileStudio Pro 13", WACOM_PKGLEN_MSPRO, 59552, 33848, 8191, 63, + WACOM_MSPRO, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 11, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET + }; +static const struct wacom_features wacom_features_0x34E = + { "Wacom MobileStudio Pro 16", WACOM_PKGLEN_MSPRO, 69920, 39680, 8191, 63, + WACOM_MSPRO, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 13, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + }; static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2070,6 +2300,10 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x12C) }, { USB_DEVICE_WACOM(0x32F) }, { USB_DEVICE_WACOM(0x343) }, + { USB_DEVICE_WACOM(0x34A) }, + { USB_DEVICE_WACOM(0x34B) }, + { USB_DEVICE_WACOM(0x34D) }, + { USB_DEVICE_WACOM(0x34E) }, { USB_DEVICE_LENOVO(0x6004) }, { } }; diff --git a/2.6.36/wacom_wac.h b/2.6.36/wacom_wac.h index 9e7024b..1615f2a 100644 --- a/2.6.36/wacom_wac.h +++ b/2.6.36/wacom_wac.h @@ -26,6 +26,8 @@ #define WACOM_PKGLEN_MTOUCH 62 #define WACOM_PKGLEN_BBTOUCH3 64 #define WACOM_PKGLEN_DTUS 68 +#define WACOM_PKGLEN_MSPRO 64 +#define WACOM_PKGLEN_MSPROT 50 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -46,9 +48,13 @@ #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 #define WACOM_REPORT_DTUS 17 +#define WACOM_REPORT_MSPRO 16 +#define WACOM_REPORT_MSPROPAD 17 +#define WACOM_REPORT_MSPRODEVICE 19 /* wacom data size per MT contact */ #define WACOM_BYTES_PER_MT_PACKET 11 +#define WACOM_BYTES_PER_MSPROT_PACKET 9 /* device quirks */ #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 @@ -83,10 +89,12 @@ enum { WACOM_22HD, DTK, WACOM_24HD, + WACOM_MSPRO, CINTIQ, WACOM_BEE, WACOM_13HD, WACOM_MO, + WACOM_MSPROT, TABLETPC, TABLETPCE, TABLETPC2FG, diff --git a/2.6.38/wacom_sys.c b/2.6.38/wacom_sys.c index 97faf87..0654118 100644 --- a/2.6.38/wacom_sys.c +++ b/2.6.38/wacom_sys.c @@ -385,6 +385,10 @@ static int wacom_parse_hid(struct usb_interface *intf, features->pktlen = WACOM_PKGLEN_BBTOUCH; break; + case WACOM_MSPROT: + features->pktlen = WACOM_PKGLEN_MSPROT; + break; + default: features->pktlen = WACOM_PKGLEN_GRAPHIRE; break; @@ -421,6 +425,7 @@ static int wacom_parse_hid(struct usb_interface *intf, i += 9; break; + case WACOM_MSPROT: case MTTPC_B: features->x_max = get_unaligned_le16(&report[i + 3]); @@ -491,6 +496,7 @@ static int wacom_parse_hid(struct usb_interface *intf, i += 12; break; + case WACOM_MSPROT: case MTTPC_B: features->y_max = get_unaligned_le16(&report[i + 3]); @@ -613,6 +619,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat else if (features->type == WACOM_27QHDT) { return wacom_set_device_mode(intf, 131, 3, 2); } + else if (features->type == WACOM_MSPROT) { + return wacom_set_device_mode(intf, 14, 2, 2); + } } else if (features->device_type == BTN_TOOL_PEN) { if (features->type <= BAMBOO_PT) { return wacom_set_device_mode(intf, 2, 2, 2); diff --git a/2.6.38/wacom_wac.c b/2.6.38/wacom_wac.c index 56d603a..5933417 100644 --- a/2.6.38/wacom_wac.c +++ b/2.6.38/wacom_wac.c @@ -588,6 +588,7 @@ static int wacom_intuos_get_tool_type(int tool_id) break; case 0x82a: /* Eraser */ + case 0x84a: case 0x85a: case 0x91a: case 0xd1a: @@ -1103,6 +1104,54 @@ static int wacom_wac_finger_count_touches(struct wacom_wac *wacom) return count; } +static int wacom_msprot_irq(struct wacom_wac *wacom) +{ + struct input_dev *input = wacom->input; + unsigned char *data = wacom->data; + int i; + int current_num_contacts = data[2]; + int contacts_to_send = 0; + + if (current_num_contacts) + wacom->num_contacts_left = current_num_contacts; + + contacts_to_send = min(5, wacom->num_contacts_left); + + for (i = 0; i < contacts_to_send; i++) { + int offset = WACOM_BYTES_PER_MSPROT_PACKET * i + 3; + bool touch = (data[offset] & 0x1) && report_touch_events(wacom); + int id = get_unaligned_le16(&data[offset + 1]); + int slot = find_slot_from_contactid(wacom, id); + + if (slot < 0) + continue; + + input_mt_slot(input, slot); + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + if (touch) { + int x = get_unaligned_le16(&data[offset + 3]); + int y = get_unaligned_le16(&data[offset + 5]); + int w = get_unaligned_le16(&data[offset + 7]); + int h = get_unaligned_le16(&data[offset + 9]); + input_report_abs(input, ABS_MT_POSITION_X, x); + input_report_abs(input, ABS_MT_POSITION_Y, y); + input_report_abs(input, ABS_MT_WIDTH_MAJOR, max(w, h)); + input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); + input_report_abs(input, ABS_MT_ORIENTATION, w > h); + } + wacom->slots[slot] = touch ? id : -1; + } + + 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_mt_report_pointer_emulation(input, true); + return 1; +} + static int wacom_24hdt_irq(struct wacom_wac *wacom) { struct input_dev *input = wacom->input; @@ -1652,6 +1701,160 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len) return 0; } +static int wacom_mspro_device_irq(struct wacom_wac *wacom) +{ + struct wacom *w = container_of(wacom, struct wacom, wacom_wac); + struct wacom_features *features = &wacom->features; + unsigned char *data = wacom->data; + bool bat_charging; + int battery_level; + + battery_level = data[1] & 0x7F; + bat_charging = data[1] & 0x80; + + if (!w->battery.battery.dev && + !(features->quirks & WACOM_QUIRK_BATTERY)) { + features->quirks |= WACOM_QUIRK_BATTERY; + wacom_schedule_work(wacom, WACOM_WORKER_BATTERY); + } + + wacom_notify_battery(wacom, battery_level, bat_charging, 1, + bat_charging); + + return 0; +} + +static int wacom_mspro_pad_irq(struct wacom_wac *wacom) +{ + struct wacom_features *features = &wacom->features; + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + int nbuttons = features->numbered_buttons; + bool prox; + int buttons, ring; + + switch (nbuttons) { + case 11: + buttons = (data[1] >> 1) | (data[3] << 6); + break; + case 13: + buttons = data[1] | (data[3] << 8); + break; + default: + dev_warn(input->dev.parent, "%s: unsupported device #%d\n", __func__, data[0]); + return 0; + } + + ring = le16_to_cpup((__le16 *)&data[4]); + + prox = buttons || ring; + + wacom_report_numbered_buttons(input, nbuttons, buttons); + input_report_abs(input, ABS_WHEEL, (ring & 0x80) ? (ring & 0x7f) : 0); + + input_report_key(input, wacom->tool[1], prox ? 1 : 0); + input_report_abs(input, ABS_MISC, prox ? PAD_DEVICE_ID : 0); + + input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff); + + return 1; +} + +static int wacom_mspro_pen_irq(struct wacom_wac *wacom) +{ + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + bool tip, sw1, sw2, range, proximity; + unsigned int x, y; + unsigned int pressure; + int tilt_x, tilt_y; + int rotation; + unsigned int fingerwheel; + unsigned int height; + u64 tool_uid; + unsigned int tool_type; + + if (delay_pen_events(wacom)) + return 1; + + tip = data[1] & 0x01; + sw1 = data[1] & 0x02; + sw2 = data[1] & 0x04; + /* eraser = data[1] & 0x08; */ + /* invert = data[1] & 0x10; */ + range = data[1] & 0x20; + proximity = data[1] & 0x40; + x = le32_to_cpup((__le32 *)&data[2]) & 0xFFFFFF; + y = le32_to_cpup((__le32 *)&data[5]) & 0xFFFFFF; + pressure = le16_to_cpup((__le16 *)&data[8]); + tilt_x = data[10]; + tilt_y = data[11]; + rotation = le16_to_cpup((__le16 *)&data[12]); + fingerwheel = le16_to_cpup((__le16 *)&data[14]); + height = data[16]; + tool_uid = le64_to_cpup((__le64 *)&data[17]); + tool_type = le16_to_cpup((__le16 *)&data[25]); + + wacom->serial[0] = (tool_uid & 0xFFFFFFFF); + wacom->id[0] = (tool_uid >> 32) | tool_type; + if (range) { + wacom->tool[0] = wacom_intuos_get_tool_type(wacom->id[0] & 0xFFFFF); + } + + /* pointer going from fully "in range" to merely "in proximity" */ + if (!range && wacom->tool[0]) { + height = wacom->features.distance_max; + } + + /* + * only report data if there's a tool for userspace to associate + * the events with. + */ + if (wacom->tool[0]) { + input_report_key(input, BTN_TOUCH, tip); + input_report_key(input, BTN_STYLUS, sw1); + input_report_key(input, BTN_STYLUS2, sw2); + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + input_report_abs(input, ABS_PRESSURE, pressure); + input_report_abs(input, ABS_TILT_X, tilt_x); + input_report_abs(input, ABS_TILT_Y, tilt_y); + input_report_abs(input, ABS_Z, rotation); + input_report_abs(input, ABS_WHEEL, fingerwheel); + input_report_abs(input, ABS_DISTANCE, height); + input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[0]); + input_report_abs(input, ABS_MISC, wacom_intuos_id_mangle(wacom->id[0])); + input_report_key(input, wacom->tool[0], range ? 1 : 0); + + if (!range) + wacom->tool[0] = 0; + } + + wacom->shared->stylus_in_proximity = proximity; + + return 1; +} + +static int wacom_mspro_irq(struct wacom_wac *wacom) +{ + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + + switch (data[0]) { + case WACOM_REPORT_MSPRO: + return wacom_mspro_pen_irq(wacom); + case WACOM_REPORT_MSPROPAD: + return wacom_mspro_pad_irq(wacom); + case WACOM_REPORT_MSPRODEVICE: + return wacom_mspro_device_irq(wacom); + default: + dev_dbg(input->dev.parent, + "%s: received unknown report #%d\n", __func__, data[0]); + break; + } + return 0; +} + void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) { bool sync; @@ -1704,6 +1907,14 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_intuos_irq(wacom_wac); break; + case WACOM_MSPRO: + sync = wacom_mspro_irq(wacom_wac); + break; + + case WACOM_MSPROT: + sync = wacom_msprot_irq(wacom_wac); + break; + case WACOM_24HDT: case WACOM_27QHDT: sync = wacom_24hdt_irq(wacom_wac); @@ -2017,6 +2228,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case WACOM_13HD: case CINTIQ_HYBRID: case CINTIQ_COMPANION_2: + case WACOM_MSPRO: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); /* fall through */ @@ -2104,6 +2316,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, } break; + case WACOM_MSPROT: case WACOM_24HDT: if (features->device_type == BTN_TOOL_FINGER) { input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); @@ -2767,6 +2980,25 @@ static const struct wacom_features wacom_features_0x343 = 0, 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_0x34A = + { "Wacom MobileStudio Pro 13 Touch", WACOM_PKGLEN_MSPROT, .type = WACOM_MSPROT, /* Touch */ + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x34D }; +static const struct wacom_features wacom_features_0x34B = + { "Wacom MobileStudio Pro 16 Touch", WACOM_PKGLEN_MSPROT, .type = WACOM_MSPROT, /* Touch */ + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x34E }; +static const struct wacom_features wacom_features_0x34D = + { "Wacom MobileStudio Pro 13", WACOM_PKGLEN_MSPRO, 59552, 33848, 8191, 63, + WACOM_MSPRO, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 11, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x34A }; +static const struct wacom_features wacom_features_0x34E = + { "Wacom MobileStudio Pro 16", WACOM_PKGLEN_MSPRO, 69920, 39680, 8191, 63, + WACOM_MSPRO, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 13, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x34B }; + #define USB_DEVICE_WACOM(prod) \ USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ .driver_info = (kernel_ulong_t)&wacom_features_##prod @@ -2934,6 +3166,10 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_DETAILED(0x33D, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_DETAILED(0x33E, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_WACOM(0x343) }, + { USB_DEVICE_WACOM(0x34A) }, + { USB_DEVICE_WACOM(0x34B) }, + { USB_DEVICE_WACOM(0x34D) }, + { USB_DEVICE_WACOM(0x34E) }, { USB_DEVICE_LENOVO(0x6004) }, { } }; diff --git a/2.6.38/wacom_wac.h b/2.6.38/wacom_wac.h index cc34b0b..4caa2f5 100644 --- a/2.6.38/wacom_wac.h +++ b/2.6.38/wacom_wac.h @@ -35,11 +35,14 @@ #define WACOM_PKGLEN_DTUS 68 #define WACOM_PKGLEN_PENABLED 8 #define WACOM_PKGLEN_27QHDT 64 +#define WACOM_PKGLEN_MSPRO 64 +#define WACOM_PKGLEN_MSPROT 50 /* wacom data size per MT contact */ #define WACOM_BYTES_PER_MT_PACKET 11 #define WACOM_BYTES_PER_24HDT_PACKET 14 #define WACOM_BYTES_PER_QHDTHID_PACKET 6 +#define WACOM_BYTES_PER_MSPROT_PACKET 9 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -62,10 +65,13 @@ #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 #define WACOM_REPORT_CINTIQ 16 +#define WACOM_REPORT_MSPRO 16 #define WACOM_REPORT_INTUOS_PEN 16 #define WACOM_REPORT_CINTIQPAD 17 #define WACOM_REPORT_DTUS 17 +#define WACOM_REPORT_MSPROPAD 17 #define WACOM_REPORT_TPC1FGE 18 +#define WACOM_REPORT_MSPRODEVICE 19 #define WACOM_REPORT_24HDT 1 #define WACOM_REPORT_WL 128 #define WACOM_REPORT_USB 192 @@ -107,6 +113,7 @@ enum { WACOM_27QHD, CINTIQ_HYBRID, CINTIQ_COMPANION_2, + WACOM_MSPRO, CINTIQ, WACOM_BEE, WACOM_13HD, @@ -116,6 +123,7 @@ enum { BAMBOO_PT, WACOM_24HDT, WACOM_27QHDT, + WACOM_MSPROT, WIRELESS, REMOTE, TABLETPC, /* add new TPC below */ diff --git a/3.7/wacom_sys.c b/3.7/wacom_sys.c index 75d363e..d54c71a 100644 --- a/3.7/wacom_sys.c +++ b/3.7/wacom_sys.c @@ -386,6 +386,10 @@ static int wacom_parse_hid(struct usb_interface *intf, features->pktlen = WACOM_PKGLEN_BBTOUCH; break; + case WACOM_MSPROT: + features->pktlen = WACOM_PKGLEN_MSPROT; + break; + default: features->pktlen = WACOM_PKGLEN_GRAPHIRE; break; @@ -422,6 +426,7 @@ static int wacom_parse_hid(struct usb_interface *intf, i += 9; break; + case WACOM_MSPROT: case MTTPC_B: features->x_max = get_unaligned_le16(&report[i + 3]); @@ -492,6 +497,7 @@ static int wacom_parse_hid(struct usb_interface *intf, i += 12; break; + case WACOM_MSPROT: case MTTPC_B: features->y_max = get_unaligned_le16(&report[i + 3]); @@ -614,6 +620,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat else if (features->type == WACOM_27QHDT) { return wacom_set_device_mode(intf, 131, 3, 2); } + else if (features->type == WACOM_MSPROT) { + return wacom_set_device_mode(intf, 14, 2, 2); + } } else if (features->device_type == BTN_TOOL_PEN) { if (features->type <= BAMBOO_PT) { return wacom_set_device_mode(intf, 2, 2, 2); diff --git a/3.7/wacom_wac.c b/3.7/wacom_wac.c index 0ea1f27..458b03b 100644 --- a/3.7/wacom_wac.c +++ b/3.7/wacom_wac.c @@ -588,6 +588,7 @@ static int wacom_intuos_get_tool_type(int tool_id) break; case 0x82a: /* Eraser */ + case 0x84a: case 0x85a: case 0x91a: case 0xd1a: @@ -1084,6 +1085,53 @@ static int wacom_wac_finger_count_touches(struct wacom_wac *wacom) return count; } +static int wacom_msprot_irq(struct wacom_wac *wacom) +{ + struct input_dev *input = wacom->input; + unsigned char *data = wacom->data; + int i; + int current_num_contacts = data[2]; + int contacts_to_send = 0; + + if (current_num_contacts) + wacom->num_contacts_left = current_num_contacts; + + contacts_to_send = min(5, wacom->num_contacts_left); + + for (i = 0; i < contacts_to_send; i++) { + int offset = WACOM_BYTES_PER_MSPROT_PACKET * i + 3; + bool touch = (data[offset] & 0x1) && report_touch_events(wacom); + int id = get_unaligned_le16(&data[offset + 1]); + int slot = input_mt_get_slot_by_key(input, id); + + if (slot < 0) + continue; + + input_mt_slot(input, slot); + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + if (touch) { + int x = get_unaligned_le16(&data[offset + 3]); + int y = get_unaligned_le16(&data[offset + 5]); + int w = get_unaligned_le16(&data[offset + 7]); + int h = get_unaligned_le16(&data[offset + 9]); + input_report_abs(input, ABS_MT_POSITION_X, x); + input_report_abs(input, ABS_MT_POSITION_Y, y); + input_report_abs(input, ABS_MT_WIDTH_MAJOR, max(w, h)); + input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); + input_report_abs(input, ABS_MT_ORIENTATION, w > h); + } + } + + 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_mt_sync_frame(input); + return 1; +} + static int wacom_24hdt_irq(struct wacom_wac *wacom) { struct input_dev *input = wacom->input; @@ -1633,6 +1681,160 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len) return 0; } +static int wacom_mspro_device_irq(struct wacom_wac *wacom) +{ + struct wacom *w = container_of(wacom, struct wacom, wacom_wac); + struct wacom_features *features = &wacom->features; + unsigned char *data = wacom->data; + bool bat_charging; + int battery_level; + + battery_level = data[1] & 0x7F; + bat_charging = data[1] & 0x80; + + if (!w->battery.battery.dev && + !(features->quirks & WACOM_QUIRK_BATTERY)) { + features->quirks |= WACOM_QUIRK_BATTERY; + wacom_schedule_work(wacom, WACOM_WORKER_BATTERY); + } + + wacom_notify_battery(wacom, battery_level, bat_charging, 1, + bat_charging); + + return 0; +} + +static int wacom_mspro_pad_irq(struct wacom_wac *wacom) +{ + struct wacom_features *features = &wacom->features; + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + int nbuttons = features->numbered_buttons; + bool prox; + int buttons, ring; + + switch (nbuttons) { + case 11: + buttons = (data[1] >> 1) | (data[3] << 6); + break; + case 13: + buttons = data[1] | (data[3] << 8); + break; + default: + dev_warn(input->dev.parent, "%s: unsupported device #%d\n", __func__, data[0]); + return 0; + } + + ring = le16_to_cpup((__le16 *)&data[4]); + + prox = buttons || ring; + + wacom_report_numbered_buttons(input, nbuttons, buttons); + input_report_abs(input, ABS_WHEEL, (ring & 0x80) ? (ring & 0x7f) : 0); + + input_report_key(input, wacom->tool[1], prox ? 1 : 0); + input_report_abs(input, ABS_MISC, prox ? PAD_DEVICE_ID : 0); + + input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff); + + return 1; +} + +static int wacom_mspro_pen_irq(struct wacom_wac *wacom) +{ + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + bool tip, sw1, sw2, range, proximity; + unsigned int x, y; + unsigned int pressure; + int tilt_x, tilt_y; + int rotation; + unsigned int fingerwheel; + unsigned int height; + u64 tool_uid; + unsigned int tool_type; + + if (delay_pen_events(wacom)) + return 1; + + tip = data[1] & 0x01; + sw1 = data[1] & 0x02; + sw2 = data[1] & 0x04; + /* eraser = data[1] & 0x08; */ + /* invert = data[1] & 0x10; */ + range = data[1] & 0x20; + proximity = data[1] & 0x40; + x = le32_to_cpup((__le32 *)&data[2]) & 0xFFFFFF; + y = le32_to_cpup((__le32 *)&data[5]) & 0xFFFFFF; + pressure = le16_to_cpup((__le16 *)&data[8]); + tilt_x = data[10]; + tilt_y = data[11]; + rotation = le16_to_cpup((__le16 *)&data[12]); + fingerwheel = le16_to_cpup((__le16 *)&data[14]); + height = data[16]; + tool_uid = le64_to_cpup((__le64 *)&data[17]); + tool_type = le16_to_cpup((__le16 *)&data[25]); + + wacom->serial[0] = (tool_uid & 0xFFFFFFFF); + wacom->id[0] = (tool_uid >> 32) | tool_type; + if (range) { + wacom->tool[0] = wacom_intuos_get_tool_type(wacom->id[0] & 0xFFFFF); + } + + /* pointer going from fully "in range" to merely "in proximity" */ + if (!range && wacom->tool[0]) { + height = wacom->features.distance_max; + } + + /* + * only report data if there's a tool for userspace to associate + * the events with. + */ + if (wacom->tool[0]) { + input_report_key(input, BTN_TOUCH, tip); + input_report_key(input, BTN_STYLUS, sw1); + input_report_key(input, BTN_STYLUS2, sw2); + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + input_report_abs(input, ABS_PRESSURE, pressure); + input_report_abs(input, ABS_TILT_X, tilt_x); + input_report_abs(input, ABS_TILT_Y, tilt_y); + input_report_abs(input, ABS_Z, rotation); + input_report_abs(input, ABS_WHEEL, fingerwheel); + input_report_abs(input, ABS_DISTANCE, height); + input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[0]); + input_report_abs(input, ABS_MISC, wacom_intuos_id_mangle(wacom->id[0])); + input_report_key(input, wacom->tool[0], range ? 1 : 0); + + if (!range) + wacom->tool[0] = 0; + } + + wacom->shared->stylus_in_proximity = proximity; + + return 1; +} + +static int wacom_mspro_irq(struct wacom_wac *wacom) +{ + unsigned char *data = wacom->data; + struct input_dev *input = wacom->input; + + switch (data[0]) { + case WACOM_REPORT_MSPRO: + return wacom_mspro_pen_irq(wacom); + case WACOM_REPORT_MSPROPAD: + return wacom_mspro_pad_irq(wacom); + case WACOM_REPORT_MSPRODEVICE: + return wacom_mspro_device_irq(wacom); + default: + dev_dbg(input->dev.parent, + "%s: received unknown report #%d\n", __func__, data[0]); + break; + } + return 0; +} + void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) { bool sync; @@ -1685,6 +1887,14 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_intuos_irq(wacom_wac); break; + case WACOM_MSPRO: + sync = wacom_mspro_irq(wacom_wac); + break; + + case WACOM_MSPROT: + sync = wacom_msprot_irq(wacom_wac); + break; + case WACOM_24HDT: case WACOM_27QHDT: sync = wacom_24hdt_irq(wacom_wac); @@ -2003,6 +2213,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case WACOM_13HD: case CINTIQ_HYBRID: case CINTIQ_COMPANION_2: + case WACOM_MSPRO: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); /* fall through */ @@ -2093,6 +2304,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(INPUT_PROP_POINTER, input_dev->propbit); break; + case WACOM_MSPROT: case WACOM_24HDT: if (features->device_type == BTN_TOOL_FINGER) { input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); @@ -2724,6 +2936,24 @@ 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_0x34A = + { "Wacom MobileStudio Pro 13 Touch", WACOM_PKGLEN_MSPROT, .type = WACOM_MSPROT, /* Touch */ + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x34D }; +static const struct wacom_features wacom_features_0x34B = + { "Wacom MobileStudio Pro 16 Touch", WACOM_PKGLEN_MSPROT, .type = WACOM_MSPROT, /* Touch */ + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x34E }; +static const struct wacom_features wacom_features_0x34D = + { "Wacom MobileStudio Pro 13", WACOM_PKGLEN_MSPRO, 59552, 33848, 8191, 63, + WACOM_MSPRO, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 11, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x34A }; +static const struct wacom_features wacom_features_0x34E = + { "Wacom MobileStudio Pro 16", WACOM_PKGLEN_MSPRO, 69920, 39680, 8191, 63, + WACOM_MSPRO, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 13, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x34B }; #define USB_DEVICE_WACOM(prod) \ USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ @@ -2892,6 +3122,10 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_DETAILED(0x33D, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_DETAILED(0x33E, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_WACOM(0x343) }, + { USB_DEVICE_WACOM(0x34A) }, + { USB_DEVICE_WACOM(0x34B) }, + { USB_DEVICE_WACOM(0x34D) }, + { USB_DEVICE_WACOM(0x34E) }, { USB_DEVICE_LENOVO(0x6004) }, { } }; diff --git a/3.7/wacom_wac.h b/3.7/wacom_wac.h index 21fc30d..cb42c2e 100644 --- a/3.7/wacom_wac.h +++ b/3.7/wacom_wac.h @@ -35,11 +35,14 @@ #define WACOM_PKGLEN_DTUS 68 #define WACOM_PKGLEN_PENABLED 8 #define WACOM_PKGLEN_27QHDT 64 +#define WACOM_PKGLEN_MSPRO 64 +#define WACOM_PKGLEN_MSPROT 50 /* wacom data size per MT contact */ #define WACOM_BYTES_PER_MT_PACKET 11 #define WACOM_BYTES_PER_24HDT_PACKET 14 #define WACOM_BYTES_PER_QHDTHID_PACKET 6 +#define WACOM_BYTES_PER_MSPROT_PACKET 9 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -62,10 +65,13 @@ #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 #define WACOM_REPORT_CINTIQ 16 +#define WACOM_REPORT_MSPRO 16 #define WACOM_REPORT_INTUOS_PEN 16 #define WACOM_REPORT_CINTIQPAD 17 #define WACOM_REPORT_DTUS 17 +#define WACOM_REPORT_MSPROPAD 17 #define WACOM_REPORT_TPC1FGE 18 +#define WACOM_REPORT_MSPRODEVICE 19 #define WACOM_REPORT_24HDT 1 #define WACOM_REPORT_WL 128 #define WACOM_REPORT_USB 192 @@ -107,6 +113,7 @@ enum { WACOM_27QHD, CINTIQ_HYBRID, CINTIQ_COMPANION_2, + WACOM_MSPRO, CINTIQ, WACOM_BEE, WACOM_13HD, @@ -116,6 +123,7 @@ enum { BAMBOO_PT, WACOM_24HDT, WACOM_27QHDT, + WACOM_MSPROT, WIRELESS, REMOTE, TABLETPC, /* add new TPC below */ -- 2.10.2 ------------------------------------------------------------------------------ _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel