|
@@ -34,6 +34,9 @@
|
|
|
*/
|
|
|
#define WACOM_CONTACT_AREA_SCALE 2607
|
|
|
|
|
|
+static void wacom_report_numbered_buttons(struct input_dev *input_dev,
|
|
|
+ int button_count, int mask);
|
|
|
+
|
|
|
/*
|
|
|
* Percent of battery capacity for Graphire.
|
|
|
* 8th value means AC online and show 100% capacity.
|
|
@@ -436,16 +439,142 @@ exit:
|
|
|
static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
|
|
|
{
|
|
|
struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
|
|
|
+ struct wacom_features *features = &wacom_wac->features;
|
|
|
struct hid_report *r;
|
|
|
struct hid_report_enum *re;
|
|
|
|
|
|
re = &(wacom->hdev->report_enum[HID_FEATURE_REPORT]);
|
|
|
- r = re->report_id_hash[WACOM_REPORT_INTUOSREAD];
|
|
|
+ if (features->type == INTUOSHT2)
|
|
|
+ r = re->report_id_hash[WACOM_REPORT_INTUOSHT2_ID];
|
|
|
+ else
|
|
|
+ r = re->report_id_hash[WACOM_REPORT_INTUOS_ID1];
|
|
|
if (r) {
|
|
|
hid_hw_request(wacom->hdev, r, HID_REQ_GET_REPORT);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static int wacom_intuos_pad(struct wacom_wac *wacom)
|
|
|
+{
|
|
|
+ struct wacom_features *features = &wacom->features;
|
|
|
+ unsigned char *data = wacom->data;
|
|
|
+ struct input_dev *input = wacom->pad_input;
|
|
|
+ int i;
|
|
|
+ int buttons = 0, nbuttons = features->numbered_buttons;
|
|
|
+ int keys = 0, nkeys = 0;
|
|
|
+ int ring1 = 0, ring2 = 0;
|
|
|
+ int strip1 = 0, strip2 = 0;
|
|
|
+ bool prox = false;
|
|
|
+
|
|
|
+ /* pad packets. Works as a second tool and is always in prox */
|
|
|
+ if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
|
|
|
+ data[0] == WACOM_REPORT_CINTIQPAD))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
|
|
|
+ buttons = (data[3] << 1) | (data[2] & 0x01);
|
|
|
+ ring1 = data[1];
|
|
|
+ } else if (features->type == DTK) {
|
|
|
+ buttons = data[6];
|
|
|
+ } else if (features->type == WACOM_13HD) {
|
|
|
+ buttons = (data[4] << 1) | (data[3] & 0x01);
|
|
|
+ } else if (features->type == WACOM_24HD) {
|
|
|
+ buttons = (data[8] << 8) | data[6];
|
|
|
+ ring1 = data[1];
|
|
|
+ ring2 = data[2];
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Three "buttons" are available on the 24HD which are
|
|
|
+ * physically implemented as a touchstrip. Each button
|
|
|
+ * is approximately 3 bits wide with a 2 bit spacing.
|
|
|
+ * The raw touchstrip bits are stored at:
|
|
|
+ * ((data[3] & 0x1f) << 8) | data[4])
|
|
|
+ */
|
|
|
+ nkeys = 3;
|
|
|
+ keys = ((data[3] & 0x1C) ? 1<<2 : 0) |
|
|
|
+ ((data[4] & 0xE0) ? 1<<1 : 0) |
|
|
|
+ ((data[4] & 0x07) ? 1<<0 : 0);
|
|
|
+ } else if (features->type == WACOM_27QHD) {
|
|
|
+ nkeys = 3;
|
|
|
+ keys = data[2] & 0x07;
|
|
|
+
|
|
|
+ input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4]));
|
|
|
+ input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6]));
|
|
|
+ input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8]));
|
|
|
+ } else if (features->type == CINTIQ_HYBRID) {
|
|
|
+ /*
|
|
|
+ * Do not send hardware buttons under Android. They
|
|
|
+ * are already sent to the system through GPIO (and
|
|
|
+ * have different meaning).
|
|
|
+ *
|
|
|
+ * d-pad right -> data[4] & 0x10
|
|
|
+ * d-pad up -> data[4] & 0x20
|
|
|
+ * d-pad left -> data[4] & 0x40
|
|
|
+ * d-pad down -> data[4] & 0x80
|
|
|
+ * d-pad center -> data[3] & 0x01
|
|
|
+ */
|
|
|
+ buttons = (data[4] << 1) | (data[3] & 0x01);
|
|
|
+ } else if (features->type == CINTIQ_COMPANION_2) {
|
|
|
+ /* d-pad right -> data[4] & 0x10
|
|
|
+ * d-pad up -> data[4] & 0x20
|
|
|
+ * d-pad left -> data[4] & 0x40
|
|
|
+ * d-pad down -> data[4] & 0x80
|
|
|
+ * d-pad center -> data[3] & 0x01
|
|
|
+ */
|
|
|
+ buttons = ((data[2] >> 4) << 7) |
|
|
|
+ ((data[1] & 0x04) << 6) |
|
|
|
+ ((data[2] & 0x0F) << 2) |
|
|
|
+ (data[1] & 0x03);
|
|
|
+ } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
|
|
|
+ /*
|
|
|
+ * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
|
|
|
+ * addition to the mechanical switch. Switch data is
|
|
|
+ * stored in data[4], capacitive data in data[5].
|
|
|
+ *
|
|
|
+ * Touch ring mode switch (data[3]) has no capacitive sensor
|
|
|
+ */
|
|
|
+ buttons = (data[4] << 1) | (data[3] & 0x01);
|
|
|
+ ring1 = data[2];
|
|
|
+ } else {
|
|
|
+ if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
|
|
|
+ buttons = (data[8] << 10) | ((data[7] & 0x01) << 9) |
|
|
|
+ (data[6] << 1) | (data[5] & 0x01);
|
|
|
+
|
|
|
+ if (features->type == WACOM_22HD) {
|
|
|
+ nkeys = 3;
|
|
|
+ keys = data[9] & 0x07;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ buttons = ((data[6] & 0x10) << 10) |
|
|
|
+ ((data[5] & 0x10) << 9) |
|
|
|
+ ((data[6] & 0x0F) << 4) |
|
|
|
+ (data[5] & 0x0F);
|
|
|
+ }
|
|
|
+ strip1 = ((data[1] & 0x1f) << 8) | data[2];
|
|
|
+ strip2 = ((data[3] & 0x1f) << 8) | data[4];
|
|
|
+ }
|
|
|
+
|
|
|
+ prox = (buttons & ~(~0 << nbuttons)) | (keys & ~(~0 << nkeys)) |
|
|
|
+ (ring1 & 0x80) | (ring2 & 0x80) | strip1 | strip2;
|
|
|
+
|
|
|
+ wacom_report_numbered_buttons(input, nbuttons, buttons);
|
|
|
+
|
|
|
+ for (i = 0; i < nkeys; i++)
|
|
|
+ input_report_key(input, KEY_PROG1 + i, keys & (1 << i));
|
|
|
+
|
|
|
+ input_report_abs(input, ABS_RX, strip1);
|
|
|
+ input_report_abs(input, ABS_RY, strip2);
|
|
|
+
|
|
|
+ input_report_abs(input, ABS_WHEEL, (ring1 & 0x80) ? (ring1 & 0x7f) : 0);
|
|
|
+ input_report_abs(input, ABS_THROTTLE, (ring2 & 0x80) ? (ring2 & 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_intuos_inout(struct wacom_wac *wacom)
|
|
|
{
|
|
|
struct wacom_features *features = &wacom->features;
|
|
@@ -755,19 +884,40 @@ static int wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void wacom_intuos_general(struct wacom_wac *wacom)
|
|
|
+static int wacom_intuos_general(struct wacom_wac *wacom)
|
|
|
{
|
|
|
struct wacom_features *features = &wacom->features;
|
|
|
unsigned char *data = wacom->data;
|
|
|
struct input_dev *input = wacom->pen_input;
|
|
|
- unsigned int t;
|
|
|
+ int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0;
|
|
|
+ unsigned char type = (data[1] >> 1) & 0x0F;
|
|
|
+ unsigned int x, y, distance, t;
|
|
|
|
|
|
- /* general pen packet */
|
|
|
- if ((data[1] & 0xb8) == 0xa0) {
|
|
|
- t = (data[6] << 2) | ((data[7] >> 6) & 3);
|
|
|
- if (features->pressure_max == 2047) {
|
|
|
- t = (t << 1) | (data[1] & 1);
|
|
|
- }
|
|
|
+ if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_CINTIQ &&
|
|
|
+ data[0] != WACOM_REPORT_INTUOS_PEN)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1);
|
|
|
+ y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1);
|
|
|
+ distance = data[9] >> 2;
|
|
|
+ if (features->type < INTUOS3S) {
|
|
|
+ x >>= 1;
|
|
|
+ y >>= 1;
|
|
|
+ distance >>= 1;
|
|
|
+ }
|
|
|
+ input_report_abs(input, ABS_X, x);
|
|
|
+ input_report_abs(input, ABS_Y, y);
|
|
|
+ input_report_abs(input, ABS_DISTANCE, distance);
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ case 0x00:
|
|
|
+ case 0x01:
|
|
|
+ case 0x02:
|
|
|
+ case 0x03:
|
|
|
+ /* general pen packet */
|
|
|
+ t = (data[6] << 3) | ((data[7] & 0xC0) >> 5) | (data[1] & 1);
|
|
|
+ if (features->pressure_max < 2047)
|
|
|
+ t >>= 1;
|
|
|
input_report_abs(input, ABS_PRESSURE, t);
|
|
|
if (features->type != INTUOSHT2) {
|
|
|
input_report_abs(input, ABS_TILT_X,
|
|
@@ -777,29 +927,112 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
|
|
|
input_report_key(input, BTN_STYLUS, data[1] & 2);
|
|
|
input_report_key(input, BTN_STYLUS2, data[1] & 4);
|
|
|
input_report_key(input, BTN_TOUCH, t > 10);
|
|
|
- }
|
|
|
+ break;
|
|
|
|
|
|
- /* airbrush second packet */
|
|
|
- if ((data[1] & 0xbc) == 0xb4) {
|
|
|
+ case 0x0a:
|
|
|
+ /* airbrush second packet */
|
|
|
input_report_abs(input, ABS_WHEEL,
|
|
|
(data[6] << 2) | ((data[7] >> 6) & 3));
|
|
|
input_report_abs(input, ABS_TILT_X,
|
|
|
(((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
|
|
|
input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 0x05:
|
|
|
+ /* Rotation packet */
|
|
|
+ if (features->type >= INTUOS3S) {
|
|
|
+ /* I3 marker pen rotation */
|
|
|
+ t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
|
|
+ t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
|
|
|
+ ((t-1) / 2 + 450)) : (450 - t / 2) ;
|
|
|
+ input_report_abs(input, ABS_Z, t);
|
|
|
+ } else {
|
|
|
+ /* 4D mouse 2nd packet */
|
|
|
+ t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
|
|
+ input_report_abs(input, ABS_RZ, (data[7] & 0x20) ?
|
|
|
+ ((t - 1) / 2) : -t / 2);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 0x04:
|
|
|
+ /* 4D mouse 1st packet */
|
|
|
+ input_report_key(input, BTN_LEFT, data[8] & 0x01);
|
|
|
+ input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
|
|
|
+ input_report_key(input, BTN_RIGHT, data[8] & 0x04);
|
|
|
+
|
|
|
+ input_report_key(input, BTN_SIDE, data[8] & 0x20);
|
|
|
+ input_report_key(input, BTN_EXTRA, data[8] & 0x10);
|
|
|
+ t = (data[6] << 2) | ((data[7] >> 6) & 3);
|
|
|
+ input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 0x06:
|
|
|
+ /* I4 mouse */
|
|
|
+ input_report_key(input, BTN_LEFT, data[6] & 0x01);
|
|
|
+ input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
|
|
|
+ input_report_key(input, BTN_RIGHT, data[6] & 0x04);
|
|
|
+ input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7)
|
|
|
+ - ((data[7] & 0x40) >> 6));
|
|
|
+ input_report_key(input, BTN_SIDE, data[6] & 0x08);
|
|
|
+ input_report_key(input, BTN_EXTRA, data[6] & 0x10);
|
|
|
+
|
|
|
+ input_report_abs(input, ABS_TILT_X,
|
|
|
+ (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
|
|
|
+ input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 0x08:
|
|
|
+ if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
|
|
|
+ /* 2D mouse packet */
|
|
|
+ input_report_key(input, BTN_LEFT, data[8] & 0x04);
|
|
|
+ input_report_key(input, BTN_MIDDLE, data[8] & 0x08);
|
|
|
+ input_report_key(input, BTN_RIGHT, data[8] & 0x10);
|
|
|
+ input_report_rel(input, REL_WHEEL, (data[8] & 0x01)
|
|
|
+ - ((data[8] & 0x02) >> 1));
|
|
|
+
|
|
|
+ /* I3 2D mouse side buttons */
|
|
|
+ if (features->type >= INTUOS3S && features->type <= INTUOS3L) {
|
|
|
+ input_report_key(input, BTN_SIDE, data[8] & 0x40);
|
|
|
+ input_report_key(input, BTN_EXTRA, data[8] & 0x20);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (wacom->tool[idx] == BTN_TOOL_LENS) {
|
|
|
+ /* Lens cursor packets */
|
|
|
+ input_report_key(input, BTN_LEFT, data[8] & 0x01);
|
|
|
+ input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
|
|
|
+ input_report_key(input, BTN_RIGHT, data[8] & 0x04);
|
|
|
+ input_report_key(input, BTN_SIDE, data[8] & 0x10);
|
|
|
+ input_report_key(input, BTN_EXTRA, data[8] & 0x08);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 0x07:
|
|
|
+ case 0x09:
|
|
|
+ case 0x0b:
|
|
|
+ case 0x0c:
|
|
|
+ case 0x0d:
|
|
|
+ case 0x0e:
|
|
|
+ case 0x0f:
|
|
|
+ /* unhandled */
|
|
|
+ break;
|
|
|
}
|
|
|
+
|
|
|
+ input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
|
|
|
+ input_report_key(input, wacom->tool[idx], 1);
|
|
|
+ input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
|
|
|
+ wacom->reporting_data = true;
|
|
|
+ return 2;
|
|
|
}
|
|
|
|
|
|
static int wacom_intuos_irq(struct wacom_wac *wacom)
|
|
|
{
|
|
|
- struct wacom_features *features = &wacom->features;
|
|
|
unsigned char *data = wacom->data;
|
|
|
struct input_dev *input = wacom->pen_input;
|
|
|
- unsigned int t;
|
|
|
- int idx = 0, result;
|
|
|
+ int result;
|
|
|
|
|
|
if (data[0] != WACOM_REPORT_PENABLED &&
|
|
|
- data[0] != WACOM_REPORT_INTUOSREAD &&
|
|
|
- data[0] != WACOM_REPORT_INTUOSWRITE &&
|
|
|
+ data[0] != WACOM_REPORT_INTUOS_ID1 &&
|
|
|
+ data[0] != WACOM_REPORT_INTUOS_ID2 &&
|
|
|
data[0] != WACOM_REPORT_INTUOSPAD &&
|
|
|
data[0] != WACOM_REPORT_INTUOS_PEN &&
|
|
|
data[0] != WACOM_REPORT_CINTIQ &&
|
|
@@ -810,339 +1043,22 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- /* tool number */
|
|
|
- if (features->type == INTUOS)
|
|
|
- idx = data[1] & 0x01;
|
|
|
-
|
|
|
- /* pad packets. Works as a second tool and is always in prox */
|
|
|
- if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
|
|
|
- data[0] == WACOM_REPORT_CINTIQPAD) {
|
|
|
- input = wacom->pad_input;
|
|
|
- if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
|
|
|
- input_report_key(input, BTN_0, (data[2] & 0x01));
|
|
|
- input_report_key(input, BTN_1, (data[3] & 0x01));
|
|
|
- input_report_key(input, BTN_2, (data[3] & 0x02));
|
|
|
- input_report_key(input, BTN_3, (data[3] & 0x04));
|
|
|
- input_report_key(input, BTN_4, (data[3] & 0x08));
|
|
|
- input_report_key(input, BTN_5, (data[3] & 0x10));
|
|
|
- input_report_key(input, BTN_6, (data[3] & 0x20));
|
|
|
- if (data[1] & 0x80) {
|
|
|
- input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
|
|
|
- } else {
|
|
|
- /* Out of proximity, clear wheel value. */
|
|
|
- input_report_abs(input, ABS_WHEEL, 0);
|
|
|
- }
|
|
|
- if (features->type != INTUOS4S) {
|
|
|
- input_report_key(input, BTN_7, (data[3] & 0x40));
|
|
|
- input_report_key(input, BTN_8, (data[3] & 0x80));
|
|
|
- }
|
|
|
- if (data[1] | (data[2] & 0x01) | data[3]) {
|
|
|
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
|
|
- } else {
|
|
|
- input_report_abs(input, ABS_MISC, 0);
|
|
|
- }
|
|
|
- } else if (features->type == DTK) {
|
|
|
- input_report_key(input, BTN_0, (data[6] & 0x01));
|
|
|
- input_report_key(input, BTN_1, (data[6] & 0x02));
|
|
|
- input_report_key(input, BTN_2, (data[6] & 0x04));
|
|
|
- input_report_key(input, BTN_3, (data[6] & 0x08));
|
|
|
- input_report_key(input, BTN_4, (data[6] & 0x10));
|
|
|
- input_report_key(input, BTN_5, (data[6] & 0x20));
|
|
|
- if (data[6] & 0x3f) {
|
|
|
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
|
|
- } else {
|
|
|
- input_report_abs(input, ABS_MISC, 0);
|
|
|
- }
|
|
|
- } else if (features->type == WACOM_13HD) {
|
|
|
- input_report_key(input, BTN_0, (data[3] & 0x01));
|
|
|
- input_report_key(input, BTN_1, (data[4] & 0x01));
|
|
|
- input_report_key(input, BTN_2, (data[4] & 0x02));
|
|
|
- input_report_key(input, BTN_3, (data[4] & 0x04));
|
|
|
- input_report_key(input, BTN_4, (data[4] & 0x08));
|
|
|
- input_report_key(input, BTN_5, (data[4] & 0x10));
|
|
|
- input_report_key(input, BTN_6, (data[4] & 0x20));
|
|
|
- input_report_key(input, BTN_7, (data[4] & 0x40));
|
|
|
- input_report_key(input, BTN_8, (data[4] & 0x80));
|
|
|
- if ((data[3] & 0x01) | data[4]) {
|
|
|
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
|
|
- } else {
|
|
|
- input_report_abs(input, ABS_MISC, 0);
|
|
|
- }
|
|
|
- } else if (features->type == WACOM_24HD) {
|
|
|
- input_report_key(input, BTN_0, (data[6] & 0x01));
|
|
|
- input_report_key(input, BTN_1, (data[6] & 0x02));
|
|
|
- input_report_key(input, BTN_2, (data[6] & 0x04));
|
|
|
- input_report_key(input, BTN_3, (data[6] & 0x08));
|
|
|
- input_report_key(input, BTN_4, (data[6] & 0x10));
|
|
|
- input_report_key(input, BTN_5, (data[6] & 0x20));
|
|
|
- input_report_key(input, BTN_6, (data[6] & 0x40));
|
|
|
- input_report_key(input, BTN_7, (data[6] & 0x80));
|
|
|
- input_report_key(input, BTN_8, (data[8] & 0x01));
|
|
|
- input_report_key(input, BTN_9, (data[8] & 0x02));
|
|
|
- input_report_key(input, BTN_A, (data[8] & 0x04));
|
|
|
- input_report_key(input, BTN_B, (data[8] & 0x08));
|
|
|
- input_report_key(input, BTN_C, (data[8] & 0x10));
|
|
|
- input_report_key(input, BTN_X, (data[8] & 0x20));
|
|
|
- input_report_key(input, BTN_Y, (data[8] & 0x40));
|
|
|
- input_report_key(input, BTN_Z, (data[8] & 0x80));
|
|
|
-
|
|
|
- /*
|
|
|
- * Three "buttons" are available on the 24HD which are
|
|
|
- * physically implemented as a touchstrip. Each button
|
|
|
- * is approximately 3 bits wide with a 2 bit spacing.
|
|
|
- * The raw touchstrip bits are stored at:
|
|
|
- * ((data[3] & 0x1f) << 8) | data[4])
|
|
|
- */
|
|
|
- input_report_key(input, KEY_PROG1, data[4] & 0x07);
|
|
|
- input_report_key(input, KEY_PROG2, data[4] & 0xE0);
|
|
|
- input_report_key(input, KEY_PROG3, data[3] & 0x1C);
|
|
|
-
|
|
|
- if (data[1] & 0x80) {
|
|
|
- input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
|
|
|
- } else {
|
|
|
- /* Out of proximity, clear wheel value. */
|
|
|
- input_report_abs(input, ABS_WHEEL, 0);
|
|
|
- }
|
|
|
-
|
|
|
- if (data[2] & 0x80) {
|
|
|
- input_report_abs(input, ABS_THROTTLE, (data[2] & 0x7f));
|
|
|
- } else {
|
|
|
- /* Out of proximity, clear second wheel value. */
|
|
|
- input_report_abs(input, ABS_THROTTLE, 0);
|
|
|
- }
|
|
|
-
|
|
|
- if (data[1] | data[2] | (data[3] & 0x1f) | data[4] | data[6] | data[8]) {
|
|
|
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
|
|
- } else {
|
|
|
- input_report_abs(input, ABS_MISC, 0);
|
|
|
- }
|
|
|
- } else if (features->type == WACOM_27QHD) {
|
|
|
- input_report_key(input, KEY_PROG1, data[2] & 0x01);
|
|
|
- input_report_key(input, KEY_PROG2, data[2] & 0x02);
|
|
|
- input_report_key(input, KEY_PROG3, data[2] & 0x04);
|
|
|
-
|
|
|
- input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4]));
|
|
|
- input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6]));
|
|
|
- input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8]));
|
|
|
- if ((data[2] & 0x07) | data[4] | data[5] | data[6] | data[7] | data[8] | data[9]) {
|
|
|
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
|
|
- } else {
|
|
|
- input_report_abs(input, ABS_MISC, 0);
|
|
|
- }
|
|
|
- } else if (features->type == CINTIQ_HYBRID) {
|
|
|
- /*
|
|
|
- * Do not send hardware buttons under Android. They
|
|
|
- * are already sent to the system through GPIO (and
|
|
|
- * have different meaning).
|
|
|
- */
|
|
|
- input_report_key(input, BTN_1, (data[4] & 0x01));
|
|
|
- input_report_key(input, BTN_2, (data[4] & 0x02));
|
|
|
- input_report_key(input, BTN_3, (data[4] & 0x04));
|
|
|
- input_report_key(input, BTN_4, (data[4] & 0x08));
|
|
|
-
|
|
|
- input_report_key(input, BTN_5, (data[4] & 0x10)); /* Right */
|
|
|
- input_report_key(input, BTN_6, (data[4] & 0x20)); /* Up */
|
|
|
- input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left */
|
|
|
- input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down */
|
|
|
- input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */
|
|
|
-
|
|
|
- if (data[4] | (data[3] & 0x01)) {
|
|
|
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
|
|
- } else {
|
|
|
- input_report_abs(input, ABS_MISC, 0);
|
|
|
- }
|
|
|
-
|
|
|
- } else if (features->type == CINTIQ_COMPANION_2) {
|
|
|
- input_report_key(input, BTN_1, (data[1] & 0x02));
|
|
|
- input_report_key(input, BTN_2, (data[2] & 0x01));
|
|
|
- input_report_key(input, BTN_3, (data[2] & 0x02));
|
|
|
- input_report_key(input, BTN_4, (data[2] & 0x04));
|
|
|
- input_report_key(input, BTN_5, (data[2] & 0x08));
|
|
|
- input_report_key(input, BTN_6, (data[1] & 0x04));
|
|
|
-
|
|
|
- input_report_key(input, BTN_7, (data[2] & 0x10)); /* Right */
|
|
|
- input_report_key(input, BTN_8, (data[2] & 0x20)); /* Up */
|
|
|
- input_report_key(input, BTN_9, (data[2] & 0x40)); /* Left */
|
|
|
- input_report_key(input, BTN_A, (data[2] & 0x80)); /* Down */
|
|
|
- input_report_key(input, BTN_0, (data[1] & 0x01)); /* Center */
|
|
|
-
|
|
|
- if (data[2] | (data[1] & 0x07)) {
|
|
|
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
|
|
- } else {
|
|
|
- input_report_abs(input, ABS_MISC, 0);
|
|
|
- }
|
|
|
-
|
|
|
- } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
|
|
|
- int i;
|
|
|
-
|
|
|
- /* Touch ring mode switch has no capacitive sensor */
|
|
|
- input_report_key(input, BTN_0, (data[3] & 0x01));
|
|
|
-
|
|
|
- /*
|
|
|
- * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
|
|
|
- * addition to the mechanical switch. Switch data is
|
|
|
- * stored in data[4], capacitive data in data[5].
|
|
|
- */
|
|
|
- for (i = 0; i < 8; i++)
|
|
|
- input_report_key(input, BTN_1 + i, data[4] & (1 << i));
|
|
|
-
|
|
|
- if (data[2] & 0x80) {
|
|
|
- input_report_abs(input, ABS_WHEEL, (data[2] & 0x7f));
|
|
|
- } else {
|
|
|
- /* Out of proximity, clear wheel value. */
|
|
|
- input_report_abs(input, ABS_WHEEL, 0);
|
|
|
- }
|
|
|
-
|
|
|
- if (data[2] | (data[3] & 0x01) | data[4] | data[5]) {
|
|
|
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
|
|
- } else {
|
|
|
- input_report_abs(input, ABS_MISC, 0);
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
|
|
|
- input_report_key(input, BTN_0, (data[5] & 0x01));
|
|
|
- input_report_key(input, BTN_1, (data[6] & 0x01));
|
|
|
- input_report_key(input, BTN_2, (data[6] & 0x02));
|
|
|
- input_report_key(input, BTN_3, (data[6] & 0x04));
|
|
|
- input_report_key(input, BTN_4, (data[6] & 0x08));
|
|
|
- input_report_key(input, BTN_5, (data[6] & 0x10));
|
|
|
- input_report_key(input, BTN_6, (data[6] & 0x20));
|
|
|
- input_report_key(input, BTN_7, (data[6] & 0x40));
|
|
|
- input_report_key(input, BTN_8, (data[6] & 0x80));
|
|
|
- input_report_key(input, BTN_9, (data[7] & 0x01));
|
|
|
- input_report_key(input, BTN_A, (data[8] & 0x01));
|
|
|
- input_report_key(input, BTN_B, (data[8] & 0x02));
|
|
|
- input_report_key(input, BTN_C, (data[8] & 0x04));
|
|
|
- input_report_key(input, BTN_X, (data[8] & 0x08));
|
|
|
- input_report_key(input, BTN_Y, (data[8] & 0x10));
|
|
|
- input_report_key(input, BTN_Z, (data[8] & 0x20));
|
|
|
- input_report_key(input, BTN_BASE, (data[8] & 0x40));
|
|
|
- input_report_key(input, BTN_BASE2, (data[8] & 0x80));
|
|
|
-
|
|
|
- if (features->type == WACOM_22HD) {
|
|
|
- input_report_key(input, KEY_PROG1, data[9] & 0x01);
|
|
|
- input_report_key(input, KEY_PROG2, data[9] & 0x02);
|
|
|
- input_report_key(input, KEY_PROG3, data[9] & 0x04);
|
|
|
- }
|
|
|
- } else {
|
|
|
- input_report_key(input, BTN_0, (data[5] & 0x01));
|
|
|
- input_report_key(input, BTN_1, (data[5] & 0x02));
|
|
|
- input_report_key(input, BTN_2, (data[5] & 0x04));
|
|
|
- input_report_key(input, BTN_3, (data[5] & 0x08));
|
|
|
- input_report_key(input, BTN_4, (data[6] & 0x01));
|
|
|
- input_report_key(input, BTN_5, (data[6] & 0x02));
|
|
|
- input_report_key(input, BTN_6, (data[6] & 0x04));
|
|
|
- input_report_key(input, BTN_7, (data[6] & 0x08));
|
|
|
- input_report_key(input, BTN_8, (data[5] & 0x10));
|
|
|
- input_report_key(input, BTN_9, (data[6] & 0x10));
|
|
|
- }
|
|
|
- input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
|
|
|
- input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
|
|
|
-
|
|
|
- if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
|
|
|
- data[2] | (data[3] & 0x1f) | data[4] | data[8] |
|
|
|
- (data[7] & 0x01)) {
|
|
|
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
|
|
- } else {
|
|
|
- input_report_abs(input, ABS_MISC, 0);
|
|
|
- }
|
|
|
- }
|
|
|
- return 1;
|
|
|
- }
|
|
|
+ /* process pad events */
|
|
|
+ result = wacom_intuos_pad(wacom);
|
|
|
+ if (result)
|
|
|
+ return result;
|
|
|
|
|
|
/* process in/out prox events */
|
|
|
result = wacom_intuos_inout(wacom);
|
|
|
if (result)
|
|
|
- return result - 1;
|
|
|
-
|
|
|
- if (features->type >= INTUOS3S) {
|
|
|
- input_report_abs(input, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
|
|
|
- input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
|
|
|
- input_report_abs(input, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
|
|
|
- } else {
|
|
|
- input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[2]));
|
|
|
- input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[4]));
|
|
|
- input_report_abs(input, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
|
|
|
- }
|
|
|
+ return result - 1;
|
|
|
|
|
|
/* process general packets */
|
|
|
- wacom_intuos_general(wacom);
|
|
|
-
|
|
|
- /* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */
|
|
|
- if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) {
|
|
|
-
|
|
|
- if (data[1] & 0x02) {
|
|
|
- /* Rotation packet */
|
|
|
- if (features->type >= INTUOS3S) {
|
|
|
- /* I3 marker pen rotation */
|
|
|
- t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
|
|
- t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
|
|
|
- ((t-1) / 2 + 450)) : (450 - t / 2) ;
|
|
|
- input_report_abs(input, ABS_Z, t);
|
|
|
- } else {
|
|
|
- /* 4D mouse rotation packet */
|
|
|
- t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
|
|
- input_report_abs(input, ABS_RZ, (data[7] & 0x20) ?
|
|
|
- ((t - 1) / 2) : -t / 2);
|
|
|
- }
|
|
|
-
|
|
|
- } else if (!(data[1] & 0x10) && features->type < INTUOS3S) {
|
|
|
- /* 4D mouse packet */
|
|
|
- input_report_key(input, BTN_LEFT, data[8] & 0x01);
|
|
|
- input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
|
|
|
- input_report_key(input, BTN_RIGHT, data[8] & 0x04);
|
|
|
-
|
|
|
- input_report_key(input, BTN_SIDE, data[8] & 0x20);
|
|
|
- input_report_key(input, BTN_EXTRA, data[8] & 0x10);
|
|
|
- t = (data[6] << 2) | ((data[7] >> 6) & 3);
|
|
|
- input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
|
|
|
-
|
|
|
- } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
|
|
|
- /* I4 mouse */
|
|
|
- if (features->type >= INTUOS4S && features->type <= INTUOSPL) {
|
|
|
- input_report_key(input, BTN_LEFT, data[6] & 0x01);
|
|
|
- input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
|
|
|
- input_report_key(input, BTN_RIGHT, data[6] & 0x04);
|
|
|
- input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7)
|
|
|
- - ((data[7] & 0x40) >> 6));
|
|
|
- input_report_key(input, BTN_SIDE, data[6] & 0x08);
|
|
|
- input_report_key(input, BTN_EXTRA, data[6] & 0x10);
|
|
|
-
|
|
|
- input_report_abs(input, ABS_TILT_X,
|
|
|
- (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
|
|
|
- input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
|
|
|
- } else {
|
|
|
- /* 2D mouse packet */
|
|
|
- input_report_key(input, BTN_LEFT, data[8] & 0x04);
|
|
|
- input_report_key(input, BTN_MIDDLE, data[8] & 0x08);
|
|
|
- input_report_key(input, BTN_RIGHT, data[8] & 0x10);
|
|
|
- input_report_rel(input, REL_WHEEL, (data[8] & 0x01)
|
|
|
- - ((data[8] & 0x02) >> 1));
|
|
|
-
|
|
|
- /* I3 2D mouse side buttons */
|
|
|
- if (features->type >= INTUOS3S && features->type <= INTUOS3L) {
|
|
|
- input_report_key(input, BTN_SIDE, data[8] & 0x40);
|
|
|
- input_report_key(input, BTN_EXTRA, data[8] & 0x20);
|
|
|
- }
|
|
|
- }
|
|
|
- } else if ((features->type < INTUOS3S || features->type == INTUOS3L ||
|
|
|
- features->type == INTUOS4L || features->type == INTUOS5L ||
|
|
|
- features->type == INTUOSPL) &&
|
|
|
- wacom->tool[idx] == BTN_TOOL_LENS) {
|
|
|
- /* Lens cursor packets */
|
|
|
- input_report_key(input, BTN_LEFT, data[8] & 0x01);
|
|
|
- input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
|
|
|
- input_report_key(input, BTN_RIGHT, data[8] & 0x04);
|
|
|
- input_report_key(input, BTN_SIDE, data[8] & 0x10);
|
|
|
- input_report_key(input, BTN_EXTRA, data[8] & 0x08);
|
|
|
- }
|
|
|
- }
|
|
|
+ result = wacom_intuos_general(wacom);
|
|
|
+ if (result)
|
|
|
+ return result - 1;
|
|
|
|
|
|
- input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
|
|
|
- input_report_key(input, wacom->tool[idx], 1);
|
|
|
- input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
|
|
|
- wacom->reporting_data = true;
|
|
|
- return 1;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int int_dist(int x1, int y1, int x2, int y2)
|
|
@@ -2509,7 +2425,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)
|
|
|
features->quirks |= WACOM_QUIRK_BATTERY;
|
|
|
|
|
|
/* quirk for bamboo touch with 2 low res touches */
|
|
|
- if (features->type == BAMBOO_PT &&
|
|
|
+ if ((features->type == BAMBOO_PT || features->type == BAMBOO_TOUCH) &&
|
|
|
features->pktlen == WACOM_PKGLEN_BBTOUCH) {
|
|
|
features->x_max <<= 5;
|
|
|
features->y_max <<= 5;
|
|
@@ -2806,6 +2722,19 @@ static void wacom_setup_numbered_buttons(struct input_dev *input_dev,
|
|
|
__set_bit(BTN_BASE + (i-16), input_dev->keybit);
|
|
|
}
|
|
|
|
|
|
+static void wacom_report_numbered_buttons(struct input_dev *input_dev,
|
|
|
+ int button_count, int mask)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < button_count && i < 10; i++)
|
|
|
+ input_report_key(input_dev, BTN_0 + i, mask & (1 << i));
|
|
|
+ for (i = 10; i < button_count && i < 16; i++)
|
|
|
+ input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i));
|
|
|
+ for (i = 16; i < button_count && i < 18; i++)
|
|
|
+ input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i));
|
|
|
+}
|
|
|
+
|
|
|
int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
|
|
|
struct wacom_wac *wacom_wac)
|
|
|
{
|