Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/dtor/input

Pull input subsystem updates from Dmitry Torokhov:
 "Mostly small fixups to PS/2 tochpad drivers (ALPS, Elantech,
  Synaptics) to better deal with specific hardware"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: elantech - update the documentation
  Input: elantech - provide a sysfs knob for crc_enabled
  Input: elantech - report the middle button of the touchpad
  Input: alps - ignore bad data on Dell Latitudes E6440 and E7440
  Input: alps - allow up to 2 invalid packets without resetting device
  Input: alps - ignore potential bare packets when device is out of sync
  Input: elantech - fix crc_enabled for Fujitsu H730
  Input: elantech - use elantech_report_trackpoint for hardware v4 too
  Input: twl4030-pwrbutton - ensure a wakeup event is recorded.
  Input: synaptics - add min/max quirk for Lenovo T440s
  • Loading branch information
torvalds committed Nov 14, 2014
2 parents 0861fd1 + c6c748e commit 56c381f
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 13 deletions.
81 changes: 75 additions & 6 deletions Documentation/input/elantech.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,38 @@ Contents
7.2.1 Status packet
7.2.2 Head packet
7.2.3 Motion packet
8. Trackpoint (for Hardware version 3 and 4)
8.1 Registers
8.2 Native relative mode 6 byte packet format
8.2.1 Status Packet



1. Introduction
~~~~~~~~~~~~

Currently the Linux Elantech touchpad driver is aware of two different
hardware versions unimaginatively called version 1 and version 2. Version 1
is found in "older" laptops and uses 4 bytes per packet. Version 2 seems to
be introduced with the EeePC and uses 6 bytes per packet, and provides
additional features such as position of two fingers, and width of the touch.
Currently the Linux Elantech touchpad driver is aware of four different
hardware versions unimaginatively called version 1,version 2, version 3
and version 4. Version 1 is found in "older" laptops and uses 4 bytes per
packet. Version 2 seems to be introduced with the EeePC and uses 6 bytes
per packet, and provides additional features such as position of two fingers,
and width of the touch. Hardware version 3 uses 6 bytes per packet (and
for 2 fingers the concatenation of two 6 bytes packets) and allows tracking
of up to 3 fingers. Hardware version 4 uses 6 bytes per packet, and can
combine a status packet with multiple head or motion packets. Hardware version
4 allows tracking up to 5 fingers.

Some Hardware version 3 and version 4 also have a trackpoint which uses a
separate packet format. It is also 6 bytes per packet.

The driver tries to support both hardware versions and should be compatible
with the Xorg Synaptics touchpad driver and its graphical configuration
utilities.

Note that a mouse button is also associated with either the touchpad or the
trackpoint when a trackpoint is available. Disabling the Touchpad in xorg
(TouchPadOff=0) will also disable the buttons associated with the touchpad.

Additionally the operation of the touchpad can be altered by adjusting the
contents of some of its internal registers. These registers are represented
by the driver as sysfs entries under /sys/bus/serio/drivers/psmouse/serio?
Expand All @@ -78,7 +94,7 @@ completeness sake.
2. Extra knobs
~~~~~~~~~~~

Currently the Linux Elantech touchpad driver provides two extra knobs under
Currently the Linux Elantech touchpad driver provides three extra knobs under
/sys/bus/serio/drivers/psmouse/serio? for the user.

* debug
Expand Down Expand Up @@ -112,6 +128,20 @@ Currently the Linux Elantech touchpad driver provides two extra knobs under
data consistency checking can be done. For now checking is disabled by
default. Currently even turning it on will do nothing.

* crc_enabled

Sets crc_enabled to 0/1. The name "crc_enabled" is the official name of
this integrity check, even though it is not an actual cyclic redundancy
check.

Depending on the state of crc_enabled, certain basic data integrity
verification is done by the driver on hardware version 3 and 4. The
driver will reject any packet that appears corrupted. Using this knob,
The state of crc_enabled can be altered with this knob.

