diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 4790110..77bf355 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -412,70 +412,86 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, struct input_dev *dev = psmouse->dev; struct elantech_data *etd = psmouse->private; unsigned char *packet = psmouse->packet; - unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; + static unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; unsigned int width = 0, pres = 0; + int rel_x = 0, rel_y = 0; - /* byte 0: n1 n0 . . . . R L */ - fingers = (packet[0] & 0xc0) >> 6; - switch (fingers) { - case 3: - case 1: - /* - * byte 1: . . . . x11 x10 x9 x8 - * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 - */ - x1 = ((packet[1] & 0x0f) << 8) | packet[2]; - /* - * byte 4: . . . . y11 y10 y9 y8 - * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 - */ - y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); - break; + if(packet_type == PACKET_V3_TRACKPOINT) { + rel_x = (packet[1] & 0x80) == 0x80 ? packet[4] : packet[4]-255; + rel_y = (packet[2] & 0x80) == 0x80 ? -packet[5] : 255-packet[5]; - case 2: - if (packet_type == PACKET_V3_HEAD) { - /* - * byte 1: . . . . ax11 ax10 ax9 ax8 - * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 - */ - etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; + input_report_key(dev, BTN_LEFT, packet[0] & 0x01); + input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); + input_report_key(dev, BTN_MIDDLE, packet[0] & 0x04); + + input_report_rel(dev, REL_X, rel_x); + input_report_rel(dev, REL_Y, rel_y); + } else { + /* byte 0: n1 n0 . . . . R L */ + fingers = (packet[0] & 0xc0) >> 6; + + switch (fingers) { + case 3: + case 1: /* - * byte 4: . . . . ay11 ay10 ay9 ay8 - * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 + * byte 1: . . . . x11 x10 x9 x8 + * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 */ - etd->mt[0].y = etd->y_max - - (((packet[4] & 0x0f) << 8) | packet[5]); + x1 = ((packet[1] & 0x0f) << 8) | packet[2]; /* - * wait for next packet + * byte 4: . . . . y11 y10 y9 y8 + * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 */ - return; + y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); + break; + + case 2: + if (packet_type == PACKET_V3_HEAD) { + /* + * byte 1: . . . . ax11 ax10 ax9 ax8 + * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 + */ + etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; + /* + * byte 4: . . . . ay11 ay10 ay9 ay8 + * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 + */ + etd->mt[0].y = etd->y_max - + (((packet[4] & 0x0f) << 8) | packet[5]); + /* + * wait for next packet + */ + return; + } + + /* packet_type == PACKET_V3_TAIL */ + x1 = etd->mt[0].x; + y1 = etd->mt[0].y; + x2 = ((packet[1] & 0x0f) << 8) | packet[2]; + y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); + break; } - /* packet_type == PACKET_V3_TAIL */ - x1 = etd->mt[0].x; - y1 = etd->mt[0].y; - x2 = ((packet[1] & 0x0f) << 8) | packet[2]; - y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); - break; - } + pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); + width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); - pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); - width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); + input_report_key(dev, BTN_TOUCH, fingers != 0); + if (fingers != 0) { + input_report_abs(dev, ABS_X, x1); + input_report_abs(dev, ABS_Y, y1); + } + elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); + input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); + input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); + input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); - input_report_key(dev, BTN_TOUCH, fingers != 0); - if (fingers != 0) { - input_report_abs(dev, ABS_X, x1); - input_report_abs(dev, ABS_Y, y1); + input_report_key(dev, BTN_LEFT, packet[0] & 0x01); + input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); + + input_report_abs(dev, ABS_PRESSURE, pres); + input_report_abs(dev, ABS_TOOL_WIDTH, width); } - elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); - input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); - input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); - input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); - input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - input_report_abs(dev, ABS_PRESSURE, pres); - input_report_abs(dev, ABS_TOOL_WIDTH, width); input_sync(dev); } @@ -688,6 +704,10 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) return PACKET_V3_TAIL; + if((packet[3] & 0x06) == 0x06) + return PACKET_V3_TRACKPOINT; + + elantech_packet_dump(psmouse); return PACKET_UNKNOWN; } @@ -969,10 +989,15 @@ static int elantech_set_input_params(struct psmouse *psmouse) __set_bit(INPUT_PROP_POINTER, dev->propbit); __set_bit(EV_KEY, dev->evbit); __set_bit(EV_ABS, dev->evbit); - __clear_bit(EV_REL, dev->evbit); + __set_bit(EV_REL, dev->evbit); + //__clear_bit(EV_REL, dev->evbit); __set_bit(BTN_LEFT, dev->keybit); __set_bit(BTN_RIGHT, dev->keybit); + __set_bit(BTN_MIDDLE, dev->keybit); + + __set_bit(REL_X, dev->relbit); + __set_bit(REL_Y, dev->relbit); __set_bit(BTN_TOUCH, dev->keybit); __set_bit(BTN_TOOL_FINGER, dev->keybit); diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index 46db3be..224871a 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -94,6 +94,7 @@ #define PACKET_V4_HEAD 0x05 #define PACKET_V4_MOTION 0x06 #define PACKET_V4_STATUS 0x07 +#define PACKET_V3_TRACKPOINT 0x08 /* * track up to 5 fingers for v4 hardware