Re: [PATCH v5 7/8] Input: elantech - add v3 hardware support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi JJ,

On Mon, Sep 5, 2011 at 4:39 PM, Daniel Kurtz <djkurtz@xxxxxxxxxxxx> wrote:
> Hi JJ,
>
> On Mon, Sep 5, 2011 at 3:10 PM, JJ Ding <jj_ding@xxxxxxxxxx> wrote:
>> Hi Daniel,
>>
>> On Mon, 5 Sep 2011 12:35:28 +0800, Daniel Kurtz <djkurtz@xxxxxxxxxxxx> wrote:
>>> Hi JJ,
>>>
>>> On Mon, Sep 5, 2011 at 10:16 AM, JJ Ding <jj_ding@xxxxxxxxxx> 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.
>
>
> If I read this code correctly, it looks like in the 3-finger case,
> (x1,y1) as reported in the (ABS_X, ABS_Y), and in the call to
> elantech_report_semi_mt_data() will bounce back and forth between the
> 1st finger and 3rd finger ("lowest value of x and the biggest value of
> y").  Won't this be very confusing for userspace (i.e.
> xf86-input=synaptics)?

Oh, never mind.  Sorry for the confusion.  I guess in the 3-finger
case, you only get "3-finger" packets containing the single ("lowest
value of x and the biggest value of y") bounding box coordinate, not
V3_HEAD/V3_TAIL packets.
I believe this shouldn't be reported as MT-B slot 0, though.  If
anything, perhaps you should use MT-B slot 2 for this coordinate?
It's not really the third finger, but at least it won't be considered
a continuation of the motion of the first finger.
I guess you really have no choice but to use it as the (ABS_X, ABS_Y)
coordinate.

-Dan
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux