in wacom_wac.c [475:634]
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;
bool wrench = false, keyboard = false, mute_touch = false, menu = false,
info = 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);
keyboard = !!(data[4] & 0xE0);
info = !!(data[3] & 0x1C);
if (features->oPid) {
mute_touch = !!(data[4] & 0x07);
if (mute_touch)
wacom->shared->is_touch_on =
!wacom->shared->is_touch_on;
} else {
wrench = !!(data[4] & 0x07);
}
} else if (features->type == WACOM_27QHD) {
nkeys = 3;
keys = data[2] & 0x07;
wrench = !!(data[2] & 0x01);
keyboard = !!(data[2] & 0x02);
if (features->oPid) {
mute_touch = !!(data[2] & 0x04);
if (mute_touch)
wacom->shared->is_touch_on =
!wacom->shared->is_touch_on;
} else {
menu = !!(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]));
} 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[2] & 0x10
* d-pad up -> data[2] & 0x20
* d-pad left -> data[2] & 0x40
* d-pad down -> data[2] & 0x80
* d-pad center -> data[1] & 0x01
*/
buttons = ((data[2] >> 4) << 7) |
((data[1] & 0x04) << 4) |
((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;
info = !!(data[9] & 0x01);
wrench = !!(data[9] & 0x02);
}
} else {
buttons = ((data[6] & 0x10) << 5) |
((data[5] & 0x10) << 4) |
((data[6] & 0x0F) << 4) |
(data[5] & 0x0F);
}
strip1 = ((data[1] & 0x1f) << 8) | data[2];
strip2 = ((data[3] & 0x1f) << 8) | data[4];
}
prox = (buttons & ~(~0U << nbuttons)) | (keys & ~(~0U << 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_key(input, KEY_BUTTONCONFIG, wrench);
input_report_key(input, KEY_ONSCREEN_KEYBOARD, keyboard);
input_report_key(input, KEY_CONTROLPANEL, menu);
input_report_key(input, KEY_INFO, info);
if (wacom->shared && wacom->shared->touch_input) {
input_report_switch(wacom->shared->touch_input,
SW_MUTE_DEVICE,
!wacom->shared->is_touch_on);
input_sync(wacom->shared->touch_input);
}
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;
}