he1per / psmouse-dkms-alpsv7

Linux kernel driver for newer ALPS touchpads (as of Mar 2014)
26 stars 26 forks source link

ALPSv7: trackstick support #4

Closed vencik closed 10 years ago

vencik commented 10 years ago

Hello everyone,

I've taken the liberty to merge in support for the trackstick found on Toshiba Portege Z30-A models. See below.

If anyone has such a device with the trackstick, please could you test it? I already know of one guy (Hi Drejc!), but the more the better. Also, it would be great if someone without the TS could re-test the patch...

Btw, I've noticed that the tree is behind time; Elaine's latest patch adds more (finger rest zone I think, at the very least); does anyone know how active this project is (or is supposed to be)?

Thanks,

vencik

From 8ffaa4eee8c2803a54618ffe77639b873be31a9e Mon Sep 17 00:00:00 2001
From: vencik <vencik@razdva.cz>
Date: Tue, 29 Apr 2014 09:24:50 +0200
Subject: [PATCH] Added support for trackstick

Piggybacking: fixed a few glitches in dkms.conf and th install.sh script.

---
 dkms.conf  |  4 ++--
 install.sh |  6 +++---
 src/alps.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/alps.h |  1 +
 4 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/dkms.conf b/dkms.conf
index b4a1183..e1361af 100644
--- a/dkms.conf
+++ b/dkms.conf
@@ -2,12 +2,12 @@
 # Modified by helper

 PACKAGE_NAME="psmouse-dkms-alpsv7"
-PACKAGE_VERSION="1.0"
+PACKAGE_VERSION="1.1"
 CLEAN="rm -f *.*o"

 BUILT_MODULE_NAME[0]="psmouse"
 MAKE[0]="make -C $kernel_source_dir M=$dkms_tree/$PACKAGE_NAME/$PACKAGE_VERSION/build/src psmouse.ko"
 BUILT_MODULE_LOCATION[0]="src"
-DEST_MODULE_LOCATION[0]="/updates"
+DEST_MODULE_LOCATION[0]="/updates/dkms"

 AUTOINSTALL="yes"
diff --git a/install.sh b/install.sh
index 19555cb..ed17c4b 100755
--- a/install.sh
+++ b/install.sh
@@ -1,15 +1,15 @@
-#!/bin/sh
+#!/bin/bash

 source ./dkms.conf

-MDIR="/usr/lib/modules/$(uname -r)"
+MDIR="/lib/modules/$(uname -r)"
 NEWMDIR="$MDIR/${DEST_MODULE_LOCATION[0]}"

 MFILE="$MDIR/kernel/drivers/input/mouse/${BUILT_MODULE_NAME[0]}.ko"
 NEWMFILE="$NEWMDIR/${BUILT_MODULE_NAME[0]}.ko"

 M=psmouse-dkms-alpsv7
-V=1.0
+V=1.1

 #Print error message and exit
 abort()
diff --git a/src/alps.c b/src/alps.c
index 3e8e8f7..63ba243 100644
--- a/src/alps.c
+++ b/src/alps.c
@@ -1003,6 +1003,8 @@ static unsigned char alps_get_packet_id_v7(char *byte)
        packet_id = V7_PACKET_ID_MULTI;
    else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
        packet_id = V7_PACKET_ID_NEW;
+   else if (byte[1] & 0x08)
+       packet_id = V7_PACKET_ID_TRACKSTICK;
    else
        packet_id = V7_PACKET_ID_IDLE;

@@ -1056,8 +1058,6 @@ static void alps_decode_packet_v7(struct alps_fields *f,
 {
    struct alps_data *priv = psmouse->private;

-   priv->r.v7.pkt_id = alps_get_packet_id_v7(p);
-
    alps_get_finger_coordinate_v7(f->pt_img, p, priv->r.v7.pkt_id);

    priv->r.v7.rest_left = 0;
@@ -1236,12 +1236,60 @@ static void alps_assign_buttons_v7(struct psmouse *psmouse,
    priv->prev_phy_btn = priv->phy_btn;
 }

+static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
+{
+   unsigned char    *packet = psmouse->packet;
+   struct alps_data *priv   = psmouse->private;
+   struct input_dev *dev    = priv->dev2;
+
+   int x, y;  /* trackstick vector */
+
+   /* Buttons status is reported for any packet */
+   input_report_key(dev, BTN_LEFT,  !!(0x01 & packet[1]));
+   input_report_key(dev, BTN_RIGHT, !!(0x02 & packet[1]));
+
+   /*
+    * AlpsPS/2 v7 trackstick produces 2D relative coorinates
+    * as signed integers (normal binary complement +1 encoding)
+    */
+
+   x  = (0x3f & packet[2]);       /* low 6 bits */
+   x |= (0x10 & packet[3]) << 2;  /* bit 7      */
+   x |= (0x80 & packet[2]);       /* bit 8      */
+
+   /* x sign */
+   if (0x10 & packet[1])
+       x |= -1 << 8;
+
+   y  = (0x07 & packet[3]);       /* low 3 bits */
+   y |= (0x20 & packet[3]) >> 2;  /* bit 4      */
+   y |= (0x38 & packet[4]) << 1;  /* bits 5 - 7 */
+   y |= (0x80 & packet[4]);       /* bit 8      */
+
+   /* y sign */
+   if (0x20 & packet[1])
+       y |= -1 << 8;
+
+   /* Report trackstick vector */
+   input_report_rel(dev, REL_X,  x / 6);
+   input_report_rel(dev, REL_Y, -y / 8);
+
+   input_sync(dev);
+}
+
 static void alps_process_packet_v7(struct psmouse *psmouse)
 {
    struct alps_data *priv = psmouse->private;
    struct alps_fields f = {0};
    unsigned char *packet = psmouse->packet;

+   /* Resolve packet ID */
+   priv->r.v7.pkt_id = alps_get_packet_id_v7(packet);
+
+   /* Process trackstick packet separately */
+   if (priv->r.v7.pkt_id == V7_PACKET_ID_TRACKSTICK)
+       return alps_process_trackstick_packet_v7(psmouse);
+
    priv->decode_fields(&f, packet, psmouse);

    if (alps_drop_unsupported_packet_v7(psmouse))
diff --git a/src/alps.h b/src/alps.h
index 5d2f9ea..c2ba260 100644
--- a/src/alps.h
+++ b/src/alps.h
@@ -46,6 +46,7 @@ enum V7_PACKET_ID {
     V7_PACKET_ID_TWO,
     V7_PACKET_ID_MULTI,
     V7_PACKET_ID_NEW,
+    V7_PACKET_ID_TRACKSTICK,
 };

 /**
-- 
1.9.2
vencik commented 10 years ago

@jpffitch Strange; I can't see any error logged; it seems that the module was actually built fine... As @alehandrof suggested above, if kernel 3.17 is available for OpenSUSE, it's your best choice, anyway.

he1per commented 10 years ago

Thank you for all your work, I have updated the patch with newer version from March (thanks to Volker and @vencik); and also fixed some bogus error messages (when sources already existed). Also added some more user-friendly checks for running as root.