Reading the crc_enabled value will show the active value. Echoing
"0" or "1" to this file will set the state to "0" or "1".

/////////////////////////////////////////////////////////////////////////////

3. Differentiating hardware versions
Expand Down Expand Up @@ -746,3 +776,42 @@ byte 5:

byte 0 ~ 2 for one finger
byte 3 ~ 5 for another


8. Trackpoint (for Hardware version 3 and 4)
=========================================
8.1 Registers
~~~~~~~~~
No special registers have been identified.

8.2 Native relative mode 6 byte packet format
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8.2.1 Status Packet
~~~~~~~~~~~~~

byte 0:
bit 7 6 5 4 3 2 1 0
0 0 sx sy 0 M R L
byte 1:
bit 7 6 5 4 3 2 1 0
~sx 0 0 0 0 0 0 0
byte 2:
bit 7 6 5 4 3 2 1 0
~sy 0 0 0 0 0 0 0
byte 3:
bit 7 6 5 4 3 2 1 0
0 0 ~sy ~sx 0 1 1 0
byte 4:
bit 7 6 5 4 3 2 1 0
x7 x6 x5 x4 x3 x2 x1 x0
byte 5:
bit 7 6 5 4 3 2 1 0
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.
~sx is the inverse of sx, ~sy is the inverse of sy.
The sign of y is opposite to what the input driver
expects for a relative movement
1 change: 1 addition & 0 deletions drivers/input/misc/twl4030-pwrbutton.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev)
}

platform_set_drvdata(pdev, pwr);
device_init_wakeup(&pdev->dev, true);

return 0;
}
Expand Down
28 changes: 26 additions & 2 deletions drivers/input/mouse/alps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1156,7 +1156,13 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;

if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
/*
* Check if we are dealing with a bare PS/2 packet, presumably from
* a device connected to the external PS/2 port. Because bare PS/2
* protocol does not have enough constant bits to self-synchronize
* properly we only do this if the device is fully synchronized.
*/
if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) {
if (psmouse->pktcnt == 3) {
alps_report_bare_ps2_packet(psmouse, psmouse->packet,
true);
Expand All @@ -1180,12 +1186,27 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
}

/* Bytes 2 - pktsize should have 0 in the highest bit */
if ((priv->proto_version < ALPS_PROTO_V5) &&
if (priv->proto_version < ALPS_PROTO_V5 &&
psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
(psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
psmouse->pktcnt - 1,
psmouse->packet[psmouse->pktcnt - 1]);

if (priv->proto_version == ALPS_PROTO_V3 &&
psmouse->pktcnt == psmouse->pktsize) {
/*
* Some Dell boxes, such as Latitude E6440 or E7440
* with closed lid, quite often smash last byte of
* otherwise valid packet with 0xff. Given that the
* next packet is very likely to be valid let's
* report PSMOUSE_FULL_PACKET but not process data,
* rather than reporting PSMOUSE_BAD_DATA and
* filling the logs.
*/
return PSMOUSE_FULL_PACKET;
}

return PSMOUSE_BAD_DATA;
}

Expand Down Expand Up @@ -2389,6 +2410,9 @@ int alps_init(struct psmouse *psmouse)
/* We are having trouble resyncing ALPS touchpads so disable it for now */
psmouse->resync_time = 0;

/* Allow 2 invalid packets without resetting device */
psmouse->resetafter = psmouse->pktsize * 2;

return 0;

init_fail:
Expand Down
56 changes: 53 additions & 3 deletions drivers/input/mouse/elantech.c
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ static void elantech_input_sync_v4(struct psmouse *psmouse)
} else {
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_mt_report_pointer_emulation(dev, true);
Expand Down Expand Up @@ -792,6 +793,9 @@ static int elantech_packet_check_v4(struct psmouse *psmouse)
unsigned char packet_type = packet[3] & 0x03;
bool sanity_check;

if ((packet[3] & 0x0f) == 0x06)
return PACKET_TRACKPOINT;

/*
* Sanity check based on the constant bits of a packet.
* The constant bits change depending on the value of
Expand Down Expand Up @@ -877,10 +881,19 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)

case 4:
packet_type = elantech_packet_check_v4(psmouse);
if (packet_type == PACKET_UNKNOWN)
switch (packet_type) {
case PACKET_UNKNOWN:
return PSMOUSE_BAD_DATA;

elantech_report_absolute_v4(psmouse, packet_type);
case PACKET_TRACKPOINT:
elantech_report_trackpoint(psmouse, packet_type);
break;

default:
elantech_report_absolute_v4(psmouse, packet_type);
break;
}

break;
}

Expand Down Expand Up @@ -1119,6 +1132,22 @@ static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
}
}

/*
* Some hw_version 4 models do have a middle button
*/
static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
{
/* Fujitsu H730 has a middle button */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"),
},
},
#endif
{ }
};

