---
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel