diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/drivers/input/mouse | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/drivers/input/mouse')
37 files changed, 0 insertions, 16778 deletions
diff --git a/ANDROID_3.4.5/drivers/input/mouse/Kconfig b/ANDROID_3.4.5/drivers/input/mouse/Kconfig deleted file mode 100644 index 9b8db821..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/Kconfig +++ /dev/null @@ -1,342 +0,0 @@ -# -# Mouse driver configuration -# -menuconfig INPUT_MOUSE - bool "Mice" - default y - help - Say Y here, and a list of supported mice will be displayed. - This option doesn't affect the kernel. - - If unsure, say Y. - -if INPUT_MOUSE - -config MOUSE_PS2 - tristate "PS/2 mouse" - default y - select SERIO - select SERIO_LIBPS2 - select SERIO_I8042 if X86 - select SERIO_GSCPS2 if GSC - help - Say Y here if you have a PS/2 mouse connected to your system. This - includes the standard 2 or 3-button PS/2 mouse, as well as PS/2 - mice with wheels and extra buttons, Microsoft, Logitech or Genius - compatible. - - Synaptics, ALPS or Elantech TouchPad users might be interested - in a specialized Xorg/XFree86 driver at: - <http://w1.894.telia.com/~u89404340/touchpad/index.html> - and a new version of GPM at: - <http://www.geocities.com/dt_or/gpm/gpm.html> - <http://xorg.freedesktop.org/archive/individual/driver/> - to take advantage of the advanced features of the touchpad. - - If unsure, say Y. - - To compile this driver as a module, choose M here: the - module will be called psmouse. - -config MOUSE_PS2_ALPS - bool "ALPS PS/2 mouse protocol extension" if EXPERT - default y - depends on MOUSE_PS2 - help - Say Y here if you have an ALPS PS/2 touchpad connected to - your system. - - If unsure, say Y. - -config MOUSE_PS2_LOGIPS2PP - bool "Logitech PS/2++ mouse protocol extension" if EXPERT - default y - depends on MOUSE_PS2 - help - Say Y here if you have a Logictech PS/2++ mouse connected to - your system. - - If unsure, say Y. - -config MOUSE_PS2_SYNAPTICS - bool "Synaptics PS/2 mouse protocol extension" if EXPERT - default y - depends on MOUSE_PS2 - help - Say Y here if you have a Synaptics PS/2 TouchPad connected to - your system. - - If unsure, say Y. - -config MOUSE_PS2_LIFEBOOK - bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT - default y - depends on MOUSE_PS2 && X86 && DMI - help - Say Y here if you have a Fujitsu B-series Lifebook PS/2 - TouchScreen connected to your system. - - If unsure, say Y. - -config MOUSE_PS2_TRACKPOINT - bool "IBM Trackpoint PS/2 mouse protocol extension" if EXPERT - default y - depends on MOUSE_PS2 - help - Say Y here if you have an IBM Trackpoint PS/2 mouse connected - to your system. - - If unsure, say Y. - -config MOUSE_PS2_ELANTECH - bool "Elantech PS/2 protocol extension" - depends on MOUSE_PS2 - help - Say Y here if you have an Elantech PS/2 touchpad connected - to your system. - - Note that if you enable this driver you will need an updated - X.org Synaptics driver that does not require ABS_PRESSURE - reports from the touchpad (i.e. post 1.5.0 version). You can - grab a patch for the driver here: - - http://userweb.kernel.org/~dtor/synaptics-no-abspressure.patch - - If unsure, say N. - - This driver exposes some configuration registers via sysfs - entries. For further information, - see <file:Documentation/input/elantech.txt>. - -config MOUSE_PS2_SENTELIC - bool "Sentelic Finger Sensing Pad PS/2 protocol extension" - depends on MOUSE_PS2 - help - Say Y here if you have a laptop (such as MSI WIND Netbook) - with Sentelic Finger Sensing Pad touchpad. - - If unsure, say N. - -config MOUSE_PS2_TOUCHKIT - bool "eGalax TouchKit PS/2 protocol extension" - depends on MOUSE_PS2 - help - Say Y here if you have an eGalax TouchKit PS/2 touchscreen - connected to your system. - - If unsure, say N. - -config MOUSE_PS2_OLPC - bool "OLPC PS/2 mouse protocol extension" - depends on MOUSE_PS2 && OLPC - help - Say Y here if you have an OLPC XO-1 laptop (with built-in - PS/2 touchpad/tablet device). The manufacturer calls the - touchpad an HGPK. - - If unsure, say N. - -config MOUSE_SERIAL - tristate "Serial mouse" - select SERIO - help - Say Y here if you have a serial (RS-232, COM port) mouse connected - to your system. This includes Sun, MouseSystems, Microsoft, - Logitech and all other compatible serial mice. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called sermouse. - -config MOUSE_APPLETOUCH - tristate "Apple USB Touchpad support" - depends on USB_ARCH_HAS_HCD - select USB - help - Say Y here if you want to use an Apple USB Touchpad. - - These are the touchpads that can be found on post-February 2005 - Apple Powerbooks (prior models have a Synaptics touchpad connected - to the ADB bus). - - This driver provides a basic mouse driver but can be interfaced - with the synaptics X11 driver to provide acceleration and - scrolling in X11. - - For further information, see - <file:Documentation/input/appletouch.txt>. - - To compile this driver as a module, choose M here: the - module will be called appletouch. - -config MOUSE_BCM5974 - tristate "Apple USB BCM5974 Multitouch trackpad support" - depends on USB_ARCH_HAS_HCD - select USB - help - Say Y here if you have an Apple USB BCM5974 Multitouch - trackpad. - - The BCM5974 is the multitouch trackpad found in the Macbook - Air (JAN2008) and Macbook Pro Penryn (FEB2008) laptops. - - It is also found in the IPhone (2007) and Ipod Touch (2008). - - This driver provides multitouch functionality together with - the synaptics X11 driver. - - The interface is currently identical to the appletouch interface, - for further information, see - <file:Documentation/input/appletouch.txt>. - - To compile this driver as a module, choose M here: the - module will be called bcm5974. - -config MOUSE_INPORT - tristate "InPort/MS/ATIXL busmouse" - depends on ISA - help - Say Y here if you have an InPort, Microsoft or ATI XL busmouse. - They are rather rare these days. - - To compile this driver as a module, choose M here: the - module will be called inport. - -config MOUSE_ATIXL - bool "ATI XL variant" - depends on MOUSE_INPORT - help - Say Y here if your mouse is of the ATI XL variety. - -config MOUSE_LOGIBM - tristate "Logitech busmouse" - depends on ISA - help - Say Y here if you have a Logitech busmouse. - They are rather rare these days. - - To compile this driver as a module, choose M here: the - module will be called logibm. - -config MOUSE_PC110PAD - tristate "IBM PC110 touchpad" - depends on ISA - help - Say Y if you have the IBM PC-110 micro-notebook and want its - touchpad supported. - - To compile this driver as a module, choose M here: the - module will be called pc110pad. - -config MOUSE_AMIGA - tristate "Amiga mouse" - depends on AMIGA - help - Say Y here if you have an Amiga and want its native mouse - supported by the kernel. - - To compile this driver as a module, choose M here: the - module will be called amimouse. - -config MOUSE_ATARI - tristate "Atari mouse" - depends on ATARI - select ATARI_KBD_CORE - help - Say Y here if you have an Atari and want its native mouse - supported by the kernel. - - To compile this driver as a module, choose M here: the - module will be called atarimouse. - -config MOUSE_RISCPC - tristate "Acorn RiscPC mouse" - depends on ARCH_ACORN - help - Say Y here if you have the Acorn RiscPC computer and want its - native mouse supported. - - To compile this driver as a module, choose M here: the - module will be called rpcmouse. - -config MOUSE_VSXXXAA - tristate "DEC VSXXX-AA/GA mouse and VSXXX-AB tablet" - select SERIO - help - Say Y (or M) if you want to use a DEC VSXXX-AA (hockey - puck) or a VSXXX-GA (rectangular) mouse. Theses mice are - typically used on DECstations or VAXstations, but can also - be used on any box capable of RS232 (with some adaptor - described in the source file). This driver also works with the - digitizer (VSXXX-AB) DEC produced. - -config MOUSE_GPIO - tristate "GPIO mouse" - depends on GENERIC_GPIO - select INPUT_POLLDEV - help - This driver simulates a mouse on GPIO lines of various CPUs (and some - other chips). - - Say Y here if your device has buttons or a simple joystick connected - directly to GPIO lines. Your board-specific setup logic must also - provide a platform device and platform data saying which GPIOs are - used. - - To compile this driver as a module, choose M here: the - module will be called gpio_mouse. - -config MOUSE_PXA930_TRKBALL - tristate "PXA930 Trackball mouse" - depends on CPU_PXA930 || CPU_PXA935 - help - Say Y here to support PXA930 Trackball mouse. - -config MOUSE_MAPLE - tristate "Maple mouse (for the Dreamcast)" - depends on MAPLE - help - This driver supports the Maple mouse on the SEGA Dreamcast. - - Most Dreamcast users, who have a mouse, will say Y here. - - To compile this driver as a module choose M here: the module will be - called maplemouse. - -config MOUSE_SYNAPTICS_I2C - tristate "Synaptics I2C Touchpad support" - depends on I2C - help - This driver supports Synaptics I2C touchpad controller on eXeda - mobile device. - The device will not work the synaptics X11 driver because - (i) it reports only relative coordinates and has no capabilities - to report absolute coordinates - (ii) the eXeda device itself uses Xfbdev as X Server and it does - not allow using xf86-input-* drivers. - - Say y here if you have eXeda device and want to use a Synaptics - I2C Touchpad. - - To compile this driver as a module, choose M here: the - module will be called synaptics_i2c. - -config MOUSE_SYNAPTICS_USB - tristate "Synaptics USB device support" - depends on USB_ARCH_HAS_HCD - select USB - help - Say Y here if you want to use a Synaptics USB touchpad or pointing - stick. - - While these devices emulate an USB mouse by default and can be used - with standard usbhid driver, this driver, together with its X.Org - counterpart, allows you to fully utilize capabilities of the device. - More information can be found at: - <http://jan-steinhoff.de/linux/synaptics-usb.html> - - To compile this driver as a module, choose M here: the - module will be called synaptics_usb. - -endif diff --git a/ANDROID_3.4.5/drivers/input/mouse/Makefile b/ANDROID_3.4.5/drivers/input/mouse/Makefile deleted file mode 100644 index 4718effe..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# -# Makefile for the mouse drivers. -# - -# Each configuration option enables a list of files. - -obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o -obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o -obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o -obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o -obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o -obj-$(CONFIG_MOUSE_INPORT) += inport.o -obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o -obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o -obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o -obj-$(CONFIG_MOUSE_PS2) += psmouse.o -obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o -obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o -obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o -obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o -obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o -obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o - -psmouse-objs := psmouse-base.o synaptics.o - -psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o -psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o -psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o -psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o -psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o -psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o -psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o -psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o diff --git a/ANDROID_3.4.5/drivers/input/mouse/alps.c b/ANDROID_3.4.5/drivers/input/mouse/alps.c deleted file mode 100644 index 4c6a72d3..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/alps.c +++ /dev/null @@ -1,1649 +0,0 @@ -/* - * ALPS touchpad PS/2 mouse driver - * - * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au> - * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> - * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> - * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net> - * - * ALPS detection, tap switching and status querying info is taken from - * tpconfig utility (by C. Scott Ananian and Bruce Kall). - * - * 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. - */ - -#include <linux/slab.h> -#include <linux/input.h> -#include <linux/input/mt.h> -#include <linux/serio.h> -#include <linux/libps2.h> - -#include "psmouse.h" -#include "alps.h" - -/* - * Definitions for ALPS version 3 and 4 command mode protocol - */ -#define ALPS_V3_X_MAX 2000 -#define ALPS_V3_Y_MAX 1400 - -#define ALPS_BITMAP_X_BITS 15 -#define ALPS_BITMAP_Y_BITS 11 - -#define ALPS_CMD_NIBBLE_10 0x01f2 - -static const struct alps_nibble_commands alps_v3_nibble_commands[] = { - { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ - { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ - { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ - { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ - { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ - { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ - { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ - { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ - { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ - { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ - { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ - { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ - { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ - { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ - { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ - { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ -}; - -static const struct alps_nibble_commands alps_v4_nibble_commands[] = { - { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ - { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ - { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ - { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ - { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ - { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ - { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ - { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ - { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ - { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ - { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ - { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ - { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ - { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ - { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ - { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ -}; - - -#define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ -#define ALPS_PASS 0x04 /* device has a pass-through port */ - -#define ALPS_WHEEL 0x08 /* hardware wheel present */ -#define ALPS_FW_BK_1 0x10 /* front & back buttons present */ -#define ALPS_FW_BK_2 0x20 /* front & back buttons present */ -#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ -#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with - 6-byte ALPS packet */ - -static const struct alps_model_info alps_model_data[] = { - { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ - { { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ - { { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, - { { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, - { { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ - { { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, - { { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, - { { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ - { { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ - { { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ - { { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, - { { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ - { { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ - { { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, - { { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ - { { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ - { { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, - { { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ - /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ - { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, - { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ - { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ - { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, - { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, - { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, -}; - -/* - * XXX - this entry is suspicious. First byte has zero lower nibble, - * which is what a normal mouse would report. Also, the value 0x0e - * isn't valid per PS/2 spec. - */ - -/* Packet formats are described in Documentation/input/alps.txt */ - -static bool alps_is_valid_first_byte(const struct alps_model_info *model, - unsigned char data) -{ - return (data & model->mask0) == model->byte0; -} - -static void alps_report_buttons(struct psmouse *psmouse, - struct input_dev *dev1, struct input_dev *dev2, - int left, int right, int middle) -{ - struct input_dev *dev; - - /* - * If shared button has already been reported on the - * other device (dev2) then this event should be also - * sent through that device. - */ - dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_LEFT, left); - - dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_RIGHT, right); - - dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_MIDDLE, middle); - - /* - * Sync the _other_ device now, we'll do the first - * device later once we report the rest of the events. - */ - input_sync(dev2); -} - -static void alps_process_packet_v1_v2(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - unsigned char *packet = psmouse->packet; - struct input_dev *dev = psmouse->dev; - struct input_dev *dev2 = priv->dev2; - int x, y, z, ges, fin, left, right, middle; - int back = 0, forward = 0; - - if (model->proto_version == ALPS_PROTO_V1) { - left = packet[2] & 0x10; - right = packet[2] & 0x08; - middle = 0; - x = packet[1] | ((packet[0] & 0x07) << 7); - y = packet[4] | ((packet[3] & 0x07) << 7); - z = packet[5]; - } else { - left = packet[3] & 1; - right = packet[3] & 2; - middle = packet[3] & 4; - x = packet[1] | ((packet[2] & 0x78) << (7 - 3)); - y = packet[4] | ((packet[3] & 0x70) << (7 - 4)); - z = packet[5]; - } - - if (model->flags & ALPS_FW_BK_1) { - back = packet[0] & 0x10; - forward = packet[2] & 4; - } - - if (model->flags & ALPS_FW_BK_2) { - back = packet[3] & 4; - forward = packet[2] & 4; - if ((middle = forward && back)) - forward = back = 0; - } - - ges = packet[2] & 1; - fin = packet[2] & 2; - - if ((model->flags & ALPS_DUALPOINT) && z == 127) { - input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); - input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); - - alps_report_buttons(psmouse, dev2, dev, left, right, middle); - - input_sync(dev2); - return; - } - - alps_report_buttons(psmouse, dev, dev2, left, right, middle); - - /* Convert hardware tap to a reasonable Z value */ - if (ges && !fin) - z = 40; - - /* - * A "tap and drag" operation is reported by the hardware as a transition - * from (!fin && ges) to (fin && ges). This should be translated to the - * sequence Z>0, Z==0, Z>0, so the Z==0 event has to be generated manually. - */ - if (ges && fin && !priv->prev_fin) { - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - input_report_abs(dev, ABS_PRESSURE, 0); - input_report_key(dev, BTN_TOOL_FINGER, 0); - input_sync(dev); - } - priv->prev_fin = fin; - - if (z > 30) - input_report_key(dev, BTN_TOUCH, 1); - if (z < 25) - input_report_key(dev, BTN_TOUCH, 0); - - if (z > 0) { - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - } - - input_report_abs(dev, ABS_PRESSURE, z); - input_report_key(dev, BTN_TOOL_FINGER, z > 0); - - if (model->flags & ALPS_WHEEL) - input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); - - if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { - input_report_key(dev, BTN_FORWARD, forward); - input_report_key(dev, BTN_BACK, back); - } - - if (model->flags & ALPS_FOUR_BUTTONS) { - input_report_key(dev, BTN_0, packet[2] & 4); - input_report_key(dev, BTN_1, packet[0] & 0x10); - input_report_key(dev, BTN_2, packet[3] & 4); - input_report_key(dev, BTN_3, packet[0] & 0x20); - } - - input_sync(dev); -} - -/* - * Process bitmap data from v3 and v4 protocols. Returns the number of - * fingers detected. A return value of 0 means at least one of the - * bitmaps was empty. - * - * The bitmaps don't have enough data to track fingers, so this function - * only generates points representing a bounding box of all contacts. - * These points are returned in x1, y1, x2, and y2 when the return value - * is greater than 0. - */ -static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, - int *x1, int *y1, int *x2, int *y2) -{ - struct alps_bitmap_point { - int start_bit; - int num_bits; - }; - - int fingers_x = 0, fingers_y = 0, fingers; - int i, bit, prev_bit; - struct alps_bitmap_point x_low = {0,}, x_high = {0,}; - struct alps_bitmap_point y_low = {0,}, y_high = {0,}; - struct alps_bitmap_point *point; - - if (!x_map || !y_map) - return 0; - - *x1 = *y1 = *x2 = *y2 = 0; - - prev_bit = 0; - point = &x_low; - for (i = 0; x_map != 0; i++, x_map >>= 1) { - bit = x_map & 1; - if (bit) { - if (!prev_bit) { - point->start_bit = i; - fingers_x++; - } - point->num_bits++; - } else { - if (prev_bit) - point = &x_high; - else - point->num_bits = 0; - } - prev_bit = bit; - } - - /* - * y bitmap is reversed for what we need (lower positions are in - * higher bits), so we process from the top end. - */ - y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); - prev_bit = 0; - point = &y_low; - for (i = 0; y_map != 0; i++, y_map <<= 1) { - bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1)); - if (bit) { - if (!prev_bit) { - point->start_bit = i; - fingers_y++; - } - point->num_bits++; - } else { - if (prev_bit) - point = &y_high; - else - point->num_bits = 0; - } - prev_bit = bit; - } - - /* - * Fingers can overlap, so we use the maximum count of fingers - * on either axis as the finger count. - */ - fingers = max(fingers_x, fingers_y); - - /* - * If total fingers is > 1 but either axis reports only a single - * contact, we have overlapping or adjacent fingers. For the - * purposes of creating a bounding box, divide the single contact - * (roughly) equally between the two points. - */ - if (fingers > 1) { - if (fingers_x == 1) { - i = x_low.num_bits / 2; - x_low.num_bits = x_low.num_bits - i; - x_high.start_bit = x_low.start_bit + i; - x_high.num_bits = max(i, 1); - } else if (fingers_y == 1) { - i = y_low.num_bits / 2; - y_low.num_bits = y_low.num_bits - i; - y_high.start_bit = y_low.start_bit + i; - y_high.num_bits = max(i, 1); - } - } - - *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / - (2 * (ALPS_BITMAP_X_BITS - 1)); - *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / - (2 * (ALPS_BITMAP_Y_BITS - 1)); - - if (fingers > 1) { - *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / - (2 * (ALPS_BITMAP_X_BITS - 1)); - *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / - (2 * (ALPS_BITMAP_Y_BITS - 1)); - } - - return fingers; -} - -static void alps_set_slot(struct input_dev *dev, int slot, bool active, - int x, int y) -{ - 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); - input_report_abs(dev, ABS_MT_POSITION_Y, y); - } -} - -static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers, - int x1, int y1, int x2, int y2) -{ - alps_set_slot(dev, 0, num_fingers != 0, x1, y1); - alps_set_slot(dev, 1, num_fingers == 2, x2, y2); -} - -static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - unsigned char *packet = psmouse->packet; - struct input_dev *dev = priv->dev2; - int x, y, z, left, right, middle; - - /* Sanity check packet */ - if (!(packet[0] & 0x40)) { - psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); - return; - } - - /* - * There's a special packet that seems to indicate the end - * of a stream of trackstick data. Filter these out. - */ - if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f) - return; - - x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); - y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); - z = (packet[4] & 0x7c) >> 2; - - /* - * The x and y values tend to be quite large, and when used - * alone the trackstick is difficult to use. Scale them down - * to compensate. - */ - x /= 8; - y /= 8; - - input_report_rel(dev, REL_X, x); - input_report_rel(dev, REL_Y, -y); - - /* - * Most ALPS models report the trackstick buttons in the touchpad - * packets, but a few report them here. No reliable way has been - * found to differentiate between the models upfront, so we enable - * the quirk in response to seeing a button press in the trackstick - * packet. - */ - left = packet[3] & 0x01; - right = packet[3] & 0x02; - middle = packet[3] & 0x04; - - if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) && - (left || right || middle)) - priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS; - - if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) { - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_RIGHT, right); - input_report_key(dev, BTN_MIDDLE, middle); - } - - input_sync(dev); - return; -} - -static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - unsigned char *packet = psmouse->packet; - struct input_dev *dev = psmouse->dev; - struct input_dev *dev2 = priv->dev2; - int x, y, z; - int left, right, middle; - int x1 = 0, y1 = 0, x2 = 0, y2 = 0; - int fingers = 0, bmap_fingers; - unsigned int x_bitmap, y_bitmap; - - /* - * There's no single feature of touchpad position and bitmap packets - * that can be used to distinguish between them. We rely on the fact - * that a bitmap packet should always follow a position packet with - * bit 6 of packet[4] set. - */ - if (priv->multi_packet) { - /* - * Sometimes a position packet will indicate a multi-packet - * sequence, but then what follows is another position - * packet. Check for this, and when it happens process the - * position packet as usual. - */ - if (packet[0] & 0x40) { - fingers = (packet[5] & 0x3) + 1; - x_bitmap = ((packet[4] & 0x7e) << 8) | - ((packet[1] & 0x7f) << 2) | - ((packet[0] & 0x30) >> 4); - y_bitmap = ((packet[3] & 0x70) << 4) | - ((packet[2] & 0x7f) << 1) | - (packet[4] & 0x01); - - bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, - &x1, &y1, &x2, &y2); - - /* - * We shouldn't report more than one finger if - * we don't have two coordinates. - */ - if (fingers > 1 && bmap_fingers < 2) - fingers = bmap_fingers; - - /* Now process position packet */ - packet = priv->multi_data; - } else { - priv->multi_packet = 0; - } - } - - /* - * Bit 6 of byte 0 is not usually set in position packets. The only - * times it seems to be set is in situations where the data is - * suspect anyway, e.g. a palm resting flat on the touchpad. Given - * this combined with the fact that this bit is useful for filtering - * out misidentified bitmap packets, we reject anything with this - * bit set. - */ - if (packet[0] & 0x40) - return; - - if (!priv->multi_packet && (packet[4] & 0x40)) { - priv->multi_packet = 1; - memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); - return; - } - - priv->multi_packet = 0; - - left = packet[3] & 0x01; - right = packet[3] & 0x02; - middle = packet[3] & 0x04; - - x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | - ((packet[0] & 0x30) >> 4); - y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); - z = packet[5] & 0x7f; - - /* - * Sometimes the hardware sends a single packet with z = 0 - * in the middle of a stream. Real releases generate packets - * with x, y, and z all zero, so these seem to be flukes. - * Ignore them. - */ - if (x && y && !z) - return; - - /* - * If we don't have MT data or the bitmaps were empty, we have - * to rely on ST data. - */ - if (!fingers) { - x1 = x; - y1 = y; - fingers = z > 0 ? 1 : 0; - } - - if (z >= 64) - input_report_key(dev, BTN_TOUCH, 1); - else - input_report_key(dev, BTN_TOUCH, 0); - - alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); - - input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); - input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); - input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); - input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); - - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_RIGHT, right); - input_report_key(dev, BTN_MIDDLE, middle); - - if (z > 0) { - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - } - input_report_abs(dev, ABS_PRESSURE, z); - - input_sync(dev); - - if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { - left = packet[3] & 0x10; - right = packet[3] & 0x20; - middle = packet[3] & 0x40; - - input_report_key(dev2, BTN_LEFT, left); - input_report_key(dev2, BTN_RIGHT, right); - input_report_key(dev2, BTN_MIDDLE, middle); - input_sync(dev2); - } -} - -static void alps_process_packet_v3(struct psmouse *psmouse) -{ - unsigned char *packet = psmouse->packet; - - /* - * v3 protocol packets come in three types, two representing - * touchpad data and one representing trackstick data. - * Trackstick packets seem to be distinguished by always - * having 0x3f in the last byte. This value has never been - * observed in the last byte of either of the other types - * of packets. - */ - if (packet[5] == 0x3f) { - alps_process_trackstick_packet_v3(psmouse); - return; - } - - alps_process_touchpad_packet_v3(psmouse); -} - -static void alps_process_packet_v4(struct psmouse *psmouse) -{ - unsigned char *packet = psmouse->packet; - struct input_dev *dev = psmouse->dev; - int x, y, z; - int left, right; - - left = packet[4] & 0x01; - right = packet[4] & 0x02; - - x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | - ((packet[0] & 0x30) >> 4); - y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); - z = packet[5] & 0x7f; - - if (z >= 64) - input_report_key(dev, BTN_TOUCH, 1); - else - input_report_key(dev, BTN_TOUCH, 0); - - if (z > 0) { - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - } - input_report_abs(dev, ABS_PRESSURE, z); - - input_report_key(dev, BTN_TOOL_FINGER, z > 0); - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_RIGHT, right); - - input_sync(dev); -} - -static void alps_process_packet(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - - switch (model->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - alps_process_packet_v1_v2(psmouse); - break; - case ALPS_PROTO_V3: - alps_process_packet_v3(psmouse); - break; - case ALPS_PROTO_V4: - alps_process_packet_v4(psmouse); - break; - } -} - -static void alps_report_bare_ps2_packet(struct psmouse *psmouse, - unsigned char packet[], - bool report_buttons) -{ - struct alps_data *priv = psmouse->private; - struct input_dev *dev2 = priv->dev2; - - if (report_buttons) - alps_report_buttons(psmouse, dev2, psmouse->dev, - packet[0] & 1, packet[0] & 2, packet[0] & 4); - - input_report_rel(dev2, REL_X, - packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); - input_report_rel(dev2, REL_Y, - packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); - - input_sync(dev2); -} - -static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - - if (psmouse->pktcnt < 6) - return PSMOUSE_GOOD_DATA; - - if (psmouse->pktcnt == 6) { - /* - * Start a timer to flush the packet if it ends up last - * 6-byte packet in the stream. Timer needs to fire - * psmouse core times out itself. 20 ms should be enough - * to decide if we are getting more data or not. - */ - mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20)); - return PSMOUSE_GOOD_DATA; - } - - del_timer(&priv->timer); - - if (psmouse->packet[6] & 0x80) { - - /* - * Highest bit is set - that means we either had - * complete ALPS packet and this is start of the - * next packet or we got garbage. - */ - - if (((psmouse->packet[3] | - psmouse->packet[4] | - psmouse->packet[5]) & 0x80) || - (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { - psmouse_dbg(psmouse, - "refusing packet %x %x %x %x (suspected interleaved ps/2)\n", - psmouse->packet[3], psmouse->packet[4], - psmouse->packet[5], psmouse->packet[6]); - return PSMOUSE_BAD_DATA; - } - - alps_process_packet(psmouse); - - /* Continue with the next packet */ - psmouse->packet[0] = psmouse->packet[6]; - psmouse->pktcnt = 1; - - } else { - - /* - * High bit is 0 - that means that we indeed got a PS/2 - * packet in the middle of ALPS packet. - * - * There is also possibility that we got 6-byte ALPS - * packet followed by 3-byte packet from trackpoint. We - * can not distinguish between these 2 scenarios but - * because the latter is unlikely to happen in course of - * normal operation (user would need to press all - * buttons on the pad and start moving trackpoint - * without touching the pad surface) we assume former. - * Even if we are wrong the wost thing that would happen - * the cursor would jump but we should not get protocol - * de-synchronization. - */ - - alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], - false); - - /* - * Continue with the standard ALPS protocol handling, - * but make sure we won't process it as an interleaved - * packet again, which may happen if all buttons are - * pressed. To avoid this let's reset the 4th bit which - * is normally 1. - */ - psmouse->packet[3] = psmouse->packet[6] & 0xf7; - psmouse->pktcnt = 4; - } - - return PSMOUSE_GOOD_DATA; -} - -static void alps_flush_packet(unsigned long data) -{ - struct psmouse *psmouse = (struct psmouse *)data; - - serio_pause_rx(psmouse->ps2dev.serio); - - if (psmouse->pktcnt == psmouse->pktsize) { - - /* - * We did not any more data in reasonable amount of time. - * Validate the last 3 bytes and process as a standard - * ALPS packet. - */ - if ((psmouse->packet[3] | - psmouse->packet[4] | - psmouse->packet[5]) & 0x80) { - psmouse_dbg(psmouse, - "refusing packet %x %x %x (suspected interleaved ps/2)\n", - psmouse->packet[3], psmouse->packet[4], - psmouse->packet[5]); - } else { - alps_process_packet(psmouse); - } - psmouse->pktcnt = 0; - } - - serio_continue_rx(psmouse->ps2dev.serio); -} - -static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - - if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ - if (psmouse->pktcnt == 3) { - alps_report_bare_ps2_packet(psmouse, psmouse->packet, - true); - return PSMOUSE_FULL_PACKET; - } - return PSMOUSE_GOOD_DATA; - } - - /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ - - if ((model->flags & ALPS_PS2_INTERLEAVED) && - psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { - return alps_handle_interleaved_ps2(psmouse); - } - - if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { - psmouse_dbg(psmouse, - "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", - psmouse->packet[0], model->mask0, model->byte0); - return PSMOUSE_BAD_DATA; - } - - /* Bytes 2 - pktsize should have 0 in the highest bit */ - if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { - psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", - psmouse->pktcnt - 1, - psmouse->packet[psmouse->pktcnt - 1]); - return PSMOUSE_BAD_DATA; - } - - if (psmouse->pktcnt == psmouse->pktsize) { - alps_process_packet(psmouse); - return PSMOUSE_FULL_PACKET; - } - - return PSMOUSE_GOOD_DATA; -} - -static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - struct alps_data *priv = psmouse->private; - int command; - unsigned char *param; - unsigned char dummy[4]; - - BUG_ON(nibble > 0xf); - - command = priv->nibble_commands[nibble].command; - param = (command & 0x0f00) ? - dummy : (unsigned char *)&priv->nibble_commands[nibble].data; - - if (ps2_command(ps2dev, param, command)) - return -1; - - return 0; -} - -static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - struct alps_data *priv = psmouse->private; - int i, nibble; - - if (ps2_command(ps2dev, NULL, priv->addr_command)) - return -1; - - for (i = 12; i >= 0; i -= 4) { - nibble = (addr >> i) & 0xf; - if (alps_command_mode_send_nibble(psmouse, nibble)) - return -1; - } - - return 0; -} - -static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - - if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) - return -1; - - /* - * The address being read is returned in the first two bytes - * of the result. Check that this address matches the expected - * address. - */ - if (addr != ((param[0] << 8) | param[1])) - return -1; - - return param[2]; -} - -static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr) -{ - if (alps_command_mode_set_addr(psmouse, addr)) - return -1; - return __alps_command_mode_read_reg(psmouse, addr); -} - -static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value) -{ - if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf)) - return -1; - if (alps_command_mode_send_nibble(psmouse, value & 0xf)) - return -1; - return 0; -} - -static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, - u8 value) -{ - if (alps_command_mode_set_addr(psmouse, addr)) - return -1; - return __alps_command_mode_write_reg(psmouse, value); -} - -static int alps_enter_command_mode(struct psmouse *psmouse, - unsigned char *resp) -{ - unsigned char param[4]; - struct ps2dev *ps2dev = &psmouse->ps2dev; - - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { - psmouse_err(psmouse, "failed to enter command mode\n"); - return -1; - } - - if (param[0] != 0x88 && param[1] != 0x07) { - psmouse_dbg(psmouse, - "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", - param[0], param[1], param[2]); - return -1; - } - - if (resp) - *resp = param[2]; - return 0; -} - -static inline int alps_exit_command_mode(struct psmouse *psmouse) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) - return -1; - return 0; -} - -static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; - unsigned char param[4]; - const struct alps_model_info *model = NULL; - int i; - - /* - * First try "E6 report". - * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. - * The bits 0-2 of the first byte will be 1s if some buttons are - * pressed. - */ - param[0] = 0; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) - return NULL; - - param[0] = param[1] = param[2] = 0xff; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) - return NULL; - - psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", - param[0], param[1], param[2]); - - if ((param[0] & 0xf8) != 0 || param[1] != 0 || - (param[2] != 10 && param[2] != 100)) - return NULL; - - /* - * Now try "E7 report". Allowed responses are in - * alps_model_data[].signature - */ - param[0] = 0; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) - return NULL; - - param[0] = param[1] = param[2] = 0xff; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) - return NULL; - - psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", - param[0], param[1], param[2]); - - if (version) { - for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) - /* empty */; - *version = (param[0] << 8) | (param[1] << 4) | i; - } - - for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { - if (!memcmp(param, alps_model_data[i].signature, - sizeof(alps_model_data[i].signature))) { - model = alps_model_data + i; - break; - } - } - - if (model && model->proto_version > ALPS_PROTO_V2) { - /* - * Need to check command mode response to identify - * model - */ - model = NULL; - if (alps_enter_command_mode(psmouse, param)) { - psmouse_warn(psmouse, - "touchpad failed to enter command mode\n"); - } else { - for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { - if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && - alps_model_data[i].command_mode_resp == param[0]) { - model = alps_model_data + i; - break; - } - } - alps_exit_command_mode(psmouse); - - if (!model) - psmouse_dbg(psmouse, - "Unknown command mode response %2.2x\n", - param[0]); - } - } - - return model; -} - -/* - * For DualPoint devices select the device that should respond to - * subsequent commands. It looks like glidepad is behind stickpointer, - * I'd thought it would be other way around... - */ -static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; - - if (ps2_command(ps2dev, NULL, cmd) || - ps2_command(ps2dev, NULL, cmd) || - ps2_command(ps2dev, NULL, cmd) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE)) - return -1; - - /* we may get 3 more bytes, just ignore them */ - ps2_drain(ps2dev, 3, 100); - - return 0; -} - -static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - - /* Try ALPS magic knock - 4 disable before enable */ - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) - return -1; - - /* - * Switch mouse to poll (remote) mode so motion data will not - * get in our way - */ - return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL); -} - -static int alps_get_status(struct psmouse *psmouse, char *param) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - - /* Get status: 0xF5 0xF5 0xF5 0xE9 */ - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) - return -1; - - psmouse_dbg(psmouse, "Status: %2.2x %2.2x %2.2x", - param[0], param[1], param[2]); - - return 0; -} - -/* - * Turn touchpad tapping on or off. The sequences are: - * 0xE9 0xF5 0xF5 0xF3 0x0A to enable, - * 0xE9 0xF5 0xF5 0xE8 0x00 to disable. - * My guess that 0xE9 (GetInfo) is here as a sync point. - * For models that also have stickpointer (DualPoints) its tapping - * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but - * we don't fiddle with it. - */ -static int alps_tap_mode(struct psmouse *psmouse, int enable) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES; - unsigned char tap_arg = enable ? 0x0A : 0x00; - unsigned char param[4]; - - if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, &tap_arg, cmd)) - return -1; - - if (alps_get_status(psmouse, param)) - return -1; - - return 0; -} - -/* - * alps_poll() - poll the touchpad for current motion packet. - * Used in resync. - */ -static int alps_poll(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - unsigned char buf[sizeof(psmouse->packet)]; - bool poll_failed; - - if (priv->i->flags & ALPS_PASS) - alps_passthrough_mode_v2(psmouse, true); - - poll_failed = ps2_command(&psmouse->ps2dev, buf, - PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; - - if (priv->i->flags & ALPS_PASS) - alps_passthrough_mode_v2(psmouse, false); - - if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) - return -1; - - if ((psmouse->badbyte & 0xc8) == 0x08) { -/* - * Poll the track stick ... - */ - if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8))) - return -1; - } - - memcpy(psmouse->packet, buf, sizeof(buf)); - return 0; -} - -static int alps_hw_init_v1_v2(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - - if ((model->flags & ALPS_PASS) && - alps_passthrough_mode_v2(psmouse, true)) { - return -1; - } - - if (alps_tap_mode(psmouse, true)) { - psmouse_warn(psmouse, "Failed to enable hardware tapping\n"); - return -1; - } - - if (alps_absolute_mode_v1_v2(psmouse)) { - psmouse_err(psmouse, "Failed to enable absolute mode\n"); - return -1; - } - - if ((model->flags & ALPS_PASS) && - alps_passthrough_mode_v2(psmouse, false)) { - return -1; - } - - /* ALPS needs stream mode, otherwise it won't report any data */ - if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { - psmouse_err(psmouse, "Failed to enable stream mode\n"); - return -1; - } - - return 0; -} - -/* - * Enable or disable passthrough mode to the trackstick. Must be in - * command mode when calling this function. - */ -static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) -{ - int reg_val; - - reg_val = alps_command_mode_read_reg(psmouse, 0x0008); - if (reg_val == -1) - return -1; - - if (enable) - reg_val |= 0x01; - else - reg_val &= ~0x01; - - if (__alps_command_mode_write_reg(psmouse, reg_val)) - return -1; - - return 0; -} - -/* Must be in command mode when calling this function */ -static int alps_absolute_mode_v3(struct psmouse *psmouse) -{ - int reg_val; - - reg_val = alps_command_mode_read_reg(psmouse, 0x0004); - if (reg_val == -1) - return -1; - - reg_val |= 0x06; - if (__alps_command_mode_write_reg(psmouse, reg_val)) - return -1; - - return 0; -} - -static int alps_hw_init_v3(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - int reg_val; - unsigned char param[4]; - - priv->nibble_commands = alps_v3_nibble_commands; - priv->addr_command = PSMOUSE_CMD_RESET_WRAP; - - if (alps_enter_command_mode(psmouse, NULL)) - goto error; - - /* Check for trackstick */ - reg_val = alps_command_mode_read_reg(psmouse, 0x0008); - if (reg_val == -1) - goto error; - if (reg_val & 0x80) { - if (alps_passthrough_mode_v3(psmouse, true)) - goto error; - if (alps_exit_command_mode(psmouse)) - goto error; - - /* - * E7 report for the trackstick - * - * There have been reports of failures to seem to trace back - * to the above trackstick check failing. When these occur - * this E7 report fails, so when that happens we continue - * with the assumption that there isn't a trackstick after - * all. - */ - param[0] = 0x64; - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { - psmouse_warn(psmouse, "trackstick E7 report failed\n"); - } else { - psmouse_dbg(psmouse, - "trackstick E7 report: %2.2x %2.2x %2.2x\n", - param[0], param[1], param[2]); - - /* - * Not sure what this does, but it is absolutely - * essential. Without it, the touchpad does not - * work at all and the trackstick just emits normal - * PS/2 packets. - */ - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - alps_command_mode_send_nibble(psmouse, 0x9) || - alps_command_mode_send_nibble(psmouse, 0x4)) { - psmouse_err(psmouse, - "Error sending magic E6 sequence\n"); - goto error_passthrough; - } - } - - if (alps_enter_command_mode(psmouse, NULL)) - goto error_passthrough; - if (alps_passthrough_mode_v3(psmouse, false)) - goto error; - } - - if (alps_absolute_mode_v3(psmouse)) { - psmouse_err(psmouse, "Failed to enter absolute mode\n"); - goto error; - } - - reg_val = alps_command_mode_read_reg(psmouse, 0x0006); - if (reg_val == -1) - goto error; - if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) - goto error; - - reg_val = alps_command_mode_read_reg(psmouse, 0x0007); - if (reg_val == -1) - goto error; - if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) - goto error; - - if (alps_command_mode_read_reg(psmouse, 0x0144) == -1) - goto error; - if (__alps_command_mode_write_reg(psmouse, 0x04)) - goto error; - - if (alps_command_mode_read_reg(psmouse, 0x0159) == -1) - goto error; - if (__alps_command_mode_write_reg(psmouse, 0x03)) - goto error; - - if (alps_command_mode_read_reg(psmouse, 0x0163) == -1) - goto error; - if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03)) - goto error; - - if (alps_command_mode_read_reg(psmouse, 0x0162) == -1) - goto error; - if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) - goto error; - - /* - * This ensures the trackstick packets are in the format - * supported by this driver. If bit 1 isn't set the packet - * format is different. - */ - if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82)) - goto error; - - alps_exit_command_mode(psmouse); - - /* Set rate and enable data reporting */ - param[0] = 0x64; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { - psmouse_err(psmouse, "Failed to enable data reporting\n"); - return -1; - } - - return 0; - -error_passthrough: - /* Something failed while in passthrough mode, so try to get out */ - if (!alps_enter_command_mode(psmouse, NULL)) - alps_passthrough_mode_v3(psmouse, false); -error: - /* - * Leaving the touchpad in command mode will essentially render - * it unusable until the machine reboots, so exit it here just - * to be safe - */ - alps_exit_command_mode(psmouse); - return -1; -} - -/* Must be in command mode when calling this function */ -static int alps_absolute_mode_v4(struct psmouse *psmouse) -{ - int reg_val; - - reg_val = alps_command_mode_read_reg(psmouse, 0x0004); - if (reg_val == -1) - return -1; - - reg_val |= 0x02; - if (__alps_command_mode_write_reg(psmouse, reg_val)) - return -1; - - return 0; -} - -static int alps_hw_init_v4(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - - priv->nibble_commands = alps_v4_nibble_commands; - priv->addr_command = PSMOUSE_CMD_DISABLE; - - if (alps_enter_command_mode(psmouse, NULL)) - goto error; - - if (alps_absolute_mode_v4(psmouse)) { - psmouse_err(psmouse, "Failed to enter absolute mode\n"); - goto error; - } - - if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c)) - goto error; - - if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03)) - goto error; - - if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03)) - goto error; - - if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15)) - goto error; - - if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01)) - goto error; - - if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03)) - goto error; - - if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03)) - goto error; - - if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03)) - goto error; - - alps_exit_command_mode(psmouse); - - /* - * This sequence changes the output from a 9-byte to an - * 8-byte format. All the same data seems to be present, - * just in a more compact format. - */ - param[0] = 0xc8; - param[1] = 0x64; - param[2] = 0x50; - if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || - ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) || - ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) - return -1; - - /* Set rate and enable data reporting */ - param[0] = 0x64; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { - psmouse_err(psmouse, "Failed to enable data reporting\n"); - return -1; - } - - return 0; - -error: - /* - * Leaving the touchpad in command mode will essentially render - * it unusable until the machine reboots, so exit it here just - * to be safe - */ - alps_exit_command_mode(psmouse); - return -1; -} - -static int alps_hw_init(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - int ret = -1; - - switch (model->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - ret = alps_hw_init_v1_v2(psmouse); - break; - case ALPS_PROTO_V3: - ret = alps_hw_init_v3(psmouse); - break; - case ALPS_PROTO_V4: - ret = alps_hw_init_v4(psmouse); - break; - } - - return ret; -} - -static int alps_reconnect(struct psmouse *psmouse) -{ - const struct alps_model_info *model; - - psmouse_reset(psmouse); - - model = alps_get_model(psmouse, NULL); - if (!model) - return -1; - - return alps_hw_init(psmouse); -} - -static void alps_disconnect(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - - psmouse_reset(psmouse); - del_timer_sync(&priv->timer); - input_unregister_device(priv->dev2); - kfree(priv); -} - -int alps_init(struct psmouse *psmouse) -{ - struct alps_data *priv; - const struct alps_model_info *model; - struct input_dev *dev1 = psmouse->dev, *dev2; - int version; - - priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); - dev2 = input_allocate_device(); - if (!priv || !dev2) - goto init_fail; - - priv->dev2 = dev2; - setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse); - - psmouse->private = priv; - - psmouse_reset(psmouse); - - model = alps_get_model(psmouse, &version); - if (!model) - goto init_fail; - - priv->i = model; - - if (alps_hw_init(psmouse)) - goto init_fail; - - /* - * Undo part of setup done for us by psmouse core since touchpad - * is not a relative device. - */ - __clear_bit(EV_REL, dev1->evbit); - __clear_bit(REL_X, dev1->relbit); - __clear_bit(REL_Y, dev1->relbit); - - /* - * Now set up our capabilities. - */ - dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); - dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); - dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); - dev1->keybit[BIT_WORD(BTN_LEFT)] |= - BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); - - dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); - - switch (model->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); - input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); - break; - case ALPS_PROTO_V3: - set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); - input_mt_init_slots(dev1, 2); - input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); - input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); - - set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); - set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); - set_bit(BTN_TOOL_QUADTAP, dev1->keybit); - /* fall through */ - case ALPS_PROTO_V4: - input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); - input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); - break; - } - - input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); - - if (model->flags & ALPS_WHEEL) { - dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); - dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); - } - - if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { - dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); - dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); - } - - if (model->flags & ALPS_FOUR_BUTTONS) { - dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); - dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); - dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); - dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3); - } else { - dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE); - } - - snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); - dev2->phys = priv->phys; - dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; - dev2->id.bustype = BUS_I8042; - dev2->id.vendor = 0x0002; - dev2->id.product = PSMOUSE_ALPS; - dev2->id.version = 0x0000; - dev2->dev.parent = &psmouse->ps2dev.serio->dev; - - dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - dev2->keybit[BIT_WORD(BTN_LEFT)] = - BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); - - if (input_register_device(priv->dev2)) - goto init_fail; - - psmouse->protocol_handler = alps_process_byte; - psmouse->poll = alps_poll; - psmouse->disconnect = alps_disconnect; - psmouse->reconnect = alps_reconnect; - psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; - - /* We are having trouble resyncing ALPS touchpads so disable it for now */ - psmouse->resync_time = 0; - - return 0; - -init_fail: - psmouse_reset(psmouse); - input_free_device(dev2); - kfree(priv); - psmouse->private = NULL; - return -1; -} - -int alps_detect(struct psmouse *psmouse, bool set_properties) -{ - int version; - const struct alps_model_info *model; - - model = alps_get_model(psmouse, &version); - if (!model) - return -1; - - if (set_properties) { - psmouse->vendor = "ALPS"; - psmouse->name = model->flags & ALPS_DUALPOINT ? - "DualPoint TouchPad" : "GlidePoint"; - psmouse->model = version; - } - return 0; -} - diff --git a/ANDROID_3.4.5/drivers/input/mouse/alps.h b/ANDROID_3.4.5/drivers/input/mouse/alps.h deleted file mode 100644 index a00a4ab9..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/alps.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ALPS touchpad PS/2 mouse driver - * - * Copyright (c) 2003 Peter Osterlund <petero2@telia.com> - * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> - * - * 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. - */ - -#ifndef _ALPS_H -#define _ALPS_H - -#define ALPS_PROTO_V1 0 -#define ALPS_PROTO_V2 1 -#define ALPS_PROTO_V3 2 -#define ALPS_PROTO_V4 3 - -struct alps_model_info { - unsigned char signature[3]; - unsigned char command_mode_resp; /* v3/v4 only */ - unsigned char proto_version; - unsigned char byte0, mask0; - unsigned char flags; -}; - -struct alps_nibble_commands { - int command; - unsigned char data; -}; - -struct alps_data { - struct input_dev *dev2; /* Relative device */ - char phys[32]; /* Phys */ - const struct alps_model_info *i;/* Info */ - const struct alps_nibble_commands *nibble_commands; - int addr_command; /* Command to set register address */ - int prev_fin; /* Finger bit from previous packet */ - int multi_packet; /* Multi-packet data in progress */ - unsigned char multi_data[6]; /* Saved multi-packet data */ - u8 quirks; - struct timer_list timer; -}; - -#define ALPS_QUIRK_TRACKSTICK_BUTTONS 1 /* trakcstick buttons in trackstick packet */ - -#ifdef CONFIG_MOUSE_PS2_ALPS -int alps_detect(struct psmouse *psmouse, bool set_properties); -int alps_init(struct psmouse *psmouse); -#else -inline int alps_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -inline int alps_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_ALPS */ - -#endif diff --git a/ANDROID_3.4.5/drivers/input/mouse/amimouse.c b/ANDROID_3.4.5/drivers/input/mouse/amimouse.c deleted file mode 100644 index 5fa99341..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/amimouse.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Amiga mouse driver for Linux/m68k - * - * Copyright (c) 2000-2002 Vojtech Pavlik - * - * Based on the work of: - * Michael Rausch James Banks - * Matther Dillon David Giller - * Nathan Laredo Linus Torvalds - * Johan Myreen Jes Sorensen - * Russell King - */ - -/* - * 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 - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/input.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> - -#include <asm/irq.h> -#include <asm/setup.h> -#include <asm/uaccess.h> -#include <asm/amigahw.h> -#include <asm/amigaints.h> - -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); -MODULE_DESCRIPTION("Amiga mouse driver"); -MODULE_LICENSE("GPL"); - -static int amimouse_lastx, amimouse_lasty; - -static irqreturn_t amimouse_interrupt(int irq, void *data) -{ - struct input_dev *dev = data; - unsigned short joy0dat, potgor; - int nx, ny, dx, dy; - - joy0dat = amiga_custom.joy0dat; - - nx = joy0dat & 0xff; - ny = joy0dat >> 8; - - dx = nx - amimouse_lastx; - dy = ny - amimouse_lasty; - - if (dx < -127) dx = (256 + nx) - amimouse_lastx; - if (dx > 127) dx = (nx - 256) - amimouse_lastx; - if (dy < -127) dy = (256 + ny) - amimouse_lasty; - if (dy > 127) dy = (ny - 256) - amimouse_lasty; - - amimouse_lastx = nx; - amimouse_lasty = ny; - - potgor = amiga_custom.potgor; - - input_report_rel(dev, REL_X, dx); - input_report_rel(dev, REL_Y, dy); - - input_report_key(dev, BTN_LEFT, ciaa.pra & 0x40); - input_report_key(dev, BTN_MIDDLE, potgor & 0x0100); - input_report_key(dev, BTN_RIGHT, potgor & 0x0400); - - input_sync(dev); - - return IRQ_HANDLED; -} - -static int amimouse_open(struct input_dev *dev) -{ - unsigned short joy0dat; - int error; - - joy0dat = amiga_custom.joy0dat; - - amimouse_lastx = joy0dat & 0xff; - amimouse_lasty = joy0dat >> 8; - - error = request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", - dev); - if (error) - dev_err(&dev->dev, "Can't allocate irq %d\n", IRQ_AMIGA_VERTB); - - return error; -} - -static void amimouse_close(struct input_dev *dev) -{ - free_irq(IRQ_AMIGA_VERTB, dev); -} - -static int __init amimouse_probe(struct platform_device *pdev) -{ - int err; - struct input_dev *dev; - - dev = input_allocate_device(); - if (!dev) - return -ENOMEM; - - dev->name = pdev->name; - dev->phys = "amimouse/input0"; - dev->id.bustype = BUS_AMIGA; - dev->id.vendor = 0x0001; - dev->id.product = 0x0002; - dev->id.version = 0x0100; - - dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); - dev->open = amimouse_open; - dev->close = amimouse_close; - dev->dev.parent = &pdev->dev; - - err = input_register_device(dev); - if (err) { - input_free_device(dev); - return err; - } - - platform_set_drvdata(pdev, dev); - - return 0; -} - -static int __exit amimouse_remove(struct platform_device *pdev) -{ - struct input_dev *dev = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - input_unregister_device(dev); - return 0; -} - -static struct platform_driver amimouse_driver = { - .remove = __exit_p(amimouse_remove), - .driver = { - .name = "amiga-mouse", - .owner = THIS_MODULE, - }, -}; - -static int __init amimouse_init(void) -{ - return platform_driver_probe(&amimouse_driver, amimouse_probe); -} - -module_init(amimouse_init); - -static void __exit amimouse_exit(void) -{ - platform_driver_unregister(&amimouse_driver); -} - -module_exit(amimouse_exit); - -MODULE_ALIAS("platform:amiga-mouse"); diff --git a/ANDROID_3.4.5/drivers/input/mouse/appletouch.c b/ANDROID_3.4.5/drivers/input/mouse/appletouch.c deleted file mode 100644 index 0acbc7d5..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/appletouch.c +++ /dev/null @@ -1,941 +0,0 @@ -/* - * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver - * - * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2005-2008 Johannes Berg (johannes@sipsolutions.net) - * Copyright (C) 2005-2008 Stelian Pop (stelian@popies.net) - * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) - * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) - * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) - * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) - * Copyright (C) 2007-2008 Sven Anders (anders@anduras.de) - * - * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/usb/input.h> - -/* - * Note: We try to keep the touchpad aspect ratio while still doing only - * simple arithmetics: - * 0 <= x <= (xsensors - 1) * xfact - * 0 <= y <= (ysensors - 1) * yfact - */ -struct atp_info { - int xsensors; /* number of X sensors */ - int xsensors_17; /* 17" models have more sensors */ - int ysensors; /* number of Y sensors */ - int xfact; /* X multiplication factor */ - int yfact; /* Y multiplication factor */ - int datalen; /* size of USB transfers */ - void (*callback)(struct urb *); /* callback function */ -}; - -static void atp_complete_geyser_1_2(struct urb *urb); -static void atp_complete_geyser_3_4(struct urb *urb); - -static const struct atp_info fountain_info = { - .xsensors = 16, - .xsensors_17 = 26, - .ysensors = 16, - .xfact = 64, - .yfact = 43, - .datalen = 81, - .callback = atp_complete_geyser_1_2, -}; - -static const struct atp_info geyser1_info = { - .xsensors = 16, - .xsensors_17 = 26, - .ysensors = 16, - .xfact = 64, - .yfact = 43, - .datalen = 81, - .callback = atp_complete_geyser_1_2, -}; - -static const struct atp_info geyser2_info = { - .xsensors = 15, - .xsensors_17 = 20, - .ysensors = 9, - .xfact = 64, - .yfact = 43, - .datalen = 64, - .callback = atp_complete_geyser_1_2, -}; - -static const struct atp_info geyser3_info = { - .xsensors = 20, - .ysensors = 10, - .xfact = 64, - .yfact = 64, - .datalen = 64, - .callback = atp_complete_geyser_3_4, -}; - -static const struct atp_info geyser4_info = { - .xsensors = 20, - .ysensors = 10, - .xfact = 64, - .yfact = 64, - .datalen = 64, - .callback = atp_complete_geyser_3_4, -}; - -#define ATP_DEVICE(prod, info) \ -{ \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_CLASS | \ - USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ - .idVendor = 0x05ac, /* Apple */ \ - .idProduct = (prod), \ - .bInterfaceClass = 0x03, \ - .bInterfaceProtocol = 0x02, \ - .driver_info = (unsigned long) &info, \ -} - -/* - * Table of devices (Product IDs) that work with this driver. - * (The names come from Info.plist in AppleUSBTrackpad.kext, - * According to Info.plist Geyser IV is the same as Geyser III.) - */ - -static struct usb_device_id atp_table[] = { - /* PowerBooks Feb 2005, iBooks G4 */ - ATP_DEVICE(0x020e, fountain_info), /* FOUNTAIN ANSI */ - ATP_DEVICE(0x020f, fountain_info), /* FOUNTAIN ISO */ - ATP_DEVICE(0x030a, fountain_info), /* FOUNTAIN TP ONLY */ - ATP_DEVICE(0x030b, geyser1_info), /* GEYSER 1 TP ONLY */ - - /* PowerBooks Oct 2005 */ - ATP_DEVICE(0x0214, geyser2_info), /* GEYSER 2 ANSI */ - ATP_DEVICE(0x0215, geyser2_info), /* GEYSER 2 ISO */ - ATP_DEVICE(0x0216, geyser2_info), /* GEYSER 2 JIS */ - - /* Core Duo MacBook & MacBook Pro */ - ATP_DEVICE(0x0217, geyser3_info), /* GEYSER 3 ANSI */ - ATP_DEVICE(0x0218, geyser3_info), /* GEYSER 3 ISO */ - ATP_DEVICE(0x0219, geyser3_info), /* GEYSER 3 JIS */ - - /* Core2 Duo MacBook & MacBook Pro */ - ATP_DEVICE(0x021a, geyser4_info), /* GEYSER 4 ANSI */ - ATP_DEVICE(0x021b, geyser4_info), /* GEYSER 4 ISO */ - ATP_DEVICE(0x021c, geyser4_info), /* GEYSER 4 JIS */ - - /* Core2 Duo MacBook3,1 */ - ATP_DEVICE(0x0229, geyser4_info), /* GEYSER 4 HF ANSI */ - ATP_DEVICE(0x022a, geyser4_info), /* GEYSER 4 HF ISO */ - ATP_DEVICE(0x022b, geyser4_info), /* GEYSER 4 HF JIS */ - - /* Terminating entry */ - { } -}; -MODULE_DEVICE_TABLE(usb, atp_table); - -/* maximum number of sensors */ -#define ATP_XSENSORS 26 -#define ATP_YSENSORS 16 - -/* amount of fuzz this touchpad generates */ -#define ATP_FUZZ 16 - -/* maximum pressure this driver will report */ -#define ATP_PRESSURE 300 - -/* - * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is - * ignored. - */ -#define ATP_THRESHOLD 5 - -/* Geyser initialization constants */ -#define ATP_GEYSER_MODE_READ_REQUEST_ID 1 -#define ATP_GEYSER_MODE_WRITE_REQUEST_ID 9 -#define ATP_GEYSER_MODE_REQUEST_VALUE 0x300 -#define ATP_GEYSER_MODE_REQUEST_INDEX 0 -#define ATP_GEYSER_MODE_VENDOR_VALUE 0x04 - -/** - * enum atp_status_bits - status bit meanings - * - * These constants represent the meaning of the status bits. - * (only Geyser 3/4) - * - * @ATP_STATUS_BUTTON: The button was pressed - * @ATP_STATUS_BASE_UPDATE: Update of the base values (untouched pad) - * @ATP_STATUS_FROM_RESET: Reset previously performed - */ -enum atp_status_bits { - ATP_STATUS_BUTTON = BIT(0), - ATP_STATUS_BASE_UPDATE = BIT(2), - ATP_STATUS_FROM_RESET = BIT(4), -}; - -/* Structure to hold all of our device specific stuff */ -struct atp { - char phys[64]; - struct usb_device *udev; /* usb device */ - struct urb *urb; /* usb request block */ - u8 *data; /* transferred data */ - struct input_dev *input; /* input dev */ - const struct atp_info *info; /* touchpad model */ - bool open; - bool valid; /* are the samples valid? */ - bool size_detect_done; - bool overflow_warned; - int x_old; /* last reported x/y, */ - int y_old; /* used for smoothing */ - signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; - signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; - int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; - int idlecount; /* number of empty packets */ - struct work_struct work; -}; - -#define dbg_dump(msg, tab) \ - if (debug > 1) { \ - int __i; \ - printk(KERN_DEBUG "appletouch: %s", msg); \ - for (__i = 0; __i < ATP_XSENSORS + ATP_YSENSORS; __i++) \ - printk(" %02x", tab[__i]); \ - printk("\n"); \ - } - -#define dprintk(format, a...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG format, ##a); \ - } while (0) - -MODULE_AUTHOR("Johannes Berg"); -MODULE_AUTHOR("Stelian Pop"); -MODULE_AUTHOR("Frank Arnold"); -MODULE_AUTHOR("Michael Hanselmann"); -MODULE_AUTHOR("Sven Anders"); -MODULE_DESCRIPTION("Apple PowerBook and MacBook USB touchpad driver"); -MODULE_LICENSE("GPL"); - -/* - * Make the threshold a module parameter - */ -static int threshold = ATP_THRESHOLD; -module_param(threshold, int, 0644); -MODULE_PARM_DESC(threshold, "Discard any change in data from a sensor" - " (the trackpad has many of these sensors)" - " less than this value."); - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Activate debugging output"); - -/* - * By default newer Geyser devices send standard USB HID mouse - * packets (Report ID 2). This code changes device mode, so it - * sends raw sensor reports (Report ID 5). - */ -static int atp_geyser_init(struct usb_device *udev) -{ - char *data; - int size; - int i; - int ret; - - data = kmalloc(8, GFP_KERNEL); - if (!data) { - err("Out of memory"); - return -ENOMEM; - } - - size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - ATP_GEYSER_MODE_READ_REQUEST_ID, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ATP_GEYSER_MODE_REQUEST_VALUE, - ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000); - - if (size != 8) { - dprintk("atp_geyser_init: read error\n"); - for (i = 0; i < 8; i++) - dprintk("appletouch[%d]: %d\n", i, data[i]); - - err("Failed to read mode from device."); - ret = -EIO; - goto out_free; - } - - /* Apply the mode switch */ - data[0] = ATP_GEYSER_MODE_VENDOR_VALUE; - - size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - ATP_GEYSER_MODE_WRITE_REQUEST_ID, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ATP_GEYSER_MODE_REQUEST_VALUE, - ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000); - - if (size != 8) { - dprintk("atp_geyser_init: write error\n"); - for (i = 0; i < 8; i++) - dprintk("appletouch[%d]: %d\n", i, data[i]); - - err("Failed to request geyser raw mode"); - ret = -EIO; - goto out_free; - } - ret = 0; -out_free: - kfree(data); - return ret; -} - -/* - * Reinitialise the device. This usually stops stream of empty packets - * coming from it. - */ -static void atp_reinit(struct work_struct *work) -{ - struct atp *dev = container_of(work, struct atp, work); - struct usb_device *udev = dev->udev; - int retval; - - dprintk("appletouch: putting appletouch to sleep (reinit)\n"); - atp_geyser_init(udev); - - retval = usb_submit_urb(dev->urb, GFP_ATOMIC); - if (retval) - err("atp_reinit: usb_submit_urb failed with error %d", - retval); -} - -static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, - int *z, int *fingers) -{ - int i; - /* values to calculate mean */ - int pcum = 0, psum = 0; - int is_increasing = 0; - - *fingers = 0; - - for (i = 0; i < nb_sensors; i++) { - if (xy_sensors[i] < threshold) { - if (is_increasing) - is_increasing = 0; - - continue; - } - - /* - * Makes the finger detection more versatile. For example, - * two fingers with no gap will be detected. Also, my - * tests show it less likely to have intermittent loss - * of multiple finger readings while moving around (scrolling). - * - * Changes the multiple finger detection to counting humps on - * sensors (transitions from nonincreasing to increasing) - * instead of counting transitions from low sensors (no - * finger reading) to high sensors (finger above - * sensor) - * - * - Jason Parekh <jasonparekh@gmail.com> - */ - if (i < 1 || - (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { - (*fingers)++; - is_increasing = 1; - } else if (i > 0 && (xy_sensors[i - 1] - xy_sensors[i] > threshold)) { - is_increasing = 0; - } - - /* - * Subtracts threshold so a high sensor that just passes the - * threshold won't skew the calculated absolute coordinate. - * Fixes an issue where slowly moving the mouse would - * occasionally jump a number of pixels (slowly moving the - * finger makes this issue most apparent.) - */ - pcum += (xy_sensors[i] - threshold) * i; - psum += (xy_sensors[i] - threshold); - } - - if (psum > 0) { - *z = psum; - return pcum * fact / psum; - } - - return 0; -} - -static inline void atp_report_fingers(struct input_dev *input, int fingers) -{ - input_report_key(input, BTN_TOOL_FINGER, fingers == 1); - input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2); - input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); -} - -/* Check URB status and for correct length of data package */ - -#define ATP_URB_STATUS_SUCCESS 0 -#define ATP_URB_STATUS_ERROR 1 -#define ATP_URB_STATUS_ERROR_FATAL 2 - -static int atp_status_check(struct urb *urb) -{ - struct atp *dev = urb->context; - - switch (urb->status) { - case 0: - /* success */ - break; - case -EOVERFLOW: - if (!dev->overflow_warned) { - printk(KERN_WARNING "appletouch: OVERFLOW with data " - "length %d, actual length is %d\n", - dev->info->datalen, dev->urb->actual_length); - dev->overflow_warned = true; - } - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* This urb is terminated, clean up */ - dbg("atp_complete: urb shutting down with status: %d", - urb->status); - return ATP_URB_STATUS_ERROR_FATAL; - - default: - dbg("atp_complete: nonzero urb status received: %d", - urb->status); - return ATP_URB_STATUS_ERROR; - } - - /* drop incomplete datasets */ - if (dev->urb->actual_length != dev->info->datalen) { - dprintk("appletouch: incomplete data package" - " (first byte: %d, length: %d).\n", - dev->data[0], dev->urb->actual_length); - return ATP_URB_STATUS_ERROR; - } - - return ATP_URB_STATUS_SUCCESS; -} - -static void atp_detect_size(struct atp *dev) -{ - int i; - - /* 17" Powerbooks have extra X sensors */ - for (i = dev->info->xsensors; i < ATP_XSENSORS; i++) { - if (dev->xy_cur[i]) { - - printk(KERN_INFO "appletouch: 17\" model detected.\n"); - - input_set_abs_params(dev->input, ABS_X, 0, - (dev->info->xsensors_17 - 1) * - dev->info->xfact - 1, - ATP_FUZZ, 0); - break; - } - } -} - -/* - * USB interrupt callback functions - */ - -/* Interrupt function for older touchpads: FOUNTAIN/GEYSER1/GEYSER2 */ - -static void atp_complete_geyser_1_2(struct urb *urb) -{ - int x, y, x_z, y_z, x_f, y_f; - int retval, i, j; - int key; - struct atp *dev = urb->context; - int status = atp_status_check(urb); - - if (status == ATP_URB_STATUS_ERROR_FATAL) - return; - else if (status == ATP_URB_STATUS_ERROR) - goto exit; - - /* reorder the sensors values */ - if (dev->info == &geyser2_info) { - memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); - - /* - * The values are laid out like this: - * Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ... - * '-' is an unused value. - */ - - /* read X values */ - for (i = 0, j = 19; i < 20; i += 2, j += 3) { - dev->xy_cur[i] = dev->data[j]; - dev->xy_cur[i + 1] = dev->data[j + 1]; - } - - /* read Y values */ - for (i = 0, j = 1; i < 9; i += 2, j += 3) { - dev->xy_cur[ATP_XSENSORS + i] = dev->data[j]; - dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1]; - } - } else { - for (i = 0; i < 8; i++) { - /* X values */ - dev->xy_cur[i + 0] = dev->data[5 * i + 2]; - dev->xy_cur[i + 8] = dev->data[5 * i + 4]; - dev->xy_cur[i + 16] = dev->data[5 * i + 42]; - if (i < 2) - dev->xy_cur[i + 24] = dev->data[5 * i + 44]; - - /* Y values */ - dev->xy_cur[ATP_XSENSORS + i] = dev->data[5 * i + 1]; - dev->xy_cur[ATP_XSENSORS + i + 8] = dev->data[5 * i + 3]; - } - } - - dbg_dump("sample", dev->xy_cur); - - if (!dev->valid) { - /* first sample */ - dev->valid = true; - dev->x_old = dev->y_old = -1; - - /* Store first sample */ - memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); - - /* Perform size detection, if not done already */ - if (unlikely(!dev->size_detect_done)) { - atp_detect_size(dev); - dev->size_detect_done = 1; - goto exit; - } - } - - for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { - /* accumulate the change */ - signed char change = dev->xy_old[i] - dev->xy_cur[i]; - dev->xy_acc[i] -= change; - - /* prevent down drifting */ - if (dev->xy_acc[i] < 0) - dev->xy_acc[i] = 0; - } - - memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); - - dbg_dump("accumulator", dev->xy_acc); - - x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, - dev->info->xfact, &x_z, &x_f); - y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, - dev->info->yfact, &y_z, &y_f); - key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; - - if (x && y) { - if (dev->x_old != -1) { - x = (dev->x_old * 3 + x) >> 2; - y = (dev->y_old * 3 + y) >> 2; - dev->x_old = x; - dev->y_old = y; - - if (debug > 1) - printk(KERN_DEBUG "appletouch: " - "X: %3d Y: %3d Xz: %3d Yz: %3d\n", - x, y, x_z, y_z); - - input_report_key(dev->input, BTN_TOUCH, 1); - input_report_abs(dev->input, ABS_X, x); - input_report_abs(dev->input, ABS_Y, y); - input_report_abs(dev->input, ABS_PRESSURE, - min(ATP_PRESSURE, x_z + y_z)); - atp_report_fingers(dev->input, max(x_f, y_f)); - } - dev->x_old = x; - dev->y_old = y; - - } else if (!x && !y) { - - dev->x_old = dev->y_old = -1; - input_report_key(dev->input, BTN_TOUCH, 0); - input_report_abs(dev->input, ABS_PRESSURE, 0); - atp_report_fingers(dev->input, 0); - - /* reset the accumulator on release */ - memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); - } - - input_report_key(dev->input, BTN_LEFT, key); - input_sync(dev->input); - - exit: - retval = usb_submit_urb(dev->urb, GFP_ATOMIC); - if (retval) - err("atp_complete: usb_submit_urb failed with result %d", - retval); -} - -/* Interrupt function for older touchpads: GEYSER3/GEYSER4 */ - -static void atp_complete_geyser_3_4(struct urb *urb) -{ - int x, y, x_z, y_z, x_f, y_f; - int retval, i, j; - int key; - struct atp *dev = urb->context; - int status = atp_status_check(urb); - - if (status == ATP_URB_STATUS_ERROR_FATAL) - return; - else if (status == ATP_URB_STATUS_ERROR) - goto exit; - - /* Reorder the sensors values: - * - * The values are laid out like this: - * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... - * '-' is an unused value. - */ - - /* read X values */ - for (i = 0, j = 19; i < 20; i += 2, j += 3) { - dev->xy_cur[i] = dev->data[j + 1]; - dev->xy_cur[i + 1] = dev->data[j + 2]; - } - /* read Y values */ - for (i = 0, j = 1; i < 9; i += 2, j += 3) { - dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; - dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; - } - - dbg_dump("sample", dev->xy_cur); - - /* Just update the base values (i.e. touchpad in untouched state) */ - if (dev->data[dev->info->datalen - 1] & ATP_STATUS_BASE_UPDATE) { - - dprintk("appletouch: updated base values\n"); - - memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); - goto exit; - } - - for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { - /* calculate the change */ - dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i]; - - /* this is a round-robin value, so couple with that */ - if (dev->xy_acc[i] > 127) - dev->xy_acc[i] -= 256; - - if (dev->xy_acc[i] < -127) - dev->xy_acc[i] += 256; - - /* prevent down drifting */ - if (dev->xy_acc[i] < 0) - dev->xy_acc[i] = 0; - } - - dbg_dump("accumulator", dev->xy_acc); - - x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, - dev->info->xfact, &x_z, &x_f); - y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, - dev->info->yfact, &y_z, &y_f); - key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON; - - if (x && y) { - if (dev->x_old != -1) { - x = (dev->x_old * 3 + x) >> 2; - y = (dev->y_old * 3 + y) >> 2; - dev->x_old = x; - dev->y_old = y; - - if (debug > 1) - printk(KERN_DEBUG "appletouch: X: %3d Y: %3d " - "Xz: %3d Yz: %3d\n", - x, y, x_z, y_z); - - input_report_key(dev->input, BTN_TOUCH, 1); - input_report_abs(dev->input, ABS_X, x); - input_report_abs(dev->input, ABS_Y, y); - input_report_abs(dev->input, ABS_PRESSURE, - min(ATP_PRESSURE, x_z + y_z)); - atp_report_fingers(dev->input, max(x_f, y_f)); - } - dev->x_old = x; - dev->y_old = y; - - } else if (!x && !y) { - - dev->x_old = dev->y_old = -1; - input_report_key(dev->input, BTN_TOUCH, 0); - input_report_abs(dev->input, ABS_PRESSURE, 0); - atp_report_fingers(dev->input, 0); - - /* reset the accumulator on release */ - memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); - } - - input_report_key(dev->input, BTN_LEFT, key); - input_sync(dev->input); - - /* - * Geysers 3/4 will continue to send packets continually after - * the first touch unless reinitialised. Do so if it's been - * idle for a while in order to avoid waking the kernel up - * several hundred times a second. - */ - - /* - * Button must not be pressed when entering suspend, - * otherwise we will never release the button. - */ - if (!x && !y && !key) { - dev->idlecount++; - if (dev->idlecount == 10) { - dev->x_old = dev->y_old = -1; - dev->idlecount = 0; - schedule_work(&dev->work); - /* Don't resubmit urb here, wait for reinit */ - return; - } - } else - dev->idlecount = 0; - - exit: - retval = usb_submit_urb(dev->urb, GFP_ATOMIC); - if (retval) - err("atp_complete: usb_submit_urb failed with result %d", - retval); -} - -static int atp_open(struct input_dev *input) -{ - struct atp *dev = input_get_drvdata(input); - - if (usb_submit_urb(dev->urb, GFP_ATOMIC)) - return -EIO; - - dev->open = 1; - return 0; -} - -static void atp_close(struct input_dev *input) -{ - struct atp *dev = input_get_drvdata(input); - - usb_kill_urb(dev->urb); - cancel_work_sync(&dev->work); - dev->open = 0; -} - -static int atp_handle_geyser(struct atp *dev) -{ - struct usb_device *udev = dev->udev; - - if (dev->info != &fountain_info) { - /* switch to raw sensor mode */ - if (atp_geyser_init(udev)) - return -EIO; - - printk(KERN_INFO "appletouch: Geyser mode initialized.\n"); - } - - return 0; -} - -static int atp_probe(struct usb_interface *iface, - const struct usb_device_id *id) -{ - struct atp *dev; - struct input_dev *input_dev; - struct usb_device *udev = interface_to_usbdev(iface); - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int int_in_endpointAddr = 0; - int i, error = -ENOMEM; - const struct atp_info *info = (const struct atp_info *)id->driver_info; - - /* set up the endpoint information */ - /* use only the first interrupt-in endpoint */ - iface_desc = iface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { - endpoint = &iface_desc->endpoint[i].desc; - if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) { - /* we found an interrupt in endpoint */ - int_in_endpointAddr = endpoint->bEndpointAddress; - break; - } - } - if (!int_in_endpointAddr) { - err("Could not find int-in endpoint"); - return -EIO; - } - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(struct atp), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!dev || !input_dev) { - err("Out of memory"); - goto err_free_devs; - } - - dev->udev = udev; - dev->input = input_dev; - dev->info = info; - dev->overflow_warned = false; - - dev->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->urb) - goto err_free_devs; - - dev->data = usb_alloc_coherent(dev->udev, dev->info->datalen, GFP_KERNEL, - &dev->urb->transfer_dma); - if (!dev->data) - goto err_free_urb; - - usb_fill_int_urb(dev->urb, udev, - usb_rcvintpipe(udev, int_in_endpointAddr), - dev->data, dev->info->datalen, - dev->info->callback, dev, 1); - - error = atp_handle_geyser(dev); - if (error) - goto err_free_buffer; - - usb_make_path(udev, dev->phys, sizeof(dev->phys)); - strlcat(dev->phys, "/input0", sizeof(dev->phys)); - - input_dev->name = "appletouch"; - input_dev->phys = dev->phys; - usb_to_input_id(dev->udev, &input_dev->id); - input_dev->dev.parent = &iface->dev; - - input_set_drvdata(input_dev, dev); - - input_dev->open = atp_open; - input_dev->close = atp_close; - - set_bit(EV_ABS, input_dev->evbit); - - input_set_abs_params(input_dev, ABS_X, 0, - (dev->info->xsensors - 1) * dev->info->xfact - 1, - ATP_FUZZ, 0); - input_set_abs_params(input_dev, ABS_Y, 0, - (dev->info->ysensors - 1) * dev->info->yfact - 1, - ATP_FUZZ, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); - - set_bit(EV_KEY, input_dev->evbit); - set_bit(BTN_TOUCH, input_dev->keybit); - set_bit(BTN_TOOL_FINGER, input_dev->keybit); - set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); - set_bit(BTN_LEFT, input_dev->keybit); - - error = input_register_device(dev->input); - if (error) - goto err_free_buffer; - - /* save our data pointer in this interface device */ - usb_set_intfdata(iface, dev); - - INIT_WORK(&dev->work, atp_reinit); - - return 0; - - err_free_buffer: - usb_free_coherent(dev->udev, dev->info->datalen, - dev->data, dev->urb->transfer_dma); - err_free_urb: - usb_free_urb(dev->urb); - err_free_devs: - usb_set_intfdata(iface, NULL); - kfree(dev); - input_free_device(input_dev); - return error; -} - -static void atp_disconnect(struct usb_interface *iface) -{ - struct atp *dev = usb_get_intfdata(iface); - - usb_set_intfdata(iface, NULL); - if (dev) { - usb_kill_urb(dev->urb); - input_unregister_device(dev->input); - usb_free_coherent(dev->udev, dev->info->datalen, - dev->data, dev->urb->transfer_dma); - usb_free_urb(dev->urb); - kfree(dev); - } - printk(KERN_INFO "input: appletouch disconnected\n"); -} - -static int atp_recover(struct atp *dev) -{ - int error; - - error = atp_handle_geyser(dev); - if (error) - return error; - - if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC)) - return -EIO; - - return 0; -} - -static int atp_suspend(struct usb_interface *iface, pm_message_t message) -{ - struct atp *dev = usb_get_intfdata(iface); - - usb_kill_urb(dev->urb); - return 0; -} - -static int atp_resume(struct usb_interface *iface) -{ - struct atp *dev = usb_get_intfdata(iface); - - if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC)) - return -EIO; - - return 0; -} - -static int atp_reset_resume(struct usb_interface *iface) -{ - struct atp *dev = usb_get_intfdata(iface); - - return atp_recover(dev); -} - -static struct usb_driver atp_driver = { - .name = "appletouch", - .probe = atp_probe, - .disconnect = atp_disconnect, - .suspend = atp_suspend, - .resume = atp_resume, - .reset_resume = atp_reset_resume, - .id_table = atp_table, -}; - -module_usb_driver(atp_driver); diff --git a/ANDROID_3.4.5/drivers/input/mouse/atarimouse.c b/ANDROID_3.4.5/drivers/input/mouse/atarimouse.c deleted file mode 100644 index d1c43236..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/atarimouse.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Atari mouse driver for Linux/m68k - * - * Copyright (c) 2005 Michael Schmitz - * - * Based on: - * Amiga mouse driver for Linux/m68k - * - * Copyright (c) 2000-2002 Vojtech Pavlik - * - */ -/* - * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c - * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard - * interrupt is shared with the MIDI ACIA so MIDI data also get handled there). - * This driver only deals with handing key events off to the input layer. - * - * Largely based on the old: - * - * Atari Mouse Driver for Linux - * by Robert de Vries (robert@and.nl) 19Jul93 - * - * 16 Nov 1994 Andreas Schwab - * Compatibility with busmouse - * Support for three button mouse (shamelessly stolen from MiNT) - * third button wired to one of the joystick directions on joystick 1 - * - * 1996/02/11 Andreas Schwab - * Module support - * Allow multiple open's - * - * Converted to use new generic busmouse code. 5 Apr 1998 - * Russell King <rmk@arm.uk.linux.org> - */ - - -/* - * 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 - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/input.h> -#include <linux/interrupt.h> - -#include <asm/irq.h> -#include <asm/setup.h> -#include <asm/uaccess.h> -#include <asm/atarihw.h> -#include <asm/atarikb.h> -#include <asm/atariints.h> - -MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>"); -MODULE_DESCRIPTION("Atari mouse driver"); -MODULE_LICENSE("GPL"); - -static int mouse_threshold[2] = {2, 2}; -module_param_array(mouse_threshold, int, NULL, 0); - -#ifdef FIXED_ATARI_JOYSTICK -extern int atari_mouse_buttons; -#endif - -static struct input_dev *atamouse_dev; - -static void atamouse_interrupt(char *buf) -{ - int buttons, dx, dy; - - buttons = (buf[0] & 1) | ((buf[0] & 2) << 1); -#ifdef FIXED_ATARI_JOYSTICK - buttons |= atari_mouse_buttons & 2; - atari_mouse_buttons = buttons; -#endif - - /* only relative events get here */ - dx = buf[1]; - dy = buf[2]; - - input_report_rel(atamouse_dev, REL_X, dx); - input_report_rel(atamouse_dev, REL_Y, dy); - - input_report_key(atamouse_dev, BTN_LEFT, buttons & 0x4); - input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2); - input_report_key(atamouse_dev, BTN_RIGHT, buttons & 0x1); - - input_sync(atamouse_dev); - - return; -} - -static int atamouse_open(struct input_dev *dev) -{ -#ifdef FIXED_ATARI_JOYSTICK - atari_mouse_buttons = 0; -#endif - ikbd_mouse_y0_top(); - ikbd_mouse_thresh(mouse_threshold[0], mouse_threshold[1]); - ikbd_mouse_rel_pos(); - atari_input_mouse_interrupt_hook = atamouse_interrupt; - - return 0; -} - -static void atamouse_close(struct input_dev *dev) -{ - ikbd_mouse_disable(); - atari_input_mouse_interrupt_hook = NULL; -} - -static int __init atamouse_init(void) -{ - int error; - - if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP)) - return -ENODEV; - - error = atari_keyb_init(); - if (error) - return error; - - atamouse_dev = input_allocate_device(); - if (!atamouse_dev) - return -ENOMEM; - - atamouse_dev->name = "Atari mouse"; - atamouse_dev->phys = "atamouse/input0"; - atamouse_dev->id.bustype = BUS_HOST; - atamouse_dev->id.vendor = 0x0001; - atamouse_dev->id.product = 0x0002; - atamouse_dev->id.version = 0x0100; - - atamouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - atamouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - atamouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); - - atamouse_dev->open = atamouse_open; - atamouse_dev->close = atamouse_close; - - error = input_register_device(atamouse_dev); - if (error) { - input_free_device(atamouse_dev); - return error; - } - - return 0; -} - -static void __exit atamouse_exit(void) -{ - input_unregister_device(atamouse_dev); -} - -module_init(atamouse_init); -module_exit(atamouse_exit); diff --git a/ANDROID_3.4.5/drivers/input/mouse/bcm5974.c b/ANDROID_3.4.5/drivers/input/mouse/bcm5974.c deleted file mode 100644 index f9e2758b..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/bcm5974.c +++ /dev/null @@ -1,947 +0,0 @@ -/* - * Apple USB BCM5974 (Macbook Air and Penryn Macbook Pro) multitouch driver - * - * Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se) - * - * The USB initialization and package decoding was made by - * Scott Shawcroft as part of the touchd user-space driver project: - * Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com) - * - * The BCM5974 driver is based on the appletouch driver: - * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) - * Copyright (C) 2005 Stelian Pop (stelian@popies.net) - * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) - * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) - * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) - * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/usb/input.h> -#include <linux/hid.h> -#include <linux/mutex.h> - -#define USB_VENDOR_ID_APPLE 0x05ac - -/* MacbookAir, aka wellspring */ -#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223 -#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224 -#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225 -/* MacbookProPenryn, aka wellspring2 */ -#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 -#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 -#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 -/* Macbook5,1 (unibody), aka wellspring3 */ -#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 -#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 -#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 -/* MacbookAir3,2 (unibody), aka wellspring5 */ -#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f -#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240 -#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241 -/* MacbookAir3,1 (unibody), aka wellspring4 */ -#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 -#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 -#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 -/* Macbook8 (unibody, March 2011) */ -#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 -#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 -#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 -/* MacbookAir4,1 (unibody, July 2011) */ -#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 -#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a -#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b -/* MacbookAir4,2 (unibody, July 2011) */ -#define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c -#define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d -#define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS 0x024e -/* Macbook8,2 (unibody) */ -#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 -#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 -#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 - -#define BCM5974_DEVICE(prod) { \ - .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_CLASS | \ - USB_DEVICE_ID_MATCH_INT_PROTOCOL), \ - .idVendor = USB_VENDOR_ID_APPLE, \ - .idProduct = (prod), \ - .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ - .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE \ -} - -/* table of devices that work with this driver */ -static const struct usb_device_id bcm5974_table[] = { - /* MacbookAir1.1 */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_JIS), - /* MacbookProPenryn */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), - /* Macbook5,1 */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), - /* MacbookAir3,2 */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_JIS), - /* MacbookAir3,1 */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), - /* MacbookPro8 */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), - /* MacbookAir4,1 */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS), - /* MacbookAir4,2 */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_JIS), - /* MacbookPro8,2 */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS), - /* Terminating entry */ - {} -}; -MODULE_DEVICE_TABLE(usb, bcm5974_table); - -MODULE_AUTHOR("Henrik Rydberg"); -MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver"); -MODULE_LICENSE("GPL"); - -#define dprintk(level, format, a...)\ - { if (debug >= level) printk(KERN_DEBUG format, ##a); } - -static int debug = 1; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Activate debugging output"); - -/* button data structure */ -struct bt_data { - u8 unknown1; /* constant */ - u8 button; /* left button */ - u8 rel_x; /* relative x coordinate */ - u8 rel_y; /* relative y coordinate */ -}; - -/* trackpad header types */ -enum tp_type { - TYPE1, /* plain trackpad */ - TYPE2 /* button integrated in trackpad */ -}; - -/* trackpad finger data offsets, le16-aligned */ -#define FINGER_TYPE1 (13 * sizeof(__le16)) -#define FINGER_TYPE2 (15 * sizeof(__le16)) - -/* trackpad button data offsets */ -#define BUTTON_TYPE2 15 - -/* list of device capability bits */ -#define HAS_INTEGRATED_BUTTON 1 - -/* trackpad finger structure, le16-aligned */ -struct tp_finger { - __le16 origin; /* zero when switching track finger */ - __le16 abs_x; /* absolute x coodinate */ - __le16 abs_y; /* absolute y coodinate */ - __le16 rel_x; /* relative x coodinate */ - __le16 rel_y; /* relative y coodinate */ - __le16 size_major; /* finger size, major axis? */ - __le16 size_minor; /* finger size, minor axis? */ - __le16 orientation; /* 16384 when point, else 15 bit angle */ - __le16 force_major; /* trackpad force, major axis? */ - __le16 force_minor; /* trackpad force, minor axis? */ - __le16 unused[3]; /* zeros */ - __le16 multi; /* one finger: varies, more fingers: constant */ -} __attribute__((packed,aligned(2))); - -/* trackpad finger data size, empirically at least ten fingers */ -#define SIZEOF_FINGER sizeof(struct tp_finger) -#define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) -#define MAX_FINGER_ORIENTATION 16384 - -/* device-specific parameters */ -struct bcm5974_param { - int dim; /* logical dimension */ - int fuzz; /* logical noise value */ - int devmin; /* device minimum reading */ - int devmax; /* device maximum reading */ -}; - -/* device-specific configuration */ -struct bcm5974_config { - int ansi, iso, jis; /* the product id of this device */ - int caps; /* device capability bitmask */ - int bt_ep; /* the endpoint of the button interface */ - int bt_datalen; /* data length of the button interface */ - int tp_ep; /* the endpoint of the trackpad interface */ - enum tp_type tp_type; /* type of trackpad interface */ - int tp_offset; /* offset to trackpad finger data */ - int tp_datalen; /* data length of the trackpad interface */ - struct bcm5974_param p; /* finger pressure limits */ - struct bcm5974_param w; /* finger width limits */ - struct bcm5974_param x; /* horizontal limits */ - struct bcm5974_param y; /* vertical limits */ -}; - -/* logical device structure */ -struct bcm5974 { - char phys[64]; - struct usb_device *udev; /* usb device */ - struct usb_interface *intf; /* our interface */ - struct input_dev *input; /* input dev */ - struct bcm5974_config cfg; /* device configuration */ - struct mutex pm_mutex; /* serialize access to open/suspend */ - int opened; /* 1: opened, 0: closed */ - struct urb *bt_urb; /* button usb request block */ - struct bt_data *bt_data; /* button transferred data */ - struct urb *tp_urb; /* trackpad usb request block */ - u8 *tp_data; /* trackpad transferred data */ - int fingers; /* number of fingers on trackpad */ -}; - -/* logical dimensions */ -#define DIM_PRESSURE 256 /* maximum finger pressure */ -#define DIM_WIDTH 16 /* maximum finger width */ -#define DIM_X 1280 /* maximum trackpad x value */ -#define DIM_Y 800 /* maximum trackpad y value */ - -/* logical signal quality */ -#define SN_PRESSURE 45 /* pressure signal-to-noise ratio */ -#define SN_WIDTH 100 /* width signal-to-noise ratio */ -#define SN_COORD 250 /* coordinate signal-to-noise ratio */ - -/* pressure thresholds */ -#define PRESSURE_LOW (2 * DIM_PRESSURE / SN_PRESSURE) -#define PRESSURE_HIGH (3 * PRESSURE_LOW) - -/* device constants */ -static const struct bcm5974_config bcm5974_config_table[] = { - { - USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, - USB_DEVICE_ID_APPLE_WELLSPRING_ISO, - USB_DEVICE_ID_APPLE_WELLSPRING_JIS, - 0, - 0x84, sizeof(struct bt_data), - 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, - { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, - { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, - { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, - { DIM_Y, DIM_Y / SN_COORD, -172, 5820 } - }, - { - USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, - USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, - USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, - 0, - 0x84, sizeof(struct bt_data), - 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, - { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, - { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, - { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, - { DIM_Y, DIM_Y / SN_COORD, -172, 4290 } - }, - { - USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI, - USB_DEVICE_ID_APPLE_WELLSPRING3_ISO, - USB_DEVICE_ID_APPLE_WELLSPRING3_JIS, - HAS_INTEGRATED_BUTTON, - 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, - { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, - { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, - { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } - }, - { - USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI, - USB_DEVICE_ID_APPLE_WELLSPRING4_ISO, - USB_DEVICE_ID_APPLE_WELLSPRING4_JIS, - HAS_INTEGRATED_BUTTON, - 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, - { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, - { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, - { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } - }, - { - USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI, - USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO, - USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS, - HAS_INTEGRATED_BUTTON, - 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, - { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, - { DIM_X, DIM_X / SN_COORD, -4616, 5112 }, - { DIM_Y, DIM_Y / SN_COORD, -142, 5234 } - }, - { - USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI, - USB_DEVICE_ID_APPLE_WELLSPRING5_ISO, - USB_DEVICE_ID_APPLE_WELLSPRING5_JIS, - HAS_INTEGRATED_BUTTON, - 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, - { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, - { DIM_X, DIM_X / SN_COORD, -4415, 5050 }, - { DIM_Y, DIM_Y / SN_COORD, -55, 6680 } - }, - { - USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI, - USB_DEVICE_ID_APPLE_WELLSPRING6_ISO, - USB_DEVICE_ID_APPLE_WELLSPRING6_JIS, - HAS_INTEGRATED_BUTTON, - 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, - { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, - { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, - { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } - }, - { - USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI, - USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO, - USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS, - HAS_INTEGRATED_BUTTON, - 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, - { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, - { DIM_X, DIM_X / SN_COORD, -4750, 5280 }, - { DIM_Y, DIM_Y / SN_COORD, -150, 6730 } - }, - { - USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI, - USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO, - USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS, - HAS_INTEGRATED_BUTTON, - 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, - { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, - { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, - { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, - { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } - }, - {} -}; - -/* return the device-specific configuration by device */ -static const struct bcm5974_config *bcm5974_get_config(struct usb_device *udev) -{ - u16 id = le16_to_cpu(udev->descriptor.idProduct); - const struct bcm5974_config *cfg; - - for (cfg = bcm5974_config_table; cfg->ansi; ++cfg) - if (cfg->ansi == id || cfg->iso == id || cfg->jis == id) - return cfg; - - return bcm5974_config_table; -} - -/* convert 16-bit little endian to signed integer */ -static inline int raw2int(__le16 x) -{ - return (signed short)le16_to_cpu(x); -} - -/* scale device data to logical dimensions (asserts devmin < devmax) */ -static inline int int2scale(const struct bcm5974_param *p, int x) -{ - return x * p->dim / (p->devmax - p->devmin); -} - -/* all logical value ranges are [0,dim). */ -static inline int int2bound(const struct bcm5974_param *p, int x) -{ - int s = int2scale(p, x); - - return clamp_val(s, 0, p->dim - 1); -} - -/* setup which logical events to report */ -static void setup_events_to_report(struct input_dev *input_dev, - const struct bcm5974_config *cfg) -{ - __set_bit(EV_ABS, input_dev->evbit); - - input_set_abs_params(input_dev, ABS_PRESSURE, - 0, cfg->p.dim, cfg->p.fuzz, 0); - input_set_abs_params(input_dev, ABS_TOOL_WIDTH, - 0, cfg->w.dim, cfg->w.fuzz, 0); - input_set_abs_params(input_dev, ABS_X, - 0, cfg->x.dim, cfg->x.fuzz, 0); - input_set_abs_params(input_dev, ABS_Y, - 0, cfg->y.dim, cfg->y.fuzz, 0); - - /* finger touch area */ - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, - cfg->w.devmin, cfg->w.devmax, 0, 0); - input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, - cfg->w.devmin, cfg->w.devmax, 0, 0); - /* finger approach area */ - input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, - cfg->w.devmin, cfg->w.devmax, 0, 0); - input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, - cfg->w.devmin, cfg->w.devmax, 0, 0); - /* finger orientation */ - input_set_abs_params(input_dev, ABS_MT_ORIENTATION, - -MAX_FINGER_ORIENTATION, - MAX_FINGER_ORIENTATION, 0, 0); - /* finger position */ - input_set_abs_params(input_dev, ABS_MT_POSITION_X, - cfg->x.devmin, cfg->x.devmax, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - cfg->y.devmin, cfg->y.devmax, 0, 0); - - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(BTN_TOUCH, input_dev->keybit); - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); - __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); - __set_bit(BTN_LEFT, input_dev->keybit); - - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); - if (cfg->caps & HAS_INTEGRATED_BUTTON) - __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); - - input_set_events_per_packet(input_dev, 60); -} - -/* report button data as logical button state */ -static int report_bt_state(struct bcm5974 *dev, int size) -{ - if (size != sizeof(struct bt_data)) - return -EIO; - - dprintk(7, - "bcm5974: button data: %x %x %x %x\n", - dev->bt_data->unknown1, dev->bt_data->button, - dev->bt_data->rel_x, dev->bt_data->rel_y); - - input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); - input_sync(dev->input); - - return 0; -} - -static void report_finger_data(struct input_dev *input, - const struct bcm5974_config *cfg, - const struct tp_finger *f) -{ - input_report_abs(input, ABS_MT_TOUCH_MAJOR, - raw2int(f->force_major) << 1); - input_report_abs(input, ABS_MT_TOUCH_MINOR, - raw2int(f->force_minor) << 1); - input_report_abs(input, ABS_MT_WIDTH_MAJOR, - raw2int(f->size_major) << 1); - input_report_abs(input, ABS_MT_WIDTH_MINOR, - raw2int(f->size_minor) << 1); - input_report_abs(input, ABS_MT_ORIENTATION, - MAX_FINGER_ORIENTATION - raw2int(f->orientation)); - input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x)); - input_report_abs(input, ABS_MT_POSITION_Y, - cfg->y.devmin + cfg->y.devmax - raw2int(f->abs_y)); - input_mt_sync(input); -} - -/* report trackpad data as logical trackpad state */ -static int report_tp_state(struct bcm5974 *dev, int size) -{ - const struct bcm5974_config *c = &dev->cfg; - const struct tp_finger *f; - struct input_dev *input = dev->input; - int raw_p, raw_w, raw_x, raw_y, raw_n, i; - int ptest, origin, ibt = 0, nmin = 0, nmax = 0; - int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; - - if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) - return -EIO; - - /* finger data, le16-aligned */ - f = (const struct tp_finger *)(dev->tp_data + c->tp_offset); - raw_n = (size - c->tp_offset) / SIZEOF_FINGER; - - /* always track the first finger; when detached, start over */ - if (raw_n) { - - /* report raw trackpad data */ - for (i = 0; i < raw_n; i++) - report_finger_data(input, c, &f[i]); - - raw_p = raw2int(f->force_major); - raw_w = raw2int(f->size_major); - raw_x = raw2int(f->abs_x); - raw_y = raw2int(f->abs_y); - - dprintk(9, - "bcm5974: " - "raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", - raw_p, raw_w, raw_x, raw_y, raw_n); - - ptest = int2bound(&c->p, raw_p); - origin = raw2int(f->origin); - - /* while tracking finger still valid, count all fingers */ - if (ptest > PRESSURE_LOW && origin) { - abs_p = ptest; - abs_w = int2bound(&c->w, raw_w); - abs_x = int2bound(&c->x, raw_x - c->x.devmin); - abs_y = int2bound(&c->y, c->y.devmax - raw_y); - while (raw_n--) { - ptest = int2bound(&c->p, - raw2int(f->force_major)); - if (ptest > PRESSURE_LOW) - nmax++; - if (ptest > PRESSURE_HIGH) - nmin++; - f++; - } - } - } - - /* set the integrated button if applicable */ - if (c->tp_type == TYPE2) - ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); - - if (dev->fingers < nmin) - dev->fingers = nmin; - if (dev->fingers > nmax) - dev->fingers = nmax; - - input_report_key(input, BTN_TOUCH, dev->fingers > 0); - input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); - input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); - input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3); - input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3); - - input_report_abs(input, ABS_PRESSURE, abs_p); - input_report_abs(input, ABS_TOOL_WIDTH, abs_w); - - if (abs_p) { - input_report_abs(input, ABS_X, abs_x); - input_report_abs(input, ABS_Y, abs_y); - - dprintk(8, - "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " - "nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w, - abs_x, abs_y, nmin, nmax, dev->fingers, ibt); - - } - - /* type 2 reports button events via ibt only */ - if (c->tp_type == TYPE2) - input_report_key(input, BTN_LEFT, ibt); - - input_sync(input); - - return 0; -} - -/* Wellspring initialization constants */ -#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1 -#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9 -#define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300 -#define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0 -#define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01 -#define BCM5974_WELLSPRING_MODE_NORMAL_VALUE 0x08 - -static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) -{ - char *data = kmalloc(8, GFP_KERNEL); - int retval = 0, size; - - if (!data) { - err("bcm5974: out of memory"); - retval = -ENOMEM; - goto out; - } - - /* read configuration */ - size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), - BCM5974_WELLSPRING_MODE_READ_REQUEST_ID, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - BCM5974_WELLSPRING_MODE_REQUEST_VALUE, - BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); - - if (size != 8) { - err("bcm5974: could not read from device"); - retval = -EIO; - goto out; - } - - /* apply the mode switch */ - data[0] = on ? - BCM5974_WELLSPRING_MODE_VENDOR_VALUE : - BCM5974_WELLSPRING_MODE_NORMAL_VALUE; - - /* write configuration */ - size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - BCM5974_WELLSPRING_MODE_REQUEST_VALUE, - BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); - - if (size != 8) { - err("bcm5974: could not write to device"); - retval = -EIO; - goto out; - } - - dprintk(2, "bcm5974: switched to %s mode.\n", - on ? "wellspring" : "normal"); - - out: - kfree(data); - return retval; -} - -static void bcm5974_irq_button(struct urb *urb) -{ - struct bcm5974 *dev = urb->context; - int error; - - switch (urb->status) { - case 0: - break; - case -EOVERFLOW: - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - dbg("bcm5974: button urb shutting down: %d", urb->status); - return; - default: - dbg("bcm5974: button urb status: %d", urb->status); - goto exit; - } - - if (report_bt_state(dev, dev->bt_urb->actual_length)) - dprintk(1, "bcm5974: bad button package, length: %d\n", - dev->bt_urb->actual_length); - -exit: - error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC); - if (error) - err("bcm5974: button urb failed: %d", error); -} - -static void bcm5974_irq_trackpad(struct urb *urb) -{ - struct bcm5974 *dev = urb->context; - int error; - - switch (urb->status) { - case 0: - break; - case -EOVERFLOW: - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - dbg("bcm5974: trackpad urb shutting down: %d", urb->status); - return; - default: - dbg("bcm5974: trackpad urb status: %d", urb->status); - goto exit; - } - - /* control response ignored */ - if (dev->tp_urb->actual_length == 2) - goto exit; - - if (report_tp_state(dev, dev->tp_urb->actual_length)) - dprintk(1, "bcm5974: bad trackpad package, length: %d\n", - dev->tp_urb->actual_length); - -exit: - error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC); - if (error) - err("bcm5974: trackpad urb failed: %d", error); -} - -/* - * The Wellspring trackpad, like many recent Apple trackpads, share - * the usb device with the keyboard. Since keyboards are usually - * handled by the HID system, the device ends up being handled by two - * modules. Setting up the device therefore becomes slightly - * complicated. To enable multitouch features, a mode switch is - * required, which is usually applied via the control interface of the - * device. It can be argued where this switch should take place. In - * some drivers, like appletouch, the switch is made during - * probe. However, the hid module may also alter the state of the - * device, resulting in trackpad malfunction under certain - * circumstances. To get around this problem, there is at least one - * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to - * receive a reset_resume request rather than the normal resume. - * Since the implementation of reset_resume is equal to mode switch - * plus start_traffic, it seems easier to always do the switch when - * starting traffic on the device. - */ -static int bcm5974_start_traffic(struct bcm5974 *dev) -{ - int error; - - error = bcm5974_wellspring_mode(dev, true); - if (error) { - dprintk(1, "bcm5974: mode switch failed\n"); - goto err_out; - } - - error = usb_submit_urb(dev->bt_urb, GFP_KERNEL); - if (error) - goto err_reset_mode; - - error = usb_submit_urb(dev->tp_urb, GFP_KERNEL); - if (error) - goto err_kill_bt; - - return 0; - -err_kill_bt: - usb_kill_urb(dev->bt_urb); -err_reset_mode: - bcm5974_wellspring_mode(dev, false); -err_out: - return error; -} - -static void bcm5974_pause_traffic(struct bcm5974 *dev) -{ - usb_kill_urb(dev->tp_urb); - usb_kill_urb(dev->bt_urb); - bcm5974_wellspring_mode(dev, false); -} - -/* - * The code below implements open/close and manual suspend/resume. - * All functions may be called in random order. - * - * Opening a suspended device fails with EACCES - permission denied. - * - * Failing a resume leaves the device resumed but closed. - */ -static int bcm5974_open(struct input_dev *input) -{ - struct bcm5974 *dev = input_get_drvdata(input); - int error; - - error = usb_autopm_get_interface(dev->intf); - if (error) - return error; - - mutex_lock(&dev->pm_mutex); - - error = bcm5974_start_traffic(dev); - if (!error) - dev->opened = 1; - - mutex_unlock(&dev->pm_mutex); - - if (error) - usb_autopm_put_interface(dev->intf); - - return error; -} - -static void bcm5974_close(struct input_dev *input) -{ - struct bcm5974 *dev = input_get_drvdata(input); - - mutex_lock(&dev->pm_mutex); - - bcm5974_pause_traffic(dev); - dev->opened = 0; - - mutex_unlock(&dev->pm_mutex); - - usb_autopm_put_interface(dev->intf); -} - -static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message) -{ - struct bcm5974 *dev = usb_get_intfdata(iface); - - mutex_lock(&dev->pm_mutex); - - if (dev->opened) - bcm5974_pause_traffic(dev); - - mutex_unlock(&dev->pm_mutex); - - return 0; -} - -static int bcm5974_resume(struct usb_interface *iface) -{ - struct bcm5974 *dev = usb_get_intfdata(iface); - int error = 0; - - mutex_lock(&dev->pm_mutex); - - if (dev->opened) - error = bcm5974_start_traffic(dev); - - mutex_unlock(&dev->pm_mutex); - - return error; -} - -static int bcm5974_probe(struct usb_interface *iface, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(iface); - const struct bcm5974_config *cfg; - struct bcm5974 *dev; - struct input_dev *input_dev; - int error = -ENOMEM; - - /* find the product index */ - cfg = bcm5974_get_config(udev); - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!dev || !input_dev) { - err("bcm5974: out of memory"); - goto err_free_devs; - } - - dev->udev = udev; - dev->intf = iface; - dev->input = input_dev; - dev->cfg = *cfg; - mutex_init(&dev->pm_mutex); - - /* setup urbs */ - dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->bt_urb) - goto err_free_devs; - - dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->tp_urb) - goto err_free_bt_urb; - - dev->bt_data = usb_alloc_coherent(dev->udev, - dev->cfg.bt_datalen, GFP_KERNEL, - &dev->bt_urb->transfer_dma); - if (!dev->bt_data) - goto err_free_urb; - - dev->tp_data = usb_alloc_coherent(dev->udev, - dev->cfg.tp_datalen, GFP_KERNEL, - &dev->tp_urb->transfer_dma); - if (!dev->tp_data) - goto err_free_bt_buffer; - - usb_fill_int_urb(dev->bt_urb, udev, - usb_rcvintpipe(udev, cfg->bt_ep), - dev->bt_data, dev->cfg.bt_datalen, - bcm5974_irq_button, dev, 1); - - usb_fill_int_urb(dev->tp_urb, udev, - usb_rcvintpipe(udev, cfg->tp_ep), - dev->tp_data, dev->cfg.tp_datalen, - bcm5974_irq_trackpad, dev, 1); - - /* create bcm5974 device */ - usb_make_path(udev, dev->phys, sizeof(dev->phys)); - strlcat(dev->phys, "/input0", sizeof(dev->phys)); - - input_dev->name = "bcm5974"; - input_dev->phys = dev->phys; - usb_to_input_id(dev->udev, &input_dev->id); - /* report driver capabilities via the version field */ - input_dev->id.version = cfg->caps; - input_dev->dev.parent = &iface->dev; - - input_set_drvdata(input_dev, dev); - - input_dev->open = bcm5974_open; - input_dev->close = bcm5974_close; - - setup_events_to_report(input_dev, cfg); - - error = input_register_device(dev->input); - if (error) - goto err_free_buffer; - - /* save our data pointer in this interface device */ - usb_set_intfdata(iface, dev); - - return 0; - -err_free_buffer: - usb_free_coherent(dev->udev, dev->cfg.tp_datalen, - dev->tp_data, dev->tp_urb->transfer_dma); -err_free_bt_buffer: - usb_free_coherent(dev->udev, dev->cfg.bt_datalen, - dev->bt_data, dev->bt_urb->transfer_dma); -err_free_urb: - usb_free_urb(dev->tp_urb); -err_free_bt_urb: - usb_free_urb(dev->bt_urb); -err_free_devs: - usb_set_intfdata(iface, NULL); - input_free_device(input_dev); - kfree(dev); - return error; -} - -static void bcm5974_disconnect(struct usb_interface *iface) -{ - struct bcm5974 *dev = usb_get_intfdata(iface); - - usb_set_intfdata(iface, NULL); - - input_unregister_device(dev->input); - usb_free_coherent(dev->udev, dev->cfg.tp_datalen, - dev->tp_data, dev->tp_urb->transfer_dma); - usb_free_coherent(dev->udev, dev->cfg.bt_datalen, - dev->bt_data, dev->bt_urb->transfer_dma); - usb_free_urb(dev->tp_urb); - usb_free_urb(dev->bt_urb); - kfree(dev); -} - -static struct usb_driver bcm5974_driver = { - .name = "bcm5974", - .probe = bcm5974_probe, - .disconnect = bcm5974_disconnect, - .suspend = bcm5974_suspend, - .resume = bcm5974_resume, - .id_table = bcm5974_table, - .supports_autosuspend = 1, -}; - -module_usb_driver(bcm5974_driver); diff --git a/ANDROID_3.4.5/drivers/input/mouse/elantech.c b/ANDROID_3.4.5/drivers/input/mouse/elantech.c deleted file mode 100644 index 47901100..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/elantech.c +++ /dev/null @@ -1,1394 +0,0 @@ -/* - * Elantech Touchpad driver (v6) - * - * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net> - * - * 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/delay.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/input.h> -#include <linux/input/mt.h> -#include <linux/serio.h> -#include <linux/libps2.h> -#include "psmouse.h" -#include "elantech.h" - -#define elantech_debug(fmt, ...) \ - do { \ - if (etd->debug) \ - psmouse_printk(KERN_DEBUG, psmouse, \ - fmt, ##__VA_ARGS__); \ - } while (0) - -/* - * Send a Synaptics style sliced query command - */ -static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, - unsigned char *param) -{ - if (psmouse_sliced_command(psmouse, c) || - ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { - psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c); - return -1; - } - - return 0; -} - -/* - * V3 and later support this fast command - */ -static int elantech_send_cmd(struct psmouse *psmouse, unsigned char c, - unsigned char *param) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - - if (ps2_command(ps2dev, NULL, ETP_PS2_CUSTOM_COMMAND) || - ps2_command(ps2dev, NULL, c) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { - psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c); - return -1; - } - - return 0; -} - -/* - * A retrying version of ps2_command - */ -static int elantech_ps2_command(struct psmouse *psmouse, - unsigned char *param, int command) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - struct elantech_data *etd = psmouse->private; - int rc; - int tries = ETP_PS2_COMMAND_TRIES; - - do { - rc = ps2_command(ps2dev, param, command); - if (rc == 0) - break; - tries--; - elantech_debug("retrying ps2 command 0x%02x (%d).\n", - command, tries); - msleep(ETP_PS2_COMMAND_DELAY); - } while (tries > 0); - - if (rc) - psmouse_err(psmouse, "ps2 command 0x%02x failed.\n", command); - - return rc; -} - -/* - * Send an Elantech style special command to read a value from a register - */ -static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, - unsigned char *val) -{ - struct elantech_data *etd = psmouse->private; - unsigned char param[3]; - int rc = 0; - - if (reg < 0x07 || reg > 0x26) - return -1; - - if (reg > 0x11 && reg < 0x20) - return -1; - - switch (etd->hw_version) { - case 1: - if (psmouse_sliced_command(psmouse, ETP_REGISTER_READ) || - psmouse_sliced_command(psmouse, reg) || - ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { - rc = -1; - } - break; - - case 2: - if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READ) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, reg) || - elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { - rc = -1; - } - break; - - case 3 ... 4: - if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, reg) || - elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { - rc = -1; - } - break; - } - - if (rc) - psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg); - else if (etd->hw_version != 4) - *val = param[0]; - else - *val = param[1]; - - return rc; -} - -/* - * Send an Elantech style special command to write a register with a value - */ -static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, - unsigned char val) -{ - struct elantech_data *etd = psmouse->private; - int rc = 0; - - if (reg < 0x07 || reg > 0x26) - return -1; - - if (reg > 0x11 && reg < 0x20) - return -1; - - switch (etd->hw_version) { - case 1: - if (psmouse_sliced_command(psmouse, ETP_REGISTER_WRITE) || - psmouse_sliced_command(psmouse, reg) || - psmouse_sliced_command(psmouse, val) || - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) { - rc = -1; - } - break; - - case 2: - if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, ETP_REGISTER_WRITE) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, reg) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, val) || - elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { - rc = -1; - } - break; - - case 3: - if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, reg) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, val) || - elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { - rc = -1; - } - break; - - case 4: - if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, reg) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, val) || - elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { - rc = -1; - } - break; - } - - if (rc) - psmouse_err(psmouse, - "failed to write register 0x%02x with value 0x%02x.\n", - reg, val); - - return rc; -} - -/* - * Dump a complete mouse movement packet to the syslog - */ -static void elantech_packet_dump(struct psmouse *psmouse) -{ - int i; - - psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet ["); - for (i = 0; i < psmouse->pktsize; i++) - printk("%s0x%02x ", i ? ", " : " ", psmouse->packet[i]); - printk("]\n"); -} - -/* - * Interpret complete data packets and report absolute mode input events for - * hardware version 1. (4 byte packets) - */ -static void elantech_report_absolute_v1(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; - unsigned char *packet = psmouse->packet; - int fingers; - - if (etd->fw_version < 0x020000) { - /* - * byte 0: D U p1 p2 1 p3 R L - * byte 1: f 0 th tw x9 x8 y9 y8 - */ - fingers = ((packet[1] & 0x80) >> 7) + - ((packet[1] & 0x30) >> 4); - } else { - /* - * byte 0: n1 n0 p2 p1 1 p3 R L - * byte 1: 0 0 0 0 x9 x8 y9 y8 - */ - fingers = (packet[0] & 0xc0) >> 6; - } - - if (etd->jumpy_cursor) { - if (fingers != 1) { - etd->single_finger_reports = 0; - } else if (etd->single_finger_reports < 2) { - /* Discard first 2 reports of one finger, bogus */ - etd->single_finger_reports++; - elantech_debug("discarding packet\n"); - return; - } - } - - input_report_key(dev, BTN_TOUCH, fingers != 0); - - /* - * byte 2: x7 x6 x5 x4 x3 x2 x1 x0 - * byte 3: y7 y6 y5 y4 y3 y2 y1 y0 - */ - if (fingers) { - input_report_abs(dev, ABS_X, - ((packet[1] & 0x0c) << 6) | packet[2]); - input_report_abs(dev, ABS_Y, - etd->y_max - (((packet[1] & 0x03) << 8) | packet[3])); - } - - input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); - input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); - input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); - input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - - if (etd->fw_version < 0x020000 && - (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { - /* rocker up */ - input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); - /* rocker down */ - input_report_key(dev, BTN_BACK, packet[0] & 0x80); - } - - input_sync(dev); -} - -static void elantech_set_slot(struct input_dev *dev, int slot, bool active, - unsigned int x, unsigned int y) -{ - 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); - input_report_abs(dev, ABS_MT_POSITION_Y, y); - } -} - -/* x1 < x2 and y1 < y2 when two fingers, x = y = 0 when not pressed */ -static void elantech_report_semi_mt_data(struct input_dev *dev, - unsigned int num_fingers, - unsigned int x1, unsigned int y1, - unsigned int x2, unsigned int y2) -{ - elantech_set_slot(dev, 0, num_fingers != 0, x1, y1); - elantech_set_slot(dev, 1, num_fingers == 2, x2, y2); -} - -/* - * Interpret complete data packets and report absolute mode input events for - * hardware version 2. (6 byte packets) - */ -static void elantech_report_absolute_v2(struct psmouse *psmouse) -{ - struct elantech_data *etd = psmouse->private; - struct input_dev *dev = psmouse->dev; - unsigned char *packet = psmouse->packet; - unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0; - unsigned int width = 0, pres = 0; - - /* byte 0: n1 n0 . . . . R L */ - fingers = (packet[0] & 0xc0) >> 6; - - switch (fingers) { - case 3: - /* - * Same as one finger, except report of more than 3 fingers: - * byte 3: n4 . w1 w0 . . . . - */ - if (packet[3] & 0x80) - fingers = 4; - /* pass through... */ - case 1: - /* - * byte 1: . . . . x11 x10 x9 x8 - * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 - */ - x1 = ((packet[1] & 0x0f) << 8) | packet[2]; - /* - * byte 4: . . . . y11 y10 y9 y8 - * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 - */ - y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); - - pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); - width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); - break; - - case 2: - /* - * The coordinate of each finger is reported separately - * with a lower resolution for two finger touches: - * byte 0: . . ay8 ax8 . . . . - * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 - */ - x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; - /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ - y1 = etd->y_max - - ((((packet[0] & 0x20) << 3) | packet[2]) << 2); - /* - * byte 3: . . by8 bx8 . . . . - * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 - */ - x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; - /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ - y2 = etd->y_max - - ((((packet[3] & 0x20) << 3) | packet[5]) << 2); - - /* Unknown so just report sensible values */ - pres = 127; - width = 7; - break; - } - - input_report_key(dev, BTN_TOUCH, fingers != 0); - if (fingers != 0) { - input_report_abs(dev, ABS_X, x1); - input_report_abs(dev, ABS_Y, y1); - } - elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); - input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); - input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); - input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); - input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); - input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - if (etd->reports_pressure) { - input_report_abs(dev, ABS_PRESSURE, pres); - input_report_abs(dev, ABS_TOOL_WIDTH, width); - } - - input_sync(dev); -} - -/* - * Interpret complete data packets and report absolute mode input events for - * hardware version 3. (12 byte packets for two fingers) - */ -static void elantech_report_absolute_v3(struct psmouse *psmouse, - int packet_type) -{ - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; - unsigned char *packet = psmouse->packet; - unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; - unsigned int width = 0, pres = 0; - - /* byte 0: n1 n0 . . . . R L */ - fingers = (packet[0] & 0xc0) >> 6; - - switch (fingers) { - case 3: - case 1: - /* - * byte 1: . . . . x11 x10 x9 x8 - * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 - */ - x1 = ((packet[1] & 0x0f) << 8) | packet[2]; - /* - * byte 4: . . . . y11 y10 y9 y8 - * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 - */ - y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); - break; - - case 2: - if (packet_type == PACKET_V3_HEAD) { - /* - * byte 1: . . . . ax11 ax10 ax9 ax8 - * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 - */ - etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; - /* - * byte 4: . . . . ay11 ay10 ay9 ay8 - * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 - */ - etd->mt[0].y = etd->y_max - - (((packet[4] & 0x0f) << 8) | packet[5]); - /* - * wait for next packet - */ - return; - } - - /* packet_type == PACKET_V3_TAIL */ - x1 = etd->mt[0].x; - y1 = etd->mt[0].y; - x2 = ((packet[1] & 0x0f) << 8) | packet[2]; - y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); - break; - } - - pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); - width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); - - input_report_key(dev, BTN_TOUCH, fingers != 0); - if (fingers != 0) { - input_report_abs(dev, ABS_X, x1); - input_report_abs(dev, ABS_Y, y1); - } - elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); - input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); - input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); - input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); - input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - input_report_abs(dev, ABS_PRESSURE, pres); - input_report_abs(dev, ABS_TOOL_WIDTH, width); - - input_sync(dev); -} - -static void elantech_input_sync_v4(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - unsigned char *packet = psmouse->packet; - - input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_mt_report_pointer_emulation(dev, true); - input_sync(dev); -} - -static void process_packet_status_v4(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - unsigned char *packet = psmouse->packet; - unsigned fingers; - int i; - - /* notify finger state change */ - fingers = packet[1] & 0x1f; - for (i = 0; i < ETP_MAX_FINGERS; i++) { - if ((fingers & (1 << i)) == 0) { - input_mt_slot(dev, i); - input_mt_report_slot_state(dev, MT_TOOL_FINGER, false); - } - } - - elantech_input_sync_v4(psmouse); -} - -static void process_packet_head_v4(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; - unsigned char *packet = psmouse->packet; - int id = ((packet[3] & 0xe0) >> 5) - 1; - int pres, traces; - - if (id < 0) - return; - - etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2]; - etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); - pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); - traces = (packet[0] & 0xf0) >> 4; - - input_mt_slot(dev, id); - input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); - - input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); - input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); - input_report_abs(dev, ABS_MT_PRESSURE, pres); - input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width); - /* report this for backwards compatibility */ - input_report_abs(dev, ABS_TOOL_WIDTH, traces); - - elantech_input_sync_v4(psmouse); -} - -static void process_packet_motion_v4(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; - unsigned char *packet = psmouse->packet; - int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0; - int id, sid; - - id = ((packet[0] & 0xe0) >> 5) - 1; - if (id < 0) - return; - - sid = ((packet[3] & 0xe0) >> 5) - 1; - weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1; - /* - * Motion packets give us the delta of x, y values of specific fingers, - * but in two's complement. Let the compiler do the conversion for us. - * Also _enlarge_ the numbers to int, in case of overflow. - */ - delta_x1 = (signed char)packet[1]; - delta_y1 = (signed char)packet[2]; - delta_x2 = (signed char)packet[4]; - delta_y2 = (signed char)packet[5]; - - etd->mt[id].x += delta_x1 * weight; - etd->mt[id].y -= delta_y1 * weight; - input_mt_slot(dev, id); - input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); - input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); - - if (sid >= 0) { - etd->mt[sid].x += delta_x2 * weight; - etd->mt[sid].y -= delta_y2 * weight; - input_mt_slot(dev, sid); - input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x); - input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y); - } - - elantech_input_sync_v4(psmouse); -} - -static void elantech_report_absolute_v4(struct psmouse *psmouse, - int packet_type) -{ - switch (packet_type) { - case PACKET_V4_STATUS: - process_packet_status_v4(psmouse); - break; - - case PACKET_V4_HEAD: - process_packet_head_v4(psmouse); - break; - - case PACKET_V4_MOTION: - process_packet_motion_v4(psmouse); - break; - - case PACKET_UNKNOWN: - default: - /* impossible to get here */ - break; - } -} - -static int elantech_packet_check_v1(struct psmouse *psmouse) -{ - struct elantech_data *etd = psmouse->private; - unsigned char *packet = psmouse->packet; - unsigned char p1, p2, p3; - - /* Parity bits are placed differently */ - if (etd->fw_version < 0x020000) { - /* byte 0: D U p1 p2 1 p3 R L */ - p1 = (packet[0] & 0x20) >> 5; - p2 = (packet[0] & 0x10) >> 4; - } else { - /* byte 0: n1 n0 p2 p1 1 p3 R L */ - p1 = (packet[0] & 0x10) >> 4; - p2 = (packet[0] & 0x20) >> 5; - } - - p3 = (packet[0] & 0x04) >> 2; - - return etd->parity[packet[1]] == p1 && - etd->parity[packet[2]] == p2 && - etd->parity[packet[3]] == p3; -} - -static int elantech_debounce_check_v2(struct psmouse *psmouse) -{ - /* - * When we encounter packet that matches this exactly, it means the - * hardware is in debounce status. Just ignore the whole packet. - */ - const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff }; - unsigned char *packet = psmouse->packet; - - return !memcmp(packet, debounce_packet, sizeof(debounce_packet)); -} - -static int elantech_packet_check_v2(struct psmouse *psmouse) -{ - struct elantech_data *etd = psmouse->private; - unsigned char *packet = psmouse->packet; - - /* - * V2 hardware has two flavors. Older ones that do not report pressure, - * and newer ones that reports pressure and width. With newer ones, all - * packets (1, 2, 3 finger touch) have the same constant bits. With - * older ones, 1/3 finger touch packets and 2 finger touch packets - * have different constant bits. - * With all three cases, if the constant bits are not exactly what I - * expected, I consider them invalid. - */ - if (etd->reports_pressure) - return (packet[0] & 0x0c) == 0x04 && - (packet[3] & 0x0f) == 0x02; - - if ((packet[0] & 0xc0) == 0x80) - return (packet[0] & 0x0c) == 0x0c && - (packet[3] & 0x0e) == 0x08; - - return (packet[0] & 0x3c) == 0x3c && - (packet[1] & 0xf0) == 0x00 && - (packet[3] & 0x3e) == 0x38 && - (packet[4] & 0xf0) == 0x00; -} - -/* - * We check the constant bits to determine what packet type we get, - * so packet checking is mandatory for v3 and later hardware. - */ -static int elantech_packet_check_v3(struct psmouse *psmouse) -{ - const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; - unsigned char *packet = psmouse->packet; - - /* - * check debounce first, it has the same signature in byte 0 - * and byte 3 as PACKET_V3_HEAD. - */ - if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) - return PACKET_DEBOUNCE; - - if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) - return PACKET_V3_HEAD; - - if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) - return PACKET_V3_TAIL; - - return PACKET_UNKNOWN; -} - -static int elantech_packet_check_v4(struct psmouse *psmouse) -{ - unsigned char *packet = psmouse->packet; - - if ((packet[0] & 0x0c) == 0x04 && - (packet[3] & 0x1f) == 0x11) - return PACKET_V4_HEAD; - - if ((packet[0] & 0x0c) == 0x04 && - (packet[3] & 0x1f) == 0x12) - return PACKET_V4_MOTION; - - if ((packet[0] & 0x0c) == 0x04 && - (packet[3] & 0x1f) == 0x10) - return PACKET_V4_STATUS; - - return PACKET_UNKNOWN; -} - -/* - * Process byte stream from mouse and handle complete packets - */ -static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) -{ - struct elantech_data *etd = psmouse->private; - int packet_type; - - if (psmouse->pktcnt < psmouse->pktsize) - return PSMOUSE_GOOD_DATA; - - if (etd->debug > 1) - elantech_packet_dump(psmouse); - - switch (etd->hw_version) { - case 1: - if (etd->paritycheck && !elantech_packet_check_v1(psmouse)) - return PSMOUSE_BAD_DATA; - - elantech_report_absolute_v1(psmouse); - break; - - case 2: - /* ignore debounce */ - if (elantech_debounce_check_v2(psmouse)) - return PSMOUSE_FULL_PACKET; - - if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) - return PSMOUSE_BAD_DATA; - - elantech_report_absolute_v2(psmouse); - break; - - case 3: - packet_type = elantech_packet_check_v3(psmouse); - /* ignore debounce */ - if (packet_type == PACKET_DEBOUNCE) - return PSMOUSE_FULL_PACKET; - - if (packet_type == PACKET_UNKNOWN) - return PSMOUSE_BAD_DATA; - - elantech_report_absolute_v3(psmouse, packet_type); - break; - - case 4: - packet_type = elantech_packet_check_v4(psmouse); - if (packet_type == PACKET_UNKNOWN) - return PSMOUSE_BAD_DATA; - - elantech_report_absolute_v4(psmouse, packet_type); - break; - } - - return PSMOUSE_FULL_PACKET; -} - -/* - * Put the touchpad into absolute mode - */ -static int elantech_set_absolute_mode(struct psmouse *psmouse) -{ - struct elantech_data *etd = psmouse->private; - unsigned char val; - int tries = ETP_READ_BACK_TRIES; - int rc = 0; - - switch (etd->hw_version) { - case 1: - etd->reg_10 = 0x16; - etd->reg_11 = 0x8f; - if (elantech_write_reg(psmouse, 0x10, etd->reg_10) || - elantech_write_reg(psmouse, 0x11, etd->reg_11)) { - rc = -1; - } - break; - - case 2: - /* Windows driver values */ - etd->reg_10 = 0x54; - etd->reg_11 = 0x88; /* 0x8a */ - etd->reg_21 = 0x60; /* 0x00 */ - if (elantech_write_reg(psmouse, 0x10, etd->reg_10) || - elantech_write_reg(psmouse, 0x11, etd->reg_11) || - elantech_write_reg(psmouse, 0x21, etd->reg_21)) { - rc = -1; - } - break; - - case 3: - etd->reg_10 = 0x0b; - if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) - rc = -1; - - break; - - case 4: - etd->reg_07 = 0x01; - if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) - rc = -1; - - goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */ - } - - if (rc == 0) { - /* - * Read back reg 0x10. For hardware version 1 we must make - * sure the absolute mode bit is set. For hardware version 2 - * the touchpad is probably initializing and not ready until - * we read back the value we just wrote. - */ - do { - rc = elantech_read_reg(psmouse, 0x10, &val); - if (rc == 0) - break; - tries--; - elantech_debug("retrying read (%d).\n", tries); - msleep(ETP_READ_BACK_DELAY); - } while (tries > 0); - - if (rc) { - psmouse_err(psmouse, - "failed to read back register 0x10.\n"); - } else if (etd->hw_version == 1 && - !(val & ETP_R10_ABSOLUTE_MODE)) { - psmouse_err(psmouse, - "touchpad refuses to switch to absolute mode.\n"); - rc = -1; - } - } - - skip_readback_reg_10: - if (rc) - psmouse_err(psmouse, "failed to initialise registers.\n"); - - return rc; -} - -static int elantech_set_range(struct psmouse *psmouse, - unsigned int *x_min, unsigned int *y_min, - unsigned int *x_max, unsigned int *y_max, - unsigned int *width) -{ - struct elantech_data *etd = psmouse->private; - unsigned char param[3]; - unsigned char traces; - - switch (etd->hw_version) { - case 1: - *x_min = ETP_XMIN_V1; - *y_min = ETP_YMIN_V1; - *x_max = ETP_XMAX_V1; - *y_max = ETP_YMAX_V1; - break; - - case 2: - if (etd->fw_version == 0x020800 || - etd->fw_version == 0x020b00 || - etd->fw_version == 0x020030) { - *x_min = ETP_XMIN_V2; - *y_min = ETP_YMIN_V2; - *x_max = ETP_XMAX_V2; - *y_max = ETP_YMAX_V2; - } else { - int i; - int fixed_dpi; - - i = (etd->fw_version > 0x020800 && - etd->fw_version < 0x020900) ? 1 : 2; - - if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) - return -1; - - fixed_dpi = param[1] & 0x10; - - if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) { - if (etd->send_cmd(psmouse, ETP_SAMPLE_QUERY, param)) - return -1; - - *x_max = (etd->capabilities[1] - i) * param[1] / 2; - *y_max = (etd->capabilities[2] - i) * param[2] / 2; - } else if (etd->fw_version == 0x040216) { - *x_max = 819; - *y_max = 405; - } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) { - *x_max = 900; - *y_max = 500; - } else { - *x_max = (etd->capabilities[1] - i) * 64; - *y_max = (etd->capabilities[2] - i) * 64; - } - } - break; - - case 3: - if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) - return -1; - - *x_max = (0x0f & param[0]) << 8 | param[1]; - *y_max = (0xf0 & param[0]) << 4 | param[2]; - break; - - case 4: - if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) - return -1; - - *x_max = (0x0f & param[0]) << 8 | param[1]; - *y_max = (0xf0 & param[0]) << 4 | param[2]; - traces = etd->capabilities[1]; - if ((traces < 2) || (traces > *x_max)) - return -1; - - *width = *x_max / (traces - 1); - break; - } - - return 0; -} - -/* - * (value from firmware) * 10 + 790 = dpi - * we also have to convert dpi to dots/mm (*10/254 to avoid floating point) - */ -static unsigned int elantech_convert_res(unsigned int val) -{ - return (val * 10 + 790) * 10 / 254; -} - -static int elantech_get_resolution_v4(struct psmouse *psmouse, - unsigned int *x_res, - unsigned int *y_res) -{ - unsigned char param[3]; - - if (elantech_send_cmd(psmouse, ETP_RESOLUTION_QUERY, param)) - return -1; - - *x_res = elantech_convert_res(param[1] & 0x0f); - *y_res = elantech_convert_res((param[1] & 0xf0) >> 4); - - return 0; -} - -/* - * Set the appropriate event bits for the input subsystem - */ -static int elantech_set_input_params(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; - unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; - unsigned int x_res = 0, y_res = 0; - - if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) - return -1; - - __set_bit(INPUT_PROP_POINTER, dev->propbit); - __set_bit(EV_KEY, dev->evbit); - __set_bit(EV_ABS, dev->evbit); - __clear_bit(EV_REL, dev->evbit); - - __set_bit(BTN_LEFT, dev->keybit); - __set_bit(BTN_RIGHT, dev->keybit); - - __set_bit(BTN_TOUCH, dev->keybit); - __set_bit(BTN_TOOL_FINGER, dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); - __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); - - switch (etd->hw_version) { - case 1: - /* Rocker button */ - if (etd->fw_version < 0x020000 && - (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { - __set_bit(BTN_FORWARD, dev->keybit); - __set_bit(BTN_BACK, dev->keybit); - } - input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - break; - - case 2: - __set_bit(BTN_TOOL_QUADTAP, dev->keybit); - __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); - /* fall through */ - case 3: - input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - if (etd->reports_pressure) { - input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, - ETP_PMAX_V2, 0, 0); - input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, - ETP_WMAX_V2, 0, 0); - } - input_mt_init_slots(dev, 2); - input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); - break; - - case 4: - if (elantech_get_resolution_v4(psmouse, &x_res, &y_res)) { - /* - * if query failed, print a warning and leave the values - * zero to resemble synaptics.c behavior. - */ - psmouse_warn(psmouse, "couldn't query resolution data.\n"); - } - /* v4 is clickpad, with only one button. */ - __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); - __clear_bit(BTN_RIGHT, dev->keybit); - __set_bit(BTN_TOOL_QUADTAP, dev->keybit); - /* For X to recognize me as touchpad. */ - input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - input_abs_set_res(dev, ABS_X, x_res); - input_abs_set_res(dev, ABS_Y, y_res); - /* - * range of pressure and width is the same as v2, - * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. - */ - input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, - ETP_PMAX_V2, 0, 0); - input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, - ETP_WMAX_V2, 0, 0); - /* Multitouch capable pad, up to 5 fingers. */ - input_mt_init_slots(dev, ETP_MAX_FINGERS); - input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); - input_abs_set_res(dev, ABS_MT_POSITION_X, x_res); - input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res); - input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, - ETP_PMAX_V2, 0, 0); - /* - * The firmware reports how many trace lines the finger spans, - * convert to surface unit as Protocol-B requires. - */ - input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, - ETP_WMAX_V2 * width, 0, 0); - break; - } - - etd->y_max = y_max; - etd->width = width; - - return 0; -} - -struct elantech_attr_data { - size_t field_offset; - unsigned char reg; -}; - -/* - * Display a register value by reading a sysfs entry - */ -static ssize_t elantech_show_int_attr(struct psmouse *psmouse, void *data, - char *buf) -{ - struct elantech_data *etd = psmouse->private; - struct elantech_attr_data *attr = data; - unsigned char *reg = (unsigned char *) etd + attr->field_offset; - int rc = 0; - - if (attr->reg) - rc = elantech_read_reg(psmouse, attr->reg, reg); - - return sprintf(buf, "0x%02x\n", (attr->reg && rc) ? -1 : *reg); -} - -/* - * Write a register value by writing a sysfs entry - */ -static ssize_t elantech_set_int_attr(struct psmouse *psmouse, - void *data, const char *buf, size_t count) -{ - struct elantech_data *etd = psmouse->private; - struct elantech_attr_data *attr = data; - unsigned char *reg = (unsigned char *) etd + attr->field_offset; - unsigned char value; - int err; - - err = kstrtou8(buf, 16, &value); - if (err) - return err; - - /* Do we need to preserve some bits for version 2 hardware too? */ - if (etd->hw_version == 1) { - if (attr->reg == 0x10) - /* Force absolute mode always on */ - value |= ETP_R10_ABSOLUTE_MODE; - else if (attr->reg == 0x11) - /* Force 4 byte mode always on */ - value |= ETP_R11_4_BYTE_MODE; - } - - if (!attr->reg || elantech_write_reg(psmouse, attr->reg, value) == 0) - *reg = value; - - return count; -} - -#define ELANTECH_INT_ATTR(_name, _register) \ - static struct elantech_attr_data elantech_attr_##_name = { \ - .field_offset = offsetof(struct elantech_data, _name), \ - .reg = _register, \ - }; \ - PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ - &elantech_attr_##_name, \ - elantech_show_int_attr, \ - elantech_set_int_attr) - -ELANTECH_INT_ATTR(reg_07, 0x07); -ELANTECH_INT_ATTR(reg_10, 0x10); -ELANTECH_INT_ATTR(reg_11, 0x11); -ELANTECH_INT_ATTR(reg_20, 0x20); -ELANTECH_INT_ATTR(reg_21, 0x21); -ELANTECH_INT_ATTR(reg_22, 0x22); -ELANTECH_INT_ATTR(reg_23, 0x23); -ELANTECH_INT_ATTR(reg_24, 0x24); -ELANTECH_INT_ATTR(reg_25, 0x25); -ELANTECH_INT_ATTR(reg_26, 0x26); -ELANTECH_INT_ATTR(debug, 0); -ELANTECH_INT_ATTR(paritycheck, 0); - -static struct attribute *elantech_attrs[] = { - &psmouse_attr_reg_07.dattr.attr, - &psmouse_attr_reg_10.dattr.attr, - &psmouse_attr_reg_11.dattr.attr, - &psmouse_attr_reg_20.dattr.attr, - &psmouse_attr_reg_21.dattr.attr, - &psmouse_attr_reg_22.dattr.attr, - &psmouse_attr_reg_23.dattr.attr, - &psmouse_attr_reg_24.dattr.attr, - &psmouse_attr_reg_25.dattr.attr, - &psmouse_attr_reg_26.dattr.attr, - &psmouse_attr_debug.dattr.attr, - &psmouse_attr_paritycheck.dattr.attr, - NULL -}; - -static struct attribute_group elantech_attr_group = { - .attrs = elantech_attrs, -}; - -static bool elantech_is_signature_valid(const unsigned char *param) -{ - static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10 }; - int i; - - if (param[0] == 0) - return false; - - if (param[1] == 0) - return true; - - for (i = 0; i < ARRAY_SIZE(rates); i++) - if (param[2] == rates[i]) - return false; - - return true; -} - -/* - * Use magic knock to detect Elantech touchpad - */ -int elantech_detect(struct psmouse *psmouse, bool set_properties) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[3]; - - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); - - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { - psmouse_dbg(psmouse, "sending Elantech magic knock failed.\n"); - return -1; - } - - /* - * Report this in case there are Elantech models that use a different - * set of magic numbers - */ - if (param[0] != 0x3c || param[1] != 0x03 || - (param[2] != 0xc8 && param[2] != 0x00)) { - psmouse_dbg(psmouse, - "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", - param[0], param[1], param[2]); - return -1; - } - - /* - * Query touchpad's firmware version and see if it reports known - * value to avoid mis-detection. Logitech mice are known to respond - * to Elantech magic knock and there might be more. - */ - if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { - psmouse_dbg(psmouse, "failed to query firmware version.\n"); - return -1; - } - - psmouse_dbg(psmouse, - "Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", - param[0], param[1], param[2]); - - if (!elantech_is_signature_valid(param)) { - psmouse_dbg(psmouse, - "Probably not a real Elantech touchpad. Aborting.\n"); - return -1; - } - - if (set_properties) { - psmouse->vendor = "Elantech"; - psmouse->name = "Touchpad"; - } - - return 0; -} - -/* - * Clean up sysfs entries when disconnecting - */ -static void elantech_disconnect(struct psmouse *psmouse) -{ - sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, - &elantech_attr_group); - kfree(psmouse->private); - psmouse->private = NULL; -} - -/* - * Put the touchpad back into absolute mode when reconnecting - */ -static int elantech_reconnect(struct psmouse *psmouse) -{ - psmouse_reset(psmouse); - - if (elantech_detect(psmouse, 0)) - return -1; - - if (elantech_set_absolute_mode(psmouse)) { - psmouse_err(psmouse, - "failed to put touchpad back into absolute mode.\n"); - return -1; - } - - return 0; -} - -/* - * determine hardware version and set some properties according to it. - */ -static int elantech_set_properties(struct elantech_data *etd) -{ - /* This represents the version of IC body. */ - int ver = (etd->fw_version & 0x0f0000) >> 16; - - /* Early version of Elan touchpads doesn't obey the rule. */ - if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) - etd->hw_version = 1; - else { - switch (ver) { - case 2: - case 4: - etd->hw_version = 2; - break; - case 5: - etd->hw_version = 3; - break; - case 6: - etd->hw_version = 4; - break; - default: - return -1; - } - } - - /* decide which send_cmd we're gonna use early */ - etd->send_cmd = etd->hw_version >= 3 ? elantech_send_cmd : - synaptics_send_cmd; - - /* Turn on packet checking by default */ - etd->paritycheck = 1; - - /* - * This firmware suffers from misreporting coordinates when - * a touch action starts causing the mouse cursor or scrolled page - * to jump. Enable a workaround. - */ - etd->jumpy_cursor = - (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); - - if (etd->hw_version > 1) { - /* For now show extra debug information */ - etd->debug = 1; - - if (etd->fw_version >= 0x020800) - etd->reports_pressure = true; - } - - return 0; -} - -/* - * Initialize the touchpad and create sysfs entries - */ -int elantech_init(struct psmouse *psmouse) -{ - struct elantech_data *etd; - int i, error; - unsigned char param[3]; - - psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); - if (!etd) - return -ENOMEM; - - psmouse_reset(psmouse); - - etd->parity[0] = 1; - for (i = 1; i < 256; i++) - etd->parity[i] = etd->parity[i & (i - 1)] ^ 1; - - /* - * Do the version query again so we can store the result - */ - if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { - psmouse_err(psmouse, "failed to query firmware version.\n"); - goto init_fail; - } - etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; - - if (elantech_set_properties(etd)) { - psmouse_err(psmouse, "unknown hardware version, aborting...\n"); - goto init_fail; - } - psmouse_info(psmouse, - "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n", - etd->hw_version, param[0], param[1], param[2]); - - if (etd->send_cmd(psmouse, ETP_CAPABILITIES_QUERY, - etd->capabilities)) { - psmouse_err(psmouse, "failed to query capabilities.\n"); - goto init_fail; - } - psmouse_info(psmouse, - "Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", - etd->capabilities[0], etd->capabilities[1], - etd->capabilities[2]); - - if (elantech_set_absolute_mode(psmouse)) { - psmouse_err(psmouse, - "failed to put touchpad into absolute mode.\n"); - goto init_fail; - } - - if (elantech_set_input_params(psmouse)) { - psmouse_err(psmouse, "failed to query touchpad range.\n"); - goto init_fail; - } - - error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, - &elantech_attr_group); - if (error) { - psmouse_err(psmouse, - "failed to create sysfs attributes, error: %d.\n", - error); - goto init_fail; - } - - psmouse->protocol_handler = elantech_process_byte; - psmouse->disconnect = elantech_disconnect; - psmouse->reconnect = elantech_reconnect; - psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; - - return 0; - - init_fail: - kfree(etd); - return -1; -} diff --git a/ANDROID_3.4.5/drivers/input/mouse/elantech.h b/ANDROID_3.4.5/drivers/input/mouse/elantech.h deleted file mode 100644 index 46db3be4..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/elantech.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Elantech Touchpad driver (v6) - * - * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net> - * - * 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. - */ - -#ifndef _ELANTECH_H -#define _ELANTECH_H - -/* - * Command values for Synaptics style queries - */ -#define ETP_FW_ID_QUERY 0x00 -#define ETP_FW_VERSION_QUERY 0x01 -#define ETP_CAPABILITIES_QUERY 0x02 -#define ETP_SAMPLE_QUERY 0x03 -#define ETP_RESOLUTION_QUERY 0x04 - -/* - * Command values for register reading or writing - */ -#define ETP_REGISTER_READ 0x10 -#define ETP_REGISTER_WRITE 0x11 -#define ETP_REGISTER_READWRITE 0x00 - -/* - * Hardware version 2 custom PS/2 command value - */ -#define ETP_PS2_CUSTOM_COMMAND 0xf8 - -/* - * Times to retry a ps2_command and millisecond delay between tries - */ -#define ETP_PS2_COMMAND_TRIES 3 -#define ETP_PS2_COMMAND_DELAY 500 - -/* - * Times to try to read back a register and millisecond delay between tries - */ -#define ETP_READ_BACK_TRIES 5 -#define ETP_READ_BACK_DELAY 2000 - -/* - * Register bitmasks for hardware version 1 - */ -#define ETP_R10_ABSOLUTE_MODE 0x04 -#define ETP_R11_4_BYTE_MODE 0x02 - -/* - * Capability bitmasks - */ -#define ETP_CAP_HAS_ROCKER 0x04 - -/* - * One hard to find application note states that X axis range is 0 to 576 - * and Y axis range is 0 to 384 for harware version 1. - * Edge fuzz might be necessary because of bezel around the touchpad - */ -#define ETP_EDGE_FUZZ_V1 32 - -#define ETP_XMIN_V1 ( 0 + ETP_EDGE_FUZZ_V1) -#define ETP_XMAX_V1 (576 - ETP_EDGE_FUZZ_V1) -#define ETP_YMIN_V1 ( 0 + ETP_EDGE_FUZZ_V1) -#define ETP_YMAX_V1 (384 - ETP_EDGE_FUZZ_V1) - -/* - * The resolution for older v2 hardware doubled. - * (newer v2's firmware provides command so we can query) - */ -#define ETP_XMIN_V2 0 -#define ETP_XMAX_V2 1152 -#define ETP_YMIN_V2 0 -#define ETP_YMAX_V2 768 - -#define ETP_PMIN_V2 0 -#define ETP_PMAX_V2 255 -#define ETP_WMIN_V2 0 -#define ETP_WMAX_V2 15 - -/* - * v3 hardware has 2 kinds of packet types, - * v4 hardware has 3. - */ -#define PACKET_UNKNOWN 0x01 -#define PACKET_DEBOUNCE 0x02 -#define PACKET_V3_HEAD 0x03 -#define PACKET_V3_TAIL 0x04 -#define PACKET_V4_HEAD 0x05 -#define PACKET_V4_MOTION 0x06 -#define PACKET_V4_STATUS 0x07 - -/* - * track up to 5 fingers for v4 hardware - */ -#define ETP_MAX_FINGERS 5 - -/* - * weight value for v4 hardware - */ -#define ETP_WEIGHT_VALUE 5 - -/* - * The base position for one finger, v4 hardware - */ -struct finger_pos { - unsigned int x; - unsigned int y; -}; - -struct elantech_data { - unsigned char reg_07; - unsigned char reg_10; - unsigned char reg_11; - unsigned char reg_20; - unsigned char reg_21; - unsigned char reg_22; - unsigned char reg_23; - unsigned char reg_24; - unsigned char reg_25; - unsigned char reg_26; - unsigned char debug; - unsigned char capabilities[3]; - bool paritycheck; - bool jumpy_cursor; - bool reports_pressure; - unsigned char hw_version; - unsigned int fw_version; - unsigned int single_finger_reports; - unsigned int y_max; - unsigned int width; - struct finger_pos mt[ETP_MAX_FINGERS]; - unsigned char parity[256]; - int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param); -}; - -#ifdef CONFIG_MOUSE_PS2_ELANTECH -int elantech_detect(struct psmouse *psmouse, bool set_properties); -int elantech_init(struct psmouse *psmouse); -#else -static inline int elantech_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -static inline int elantech_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_ELANTECH */ - -#endif diff --git a/ANDROID_3.4.5/drivers/input/mouse/gpio_mouse.c b/ANDROID_3.4.5/drivers/input/mouse/gpio_mouse.c deleted file mode 100644 index 39fe9b73..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/gpio_mouse.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Driver for simulating a mouse on GPIO lines. - * - * Copyright (C) 2007 Atmel Corporation - * - * 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. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/input-polldev.h> -#include <linux/gpio.h> -#include <linux/gpio_mouse.h> - - -/* - * Timer function which is run every scan_ms ms when the device is opened. - * The dev input variable is set to the the input_dev pointer. - */ -static void gpio_mouse_scan(struct input_polled_dev *dev) -{ - struct gpio_mouse_platform_data *gpio = dev->private; - struct input_dev *input = dev->input; - int x, y; - - if (gpio->bleft >= 0) - input_report_key(input, BTN_LEFT, - gpio_get_value(gpio->bleft) ^ gpio->polarity); - if (gpio->bmiddle >= 0) - input_report_key(input, BTN_MIDDLE, - gpio_get_value(gpio->bmiddle) ^ gpio->polarity); - if (gpio->bright >= 0) - input_report_key(input, BTN_RIGHT, - gpio_get_value(gpio->bright) ^ gpio->polarity); - - x = (gpio_get_value(gpio->right) ^ gpio->polarity) - - (gpio_get_value(gpio->left) ^ gpio->polarity); - y = (gpio_get_value(gpio->down) ^ gpio->polarity) - - (gpio_get_value(gpio->up) ^ gpio->polarity); - - input_report_rel(input, REL_X, x); - input_report_rel(input, REL_Y, y); - input_sync(input); -} - -static int __devinit gpio_mouse_probe(struct platform_device *pdev) -{ - struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; - struct input_polled_dev *input_poll; - struct input_dev *input; - int pin, i; - int error; - - if (!pdata) { - dev_err(&pdev->dev, "no platform data\n"); - error = -ENXIO; - goto out; - } - - if (pdata->scan_ms < 0) { - dev_err(&pdev->dev, "invalid scan time\n"); - error = -EINVAL; - goto out; - } - - for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) { - pin = pdata->pins[i]; - - if (pin < 0) { - - if (i <= GPIO_MOUSE_PIN_RIGHT) { - /* Mouse direction is required. */ - dev_err(&pdev->dev, - "missing GPIO for directions\n"); - error = -EINVAL; - goto out_free_gpios; - } - - if (i == GPIO_MOUSE_PIN_BLEFT) - dev_dbg(&pdev->dev, "no left button defined\n"); - - } else { - error = gpio_request(pin, "gpio_mouse"); - if (error) { - dev_err(&pdev->dev, "fail %d pin (%d idx)\n", - pin, i); - goto out_free_gpios; - } - - gpio_direction_input(pin); - } - } - - input_poll = input_allocate_polled_device(); - if (!input_poll) { - dev_err(&pdev->dev, "not enough memory for input device\n"); - error = -ENOMEM; - goto out_free_gpios; - } - - platform_set_drvdata(pdev, input_poll); - - /* set input-polldev handlers */ - input_poll->private = pdata; - input_poll->poll = gpio_mouse_scan; - input_poll->poll_interval = pdata->scan_ms; - - input = input_poll->input; - input->name = pdev->name; - input->id.bustype = BUS_HOST; - input->dev.parent = &pdev->dev; - - input_set_capability(input, EV_REL, REL_X); - input_set_capability(input, EV_REL, REL_Y); - if (pdata->bleft >= 0) - input_set_capability(input, EV_KEY, BTN_LEFT); - if (pdata->bmiddle >= 0) - input_set_capability(input, EV_KEY, BTN_MIDDLE); - if (pdata->bright >= 0) - input_set_capability(input, EV_KEY, BTN_RIGHT); - - error = input_register_polled_device(input_poll); - if (error) { - dev_err(&pdev->dev, "could not register input device\n"); - goto out_free_polldev; - } - - dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n", - pdata->scan_ms, - pdata->bleft < 0 ? "" : "left ", - pdata->bmiddle < 0 ? "" : "middle ", - pdata->bright < 0 ? "" : "right"); - - return 0; - - out_free_polldev: - input_free_polled_device(input_poll); - platform_set_drvdata(pdev, NULL); - - out_free_gpios: - while (--i >= 0) { - pin = pdata->pins[i]; - if (pin) - gpio_free(pin); - } - out: - return error; -} - -static int __devexit gpio_mouse_remove(struct platform_device *pdev) -{ - struct input_polled_dev *input = platform_get_drvdata(pdev); - struct gpio_mouse_platform_data *pdata = input->private; - int pin, i; - - input_unregister_polled_device(input); - input_free_polled_device(input); - - for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) { - pin = pdata->pins[i]; - if (pin >= 0) - gpio_free(pin); - } - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver gpio_mouse_device_driver = { - .probe = gpio_mouse_probe, - .remove = __devexit_p(gpio_mouse_remove), - .driver = { - .name = "gpio_mouse", - .owner = THIS_MODULE, - } -}; -module_platform_driver(gpio_mouse_device_driver); - -MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>"); -MODULE_DESCRIPTION("GPIO mouse driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */ - diff --git a/ANDROID_3.4.5/drivers/input/mouse/hgpk.c b/ANDROID_3.4.5/drivers/input/mouse/hgpk.c deleted file mode 100644 index 575f8807..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/hgpk.c +++ /dev/null @@ -1,1070 +0,0 @@ -/* - * OLPC HGPK (XO-1) touchpad PS/2 mouse driver - * - * Copyright (c) 2006-2008 One Laptop Per Child - * Authors: - * Zephaniah E. Hull - * Andres Salomon <dilinger@debian.org> - * - * This driver is partly based on the ALPS driver, which is: - * - * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au> - * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> - * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> - * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> - * - * 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. - */ - -/* - * The spec from ALPS is available from - * <http://wiki.laptop.org/go/Touch_Pad/Tablet>. It refers to this - * device as HGPK (Hybrid GS, PT, and Keymatrix). - * - * The earliest versions of the device had simultaneous reporting; that - * was removed. After that, the device used the Advanced Mode GS/PT streaming - * stuff. That turned out to be too buggy to support, so we've finally - * switched to Mouse Mode (which utilizes only the center 1/3 of the touchpad). - */ - -#define DEBUG -#include <linux/slab.h> -#include <linux/input.h> -#include <linux/module.h> -#include <linux/serio.h> -#include <linux/libps2.h> -#include <linux/delay.h> -#include <asm/olpc.h> - -#include "psmouse.h" -#include "hgpk.h" - -#define ILLEGAL_XY 999999 - -static bool tpdebug; -module_param(tpdebug, bool, 0644); -MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); - -static int recalib_delta = 100; -module_param(recalib_delta, int, 0644); -MODULE_PARM_DESC(recalib_delta, - "packets containing a delta this large will be discarded, and a " - "recalibration may be scheduled."); - -static int jumpy_delay = 20; -module_param(jumpy_delay, int, 0644); -MODULE_PARM_DESC(jumpy_delay, - "delay (ms) before recal after jumpiness detected"); - -static int spew_delay = 1; -module_param(spew_delay, int, 0644); -MODULE_PARM_DESC(spew_delay, - "delay (ms) before recal after packet spew detected"); - -static int recal_guard_time; -module_param(recal_guard_time, int, 0644); -MODULE_PARM_DESC(recal_guard_time, - "interval (ms) during which recal will be restarted if packet received"); - -static int post_interrupt_delay = 40; -module_param(post_interrupt_delay, int, 0644); -MODULE_PARM_DESC(post_interrupt_delay, - "delay (ms) before recal after recal interrupt detected"); - -static bool autorecal = true; -module_param(autorecal, bool, 0644); -MODULE_PARM_DESC(autorecal, "enable recalibration in the driver"); - -static char hgpk_mode_name[16]; -module_param_string(hgpk_mode, hgpk_mode_name, sizeof(hgpk_mode_name), 0644); -MODULE_PARM_DESC(hgpk_mode, - "default hgpk mode: mouse, glidesensor or pentablet"); - -static int hgpk_default_mode = HGPK_MODE_MOUSE; - -static const char * const hgpk_mode_names[] = { - [HGPK_MODE_MOUSE] = "Mouse", - [HGPK_MODE_GLIDESENSOR] = "GlideSensor", - [HGPK_MODE_PENTABLET] = "PenTablet", -}; - -static int hgpk_mode_from_name(const char *buf, int len) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hgpk_mode_names); i++) { - const char *name = hgpk_mode_names[i]; - if (strlen(name) == len && !strncasecmp(name, buf, len)) - return i; - } - - return HGPK_MODE_INVALID; -} - -/* - * see if new value is within 20% of half of old value - */ -static int approx_half(int curr, int prev) -{ - int belowhalf, abovehalf; - - if (curr < 5 || prev < 5) - return 0; - - belowhalf = (prev * 8) / 20; - abovehalf = (prev * 12) / 20; - - return belowhalf < curr && curr <= abovehalf; -} - -/* - * Throw out oddly large delta packets, and any that immediately follow whose - * values are each approximately half of the previous. It seems that the ALPS - * firmware emits errant packets, and they get averaged out slowly. - */ -static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y) -{ - struct hgpk_data *priv = psmouse->private; - int avx, avy; - bool do_recal = false; - - avx = abs(x); - avy = abs(y); - - /* discard if too big, or half that but > 4 times the prev delta */ - if (avx > recalib_delta || - (avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) { - psmouse_warn(psmouse, "detected %dpx jump in x\n", x); - priv->xbigj = avx; - } else if (approx_half(avx, priv->xbigj)) { - psmouse_warn(psmouse, "detected secondary %dpx jump in x\n", x); - priv->xbigj = avx; - priv->xsaw_secondary++; - } else { - if (priv->xbigj && priv->xsaw_secondary > 1) - do_recal = true; - priv->xbigj = 0; - priv->xsaw_secondary = 0; - } - - if (avy > recalib_delta || - (avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) { - psmouse_warn(psmouse, "detected %dpx jump in y\n", y); - priv->ybigj = avy; - } else if (approx_half(avy, priv->ybigj)) { - psmouse_warn(psmouse, "detected secondary %dpx jump in y\n", y); - priv->ybigj = avy; - priv->ysaw_secondary++; - } else { - if (priv->ybigj && priv->ysaw_secondary > 1) - do_recal = true; - priv->ybigj = 0; - priv->ysaw_secondary = 0; - } - - priv->xlast = avx; - priv->ylast = avy; - - if (do_recal && jumpy_delay) { - psmouse_warn(psmouse, "scheduling recalibration\n"); - psmouse_queue_work(psmouse, &priv->recalib_wq, - msecs_to_jiffies(jumpy_delay)); - } - - return priv->xbigj || priv->ybigj; -} - -static void hgpk_reset_spew_detection(struct hgpk_data *priv) -{ - priv->spew_count = 0; - priv->dupe_count = 0; - priv->x_tally = 0; - priv->y_tally = 0; - priv->spew_flag = NO_SPEW; -} - -static void hgpk_reset_hack_state(struct psmouse *psmouse) -{ - struct hgpk_data *priv = psmouse->private; - - priv->abs_x = priv->abs_y = -1; - priv->xlast = priv->ylast = ILLEGAL_XY; - priv->xbigj = priv->ybigj = 0; - priv->xsaw_secondary = priv->ysaw_secondary = 0; - hgpk_reset_spew_detection(priv); -} - -/* - * We have no idea why this particular hardware bug occurs. The touchpad - * will randomly start spewing packets without anything touching the - * pad. This wouldn't necessarily be bad, but it's indicative of a - * severely miscalibrated pad; attempting to use the touchpad while it's - * spewing means the cursor will jump all over the place, and act "drunk". - * - * The packets that are spewed tend to all have deltas between -2 and 2, and - * the cursor will move around without really going very far. It will - * tend to end up in the same location; if we tally up the changes over - * 100 packets, we end up w/ a final delta of close to 0. This happens - * pretty regularly when the touchpad is spewing, and is pretty hard to - * manually trigger (at least for *my* fingers). So, it makes a perfect - * scheme for detecting spews. - */ -static void hgpk_spewing_hack(struct psmouse *psmouse, - int l, int r, int x, int y) -{ - struct hgpk_data *priv = psmouse->private; - - /* ignore button press packets; many in a row could trigger - * a false-positive! */ - if (l || r) - return; - - /* don't track spew if the workaround feature has been turned off */ - if (!spew_delay) - return; - - if (abs(x) > 3 || abs(y) > 3) { - /* no spew, or spew ended */ - hgpk_reset_spew_detection(priv); - return; - } - - /* Keep a tally of the overall delta to the cursor position caused by - * the spew */ - priv->x_tally += x; - priv->y_tally += y; - - switch (priv->spew_flag) { - case NO_SPEW: - /* we're not spewing, but this packet might be the start */ - priv->spew_flag = MAYBE_SPEWING; - - /* fall-through */ - - case MAYBE_SPEWING: - priv->spew_count++; - - if (priv->spew_count < SPEW_WATCH_COUNT) - break; - - /* excessive spew detected, request recalibration */ - priv->spew_flag = SPEW_DETECTED; - - /* fall-through */ - - case SPEW_DETECTED: - /* only recalibrate when the overall delta to the cursor - * is really small. if the spew is causing significant cursor - * movement, it is probably a case of the user moving the - * cursor very slowly across the screen. */ - if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { - psmouse_warn(psmouse, "packet spew detected (%d,%d)\n", - priv->x_tally, priv->y_tally); - priv->spew_flag = RECALIBRATING; - psmouse_queue_work(psmouse, &priv->recalib_wq, - msecs_to_jiffies(spew_delay)); - } - - break; - case RECALIBRATING: - /* we already detected a spew and requested a recalibration, - * just wait for the queue to kick into action. */ - break; - } -} - -/* - * HGPK Mouse Mode format (standard mouse format, sans middle button) - * - * byte 0: y-over x-over y-neg x-neg 1 0 swr swl - * byte 1: x7 x6 x5 x4 x3 x2 x1 x0 - * byte 2: y7 y6 y5 y4 y3 y2 y1 y0 - * - * swr/swl are the left/right buttons. - * x-neg/y-neg are the x and y delta negative bits - * x-over/y-over are the x and y overflow bits - * - * --- - * - * HGPK Advanced Mode - single-mode format - * - * byte 0(PT): 1 1 0 0 1 1 1 1 - * byte 0(GS): 1 1 1 1 1 1 1 1 - * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 - * byte 2(PT): 0 0 x9 x8 x7 ? pt-dsw 0 - * byte 2(GS): 0 x10 x9 x8 x7 ? gs-dsw pt-dsw - * byte 3: 0 y9 y8 y7 1 0 swr swl - * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 - * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 - * - * ?'s are not defined in the protocol spec, may vary between models. - * - * swr/swl are the left/right buttons. - * - * pt-dsw/gs-dsw indicate that the pt/gs sensor is detecting a - * pen/finger - */ -static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet) -{ - struct hgpk_data *priv = psmouse->private; - int pktcnt = psmouse->pktcnt; - bool valid; - - switch (priv->mode) { - case HGPK_MODE_MOUSE: - valid = (packet[0] & 0x0C) == 0x08; - break; - - case HGPK_MODE_GLIDESENSOR: - valid = pktcnt == 1 ? - packet[0] == HGPK_GS : !(packet[pktcnt - 1] & 0x80); - break; - - case HGPK_MODE_PENTABLET: - valid = pktcnt == 1 ? - packet[0] == HGPK_PT : !(packet[pktcnt - 1] & 0x80); - break; - - default: - valid = false; - break; - } - - if (!valid) - psmouse_dbg(psmouse, - "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n", - priv->mode, pktcnt, - psmouse->packet[0], psmouse->packet[1], - psmouse->packet[2], psmouse->packet[3], - psmouse->packet[4], psmouse->packet[5]); - - return valid; -} - -static void hgpk_process_advanced_packet(struct psmouse *psmouse) -{ - struct hgpk_data *priv = psmouse->private; - struct input_dev *idev = psmouse->dev; - unsigned char *packet = psmouse->packet; - int down = !!(packet[2] & 2); - int left = !!(packet[3] & 1); - int right = !!(packet[3] & 2); - int x = packet[1] | ((packet[2] & 0x78) << 4); - int y = packet[4] | ((packet[3] & 0x70) << 3); - - if (priv->mode == HGPK_MODE_GLIDESENSOR) { - int pt_down = !!(packet[2] & 1); - int finger_down = !!(packet[2] & 2); - int z = packet[5]; - - input_report_abs(idev, ABS_PRESSURE, z); - if (tpdebug) - psmouse_dbg(psmouse, "pd=%d fd=%d z=%d", - pt_down, finger_down, z); - } else { - /* - * PenTablet mode does not report pressure, so we don't - * report it here - */ - if (tpdebug) - psmouse_dbg(psmouse, "pd=%d ", down); - } - - if (tpdebug) - psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", - left, right, x, y); - - input_report_key(idev, BTN_TOUCH, down); - input_report_key(idev, BTN_LEFT, left); - input_report_key(idev, BTN_RIGHT, right); - - /* - * If this packet says that the finger was removed, reset our position - * tracking so that we don't erroneously detect a jump on next press. - */ - if (!down) { - hgpk_reset_hack_state(psmouse); - goto done; - } - - /* - * Weed out duplicate packets (we get quite a few, and they mess up - * our jump detection) - */ - if (x == priv->abs_x && y == priv->abs_y) { - if (++priv->dupe_count > SPEW_WATCH_COUNT) { - if (tpdebug) - psmouse_dbg(psmouse, "hard spew detected\n"); - priv->spew_flag = RECALIBRATING; - psmouse_queue_work(psmouse, &priv->recalib_wq, - msecs_to_jiffies(spew_delay)); - } - goto done; - } - - /* not a duplicate, continue with position reporting */ - priv->dupe_count = 0; - - /* Don't apply hacks in PT mode, it seems reliable */ - if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) { - int x_diff = priv->abs_x - x; - int y_diff = priv->abs_y - y; - if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) { - if (tpdebug) - psmouse_dbg(psmouse, "discarding\n"); - goto done; - } - hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff); - } - - input_report_abs(idev, ABS_X, x); - input_report_abs(idev, ABS_Y, y); - priv->abs_x = x; - priv->abs_y = y; - -done: - input_sync(idev); -} - -static void hgpk_process_simple_packet(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - unsigned char *packet = psmouse->packet; - int left = packet[0] & 1; - int right = (packet[0] >> 1) & 1; - int x = packet[1] - ((packet[0] << 4) & 0x100); - int y = ((packet[0] << 3) & 0x100) - packet[2]; - - if (packet[0] & 0xc0) - psmouse_dbg(psmouse, - "overflow -- 0x%02x 0x%02x 0x%02x\n", - packet[0], packet[1], packet[2]); - - if (hgpk_discard_decay_hack(psmouse, x, y)) { - if (tpdebug) - psmouse_dbg(psmouse, "discarding\n"); - return; - } - - hgpk_spewing_hack(psmouse, left, right, x, y); - - if (tpdebug) - psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", - left, right, x, y); - - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_RIGHT, right); - - input_report_rel(dev, REL_X, x); - input_report_rel(dev, REL_Y, y); - - input_sync(dev); -} - -static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse) -{ - struct hgpk_data *priv = psmouse->private; - - if (!hgpk_is_byte_valid(psmouse, psmouse->packet)) - return PSMOUSE_BAD_DATA; - - if (psmouse->pktcnt >= psmouse->pktsize) { - if (priv->mode == HGPK_MODE_MOUSE) - hgpk_process_simple_packet(psmouse); - else - hgpk_process_advanced_packet(psmouse); - return PSMOUSE_FULL_PACKET; - } - - if (priv->recalib_window) { - if (time_before(jiffies, priv->recalib_window)) { - /* - * ugh, got a packet inside our recalibration - * window, schedule another recalibration. - */ - psmouse_dbg(psmouse, - "packet inside calibration window, queueing another recalibration\n"); - psmouse_queue_work(psmouse, &priv->recalib_wq, - msecs_to_jiffies(post_interrupt_delay)); - } - priv->recalib_window = 0; - } - - return PSMOUSE_GOOD_DATA; -} - -static int hgpk_select_mode(struct psmouse *psmouse) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - struct hgpk_data *priv = psmouse->private; - int i; - int cmd; - - /* - * 4 disables to enable advanced mode - * then 3 0xf2 bytes as the preamble for GS/PT selection - */ - const int advanced_init[] = { - PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE, - PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE, - 0xf2, 0xf2, 0xf2, - }; - - switch (priv->mode) { - case HGPK_MODE_MOUSE: - psmouse->pktsize = 3; - break; - - case HGPK_MODE_GLIDESENSOR: - case HGPK_MODE_PENTABLET: - psmouse->pktsize = 6; - - /* Switch to 'Advanced mode.', four disables in a row. */ - for (i = 0; i < ARRAY_SIZE(advanced_init); i++) - if (ps2_command(ps2dev, NULL, advanced_init[i])) - return -EIO; - - /* select between GlideSensor (mouse) or PenTablet */ - cmd = priv->mode == HGPK_MODE_GLIDESENSOR ? - PSMOUSE_CMD_SETSCALE11 : PSMOUSE_CMD_SETSCALE21; - - if (ps2_command(ps2dev, NULL, cmd)) - return -EIO; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static void hgpk_setup_input_device(struct input_dev *input, - struct input_dev *old_input, - enum hgpk_mode mode) -{ - if (old_input) { - input->name = old_input->name; - input->phys = old_input->phys; - input->id = old_input->id; - input->dev.parent = old_input->dev.parent; - } - - memset(input->evbit, 0, sizeof(input->evbit)); - memset(input->relbit, 0, sizeof(input->relbit)); - memset(input->keybit, 0, sizeof(input->keybit)); - - /* All modes report left and right buttons */ - __set_bit(EV_KEY, input->evbit); - __set_bit(BTN_LEFT, input->keybit); - __set_bit(BTN_RIGHT, input->keybit); - - switch (mode) { - case HGPK_MODE_MOUSE: - __set_bit(EV_REL, input->evbit); - __set_bit(REL_X, input->relbit); - __set_bit(REL_Y, input->relbit); - break; - - case HGPK_MODE_GLIDESENSOR: - __set_bit(BTN_TOUCH, input->keybit); - __set_bit(BTN_TOOL_FINGER, input->keybit); - - __set_bit(EV_ABS, input->evbit); - - /* GlideSensor has pressure sensor, PenTablet does not */ - input_set_abs_params(input, ABS_PRESSURE, 0, 15, 0, 0); - - /* From device specs */ - input_set_abs_params(input, ABS_X, 0, 399, 0, 0); - input_set_abs_params(input, ABS_Y, 0, 290, 0, 0); - - /* Calculated by hand based on usable size (52mm x 38mm) */ - input_abs_set_res(input, ABS_X, 8); - input_abs_set_res(input, ABS_Y, 8); - break; - - case HGPK_MODE_PENTABLET: - __set_bit(BTN_TOUCH, input->keybit); - __set_bit(BTN_TOOL_FINGER, input->keybit); - - __set_bit(EV_ABS, input->evbit); - - /* From device specs */ - input_set_abs_params(input, ABS_X, 0, 999, 0, 0); - input_set_abs_params(input, ABS_Y, 5, 239, 0, 0); - - /* Calculated by hand based on usable size (156mm x 38mm) */ - input_abs_set_res(input, ABS_X, 6); - input_abs_set_res(input, ABS_Y, 8); - break; - - default: - BUG(); - } -} - -static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate) -{ - int err; - - psmouse_reset(psmouse); - - if (recalibrate) { - struct ps2dev *ps2dev = &psmouse->ps2dev; - - /* send the recalibrate request */ - if (ps2_command(ps2dev, NULL, 0xf5) || - ps2_command(ps2dev, NULL, 0xf5) || - ps2_command(ps2dev, NULL, 0xe6) || - ps2_command(ps2dev, NULL, 0xf5)) { - return -1; - } - - /* according to ALPS, 150mS is required for recalibration */ - msleep(150); - } - - err = hgpk_select_mode(psmouse); - if (err) { - psmouse_err(psmouse, "failed to select mode\n"); - return err; - } - - hgpk_reset_hack_state(psmouse); - - return 0; -} - -static int hgpk_force_recalibrate(struct psmouse *psmouse) -{ - struct hgpk_data *priv = psmouse->private; - int err; - - /* C-series touchpads added the recalibrate command */ - if (psmouse->model < HGPK_MODEL_C) - return 0; - - if (!autorecal) { - psmouse_dbg(psmouse, "recalibration disabled, ignoring\n"); - return 0; - } - - psmouse_dbg(psmouse, "recalibrating touchpad..\n"); - - /* we don't want to race with the irq handler, nor with resyncs */ - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - - /* start by resetting the device */ - err = hgpk_reset_device(psmouse, true); - if (err) - return err; - - /* - * XXX: If a finger is down during this delay, recalibration will - * detect capacitance incorrectly. This is a hardware bug, and - * we don't have a good way to deal with it. The 2s window stuff - * (below) is our best option for now. - */ - if (psmouse_activate(psmouse)) - return -1; - - if (tpdebug) - psmouse_dbg(psmouse, "touchpad reactivated\n"); - - /* - * If we get packets right away after recalibrating, it's likely - * that a finger was on the touchpad. If so, it's probably - * miscalibrated, so we optionally schedule another. - */ - if (recal_guard_time) - priv->recalib_window = jiffies + - msecs_to_jiffies(recal_guard_time); - - return 0; -} - -/* - * This puts the touchpad in a power saving mode; according to ALPS, current - * consumption goes down to 50uA after running this. To turn power back on, - * we drive MS-DAT low. Measuring with a 1mA resolution ammeter says that - * the current on the SUS_3.3V rail drops from 3mA or 4mA to 0 when we do this. - * - * We have no formal spec that details this operation -- the low-power - * sequence came from a long-lost email trail. - */ -static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - int timeo; - int err; - - /* Added on D-series touchpads */ - if (psmouse->model < HGPK_MODEL_D) - return 0; - - if (enable) { - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - - /* - * Sending a byte will drive MS-DAT low; this will wake up - * the controller. Once we get an ACK back from it, it - * means we can continue with the touchpad re-init. ALPS - * tells us that 1s should be long enough, so set that as - * the upper bound. (in practice, it takes about 3 loops.) - */ - for (timeo = 20; timeo > 0; timeo--) { - if (!ps2_sendbyte(&psmouse->ps2dev, - PSMOUSE_CMD_DISABLE, 20)) - break; - msleep(25); - } - - err = hgpk_reset_device(psmouse, false); - if (err) { - psmouse_err(psmouse, "Failed to reset device!\n"); - return err; - } - - /* should be all set, enable the touchpad */ - psmouse_activate(psmouse); - psmouse_dbg(psmouse, "Touchpad powered up.\n"); - } else { - psmouse_dbg(psmouse, "Powering off touchpad.\n"); - - if (ps2_command(ps2dev, NULL, 0xec) || - ps2_command(ps2dev, NULL, 0xec) || - ps2_command(ps2dev, NULL, 0xea)) { - return -1; - } - - psmouse_set_state(psmouse, PSMOUSE_IGNORE); - - /* probably won't see an ACK, the touchpad will be off */ - ps2_sendbyte(&psmouse->ps2dev, 0xec, 20); - } - - return 0; -} - -static int hgpk_poll(struct psmouse *psmouse) -{ - /* We can't poll, so always return failure. */ - return -1; -} - -static int hgpk_reconnect(struct psmouse *psmouse) -{ - struct hgpk_data *priv = psmouse->private; - - /* - * During suspend/resume the ps2 rails remain powered. We don't want - * to do a reset because it's flush data out of buffers; however, - * earlier prototypes (B1) had some brokenness that required a reset. - */ - if (olpc_board_at_least(olpc_board(0xb2))) - if (psmouse->ps2dev.serio->dev.power.power_state.event != - PM_EVENT_ON) - return 0; - - priv->powered = 1; - return hgpk_reset_device(psmouse, false); -} - -static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf) -{ - struct hgpk_data *priv = psmouse->private; - - return sprintf(buf, "%d\n", priv->powered); -} - -static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - struct hgpk_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->powered) { - /* - * hgpk_toggle_power will deal w/ state so - * we're not racing w/ irq - */ - err = hgpk_toggle_powersave(psmouse, value); - if (!err) - priv->powered = value; - } - - return err ? err : count; -} - -__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, - hgpk_show_powered, hgpk_set_powered, false); - -static ssize_t attr_show_mode(struct psmouse *psmouse, void *data, char *buf) -{ - struct hgpk_data *priv = psmouse->private; - - return sprintf(buf, "%s\n", hgpk_mode_names[priv->mode]); -} - -static ssize_t attr_set_mode(struct psmouse *psmouse, void *data, - const char *buf, size_t len) -{ - struct hgpk_data *priv = psmouse->private; - enum hgpk_mode old_mode = priv->mode; - enum hgpk_mode new_mode = hgpk_mode_from_name(buf, len); - struct input_dev *old_dev = psmouse->dev; - struct input_dev *new_dev; - int err; - - if (new_mode == HGPK_MODE_INVALID) - return -EINVAL; - - if (old_mode == new_mode) - return len; - - new_dev = input_allocate_device(); - if (!new_dev) - return -ENOMEM; - - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - - /* Switch device into the new mode */ - priv->mode = new_mode; - err = hgpk_reset_device(psmouse, false); - if (err) - goto err_try_restore; - - hgpk_setup_input_device(new_dev, old_dev, new_mode); - - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - - err = input_register_device(new_dev); - if (err) - goto err_try_restore; - - psmouse->dev = new_dev; - input_unregister_device(old_dev); - - return len; - -err_try_restore: - input_free_device(new_dev); - priv->mode = old_mode; - hgpk_reset_device(psmouse, false); - - return err; -} - -PSMOUSE_DEFINE_ATTR(hgpk_mode, S_IWUSR | S_IRUGO, NULL, - attr_show_mode, attr_set_mode); - -static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse, - void *data, char *buf) -{ - return -EINVAL; -} - -static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - struct hgpk_data *priv = psmouse->private; - unsigned int value; - int err; - - err = kstrtouint(buf, 10, &value); - if (err) - return err; - - if (value != 1) - return -EINVAL; - - /* - * We queue work instead of doing recalibration right here - * to avoid adding locking to to hgpk_force_recalibrate() - * since workqueue provides serialization. - */ - psmouse_queue_work(psmouse, &priv->recalib_wq, 0); - return count; -} - -__PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL, - hgpk_trigger_recal_show, hgpk_trigger_recal, false); - -static void hgpk_disconnect(struct psmouse *psmouse) -{ - struct hgpk_data *priv = psmouse->private; - - device_remove_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_powered.dattr); - device_remove_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_hgpk_mode.dattr); - - if (psmouse->model >= HGPK_MODEL_C) - device_remove_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_recalibrate.dattr); - - psmouse_reset(psmouse); - kfree(priv); -} - -static void hgpk_recalib_work(struct work_struct *work) -{ - struct delayed_work *w = to_delayed_work(work); - struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq); - struct psmouse *psmouse = priv->psmouse; - - if (hgpk_force_recalibrate(psmouse)) - psmouse_err(psmouse, "recalibration failed!\n"); -} - -static int hgpk_register(struct psmouse *psmouse) -{ - struct hgpk_data *priv = psmouse->private; - int err; - - /* register handlers */ - psmouse->protocol_handler = hgpk_process_byte; - psmouse->poll = hgpk_poll; - psmouse->disconnect = hgpk_disconnect; - psmouse->reconnect = hgpk_reconnect; - - /* Disable the idle resync. */ - psmouse->resync_time = 0; - /* Reset after a lot of bad bytes. */ - psmouse->resetafter = 1024; - - hgpk_setup_input_device(psmouse->dev, NULL, priv->mode); - - err = device_create_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_powered.dattr); - if (err) { - psmouse_err(psmouse, "Failed creating 'powered' sysfs node\n"); - return err; - } - - err = device_create_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_hgpk_mode.dattr); - if (err) { - psmouse_err(psmouse, - "Failed creating 'hgpk_mode' sysfs node\n"); - goto err_remove_powered; - } - - /* C-series touchpads added the recalibrate command */ - if (psmouse->model >= HGPK_MODEL_C) { - err = device_create_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_recalibrate.dattr); - if (err) { - psmouse_err(psmouse, - "Failed creating 'recalibrate' sysfs node\n"); - goto err_remove_mode; - } - } - - return 0; - -err_remove_mode: - device_remove_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_hgpk_mode.dattr); -err_remove_powered: - device_remove_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_powered.dattr); - return err; -} - -int hgpk_init(struct psmouse *psmouse) -{ - struct hgpk_data *priv; - int err; - - priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL); - if (!priv) { - err = -ENOMEM; - goto alloc_fail; - } - - psmouse->private = priv; - - priv->psmouse = psmouse; - priv->powered = true; - priv->mode = hgpk_default_mode; - INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); - - err = hgpk_reset_device(psmouse, false); - if (err) - goto init_fail; - - err = hgpk_register(psmouse); - if (err) - goto init_fail; - - return 0; - -init_fail: - kfree(priv); -alloc_fail: - return err; -} - -static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[3]; - - /* E7, E7, E7, E9 gets us a 3 byte identifier */ - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { - return -EIO; - } - - psmouse_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]); - - /* HGPK signature: 0x67, 0x00, 0x<model> */ - if (param[0] != 0x67 || param[1] != 0x00) - return -ENODEV; - - psmouse_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]); - - return param[2]; -} - -int hgpk_detect(struct psmouse *psmouse, bool set_properties) -{ - int version; - - version = hgpk_get_model(psmouse); - if (version < 0) - return version; - - if (set_properties) { - psmouse->vendor = "ALPS"; - psmouse->name = "HGPK"; - psmouse->model = version; - } - - return 0; -} - -void hgpk_module_init(void) -{ - hgpk_default_mode = hgpk_mode_from_name(hgpk_mode_name, - strlen(hgpk_mode_name)); - if (hgpk_default_mode == HGPK_MODE_INVALID) { - hgpk_default_mode = HGPK_MODE_MOUSE; - strlcpy(hgpk_mode_name, hgpk_mode_names[HGPK_MODE_MOUSE], - sizeof(hgpk_mode_name)); - } -} diff --git a/ANDROID_3.4.5/drivers/input/mouse/hgpk.h b/ANDROID_3.4.5/drivers/input/mouse/hgpk.h deleted file mode 100644 index dd686771..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/hgpk.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * OLPC HGPK (XO-1) touchpad PS/2 mouse driver - */ - -#ifndef _HGPK_H -#define _HGPK_H - -#define HGPK_GS 0xff /* The GlideSensor */ -#define HGPK_PT 0xcf /* The PenTablet */ - -enum hgpk_model_t { - HGPK_MODEL_PREA = 0x0a, /* pre-B1s */ - HGPK_MODEL_A = 0x14, /* found on B1s, PT disabled in hardware */ - HGPK_MODEL_B = 0x28, /* B2s, has capacitance issues */ - HGPK_MODEL_C = 0x3c, - HGPK_MODEL_D = 0x50, /* C1, mass production */ -}; - -enum hgpk_spew_flag { - NO_SPEW, - MAYBE_SPEWING, - SPEW_DETECTED, - RECALIBRATING, -}; - -#define SPEW_WATCH_COUNT 42 /* at 12ms/packet, this is 1/2 second */ - -enum hgpk_mode { - HGPK_MODE_MOUSE, - HGPK_MODE_GLIDESENSOR, - HGPK_MODE_PENTABLET, - HGPK_MODE_INVALID -}; - -struct hgpk_data { - struct psmouse *psmouse; - enum hgpk_mode mode; - bool powered; - enum hgpk_spew_flag spew_flag; - int spew_count, x_tally, y_tally; /* spew detection */ - unsigned long recalib_window; - struct delayed_work recalib_wq; - int abs_x, abs_y; - int dupe_count; - int xbigj, ybigj, xlast, ylast; /* jumpiness detection */ - int xsaw_secondary, ysaw_secondary; /* jumpiness detection */ -}; - -#ifdef CONFIG_MOUSE_PS2_OLPC -void hgpk_module_init(void); -int hgpk_detect(struct psmouse *psmouse, bool set_properties); -int hgpk_init(struct psmouse *psmouse); -#else -static inline void hgpk_module_init(void) -{ -} -static inline int hgpk_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENODEV; -} -static inline int hgpk_init(struct psmouse *psmouse) -{ - return -ENODEV; -} -#endif - -#endif diff --git a/ANDROID_3.4.5/drivers/input/mouse/inport.c b/ANDROID_3.4.5/drivers/input/mouse/inport.c deleted file mode 100644 index 3827a223..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/inport.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 1999-2001 Vojtech Pavlik - * - * Based on the work of: - * Teemu Rantanen Derrick Cole - * Peter Cervasio Christoph Niemann - * Philip Blundell Russell King - * Bob Harris - */ - -/* - * Inport (ATI XL and Microsoft) busmouse driver for Linux - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/input.h> - -#include <asm/io.h> -#include <asm/irq.h> - -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); -MODULE_DESCRIPTION("Inport (ATI XL and Microsoft) busmouse driver"); -MODULE_LICENSE("GPL"); - -#define INPORT_BASE 0x23c -#define INPORT_EXTENT 4 - -#define INPORT_CONTROL_PORT INPORT_BASE + 0 -#define INPORT_DATA_PORT INPORT_BASE + 1 -#define INPORT_SIGNATURE_PORT INPORT_BASE + 2 - -#define INPORT_REG_BTNS 0x00 -#define INPORT_REG_X 0x01 -#define INPORT_REG_Y 0x02 -#define INPORT_REG_MODE 0x07 -#define INPORT_RESET 0x80 - -#ifdef CONFIG_MOUSE_ATIXL -#define INPORT_NAME "ATI XL Mouse" -#define INPORT_VENDOR 0x0002 -#define INPORT_SPEED_30HZ 0x01 -#define INPORT_SPEED_50HZ 0x02 -#define INPORT_SPEED_100HZ 0x03 -#define INPORT_SPEED_200HZ 0x04 -#define INPORT_MODE_BASE INPORT_SPEED_100HZ -#define INPORT_MODE_IRQ 0x08 -#else -#define INPORT_NAME "Microsoft InPort Mouse" -#define INPORT_VENDOR 0x0001 -#define INPORT_MODE_BASE 0x10 -#define INPORT_MODE_IRQ 0x01 -#endif -#define INPORT_MODE_HOLD 0x20 - -#define INPORT_IRQ 5 - -static int inport_irq = INPORT_IRQ; -module_param_named(irq, inport_irq, uint, 0); -MODULE_PARM_DESC(irq, "IRQ number (5=default)"); - -static struct input_dev *inport_dev; - -static irqreturn_t inport_interrupt(int irq, void *dev_id) -{ - unsigned char buttons; - - outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); - outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); - - outb(INPORT_REG_X, INPORT_CONTROL_PORT); - input_report_rel(inport_dev, REL_X, inb(INPORT_DATA_PORT)); - - outb(INPORT_REG_Y, INPORT_CONTROL_PORT); - input_report_rel(inport_dev, REL_Y, inb(INPORT_DATA_PORT)); - - outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT); - buttons = inb(INPORT_DATA_PORT); - - input_report_key(inport_dev, BTN_MIDDLE, buttons & 1); - input_report_key(inport_dev, BTN_LEFT, buttons & 2); - input_report_key(inport_dev, BTN_RIGHT, buttons & 4); - - outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); - outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); - - input_sync(inport_dev); - return IRQ_HANDLED; -} - -static int inport_open(struct input_dev *dev) -{ - if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) - return -EBUSY; - outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); - outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); - - return 0; -} - -static void inport_close(struct input_dev *dev) -{ - outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); - outb(INPORT_MODE_BASE, INPORT_DATA_PORT); - free_irq(inport_irq, NULL); -} - -static int __init inport_init(void) -{ - unsigned char a, b, c; - int err; - - if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) { - printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE); - return -EBUSY; - } - - a = inb(INPORT_SIGNATURE_PORT); - b = inb(INPORT_SIGNATURE_PORT); - c = inb(INPORT_SIGNATURE_PORT); - if (a == b || a != c) { - printk(KERN_INFO "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE); - err = -ENODEV; - goto err_release_region; - } - - inport_dev = input_allocate_device(); - if (!inport_dev) { - printk(KERN_ERR "inport.c: Not enough memory for input device\n"); - err = -ENOMEM; - goto err_release_region; - } - - inport_dev->name = INPORT_NAME; - inport_dev->phys = "isa023c/input0"; - inport_dev->id.bustype = BUS_ISA; - inport_dev->id.vendor = INPORT_VENDOR; - inport_dev->id.product = 0x0001; - inport_dev->id.version = 0x0100; - - inport_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - inport_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); - inport_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - - inport_dev->open = inport_open; - inport_dev->close = inport_close; - - outb(INPORT_RESET, INPORT_CONTROL_PORT); - outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); - outb(INPORT_MODE_BASE, INPORT_DATA_PORT); - - err = input_register_device(inport_dev); - if (err) - goto err_free_dev; - - return 0; - - err_free_dev: - input_free_device(inport_dev); - err_release_region: - release_region(INPORT_BASE, INPORT_EXTENT); - - return err; -} - -static void __exit inport_exit(void) -{ - input_unregister_device(inport_dev); - release_region(INPORT_BASE, INPORT_EXTENT); -} - -module_init(inport_init); -module_exit(inport_exit); diff --git a/ANDROID_3.4.5/drivers/input/mouse/lifebook.c b/ANDROID_3.4.5/drivers/input/mouse/lifebook.c deleted file mode 100644 index 2c4db636..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/lifebook.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Fujitsu B-series Lifebook PS/2 TouchScreen driver - * - * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Kenan Esau <kenan.esau@conan.de> - * - * TouchScreen detection, absolute mode setting and packet layout is taken from - * Harald Hoyer's description of the device. - * - * 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. - */ - -#include <linux/input.h> -#include <linux/serio.h> -#include <linux/libps2.h> -#include <linux/dmi.h> -#include <linux/slab.h> - -#include "psmouse.h" -#include "lifebook.h" - -struct lifebook_data { - struct input_dev *dev2; /* Relative device */ - char phys[32]; -}; - -static bool lifebook_present; - -static const char *desired_serio_phys; - -static int lifebook_limit_serio3(const struct dmi_system_id *d) -{ - desired_serio_phys = "isa0060/serio3"; - return 1; -} - -static bool lifebook_use_6byte_proto; - -static int lifebook_set_6byte_proto(const struct dmi_system_id *d) -{ - lifebook_use_6byte_proto = true; - return 1; -} - -static const struct dmi_system_id __initconst lifebook_dmi_table[] = { - { - /* FLORA-ie 55mi */ - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"), - }, - }, - { - /* LifeBook B */ - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "Lifebook B Series"), - }, - }, - { - /* LifeBook B */ - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"), - }, - }, - { - /* Lifebook B */ - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), - }, - }, - { - /* Lifebook B-2130 */ - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"), - }, - }, - { - /* Lifebook B213x/B2150 */ - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), - }, - }, - { - /* Zephyr */ - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"), - }, - }, - { - /* Panasonic CF-18 */ - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"), - }, - .callback = lifebook_limit_serio3, - }, - { - /* Panasonic CF-28 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), - DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"), - }, - .callback = lifebook_set_6byte_proto, - }, - { - /* Panasonic CF-29 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), - DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"), - }, - .callback = lifebook_set_6byte_proto, - }, - { - /* Panasonic CF-72 */ - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"), - }, - .callback = lifebook_set_6byte_proto, - }, - { - /* Lifebook B142 */ - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), - }, - }, - { } -}; - -void __init lifebook_module_init(void) -{ - lifebook_present = dmi_check_system(lifebook_dmi_table); -} - -static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) -{ - struct lifebook_data *priv = psmouse->private; - struct input_dev *dev1 = psmouse->dev; - struct input_dev *dev2 = priv ? priv->dev2 : NULL; - unsigned char *packet = psmouse->packet; - bool relative_packet = packet[0] & 0x08; - - if (relative_packet || !lifebook_use_6byte_proto) { - if (psmouse->pktcnt != 3) - return PSMOUSE_GOOD_DATA; - } else { - switch (psmouse->pktcnt) { - case 1: - return (packet[0] & 0xf8) == 0x00 ? - PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; - case 2: - return PSMOUSE_GOOD_DATA; - case 3: - return ((packet[2] & 0x30) << 2) == (packet[2] & 0xc0) ? - PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; - case 4: - return (packet[3] & 0xf8) == 0xc0 ? - PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; - case 5: - return (packet[4] & 0xc0) == (packet[2] & 0xc0) ? - PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; - case 6: - if (((packet[5] & 0x30) << 2) != (packet[5] & 0xc0)) - return PSMOUSE_BAD_DATA; - if ((packet[5] & 0xc0) != (packet[1] & 0xc0)) - return PSMOUSE_BAD_DATA; - break; /* report data */ - } - } - - if (relative_packet) { - if (!dev2) - psmouse_warn(psmouse, - "got relative packet but no relative device set up\n"); - } else { - if (lifebook_use_6byte_proto) { - input_report_abs(dev1, ABS_X, - ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f)); - input_report_abs(dev1, ABS_Y, - 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f))); - } else { - input_report_abs(dev1, ABS_X, - (packet[1] | ((packet[0] & 0x30) << 4))); - input_report_abs(dev1, ABS_Y, - 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); - } - input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04); - input_sync(dev1); - } - - if (dev2) { - if (relative_packet) { - input_report_rel(dev2, REL_X, - ((packet[0] & 0x10) ? packet[1] - 256 : packet[1])); - input_report_rel(dev2, REL_Y, - -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2])); - } - input_report_key(dev2, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev2, BTN_RIGHT, packet[0] & 0x02); - input_sync(dev2); - } - - return PSMOUSE_FULL_PACKET; -} - -static int lifebook_absolute_mode(struct psmouse *psmouse) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param; - - if (psmouse_reset(psmouse)) - return -1; - - /* - * Enable absolute output -- ps2_command fails always but if - * you leave this call out the touchscreen will never send - * absolute coordinates - */ - param = lifebook_use_6byte_proto ? 0x08 : 0x07; - ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); - - return 0; -} - -static void lifebook_relative_mode(struct psmouse *psmouse) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param = 0x06; - - ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); -} - -static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution) -{ - static const unsigned char params[] = { 0, 1, 2, 2, 3 }; - unsigned char p; - - if (resolution == 0 || resolution > 400) - resolution = 400; - - p = params[resolution / 100]; - ps2_command(&psmouse->ps2dev, &p, PSMOUSE_CMD_SETRES); - psmouse->resolution = 50 << p; -} - -static void lifebook_disconnect(struct psmouse *psmouse) -{ - struct lifebook_data *priv = psmouse->private; - - psmouse_reset(psmouse); - if (priv) { - input_unregister_device(priv->dev2); - kfree(priv); - } - psmouse->private = NULL; -} - -int lifebook_detect(struct psmouse *psmouse, bool set_properties) -{ - if (!lifebook_present) - return -1; - - if (desired_serio_phys && - strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys)) - return -1; - - if (set_properties) { - psmouse->vendor = "Fujitsu"; - psmouse->name = "Lifebook TouchScreen"; - } - - return 0; -} - -static int lifebook_create_relative_device(struct psmouse *psmouse) -{ - struct input_dev *dev2; - struct lifebook_data *priv; - int error = -ENOMEM; - - priv = kzalloc(sizeof(struct lifebook_data), GFP_KERNEL); - dev2 = input_allocate_device(); - if (!priv || !dev2) - goto err_out; - - priv->dev2 = dev2; - snprintf(priv->phys, sizeof(priv->phys), - "%s/input1", psmouse->ps2dev.serio->phys); - - dev2->phys = priv->phys; - dev2->name = "PS/2 Touchpad"; - dev2->id.bustype = BUS_I8042; - dev2->id.vendor = 0x0002; - dev2->id.product = PSMOUSE_LIFEBOOK; - dev2->id.version = 0x0000; - dev2->dev.parent = &psmouse->ps2dev.serio->dev; - - dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - dev2->keybit[BIT_WORD(BTN_LEFT)] = - BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); - - error = input_register_device(priv->dev2); - if (error) - goto err_out; - - psmouse->private = priv; - return 0; - - err_out: - input_free_device(dev2); - kfree(priv); - return error; -} - -int lifebook_init(struct psmouse *psmouse) -{ - struct input_dev *dev1 = psmouse->dev; - int max_coord = lifebook_use_6byte_proto ? 4096 : 1024; - - if (lifebook_absolute_mode(psmouse)) - return -1; - - dev1->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); - dev1->relbit[0] = 0; - dev1->keybit[BIT_WORD(BTN_MOUSE)] = 0; - dev1->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0); - input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0); - - if (!desired_serio_phys) { - if (lifebook_create_relative_device(psmouse)) { - lifebook_relative_mode(psmouse); - return -1; - } - } - - psmouse->protocol_handler = lifebook_process_byte; - psmouse->set_resolution = lifebook_set_resolution; - psmouse->disconnect = lifebook_disconnect; - psmouse->reconnect = lifebook_absolute_mode; - - psmouse->model = lifebook_use_6byte_proto ? 6 : 3; - - /* - * Use packet size = 3 even when using 6-byte protocol because - * that's what POLL will return on Lifebooks (according to spec). - */ - psmouse->pktsize = 3; - - return 0; -} - diff --git a/ANDROID_3.4.5/drivers/input/mouse/lifebook.h b/ANDROID_3.4.5/drivers/input/mouse/lifebook.h deleted file mode 100644 index 4c4326c6..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/lifebook.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Fujitsu B-series Lifebook PS/2 TouchScreen driver - * - * Copyright (c) 2005 Vojtech Pavlik - * - * 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. - */ - -#ifndef _LIFEBOOK_H -#define _LIFEBOOK_H - -#ifdef CONFIG_MOUSE_PS2_LIFEBOOK -void lifebook_module_init(void); -int lifebook_detect(struct psmouse *psmouse, bool set_properties); -int lifebook_init(struct psmouse *psmouse); -#else -inline void lifebook_module_init(void) -{ -} -inline int lifebook_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -inline int lifebook_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif - -#endif diff --git a/ANDROID_3.4.5/drivers/input/mouse/logibm.c b/ANDROID_3.4.5/drivers/input/mouse/logibm.c deleted file mode 100644 index e2413113..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/logibm.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 1999-2001 Vojtech Pavlik - * - * Based on the work of: - * James Banks Matthew Dillon - * David Giller Nathan Laredo - * Linus Torvalds Johan Myreen - * Cliff Matthews Philip Blundell - * Russell King - */ - -/* - * Logitech Bus Mouse Driver for Linux - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/input.h> -#include <linux/interrupt.h> - -#include <asm/io.h> -#include <asm/irq.h> - -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); -MODULE_DESCRIPTION("Logitech busmouse driver"); -MODULE_LICENSE("GPL"); - -#define LOGIBM_BASE 0x23c -#define LOGIBM_EXTENT 4 - -#define LOGIBM_DATA_PORT LOGIBM_BASE + 0 -#define LOGIBM_SIGNATURE_PORT LOGIBM_BASE + 1 -#define LOGIBM_CONTROL_PORT LOGIBM_BASE + 2 -#define LOGIBM_CONFIG_PORT LOGIBM_BASE + 3 - -#define LOGIBM_ENABLE_IRQ 0x00 -#define LOGIBM_DISABLE_IRQ 0x10 -#define LOGIBM_READ_X_LOW 0x80 -#define LOGIBM_READ_X_HIGH 0xa0 -#define LOGIBM_READ_Y_LOW 0xc0 -#define LOGIBM_READ_Y_HIGH 0xe0 - -#define LOGIBM_DEFAULT_MODE 0x90 -#define LOGIBM_CONFIG_BYTE 0x91 -#define LOGIBM_SIGNATURE_BYTE 0xa5 - -#define LOGIBM_IRQ 5 - -static int logibm_irq = LOGIBM_IRQ; -module_param_named(irq, logibm_irq, uint, 0); -MODULE_PARM_DESC(irq, "IRQ number (5=default)"); - -static struct input_dev *logibm_dev; - -static irqreturn_t logibm_interrupt(int irq, void *dev_id) -{ - char dx, dy; - unsigned char buttons; - - outb(LOGIBM_READ_X_LOW, LOGIBM_CONTROL_PORT); - dx = (inb(LOGIBM_DATA_PORT) & 0xf); - outb(LOGIBM_READ_X_HIGH, LOGIBM_CONTROL_PORT); - dx |= (inb(LOGIBM_DATA_PORT) & 0xf) << 4; - outb(LOGIBM_READ_Y_LOW, LOGIBM_CONTROL_PORT); - dy = (inb(LOGIBM_DATA_PORT) & 0xf); - outb(LOGIBM_READ_Y_HIGH, LOGIBM_CONTROL_PORT); - buttons = inb(LOGIBM_DATA_PORT); - dy |= (buttons & 0xf) << 4; - buttons = ~buttons >> 5; - - input_report_rel(logibm_dev, REL_X, dx); - input_report_rel(logibm_dev, REL_Y, dy); - input_report_key(logibm_dev, BTN_RIGHT, buttons & 1); - input_report_key(logibm_dev, BTN_MIDDLE, buttons & 2); - input_report_key(logibm_dev, BTN_LEFT, buttons & 4); - input_sync(logibm_dev); - - outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT); - return IRQ_HANDLED; -} - -static int logibm_open(struct input_dev *dev) -{ - if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) { - printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq); - return -EBUSY; - } - outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT); - return 0; -} - -static void logibm_close(struct input_dev *dev) -{ - outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); - free_irq(logibm_irq, NULL); -} - -static int __init logibm_init(void) -{ - int err; - - if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) { - printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE); - return -EBUSY; - } - - outb(LOGIBM_CONFIG_BYTE, LOGIBM_CONFIG_PORT); - outb(LOGIBM_SIGNATURE_BYTE, LOGIBM_SIGNATURE_PORT); - udelay(100); - - if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) { - printk(KERN_INFO "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE); - err = -ENODEV; - goto err_release_region; - } - - outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT); - outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); - - logibm_dev = input_allocate_device(); - if (!logibm_dev) { - printk(KERN_ERR "logibm.c: Not enough memory for input device\n"); - err = -ENOMEM; - goto err_release_region; - } - - logibm_dev->name = "Logitech bus mouse"; - logibm_dev->phys = "isa023c/input0"; - logibm_dev->id.bustype = BUS_ISA; - logibm_dev->id.vendor = 0x0003; - logibm_dev->id.product = 0x0001; - logibm_dev->id.version = 0x0100; - - logibm_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - logibm_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); - logibm_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - - logibm_dev->open = logibm_open; - logibm_dev->close = logibm_close; - - err = input_register_device(logibm_dev); - if (err) - goto err_free_dev; - - return 0; - - err_free_dev: - input_free_device(logibm_dev); - err_release_region: - release_region(LOGIBM_BASE, LOGIBM_EXTENT); - - return err; -} - -static void __exit logibm_exit(void) -{ - input_unregister_device(logibm_dev); - release_region(LOGIBM_BASE, LOGIBM_EXTENT); -} - -module_init(logibm_init); -module_exit(logibm_exit); diff --git a/ANDROID_3.4.5/drivers/input/mouse/logips2pp.c b/ANDROID_3.4.5/drivers/input/mouse/logips2pp.c deleted file mode 100644 index 84de2fc6..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/logips2pp.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Logitech PS/2++ mouse driver - * - * Copyright (c) 1999-2003 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2003 Eric Wong <eric@yhbt.net> - * - * 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. - */ - -#include <linux/input.h> -#include <linux/serio.h> -#include <linux/libps2.h> -#include "psmouse.h" -#include "logips2pp.h" - -/* Logitech mouse types */ -#define PS2PP_KIND_WHEEL 1 -#define PS2PP_KIND_MX 2 -#define PS2PP_KIND_TP3 3 -#define PS2PP_KIND_TRACKMAN 4 - -/* Logitech mouse features */ -#define PS2PP_WHEEL 0x01 -#define PS2PP_HWHEEL 0x02 -#define PS2PP_SIDE_BTN 0x04 -#define PS2PP_EXTRA_BTN 0x08 -#define PS2PP_TASK_BTN 0x10 -#define PS2PP_NAV_BTN 0x20 - -struct ps2pp_info { - u8 model; - u8 kind; - u16 features; -}; - -/* - * Process a PS2++ or PS2T++ packet. - */ - -static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - unsigned char *packet = psmouse->packet; - - if (psmouse->pktcnt < 3) - return PSMOUSE_GOOD_DATA; - -/* - * Full packet accumulated, process it - */ - - if ((packet[0] & 0x48) == 0x48 && (packet[1] & 0x02) == 0x02) { - - /* Logitech extended packet */ - switch ((packet[1] >> 4) | (packet[0] & 0x30)) { - - case 0x0d: /* Mouse extra info */ - - input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL, - (int) (packet[2] & 8) - (int) (packet[2] & 7)); - input_report_key(dev, BTN_SIDE, (packet[2] >> 4) & 1); - input_report_key(dev, BTN_EXTRA, (packet[2] >> 5) & 1); - - break; - - case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */ - - input_report_key(dev, BTN_SIDE, (packet[2]) & 1); - input_report_key(dev, BTN_EXTRA, (packet[2] >> 1) & 1); - input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1); - input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1); - input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1); - - break; - - case 0x0f: /* TouchPad extra info */ - - input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL, - (int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7)); - packet[0] = packet[2] | 0x08; - break; - - default: - psmouse_dbg(psmouse, - "Received PS2++ packet #%x, but don't know how to handle.\n", - (packet[1] >> 4) | (packet[0] & 0x30)); - break; - } - } else { - /* Standard PS/2 motion data */ - input_report_rel(dev, REL_X, packet[1] ? (int) packet[1] - (int) ((packet[0] << 4) & 0x100) : 0); - input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0); - } - - input_report_key(dev, BTN_LEFT, packet[0] & 1); - input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1); - input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1); - - input_sync(dev); - - return PSMOUSE_FULL_PACKET; - -} - -/* - * ps2pp_cmd() sends a PS2++ command, sliced into two bit - * pieces through the SETRES command. This is needed to send extended - * commands to mice on notebooks that try to understand the PS/2 protocol - * Ugly. - */ - -static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned char command) -{ - if (psmouse_sliced_command(psmouse, command)) - return -1; - - if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300)) - return -1; - - return 0; -} - -/* - * SmartScroll / CruiseControl for some newer Logitech mice Defaults to - * enabled if we do nothing to it. Of course I put this in because I want it - * disabled :P - * 1 - enabled (if previously disabled, also default) - * 0 - disabled - */ - -static void ps2pp_set_smartscroll(struct psmouse *psmouse, bool smartscroll) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - - ps2pp_cmd(psmouse, param, 0x32); - - param[0] = 0; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - - param[0] = smartscroll; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); -} - -static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, - void *data, char *buf) -{ - return sprintf(buf, "%d\n", psmouse->smartscroll); -} - -static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - unsigned int value; - int err; - - err = kstrtouint(buf, 10, &value); - if (err) - return err; - - if (value > 1) - return -EINVAL; - - ps2pp_set_smartscroll(psmouse, value); - psmouse->smartscroll = value; - return count; -} - -PSMOUSE_DEFINE_ATTR(smartscroll, S_IWUSR | S_IRUGO, NULL, - ps2pp_attr_show_smartscroll, ps2pp_attr_set_smartscroll); - -/* - * Support 800 dpi resolution _only_ if the user wants it (there are good - * reasons to not use it even if the mouse supports it, and of course there are - * also good reasons to use it, let the user decide). - */ - -static void ps2pp_set_resolution(struct psmouse *psmouse, unsigned int resolution) -{ - if (resolution > 400) { - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param = 3; - - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); - ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); - psmouse->resolution = 800; - } else - psmouse_set_resolution(psmouse, resolution); -} - -static void ps2pp_disconnect(struct psmouse *psmouse) -{ - device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr); -} - -static const struct ps2pp_info *get_model_info(unsigned char model) -{ - static const struct ps2pp_info ps2pp_list[] = { - { 1, 0, 0 }, /* Simple 2-button mouse */ - { 12, 0, PS2PP_SIDE_BTN}, - { 13, 0, 0 }, - { 15, PS2PP_KIND_MX, /* MX1000 */ - PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | - PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL }, - { 40, 0, PS2PP_SIDE_BTN }, - { 41, 0, PS2PP_SIDE_BTN }, - { 42, 0, PS2PP_SIDE_BTN }, - { 43, 0, PS2PP_SIDE_BTN }, - { 50, 0, 0 }, - { 51, 0, 0 }, - { 52, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, - { 53, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, - { 56, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, /* Cordless MouseMan Wheel */ - { 61, PS2PP_KIND_MX, /* MX700 */ - PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | - PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, - { 66, PS2PP_KIND_MX, /* MX3100 reciver */ - PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | - PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL }, - { 72, PS2PP_KIND_TRACKMAN, 0 }, /* T-CH11: TrackMan Marble */ - { 73, PS2PP_KIND_TRACKMAN, PS2PP_SIDE_BTN }, /* TrackMan FX */ - { 75, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, - { 76, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, - { 79, PS2PP_KIND_TRACKMAN, PS2PP_WHEEL }, /* TrackMan with wheel */ - { 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, - { 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, - { 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, - { 85, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, - { 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, - { 87, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, - { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, - { 96, 0, 0 }, - { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL }, - { 99, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, - { 100, PS2PP_KIND_MX, /* MX510 */ - PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | - PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, - { 111, PS2PP_KIND_MX, PS2PP_WHEEL | PS2PP_SIDE_BTN }, /* MX300 reports task button as side */ - { 112, PS2PP_KIND_MX, /* MX500 */ - PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | - PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, - { 114, PS2PP_KIND_MX, /* MX310 */ - PS2PP_WHEEL | PS2PP_SIDE_BTN | - PS2PP_TASK_BTN | PS2PP_EXTRA_BTN } - }; - int i; - - for (i = 0; i < ARRAY_SIZE(ps2pp_list); i++) - if (model == ps2pp_list[i].model) - return &ps2pp_list[i]; - - return NULL; -} - -/* - * Set up input device's properties based on the detected mouse model. - */ - -static void ps2pp_set_model_properties(struct psmouse *psmouse, - const struct ps2pp_info *model_info, - bool using_ps2pp) -{ - struct input_dev *input_dev = psmouse->dev; - - if (model_info->features & PS2PP_SIDE_BTN) - __set_bit(BTN_SIDE, input_dev->keybit); - - if (model_info->features & PS2PP_EXTRA_BTN) - __set_bit(BTN_EXTRA, input_dev->keybit); - - if (model_info->features & PS2PP_TASK_BTN) - __set_bit(BTN_TASK, input_dev->keybit); - - if (model_info->features & PS2PP_NAV_BTN) { - __set_bit(BTN_FORWARD, input_dev->keybit); - __set_bit(BTN_BACK, input_dev->keybit); - } - - if (model_info->features & PS2PP_WHEEL) - __set_bit(REL_WHEEL, input_dev->relbit); - - if (model_info->features & PS2PP_HWHEEL) - __set_bit(REL_HWHEEL, input_dev->relbit); - - switch (model_info->kind) { - - case PS2PP_KIND_WHEEL: - psmouse->name = "Wheel Mouse"; - break; - - case PS2PP_KIND_MX: - psmouse->name = "MX Mouse"; - break; - - case PS2PP_KIND_TP3: - psmouse->name = "TouchPad 3"; - break; - - case PS2PP_KIND_TRACKMAN: - psmouse->name = "TrackMan"; - break; - - default: - /* - * Set name to "Mouse" only when using PS2++, - * otherwise let other protocols define suitable - * name - */ - if (using_ps2pp) - psmouse->name = "Mouse"; - break; - } -} - - -/* - * Logitech magic init. Detect whether the mouse is a Logitech one - * and its exact model and try turning on extended protocol for ones - * that support it. - */ - -int ps2pp_init(struct psmouse *psmouse, bool set_properties) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - unsigned char model, buttons; - const struct ps2pp_info *model_info; - bool use_ps2pp = false; - int error; - - param[0] = 0; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); - param[1] = 0; - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); - - model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78); - buttons = param[1]; - - if (!model || !buttons) - return -1; - - model_info = get_model_info(model); - if (model_info) { - -/* - * Do Logitech PS2++ / PS2T++ magic init. - */ - if (model_info->kind == PS2PP_KIND_TP3) { /* Touch Pad 3 */ - - /* Unprotect RAM */ - param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; - ps2_command(ps2dev, param, 0x30d1); - /* Enable features */ - param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; - ps2_command(ps2dev, param, 0x30d1); - /* Enable PS2++ */ - param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; - ps2_command(ps2dev, param, 0x30d1); - - param[0] = 0; - if (!ps2_command(ps2dev, param, 0x13d1) && - param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { - use_ps2pp = true; - } - - } else { - - param[0] = param[1] = param[2] = 0; - ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */ - ps2pp_cmd(psmouse, param, 0xDB); - - if ((param[0] & 0x78) == 0x48 && - (param[1] & 0xf3) == 0xc2 && - (param[2] & 0x03) == ((param[1] >> 2) & 3)) { - ps2pp_set_smartscroll(psmouse, false); - use_ps2pp = true; - } - } - - } else { - psmouse_warn(psmouse, "Detected unknown Logitech mouse model %d\n", model); - } - - if (set_properties) { - psmouse->vendor = "Logitech"; - psmouse->model = model; - - if (use_ps2pp) { - psmouse->protocol_handler = ps2pp_process_byte; - psmouse->pktsize = 3; - - if (model_info->kind != PS2PP_KIND_TP3) { - psmouse->set_resolution = ps2pp_set_resolution; - psmouse->disconnect = ps2pp_disconnect; - - error = device_create_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_smartscroll.dattr); - if (error) { - psmouse_err(psmouse, - "failed to create smartscroll sysfs attribute, error: %d\n", - error); - return -1; - } - } - } - - if (buttons >= 3) - __set_bit(BTN_MIDDLE, psmouse->dev->keybit); - - if (model_info) - ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); - } - - return use_ps2pp ? 0 : -1; -} - diff --git a/ANDROID_3.4.5/drivers/input/mouse/logips2pp.h b/ANDROID_3.4.5/drivers/input/mouse/logips2pp.h deleted file mode 100644 index 0c186f02..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/logips2pp.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Logitech PS/2++ mouse driver header - * - * Copyright (c) 2003 Vojtech Pavlik <vojtech@suse.cz> - * - * 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. - */ - -#ifndef _LOGIPS2PP_H -#define _LOGIPS2PP_H - -#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP -int ps2pp_init(struct psmouse *psmouse, bool set_properties); -#else -inline int ps2pp_init(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_LOGIPS2PP */ - -#endif diff --git a/ANDROID_3.4.5/drivers/input/mouse/maplemouse.c b/ANDROID_3.4.5/drivers/input/mouse/maplemouse.c deleted file mode 100644 index 5f278176..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/maplemouse.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * SEGA Dreamcast mouse driver - * Based on drivers/usb/usbmouse.c - * - * Copyright (c) Yaegashi Takeshi, 2001 - * Copyright (c) Adrian McMenamin, 2008 - 2009 - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/input.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/timer.h> -#include <linux/maple.h> - -MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>"); -MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); -MODULE_LICENSE("GPL"); - -struct dc_mouse { - struct input_dev *dev; - struct maple_device *mdev; -}; - -static void dc_mouse_callback(struct mapleq *mq) -{ - int buttons, relx, rely, relz; - struct maple_device *mapledev = mq->dev; - struct dc_mouse *mse = maple_get_drvdata(mapledev); - struct input_dev *dev = mse->dev; - unsigned char *res = mq->recvbuf->buf; - - buttons = ~res[8]; - relx = *(unsigned short *)(res + 12) - 512; - rely = *(unsigned short *)(res + 14) - 512; - relz = *(unsigned short *)(res + 16) - 512; - - input_report_key(dev, BTN_LEFT, buttons & 4); - input_report_key(dev, BTN_MIDDLE, buttons & 9); - input_report_key(dev, BTN_RIGHT, buttons & 2); - input_report_rel(dev, REL_X, relx); - input_report_rel(dev, REL_Y, rely); - input_report_rel(dev, REL_WHEEL, relz); - input_sync(dev); -} - -static int dc_mouse_open(struct input_dev *dev) -{ - struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev)); - - maple_getcond_callback(mse->mdev, dc_mouse_callback, HZ/50, - MAPLE_FUNC_MOUSE); - - return 0; -} - -static void dc_mouse_close(struct input_dev *dev) -{ - struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev)); - - maple_getcond_callback(mse->mdev, dc_mouse_callback, 0, - MAPLE_FUNC_MOUSE); -} - -/* allow the mouse to be used */ -static int __devinit probe_maple_mouse(struct device *dev) -{ - struct maple_device *mdev = to_maple_dev(dev); - struct maple_driver *mdrv = to_maple_driver(dev->driver); - int error; - struct input_dev *input_dev; - struct dc_mouse *mse; - - mse = kzalloc(sizeof(struct dc_mouse), GFP_KERNEL); - if (!mse) { - error = -ENOMEM; - goto fail; - } - - input_dev = input_allocate_device(); - if (!input_dev) { - error = -ENOMEM; - goto fail_nomem; - } - - mse->dev = input_dev; - mse->mdev = mdev; - - input_set_drvdata(input_dev, mse); - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); - input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | - BIT_MASK(REL_WHEEL); - input_dev->open = dc_mouse_open; - input_dev->close = dc_mouse_close; - input_dev->name = mdev->product_name; - input_dev->id.bustype = BUS_HOST; - error = input_register_device(input_dev); - if (error) - goto fail_register; - - mdev->driver = mdrv; - maple_set_drvdata(mdev, mse); - - return error; - -fail_register: - input_free_device(input_dev); -fail_nomem: - kfree(mse); -fail: - return error; -} - -static int __devexit remove_maple_mouse(struct device *dev) -{ - struct maple_device *mdev = to_maple_dev(dev); - struct dc_mouse *mse = maple_get_drvdata(mdev); - - mdev->callback = NULL; - input_unregister_device(mse->dev); - maple_set_drvdata(mdev, NULL); - kfree(mse); - - return 0; -} - -static struct maple_driver dc_mouse_driver = { - .function = MAPLE_FUNC_MOUSE, - .drv = { - .name = "Dreamcast_mouse", - .probe = probe_maple_mouse, - .remove = __devexit_p(remove_maple_mouse), - }, -}; - -static int __init dc_mouse_init(void) -{ - return maple_driver_register(&dc_mouse_driver); -} - -static void __exit dc_mouse_exit(void) -{ - maple_driver_unregister(&dc_mouse_driver); -} - -module_init(dc_mouse_init); -module_exit(dc_mouse_exit); diff --git a/ANDROID_3.4.5/drivers/input/mouse/pc110pad.c b/ANDROID_3.4.5/drivers/input/mouse/pc110pad.c deleted file mode 100644 index 7b02b652..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/pc110pad.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2000-2001 Vojtech Pavlik - * - * Based on the work of: - * Alan Cox Robin O'Leary - */ - -/* - * IBM PC110 touchpad driver for Linux - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/input.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/delay.h> - -#include <asm/io.h> -#include <asm/irq.h> - -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); -MODULE_DESCRIPTION("IBM PC110 touchpad driver"); -MODULE_LICENSE("GPL"); - -#define PC110PAD_OFF 0x30 -#define PC110PAD_ON 0x38 - -static int pc110pad_irq = 10; -static int pc110pad_io = 0x15e0; - -static struct input_dev *pc110pad_dev; -static int pc110pad_data[3]; -static int pc110pad_count; - -static irqreturn_t pc110pad_interrupt(int irq, void *ptr) -{ - int value = inb_p(pc110pad_io); - int handshake = inb_p(pc110pad_io + 2); - - outb(handshake | 1, pc110pad_io + 2); - udelay(2); - outb(handshake & ~1, pc110pad_io + 2); - udelay(2); - inb_p(0x64); - - pc110pad_data[pc110pad_count++] = value; - - if (pc110pad_count < 3) - return IRQ_HANDLED; - - input_report_key(pc110pad_dev, BTN_TOUCH, - pc110pad_data[0] & 0x01); - input_report_abs(pc110pad_dev, ABS_X, - pc110pad_data[1] | ((pc110pad_data[0] << 3) & 0x80) | ((pc110pad_data[0] << 1) & 0x100)); - input_report_abs(pc110pad_dev, ABS_Y, - pc110pad_data[2] | ((pc110pad_data[0] << 4) & 0x80)); - input_sync(pc110pad_dev); - - pc110pad_count = 0; - return IRQ_HANDLED; -} - -static void pc110pad_close(struct input_dev *dev) -{ - outb(PC110PAD_OFF, pc110pad_io + 2); -} - -static int pc110pad_open(struct input_dev *dev) -{ - pc110pad_interrupt(0, NULL); - pc110pad_interrupt(0, NULL); - pc110pad_interrupt(0, NULL); - outb(PC110PAD_ON, pc110pad_io + 2); - pc110pad_count = 0; - - return 0; -} - -/* - * We try to avoid enabling the hardware if it's not - * there, but we don't know how to test. But we do know - * that the PC110 is not a PCI system. So if we find any - * PCI devices in the machine, we don't have a PC110. - */ -static int __init pc110pad_init(void) -{ - int err; - - if (!no_pci_devices()) - return -ENODEV; - - if (!request_region(pc110pad_io, 4, "pc110pad")) { - printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", - pc110pad_io, pc110pad_io + 4); - return -EBUSY; - } - - outb(PC110PAD_OFF, pc110pad_io + 2); - - if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) { - printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq); - err = -EBUSY; - goto err_release_region; - } - - pc110pad_dev = input_allocate_device(); - if (!pc110pad_dev) { - printk(KERN_ERR "pc110pad: Not enough memory.\n"); - err = -ENOMEM; - goto err_free_irq; - } - - pc110pad_dev->name = "IBM PC110 TouchPad"; - pc110pad_dev->phys = "isa15e0/input0"; - pc110pad_dev->id.bustype = BUS_ISA; - pc110pad_dev->id.vendor = 0x0003; - pc110pad_dev->id.product = 0x0001; - pc110pad_dev->id.version = 0x0100; - - pc110pad_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - pc110pad_dev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y); - pc110pad_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - - input_abs_set_max(pc110pad_dev, ABS_X, 0x1ff); - input_abs_set_max(pc110pad_dev, ABS_Y, 0x0ff); - - pc110pad_dev->open = pc110pad_open; - pc110pad_dev->close = pc110pad_close; - - err = input_register_device(pc110pad_dev); - if (err) - goto err_free_dev; - - return 0; - - err_free_dev: - input_free_device(pc110pad_dev); - err_free_irq: - free_irq(pc110pad_irq, NULL); - err_release_region: - release_region(pc110pad_io, 4); - - return err; -} - -static void __exit pc110pad_exit(void) -{ - outb(PC110PAD_OFF, pc110pad_io + 2); - free_irq(pc110pad_irq, NULL); - input_unregister_device(pc110pad_dev); - release_region(pc110pad_io, 4); -} - -module_init(pc110pad_init); -module_exit(pc110pad_exit); diff --git a/ANDROID_3.4.5/drivers/input/mouse/psmouse-base.c b/ANDROID_3.4.5/drivers/input/mouse/psmouse-base.c deleted file mode 100644 index 22fe2547..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/psmouse-base.c +++ /dev/null @@ -1,1817 +0,0 @@ -/* - * PS/2 mouse driver - * - * Copyright (c) 1999-2002 Vojtech Pavlik - * Copyright (c) 2003-2004 Dmitry Torokhov - */ - -/* - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define psmouse_fmt(fmt) fmt - -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/input.h> -#include <linux/serio.h> -#include <linux/init.h> -#include <linux/libps2.h> -#include <linux/mutex.h> - -#include "psmouse.h" -#include "synaptics.h" -#include "logips2pp.h" -#include "alps.h" -#include "hgpk.h" -#include "lifebook.h" -#include "trackpoint.h" -#include "touchkit_ps2.h" -#include "elantech.h" -#include "sentelic.h" - -#define DRIVER_DESC "PS/2 mouse driver" - -MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -static unsigned int psmouse_max_proto = PSMOUSE_AUTO; -static int psmouse_set_maxproto(const char *val, const struct kernel_param *); -static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp); -static struct kernel_param_ops param_ops_proto_abbrev = { - .set = psmouse_set_maxproto, - .get = psmouse_get_maxproto, -}; -#define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) -module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644); -MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches."); - -static unsigned int psmouse_resolution = 200; -module_param_named(resolution, psmouse_resolution, uint, 0644); -MODULE_PARM_DESC(resolution, "Resolution, in dpi."); - -static unsigned int psmouse_rate = 100; -module_param_named(rate, psmouse_rate, uint, 0644); -MODULE_PARM_DESC(rate, "Report rate, in reports per second."); - -static bool psmouse_smartscroll = 1; -module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); -MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); - -static unsigned int psmouse_resetafter = 5; -module_param_named(resetafter, psmouse_resetafter, uint, 0644); -MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); - -static unsigned int psmouse_resync_time; -module_param_named(resync_time, psmouse_resync_time, uint, 0644); -MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never)."); - -PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, - NULL, - psmouse_attr_show_protocol, psmouse_attr_set_protocol); -PSMOUSE_DEFINE_ATTR(rate, S_IWUSR | S_IRUGO, - (void *) offsetof(struct psmouse, rate), - psmouse_show_int_attr, psmouse_attr_set_rate); -PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO, - (void *) offsetof(struct psmouse, resolution), - psmouse_show_int_attr, psmouse_attr_set_resolution); -PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, - (void *) offsetof(struct psmouse, resetafter), - psmouse_show_int_attr, psmouse_set_int_attr); -PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO, - (void *) offsetof(struct psmouse, resync_time), - psmouse_show_int_attr, psmouse_set_int_attr); - -static struct attribute *psmouse_attributes[] = { - &psmouse_attr_protocol.dattr.attr, - &psmouse_attr_rate.dattr.attr, - &psmouse_attr_resolution.dattr.attr, - &psmouse_attr_resetafter.dattr.attr, - &psmouse_attr_resync_time.dattr.attr, - NULL -}; - -static struct attribute_group psmouse_attribute_group = { - .attrs = psmouse_attributes, -}; - -/* - * psmouse_mutex protects all operations changing state of mouse - * (connecting, disconnecting, changing rate or resolution via - * sysfs). We could use a per-device semaphore but since there - * rarely more than one PS/2 mouse connected and since semaphore - * is taken in "slow" paths it is not worth it. - */ -static DEFINE_MUTEX(psmouse_mutex); - -static struct workqueue_struct *kpsmoused_wq; - -struct psmouse_protocol { - enum psmouse_type type; - bool maxproto; - bool ignore_parity; /* Protocol should ignore parity errors from KBC */ - const char *name; - const char *alias; - int (*detect)(struct psmouse *, bool); - int (*init)(struct psmouse *); -}; - -/* - * psmouse_process_byte() analyzes the PS/2 data stream and reports - * relevant events to the input module once full packet has arrived. - */ - -psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - unsigned char *packet = psmouse->packet; - - if (psmouse->pktcnt < psmouse->pktsize) - return PSMOUSE_GOOD_DATA; - -/* - * Full packet accumulated, process it - */ - -/* - * Scroll wheel on IntelliMice, scroll buttons on NetMice - */ - - if (psmouse->type == PSMOUSE_IMPS || psmouse->type == PSMOUSE_GENPS) - input_report_rel(dev, REL_WHEEL, -(signed char) packet[3]); - -/* - * Scroll wheel and buttons on IntelliMouse Explorer - */ - - if (psmouse->type == PSMOUSE_IMEX) { - switch (packet[3] & 0xC0) { - case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */ - input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); - break; - case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */ - input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); - break; - case 0x00: - case 0xC0: - input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); - input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); - input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); - break; - } - } - -/* - * Extra buttons on Genius NewNet 3D - */ - - if (psmouse->type == PSMOUSE_GENPS) { - input_report_key(dev, BTN_SIDE, (packet[0] >> 6) & 1); - input_report_key(dev, BTN_EXTRA, (packet[0] >> 7) & 1); - } - -/* - * Extra button on ThinkingMouse - */ - if (psmouse->type == PSMOUSE_THINKPS) { - input_report_key(dev, BTN_EXTRA, (packet[0] >> 3) & 1); - /* Without this bit of weirdness moving up gives wildly high Y changes. */ - packet[1] |= (packet[0] & 0x40) << 1; - } - -/* - * Cortron PS2 Trackball reports SIDE button on the 4th bit of the first - * byte. - */ - if (psmouse->type == PSMOUSE_CORTRON) { - input_report_key(dev, BTN_SIDE, (packet[0] >> 3) & 1); - packet[0] |= 0x08; - } - -/* - * Generic PS/2 Mouse - */ - - input_report_key(dev, BTN_LEFT, packet[0] & 1); - input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1); - input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1); - - input_report_rel(dev, REL_X, packet[1] ? (int) packet[1] - (int) ((packet[0] << 4) & 0x100) : 0); - input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0); - - input_sync(dev); - - return PSMOUSE_FULL_PACKET; -} - -void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, - unsigned long delay) -{ - queue_delayed_work(kpsmoused_wq, work, delay); -} - -/* - * __psmouse_set_state() sets new psmouse state and resets all flags. - */ - -static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) -{ - psmouse->state = new_state; - psmouse->pktcnt = psmouse->out_of_sync_cnt = 0; - psmouse->ps2dev.flags = 0; - psmouse->last = jiffies; -} - - -/* - * psmouse_set_state() sets new psmouse state and resets all flags and - * counters while holding serio lock so fighting with interrupt handler - * is not a concern. - */ - -void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) -{ - serio_pause_rx(psmouse->ps2dev.serio); - __psmouse_set_state(psmouse, new_state); - serio_continue_rx(psmouse->ps2dev.serio); -} - -/* - * psmouse_handle_byte() processes one byte of the input data stream - * by calling corresponding protocol handler. - */ - -static int psmouse_handle_byte(struct psmouse *psmouse) -{ - psmouse_ret_t rc = psmouse->protocol_handler(psmouse); - - switch (rc) { - case PSMOUSE_BAD_DATA: - if (psmouse->state == PSMOUSE_ACTIVATED) { - psmouse_warn(psmouse, - "%s at %s lost sync at byte %d\n", - psmouse->name, psmouse->phys, - psmouse->pktcnt); - if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { - __psmouse_set_state(psmouse, PSMOUSE_IGNORE); - psmouse_notice(psmouse, - "issuing reconnect request\n"); - serio_reconnect(psmouse->ps2dev.serio); - return -1; - } - } - psmouse->pktcnt = 0; - break; - - case PSMOUSE_FULL_PACKET: - psmouse->pktcnt = 0; - if (psmouse->out_of_sync_cnt) { - psmouse->out_of_sync_cnt = 0; - psmouse_notice(psmouse, - "%s at %s - driver resynced.\n", - psmouse->name, psmouse->phys); - } - break; - - case PSMOUSE_GOOD_DATA: - break; - } - return 0; -} - -/* - * psmouse_interrupt() handles incoming characters, either passing them - * for normal processing or gathering them as command response. - */ - -static irqreturn_t psmouse_interrupt(struct serio *serio, - unsigned char data, unsigned int flags) -{ - struct psmouse *psmouse = serio_get_drvdata(serio); - - if (psmouse->state == PSMOUSE_IGNORE) - goto out; - - if (unlikely((flags & SERIO_TIMEOUT) || - ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { - - if (psmouse->state == PSMOUSE_ACTIVATED) - psmouse_warn(psmouse, - "bad data from KBC -%s%s\n", - flags & SERIO_TIMEOUT ? " timeout" : "", - flags & SERIO_PARITY ? " bad parity" : ""); - ps2_cmd_aborted(&psmouse->ps2dev); - goto out; - } - - if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_ACK)) - if (ps2_handle_ack(&psmouse->ps2dev, data)) - goto out; - - if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_CMD)) - if (ps2_handle_response(&psmouse->ps2dev, data)) - goto out; - - if (psmouse->state <= PSMOUSE_RESYNCING) - goto out; - - if (psmouse->state == PSMOUSE_ACTIVATED && - psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { - psmouse_info(psmouse, "%s at %s lost synchronization, throwing %d bytes away.\n", - psmouse->name, psmouse->phys, psmouse->pktcnt); - psmouse->badbyte = psmouse->packet[0]; - __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); - psmouse_queue_work(psmouse, &psmouse->resync_work, 0); - goto out; - } - - psmouse->packet[psmouse->pktcnt++] = data; -/* - * Check if this is a new device announcement (0xAA 0x00) - */ - if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { - if (psmouse->pktcnt == 1) { - psmouse->last = jiffies; - goto out; - } - - if (psmouse->packet[1] == PSMOUSE_RET_ID || - (psmouse->type == PSMOUSE_HGPK && - psmouse->packet[1] == PSMOUSE_RET_BAT)) { - __psmouse_set_state(psmouse, PSMOUSE_IGNORE); - serio_reconnect(serio); - goto out; - } -/* - * Not a new device, try processing first byte normally - */ - psmouse->pktcnt = 1; - if (psmouse_handle_byte(psmouse)) - goto out; - - psmouse->packet[psmouse->pktcnt++] = data; - } - -/* - * See if we need to force resync because mouse was idle for too long - */ - if (psmouse->state == PSMOUSE_ACTIVATED && - psmouse->pktcnt == 1 && psmouse->resync_time && - time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { - psmouse->badbyte = psmouse->packet[0]; - __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); - psmouse_queue_work(psmouse, &psmouse->resync_work, 0); - goto out; - } - - psmouse->last = jiffies; - psmouse_handle_byte(psmouse); - - out: - return IRQ_HANDLED; -} - - -/* - * psmouse_sliced_command() sends an extended PS/2 command to the mouse - * using sliced syntax, understood by advanced devices, such as Logitech - * or Synaptics touchpads. The command is encoded as: - * 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu - * is the command. - */ -int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command) -{ - int i; - - if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) - return -1; - - for (i = 6; i >= 0; i -= 2) { - unsigned char d = (command >> i) & 3; - if (ps2_command(&psmouse->ps2dev, &d, PSMOUSE_CMD_SETRES)) - return -1; - } - - return 0; -} - - -/* - * psmouse_reset() resets the mouse into power-on state. - */ -int psmouse_reset(struct psmouse *psmouse) -{ - unsigned char param[2]; - - if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_RESET_BAT)) - return -1; - - if (param[0] != PSMOUSE_RET_BAT && param[1] != PSMOUSE_RET_ID) - return -1; - - return 0; -} - -/* - * Here we set the mouse resolution. - */ - -void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution) -{ - static const unsigned char params[] = { 0, 1, 2, 2, 3 }; - unsigned char p; - - if (resolution == 0 || resolution > 200) - resolution = 200; - - p = params[resolution / 50]; - ps2_command(&psmouse->ps2dev, &p, PSMOUSE_CMD_SETRES); - psmouse->resolution = 25 << p; -} - -/* - * Here we set the mouse report rate. - */ - -static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate) -{ - static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 }; - unsigned char r; - int i = 0; - - while (rates[i] > rate) i++; - r = rates[i]; - ps2_command(&psmouse->ps2dev, &r, PSMOUSE_CMD_SETRATE); - psmouse->rate = r; -} - -/* - * psmouse_poll() - default poll handler. Everyone except for ALPS uses it. - */ - -static int psmouse_poll(struct psmouse *psmouse) -{ - return ps2_command(&psmouse->ps2dev, psmouse->packet, - PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); -} - - -/* - * Genius NetMouse magic init. - */ -static int genius_detect(struct psmouse *psmouse, bool set_properties) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - - param[0] = 3; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); - - if (param[0] != 0x00 || param[1] != 0x33 || param[2] != 0x55) - return -1; - - if (set_properties) { - __set_bit(BTN_MIDDLE, psmouse->dev->keybit); - __set_bit(BTN_EXTRA, psmouse->dev->keybit); - __set_bit(BTN_SIDE, psmouse->dev->keybit); - __set_bit(REL_WHEEL, psmouse->dev->relbit); - - psmouse->vendor = "Genius"; - psmouse->name = "Mouse"; - psmouse->pktsize = 4; - } - - return 0; -} - -/* - * IntelliMouse magic init. - */ -static int intellimouse_detect(struct psmouse *psmouse, bool set_properties) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[2]; - - param[0] = 200; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - param[0] = 100; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - param[0] = 80; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); - - if (param[0] != 3) - return -1; - - if (set_properties) { - __set_bit(BTN_MIDDLE, psmouse->dev->keybit); - __set_bit(REL_WHEEL, psmouse->dev->relbit); - - if (!psmouse->vendor) - psmouse->vendor = "Generic"; - if (!psmouse->name) - psmouse->name = "Wheel Mouse"; - psmouse->pktsize = 4; - } - - return 0; -} - -/* - * Try IntelliMouse/Explorer magic init. - */ -static int im_explorer_detect(struct psmouse *psmouse, bool set_properties) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[2]; - - intellimouse_detect(psmouse, 0); - - param[0] = 200; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - param[0] = 200; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - param[0] = 80; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); - - if (param[0] != 4) - return -1; - -/* Magic to enable horizontal scrolling on IntelliMouse 4.0 */ - param[0] = 200; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - param[0] = 80; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - param[0] = 40; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - - if (set_properties) { - __set_bit(BTN_MIDDLE, psmouse->dev->keybit); - __set_bit(REL_WHEEL, psmouse->dev->relbit); - __set_bit(REL_HWHEEL, psmouse->dev->relbit); - __set_bit(BTN_SIDE, psmouse->dev->keybit); - __set_bit(BTN_EXTRA, psmouse->dev->keybit); - - if (!psmouse->vendor) - psmouse->vendor = "Generic"; - if (!psmouse->name) - psmouse->name = "Explorer Mouse"; - psmouse->pktsize = 4; - } - - return 0; -} - -/* - * Kensington ThinkingMouse / ExpertMouse magic init. - */ -static int thinking_detect(struct psmouse *psmouse, bool set_properties) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[2]; - static const unsigned char seq[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 }; - int i; - - param[0] = 10; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - param[0] = 0; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - for (i = 0; i < ARRAY_SIZE(seq); i++) { - param[0] = seq[i]; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - } - ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); - - if (param[0] != 2) - return -1; - - if (set_properties) { - __set_bit(BTN_MIDDLE, psmouse->dev->keybit); - __set_bit(BTN_EXTRA, psmouse->dev->keybit); - - psmouse->vendor = "Kensington"; - psmouse->name = "ThinkingMouse"; - } - - return 0; -} - -/* - * Bare PS/2 protocol "detection". Always succeeds. - */ -static int ps2bare_detect(struct psmouse *psmouse, bool set_properties) -{ - if (set_properties) { - if (!psmouse->vendor) - psmouse->vendor = "Generic"; - if (!psmouse->name) - psmouse->name = "Mouse"; - -/* - * We have no way of figuring true number of buttons so let's - * assume that the device has 3. - */ - __set_bit(BTN_MIDDLE, psmouse->dev->keybit); - } - - return 0; -} - -/* - * Cortron PS/2 protocol detection. There's no special way to detect it, so it - * must be forced by sysfs protocol writing. - */ -static int cortron_detect(struct psmouse *psmouse, bool set_properties) -{ - if (set_properties) { - psmouse->vendor = "Cortron"; - psmouse->name = "PS/2 Trackball"; - - __set_bit(BTN_MIDDLE, psmouse->dev->keybit); - __set_bit(BTN_SIDE, psmouse->dev->keybit); - } - - return 0; -} - -/* - * Apply default settings to the psmouse structure. Most of them will - * be overridden by individual protocol initialization routines. - */ - -static void psmouse_apply_defaults(struct psmouse *psmouse) -{ - struct input_dev *input_dev = psmouse->dev; - - memset(input_dev->evbit, 0, sizeof(input_dev->evbit)); - memset(input_dev->keybit, 0, sizeof(input_dev->keybit)); - memset(input_dev->relbit, 0, sizeof(input_dev->relbit)); - memset(input_dev->absbit, 0, sizeof(input_dev->absbit)); - memset(input_dev->mscbit, 0, sizeof(input_dev->mscbit)); - - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(EV_REL, input_dev->evbit); - - __set_bit(BTN_LEFT, input_dev->keybit); - __set_bit(BTN_RIGHT, input_dev->keybit); - - __set_bit(REL_X, input_dev->relbit); - __set_bit(REL_Y, input_dev->relbit); - - psmouse->set_rate = psmouse_set_rate; - psmouse->set_resolution = psmouse_set_resolution; - psmouse->poll = psmouse_poll; - psmouse->protocol_handler = psmouse_process_byte; - psmouse->pktsize = 3; - psmouse->reconnect = NULL; - psmouse->disconnect = NULL; - psmouse->cleanup = NULL; - psmouse->pt_activate = NULL; - psmouse->pt_deactivate = NULL; -} - -/* - * Apply default settings to the psmouse structure and call specified - * protocol detection or initialization routine. - */ -static int psmouse_do_detect(int (*detect)(struct psmouse *psmouse, - bool set_properties), - struct psmouse *psmouse, bool set_properties) -{ - if (set_properties) - psmouse_apply_defaults(psmouse); - - return detect(psmouse, set_properties); -} - -/* - * psmouse_extensions() probes for any extensions to the basic PS/2 protocol - * the mouse may have. - */ - -static int psmouse_extensions(struct psmouse *psmouse, - unsigned int max_proto, bool set_properties) -{ - bool synaptics_hardware = false; - -/* - * We always check for lifebook because it does not disturb mouse - * (it only checks DMI information). - */ - if (psmouse_do_detect(lifebook_detect, psmouse, set_properties) == 0) { - if (max_proto > PSMOUSE_IMEX) { - if (!set_properties || lifebook_init(psmouse) == 0) - return PSMOUSE_LIFEBOOK; - } - } - -/* - * Try Kensington ThinkingMouse (we try first, because synaptics probe - * upsets the thinkingmouse). - */ - - if (max_proto > PSMOUSE_IMEX && - psmouse_do_detect(thinking_detect, psmouse, set_properties) == 0) { - return PSMOUSE_THINKPS; - } - -/* - * Try Synaptics TouchPad. Note that probing is done even if Synaptics protocol - * support is disabled in config - we need to know if it is synaptics so we - * can reset it properly after probing for intellimouse. - */ - if (max_proto > PSMOUSE_PS2 && - psmouse_do_detect(synaptics_detect, psmouse, set_properties) == 0) { - synaptics_hardware = true; - - if (max_proto > PSMOUSE_IMEX) { -/* - * Try activating protocol, but check if support is enabled first, since - * we try detecting Synaptics even when protocol is disabled. - */ - if (synaptics_supported() && - (!set_properties || synaptics_init(psmouse) == 0)) { - return PSMOUSE_SYNAPTICS; - } - -/* - * Some Synaptics touchpads can emulate extended protocols (like IMPS/2). - * Unfortunately Logitech/Genius probes confuse some firmware versions so - * we'll have to skip them. - */ - max_proto = PSMOUSE_IMEX; - } -/* - * Make sure that touchpad is in relative mode, gestures (taps) are enabled - */ - synaptics_reset(psmouse); - } - -/* - * Try ALPS TouchPad - */ - if (max_proto > PSMOUSE_IMEX) { - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); - if (psmouse_do_detect(alps_detect, - psmouse, set_properties) == 0) { - if (!set_properties || alps_init(psmouse) == 0) - return PSMOUSE_ALPS; -/* - * Init failed, try basic relative protocols - */ - max_proto = PSMOUSE_IMEX; - } - } - -/* - * Try OLPC HGPK touchpad. - */ - if (max_proto > PSMOUSE_IMEX && - psmouse_do_detect(hgpk_detect, psmouse, set_properties) == 0) { - if (!set_properties || hgpk_init(psmouse) == 0) - return PSMOUSE_HGPK; -/* - * Init failed, try basic relative protocols - */ - max_proto = PSMOUSE_IMEX; - } - -/* - * Try Elantech touchpad. - */ - if (max_proto > PSMOUSE_IMEX && - psmouse_do_detect(elantech_detect, psmouse, set_properties) == 0) { - if (!set_properties || elantech_init(psmouse) == 0) - return PSMOUSE_ELANTECH; -/* - * Init failed, try basic relative protocols - */ - max_proto = PSMOUSE_IMEX; - } - - if (max_proto > PSMOUSE_IMEX) { - if (psmouse_do_detect(genius_detect, - psmouse, set_properties) == 0) - return PSMOUSE_GENPS; - - if (psmouse_do_detect(ps2pp_init, - psmouse, set_properties) == 0) - return PSMOUSE_PS2PP; - - if (psmouse_do_detect(trackpoint_detect, - psmouse, set_properties) == 0) - return PSMOUSE_TRACKPOINT; - - if (psmouse_do_detect(touchkit_ps2_detect, - psmouse, set_properties) == 0) - return PSMOUSE_TOUCHKIT_PS2; - } - -/* - * Try Finger Sensing Pad. We do it here because its probe upsets - * Trackpoint devices (causing TP_READ_ID command to time out). - */ - if (max_proto > PSMOUSE_IMEX) { - if (psmouse_do_detect(fsp_detect, - psmouse, set_properties) == 0) { - if (!set_properties || fsp_init(psmouse) == 0) - return PSMOUSE_FSP; -/* - * Init failed, try basic relative protocols - */ - max_proto = PSMOUSE_IMEX; - } - } - -/* - * Reset to defaults in case the device got confused by extended - * protocol probes. Note that we follow up with full reset because - * some mice put themselves to sleep when they see PSMOUSE_RESET_DIS. - */ - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); - psmouse_reset(psmouse); - - if (max_proto >= PSMOUSE_IMEX && - psmouse_do_detect(im_explorer_detect, - psmouse, set_properties) == 0) { - return PSMOUSE_IMEX; - } - - if (max_proto >= PSMOUSE_IMPS && - psmouse_do_detect(intellimouse_detect, - psmouse, set_properties) == 0) { - return PSMOUSE_IMPS; - } - -/* - * Okay, all failed, we have a standard mouse here. The number of the buttons - * is still a question, though. We assume 3. - */ - psmouse_do_detect(ps2bare_detect, psmouse, set_properties); - - if (synaptics_hardware) { -/* - * We detected Synaptics hardware but it did not respond to IMPS/2 probes. - * We need to reset the touchpad because if there is a track point on the - * pass through port it could get disabled while probing for protocol - * extensions. - */ - psmouse_reset(psmouse); - } - - return PSMOUSE_PS2; -} - -static const struct psmouse_protocol psmouse_protocols[] = { - { - .type = PSMOUSE_PS2, - .name = "PS/2", - .alias = "bare", - .maxproto = true, - .ignore_parity = true, - .detect = ps2bare_detect, - }, -#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP - { - .type = PSMOUSE_PS2PP, - .name = "PS2++", - .alias = "logitech", - .detect = ps2pp_init, - }, -#endif - { - .type = PSMOUSE_THINKPS, - .name = "ThinkPS/2", - .alias = "thinkps", - .detect = thinking_detect, - }, - { - .type = PSMOUSE_GENPS, - .name = "GenPS/2", - .alias = "genius", - .detect = genius_detect, - }, - { - .type = PSMOUSE_IMPS, - .name = "ImPS/2", - .alias = "imps", - .maxproto = true, - .ignore_parity = true, - .detect = intellimouse_detect, - }, - { - .type = PSMOUSE_IMEX, - .name = "ImExPS/2", - .alias = "exps", - .maxproto = true, - .ignore_parity = true, - .detect = im_explorer_detect, - }, -#ifdef CONFIG_MOUSE_PS2_SYNAPTICS - { - .type = PSMOUSE_SYNAPTICS, - .name = "SynPS/2", - .alias = "synaptics", - .detect = synaptics_detect, - .init = synaptics_init, - }, - { - .type = PSMOUSE_SYNAPTICS_RELATIVE, - .name = "SynRelPS/2", - .alias = "synaptics-relative", - .detect = synaptics_detect, - .init = synaptics_init_relative, - }, -#endif -#ifdef CONFIG_MOUSE_PS2_ALPS - { - .type = PSMOUSE_ALPS, - .name = "AlpsPS/2", - .alias = "alps", - .detect = alps_detect, - .init = alps_init, - }, -#endif -#ifdef CONFIG_MOUSE_PS2_LIFEBOOK - { - .type = PSMOUSE_LIFEBOOK, - .name = "LBPS/2", - .alias = "lifebook", - .init = lifebook_init, - }, -#endif -#ifdef CONFIG_MOUSE_PS2_TRACKPOINT - { - .type = PSMOUSE_TRACKPOINT, - .name = "TPPS/2", - .alias = "trackpoint", - .detect = trackpoint_detect, - }, -#endif -#ifdef CONFIG_MOUSE_PS2_TOUCHKIT - { - .type = PSMOUSE_TOUCHKIT_PS2, - .name = "touchkitPS/2", - .alias = "touchkit", - .detect = touchkit_ps2_detect, - }, -#endif -#ifdef CONFIG_MOUSE_PS2_OLPC - { - .type = PSMOUSE_HGPK, - .name = "OLPC HGPK", - .alias = "hgpk", - .detect = hgpk_detect, - }, -#endif -#ifdef CONFIG_MOUSE_PS2_ELANTECH - { - .type = PSMOUSE_ELANTECH, - .name = "ETPS/2", - .alias = "elantech", - .detect = elantech_detect, - .init = elantech_init, - }, -#endif -#ifdef CONFIG_MOUSE_PS2_SENTELIC - { - .type = PSMOUSE_FSP, - .name = "FSPPS/2", - .alias = "fsp", - .detect = fsp_detect, - .init = fsp_init, - }, -#endif - { - .type = PSMOUSE_CORTRON, - .name = "CortronPS/2", - .alias = "cortps", - .detect = cortron_detect, - }, - { - .type = PSMOUSE_AUTO, - .name = "auto", - .alias = "any", - .maxproto = true, - }, -}; - -static const struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) - if (psmouse_protocols[i].type == type) - return &psmouse_protocols[i]; - - WARN_ON(1); - return &psmouse_protocols[0]; -} - -static const struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len) -{ - const struct psmouse_protocol *p; - int i; - - for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) { - p = &psmouse_protocols[i]; - - if ((strlen(p->name) == len && !strncmp(p->name, name, len)) || - (strlen(p->alias) == len && !strncmp(p->alias, name, len))) - return &psmouse_protocols[i]; - } - - return NULL; -} - - -/* - * psmouse_probe() probes for a PS/2 mouse. - */ - -static int psmouse_probe(struct psmouse *psmouse) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[2]; - -/* - * First, we check if it's a mouse. It should send 0x00 or 0x03 - * in case of an IntelliMouse in 4-byte mode or 0x04 for IM Explorer. - * Sunrex K8561 IR Keyboard/Mouse reports 0xff on second and subsequent - * ID queries, probably due to a firmware bug. - */ - - param[0] = 0xa5; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) - return -1; - - if (param[0] != 0x00 && param[0] != 0x03 && - param[0] != 0x04 && param[0] != 0xff) - return -1; - -/* - * Then we reset and disable the mouse so that it doesn't generate events. - */ - - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS)) - psmouse_warn(psmouse, "Failed to reset mouse on %s\n", - ps2dev->serio->phys); - - return 0; -} - -/* - * psmouse_initialize() initializes the mouse to a sane state. - */ - -static void psmouse_initialize(struct psmouse *psmouse) -{ -/* - * We set the mouse report rate, resolution and scaling. - */ - - if (psmouse_max_proto != PSMOUSE_PS2) { - psmouse->set_rate(psmouse, psmouse->rate); - psmouse->set_resolution(psmouse, psmouse->resolution); - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); - } -} - -/* - * psmouse_activate() enables the mouse so that we get motion reports from it. - */ - -int psmouse_activate(struct psmouse *psmouse) -{ - if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { - psmouse_warn(psmouse, "Failed to enable mouse on %s\n", - psmouse->ps2dev.serio->phys); - return -1; - } - - psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); - return 0; -} - -/* - * psmouse_deactivate() puts the mouse into poll mode so that we don't get motion - * reports from it unless we explicitly request it. - */ - -int psmouse_deactivate(struct psmouse *psmouse) -{ - if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) { - psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n", - psmouse->ps2dev.serio->phys); - return -1; - } - - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - return 0; -} - - -/* - * psmouse_resync() attempts to re-validate current protocol. - */ - -static void psmouse_resync(struct work_struct *work) -{ - struct psmouse *parent = NULL, *psmouse = - container_of(work, struct psmouse, resync_work.work); - struct serio *serio = psmouse->ps2dev.serio; - psmouse_ret_t rc = PSMOUSE_GOOD_DATA; - bool failed = false, enabled = false; - int i; - - mutex_lock(&psmouse_mutex); - - if (psmouse->state != PSMOUSE_RESYNCING) - goto out; - - if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); - psmouse_deactivate(parent); - } - -/* - * Some mice don't ACK commands sent while they are in the middle of - * transmitting motion packet. To avoid delay we use ps2_sendbyte() - * instead of ps2_command() which would wait for 200ms for an ACK - * that may never come. - * As an additional quirk ALPS touchpads may not only forget to ACK - * disable command but will stop reporting taps, so if we see that - * mouse at least once ACKs disable we will do full reconnect if ACK - * is missing. - */ - psmouse->num_resyncs++; - - if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { - if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) - failed = true; - } else - psmouse->acks_disable_command = true; - -/* - * Poll the mouse. If it was reset the packet will be shorter than - * psmouse->pktsize and ps2_command will fail. We do not expect and - * do not handle scenario when mouse "upgrades" its protocol while - * disconnected since it would require additional delay. If we ever - * see a mouse that does it we'll adjust the code. - */ - if (!failed) { - if (psmouse->poll(psmouse)) - failed = true; - else { - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - for (i = 0; i < psmouse->pktsize; i++) { - psmouse->pktcnt++; - rc = psmouse->protocol_handler(psmouse); - if (rc != PSMOUSE_GOOD_DATA) - break; - } - if (rc != PSMOUSE_FULL_PACKET) - failed = true; - psmouse_set_state(psmouse, PSMOUSE_RESYNCING); - } - } -/* - * Now try to enable mouse. We try to do that even if poll failed and also - * repeat our attempts 5 times, otherwise we may be left out with disabled - * mouse. - */ - for (i = 0; i < 5; i++) { - if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { - enabled = true; - break; - } - msleep(200); - } - - if (!enabled) { - psmouse_warn(psmouse, "failed to re-enable mouse on %s\n", - psmouse->ps2dev.serio->phys); - failed = true; - } - - if (failed) { - psmouse_set_state(psmouse, PSMOUSE_IGNORE); - psmouse_info(psmouse, - "resync failed, issuing reconnect request\n"); - serio_reconnect(serio); - } else - psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); - - if (parent) - psmouse_activate(parent); - out: - mutex_unlock(&psmouse_mutex); -} - -/* - * psmouse_cleanup() resets the mouse into power-on state. - */ - -static void psmouse_cleanup(struct serio *serio) -{ - struct psmouse *psmouse = serio_get_drvdata(serio); - struct psmouse *parent = NULL; - - mutex_lock(&psmouse_mutex); - - if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); - psmouse_deactivate(parent); - } - - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - - /* - * Disable stream mode so cleanup routine can proceed undisturbed. - */ - if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) - psmouse_warn(psmouse, "Failed to disable mouse on %s\n", - psmouse->ps2dev.serio->phys); - - if (psmouse->cleanup) - psmouse->cleanup(psmouse); - -/* - * Reset the mouse to defaults (bare PS/2 protocol). - */ - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); - -/* - * Some boxes, such as HP nx7400, get terribly confused if mouse - * is not fully enabled before suspending/shutting down. - */ - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); - - if (parent) { - if (parent->pt_deactivate) - parent->pt_deactivate(parent); - - psmouse_activate(parent); - } - - mutex_unlock(&psmouse_mutex); -} - -/* - * psmouse_disconnect() closes and frees. - */ - -static void psmouse_disconnect(struct serio *serio) -{ - struct psmouse *psmouse, *parent = NULL; - - psmouse = serio_get_drvdata(serio); - - sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group); - - mutex_lock(&psmouse_mutex); - - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - - /* make sure we don't have a resync in progress */ - mutex_unlock(&psmouse_mutex); - flush_workqueue(kpsmoused_wq); - mutex_lock(&psmouse_mutex); - - if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); - psmouse_deactivate(parent); - } - - if (psmouse->disconnect) - psmouse->disconnect(psmouse); - - if (parent && parent->pt_deactivate) - parent->pt_deactivate(parent); - - psmouse_set_state(psmouse, PSMOUSE_IGNORE); - - serio_close(serio); - serio_set_drvdata(serio, NULL); - input_unregister_device(psmouse->dev); - kfree(psmouse); - - if (parent) - psmouse_activate(parent); - - mutex_unlock(&psmouse_mutex); -} - -static int psmouse_switch_protocol(struct psmouse *psmouse, - const struct psmouse_protocol *proto) -{ - const struct psmouse_protocol *selected_proto; - struct input_dev *input_dev = psmouse->dev; - - input_dev->dev.parent = &psmouse->ps2dev.serio->dev; - - if (proto && (proto->detect || proto->init)) { - psmouse_apply_defaults(psmouse); - - if (proto->detect && proto->detect(psmouse, true) < 0) - return -1; - - if (proto->init && proto->init(psmouse) < 0) - return -1; - - psmouse->type = proto->type; - selected_proto = proto; - } else { - psmouse->type = psmouse_extensions(psmouse, - psmouse_max_proto, true); - selected_proto = psmouse_protocol_by_type(psmouse->type); - } - - psmouse->ignore_parity = selected_proto->ignore_parity; - - /* - * If mouse's packet size is 3 there is no point in polling the - * device in hopes to detect protocol reset - we won't get less - * than 3 bytes response anyhow. - */ - if (psmouse->pktsize == 3) - psmouse->resync_time = 0; - - /* - * Some smart KVMs fake response to POLL command returning just - * 3 bytes and messing up our resync logic, so if initial poll - * fails we won't try polling the device anymore. Hopefully - * such KVM will maintain initially selected protocol. - */ - if (psmouse->resync_time && psmouse->poll(psmouse)) - psmouse->resync_time = 0; - - snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", - selected_proto->name, psmouse->vendor, psmouse->name); - - input_dev->name = psmouse->devname; - input_dev->phys = psmouse->phys; - input_dev->id.bustype = BUS_I8042; - input_dev->id.vendor = 0x0002; - input_dev->id.product = psmouse->type; - input_dev->id.version = psmouse->model; - - return 0; -} - -/* - * psmouse_connect() is a callback from the serio module when - * an unhandled serio port is found. - */ -static int psmouse_connect(struct serio *serio, struct serio_driver *drv) -{ - struct psmouse *psmouse, *parent = NULL; - struct input_dev *input_dev; - int retval = 0, error = -ENOMEM; - - mutex_lock(&psmouse_mutex); - - /* - * If this is a pass-through port deactivate parent so the device - * connected to this port can be successfully identified - */ - if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); - psmouse_deactivate(parent); - } - - psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!psmouse || !input_dev) - goto err_free; - - ps2_init(&psmouse->ps2dev, serio); - INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync); - psmouse->dev = input_dev; - snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); - - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - - serio_set_drvdata(serio, psmouse); - - error = serio_open(serio, drv); - if (error) - goto err_clear_drvdata; - - if (psmouse_probe(psmouse) < 0) { - error = -ENODEV; - goto err_close_serio; - } - - psmouse->rate = psmouse_rate; - psmouse->resolution = psmouse_resolution; - psmouse->resetafter = psmouse_resetafter; - psmouse->resync_time = parent ? 0 : psmouse_resync_time; - psmouse->smartscroll = psmouse_smartscroll; - - psmouse_switch_protocol(psmouse, NULL); - - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - psmouse_initialize(psmouse); - - error = input_register_device(psmouse->dev); - if (error) - goto err_protocol_disconnect; - - if (parent && parent->pt_activate) - parent->pt_activate(parent); - - error = sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group); - if (error) - goto err_pt_deactivate; - - psmouse_activate(psmouse); - - out: - /* If this is a pass-through port the parent needs to be re-activated */ - if (parent) - psmouse_activate(parent); - - mutex_unlock(&psmouse_mutex); - return retval; - - err_pt_deactivate: - if (parent && parent->pt_deactivate) - parent->pt_deactivate(parent); - input_unregister_device(psmouse->dev); - input_dev = NULL; /* so we don't try to free it below */ - err_protocol_disconnect: - if (psmouse->disconnect) - psmouse->disconnect(psmouse); - psmouse_set_state(psmouse, PSMOUSE_IGNORE); - err_close_serio: - serio_close(serio); - err_clear_drvdata: - serio_set_drvdata(serio, NULL); - err_free: - input_free_device(input_dev); - kfree(psmouse); - - retval = error; - goto out; -} - - -static int psmouse_reconnect(struct serio *serio) -{ - struct psmouse *psmouse = serio_get_drvdata(serio); - struct psmouse *parent = NULL; - struct serio_driver *drv = serio->drv; - unsigned char type; - int rc = -1; - - if (!drv || !psmouse) { - psmouse_dbg(psmouse, - "reconnect request, but serio is disconnected, ignoring...\n"); - return -1; - } - - mutex_lock(&psmouse_mutex); - - if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); - psmouse_deactivate(parent); - } - - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - - if (psmouse->reconnect) { - if (psmouse->reconnect(psmouse)) - goto out; - } else { - psmouse_reset(psmouse); - - if (psmouse_probe(psmouse) < 0) - goto out; - - type = psmouse_extensions(psmouse, psmouse_max_proto, false); - if (psmouse->type != type) - goto out; - } - - /* - * OK, the device type (and capabilities) match the old one, - * we can continue using it, complete initialization - */ - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - - psmouse_initialize(psmouse); - - if (parent && parent->pt_activate) - parent->pt_activate(parent); - - psmouse_activate(psmouse); - rc = 0; - -out: - /* If this is a pass-through port the parent waits to be activated */ - if (parent) - psmouse_activate(parent); - - mutex_unlock(&psmouse_mutex); - return rc; -} - -static struct serio_device_id psmouse_serio_ids[] = { - { - .type = SERIO_8042, - .proto = SERIO_ANY, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { - .type = SERIO_PS_PSTHRU, - .proto = SERIO_ANY, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { 0 } -}; - -MODULE_DEVICE_TABLE(serio, psmouse_serio_ids); - -static struct serio_driver psmouse_drv = { - .driver = { - .name = "psmouse", - }, - .description = DRIVER_DESC, - .id_table = psmouse_serio_ids, - .interrupt = psmouse_interrupt, - .connect = psmouse_connect, - .reconnect = psmouse_reconnect, - .disconnect = psmouse_disconnect, - .cleanup = psmouse_cleanup, -}; - -ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct serio *serio = to_serio_port(dev); - struct psmouse_attribute *attr = to_psmouse_attr(devattr); - struct psmouse *psmouse; - - psmouse = serio_get_drvdata(serio); - - return attr->show(psmouse, attr->data, buf); -} - -ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct serio *serio = to_serio_port(dev); - struct psmouse_attribute *attr = to_psmouse_attr(devattr); - struct psmouse *psmouse, *parent = NULL; - int retval; - - retval = mutex_lock_interruptible(&psmouse_mutex); - if (retval) - goto out; - - psmouse = serio_get_drvdata(serio); - - if (attr->protect) { - if (psmouse->state == PSMOUSE_IGNORE) { - retval = -ENODEV; - goto out_unlock; - } - - if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); - psmouse_deactivate(parent); - } - - psmouse_deactivate(psmouse); - } - - retval = attr->set(psmouse, attr->data, buf, count); - - if (attr->protect) { - if (retval != -ENODEV) - psmouse_activate(psmouse); - - if (parent) - psmouse_activate(parent); - } - - out_unlock: - mutex_unlock(&psmouse_mutex); - out: - return retval; -} - -static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf) -{ - unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); - - return sprintf(buf, "%u\n", *field); -} - -static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count) -{ - unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); - unsigned int value; - int err; - - err = kstrtouint(buf, 10, &value); - if (err) - return err; - - *field = value; - - return count; -} - -static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, void *data, char *buf) -{ - return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name); -} - -static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, const char *buf, size_t count) -{ - struct serio *serio = psmouse->ps2dev.serio; - struct psmouse *parent = NULL; - struct input_dev *old_dev, *new_dev; - const struct psmouse_protocol *proto, *old_proto; - int error; - int retry = 0; - - proto = psmouse_protocol_by_name(buf, count); - if (!proto) - return -EINVAL; - - if (psmouse->type == proto->type) - return count; - - new_dev = input_allocate_device(); - if (!new_dev) - return -ENOMEM; - - while (!list_empty(&serio->children)) { - if (++retry > 3) { - psmouse_warn(psmouse, - "failed to destroy children ports, protocol change aborted.\n"); - input_free_device(new_dev); - return -EIO; - } - - mutex_unlock(&psmouse_mutex); - serio_unregister_child_port(serio); - mutex_lock(&psmouse_mutex); - - if (serio->drv != &psmouse_drv) { - input_free_device(new_dev); - return -ENODEV; - } - - if (psmouse->type == proto->type) { - input_free_device(new_dev); - return count; /* switched by other thread */ - } - } - - if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); - if (parent->pt_deactivate) - parent->pt_deactivate(parent); - } - - old_dev = psmouse->dev; - old_proto = psmouse_protocol_by_type(psmouse->type); - - if (psmouse->disconnect) - psmouse->disconnect(psmouse); - - psmouse_set_state(psmouse, PSMOUSE_IGNORE); - - psmouse->dev = new_dev; - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - - if (psmouse_switch_protocol(psmouse, proto) < 0) { - psmouse_reset(psmouse); - /* default to PSMOUSE_PS2 */ - psmouse_switch_protocol(psmouse, &psmouse_protocols[0]); - } - - psmouse_initialize(psmouse); - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - - error = input_register_device(psmouse->dev); - if (error) { - if (psmouse->disconnect) - psmouse->disconnect(psmouse); - - psmouse_set_state(psmouse, PSMOUSE_IGNORE); - input_free_device(new_dev); - psmouse->dev = old_dev; - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - psmouse_switch_protocol(psmouse, old_proto); - psmouse_initialize(psmouse); - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - - return error; - } - - input_unregister_device(old_dev); - - if (parent && parent->pt_activate) - parent->pt_activate(parent); - - return count; -} - -static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count) -{ - unsigned int value; - int err; - - err = kstrtouint(buf, 10, &value); - if (err) - return err; - - psmouse->set_rate(psmouse, value); - return count; -} - -static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count) -{ - unsigned int value; - int err; - - err = kstrtouint(buf, 10, &value); - if (err) - return err; - - psmouse->set_resolution(psmouse, value); - return count; -} - - -static int psmouse_set_maxproto(const char *val, const struct kernel_param *kp) -{ - const struct psmouse_protocol *proto; - - if (!val) - return -EINVAL; - - proto = psmouse_protocol_by_name(val, strlen(val)); - - if (!proto || !proto->maxproto) - return -EINVAL; - - *((unsigned int *)kp->arg) = proto->type; - - return 0; -} - -static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp) -{ - int type = *((unsigned int *)kp->arg); - - return sprintf(buffer, "%s", psmouse_protocol_by_type(type)->name); -} - -static int __init psmouse_init(void) -{ - int err; - - lifebook_module_init(); - synaptics_module_init(); - hgpk_module_init(); - - kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); - if (!kpsmoused_wq) { - pr_err("failed to create kpsmoused workqueue\n"); - return -ENOMEM; - } - - err = serio_register_driver(&psmouse_drv); - if (err) - destroy_workqueue(kpsmoused_wq); - - return err; -} - -static void __exit psmouse_exit(void) -{ - serio_unregister_driver(&psmouse_drv); - destroy_workqueue(kpsmoused_wq); -} - -module_init(psmouse_init); -module_exit(psmouse_exit); diff --git a/ANDROID_3.4.5/drivers/input/mouse/psmouse.h b/ANDROID_3.4.5/drivers/input/mouse/psmouse.h deleted file mode 100644 index fe1df231..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/psmouse.h +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef _PSMOUSE_H -#define _PSMOUSE_H - -#define PSMOUSE_CMD_SETSCALE11 0x00e6 -#define PSMOUSE_CMD_SETSCALE21 0x00e7 -#define PSMOUSE_CMD_SETRES 0x10e8 -#define PSMOUSE_CMD_GETINFO 0x03e9 -#define PSMOUSE_CMD_SETSTREAM 0x00ea -#define PSMOUSE_CMD_SETPOLL 0x00f0 -#define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ -#define PSMOUSE_CMD_RESET_WRAP 0x00ec -#define PSMOUSE_CMD_GETID 0x02f2 -#define PSMOUSE_CMD_SETRATE 0x10f3 -#define PSMOUSE_CMD_ENABLE 0x00f4 -#define PSMOUSE_CMD_DISABLE 0x00f5 -#define PSMOUSE_CMD_RESET_DIS 0x00f6 -#define PSMOUSE_CMD_RESET_BAT 0x02ff - -#define PSMOUSE_RET_BAT 0xaa -#define PSMOUSE_RET_ID 0x00 -#define PSMOUSE_RET_ACK 0xfa -#define PSMOUSE_RET_NAK 0xfe - -enum psmouse_state { - PSMOUSE_IGNORE, - PSMOUSE_INITIALIZING, - PSMOUSE_RESYNCING, - PSMOUSE_CMD_MODE, - PSMOUSE_ACTIVATED, -}; - -/* psmouse protocol handler return codes */ -typedef enum { - PSMOUSE_BAD_DATA, - PSMOUSE_GOOD_DATA, - PSMOUSE_FULL_PACKET -} psmouse_ret_t; - -struct psmouse { - void *private; - struct input_dev *dev; - struct ps2dev ps2dev; - struct delayed_work resync_work; - char *vendor; - char *name; - unsigned char packet[8]; - unsigned char badbyte; - unsigned char pktcnt; - unsigned char pktsize; - unsigned char type; - bool ignore_parity; - bool acks_disable_command; - unsigned int model; - unsigned long last; - unsigned long out_of_sync_cnt; - unsigned long num_resyncs; - enum psmouse_state state; - char devname[64]; - char phys[32]; - - unsigned int rate; - unsigned int resolution; - unsigned int resetafter; - unsigned int resync_time; - bool smartscroll; /* Logitech only */ - - psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse); - void (*set_rate)(struct psmouse *psmouse, unsigned int rate); - void (*set_resolution)(struct psmouse *psmouse, unsigned int resolution); - - int (*reconnect)(struct psmouse *psmouse); - void (*disconnect)(struct psmouse *psmouse); - void (*cleanup)(struct psmouse *psmouse); - int (*poll)(struct psmouse *psmouse); - - void (*pt_activate)(struct psmouse *psmouse); - void (*pt_deactivate)(struct psmouse *psmouse); -}; - -enum psmouse_type { - PSMOUSE_NONE, - PSMOUSE_PS2, - PSMOUSE_PS2PP, - PSMOUSE_THINKPS, - PSMOUSE_GENPS, - PSMOUSE_IMPS, - PSMOUSE_IMEX, - PSMOUSE_SYNAPTICS, - PSMOUSE_ALPS, - PSMOUSE_LIFEBOOK, - PSMOUSE_TRACKPOINT, - PSMOUSE_TOUCHKIT_PS2, - PSMOUSE_CORTRON, - PSMOUSE_HGPK, - PSMOUSE_ELANTECH, - PSMOUSE_FSP, - PSMOUSE_SYNAPTICS_RELATIVE, - PSMOUSE_AUTO /* This one should always be last */ -}; - -void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, - unsigned long delay); -int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); -int psmouse_reset(struct psmouse *psmouse); -void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state); -void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); -psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse); -int psmouse_activate(struct psmouse *psmouse); -int psmouse_deactivate(struct psmouse *psmouse); - -struct psmouse_attribute { - struct device_attribute dattr; - void *data; - ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); - ssize_t (*set)(struct psmouse *psmouse, void *data, - const char *buf, size_t count); - bool protect; -}; -#define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) - -ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *attr, - char *buf); -ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); - -#define __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) \ -static struct psmouse_attribute psmouse_attr_##_name = { \ - .dattr = { \ - .attr = { \ - .name = __stringify(_name), \ - .mode = _mode, \ - }, \ - .show = psmouse_attr_show_helper, \ - .store = psmouse_attr_set_helper, \ - }, \ - .data = _data, \ - .show = _show, \ - .set = _set, \ - .protect = _protect, \ -} - -#define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ - static ssize_t _show(struct psmouse *, void *, char *); \ - static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ - __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) - -#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ - __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, true) - -#define PSMOUSE_DEFINE_RO_ATTR(_name, _mode, _data, _show) \ - static ssize_t _show(struct psmouse *, void *, char *); \ - __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, NULL, true) - -#define PSMOUSE_DEFINE_WO_ATTR(_name, _mode, _data, _set) \ - static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ - __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true) - -#ifndef psmouse_fmt -#define psmouse_fmt(fmt) KBUILD_BASENAME ": " fmt -#endif - -#define psmouse_dbg(psmouse, format, ...) \ - dev_dbg(&(psmouse)->ps2dev.serio->dev, \ - psmouse_fmt(format), ##__VA_ARGS__) -#define psmouse_info(psmouse, format, ...) \ - dev_info(&(psmouse)->ps2dev.serio->dev, \ - psmouse_fmt(format), ##__VA_ARGS__) -#define psmouse_warn(psmouse, format, ...) \ - dev_warn(&(psmouse)->ps2dev.serio->dev, \ - psmouse_fmt(format), ##__VA_ARGS__) -#define psmouse_err(psmouse, format, ...) \ - dev_err(&(psmouse)->ps2dev.serio->dev, \ - psmouse_fmt(format), ##__VA_ARGS__) -#define psmouse_notice(psmouse, format, ...) \ - dev_notice(&(psmouse)->ps2dev.serio->dev, \ - psmouse_fmt(format), ##__VA_ARGS__) -#define psmouse_printk(level, psmouse, format, ...) \ - dev_printk(level, \ - &(psmouse)->ps2dev.serio->dev, \ - psmouse_fmt(format), ##__VA_ARGS__) - - -#endif /* _PSMOUSE_H */ diff --git a/ANDROID_3.4.5/drivers/input/mouse/pxa930_trkball.c b/ANDROID_3.4.5/drivers/input/mouse/pxa930_trkball.c deleted file mode 100644 index a9e4bfdf..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/pxa930_trkball.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * PXA930 track ball mouse driver - * - * Copyright (C) 2007 Marvell International Ltd. - * 2008-02-28: Yong Yao <yaoyong@marvell.com> - * initial version - * - * 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. - */ - -#include <linux/init.h> -#include <linux/input.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/slab.h> - -#include <mach/hardware.h> -#include <mach/pxa930_trkball.h> - -/* Trackball Controller Register Definitions */ -#define TBCR (0x000C) -#define TBCNTR (0x0010) -#define TBSBC (0x0014) - -#define TBCR_TBRST (1 << 1) -#define TBCR_TBSB (1 << 10) - -#define TBCR_Y_FLT(n) (((n) & 0xf) << 6) -#define TBCR_X_FLT(n) (((n) & 0xf) << 2) - -#define TBCNTR_YM(n) (((n) >> 24) & 0xff) -#define TBCNTR_YP(n) (((n) >> 16) & 0xff) -#define TBCNTR_XM(n) (((n) >> 8) & 0xff) -#define TBCNTR_XP(n) ((n) & 0xff) - -#define TBSBC_TBSBC (0x1) - -struct pxa930_trkball { - struct pxa930_trkball_platform_data *pdata; - - /* Memory Mapped Register */ - struct resource *mem; - void __iomem *mmio_base; - - struct input_dev *input; -}; - -static irqreturn_t pxa930_trkball_interrupt(int irq, void *dev_id) -{ - struct pxa930_trkball *trkball = dev_id; - struct input_dev *input = trkball->input; - int tbcntr, x, y; - - /* According to the spec software must read TBCNTR twice: - * if the read value is the same, the reading is valid - */ - tbcntr = __raw_readl(trkball->mmio_base + TBCNTR); - - if (tbcntr == __raw_readl(trkball->mmio_base + TBCNTR)) { - x = (TBCNTR_XP(tbcntr) - TBCNTR_XM(tbcntr)) / 2; - y = (TBCNTR_YP(tbcntr) - TBCNTR_YM(tbcntr)) / 2; - - input_report_rel(input, REL_X, x); - input_report_rel(input, REL_Y, y); - input_sync(input); - } - - __raw_writel(TBSBC_TBSBC, trkball->mmio_base + TBSBC); - __raw_writel(0, trkball->mmio_base + TBSBC); - - return IRQ_HANDLED; -} - -/* For TBCR, we need to wait for a while to make sure it has been modified. */ -static int write_tbcr(struct pxa930_trkball *trkball, int v) -{ - int i = 100; - - __raw_writel(v, trkball->mmio_base + TBCR); - - while (--i) { - if (__raw_readl(trkball->mmio_base + TBCR) == v) - break; - msleep(1); - } - - if (i == 0) { - pr_err("%s: timed out writing TBCR(%x)!\n", __func__, v); - return -ETIMEDOUT; - } - - return 0; -} - -static void pxa930_trkball_config(struct pxa930_trkball *trkball) -{ - uint32_t tbcr; - - /* According to spec, need to write the filters of x,y to 0xf first! */ - tbcr = __raw_readl(trkball->mmio_base + TBCR); - write_tbcr(trkball, tbcr | TBCR_X_FLT(0xf) | TBCR_Y_FLT(0xf)); - write_tbcr(trkball, TBCR_X_FLT(trkball->pdata->x_filter) | - TBCR_Y_FLT(trkball->pdata->y_filter)); - - /* According to spec, set TBCR_TBRST first, before clearing it! */ - tbcr = __raw_readl(trkball->mmio_base + TBCR); - write_tbcr(trkball, tbcr | TBCR_TBRST); - write_tbcr(trkball, tbcr & ~TBCR_TBRST); - - __raw_writel(TBSBC_TBSBC, trkball->mmio_base + TBSBC); - __raw_writel(0, trkball->mmio_base + TBSBC); - - pr_debug("%s: final TBCR=%x!\n", __func__, - __raw_readl(trkball->mmio_base + TBCR)); -} - -static int pxa930_trkball_open(struct input_dev *dev) -{ - struct pxa930_trkball *trkball = input_get_drvdata(dev); - - pxa930_trkball_config(trkball); - - return 0; -} - -static void pxa930_trkball_disable(struct pxa930_trkball *trkball) -{ - uint32_t tbcr = __raw_readl(trkball->mmio_base + TBCR); - - /* Held in reset, gate the 32-KHz input clock off */ - write_tbcr(trkball, tbcr | TBCR_TBRST); -} - -static void pxa930_trkball_close(struct input_dev *dev) -{ - struct pxa930_trkball *trkball = input_get_drvdata(dev); - - pxa930_trkball_disable(trkball); -} - -static int __devinit pxa930_trkball_probe(struct platform_device *pdev) -{ - struct pxa930_trkball *trkball; - struct input_dev *input; - struct resource *res; - int irq, error; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get trkball irq\n"); - return -ENXIO; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "failed to get register memory\n"); - return -ENXIO; - } - - trkball = kzalloc(sizeof(struct pxa930_trkball), GFP_KERNEL); - if (!trkball) - return -ENOMEM; - - trkball->pdata = pdev->dev.platform_data; - if (!trkball->pdata) { - dev_err(&pdev->dev, "no platform data defined\n"); - error = -EINVAL; - goto failed; - } - - trkball->mmio_base = ioremap_nocache(res->start, resource_size(res)); - if (!trkball->mmio_base) { - dev_err(&pdev->dev, "failed to ioremap registers\n"); - error = -ENXIO; - goto failed; - } - - /* held the module in reset, will be enabled in open() */ - pxa930_trkball_disable(trkball); - - error = request_irq(irq, pxa930_trkball_interrupt, 0, - pdev->name, trkball); - if (error) { - dev_err(&pdev->dev, "failed to request irq: %d\n", error); - goto failed_free_io; - } - - platform_set_drvdata(pdev, trkball); - - input = input_allocate_device(); - if (!input) { - dev_err(&pdev->dev, "failed to allocate input device\n"); - error = -ENOMEM; - goto failed_free_irq; - } - - input->name = pdev->name; - input->id.bustype = BUS_HOST; - input->open = pxa930_trkball_open; - input->close = pxa930_trkball_close; - input->dev.parent = &pdev->dev; - input_set_drvdata(input, trkball); - - trkball->input = input; - - input_set_capability(input, EV_REL, REL_X); - input_set_capability(input, EV_REL, REL_Y); - - error = input_register_device(input); - if (error) { - dev_err(&pdev->dev, "unable to register input device\n"); - goto failed_free_input; - } - - return 0; - -failed_free_input: - input_free_device(input); -failed_free_irq: - free_irq(irq, trkball); -failed_free_io: - iounmap(trkball->mmio_base); -failed: - kfree(trkball); - return error; -} - -static int __devexit pxa930_trkball_remove(struct platform_device *pdev) -{ - struct pxa930_trkball *trkball = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - - input_unregister_device(trkball->input); - free_irq(irq, trkball); - iounmap(trkball->mmio_base); - kfree(trkball); - - return 0; -} - -static struct platform_driver pxa930_trkball_driver = { - .driver = { - .name = "pxa930-trkball", - }, - .probe = pxa930_trkball_probe, - .remove = __devexit_p(pxa930_trkball_remove), -}; -module_platform_driver(pxa930_trkball_driver); - -MODULE_AUTHOR("Yong Yao <yaoyong@marvell.com>"); -MODULE_DESCRIPTION("PXA930 Trackball Mouse Driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/input/mouse/rpcmouse.c b/ANDROID_3.4.5/drivers/input/mouse/rpcmouse.c deleted file mode 100644 index 272deddc..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/rpcmouse.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Acorn RiscPC mouse driver for Linux/ARM - * - * Copyright (c) 2000-2002 Vojtech Pavlik - * Copyright (C) 1996-2002 Russell King - * - */ - -/* - * 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. - * - * This handles the Acorn RiscPCs mouse. We basically have a couple of - * hardware registers that track the sensor count for the X-Y movement and - * another register holding the button state. On every VSYNC interrupt we read - * the complete state and then work out if something has changed. - */ - -#include <linux/module.h> -#include <linux/ptrace.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/input.h> -#include <linux/io.h> - -#include <mach/hardware.h> -#include <asm/irq.h> -#include <asm/hardware/iomd.h> - -MODULE_AUTHOR("Vojtech Pavlik, Russell King"); -MODULE_DESCRIPTION("Acorn RiscPC mouse driver"); -MODULE_LICENSE("GPL"); - -static short rpcmouse_lastx, rpcmouse_lasty; -static struct input_dev *rpcmouse_dev; - -static irqreturn_t rpcmouse_irq(int irq, void *dev_id) -{ - struct input_dev *dev = dev_id; - short x, y, dx, dy, b; - - x = (short) iomd_readl(IOMD_MOUSEX); - y = (short) iomd_readl(IOMD_MOUSEY); - b = (short) (__raw_readl(0xe0310000) ^ 0x70); - - dx = x - rpcmouse_lastx; - dy = y - rpcmouse_lasty; - - rpcmouse_lastx = x; - rpcmouse_lasty = y; - - input_report_rel(dev, REL_X, dx); - input_report_rel(dev, REL_Y, -dy); - - input_report_key(dev, BTN_LEFT, b & 0x40); - input_report_key(dev, BTN_MIDDLE, b & 0x20); - input_report_key(dev, BTN_RIGHT, b & 0x10); - - input_sync(dev); - - return IRQ_HANDLED; -} - - -static int __init rpcmouse_init(void) -{ - int err; - - rpcmouse_dev = input_allocate_device(); - if (!rpcmouse_dev) - return -ENOMEM; - - rpcmouse_dev->name = "Acorn RiscPC Mouse"; - rpcmouse_dev->phys = "rpcmouse/input0"; - rpcmouse_dev->id.bustype = BUS_HOST; - rpcmouse_dev->id.vendor = 0x0005; - rpcmouse_dev->id.product = 0x0001; - rpcmouse_dev->id.version = 0x0100; - - rpcmouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - rpcmouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); - rpcmouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - - rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX); - rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY); - - if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, IRQF_SHARED, "rpcmouse", rpcmouse_dev)) { - printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n"); - err = -EBUSY; - goto err_free_dev; - } - - err = input_register_device(rpcmouse_dev); - if (err) - goto err_free_irq; - - return 0; - - err_free_irq: - free_irq(IRQ_VSYNCPULSE, rpcmouse_dev); - err_free_dev: - input_free_device(rpcmouse_dev); - - return err; -} - -static void __exit rpcmouse_exit(void) -{ - free_irq(IRQ_VSYNCPULSE, rpcmouse_dev); - input_unregister_device(rpcmouse_dev); -} - -module_init(rpcmouse_init); -module_exit(rpcmouse_exit); diff --git a/ANDROID_3.4.5/drivers/input/mouse/sentelic.c b/ANDROID_3.4.5/drivers/input/mouse/sentelic.c deleted file mode 100644 index 661a0ca3..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/sentelic.c +++ /dev/null @@ -1,1050 +0,0 @@ -/*- - * Finger Sensing Pad PS/2 mouse driver. - * - * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. - * Copyright (C) 2005-2012 Tai-hwa Liang, Sentelic Corporation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/input.h> -#include <linux/input/mt.h> -#include <linux/ctype.h> -#include <linux/libps2.h> -#include <linux/serio.h> -#include <linux/jiffies.h> -#include <linux/slab.h> - -#include "psmouse.h" -#include "sentelic.h" - -/* - * Timeout for FSP PS/2 command only (in milliseconds). - */ -#define FSP_CMD_TIMEOUT 200 -#define FSP_CMD_TIMEOUT2 30 - -#define GET_ABS_X(packet) ((packet[1] << 2) | ((packet[3] >> 2) & 0x03)) -#define GET_ABS_Y(packet) ((packet[2] << 2) | (packet[3] & 0x03)) - -/** Driver version. */ -static const char fsp_drv_ver[] = "1.0.0-K"; - -/* - * Make sure that the value being sent to FSP will not conflict with - * possible sample rate values. - */ -static unsigned char fsp_test_swap_cmd(unsigned char reg_val) -{ - switch (reg_val) { - case 10: case 20: case 40: case 60: case 80: case 100: case 200: - /* - * The requested value being sent to FSP matched to possible - * sample rates, swap the given value such that the hardware - * wouldn't get confused. - */ - return (reg_val >> 4) | (reg_val << 4); - default: - return reg_val; /* swap isn't necessary */ - } -} - -/* - * Make sure that the value being sent to FSP will not conflict with certain - * commands. - */ -static unsigned char fsp_test_invert_cmd(unsigned char reg_val) -{ - switch (reg_val) { - case 0xe9: case 0xee: case 0xf2: case 0xff: - /* - * The requested value being sent to FSP matched to certain - * commands, inverse the given value such that the hardware - * wouldn't get confused. - */ - return ~reg_val; - default: - return reg_val; /* inversion isn't necessary */ - } -} - -static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[3]; - unsigned char addr; - int rc = -1; - - /* - * We need to shut off the device and switch it into command - * mode so we don't confuse our protocol handler. We don't need - * to do that for writes because sysfs set helper does this for - * us. - */ - psmouse_deactivate(psmouse); - - ps2_begin_command(ps2dev); - - if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) - goto out; - - /* should return 0xfe(request for resending) */ - ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); - /* should return 0xfc(failed) */ - ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); - - if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) - goto out; - - if ((addr = fsp_test_invert_cmd(reg_addr)) != reg_addr) { - ps2_sendbyte(ps2dev, 0x68, FSP_CMD_TIMEOUT2); - } else if ((addr = fsp_test_swap_cmd(reg_addr)) != reg_addr) { - /* swapping is required */ - ps2_sendbyte(ps2dev, 0xcc, FSP_CMD_TIMEOUT2); - /* expect 0xfe */ - } else { - /* swapping isn't necessary */ - ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); - /* expect 0xfe */ - } - /* should return 0xfc(failed) */ - ps2_sendbyte(ps2dev, addr, FSP_CMD_TIMEOUT); - - if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) < 0) - goto out; - - *reg_val = param[2]; - rc = 0; - - out: - ps2_end_command(ps2dev); - psmouse_activate(psmouse); - psmouse_dbg(psmouse, - "READ REG: 0x%02x is 0x%02x (rc = %d)\n", - reg_addr, *reg_val, rc); - return rc; -} - -static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char v; - int rc = -1; - - ps2_begin_command(ps2dev); - - if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) - goto out; - - if ((v = fsp_test_invert_cmd(reg_addr)) != reg_addr) { - /* inversion is required */ - ps2_sendbyte(ps2dev, 0x74, FSP_CMD_TIMEOUT2); - } else { - if ((v = fsp_test_swap_cmd(reg_addr)) != reg_addr) { - /* swapping is required */ - ps2_sendbyte(ps2dev, 0x77, FSP_CMD_TIMEOUT2); - } else { - /* swapping isn't necessary */ - ps2_sendbyte(ps2dev, 0x55, FSP_CMD_TIMEOUT2); - } - } - /* write the register address in correct order */ - ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); - - if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) - goto out; - - if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) { - /* inversion is required */ - ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2); - } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) { - /* swapping is required */ - ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2); - } else { - /* swapping isn't necessary */ - ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2); - } - - /* write the register value in correct order */ - ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); - rc = 0; - - out: - ps2_end_command(ps2dev); - psmouse_dbg(psmouse, - "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", - reg_addr, reg_val, rc); - return rc; -} - -/* Enable register clock gating for writing certain registers */ -static int fsp_reg_write_enable(struct psmouse *psmouse, bool enable) -{ - int v, nv; - - if (fsp_reg_read(psmouse, FSP_REG_SYSCTL1, &v) == -1) - return -1; - - if (enable) - nv = v | FSP_BIT_EN_REG_CLK; - else - nv = v & ~FSP_BIT_EN_REG_CLK; - - /* only write if necessary */ - if (nv != v) - if (fsp_reg_write(psmouse, FSP_REG_SYSCTL1, nv) == -1) - return -1; - - return 0; -} - -static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[3]; - int rc = -1; - - psmouse_deactivate(psmouse); - - ps2_begin_command(ps2dev); - - if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) - goto out; - - ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); - ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); - - if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) - goto out; - - ps2_sendbyte(ps2dev, 0x83, FSP_CMD_TIMEOUT2); - ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); - - /* get the returned result */ - if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) - goto out; - - *reg_val = param[2]; - rc = 0; - - out: - ps2_end_command(ps2dev); - psmouse_activate(psmouse); - psmouse_dbg(psmouse, - "READ PAGE REG: 0x%02x (rc = %d)\n", - *reg_val, rc); - return rc; -} - -static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char v; - int rc = -1; - - ps2_begin_command(ps2dev); - - if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) - goto out; - - ps2_sendbyte(ps2dev, 0x38, FSP_CMD_TIMEOUT2); - ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); - - if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) - goto out; - - if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) { - ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2); - } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) { - /* swapping is required */ - ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2); - } else { - /* swapping isn't necessary */ - ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2); - } - - ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); - rc = 0; - - out: - ps2_end_command(ps2dev); - psmouse_dbg(psmouse, - "WRITE PAGE REG: to 0x%02x (rc = %d)\n", - reg_val, rc); - return rc; -} - -static int fsp_get_version(struct psmouse *psmouse, int *version) -{ - if (fsp_reg_read(psmouse, FSP_REG_VERSION, version)) - return -EIO; - - return 0; -} - -static int fsp_get_revision(struct psmouse *psmouse, int *rev) -{ - if (fsp_reg_read(psmouse, FSP_REG_REVISION, rev)) - return -EIO; - - return 0; -} - -static int fsp_get_buttons(struct psmouse *psmouse, int *btn) -{ - static const int buttons[] = { - 0x16, /* Left/Middle/Right/Forward/Backward & Scroll Up/Down */ - 0x06, /* Left/Middle/Right & Scroll Up/Down/Right/Left */ - 0x04, /* Left/Middle/Right & Scroll Up/Down */ - 0x02, /* Left/Middle/Right */ - }; - int val; - - if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS, &val) == -1) - return -EIO; - - *btn = buttons[(val & 0x30) >> 4]; - return 0; -} - -/* Enable on-pad command tag output */ -static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) -{ - int v, nv; - int res = 0; - - if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) { - psmouse_err(psmouse, "Unable get OPC state.\n"); - return -EIO; - } - - if (enable) - nv = v | FSP_BIT_EN_OPC_TAG; - else - nv = v & ~FSP_BIT_EN_OPC_TAG; - - /* only write if necessary */ - if (nv != v) { - fsp_reg_write_enable(psmouse, true); - res = fsp_reg_write(psmouse, FSP_REG_OPC_QDOWN, nv); - fsp_reg_write_enable(psmouse, false); - } - - if (res != 0) { - psmouse_err(psmouse, "Unable to enable OPC tag.\n"); - res = -EIO; - } - - return res; -} - -static int fsp_onpad_vscr(struct psmouse *psmouse, bool enable) -{ - struct fsp_data *pad = psmouse->private; - int val; - - if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val)) - return -EIO; - - pad->vscroll = enable; - - if (enable) - val |= (FSP_BIT_FIX_VSCR | FSP_BIT_ONPAD_ENABLE); - else - val &= ~FSP_BIT_FIX_VSCR; - - if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val)) - return -EIO; - - return 0; -} - -static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable) -{ - struct fsp_data *pad = psmouse->private; - int val, v2; - - if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val)) - return -EIO; - - if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &v2)) - return -EIO; - - pad->hscroll = enable; - - if (enable) { - val |= (FSP_BIT_FIX_HSCR | FSP_BIT_ONPAD_ENABLE); - v2 |= FSP_BIT_EN_MSID6; - } else { - val &= ~FSP_BIT_FIX_HSCR; - v2 &= ~(FSP_BIT_EN_MSID6 | FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8); - } - - if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val)) - return -EIO; - - /* reconfigure horizontal scrolling packet output */ - if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, v2)) - return -EIO; - - return 0; -} - -/* - * Write device specific initial parameters. - * - * ex: 0xab 0xcd - write oxcd into register 0xab - */ -static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - int reg, val; - char *rest; - ssize_t retval; - - reg = simple_strtoul(buf, &rest, 16); - if (rest == buf || *rest != ' ' || reg > 0xff) - return -EINVAL; - - retval = kstrtoint(rest + 1, 16, &val); - if (retval) - return retval; - - if (val > 0xff) - return -EINVAL; - - if (fsp_reg_write_enable(psmouse, true)) - return -EIO; - - retval = fsp_reg_write(psmouse, reg, val) < 0 ? -EIO : count; - - fsp_reg_write_enable(psmouse, false); - - return count; -} - -PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg); - -static ssize_t fsp_attr_show_getreg(struct psmouse *psmouse, - void *data, char *buf) -{ - struct fsp_data *pad = psmouse->private; - - return sprintf(buf, "%02x%02x\n", pad->last_reg, pad->last_val); -} - -/* - * Read a register from device. - * - * ex: 0xab -- read content from register 0xab - */ -static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - struct fsp_data *pad = psmouse->private; - int reg, val, err; - - err = kstrtoint(buf, 16, ®); - if (err) - return err; - - if (reg > 0xff) - return -EINVAL; - - if (fsp_reg_read(psmouse, reg, &val)) - return -EIO; - - pad->last_reg = reg; - pad->last_val = val; - - return count; -} - -PSMOUSE_DEFINE_ATTR(getreg, S_IWUSR | S_IRUGO, NULL, - fsp_attr_show_getreg, fsp_attr_set_getreg); - -static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse, - void *data, char *buf) -{ - int val = 0; - - if (fsp_page_reg_read(psmouse, &val)) - return -EIO; - - return sprintf(buf, "%02x\n", val); -} - -static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - int val, err; - - err = kstrtoint(buf, 16, &val); - if (err) - return err; - - if (val > 0xff) - return -EINVAL; - - if (fsp_page_reg_write(psmouse, val)) - return -EIO; - - return count; -} - -PSMOUSE_DEFINE_ATTR(page, S_IWUSR | S_IRUGO, NULL, - fsp_attr_show_pagereg, fsp_attr_set_pagereg); - -static ssize_t fsp_attr_show_vscroll(struct psmouse *psmouse, - void *data, char *buf) -{ - struct fsp_data *pad = psmouse->private; - - return sprintf(buf, "%d\n", pad->vscroll); -} - -static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - unsigned int val; - int err; - - err = kstrtouint(buf, 10, &val); - if (err) - return err; - - if (val > 1) - return -EINVAL; - - fsp_onpad_vscr(psmouse, val); - - return count; -} - -PSMOUSE_DEFINE_ATTR(vscroll, S_IWUSR | S_IRUGO, NULL, - fsp_attr_show_vscroll, fsp_attr_set_vscroll); - -static ssize_t fsp_attr_show_hscroll(struct psmouse *psmouse, - void *data, char *buf) -{ - struct fsp_data *pad = psmouse->private; - - return sprintf(buf, "%d\n", pad->hscroll); -} - -static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - unsigned int val; - int err; - - err = kstrtouint(buf, 10, &val); - if (err) - return err; - - if (val > 1) - return -EINVAL; - - fsp_onpad_hscr(psmouse, val); - - return count; -} - -PSMOUSE_DEFINE_ATTR(hscroll, S_IWUSR | S_IRUGO, NULL, - fsp_attr_show_hscroll, fsp_attr_set_hscroll); - -static ssize_t fsp_attr_show_flags(struct psmouse *psmouse, - void *data, char *buf) -{ - struct fsp_data *pad = psmouse->private; - - return sprintf(buf, "%c\n", - pad->flags & FSPDRV_FLAG_EN_OPC ? 'C' : 'c'); -} - -static ssize_t fsp_attr_set_flags(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - struct fsp_data *pad = psmouse->private; - size_t i; - - for (i = 0; i < count; i++) { - switch (buf[i]) { - case 'C': - pad->flags |= FSPDRV_FLAG_EN_OPC; - break; - case 'c': - pad->flags &= ~FSPDRV_FLAG_EN_OPC; - break; - default: - return -EINVAL; - } - } - return count; -} - -PSMOUSE_DEFINE_ATTR(flags, S_IWUSR | S_IRUGO, NULL, - fsp_attr_show_flags, fsp_attr_set_flags); - -static ssize_t fsp_attr_show_ver(struct psmouse *psmouse, - void *data, char *buf) -{ - return sprintf(buf, "Sentelic FSP kernel module %s\n", fsp_drv_ver); -} - -PSMOUSE_DEFINE_RO_ATTR(ver, S_IRUGO, NULL, fsp_attr_show_ver); - -static struct attribute *fsp_attributes[] = { - &psmouse_attr_setreg.dattr.attr, - &psmouse_attr_getreg.dattr.attr, - &psmouse_attr_page.dattr.attr, - &psmouse_attr_vscroll.dattr.attr, - &psmouse_attr_hscroll.dattr.attr, - &psmouse_attr_flags.dattr.attr, - &psmouse_attr_ver.dattr.attr, - NULL -}; - -static struct attribute_group fsp_attribute_group = { - .attrs = fsp_attributes, -}; - -#ifdef FSP_DEBUG -static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[]) -{ - static unsigned int ps2_packet_cnt; - static unsigned int ps2_last_second; - unsigned int jiffies_msec; - const char *packet_type = "UNKNOWN"; - unsigned short abs_x = 0, abs_y = 0; - - /* Interpret & dump the packet data. */ - switch (packet[0] >> FSP_PKT_TYPE_SHIFT) { - case FSP_PKT_TYPE_ABS: - packet_type = "Absolute"; - abs_x = GET_ABS_X(packet); - abs_y = GET_ABS_Y(packet); - break; - case FSP_PKT_TYPE_NORMAL: - packet_type = "Normal"; - break; - case FSP_PKT_TYPE_NOTIFY: - packet_type = "Notify"; - break; - case FSP_PKT_TYPE_NORMAL_OPC: - packet_type = "Normal-OPC"; - break; - } - - ps2_packet_cnt++; - jiffies_msec = jiffies_to_msecs(jiffies); - psmouse_dbg(psmouse, - "%08dms %s packets: %02x, %02x, %02x, %02x; " - "abs_x: %d, abs_y: %d\n", - jiffies_msec, packet_type, - packet[0], packet[1], packet[2], packet[3], abs_x, abs_y); - - if (jiffies_msec - ps2_last_second > 1000) { - psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt); - ps2_packet_cnt = 0; - ps2_last_second = jiffies_msec; - } -} -#else -static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[]) -{ -} -#endif - -static void fsp_set_slot(struct input_dev *dev, int slot, bool active, - unsigned int x, unsigned int y) -{ - 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); - input_report_abs(dev, ABS_MT_POSITION_Y, y); - } -} - -static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - struct fsp_data *ad = psmouse->private; - unsigned char *packet = psmouse->packet; - unsigned char button_status = 0, lscroll = 0, rscroll = 0; - unsigned short abs_x, abs_y, fgrs = 0; - int rel_x, rel_y; - - if (psmouse->pktcnt < 4) - return PSMOUSE_GOOD_DATA; - - /* - * Full packet accumulated, process it - */ - - fsp_packet_debug(psmouse, packet); - - switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { - case FSP_PKT_TYPE_ABS: - abs_x = GET_ABS_X(packet); - abs_y = GET_ABS_Y(packet); - - if (packet[0] & FSP_PB0_MFMC) { - /* - * MFMC packet: assume that there are two fingers on - * pad - */ - fgrs = 2; - - /* MFMC packet */ - if (packet[0] & FSP_PB0_MFMC_FGR2) { - /* 2nd finger */ - if (ad->last_mt_fgr == 2) { - /* - * workaround for buggy firmware - * which doesn't clear MFMC bit if - * the 1st finger is up - */ - fgrs = 1; - fsp_set_slot(dev, 0, false, 0, 0); - } - ad->last_mt_fgr = 2; - - fsp_set_slot(dev, 1, fgrs == 2, abs_x, abs_y); - } else { - /* 1st finger */ - if (ad->last_mt_fgr == 1) { - /* - * workaround for buggy firmware - * which doesn't clear MFMC bit if - * the 2nd finger is up - */ - fgrs = 1; - fsp_set_slot(dev, 1, false, 0, 0); - } - ad->last_mt_fgr = 1; - fsp_set_slot(dev, 0, fgrs != 0, abs_x, abs_y); - } - } else { - /* SFAC packet */ - if ((packet[0] & (FSP_PB0_LBTN|FSP_PB0_PHY_BTN)) == - FSP_PB0_LBTN) { - /* On-pad click in SFAC mode should be handled - * by userspace. On-pad clicks in MFMC mode - * are real clickpad clicks, and not ignored. - */ - packet[0] &= ~FSP_PB0_LBTN; - } - - /* no multi-finger information */ - ad->last_mt_fgr = 0; - - if (abs_x != 0 && abs_y != 0) - fgrs = 1; - - fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y); - fsp_set_slot(dev, 1, false, 0, 0); - } - if (fgrs > 0) { - input_report_abs(dev, ABS_X, abs_x); - input_report_abs(dev, ABS_Y, abs_y); - } - input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - input_report_key(dev, BTN_TOUCH, fgrs); - input_report_key(dev, BTN_TOOL_FINGER, fgrs == 1); - input_report_key(dev, BTN_TOOL_DOUBLETAP, fgrs == 2); - break; - - case FSP_PKT_TYPE_NORMAL_OPC: - /* on-pad click, filter it if necessary */ - if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) - packet[0] &= ~FSP_PB0_LBTN; - /* fall through */ - - case FSP_PKT_TYPE_NORMAL: - /* normal packet */ - /* special packet data translation from on-pad packets */ - if (packet[3] != 0) { - if (packet[3] & BIT(0)) - button_status |= 0x01; /* wheel down */ - if (packet[3] & BIT(1)) - button_status |= 0x0f; /* wheel up */ - if (packet[3] & BIT(2)) - button_status |= BIT(4);/* horizontal left */ - if (packet[3] & BIT(3)) - button_status |= BIT(5);/* horizontal right */ - /* push back to packet queue */ - if (button_status != 0) - packet[3] = button_status; - rscroll = (packet[3] >> 4) & 1; - lscroll = (packet[3] >> 5) & 1; - } - /* - * Processing wheel up/down and extra button events - */ - input_report_rel(dev, REL_WHEEL, - (int)(packet[3] & 8) - (int)(packet[3] & 7)); - input_report_rel(dev, REL_HWHEEL, lscroll - rscroll); - input_report_key(dev, BTN_BACK, lscroll); - input_report_key(dev, BTN_FORWARD, rscroll); - - /* - * Standard PS/2 Mouse - */ - input_report_key(dev, BTN_LEFT, packet[0] & 1); - input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1); - input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1); - - rel_x = packet[1] ? (int)packet[1] - (int)((packet[0] << 4) & 0x100) : 0; - rel_y = packet[2] ? (int)((packet[0] << 3) & 0x100) - (int)packet[2] : 0; - - input_report_rel(dev, REL_X, rel_x); - input_report_rel(dev, REL_Y, rel_y); - break; - } - - input_sync(dev); - - return PSMOUSE_FULL_PACKET; -} - -static int fsp_activate_protocol(struct psmouse *psmouse) -{ - struct fsp_data *pad = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[2]; - int val; - - /* - * Standard procedure to enter FSP Intellimouse mode - * (scrolling wheel, 4th and 5th buttons) - */ - param[0] = 200; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - param[0] = 200; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - param[0] = 80; - ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - - ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); - if (param[0] != 0x04) { - psmouse_err(psmouse, - "Unable to enable 4 bytes packet format.\n"); - return -EIO; - } - - if (pad->ver < FSP_VER_STL3888_C0) { - /* Preparing relative coordinates output for older hardware */ - if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) { - psmouse_err(psmouse, - "Unable to read SYSCTL5 register.\n"); - return -EIO; - } - - if (fsp_get_buttons(psmouse, &pad->buttons)) { - psmouse_err(psmouse, - "Unable to retrieve number of buttons.\n"); - return -EIO; - } - - val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8); - /* Ensure we are not in absolute mode */ - val &= ~FSP_BIT_EN_PKT_G0; - if (pad->buttons == 0x06) { - /* Left/Middle/Right & Scroll Up/Down/Right/Left */ - val |= FSP_BIT_EN_MSID6; - } - - if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) { - psmouse_err(psmouse, - "Unable to set up required mode bits.\n"); - return -EIO; - } - - /* - * Enable OPC tags such that driver can tell the difference - * between on-pad and real button click - */ - if (fsp_opc_tag_enable(psmouse, true)) - psmouse_warn(psmouse, - "Failed to enable OPC tag mode.\n"); - /* enable on-pad click by default */ - pad->flags |= FSPDRV_FLAG_EN_OPC; - - /* Enable on-pad vertical and horizontal scrolling */ - fsp_onpad_vscr(psmouse, true); - fsp_onpad_hscr(psmouse, true); - } else { - /* Enable absolute coordinates output for Cx/Dx hardware */ - if (fsp_reg_write(psmouse, FSP_REG_SWC1, - FSP_BIT_SWC1_EN_ABS_1F | - FSP_BIT_SWC1_EN_ABS_2F | - FSP_BIT_SWC1_EN_FUP_OUT | - FSP_BIT_SWC1_EN_ABS_CON)) { - psmouse_err(psmouse, - "Unable to enable absolute coordinates output.\n"); - return -EIO; - } - } - - return 0; -} - -static int fsp_set_input_params(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - struct fsp_data *pad = psmouse->private; - - if (pad->ver < FSP_VER_STL3888_C0) { - __set_bit(BTN_MIDDLE, dev->keybit); - __set_bit(BTN_BACK, dev->keybit); - __set_bit(BTN_FORWARD, dev->keybit); - __set_bit(REL_WHEEL, dev->relbit); - __set_bit(REL_HWHEEL, dev->relbit); - } else { - /* - * Hardware prior to Cx performs much better in relative mode; - * hence, only enable absolute coordinates output as well as - * multi-touch output for the newer hardware. - * - * Maximum coordinates can be computed as: - * - * number of scanlines * 64 - 57 - * - * where number of X/Y scanline lines are 16/12. - */ - int abs_x = 967, abs_y = 711; - - __set_bit(EV_ABS, dev->evbit); - __clear_bit(EV_REL, dev->evbit); - __set_bit(BTN_TOUCH, dev->keybit); - __set_bit(BTN_TOOL_FINGER, dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); - __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); - - input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0); - input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0); - input_mt_init_slots(dev, 2); - input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0); - input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0); - } - - return 0; -} - -int fsp_detect(struct psmouse *psmouse, bool set_properties) -{ - int id; - - if (fsp_reg_read(psmouse, FSP_REG_DEVICE_ID, &id)) - return -EIO; - - if (id != 0x01) - return -ENODEV; - - if (set_properties) { - psmouse->vendor = "Sentelic"; - psmouse->name = "FingerSensingPad"; - } - - return 0; -} - -static void fsp_reset(struct psmouse *psmouse) -{ - fsp_opc_tag_enable(psmouse, false); - fsp_onpad_vscr(psmouse, false); - fsp_onpad_hscr(psmouse, false); -} - -static void fsp_disconnect(struct psmouse *psmouse) -{ - sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, - &fsp_attribute_group); - - fsp_reset(psmouse); - kfree(psmouse->private); -} - -static int fsp_reconnect(struct psmouse *psmouse) -{ - int version; - - if (fsp_detect(psmouse, 0)) - return -ENODEV; - - if (fsp_get_version(psmouse, &version)) - return -ENODEV; - - if (fsp_activate_protocol(psmouse)) - return -EIO; - - return 0; -} - -int fsp_init(struct psmouse *psmouse) -{ - struct fsp_data *priv; - int ver, rev; - int error; - - if (fsp_get_version(psmouse, &ver) || - fsp_get_revision(psmouse, &rev)) { - return -ENODEV; - } - - psmouse_info(psmouse, "Finger Sensing Pad, hw: %d.%d.%d, sw: %s\n", - ver >> 4, ver & 0x0F, rev, fsp_drv_ver); - - psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->ver = ver; - priv->rev = rev; - - psmouse->protocol_handler = fsp_process_byte; - psmouse->disconnect = fsp_disconnect; - psmouse->reconnect = fsp_reconnect; - psmouse->cleanup = fsp_reset; - psmouse->pktsize = 4; - - error = fsp_activate_protocol(psmouse); - if (error) - goto err_out; - - /* Set up various supported input event bits */ - error = fsp_set_input_params(psmouse); - if (error) - goto err_out; - - error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, - &fsp_attribute_group); - if (error) { - psmouse_err(psmouse, - "Failed to create sysfs attributes (%d)", error); - goto err_out; - } - - return 0; - - err_out: - kfree(psmouse->private); - psmouse->private = NULL; - return error; -} diff --git a/ANDROID_3.4.5/drivers/input/mouse/sentelic.h b/ANDROID_3.4.5/drivers/input/mouse/sentelic.h deleted file mode 100644 index 334de19e..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/sentelic.h +++ /dev/null @@ -1,130 +0,0 @@ -/*- - * Finger Sensing Pad PS/2 mouse driver. - * - * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. - * Copyright (C) 2005-2012 Tai-hwa Liang, Sentelic Corporation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __SENTELIC_H -#define __SENTELIC_H - -/* Finger-sensing Pad information registers */ -#define FSP_REG_DEVICE_ID 0x00 -#define FSP_REG_VERSION 0x01 -#define FSP_REG_REVISION 0x04 -#define FSP_REG_TMOD_STATUS1 0x0B -#define FSP_BIT_NO_ROTATION BIT(3) -#define FSP_REG_PAGE_CTRL 0x0F - -/* Finger-sensing Pad control registers */ -#define FSP_REG_SYSCTL1 0x10 -#define FSP_BIT_EN_REG_CLK BIT(5) -#define FSP_REG_TMOD_STATUS 0x20 -#define FSP_REG_OPC_QDOWN 0x31 -#define FSP_BIT_EN_OPC_TAG BIT(7) -#define FSP_REG_OPTZ_XLO 0x34 -#define FSP_REG_OPTZ_XHI 0x35 -#define FSP_REG_OPTZ_YLO 0x36 -#define FSP_REG_OPTZ_YHI 0x37 -#define FSP_REG_SYSCTL5 0x40 -#define FSP_BIT_90_DEGREE BIT(0) -#define FSP_BIT_EN_MSID6 BIT(1) -#define FSP_BIT_EN_MSID7 BIT(2) -#define FSP_BIT_EN_MSID8 BIT(3) -#define FSP_BIT_EN_AUTO_MSID8 BIT(5) -#define FSP_BIT_EN_PKT_G0 BIT(6) - -#define FSP_REG_ONPAD_CTL 0x43 -#define FSP_BIT_ONPAD_ENABLE BIT(0) -#define FSP_BIT_ONPAD_FBBB BIT(1) -#define FSP_BIT_FIX_VSCR BIT(3) -#define FSP_BIT_FIX_HSCR BIT(5) -#define FSP_BIT_DRAG_LOCK BIT(6) - -#define FSP_REG_SWC1 (0x90) -#define FSP_BIT_SWC1_EN_ABS_1F BIT(0) -#define FSP_BIT_SWC1_EN_GID BIT(1) -#define FSP_BIT_SWC1_EN_ABS_2F BIT(2) -#define FSP_BIT_SWC1_EN_FUP_OUT BIT(3) -#define FSP_BIT_SWC1_EN_ABS_CON BIT(4) -#define FSP_BIT_SWC1_GST_GRP0 BIT(5) -#define FSP_BIT_SWC1_GST_GRP1 BIT(6) -#define FSP_BIT_SWC1_BX_COMPAT BIT(7) - -/* Finger-sensing Pad packet formating related definitions */ - -/* absolute packet type */ -#define FSP_PKT_TYPE_NORMAL (0x00) -#define FSP_PKT_TYPE_ABS (0x01) -#define FSP_PKT_TYPE_NOTIFY (0x02) -#define FSP_PKT_TYPE_NORMAL_OPC (0x03) -#define FSP_PKT_TYPE_SHIFT (6) - -/* bit definitions for the first byte of report packet */ -#define FSP_PB0_LBTN BIT(0) -#define FSP_PB0_RBTN BIT(1) -#define FSP_PB0_MBTN BIT(2) -#define FSP_PB0_MFMC_FGR2 FSP_PB0_MBTN -#define FSP_PB0_MUST_SET BIT(3) -#define FSP_PB0_PHY_BTN BIT(4) -#define FSP_PB0_MFMC BIT(5) - -/* hardware revisions */ -#define FSP_VER_STL3888_A4 (0xC1) -#define FSP_VER_STL3888_B0 (0xD0) -#define FSP_VER_STL3888_B1 (0xD1) -#define FSP_VER_STL3888_B2 (0xD2) -#define FSP_VER_STL3888_C0 (0xE0) -#define FSP_VER_STL3888_C1 (0xE1) -#define FSP_VER_STL3888_D0 (0xE2) -#define FSP_VER_STL3888_D1 (0xE3) -#define FSP_VER_STL3888_E0 (0xE4) - -#ifdef __KERNEL__ - -struct fsp_data { - unsigned char ver; /* hardware version */ - unsigned char rev; /* hardware revison */ - unsigned int buttons; /* Number of buttons */ - unsigned int flags; -#define FSPDRV_FLAG_EN_OPC (0x001) /* enable on-pad clicking */ - - bool vscroll; /* Vertical scroll zone enabled */ - bool hscroll; /* Horizontal scroll zone enabled */ - - unsigned char last_reg; /* Last register we requested read from */ - unsigned char last_val; - unsigned int last_mt_fgr; /* Last seen finger(multitouch) */ -}; - -#ifdef CONFIG_MOUSE_PS2_SENTELIC -extern int fsp_detect(struct psmouse *psmouse, bool set_properties); -extern int fsp_init(struct psmouse *psmouse); -#else -inline int fsp_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -inline int fsp_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif - -#endif /* __KERNEL__ */ - -#endif /* !__SENTELIC_H */ diff --git a/ANDROID_3.4.5/drivers/input/mouse/sermouse.c b/ANDROID_3.4.5/drivers/input/mouse/sermouse.c deleted file mode 100644 index 17ff137b..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/sermouse.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (c) 1999-2001 Vojtech Pavlik - */ - -/* - * Serial mouse driver for Linux - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/input.h> -#include <linux/serio.h> -#include <linux/init.h> - -#define DRIVER_DESC "Serial mouse driver" - -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -static const char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse", - "Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse", - "Logitech MZ++ Mouse"}; - -struct sermouse { - struct input_dev *dev; - signed char buf[8]; - unsigned char count; - unsigned char type; - unsigned long last; - char phys[32]; -}; - -/* - * sermouse_process_msc() analyzes the incoming MSC/Sun bytestream and - * applies some prediction to the data, resulting in 96 updates per - * second, which is as good as a PS/2 or USB mouse. - */ - -static void sermouse_process_msc(struct sermouse *sermouse, signed char data) -{ - struct input_dev *dev = sermouse->dev; - signed char *buf = sermouse->buf; - - switch (sermouse->count) { - - case 0: - if ((data & 0xf8) != 0x80) - return; - input_report_key(dev, BTN_LEFT, !(data & 4)); - input_report_key(dev, BTN_RIGHT, !(data & 1)); - input_report_key(dev, BTN_MIDDLE, !(data & 2)); - break; - - case 1: - case 3: - input_report_rel(dev, REL_X, data / 2); - input_report_rel(dev, REL_Y, -buf[1]); - buf[0] = data - data / 2; - break; - - case 2: - case 4: - input_report_rel(dev, REL_X, buf[0]); - input_report_rel(dev, REL_Y, buf[1] - data); - buf[1] = data / 2; - break; - } - - input_sync(dev); - - if (++sermouse->count == 5) - sermouse->count = 0; -} - -/* - * sermouse_process_ms() anlyzes the incoming MS(Z/+/++) bytestream and - * generates events. With prediction it gets 80 updates/sec, assuming - * standard 3-byte packets and 1200 bps. - */ - -static void sermouse_process_ms(struct sermouse *sermouse, signed char data) -{ - struct input_dev *dev = sermouse->dev; - signed char *buf = sermouse->buf; - - if (data & 0x40) - sermouse->count = 0; - else if (sermouse->count == 0) - return; - - switch (sermouse->count) { - - case 0: - buf[1] = data; - input_report_key(dev, BTN_LEFT, (data >> 5) & 1); - input_report_key(dev, BTN_RIGHT, (data >> 4) & 1); - break; - - case 1: - buf[2] = data; - data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f)); - input_report_rel(dev, REL_X, data / 2); - input_report_rel(dev, REL_Y, buf[4]); - buf[3] = data - data / 2; - break; - - case 2: - /* Guessing the state of the middle button on 3-button MS-protocol mice - ugly. */ - if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1])) - input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key)); - buf[0] = buf[1]; - - data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f)); - input_report_rel(dev, REL_X, buf[3]); - input_report_rel(dev, REL_Y, data - buf[4]); - buf[4] = data / 2; - break; - - case 3: - - switch (sermouse->type) { - - case SERIO_MS: - sermouse->type = SERIO_MP; - - case SERIO_MP: - if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */ - input_report_key(dev, BTN_MIDDLE, (data >> 5) & 1); - input_report_key(dev, BTN_SIDE, (data >> 4) & 1); - break; - - case SERIO_MZP: - case SERIO_MZPP: - input_report_key(dev, BTN_SIDE, (data >> 5) & 1); - - case SERIO_MZ: - input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1); - input_report_rel(dev, REL_WHEEL, (data & 8) - (data & 7)); - break; - } - - break; - - case 4: - case 6: /* MZ++ packet type. We can get these bytes for M++ too but we ignore them later. */ - buf[1] = (data >> 2) & 0x0f; - break; - - case 5: - case 7: /* Ignore anything besides MZ++ */ - if (sermouse->type != SERIO_MZPP) - break; - - switch (buf[1]) { - - case 1: /* Extra mouse info */ - - input_report_key(dev, BTN_SIDE, (data >> 4) & 1); - input_report_key(dev, BTN_EXTRA, (data >> 5) & 1); - input_report_rel(dev, data & 0x80 ? REL_HWHEEL : REL_WHEEL, (data & 7) - (data & 8)); - - break; - - default: /* We don't decode anything else yet. */ - - printk(KERN_WARNING - "sermouse.c: Received MZ++ packet %x, don't know how to handle.\n", buf[1]); - break; - } - - break; - } - - input_sync(dev); - - sermouse->count++; -} - -/* - * sermouse_interrupt() handles incoming characters, either gathering them into - * packets or passing them to the command routine as command output. - */ - -static irqreturn_t sermouse_interrupt(struct serio *serio, - unsigned char data, unsigned int flags) -{ - struct sermouse *sermouse = serio_get_drvdata(serio); - - if (time_after(jiffies, sermouse->last + HZ/10)) - sermouse->count = 0; - - sermouse->last = jiffies; - - if (sermouse->type > SERIO_SUN) - sermouse_process_ms(sermouse, data); - else - sermouse_process_msc(sermouse, data); - - return IRQ_HANDLED; -} - -/* - * sermouse_disconnect() cleans up after we don't want talk - * to the mouse anymore. - */ - -static void sermouse_disconnect(struct serio *serio) -{ - struct sermouse *sermouse = serio_get_drvdata(serio); - - serio_close(serio); - serio_set_drvdata(serio, NULL); - input_unregister_device(sermouse->dev); - kfree(sermouse); -} - -/* - * sermouse_connect() is a callback form the serio module when - * an unhandled serio port is found. - */ - -static int sermouse_connect(struct serio *serio, struct serio_driver *drv) -{ - struct sermouse *sermouse; - struct input_dev *input_dev; - unsigned char c = serio->id.extra; - int err = -ENOMEM; - - sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!sermouse || !input_dev) - goto fail1; - - sermouse->dev = input_dev; - snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys); - sermouse->type = serio->id.proto; - - input_dev->name = sermouse_protocols[sermouse->type]; - input_dev->phys = sermouse->phys; - input_dev->id.bustype = BUS_RS232; - input_dev->id.vendor = sermouse->type; - input_dev->id.product = c; - input_dev->id.version = 0x0100; - input_dev->dev.parent = &serio->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_RIGHT); - input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - - if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit); - if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit); - if (c & 0x04) set_bit(BTN_EXTRA, input_dev->keybit); - if (c & 0x10) set_bit(REL_WHEEL, input_dev->relbit); - if (c & 0x20) set_bit(REL_HWHEEL, input_dev->relbit); - - serio_set_drvdata(serio, sermouse); - - err = serio_open(serio, drv); - if (err) - goto fail2; - - err = input_register_device(sermouse->dev); - if (err) - goto fail3; - - return 0; - - fail3: serio_close(serio); - fail2: serio_set_drvdata(serio, NULL); - fail1: input_free_device(input_dev); - kfree(sermouse); - return err; -} - -static struct serio_device_id sermouse_serio_ids[] = { - { - .type = SERIO_RS232, - .proto = SERIO_MSC, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { - .type = SERIO_RS232, - .proto = SERIO_SUN, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { - .type = SERIO_RS232, - .proto = SERIO_MS, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { - .type = SERIO_RS232, - .proto = SERIO_MP, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { - .type = SERIO_RS232, - .proto = SERIO_MZ, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { - .type = SERIO_RS232, - .proto = SERIO_MZP, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { - .type = SERIO_RS232, - .proto = SERIO_MZPP, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { 0 } -}; - -MODULE_DEVICE_TABLE(serio, sermouse_serio_ids); - -static struct serio_driver sermouse_drv = { - .driver = { - .name = "sermouse", - }, - .description = DRIVER_DESC, - .id_table = sermouse_serio_ids, - .interrupt = sermouse_interrupt, - .connect = sermouse_connect, - .disconnect = sermouse_disconnect, -}; - -static int __init sermouse_init(void) -{ - return serio_register_driver(&sermouse_drv); -} - -static void __exit sermouse_exit(void) -{ - serio_unregister_driver(&sermouse_drv); -} - -module_init(sermouse_init); -module_exit(sermouse_exit); diff --git a/ANDROID_3.4.5/drivers/input/mouse/synaptics.c b/ANDROID_3.4.5/drivers/input/mouse/synaptics.c deleted file mode 100644 index a4b14a41..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/synaptics.c +++ /dev/null @@ -1,1536 +0,0 @@ -/* - * 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> -#include <linux/delay.h> -#include <linux/dmi.h> -#include <linux/input/mt.h> -#include <linux/serio.h> -#include <linux/libps2.h> -#include <linux/slab.h> -#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. - * Note that newer firmware allows querying device for maximum useable - * coordinates. - */ -#define XMIN_NOMINAL 1472 -#define XMAX_NOMINAL 5472 -#define YMIN_NOMINAL 1408 -#define YMAX_NOMINAL 4448 - -/* - * 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; -} - - -/***************************************************************************** - * Stuff we need even when we do not want native Synaptics support - ****************************************************************************/ - -/* - * Set the synaptics touchpad mode byte by special commands - */ -static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode) -{ - unsigned char param[1]; - - if (psmouse_sliced_command(psmouse, mode)) - return -1; - param[0] = SYN_PS_SET_MODE2; - if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE)) - return -1; - return 0; -} - -int synaptics_detect(struct psmouse *psmouse, bool set_properties) -{ - 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 - -/***************************************************************************** - * Synaptics communications functions - ****************************************************************************/ - -/* - * Send a command to the synpatics touchpad by special commands - */ -static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param) -{ - if (psmouse_sliced_command(psmouse, c)) - return -1; - if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) - 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; -} - -/* - * 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]; - priv->ext_cap = priv->ext_cap_0c = 0; - - /* - * Older firmwares had submodel ID fixed to 0x47 - */ - if (SYN_ID_FULL(priv->identity) < 0x705 && - SYN_CAP_SUBMODEL_ID(priv->capabilities) != 0x47) { - return -1; - } - - /* - * 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)) { - psmouse_warn(psmouse, - "device claims to have extended capabilities, but I'm not able to read them.\n"); - } 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; - } - } - - if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) { - if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) { - psmouse_warn(psmouse, - "device claims to have extended capability 0x0c, but I'm not able to read it.\n"); - } else { - priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2]; - } - } - - 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; -} - -/* - * Read touchpad resolution and maximum reported coordinates - * Resolution is left zero if touchpad does not support the query - */ -static int synaptics_resolution(struct psmouse *psmouse) -{ - struct synaptics_data *priv = psmouse->private; - unsigned char resp[3]; - - if (SYN_ID_MAJOR(priv->identity) < 4) - return 0; - - 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 */ - } - } - - if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && - SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { - if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { - psmouse_warn(psmouse, - "device claims to have max coordinates query, but I'm not able to read it.\n"); - } else { - priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); - priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); - } - } - - if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 && - SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) { - if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) { - psmouse_warn(psmouse, - "device claims to have min coordinates query, but I'm not able to read it.\n"); - } else { - priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); - priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); - } - } - - return 0; -} - -static int synaptics_query_hardware(struct psmouse *psmouse) -{ - if (synaptics_identify(psmouse)) - return -1; - if (synaptics_model_id(psmouse)) - return -1; - if (synaptics_capability(psmouse)) - return -1; - if (synaptics_resolution(psmouse)) - return -1; - - return 0; -} - -static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) -{ - static unsigned char param = 0xc8; - struct synaptics_data *priv = psmouse->private; - - if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || - SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) - 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) -{ - struct synaptics_data *priv = psmouse->private; - - priv->mode = 0; - if (priv->absolute_mode) - priv->mode |= SYN_BIT_ABSOLUTE_MODE; - if (priv->disable_gesture) - priv->mode |= SYN_BIT_DISABLE_GESTURE; - if (psmouse->rate >= 80) - priv->mode |= SYN_BIT_HIGH_RATE; - if (SYN_CAP_EXTENDED(priv->capabilities)) - priv->mode |= SYN_BIT_W_MODE; - - if (synaptics_mode_cmd(psmouse, priv->mode)) - return -1; - - if (priv->absolute_mode && - synaptics_set_advanced_gesture_mode(psmouse)) { - psmouse_err(psmouse, "Advanced gesture mode init failed.\n"); - return -1; - } - - 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; -} - -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) -{ - return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; -} - -static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet) -{ - struct psmouse *child = serio_get_drvdata(ptport); - - if (child && child->state == PSMOUSE_ACTIVATED) { - serio_interrupt(ptport, packet[1], 0); - serio_interrupt(ptport, packet[4], 0); - serio_interrupt(ptport, packet[5], 0); - if (child->pktsize == 4) - serio_interrupt(ptport, packet[2], 0); - } else - serio_interrupt(ptport, packet[1], 0); -} - -static void synaptics_pt_activate(struct psmouse *psmouse) -{ - struct synaptics_data *priv = psmouse->private; - struct psmouse *child = serio_get_drvdata(priv->pt_port); - - /* adjust the touchpad to child's choice of protocol */ - if (child) { - if (child->pktsize == 4) - priv->mode |= SYN_BIT_FOUR_BYTE_CLIENT; - else - priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT; - - if (synaptics_mode_cmd(psmouse, priv->mode)) - psmouse_warn(psmouse, - "failed to switch guest protocol\n"); - } -} - -static void synaptics_pt_create(struct psmouse *psmouse) -{ - struct serio *serio; - - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); - if (!serio) { - psmouse_err(psmouse, - "not enough memory for pass-through port\n"); - 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; - serio->start = synaptics_pt_start; - serio->stop = synaptics_pt_stop; - serio->parent = psmouse->ps2dev.serio; - - psmouse->pt_activate = synaptics_pt_activate; - - psmouse_info(psmouse, "serio: %s port at %s\n", - serio->name, psmouse->phys); - serio_register_port(serio); -} - -/***************************************************************************** - * Functions to interpret the absolute mode packets - ****************************************************************************/ - -static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count, - int sgm, int agm) -{ - state->count = count; - state->sgm = sgm; - state->agm = agm; -} - -static void synaptics_parse_agm(const unsigned char buf[], - struct synaptics_data *priv, - struct synaptics_hw_state *hw) -{ - struct synaptics_hw_state *agm = &priv->agm; - 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: - /* AGM-CONTACT packet: (count, sgm, agm) */ - synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]); - break; - - default: - break; - } - - /* Record that at least one AGM has been received since last SGM */ - priv->agm_pending = true; -} - -static int synaptics_parse_hw_state(const unsigned char buf[], - struct synaptics_data *priv, - struct synaptics_hw_state *hw) -{ - 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)); - - hw->left = (buf[0] & 0x01) ? 1 : 0; - hw->right = (buf[0] & 0x02) ? 1 : 0; - - if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { - /* - * 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)) { - 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; - } - - 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]; - - if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && - ((buf[0] ^ buf[3]) & 0x02)) { - switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { - default: - /* - * if nExtBtn is greater than 8 it should be - * considered invalid and treated as 0 - */ - break; - case 8: - hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0; - hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0; - case 6: - hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0; - hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0; - case 4: - hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0; - hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0; - case 2: - hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0; - hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0; - } - } - } 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; - } - - return 0; -} - -static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot, - bool active, int x, int y) -{ - 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); - input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y)); - } -} - -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) { - 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)); - } else if (num_fingers == 1) { - synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y); - synaptics_report_semi_mt_slot(dev, 1, false, 0, 0); - } else { - synaptics_report_semi_mt_slot(dev, 0, false, 0, 0); - synaptics_report_semi_mt_slot(dev, 1, false, 0, 0); - } -} - -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; - int i; - - 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); - } - - for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) - input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i)); -} - -static void synaptics_report_slot(struct input_dev *dev, int slot, - const struct synaptics_hw_state *hw) -{ - input_mt_slot(dev, slot); - input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL)); - if (!hw) - return; - - input_report_abs(dev, ABS_MT_POSITION_X, hw->x); - input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y)); - input_report_abs(dev, ABS_MT_PRESSURE, hw->z); -} - -static void synaptics_report_mt_data(struct psmouse *psmouse, - struct synaptics_mt_state *mt_state, - const struct synaptics_hw_state *sgm) -{ - struct input_dev *dev = psmouse->dev; - struct synaptics_data *priv = psmouse->private; - struct synaptics_hw_state *agm = &priv->agm; - struct synaptics_mt_state *old = &priv->mt_state; - - switch (mt_state->count) { - case 0: - synaptics_report_slot(dev, 0, NULL); - synaptics_report_slot(dev, 1, NULL); - break; - case 1: - if (mt_state->sgm == -1) { - synaptics_report_slot(dev, 0, NULL); - synaptics_report_slot(dev, 1, NULL); - } else if (mt_state->sgm == 0) { - synaptics_report_slot(dev, 0, sgm); - synaptics_report_slot(dev, 1, NULL); - } else { - synaptics_report_slot(dev, 0, NULL); - synaptics_report_slot(dev, 1, sgm); - } - break; - default: - /* - * If the finger slot contained in SGM is valid, and either - * hasn't changed, or is new, then report SGM in MTB slot 0. - * Otherwise, empty MTB slot 0. - */ - if (mt_state->sgm != -1 && - (mt_state->sgm == old->sgm || old->sgm == -1)) - synaptics_report_slot(dev, 0, sgm); - else - synaptics_report_slot(dev, 0, NULL); - - /* - * If the finger slot contained in AGM is valid, and either - * hasn't changed, or is new, then report AGM in MTB slot 1. - * Otherwise, empty MTB slot 1. - */ - if (mt_state->agm != -1 && - (mt_state->agm == old->agm || old->agm == -1)) - synaptics_report_slot(dev, 1, agm); - else - synaptics_report_slot(dev, 1, NULL); - break; - } - - /* 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. */ - input_mt_report_finger_count(dev, mt_state->count); - - synaptics_report_buttons(psmouse, sgm); - - input_sync(dev); -} - -/* Handle case where mt_state->count = 0 */ -static void synaptics_image_sensor_0f(struct synaptics_data *priv, - struct synaptics_mt_state *mt_state) -{ - synaptics_mt_state_set(mt_state, 0, -1, -1); - priv->mt_state_lost = false; -} - -/* Handle case where mt_state->count = 1 */ -static void synaptics_image_sensor_1f(struct synaptics_data *priv, - struct synaptics_mt_state *mt_state) -{ - struct synaptics_hw_state *agm = &priv->agm; - struct synaptics_mt_state *old = &priv->mt_state; - - /* - * If the last AGM was (0,0,0), and there is only one finger left, - * then we absolutely know that SGM contains slot 0, and all other - * fingers have been removed. - */ - if (priv->agm_pending && agm->z == 0) { - synaptics_mt_state_set(mt_state, 1, 0, -1); - priv->mt_state_lost = false; - return; - } - - switch (old->count) { - case 0: - synaptics_mt_state_set(mt_state, 1, 0, -1); - break; - case 1: - /* - * If mt_state_lost, then the previous transition was 3->1, - * and SGM now contains either slot 0 or 1, but we don't know - * which. So, we just assume that the SGM now contains slot 1. - * - * If pending AGM and either: - * (a) the previous SGM slot contains slot 0, or - * (b) there was no SGM slot - * then, the SGM now contains slot 1 - * - * Case (a) happens with very rapid "drum roll" gestures, where - * slot 0 finger is lifted and a new slot 1 finger touches - * within one reporting interval. - * - * Case (b) happens if initially two or more fingers tap - * briefly, and all but one lift before the end of the first - * reporting interval. - * - * (In both these cases, slot 0 will becomes empty, so SGM - * contains slot 1 with the new finger) - * - * Else, if there was no previous SGM, it now contains slot 0. - * - * Otherwise, SGM still contains the same slot. - */ - if (priv->mt_state_lost || - (priv->agm_pending && old->sgm <= 0)) - synaptics_mt_state_set(mt_state, 1, 1, -1); - else if (old->sgm == -1) - synaptics_mt_state_set(mt_state, 1, 0, -1); - break; - case 2: - /* - * If mt_state_lost, we don't know which finger SGM contains. - * - * So, report 1 finger, but with both slots empty. - * We will use slot 1 on subsequent 1->1 - */ - if (priv->mt_state_lost) { - synaptics_mt_state_set(mt_state, 1, -1, -1); - break; - } - /* - * Since the last AGM was NOT (0,0,0), it was the finger in - * slot 0 that has been removed. - * So, SGM now contains previous AGM's slot, and AGM is now - * empty. - */ - synaptics_mt_state_set(mt_state, 1, old->agm, -1); - break; - case 3: - /* - * Since last AGM was not (0,0,0), we don't know which finger - * is left. - * - * So, report 1 finger, but with both slots empty. - * We will use slot 1 on subsequent 1->1 - */ - synaptics_mt_state_set(mt_state, 1, -1, -1); - priv->mt_state_lost = true; - break; - case 4: - case 5: - /* mt_state was updated by AGM-CONTACT packet */ - break; - } -} - -/* Handle case where mt_state->count = 2 */ -static void synaptics_image_sensor_2f(struct synaptics_data *priv, - struct synaptics_mt_state *mt_state) -{ - struct synaptics_mt_state *old = &priv->mt_state; - - switch (old->count) { - case 0: - synaptics_mt_state_set(mt_state, 2, 0, 1); - break; - case 1: - /* - * If previous SGM contained slot 1 or higher, SGM now contains - * slot 0 (the newly touching finger) and AGM contains SGM's - * previous slot. - * - * Otherwise, SGM still contains slot 0 and AGM now contains - * slot 1. - */ - if (old->sgm >= 1) - synaptics_mt_state_set(mt_state, 2, 0, old->sgm); - else - synaptics_mt_state_set(mt_state, 2, 0, 1); - break; - case 2: - /* - * If mt_state_lost, SGM now contains either finger 1 or 2, but - * we don't know which. - * So, we just assume that the SGM contains slot 0 and AGM 1. - */ - if (priv->mt_state_lost) - synaptics_mt_state_set(mt_state, 2, 0, 1); - /* - * Otherwise, use the same mt_state, since it either hasn't - * changed, or was updated by a recently received AGM-CONTACT - * packet. - */ - break; - case 3: - /* - * 3->2 transitions have two unsolvable problems: - * 1) no indication is given which finger was removed - * 2) no way to tell if agm packet was for finger 3 - * before 3->2, or finger 2 after 3->2. - * - * So, report 2 fingers, but empty all slots. - * We will guess slots [0,1] on subsequent 2->2. - */ - synaptics_mt_state_set(mt_state, 2, -1, -1); - priv->mt_state_lost = true; - break; - case 4: - case 5: - /* mt_state was updated by AGM-CONTACT packet */ - break; - } -} - -/* Handle case where mt_state->count = 3 */ -static void synaptics_image_sensor_3f(struct synaptics_data *priv, - struct synaptics_mt_state *mt_state) -{ - struct synaptics_mt_state *old = &priv->mt_state; - - switch (old->count) { - case 0: - synaptics_mt_state_set(mt_state, 3, 0, 2); - break; - case 1: - /* - * If previous SGM contained slot 2 or higher, SGM now contains - * slot 0 (one of the newly touching fingers) and AGM contains - * SGM's previous slot. - * - * Otherwise, SGM now contains slot 0 and AGM contains slot 2. - */ - if (old->sgm >= 2) - synaptics_mt_state_set(mt_state, 3, 0, old->sgm); - else - synaptics_mt_state_set(mt_state, 3, 0, 2); - break; - case 2: - /* - * If the AGM previously contained slot 3 or higher, then the - * newly touching finger is in the lowest available slot. - * - * If SGM was previously 1 or higher, then the new SGM is - * now slot 0 (with a new finger), otherwise, the new finger - * is now in a hidden slot between 0 and AGM's slot. - * - * In all such cases, the SGM now contains slot 0, and the AGM - * continues to contain the same slot as before. - */ - if (old->agm >= 3) { - synaptics_mt_state_set(mt_state, 3, 0, old->agm); - break; - } - - /* - * After some 3->1 and all 3->2 transitions, we lose track - * of which slot is reported by SGM and AGM. - * - * For 2->3 in this state, report 3 fingers, but empty all - * slots, and we will guess (0,2) on a subsequent 0->3. - * - * To userspace, the resulting transition will look like: - * 2:[0,1] -> 3:[-1,-1] -> 3:[0,2] - */ - if (priv->mt_state_lost) { - synaptics_mt_state_set(mt_state, 3, -1, -1); - break; - } - - /* - * If the (SGM,AGM) really previously contained slots (0, 1), - * then we cannot know what slot was just reported by the AGM, - * because the 2->3 transition can occur either before or after - * the AGM packet. Thus, this most recent AGM could contain - * either the same old slot 1 or the new slot 2. - * Subsequent AGMs will be reporting slot 2. - * - * To userspace, the resulting transition will look like: - * 2:[0,1] -> 3:[0,-1] -> 3:[0,2] - */ - synaptics_mt_state_set(mt_state, 3, 0, -1); - break; - case 3: - /* - * If, for whatever reason, the previous agm was invalid, - * Assume SGM now contains slot 0, AGM now contains slot 2. - */ - if (old->agm <= 2) - synaptics_mt_state_set(mt_state, 3, 0, 2); - /* - * mt_state either hasn't changed, or was updated by a recently - * received AGM-CONTACT packet. - */ - break; - - case 4: - case 5: - /* mt_state was updated by AGM-CONTACT packet */ - break; - } -} - -/* Handle case where mt_state->count = 4, or = 5 */ -static void synaptics_image_sensor_45f(struct synaptics_data *priv, - struct synaptics_mt_state *mt_state) -{ - /* mt_state was updated correctly by AGM-CONTACT packet */ - priv->mt_state_lost = false; -} - -static void synaptics_image_sensor_process(struct psmouse *psmouse, - struct synaptics_hw_state *sgm) -{ - struct synaptics_data *priv = psmouse->private; - struct synaptics_hw_state *agm = &priv->agm; - struct synaptics_mt_state mt_state; - - /* Initialize using current mt_state (as updated by last agm) */ - mt_state = agm->mt_state; - - /* - * Update mt_state using the new finger count and current mt_state. - */ - if (sgm->z == 0) - synaptics_image_sensor_0f(priv, &mt_state); - else if (sgm->w >= 4) - synaptics_image_sensor_1f(priv, &mt_state); - else if (sgm->w == 0) - synaptics_image_sensor_2f(priv, &mt_state); - else if (sgm->w == 1 && mt_state.count <= 3) - synaptics_image_sensor_3f(priv, &mt_state); - else - synaptics_image_sensor_45f(priv, &mt_state); - - /* Send resulting input events to user space */ - synaptics_report_mt_data(psmouse, &mt_state, sgm); - - /* Store updated mt_state */ - priv->mt_state = agm->mt_state = mt_state; - priv->agm_pending = false; -} - -/* - * called for each full received packet from the touchpad - */ -static void synaptics_process_packet(struct psmouse *psmouse) -{ - struct input_dev *dev = psmouse->dev; - struct synaptics_data *priv = psmouse->private; - struct synaptics_hw_state hw; - int num_fingers; - int finger_width; - - if (synaptics_parse_hw_state(psmouse->packet, priv, &hw)) - return; - - if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { - synaptics_image_sensor_process(psmouse, &hw); - return; - } - - 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; - } - - if (hw.z > 0 && hw.x > 1) { - 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; - } - - if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) - synaptics_report_semi_mt_data(dev, &hw, &priv->agm, - num_fingers); - - /* 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); - - if (num_fingers > 0) { - input_report_abs(dev, ABS_X, hw.x); - input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y)); - } - input_report_abs(dev, ABS_PRESSURE, hw.z); - - if (SYN_CAP_PALMDETECT(priv->capabilities)) - input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); - - input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); - 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); - } - - synaptics_report_buttons(psmouse, &hw); - - input_sync(dev); -} - -static int synaptics_validate_byte(struct psmouse *psmouse, - int idx, unsigned char pkt_type) -{ - 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 }; - const char *packet = psmouse->packet; - - if (idx < 0 || idx > 4) - return 0; - - switch (pkt_type) { - - case SYN_NEWABS: - case SYN_NEWABS_RELAXED: - return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx]; - - case SYN_NEWABS_STRICT: - return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx]; - - case SYN_OLDABS: - return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx]; - - default: - psmouse_err(psmouse, "unknown packet type %d\n", pkt_type); - return 0; - } -} - -static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse) -{ - int i; - - for (i = 0; i < 5; i++) - if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) { - psmouse_info(psmouse, "using relaxed packet validation\n"); - return SYN_NEWABS_RELAXED; - } - - return SYN_NEWABS_STRICT; -} - -static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) -{ - 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); - - if (SYN_CAP_PASS_THROUGH(priv->capabilities) && - synaptics_is_pt_packet(psmouse->packet)) { - if (priv->pt_port) - synaptics_pass_pt_packet(priv->pt_port, psmouse->packet); - } else - synaptics_process_packet(psmouse); - - return PSMOUSE_FULL_PACKET; - } - - return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ? - PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; -} - -/***************************************************************************** - * Driver initialization/cleanup functions - ****************************************************************************/ -static void set_abs_position_params(struct input_dev *dev, - struct synaptics_data *priv, int x_code, - int y_code) -{ - 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; - int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ? - SYN_REDUCED_FILTER_FUZZ : 0; - - 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); -} - -static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) -{ - int i; - - /* Things that apply to both modes */ - __set_bit(INPUT_PROP_POINTER, dev->propbit); - __set_bit(EV_KEY, dev->evbit); - __set_bit(BTN_LEFT, dev->keybit); - __set_bit(BTN_RIGHT, dev->keybit); - - 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 */ - __set_bit(EV_ABS, dev->evbit); - set_abs_position_params(dev, priv, ABS_X, ABS_Y); - input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); - - if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { - input_mt_init_slots(dev, 2); - 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); - - /* Image sensors can signal 4 and 5 finger clicks */ - __set_bit(BTN_TOOL_QUADTAP, dev->keybit); - __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); - } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { - /* Non-image sensors with AGM use semi-mt */ - __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); - input_mt_init_slots(dev, 2); - set_abs_position_params(dev, priv, ABS_MT_POSITION_X, - ABS_MT_POSITION_Y); - } - - if (SYN_CAP_PALMDETECT(priv->capabilities)) - input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); - - __set_bit(BTN_TOUCH, dev->keybit); - __set_bit(BTN_TOOL_FINGER, dev->keybit); - - if (SYN_CAP_MULTIFINGER(priv->capabilities)) { - __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); - __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); - } - - if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || - SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { - __set_bit(BTN_FORWARD, dev->keybit); - __set_bit(BTN_BACK, dev->keybit); - } - - for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) - __set_bit(BTN_0 + i, dev->keybit); - - __clear_bit(EV_REL, dev->evbit); - __clear_bit(REL_X, dev->relbit); - __clear_bit(REL_Y, dev->relbit); - - if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { - __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); - /* Clickpads report only left button */ - __clear_bit(BTN_RIGHT, dev->keybit); - __clear_bit(BTN_MIDDLE, dev->keybit); - } -} - -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); - -static void synaptics_disconnect(struct psmouse *psmouse) -{ - 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); - - synaptics_reset(psmouse); - kfree(priv); - psmouse->private = NULL; -} - -static int synaptics_reconnect(struct psmouse *psmouse) -{ - struct synaptics_data *priv = psmouse->private; - struct synaptics_data old_priv = *priv; - int retry = 0; - int error; - - do { - psmouse_reset(psmouse); - 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); - } - error = synaptics_detect(psmouse, 0); - } while (error && ++retry < 3); - - if (error) - return -1; - - if (retry > 1) - psmouse_dbg(psmouse, "reconnected after %d tries\n", retry); - - if (synaptics_query_hardware(psmouse)) { - psmouse_err(psmouse, "Unable to query device.\n"); - return -1; - } - - if (synaptics_set_mode(psmouse)) { - psmouse_err(psmouse, "Unable to initialize device.\n"); - return -1; - } - - 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) { - 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); - return -1; - } - - return 0; -} - -static bool impaired_toshiba_kbc; - -static const struct dmi_system_id __initconst toshiba_dmi_table[] = { -#if defined(CONFIG_DMI) && defined(CONFIG_X86) - { - /* Toshiba Satellite */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"), - }, - }, - { - /* Toshiba Dynabook */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"), - }, - }, - { - /* Toshiba Portege M300 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"), - }, - - }, - { - /* Toshiba Portege M300 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"), - }, - - }, -#endif - { } -}; - -static bool broken_olpc_ec; - -static const struct dmi_system_id __initconst olpc_dmi_table[] = { -#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 - { } -}; - -void __init synaptics_module_init(void) -{ - impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); - broken_olpc_ec = dmi_check_system(olpc_dmi_table); -} - -static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) -{ - struct synaptics_data *priv; - int err = -1; - - /* - * 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. - */ - if (absolute_mode && broken_olpc_ec) { - psmouse_info(psmouse, - "OLPC XO detected, not enabling Synaptics protocol.\n"); - return -ENODEV; - } - - psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - psmouse_reset(psmouse); - - if (synaptics_query_hardware(psmouse)) { - psmouse_err(psmouse, "Unable to query device.\n"); - goto init_fail; - } - - priv->absolute_mode = absolute_mode; - if (SYN_ID_DISGEST_SUPPORTED(priv->identity)) - priv->disable_gesture = true; - - if (synaptics_set_mode(psmouse)) { - psmouse_err(psmouse, "Unable to initialize device.\n"); - goto init_fail; - } - - priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; - - psmouse_info(psmouse, - "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", - SYN_ID_MODEL(priv->identity), - SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), - priv->model_id, - priv->capabilities, priv->ext_cap, priv->ext_cap_0c); - - set_input_params(psmouse->dev, priv); - - /* - * 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); - - 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; - } - - psmouse->set_rate = synaptics_set_rate; - psmouse->disconnect = synaptics_disconnect; - psmouse->reconnect = synaptics_reconnect; - psmouse->cleanup = synaptics_reset; - /* Synaptics can usually stay in sync without extra help */ - psmouse->resync_time = 0; - - if (SYN_CAP_PASS_THROUGH(priv->capabilities)) - synaptics_pt_create(psmouse); - - /* - * Toshiba's KBC seems to have trouble handling data from - * Synaptics at full rate. Switch to a lower rate (roughly - * the same rate as a standard PS/2 mouse). - */ - if (psmouse->rate >= 80 && impaired_toshiba_kbc) { - psmouse_info(psmouse, - "Toshiba %s detected, limiting rate to 40pps.\n", - dmi_get_system_info(DMI_PRODUCT_NAME)); - psmouse->rate = 40; - } - - 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; - } - } - - return 0; - - init_fail: - kfree(priv); - 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); -} - -bool synaptics_supported(void) -{ - return true; -} - -#else /* CONFIG_MOUSE_PS2_SYNAPTICS */ - -void __init synaptics_module_init(void) -{ -} - -int synaptics_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} - -bool synaptics_supported(void) -{ - return false; -} - -#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ diff --git a/ANDROID_3.4.5/drivers/input/mouse/synaptics.h b/ANDROID_3.4.5/drivers/input/mouse/synaptics.h deleted file mode 100644 index fd26ccca..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/synaptics.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Synaptics TouchPad PS/2 mouse driver - * - * 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. - */ - -#ifndef _SYNAPTICS_H -#define _SYNAPTICS_H - -/* synaptics queries */ -#define SYN_QUE_IDENTIFY 0x00 -#define SYN_QUE_MODES 0x01 -#define SYN_QUE_CAPABILITIES 0x02 -#define SYN_QUE_MODEL 0x03 -#define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06 -#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 -#define SYN_QUE_RESOLUTION 0x08 -#define SYN_QUE_EXT_CAPAB 0x09 -#define SYN_QUE_EXT_CAPAB_0C 0x0c -#define SYN_QUE_EXT_MAX_COORDS 0x0d -#define SYN_QUE_EXT_MIN_COORDS 0x0f - -/* synatics modes */ -#define SYN_BIT_ABSOLUTE_MODE (1 << 7) -#define SYN_BIT_HIGH_RATE (1 << 6) -#define SYN_BIT_SLEEP_MODE (1 << 3) -#define SYN_BIT_DISABLE_GESTURE (1 << 2) -#define SYN_BIT_FOUR_BYTE_CLIENT (1 << 1) -#define SYN_BIT_W_MODE (1 << 0) - -/* synaptics model ID bits */ -#define SYN_MODEL_ROT180(m) ((m) & (1 << 23)) -#define SYN_MODEL_PORTRAIT(m) ((m) & (1 << 22)) -#define SYN_MODEL_SENSOR(m) (((m) >> 16) & 0x3f) -#define SYN_MODEL_HARDWARE(m) (((m) >> 9) & 0x7f) -#define SYN_MODEL_NEWABS(m) ((m) & (1 << 7)) -#define SYN_MODEL_PEN(m) ((m) & (1 << 6)) -#define SYN_MODEL_SIMPLIC(m) ((m) & (1 << 5)) -#define SYN_MODEL_GEOMETRY(m) ((m) & 0x0f) - -/* synaptics capability bits */ -#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23)) -#define SYN_CAP_MIDDLE_BUTTON(c) ((c) & (1 << 18)) -#define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7)) -#define SYN_CAP_SLEEP(c) ((c) & (1 << 4)) -#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3)) -#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1)) -#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0)) -#define SYN_CAP_SUBMODEL_ID(c) (((c) & 0x00ff00) >> 8) -#define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) -#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) -#define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) - -/* - * The following describes response for the 0x0c query. - * - * byte mask name meaning - * ---- ---- ------- ------------ - * 1 0x01 adjustable threshold capacitive button sensitivity - * can be adjusted - * 1 0x02 report max query 0x0d gives max coord reported - * 1 0x04 clearpad sensor is ClearPad product - * 1 0x08 advanced gesture not particularly meaningful - * 1 0x10 clickpad bit 0 1-button ClickPad - * 1 0x60 multifinger mode identifies firmware finger counting - * (not reporting!) algorithm. - * Not particularly meaningful - * 1 0x80 covered pad W clipped to 14, 15 == pad mostly covered - * 2 0x01 clickpad bit 1 2-button ClickPad - * 2 0x02 deluxe LED controls touchpad support LED commands - * ala multimedia control bar - * 2 0x04 reduced filtering firmware does less filtering on - * position data, driver should watch - * for noise. - * 2 0x08 image sensor image sensor tracks 5 fingers, but only - * reports 2. - * 2 0x20 report min query 0x0f gives min coord reported - */ -#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ -#define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ -#define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) -#define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x002000) -#define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) -#define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) -#define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) - -/* synaptics modes query bits */ -#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) -#define SYN_MODE_RATE(m) ((m) & (1 << 6)) -#define SYN_MODE_BAUD_SLEEP(m) ((m) & (1 << 3)) -#define SYN_MODE_DISABLE_GESTURE(m) ((m) & (1 << 2)) -#define SYN_MODE_PACKSIZE(m) ((m) & (1 << 1)) -#define SYN_MODE_WMODE(m) ((m) & (1 << 0)) - -/* synaptics identify query bits */ -#define SYN_ID_MODEL(i) (((i) >> 4) & 0x0f) -#define SYN_ID_MAJOR(i) ((i) & 0x0f) -#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff) -#define SYN_ID_FULL(i) ((SYN_ID_MAJOR(i) << 8) | SYN_ID_MINOR(i)) -#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47) -#define SYN_ID_DISGEST_SUPPORTED(i) (SYN_ID_MAJOR(i) >= 4) - -/* synaptics special commands */ -#define SYN_PS_SET_MODE2 0x14 -#define SYN_PS_CLIENT_CMD 0x28 - -/* synaptics packet types */ -#define SYN_NEWABS 0 -#define SYN_NEWABS_STRICT 1 -#define SYN_NEWABS_RELAXED 2 -#define SYN_OLDABS 3 - -/* amount to fuzz position data when touchpad reports reduced filtering */ -#define SYN_REDUCED_FILTER_FUZZ 8 - -/* - * A structure to describe which internal touchpad finger slots are being - * reported in raw packets. - */ -struct synaptics_mt_state { - int count; /* num fingers being tracked */ - int sgm; /* which slot is reported by sgm pkt */ - int agm; /* which slot is reported by agm pkt*/ -}; - -/* - * A structure to describe the state of the touchpad hardware (buttons and pad) - */ -struct synaptics_hw_state { - int x; - int y; - int z; - int w; - unsigned int left:1; - unsigned int right:1; - unsigned int middle:1; - unsigned int up:1; - unsigned int down:1; - unsigned char ext_buttons; - signed char scroll; - - /* As reported in last AGM-CONTACT packets */ - struct synaptics_mt_state mt_state; -}; - -struct synaptics_data { - /* Data read from the touchpad */ - unsigned long int model_id; /* Model-ID */ - unsigned long int capabilities; /* Capabilities */ - unsigned long int ext_cap; /* Extended Capabilities */ - unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ - unsigned long int identity; /* Identification */ - unsigned int x_res, y_res; /* X/Y resolution in units/mm */ - unsigned int x_max, y_max; /* Max coordinates (from FW) */ - unsigned int x_min, y_min; /* Min coordinates (from FW) */ - - unsigned char pkt_type; /* packet type - old, new, etc */ - unsigned char mode; /* current mode byte */ - int scroll; - - bool absolute_mode; /* run in Absolute mode */ - bool disable_gesture; /* disable gestures */ - - struct serio *pt_port; /* Pass-through serio port */ - - struct synaptics_mt_state mt_state; /* Current mt finger state */ - bool mt_state_lost; /* mt_state may be incorrect */ - - /* - * Last received Advanced Gesture Mode (AGM) packet. An AGM packet - * contains position data for a second contact, at half resolution. - */ - struct synaptics_hw_state agm; - bool agm_pending; /* new AGM packet received */ -}; - -void synaptics_module_init(void); -int synaptics_detect(struct psmouse *psmouse, bool set_properties); -int synaptics_init(struct psmouse *psmouse); -int synaptics_init_relative(struct psmouse *psmouse); -void synaptics_reset(struct psmouse *psmouse); -bool synaptics_supported(void); - -#endif /* _SYNAPTICS_H */ diff --git a/ANDROID_3.4.5/drivers/input/mouse/synaptics_i2c.c b/ANDROID_3.4.5/drivers/input/mouse/synaptics_i2c.c deleted file mode 100644 index f1467570..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/synaptics_i2c.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Synaptics touchpad with I2C interface - * - * Copyright (C) 2009 Compulab, Ltd. - * Mike Rapoport <mike@compulab.co.il> - * Igor Grinberg <grinberg@compulab.co.il> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/input.h> -#include <linux/delay.h> -#include <linux/workqueue.h> -#include <linux/slab.h> -#include <linux/pm.h> - -#define DRIVER_NAME "synaptics_i2c" -/* maximum product id is 15 characters */ -#define PRODUCT_ID_LENGTH 15 -#define REGISTER_LENGTH 8 - -/* - * after soft reset, we should wait for 1 ms - * before the device becomes operational - */ -#define SOFT_RESET_DELAY_MS 3 -/* and after hard reset, we should wait for max 500ms */ -#define HARD_RESET_DELAY_MS 500 - -/* Registers by SMBus address */ -#define PAGE_SEL_REG 0xff -#define DEVICE_STATUS_REG 0x09 - -/* Registers by RMI address */ -#define DEV_CONTROL_REG 0x0000 -#define INTERRUPT_EN_REG 0x0001 -#define ERR_STAT_REG 0x0002 -#define INT_REQ_STAT_REG 0x0003 -#define DEV_COMMAND_REG 0x0004 - -#define RMI_PROT_VER_REG 0x0200 -#define MANUFACT_ID_REG 0x0201 -#define PHYS_INT_VER_REG 0x0202 -#define PROD_PROPERTY_REG 0x0203 -#define INFO_QUERY_REG0 0x0204 -#define INFO_QUERY_REG1 (INFO_QUERY_REG0 + 1) -#define INFO_QUERY_REG2 (INFO_QUERY_REG0 + 2) -#define INFO_QUERY_REG3 (INFO_QUERY_REG0 + 3) - -#define PRODUCT_ID_REG0 0x0210 -#define PRODUCT_ID_REG1 (PRODUCT_ID_REG0 + 1) -#define PRODUCT_ID_REG2 (PRODUCT_ID_REG0 + 2) -#define PRODUCT_ID_REG3 (PRODUCT_ID_REG0 + 3) -#define PRODUCT_ID_REG4 (PRODUCT_ID_REG0 + 4) -#define PRODUCT_ID_REG5 (PRODUCT_ID_REG0 + 5) -#define PRODUCT_ID_REG6 (PRODUCT_ID_REG0 + 6) -#define PRODUCT_ID_REG7 (PRODUCT_ID_REG0 + 7) -#define PRODUCT_ID_REG8 (PRODUCT_ID_REG0 + 8) -#define PRODUCT_ID_REG9 (PRODUCT_ID_REG0 + 9) -#define PRODUCT_ID_REG10 (PRODUCT_ID_REG0 + 10) -#define PRODUCT_ID_REG11 (PRODUCT_ID_REG0 + 11) -#define PRODUCT_ID_REG12 (PRODUCT_ID_REG0 + 12) -#define PRODUCT_ID_REG13 (PRODUCT_ID_REG0 + 13) -#define PRODUCT_ID_REG14 (PRODUCT_ID_REG0 + 14) -#define PRODUCT_ID_REG15 (PRODUCT_ID_REG0 + 15) - -#define DATA_REG0 0x0400 -#define ABS_PRESSURE_REG 0x0401 -#define ABS_MSB_X_REG 0x0402 -#define ABS_LSB_X_REG (ABS_MSB_X_REG + 1) -#define ABS_MSB_Y_REG 0x0404 -#define ABS_LSB_Y_REG (ABS_MSB_Y_REG + 1) -#define REL_X_REG 0x0406 -#define REL_Y_REG 0x0407 - -#define DEV_QUERY_REG0 0x1000 -#define DEV_QUERY_REG1 (DEV_QUERY_REG0 + 1) -#define DEV_QUERY_REG2 (DEV_QUERY_REG0 + 2) -#define DEV_QUERY_REG3 (DEV_QUERY_REG0 + 3) -#define DEV_QUERY_REG4 (DEV_QUERY_REG0 + 4) -#define DEV_QUERY_REG5 (DEV_QUERY_REG0 + 5) -#define DEV_QUERY_REG6 (DEV_QUERY_REG0 + 6) -#define DEV_QUERY_REG7 (DEV_QUERY_REG0 + 7) -#define DEV_QUERY_REG8 (DEV_QUERY_REG0 + 8) - -#define GENERAL_2D_CONTROL_REG 0x1041 -#define SENSOR_SENSITIVITY_REG 0x1044 -#define SENS_MAX_POS_MSB_REG 0x1046 -#define SENS_MAX_POS_LSB_REG (SENS_MAX_POS_UPPER_REG + 1) - -/* Register bits */ -/* Device Control Register Bits */ -#define REPORT_RATE_1ST_BIT 6 - -/* Interrupt Enable Register Bits (INTERRUPT_EN_REG) */ -#define F10_ABS_INT_ENA 0 -#define F10_REL_INT_ENA 1 -#define F20_INT_ENA 2 - -/* Interrupt Request Register Bits (INT_REQ_STAT_REG | DEVICE_STATUS_REG) */ -#define F10_ABS_INT_REQ 0 -#define F10_REL_INT_REQ 1 -#define F20_INT_REQ 2 -/* Device Status Register Bits (DEVICE_STATUS_REG) */ -#define STAT_CONFIGURED 6 -#define STAT_ERROR 7 - -/* Device Command Register Bits (DEV_COMMAND_REG) */ -#define RESET_COMMAND 0x01 -#define REZERO_COMMAND 0x02 - -/* Data Register 0 Bits (DATA_REG0) */ -#define GESTURE 3 - -/* Device Query Registers Bits */ -/* DEV_QUERY_REG3 */ -#define HAS_PALM_DETECT 1 -#define HAS_MULTI_FING 2 -#define HAS_SCROLLER 4 -#define HAS_2D_SCROLL 5 - -/* General 2D Control Register Bits (GENERAL_2D_CONTROL_REG) */ -#define NO_DECELERATION 1 -#define REDUCE_REPORTING 3 -#define NO_FILTER 5 - -/* Function Masks */ -/* Device Control Register Masks (DEV_CONTROL_REG) */ -#define REPORT_RATE_MSK 0xc0 -#define SLEEP_MODE_MSK 0x07 - -/* Device Sleep Modes */ -#define FULL_AWAKE 0x0 -#define NORMAL_OP 0x1 -#define LOW_PWR_OP 0x2 -#define VERY_LOW_PWR_OP 0x3 -#define SENS_SLEEP 0x4 -#define SLEEP_MOD 0x5 -#define DEEP_SLEEP 0x6 -#define HIBERNATE 0x7 - -/* Interrupt Register Mask */ -/* (INT_REQ_STAT_REG | DEVICE_STATUS_REG | INTERRUPT_EN_REG) */ -#define INT_ENA_REQ_MSK 0x07 -#define INT_ENA_ABS_MSK 0x01 -#define INT_ENA_REL_MSK 0x02 -#define INT_ENA_F20_MSK 0x04 - -/* Device Status Register Masks (DEVICE_STATUS_REG) */ -#define CONFIGURED_MSK 0x40 -#define ERROR_MSK 0x80 - -/* Data Register 0 Masks */ -#define FINGER_WIDTH_MSK 0xf0 -#define GESTURE_MSK 0x08 -#define SENSOR_STATUS_MSK 0x07 - -/* - * MSB Position Register Masks - * ABS_MSB_X_REG | ABS_MSB_Y_REG | SENS_MAX_POS_MSB_REG | - * DEV_QUERY_REG3 | DEV_QUERY_REG5 - */ -#define MSB_POSITION_MSK 0x1f - -/* Device Query Registers Masks */ - -/* DEV_QUERY_REG2 */ -#define NUM_EXTRA_POS_MSK 0x07 - -/* When in IRQ mode read the device every THREAD_IRQ_SLEEP_SECS */ -#define THREAD_IRQ_SLEEP_SECS 2 -#define THREAD_IRQ_SLEEP_MSECS (THREAD_IRQ_SLEEP_SECS * MSEC_PER_SEC) - -/* - * When in Polling mode and no data received for NO_DATA_THRES msecs - * reduce the polling rate to NO_DATA_SLEEP_MSECS - */ -#define NO_DATA_THRES (MSEC_PER_SEC) -#define NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) - -/* Control touchpad's No Deceleration option */ -static bool no_decel = 1; -module_param(no_decel, bool, 0644); -MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)"); - -/* Control touchpad's Reduced Reporting option */ -static bool reduce_report; -module_param(reduce_report, bool, 0644); -MODULE_PARM_DESC(reduce_report, "Reduced Reporting. Default = 0 (off)"); - -/* Control touchpad's No Filter option */ -static bool no_filter; -module_param(no_filter, bool, 0644); -MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)"); - -/* - * touchpad Attention line is Active Low and Open Drain, - * therefore should be connected to pulled up line - * and the irq configuration should be set to Falling Edge Trigger - */ -/* Control IRQ / Polling option */ -static bool polling_req; -module_param(polling_req, bool, 0444); -MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); - -/* Control Polling Rate */ -static int scan_rate = 80; -module_param(scan_rate, int, 0644); -MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 80"); - -/* The main device structure */ -struct synaptics_i2c { - struct i2c_client *client; - struct input_dev *input; - struct delayed_work dwork; - spinlock_t lock; - int no_data_count; - int no_decel_param; - int reduce_report_param; - int no_filter_param; - int scan_rate_param; - int scan_ms; -}; - -static inline void set_scan_rate(struct synaptics_i2c *touch, int scan_rate) -{ - touch->scan_ms = MSEC_PER_SEC / scan_rate; - touch->scan_rate_param = scan_rate; -} - -/* - * Driver's initial design makes no race condition possible on i2c bus, - * so there is no need in any locking. - * Keep it in mind, while playing with the code. - */ -static s32 synaptics_i2c_reg_get(struct i2c_client *client, u16 reg) -{ - int ret; - - ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); - if (ret == 0) - ret = i2c_smbus_read_byte_data(client, reg & 0xff); - - return ret; -} - -static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val) -{ - int ret; - - ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); - if (ret == 0) - ret = i2c_smbus_write_byte_data(client, reg & 0xff, val); - - return ret; -} - -static s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg) -{ - int ret; - - ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); - if (ret == 0) - ret = i2c_smbus_read_word_data(client, reg & 0xff); - - return ret; -} - -static int synaptics_i2c_config(struct i2c_client *client) -{ - int ret, control; - u8 int_en; - - /* set Report Rate to Device Highest (>=80) and Sleep to normal */ - ret = synaptics_i2c_reg_set(client, DEV_CONTROL_REG, 0xc1); - if (ret) - return ret; - - /* set Interrupt Disable to Func20 / Enable to Func10) */ - int_en = (polling_req) ? 0 : INT_ENA_ABS_MSK | INT_ENA_REL_MSK; - ret = synaptics_i2c_reg_set(client, INTERRUPT_EN_REG, int_en); - if (ret) - return ret; - - control = synaptics_i2c_reg_get(client, GENERAL_2D_CONTROL_REG); - /* No Deceleration */ - control |= no_decel ? 1 << NO_DECELERATION : 0; - /* Reduced Reporting */ - control |= reduce_report ? 1 << REDUCE_REPORTING : 0; - /* No Filter */ - control |= no_filter ? 1 << NO_FILTER : 0; - ret = synaptics_i2c_reg_set(client, GENERAL_2D_CONTROL_REG, control); - if (ret) - return ret; - - return 0; -} - -static int synaptics_i2c_reset_config(struct i2c_client *client) -{ - int ret; - - /* Reset the Touchpad */ - ret = synaptics_i2c_reg_set(client, DEV_COMMAND_REG, RESET_COMMAND); - if (ret) { - dev_err(&client->dev, "Unable to reset device\n"); - } else { - msleep(SOFT_RESET_DELAY_MS); - ret = synaptics_i2c_config(client); - if (ret) - dev_err(&client->dev, "Unable to config device\n"); - } - - return ret; -} - -static int synaptics_i2c_check_error(struct i2c_client *client) -{ - int status, ret = 0; - - status = i2c_smbus_read_byte_data(client, DEVICE_STATUS_REG) & - (CONFIGURED_MSK | ERROR_MSK); - - if (status != CONFIGURED_MSK) - ret = synaptics_i2c_reset_config(client); - - return ret; -} - -static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) -{ - struct input_dev *input = touch->input; - int xy_delta, gesture; - s32 data; - s8 x_delta, y_delta; - - /* Deal with spontanious resets and errors */ - if (synaptics_i2c_check_error(touch->client)) - return 0; - - /* Get Gesture Bit */ - data = synaptics_i2c_reg_get(touch->client, DATA_REG0); - gesture = (data >> GESTURE) & 0x1; - - /* - * Get Relative axes. we have to get them in one shot, - * so we get 2 bytes starting from REL_X_REG. - */ - xy_delta = synaptics_i2c_word_get(touch->client, REL_X_REG) & 0xffff; - - /* Separate X from Y */ - x_delta = xy_delta & 0xff; - y_delta = (xy_delta >> REGISTER_LENGTH) & 0xff; - - /* Report the button event */ - input_report_key(input, BTN_LEFT, gesture); - - /* Report the deltas */ - input_report_rel(input, REL_X, x_delta); - input_report_rel(input, REL_Y, -y_delta); - input_sync(input); - - return xy_delta || gesture; -} - -static void synaptics_i2c_reschedule_work(struct synaptics_i2c *touch, - unsigned long delay) -{ - unsigned long flags; - - spin_lock_irqsave(&touch->lock, flags); - - /* - * If work is already scheduled then subsequent schedules will not - * change the scheduled time that's why we have to cancel it first. - */ - __cancel_delayed_work(&touch->dwork); - schedule_delayed_work(&touch->dwork, delay); - - spin_unlock_irqrestore(&touch->lock, flags); -} - -static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) -{ - struct synaptics_i2c *touch = dev_id; - - synaptics_i2c_reschedule_work(touch, 0); - - return IRQ_HANDLED; -} - -static void synaptics_i2c_check_params(struct synaptics_i2c *touch) -{ - bool reset = false; - - if (scan_rate != touch->scan_rate_param) - set_scan_rate(touch, scan_rate); - - if (no_decel != touch->no_decel_param) { - touch->no_decel_param = no_decel; - reset = true; - } - - if (no_filter != touch->no_filter_param) { - touch->no_filter_param = no_filter; - reset = true; - } - - if (reduce_report != touch->reduce_report_param) { - touch->reduce_report_param = reduce_report; - reset = true; - } - - if (reset) - synaptics_i2c_reset_config(touch->client); -} - -/* Control the Device polling rate / Work Handler sleep time */ -static unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch, - bool have_data) -{ - unsigned long delay, nodata_count_thres; - - if (polling_req) { - delay = touch->scan_ms; - if (have_data) { - touch->no_data_count = 0; - } else { - nodata_count_thres = NO_DATA_THRES / touch->scan_ms; - if (touch->no_data_count < nodata_count_thres) - touch->no_data_count++; - else - delay = NO_DATA_SLEEP_MSECS; - } - return msecs_to_jiffies(delay); - } else { - delay = msecs_to_jiffies(THREAD_IRQ_SLEEP_MSECS); - return round_jiffies_relative(delay); - } -} - -/* Work Handler */ -static void synaptics_i2c_work_handler(struct work_struct *work) -{ - bool have_data; - struct synaptics_i2c *touch = - container_of(work, struct synaptics_i2c, dwork.work); - unsigned long delay; - - synaptics_i2c_check_params(touch); - - have_data = synaptics_i2c_get_input(touch); - delay = synaptics_i2c_adjust_delay(touch, have_data); - - /* - * While interrupt driven, there is no real need to poll the device. - * But touchpads are very sensitive, so there could be errors - * related to physical environment and the attention line isn't - * necessarily asserted. In such case we can lose the touchpad. - * We poll the device once in THREAD_IRQ_SLEEP_SECS and - * if error is detected, we try to reset and reconfigure the touchpad. - */ - synaptics_i2c_reschedule_work(touch, delay); -} - -static int synaptics_i2c_open(struct input_dev *input) -{ - struct synaptics_i2c *touch = input_get_drvdata(input); - int ret; - - ret = synaptics_i2c_reset_config(touch->client); - if (ret) - return ret; - - if (polling_req) - synaptics_i2c_reschedule_work(touch, - msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); - - return 0; -} - -static void synaptics_i2c_close(struct input_dev *input) -{ - struct synaptics_i2c *touch = input_get_drvdata(input); - - if (!polling_req) - synaptics_i2c_reg_set(touch->client, INTERRUPT_EN_REG, 0); - - cancel_delayed_work_sync(&touch->dwork); - - /* Save some power */ - synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); -} - -static void synaptics_i2c_set_input_params(struct synaptics_i2c *touch) -{ - struct input_dev *input = touch->input; - - input->name = touch->client->name; - input->phys = touch->client->adapter->name; - input->id.bustype = BUS_I2C; - input->id.version = synaptics_i2c_word_get(touch->client, - INFO_QUERY_REG0); - input->dev.parent = &touch->client->dev; - input->open = synaptics_i2c_open; - input->close = synaptics_i2c_close; - input_set_drvdata(input, touch); - - /* Register the device as mouse */ - __set_bit(EV_REL, input->evbit); - __set_bit(REL_X, input->relbit); - __set_bit(REL_Y, input->relbit); - - /* Register device's buttons and keys */ - __set_bit(EV_KEY, input->evbit); - __set_bit(BTN_LEFT, input->keybit); -} - -static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) -{ - struct synaptics_i2c *touch; - - touch = kzalloc(sizeof(struct synaptics_i2c), GFP_KERNEL); - if (!touch) - return NULL; - - touch->client = client; - touch->no_decel_param = no_decel; - touch->scan_rate_param = scan_rate; - set_scan_rate(touch, scan_rate); - INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); - spin_lock_init(&touch->lock); - - return touch; -} - -static int __devinit synaptics_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - int ret; - struct synaptics_i2c *touch; - - touch = synaptics_i2c_touch_create(client); - if (!touch) - return -ENOMEM; - - ret = synaptics_i2c_reset_config(client); - if (ret) - goto err_mem_free; - - if (client->irq < 1) - polling_req = true; - - touch->input = input_allocate_device(); - if (!touch->input) { - ret = -ENOMEM; - goto err_mem_free; - } - - synaptics_i2c_set_input_params(touch); - - if (!polling_req) { - dev_dbg(&touch->client->dev, - "Requesting IRQ: %d\n", touch->client->irq); - - ret = request_irq(touch->client->irq, synaptics_i2c_irq, - IRQ_TYPE_EDGE_FALLING, - DRIVER_NAME, touch); - if (ret) { - dev_warn(&touch->client->dev, - "IRQ request failed: %d, " - "falling back to polling\n", ret); - polling_req = true; - synaptics_i2c_reg_set(touch->client, - INTERRUPT_EN_REG, 0); - } - } - - if (polling_req) - dev_dbg(&touch->client->dev, - "Using polling at rate: %d times/sec\n", scan_rate); - - /* Register the device in input subsystem */ - ret = input_register_device(touch->input); - if (ret) { - dev_err(&client->dev, - "Input device register failed: %d\n", ret); - goto err_input_free; - } - - i2c_set_clientdata(client, touch); - - return 0; - -err_input_free: - input_free_device(touch->input); -err_mem_free: - kfree(touch); - - return ret; -} - -static int __devexit synaptics_i2c_remove(struct i2c_client *client) -{ - struct synaptics_i2c *touch = i2c_get_clientdata(client); - - if (!polling_req) - free_irq(client->irq, touch); - - input_unregister_device(touch->input); - kfree(touch); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int synaptics_i2c_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct synaptics_i2c *touch = i2c_get_clientdata(client); - - cancel_delayed_work_sync(&touch->dwork); - - /* Save some power */ - synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); - - return 0; -} - -static int synaptics_i2c_resume(struct device *dev) -{ - int ret; - struct i2c_client *client = to_i2c_client(dev); - struct synaptics_i2c *touch = i2c_get_clientdata(client); - - ret = synaptics_i2c_reset_config(client); - if (ret) - return ret; - - synaptics_i2c_reschedule_work(touch, - msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend, - synaptics_i2c_resume); - -static const struct i2c_device_id synaptics_i2c_id_table[] = { - { "synaptics_i2c", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table); - -static struct i2c_driver synaptics_i2c_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - .pm = &synaptics_i2c_pm, - }, - - .probe = synaptics_i2c_probe, - .remove = __devexit_p(synaptics_i2c_remove), - - .id_table = synaptics_i2c_id_table, -}; - -module_i2c_driver(synaptics_i2c_driver); - -MODULE_DESCRIPTION("Synaptics I2C touchpad driver"); -MODULE_AUTHOR("Mike Rapoport, Igor Grinberg, Compulab"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/drivers/input/mouse/synaptics_usb.c b/ANDROID_3.4.5/drivers/input/mouse/synaptics_usb.c deleted file mode 100644 index 3c5eaaa5..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/synaptics_usb.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * USB Synaptics device driver - * - * Copyright (c) 2002 Rob Miller (rob@inpharmatica . co . uk) - * Copyright (c) 2003 Ron Lee (ron@debian.org) - * cPad driver for kernel 2.4 - * - * Copyright (c) 2004 Jan Steinhoff (cpad@jan-steinhoff . de) - * Copyright (c) 2004 Ron Lee (ron@debian.org) - * rewritten for kernel 2.6 - * - * cPad display character device part is not included. It can be found at - * http://jan-steinhoff.de/linux/synaptics-usb.html - * - * Bases on: usb_skeleton.c v2.2 by Greg Kroah-Hartman - * drivers/hid/usbhid/usbmouse.c by Vojtech Pavlik - * drivers/input/mouse/synaptics.c by Peter Osterlund - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * Trademarks are the property of their respective owners. - */ - -/* - * There are three different types of Synaptics USB devices: Touchpads, - * touchsticks (or trackpoints), and touchscreens. Touchpads are well supported - * by this driver, touchstick support has not been tested much yet, and - * touchscreens have not been tested at all. - * - * Up to three alternate settings are possible: - * setting 0: one int endpoint for relative movement (used by usbhid.ko) - * setting 1: one int endpoint for absolute finger position - * setting 2 (cPad only): one int endpoint for absolute finger position and - * two bulk endpoints for the display (in/out) - * This driver uses setting 1. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/usb.h> -#include <linux/input.h> -#include <linux/usb/input.h> - -#define USB_VENDOR_ID_SYNAPTICS 0x06cb -#define USB_DEVICE_ID_SYNAPTICS_TP 0x0001 /* Synaptics USB TouchPad */ -#define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002 /* Integrated USB TouchPad */ -#define USB_DEVICE_ID_SYNAPTICS_CPAD 0x0003 /* Synaptics cPad */ -#define USB_DEVICE_ID_SYNAPTICS_TS 0x0006 /* Synaptics TouchScreen */ -#define USB_DEVICE_ID_SYNAPTICS_STICK 0x0007 /* Synaptics USB Styk */ -#define USB_DEVICE_ID_SYNAPTICS_WP 0x0008 /* Synaptics USB WheelPad */ -#define USB_DEVICE_ID_SYNAPTICS_COMP_TP 0x0009 /* Composite USB TouchPad */ -#define USB_DEVICE_ID_SYNAPTICS_WTP 0x0010 /* Wireless TouchPad */ -#define USB_DEVICE_ID_SYNAPTICS_DPAD 0x0013 /* DisplayPad */ - -#define SYNUSB_TOUCHPAD (1 << 0) -#define SYNUSB_STICK (1 << 1) -#define SYNUSB_TOUCHSCREEN (1 << 2) -#define SYNUSB_AUXDISPLAY (1 << 3) /* For cPad */ -#define SYNUSB_COMBO (1 << 4) /* Composite device (TP + stick) */ -#define SYNUSB_IO_ALWAYS (1 << 5) - -#define USB_DEVICE_SYNAPTICS(prod, kind) \ - USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, \ - USB_DEVICE_ID_SYNAPTICS_##prod), \ - .driver_info = (kind), - -#define SYNUSB_RECV_SIZE 8 - -#define XMIN_NOMINAL 1472 -#define XMAX_NOMINAL 5472 -#define YMIN_NOMINAL 1408 -#define YMAX_NOMINAL 4448 - -struct synusb { - struct usb_device *udev; - struct usb_interface *intf; - struct urb *urb; - unsigned char *data; - - /* input device related data structures */ - struct input_dev *input; - char name[128]; - char phys[64]; - - /* characteristics of the device */ - unsigned long flags; -}; - -static void synusb_report_buttons(struct synusb *synusb) -{ - struct input_dev *input_dev = synusb->input; - - input_report_key(input_dev, BTN_LEFT, synusb->data[1] & 0x04); - input_report_key(input_dev, BTN_RIGHT, synusb->data[1] & 0x01); - input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x02); -} - -static void synusb_report_stick(struct synusb *synusb) -{ - struct input_dev *input_dev = synusb->input; - int x, y; - unsigned int pressure; - - pressure = synusb->data[6]; - x = (s16)(be16_to_cpup((__be16 *)&synusb->data[2]) << 3) >> 7; - y = (s16)(be16_to_cpup((__be16 *)&synusb->data[4]) << 3) >> 7; - - if (pressure > 0) { - input_report_rel(input_dev, REL_X, x); - input_report_rel(input_dev, REL_Y, -y); - } - - input_report_abs(input_dev, ABS_PRESSURE, pressure); - - synusb_report_buttons(synusb); - - input_sync(input_dev); -} - -static void synusb_report_touchpad(struct synusb *synusb) -{ - struct input_dev *input_dev = synusb->input; - unsigned int num_fingers, tool_width; - unsigned int x, y; - unsigned int pressure, w; - - pressure = synusb->data[6]; - x = be16_to_cpup((__be16 *)&synusb->data[2]); - y = be16_to_cpup((__be16 *)&synusb->data[4]); - w = synusb->data[0] & 0x0f; - - if (pressure > 0) { - num_fingers = 1; - tool_width = 5; - switch (w) { - case 0 ... 1: - num_fingers = 2 + w; - break; - - case 2: /* pen, pretend its a finger */ - break; - - case 4 ... 15: - tool_width = w; - break; - } - } else { - num_fingers = 0; - tool_width = 0; - } - - /* - * Post events - * BTN_TOUCH has to be first as mousedev relies on it when doing - * absolute -> relative conversion - */ - - if (pressure > 30) - input_report_key(input_dev, BTN_TOUCH, 1); - if (pressure < 25) - input_report_key(input_dev, BTN_TOUCH, 0); - - if (num_fingers > 0) { - input_report_abs(input_dev, ABS_X, x); - input_report_abs(input_dev, ABS_Y, - YMAX_NOMINAL + YMIN_NOMINAL - y); - } - - input_report_abs(input_dev, ABS_PRESSURE, pressure); - input_report_abs(input_dev, ABS_TOOL_WIDTH, tool_width); - - input_report_key(input_dev, BTN_TOOL_FINGER, num_fingers == 1); - input_report_key(input_dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); - input_report_key(input_dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); - - synusb_report_buttons(synusb); - if (synusb->flags & SYNUSB_AUXDISPLAY) - input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x08); - - input_sync(input_dev); -} - -static void synusb_irq(struct urb *urb) -{ - struct synusb *synusb = urb->context; - int error; - - /* Check our status in case we need to bail out early. */ - switch (urb->status) { - case 0: - usb_mark_last_busy(synusb->udev); - break; - - /* Device went away so don't keep trying to read from it. */ - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - return; - - default: - goto resubmit; - break; - } - - if (synusb->flags & SYNUSB_STICK) - synusb_report_stick(synusb); - else - synusb_report_touchpad(synusb); - -resubmit: - error = usb_submit_urb(urb, GFP_ATOMIC); - if (error && error != -EPERM) - dev_err(&synusb->intf->dev, - "%s - usb_submit_urb failed with result: %d", - __func__, error); -} - -static struct usb_endpoint_descriptor * -synusb_get_in_endpoint(struct usb_host_interface *iface) -{ - - struct usb_endpoint_descriptor *endpoint; - int i; - - for (i = 0; i < iface->desc.bNumEndpoints; ++i) { - endpoint = &iface->endpoint[i].desc; - - if (usb_endpoint_is_int_in(endpoint)) { - /* we found our interrupt in endpoint */ - return endpoint; - } - } - - return NULL; -} - -static int synusb_open(struct input_dev *dev) -{ - struct synusb *synusb = input_get_drvdata(dev); - int retval; - - retval = usb_autopm_get_interface(synusb->intf); - if (retval) { - dev_err(&synusb->intf->dev, - "%s - usb_autopm_get_interface failed, error: %d\n", - __func__, retval); - return retval; - } - - retval = usb_submit_urb(synusb->urb, GFP_KERNEL); - if (retval) { - dev_err(&synusb->intf->dev, - "%s - usb_submit_urb failed, error: %d\n", - __func__, retval); - retval = -EIO; - goto out; - } - - synusb->intf->needs_remote_wakeup = 1; - -out: - usb_autopm_put_interface(synusb->intf); - return retval; -} - -static void synusb_close(struct input_dev *dev) -{ - struct synusb *synusb = input_get_drvdata(dev); - int autopm_error; - - autopm_error = usb_autopm_get_interface(synusb->intf); - - usb_kill_urb(synusb->urb); - synusb->intf->needs_remote_wakeup = 0; - - if (!autopm_error) - usb_autopm_put_interface(synusb->intf); -} - -static int synusb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_endpoint_descriptor *ep; - struct synusb *synusb; - struct input_dev *input_dev; - unsigned int intf_num = intf->cur_altsetting->desc.bInterfaceNumber; - unsigned int altsetting = min(intf->num_altsetting, 1U); - int error; - - error = usb_set_interface(udev, intf_num, altsetting); - if (error) { - dev_err(&udev->dev, - "Can not set alternate setting to %i, error: %i", - altsetting, error); - return error; - } - - ep = synusb_get_in_endpoint(intf->cur_altsetting); - if (!ep) - return -ENODEV; - - synusb = kzalloc(sizeof(*synusb), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!synusb || !input_dev) { - error = -ENOMEM; - goto err_free_mem; - } - - synusb->udev = udev; - synusb->intf = intf; - synusb->input = input_dev; - - synusb->flags = id->driver_info; - if (synusb->flags & SYNUSB_COMBO) { - /* - * This is a combo device, we need to set proper - * capability, depending on the interface. - */ - synusb->flags |= intf_num == 1 ? - SYNUSB_STICK : SYNUSB_TOUCHPAD; - } - - synusb->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!synusb->urb) { - error = -ENOMEM; - goto err_free_mem; - } - - synusb->data = usb_alloc_coherent(udev, SYNUSB_RECV_SIZE, GFP_KERNEL, - &synusb->urb->transfer_dma); - if (!synusb->data) { - error = -ENOMEM; - goto err_free_urb; - } - - usb_fill_int_urb(synusb->urb, udev, - usb_rcvintpipe(udev, ep->bEndpointAddress), - synusb->data, SYNUSB_RECV_SIZE, - synusb_irq, synusb, - ep->bInterval); - synusb->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - if (udev->manufacturer) - strlcpy(synusb->name, udev->manufacturer, - sizeof(synusb->name)); - - if (udev->product) { - if (udev->manufacturer) - strlcat(synusb->name, " ", sizeof(synusb->name)); - strlcat(synusb->name, udev->product, sizeof(synusb->name)); - } - - if (!strlen(synusb->name)) - snprintf(synusb->name, sizeof(synusb->name), - "USB Synaptics Device %04x:%04x", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - if (synusb->flags & SYNUSB_STICK) - strlcat(synusb->name, " (Stick) ", sizeof(synusb->name)); - - usb_make_path(udev, synusb->phys, sizeof(synusb->phys)); - strlcat(synusb->phys, "/input0", sizeof(synusb->phys)); - - input_dev->name = synusb->name; - input_dev->phys = synusb->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &synusb->intf->dev; - - if (!(synusb->flags & SYNUSB_IO_ALWAYS)) { - input_dev->open = synusb_open; - input_dev->close = synusb_close; - } - - input_set_drvdata(input_dev, synusb); - - __set_bit(EV_ABS, input_dev->evbit); - __set_bit(EV_KEY, input_dev->evbit); - - if (synusb->flags & SYNUSB_STICK) { - __set_bit(EV_REL, input_dev->evbit); - __set_bit(REL_X, input_dev->relbit); - __set_bit(REL_Y, input_dev->relbit); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); - } else { - input_set_abs_params(input_dev, ABS_X, - XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); - input_set_abs_params(input_dev, ABS_Y, - YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); - input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); - __set_bit(BTN_TOUCH, input_dev->keybit); - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); - } - - __set_bit(BTN_LEFT, input_dev->keybit); - __set_bit(BTN_RIGHT, input_dev->keybit); - __set_bit(BTN_MIDDLE, input_dev->keybit); - - usb_set_intfdata(intf, synusb); - - if (synusb->flags & SYNUSB_IO_ALWAYS) { - error = synusb_open(input_dev); - if (error) - goto err_free_dma; - } - - error = input_register_device(input_dev); - if (error) { - dev_err(&udev->dev, - "Failed to register input device, error %d\n", - error); - goto err_stop_io; - } - - return 0; - -err_stop_io: - if (synusb->flags & SYNUSB_IO_ALWAYS) - synusb_close(synusb->input); -err_free_dma: - usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data, - synusb->urb->transfer_dma); -err_free_urb: - usb_free_urb(synusb->urb); -err_free_mem: - input_free_device(input_dev); - kfree(synusb); - usb_set_intfdata(intf, NULL); - - return error; -} - -static void synusb_disconnect(struct usb_interface *intf) -{ - struct synusb *synusb = usb_get_intfdata(intf); - struct usb_device *udev = interface_to_usbdev(intf); - - if (synusb->flags & SYNUSB_IO_ALWAYS) - synusb_close(synusb->input); - - input_unregister_device(synusb->input); - - usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data, - synusb->urb->transfer_dma); - usb_free_urb(synusb->urb); - kfree(synusb); - - usb_set_intfdata(intf, NULL); -} - -static int synusb_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct synusb *synusb = usb_get_intfdata(intf); - struct input_dev *input_dev = synusb->input; - - mutex_lock(&input_dev->mutex); - usb_kill_urb(synusb->urb); - mutex_unlock(&input_dev->mutex); - - return 0; -} - -static int synusb_resume(struct usb_interface *intf) -{ - struct synusb *synusb = usb_get_intfdata(intf); - struct input_dev *input_dev = synusb->input; - int retval = 0; - - mutex_lock(&input_dev->mutex); - - if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) && - usb_submit_urb(synusb->urb, GFP_NOIO) < 0) { - retval = -EIO; - } - - mutex_unlock(&input_dev->mutex); - - return retval; -} - -static int synusb_pre_reset(struct usb_interface *intf) -{ - struct synusb *synusb = usb_get_intfdata(intf); - struct input_dev *input_dev = synusb->input; - - mutex_lock(&input_dev->mutex); - usb_kill_urb(synusb->urb); - - return 0; -} - -static int synusb_post_reset(struct usb_interface *intf) -{ - struct synusb *synusb = usb_get_intfdata(intf); - struct input_dev *input_dev = synusb->input; - int retval = 0; - - if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) && - usb_submit_urb(synusb->urb, GFP_NOIO) < 0) { - retval = -EIO; - } - - mutex_unlock(&input_dev->mutex); - - return retval; -} - -static int synusb_reset_resume(struct usb_interface *intf) -{ - return synusb_resume(intf); -} - -static struct usb_device_id synusb_idtable[] = { - { USB_DEVICE_SYNAPTICS(TP, SYNUSB_TOUCHPAD) }, - { USB_DEVICE_SYNAPTICS(INT_TP, SYNUSB_TOUCHPAD) }, - { USB_DEVICE_SYNAPTICS(CPAD, - SYNUSB_TOUCHPAD | SYNUSB_AUXDISPLAY | SYNUSB_IO_ALWAYS) }, - { USB_DEVICE_SYNAPTICS(TS, SYNUSB_TOUCHSCREEN) }, - { USB_DEVICE_SYNAPTICS(STICK, SYNUSB_STICK) }, - { USB_DEVICE_SYNAPTICS(WP, SYNUSB_TOUCHPAD) }, - { USB_DEVICE_SYNAPTICS(COMP_TP, SYNUSB_COMBO) }, - { USB_DEVICE_SYNAPTICS(WTP, SYNUSB_TOUCHPAD) }, - { USB_DEVICE_SYNAPTICS(DPAD, SYNUSB_TOUCHPAD) }, - { } -}; -MODULE_DEVICE_TABLE(usb, synusb_idtable); - -static struct usb_driver synusb_driver = { - .name = "synaptics_usb", - .probe = synusb_probe, - .disconnect = synusb_disconnect, - .id_table = synusb_idtable, - .suspend = synusb_suspend, - .resume = synusb_resume, - .pre_reset = synusb_pre_reset, - .post_reset = synusb_post_reset, - .reset_resume = synusb_reset_resume, - .supports_autosuspend = 1, -}; - -module_usb_driver(synusb_driver); - -MODULE_AUTHOR("Rob Miller <rob@inpharmatica.co.uk>, " - "Ron Lee <ron@debian.org>, " - "Jan Steinhoff <cpad@jan-steinhoff.de>"); -MODULE_DESCRIPTION("Synaptics USB device driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/input/mouse/touchkit_ps2.c b/ANDROID_3.4.5/drivers/input/mouse/touchkit_ps2.c deleted file mode 100644 index 1fd8f5e1..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/touchkit_ps2.c +++ /dev/null @@ -1,100 +0,0 @@ -/* ---------------------------------------------------------------------------- - * touchkit_ps2.c -- Driver for eGalax TouchKit PS/2 Touchscreens - * - * Copyright (C) 2005 by Stefan Lucke - * Copyright (C) 2004 by Daniel Ritz - * Copyright (C) by Todd E. Johnson (mtouchusb.c) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based upon touchkitusb.c - * - * Vendor documentation is available at: - * http://home.eeti.com.tw/web20/drivers/Software%20Programming%20Guide_v2.0.pdf - */ - -#include <linux/kernel.h> - -#include <linux/input.h> -#include <linux/serio.h> -#include <linux/libps2.h> - -#include "psmouse.h" -#include "touchkit_ps2.h" - -#define TOUCHKIT_MAX_XC 0x07ff -#define TOUCHKIT_MAX_YC 0x07ff - -#define TOUCHKIT_CMD 0x0a -#define TOUCHKIT_CMD_LENGTH 1 - -#define TOUCHKIT_CMD_ACTIVE 'A' -#define TOUCHKIT_CMD_FIRMWARE_VERSION 'D' -#define TOUCHKIT_CMD_CONTROLLER_TYPE 'E' - -#define TOUCHKIT_SEND_PARMS(s, r, c) ((s) << 12 | (r) << 8 | (c)) - -#define TOUCHKIT_GET_TOUCHED(packet) (((packet)[0]) & 0x01) -#define TOUCHKIT_GET_X(packet) (((packet)[1] << 7) | (packet)[2]) -#define TOUCHKIT_GET_Y(packet) (((packet)[3] << 7) | (packet)[4]) - -static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse) -{ - unsigned char *packet = psmouse->packet; - struct input_dev *dev = psmouse->dev; - - if (psmouse->pktcnt != 5) - return PSMOUSE_GOOD_DATA; - - input_report_abs(dev, ABS_X, TOUCHKIT_GET_X(packet)); - input_report_abs(dev, ABS_Y, TOUCHKIT_GET_Y(packet)); - input_report_key(dev, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(packet)); - input_sync(dev); - - return PSMOUSE_FULL_PACKET; -} - -int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties) -{ - struct input_dev *dev = psmouse->dev; - unsigned char param[3]; - int command; - - param[0] = TOUCHKIT_CMD_LENGTH; - param[1] = TOUCHKIT_CMD_ACTIVE; - command = TOUCHKIT_SEND_PARMS(2, 3, TOUCHKIT_CMD); - - if (ps2_command(&psmouse->ps2dev, param, command)) - return -ENODEV; - - if (param[0] != TOUCHKIT_CMD || param[1] != 0x01 || - param[2] != TOUCHKIT_CMD_ACTIVE) - return -ENODEV; - - if (set_properties) { - dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - dev->keybit[BIT_WORD(BTN_MOUSE)] = 0; - dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); - input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); - - psmouse->vendor = "eGalax"; - psmouse->name = "Touchscreen"; - psmouse->protocol_handler = touchkit_ps2_process_byte; - psmouse->pktsize = 5; - } - - return 0; -} diff --git a/ANDROID_3.4.5/drivers/input/mouse/touchkit_ps2.h b/ANDROID_3.4.5/drivers/input/mouse/touchkit_ps2.h deleted file mode 100644 index 2efe9ea2..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/touchkit_ps2.h +++ /dev/null @@ -1,25 +0,0 @@ -/* ---------------------------------------------------------------------------- - * touchkit_ps2.h -- Driver for eGalax TouchKit PS/2 Touchscreens - * - * Copyright (C) 2005 by Stefan Lucke - * Copyright (c) 2005 Vojtech Pavlik - * - * 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. - */ - -#ifndef _TOUCHKIT_PS2_H -#define _TOUCHKIT_PS2_H - -#ifdef CONFIG_MOUSE_PS2_TOUCHKIT -int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties); -#else -static inline int touchkit_ps2_detect(struct psmouse *psmouse, - bool set_properties) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_TOUCHKIT */ - -#endif diff --git a/ANDROID_3.4.5/drivers/input/mouse/trackpoint.c b/ANDROID_3.4.5/drivers/input/mouse/trackpoint.c deleted file mode 100644 index f3102494..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/trackpoint.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Stephen Evanchik <evanchsa@gmail.com> - * - * 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/slab.h> -#include <linux/delay.h> -#include <linux/serio.h> -#include <linux/module.h> -#include <linux/input.h> -#include <linux/libps2.h> -#include <linux/proc_fs.h> -#include <asm/uaccess.h> -#include "psmouse.h" -#include "trackpoint.h" - -/* - * Device IO: read, write and toggle bit - */ -static int trackpoint_read(struct ps2dev *ps2dev, unsigned char loc, unsigned char *results) -{ - if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) || - ps2_command(ps2dev, results, MAKE_PS2_CMD(0, 1, loc))) { - return -1; - } - - return 0; -} - -static int trackpoint_write(struct ps2dev *ps2dev, unsigned char loc, unsigned char val) -{ - if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) || - ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_WRITE_MEM)) || - ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) || - ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, val))) { - return -1; - } - - return 0; -} - -static int trackpoint_toggle_bit(struct ps2dev *ps2dev, unsigned char loc, unsigned char mask) -{ - /* Bad things will happen if the loc param isn't in this range */ - if (loc < 0x20 || loc >= 0x2F) - return -1; - - if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) || - ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_TOGGLE)) || - ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) || - ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, mask))) { - return -1; - } - - return 0; -} - - -/* - * Trackpoint-specific attributes - */ -struct trackpoint_attr_data { - size_t field_offset; - unsigned char command; - unsigned char mask; - unsigned char inverted; -}; - -static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf) -{ - struct trackpoint_data *tp = psmouse->private; - struct trackpoint_attr_data *attr = data; - unsigned char value = *(unsigned char *)((char *)tp + attr->field_offset); - - if (attr->inverted) - value = !value; - - return sprintf(buf, "%u\n", value); -} - -static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - struct trackpoint_data *tp = psmouse->private; - struct trackpoint_attr_data *attr = data; - unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); - unsigned char value; - int err; - - err = kstrtou8(buf, 10, &value); - if (err) - return err; - - *field = value; - trackpoint_write(&psmouse->ps2dev, attr->command, value); - - return count; -} - -#define TRACKPOINT_INT_ATTR(_name, _command) \ - static struct trackpoint_attr_data trackpoint_attr_##_name = { \ - .field_offset = offsetof(struct trackpoint_data, _name), \ - .command = _command, \ - }; \ - PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ - &trackpoint_attr_##_name, \ - trackpoint_show_int_attr, trackpoint_set_int_attr) - -static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data, - const char *buf, size_t count) -{ - struct trackpoint_data *tp = psmouse->private; - struct trackpoint_attr_data *attr = data; - unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); - unsigned int value; - int err; - - err = kstrtouint(buf, 10, &value); - if (err) - return err; - - if (value > 1) - return -EINVAL; - - if (attr->inverted) - value = !value; - - if (*field != value) { - *field = value; - trackpoint_toggle_bit(&psmouse->ps2dev, attr->command, attr->mask); - } - - return count; -} - - -#define TRACKPOINT_BIT_ATTR(_name, _command, _mask, _inv) \ - static struct trackpoint_attr_data trackpoint_attr_##_name = { \ - .field_offset = offsetof(struct trackpoint_data, _name), \ - .command = _command, \ - .mask = _mask, \ - .inverted = _inv, \ - }; \ - PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ - &trackpoint_attr_##_name, \ - trackpoint_show_int_attr, trackpoint_set_bit_attr) - -TRACKPOINT_INT_ATTR(sensitivity, TP_SENS); -TRACKPOINT_INT_ATTR(speed, TP_SPEED); -TRACKPOINT_INT_ATTR(inertia, TP_INERTIA); -TRACKPOINT_INT_ATTR(reach, TP_REACH); -TRACKPOINT_INT_ATTR(draghys, TP_DRAGHYS); -TRACKPOINT_INT_ATTR(mindrag, TP_MINDRAG); -TRACKPOINT_INT_ATTR(thresh, TP_THRESH); -TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH); -TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME); -TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV); - -TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON, 0); -TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK, 0); -TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV, 1); - -static struct attribute *trackpoint_attrs[] = { - &psmouse_attr_sensitivity.dattr.attr, - &psmouse_attr_speed.dattr.attr, - &psmouse_attr_inertia.dattr.attr, - &psmouse_attr_reach.dattr.attr, - &psmouse_attr_draghys.dattr.attr, - &psmouse_attr_mindrag.dattr.attr, - &psmouse_attr_thresh.dattr.attr, - &psmouse_attr_upthresh.dattr.attr, - &psmouse_attr_ztime.dattr.attr, - &psmouse_attr_jenks.dattr.attr, - &psmouse_attr_press_to_select.dattr.attr, - &psmouse_attr_skipback.dattr.attr, - &psmouse_attr_ext_dev.dattr.attr, - NULL -}; - -static struct attribute_group trackpoint_attr_group = { - .attrs = trackpoint_attrs, -}; - -static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *firmware_id) -{ - unsigned char param[2] = { 0 }; - - if (ps2_command(&psmouse->ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID))) - return -1; - - if (param[0] != TP_MAGIC_IDENT) - return -1; - - if (firmware_id) - *firmware_id = param[1]; - - return 0; -} - -static int trackpoint_sync(struct psmouse *psmouse) -{ - struct trackpoint_data *tp = psmouse->private; - unsigned char toggle; - - /* Disable features that may make device unusable with this driver */ - trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle); - if (toggle & TP_MASK_TWOHAND) - trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, TP_MASK_TWOHAND); - - trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, &toggle); - if (toggle & TP_MASK_SOURCE_TAG) - trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, TP_MASK_SOURCE_TAG); - - trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_MB, &toggle); - if (toggle & TP_MASK_MB) - trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_MB, TP_MASK_MB); - - /* Push the config to the device */ - trackpoint_write(&psmouse->ps2dev, TP_SENS, tp->sensitivity); - trackpoint_write(&psmouse->ps2dev, TP_INERTIA, tp->inertia); - trackpoint_write(&psmouse->ps2dev, TP_SPEED, tp->speed); - - trackpoint_write(&psmouse->ps2dev, TP_REACH, tp->reach); - trackpoint_write(&psmouse->ps2dev, TP_DRAGHYS, tp->draghys); - trackpoint_write(&psmouse->ps2dev, TP_MINDRAG, tp->mindrag); - - trackpoint_write(&psmouse->ps2dev, TP_THRESH, tp->thresh); - trackpoint_write(&psmouse->ps2dev, TP_UP_THRESH, tp->upthresh); - - trackpoint_write(&psmouse->ps2dev, TP_Z_TIME, tp->ztime); - trackpoint_write(&psmouse->ps2dev, TP_JENKS_CURV, tp->jenks); - - trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_PTSON, &toggle); - if (((toggle & TP_MASK_PTSON) == TP_MASK_PTSON) != tp->press_to_select) - trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_PTSON, TP_MASK_PTSON); - - trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, &toggle); - if (((toggle & TP_MASK_SKIPBACK) == TP_MASK_SKIPBACK) != tp->skipback) - trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK); - - trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, &toggle); - if (((toggle & TP_MASK_EXT_DEV) == TP_MASK_EXT_DEV) != tp->ext_dev) - trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV); - - return 0; -} - -static void trackpoint_defaults(struct trackpoint_data *tp) -{ - tp->press_to_select = TP_DEF_PTSON; - tp->sensitivity = TP_DEF_SENS; - tp->speed = TP_DEF_SPEED; - tp->reach = TP_DEF_REACH; - - tp->draghys = TP_DEF_DRAGHYS; - tp->mindrag = TP_DEF_MINDRAG; - - tp->thresh = TP_DEF_THRESH; - tp->upthresh = TP_DEF_UP_THRESH; - - tp->ztime = TP_DEF_Z_TIME; - tp->jenks = TP_DEF_JENKS_CURV; - - tp->inertia = TP_DEF_INERTIA; - tp->skipback = TP_DEF_SKIPBACK; - tp->ext_dev = TP_DEF_EXT_DEV; -} - -static void trackpoint_disconnect(struct psmouse *psmouse) -{ - sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group); - - kfree(psmouse->private); - psmouse->private = NULL; -} - -static int trackpoint_reconnect(struct psmouse *psmouse) -{ - if (trackpoint_start_protocol(psmouse, NULL)) - return -1; - - if (trackpoint_sync(psmouse)) - return -1; - - return 0; -} - -int trackpoint_detect(struct psmouse *psmouse, bool set_properties) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char firmware_id; - unsigned char button_info; - int error; - - if (trackpoint_start_protocol(psmouse, &firmware_id)) - return -1; - - if (!set_properties) - return 0; - - if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) { - psmouse_warn(psmouse, "failed to get extended button data\n"); - button_info = 0; - } - - psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); - if (!psmouse->private) - return -ENOMEM; - - psmouse->vendor = "IBM"; - psmouse->name = "TrackPoint"; - - psmouse->reconnect = trackpoint_reconnect; - psmouse->disconnect = trackpoint_disconnect; - - if ((button_info & 0x0f) >= 3) - __set_bit(BTN_MIDDLE, psmouse->dev->keybit); - - trackpoint_defaults(psmouse->private); - trackpoint_sync(psmouse); - - error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group); - if (error) { - psmouse_err(psmouse, - "failed to create sysfs attributes, error: %d\n", - error); - kfree(psmouse->private); - psmouse->private = NULL; - return -1; - } - - psmouse_info(psmouse, - "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n", - firmware_id, - (button_info & 0xf0) >> 4, button_info & 0x0f); - - return 0; -} - diff --git a/ANDROID_3.4.5/drivers/input/mouse/trackpoint.h b/ANDROID_3.4.5/drivers/input/mouse/trackpoint.h deleted file mode 100644 index e558a709..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/trackpoint.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * IBM TrackPoint PS/2 mouse driver - * - * Stephen Evanchik <evanchsa@gmail.com> - * - * 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. - */ - -#ifndef _TRACKPOINT_H -#define _TRACKPOINT_H - -/* - * These constants are from the TrackPoint System - * Engineering documentation Version 4 from IBM Watson - * research: - * http://wwwcssrv.almaden.ibm.com/trackpoint/download.html - */ - -#define TP_COMMAND 0xE2 /* Commands start with this */ - -#define TP_READ_ID 0xE1 /* Sent for device identification */ -#define TP_MAGIC_IDENT 0x01 /* Sent after a TP_READ_ID followed */ - /* by the firmware ID */ - - -/* - * Commands - */ -#define TP_RECALIB 0x51 /* Recalibrate */ -#define TP_POWER_DOWN 0x44 /* Can only be undone through HW reset */ -#define TP_EXT_DEV 0x21 /* Determines if external device is connected (RO) */ -#define TP_EXT_BTN 0x4B /* Read extended button status */ -#define TP_POR 0x7F /* Execute Power on Reset */ -#define TP_POR_RESULTS 0x25 /* Read Power on Self test results */ -#define TP_DISABLE_EXT 0x40 /* Disable external pointing device */ -#define TP_ENABLE_EXT 0x41 /* Enable external pointing device */ - -/* - * Mode manipulation - */ -#define TP_SET_SOFT_TRANS 0x4E /* Set mode */ -#define TP_CANCEL_SOFT_TRANS 0xB9 /* Cancel mode */ -#define TP_SET_HARD_TRANS 0x45 /* Mode can only be set */ - - -/* - * Register oriented commands/properties - */ -#define TP_WRITE_MEM 0x81 -#define TP_READ_MEM 0x80 /* Not used in this implementation */ - -/* -* RAM Locations for properties - */ -#define TP_SENS 0x4A /* Sensitivity */ -#define TP_MB 0x4C /* Read Middle Button Status (RO) */ -#define TP_INERTIA 0x4D /* Negative Inertia */ -#define TP_SPEED 0x60 /* Speed of TP Cursor */ -#define TP_REACH 0x57 /* Backup for Z-axis press */ -#define TP_DRAGHYS 0x58 /* Drag Hysteresis */ - /* (how hard it is to drag */ - /* with Z-axis pressed) */ - -#define TP_MINDRAG 0x59 /* Minimum amount of force needed */ - /* to trigger dragging */ - -#define TP_THRESH 0x5C /* Minimum value for a Z-axis press */ -#define TP_UP_THRESH 0x5A /* Used to generate a 'click' on Z-axis */ -#define TP_Z_TIME 0x5E /* How sharp of a press */ -#define TP_JENKS_CURV 0x5D /* Minimum curvature for double click */ - -/* - * Toggling Flag bits - */ -#define TP_TOGGLE 0x47 /* Toggle command */ - -#define TP_TOGGLE_MB 0x23 /* Disable/Enable Middle Button */ -#define TP_MASK_MB 0x01 -#define TP_TOGGLE_EXT_DEV 0x23 /* Disable external device */ -#define TP_MASK_EXT_DEV 0x02 -#define TP_TOGGLE_DRIFT 0x23 /* Drift Correction */ -#define TP_MASK_DRIFT 0x80 -#define TP_TOGGLE_BURST 0x28 /* Burst Mode */ -#define TP_MASK_BURST 0x80 -#define TP_TOGGLE_PTSON 0x2C /* Press to Select */ -#define TP_MASK_PTSON 0x01 -#define TP_TOGGLE_HARD_TRANS 0x2C /* Alternate method to set Hard Transparency */ -#define TP_MASK_HARD_TRANS 0x80 -#define TP_TOGGLE_TWOHAND 0x2D /* Two handed */ -#define TP_MASK_TWOHAND 0x01 -#define TP_TOGGLE_STICKY_TWO 0x2D /* Sticky two handed */ -#define TP_MASK_STICKY_TWO 0x04 -#define TP_TOGGLE_SKIPBACK 0x2D /* Suppress movement after drag release */ -#define TP_MASK_SKIPBACK 0x08 -#define TP_TOGGLE_SOURCE_TAG 0x20 /* Bit 3 of the first packet will be set to - to the origin of the packet (external or TP) */ -#define TP_MASK_SOURCE_TAG 0x80 -#define TP_TOGGLE_EXT_TAG 0x22 /* Bit 3 of the first packet coming from the - external device will be forced to 1 */ -#define TP_MASK_EXT_TAG 0x04 - - -/* Power on Self Test Results */ -#define TP_POR_SUCCESS 0x3B - -/* - * Default power on values - */ -#define TP_DEF_SENS 0x80 -#define TP_DEF_INERTIA 0x06 -#define TP_DEF_SPEED 0x61 -#define TP_DEF_REACH 0x0A - -#define TP_DEF_DRAGHYS 0xFF -#define TP_DEF_MINDRAG 0x14 - -#define TP_DEF_THRESH 0x08 -#define TP_DEF_UP_THRESH 0xFF -#define TP_DEF_Z_TIME 0x26 -#define TP_DEF_JENKS_CURV 0x87 - -/* Toggles */ -#define TP_DEF_MB 0x00 -#define TP_DEF_PTSON 0x00 -#define TP_DEF_SKIPBACK 0x00 -#define TP_DEF_EXT_DEV 0x00 /* 0 means enabled */ - -#define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd)) - -struct trackpoint_data -{ - unsigned char sensitivity, speed, inertia, reach; - unsigned char draghys, mindrag; - unsigned char thresh, upthresh; - unsigned char ztime, jenks; - - unsigned char press_to_select; - unsigned char skipback; - - unsigned char ext_dev; -}; - -#ifdef CONFIG_MOUSE_PS2_TRACKPOINT -int trackpoint_detect(struct psmouse *psmouse, bool set_properties); -#else -inline int trackpoint_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_TRACKPOINT */ - -#endif /* _TRACKPOINT_H */ diff --git a/ANDROID_3.4.5/drivers/input/mouse/vsxxxaa.c b/ANDROID_3.4.5/drivers/input/mouse/vsxxxaa.c deleted file mode 100644 index eb9a3cfb..00000000 --- a/ANDROID_3.4.5/drivers/input/mouse/vsxxxaa.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers) - * DEC VSXXX-GA mouse (rectangular mouse, with ball) - * DEC VSXXX-AB tablet (digitizer with hair cross or stylus) - * - * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de> - * - * The packet format was initially taken from a patch to GPM which is (C) 2001 - * by Karsten Merker <merker@linuxtag.org> - * and Maciej W. Rozycki <macro@ds2.pg.gda.pl> - * Later on, I had access to the device's documentation (referenced below). - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Building an adaptor to DE9 / DB25 RS232 - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * DISCLAIMER: Use this description AT YOUR OWN RISK! I'll not pay for - * anything if you break your mouse, your computer or whatever! - * - * In theory, this mouse is a simple RS232 device. In practice, it has got - * a quite uncommon plug and the requirement to additionally get a power - * supply at +5V and -12V. - * - * If you look at the socket/jack (_not_ at the plug), we use this pin - * numbering: - * _______ - * / 7 6 5 \ - * | 4 --- 3 | - * \ 2 1 / - * ------- - * - * DEC socket DE9 DB25 Note - * 1 (GND) 5 7 - - * 2 (RxD) 2 3 - - * 3 (TxD) 3 2 - - * 4 (-12V) - - Somewhere from the PSU. At ATX, it's - * the thin blue wire at pin 12 of the - * ATX power connector. Only required for - * VSXXX-AA/-GA mice. - * 5 (+5V) - - PSU (red wires of ATX power connector - * on pin 4, 6, 19 or 20) or HDD power - * connector (also red wire). - * 6 (+12V) - - HDD power connector, yellow wire. Only - * required for VSXXX-AB digitizer. - * 7 (dev. avail.) - - The mouse shorts this one to pin 1. - * This way, the host computer can detect - * the mouse. To use it with the adaptor, - * simply don't connect this pin. - * - * So to get a working adaptor, you need to connect the mouse with three - * wires to a RS232 port and two or three additional wires for +5V, +12V and - * -12V to the PSU. - * - * Flow specification for the link is 4800, 8o1. - * - * The mice and tablet are described in "VCB02 Video Subsystem - Technical - * Manual", DEC EK-104AA-TM-001. You'll find it at MANX, a search engine - * specific for DEC documentation. Try - * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1 - */ - -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/input.h> -#include <linux/serio.h> -#include <linux/init.h> - -#define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet" - -MODULE_AUTHOR("Jan-Benedict Glaw <jbglaw@lug-owl.de>"); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -#undef VSXXXAA_DEBUG -#ifdef VSXXXAA_DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) do {} while (0) -#endif - -#define VSXXXAA_INTRO_MASK 0x80 -#define VSXXXAA_INTRO_HEAD 0x80 -#define IS_HDR_BYTE(x) \ - (((x) & VSXXXAA_INTRO_MASK) == VSXXXAA_INTRO_HEAD) - -#define VSXXXAA_PACKET_MASK 0xe0 -#define VSXXXAA_PACKET_REL 0x80 -#define VSXXXAA_PACKET_ABS 0xc0 -#define VSXXXAA_PACKET_POR 0xa0 -#define MATCH_PACKET_TYPE(data, type) \ - (((data) & VSXXXAA_PACKET_MASK) == (type)) - - - -struct vsxxxaa { - struct input_dev *dev; - struct serio *serio; -#define BUFLEN 15 /* At least 5 is needed for a full tablet packet */ - unsigned char buf[BUFLEN]; - unsigned char count; - unsigned char version; - unsigned char country; - unsigned char type; - char name[64]; - char phys[32]; -}; - -static void vsxxxaa_drop_bytes(struct vsxxxaa *mouse, int num) -{ - if (num >= mouse->count) { - mouse->count = 0; - } else { - memmove(mouse->buf, mouse->buf + num - 1, BUFLEN - num); - mouse->count -= num; - } -} - -static void vsxxxaa_queue_byte(struct vsxxxaa *mouse, unsigned char byte) -{ - if (mouse->count == BUFLEN) { - printk(KERN_ERR "%s on %s: Dropping a byte of full buffer.\n", - mouse->name, mouse->phys); - vsxxxaa_drop_bytes(mouse, 1); - } - - DBG(KERN_INFO "Queueing byte 0x%02x\n", byte); - - mouse->buf[mouse->count++] = byte; -} - -static void vsxxxaa_detection_done(struct vsxxxaa *mouse) -{ - switch (mouse->type) { - case 0x02: - strlcpy(mouse->name, "DEC VSXXX-AA/-GA mouse", - sizeof(mouse->name)); - break; - - case 0x04: - strlcpy(mouse->name, "DEC VSXXX-AB digitizer", - sizeof(mouse->name)); - break; - - default: - snprintf(mouse->name, sizeof(mouse->name), - "unknown DEC pointer device (type = 0x%02x)", - mouse->type); - break; - } - - printk(KERN_INFO - "Found %s version 0x%02x from country 0x%02x on port %s\n", - mouse->name, mouse->version, mouse->country, mouse->phys); -} - -/* - * Returns number of bytes to be dropped, 0 if packet is okay. - */ -static int vsxxxaa_check_packet(struct vsxxxaa *mouse, int packet_len) -{ - int i; - - /* First byte must be a header byte */ - if (!IS_HDR_BYTE(mouse->buf[0])) { - DBG("vsck: len=%d, 1st=0x%02x\n", packet_len, mouse->buf[0]); - return 1; - } - - /* Check all following bytes */ - for (i = 1; i < packet_len; i++) { - if (IS_HDR_BYTE(mouse->buf[i])) { - printk(KERN_ERR - "Need to drop %d bytes of a broken packet.\n", - i - 1); - DBG(KERN_INFO "check: len=%d, b[%d]=0x%02x\n", - packet_len, i, mouse->buf[i]); - return i - 1; - } - } - - return 0; -} - -static inline int vsxxxaa_smells_like_packet(struct vsxxxaa *mouse, - unsigned char type, size_t len) -{ - return mouse->count >= len && MATCH_PACKET_TYPE(mouse->buf[0], type); -} - -static void vsxxxaa_handle_REL_packet(struct vsxxxaa *mouse) -{ - struct input_dev *dev = mouse->dev; - unsigned char *buf = mouse->buf; - int left, middle, right; - int dx, dy; - - /* - * Check for normal stream packets. This is three bytes, - * with the first byte's 3 MSB set to 100. - * - * [0]: 1 0 0 SignX SignY Left Middle Right - * [1]: 0 dx dx dx dx dx dx dx - * [2]: 0 dy dy dy dy dy dy dy - */ - - /* - * Low 7 bit of byte 1 are abs(dx), bit 7 is - * 0, bit 4 of byte 0 is direction. - */ - dx = buf[1] & 0x7f; - dx *= ((buf[0] >> 4) & 0x01) ? 1 : -1; - - /* - * Low 7 bit of byte 2 are abs(dy), bit 7 is - * 0, bit 3 of byte 0 is direction. - */ - dy = buf[2] & 0x7f; - dy *= ((buf[0] >> 3) & 0x01) ? -1 : 1; - - /* - * Get button state. It's the low three bits - * (for three buttons) of byte 0. - */ - left = buf[0] & 0x04; - middle = buf[0] & 0x02; - right = buf[0] & 0x01; - - vsxxxaa_drop_bytes(mouse, 3); - - DBG(KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n", - mouse->name, mouse->phys, dx, dy, - left ? "L" : "l", middle ? "M" : "m", right ? "R" : "r"); - - /* - * Report what we've found so far... - */ - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_MIDDLE, middle); - input_report_key(dev, BTN_RIGHT, right); - input_report_key(dev, BTN_TOUCH, 0); - input_report_rel(dev, REL_X, dx); - input_report_rel(dev, REL_Y, dy); - input_sync(dev); -} - -static void vsxxxaa_handle_ABS_packet(struct vsxxxaa *mouse) -{ - struct input_dev *dev = mouse->dev; - unsigned char *buf = mouse->buf; - int left, middle, right, touch; - int x, y; - - /* - * Tablet position / button packet - * - * [0]: 1 1 0 B4 B3 B2 B1 Pr - * [1]: 0 0 X5 X4 X3 X2 X1 X0 - * [2]: 0 0 X11 X10 X9 X8 X7 X6 - * [3]: 0 0 Y5 Y4 Y3 Y2 Y1 Y0 - * [4]: 0 0 Y11 Y10 Y9 Y8 Y7 Y6 - */ - - /* - * Get X/Y position. Y axis needs to be inverted since VSXXX-AB - * counts down->top while monitor counts top->bottom. - */ - x = ((buf[2] & 0x3f) << 6) | (buf[1] & 0x3f); - y = ((buf[4] & 0x3f) << 6) | (buf[3] & 0x3f); - y = 1023 - y; - - /* - * Get button state. It's bits <4..1> of byte 0. - */ - left = buf[0] & 0x02; - middle = buf[0] & 0x04; - right = buf[0] & 0x08; - touch = buf[0] & 0x10; - - vsxxxaa_drop_bytes(mouse, 5); - - DBG(KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n", - mouse->name, mouse->phys, x, y, - left ? "L" : "l", middle ? "M" : "m", - right ? "R" : "r", touch ? "T" : "t"); - - /* - * Report what we've found so far... - */ - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_MIDDLE, middle); - input_report_key(dev, BTN_RIGHT, right); - input_report_key(dev, BTN_TOUCH, touch); - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - input_sync(dev); -} - -static void vsxxxaa_handle_POR_packet(struct vsxxxaa *mouse) -{ - struct input_dev *dev = mouse->dev; - unsigned char *buf = mouse->buf; - int left, middle, right; - unsigned char error; - - /* - * Check for Power-On-Reset packets. These are sent out - * after plugging the mouse in, or when explicitly - * requested by sending 'T'. - * - * [0]: 1 0 1 0 R3 R2 R1 R0 - * [1]: 0 M2 M1 M0 D3 D2 D1 D0 - * [2]: 0 E6 E5 E4 E3 E2 E1 E0 - * [3]: 0 0 0 0 0 Left Middle Right - * - * M: manufacturer location code - * R: revision code - * E: Error code. If it's in the range of 0x00..0x1f, only some - * minor problem occurred. Errors >= 0x20 are considered bad - * and the device may not work properly... - * D: <0010> == mouse, <0100> == tablet - */ - - mouse->version = buf[0] & 0x0f; - mouse->country = (buf[1] >> 4) & 0x07; - mouse->type = buf[1] & 0x0f; - error = buf[2] & 0x7f; - - /* - * Get button state. It's the low three bits - * (for three buttons) of byte 0. Maybe even the bit <3> - * has some meaning if a tablet is attached. - */ - left = buf[0] & 0x04; - middle = buf[0] & 0x02; - right = buf[0] & 0x01; - - vsxxxaa_drop_bytes(mouse, 4); - vsxxxaa_detection_done(mouse); - - if (error <= 0x1f) { - /* No (serious) error. Report buttons */ - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_MIDDLE, middle); - input_report_key(dev, BTN_RIGHT, right); - input_report_key(dev, BTN_TOUCH, 0); - input_sync(dev); - - if (error != 0) - printk(KERN_INFO "Your %s on %s reports error=0x%02x\n", - mouse->name, mouse->phys, error); - - } - - /* - * If the mouse was hot-plugged, we need to force differential mode - * now... However, give it a second to recover from it's reset. - */ - printk(KERN_NOTICE - "%s on %s: Forcing standard packet format, " - "incremental streaming mode and 72 samples/sec\n", - mouse->name, mouse->phys); - serio_write(mouse->serio, 'S'); /* Standard format */ - mdelay(50); - serio_write(mouse->serio, 'R'); /* Incremental */ - mdelay(50); - serio_write(mouse->serio, 'L'); /* 72 samples/sec */ -} - -static void vsxxxaa_parse_buffer(struct vsxxxaa *mouse) -{ - unsigned char *buf = mouse->buf; - int stray_bytes; - - /* - * Parse buffer to death... - */ - do { - /* - * Out of sync? Throw away what we don't understand. Each - * packet starts with a byte whose bit 7 is set. Unhandled - * packets (ie. which we don't know about or simply b0rk3d - * data...) will get shifted out of the buffer after some - * activity on the mouse. - */ - while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) { - printk(KERN_ERR "%s on %s: Dropping a byte to regain " - "sync with mouse data stream...\n", - mouse->name, mouse->phys); - vsxxxaa_drop_bytes(mouse, 1); - } - - /* - * Check for packets we know about. - */ - - if (vsxxxaa_smells_like_packet(mouse, VSXXXAA_PACKET_REL, 3)) { - /* Check for broken packet */ - stray_bytes = vsxxxaa_check_packet(mouse, 3); - if (!stray_bytes) - vsxxxaa_handle_REL_packet(mouse); - - } else if (vsxxxaa_smells_like_packet(mouse, - VSXXXAA_PACKET_ABS, 5)) { - /* Check for broken packet */ - stray_bytes = vsxxxaa_check_packet(mouse, 5); - if (!stray_bytes) - vsxxxaa_handle_ABS_packet(mouse); - - } else if (vsxxxaa_smells_like_packet(mouse, - VSXXXAA_PACKET_POR, 4)) { - /* Check for broken packet */ - stray_bytes = vsxxxaa_check_packet(mouse, 4); - if (!stray_bytes) - vsxxxaa_handle_POR_packet(mouse); - - } else { - break; /* No REL, ABS or POR packet found */ - } - - if (stray_bytes > 0) { - printk(KERN_ERR "Dropping %d bytes now...\n", - stray_bytes); - vsxxxaa_drop_bytes(mouse, stray_bytes); - } - - } while (1); -} - -static irqreturn_t vsxxxaa_interrupt(struct serio *serio, - unsigned char data, unsigned int flags) -{ - struct vsxxxaa *mouse = serio_get_drvdata(serio); - - vsxxxaa_queue_byte(mouse, data); - vsxxxaa_parse_buffer(mouse); - - return IRQ_HANDLED; -} - -static void vsxxxaa_disconnect(struct serio *serio) -{ - struct vsxxxaa *mouse = serio_get_drvdata(serio); - - serio_close(serio); - serio_set_drvdata(serio, NULL); - input_unregister_device(mouse->dev); - kfree(mouse); -} - -static int vsxxxaa_connect(struct serio *serio, struct serio_driver *drv) -{ - struct vsxxxaa *mouse; - struct input_dev *input_dev; - int err = -ENOMEM; - - mouse = kzalloc(sizeof(struct vsxxxaa), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!mouse || !input_dev) - goto fail1; - - mouse->dev = input_dev; - mouse->serio = serio; - strlcat(mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer", - sizeof(mouse->name)); - snprintf(mouse->phys, sizeof(mouse->phys), "%s/input0", serio->phys); - - input_dev->name = mouse->name; - input_dev->phys = mouse->phys; - input_dev->id.bustype = BUS_RS232; - input_dev->dev.parent = &serio->dev; - - __set_bit(EV_KEY, input_dev->evbit); /* We have buttons */ - __set_bit(EV_REL, input_dev->evbit); - __set_bit(EV_ABS, input_dev->evbit); - __set_bit(BTN_LEFT, input_dev->keybit); /* We have 3 buttons */ - __set_bit(BTN_MIDDLE, input_dev->keybit); - __set_bit(BTN_RIGHT, input_dev->keybit); - __set_bit(BTN_TOUCH, input_dev->keybit); /* ...and Tablet */ - __set_bit(REL_X, input_dev->relbit); - __set_bit(REL_Y, input_dev->relbit); - input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0); - - serio_set_drvdata(serio, mouse); - - err = serio_open(serio, drv); - if (err) - goto fail2; - - /* - * Request selftest. Standard packet format and differential - * mode will be requested after the device ID'ed successfully. - */ - serio_write(serio, 'T'); /* Test */ - - err = input_register_device(input_dev); - if (err) - goto fail3; - - return 0; - - fail3: serio_close(serio); - fail2: serio_set_drvdata(serio, NULL); - fail1: input_free_device(input_dev); - kfree(mouse); - return err; -} - -static struct serio_device_id vsxxaa_serio_ids[] = { - { - .type = SERIO_RS232, - .proto = SERIO_VSXXXAA, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { 0 } -}; - -MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids); - -static struct serio_driver vsxxxaa_drv = { - .driver = { - .name = "vsxxxaa", - }, - .description = DRIVER_DESC, - .id_table = vsxxaa_serio_ids, - .connect = vsxxxaa_connect, - .interrupt = vsxxxaa_interrupt, - .disconnect = vsxxxaa_disconnect, -}; - -static int __init vsxxxaa_init(void) -{ - return serio_register_driver(&vsxxxaa_drv); -} - -static void __exit vsxxxaa_exit(void) -{ - serio_unregister_driver(&vsxxxaa_drv); -} - -module_init(vsxxxaa_init); -module_exit(vsxxxaa_exit); - |