Hi Dmitry,

Could you please have a look at this patch. It solves the bugzilla bug
https://bugzilla.kernel.org/show_bug.cgi?id=48161

Thanks,
Best regards,
Ulrik De Bie

On Fri, Feb 14, 2014 at 09:51:26PM +0100, Ulrik De Bie wrote:
> Date: Fri, 14 Feb 2014 21:51:26 +0100
> From: Ulrik De Bie <ulrik.debie...@e2big.org>
> To: linux-input@vger.kernel.org
> Cc: linux-ker...@vger.kernel.org, Dmitry Torokhov
>  <dmitry.torok...@gmail.com>, David Herrmann <dh.herrm...@gmail.com>,
>  Jonathan Aquilina <eagles051...@gmail.com>, Ulrik De Bie
>  <ulrik_opensource-ker...@yahoo.com>
> Subject: [PATCH] Input: Support in the elantech driver of the trackpoint
>  present on for instance Lenovo L530
> X-Mailing-List:       linux-input@vger.kernel.org
> 
> Sorry it took me some time to have an email addres that would allow clean
> mails. Below you can find the updated patch previously sent on linux-input
> mailinglist. David Herrman asked to resent this patch as a proper git patch so
> here it is now. 
> 
> It also available on https://github.com/ulrikdb/linux.git elantech_trackpoint
> from commit 38dbfb59d1175ef458d006556061adeaa8751b72 (Linus 3.14-rc1) up to 
> d69e103a35c944721966105790d14adf79098a4c 
> 
> Please when responding please send either to linux-input or put Ulrik De Bie 
> <ulrik.debie...@e2big.org> in CC:, Thanks.
> 
> 
> The Lenovo L530 trackpoint does not work out of the box. It gives sync errors
> as shown below when the trackpoint or trackpoint mouse buttons are pressed and
> no input is received by userspace:
> [   29.010641] psmouse serio1: Touchpad at isa0060/serio1/input0 lost sync at 
> byte 6
> The touchpad does work.
> 
> The alternative is to do a downgrade to generic ps/2 mouse (modprobe psmouse 
> proto=bare)
> but this has the disadvantage that touchpad can't be disabled (I want 
> trackpoint, not touchpad).
> 
> With this patch, the trackpoint is provided as another input device; 
> currently called 'TPPS/2 IBM TrackPoint'
> The trackpoint now succesfully works and I can disable the touchpad with 
> synclient TouchPadOff=1
> The patch will also output messages that do not follow the expected pattern.
> In the mean time I've seen 2 unknown packets occasionally:
> 0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
> 0x00 , 0x00 , 0x00 , 0x02 , 0x00 , 0x00
> I don't know what those are for, but they can be safely ignored.
> 
> Currently all packets that are not known to v3 touchpad and where packet[3] 
> (the fourth byte) lowest
> nibble is 6 are now recognized as PACKET_TRACKPOINT and processed by the new 
> elantech_report_trackpoint.
> 
> This has been verified to work on a laptop where the touchpad/trackpoint 
> combined identify themselves as:
> psmouse serio1: elantech: assuming hardware version 3 (with firmware version 
> 0x350f02)
> psmouse serio1: elantech: Synaptics capabilities query result 0xb9, 0x15, 
> 0x0c.
> 
> Since I can't send clean email from yahoo, I've switched to a different email 
> address: ulrik.debie...@e2big.org
> Signed-off-by: Ulrik De Bie <ulrik_opensource-ker...@yahoo.com>
> Signed-off-by: Ulrik De Bie <ulrik.debie...@e2big.org>
> 
> Signed-off-by: Ulrik De Bie <ulrik.debie...@e2big.org>
> ---
>  drivers/input/mouse/elantech.c | 78 
> +++++++++++++++++++++++++++++++++++++++++-
>  drivers/input/mouse/elantech.h |  3 ++
>  2 files changed, 80 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
> index ef1cf52..21d693b 100644
> --- a/drivers/input/mouse/elantech.c
> +++ b/drivers/input/mouse/elantech.c
> @@ -402,6 +402,54 @@ static void elantech_report_absolute_v2(struct psmouse 
> *psmouse)
>       input_sync(dev);
>  }
>  
> +static void elantech_report_trackpoint(struct psmouse *psmouse,
> +                                    int packet_type)
> +{
> +     /* byte 0:  0   0 ~sx ~sy   0   M   R   L */
> +     /* byte 1: sx   0   0   0   0   0   0   0 */
> +     /* byte 2: sy   0   0   0   0   0   0   0 */
> +     /* byte 3:  0   0  sy  sx   0   1   1   0 */
> +     /* byte 4: x7  x6  x5  x4  x3  x2  x1  x0 */
> +     /* byte 5: y7  y6  y5  y4  y3  y2  y1  y0 */
> +
> +     /*
> +      * x and y are written in two's complement spread
> +      * over 9 bits with sx/sy the relative top bit and
> +      * x7..x0 and y7..y0 the lower bits.
> +      * The sign of y is opposite to what the input driver
> +      * expects for a relative movement
> +      */
> +
> +     struct elantech_data *etd = psmouse->private;
> +     struct input_dev *dev2 = etd->dev2;
> +     unsigned char *packet = psmouse->packet;
> +     int x, y;
> +     input_report_key(dev2, BTN_LEFT, packet[0] & 0x01);
> +     input_report_key(dev2, BTN_RIGHT, packet[0] & 0x02);
> +     input_report_key(dev2, BTN_MIDDLE, packet[0] & 0x04);
> +     x = (s32) ((u32) ((packet[1] & 0x80) ? 0UL : 0xFFFFFF00UL) | (u32)
> +                packet[4]);
> +     y = -(s32) ((u32) ((packet[2] & 0x80) ? 0UL : 0xFFFFFF00UL) | (u32)
> +                 packet[5]);
> +     input_report_rel(dev2, REL_X, x);
> +     input_report_rel(dev2, REL_Y, y);
> +     switch ((((u32) packet[0] & 0xF8) << 24) | ((u32) packet[1] << 16)
> +             | (u32) packet[2] << 8 | (u32) packet[3]) {
> +     case 0x00808036UL:
> +     case 0x10008026UL:
> +     case 0x20800016UL:
> +     case 0x30000006UL:
> +             break;
> +     default:
> +             /* Dump unexpected packet sequences if debug=1 (default) */
> +             if (etd->debug == 1)
> +                     elantech_packet_dump(psmouse);
> +             break;
> +     }
> +
> +     input_sync(dev2);
> +}
> +
>  /*
>   * Interpret complete data packets and report absolute mode input events for
>   * hardware version 3. (12 byte packets for two fingers)
> @@ -700,8 +748,11 @@ 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]&0x0f) == 0x06)
> +                     return PACKET_TRACKPOINT;
>       }
>  
> +
>       return PACKET_UNKNOWN;
>  }
>  
> @@ -783,7 +834,10 @@ static psmouse_ret_t elantech_process_byte(struct 
> psmouse *psmouse)
>               if (packet_type == PACKET_UNKNOWN)
>                       return PSMOUSE_BAD_DATA;
>  
> -             elantech_report_absolute_v3(psmouse, packet_type);
> +             if (packet_type == PACKET_TRACKPOINT)
> +                     elantech_report_trackpoint(psmouse, packet_type);
> +             else
> +                     elantech_report_absolute_v3(psmouse, packet_type);
>               break;
>  
>       case 4:
> @@ -1400,10 +1454,15 @@ int elantech_init(struct psmouse *psmouse)
>       struct elantech_data *etd;
>       int i, error;
>       unsigned char param[3];
> +     struct input_dev *dev2;
>  
>       psmouse->private = etd = kzalloc(sizeof(struct elantech_data), 
> GFP_KERNEL);
>       if (!etd)
>               return -ENOMEM;
> +     dev2 = input_allocate_device();
> +     if (!dev2)
> +             goto init_fail;
> +     etd->dev2 = dev2;
>  
>       psmouse_reset(psmouse);
>  
> @@ -1463,9 +1522,26 @@ int elantech_init(struct psmouse *psmouse)
>       psmouse->reconnect = elantech_reconnect;
>       psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
>  
> +     snprintf(etd->phys, sizeof(etd->phys), "%s/input1",
> +             psmouse->ps2dev.serio->phys);
> +     dev2->phys = etd->phys;
> +     dev2->name = "TPPS/2 IBM TrackPoint";
> +     dev2->id.bustype = BUS_I8042;
> +     dev2->id.vendor  = 0x0002;
> +     dev2->id.product = PSMOUSE_ELANTECH;
> +     dev2->id.version = 0x0000;
> +     dev2->dev.parent = &psmouse->ps2dev.serio->dev;
> +     dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
> +     dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
> +     dev2->keybit[BIT_WORD(BTN_LEFT)] =
> +             BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
> +
> +     if (input_register_device(etd->dev2))
> +             goto init_fail;
>       return 0;
>  
>   init_fail:
> +     input_free_device(dev2);
>       kfree(etd);
>       return -1;
>  }
> diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
> index 036a04a..27cf191 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_TRACKPOINT            0x08
>  
>  /*
>   * track up to 5 fingers for v4 hardware
> @@ -114,6 +115,8 @@ struct finger_pos {
>  };
>  
>  struct elantech_data {
> +     struct input_dev *dev2;         /* Relative device */
> +     char    phys[32];
>       unsigned char reg_07;
>       unsigned char reg_10;
>       unsigned char reg_11;
> -- 
> 1.8.5.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to