Re: [PATCH] Input: byd - enable absolute mode

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

 



On Fri, Mar 25, 2016 at 3:43 PM, Richard Pospesel <pospeselr@xxxxxxxxx> wrote:
> Pinging you on this.

Sorry for not responding earlier. It is included in my 2nd pull
request for 4.6-rc1.

>
> -Richard
>
> On Thu, Mar 17, 2016 at 8:51 AM, Richard Pospesel <pospeselr@xxxxxxxxx>
> wrote:
>>
>> Are there any more concerns Dmitry?
>>
>> best,
>> -Richard
>>
>>
>> On 03/12/2016 05:32 AM, Chris Diamand wrote:
>>>
>>> From: Richard Pospesel <pospeselr@xxxxxxxxx>
>>>
>>> The Windows driver's settings dialog contains a visualization of the
>>> regions for the hardware edge scrolling capability, which uses a
>>> temporarily-enabled limited-resolution absolute mode.
>>>
>>> This patch enables this during normal operation, and combines the
>>> absolute packets with the existing relative packets to provide
>>> accurate absolute position and touch reporting.
>>>
>>> It also adds documentation for all known gesture packets and
>>> initialization commands.
>>>
>>> Reviewed-by: Chris Diamand <chris@xxxxxxxxxxx>
>>> Signed-off-by: Richard Pospesel <pospeselr@xxxxxxxxx>
>>> ---
>>> Hi Dmitry, Richard (and others),
>>>
>>> I've tested Richard's latest patch, and can confirm that it works for me.
>>> This
>>> is a resend of that patch, but generated with git-format-patch so
>>> hopefully it
>>> should apply cleanly now. It's a verbatim copy, except I've moved one
>>> blank
>>> line which I missed last time.
>>>
>>> Cheers!
>>> Chris
>>>
>>>   drivers/input/mouse/byd.c          | 565
>>> ++++++++++++++++++++++++-------------
>>>   drivers/input/mouse/psmouse-base.c |   2 +-
>>>   2 files changed, 369 insertions(+), 198 deletions(-)
>>>
>>> diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c
>>> index 9425e0f..fdc243c 100644
>>> --- a/drivers/input/mouse/byd.c
>>> +++ b/drivers/input/mouse/byd.c
>>> @@ -12,10 +12,12 @@
>>>   #include <linux/input.h>
>>>   #include <linux/libps2.h>
>>>   #include <linux/serio.h>
>>> +#include <linux/slab.h>
>>>
>>>   #include "psmouse.h"
>>>   #include "byd.h"
>>>
>>> +/* PS2 Bits */
>>>   #define PS2_Y_OVERFLOW        BIT_MASK(7)
>>>   #define PS2_X_OVERFLOW        BIT_MASK(6)
>>>   #define PS2_Y_SIGN    BIT_MASK(5)
>>> @@ -26,69 +28,249 @@
>>>   #define PS2_LEFT      BIT_MASK(0)
>>>
>>>   /*
>>> - * The touchpad reports gestures in the last byte of each packet. It can
>>> take
>>> - * any of the following values:
>>> + * BYD pad constants
>>>    */
>>>
>>> -/* One-finger scrolling in one of the edge scroll zones. */
>>> -#define BYD_SCROLLUP           0xCA
>>> -#define BYD_SCROLLDOWN         0x36
>>> -#define BYD_SCROLLLEFT         0xCB
>>> -#define BYD_SCROLLRIGHT                0x35
>>> -/* Two-finger scrolling. */
>>> -#define BYD_2DOWN              0x2B
>>> -#define BYD_2UP                        0xD5
>>> -#define BYD_2LEFT              0xD6
>>> -#define BYD_2RIGHT             0x2A
>>> -/* Pinching in or out. */
>>> -#define BYD_ZOOMOUT            0xD8
>>> -#define BYD_ZOOMIN             0x28
>>> -/* Three-finger swipe. */
>>> -#define BYD_3UP                        0xD3
>>> -#define BYD_3DOWN              0x2D
>>> -#define BYD_3LEFT              0xD4
>>> -#define BYD_3RIGHT             0x2C
>>> -/* Four-finger swipe. */
>>> -#define BYD_4UP                        0xCD
>>> -#define BYD_4DOWN              0x33
>>> +/*
>>> + * True device resolution is unknown, however experiments show the
>>> + * resolution is about 111 units/mm.
>>> + * Absolute coordinate packets are in the range 0-255 for both X and Y
>>> + * we pick ABS_X/ABS_Y dimensions which are multiples of 256 and in
>>> + * the right ballpark given the touchpad's physical dimensions and
>>> estimate
>>> + * resolution per spec sheet, device active area dimensions are
>>> + * 101.6 x 60.1 mm.
>>> + */
>>> +#define BYD_PAD_WIDTH          11264
>>> +#define BYD_PAD_HEIGHT         6656
>>> +#define BYD_PAD_RESOLUTION     111
>>>
>>> -int byd_detect(struct psmouse *psmouse, bool set_properties)
>>> +/*
>>> + * Given the above dimensions, relative packets velocity is in multiples
>>> of
>>> + * 1 unit / 11 milliseconds.  We use this dt to estimate distance
>>> traveled
>>> + */
>>> +#define BYD_DT                 11
>>> +/* Time in jiffies used to timeout various touch events (64 ms) */
>>> +#define BYD_TOUCH_TIMEOUT      msecs_to_jiffies(64)
>>> +
>>> +/* BYD commands reverse engineered from windows driver */
>>> +
>>> +/*
>>> + * Swipe gesture from off-pad to on-pad
>>> + *  0 : disable
>>> + *  1 : enable
>>> + */
>>> +#define BYD_CMD_SET_OFFSCREEN_SWIPE            0x10cc
>>> +/*
>>> + * Tap and drag delay time
>>> + *  0 : disable
>>> + *  1 - 8 : least to most delay
>>> + */
>>> +#define BYD_CMD_SET_TAP_DRAG_DELAY_TIME                0x10cf
>>> +/*
>>> + * Physical buttons function mapping
>>> + *  0 : enable
>>> + *  4 : normal
>>> + *  5 : left button custom command
>>> + *  6 : right button custom command
>>> + *  8 : disable
>>> + */
>>> +#define BYD_CMD_SET_PHYSICAL_BUTTONS           0x10d0
>>> +/*
>>> + * Absolute mode (1 byte X/Y resolution)
>>> + *  0 : disable
>>> + *  2 : enable
>>> + */
>>> +#define BYD_CMD_SET_ABSOLUTE_MODE              0x10d1
>>> +/*
>>> + * Two finger scrolling
>>> + *  1 : vertical
>>> + *  2 : horizontal
>>> + *  3 : vertical + horizontal
>>> + *  4 : disable
>>> + */
>>> +#define BYD_CMD_SET_TWO_FINGER_SCROLL          0x10d2
>>> +/*
>>> + * Handedness
>>> + *  1 : right handed
>>> + *  2 : left handed
>>> + */
>>> +#define BYD_CMD_SET_HANDEDNESS                 0x10d3
>>> +/*
>>> + * Tap to click
>>> + *  1 : enable
>>> + *  2 : disable
>>> + */
>>> +#define BYD_CMD_SET_TAP                                0x10d4
>>> +/*
>>> + * Tap and drag
>>> + *  1 : tap and hold to drag
>>> + *  2 : tap and hold to drag + lock
>>> + *  3 : disable
>>> + */
>>> +#define BYD_CMD_SET_TAP_DRAG                   0x10d5
>>> +/*
>>> + * Touch sensitivity
>>> + *  1 - 7 : least to most sensitive
>>> + */
>>> +#define BYD_CMD_SET_TOUCH_SENSITIVITY          0x10d6
>>> +/*
>>> + * One finger scrolling
>>> + *  1 : vertical
>>> + *  2 : horizontal
>>> + *  3 : vertical + horizontal
>>> + *  4 : disable
>>> + */
>>> +#define BYD_CMD_SET_ONE_FINGER_SCROLL          0x10d7
>>> +/*
>>> + * One finger scrolling function
>>> + *  1 : free scrolling
>>> + *  2 : edge motion
>>> + *  3 : free scrolling + edge motion
>>> + *  4 : disable
>>> + */
>>> +#define BYD_CMD_SET_ONE_FINGER_SCROLL_FUNC     0x10d8
>>> +/*
>>> + * Sliding speed
>>> + *  1 - 5 : slowest to fastest
>>> + */
>>> +#define BYD_CMD_SET_SLIDING_SPEED              0x10da
>>> +/*
>>> + * Edge motion
>>> + *  1 : disable
>>> + *  2 : enable when dragging
>>> + *  3 : enable when dragging and pointing
>>> + */
>>> +#define BYD_CMD_SET_EDGE_MOTION                        0x10db
>>> +/*
>>> + * Left edge region size
>>> + *  0 - 7 : smallest to largest width
>>> + */
>>> +#define BYD_CMD_SET_LEFT_EDGE_REGION           0x10dc
>>> +/*
>>> + * Top edge region size
>>> + *  0 - 9 : smallest to largest height
>>> + */
>>> +#define BYD_CMD_SET_TOP_EDGE_REGION            0x10dd
>>> +/*
>>> + * Disregard palm press as clicks
>>> + *  1 - 6 : smallest to largest
>>> + */
>>> +#define BYD_CMD_SET_PALM_CHECK                 0x10de
>>> +/*
>>> + * Right edge region size
>>> + *  0 - 7 : smallest to largest width
>>> + */
>>> +#define BYD_CMD_SET_RIGHT_EDGE_REGION          0x10df
>>> +/*
>>> + * Bottom edge region size
>>> + *  0 - 9 : smallest to largest height
>>> + */
>>> +#define BYD_CMD_SET_BOTTOM_EDGE_REGION         0x10e1
>>> +/*
>>> + * Multitouch gestures
>>> + *  1 : enable
>>> + *  2 : disable
>>> + */
>>> +#define BYD_CMD_SET_MULTITOUCH                 0x10e3
>>> +/*
>>> + * Edge motion speed
>>> + *  0 : control with finger pressure
>>> + *  1 - 9 : slowest to fastest
>>> + */
>>> +#define BYD_CMD_SET_EDGE_MOTION_SPEED          0x10e4
>>> +/*
>>> + * Two finger scolling function
>>> + *  0 : free scrolling
>>> + *  1 : free scrolling (with momentum)
>>> + *  2 : edge motion
>>> + *  3 : free scrolling (with momentum) + edge motion
>>> + *  4 : disable
>>> + */
>>> +#define BYD_CMD_SET_TWO_FINGER_SCROLL_FUNC     0x10e5
>>> +
>>> +/*
>>> + * The touchpad generates a mixture of absolute and relative packets,
>>> indicated
>>> + * by the the last byte of each packet being set to one of the
>>> following:
>>> + */
>>> +#define BYD_PACKET_ABSOLUTE                    0xf8
>>> +#define BYD_PACKET_RELATIVE                    0x00
>>> +/* Multitouch gesture packets */
>>> +#define BYD_PACKET_PINCH_IN                    0xd8
>>> +#define BYD_PACKET_PINCH_OUT                   0x28
>>> +#define BYD_PACKET_ROTATE_CLOCKWISE            0x29
>>> +#define BYD_PACKET_ROTATE_ANTICLOCKWISE                0xd7
>>> +#define BYD_PACKET_TWO_FINGER_SCROLL_RIGHT     0x2a
>>> +#define BYD_PACKET_TWO_FINGER_SCROLL_DOWN      0x2b
>>> +#define BYD_PACKET_TWO_FINGER_SCROLL_UP                0xd5
>>> +#define BYD_PACKET_TWO_FINGER_SCROLL_LEFT      0xd6
>>> +#define BYD_PACKET_THREE_FINGER_SWIPE_RIGHT    0x2c
>>> +#define BYD_PACKET_THREE_FINGER_SWIPE_DOWN     0x2d
>>> +#define BYD_PACKET_THREE_FINGER_SWIPE_UP       0xd3
>>> +#define BYD_PACKET_THREE_FINGER_SWIPE_LEFT     0xd4
>>> +#define BYD_PACKET_FOUR_FINGER_DOWN            0x33
>>> +#define BYD_PACKET_FOUR_FINGER_UP              0xcd
>>> +#define BYD_PACKET_REGION_SCROLL_RIGHT         0x35
>>> +#define BYD_PACKET_REGION_SCROLL_DOWN          0x36
>>> +#define BYD_PACKET_REGION_SCROLL_UP            0xca
>>> +#define BYD_PACKET_REGION_SCROLL_LEFT          0xcb
>>> +#define BYD_PACKET_RIGHT_CORNER_CLICK          0xd2
>>> +#define BYD_PACKET_LEFT_CORNER_CLICK           0x2e
>>> +#define BYD_PACKET_LEFT_AND_RIGHT_CORNER_CLICK 0x2f
>>> +#define BYD_PACKET_ONTO_PAD_SWIPE_RIGHT                0x37
>>> +#define BYD_PACKET_ONTO_PAD_SWIPE_DOWN         0x30
>>> +#define BYD_PACKET_ONTO_PAD_SWIPE_UP           0xd0
>>> +#define BYD_PACKET_ONTO_PAD_SWIPE_LEFT         0xc9
>>> +
>>> +struct byd_data {
>>> +       struct timer_list timer;
>>> +       s32 abs_x;
>>> +       s32 abs_y;
>>> +       typeof(jiffies) last_touch_time;
>>> +       bool btn_left;
>>> +       bool btn_right;
>>> +       bool touch;
>>> +};
>>> +
>>> +static void byd_report_input(struct psmouse *psmouse)
>>>   {
>>> -       struct ps2dev *ps2dev = &psmouse->ps2dev;
>>> -       unsigned char param[4];
>>> +       struct byd_data *priv = psmouse->private;
>>> +       struct input_dev *dev = psmouse->dev;
>>>
>>> -       param[0] = 0x03;
>>> -       param[1] = 0x00;
>>> -       param[2] = 0x00;
>>> -       param[3] = 0x00;
>>> +       input_report_key(dev, BTN_TOUCH, priv->touch);
>>> +       input_report_key(dev, BTN_TOOL_FINGER, priv->touch);
>>>
>>> -       if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>>> -               return -1;
>>> -       if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>>> -               return -1;
>>> -       if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>>> -               return -1;
>>> -       if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>>> -               return -1;
>>> -       if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
>>> -               return -1;
>>> +       input_report_abs(dev, ABS_X, priv->abs_x);
>>> +       input_report_abs(dev, ABS_Y, priv->abs_y);
>>> +       input_report_key(dev, BTN_LEFT, priv->btn_left);
>>> +       input_report_key(dev, BTN_RIGHT, priv->btn_right);
>>>
>>> -       if (param[1] != 0x03 || param[2] != 0x64)
>>> -               return -ENODEV;
>>> +       input_sync(dev);
>>> +}
>>>
>>> -       psmouse_dbg(psmouse, "BYD touchpad detected\n");
>>> +static void byd_clear_touch(unsigned long data)
>>> +{
>>> +       struct psmouse *psmouse = (struct psmouse *)data;
>>> +       struct byd_data *priv = psmouse->private;
>>>
>>> -       if (set_properties) {
>>> -               psmouse->vendor = "BYD";
>>> -               psmouse->name = "TouchPad";
>>> -       }
>>> +       serio_pause_rx(psmouse->ps2dev.serio);
>>> +       priv->touch = false;
>>>
>>> -       return 0;
>>> +       byd_report_input(psmouse);
>>> +
>>> +       serio_continue_rx(psmouse->ps2dev.serio);
>>> +
>>> +       /*
>>> +        * Move cursor back to center of pad when we lose touch - this
>>> +        * specifically improves user experience when moving cursor with
>>> one
>>> +        * finger, and pressing a button with another.
>>> +        */
>>> +       priv->abs_x = BYD_PAD_WIDTH / 2;
>>> +       priv->abs_y = BYD_PAD_HEIGHT / 2;
>>>   }
>>>
>>>   static psmouse_ret_t byd_process_byte(struct psmouse *psmouse)
>>>   {
>>> -       struct input_dev *dev = psmouse->dev;
>>> +       struct byd_data *priv = psmouse->private;
>>>         u8 *pkt = psmouse->packet;
>>>
>>>         if (psmouse->pktcnt > 0 && !(pkt[0] & PS2_ALWAYS_1)) {
>>> @@ -102,53 +284,34 @@ static psmouse_ret_t byd_process_byte(struct
>>> psmouse *psmouse)
>>>
>>>         /* Otherwise, a full packet has been received */
>>>         switch (pkt[3]) {
>>> -       case 0: {
>>> +       case BYD_PACKET_ABSOLUTE:
>>> +               /* Only use absolute packets for the start of movement.
>>> */
>>> +               if (!priv->touch) {
>>> +                       /* needed to detect tap */
>>> +                       typeof(jiffies) tap_time =
>>> +                               priv->last_touch_time +
>>> BYD_TOUCH_TIMEOUT;
>>> +                       priv->touch = time_after(jiffies, tap_time);
>>> +
>>> +                       /* init abs position */
>>> +                       priv->abs_x = pkt[1] * (BYD_PAD_WIDTH / 256);
>>> +                       priv->abs_y = (255 - pkt[2]) * (BYD_PAD_HEIGHT /
>>> 256);
>>> +               }
>>> +               break;
>>> +       case BYD_PACKET_RELATIVE: {
>>>                 /* Standard packet */
>>>                 /* Sign-extend if a sign bit is set. */
>>> -               unsigned int signx = pkt[0] & PS2_X_SIGN ? ~0xFF : 0;
>>> -               unsigned int signy = pkt[0] & PS2_Y_SIGN ? ~0xFF : 0;
>>> -               int dx = signx | (int) pkt[1];
>>> -               int dy = signy | (int) pkt[2];
>>> +               u32 signx = pkt[0] & PS2_X_SIGN ? ~0xFF : 0;
>>> +               u32 signy = pkt[0] & PS2_Y_SIGN ? ~0xFF : 0;
>>> +               s32 dx = signx | (int) pkt[1];
>>> +               s32 dy = signy | (int) pkt[2];
>>>
>>> -               input_report_rel(psmouse->dev, REL_X, dx);
>>> -               input_report_rel(psmouse->dev, REL_Y, -dy);
>>> +               /* Update position based on velocity */
>>> +               priv->abs_x += dx * BYD_DT;
>>> +               priv->abs_y -= dy * BYD_DT;
>>>
>>> -               input_report_key(psmouse->dev, BTN_LEFT, pkt[0] &
>>> PS2_LEFT);
>>> -               input_report_key(psmouse->dev, BTN_RIGHT, pkt[0] &
>>> PS2_RIGHT);
>>> -               input_report_key(psmouse->dev, BTN_MIDDLE, pkt[0] &
>>> PS2_MIDDLE);
>>> +               priv->touch = true;
>>>                 break;
>>>         }
>>> -
>>> -       case BYD_SCROLLDOWN:
>>> -       case BYD_2DOWN:
>>> -               input_report_rel(dev, REL_WHEEL, -1);
>>> -               break;
>>> -
>>> -       case BYD_SCROLLUP:
>>> -       case BYD_2UP:
>>> -               input_report_rel(dev, REL_WHEEL, 1);
>>> -               break;
>>> -
>>> -       case BYD_SCROLLLEFT:
>>> -       case BYD_2LEFT:
>>> -               input_report_rel(dev, REL_HWHEEL, -1);
>>> -               break;
>>> -
>>> -       case BYD_SCROLLRIGHT:
>>> -       case BYD_2RIGHT:
>>> -               input_report_rel(dev, REL_HWHEEL, 1);
>>> -               break;
>>> -
>>> -       case BYD_ZOOMOUT:
>>> -       case BYD_ZOOMIN:
>>> -       case BYD_3UP:
>>> -       case BYD_3DOWN:
>>> -       case BYD_3LEFT:
>>> -       case BYD_3RIGHT:
>>> -       case BYD_4UP:
>>> -       case BYD_4DOWN:
>>> -               break;
>>> -
>>>         default:
>>>                 psmouse_warn(psmouse,
>>>                              "Unrecognized Z: pkt = %02x %02x %02x
>>> %02x\n",
>>> @@ -157,134 +320,76 @@ static psmouse_ret_t byd_process_byte(struct
>>> psmouse *psmouse)
>>>                 return PSMOUSE_BAD_DATA;
>>>         }
>>>
>>> -       input_sync(dev);
>>> +       priv->btn_left = pkt[0] & PS2_LEFT;
>>> +       priv->btn_right = pkt[0] & PS2_RIGHT;
>>>
>>> -       return PSMOUSE_FULL_PACKET;
>>> -}
>>> +       byd_report_input(psmouse);
>>>
>>> -/* Send a sequence of bytes, where each is ACKed before the next is
>>> sent. */
>>> -static int byd_send_sequence(struct psmouse *psmouse, const u8 *seq,
>>> size_t len)
>>> -{
>>> -       unsigned int i;
>>> -
>>> -       for (i = 0; i < len; ++i) {
>>> -               if (ps2_command(&psmouse->ps2dev, NULL, seq[i]))
>>> -                       return -1;
>>> +       /* Reset time since last touch. */
>>> +       if (priv->touch) {
>>> +               priv->last_touch_time = jiffies;
>>> +               mod_timer(&priv->timer, jiffies + BYD_TOUCH_TIMEOUT);
>>>         }
>>> -       return 0;
>>> -}
>>> -
>>> -/* Keep scrolling after fingers are removed. */
>>> -#define SCROLL_INERTIAL                0x01
>>> -#define SCROLL_NO_INERTIAL     0x02
>>> -
>>> -/* Clicking can be done by tapping or pressing. */
>>> -#define CLICK_BOTH             0x01
>>> -/* Clicking can only be done by pressing. */
>>> -#define CLICK_PRESS_ONLY       0x02
>>>
>>> -static int byd_enable(struct psmouse *psmouse)
>>> -{
>>> -       const u8 seq1[] = { 0xE2, 0x00, 0xE0, 0x02, 0xE0 };
>>> -       const u8 seq2[] = {
>>> -               0xD3, 0x01,
>>> -               0xD0, 0x00,
>>> -               0xD0, 0x04,
>>> -               /* Whether clicking is done by tapping or pressing. */
>>> -               0xD4, CLICK_PRESS_ONLY,
>>> -               0xD5, 0x01,
>>> -               0xD7, 0x03,
>>> -               /* Vertical and horizontal one-finger scroll zone
>>> inertia. */
>>> -               0xD8, SCROLL_INERTIAL,
>>> -               0xDA, 0x05,
>>> -               0xDB, 0x02,
>>> -               0xE4, 0x05,
>>> -               0xD6, 0x01,
>>> -               0xDE, 0x04,
>>> -               0xE3, 0x01,
>>> -               0xCF, 0x00,
>>> -               0xD2, 0x03,
>>> -               /* Vertical and horizontal two-finger scrolling inertia.
>>> */
>>> -               0xE5, SCROLL_INERTIAL,
>>> -               0xD9, 0x02,
>>> -               0xD9, 0x07,
>>> -               0xDC, 0x03,
>>> -               0xDD, 0x03,
>>> -               0xDF, 0x03,
>>> -               0xE1, 0x03,
>>> -               0xD1, 0x00,
>>> -               0xCE, 0x00,
>>> -               0xCC, 0x00,
>>> -               0xE0, 0x00,
>>> -               0xE2, 0x01
>>> -       };
>>> -       u8 param[4];
>>> -
>>> -       if (byd_send_sequence(psmouse, seq1, ARRAY_SIZE(seq1)))
>>> -               return -1;
>>> -
>>> -       /* Send a 0x01 command, which should return 4 bytes. */
>>> -       if (ps2_command(&psmouse->ps2dev, param, 0x0401))
>>> -               return -1;
>>> -
>>> -       if (byd_send_sequence(psmouse, seq2, ARRAY_SIZE(seq2)))
>>> -               return -1;
>>> -
>>> -       return 0;
>>> +       return PSMOUSE_FULL_PACKET;
>>>   }
>>>
>>> -/*
>>> - * Send the set of PS/2 commands required to make it identify as an
>>> - * intellimouse with 4-byte instead of 3-byte packets.
>>> - */
>>> -static int byd_send_intellimouse_sequence(struct psmouse *psmouse)
>>> +static int byd_reset_touchpad(struct psmouse *psmouse)
>>>   {
>>>         struct ps2dev *ps2dev = &psmouse->ps2dev;
>>>         u8 param[4];
>>> -       int i;
>>> +       size_t i;
>>> +
>>>         const struct {
>>>                 u16 command;
>>>                 u8 arg;
>>>         } seq[] = {
>>> -               { PSMOUSE_CMD_RESET_BAT, 0 },
>>> -               { PSMOUSE_CMD_RESET_BAT, 0 },
>>> -               { PSMOUSE_CMD_GETID, 0 },
>>> -               { PSMOUSE_CMD_SETSCALE11, 0 },
>>> -               { PSMOUSE_CMD_SETSCALE11, 0 },
>>> -               { PSMOUSE_CMD_SETSCALE11, 0 },
>>> -               { PSMOUSE_CMD_GETINFO, 0 },
>>> -               { PSMOUSE_CMD_SETRES, 0x03 },
>>> +               /*
>>> +                * Intellimouse initialization sequence, to get 4-byte
>>> instead
>>> +                * of 3-byte packets.
>>> +                */
>>>                 { PSMOUSE_CMD_SETRATE, 0xC8 },
>>>                 { PSMOUSE_CMD_SETRATE, 0x64 },
>>>                 { PSMOUSE_CMD_SETRATE, 0x50 },
>>>                 { PSMOUSE_CMD_GETID, 0 },
>>> -               { PSMOUSE_CMD_SETRATE, 0xC8 },
>>> -               { PSMOUSE_CMD_SETRATE, 0xC8 },
>>> -               { PSMOUSE_CMD_SETRATE, 0x50 },
>>> -               { PSMOUSE_CMD_GETID, 0 },
>>> -               { PSMOUSE_CMD_SETRATE, 0x64 },
>>> -               { PSMOUSE_CMD_SETRES, 0x03 },
>>> -               { PSMOUSE_CMD_ENABLE, 0 }
>>> +               { PSMOUSE_CMD_ENABLE, 0 },
>>> +               /*
>>> +                * BYD-specific initialization, which enables absolute
>>> mode and
>>> +                * (if desired), the touchpad's built-in gesture
>>> detection.
>>> +                */
>>> +               { 0x10E2, 0x00 },
>>> +               { 0x10E0, 0x02 },
>>> +               /* The touchpad should reply with 4 seemingly-random
>>> bytes */
>>> +               { 0x14E0, 0x01 },
>>> +               /* Pairs of parameters and values. */
>>> +               { BYD_CMD_SET_HANDEDNESS, 0x01 },
>>> +               { BYD_CMD_SET_PHYSICAL_BUTTONS, 0x04 },
>>> +               { BYD_CMD_SET_TAP, 0x02 },
>>> +               { BYD_CMD_SET_ONE_FINGER_SCROLL, 0x04 },
>>> +               { BYD_CMD_SET_ONE_FINGER_SCROLL_FUNC, 0x04 },
>>> +               { BYD_CMD_SET_EDGE_MOTION, 0x01 },
>>> +               { BYD_CMD_SET_PALM_CHECK, 0x00 },
>>> +               { BYD_CMD_SET_MULTITOUCH, 0x02 },
>>> +               { BYD_CMD_SET_TWO_FINGER_SCROLL, 0x04 },
>>> +               { BYD_CMD_SET_TWO_FINGER_SCROLL_FUNC, 0x04 },
>>> +               { BYD_CMD_SET_LEFT_EDGE_REGION, 0x00 },
>>> +               { BYD_CMD_SET_TOP_EDGE_REGION, 0x00 },
>>> +               { BYD_CMD_SET_RIGHT_EDGE_REGION, 0x00 },
>>> +               { BYD_CMD_SET_BOTTOM_EDGE_REGION, 0x00 },
>>> +               { BYD_CMD_SET_ABSOLUTE_MODE, 0x02 },
>>> +               /* Finalize initialization. */
>>> +               { 0x10E0, 0x00 },
>>> +               { 0x10E2, 0x01 },
>>>         };
>>>
>>> -       memset(param, 0, sizeof(param));
>>>         for (i = 0; i < ARRAY_SIZE(seq); ++i) {
>>> +               memset(param, 0, sizeof(param));
>>>                 param[0] = seq[i].arg;
>>>                 if (ps2_command(ps2dev, param, seq[i].command))
>>> -                       return -1;
>>> +                       return -EIO;
>>>         }
>>>
>>> -       return 0;
>>> -}
>>> -
>>> -static int byd_reset_touchpad(struct psmouse *psmouse)
>>> -{
>>> -       if (byd_send_intellimouse_sequence(psmouse))
>>> -               return -EIO;
>>> -
>>> -       if (byd_enable(psmouse))
>>> -               return -EIO;
>>> -
>>> +       psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
>>>         return 0;
>>>   }
>>>
>>> @@ -314,9 +419,50 @@ static int byd_reconnect(struct psmouse *psmouse)
>>>         return 0;
>>>   }
>>>
>>> +static void byd_disconnect(struct psmouse *psmouse)
>>> +{
>>> +       struct byd_data *priv = psmouse->private;
>>> +
>>> +       if (priv) {
>>> +               del_timer(&priv->timer);
>>> +               kfree(psmouse->private);
>>> +               psmouse->private = NULL;
>>> +       }
>>> +}
>>> +
>>> +int byd_detect(struct psmouse *psmouse, bool set_properties)
>>> +{
>>> +       struct ps2dev *ps2dev = &psmouse->ps2dev;
>>> +       u8 param[4] = {0x03, 0x00, 0x00, 0x00};
>>> +
>>> +       if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>>> +               return -1;
>>> +       if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>>> +               return -1;
>>> +       if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>>> +               return -1;
>>> +       if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>>> +               return -1;
>>> +       if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
>>> +               return -1;
>>> +
>>> +       if (param[1] != 0x03 || param[2] != 0x64)
>>> +               return -ENODEV;
>>> +
>>> +       psmouse_dbg(psmouse, "BYD touchpad detected\n");
>>> +
>>> +       if (set_properties) {
>>> +               psmouse->vendor = "BYD";
>>> +               psmouse->name = "TouchPad";
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>>   int byd_init(struct psmouse *psmouse)
>>>   {
>>>         struct input_dev *dev = psmouse->dev;
>>> +       struct byd_data *priv;
>>>
>>>         if (psmouse_reset(psmouse))
>>>                 return -EIO;
>>> @@ -324,14 +470,39 @@ int byd_init(struct psmouse *psmouse)
>>>         if (byd_reset_touchpad(psmouse))
>>>                 return -EIO;
>>>
>>> +       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
>>> +       if (!priv)
>>> +               return -ENOMEM;
>>> +
>>> +       memset(priv, 0, sizeof(*priv));
>>> +       setup_timer(&priv->timer, byd_clear_touch, (unsigned long)
>>> psmouse);
>>> +
>>> +       psmouse->private = priv;
>>> +       psmouse->disconnect = byd_disconnect;
>>>         psmouse->reconnect = byd_reconnect;
>>>         psmouse->protocol_handler = byd_process_byte;
>>>         psmouse->pktsize = 4;
>>>         psmouse->resync_time = 0;
>>>
>>> -       __set_bit(BTN_MIDDLE, dev->keybit);
>>> -       __set_bit(REL_WHEEL, dev->relbit);
>>> -       __set_bit(REL_HWHEEL, dev->relbit);
>>> +       __set_bit(INPUT_PROP_POINTER, dev->propbit);
>>> +       /* Touchpad */
>>> +       __set_bit(BTN_TOUCH, dev->keybit);
>>> +       __set_bit(BTN_TOOL_FINGER, dev->keybit);
>>> +       /* Buttons */
>>> +       __set_bit(BTN_LEFT, dev->keybit);
>>> +       __set_bit(BTN_RIGHT, dev->keybit);
>>> +       __clear_bit(BTN_MIDDLE, dev->keybit);
>>> +
>>> +       /* Absolute position */
>>> +       __set_bit(EV_ABS, dev->evbit);
>>> +       input_set_abs_params(dev, ABS_X, 0, BYD_PAD_WIDTH, 0, 0);
>>> +       input_set_abs_params(dev, ABS_Y, 0, BYD_PAD_HEIGHT, 0, 0);
>>> +       input_abs_set_res(dev, ABS_X, BYD_PAD_RESOLUTION);
>>> +       input_abs_set_res(dev, ABS_Y, BYD_PAD_RESOLUTION);
>>> +       /* No relative support */
>>> +       __clear_bit(EV_REL, dev->evbit);
>>> +       __clear_bit(REL_X, dev->relbit);
>>> +       __clear_bit(REL_Y, dev->relbit);
>>>
>>>         return 0;
>>>   }
>>> diff --git a/drivers/input/mouse/psmouse-base.c
>>> b/drivers/input/mouse/psmouse-base.c
>>> index 39d1bec..5784e20 100644
>>> --- a/drivers/input/mouse/psmouse-base.c
>>> +++ b/drivers/input/mouse/psmouse-base.c
>>> @@ -846,7 +846,7 @@ static const struct psmouse_protocol
>>> psmouse_protocols[] = {
>>>   #ifdef CONFIG_MOUSE_PS2_BYD
>>>         {
>>>                 .type           = PSMOUSE_BYD,
>>> -               .name           = "BydPS/2",
>>> +               .name           = "BYDPS/2",
>>>                 .alias          = "byd",
>>>                 .detect         = byd_detect,
>>>                 .init           = byd_init,
>>>
>



-- 
Dmitry
--
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