NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/48200: New driver fjttchps2 for fujitsu touchscreen & touchpad ps2 controller



>Number:         48200
>Category:       kern
>Synopsis:       New driver fjttchps2 for fujitsu touchscreen & touchpad ps2 
>controller
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Tue Sep 10 02:25:00 +0000 2013
>Originator:     Nat Sloss
>Release:        NetBSD Current 6.99.23
>Organization:
>Environment:
NetBSD beast 6.99.23 NetBSD 6.99.23 (LOCKDEBUG) #4: Wed Jul 17 22:24:41 EST 
2013  build@beast:/usr/src/sys/arch/i386/compile/obj/LOCKDEBUG i386
>Description:
I had written a driver for the touch screen and trackpad controller found in 
Panasonic Toughbook CF18 and possibly it will work for earlier toughbooks and 
other computers using a ps2 fujitsu touch screen controller.

Originally it was written for NetBSD 3.0.1 in 2009, I've since updated it for 
NetBSD-current and I am submitting it in this PR in the hope that others might 
find it useful.
>How-To-Repeat:

>Fix:
Simply add the following line to your kernel config:
options         PMS_FUJITSU_TOUCHPANEL          # Fujitsu touch panel.

Then apply these patches:
Index: sys/dev/pckbport/files.pckbport
===================================================================
RCS file: /cvsroot/src/sys/dev/pckbport/files.pckbport,v
retrieving revision 1.8
diff -u -r1.8 files.pckbport
--- sys/dev/pckbport/files.pckbport     7 Sep 2011 19:05:13 -0000       1.8
+++ sys/dev/pckbport/files.pckbport     10 Sep 2013 02:06:28 -0000
@@ -16,8 +16,10 @@
 obsolete defflag opt_pms.h             PMS_DISABLE_POWERHOOK
 defflag        opt_pms.h                       PMS_SYNAPTICS_TOUCHPAD
 defflag opt_pms.h                      PMS_ELANTECH_TOUCHPAD
+defflag        opt_pms.h                       PMS_FUJITSU_TOUCHPANEL
 device pms: wsmousedev
 attach pms at pckbport
 file   dev/pckbport/pms.c              pms
 file   dev/pckbport/synaptics.c        pms & pms_synaptics_touchpad
 file   dev/pckbport/elantech.c         pms & pms_elantech_touchpad
+file   dev/pckbport/fjttchps2.c        pms & pms_fujitsu_touchpanel
Index: sys/dev/pckbport/pms.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pckbport/pms.c,v
retrieving revision 1.35
diff -u -r1.35 pms.c
--- sys/dev/pckbport/pms.c      9 Sep 2011 14:29:47 -0000       1.35
+++ sys/dev/pckbport/pms.c      10 Sep 2013 02:07:05 -0000
@@ -1,5 +1,6 @@
 /* $NetBSD: pms.c,v 1.35 2011/09/09 14:29:47 jakllsch Exp $ */
 
+
 /*-
  * Copyright (c) 2004 Kentaro Kurahone.
  * Copyright (c) 2004 Ales Krenek.
@@ -46,6 +47,9 @@
 #ifdef PMS_ELANTECH_TOUCHPAD
 #include <dev/pckbport/elantechvar.h>
 #endif
+#ifdef PMS_FUJITSU_TOUCHPANEL
+#include <dev/pckbport/fjttchps2var.h>
+#endif
 
 #include <dev/pckbport/pmsreg.h>
 #include <dev/pckbport/pmsvar.h>
@@ -207,6 +211,12 @@
                sc->protocol = PMS_ELANTECH;
        } else
 #endif
+#ifdef PMS_FUJITSU_TOUCHPANEL
+       /* Probe for touchpanel touchpad. */
+       if (pms_tpanel_probe_init(sc) == 0) {
+               sc->protocol = PMS_FUJITSU;
+       } else
+#endif
                /* Install generic handler. */
                pckbport_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot,
                    pmsinput, sc, device_xname(sc->sc_dev));
@@ -255,6 +265,10 @@
        if (sc->protocol == PMS_ELANTECH)
                pms_elantech_enable(sc);
 #endif
+#ifdef PMS_FUJITSU_TOUCHPANEL
+       if (sc->protocol == PMS_FUJITSU)
+               pms_tpanel_enable(sc);
+#endif
 
        cmd[0] = PMS_DEV_ENABLE;
        res = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd,