/*
* Set the appropriate event bits for the input subsystem
*/
Expand All @@ -1138,6 +1167,8 @@ static int elantech_set_input_params(struct psmouse *psmouse)
__clear_bit(EV_REL, dev->evbit);

__set_bit(BTN_LEFT, dev->keybit);
if (dmi_check_system(elantech_dmi_has_middle_button))
__set_bit(BTN_MIDDLE, dev->keybit);
__set_bit(BTN_RIGHT, dev->keybit);

__set_bit(BTN_TOUCH, dev->keybit);
Expand Down Expand Up @@ -1299,6 +1330,7 @@ ELANTECH_INT_ATTR(reg_25, 0x25);
ELANTECH_INT_ATTR(reg_26, 0x26);
ELANTECH_INT_ATTR(debug, 0);
ELANTECH_INT_ATTR(paritycheck, 0);
ELANTECH_INT_ATTR(crc_enabled, 0);

static struct attribute *elantech_attrs[] = {
&psmouse_attr_reg_07.dattr.attr,
Expand All @@ -1313,6 +1345,7 @@ static struct attribute *elantech_attrs[] = {
&psmouse_attr_reg_26.dattr.attr,
&psmouse_attr_debug.dattr.attr,
&psmouse_attr_paritycheck.dattr.attr,
&psmouse_attr_crc_enabled.dattr.attr,
NULL
};

Expand Down Expand Up @@ -1438,6 +1471,22 @@ static int elantech_reconnect(struct psmouse *psmouse)
return 0;
}

/*
* Some hw_version 4 models do not work with crc_disabled
*/
static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
{
/* Fujitsu H730 does not work with crc_enabled == 0 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"),
},
},
#endif
{ }
};

/*
* Some hw_version 3 models go into error state when we try to set
* bit 3 and/or bit 1 of r10.
Expand Down Expand Up @@ -1513,7 +1562,8 @@ static int elantech_set_properties(struct elantech_data *etd)
* The signatures of v3 and v4 packets change depending on the
* value of this hardware flag.
*/
etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000);
etd->crc_enabled = (etd->fw_version & 0x4000) == 0x4000 ||
dmi_check_system(elantech_dmi_force_crc_enabled);

/* Enable real hardware resolution on hw_version 3 ? */
etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table);
Expand Down
5 changes: 3 additions & 2 deletions drivers/input/mouse/synaptics.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ static const struct min_max_quirk min_max_pnpid_table[] = {
1232, 5710, 1156, 4696
},
{
(const char * const []){"LEN0034", "LEN0036", "LEN2002",
"LEN2004", NULL},
(const char * const []){"LEN0034", "LEN0036", "LEN0039",
"LEN2002", "LEN2004", NULL},
1024, 5112, 2024, 4832
},
{
Expand All @@ -163,6 +163,7 @@ static const char * const topbuttonpad_pnp_ids[] = {
"LEN0036", /* T440 */
"LEN0037",
"LEN0038",
"LEN0039", /* T440s */
"LEN0041",
"LEN0042", /* Yoga */
"LEN0045",
Expand Down

0 comments on commit 56c381f

Please sign in to comment.