summaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r--drivers/input/mouse/Kconfig98
-rw-r--r--drivers/input/mouse/Makefile10
-rw-r--r--drivers/input/mouse/alps.c13
-rw-r--r--drivers/input/mouse/alps.h18
-rw-r--r--drivers/input/mouse/appletouch.c706
-rw-r--r--drivers/input/mouse/atarimouse.c160
-rw-r--r--drivers/input/mouse/hil_ptr.c97
-rw-r--r--drivers/input/mouse/lifebook.c195
-rw-r--r--drivers/input/mouse/lifebook.h11
-rw-r--r--drivers/input/mouse/logips2pp.c7
-rw-r--r--drivers/input/mouse/logips2pp.h7
-rw-r--r--drivers/input/mouse/psmouse-base.c50
-rw-r--r--drivers/input/mouse/psmouse.h1
-rw-r--r--drivers/input/mouse/sermouse.c19
-rw-r--r--drivers/input/mouse/synaptics.c111
-rw-r--r--drivers/input/mouse/synaptics.h18
-rw-r--r--drivers/input/mouse/touchkit_ps2.c100
-rw-r--r--drivers/input/mouse/touchkit_ps2.h24
-rw-r--r--drivers/input/mouse/trackpoint.h9
-rw-r--r--drivers/input/mouse/vsxxxaa.c3
20 files changed, 1494 insertions, 163 deletions
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 35d998c..2ccc114 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -2,7 +2,7 @@
# Mouse driver configuration
#
menuconfig INPUT_MOUSE
- bool "Mouse"
+ bool "Mice"
default y
help
Say Y here, and a list of supported mice will be displayed.
@@ -19,7 +19,7 @@ config MOUSE_PS2
select SERIO_LIBPS2
select SERIO_I8042 if X86_PC
select SERIO_GSCPS2 if GSC
- ---help---
+ 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
@@ -37,10 +37,69 @@ config MOUSE_PS2
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 EMBEDDED
+ 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 "Logictech PS/2++ mouse protocol extension" if EMBEDDED
+ 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 EMBEDDED
+ 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 EMBEDDED
+ default y
+ depends on MOUSE_PS2
+ 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 EMBEDDED
+ 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_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_SERIAL
tristate "Serial mouse"
select SERIO
- ---help---
+ 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.
@@ -50,6 +109,26 @@ config MOUSE_SERIAL
To compile this driver as a module, choose M here: the
module will be called sermouse.
+config MOUSE_APPLETOUCH
+ tristate "Apple USB Touchpad support"
+ 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_INPORT
tristate "InPort/MS/ATIXL busmouse"
depends on ISA
@@ -96,6 +175,17 @@ config MOUSE_AMIGA
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
@@ -118,7 +208,7 @@ config MOUSE_VSXXXAA
digitizer (VSXXX-AB) DEC produced.
config MOUSE_HIL
- tristate "HIL pointers (mice etc)."
+ tristate "HIL pointers (mice etc)."
depends on GSC || HP300
select HP_SDC
select HIL_MLC
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 21a1de6..aa4ba87 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -5,6 +5,8 @@
# 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_RISCPC) += rpcmouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
@@ -14,4 +16,10 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
-psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o
+psmouse-objs := psmouse-base.o synaptics.o
+
+psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o
+psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o
+psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
+psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
+psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4e71a66..cf3e466 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -424,14 +424,15 @@ int alps_init(struct psmouse *psmouse)
struct input_dev *dev1 = psmouse->dev, *dev2;
int version;
- psmouse->private = priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
+ priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
dev2 = input_allocate_device();
if (!priv || !dev2)
goto init_fail;
priv->dev2 = dev2;
- if (!(priv->i = alps_get_model(psmouse, &version)))
+ priv->i = alps_get_model(psmouse, &version);
+ if (!priv->i)
goto init_fail;
if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
@@ -480,7 +481,8 @@ int alps_init(struct psmouse *psmouse)
dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- input_register_device(priv->dev2);
+ if (input_register_device(priv->dev2))
+ goto init_fail;
psmouse->protocol_handler = alps_process_byte;
psmouse->poll = alps_poll;
@@ -491,9 +493,11 @@ int alps_init(struct psmouse *psmouse)
/* We are having trouble resyncing ALPS touchpads so disable it for now */
psmouse->resync_time = 0;
+ psmouse->private = priv;
return 0;
init_fail:
+ psmouse_reset(psmouse);
input_free_device(dev2);
kfree(priv);
return -1;
@@ -504,7 +508,8 @@ int alps_detect(struct psmouse *psmouse, int set_properties)
int version;
const struct alps_model_info *model;
- if (!(model = alps_get_model(psmouse, &version)))
+ model = alps_get_model(psmouse, &version);
+ if (!model)
return -1;
if (set_properties) {
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 69db732..4bbddc9 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -12,9 +12,6 @@
#ifndef _ALPS_H
#define _ALPS_H
-int alps_detect(struct psmouse *psmouse, int set_properties);
-int alps_init(struct psmouse *psmouse);
-
struct alps_model_info {
unsigned char signature[3];
unsigned char byte0, mask0;
@@ -23,10 +20,23 @@ struct alps_model_info {
struct alps_data {
struct input_dev *dev2; /* Relative device */
- char name[32]; /* Name */
char phys[32]; /* Phys */
const struct alps_model_info *i;/* Info */
int prev_fin; /* Finger bit from previous packet */
};
+#ifdef CONFIG_MOUSE_PS2_ALPS
+int alps_detect(struct psmouse *psmouse, int set_properties);
+int alps_init(struct psmouse *psmouse);
+#else
+inline int alps_detect(struct psmouse *psmouse, int set_properties)
+{
+ return -ENOSYS;
+}
+inline int alps_init(struct psmouse *psmouse)
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_ALPS */
+
#endif
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
new file mode 100644
index 0000000..e321526
--- /dev/null
+++ b/drivers/input/mouse/appletouch.c
@@ -0,0 +1,706 @@
+/*
+ * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) 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)
+ *
+ * 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>
+
+/* Apple has powerbooks which have the keyboard with different Product IDs */
+#define APPLE_VENDOR_ID 0x05AC
+
+/* These names come from Info.plist in AppleUSBTrackpad.kext */
+#define FOUNTAIN_ANSI_PRODUCT_ID 0x020E
+#define FOUNTAIN_ISO_PRODUCT_ID 0x020F
+
+#define FOUNTAIN_TP_ONLY_PRODUCT_ID 0x030A
+
+#define GEYSER1_TP_ONLY_PRODUCT_ID 0x030B
+
+#define GEYSER_ANSI_PRODUCT_ID 0x0214
+#define GEYSER_ISO_PRODUCT_ID 0x0215
+#define GEYSER_JIS_PRODUCT_ID 0x0216
+
+/* MacBook devices */
+#define GEYSER3_ANSI_PRODUCT_ID 0x0217
+#define GEYSER3_ISO_PRODUCT_ID 0x0218
+#define GEYSER3_JIS_PRODUCT_ID 0x0219
+
+/*
+ * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext
+ * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables
+ */
+#define GEYSER4_ANSI_PRODUCT_ID 0x021A
+#define GEYSER4_ISO_PRODUCT_ID 0x021B
+#define GEYSER4_JIS_PRODUCT_ID 0x021C
+
+#define ATP_DEVICE(prod) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_INT_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
+ .idVendor = APPLE_VENDOR_ID, \
+ .idProduct = (prod), \
+ .bInterfaceClass = 0x03, \
+ .bInterfaceProtocol = 0x02
+
+/* table of devices that work with this driver */
+static struct usb_device_id atp_table [] = {
+ { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) },
+
+ /* PowerBooks Oct 2005 */
+ { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+
+ /* Core Duo MacBook & MacBook Pro */
+ { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) },
+
+ /* Core2 Duo MacBook & MacBook Pro */
+ { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) },
+
+ /* Terminating entry */
+ { }
+};
+MODULE_DEVICE_TABLE (usb, atp_table);
+
+/*
+ * number of sensors. Note that only 16 instead of 26 X (horizontal)
+ * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
+ * (vertical) 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
+/*
+ * multiplication factor for the X and Y coordinates.
+ * We try to keep the touchpad aspect ratio while still doing only simple
+ * arithmetics.
+ * The factors below give coordinates like:
+ * 0 <= x < 960 on 12" and 15" Powerbooks
+ * 0 <= x < 1600 on 17" Powerbooks
+ * 0 <= y < 646
+ */
+#define ATP_XFACT 64
+#define ATP_YFACT 43
+
+/*
+ * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
+ * ignored.
+ */
+#define ATP_THRESHOLD 5
+
+/* MacBook Pro (Geyser 3 & 4) initialization constants */
+#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1
+#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9
+#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300
+#define ATP_GEYSER3_MODE_REQUEST_INDEX 0
+#define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04
+
+/* 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 */
+ signed char * data; /* transferred data */
+ int open; /* non-zero if opened */
+ struct input_dev *input; /* input dev */
+ int valid; /* are the sensors valid ? */
+ int x_old; /* last reported x/y, */
+ int y_old; /* used for smoothing */
+ /* current value of the sensors */
+ signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];
+ /* last value of the sensors */
+ signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
+ /* accumulated sensors */
+ int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+ int overflowwarn; /* overflow warning printed? */
+ int datalen; /* size of an USB urb transfer */
+};
+
+#define dbg_dump(msg, tab) \
+ if (debug > 1) { \
+ int i; \
+ printk("appletouch: %s %lld", msg, (long long)jiffies); \
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \
+ printk(" %02x", tab[i]); \
+ printk("\n"); \
+ }
+
+#define dprintk(format, a...) \
+ do { \
+ if (debug) printk(format, ##a); \
+ } while (0)
+
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
+MODULE_DESCRIPTION("Apple PowerBooks 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, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value");
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activate debugging output");
+
+/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
+static inline int atp_is_geyser_2(struct atp *dev)
+{
+ u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+ return (productId == GEYSER_ANSI_PRODUCT_ID) ||
+ (productId == GEYSER_ISO_PRODUCT_ID) ||
+ (productId == GEYSER_JIS_PRODUCT_ID);
+}
+
+static inline int atp_is_geyser_3(struct atp *dev)
+{
+ u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+ return (productId == GEYSER3_ANSI_PRODUCT_ID) ||
+ (productId == GEYSER3_ISO_PRODUCT_ID) ||
+ (productId == GEYSER3_JIS_PRODUCT_ID) ||
+ (productId == GEYSER4_ANSI_PRODUCT_ID) ||
+ (productId == GEYSER4_ISO_PRODUCT_ID) ||
+ (productId == GEYSER4_JIS_PRODUCT_ID);
+}
+
+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]) {
+ 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 occassionaly jump a number of
+ * pixels (let me restate--slowly moving the mouse 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);
+}
+
+static void atp_complete(struct urb* urb)
+{
+ int x, y, x_z, y_z, x_f, y_f;
+ int retval, i, j;
+ struct atp *dev = urb->context;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -EOVERFLOW:
+ if(!dev->overflowwarn) {
+ printk("appletouch: OVERFLOW with data "
+ "length %d, actual length is %d\n",
+ dev->datalen, dev->urb->actual_length);
+ dev->overflowwarn = 1;
+ }
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* This urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, urb->status);
+ goto exit;
+ }
+
+ /* drop incomplete datasets */
+ if (dev->urb->actual_length != dev->datalen) {
+ dprintk("appletouch: incomplete data package"
+ " (first byte: %d, length: %d).\n",
+ dev->data[0], dev->urb->actual_length);
+ goto exit;
+ }
+
+ /* reorder the sensors values */
+ if (atp_is_geyser_3(dev)) {
+ 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 + 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];
+ }
+ } else if (atp_is_geyser_2(dev)) {
+ 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 ] = 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[i + 26] = dev->data[5 * i + 1];
+ dev->xy_cur[i + 34] = dev->data[5 * i + 3];
+ }
+ }
+
+ dbg_dump("sample", dev->xy_cur);
+
+ if (!dev->valid) {
+ /* first sample */
+ dev->valid = 1;
+ dev->x_old = dev->y_old = -1;
+ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+
+ if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
+ goto exit;
+
+ /* 17" Powerbooks have extra X sensors */
+ for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
+ if (!dev->xy_cur[i]) continue;
+
+ printk("appletouch: 17\" model detected.\n");
+ if(atp_is_geyser_2(dev))
+ input_set_abs_params(dev->input, ABS_X, 0,
+ (20 - 1) *
+ ATP_XFACT - 1,
+ ATP_FUZZ, 0);
+ else
+ input_set_abs_params(dev->input, ABS_X, 0,
+ (ATP_XSENSORS - 1) *
+ ATP_XFACT - 1,
+ ATP_FUZZ, 0);
+
+ break;
+ }
+
+ 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,
+ ATP_XFACT, &x_z, &x_f);
+ y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
+ ATP_YFACT, &y_z, &y_f);
+
+ 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("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,
+ !!dev->data[dev->datalen - 1]);
+
+ input_sync(dev->input);
+
+exit:
+ retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+ if (retval) {
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, 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);
+ dev->open = 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;
+
+ /* 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->overflowwarn = 0;
+ if (atp_is_geyser_3(dev))
+ dev->datalen = 64;
+ else if (atp_is_geyser_2(dev))
+ dev->datalen = 64;
+ else
+ dev->datalen = 81;
+
+ if (atp_is_geyser_3(dev)) {
+ /*
+ * By default Geyser 3 device sends standard USB HID mouse
+ * packets (Report ID 2). This code changes device mode, so it
+ * sends raw sensor reports (Report ID 5).
+ */
+ char data[8];
+ int size;
+
+ size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ ATP_GEYSER3_MODE_READ_REQUEST_ID,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ ATP_GEYSER3_MODE_REQUEST_VALUE,
+ ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
+
+ if (size != 8) {
+ err("Could not do mode read request from device"
+ " (Geyser 3 mode)");
+ goto err_free_devs;
+ }
+
+ /* Apply the mode switch */
+ data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE;
+
+ size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ ATP_GEYSER3_MODE_WRITE_REQUEST_ID,
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ ATP_GEYSER3_MODE_REQUEST_VALUE,
+ ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
+
+ if (size != 8) {
+ err("Could not do mode write request to device"
+ " (Geyser 3 mode)");
+ goto err_free_devs;
+ }
+ printk("appletouch Geyser 3 inited.\n");
+ }
+
+ dev->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->urb)
+ goto err_free_devs;
+
+ dev->data = usb_buffer_alloc(dev->udev, dev->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->datalen, atp_complete, dev, 1);
+
+ 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);
+
+ if (atp_is_geyser_3(dev)) {
+ /*
+ * MacBook have 20 X sensors, 10 Y sensors
+ */
+ input_set_abs_params(input_dev, ABS_X, 0,
+ ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0,
+ ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+ } else if (atp_is_geyser_2(dev)) {
+ /*
+ * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
+ * later.
+ */
+ input_set_abs_params(input_dev, ABS_X, 0,
+ ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0,
+ ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+ } else {
+ /*
+ * 12" and 15" Powerbooks only have 16 x sensors,
+ * 17" models are detected later.
+ */
+ input_set_abs_params(input_dev, ABS_X, 0,
+ (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0,
+ (ATP_YSENSORS - 1) * ATP_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);
+
+ return 0;
+
+ err_free_buffer:
+ usb_buffer_free(dev->udev, dev->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_buffer_free(dev->udev, dev->datalen,
+ dev->data, dev->urb->transfer_dma);
+ usb_free_urb(dev->urb);
+ kfree(dev);
+ }
+ printk(KERN_INFO "input: appletouch disconnected\n");
+}
+
+static int atp_suspend(struct usb_interface *iface, pm_message_t message)
+{
+ struct atp *dev = usb_get_intfdata(iface);
+ usb_kill_urb(dev->urb);
+ dev->valid = 0;
+ 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 struct usb_driver atp_driver = {
+ .name = "appletouch",
+ .probe = atp_probe,
+ .disconnect = atp_disconnect,
+ .suspend = atp_suspend,
+ .resume = atp_resume,
+ .id_table = atp_table,
+};
+
+static int __init atp_init(void)
+{
+ return usb_register(&atp_driver);
+}
+
+static void __exit atp_exit(void)
+{
+ usb_deregister(&atp_driver);
+}
+
+module_init(atp_init);
+module_exit(atp_exit);
diff --git a/drivers/input/mouse/atarimouse.c b/drivers/input/mouse/atarimouse.c
new file mode 100644
index 0000000..43ab656
--- /dev/null
+++ b/drivers/input/mouse/atarimouse.c
@@ -0,0 +1,160 @@
+/*
+ * 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/system.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};
+
+#ifdef __MODULE__
+MODULE_PARM(mouse_threshold, "2i");
+#endif
+#ifdef FIXED_ATARI_JOYSTICK
+extern int atari_mouse_buttons;
+#endif
+static int atamouse_used = 0;
+
+static struct input_dev *atamouse_dev;
+
+static void atamouse_interrupt(char *buf)
+{
+ int buttons, dx, dy;
+
+/* ikbd_mouse_disable(); */
+
+ buttons = (buf[0] & 1) | ((buf[0] & 2) << 1);
+#ifdef FIXED_ATARI_JOYSTICK
+ buttons |= atari_mouse_buttons & 2;
+ atari_mouse_buttons = buttons;
+#endif
+/* ikbd_mouse_rel_pos(); */
+
+ /* 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 & 0x1);
+ input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2);
+ input_report_key(atamouse_dev, BTN_RIGHT, buttons & 0x4);
+
+ input_sync(atamouse_dev);
+
+ return;
+}
+
+static int atamouse_open(struct input_dev *dev)
+{
+ if (atamouse_used++)
+ return 0;
+
+#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)
+{
+ if (!--atamouse_used) {
+ ikbd_mouse_disable();
+ atari_mouse_interrupt_hook = NULL;
+ }
+}
+
+static int __init atamouse_init(void)
+{
+ if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
+ return -ENODEV;
+
+ if (!(atamouse_dev = input_allocate_device()))
+ return -ENOMEM;
+
+ if (!(atari_keyb_init()))
+ return -ENODEV;
+
+ atamouse_dev->name = "Atari mouse";
+ atamouse_dev->phys = "atamouse/input0";
+ atamouse_dev->id.bustype = BUS_ATARI;
+ atamouse_dev->id.vendor = 0x0001;
+ atamouse_dev->id.product = 0x0002;
+ atamouse_dev->id.version = 0x0100;
+
+ atamouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ atamouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ atamouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ atamouse_dev->open = atamouse_open;
+ atamouse_dev->close = atamouse_close;
+
+ input_register_device(atamouse_dev);
+
+ printk(KERN_INFO "input: %s at keyboard ACIA\n", atamouse_dev->name);
+ return 0;
+}
+
+static void __exit atamouse_exit(void)
+{
+ input_unregister_device(atamouse_dev);
+}
+
+module_init(atamouse_init);
+module_exit(atamouse_exit);
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index bfb174f..449bf4d 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -88,10 +88,12 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
idx = ptr->idx4/4;
p = data[idx - 1];
- if ((p & ~HIL_CMDCT_POL) ==
- (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
- if ((p & ~HIL_CMDCT_RPL) ==
- (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+ if ((p & ~HIL_CMDCT_POL) ==
+ (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+ goto report;
+ if ((p & ~HIL_CMDCT_RPL) ==
+ (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL))
+ goto report;
/* Not a poll response. See if we are loading config records. */
switch (p & HIL_PKT_DATA_MASK) {
@@ -101,27 +103,32 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
for (; i < HIL_PTR_MAX_LENGTH; i++)
ptr->idd[i] = 0;
break;
+
case HIL_CMD_RSC:
for (i = 0; i < idx; i++)
ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
for (; i < HIL_PTR_MAX_LENGTH; i++)
ptr->rsc[i] = 0;
break;
+
case HIL_CMD_EXD:
for (i = 0; i < idx; i++)
ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
for (; i < HIL_PTR_MAX_LENGTH; i++)
ptr->exd[i] = 0;
break;
+
case HIL_CMD_RNM:
for (i = 0; i < idx; i++)
ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
for (; i < HIL_PTR_MAX_LENGTH + 1; i++)
- ptr->rnm[i] = '\0';
+ ptr->rnm[i] = 0;
break;
+
default:
/* These occur when device isn't present */
- if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break;
+ if (p == (HIL_ERR_INT | HIL_PKT_CMD))
+ break;
/* Anything else we'd like to know about. */
printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
break;
@@ -130,7 +137,8 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
report:
if ((p & HIL_CMDCT_POL) != idx - 1) {
- printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx);
+ printk(KERN_WARNING PREFIX
+ "Malformed poll packet %x (idx = %i)\n", p, idx);
goto out;
}
@@ -139,7 +147,7 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
laxis += i;
ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
- absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS;
+ absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS;
for (cnt = 1; i < laxis; i++) {
unsigned int lo,hi,val;
@@ -157,7 +165,8 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
input_report_abs(dev, ABS_X + i, val);
} else {
val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
- if (i%3) val *= -1;
+ if (i%3)
+ val *= -1;
input_report_rel(dev, REL_X + i, val);
}
}
@@ -168,10 +177,11 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
btn = ptr->data[cnt++];
up = btn & 1;
btn &= 0xfe;
- if (btn == 0x8e) {
+ if (btn == 0x8e)
continue; /* TODO: proximity == touch? */
- }
- else if ((btn > 0x8c) || (btn < 0x80)) continue;
+ else
+ if ((btn > 0x8c) || (btn < 0x80))
+ continue;
btn = (btn - 0x80) >> 1;
btn = ptr->btnmap[btn];
input_report_key(dev, btn, !up);
@@ -182,14 +192,14 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
up(&ptr->sem);
}
-static void hil_ptr_process_err(struct hil_ptr *ptr) {
+static void hil_ptr_process_err(struct hil_ptr *ptr)
+{
printk(KERN_WARNING PREFIX "errored HIL packet\n");
ptr->idx4 = 0;
up(&ptr->sem);
- return;
}
-static irqreturn_t hil_ptr_interrupt(struct serio *serio,
+static irqreturn_t hil_ptr_interrupt(struct serio *serio,
unsigned char data, unsigned int flags)
{
struct hil_ptr *ptr;
@@ -197,29 +207,29 @@ static irqreturn_t hil_ptr_interrupt(struct serio *serio,
int idx;
ptr = serio_get_drvdata(serio);
- if (ptr == NULL) {
- BUG();
- return IRQ_HANDLED;
- }
+ BUG_ON(ptr == NULL);
if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) {
hil_ptr_process_err(ptr);
return IRQ_HANDLED;
}
idx = ptr->idx4/4;
- if (!(ptr->idx4 % 4)) ptr->data[idx] = 0;
+ if (!(ptr->idx4 % 4))
+ ptr->data[idx] = 0;
packet = ptr->data[idx];
packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8);
ptr->data[idx] = packet;
/* Records of N 4-byte hil_packets must terminate with a command. */
- if ((++(ptr->idx4)) % 4) return IRQ_HANDLED;
+ if ((++(ptr->idx4)) % 4)
+ return IRQ_HANDLED;
if ((packet & 0xffff0000) != HIL_ERR_INT) {
hil_ptr_process_err(ptr);
return IRQ_HANDLED;
}
- if (packet & HIL_PKT_CMD)
+ if (packet & HIL_PKT_CMD)
hil_ptr_process_record(ptr);
+
return IRQ_HANDLED;
}
@@ -228,10 +238,7 @@ static void hil_ptr_disconnect(struct serio *serio)
struct hil_ptr *ptr;
ptr = serio_get_drvdata(serio);
- if (ptr == NULL) {
- BUG();
- return;
- }
+ BUG_ON(ptr == NULL);
serio_close(serio);
input_unregister_device(ptr->dev);
@@ -241,7 +248,7 @@ static void hil_ptr_disconnect(struct serio *serio)
static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
{
struct hil_ptr *ptr;
- char *txt;
+ const char *txt;
unsigned int i, naxsets, btntype;
uint8_t did, *idd;
@@ -252,42 +259,40 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
if (!ptr->dev)
goto bail0;
- ptr->dev->private = ptr;
-
if (serio_open(serio, driver))
goto bail1;
serio_set_drvdata(serio, ptr);
ptr->serio = serio;
- init_MUTEX_LOCKED(&(ptr->sem));
+ init_MUTEX_LOCKED(&ptr->sem);
/* Get device info. MLC driver supplies devid/status/etc. */
serio->write(serio, 0);
serio->write(serio, 0);
serio->write(serio, HIL_PKT_CMD >> 8);
serio->write(serio, HIL_CMD_IDD);
- down(&(ptr->sem));
+ down(&ptr->sem);
serio->write(serio, 0);
serio->write(serio, 0);
serio->write(serio, HIL_PKT_CMD >> 8);
serio->write(serio, HIL_CMD_RSC);
- down(&(ptr->sem));
+ down(&ptr->sem);
serio->write(serio, 0);
serio->write(serio, 0);
serio->write(serio, HIL_PKT_CMD >> 8);
serio->write(serio, HIL_CMD_RNM);
- down(&(ptr->sem));
+ down(&ptr->sem);
serio->write(serio, 0);
serio->write(serio, 0);
serio->write(serio, HIL_PKT_CMD >> 8);
serio->write(serio, HIL_CMD_EXD);
- down(&(ptr->sem));
+ down(&ptr->sem);
- up(&(ptr->sem));
+ up(&ptr->sem);
did = ptr->idd[0];
idd = ptr->idd + 1;
@@ -301,12 +306,12 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
ptr->dev->evbit[0] = BIT(EV_ABS);
txt = "absolute";
}
- if (!ptr->dev->evbit[0]) {
+ if (!ptr->dev->evbit[0])
goto bail2;
- }
ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
- if (ptr->nbtn) ptr->dev->evbit[0] |= BIT(EV_KEY);
+ if (ptr->nbtn)
+ ptr->dev->evbit[0] |= BIT(EV_KEY);
naxsets = HIL_IDD_NUM_AXSETS(*idd);
ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
@@ -315,7 +320,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
did, txt);
printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n",
ptr->nbtn, naxsets, ptr->naxes);
-
+
btntype = BTN_MISC;
if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
#ifdef TABLET_SIMULATES_MOUSE
@@ -325,7 +330,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
#endif
if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
btntype = BTN_TOUCH;
-
+
if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
btntype = BTN_MOUSE;
@@ -341,12 +346,10 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
}
if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
- for (i = 0; i < ptr->naxes; i++) {
+ for (i = 0; i < ptr->naxes; i++)
set_bit(REL_X + i, ptr->dev->relbit);
- }
- for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
+ for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++)
set_bit(REL_X + i, ptr->dev->relbit);
- }
} else {
for (i = 0; i < ptr->naxes; i++) {
set_bit(ABS_X + i, ptr->dev->absbit);
@@ -375,7 +378,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
ptr->dev->id.vendor = PCI_VENDOR_ID_HP;
ptr->dev->id.product = 0x0001; /* TODO: get from ptr->rsc */
ptr->dev->id.version = 0x0100; /* TODO: get from ptr->rsc */
- ptr->dev->cdev.dev = &serio->dev;
+ ptr->dev->dev.parent = &serio->dev;
input_register_device(ptr->dev);
printk(KERN_INFO "input: %s (%s), ID: %d\n",
@@ -419,11 +422,11 @@ static int __init hil_ptr_init(void)
{
return serio_register_driver(&hil_ptr_serio_driver);
}
-
+
static void __exit hil_ptr_exit(void)
{
serio_unregister_driver(&hil_ptr_serio_driver);
}
-
+
module_init(hil_ptr_init);
module_exit(hil_ptr_exit);
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 29542f0..1740cad 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -20,6 +20,27 @@
#include "psmouse.h"
#include "lifebook.h"
+struct lifebook_data {
+ struct input_dev *dev2; /* Relative device */
+ char phys[32];
+};
+
+static const char *desired_serio_phys;
+
+static int lifebook_set_serio_phys(struct dmi_system_id *d)
+{
+ desired_serio_phys = d->driver_data;
+ return 0;
+}
+
+static unsigned char lifebook_use_6byte_proto;
+
+static int lifebook_set_6byte_proto(struct dmi_system_id *d)
+{
+ lifebook_use_6byte_proto = 1;
+ return 0;
+}
+
static struct dmi_system_id lifebook_dmi_table[] = {
{
.ident = "FLORA-ie 55mi",
@@ -56,6 +77,24 @@ static struct dmi_system_id lifebook_dmi_table[] = {
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
},
+ .callback = lifebook_set_serio_phys,
+ .driver_data = "isa0060/serio3",
+ },
+ {
+ .ident = "Panasonic CF-28",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"),
+ },
+ .callback = lifebook_set_6byte_proto,
+ },
+ {
+ .ident = "Panasonic CF-29",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
+ },
+ .callback = lifebook_set_6byte_proto,
},
{
.ident = "Lifebook B142",
@@ -68,30 +107,70 @@ static struct dmi_system_id 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->dev2;
unsigned char *packet = psmouse->packet;
- struct input_dev *dev = psmouse->dev;
+ int relative_packet = packet[0] & 0x08;
- if (psmouse->pktcnt != 3)
- return PSMOUSE_GOOD_DATA;
+ 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 */
+ }
+ }
- /* calculate X and Y */
- if ((packet[0] & 0x08) == 0x00) {
- input_report_abs(dev, ABS_X,
+ if (relative_packet) {
+ if (!dev2)
+ printk(KERN_WARNING "lifebook.c: 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(dev, ABS_Y,
+ input_report_abs(dev1, ABS_Y,
1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
- } else {
- input_report_rel(dev, REL_X,
- ((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
- input_report_rel(dev, REL_Y,
- -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
}
- input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
- input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
- input_report_key(dev, BTN_TOUCH, packet[0] & 0x04);
+ input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04);
+ input_sync(dev1);
- input_sync(dev);
+ 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;
}
@@ -109,12 +188,20 @@ static int lifebook_absolute_mode(struct psmouse *psmouse)
you leave this call out the touchsreen will never send
absolute coordinates
*/
- param = 0x07;
+ param = lifebook_use_6byte_proto ? 0x08 : 0x07;
ps2_command(ps2dev, &param, 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, &param, PSMOUSE_CMD_SETRES);
+}
+
static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution)
{
static const unsigned char params[] = { 0, 1, 2, 2, 3 };
@@ -131,6 +218,8 @@ static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolu
static void lifebook_disconnect(struct psmouse *psmouse)
{
psmouse_reset(psmouse);
+ kfree(psmouse->private);
+ psmouse->private = NULL;
}
int lifebook_detect(struct psmouse *psmouse, int set_properties)
@@ -138,6 +227,10 @@ int lifebook_detect(struct psmouse *psmouse, int set_properties)
if (!dmi_check_system(lifebook_dmi_table))
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";
@@ -146,24 +239,78 @@ int lifebook_detect(struct psmouse *psmouse, int set_properties)
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(EV_KEY) | BIT(EV_REL);
+ dev2->relbit[LONG(REL_X)] = BIT(REL_X) | BIT(REL_Y);
+ dev2->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(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 *input_dev = psmouse->dev;
+ struct input_dev *dev1 = psmouse->dev;
+ int max_coord = lifebook_use_6byte_proto ? 1024 : 4096;
if (lifebook_absolute_mode(psmouse))
return -1;
- input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
- input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
- input_set_abs_params(input_dev, ABS_X, 0, 1024, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0);
+ dev1->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+ dev1->relbit[0] = 0;
+ dev1->keybit[LONG(BTN_TOUCH)] = BIT(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/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h
index be1c094..c1647cf 100644
--- a/drivers/input/mouse/lifebook.h
+++ b/drivers/input/mouse/lifebook.h
@@ -11,7 +11,18 @@
#ifndef _LIFEBOOK_H
#define _LIFEBOOK_H
+#ifdef CONFIG_MOUSE_PS2_LIFEBOOK
int lifebook_detect(struct psmouse *psmouse, int set_properties);
int lifebook_init(struct psmouse *psmouse);
+#else
+inline int lifebook_detect(struct psmouse *psmouse, int set_properties)
+{
+ return -ENOSYS;
+}
+inline int lifebook_init(struct psmouse *psmouse)
+{
+ return -ENOSYS;
+}
+#endif
#endif
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index d3ddea2..9df74b7 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -200,6 +200,7 @@ static void ps2pp_disconnect(struct psmouse *psmouse)
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 */
@@ -338,12 +339,12 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
param[1] = 0;
ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
- if (!param[1])
- return -1;
-
model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
buttons = param[1];
+ if (!model || !buttons)
+ return -1;
+
if ((model_info = get_model_info(model)) != NULL) {
/*
diff --git a/drivers/input/mouse/logips2pp.h b/drivers/input/mouse/logips2pp.h
index 64a8ec5..6e57125 100644
--- a/drivers/input/mouse/logips2pp.h
+++ b/drivers/input/mouse/logips2pp.h
@@ -11,6 +11,13 @@
#ifndef _LOGIPS2PP_H
#define _LOGIPS2PP_H
+#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
int ps2pp_init(struct psmouse *psmouse, int set_properties);
+#else
+inline int ps2pp_init(struct psmouse *psmouse, int set_properties)
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_LOGIPS2PP */
#endif
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 0fe5869..f15f695 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -28,6 +28,7 @@
#include "alps.h"
#include "lifebook.h"
#include "trackpoint.h"
+#include "touchkit_ps2.h"
#define DRIVER_DESC "PS/2 mouse driver"
@@ -569,7 +570,9 @@ static int psmouse_extensions(struct psmouse *psmouse,
return PSMOUSE_THINKPS;
/*
- * Try Synaptics TouchPad
+ * 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 && synaptics_detect(psmouse, set_properties) == 0) {
synaptics_hardware = 1;
@@ -605,14 +608,20 @@ static int psmouse_extensions(struct psmouse *psmouse,
}
}
- if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse, set_properties) == 0)
- return PSMOUSE_GENPS;
+ if (max_proto > PSMOUSE_IMEX) {
+
+ if (genius_detect(psmouse, set_properties) == 0)
+ return PSMOUSE_GENPS;
- if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0)
- return PSMOUSE_PS2PP;
+ if (ps2pp_init(psmouse, set_properties) == 0)
+ return PSMOUSE_PS2PP;
- if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
- return PSMOUSE_TRACKPOINT;
+ if (trackpoint_detect(psmouse, set_properties) == 0)
+ return PSMOUSE_TRACKPOINT;
+
+ if (touchkit_ps2_detect(psmouse, set_properties) == 0)
+ return PSMOUSE_TOUCHKIT_PS2;
+ }
/*
* Reset to defaults in case the device got confused by extended
@@ -654,12 +663,14 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.maxproto = 1,
.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",
@@ -686,6 +697,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.maxproto = 1,
.detect = im_explorer_detect,
},
+#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
{
.type = PSMOUSE_SYNAPTICS,
.name = "SynPS/2",
@@ -693,6 +705,8 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.detect = synaptics_detect,
.init = synaptics_init,
},
+#endif
+#ifdef CONFIG_MOUSE_PS2_ALPS
{
.type = PSMOUSE_ALPS,
.name = "AlpsPS/2",
@@ -700,18 +714,31 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.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
{
.type = PSMOUSE_AUTO,
.name = "auto",
@@ -823,12 +850,6 @@ static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate)
static void psmouse_initialize(struct psmouse *psmouse)
{
/*
- * We set the mouse into streaming mode.
- */
-
- ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM);
-
-/*
* We set the mouse report rate, resolution and scaling.
*/
@@ -1062,8 +1083,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse
{
struct input_dev *input_dev = psmouse->dev;
- input_dev->private = psmouse;
- input_dev->cdev.dev = &psmouse->ps2dev.serio->dev;
+ input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index cf1de95..3964e8a 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -87,6 +87,7 @@ enum psmouse_type {
PSMOUSE_ALPS,
PSMOUSE_LIFEBOOK,
PSMOUSE_TRACKPOINT,
+ PSMOUSE_TOUCHKIT_PS2,
PSMOUSE_AUTO /* This one should always be last */
};
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index a85d747..77b8ee2 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -69,7 +69,8 @@ static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
switch (sermouse->count) {
case 0:
- if ((data & 0xf8) != 0x80) return;
+ 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));
@@ -107,7 +108,10 @@ 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;
+ if (data & 0x40)
+ sermouse->count = 0;
+ else if (sermouse->count == 0)
+ return;
switch (sermouse->count) {
@@ -169,7 +173,8 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
case 5:
case 7: /* Ignore anything besides MZ++ */
- if (sermouse->type != SERIO_MZPP) break;
+ if (sermouse->type != SERIO_MZPP)
+ break;
switch (buf[1]) {
@@ -206,13 +211,16 @@ static irqreturn_t sermouse_interrupt(struct serio *serio,
{
struct sermouse *sermouse = serio_get_drvdata(serio);
- if (time_after(jiffies, sermouse->last + HZ/10)) sermouse->count = 0;
+ 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;
}
@@ -258,12 +266,11 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.vendor = sermouse->type;
input_dev->id.product = c;
input_dev->id.version = 0x0100;
- input_dev->cdev.dev = &serio->dev;
+ input_dev->dev.parent = &serio->dev;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
- input_dev->private = sermouse;
if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index f0f9413..666ad3a 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -40,33 +40,70 @@
#define YMIN_NOMINAL 1408
#define YMAX_NOMINAL 4448
+
/*****************************************************************************
- * Synaptics communications functions
+ * Stuff we need even when we do not want native Synaptics support
****************************************************************************/
/*
- * Send a command to the synpatics touchpad by special commands
+ * Set the synaptics touchpad mode byte by special commands
*/
-static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
+static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode)
{
- if (psmouse_sliced_command(psmouse, c))
+ unsigned char param[1];
+
+ if (psmouse_sliced_command(psmouse, mode))
return -1;
- if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
+ 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, int 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
+ ****************************************************************************/
+
/*
- * Set the synaptics touchpad mode byte by special commands
+ * Send a command to the synpatics touchpad by special commands
*/
-static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode)
+static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
{
- unsigned char param[1];
-
- if (psmouse_sliced_command(psmouse, mode))
+ if (psmouse_sliced_command(psmouse, c))
return -1;
- param[0] = SYN_PS_SET_MODE2;
- if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE))
+ if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
return -1;
return 0;
}
@@ -148,7 +185,7 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
int retries = 0;
while ((retries++ < 3) && psmouse_reset(psmouse))
- printk(KERN_ERR "synaptics reset failed\n");
+ /* empty */;
if (synaptics_identify(psmouse))
return -1;
@@ -529,12 +566,6 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
clear_bit(REL_Y, dev->relbit);
}
-void synaptics_reset(struct psmouse *psmouse)
-{
- /* reset touchpad back to relative mode, gestures enabled */
- synaptics_mode_cmd(psmouse, 0);
-}
-
static void synaptics_disconnect(struct psmouse *psmouse)
{
synaptics_reset(psmouse);
@@ -569,30 +600,6 @@ static int synaptics_reconnect(struct psmouse *psmouse)
return 0;
}
-int synaptics_detect(struct psmouse *psmouse, int 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 -1;
-
- if (set_properties) {
- psmouse->vendor = "Synaptics";
- psmouse->name = "TouchPad";
- }
-
- return 0;
-}
-
#if defined(__i386__)
#include <linux/dmi.h>
static struct dmi_system_id toshiba_dmi_table[] = {
@@ -648,6 +655,16 @@ int synaptics_init(struct psmouse *psmouse)
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);
+
psmouse->protocol_handler = synaptics_process_byte;
psmouse->set_rate = synaptics_set_rate;
psmouse->disconnect = synaptics_disconnect;
@@ -680,4 +697,12 @@ int synaptics_init(struct psmouse *psmouse)
return -1;
}
+#else /* CONFIG_MOUSE_PS2_SYNAPTICS */
+
+int synaptics_init(struct psmouse *psmouse)
+{
+ return -ENOSYS;
+}
+
+#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 68fff1d..02aa4cf 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -9,10 +9,6 @@
#ifndef _SYNAPTICS_H
#define _SYNAPTICS_H
-extern int synaptics_detect(struct psmouse *psmouse, int set_properties);
-extern int synaptics_init(struct psmouse *psmouse);
-extern void synaptics_reset(struct psmouse *psmouse);
-
/* synaptics queries */
#define SYN_QUE_IDENTIFY 0x00
#define SYN_QUE_MODES 0x01
@@ -62,9 +58,9 @@ extern void synaptics_reset(struct psmouse *psmouse);
#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_MODEL(i) (((i) >> 4) & 0x0f)
+#define SYN_ID_MAJOR(i) ((i) & 0x0f)
+#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff)
#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47)
/* synaptics special commands */
@@ -98,8 +94,8 @@ struct synaptics_hw_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 capabilities; /* Capabilities */
+ unsigned long int ext_cap; /* Extended Capabilities */
unsigned long int identity; /* Identification */
unsigned char pkt_type; /* packet type - old, new, etc */
@@ -107,4 +103,8 @@ struct synaptics_data {
int scroll;
};
+int synaptics_detect(struct psmouse *psmouse, int set_properties);
+int synaptics_init(struct psmouse *psmouse);
+void synaptics_reset(struct psmouse *psmouse);
+
#endif /* _SYNAPTICS_H */
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c
new file mode 100644
index 0000000..7b977fd
--- /dev/null
+++ b/drivers/input/mouse/touchkit_ps2.c
@@ -0,0 +1,100 @@
+/* ----------------------------------------------------------------------------
+ * 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 in support section of:
+ * http://www.egalax.com.tw/
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.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, int 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(EV_KEY) | BIT(EV_ABS);
+ set_bit(BTN_TOUCH, dev->keybit);
+ 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/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h
new file mode 100644
index 0000000..61e9dfd
--- /dev/null
+++ b/drivers/input/mouse/touchkit_ps2.h
@@ -0,0 +1,24 @@
+/* ----------------------------------------------------------------------------
+ * 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, int set_properties);
+#else
+inline int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties)
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_TOUCHKIT */
+
+#endif
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
index 050298b..c10a6e7 100644
--- a/drivers/input/mouse/trackpoint.h
+++ b/drivers/input/mouse/trackpoint.h
@@ -142,6 +142,13 @@ struct trackpoint_data
unsigned char ext_dev;
};
-extern int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+#ifdef CONFIG_MOUSE_PS2_TRACKPOINT
+int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+#else
+inline int trackpoint_detect(struct psmouse *psmouse, int set_properties)
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_TRACKPOINT */
#endif /* _TRACKPOINT_H */
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index c3d64fc..4a32157 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -508,8 +508,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
input_dev->name = mouse->name;
input_dev->phys = mouse->phys;
input_dev->id.bustype = BUS_RS232;
- input_dev->cdev.dev = &serio->dev;
- input_dev->private = mouse;
+ input_dev->dev.parent = &serio->dev;
set_bit (EV_KEY, input_dev->evbit); /* We have buttons */
set_bit (EV_REL, input_dev->evbit);
OpenPOWER on IntegriCloud