NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/42853: Synaptics touchpad driver breaks passthrough device (ie, trackpoint)
>Number: 42853
>Category: kern
>Synopsis: Synaptics touchpad driver breaks passthrough device (ie,
>trackpoint)
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Feb 20 18:10:00 +0000 2010
>Originator: Rafal Boni
>Release: NetBSD 5.99.24 (2010/02/18 15:25:28 -0500)
>Organization:
TNF
>Environment:
System: NetBSD plasmodium 5.99.24 NetBSD 5.99.24 (MONOLITHIC_DRM) #19: Sat Feb
20 11:11:03 EST 2010
rafal@puck:/extra/i386/obj/sys/arch/i386/compile/MONOLITHIC_DRM i386
Architecture: i386 / x86_64
Machine: i386 / amd64
>Description:
The synaptics driver apparently confuses the attached 'passthrough'
device i.e., the trackpoint on my T4x during the capability probe
sequence, resulting in a working touchpad but non-working trackpoint.
>How-To-Repeat:
Boot -current on a Thinkpad T4x, wonder why the trackpoint doesn't
work when it does in Windows.
>Fix:
Resetting the device first think during attach seems to do the
trick. Included in the change is a sysctl knob for disabling
the passthrough device for those who saw this as a 'feature'.
Note that I've also changed the 'pms_synaptics_send_command'
function to follow the strict(er) protocol followed by e.g.
the Linux drivers, that is sending the PMS_SET_SCALE11 command
before the 'sliced' command. This didn't affect functionality
but seemed The Right Thing(tm) to do.
diff --git a/sys/dev/pckbport/synaptics.c b/sys/dev/pckbport/synaptics.c
index 6712973..a022907 100644
--- a/sys/dev/pckbport/synaptics.c
+++ b/sys/dev/pckbport/synaptics.c
@@ -111,6 +111,7 @@ static int synaptics_scale_y = 16;
static int synaptics_max_speed_x = 32;
static int synaptics_max_speed_y = 32;
static int synaptics_movement_threshold = 4;
+static int synaptics_passthrough_enable = 1;
/* Sysctl nodes. */
static int synaptics_up_down_emul_nodenum;
@@ -241,6 +242,10 @@ pms_synaptics_probe_init(void *vsc)
const char comma[] = ", ";
const char *sep = "";
aprint_normal_dev(psc->sc_dev, "");
+ if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) {
+ aprint_normal("%sPassthrough", sep);
+ sep = comma;
+ }
if (sc->flags & SYN_FLAG_HAS_MIDDLE_BUTTON) {
aprint_normal("%sMiddle button", sep);
sep = comma;
@@ -276,9 +281,19 @@ pms_synaptics_enable(void *vsc)
{
struct pms_softc *psc = vsc;
struct synaptics_softc *sc = &psc->u.synaptics;
- u_char cmd[2];
+ u_char cmd[2], resp[2] = { 0,0 };
int res;
+ if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) {
+ /*
+ * Extended capability probes can confuse the passthrough device;
+ * reset the touchpad now to cure that.
+ */
+ cmd[0] = PMS_RESET;
+ res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 2,
+ resp, 1);
+ }
+
/*
* Enable Absolute mode with W (width) reporting, and set
* the packet rate to maximum (80 packets per second).
@@ -286,7 +301,7 @@ pms_synaptics_enable(void *vsc)
res = pms_synaptics_send_command(psc->sc_kbctag, psc->sc_kbcslot,
SYNAPTICS_MODE_ABSOLUTE | SYNAPTICS_MODE_W | SYNAPTICS_MODE_RATE);
cmd[0] = PMS_SET_SAMPLE;
- cmd[1] = 0x14; /* doit */
+ cmd[1] = SYNAPTICS_CMD_SET_MODE2; /* doit */
res |= pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 2, 0,
1, NULL);
sc->up_down = 0;
@@ -541,6 +556,17 @@ pms_sysctl_synaptics(struct sysctllog **clog)
goto err;
synaptics_movement_threshold_nodenum = node->sysctl_num;
+
+ if ((rc = sysctl_createv(clog, 0, NULL, &node,
+ CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+ CTLTYPE_INT, "passthrough_enable",
+ SYSCTL_DESCR("Enable/disable passthrough port"),
+ NULL, 0,
+ &synaptics_passthrough_enable,
+ 0, CTL_HW, root_num, CTL_CREATE,
+ CTL_EOL)) != 0)
+ goto err;
+
return;
err:
@@ -616,13 +642,16 @@ pms_synaptics_send_command(pckbport_tag_t tag,
pckbport_slot_t slot,
u_char cmd[2];
int res;
+ cmd[0] = PMS_SET_SCALE11;
+ res = pckbport_poll_cmd(tag, slot, cmd, 1, 0, NULL, 0);
+
/*
* Need to send 4 Set Resolution commands, with the argument
* encoded in the bottom most 2 bits.
*/
cmd[0] = PMS_SET_RES;
cmd[1] = syn_cmd >> 6;
- res = pckbport_poll_cmd(tag, slot, cmd, 2, 0, NULL, 0);
+ res |= pckbport_poll_cmd(tag, slot, cmd, 2, 0, NULL, 0);
cmd[0] = PMS_SET_RES;
cmd[1] = (syn_cmd & 0x30) >> 4;
@@ -710,6 +739,9 @@ pms_synaptics_passthrough(struct pms_softc *psc)
int buttons, changed;
int s;
+ if (!synaptics_passthrough_enable)
+ return;
+
buttons = ((psc->packet[1] & PMS_LBUTMASK) ? 0x20 : 0) |
((psc->packet[1] & PMS_MBUTMASK) ? 0x40 : 0) |
((psc->packet[1] & PMS_RBUTMASK) ? 0x80 : 0);
diff --git a/sys/dev/pckbport/synapticsreg.h b/sys/dev/pckbport/synapticsreg.h
index c9c5d6e..a31c47d 100644
--- a/sys/dev/pckbport/synapticsreg.h
+++ b/sys/dev/pckbport/synapticsreg.h
@@ -45,6 +45,10 @@
#define SYNAPTICS_READ_MODEL_ID 0x3
#define SYNAPTICS_EXTENDED_QUERY 0x9
+/* Synaptics special commands */
+#define SYNAPTICS_CMD_SET_MODE2 0x14
+#define SYNAPTICS_CMD_CLIENT_CMD 0x28
+
/* Magic numbers. */
#define SYNAPTICS_MIN_VERSION 45 /* 4.5 */
#define SYNAPTICS_MAGIC_BYTE 0x47
@@ -64,6 +68,7 @@
#define SYNAPTICS_MODE_RATE (1 << 6)
#define SYNAPTICS_MODE_SLEEP (1 << 3)
#define SYNAPTICS_MODE_GEST (1 << 2)
+#define SYNAPTICS_MODE_4BYTE_CLIENT (1 << 1)
#define SYNAPTICS_MODE_W (1)
/* Extended mode button masks. */
Home |
Main Index |
Thread Index |
Old Index