[rfc/rft] Fujitsu B-Series Lifebook PS/2 TouchScreen driver

From: Vojtech Pavlik
Date: Fri Feb 11 2005 - 15:18:16 EST


Hi!

I've reimplemented the Lifebook touchscreen driver using libps2 and
input, to make it short and fitting into the kernel drivers.

Please comment on code and test for functionality!

PS.: The driver should register two input devices. It doesn't yet,
since that isn't very straightforward in the psmouse framework.

--
Vojtech Pavlik
SuSE Labs, SuSE CR
ChangeSet@xxxxxx, 2005-02-11 21:03:32+01:00, vojtech@xxxxxxx
input: Fujitsu Lifebook driver, experimental.

Signed-off-by: Vojtech Pavlik <vojtech@xxxxxxx>


Makefile | 2
lifebook.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lifebook.h | 16 ++++++
psmouse-base.c | 6 ++
psmouse.h | 1
5 files changed, 157 insertions(+), 2 deletions(-)


diff -Nru a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
--- a/drivers/input/mouse/Makefile 2005-02-11 21:04:00 +01:00
+++ b/drivers/input/mouse/Makefile 2005-02-11 21:04:00 +01:00
@@ -15,4 +15,4 @@
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o

-psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o
+psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o
diff -Nru a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/input/mouse/lifebook.c 2005-02-11 21:04:00 +01:00
@@ -0,0 +1,134 @@
+/*
+ * Fujitsu B-series Lifebook PS/2 TouchScreen driver
+ *
+ * Copyright (c) 2005 Vojtech Pavlik <vojtech@xxxxxxx>
+ *
+ * TouchSceeen 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 "psmouse.h"
+#include "lifebook.h"
+
+static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+{
+ unsigned char *packet = psmouse->packet;
+ struct input_dev *dev = &psmouse->dev;
+
+ if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
+ if (psmouse->pktcnt == 3) {
+
+ input_regs(dev, regs);
+ 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;
+ }
+ return PSMOUSE_GOOD_DATA;
+ }
+
+ if ((psmouse->packet[0] & 0x0b) == 0x00) { /* Absolute packet */
+ if (psmouse->pktcnt == 3) {
+
+ input_regs(dev, regs);
+ input_report_key(dev, BTN_TOUCH, packet[0] & 4);
+ input_report_rel(dev, ABS_X, ((packet[0] & 0x30) << 4) | packet[1]);
+ input_report_rel(dev, ABS_Y, ((packet[0] & 0xc0) << 2) | packet[2]);
+ input_sync(dev);
+
+ return PSMOUSE_FULL_PACKET;
+ }
+ return PSMOUSE_GOOD_DATA;
+ }
+
+ return PSMOUSE_BAD_DATA;
+}
+
+static int lifebook_reconnect(struct psmouse *psmouse)
+{
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ unsigned char param;
+
+ param = 7;
+ if (ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES))
+ return -1;
+
+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
+ return -1;
+
+ return 0;
+}
+
+static void lifebook_disconnect(struct psmouse *psmouse)
+{
+ psmouse_reset(psmouse);
+}
+
+int lifebook_detect(struct psmouse *psmouse, int set_properties)
+{
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ unsigned char param;
+
+/*
+ * This might be a magic knock sequence, or just a part of
+ * a standard mouse init for the mouse behind the screen.
+ * Rate of 40 also seems pretty low, but that's what the
+ * Windows driver supposedly does.
+ */
+
+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11))
+ return -1;
+
+ param = 40;
+ if (ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRATE))
+ return -1;
+
+ param = 3;
+ if (ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES))
+ return -1;
+
+/*
+ * This should fail on normal mice, SETRES only accepts
+ * values from 0 to 3.
+ */
+
+ param = 7;
+ if (ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES))
+ return -1;
+
+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
+ return -1;
+
+ if (set_properties) {
+ psmouse->vendor = "Fujitsu Lifebook";
+ psmouse->name = "TouchScreen";
+ }
+
+ psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
+ psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_set_abs_params(&psmouse->dev, ABS_X, 130, 885, 0, 0);
+ input_set_abs_params(&psmouse->dev, ABS_Y, 272, 830, 0, 0);
+
+ psmouse->protocol_handler = lifebook_process_byte;
+ psmouse->disconnect = lifebook_disconnect;
+ psmouse->reconnect = lifebook_reconnect;
+ psmouse->pktsize = 3;
+
+ return 0;
+}
diff -Nru a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/input/mouse/lifebook.h 2005-02-11 21:04:00 +01:00
@@ -0,0 +1,16 @@
+/*
+ * 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
+
+int lifebook_detect(struct psmouse *psmouse, int set_properties);
+
+#endif
diff -Nru a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
--- a/drivers/input/mouse/psmouse-base.c 2005-02-11 21:04:00 +01:00
+++ b/drivers/input/mouse/psmouse-base.c 2005-02-11 21:04:00 +01:00
@@ -24,6 +24,7 @@
#include "synaptics.h"
#include "logips2pp.h"
#include "alps.h"
+#include "lifebook.h"

#define DRIVER_DESC "PS/2 mouse driver"

@@ -62,7 +63,7 @@
__obsolete_setup("psmouse_resetafter=");
__obsolete_setup("psmouse_rate=");

-static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" };
+static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2", "LBPS/2" };

/*
* psmouse_process_byte() analyzes the PS/2 data stream and reports
@@ -462,6 +463,9 @@
max_proto = PSMOUSE_IMEX;
}
}
+
+ if (max_proto > PSMOUSE_IMEX && lifebook_detect(psmouse, set_properties) == 0)
+ return PSMOUSE_LIFEBOOK;

if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse, set_properties) == 0)
return PSMOUSE_GENPS;
diff -Nru a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
--- a/drivers/input/mouse/psmouse.h 2005-02-11 21:04:00 +01:00
+++ b/drivers/input/mouse/psmouse.h 2005-02-11 21:04:00 +01:00
@@ -77,6 +77,7 @@
PSMOUSE_IMEX,
PSMOUSE_SYNAPTICS,
PSMOUSE_ALPS,
+ PSMOUSE_LIFEBOOK,
};

int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);