From: JJ Ding <jj_ding@emc.com.tw>
To: Daniel Kurtz <djkurtz@chromium.org>
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
"Seth Forshee" <seth.forshee@canonical.com>,
"Dmitry Torokhov" <dmitry.torokhov@gmail.com>,
"Aaron Huang" <aaron_huang@emc.com.tw>,
"Tom Lin" <tom_lin@emc.com.tw>,
"Éric Piel" <E.A.B.Piel@tudelft.nl>,
"Chase Douglas" <chase.douglas@canonical.com>,
"Henrik Rydberg" <rydberg@euromail.se>,
"Alessandro Rubini" <rubini@cvml.unipv.it>
Subject: Re: [PATCH v5 7/8] Input: elantech - add v3 hardware support
Date: Mon, 05 Sep 2011 15:10:01 +0800 [thread overview]
Message-ID: <874o0rqxbq.fsf@emc.com.tw> (raw)
In-Reply-To: <CAGS+omCTDb-y7Gut=KgU5wz70R9=75gkmruYpOOS5JUECOK_UA@mail.gmail.com>
Hi Daniel,
On Mon, 5 Sep 2011 12:35:28 +0800, Daniel Kurtz <djkurtz@chromium.org> wrote:
> Hi JJ,
>
> On Mon, Sep 5, 2011 at 10:16 AM, JJ Ding <jj_ding@emc.com.tw> wrote:
> > diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
> > index 2ae7c49..c4ceefd 100644
> > --- a/drivers/input/mouse/elantech.c
> > +++ b/drivers/input/mouse/elantech.c
> > @@ -108,6 +108,16 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
> > rc = -1;
> > }
> > break;
> > +
> > + case 3:
> > + if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> > + elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
> > + elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> > + elantech_ps2_command(psmouse, NULL, reg) ||
> > + elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
> > + rc = -1;
> > + }
> > + break;
> > }
> >
> > if (rc)
> > @@ -154,6 +164,18 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
> > rc = -1;
> > }
> > break;
> > +
> > + case 3:
> > + if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> > + elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
> > + elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> > + elantech_ps2_command(psmouse, NULL, reg) ||
> > + elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> > + elantech_ps2_command(psmouse, NULL, val) ||
> > + elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
> > + rc = -1;
> > + }
> > + break;
> > }
> >
> > if (rc)
> > @@ -350,6 +372,84 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
> > input_sync(dev);
> > }
> >
> > +/*
> > + * Interpret complete data packets and report absolute mode input events for
> > + * hardware version 3. (12 byte packets for two fingers)
> > + */
> > +static void elantech_report_absolute_v3(struct psmouse *psmouse,
> > + int packet_type)
> > +{
> > + 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;
> > + unsigned int width = 0, pres = 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;
> > +
> > + 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->prev_x = ((packet[1] & 0x0f) << 8) | packet[2];
> > + /*
> > + * byte 4: . . . . ay11 ay10 ay9 ay8
> > + * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0
> > + */
> > + etd->prev_y = etd->y_max -
> > + (((packet[4] & 0x0f) << 8) | packet[5]);
> > + /*
> > + * wait for next packet
> > + */
> > + return;
> > + }
> > +
> > + /* packet_type == PACKET_V3_TAIL */
> > + x1 = etd->prev_x;
> > + y1 = etd->prev_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);
> > +
> > + 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);
>
> Originally, v3 was using semi-mt, which reported corner coordinates of
> a box containing at least two of the N touches on the touchpad. I
> thought this was due to hardware limitation.
>
> If the hardware really can report true positions for (up to) 3
> contacts, then using pure MT-B is a good approach. This driver still
> seems to mix semi-mt and MT-B together a bit.
>
> Can you report all three contacts in their own slots, 0, 1 and 2,
> instead of just reoprting two of them with 0,1?
>
> Also, when reporting the 'legacy single touch' coordinate (ABS_X,
> ABS_Y), please use:
> input_mt_report_pointer_emulation(), instead of always reporting the
> last (x1,y1). Otherwise the single touch point will bounce back and
> forth between 1st and 3rd touch.
v3 can only track the true positions of two fingers. With 3 finger
touch, it reports the lowest value of x and the biggest value of y,
among the three fingers. v3 changed the protocol so it could report
2-finger touch data w/o reduced resolution and improved the hardware to
truly track 2 fingers independently, otherwise it's pretty much the same
as v2.
> > + 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);
>
> Use input_mt_report_pointer_emulation() with use_count = true. This
> will also report ABS_PRESURE (but not ABS_TOOL_WIDTH, unfortunately).
>
> > + 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);
> > +}
> > +
> > static int elantech_packet_check_v1(struct psmouse *psmouse)
> > {
> > struct elantech_data *etd = psmouse->private;
> > @@ -403,11 +503,37 @@ static int elantech_packet_check_v2(struct psmouse *psmouse)
> > }
> >
> > /*
> > + * We check the constant bits to determine what packet type we get,
> > + * so packet checking is mandatory for v3 hardware.
> > + */
> > +static int elantech_packet_check_v3(struct psmouse *psmouse)
> > +{
> > + const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
> > + unsigned char *packet = psmouse->packet;
> > +
> > + /*
> > + * check debounce first, it has the same signature in byte 0
> > + * and byte 3 as PACKET_V3_HEAD.
> > + */
> > + if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
> > + return PACKET_DEBOUNCE;
> > +
> > + if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
> > + return PACKET_V3_HEAD;
> > +
> > + if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
> > + return PACKET_V3_TAIL;
> > +
> > + return PACKET_UNKNOWN;
> > +}
> > +
> > +/*
> > * Process byte stream from mouse and handle complete packets
> > */
> > static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
> > {
> > struct elantech_data *etd = psmouse->private;
> > + int packet_type;
> >
> > if (psmouse->pktcnt < psmouse->pktsize)
> > return PSMOUSE_GOOD_DATA;
> > @@ -429,6 +555,18 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
> >
> > elantech_report_absolute_v2(psmouse);
> > break;
> > +
> > + case 3:
> > + packet_type = elantech_packet_check_v3(psmouse);
> > + /* ignore debounce */
> > + if (packet_type == PACKET_DEBOUNCE)
> > + return PSMOUSE_FULL_PACKET;
> > +
> > + if (packet_type == PACKET_UNKNOWN)
> > + return PSMOUSE_BAD_DATA;
> > +
> > + elantech_report_absolute_v3(psmouse, packet_type);
> > + break;
> > }
> >
> > return PSMOUSE_FULL_PACKET;
> > @@ -463,8 +601,15 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
> > elantech_write_reg(psmouse, 0x11, etd->reg_11) ||
> > elantech_write_reg(psmouse, 0x21, etd->reg_21)) {
> > rc = -1;
> > - break;
> > }
> > + break;
> > +
> > + case 3:
> > + etd->reg_10 = 0x0b;
> > + if (elantech_write_reg(psmouse, 0x10, etd->reg_10))
> > + rc = -1;
> > +
> > + break;
> > }
> >
> > if (rc == 0) {
> > @@ -498,11 +643,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
> > return rc;
> > }
> >
> > -static void set_range(struct psmouse *psmouse, unsigned int *x_min,
> > +static int set_range(struct psmouse *psmouse, unsigned int *x_min,
> > unsigned int *y_min, unsigned int *x_max,
> > unsigned int *y_max)
> > {
> > struct elantech_data *etd = psmouse->private;
> > + unsigned char param[3];
> > int i;
> >
> > switch (etd->hw_version) {
> > @@ -530,19 +676,30 @@ static void set_range(struct psmouse *psmouse, unsigned int *x_min,
> > *y_max = (etd->capabilities[2] - i) * 64;
> > }
> > break;
> > +
> > + case 3:
> > + if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
> > + return -1;
> > +
> > + *x_max = (0x0f & param[0]) << 8 | param[1];
> > + *y_max = (0xf0 & param[0]) << 4 | param[2];
> > + break;
> > }
> > +
> > + return 0;
> > }
> >
> > /*
> > * Set the appropriate event bits for the input subsystem
> > */
> > -static void elantech_set_input_params(struct psmouse *psmouse)
> > +static int elantech_set_input_params(struct psmouse *psmouse)
> > {
> > struct input_dev *dev = psmouse->dev;
> > struct elantech_data *etd = psmouse->private;
> > unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0;
> >
> > - set_range(psmouse, &x_min, &y_min, &x_max, &y_max);
> > + if (set_range(psmouse, &x_min, &y_min, &x_max, &y_max))
> > + return -1;
> >
> > __set_bit(EV_KEY, dev->evbit);
> > __set_bit(EV_ABS, dev->evbit);
> > @@ -570,6 +727,9 @@ static void elantech_set_input_params(struct psmouse *psmouse)
> >
> > case 2:
> > __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
> > + __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
> > + /* fall through */
> > + case 3:
> > input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
> > input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
> > if (etd->reports_pressure) {
> > @@ -578,7 +738,6 @@ static void elantech_set_input_params(struct psmouse *psmouse)
> > input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
> > ETP_WMAX_V2, 0, 0);
> > }
> > - __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
> > input_mt_init_slots(dev, 2);
>
> Should this be 3?
>
> > input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
> > input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
> > @@ -586,6 +745,8 @@ static void elantech_set_input_params(struct psmouse *psmouse)
> > }
> >
> > etd->y_max = y_max;
> > +
> > + return 0;
> > }
> >
> > struct elantech_attr_data {
> > @@ -727,7 +888,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
> > * Report this in case there are Elantech models that use a different
> > * set of magic numbers
> > */
> > - if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) {
> > + if (param[0] != 0x3c || param[1] != 0x03 ||
> > + (param[2] != 0xc8 && param[2] != 0x00)) {
> > pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
> > param[0], param[1], param[2]);
> > return -1;
> > @@ -793,16 +955,16 @@ static int elantech_reconnect(struct psmouse *psmouse)
> > /*
> > * determine hardware version and set some properties according to it.
> > */
> > -static void elantech_set_properties(struct elantech_data *etd)
> > +static int elantech_set_properties(struct elantech_data *etd)
> > {
> > - /*
> > - * Assume every version greater than 0x020030 is new EeePC style
> > - * hardware with 6 byte packets, except 0x020600
> > - */
> > if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
> > etd->hw_version = 1;
> > - else
> > + else if (etd->fw_version < 0x150600)
> > etd->hw_version = 2;
> > + else if ((etd->fw_version & 0x0f0000) >> 16 == 5)
> > + etd->hw_version = 3;
> > + else
> > + return -1;
> >
> > /*
> > * Turn on packet checking by default.
> > @@ -817,13 +979,15 @@ static void elantech_set_properties(struct elantech_data *etd)
> > etd->jumpy_cursor =
> > (etd->fw_version == 0x020022 || etd->fw_version == 0x020600);
> >
> > - if (etd->hw_version == 2) {
> > + if (etd->hw_version > 1) {
> > /* For now show extra debug information */
> > etd->debug = 1;
> >
> > if (etd->fw_version >= 0x020800)
> > etd->reports_pressure = true;
> > }
> > +
> > + return 0;
> > }
> >
> > /*
> > @@ -850,9 +1014,12 @@ int elantech_init(struct psmouse *psmouse)
> > pr_err("failed to query firmware version.\n");
> > goto init_fail;
> > }
> > -
> > etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
> > - elantech_set_properties(etd);
> > +
> > + if (elantech_set_properties(etd)) {
> > + pr_err("unknown hardware version, aborting...\n");
> > + goto init_fail;
> > + }
> > pr_info("assuming hardware version %d "
> > "(with firmware version 0x%02x%02x%02x)\n",
> > etd->hw_version, param[0], param[1], param[2]);
> > @@ -871,7 +1038,10 @@ int elantech_init(struct psmouse *psmouse)
> > goto init_fail;
> > }
> >
> > - elantech_set_input_params(psmouse);
> > + if (elantech_set_input_params(psmouse)) {
> > + pr_err("failed to query touchpad range.\n");
> > + goto init_fail;
> > + }
> >
> > error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
> > &elantech_attr_group);
> > @@ -883,7 +1053,7 @@ int elantech_init(struct psmouse *psmouse)
> > psmouse->protocol_handler = elantech_process_byte;
> > psmouse->disconnect = elantech_disconnect;
> > psmouse->reconnect = elantech_reconnect;
> > - psmouse->pktsize = etd->hw_version == 2 ? 6 : 4;
> > + psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
> >
> > return 0;
> >
> > diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
> > index d9e6144..236c33c 100644
> > --- a/drivers/input/mouse/elantech.h
> > +++ b/drivers/input/mouse/elantech.h
> > @@ -16,6 +16,7 @@
> > /*
> > * Command values for Synaptics style queries
> > */
> > +#define ETP_FW_ID_QUERY 0x00
> > #define ETP_FW_VERSION_QUERY 0x01
> > #define ETP_CAPABILITIES_QUERY 0x02
> >
> > @@ -24,6 +25,7 @@
> > */
> > #define ETP_REGISTER_READ 0x10
> > #define ETP_REGISTER_WRITE 0x11
> > +#define ETP_REGISTER_READWRITE 0x00
> >
> > /*
> > * Hardware version 2 custom PS/2 command value
> > @@ -79,6 +81,14 @@
> > #define ETP_WMIN_V2 0
> > #define ETP_WMAX_V2 15
> >
> > +/*
> > + * v3 hardware has 2 kinds of packet types.
> > + */
> > +#define PACKET_UNKNOWN 0x01
> > +#define PACKET_DEBOUNCE 0x02
> > +#define PACKET_V3_HEAD 0x03
> > +#define PACKET_V3_TAIL 0x04
> > +
> > struct elantech_data {
> > unsigned char reg_10;
> > unsigned char reg_11;
> > @@ -98,6 +108,8 @@ struct elantech_data {
> > unsigned int fw_version;
> > unsigned int single_finger_reports;
> > unsigned int y_max;
> > + unsigned int prev_x;
> > + unsigned int prev_y;
> > unsigned char parity[256];
> > };
> >
> > --
> > 1.7.4.1
> >
>
WARNING: multiple messages have this Message-ID (diff)
From: JJ Ding <jj_ding@emc.com.tw>
To: Daniel Kurtz <djkurtz@chromium.org>
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
"Seth Forshee" <seth.forshee@canonical.com>,
"Dmitry Torokhov" <dmitry.torokhov@gmail.com>,
"Aaron Huang" <aaron_huang@emc.com.tw>,
"Tom Lin" <tom_lin@emc.com.tw>,
"Éric Piel" <E.A.B.Piel@tudelft.nl>,
"Chase Douglas" <chase.douglas@canonical.com>,
"Henrik Rydberg" <rydberg@euromail.se>,
"Alessandro Rubini" <rubini@cvml.unipv.it>
Subject: Re: [PATCH v5 7/8] Input: elantech - add v3 hardware support
Date: Mon, 05 Sep 2011 15:10:01 +0800 [thread overview]
Message-ID: <874o0rqxbq.fsf@emc.com.tw> (raw)
In-Reply-To: <CAGS+omCTDb-y7Gut=KgU5wz70R9=75gkmruYpOOS5JUECOK_UA@mail.gmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=utf-8, Size: 19678 bytes --]
Hi Daniel,
On Mon, 5 Sep 2011 12:35:28 +0800, Daniel Kurtz <djkurtz@chromium.org> wrote:
> Hi JJ,
>
> On Mon, Sep 5, 2011 at 10:16 AM, JJ Ding <jj_ding@emc.com.tw> wrote:
> > diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
> > index 2ae7c49..c4ceefd 100644
> > --- a/drivers/input/mouse/elantech.c
> > +++ b/drivers/input/mouse/elantech.c
> > @@ -108,6 +108,16 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
> > Â Â Â Â Â Â Â Â Â Â Â Â rc = -1;
> > Â Â Â Â Â Â Â Â }
> > Â Â Â Â Â Â Â Â break;
> > +
> > + Â Â Â case 3:
> > + Â Â Â Â Â Â Â if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> > + Â Â Â Â Â Â Â Â Â elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
> > + Â Â Â Â Â Â Â Â Â elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> > + Â Â Â Â Â Â Â Â Â elantech_ps2_command(psmouse, NULL, reg) ||
> > + Â Â Â Â Â Â Â Â Â elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
> > + Â Â Â Â Â Â Â Â Â Â Â rc = -1;
> > + Â Â Â Â Â Â Â }
> > + Â Â Â Â Â Â Â break;
> > Â Â Â Â }
> >
> > Â Â Â Â if (rc)
> > @@ -154,6 +164,18 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
> > Â Â Â Â Â Â Â Â Â Â Â Â rc = -1;
> > Â Â Â Â Â Â Â Â }
> > Â Â Â Â Â Â Â Â break;
> > +
> > + Â Â Â case 3:
> > + Â Â Â Â Â Â Â if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> > + Â Â Â Â Â Â Â Â Â elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
> > + Â Â Â Â Â Â Â Â Â elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> > + Â Â Â Â Â Â Â Â Â elantech_ps2_command(psmouse, NULL, reg) ||
> > + Â Â Â Â Â Â Â Â Â elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
> > + Â Â Â Â Â Â Â Â Â elantech_ps2_command(psmouse, NULL, val) ||
> > + Â Â Â Â Â Â Â Â Â elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
> > + Â Â Â Â Â Â Â Â Â Â Â rc = -1;
> > + Â Â Â Â Â Â Â }
> > + Â Â Â Â Â Â Â break;
> > Â Â Â Â }
> >
> > Â Â Â Â if (rc)
> > @@ -350,6 +372,84 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
> > Â Â Â Â input_sync(dev);
> > Â }
> >
> > +/*
> > + * Interpret complete data packets and report absolute mode input events for
> > + * hardware version 3. (12 byte packets for two fingers)
> > + */
> > +static void elantech_report_absolute_v3(struct psmouse *psmouse,
> > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int packet_type)
> > +{
> > + Â Â Â 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;
> > + Â Â Â unsigned int width = 0, pres = 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;
> > +
> > + Â Â Â 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->prev_x = ((packet[1] & 0x0f) << 8) | packet[2];
> > + Â Â Â Â Â Â Â Â Â Â Â /*
> > + Â Â Â Â Â Â Â Â Â Â Â Â * byte 4: Â . Â Â . Â Â . Â Â . Â ay11 ay10 ay9 Â ay8
> > + Â Â Â Â Â Â Â Â Â Â Â Â * byte 5: ay7 Â ay6 Â ay5 Â ay4 Â ay3 Â ay2 Â ay1 Â ay0
> > + Â Â Â Â Â Â Â Â Â Â Â Â */
> > + Â Â Â Â Â Â Â Â Â Â Â etd->prev_y = etd->y_max -
> > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (((packet[4] & 0x0f) << 8) | packet[5]);
> > + Â Â Â Â Â Â Â Â Â Â Â /*
> > + Â Â Â Â Â Â Â Â Â Â Â Â * wait for next packet
> > + Â Â Â Â Â Â Â Â Â Â Â Â */
> > + Â Â Â Â Â Â Â Â Â Â Â return;
> > + Â Â Â Â Â Â Â }
> > +
> > + Â Â Â Â Â Â Â /* packet_type == PACKET_V3_TAIL */
> > + Â Â Â Â Â Â Â x1 = etd->prev_x;
> > + Â Â Â Â Â Â Â y1 = etd->prev_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);
> > +
> > + Â Â Â 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);
>
> Originally, v3 was using semi-mt, which reported corner coordinates of
> a box containing at least two of the N touches on the touchpad. I
> thought this was due to hardware limitation.
>
> If the hardware really can report true positions for (up to) 3
> contacts, then using pure MT-B is a good approach. This driver still
> seems to mix semi-mt and MT-B together a bit.
>
> Can you report all three contacts in their own slots, 0, 1 and 2,
> instead of just reoprting two of them with 0,1?
>
> Also, when reporting the 'legacy single touch' coordinate (ABS_X,
> ABS_Y), please use:
> input_mt_report_pointer_emulation(), instead of always reporting the
> last (x1,y1). Otherwise the single touch point will bounce back and
> forth between 1st and 3rd touch.
v3 can only track the true positions of two fingers. With 3 finger
touch, it reports the lowest value of x and the biggest value of y,
among the three fingers. v3 changed the protocol so it could report
2-finger touch data w/o reduced resolution and improved the hardware to
truly track 2 fingers independently, otherwise it's pretty much the same
as v2.
> > + Â Â Â 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);
>
> Use input_mt_report_pointer_emulation() with use_count = true. This
> will also report ABS_PRESURE (but not ABS_TOOL_WIDTH, unfortunately).
>
> > + Â Â Â 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);
> > +}
> > +
> > Â static int elantech_packet_check_v1(struct psmouse *psmouse)
> > Â {
> > Â Â Â Â struct elantech_data *etd = psmouse->private;
> > @@ -403,11 +503,37 @@ static int elantech_packet_check_v2(struct psmouse *psmouse)
> > Â }
> >
> > Â /*
> > + * We check the constant bits to determine what packet type we get,
> > + * so packet checking is mandatory for v3 hardware.
> > + */
> > +static int elantech_packet_check_v3(struct psmouse *psmouse)
> > +{
> > + Â Â Â const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
> > + Â Â Â unsigned char *packet = psmouse->packet;
> > +
> > + Â Â Â /*
> > + Â Â Â Â * check debounce first, it has the same signature in byte 0
> > + Â Â Â Â * and byte 3 as PACKET_V3_HEAD.
> > + Â Â Â Â */
> > + Â Â Â if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
> > + Â Â Â Â Â Â Â return PACKET_DEBOUNCE;
> > +
> > + Â Â Â if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
> > + Â Â Â Â Â Â Â return PACKET_V3_HEAD;
> > +
> > + Â Â Â if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
> > + Â Â Â Â Â Â Â return PACKET_V3_TAIL;
> > +
> > + Â Â Â return PACKET_UNKNOWN;
> > +}
> > +
> > +/*
> > Â * Process byte stream from mouse and handle complete packets
> > Â */
> > Â static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
> > Â {
> > Â Â Â Â struct elantech_data *etd = psmouse->private;
> > + Â Â Â int packet_type;
> >
> > Â Â Â Â if (psmouse->pktcnt < psmouse->pktsize)
> > Â Â Â Â Â Â Â Â return PSMOUSE_GOOD_DATA;
> > @@ -429,6 +555,18 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
> >
> > Â Â Â Â Â Â Â Â elantech_report_absolute_v2(psmouse);
> > Â Â Â Â Â Â Â Â break;
> > +
> > + Â Â Â case 3:
> > + Â Â Â Â Â Â Â packet_type = elantech_packet_check_v3(psmouse);
> > + Â Â Â Â Â Â Â /* ignore debounce */
> > + Â Â Â Â Â Â Â if (packet_type == PACKET_DEBOUNCE)
> > + Â Â Â Â Â Â Â Â Â Â Â return PSMOUSE_FULL_PACKET;
> > +
> > + Â Â Â Â Â Â Â if (packet_type == PACKET_UNKNOWN)
> > + Â Â Â Â Â Â Â Â Â Â Â return PSMOUSE_BAD_DATA;
> > +
> > + Â Â Â Â Â Â Â elantech_report_absolute_v3(psmouse, packet_type);
> > + Â Â Â Â Â Â Â break;
> > Â Â Â Â }
> >
> > Â Â Â Â return PSMOUSE_FULL_PACKET;
> > @@ -463,8 +601,15 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
> > Â Â Â Â Â Â Â Â Â Â elantech_write_reg(psmouse, 0x11, etd->reg_11) ||
> > Â Â Â Â Â Â Â Â Â Â elantech_write_reg(psmouse, 0x21, etd->reg_21)) {
> > Â Â Â Â Â Â Â Â Â Â Â Â rc = -1;
> > - Â Â Â Â Â Â Â Â Â Â Â break;
> > Â Â Â Â Â Â Â Â }
> > + Â Â Â Â Â Â Â break;
> > +
> > + Â Â Â case 3:
> > + Â Â Â Â Â Â Â etd->reg_10 = 0x0b;
> > + Â Â Â Â Â Â Â if (elantech_write_reg(psmouse, 0x10, etd->reg_10))
> > + Â Â Â Â Â Â Â Â Â Â Â rc = -1;
> > +
> > + Â Â Â Â Â Â Â break;
> > Â Â Â Â }
> >
> > Â Â Â Â if (rc == 0) {
> > @@ -498,11 +643,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
> > Â Â Â Â return rc;
> > Â }
> >
> > -static void set_range(struct psmouse *psmouse, unsigned int *x_min,
> > +static int set_range(struct psmouse *psmouse, unsigned int *x_min,
> > Â Â Â Â Â Â Â Â Â Â unsigned int *y_min, unsigned int *x_max,
> > Â Â Â Â Â Â Â Â Â Â unsigned int *y_max)
> > Â {
> > Â Â Â Â struct elantech_data *etd = psmouse->private;
> > + Â Â Â unsigned char param[3];
> > Â Â Â Â int i;
> >
> > Â Â Â Â switch (etd->hw_version) {
> > @@ -530,19 +676,30 @@ static void set_range(struct psmouse *psmouse, unsigned int *x_min,
> > Â Â Â Â Â Â Â Â Â Â Â Â *y_max = (etd->capabilities[2] - i) * 64;
> > Â Â Â Â Â Â Â Â }
> > Â Â Â Â Â Â Â Â break;
> > +
> > + Â Â Â case 3:
> > + Â Â Â Â Â Â Â if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
> > + Â Â Â Â Â Â Â Â Â Â Â return -1;
> > +
> > + Â Â Â Â Â Â Â *x_max = (0x0f & param[0]) << 8 | param[1];
> > + Â Â Â Â Â Â Â *y_max = (0xf0 & param[0]) << 4 | param[2];
> > + Â Â Â Â Â Â Â break;
> > Â Â Â Â }
> > +
> > + Â Â Â return 0;
> > Â }
> >
> > Â /*
> > Â * Set the appropriate event bits for the input subsystem
> > Â */
> > -static void elantech_set_input_params(struct psmouse *psmouse)
> > +static int elantech_set_input_params(struct psmouse *psmouse)
> > Â {
> > Â Â Â Â struct input_dev *dev = psmouse->dev;
> > Â Â Â Â struct elantech_data *etd = psmouse->private;
> > Â Â Â Â unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0;
> >
> > - Â Â Â set_range(psmouse, &x_min, &y_min, &x_max, &y_max);
> > + Â Â Â if (set_range(psmouse, &x_min, &y_min, &x_max, &y_max))
> > + Â Â Â Â Â Â Â return -1;
> >
> > Â Â Â Â __set_bit(EV_KEY, dev->evbit);
> > Â Â Â Â __set_bit(EV_ABS, dev->evbit);
> > @@ -570,6 +727,9 @@ static void elantech_set_input_params(struct psmouse *psmouse)
> >
> > Â Â Â Â case 2:
> > Â Â Â Â Â Â Â Â __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
> > + Â Â Â Â Â Â Â __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
> > + Â Â Â Â Â Â Â /* fall through */
> > + Â Â Â case 3:
> > Â Â Â Â Â Â Â Â input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
> > Â Â Â Â Â Â Â Â input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
> > Â Â Â Â Â Â Â Â if (etd->reports_pressure) {
> > @@ -578,7 +738,6 @@ static void elantech_set_input_params(struct psmouse *psmouse)
> > Â Â Â Â Â Â Â Â Â Â Â Â input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
> > Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ETP_WMAX_V2, 0, 0);
> > Â Â Â Â Â Â Â Â }
> > - Â Â Â Â Â Â Â __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
> > Â Â Â Â Â Â Â Â input_mt_init_slots(dev, 2);
>
> Should this be 3?
>
> > Â Â Â Â Â Â Â Â input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
> > Â Â Â Â Â Â Â Â input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
> > @@ -586,6 +745,8 @@ static void elantech_set_input_params(struct psmouse *psmouse)
> > Â Â Â Â }
> >
> > Â Â Â Â etd->y_max = y_max;
> > +
> > + Â Â Â return 0;
> > Â }
> >
> > Â struct elantech_attr_data {
> > @@ -727,7 +888,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
> > Â Â Â Â * Report this in case there are Elantech models that use a different
> > Â Â Â Â * set of magic numbers
> > Â Â Â Â */
> > - Â Â Â if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) {
> > + Â Â Â if (param[0] != 0x3c || param[1] != 0x03 ||
> > + Â Â Â Â Â (param[2] != 0xc8 && param[2] != 0x00)) {
> > Â Â Â Â Â Â Â Â pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
> > Â Â Â Â Â Â Â Â Â Â Â Â param[0], param[1], param[2]);
> > Â Â Â Â Â Â Â Â return -1;
> > @@ -793,16 +955,16 @@ static int elantech_reconnect(struct psmouse *psmouse)
> > Â /*
> > Â * determine hardware version and set some properties according to it.
> > Â */
> > -static void elantech_set_properties(struct elantech_data *etd)
> > +static int elantech_set_properties(struct elantech_data *etd)
> > Â {
> > - Â Â Â /*
> > - Â Â Â Â * Assume every version greater than 0x020030 is new EeePC style
> > - Â Â Â Â * hardware with 6 byte packets, except 0x020600
> > - Â Â Â Â */
> > Â Â Â Â if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
> > Â Â Â Â Â Â Â Â etd->hw_version = 1;
> > - Â Â Â else
> > + Â Â Â else if (etd->fw_version < 0x150600)
> > Â Â Â Â Â Â Â Â etd->hw_version = 2;
> > + Â Â Â else if ((etd->fw_version & 0x0f0000) >> 16 == 5)
> > + Â Â Â Â Â Â Â etd->hw_version = 3;
> > + Â Â Â else
> > + Â Â Â Â Â Â Â return -1;
> >
> > Â Â Â Â /*
> > Â Â Â Â * Turn on packet checking by default.
> > @@ -817,13 +979,15 @@ static void elantech_set_properties(struct elantech_data *etd)
> > Â Â Â Â etd->jumpy_cursor =
> > Â Â Â Â Â Â Â Â (etd->fw_version == 0x020022 || etd->fw_version == 0x020600);
> >
> > - Â Â Â if (etd->hw_version == 2) {
> > + Â Â Â if (etd->hw_version > 1) {
> > Â Â Â Â Â Â Â Â /* For now show extra debug information */
> > Â Â Â Â Â Â Â Â etd->debug = 1;
> >
> > Â Â Â Â Â Â Â Â if (etd->fw_version >= 0x020800)
> > Â Â Â Â Â Â Â Â Â Â Â Â etd->reports_pressure = true;
> > Â Â Â Â }
> > +
> > + Â Â Â return 0;
> > Â }
> >
> > Â /*
> > @@ -850,9 +1014,12 @@ int elantech_init(struct psmouse *psmouse)
> > Â Â Â Â Â Â Â Â pr_err("failed to query firmware version.\n");
> > Â Â Â Â Â Â Â Â goto init_fail;
> > Â Â Â Â }
> > -
> > Â Â Â Â etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
> > - Â Â Â elantech_set_properties(etd);
> > +
> > + Â Â Â if (elantech_set_properties(etd)) {
> > + Â Â Â Â Â Â Â pr_err("unknown hardware version, aborting...\n");
> > + Â Â Â Â Â Â Â goto init_fail;
> > + Â Â Â }
> > Â Â Â Â pr_info("assuming hardware version %d "
> > Â Â Â Â Â Â Â Â "(with firmware version 0x%02x%02x%02x)\n",
> > Â Â Â Â Â Â Â Â etd->hw_version, param[0], param[1], param[2]);
> > @@ -871,7 +1038,10 @@ int elantech_init(struct psmouse *psmouse)
> > Â Â Â Â Â Â Â Â goto init_fail;
> > Â Â Â Â }
> >
> > - Â Â Â elantech_set_input_params(psmouse);
> > + Â Â Â if (elantech_set_input_params(psmouse)) {
> > + Â Â Â Â Â Â Â pr_err("failed to query touchpad range.\n");
> > + Â Â Â Â Â Â Â goto init_fail;
> > + Â Â Â }
> >
> > Â Â Â Â error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
> > Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &elantech_attr_group);
> > @@ -883,7 +1053,7 @@ int elantech_init(struct psmouse *psmouse)
> > Â Â Â Â psmouse->protocol_handler = elantech_process_byte;
> > Â Â Â Â psmouse->disconnect = elantech_disconnect;
> > Â Â Â Â psmouse->reconnect = elantech_reconnect;
> > - Â Â Â psmouse->pktsize = etd->hw_version == 2 ? 6 : 4;
> > + Â Â Â psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
> >
> > Â Â Â Â return 0;
> >
> > diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
> > index d9e6144..236c33c 100644
> > --- a/drivers/input/mouse/elantech.h
> > +++ b/drivers/input/mouse/elantech.h
> > @@ -16,6 +16,7 @@
> > Â /*
> > Â * Command values for Synaptics style queries
> > Â */
> > +#define ETP_FW_ID_QUERY Â Â Â Â Â Â Â Â Â Â Â Â 0x00
> > Â #define ETP_FW_VERSION_QUERY Â Â Â Â Â 0x01
> > Â #define ETP_CAPABILITIES_QUERY Â Â Â Â 0x02
> >
> > @@ -24,6 +25,7 @@
> > Â */
> > Â #define ETP_REGISTER_READ Â Â Â Â Â Â Â 0x10
> > Â #define ETP_REGISTER_WRITE Â Â Â Â Â Â 0x11
> > +#define ETP_REGISTER_READWRITE Â Â Â Â 0x00
> >
> > Â /*
> > Â * Hardware version 2 custom PS/2 command value
> > @@ -79,6 +81,14 @@
> > Â #define ETP_WMIN_V2 Â Â Â Â Â Â Â Â Â Â 0
> > Â #define ETP_WMAX_V2 Â Â Â Â Â Â Â Â Â Â 15
> >
> > +/*
> > + * v3 hardware has 2 kinds of packet types.
> > + */
> > +#define PACKET_UNKNOWN Â Â Â Â Â Â Â Â 0x01
> > +#define PACKET_DEBOUNCE Â Â Â Â Â Â Â Â Â Â Â Â 0x02
> > +#define PACKET_V3_HEAD Â Â Â Â Â Â Â Â 0x03
> > +#define PACKET_V3_TAIL Â Â Â Â Â Â Â Â 0x04
> > +
> > Â struct elantech_data {
> > Â Â Â Â unsigned char reg_10;
> > Â Â Â Â unsigned char reg_11;
> > @@ -98,6 +108,8 @@ struct elantech_data {
> > Â Â Â Â unsigned int fw_version;
> > Â Â Â Â unsigned int single_finger_reports;
> > Â Â Â Â unsigned int y_max;
> > + Â Â Â unsigned int prev_x;
> > + Â Â Â unsigned int prev_y;
> > Â Â Â Â unsigned char parity[256];
> > Â };
> >
> > --
> > 1.7.4.1
> >
>
ÿôèº{.nÇ+·®+%Ëÿ±éݶ\x17¥wÿº{.nÇ+·¥{±þG«éÿ{ayº\x1dÊÚë,j\a¢f£¢·hïêÿêçz_è®\x03(éÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?¨èÚ&£ø§~á¶iOæ¬z·vØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?I¥
next prev parent reply other threads:[~2011-09-05 7:07 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-05 2:16 [PATCH v5 0/8] Input: elantech: add support for newer hardware JJ Ding
2011-09-05 2:16 ` [PATCH v5 1/8] Input: elantech - correct x, y value range for v2 hardware JJ Ding
2011-09-05 2:16 ` [PATCH v5 2/8] Input: elantech - get rid of ETP_2FT_* in elantech.h JJ Ding
2011-09-05 2:16 ` JJ Ding
2011-09-05 2:16 ` [PATCH v5 3/8] Input: elantech - use firmware provided x, y ranges JJ Ding
2011-09-05 2:16 ` JJ Ding
2011-09-05 2:16 ` [PATCH v5 4/8] Input: elantech - remove ETP_EDGE_FUZZ_V2 JJ Ding
2011-09-05 2:16 ` JJ Ding
2011-09-05 2:16 ` [PATCH v5 5/8] Input: elantech - packet checking for v2 hardware JJ Ding
2011-09-05 2:16 ` JJ Ding
2011-09-05 2:16 ` [PATCH v5 6/8] Input: elantech - clean up elantech_init JJ Ding
2011-09-05 2:16 ` JJ Ding
2011-09-05 2:16 ` [PATCH v5 7/8] Input: elantech - add v3 hardware support JJ Ding
2011-09-05 2:16 ` JJ Ding
2011-09-05 4:35 ` Daniel Kurtz
2011-09-05 4:35 ` Daniel Kurtz
2011-09-05 7:10 ` JJ Ding [this message]
2011-09-05 7:10 ` JJ Ding
2011-09-05 8:39 ` Daniel Kurtz
2011-09-05 8:47 ` Daniel Kurtz
2011-09-06 3:39 ` JJ Ding
2011-09-05 2:16 ` [PATCH v5 8/8] Input: elantech - add v4 " JJ Ding
2011-09-09 17:33 ` [PATCH v5 0/8] Input: elantech: add support for newer hardware Dmitry Torokhov
2011-09-09 17:33 ` Dmitry Torokhov
2011-09-13 1:43 ` JJ Ding
2011-09-12 8:44 ` Éric Piel
2011-09-12 8:44 ` Éric Piel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=874o0rqxbq.fsf@emc.com.tw \
--to=jj_ding@emc.com.tw \
--cc=E.A.B.Piel@tudelft.nl \
--cc=aaron_huang@emc.com.tw \
--cc=chase.douglas@canonical.com \
--cc=djkurtz@chromium.org \
--cc=dmitry.torokhov@gmail.com \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rubini@cvml.unipv.it \
--cc=rydberg@euromail.se \
--cc=seth.forshee@canonical.com \
--cc=tom_lin@emc.com.tw \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.