--- sys/dev/pckbport/fjttchps2var.h.orig        2013-09-10 10:06:12.000000000 
+1000
+++ sys/dev/pckbport/fjttchps2var.h     2013-09-10 09:46:06.000000000 +1000
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2009-2013 Nathanial Sloss 
<nathanialsloss%yahoo.com.au@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_PCKBCPORT_tpanelVAR_H_
+#define _DEV_PCKBCPORT_tpanelVAR_H_
+
+int pms_tpanel_probe_init(void *vsc);
+void pms_tpanel_enable(void *vsc);
+void pms_tpanel_resume(void *vsc);
+
+#endif
--- sys/dev/pckbport/fjttchps2.c.orig   2013-09-10 10:05:48.000000000 +1000
+++ sys/dev/pckbport/fjttchps2.c        2013-09-10 10:39:21.000000000 +1000
@@ -0,0 +1,304 @@
+/*-
+ * Copyright (c) 2009-2013 Nathanial Sloss 
<nathanialsloss%yahoo.com.au@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_pms.h"
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+#include <sys/kernel.h>
+#include <machine/pio.h>
+
+#include <dev/pckbport/pckbportvar.h>
+
+#include <dev/pckbport/fjttchps2var.h>
+
+#include <dev/pckbport/pmsreg.h>
+#include <dev/pckbport/pmsvar.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsmousevar.h>
+
+/*
+ * Absolute-mode packets are decoded and passed around using
+ * the following structure.
+ */
+
+struct tpanel_packet {
+    int        sp_x;           /* Unscaled absolute X/Y coordinates */
+    int        sp_y;
+    u_char     sp_z;           /* Z (pressure) */
+    char       sp_left;        /* Left mouse button status */
+    char       sp_right;       /* Right mouse button status */
+    char       sp_middle;      /* Middle button status (possibly emulated) */
+    char       sp_up;          /* Up button status */
+    char       sp_down;        /* Down button status */
+};
+
+/* Masks for the first byte of a packet */
+#define PMS_LBUTMASK 0x01
+#define PMS_RBUTMASK 0x02
+#define PMS_MBUTMASK 0x04
+
+static void pms_tpanel_input(void *, int); 
+
+int 
+pms_tpanel_probe_init(void *vsc)
+{
+    struct pms_softc *psc = vsc;
+    /*
+     * This is suppossed to check DMI strings and ensure that the device 
+     * is infact a CF-18 with a touch screen.
+     *
+     * At the moment the driver is force loaded.
+     *
+     * This will cause big problems if enabled on machines without the
+     * appropriate hardware.
+     */
+
+    pckbport_set_inputhandler(psc->sc_kbctag, psc->sc_kbcslot,
+       pms_tpanel_input, psc, device_xname(psc->sc_dev));
+
+    return (0);
+}
+
+void 
+pms_tpanel_enable(void *vsc)
+{
+    struct pms_softc *psc = vsc;
+    u_char cmd[3];
+    int res = 0;
+    
+    /*
+     * Enable the touchscreen.
+     *
+     *
+     * The cmd sequence below will enable abs. output for touch screen.
+     * Once sent, the touch screen will output data.
+     * This also has the effect on the CF-18(TS) to set the touchpad to
+     * absolute mode and then both devices use this driver.
+     */
+
+    cmd[0] = PMS_SET_SCALE11; 
+    cmd[1] = PMS_SET_SAMPLE;
+    cmd[2] = 0x28; 
+
+    res |= pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 3, 0, 1, 
NULL);
+
+    cmd[0] = PMS_SET_RES; 
+    cmd[1] = 0x03; 
+
+    res |= pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 2, 0, 1, 
NULL);
+
+    cmd[0] = PMS_SET_RES; 
+    cmd[1] = 0x08; 
+
+    res |= pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 2, 0, 1, 
NULL);
+
+    /* The above command will always report a failure though. */
+    res = 0;
+
+    cmd[0] = PMS_DEV_ENABLE; 
+    cmd[1] = PMS_DEV_ENABLE; 
+    cmd[2] = PMS_DEV_ENABLE; 
+
+    res |= pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 3, 0, 1, 
NULL);
+
+    if (res) {
+       printf("%s: tpanel_enable: Error enabling device.\n",
+             device_xname(psc->sc_dev));
+    }
+}
+
+static void 
+pms_tpanel_input(void *vsc, int data)
+{
+       struct pms_softc *sc = vsc;
+       u_int changed;
+       int dx, dy, dz = 0;
+       int newbuttons = 0;
+
+       if (!sc->sc_enabled) {
+               /* Interrupts are not expected.  Discard the byte. */
+               return;
+       }
+
+       getmicrouptime(&sc->current);
+
+       if (sc->inputstate > 0) {
+               struct timeval diff;
+
+               timersub(&sc->current, &sc->last, &diff);
+               /*
+                * Empirically, the delay should be about 1700us on a standard
+                * PS/2 port.  I have seen delays as large as 4500us (rarely)
+                * in regular use.  When using a confused mouse, I generally
+                * see delays at least as large as 30,000us.  -seebs
+                *
+                * The thinkpad trackball returns at 22-23ms. So we use
+                * >= 40ms. In the future, I'll implement adaptable timeout
+                * by increasing the timeout if the mouse reset happens
+                * too frequently -christos
+                */
+               if (diff.tv_sec > 0 || diff.tv_usec >= 40000) {
+                       printf("pms_input: unusual delay (%ld.%06ld s), "
+                           "scheduling reset\n",
+                           (long)diff.tv_sec, (long)diff.tv_usec);
+                       sc->inputstate = 0;
+                       sc->sc_enabled = 0;
+                       wakeup(&sc->sc_enabled);
+                       return;
+               }
+       }
+       sc->last = sc->current;
+
+       if (sc->inputstate == 0) {
+               /*
+                * Some devices (seen on trackballs anytime, and on
+                * some mice shortly after reset) output garbage bytes
+                * between packets.  Just ignore them.
+                */
+               if ((data & 0xc0) != 0)
+                       return; /* not in sync yet, discard input */
+       }
+
+       sc->packet[sc->inputstate++] = data & 0xff;
+       switch (sc->inputstate) {
+       case 0:
+               /* no useful processing can be done yet */
+               break;
+
+       case 1:
+               /*
+                * Why should we test for bit 0x8 and insist on it here?
+                * The old (psm.c and psm_intelli.c) drivers didn't do
+                * it, and there are devices where it does harm (that's
+                * why it is not used if using PMS_STANDARD protocol).
+                * Anyway, it does not to cause any harm to accept packets
+                * without this bit.
+                */
+               sc->protocol = PMS_FUJITSU;
+
+               if (sc->packet[0] & 0x8) 
+                    sc->protocol = PMS_STANDARD;
+               break;
+
+       case 2:
+               break;
+
+       case 4:
+              break;
+       case 3:
+               /*
+                * This is only an endpoint for scroll protocols with 4
+                * bytes, or the standard protocol with 3.
+                */
+               if (sc->protocol != PMS_STANDARD && sc->inputstate == 3)
+                       break;
+
+               newbuttons |= ((sc->packet[0] & PMS_LBUTMASK) ? 0x1 : 0) |
+                   ((sc->packet[0] & PMS_MBUTMASK) ? 0x2 : 0) |
+                   ((sc->packet[0] & PMS_RBUTMASK) ? 0x4 : 0);
+
+               dx = sc->packet[1];
+               if (dx >= 128)
+                       dx -= 256;
+               if (dx == -128)
+                       dx = -127;
+
+               dy = sc->packet[2];
+               if (dy >= 128)
+                       dy -= 256;
+               if (dy == -128)
+                       dy = -127;
+
+               sc->inputstate = 0;
+               changed = (sc->buttons ^ newbuttons);
+               sc->buttons = newbuttons;
+
+#ifdef PMSDEBUG
+               if (sc->protocol == PMS_STANDARD) {
+                       DPRINTF(("pms: packet: 0x%02x%02x%02x\n",
+                           sc->packet[0], sc->packet[1], sc->packet[2]));
+               } else {
+                       DPRINTF(("pms: packet: 0x%02x%02x%02x%02x\n",
+                           sc->packet[0], sc->packet[1], sc->packet[2],
+                           sc->packet[3]));
+               }
+#endif
+               if (dx || dy || dz || changed) {
+#ifdef PMSDEBUG
+                       DPRINTF(("pms: x %+03d y %+03d z %+03d "
+                           "buttons 0x%02x\n", dx, dy, dz, sc->buttons));
+#endif
+                       wsmouse_input(sc->sc_wsmousedev,
+                           sc->buttons, dx, dy, dz, 0,
+                           WSMOUSE_INPUT_DELTA);
+               }
+               memset(sc->packet, 0, 4);
+               break;
+
+       case 5:
+               break;
+
+       case 6:
+               if (sc->protocol == PMS_FUJITSU) {
+                  dx = ((sc->packet[2] & 0x3f) |
+                      ((sc->packet[1] & 0x3f) << 5));
+                  dy = ((sc->packet[5] & 0x3f) |
+                      ((sc->packet[4] & 0x3f) << 5));
+                  dz = 0;
+                  newbuttons = (sc->packet[0] & 0x04) >> 2;
+#ifdef tpanelDEBUG
+                   printf("X coordinate: [%d], Y coordinate: [%d] Buttons: 
[%d] \n",dx,dy,newbuttons);
+#endif         
+                 sc->inputstate = 0;
+                 changed = (sc->buttons ^ newbuttons);
+                  newbuttons = newbuttons & PMS_LBUTMASK;
+
+                 if (dx || dy || dz || changed) {
+                     wsmouse_input(sc->sc_wsmousedev, 
+                         newbuttons, dx, dy, dz, 0, 
+                         WSMOUSE_INPUT_ABSOLUTE_X|WSMOUSE_INPUT_ABSOLUTE_Y);
+               }
+            }
+
+           memset(sc->packet, 0, 4);
+           break;
+
+       /* If we get here, we have problems. */
+       default:
+               printf("pmsinput: very confused.  resetting.\n");
+               sc->inputstate = 0;
+               sc->sc_enabled = 0;
+               wakeup(&sc->sc_enabled);
+               return;
+       }
+}

Unfortunately as of this time I am yet to write a manual page but it would be 
minimal only informing that one needs to use this with the ws(4) X11 input 
driver.

I hope others find this useful.

Regards,

Nat.



Home | Main Index | Thread Index | Old Index