2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Synaptics TouchPad PS/2 mouse driver
|
|
|
|
*
|
|
|
|
* 2003 Dmitry Torokhov <dtor@mail.ru>
|
|
|
|
* Added support for pass-through port. Special thanks to Peter Berg Larsen
|
|
|
|
* for explaining various Synaptics quirks.
|
|
|
|
*
|
|
|
|
* 2003 Peter Osterlund <petero2@telia.com>
|
|
|
|
* Ported to 2.5 input device infrastructure.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
|
|
|
|
* start merging tpconfig and gpm code to a xfree-input module
|
|
|
|
* adding some changes and extensions (ex. 3rd and 4th button)
|
|
|
|
*
|
|
|
|
* Copyright (c) 1997 C. Scott Ananian <cananian@alumni.priceton.edu>
|
|
|
|
* Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com>
|
|
|
|
* code for the special synaptics commands (from the tpconfig-source)
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License version 2 as published by
|
|
|
|
* the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* Trademarks are the property of their respective owners.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
2011-12-12 16:05:53 +08:00
|
|
|
#include <linux/delay.h>
|
2009-12-04 15:21:14 +08:00
|
|
|
#include <linux/dmi.h>
|
2010-12-22 01:11:25 +08:00
|
|
|
#include <linux/input/mt.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/serio.h>
|
|
|
|
#include <linux/libps2.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 16:04:11 +08:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include "psmouse.h"
|
|
|
|
#include "synaptics.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
|
|
|
|
* section 2.3.2, which says that they should be valid regardless of the
|
|
|
|
* actual size of the sensor.
|
2010-05-11 14:06:52 +08:00
|
|
|
* Note that newer firmware allows querying device for maximum useable
|
|
|
|
* coordinates.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2012-07-25 14:54:11 +08:00
|
|
|
#define XMIN 0
|
|
|
|
#define XMAX 6143
|
|
|
|
#define YMIN 0
|
|
|
|
#define YMAX 6143
|
2005-04-17 06:20:36 +08:00
|
|
|
#define XMIN_NOMINAL 1472
|
|
|
|
#define XMAX_NOMINAL 5472
|
|
|
|
#define YMIN_NOMINAL 1408
|
|
|
|
#define YMAX_NOMINAL 4448
|
|
|
|
|
2012-07-25 14:54:11 +08:00
|
|
|
/* Size in bits of absolute position values reported by the hardware */
|
|
|
|
#define ABS_POS_BITS 13
|
|
|
|
|
|
|
|
/*
|
2012-09-29 01:29:21 +08:00
|
|
|
* These values should represent the absolute maximum value that will
|
|
|
|
* be reported for a positive position value. Some Synaptics firmware
|
|
|
|
* uses this value to indicate a finger near the edge of the touchpad
|
|
|
|
* whose precise position cannot be determined.
|
|
|
|
*
|
|
|
|
* At least one touchpad is known to report positions in excess of this
|
|
|
|
* value which are actually negative values truncated to the 13-bit
|
|
|
|
* reporting range. These values have never been observed to be lower
|
|
|
|
* than 8184 (i.e. -8), so we treat all values greater than 8176 as
|
|
|
|
* negative and any other value as positive.
|
2012-07-25 14:54:11 +08:00
|
|
|
*/
|
2012-09-29 01:29:21 +08:00
|
|
|
#define X_MAX_POSITIVE 8176
|
|
|
|
#define Y_MAX_POSITIVE 8176
|
2007-03-10 14:39:54 +08:00
|
|
|
|
2015-04-06 04:44:12 +08:00
|
|
|
/* maximum ABS_MT_POSITION displacement (in mm) */
|
|
|
|
#define DMAX 10
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*****************************************************************************
|
2007-03-10 14:39:54 +08:00
|
|
|
* Stuff we need even when we do not want native Synaptics support
|
2005-04-17 06:20:36 +08:00
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
2007-03-10 14:39:54 +08:00
|
|
|
* Set the synaptics touchpad mode byte by special commands
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2007-03-10 14:39:54 +08:00
|
|
|
static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-03-10 14:39:54 +08:00
|
|
|
unsigned char param[1];
|
|
|
|
|
|
|
|
if (psmouse_sliced_command(psmouse, mode))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -1;
|
2007-03-10 14:39:54 +08:00
|
|
|
param[0] = SYN_PS_SET_MODE2;
|
|
|
|
if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-10 10:13:20 +08:00
|
|
|
int synaptics_detect(struct psmouse *psmouse, bool set_properties)
|
2007-03-10 14:39:54 +08:00
|
|
|
{
|
|
|
|
struct ps2dev *ps2dev = &psmouse->ps2dev;
|
|
|
|
unsigned char param[4];
|
|
|
|
|
|
|
|
param[0] = 0;
|
|
|
|
|
|
|
|
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
|
|
|
|
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
|
|
|
|
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
|
|
|
|
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
|
|
|
|
ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
|
|
|
|
|
|
|
|
if (param[1] != 0x47)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
if (set_properties) {
|
|
|
|
psmouse->vendor = "Synaptics";
|
|
|
|
psmouse->name = "TouchPad";
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void synaptics_reset(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
/* reset touchpad back to relative mode, gestures enabled */
|
|
|
|
synaptics_mode_cmd(psmouse, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
|
2014-07-15 01:26:56 +08:00
|
|
|
|
|
|
|
static bool cr48_profile_sensor;
|
|
|
|
|
2015-03-09 13:29:15 +08:00
|
|
|
#define ANY_BOARD_ID 0
|
2014-05-20 13:54:09 +08:00
|
|
|
struct min_max_quirk {
|
|
|
|
const char * const *pnp_ids;
|
2015-03-09 13:29:15 +08:00
|
|
|
struct {
|
|
|
|
unsigned long int min, max;
|
|
|
|
} board_id;
|
2014-05-20 13:54:09 +08:00
|
|
|
int x_min, x_max, y_min, y_max;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct min_max_quirk min_max_pnpid_table[] = {
|
|
|
|
{
|
|
|
|
(const char * const []){"LEN0033", NULL},
|
2015-03-09 13:29:15 +08:00
|
|
|
{ANY_BOARD_ID, ANY_BOARD_ID},
|
2014-05-20 13:54:09 +08:00
|
|
|
1024, 5052, 2258, 4832
|
|
|
|
},
|
|
|
|
{
|
2015-03-09 13:29:07 +08:00
|
|
|
(const char * const []){"LEN0042", NULL},
|
2015-03-09 13:29:15 +08:00
|
|
|
{ANY_BOARD_ID, ANY_BOARD_ID},
|
2014-05-20 13:54:09 +08:00
|
|
|
1232, 5710, 1156, 4696
|
|
|
|
},
|
|
|
|
{
|
2015-01-20 08:29:25 +08:00
|
|
|
(const char * const []){"LEN0034", "LEN0036", "LEN0037",
|
|
|
|
"LEN0039", "LEN2002", "LEN2004",
|
|
|
|
NULL},
|
2015-03-09 13:29:25 +08:00
|
|
|
{ANY_BOARD_ID, 2961},
|
2014-05-20 13:54:09 +08:00
|
|
|
1024, 5112, 2024, 4832
|
|
|
|
},
|
2015-06-09 01:17:32 +08:00
|
|
|
{
|
|
|
|
(const char * const []){"LEN2000", NULL},
|
|
|
|
{ANY_BOARD_ID, ANY_BOARD_ID},
|
|
|
|
1024, 5113, 2021, 4832
|
|
|
|
},
|
2014-05-20 13:54:09 +08:00
|
|
|
{
|
|
|
|
(const char * const []){"LEN2001", NULL},
|
2015-03-09 13:29:15 +08:00
|
|
|
{ANY_BOARD_ID, ANY_BOARD_ID},
|
2014-05-20 13:54:09 +08:00
|
|
|
1024, 5022, 2508, 4832
|
|
|
|
},
|
Input: synaptics - add quirk for Thinkpad E440
Its ClickPad shares PNP ID "LEN2006" with the one in model E540 which is
already handled by the driver (both are Haswell iterations of the Edge
line, launched in 2014) but the dimensions it reports are different:
$ sudo ./touchpad-edge-detector /dev/input/event3
Touchpad SynPS/2 Synaptics TouchPad on /dev/input/event3
Move one finger around the touchpad to detect the actual edges
Kernel says: x [1472..5044], y [1408..3398]
Touchpad sends: x [1024..5045], y [2457..4832] /^C
Fortunately we can use the board ID, which is also different, to
distinguish among them.
$ dmesg | grep -i synaptics
psmouse serio1: synaptics: Touchpad model: 1, fw: 8.1, id: 0x1e2b1,
caps: 0xd001a3/0x940300/0x127c00, board id: 2691, fw id: 1494646
psmouse serio1: synaptics: serio: Synaptics pass-through port at
isa0060/serio1/input0
input: SynPS/2 Synaptics TouchPad as
/devices/platform/i8042/serio1/input/input4
Board ID in E540 is 2722:
psmouse serio1: synaptics: Touchpad model: 1, fw: 8.1, id: 0x1e2b1,
caps: 0xd001a3/0x940300/0x127c00, board id: 2722, fw id: 1484859
(from https://launchpadlibrarian.net/179702965/BootDmesg.txt)
Signed-off-by: Ramiro Morales <cramm0@gmail.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
2015-03-24 01:33:07 +08:00
|
|
|
{
|
|
|
|
(const char * const []){"LEN2006", NULL},
|
|
|
|
{2691, 2691},
|
2015-03-26 06:53:04 +08:00
|
|
|
1024, 5045, 2457, 4832
|
Input: synaptics - add quirk for Thinkpad E440
Its ClickPad shares PNP ID "LEN2006" with the one in model E540 which is
already handled by the driver (both are Haswell iterations of the Edge
line, launched in 2014) but the dimensions it reports are different:
$ sudo ./touchpad-edge-detector /dev/input/event3
Touchpad SynPS/2 Synaptics TouchPad on /dev/input/event3
Move one finger around the touchpad to detect the actual edges
Kernel says: x [1472..5044], y [1408..3398]
Touchpad sends: x [1024..5045], y [2457..4832] /^C
Fortunately we can use the board ID, which is also different, to
distinguish among them.
$ dmesg | grep -i synaptics
psmouse serio1: synaptics: Touchpad model: 1, fw: 8.1, id: 0x1e2b1,
caps: 0xd001a3/0x940300/0x127c00, board id: 2691, fw id: 1494646
psmouse serio1: synaptics: serio: Synaptics pass-through port at
isa0060/serio1/input0
input: SynPS/2 Synaptics TouchPad as
/devices/platform/i8042/serio1/input/input4
Board ID in E540 is 2722:
psmouse serio1: synaptics: Touchpad model: 1, fw: 8.1, id: 0x1e2b1,
caps: 0xd001a3/0x940300/0x127c00, board id: 2722, fw id: 1484859
(from https://launchpadlibrarian.net/179702965/BootDmesg.txt)
Signed-off-by: Ramiro Morales <cramm0@gmail.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
2015-03-24 01:33:07 +08:00
|
|
|
},
|
2014-11-17 09:23:40 +08:00
|
|
|
{
|
|
|
|
(const char * const []){"LEN2006", NULL},
|
2015-03-09 13:29:15 +08:00
|
|
|
{ANY_BOARD_ID, ANY_BOARD_ID},
|
2014-11-17 09:23:40 +08:00
|
|
|
1264, 5675, 1171, 4688
|
|
|
|
},
|
2014-05-20 13:54:09 +08:00
|
|
|
{ }
|
|
|
|
};
|
|
|
|
|
2014-04-20 13:26:41 +08:00
|
|
|
/* This list has been kindly provided by Synaptics. */
|
|
|
|
static const char * const topbuttonpad_pnp_ids[] = {
|
|
|
|
"LEN0017",
|
|
|
|
"LEN0018",
|
|
|
|
"LEN0019",
|
|
|
|
"LEN0023",
|
|
|
|
"LEN002A",
|
|
|
|
"LEN002B",
|
|
|
|
"LEN002C",
|
|
|
|
"LEN002D",
|
|
|
|
"LEN002E",
|
|
|
|
"LEN0033", /* Helix */
|
2014-05-20 13:54:09 +08:00
|
|
|
"LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */
|
2014-04-20 13:26:41 +08:00
|
|
|
"LEN0035", /* X240 */
|
|
|
|
"LEN0036", /* T440 */
|
2015-01-20 08:29:25 +08:00
|
|
|
"LEN0037", /* X1 Carbon 2nd */
|
2014-04-20 13:26:41 +08:00
|
|
|
"LEN0038",
|
2014-11-07 01:27:11 +08:00
|
|
|
"LEN0039", /* T440s */
|
2014-04-20 13:26:41 +08:00
|
|
|
"LEN0041",
|
|
|
|
"LEN0042", /* Yoga */
|
|
|
|
"LEN0045",
|
|
|
|
"LEN0047",
|
|
|
|
"LEN0049",
|
2015-06-09 01:17:32 +08:00
|
|
|
"LEN2000", /* S540 */
|
2014-05-20 13:54:09 +08:00
|
|
|
"LEN2001", /* Edge E431 */
|
2014-07-15 08:12:21 +08:00
|
|
|
"LEN2002", /* Edge E531 */
|
2014-04-20 13:26:41 +08:00
|
|
|
"LEN2003",
|
|
|
|
"LEN2004", /* L440 */
|
|
|
|
"LEN2005",
|
Input: synaptics - add quirk for Thinkpad E440
Its ClickPad shares PNP ID "LEN2006" with the one in model E540 which is
already handled by the driver (both are Haswell iterations of the Edge
line, launched in 2014) but the dimensions it reports are different:
$ sudo ./touchpad-edge-detector /dev/input/event3
Touchpad SynPS/2 Synaptics TouchPad on /dev/input/event3
Move one finger around the touchpad to detect the actual edges
Kernel says: x [1472..5044], y [1408..3398]
Touchpad sends: x [1024..5045], y [2457..4832] /^C
Fortunately we can use the board ID, which is also different, to
distinguish among them.
$ dmesg | grep -i synaptics
psmouse serio1: synaptics: Touchpad model: 1, fw: 8.1, id: 0x1e2b1,
caps: 0xd001a3/0x940300/0x127c00, board id: 2691, fw id: 1494646
psmouse serio1: synaptics: serio: Synaptics pass-through port at
isa0060/serio1/input0
input: SynPS/2 Synaptics TouchPad as
/devices/platform/i8042/serio1/input/input4
Board ID in E540 is 2722:
psmouse serio1: synaptics: Touchpad model: 1, fw: 8.1, id: 0x1e2b1,
caps: 0xd001a3/0x940300/0x127c00, board id: 2722, fw id: 1484859
(from https://launchpadlibrarian.net/179702965/BootDmesg.txt)
Signed-off-by: Ramiro Morales <cramm0@gmail.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
2015-03-24 01:33:07 +08:00
|
|
|
"LEN2006", /* Edge E440/E540 */
|
2014-04-20 13:26:41 +08:00
|
|
|
"LEN2007",
|
|
|
|
"LEN2008",
|
|
|
|
"LEN2009",
|
|
|
|
"LEN200A",
|
|
|
|
"LEN200B",
|
|
|
|
NULL
|
|
|
|
};
|
2007-03-10 14:39:54 +08:00
|
|
|
|
2014-12-30 06:43:44 +08:00
|
|
|
/* This list has been kindly provided by Synaptics. */
|
|
|
|
static const char * const forcepad_pnp_ids[] = {
|
|
|
|
"SYN300D",
|
|
|
|
"SYN3014",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2007-03-10 14:39:54 +08:00
|
|
|
/*****************************************************************************
|
|
|
|
* Synaptics communications functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
2012-05-11 13:32:00 +08:00
|
|
|
/*
|
|
|
|
* Synaptics touchpads report the y coordinate from bottom to top, which is
|
|
|
|
* opposite from what userspace expects.
|
|
|
|
* This function is used to invert y before reporting.
|
|
|
|
*/
|
|
|
|
static int synaptics_invert_y(int y)
|
|
|
|
{
|
|
|
|
return YMAX_NOMINAL + YMIN_NOMINAL - y;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2007-03-10 14:39:54 +08:00
|
|
|
* Send a command to the synpatics touchpad by special commands
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2007-03-10 14:39:54 +08:00
|
|
|
static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-03-10 14:39:54 +08:00
|
|
|
if (psmouse_sliced_command(psmouse, c))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -1;
|
2007-03-10 14:39:54 +08:00
|
|
|
if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read the model-id bytes from the touchpad
|
|
|
|
* see also SYN_MODEL_* macros
|
|
|
|
*/
|
|
|
|
static int synaptics_model_id(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
unsigned char mi[3];
|
|
|
|
|
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_MODEL, mi))
|
|
|
|
return -1;
|
|
|
|
priv->model_id = (mi[0]<<16) | (mi[1]<<8) | mi[2];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-03-09 13:34:03 +08:00
|
|
|
static int synaptics_more_extended_queries(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
unsigned char buf[3];
|
|
|
|
|
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_MEXT_CAPAB_10, buf))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
priv->ext_cap_10 = (buf[0]<<16) | (buf[1]<<8) | buf[2];
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-07-08 09:08:51 +08:00
|
|
|
/*
|
2015-03-09 13:34:03 +08:00
|
|
|
* Read the board id and the "More Extended Queries" from the touchpad
|
2012-07-08 09:08:51 +08:00
|
|
|
* The board id is encoded in the "QUERY MODES" response
|
|
|
|
*/
|
2015-03-09 13:34:03 +08:00
|
|
|
static int synaptics_query_modes(struct psmouse *psmouse)
|
2012-07-08 09:08:51 +08:00
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
unsigned char bid[3];
|
|
|
|
|
2015-03-09 13:33:36 +08:00
|
|
|
/* firmwares prior 7.5 have no board_id encoded */
|
|
|
|
if (SYN_ID_FULL(priv->identity) < 0x705)
|
|
|
|
return 0;
|
|
|
|
|
2012-07-08 09:08:51 +08:00
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid))
|
|
|
|
return -1;
|
|
|
|
priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1];
|
2015-03-09 13:34:03 +08:00
|
|
|
|
|
|
|
if (SYN_MEXT_CAP_BIT(bid[0]))
|
|
|
|
return synaptics_more_extended_queries(psmouse);
|
|
|
|
|
2012-07-08 09:08:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read the firmware id from the touchpad
|
|
|
|
*/
|
|
|
|
static int synaptics_firmware_id(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
unsigned char fwid[3];
|
|
|
|
|
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_FIRMWARE_ID, fwid))
|
|
|
|
return -1;
|
|
|
|
priv->firmware_id = (fwid[0] << 16) | (fwid[1] << 8) | fwid[2];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Read the capability-bits from the touchpad
|
|
|
|
* see also the SYN_CAP_* macros
|
|
|
|
*/
|
|
|
|
static int synaptics_capability(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
unsigned char cap[3];
|
|
|
|
|
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
|
|
|
|
return -1;
|
|
|
|
priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
|
2010-04-20 01:37:21 +08:00
|
|
|
priv->ext_cap = priv->ext_cap_0c = 0;
|
|
|
|
|
2010-07-21 15:01:19 +08:00
|
|
|
/*
|
|
|
|
* Older firmwares had submodel ID fixed to 0x47
|
|
|
|
*/
|
|
|
|
if (SYN_ID_FULL(priv->identity) < 0x705 &&
|
|
|
|
SYN_CAP_SUBMODEL_ID(priv->capabilities) != 0x47) {
|
2005-04-17 06:20:36 +08:00
|
|
|
return -1;
|
2010-07-21 15:01:19 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Unless capExtended is set the rest of the flags should be ignored
|
|
|
|
*/
|
|
|
|
if (!SYN_CAP_EXTENDED(priv->capabilities))
|
|
|
|
priv->capabilities = 0;
|
|
|
|
|
|
|
|
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
|
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_warn(psmouse,
|
|
|
|
"device claims to have extended capabilities, but I'm not able to read them.\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
} else {
|
|
|
|
priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if nExtBtn is greater than 8 it should be considered
|
|
|
|
* invalid and treated as 0
|
|
|
|
*/
|
|
|
|
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 8)
|
|
|
|
priv->ext_cap &= 0xff0fff;
|
|
|
|
}
|
|
|
|
}
|
2010-04-20 01:37:21 +08:00
|
|
|
|
|
|
|
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) {
|
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_warn(psmouse,
|
|
|
|
"device claims to have extended capability 0x0c, but I'm not able to read it.\n");
|
2010-04-20 01:37:21 +08:00
|
|
|
} else {
|
|
|
|
priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Identify Touchpad
|
|
|
|
* See also the SYN_ID_* macros
|
|
|
|
*/
|
|
|
|
static int synaptics_identify(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
unsigned char id[3];
|
|
|
|
|
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_IDENTIFY, id))
|
|
|
|
return -1;
|
|
|
|
priv->identity = (id[0]<<16) | (id[1]<<8) | id[2];
|
|
|
|
if (SYN_ID_IS_SYNAPTICS(priv->identity))
|
|
|
|
return 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-06-11 14:27:24 +08:00
|
|
|
/*
|
2010-05-11 14:06:52 +08:00
|
|
|
* Read touchpad resolution and maximum reported coordinates
|
2009-06-11 14:27:24 +08:00
|
|
|
* Resolution is left zero if touchpad does not support the query
|
|
|
|
*/
|
2014-03-28 15:43:00 +08:00
|
|
|
|
2009-06-11 14:27:24 +08:00
|
|
|
static int synaptics_resolution(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
2011-07-10 03:32:56 +08:00
|
|
|
unsigned char resp[3];
|
2009-06-11 14:27:24 +08:00
|
|
|
|
|
|
|
if (SYN_ID_MAJOR(priv->identity) < 4)
|
2010-07-15 00:32:46 +08:00
|
|
|
return 0;
|
2009-06-11 14:27:24 +08:00
|
|
|
|
2011-07-10 03:32:56 +08:00
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) {
|
|
|
|
if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) {
|
|
|
|
priv->x_res = resp[0]; /* x resolution in units/mm */
|
|
|
|
priv->y_res = resp[2]; /* y resolution in units/mm */
|
2010-05-11 14:06:52 +08:00
|
|
|
}
|
|
|
|
}
|
2009-06-11 14:27:24 +08:00
|
|
|
|
2010-05-11 14:06:52 +08:00
|
|
|
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
|
|
|
|
SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
|
2011-07-10 03:32:56 +08:00
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_warn(psmouse,
|
|
|
|
"device claims to have max coordinates query, but I'm not able to read it.\n");
|
2011-07-10 03:32:56 +08:00
|
|
|
} else {
|
|
|
|
priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
|
|
|
|
priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
|
2015-03-09 13:28:29 +08:00
|
|
|
psmouse_info(psmouse,
|
|
|
|
"queried max coordinates: x [..%d], y [..%d]\n",
|
|
|
|
priv->x_max, priv->y_max);
|
2011-07-10 03:32:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-09 13:28:40 +08:00
|
|
|
if (SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c) &&
|
|
|
|
(SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 ||
|
|
|
|
/*
|
|
|
|
* Firmware v8.1 does not report proper number of extended
|
|
|
|
* capabilities, but has been proven to report correct min
|
|
|
|
* coordinates.
|
|
|
|
*/
|
|
|
|
SYN_ID_FULL(priv->identity) == 0x801)) {
|
2011-07-10 03:32:56 +08:00
|
|
|
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_warn(psmouse,
|
|
|
|
"device claims to have min coordinates query, but I'm not able to read it.\n");
|
2010-05-11 14:06:52 +08:00
|
|
|
} else {
|
2011-07-10 03:32:56 +08:00
|
|
|
priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
|
|
|
|
priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
|
2015-03-09 13:28:29 +08:00
|
|
|
psmouse_info(psmouse,
|
|
|
|
"queried min coordinates: x [%d..], y [%d..]\n",
|
|
|
|
priv->x_min, priv->y_min);
|
2010-05-11 14:06:52 +08:00
|
|
|
}
|
2009-06-11 14:27:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-03-09 13:27:37 +08:00
|
|
|
/*
|
|
|
|
* Apply quirk(s) if the hardware matches
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void synaptics_apply_quirks(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) {
|
2015-03-09 13:29:15 +08:00
|
|
|
if (!psmouse_matches_pnp_id(psmouse,
|
|
|
|
min_max_pnpid_table[i].pnp_ids))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (min_max_pnpid_table[i].board_id.min != ANY_BOARD_ID &&
|
|
|
|
priv->board_id < min_max_pnpid_table[i].board_id.min)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (min_max_pnpid_table[i].board_id.max != ANY_BOARD_ID &&
|
|
|
|
priv->board_id > min_max_pnpid_table[i].board_id.max)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
priv->x_min = min_max_pnpid_table[i].x_min;
|
|
|
|
priv->x_max = min_max_pnpid_table[i].x_max;
|
|
|
|
priv->y_min = min_max_pnpid_table[i].y_min;
|
|
|
|
priv->y_max = min_max_pnpid_table[i].y_max;
|
|
|
|
psmouse_info(psmouse,
|
|
|
|
"quirked min/max coordinates: x [%d..%d], y [%d..%d]\n",
|
|
|
|
priv->x_min, priv->x_max,
|
|
|
|
priv->y_min, priv->y_max);
|
|
|
|
break;
|
2015-03-09 13:27:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static int synaptics_query_hardware(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
if (synaptics_identify(psmouse))
|
|
|
|
return -1;
|
|
|
|
if (synaptics_model_id(psmouse))
|
|
|
|
return -1;
|
2012-07-08 09:08:51 +08:00
|
|
|
if (synaptics_firmware_id(psmouse))
|
|
|
|
return -1;
|
2015-03-09 13:34:03 +08:00
|
|
|
if (synaptics_query_modes(psmouse))
|
2012-07-08 09:08:51 +08:00
|
|
|
return -1;
|
2005-04-17 06:20:36 +08:00
|
|
|
if (synaptics_capability(psmouse))
|
|
|
|
return -1;
|
2009-06-11 14:27:24 +08:00
|
|
|
if (synaptics_resolution(psmouse))
|
|
|
|
return -1;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2015-03-09 13:27:37 +08:00
|
|
|
synaptics_apply_quirks(psmouse);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
static unsigned char param = 0xc8;
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
|
2012-04-21 13:34:49 +08:00
|
|
|
if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
|
|
|
|
SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (ps2_command(&psmouse->ps2dev, ¶m, PSMOUSE_CMD_SETRATE))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Advanced gesture mode also sends multi finger data */
|
|
|
|
priv->capabilities |= BIT(1);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int synaptics_set_mode(struct psmouse *psmouse)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
priv->mode = 0;
|
2015-10-03 01:31:32 +08:00
|
|
|
if (priv->absolute_mode)
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
priv->mode |= SYN_BIT_ABSOLUTE_MODE;
|
2015-10-03 01:31:32 +08:00
|
|
|
if (priv->disable_gesture)
|
2005-04-17 06:20:36 +08:00
|
|
|
priv->mode |= SYN_BIT_DISABLE_GESTURE;
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
if (psmouse->rate >= 80)
|
|
|
|
priv->mode |= SYN_BIT_HIGH_RATE;
|
2015-10-03 01:31:32 +08:00
|
|
|
if (SYN_CAP_EXTENDED(priv->capabilities))
|
|
|
|
priv->mode |= SYN_BIT_W_MODE;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (synaptics_mode_cmd(psmouse, priv->mode))
|
|
|
|
return -1;
|
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
if (priv->absolute_mode &&
|
|
|
|
synaptics_set_advanced_gesture_mode(psmouse)) {
|
|
|
|
psmouse_err(psmouse, "Advanced gesture mode init failed.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
|
|
|
|
if (rate >= 80) {
|
|
|
|
priv->mode |= SYN_BIT_HIGH_RATE;
|
|
|
|
psmouse->rate = 80;
|
|
|
|
} else {
|
|
|
|
priv->mode &= ~SYN_BIT_HIGH_RATE;
|
|
|
|
psmouse->rate = 40;
|
|
|
|
}
|
|
|
|
|
|
|
|
synaptics_mode_cmd(psmouse, priv->mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Synaptics pass-through PS/2 port support
|
|
|
|
****************************************************************************/
|
|
|
|
static int synaptics_pt_write(struct serio *serio, unsigned char c)
|
|
|
|
{
|
|
|
|
struct psmouse *parent = serio_get_drvdata(serio->parent);
|
|
|
|
char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
|
|
|
|
|
|
|
|
if (psmouse_sliced_command(parent, c))
|
|
|
|
return -1;
|
|
|
|
if (ps2_command(&parent->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE))
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-10-05 12:46:10 +08:00
|
|
|
static int synaptics_pt_start(struct serio *serio)
|
|
|
|
{
|
|
|
|
struct psmouse *parent = serio_get_drvdata(serio->parent);
|
|
|
|
struct synaptics_data *priv = parent->private;
|
|
|
|
|
|
|
|
serio_pause_rx(parent->ps2dev.serio);
|
|
|
|
priv->pt_port = serio;
|
|
|
|
serio_continue_rx(parent->ps2dev.serio);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void synaptics_pt_stop(struct serio *serio)
|
|
|
|
{
|
|
|
|
struct psmouse *parent = serio_get_drvdata(serio->parent);
|
|
|
|
struct synaptics_data *priv = parent->private;
|
|
|
|
|
|
|
|
serio_pause_rx(parent->ps2dev.serio);
|
|
|
|
priv->pt_port = NULL;
|
|
|
|
serio_continue_rx(parent->ps2dev.serio);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int synaptics_is_pt_packet(unsigned char *buf)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
|
|
|
|
}
|
|
|
|
|
2015-03-09 13:35:41 +08:00
|
|
|
static void synaptics_pass_pt_packet(struct psmouse *psmouse,
|
|
|
|
struct serio *ptport,
|
|
|
|
unsigned char *packet)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2015-03-09 13:35:41 +08:00
|
|
|
struct synaptics_data *priv = psmouse->private;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct psmouse *child = serio_get_drvdata(ptport);
|
|
|
|
|
|
|
|
if (child && child->state == PSMOUSE_ACTIVATED) {
|
2015-03-09 13:35:41 +08:00
|
|
|
serio_interrupt(ptport, packet[1] | priv->pt_buttons, 0);
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 21:55:46 +08:00
|
|
|
serio_interrupt(ptport, packet[4], 0);
|
|
|
|
serio_interrupt(ptport, packet[5], 0);
|
2005-07-24 13:53:32 +08:00
|
|
|
if (child->pktsize == 4)
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 21:55:46 +08:00
|
|
|
serio_interrupt(ptport, packet[2], 0);
|
2015-03-09 13:35:41 +08:00
|
|
|
} else {
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 21:55:46 +08:00
|
|
|
serio_interrupt(ptport, packet[1], 0);
|
2015-03-09 13:35:41 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void synaptics_pt_activate(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
2010-10-05 12:46:10 +08:00
|
|
|
struct psmouse *child = serio_get_drvdata(priv->pt_port);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* adjust the touchpad to child's choice of protocol */
|
|
|
|
if (child) {
|
2005-07-24 13:53:32 +08:00
|
|
|
if (child->pktsize == 4)
|
2005-04-17 06:20:36 +08:00
|
|
|
priv->mode |= SYN_BIT_FOUR_BYTE_CLIENT;
|
|
|
|
else
|
|
|
|
priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT;
|
|
|
|
|
|
|
|
if (synaptics_mode_cmd(psmouse, priv->mode))
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_warn(psmouse,
|
|
|
|
"failed to switch guest protocol\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void synaptics_pt_create(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
struct serio *serio;
|
|
|
|
|
2006-03-14 13:09:16 +08:00
|
|
|
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!serio) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_err(psmouse,
|
|
|
|
"not enough memory for pass-through port\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
serio->id.type = SERIO_PS_PSTHRU;
|
|
|
|
strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
|
|
|
|
strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
|
|
|
|
serio->write = synaptics_pt_write;
|
2010-10-05 12:46:10 +08:00
|
|
|
serio->start = synaptics_pt_start;
|
|
|
|
serio->stop = synaptics_pt_stop;
|
2005-04-17 06:20:36 +08:00
|
|
|
serio->parent = psmouse->ps2dev.serio;
|
|
|
|
|
|
|
|
psmouse->pt_activate = synaptics_pt_activate;
|
|
|
|
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_info(psmouse, "serio: %s port at %s\n",
|
|
|
|
serio->name, psmouse->phys);
|
2005-04-17 06:20:36 +08:00
|
|
|
serio_register_port(serio);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Functions to interpret the absolute mode packets
|
|
|
|
****************************************************************************/
|
|
|
|
|
2011-08-24 14:00:33 +08:00
|
|
|
static void synaptics_parse_agm(const unsigned char buf[],
|
Input: synaptics - decode AGM packet types
A Synaptics image sensor tracks 5 fingers, but can only report 2.
The algorithm for choosing which 2 fingers to report and in which packet:
Touchpad maintains 5 slots, numbered 0 to 4
Initially all slots are empty
As new fingers are detected, assign them to the lowest available slots
The touchpad always reports:
SGM: lowest numbered non-empty slot
AGM: highest numbered non-empty slot, if there is one
In addition, these touchpads have a special AGM packet type which reports
the number of fingers currently being tracked, and which finger is in
each of the two slots. Unfortunately, these "TYPE=2" packets are only used
when more than 3 fingers are being tracked. When less than 4 fingers
are present, the 'w' value must be used to track how many fingers are
present, and knowing which fingers are being reported is much more
difficult, if not impossible.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:31 +08:00
|
|
|
struct synaptics_data *priv,
|
|
|
|
struct synaptics_hw_state *hw)
|
2011-08-24 14:00:33 +08:00
|
|
|
{
|
|
|
|
struct synaptics_hw_state *agm = &priv->agm;
|
Input: synaptics - decode AGM packet types
A Synaptics image sensor tracks 5 fingers, but can only report 2.
The algorithm for choosing which 2 fingers to report and in which packet:
Touchpad maintains 5 slots, numbered 0 to 4
Initially all slots are empty
As new fingers are detected, assign them to the lowest available slots
The touchpad always reports:
SGM: lowest numbered non-empty slot
AGM: highest numbered non-empty slot, if there is one
In addition, these touchpads have a special AGM packet type which reports
the number of fingers currently being tracked, and which finger is in
each of the two slots. Unfortunately, these "TYPE=2" packets are only used
when more than 3 fingers are being tracked. When less than 4 fingers
are present, the 'w' value must be used to track how many fingers are
present, and knowing which fingers are being reported is much more
difficult, if not impossible.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:31 +08:00
|
|
|
int agm_packet_type;
|
|
|
|
|
|
|
|
agm_packet_type = (buf[5] & 0x30) >> 4;
|
|
|
|
switch (agm_packet_type) {
|
|
|
|
case 1:
|
|
|
|
/* Gesture packet: (x, y, z) half resolution */
|
|
|
|
agm->w = hw->w;
|
|
|
|
agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
|
|
|
|
agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
|
|
|
|
agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2014-12-30 06:15:24 +08:00
|
|
|
/* AGM-CONTACT packet: we are only interested in the count */
|
|
|
|
priv->agm_count = buf[1];
|
Input: synaptics - decode AGM packet types
A Synaptics image sensor tracks 5 fingers, but can only report 2.
The algorithm for choosing which 2 fingers to report and in which packet:
Touchpad maintains 5 slots, numbered 0 to 4
Initially all slots are empty
As new fingers are detected, assign them to the lowest available slots
The touchpad always reports:
SGM: lowest numbered non-empty slot
AGM: highest numbered non-empty slot, if there is one
In addition, these touchpads have a special AGM packet type which reports
the number of fingers currently being tracked, and which finger is in
each of the two slots. Unfortunately, these "TYPE=2" packets are only used
when more than 3 fingers are being tracked. When less than 4 fingers
are present, the 'w' value must be used to track how many fingers are
present, and knowing which fingers are being reported is much more
difficult, if not impossible.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:31 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2011-08-24 14:00:33 +08:00
|
|
|
}
|
|
|
|
|
2015-03-09 13:30:43 +08:00
|
|
|
static void synaptics_parse_ext_buttons(const unsigned char buf[],
|
|
|
|
struct synaptics_data *priv,
|
|
|
|
struct synaptics_hw_state *hw)
|
|
|
|
{
|
|
|
|
unsigned int ext_bits =
|
|
|
|
(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1;
|
|
|
|
unsigned int ext_mask = GENMASK(ext_bits - 1, 0);
|
|
|
|
|
|
|
|
hw->ext_buttons = buf[4] & ext_mask;
|
|
|
|
hw->ext_buttons |= (buf[5] & ext_mask) << ext_bits;
|
|
|
|
}
|
|
|
|
|
2010-12-22 01:11:25 +08:00
|
|
|
static int synaptics_parse_hw_state(const unsigned char buf[],
|
|
|
|
struct synaptics_data *priv,
|
|
|
|
struct synaptics_hw_state *hw)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
memset(hw, 0, sizeof(struct synaptics_hw_state));
|
|
|
|
|
|
|
|
if (SYN_MODEL_NEWABS(priv->model_id)) {
|
|
|
|
hw->w = (((buf[0] & 0x30) >> 2) |
|
|
|
|
((buf[0] & 0x04) >> 1) |
|
|
|
|
((buf[3] & 0x04) >> 2));
|
|
|
|
|
2014-08-31 04:51:06 +08:00
|
|
|
if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
|
|
|
|
SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
|
|
|
|
hw->w == 2) {
|
|
|
|
synaptics_parse_agm(buf, priv, hw);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
hw->x = (((buf[3] & 0x10) << 8) |
|
|
|
|
((buf[1] & 0x0f) << 8) |
|
|
|
|
buf[4]);
|
|
|
|
hw->y = (((buf[3] & 0x20) << 7) |
|
|
|
|
((buf[1] & 0xf0) << 4) |
|
|
|
|
buf[5]);
|
|
|
|
hw->z = buf[2];
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
hw->left = (buf[0] & 0x01) ? 1 : 0;
|
|
|
|
hw->right = (buf[0] & 0x02) ? 1 : 0;
|
|
|
|
|
2014-12-30 06:43:44 +08:00
|
|
|
if (priv->is_forcepad) {
|
2014-08-31 04:51:06 +08:00
|
|
|
/*
|
|
|
|
* ForcePads, like Clickpads, use middle button
|
|
|
|
* bits to report primary button clicks.
|
|
|
|
* Unfortunately they report primary button not
|
|
|
|
* only when user presses on the pad above certain
|
|
|
|
* threshold, but also when there are more than one
|
|
|
|
* finger on the touchpad, which interferes with
|
|
|
|
* out multi-finger gestures.
|
|
|
|
*/
|
|
|
|
if (hw->z == 0) {
|
|
|
|
/* No contacts */
|
|
|
|
priv->press = priv->report_press = false;
|
|
|
|
} else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) {
|
|
|
|
/*
|
|
|
|
* Single-finger touch with pressure above
|
|
|
|
* the threshold. If pressure stays long
|
|
|
|
* enough, we'll start reporting primary
|
|
|
|
* button. We rely on the device continuing
|
|
|
|
* sending data even if finger does not
|
|
|
|
* move.
|
|
|
|
*/
|
|
|
|
if (!priv->press) {
|
|
|
|
priv->press_start = jiffies;
|
|
|
|
priv->press = true;
|
|
|
|
} else if (time_after(jiffies,
|
|
|
|
priv->press_start +
|
|
|
|
msecs_to_jiffies(50))) {
|
|
|
|
priv->report_press = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
priv->press = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
hw->left = priv->report_press;
|
|
|
|
|
|
|
|
} else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
|
2010-04-20 01:37:21 +08:00
|
|
|
/*
|
|
|
|
* Clickpad's button is transmitted as middle button,
|
|
|
|
* however, since it is primary button, we will report
|
|
|
|
* it as BTN_LEFT.
|
|
|
|
*/
|
|
|
|
hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
|
|
|
|
|
|
|
|
} else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
|
2005-04-17 06:20:36 +08:00
|
|
|
hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
|
|
|
|
if (hw->w == 2)
|
|
|
|
hw->scroll = (signed char)(buf[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
|
|
|
|
hw->up = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
|
|
|
|
hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
2015-03-09 13:30:43 +08:00
|
|
|
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 0 &&
|
2005-04-17 06:20:36 +08:00
|
|
|
((buf[0] ^ buf[3]) & 0x02)) {
|
2015-03-09 13:30:43 +08:00
|
|
|
synaptics_parse_ext_buttons(buf, priv, hw);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
hw->x = (((buf[1] & 0x1f) << 8) | buf[2]);
|
|
|
|
hw->y = (((buf[4] & 0x1f) << 8) | buf[5]);
|
|
|
|
|
|
|
|
hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F));
|
|
|
|
hw->w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1));
|
|
|
|
|
|
|
|
hw->left = (buf[0] & 0x01) ? 1 : 0;
|
|
|
|
hw->right = (buf[0] & 0x02) ? 1 : 0;
|
|
|
|
}
|
2010-12-22 01:11:25 +08:00
|
|
|
|
2012-09-29 01:29:21 +08:00
|
|
|
/*
|
|
|
|
* Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE
|
|
|
|
* is used by some firmware to indicate a finger at the edge of
|
|
|
|
* the touchpad whose precise position cannot be determined, so
|
|
|
|
* convert these values to the maximum axis value.
|
|
|
|
*/
|
2012-07-25 14:54:11 +08:00
|
|
|
if (hw->x > X_MAX_POSITIVE)
|
|
|
|
hw->x -= 1 << ABS_POS_BITS;
|
2012-09-29 01:29:21 +08:00
|
|
|
else if (hw->x == X_MAX_POSITIVE)
|
|
|
|
hw->x = XMAX;
|
|
|
|
|
2012-07-25 14:54:11 +08:00
|
|
|
if (hw->y > Y_MAX_POSITIVE)
|
|
|
|
hw->y -= 1 << ABS_POS_BITS;
|
2012-09-29 01:29:21 +08:00
|
|
|
else if (hw->y == Y_MAX_POSITIVE)
|
|
|
|
hw->y = YMAX;
|
2012-07-25 14:54:11 +08:00
|
|
|
|
2010-12-22 01:11:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-07 13:42:52 +08:00
|
|
|
static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot,
|
|
|
|
bool active, int x, int y)
|
2010-12-22 01:11:25 +08:00
|
|
|
{
|
|
|
|
input_mt_slot(dev, slot);
|
|
|
|
input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
|
|
|
|
if (active) {
|
|
|
|
input_report_abs(dev, ABS_MT_POSITION_X, x);
|
2011-08-24 14:00:24 +08:00
|
|
|
input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y));
|
2010-12-22 01:11:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void synaptics_report_semi_mt_data(struct input_dev *dev,
|
|
|
|
const struct synaptics_hw_state *a,
|
|
|
|
const struct synaptics_hw_state *b,
|
|
|
|
int num_fingers)
|
|
|
|
{
|
|
|
|
if (num_fingers >= 2) {
|
2011-07-07 13:42:52 +08:00
|
|
|
synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x),
|
|
|
|
min(a->y, b->y));
|
|
|
|
synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x),
|
|
|
|
max(a->y, b->y));
|
2010-12-22 01:11:25 +08:00
|
|
|
} else if (num_fingers == 1) {
|
2011-07-07 13:42:52 +08:00
|
|
|
synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y);
|
|
|
|
synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
|
2010-12-22 01:11:25 +08:00
|
|
|
} else {
|
2011-07-07 13:42:52 +08:00
|
|
|
synaptics_report_semi_mt_slot(dev, 0, false, 0, 0);
|
|
|
|
synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
|
2010-12-22 01:11:25 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2015-03-09 13:32:43 +08:00
|
|
|
static void synaptics_report_ext_buttons(struct psmouse *psmouse,
|
|
|
|
const struct synaptics_hw_state *hw)
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
{
|
|
|
|
struct input_dev *dev = psmouse->dev;
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
2015-03-09 13:30:43 +08:00
|
|
|
int ext_bits = (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1;
|
2015-03-09 13:35:41 +08:00
|
|
|
char buf[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
int i;
|
|
|
|
|
2015-03-09 13:32:43 +08:00
|
|
|
if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Bug in FW 8.1, buttons are reported only when ExtBit is 1 */
|
|
|
|
if (SYN_ID_FULL(priv->identity) == 0x801 &&
|
|
|
|
!((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02))
|
|
|
|
return;
|
|
|
|
|
2015-03-09 13:35:41 +08:00
|
|
|
if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) {
|
|
|
|
for (i = 0; i < ext_bits; i++) {
|
|
|
|
input_report_key(dev, BTN_0 + 2 * i,
|
|
|
|
hw->ext_buttons & (1 << i));
|
|
|
|
input_report_key(dev, BTN_1 + 2 * i,
|
|
|
|
hw->ext_buttons & (1 << (i + ext_bits)));
|
|
|
|
}
|
|
|
|
return;
|
2015-03-09 13:32:43 +08:00
|
|
|
}
|
2015-03-09 13:35:41 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This generation of touchpads has the trackstick buttons
|
|
|
|
* physically wired to the touchpad. Re-route them through
|
|
|
|
* the pass-through interface.
|
|
|
|
*/
|
|
|
|
if (!priv->pt_port)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* The trackstick expects at most 3 buttons */
|
|
|
|
priv->pt_buttons = SYN_CAP_EXT_BUTTON_STICK_L(hw->ext_buttons) |
|
|
|
|
SYN_CAP_EXT_BUTTON_STICK_R(hw->ext_buttons) << 1 |
|
|
|
|
SYN_CAP_EXT_BUTTON_STICK_M(hw->ext_buttons) << 2;
|
|
|
|
|
|
|
|
synaptics_pass_pt_packet(psmouse, priv->pt_port, buf);
|
2015-03-09 13:32:43 +08:00
|
|
|
}
|
|
|
|
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
static void synaptics_report_buttons(struct psmouse *psmouse,
|
|
|
|
const struct synaptics_hw_state *hw)
|
|
|
|
{
|
|
|
|
struct input_dev *dev = psmouse->dev;
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
|
|
|
|
input_report_key(dev, BTN_LEFT, hw->left);
|
|
|
|
input_report_key(dev, BTN_RIGHT, hw->right);
|
|
|
|
|
|
|
|
if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
|
|
|
|
input_report_key(dev, BTN_MIDDLE, hw->middle);
|
|
|
|
|
|
|
|
if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
|
|
|
|
input_report_key(dev, BTN_FORWARD, hw->up);
|
|
|
|
input_report_key(dev, BTN_BACK, hw->down);
|
|
|
|
}
|
|
|
|
|
2015-03-09 13:32:43 +08:00
|
|
|
synaptics_report_ext_buttons(psmouse, hw);
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void synaptics_report_mt_data(struct psmouse *psmouse,
|
2014-12-30 06:15:24 +08:00
|
|
|
const struct synaptics_hw_state *sgm,
|
|
|
|
int num_fingers)
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
{
|
|
|
|
struct input_dev *dev = psmouse->dev;
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
2014-12-30 06:15:24 +08:00
|
|
|
const struct synaptics_hw_state *hw[2] = { sgm, &priv->agm };
|
|
|
|
struct input_mt_pos pos[2];
|
|
|
|
int slot[2], nsemi, i;
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
|
2014-12-30 06:15:24 +08:00
|
|
|
nsemi = clamp_val(num_fingers, 0, 2);
|
Input: synaptics - process finger (<=3) transitions
Synaptics image sensor touchpads track 5 fingers, but only report 2.
This patch attempts to deal with some idiosyncrasies of these touchpads:
* When there are 3 or more fingers, only two are reported.
* The touchpad tracks the 5 fingers in slot[0] through slot[4].
* It always reports the lowest and highest valid slots in SGM and AGM
packets, respectively.
* The number of fingers is only reported in the SGM packet. However,
the number of fingers can change either before or after an AGM
packet.
* Thus, if an SGM reports a different number of fingers than the last
SGM, it is impossible to tell whether the intervening AGM corresponds
to the old number of fingers or the new number of fingers.
* For example, when going from 2->3 fingers, it is not possible to tell
whether tell AGM contains slot[1] (old 2nd finger) or slot[2] (new
3rd finger).
* When fingers are added one at at time, from 1->2->3, it is possible to
track which slots are contained in the SGM and AGM packets:
1 finger: SGM = slot[0], no AGM
2 fingers: SGM = slot[0], AGM = slot[1]
3 fingers: SGM = slot[0], AGM = slot[2]
* It is also possible to track which slot is contained in the SGM when 1
of 2 fingers is removed. This is because the touchpad sends a special
(0,0,0) AGM packet whenever all fingers are removed except slot[0]:
Last AGM == (0,0,0): SGM contains slot[1]
Else: SGM contains slot[0]
* However, once there are 3 fingers, if exactly 1 finger is removed, it
is impossible to tell which 2 slots are contained in SGM and AGM.
The (SGM,AGM) could be (0,1), (0,2), or (1,2). There is no way to know.
* Similarly, if two fingers are simultaneously removed (3->1), then it
is only possible to know if SGM still contains slot[0].
* Since it is not possible to reliably track which slot is being
reported, we invalidate the tracking_id every time the number of
fingers changes until this ambiguity is resolved when:
a) All fingers are removed.
b) 4 or 5 fingers are touched, generates an AGM-CONTACT packet.
c) All fingers are removed except slot[0]. In this special case, the
ambiguity is resolved since by the (0,0,0) AGM packet.
Behavior of the driver:
When 2 or more fingers are present on the touchpad, the kernel reports
up to two MT-B slots containing the position data for two of the fingers
reported by the touchpad. If the identity of a finger cannot be tracked
when the number-of-fingers changes, the corresponding MT-B slot will be
invalidated (track_id set to -1), and a new track_id will be assigned in
a subsequent input event report.
The driver always reports the total number of fingers using one of the
EV_KEY/BTN_TOOL_*TAP events. This could differ from the number of valid
MT-B slots for two reasons:
a) There are more than 2 fingers on the pad.
b) During ambiguous number-of-fingers transitions, the correct track_id
for one or both of the slots cannot be determined, so the slots are
invalidated.
Thus, this is a hybrid singletouch/MT-B scheme. Userspace can detect
this behavior by noting that the driver supports more EV_KEY/BTN_TOOL_*TAP
events than its maximum EV_ABS/ABS_MT_SLOT.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:40 +08:00
|
|
|
|
2014-12-30 06:15:24 +08:00
|
|
|
for (i = 0; i < nsemi; i++) {
|
|
|
|
pos[i].x = hw[i]->x;
|
|
|
|
pos[i].y = synaptics_invert_y(hw[i]->y);
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
}
|
|
|
|
|
2015-04-06 04:44:12 +08:00
|
|
|
input_mt_assign_slots(dev, slot, pos, nsemi, DMAX * priv->x_res);
|
2014-12-30 06:15:24 +08:00
|
|
|
|
|
|
|
for (i = 0; i < nsemi; i++) {
|
|
|
|
input_mt_slot(dev, slot[i]);
|
|
|
|
input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
|
|
|
|
input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x);
|
|
|
|
input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y);
|
|
|
|
input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z);
|
|
|
|
}
|
|
|
|
|
|
|
|
input_mt_drop_unused(dev);
|
|
|
|
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
/* Don't use active slot count to generate BTN_TOOL events. */
|
|
|
|
input_mt_report_pointer_emulation(dev, false);
|
|
|
|
|
|
|
|
/* Send the number of fingers reported by touchpad itself. */
|
2014-12-30 06:15:24 +08:00
|
|
|
input_mt_report_finger_count(dev, num_fingers);
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
|
|
|
|
synaptics_report_buttons(psmouse, sgm);
|
|
|
|
|
|
|
|
input_sync(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void synaptics_image_sensor_process(struct psmouse *psmouse,
|
|
|
|
struct synaptics_hw_state *sgm)
|
|
|
|
{
|
Input: synaptics - process finger (<=3) transitions
Synaptics image sensor touchpads track 5 fingers, but only report 2.
This patch attempts to deal with some idiosyncrasies of these touchpads:
* When there are 3 or more fingers, only two are reported.
* The touchpad tracks the 5 fingers in slot[0] through slot[4].
* It always reports the lowest and highest valid slots in SGM and AGM
packets, respectively.
* The number of fingers is only reported in the SGM packet. However,
the number of fingers can change either before or after an AGM
packet.
* Thus, if an SGM reports a different number of fingers than the last
SGM, it is impossible to tell whether the intervening AGM corresponds
to the old number of fingers or the new number of fingers.
* For example, when going from 2->3 fingers, it is not possible to tell
whether tell AGM contains slot[1] (old 2nd finger) or slot[2] (new
3rd finger).
* When fingers are added one at at time, from 1->2->3, it is possible to
track which slots are contained in the SGM and AGM packets:
1 finger: SGM = slot[0], no AGM
2 fingers: SGM = slot[0], AGM = slot[1]
3 fingers: SGM = slot[0], AGM = slot[2]
* It is also possible to track which slot is contained in the SGM when 1
of 2 fingers is removed. This is because the touchpad sends a special
(0,0,0) AGM packet whenever all fingers are removed except slot[0]:
Last AGM == (0,0,0): SGM contains slot[1]
Else: SGM contains slot[0]
* However, once there are 3 fingers, if exactly 1 finger is removed, it
is impossible to tell which 2 slots are contained in SGM and AGM.
The (SGM,AGM) could be (0,1), (0,2), or (1,2). There is no way to know.
* Similarly, if two fingers are simultaneously removed (3->1), then it
is only possible to know if SGM still contains slot[0].
* Since it is not possible to reliably track which slot is being
reported, we invalidate the tracking_id every time the number of
fingers changes until this ambiguity is resolved when:
a) All fingers are removed.
b) 4 or 5 fingers are touched, generates an AGM-CONTACT packet.
c) All fingers are removed except slot[0]. In this special case, the
ambiguity is resolved since by the (0,0,0) AGM packet.
Behavior of the driver:
When 2 or more fingers are present on the touchpad, the kernel reports
up to two MT-B slots containing the position data for two of the fingers
reported by the touchpad. If the identity of a finger cannot be tracked
when the number-of-fingers changes, the corresponding MT-B slot will be
invalidated (track_id set to -1), and a new track_id will be assigned in
a subsequent input event report.
The driver always reports the total number of fingers using one of the
EV_KEY/BTN_TOOL_*TAP events. This could differ from the number of valid
MT-B slots for two reasons:
a) There are more than 2 fingers on the pad.
b) During ambiguous number-of-fingers transitions, the correct track_id
for one or both of the slots cannot be determined, so the slots are
invalidated.
Thus, this is a hybrid singletouch/MT-B scheme. Userspace can detect
this behavior by noting that the driver supports more EV_KEY/BTN_TOOL_*TAP
events than its maximum EV_ABS/ABS_MT_SLOT.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:40 +08:00
|
|
|
struct synaptics_data *priv = psmouse->private;
|
2014-12-30 06:15:24 +08:00
|
|
|
int num_fingers;
|
Input: synaptics - process finger (<=3) transitions
Synaptics image sensor touchpads track 5 fingers, but only report 2.
This patch attempts to deal with some idiosyncrasies of these touchpads:
* When there are 3 or more fingers, only two are reported.
* The touchpad tracks the 5 fingers in slot[0] through slot[4].
* It always reports the lowest and highest valid slots in SGM and AGM
packets, respectively.
* The number of fingers is only reported in the SGM packet. However,
the number of fingers can change either before or after an AGM
packet.
* Thus, if an SGM reports a different number of fingers than the last
SGM, it is impossible to tell whether the intervening AGM corresponds
to the old number of fingers or the new number of fingers.
* For example, when going from 2->3 fingers, it is not possible to tell
whether tell AGM contains slot[1] (old 2nd finger) or slot[2] (new
3rd finger).
* When fingers are added one at at time, from 1->2->3, it is possible to
track which slots are contained in the SGM and AGM packets:
1 finger: SGM = slot[0], no AGM
2 fingers: SGM = slot[0], AGM = slot[1]
3 fingers: SGM = slot[0], AGM = slot[2]
* It is also possible to track which slot is contained in the SGM when 1
of 2 fingers is removed. This is because the touchpad sends a special
(0,0,0) AGM packet whenever all fingers are removed except slot[0]:
Last AGM == (0,0,0): SGM contains slot[1]
Else: SGM contains slot[0]
* However, once there are 3 fingers, if exactly 1 finger is removed, it
is impossible to tell which 2 slots are contained in SGM and AGM.
The (SGM,AGM) could be (0,1), (0,2), or (1,2). There is no way to know.
* Similarly, if two fingers are simultaneously removed (3->1), then it
is only possible to know if SGM still contains slot[0].
* Since it is not possible to reliably track which slot is being
reported, we invalidate the tracking_id every time the number of
fingers changes until this ambiguity is resolved when:
a) All fingers are removed.
b) 4 or 5 fingers are touched, generates an AGM-CONTACT packet.
c) All fingers are removed except slot[0]. In this special case, the
ambiguity is resolved since by the (0,0,0) AGM packet.
Behavior of the driver:
When 2 or more fingers are present on the touchpad, the kernel reports
up to two MT-B slots containing the position data for two of the fingers
reported by the touchpad. If the identity of a finger cannot be tracked
when the number-of-fingers changes, the corresponding MT-B slot will be
invalidated (track_id set to -1), and a new track_id will be assigned in
a subsequent input event report.
The driver always reports the total number of fingers using one of the
EV_KEY/BTN_TOOL_*TAP events. This could differ from the number of valid
MT-B slots for two reasons:
a) There are more than 2 fingers on the pad.
b) During ambiguous number-of-fingers transitions, the correct track_id
for one or both of the slots cannot be determined, so the slots are
invalidated.
Thus, this is a hybrid singletouch/MT-B scheme. Userspace can detect
this behavior by noting that the driver supports more EV_KEY/BTN_TOOL_*TAP
events than its maximum EV_ABS/ABS_MT_SLOT.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:40 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Update mt_state using the new finger count and current mt_state.
|
|
|
|
*/
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
if (sgm->z == 0)
|
2014-12-30 06:15:24 +08:00
|
|
|
num_fingers = 0;
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
else if (sgm->w >= 4)
|
2014-12-30 06:15:24 +08:00
|
|
|
num_fingers = 1;
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
else if (sgm->w == 0)
|
2014-12-30 06:15:24 +08:00
|
|
|
num_fingers = 2;
|
|
|
|
else if (sgm->w == 1)
|
|
|
|
num_fingers = priv->agm_count ? priv->agm_count : 3;
|
2011-08-24 14:02:56 +08:00
|
|
|
else
|
2014-12-30 06:15:24 +08:00
|
|
|
num_fingers = 4;
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
|
|
|
|
/* Send resulting input events to user space */
|
2014-12-30 06:15:24 +08:00
|
|
|
synaptics_report_mt_data(psmouse, sgm, num_fingers);
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* called for each full received packet from the touchpad
|
|
|
|
*/
|
|
|
|
static void synaptics_process_packet(struct psmouse *psmouse)
|
|
|
|
{
|
2005-09-15 15:01:44 +08:00
|
|
|
struct input_dev *dev = psmouse->dev;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
struct synaptics_hw_state hw;
|
|
|
|
int num_fingers;
|
|
|
|
int finger_width;
|
|
|
|
|
2010-12-22 01:11:25 +08:00
|
|
|
if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
|
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
|
|
|
|
synaptics_image_sensor_process(psmouse, &hw);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (hw.scroll) {
|
|
|
|
priv->scroll += hw.scroll;
|
|
|
|
|
|
|
|
while (priv->scroll >= 4) {
|
|
|
|
input_report_key(dev, BTN_BACK, !hw.down);
|
|
|
|
input_sync(dev);
|
|
|
|
input_report_key(dev, BTN_BACK, hw.down);
|
|
|
|
input_sync(dev);
|
|
|
|
priv->scroll -= 4;
|
|
|
|
}
|
|
|
|
while (priv->scroll <= -4) {
|
|
|
|
input_report_key(dev, BTN_FORWARD, !hw.up);
|
|
|
|
input_sync(dev);
|
|
|
|
input_report_key(dev, BTN_FORWARD, hw.up);
|
|
|
|
input_sync(dev);
|
|
|
|
priv->scroll += 4;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-12-18 22:42:30 +08:00
|
|
|
if (hw.z > 0 && hw.x > 1) {
|
2005-04-17 06:20:36 +08:00
|
|
|
num_fingers = 1;
|
|
|
|
finger_width = 5;
|
|
|
|
if (SYN_CAP_EXTENDED(priv->capabilities)) {
|
|
|
|
switch (hw.w) {
|
|
|
|
case 0 ... 1:
|
|
|
|
if (SYN_CAP_MULTIFINGER(priv->capabilities))
|
|
|
|
num_fingers = hw.w + 2;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (SYN_MODEL_PEN(priv->model_id))
|
|
|
|
; /* Nothing, treat a pen as a single finger */
|
|
|
|
break;
|
|
|
|
case 4 ... 15:
|
|
|
|
if (SYN_CAP_PALMDETECT(priv->capabilities))
|
|
|
|
finger_width = hw.w;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
num_fingers = 0;
|
|
|
|
finger_width = 0;
|
|
|
|
}
|
|
|
|
|
2014-07-15 01:26:56 +08:00
|
|
|
if (cr48_profile_sensor) {
|
2014-12-30 06:17:44 +08:00
|
|
|
synaptics_report_mt_data(psmouse, &hw, num_fingers);
|
2014-07-15 01:26:56 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-12-22 01:11:25 +08:00
|
|
|
if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
|
2011-08-24 14:00:33 +08:00
|
|
|
synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
|
|
|
|
num_fingers);
|
2010-12-22 01:11:25 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/* Post events
|
|
|
|
* BTN_TOUCH has to be first as mousedev relies on it when doing
|
|
|
|
* absolute -> relative conversion
|
|
|
|
*/
|
|
|
|
if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1);
|
|
|
|
if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0);
|
|
|
|
|
2010-12-18 22:42:30 +08:00
|
|
|
if (num_fingers > 0) {
|
2005-04-17 06:20:36 +08:00
|
|
|
input_report_abs(dev, ABS_X, hw.x);
|
2011-08-24 14:00:24 +08:00
|
|
|
input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
input_report_abs(dev, ABS_PRESSURE, hw.z);
|
|
|
|
|
2010-07-20 00:06:15 +08:00
|
|
|
if (SYN_CAP_PALMDETECT(priv->capabilities))
|
|
|
|
input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
|
2008-11-21 04:24:42 +08:00
|
|
|
if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
|
|
|
|
input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
|
|
|
|
input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
|
|
|
|
}
|
|
|
|
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
synaptics_report_buttons(psmouse, &hw);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
input_sync(dev);
|
|
|
|
}
|
|
|
|
|
2011-10-11 09:27:03 +08:00
|
|
|
static int synaptics_validate_byte(struct psmouse *psmouse,
|
|
|
|
int idx, unsigned char pkt_type)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-09-11 09:54:39 +08:00
|
|
|
static const unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
|
|
|
|
static const unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
|
|
|
|
static const unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
|
|
|
|
static const unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
|
|
|
|
static const unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
|
2011-10-11 09:27:03 +08:00
|
|
|
const char *packet = psmouse->packet;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (idx < 0 || idx > 4)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (pkt_type) {
|
|
|
|
|
2010-05-20 01:39:17 +08:00
|
|
|
case SYN_NEWABS:
|
|
|
|
case SYN_NEWABS_RELAXED:
|
|
|
|
return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx];
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-05-20 01:39:17 +08:00
|
|
|
case SYN_NEWABS_STRICT:
|
|
|
|
return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-05-20 01:39:17 +08:00
|
|
|
case SYN_OLDABS:
|
|
|
|
return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
|
|
|
|
|
|
|
|
default:
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_err(psmouse, "unknown packet type %d\n", pkt_type);
|
2010-05-20 01:39:17 +08:00
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 5; i++)
|
2011-10-11 09:27:03 +08:00
|
|
|
if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) {
|
|
|
|
psmouse_info(psmouse, "using relaxed packet validation\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
return SYN_NEWABS_RELAXED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SYN_NEWABS_STRICT;
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 21:55:46 +08:00
|
|
|
static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
|
|
|
|
if (psmouse->pktcnt >= 6) { /* Full packet received */
|
|
|
|
if (unlikely(priv->pkt_type == SYN_NEWABS))
|
|
|
|
priv->pkt_type = synaptics_detect_pkt_type(psmouse);
|
|
|
|
|
2010-10-05 12:46:10 +08:00
|
|
|
if (SYN_CAP_PASS_THROUGH(priv->capabilities) &&
|
|
|
|
synaptics_is_pt_packet(psmouse->packet)) {
|
|
|
|
if (priv->pt_port)
|
2015-03-09 13:35:41 +08:00
|
|
|
synaptics_pass_pt_packet(psmouse, priv->pt_port,
|
|
|
|
psmouse->packet);
|
2005-04-17 06:20:36 +08:00
|
|
|
} else
|
|
|
|
synaptics_process_packet(psmouse);
|
|
|
|
|
|
|
|
return PSMOUSE_FULL_PACKET;
|
|
|
|
}
|
|
|
|
|
2011-10-11 09:27:03 +08:00
|
|
|
return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ?
|
2005-04-17 06:20:36 +08:00
|
|
|
PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Driver initialization/cleanup functions
|
|
|
|
****************************************************************************/
|
2011-08-24 14:00:41 +08:00
|
|
|
static void set_abs_position_params(struct input_dev *dev,
|
|
|
|
struct synaptics_data *priv, int x_code,
|
|
|
|
int y_code)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2011-08-24 14:00:41 +08:00
|
|
|
int x_min = priv->x_min ?: XMIN_NOMINAL;
|
|
|
|
int x_max = priv->x_max ?: XMAX_NOMINAL;
|
|
|
|
int y_min = priv->y_min ?: YMIN_NOMINAL;
|
|
|
|
int y_max = priv->y_max ?: YMAX_NOMINAL;
|
2011-07-07 13:39:14 +08:00
|
|
|
int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
|
|
|
|
SYN_REDUCED_FILTER_FUZZ : 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-08-24 14:00:41 +08:00
|
|
|
input_set_abs_params(dev, x_code, x_min, x_max, fuzz, 0);
|
|
|
|
input_set_abs_params(dev, y_code, y_min, y_max, fuzz, 0);
|
|
|
|
input_abs_set_res(dev, x_code, priv->x_res);
|
|
|
|
input_abs_set_res(dev, y_code, priv->y_res);
|
|
|
|
}
|
|
|
|
|
2014-04-20 13:26:41 +08:00
|
|
|
static void set_input_params(struct psmouse *psmouse,
|
|
|
|
struct synaptics_data *priv)
|
2011-08-24 14:00:41 +08:00
|
|
|
{
|
2014-04-20 13:26:41 +08:00
|
|
|
struct input_dev *dev = psmouse->dev;
|
2011-08-24 14:00:41 +08:00
|
|
|
int i;
|
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
/* Things that apply to both modes */
|
2010-12-16 16:52:23 +08:00
|
|
|
__set_bit(INPUT_PROP_POINTER, dev->propbit);
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
__set_bit(EV_KEY, dev->evbit);
|
|
|
|
__set_bit(BTN_LEFT, dev->keybit);
|
|
|
|
__set_bit(BTN_RIGHT, dev->keybit);
|
2010-12-16 16:52:23 +08:00
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
|
|
|
|
__set_bit(BTN_MIDDLE, dev->keybit);
|
|
|
|
|
|
|
|
if (!priv->absolute_mode) {
|
|
|
|
/* Relative mode */
|
|
|
|
__set_bit(EV_REL, dev->evbit);
|
|
|
|
__set_bit(REL_X, dev->relbit);
|
|
|
|
__set_bit(REL_Y, dev->relbit);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Absolute mode */
|
2009-09-10 10:13:20 +08:00
|
|
|
__set_bit(EV_ABS, dev->evbit);
|
2011-08-24 14:00:41 +08:00
|
|
|
set_abs_position_params(dev, priv, ABS_X, ABS_Y);
|
2005-04-17 06:20:36 +08:00
|
|
|
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
|
2010-07-20 00:06:15 +08:00
|
|
|
|
2014-07-15 01:26:56 +08:00
|
|
|
if (cr48_profile_sensor)
|
|
|
|
input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
|
|
|
|
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
|
|
|
|
set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
|
|
|
|
ABS_MT_POSITION_Y);
|
|
|
|
/* Image sensors can report per-contact pressure */
|
|
|
|
input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
|
2015-07-11 01:11:07 +08:00
|
|
|
input_mt_init_slots(dev, 2, INPUT_MT_POINTER | INPUT_MT_TRACK);
|
2011-08-24 14:02:56 +08:00
|
|
|
|
|
|
|
/* Image sensors can signal 4 and 5 finger clicks */
|
|
|
|
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
|
|
|
|
__set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
|
Input: synaptics - add image sensor support
Synaptics makes (at least) two kinds of touchpad sensors:
* Older pads use a profile sensor that could only infer the location
of individual fingers based on the projection of their profiles
onto row and column sensors.
* Newer pads use an image sensor that can track true finger position
using a two-dimensional sensor grid.
Both sensor types support an "Advanced Gesture Mode":
When multiple fingers are detected, the touchpad sends alternating
"Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
packets.
The AGM packets have w=2, and contain reduced resolution finger data
The SGM packets have w={0,1} and contain full resolution finger data
Profile sensors try to report the "upper" (larger y value) finger in
the SGM packet, and the lower (smaller y value) in the AGM packet.
However, due to the nature of the profile sensor, they easily get
confused when fingers cross, and can start reporting the x-coordinate
of one with the y-coordinate of the other. Thus, for profile
sensors, "semi-mt" was created, which reports a "bounding box"
created by pairing min and max coordinates of the two pairs of
reported fingers.
Image sensors can report the actual coordinates of two of the fingers
present. This patch detects if the touchpad is an image sensor and
reports finger data using the MT-B protocol.
NOTE: This patch only adds partial support for 2-finger gestures.
The proper interpretation of the slot contents when more than
two fingers are present is left to later patches. Also,
handling of 'number of fingers' transitions is incomplete.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-08-24 14:02:25 +08:00
|
|
|
} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
|
2011-08-24 14:00:41 +08:00
|
|
|
set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
|
|
|
|
ABS_MT_POSITION_Y);
|
2014-07-15 01:26:56 +08:00
|
|
|
/*
|
|
|
|
* Profile sensor in CR-48 tracks contacts reasonably well,
|
|
|
|
* other non-image sensors with AGM use semi-mt.
|
|
|
|
*/
|
2014-07-26 08:12:12 +08:00
|
|
|
input_mt_init_slots(dev, 2,
|
2014-07-15 01:26:56 +08:00
|
|
|
INPUT_MT_POINTER |
|
|
|
|
(cr48_profile_sensor ?
|
|
|
|
INPUT_MT_TRACK : INPUT_MT_SEMI_MT));
|
2010-12-22 01:11:25 +08:00
|
|
|
}
|
|
|
|
|
2010-07-20 00:06:15 +08:00
|
|
|
if (SYN_CAP_PALMDETECT(priv->capabilities))
|
2010-07-20 00:06:15 +08:00
|
|
|
input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-09-10 10:13:20 +08:00
|
|
|
__set_bit(BTN_TOUCH, dev->keybit);
|
|
|
|
__set_bit(BTN_TOOL_FINGER, dev->keybit);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-11-21 04:24:42 +08:00
|
|
|
if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
|
2009-09-10 10:13:20 +08:00
|
|
|
__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
|
|
|
|
__set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
|
2008-11-21 04:24:42 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (SYN_CAP_FOUR_BUTTON(priv->capabilities) ||
|
|
|
|
SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
|
2009-09-10 10:13:20 +08:00
|
|
|
__set_bit(BTN_FORWARD, dev->keybit);
|
|
|
|
__set_bit(BTN_BACK, dev->keybit);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2015-03-09 13:35:41 +08:00
|
|
|
if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10))
|
|
|
|
for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
|
|
|
|
__set_bit(BTN_0 + i, dev->keybit);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-09-10 10:13:20 +08:00
|
|
|
__clear_bit(EV_REL, dev->evbit);
|
|
|
|
__clear_bit(REL_X, dev->relbit);
|
|
|
|
__clear_bit(REL_Y, dev->relbit);
|
2009-06-11 14:27:24 +08:00
|
|
|
|
2010-04-20 01:37:21 +08:00
|
|
|
if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
|
2010-12-16 16:52:23 +08:00
|
|
|
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
|
2015-03-09 13:34:50 +08:00
|
|
|
if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) &&
|
|
|
|
!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10))
|
2014-05-20 13:53:23 +08:00
|
|
|
__set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit);
|
2010-04-20 01:37:21 +08:00
|
|
|
/* Clickpads report only left button */
|
|
|
|
__clear_bit(BTN_RIGHT, dev->keybit);
|
|
|
|
__clear_bit(BTN_MIDDLE, dev->keybit);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
static ssize_t synaptics_show_disable_gesture(struct psmouse *psmouse,
|
|
|
|
void *data, char *buf)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
|
|
|
|
return sprintf(buf, "%c\n", priv->disable_gesture ? '1' : '0');
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t synaptics_set_disable_gesture(struct psmouse *psmouse,
|
|
|
|
void *data, const char *buf,
|
|
|
|
size_t len)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
unsigned int value;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = kstrtouint(buf, 10, &value);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (value > 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (value == priv->disable_gesture)
|
|
|
|
return len;
|
|
|
|
|
|
|
|
priv->disable_gesture = value;
|
|
|
|
if (value)
|
|
|
|
priv->mode |= SYN_BIT_DISABLE_GESTURE;
|
|
|
|
else
|
|
|
|
priv->mode &= ~SYN_BIT_DISABLE_GESTURE;
|
|
|
|
|
|
|
|
if (synaptics_mode_cmd(psmouse, priv->mode))
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
PSMOUSE_DEFINE_ATTR(disable_gesture, S_IWUSR | S_IRUGO, NULL,
|
|
|
|
synaptics_show_disable_gesture,
|
|
|
|
synaptics_set_disable_gesture);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static void synaptics_disconnect(struct psmouse *psmouse)
|
|
|
|
{
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
|
|
|
|
if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity))
|
|
|
|
device_remove_file(&psmouse->ps2dev.serio->dev,
|
|
|
|
&psmouse_attr_disable_gesture.dattr);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
synaptics_reset(psmouse);
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
kfree(priv);
|
2005-04-17 06:20:36 +08:00
|
|
|
psmouse->private = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int synaptics_reconnect(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
struct synaptics_data *priv = psmouse->private;
|
|
|
|
struct synaptics_data old_priv = *priv;
|
2013-06-05 00:30:55 +08:00
|
|
|
unsigned char param[2];
|
2011-01-29 14:05:14 +08:00
|
|
|
int retry = 0;
|
|
|
|
int error;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-01-29 14:05:14 +08:00
|
|
|
do {
|
|
|
|
psmouse_reset(psmouse);
|
2011-12-12 16:05:53 +08:00
|
|
|
if (retry) {
|
|
|
|
/*
|
|
|
|
* On some boxes, right after resuming, the touchpad
|
|
|
|
* needs some time to finish initializing (I assume
|
|
|
|
* it needs time to calibrate) and start responding
|
|
|
|
* to Synaptics-specific queries, so let's wait a
|
|
|
|
* bit.
|
|
|
|
*/
|
|
|
|
ssleep(1);
|
|
|
|
}
|
2013-06-05 00:30:55 +08:00
|
|
|
ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETID);
|
2011-01-29 14:05:14 +08:00
|
|
|
error = synaptics_detect(psmouse, 0);
|
|
|
|
} while (error && ++retry < 3);
|
2009-03-01 04:51:01 +08:00
|
|
|
|
2011-01-29 14:05:14 +08:00
|
|
|
if (error)
|
2005-04-17 06:20:36 +08:00
|
|
|
return -1;
|
|
|
|
|
2011-01-29 14:05:14 +08:00
|
|
|
if (retry > 1)
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_dbg(psmouse, "reconnected after %d tries\n", retry);
|
2011-01-29 14:05:14 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (synaptics_query_hardware(psmouse)) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_err(psmouse, "Unable to query device.\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
if (synaptics_set_mode(psmouse)) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_err(psmouse, "Unable to initialize device.\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-01-29 14:05:14 +08:00
|
|
|
if (old_priv.identity != priv->identity ||
|
|
|
|
old_priv.model_id != priv->model_id ||
|
|
|
|
old_priv.capabilities != priv->capabilities ||
|
|
|
|
old_priv.ext_cap != priv->ext_cap) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_err(psmouse,
|
|
|
|
"hardware appears to be different: id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
|
|
|
|
old_priv.identity, priv->identity,
|
|
|
|
old_priv.model_id, priv->model_id,
|
|
|
|
old_priv.capabilities, priv->capabilities,
|
|
|
|
old_priv.ext_cap, priv->ext_cap);
|
2011-01-29 14:05:14 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-12-04 15:21:14 +08:00
|
|
|
static bool impaired_toshiba_kbc;
|
|
|
|
|
2013-08-13 02:05:58 +08:00
|
|
|
static const struct dmi_system_id toshiba_dmi_table[] __initconst = {
|
2009-12-04 15:21:14 +08:00
|
|
|
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2009-12-05 02:24:20 +08:00
|
|
|
/* Toshiba Satellite */
|
2005-04-17 06:20:36 +08:00
|
|
|
.matches = {
|
|
|
|
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
2006-04-02 13:10:18 +08:00
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
|
2005-04-17 06:20:36 +08:00
|
|
|
},
|
|
|
|
},
|
2005-07-11 14:07:20 +08:00
|
|
|
{
|
2009-12-05 02:24:20 +08:00
|
|
|
/* Toshiba Dynabook */
|
2005-07-11 14:07:20 +08:00
|
|
|
.matches = {
|
|
|
|
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
2006-04-02 13:10:18 +08:00
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2009-12-05 02:24:20 +08:00
|
|
|
/* Toshiba Portege M300 */
|
2006-04-02 13:10:18 +08:00
|
|
|
.matches = {
|
|
|
|
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
|
2005-07-11 14:07:20 +08:00
|
|
|
},
|
2009-10-13 12:35:00 +08:00
|
|
|
|
|
|
|
},
|
|
|
|
{
|
2009-12-05 02:24:20 +08:00
|
|
|
/* Toshiba Portege M300 */
|
2009-10-13 12:35:00 +08:00
|
|
|
.matches = {
|
|
|
|
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
|
|
|
|
DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"),
|
|
|
|
},
|
|
|
|
|
2005-07-11 14:07:20 +08:00
|
|
|
},
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
2011-03-31 15:01:58 +08:00
|
|
|
{ }
|
2009-12-04 15:21:14 +08:00
|
|
|
};
|
|
|
|
|
2010-12-23 17:19:38 +08:00
|
|
|
static bool broken_olpc_ec;
|
|
|
|
|
2013-08-13 02:05:58 +08:00
|
|
|
static const struct dmi_system_id olpc_dmi_table[] __initconst = {
|
2010-12-23 17:19:38 +08:00
|
|
|
#if defined(CONFIG_DMI) && defined(CONFIG_OLPC)
|
|
|
|
{
|
|
|
|
/* OLPC XO-1 or XO-1.5 */
|
|
|
|
.matches = {
|
|
|
|
DMI_MATCH(DMI_SYS_VENDOR, "OLPC"),
|
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "XO"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
#endif
|
2011-03-31 15:01:58 +08:00
|
|
|
{ }
|
2010-12-23 17:19:38 +08:00
|
|
|
};
|
|
|
|
|
2014-07-15 01:26:56 +08:00
|
|
|
static const struct dmi_system_id __initconst cr48_dmi_table[] = {
|
|
|
|
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
|
|
|
{
|
|
|
|
/* Cr-48 Chromebook (Codename Mario) */
|
|
|
|
.matches = {
|
|
|
|
DMI_MATCH(DMI_SYS_VENDOR, "IEC"),
|
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
#endif
|
|
|
|
{ }
|
|
|
|
};
|
|
|
|
|
2009-12-04 15:21:14 +08:00
|
|
|
void __init synaptics_module_init(void)
|
|
|
|
{
|
|
|
|
impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
|
2010-12-23 17:19:38 +08:00
|
|
|
broken_olpc_ec = dmi_check_system(olpc_dmi_table);
|
2014-07-15 01:26:56 +08:00
|
|
|
cr48_profile_sensor = dmi_check_system(cr48_dmi_table);
|
2009-12-04 15:21:14 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct synaptics_data *priv;
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
int err = -1;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-12-23 17:19:38 +08:00
|
|
|
/*
|
2011-11-12 08:05:04 +08:00
|
|
|
* The OLPC XO has issues with Synaptics' absolute mode; the constant
|
|
|
|
* packet spew overloads the EC such that key presses on the keyboard
|
|
|
|
* are missed. Given that, don't even attempt to use Absolute mode.
|
|
|
|
* Relative mode seems to work just fine.
|
2010-12-23 17:19:38 +08:00
|
|
|
*/
|
2011-11-12 08:05:04 +08:00
|
|
|
if (absolute_mode && broken_olpc_ec) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_info(psmouse,
|
|
|
|
"OLPC XO detected, not enabling Synaptics protocol.\n");
|
2010-12-23 17:19:38 +08:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2006-03-14 13:09:16 +08:00
|
|
|
psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!priv)
|
2010-09-30 09:53:35 +08:00
|
|
|
return -ENOMEM;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-03-01 04:51:01 +08:00
|
|
|
psmouse_reset(psmouse);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (synaptics_query_hardware(psmouse)) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_err(psmouse, "Unable to query device.\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
goto init_fail;
|
|
|
|
}
|
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
priv->absolute_mode = absolute_mode;
|
|
|
|
if (SYN_ID_DISGEST_SUPPORTED(priv->identity))
|
|
|
|
priv->disable_gesture = true;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2014-12-30 06:43:44 +08:00
|
|
|
/*
|
|
|
|
* Unfortunately ForcePad capability is not exported over PS/2,
|
|
|
|
* so we have to resort to checking PNP IDs.
|
|
|
|
*/
|
|
|
|
priv->is_forcepad = psmouse_matches_pnp_id(psmouse, forcepad_pnp_ids);
|
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
if (synaptics_set_mode(psmouse)) {
|
|
|
|
psmouse_err(psmouse, "Unable to initialize device.\n");
|
2010-12-22 01:11:25 +08:00
|
|
|
goto init_fail;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
|
|
|
|
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_info(psmouse,
|
2015-07-25 05:33:21 +08:00
|
|
|
"Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n",
|
2011-10-11 09:27:03 +08:00
|
|
|
SYN_ID_MODEL(priv->identity),
|
|
|
|
SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
|
|
|
|
priv->model_id,
|
2012-07-08 09:08:51 +08:00
|
|
|
priv->capabilities, priv->ext_cap, priv->ext_cap_0c,
|
2015-07-25 05:33:21 +08:00
|
|
|
priv->ext_cap_10, priv->board_id, priv->firmware_id);
|
2005-05-28 15:12:18 +08:00
|
|
|
|
2014-04-20 13:26:41 +08:00
|
|
|
set_input_params(psmouse, priv);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-04-12 13:30:41 +08:00
|
|
|
/*
|
|
|
|
* Encode touchpad model so that it can be used to set
|
|
|
|
* input device->id.version and be visible to userspace.
|
|
|
|
* Because version is __u16 we have to drop something.
|
|
|
|
* Hardware info bits seem to be good candidates as they
|
|
|
|
* are documented to be for Synaptics corp. internal use.
|
|
|
|
*/
|
|
|
|
psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) |
|
|
|
|
(priv->model_id & 0x000000ff);
|
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
if (absolute_mode) {
|
|
|
|
psmouse->protocol_handler = synaptics_process_byte;
|
|
|
|
psmouse->pktsize = 6;
|
|
|
|
} else {
|
|
|
|
/* Relative mode follows standard PS/2 mouse protocol */
|
|
|
|
psmouse->protocol_handler = psmouse_process_byte;
|
|
|
|
psmouse->pktsize = 3;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
psmouse->set_rate = synaptics_set_rate;
|
|
|
|
psmouse->disconnect = synaptics_disconnect;
|
|
|
|
psmouse->reconnect = synaptics_reconnect;
|
2007-02-18 14:40:24 +08:00
|
|
|
psmouse->cleanup = synaptics_reset;
|
2006-01-14 13:27:37 +08:00
|
|
|
/* Synaptics can usually stay in sync without extra help */
|
|
|
|
psmouse->resync_time = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (SYN_CAP_PASS_THROUGH(priv->capabilities))
|
|
|
|
synaptics_pt_create(psmouse);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Toshiba's KBC seems to have trouble handling data from
|
2010-12-23 17:18:28 +08:00
|
|
|
* Synaptics at full rate. Switch to a lower rate (roughly
|
|
|
|
* the same rate as a standard PS/2 mouse).
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2009-12-04 15:21:14 +08:00
|
|
|
if (psmouse->rate >= 80 && impaired_toshiba_kbc) {
|
2011-10-11 09:27:03 +08:00
|
|
|
psmouse_info(psmouse,
|
|
|
|
"Toshiba %s detected, limiting rate to 40pps.\n",
|
|
|
|
dmi_get_system_info(DMI_PRODUCT_NAME));
|
2005-04-17 06:20:36 +08:00
|
|
|
psmouse->rate = 40;
|
|
|
|
}
|
|
|
|
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity)) {
|
|
|
|
err = device_create_file(&psmouse->ps2dev.serio->dev,
|
|
|
|
&psmouse_attr_disable_gesture.dattr);
|
|
|
|
if (err) {
|
|
|
|
psmouse_err(psmouse,
|
|
|
|
"Failed to create disable_gesture attribute (%d)",
|
|
|
|
err);
|
|
|
|
goto init_fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
init_fail:
|
|
|
|
kfree(priv);
|
Input: synaptics - add support for Relative mode
Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.
For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.
This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.
This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.
Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2011-11-08 16:00:35 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
int synaptics_init(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
return __synaptics_init(psmouse, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
int synaptics_init_relative(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
return __synaptics_init(psmouse, false);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2007-03-10 14:39:54 +08:00
|
|
|
#else /* CONFIG_MOUSE_PS2_SYNAPTICS */
|
|
|
|
|
2009-12-04 15:21:14 +08:00
|
|
|
void __init synaptics_module_init(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2007-03-10 14:39:54 +08:00
|
|
|
int synaptics_init(struct psmouse *psmouse)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
|