From: Stephen Evanchik <evanchsa@gmail.com>
To: Vojtech Pavlik <vojtech@suse.cz>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH 2.6.11-rc3] IBM Trackpoint support
Date: Thu, 3 Feb 2005 17:43:29 -0500 [thread overview]
Message-ID: <a71293c20502031443764fb4e5@mail.gmail.com> (raw)
Vojtech,
Here is a patch that exposes the IBM TrackPoint's extended properties
as well as scroll wheel emulation.
I would appreciate comments and suggestions to make this more acceptable.
Stephen
diff -uNr a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
--- a/drivers/input/mouse/Makefile 2005-02-03 17:30:40.000000000 -0500
+++ b/drivers/input/mouse/Makefile 2005-02-03 17:29:42.000000000 -0500
@@ -14,4 +14,4 @@
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.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 trackpoint.o
diff -uNr a/drivers/input/mouse/psmouse-base.c
b/drivers/input/mouse/psmouse-base.c
--- a/drivers/input/mouse/psmouse-base.c 2005-02-03 17:30:40.000000000 -0500
+++ b/drivers/input/mouse/psmouse-base.c 2005-02-03 17:29:42.000000000 -0500
@@ -23,6 +23,7 @@
#include "psmouse.h"
#include "synaptics.h"
#include "logips2pp.h"
+#include "trackpoint.h"
#include "alps.h"
#define DRIVER_DESC "PS/2 mouse driver"
@@ -119,6 +120,13 @@
}
/*
+ * TrackPoint scroll simulation handler if the BTN_MIDDLE is down
+ */
+
+ if(psmouse->model == PSMOUSE_TRACKPOINT)
+ trackpoint_sim_scroll(psmouse);
+
+/*
* Generic PS/2 Mouse
*/
@@ -482,6 +490,16 @@
return PSMOUSE_IMPS;
/*
+ * Try to initialize the IBM TrackPoint
+ */
+ if (max_proto > PSMOUSE_PS2 && trackpoint_init(psmouse) == 0) {
+ psmouse->vendor = "IBM";
+ psmouse->name = "TrackPoint";
+
+ return PSMOUSE_PS2;
+ }
+
+/*
* Okay, all failed, we have a standard mouse here. The number of the buttons
* is still a question, though. We assume 3.
*/
diff -uNr a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
--- a/drivers/input/mouse/trackpoint.c 1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/input/mouse/trackpoint.c 2005-02-03 17:29:42.000000000 -0500
@@ -0,0 +1,649 @@
+/*
+ * Stephen Evanchik <evanchsa@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Trademarks are the property of their respective owners.
+ *
+ * 29/01/2005 - Fixed UltraNav support
+ * Moved to libps2 interface
+ * Renamed internal property variables to be consistent with reference docs
+ * Fixed negative inertia not being set properly
+ * Added middle button scroll module parameter
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/serio.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/input.h>
+#include <linux/libps2.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include "psmouse.h"
+#include "trackpoint.h"
+
+
+int tp_sens = TP_DEF_SENS;
+module_param_named(sens, tp_sens, uint, 0);
+MODULE_PARM_DESC(sens, "Sensitivity");
+
+int tp_speed = TP_DEF_SPEED;
+module_param_named(speed, tp_speed, uint, 0);
+MODULE_PARM_DESC(speed, "Speed of pointer");
+
+int tp_reach = TP_DEF_REACH;
+module_param_named(reach, tp_reach, uint, 0);
+MODULE_PARM_DESC(reach, "Backup Range");
+
+int tp_draghys = TP_DEF_DRAGHYS;
+module_param_named(draghys, tp_draghys, uint, 0);
+MODULE_PARM_DESC(draghys, "Resistance to dragging");
+
+int tp_mindrag = TP_DEF_MINDRAG;
+module_param_named(mindrag, tp_mindrag, uint, 0);
+MODULE_PARM_DESC(mindrag, "Drag threshold");
+
+int tp_thresh = TP_DEF_THRESH;
+module_param_named(thresh, tp_thresh, uint, 0);
+MODULE_PARM_DESC(thresh, "Force necessary to trigger a press or release");
+
+int tp_upthresh = TP_UP_THRESH;
+module_param_named(upthresh, tp_upthresh, uint, 0);
+MODULE_PARM_DESC(upthresh, "Force necessary to trigger a click");
+
+int tp_ztime = TP_DEF_Z_TIME;
+module_param_named(ztime, tp_ztime, uint, 0);
+MODULE_PARM_DESC(ztime, "Determines how sharp a press is");
+
+int tp_jenks = TP_DEF_JENKS_CURV;
+module_param_named(jenks, tp_jenks, uint, 0);
+MODULE_PARM_DESC(jenks, "Double click sensitivity");
+
+
+/* Toggles */
+int tp_ptson = TP_DEF_PTSON;
+module_param_named(ptson, tp_ptson, uint, 0);
+MODULE_PARM_DESC(ptson, "Press to Select");
+
+int tp_mb = TP_DEF_MB;
+module_param_named(mb, tp_mb, uint, 0);
+MODULE_PARM_DESC(mb, "Middle button is disabled");
+
+int tp_mb_scroll = TP_DEF_MB_SCROLL;
+module_param_named(mb_scroll, tp_mb_scroll, uint, 0);
+MODULE_PARM_DESC(mb_scroll, "Scroll with middle button");
+
+
+__obsolete_setup("pts=");
+__obsolete_setup("backup=");
+__obsolete_setup("draghyst=");
+
+/*
+ * Device IO: read, write and toggle bit
+ */
+static void trackpoint_command(struct ps2dev *ps2dev, unsigned char cmd)
+{
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND));
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, cmd));
+}
+
+static void trackpoint_read(struct ps2dev *ps2dev, unsigned char loc,
unsigned char *results)
+{
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND));
+ ps2_command(ps2dev, results, MAKE_PS2_CMD(0, 1, loc));
+}
+
+static void trackpoint_write(struct ps2dev *ps2dev, unsigned char
loc, unsigned char val)
+{
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND));
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_WRITE_MEM));
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc));
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, val));
+}
+
+static int trackpoint_toggle_bit(struct ps2dev *ps2dev, unsigned char
loc, unsigned char mask)
+{
+ /* Bad things will happen if the loc param isn't in this range */
+ if(loc < 0x20 || loc >= 0x2F)
+ return -1;
+
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND));
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_TOGGLE));
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc));
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, mask));
+
+ return 0;
+}
+
+
+#ifdef CONFIG_PROC_FS
+
+#define PROC_READ_NAME(name) name##_read_func
+#define PROC_WRITE_NAME(name) name##_write_func
+#define PROC_TOGGLE_NAME(name) name##_toggle_func
+
+#define MAKE_PROC_READ(name, item) \
+ static int name(char* page, char** start, off_t off, int count, int*
eof, void* data) \
+ { \
+ int len; \
+ struct psmouse *psmouse = (struct psmouse *)data; \
+ struct trackpoint_data *tp = (struct trackpoint_data*)psmouse->private; \
+ len = sprintf(page, "%lu\n", (unsigned long)tp->item); \
+ *eof = 1; \
+ return len; \
+ }
+
+#define MAKE_PROC_WRITE(name, item, command) \
+ static int name(struct file *file, const char __user *buffer,
unsigned long count, void *data) \
+ { \
+ int len = count; \
+ unsigned char tmp[5]; \
+ struct psmouse *psmouse = (struct psmouse *)data; \
+ struct trackpoint_data *tp = (struct trackpoint_data*)psmouse->private; \
+ if(count > sizeof(tmp) - 1) \
+ len = sizeof(tmp) - 1; \
+ if(copy_from_user(tmp, buffer, len)) \
+ return -EFAULT; \
+ tmp[len] = '\0'; \
+ tp->item = simple_strtoul(tmp, 0, 10); \
+ trackpoint_write(&psmouse->ps2dev, command, tp->item); \
+ return len; \
+ }
+
+#define MAKE_PROC_TOGGLE(name, item, command, mask) \
+ static int name(struct file *file, const char __user *buffer,
unsigned long count, void *data) \
+ { \
+ int len = count; \
+ unsigned char toggle, tmp[5]; \
+ struct psmouse *psmouse = (struct psmouse *)data; \
+ struct trackpoint_data *tp = (struct trackpoint_data*)psmouse->private; \
+ if(count > sizeof(tmp) - 1) \
+ len = sizeof(tmp) - 1; \
+ if(copy_from_user(tmp, buffer, len)) \
+ return -EFAULT; \
+ tmp[len] = '\0'; \
+ toggle = (tmp[0] == '1') ? 1 : 0; \
+ if( toggle != tp->item) { \
+ tp->item = toggle; \
+ trackpoint_toggle_bit(&psmouse->ps2dev, command, mask); \
+ } \
+ return len; \
+ }
+
+
+MAKE_PROC_WRITE(PROC_WRITE_NAME(sensitivity), sens, TP_SENS);
+MAKE_PROC_READ(PROC_READ_NAME(sensitivity), sens);
+
+MAKE_PROC_WRITE(PROC_WRITE_NAME(speed), speed, TP_SPEED);
+MAKE_PROC_READ(PROC_READ_NAME(speed), speed);
+
+MAKE_PROC_WRITE(PROC_WRITE_NAME(neg_inertia), inertia, TP_INERTIA);
+MAKE_PROC_READ(PROC_READ_NAME(neg_inertia), inertia);
+
+MAKE_PROC_WRITE(PROC_WRITE_NAME(backup), reach, TP_REACH);
+MAKE_PROC_READ(PROC_READ_NAME(backup), reach);
+
+MAKE_PROC_WRITE(PROC_WRITE_NAME(drag_hyst), draghys, TP_DRAGHYS);
+MAKE_PROC_READ(PROC_READ_NAME(drag_hyst), draghys);
+
+MAKE_PROC_WRITE(PROC_WRITE_NAME(min_drag), mindrag, TP_MINDRAG);
+MAKE_PROC_READ(PROC_READ_NAME(min_drag), mindrag);
+
+MAKE_PROC_WRITE(PROC_WRITE_NAME(thresh), thresh, TP_THRESH);
+MAKE_PROC_READ(PROC_READ_NAME(thresh), thresh);
+
+MAKE_PROC_WRITE(PROC_WRITE_NAME(up_thresh), up_thresh, TP_UP_THRESH);
+MAKE_PROC_READ(PROC_READ_NAME(up_thresh), up_thresh);
+
+MAKE_PROC_WRITE(PROC_WRITE_NAME(z_time), z_time, TP_Z_TIME);
+MAKE_PROC_READ(PROC_READ_NAME(z_time), z_time);
+
+MAKE_PROC_WRITE(PROC_WRITE_NAME(jenks_curv), jenks_curv, TP_JENKS_CURV);
+MAKE_PROC_READ(PROC_READ_NAME(jenks_curv), jenks_curv);
+
+MAKE_PROC_TOGGLE(PROC_TOGGLE_NAME(ptson), ptson, TP_TOGGLE_PTSON,
TP_MASK_PTSON);
+MAKE_PROC_READ(PROC_READ_NAME(ptson), ptson);
+
+MAKE_PROC_TOGGLE(PROC_TOGGLE_NAME(skip_back), skipback,
TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
+MAKE_PROC_READ(PROC_READ_NAME(skip_back), skipback);
+
+MAKE_PROC_TOGGLE(PROC_TOGGLE_NAME(mb), mb, TP_TOGGLE_MB, TP_MASK_MB);
+MAKE_PROC_READ(PROC_READ_NAME(mb), mb);
+
+MAKE_PROC_TOGGLE(PROC_TOGGLE_NAME(ext_dev), ext_dev,
TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
+MAKE_PROC_READ(PROC_READ_NAME(ext_dev), ext_dev);
+
+/* MAKE_PROC_WRITE( ) for Soft Transparent mode */
+static int transparent_write_func(struct file *file, const char
__user *buffer, unsigned long count, void *data)
+{
+ int len = count;
+ unsigned char command;
+ unsigned char tmp[5];
+ struct psmouse *psmouse = (struct psmouse *)data;
+ struct trackpoint_data *tp = (struct trackpoint_data*)psmouse->private;
+ if(count > sizeof(tmp) - 1)
+ len = sizeof(tmp) - 1;
+ if(copy_from_user(tmp, buffer, len))
+ return -EFAULT;
+ tmp[len] = '\0'; \
+ tp->transparent = simple_strtoul(tmp, 0, 10);
+ command = (tp->transparent) ? TP_SET_SOFT_TRANS : TP_CANCEL_SOFT_TRANS;
+
+ trackpoint_command(&psmouse->ps2dev, command);
+ return len;
+}
+
+MAKE_PROC_READ(PROC_READ_NAME(transparent), transparent);
+
+/* MAKE_PROC_WRITE( ) for Middle Button Scroll mode */
+static int scroll_write_func(struct file *file, const char __user
*buffer, unsigned long count, void *data)
+{
+ int len = count;
+ unsigned char tmp[5];
+ struct psmouse *psmouse = (struct psmouse *)data;
+ struct trackpoint_data *tp = (struct trackpoint_data*)psmouse->private;
+ if(count > sizeof(tmp) - 1)
+ len = sizeof(tmp) - 1;
+ if(copy_from_user(tmp, buffer, len))
+ return -EFAULT;
+ tmp[len] = '\0'; \
+ tp->mb_scroll = simple_strtoul(tmp, 0, 10);
+
+ return len;
+}
+
+MAKE_PROC_READ(PROC_READ_NAME(scroll), mb_scroll);
+
+/* MAKE_PROC_WRITE( ) for delay before scroll */
+static int scroll_delay_write_func(struct file *file, const char
__user *buffer, unsigned long count, void *data)
+{
+ int len = count;
+ unsigned char tmp[5];
+ struct psmouse *psmouse = (struct psmouse *)data;
+ struct trackpoint_data *tp = (struct trackpoint_data*)psmouse->private;
+ if(count > sizeof(tmp) - 1)
+ len = sizeof(tmp) - 1;
+ if(copy_from_user(tmp, buffer, len))
+ return -EFAULT;
+ tmp[len] = '\0'; \
+ tp->scroll_delay = simple_strtoul(tmp, 0, 10);
+
+ return len;
+}
+
+MAKE_PROC_READ(PROC_READ_NAME(scroll_delay), scroll_delay);
+
+
+
+#define NEW_PROC_ENTRY(name) \
+ entry = create_proc_entry(#name, 0644, tp_dir); \
+ if(!entry) \
+ goto no_##name; \
+ entry->owner = THIS_MODULE; \
+ entry->data = psmouse; \
+ entry->read_proc = PROC_READ_NAME(name); \
+ entry->write_proc = PROC_WRITE_NAME(name);
+
+
+#define NEW_PROC_TOGGLE_ENTRY(name) \
+ entry = create_proc_entry(#name, 0644, tp_dir); \
+ if(!entry) \
+ goto no_##name; \
+ entry->owner = THIS_MODULE; \
+ entry->data = psmouse; \
+ entry->read_proc = PROC_READ_NAME(name); \
+ entry->write_proc = PROC_TOGGLE_NAME(name);
+
+
+
+static struct proc_dir_entry *tp_dir = NULL;
+
+
+static int trackpoint_proc_init(struct psmouse *psmouse)
+{
+ struct proc_dir_entry *entry = NULL;
+
+ tp_dir = proc_mkdir("trackpoint", NULL);
+ if(!tp_dir)
+ return -ENOMEM;
+
+ tp_dir->owner = THIS_MODULE;
+
+ NEW_PROC_ENTRY(sensitivity);
+ NEW_PROC_ENTRY(speed);
+ NEW_PROC_ENTRY(neg_inertia);
+ NEW_PROC_ENTRY(backup);
+ NEW_PROC_ENTRY(drag_hyst);
+ NEW_PROC_ENTRY(min_drag);
+ NEW_PROC_ENTRY(thresh);
+ NEW_PROC_ENTRY(up_thresh);
+ NEW_PROC_ENTRY(z_time);
+ NEW_PROC_ENTRY(jenks_curv);
+
+ NEW_PROC_TOGGLE_ENTRY(ptson);
+ NEW_PROC_TOGGLE_ENTRY(skip_back);
+ NEW_PROC_TOGGLE_ENTRY(mb);
+ NEW_PROC_TOGGLE_ENTRY(ext_dev);
+
+ /* Soft Transparent mode isn't a toggle or a single
+ * command used to read/write the value
+ */
+ entry = create_proc_entry("transparent", 0644, tp_dir);
+ if(!entry)
+ goto no_transparent;
+ entry->owner = THIS_MODULE;
+ entry->data = psmouse;
+ entry->read_proc = transparent_read_func;
+ entry->write_proc = transparent_write_func;
+
+ entry = create_proc_entry("scroll", 0644, tp_dir);
+ if(!entry)
+ goto no_scroll;
+ entry->owner = THIS_MODULE;
+ entry->data = psmouse;
+ entry->read_proc = scroll_read_func;
+ entry->write_proc = scroll_write_func;
+
+ entry = create_proc_entry("scroll_delay", 0644, tp_dir);
+ if(!entry)
+ goto no_scroll_delay;
+ entry->owner = THIS_MODULE;
+ entry->data = psmouse;
+ entry->read_proc = scroll_delay_read_func;
+ entry->write_proc = scroll_delay_write_func;
+
+ return 0;
+
+no_scroll_delay:
+ remove_proc_entry("scroll_delay", tp_dir);
+
+no_scroll:
+ remove_proc_entry("transparent", tp_dir);
+
+no_transparent:
+ remove_proc_entry("ext_dev", tp_dir);
+
+no_ext_dev:
+ remove_proc_entry("mb", tp_dir);
+
+no_mb:
+ remove_proc_entry("skip_back", tp_dir);
+
+no_skip_back:
+ remove_proc_entry("ptson", tp_dir);
+
+no_ptson:
+ remove_proc_entry("jenks_curv", tp_dir);
+
+no_jenks_curv:
+ remove_proc_entry("z_time", tp_dir);
+
+no_z_time:
+ remove_proc_entry("up_thresh", tp_dir);
+
+no_up_thresh:
+ remove_proc_entry("thresh", tp_dir);
+
+no_thresh:
+ remove_proc_entry("min_drag", tp_dir);
+
+no_min_drag:
+ remove_proc_entry("drag_hyst", tp_dir);
+
+no_drag_hyst:
+ remove_proc_entry("backup", tp_dir);
+
+no_backup:
+ remove_proc_entry("neg_inertia", tp_dir);
+
+no_neg_inertia:
+ remove_proc_entry("speed", tp_dir);
+
+no_speed:
+ remove_proc_entry("sensitivity", tp_dir);
+
+no_sensitivity:
+ remove_proc_entry("trackpoint", NULL);
+
+ return -ENOMEM;
+}
+
+static void trackpoint_proc_remove(void)
+{
+ remove_proc_entry("scroll_delay", tp_dir);
+ remove_proc_entry("scroll", tp_dir);
+ remove_proc_entry("transparent", tp_dir);
+ remove_proc_entry("ext_dev", tp_dir);
+ remove_proc_entry("mb", tp_dir);
+ remove_proc_entry("skip_back", tp_dir);
+ remove_proc_entry("ptson", tp_dir);
+ remove_proc_entry("jenks_curv", tp_dir);
+ remove_proc_entry("z_time", tp_dir);
+ remove_proc_entry("up_thresh", tp_dir);
+ remove_proc_entry("thresh", tp_dir);
+ remove_proc_entry("min_drag", tp_dir);
+ remove_proc_entry("drag_hyst", tp_dir);
+ remove_proc_entry("backup", tp_dir);
+ remove_proc_entry("neg_inertia", tp_dir);
+ remove_proc_entry("speed", tp_dir);
+ remove_proc_entry("sensitivity", tp_dir);
+ remove_proc_entry("trackpoint", NULL);
+}
+
+#else
+static int trackpoint_proc_init(struct psmouse *psmouse) { return 0; }
+static void trackpoint_proc_remove(void) { }
+#endif
+
+
+/* This is much cleaner now, it probably could be better.
+ * The only thing left here is to make the scroll feature more gradual.
+ */
+
+void trackpoint_sim_scroll(struct psmouse *psmouse)
+{
+ int diff;
+ struct trackpoint_data *tp = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+
+ if(!tp->mb_scroll)
+ return;
+
+ if( ((packet[0] >> 2) & 1) == 0 ) {
+
+ if(tp->mb_was_down &&
+ time_after(tp->last_mb_press +
msecs_to_jiffies(tp->scroll_delay), jiffies)) {
+
+ /* This doesn't seem to get processed until the next
+ * mouse move.
+ */
+ input_report_key(&psmouse->dev, BTN_MIDDLE, 1);
+
+ input_sync(&psmouse->dev);
+ }
+
+ tp->scrolling = 0;
+ tp->mb_was_down = 0;
+ }
+ else if(tp->scrolling) {
+
+ /* Vertical scrolling */
+ diff = (int) ((packet[0] << 3) & 0x100) - (int) packet[2];
+ if( diff < -2 ) {
+ input_report_rel(&psmouse->dev, REL_WHEEL, 1);
+ }
+ else if(diff > 2) {
+ input_report_rel(&psmouse->dev, REL_WHEEL, -1);
+ }
+
+ /* Horizontal scrolling */
+ diff = (int) packet[1] - (int) ((packet[0] << 4) & 0x100);
+ if( diff < -2) {
+ input_report_rel(&psmouse->dev, REL_HWHEEL, 1);
+ }
+ else if( diff > 2) {
+ input_report_rel(&psmouse->dev, REL_HWHEEL, -1);
+ }
+
+ packet[1] &= 0x00;
+ packet[2] &= 0x00;
+ }
+ else {
+ /* Middle button is down, but we aren't scrolling */
+ if( time_after_eq(jiffies, tp->last_mb_press +
msecs_to_jiffies(tp->scroll_delay)) )
+ tp->scrolling = 1;
+
+ tp->last_mb_press = jiffies;
+ tp->mb_was_down = 1;
+ }
+
+ /* Suppress the key event from entering the queue */
+ packet[0] &= 0xFB;
+}
+
+void trackpoint_disconnect(struct psmouse *psmouse)
+{
+ trackpoint_proc_remove();
+ kfree(psmouse->private);
+}
+
+int trackpoint_reconnect(struct psmouse *psmouse)
+{
+ unsigned char toggle;
+ struct trackpoint_data *tp = psmouse->private;
+
+ /* Push the config to the device */
+
+ trackpoint_write(&psmouse->ps2dev, TP_SENS, tp->sens);
+ trackpoint_write(&psmouse->ps2dev, TP_INERTIA, tp->inertia);
+ trackpoint_write(&psmouse->ps2dev, TP_SPEED, tp->speed);
+
+ trackpoint_write(&psmouse->ps2dev, TP_REACH, tp->reach);
+ trackpoint_write(&psmouse->ps2dev, TP_DRAGHYS, tp->draghys);
+ trackpoint_write(&psmouse->ps2dev, TP_MINDRAG, tp->mindrag);
+
+ trackpoint_write(&psmouse->ps2dev, TP_THRESH, tp->thresh);
+ trackpoint_write(&psmouse->ps2dev, TP_UP_THRESH, tp->up_thresh);
+
+ trackpoint_write(&psmouse->ps2dev, TP_Z_TIME, tp->z_time);
+ trackpoint_write(&psmouse->ps2dev, TP_JENKS_CURV, tp->jenks_curv);
+
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_PTSON, &toggle);
+ if(((toggle & TP_MASK_PTSON) == TP_MASK_PTSON)!= tp->ptson)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_PTSON, TP_MASK_PTSON);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_MB, &toggle);
+ if(((toggle & TP_MASK_MB) == TP_MASK_MB) != tp->mb)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_MB, TP_MASK_MB);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle);
+ if(((toggle & TP_MASK_TWOHAND) == TP_MASK_TWOHAND) != tp->twohand)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, TP_MASK_TWOHAND);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, &toggle);
+ if(((toggle & TP_MASK_SKIPBACK) == TP_MASK_SKIPBACK) != tp->skipback)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK,
TP_MASK_SKIPBACK);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_MB, &toggle);
+ if(((toggle & TP_MASK_MB) == TP_MASK_MB) != tp->mb)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_MB, TP_MASK_MB);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, &toggle);
+ if(((toggle & TP_MASK_SOURCE_TAG) == TP_MASK_SOURCE_TAG) != tp->source_tag)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG,
TP_MASK_SOURCE_TAG);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, &toggle);
+ if(((toggle & TP_MASK_EXT_DEV) == TP_MASK_EXT_DEV) != tp->skipback)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
+
+ return 0;
+}
+
+static void trackpoint_defaults(struct trackpoint_data *tp)
+{
+ tp->ptson = tp_ptson;
+ tp->sens = tp_sens;
+ tp->speed = tp_speed;
+ tp->reach = tp_reach;
+
+ tp->draghys = tp_draghys;
+ tp->mindrag = tp_mindrag;
+
+ tp->thresh = tp_thresh;
+ tp->up_thresh = tp_upthresh;
+
+ tp->z_time = tp_ztime;
+ tp->jenks_curv = tp_jenks;
+
+ tp->mb = tp_mb;
+ tp->mb_scroll = tp_mb_scroll;
+
+ /* The following can't be set via module parameters */
+ tp->inertia = TP_DEF_INERTIA;
+ tp->skipback = TP_DEF_SKIPBACK;
+ tp->ext_dev = TP_DEF_EXT_DEV;
+ tp->scroll_delay = TP_DEF_SCROLL_DELAY;
+
+ tp->scrolling = tp->mb_was_down = 0;
+ tp->xacc = tp->yacc = 0;
+}
+
+
+
+int trackpoint_init(struct psmouse *psmouse)
+{
+ unsigned char param[2];
+ struct trackpoint_data *priv;
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+ param[0] = param[1] = 0;
+
+ /* The real driver disables, queries and
+ then enables so we'll do that too
+ */
+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
+
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_DISABLE));
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_DISABLE_EXT));
+
+ ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID));
+
+ if(param[0] != TP_MAGIC_IDENT)
+ return -1;
+
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_ENABLE_EXT));
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_ENABLE));
+
+ psmouse->private = priv = kmalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
+
+ if(!priv)
+ return -1;
+
+ memset(priv, 0, sizeof(struct trackpoint_data));
+
+ priv->firmware_id = param[1];
+ trackpoint_defaults(priv);
+
+ trackpoint_reconnect(psmouse);
+ trackpoint_proc_init(psmouse);
+
+
+ /* Used to simulate wheel scrolling */
+ set_bit(REL_HWHEEL, psmouse->dev.relbit);
+ set_bit(REL_WHEEL, psmouse->dev.relbit);
+
+ psmouse->model = PSMOUSE_TRACKPOINT;
+
+ psmouse->reconnect = trackpoint_reconnect;
+ psmouse->disconnect = trackpoint_disconnect;
+
+ printk("IBM TrackPoint firmware: 0x%02X\n", param[1]);
+
+ return 0;
+}
+
diff -uNr a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
--- a/drivers/input/mouse/trackpoint.h 1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/input/mouse/trackpoint.h 2005-02-03 17:29:42.000000000 -0500
@@ -0,0 +1,170 @@
+/*
+ * IBM TrackPoint PS/2 mouse driver
+ *
+ * Stephen Evanchik <evanchsa@clarkson.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _TRACKPOINT_H
+#define _TRACKPOINT_H
+
+/*
+ * These constants are from the TrackPoint System
+ * Engineering documentation Version 4 from IBM Watson
+ * research:
+ * http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
+ */
+
+#define TP_DISABLE (0xF5)
+#define TP_ENABLE (0xF4)
+
+#define TP_READ_ID (0xE1) /* Sent for device identification */
+#define TP_MAGIC_IDENT (0x01) /* Sent after a TP_READ_ID followed */
+ /* by the firmware ID */
+
+#define TP_COMMAND (0xE2) /* Commands start with this */
+
+
+/*
+ * Commands
+ */
+#define TP_RECALIB (0x51) /* Recalibrate */
+#define TP_POWER_DOWN (0x44) /* Can only be undone through HW reset */
+#define TP_EXT_DEV (0x21) /* Determines if external device is connected (RO) */
+#define TP_EXT_BTN (0x4B) /* Read extended button status */
+#define TP_POR (0x7F) /* Execute Power on Reset */
+#define TP_POR_RESULTS (0x25) /* Read Power on Self test results */
+#define TP_DISABLE_EXT (0x40) /* Disable external pointing device */
+#define TP_ENABLE_EXT (0x41) /* Enable external pointing device */
+
+/*
+ * Mode manipulation
+ */
+#define TP_SET_SOFT_TRANS (0x4E) /* Set mode */
+#define TP_CANCEL_SOFT_TRANS (0xB9) /* Cancel mode */
+#define TP_SET_HARD_TRANS (0x45) /* Mode can only be set */
+
+
+/*
+ * Register oriented commands/properties
+ */
+#define TP_WRITE_MEM (0x81)
+#define TP_READ_MEM (0x80) /* Not used in this implementation */
+
+/*
+* RAM Locations for properties
+ */
+#define TP_SENS (0x4A) /* Sensitivity */
+#define TP_MB (0x4C) /* Read Middle Button Status (RO) */
+#define TP_INERTIA (0x4D) /* Negative Inertia */
+#define TP_SPEED (0x60) /* Speed of TP Cursor */
+#define TP_REACH (0x57) /* Backup for Z-axis press */
+#define TP_DRAGHYS (0x58) /* Drag Hysteresis */
+ /* (how hard it is to drag */
+ /* with Z-axis pressed) */
+
+#define TP_MINDRAG (0x59) /* Minimum amount of force needed */
+ /* to trigger dragging */
+
+#define TP_THRESH (0x5C) /* Minimum value for a Z-axis press */
+#define TP_UP_THRESH (0x5A) /* Used to generate a 'click' on Z-axis */
+#define TP_Z_TIME (0x5E) /* How sharp of a press */
+#define TP_JENKS_CURV (0x5D) /* Minimum curvature for double click */
+
+/*
+ * Toggling Flag bits
+ */
+#define TP_TOGGLE (0x47) /* Toggle command */
+
+#define TP_TOGGLE_MB (0x23) /* Disable/Enable Middle Button */
+#define TP_TOGGLE_DRIFT (0x23) /* Drift Correction */
+#define TP_TOGGLE_BURST (0x28) /* Burst Mode */
+#define TP_TOGGLE_PTSON (0x2C) /* Press to Select */
+#define TP_TOGGLE_HARD_TRANS (0x2C) /* Alternate method to set Hard
Transparency */
+#define TP_TOGGLE_TWOHAND (0x2D) /* Two handed */
+#define TP_TOGGLE_STICKY_TWO (0x2D) /* Sticky two handed */
+#define TP_TOGGLE_SKIPBACK (0x2D) /* Suppress movement */
+ /* after drag release */
+#define TP_TOGGLE_EXT_DEV (0x23) /* Toggle external device */
+#define TP_TOGGLE_SOURCE_TAG (0x20) /* Bit 3 of the first packet
will be set to
+ to the origin of the packet (external or TP) */
+
+/*
+ * Various makses for registers
+ * XOR'd to current contents for new value
+ */
+#define TP_MASK_PTSON (0x01)
+#define TP_MASK_SKIPBACK (0x08)
+#define TP_MASK_TWOHAND (0x01)
+#define TP_MASK_STICKY_TWO (0x04)
+#define TP_MASK_HARD_TRANS (0x80)
+#define TP_MASK_BURST (0x80)
+#define TP_MASK_MB (0x01)
+#define TP_MASK_DRIFT (0x80)
+#define TP_MASK_EXT_DEV (0x02)
+#define TP_MASK_SOURCE_TAG (0x80)
+
+/* Power on Self Test Results */
+#define TP_POR_SUCCESS (0x3B)
+
+/*
+ * Default power on values
+ */
+#define TP_DEF_SENS (0x80)
+#define TP_DEF_INERTIA (0x06)
+#define TP_DEF_SPEED (0x61)
+#define TP_DEF_REACH (0x0A)
+
+#define TP_DEF_DRAGHYS (0xFF)
+#define TP_DEF_MINDRAG (0x14)
+
+#define TP_DEF_THRESH (0x08)
+#define TP_DEF_UP_THRESH (0xFF)
+#define TP_DEF_Z_TIME (0x26)
+#define TP_DEF_JENKS_CURV (0x87)
+
+/* Toggles */
+#define TP_DEF_MB (0x00)
+#define TP_DEF_PTSON (0x00)
+#define TP_DEF_SKIPBACK (0x00)
+#define TP_DEF_EXT_DEV (0x01)
+#define TP_DEF_MB_SCROLL (0x00)
+#define TP_DEF_SCROLL_DELAY (200)
+
+#define MAKE_PS2_CMD(params, results, cmd) ((params<<12) |
(results<<8) | (cmd))
+
+#define PSMOUSE_TRACKPOINT 42
+#define Z_ACCEL_EXP 1.2
+#define Z_ACCEL_MULT 0.02
+
+
+struct trackpoint_data
+{
+ unsigned char firmware_id;
+
+ unsigned char sens, speed, inertia, reach;
+ unsigned char draghys, mindrag;
+ unsigned char thresh, up_thresh;
+ unsigned char z_time, jenks_curv;
+
+ unsigned char ptson; /* Press to Select */
+ unsigned char twohand, skipback;
+ unsigned char mb;
+
+ unsigned char ext_dev;
+ unsigned char transparent;
+ unsigned char source_tag;
+
+ unsigned char mb_scroll, mb_was_down, scrolling;
+ unsigned long scroll_delay, last_mb_press;
+
+ int xacc, yacc;
+};
+
+extern int trackpoint_init (struct psmouse *psmouse);
+extern void trackpoint_sim_scroll(struct psmouse *psmouse);
+
+#endif /* _TRACKPOINT_H */
next reply other threads:[~2005-02-03 22:53 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-02-03 22:43 Stephen Evanchik [this message]
2005-02-04 0:34 ` [PATCH 2.6.11-rc3] IBM Trackpoint support Dmitry Torokhov
2005-02-04 3:52 ` Dmitry Torokhov
2005-02-04 4:39 ` Stephen Evanchik
2005-02-13 19:13 ` Stephen Evanchik
2005-02-13 19:31 ` Vojtech Pavlik
2005-02-13 20:31 ` Stephen Evanchik
2005-02-13 23:50 ` Dmitry Torokhov
2005-02-04 6:35 ` Vojtech Pavlik
2005-02-04 6:46 ` Fabio Massimo Di Nitto
2005-02-04 6:52 ` Dmitry Torokhov
2005-02-04 6:54 ` Vojtech Pavlik
2005-02-04 14:17 ` Dmitry Torokhov
2005-02-04 14:45 ` Vojtech Pavlik
2005-02-05 6:56 ` Dmitry Torokhov
2005-02-05 12:24 ` Vojtech Pavlik
2005-02-04 13:17 ` Stephen Evanchik
2005-02-04 13:45 ` Vojtech Pavlik
2005-02-04 14:12 ` Dmitry Torokhov
2005-02-05 10:44 ` Pavel Machek
2005-02-07 10:14 ` Vojtech Pavlik
2005-02-13 19:07 ` Stephen Evanchik
2005-02-13 19:13 ` Vojtech Pavlik
2005-02-06 20:17 ` Domen Puncer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a71293c20502031443764fb4e5@mail.gmail.com \
--to=evanchsa@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=vojtech@suse.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.