View | Details | Raw Unified | Return to bug 205690 | Differences between
and this patch

Collapse All | Expand All

(-)sys/dev/atkbdc/atkbd.c (-42 / +87 lines)
Lines 49-57 Link Here
49
#include <dev/atkbdc/atkbdreg.h>
49
#include <dev/atkbdc/atkbdreg.h>
50
#include <dev/atkbdc/atkbdcreg.h>
50
#include <dev/atkbdc/atkbdcreg.h>
51
51
52
static timeout_t	atkbd_timeout;
52
typedef struct atkbd_state {
53
	KBDC		kbdc;		/* keyboard controller */
54
	int		ks_mode;	/* input mode (K_XLATE,K_RAW,K_CODE) */
55
	int		ks_flags;	/* flags */
56
#define COMPOSE		(1 << 0)
57
	int		ks_polling;
58
	int		ks_state;	/* shift/lock key state */
59
	int		ks_accents;	/* accent key index (> 0) */
60
	u_int		ks_composed_char; /* composed char code (> 0) */
61
	u_char		ks_prefix;	/* AT scan code prefix */
62
	struct callout	ks_timer;
63
} atkbd_state_t;
64
65
static void		atkbd_timeout(void *arg);
53
static void		atkbd_shutdown_final(void *v);
66
static void		atkbd_shutdown_final(void *v);
67
static int		atkbd_reset(KBDC kbdc, int flags, int c);
54
68
69
#define HAS_QUIRK(p, q)		(((atkbdc_softc_t *)(p))->quirks & q)
70
#define ALLOW_DISABLE_KBD(kbdc)	!HAS_QUIRK(kbdc, KBDC_QUIRK_KEEP_ACTIVATED)
71
55
#define DEFAULT_DELAY		0x1  /* 500ms */
72
#define DEFAULT_DELAY		0x1  /* 500ms */
56
#define DEFAULT_RATE		0x10 /* 14Hz */
73
#define DEFAULT_RATE		0x10 /* 14Hz */
57
74
Lines 78-83 Link Here
78
atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags)
95
atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags)
79
{
96
{
80
	keyboard_switch_t *sw;
97
	keyboard_switch_t *sw;
98
	atkbd_state_t *state;
81
	int args[2];
99
	int args[2];
82
	int error;
100
	int error;
83
	int unit;
101
	int unit;
Lines 110-115 Link Here
110
	 * This is a kludge to compensate for lost keyboard interrupts.
128
	 * This is a kludge to compensate for lost keyboard interrupts.
111
	 * A similar code used to be in syscons. See below. XXX
129
	 * A similar code used to be in syscons. See below. XXX
112
	 */
130
	 */
131
	state = (atkbd_state_t *)(*kbd)->kb_data;
132
	callout_init(&state->ks_timer, 0);
113
	atkbd_timeout(*kbd);
133
	atkbd_timeout(*kbd);
114
134
115
	if (bootverbose)
135
	if (bootverbose)
Lines 124-129 Link Here
124
static void
144
static void
125
atkbd_timeout(void *arg)
145
atkbd_timeout(void *arg)
126
{
146
{
147
	atkbd_state_t *state;
127
	keyboard_t *kbd;
148
	keyboard_t *kbd;
128
	int s;
149
	int s;
129
150
Lines 165-171 Link Here
165
			kbdd_intr(kbd, NULL);
186
			kbdd_intr(kbd, NULL);
166
	}
187
	}
167
	splx(s);
188
	splx(s);
168
	timeout(atkbd_timeout, arg, hz/10);
189
	state = (atkbd_state_t *)kbd->kb_data;
190
	callout_reset(&state->ks_timer, hz / 10, atkbd_timeout, arg);
169
}
191
}
170
192
171
/* LOW-LEVEL */
193
/* LOW-LEVEL */
Lines 172-189 Link Here
172
194
173
#define ATKBD_DEFAULT	0
195
#define ATKBD_DEFAULT	0
174
196
175
typedef struct atkbd_state {
176
	KBDC		kbdc;		/* keyboard controller */
177
	int		ks_mode;	/* input mode (K_XLATE,K_RAW,K_CODE) */
178
	int		ks_flags;	/* flags */
179
#define COMPOSE		(1 << 0)
180
	int		ks_polling;
181
	int		ks_state;	/* shift/lock key state */
182
	int		ks_accents;	/* accent key index (> 0) */
183
	u_int		ks_composed_char; /* composed char code (> 0) */
184
	u_char		ks_prefix;	/* AT scan code prefix */
185
} atkbd_state_t;
186
187
/* keyboard driver declaration */
197
/* keyboard driver declaration */
188
static int		atkbd_configure(int flags);
198
static int		atkbd_configure(int flags);
189
static kbd_probe_t	atkbd_probe;
199
static kbd_probe_t	atkbd_probe;
Lines 460-466 Link Here
460
static int
470
static int
461
atkbd_term(keyboard_t *kbd)
471
atkbd_term(keyboard_t *kbd)
462
{
472
{
473
	atkbd_state_t *state = (atkbd_state_t *)kbd->kb_data;
474
463
	kbd_unregister(kbd);
475
	kbd_unregister(kbd);
476
	callout_drain(&state->ks_timer);
464
	return 0;
477
	return 0;
465
}
478
}
466
479
Lines 1076-1081 Link Here
1076
#endif
1089
#endif
1077
}
1090
}
1078
1091
1092
static int
1093
atkbd_reset(KBDC kbdc, int flags, int c)
1094
{
1095
	/* reset keyboard hardware */
1096
	if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) {
1097
		/*
1098
		 * KEYBOARD ERROR
1099
		 * Keyboard reset may fail either because the keyboard
1100
		 * doen't exist, or because the keyboard doesn't pass
1101
		 * the self-test, or the keyboard controller on the
1102
		 * motherboard and the keyboard somehow fail to shake hands.
1103
		 * It is just possible, particularly in the last case,
1104
		 * that the keyboard controller may be left in a hung state.
1105
		 * test_controller() and test_kbd_port() appear to bring
1106
		 * the keyboard controller back (I don't know why and how,
1107
		 * though.)
1108
		 */
1109
		empty_both_buffers(kbdc, 10);
1110
		test_controller(kbdc);
1111
		test_kbd_port(kbdc);
1112
		/*
1113
		 * We could disable the keyboard port and interrupt... but, 
1114
		 * the keyboard may still exist (see above). 
1115
		 */
1116
		set_controller_command_byte(kbdc,
1117
		    ALLOW_DISABLE_KBD(kbdc) ? 0xff : KBD_KBD_CONTROL_BITS, c);
1118
		if (bootverbose)
1119
			printf("atkbd: failed to reset the keyboard.\n");
1120
		return (EIO);
1121
	}
1122
	return (0);
1123
}
1124
1079
/* local functions */
1125
/* local functions */
1080
1126
1081
static int
1127
static int
Lines 1193-1205 Link Here
1193
		kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS);
1239
		kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS);
1194
	} else {
1240
	} else {
1195
		/* try to restore the command byte as before */
1241
		/* try to restore the command byte as before */
1196
		set_controller_command_byte(kbdc, 0xff, c);
1242
		set_controller_command_byte(kbdc,
1243
		    ALLOW_DISABLE_KBD(kbdc) ? 0xff : KBD_KBD_CONTROL_BITS, c);
1197
		kbdc_set_device_mask(kbdc, m);
1244
		kbdc_set_device_mask(kbdc, m);
1198
	}
1245
	}
1199
#endif
1246
#endif
1200
1247
1201
	kbdc_lock(kbdc, FALSE);
1248
	kbdc_lock(kbdc, FALSE);
1202
	return err;
1249
	return (HAS_QUIRK(kbdc, KBDC_QUIRK_IGNORE_PROBE_RESULT) ? 0 : err);
1203
}
1250
}
1204
1251
1205
static int
1252
static int
Lines 1242-1247 Link Here
1242
		return EIO;
1289
		return EIO;
1243
	}
1290
	}
1244
1291
1292
	if (HAS_QUIRK(kbdc, KBDC_QUIRK_RESET_AFTER_PROBE) &&
1293
	    atkbd_reset(kbdc, flags, c)) {
1294
		kbdc_lock(kbdc, FALSE);
1295
		return EIO;
1296
	}
1297
1245
	/* 
1298
	/* 
1246
	 * Check if we have an XT keyboard before we attempt to reset it. 
1299
	 * Check if we have an XT keyboard before we attempt to reset it. 
1247
	 * The procedure assumes that the keyboard and the controller have 
1300
	 * The procedure assumes that the keyboard and the controller have 
Lines 1286-1316 Link Here
1286
	if (bootverbose)
1339
	if (bootverbose)
1287
		printf("atkbd: keyboard ID 0x%x (%d)\n", id, *type);
1340
		printf("atkbd: keyboard ID 0x%x (%d)\n", id, *type);
1288
1341
1289
	/* reset keyboard hardware */
1342
	if (!HAS_QUIRK(kbdc, KBDC_QUIRK_RESET_AFTER_PROBE) &&
1290
	if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) {
1343
	    atkbd_reset(kbdc, flags, c)) {
1291
		/*
1292
		 * KEYBOARD ERROR
1293
		 * Keyboard reset may fail either because the keyboard
1294
		 * doen't exist, or because the keyboard doesn't pass
1295
		 * the self-test, or the keyboard controller on the
1296
		 * motherboard and the keyboard somehow fail to shake hands.
1297
		 * It is just possible, particularly in the last case,
1298
		 * that the keyboard controller may be left in a hung state.
1299
		 * test_controller() and test_kbd_port() appear to bring
1300
		 * the keyboard controller back (I don't know why and how,
1301
		 * though.)
1302
		 */
1303
		empty_both_buffers(kbdc, 10);
1304
		test_controller(kbdc);
1305
		test_kbd_port(kbdc);
1306
		/*
1307
		 * We could disable the keyboard port and interrupt... but, 
1308
		 * the keyboard may still exist (see above). 
1309
		 */
1310
		set_controller_command_byte(kbdc, 0xff, c);
1311
		kbdc_lock(kbdc, FALSE);
1344
		kbdc_lock(kbdc, FALSE);
1312
		if (bootverbose)
1313
			printf("atkbd: failed to reset the keyboard.\n");
1314
		return EIO;
1345
		return EIO;
1315
	}
1346
	}
1316
1347
Lines 1330-1336 Link Here
1330
			 * The XT kbd isn't usable unless the proper scan
1361
			 * The XT kbd isn't usable unless the proper scan
1331
			 * code set is selected. 
1362
			 * code set is selected. 
1332
			 */
1363
			 */
1333
			set_controller_command_byte(kbdc, 0xff, c);
1364
			set_controller_command_byte(kbdc, ALLOW_DISABLE_KBD(kbdc)
1365
			    ? 0xff : KBD_KBD_CONTROL_BITS, c);
1334
			kbdc_lock(kbdc, FALSE);
1366
			kbdc_lock(kbdc, FALSE);
1335
			printf("atkbd: unable to set the XT keyboard mode.\n");
1367
			printf("atkbd: unable to set the XT keyboard mode.\n");
1336
			return EIO;
1368
			return EIO;
Lines 1345-1350 Link Here
1345
	c |= KBD_TRANSLATION;
1377
	c |= KBD_TRANSLATION;
1346
#endif
1378
#endif
1347
1379
1380
	/*
1381
	 * Some keyboards require a SETLEDS command to be sent after
1382
	 * the reset command before they will send keystrokes to us
1383
	 */
1384
	if (HAS_QUIRK(kbdc, KBDC_QUIRK_SETLEDS_ON_INIT) &&
1385
	    send_kbd_command_and_data(kbdc, KBDC_SET_LEDS, 0) != KBD_ACK) {
1386
		printf("atkbd: setleds failed\n");
1387
	}
1388
	if (!ALLOW_DISABLE_KBD(kbdc))
1389
	    send_kbd_command(kbdc, KBDC_ENABLE_KBD);
1390
1348
	/* enable the keyboard port and intr. */
1391
	/* enable the keyboard port and intr. */
1349
	if (!set_controller_command_byte(kbdc, 
1392
	if (!set_controller_command_byte(kbdc, 
1350
		KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK,
1393
		KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK,
Lines 1355-1361 Link Here
1355
		 * This is serious; we are left with the disabled
1398
		 * This is serious; we are left with the disabled
1356
		 * keyboard intr. 
1399
		 * keyboard intr. 
1357
		 */
1400
		 */
1358
		set_controller_command_byte(kbdc, 0xff, c);
1401
		set_controller_command_byte(kbdc, ALLOW_DISABLE_KBD(kbdc)
1402
		    ? 0xff : (KBD_KBD_CONTROL_BITS | KBD_TRANSLATION |
1403
			KBD_OVERRIDE_KBD_LOCK), c);
1359
		kbdc_lock(kbdc, FALSE);
1404
		kbdc_lock(kbdc, FALSE);
1360
		printf("atkbd: unable to enable the keyboard port and intr.\n");
1405
		printf("atkbd: unable to enable the keyboard port and intr.\n");
1361
		return EIO;
1406
		return EIO;
(-)sys/dev/atkbdc/atkbdc.c (-3 / +38 lines)
Lines 114-119 Link Here
114
static int wait_for_aux_data(atkbdc_softc_t *kbdc);
114
static int wait_for_aux_data(atkbdc_softc_t *kbdc);
115
static int wait_for_aux_ack(atkbdc_softc_t *kbdc);
115
static int wait_for_aux_ack(atkbdc_softc_t *kbdc);
116
116
117
struct atkbdc_quirks {
118
    const char* bios_vendor;
119
    const char*	maker;
120
    const char*	product;
121
    int		quirk;
122
};
123
124
static struct atkbdc_quirks quirks[] = {
125
    {"coreboot", "Acer", "Peppy",
126
	KBDC_QUIRK_KEEP_ACTIVATED | KBDC_QUIRK_IGNORE_PROBE_RESULT |
127
	KBDC_QUIRK_RESET_AFTER_PROBE | KBDC_QUIRK_SETLEDS_ON_INIT},
128
129
    {NULL, NULL, NULL, 0}
130
};
131
132
#define QUIRK_STR_MATCH(s1, s2) (s1 == NULL || \
133
    (s2 != NULL && !strcmp(s1, s2)))
134
135
static int
136
atkbdc_getquirks(void)
137
{
138
    int i;
139
    char* bios_vendor = getenv("smbios.bios.vendor");
140
    char* maker = getenv("smbios.system.maker");
141
    char* product = getenv("smbios.system.product");
142
143
    for (i=0; quirks[i].quirk != 0; ++i)
144
	if (QUIRK_STR_MATCH(quirks[i].bios_vendor, bios_vendor) &&
145
	    QUIRK_STR_MATCH(quirks[i].maker, maker) &&
146
	    QUIRK_STR_MATCH(quirks[i].product, product))
147
		return (quirks[i].quirk);
148
149
    return (0);
150
}
151
117
atkbdc_softc_t
152
atkbdc_softc_t
118
*atkbdc_get_softc(int unit)
153
*atkbdc_get_softc(int unit)
119
{
154
{
Lines 176-183 Link Here
176
	/* XXX: tag should be passed from the caller */
211
	/* XXX: tag should be passed from the caller */
177
#if defined(__amd64__) || defined(__i386__)
212
#if defined(__amd64__) || defined(__i386__)
178
	tag = X86_BUS_SPACE_IO;
213
	tag = X86_BUS_SPACE_IO;
179
#elif defined(__ia64__)
180
	tag = IA64_BUS_SPACE_IO;
181
#elif defined(__sparc64__)
214
#elif defined(__sparc64__)
182
	tag = &atkbdc_bst_store[0];
215
	tag = &atkbdc_bst_store[0];
183
#else
216
#else
Lines 297-302 Link Here
297
#else
330
#else
298
	sc->retry = 5000;
331
	sc->retry = 5000;
299
#endif
332
#endif
333
	sc->quirks = atkbdc_getquirks();
300
334
301
	return 0;
335
	return 0;
302
}
336
}
Lines 1126-1132 Link Here
1126
kbdc_set_device_mask(KBDC p, int mask)
1160
kbdc_set_device_mask(KBDC p, int mask)
1127
{
1161
{
1128
    kbdcp(p)->command_mask = 
1162
    kbdcp(p)->command_mask = 
1129
	mask & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS);
1163
	mask & (((kbdcp(p)->quirks & KBDC_QUIRK_KEEP_ACTIVATED)
1164
	    ? 0 : KBD_KBD_CONTROL_BITS) | KBD_AUX_CONTROL_BITS);
1130
}
1165
}
1131
1166
1132
int
1167
int
(-)sys/dev/atkbdc/atkbdcreg.h (+5 lines)
Lines 202-207 Link Here
202
    kqueue kbd;			/* keyboard data queue */
202
    kqueue kbd;			/* keyboard data queue */
203
    kqueue aux;			/* auxiliary data queue */
203
    kqueue aux;			/* auxiliary data queue */
204
    int retry;
204
    int retry;
205
    int quirks;			/* controller doesn't like deactivate */
206
#define KBDC_QUIRK_KEEP_ACTIVATED	(1 << 0)
207
#define KBDC_QUIRK_IGNORE_PROBE_RESULT	(1 << 1)
208
#define KBDC_QUIRK_RESET_AFTER_PROBE	(1 << 2)
209
#define KBDC_QUIRK_SETLEDS_ON_INIT	(1 << 3)
205
} atkbdc_softc_t; 
210
} atkbdc_softc_t; 
206
211
207
enum kbdc_device_ivar {
212
enum kbdc_device_ivar {
(-)sys/dev/atkbdc/psm.c (-290 / +1510 lines)
Lines 81-86 Link Here
81
#include <sys/sysctl.h>
81
#include <sys/sysctl.h>
82
#include <sys/time.h>
82
#include <sys/time.h>
83
#include <sys/uio.h>
83
#include <sys/uio.h>
84
#include <sys/libkern.h>
84
85
85
#include <sys/limits.h>
86
#include <sys/limits.h>
86
#include <sys/mouse.h>
87
#include <sys/mouse.h>
Lines 161-200 Link Here
161
#define	PSM_PACKETQUEUE	128
162
#define	PSM_PACKETQUEUE	128
162
#endif
163
#endif
163
164
164
enum {
165
	SYNAPTICS_SYSCTL_MIN_PRESSURE,
166
	SYNAPTICS_SYSCTL_MAX_PRESSURE,
167
	SYNAPTICS_SYSCTL_MAX_WIDTH,
168
	SYNAPTICS_SYSCTL_MARGIN_TOP,
169
	SYNAPTICS_SYSCTL_MARGIN_RIGHT,
170
	SYNAPTICS_SYSCTL_MARGIN_BOTTOM,
171
	SYNAPTICS_SYSCTL_MARGIN_LEFT,
172
	SYNAPTICS_SYSCTL_NA_TOP,
173
	SYNAPTICS_SYSCTL_NA_RIGHT,
174
	SYNAPTICS_SYSCTL_NA_BOTTOM,
175
	SYNAPTICS_SYSCTL_NA_LEFT,
176
	SYNAPTICS_SYSCTL_WINDOW_MIN,
177
	SYNAPTICS_SYSCTL_WINDOW_MAX,
178
	SYNAPTICS_SYSCTL_MULTIPLICATOR,
179
	SYNAPTICS_SYSCTL_WEIGHT_CURRENT,
180
	SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS,
181
	SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA,
182
	SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED,
183
	SYNAPTICS_SYSCTL_DIV_MIN,
184
	SYNAPTICS_SYSCTL_DIV_MAX,
185
	SYNAPTICS_SYSCTL_DIV_MAX_NA,
186
	SYNAPTICS_SYSCTL_DIV_LEN,
187
	SYNAPTICS_SYSCTL_TAP_MAX_DELTA,
188
	SYNAPTICS_SYSCTL_TAP_MIN_QUEUE,
189
	SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT,
190
	SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA,
191
	SYNAPTICS_SYSCTL_VSCROLL_VER_AREA,
192
	SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA,
193
	SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN,
194
	SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX,
195
	SYNAPTICS_SYSCTL_TOUCHPAD_OFF
196
};
197
198
typedef struct synapticsinfo {
165
typedef struct synapticsinfo {
199
	struct sysctl_ctx_list	 sysctl_ctx;
166
	struct sysctl_ctx_list	 sysctl_ctx;
200
	struct sysctl_oid	*sysctl_tree;
167
	struct sysctl_oid	*sysctl_tree;
Lines 231-236 Link Here
231
	int			 vscroll_div_min;
198
	int			 vscroll_div_min;
232
	int			 vscroll_div_max;
199
	int			 vscroll_div_max;
233
	int			 touchpad_off;
200
	int			 touchpad_off;
201
	int			 softbuttons;
202
	int			 softbuttons_y;
203
	int			 softbutton2_x;
204
	int			 softbutton3_x;
205
	int			 softbutton_nomove;
234
} synapticsinfo_t;
206
} synapticsinfo_t;
235
207
236
typedef struct synapticspacket {
208
typedef struct synapticspacket {
Lines 295-300 Link Here
295
	int	skipback;
267
	int	skipback;
296
} trackpointinfo_t;
268
} trackpointinfo_t;
297
269
270
typedef struct finger {
271
	int			x;
272
	int			y;
273
	int			p;
274
	int			w;
275
	int			flags;
276
} finger_t;
277
#define	PSM_GESTURE_FINGERS	2
278
#define	PSM_FINGER_IS_PEN	(1<<0)
279
#define	PSM_FINGER_FUZZY	(1<<1)
280
#define	PSM_FINGER_IS_SET(f) ((f).x != -1 && (f).y != -1 && (f).p != 0)
281
#define	PSM_FINGER_RESET(f) do \
282
	(f) = (finger_t) { .x = -1, .y = -1, .p = 0, .w = 0, .flags = 0 }; \
283
while (0)
284
285
typedef struct elantechhw {
286
	int			hwversion;
287
	int			fwversion;
288
	int			sizex;
289
	int			sizey;
290
	int			dpix;
291
	int			dpiy;
292
	int			ntracesx;
293
	int			ntracesy;
294
	int			isclickpad;
295
	int			hascrc;
296
	int			hastrackpad;
297
	int			haspressure;
298
} elantechhw_t;
299
300
/* minimum versions supported by this driver */
301
#define	ELANTECH_HW_IS_V1(fwver) ((fwver) < 0x020030 || (fwver) == 0x020600)
302
303
#define	ELANTECH_MAGIC(magic)				\
304
	((magic)[0] == 0x3c && (magic)[1] == 0x03 &&	\
305
	((magic)[2] == 0xc8 || (magic)[2] == 0x00))
306
307
#define	ELANTECH_FW_ID		0x00
308
#define	ELANTECH_FW_VERSION	0x01
309
#define	ELANTECH_CAPABILITIES	0x02
310
#define	ELANTECH_SAMPLE		0x03
311
#define	ELANTECH_RESOLUTION	0x04
312
#define	ELANTECH_REG_READ	0x10
313
#define	ELANTECH_REG_WRITE	0x11
314
#define	ELANTECH_REG_RDWR	0x00
315
#define	ELANTECH_CUSTOM_CMD	0xf8
316
317
#define	ELANTECH_FINGER_DEFAULT_P tap_threshold
318
#define	ELANTECH_FINGER_DEFAULT_W 1
319
#define	ELANTECH_FINGER_SET_XYP(pb) (finger_t) {			\
320
    .x = (((pb)->ipacket[1] & 0x0f) << 8) | (pb)->ipacket[2],		\
321
    .y = (((pb)->ipacket[4] & 0x0f) << 8) | (pb)->ipacket[5],		\
322
    .p = ((pb)->ipacket[1] & 0xf0) | (((pb)->ipacket[4] >> 4) & 0x0f),	\
323
    .w = ELANTECH_FINGER_DEFAULT_W,					\
324
    .flags = 0								\
325
}
326
327
enum {
328
	ELANTECH_PKT_NOP,
329
	ELANTECH_PKT_TRACKPOINT,
330
	ELANTECH_PKT_V2_COMMON,
331
	ELANTECH_PKT_V2_2FINGER,
332
	ELANTECH_PKT_V3,
333
	ELANTECH_PKT_V4_STATUS,
334
	ELANTECH_PKT_V4_HEAD,
335
	ELANTECH_PKT_V4_MOTION
336
};
337
338
#define	ELANTECH_PKT_IS_TRACKPOINT(pb) (((pb)->ipacket[3] & 0x0f) == 0x06)
339
#define	ELANTECH_PKT_IS_DEBOUNCE(pb, hwversion) ((hwversion) == 4 ? 0 :	\
340
    (pb)->ipacket[0] == ((hwversion) == 2 ? 0x84 : 0xc4) &&		\
341
    (pb)->ipacket[1] == 0xff && (pb)->ipacket[2] == 0xff &&		\
342
    (pb)->ipacket[3] == 0x02 && (pb)->ipacket[4] == 0xff &&		\
343
    (pb)->ipacket[5] == 0xff)
344
#define	ELANTECH_PKT_IS_V2(pb) 						\
345
    (((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x0f) == 0x02)
346
#define	ELANTECH_PKT_IS_V3_HEAD(pb, hascrc) ((hascrc) ? 		\
347
    ((pb)->ipacket[3] & 0x09) == 0x08 : 				\
348
    ((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0xcf) == 0x02)
349
#define	ELANTECH_PKT_IS_V3_TAIL(pb, hascrc) ((hascrc) ? 		\
350
    ((pb)->ipacket[3] & 0x09) == 0x09 : 				\
351
    ((pb)->ipacket[0] & 0x0c) == 0x0c && ((pb)->ipacket[3] & 0xce) == 0x0c)
352
#define	ELANTECH_PKT_IS_V4(pb, hascrc) ((hascrc) ? 			\
353
    ((pb)->ipacket[3] & 0x08) == 0x00 :					\
354
    ((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x1c) == 0x10)
355
356
typedef struct elantechaction {
357
	finger_t		fingers[PSM_GESTURE_FINGERS];
358
	int			nfingers;
359
} elantechaction_t;
360
298
/* driver control block */
361
/* driver control block */
299
struct psm_softc {		/* Driver status information */
362
struct psm_softc {		/* Driver status information */
300
	int		unit;
363
	int		unit;
Lines 308-314 Link Here
308
	mousehw_t	hw;		/* hardware information */
371
	mousehw_t	hw;		/* hardware information */
309
	synapticshw_t	synhw;		/* Synaptics hardware information */
372
	synapticshw_t	synhw;		/* Synaptics hardware information */
310
	synapticsinfo_t	syninfo;	/* Synaptics configuration */
373
	synapticsinfo_t	syninfo;	/* Synaptics configuration */
311
	synapticsaction_t synaction;	/* Synaptics action context */
374
	synapticsaction_t
375
	    synaction[PSM_GESTURE_FINGERS]; /* Synaptics action context */
376
	elantechhw_t	elanhw;		/* Elantech hardware information */
377
	elantechaction_t elanaction;	/* Elantech action context */
312
	int		tphw;		/* TrackPoint hardware information */
378
	int		tphw;		/* TrackPoint hardware information */
313
	trackpointinfo_t tpinfo;	/* TrackPoint configuration */
379
	trackpointinfo_t tpinfo;	/* TrackPoint configuration */
314
	mousemode_t	mode;		/* operation mode */
380
	mousemode_t	mode;		/* operation mode */
Lines 331-336 Link Here
331
	struct timeval	lastsoftintr;	/* time of last soft interrupt */
397
	struct timeval	lastsoftintr;	/* time of last soft interrupt */
332
	struct timeval	lastinputerr;	/* time last sync error happened */
398
	struct timeval	lastinputerr;	/* time last sync error happened */
333
	struct timeval	taptimeout;	/* tap timeout for touchpads */
399
	struct timeval	taptimeout;	/* tap timeout for touchpads */
400
	struct timeval	idletimeout;
401
	packetbuf_t	idlepacket;	/* packet to send after idle timeout */
334
	int		watchdog;	/* watchdog timer flag */
402
	int		watchdog;	/* watchdog timer flag */
335
	struct callout	callout;	/* watchdog timer call out */
403
	struct callout	callout;	/* watchdog timer call out */
336
	struct callout	softcallout; /* buffer timer call out */
404
	struct callout	softcallout; /* buffer timer call out */
Lines 375-380 Link Here
375
/* other flags (flags) */
443
/* other flags (flags) */
376
#define	PSM_FLAGS_FINGERDOWN	0x0001	/* VersaPad finger down */
444
#define	PSM_FLAGS_FINGERDOWN	0x0001	/* VersaPad finger down */
377
445
446
#define kbdcp(p)			((atkbdc_softc_t *)(p))
447
#define ALWAYS_RESTORE_CONTROLLER(kbdc)	!(kbdcp(kbdc)->quirks \
448
    & KBDC_QUIRK_KEEP_ACTIVATED)
449
378
/* Tunables */
450
/* Tunables */
379
static int tap_enabled = -1;
451
static int tap_enabled = -1;
380
TUNABLE_INT("hw.psm.tap_enabled", &tap_enabled);
452
TUNABLE_INT("hw.psm.tap_enabled", &tap_enabled);
Lines 385-390 Link Here
385
static int trackpoint_support = 0;
457
static int trackpoint_support = 0;
386
TUNABLE_INT("hw.psm.trackpoint_support", &trackpoint_support);
458
TUNABLE_INT("hw.psm.trackpoint_support", &trackpoint_support);
387
459
460
static int elantech_support = 0;
461
TUNABLE_INT("hw.psm.elantech_support", &elantech_support);
462
388
static int verbose = PSM_DEBUG;
463
static int verbose = PSM_DEBUG;
389
TUNABLE_INT("debug.psm.loglevel", &verbose);
464
TUNABLE_INT("debug.psm.loglevel", &verbose);
390
465
Lines 407-412 Link Here
407
	int	accelfactor;
482
	int	accelfactor;
408
} old_mousemode_t;
483
} old_mousemode_t;
409
484
485
#define SYN_OFFSET(field) offsetof(struct psm_softc, syninfo.field)
486
enum {
487
	SYNAPTICS_SYSCTL_MIN_PRESSURE =		SYN_OFFSET(min_pressure),
488
	SYNAPTICS_SYSCTL_MAX_PRESSURE =		SYN_OFFSET(max_pressure),
489
	SYNAPTICS_SYSCTL_MAX_WIDTH =		SYN_OFFSET(max_width),
490
	SYNAPTICS_SYSCTL_MARGIN_TOP =		SYN_OFFSET(margin_top),
491
	SYNAPTICS_SYSCTL_MARGIN_RIGHT =		SYN_OFFSET(margin_right),
492
	SYNAPTICS_SYSCTL_MARGIN_BOTTOM =	SYN_OFFSET(margin_bottom),
493
	SYNAPTICS_SYSCTL_MARGIN_LEFT =		SYN_OFFSET(margin_left),
494
	SYNAPTICS_SYSCTL_NA_TOP =		SYN_OFFSET(na_top),
495
	SYNAPTICS_SYSCTL_NA_RIGHT =		SYN_OFFSET(na_right),
496
	SYNAPTICS_SYSCTL_NA_BOTTOM =		SYN_OFFSET(na_bottom),
497
	SYNAPTICS_SYSCTL_NA_LEFT = 		SYN_OFFSET(na_left),
498
	SYNAPTICS_SYSCTL_WINDOW_MIN =		SYN_OFFSET(window_min),
499
	SYNAPTICS_SYSCTL_WINDOW_MAX =		SYN_OFFSET(window_max),
500
	SYNAPTICS_SYSCTL_MULTIPLICATOR =	SYN_OFFSET(multiplicator),
501
	SYNAPTICS_SYSCTL_WEIGHT_CURRENT =	SYN_OFFSET(weight_current),
502
	SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS =	SYN_OFFSET(weight_previous),
503
	SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA =	SYN_OFFSET(weight_previous_na),
504
	SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED =	SYN_OFFSET(weight_len_squared),
505
	SYNAPTICS_SYSCTL_DIV_MIN =		SYN_OFFSET(div_min),
506
	SYNAPTICS_SYSCTL_DIV_MAX =		SYN_OFFSET(div_max),
507
	SYNAPTICS_SYSCTL_DIV_MAX_NA =		SYN_OFFSET(div_max_na),
508
	SYNAPTICS_SYSCTL_DIV_LEN =		SYN_OFFSET(div_len),
509
	SYNAPTICS_SYSCTL_TAP_MAX_DELTA =	SYN_OFFSET(tap_max_delta),
510
	SYNAPTICS_SYSCTL_TAP_MIN_QUEUE =	SYN_OFFSET(tap_min_queue),
511
	SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT =	SYN_OFFSET(taphold_timeout),
512
	SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA =	SYN_OFFSET(vscroll_hor_area),
513
	SYNAPTICS_SYSCTL_VSCROLL_VER_AREA =	SYN_OFFSET(vscroll_ver_area),
514
	SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA =	SYN_OFFSET(vscroll_min_delta),
515
	SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN =	SYN_OFFSET(vscroll_div_min),
516
	SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX =	SYN_OFFSET(vscroll_div_max),
517
	SYNAPTICS_SYSCTL_TOUCHPAD_OFF =		SYN_OFFSET(touchpad_off),
518
	SYNAPTICS_SYSCTL_SOFTBUTTONS =		SYN_OFFSET(softbuttons),
519
	SYNAPTICS_SYSCTL_SOFTBUTTONS_Y =	SYN_OFFSET(softbuttons_y),
520
	SYNAPTICS_SYSCTL_SOFTBUTTON2_X =	SYN_OFFSET(softbutton2_x),
521
	SYNAPTICS_SYSCTL_SOFTBUTTON3_X =	SYN_OFFSET(softbutton3_x),
522
	SYNAPTICS_SYSCTL_SOFTBUTTON_NOMOVE =	SYN_OFFSET(softbutton_nomove)
523
};
524
410
/* packet formatting function */
525
/* packet formatting function */
411
typedef int	packetfunc_t(struct psm_softc *, u_char *, int *, int,
526
typedef int	packetfunc_t(struct psm_softc *, u_char *, int *, int,
412
    mousestatus_t *);
527
    mousestatus_t *);
Lines 442-447 Link Here
442
static int	reinitialize(struct psm_softc *, int);
557
static int	reinitialize(struct psm_softc *, int);
443
static char	*model_name(int);
558
static char	*model_name(int);
444
static void	psmsoftintr(void *);
559
static void	psmsoftintr(void *);
560
static void	psmsoftintridle(void *);
445
static void	psmintr(void *);
561
static void	psmintr(void *);
446
static void	psmtimeout(void *);
562
static void	psmtimeout(void *);
447
static int	timeelapsed(const struct timeval *, int, int,
563
static int	timeelapsed(const struct timeval *, int, int,
Lines 454-464 Link Here
454
		    mousestatus_t *, int *, int *, int *);
570
		    mousestatus_t *, int *, int *, int *);
455
static void	proc_versapad(struct psm_softc *, packetbuf_t *,
571
static void	proc_versapad(struct psm_softc *, packetbuf_t *,
456
		    mousestatus_t *, int *, int *, int *);
572
		    mousestatus_t *, int *, int *, int *);
573
static int	proc_elantech(struct psm_softc *, packetbuf_t *,
574
		    mousestatus_t *, int *, int *, int *);
575
static void	psmgestures(struct psm_softc *, synapticsaction_t *, finger_t,
576
		    int, mousestatus_t *, int *, int *);
577
static int	psmsoftbuttons(struct psm_softc *, finger_t, int);
457
static int	tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *,
578
static int	tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *,
458
		    u_char *);
579
		    u_char *);
459
580
460
/* vendor specific features */
581
/* vendor specific features */
461
typedef int	probefunc_t(KBDC, struct psm_softc *);
582
enum probearg { PROBE, REINIT };
583
typedef int	probefunc_t(struct psm_softc *, enum probearg);
462
584
463
static int	mouse_id_proc1(KBDC, int, int, int *);
585
static int	mouse_id_proc1(KBDC, int, int, int *);
464
static int	mouse_ext_command(KBDC, int);
586
static int	mouse_ext_command(KBDC, int);
Lines 475-484 Link Here
475
static probefunc_t	enable_synaptics;
597
static probefunc_t	enable_synaptics;
476
static probefunc_t	enable_trackpoint;
598
static probefunc_t	enable_trackpoint;
477
static probefunc_t	enable_versapad;
599
static probefunc_t	enable_versapad;
600
static probefunc_t	enable_elantech;
478
601
479
static void set_trackpoint_parameters(struct psm_softc *sc);
602
static void set_trackpoint_parameters(struct psm_softc *sc);
480
static void synaptics_passthrough_on(struct psm_softc *sc);
603
static void synaptics_passthrough_on(struct psm_softc *sc);
481
static void synaptics_passthrough_off(struct psm_softc *sc);
604
static void synaptics_passthrough_off(struct psm_softc *sc);
605
static int synaptics_preferred_mode(struct psm_softc *sc);
606
static void synaptics_set_mode(struct psm_softc *sc, int mode_byte);
482
607
483
static struct {
608
static struct {
484
	int		model;
609
	int		model;
Lines 504-509 Link Here
504
	  0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus },
629
	  0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus },
505
	{ MOUSE_MODEL_SYNAPTICS,	/* Synaptics Touchpad */
630
	{ MOUSE_MODEL_SYNAPTICS,	/* Synaptics Touchpad */
506
	  0xc0, MOUSE_SYNAPTICS_PACKETSIZE, enable_synaptics },
631
	  0xc0, MOUSE_SYNAPTICS_PACKETSIZE, enable_synaptics },
632
	{ MOUSE_MODEL_ELANTECH,		/* Elantech Touchpad */
633
	  0x04, MOUSE_ELANTECH_PACKETSIZE, enable_elantech },
507
	{ MOUSE_MODEL_INTELLI,		/* Microsoft IntelliMouse */
634
	{ MOUSE_MODEL_INTELLI,		/* Microsoft IntelliMouse */
508
	  0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli },
635
	  0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli },
509
	{ MOUSE_MODEL_GLIDEPOINT,	/* ALPS GlidePoint */
636
	{ MOUSE_MODEL_GLIDEPOINT,	/* ALPS GlidePoint */
Lines 756-761 Link Here
756
		{ MOUSE_MODEL_4DPLUS,		"4D+ Mouse" },
883
		{ MOUSE_MODEL_4DPLUS,		"4D+ Mouse" },
757
		{ MOUSE_MODEL_SYNAPTICS,	"Synaptics Touchpad" },
884
		{ MOUSE_MODEL_SYNAPTICS,	"Synaptics Touchpad" },
758
		{ MOUSE_MODEL_TRACKPOINT,	"IBM/Lenovo TrackPoint" },
885
		{ MOUSE_MODEL_TRACKPOINT,	"IBM/Lenovo TrackPoint" },
886
		{ MOUSE_MODEL_ELANTECH,		"Elantech Touchpad" },
759
		{ MOUSE_MODEL_GENERIC,		"Generic PS/2 mouse" },
887
		{ MOUSE_MODEL_GENERIC,		"Generic PS/2 mouse" },
760
		{ MOUSE_MODEL_UNKNOWN,		"Unknown" },
888
		{ MOUSE_MODEL_UNKNOWN,		"Unknown" },
761
	};
889
	};
Lines 876-882 Link Here
876
	/* Re-enable the mouse. */
1004
	/* Re-enable the mouse. */
877
	for (i = 0; vendortype[i].probefunc != NULL; ++i)
1005
	for (i = 0; vendortype[i].probefunc != NULL; ++i)
878
		if (vendortype[i].model == sc->hw.model)
1006
		if (vendortype[i].model == sc->hw.model)
879
			(*vendortype[i].probefunc)(sc->kbdc, NULL);
1007
			(*vendortype[i].probefunc)(sc, REINIT);
880
1008
881
	/* set mouse parameters */
1009
	/* set mouse parameters */
882
	if (mode != (mousemode_t *)NULL) {
1010
	if (mode != (mousemode_t *)NULL) {
Lines 887-899 Link Here
887
			    set_mouse_resolution(kbdc, mode->resolution);
1015
			    set_mouse_resolution(kbdc, mode->resolution);
888
		set_mouse_scaling(kbdc, 1);
1016
		set_mouse_scaling(kbdc, 1);
889
		set_mouse_mode(kbdc);
1017
		set_mouse_mode(kbdc);
890
891
		/*
892
		 * Trackpoint settings are lost on resume.
893
		 * Restore them here.
894
		 */
895
		if (sc->tphw > 0)
896
			set_trackpoint_parameters(sc);
897
	}
1018
	}
898
1019
899
	/* Record sync on the next data packet we see. */
1020
	/* Record sync on the next data packet we see. */
Lines 929-942 Link Here
929
		get_mouse_status(sc->kbdc, stat, 0, 3);
1050
		get_mouse_status(sc->kbdc, stat, 0, 3);
930
		if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) ||
1051
		if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) ||
931
		     stat[1] == 0x47) &&
1052
		     stat[1] == 0x47) &&
932
		    stat[2] == 0x40) {
1053
		     stat[2] == 0x40) {
933
			/* Set the mode byte -- request wmode where
1054
			synaptics_set_mode(sc, synaptics_preferred_mode(sc));
934
			 * available */
935
			if (sc->synhw.capExtended)
936
				mouse_ext_command(sc->kbdc, 0xc1);
937
			else
938
				mouse_ext_command(sc->kbdc, 0xc0);
939
			set_mouse_sampling_rate(sc->kbdc, 20);
940
			VLOG(5, (LOG_DEBUG, "psm%d: Synaptis Absolute Mode "
1055
			VLOG(5, (LOG_DEBUG, "psm%d: Synaptis Absolute Mode "
941
			    "hopefully restored\n",
1056
			    "hopefully restored\n",
942
			    sc->unit));
1057
			    sc->unit));
Lines 1246-1252 Link Here
1246
		 * this is CONTROLLER ERROR; I don't know how to recover
1361
		 * this is CONTROLLER ERROR; I don't know how to recover
1247
		 * from this error...
1362
		 * from this error...
1248
		 */
1363
		 */
1249
		restore_controller(sc->kbdc, command_byte);
1364
		if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1365
			restore_controller(sc->kbdc, command_byte);
1250
		printf("psm%d: unable to set the command byte.\n", unit);
1366
		printf("psm%d: unable to set the command byte.\n", unit);
1251
		endprobe(ENXIO);
1367
		endprobe(ENXIO);
1252
	}
1368
	}
Lines 1285-1291 Link Here
1285
		recover_from_error(sc->kbdc);
1401
		recover_from_error(sc->kbdc);
1286
		if (sc->config & PSM_CONFIG_IGNPORTERROR)
1402
		if (sc->config & PSM_CONFIG_IGNPORTERROR)
1287
			break;
1403
			break;
1288
		restore_controller(sc->kbdc, command_byte);
1404
		if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1405
			restore_controller(sc->kbdc, command_byte);
1289
		if (verbose)
1406
		if (verbose)
1290
			printf("psm%d: the aux port is not functioning (%d).\n",
1407
			printf("psm%d: the aux port is not functioning (%d).\n",
1291
			    unit, i);
1408
			    unit, i);
Lines 1308-1314 Link Here
1308
		 */
1425
		 */
1309
		if (!reset_aux_dev(sc->kbdc)) {
1426
		if (!reset_aux_dev(sc->kbdc)) {
1310
			recover_from_error(sc->kbdc);
1427
			recover_from_error(sc->kbdc);
1311
			restore_controller(sc->kbdc, command_byte);
1428
			if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1429
				restore_controller(sc->kbdc, command_byte);
1312
			if (verbose)
1430
			if (verbose)
1313
				printf("psm%d: failed to reset the aux "
1431
				printf("psm%d: failed to reset the aux "
1314
				    "device.\n", unit);
1432
				    "device.\n", unit);
Lines 1330-1336 Link Here
1330
	if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {
1448
	if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {
1331
		/* MOUSE ERROR */
1449
		/* MOUSE ERROR */
1332
		recover_from_error(sc->kbdc);
1450
		recover_from_error(sc->kbdc);
1333
		restore_controller(sc->kbdc, command_byte);
1451
		if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1452
			restore_controller(sc->kbdc, command_byte);
1334
		if (verbose)
1453
		if (verbose)
1335
			printf("psm%d: failed to enable the aux device.\n",
1454
			printf("psm%d: failed to enable the aux device.\n",
1336
			    unit);
1455
			    unit);
Lines 1352-1358 Link Here
1352
	/* verify the device is a mouse */
1471
	/* verify the device is a mouse */
1353
	sc->hw.hwid = get_aux_id(sc->kbdc);
1472
	sc->hw.hwid = get_aux_id(sc->kbdc);
1354
	if (!is_a_mouse(sc->hw.hwid)) {
1473
	if (!is_a_mouse(sc->hw.hwid)) {
1355
		restore_controller(sc->kbdc, command_byte);
1474
		if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1475
			restore_controller(sc->kbdc, command_byte);
1356
		if (verbose)
1476
		if (verbose)
1357
			printf("psm%d: unknown device type (%d).\n", unit,
1477
			printf("psm%d: unknown device type (%d).\n", unit,
1358
			    sc->hw.hwid);
1478
			    sc->hw.hwid);
Lines 1383-1389 Link Here
1383
1503
1384
		/* other parameters */
1504
		/* other parameters */
1385
		for (i = 0; vendortype[i].probefunc != NULL; ++i)
1505
		for (i = 0; vendortype[i].probefunc != NULL; ++i)
1386
			if ((*vendortype[i].probefunc)(sc->kbdc, sc)) {
1506
			if ((*vendortype[i].probefunc)(sc, PROBE)) {
1387
				if (verbose >= 2)
1507
				if (verbose >= 2)
1388
					printf("psm%d: found %s\n", unit,
1508
					printf("psm%d: found %s\n", unit,
1389
					    model_name(vendortype[i].model));
1509
					    model_name(vendortype[i].model));
Lines 1458-1464 Link Here
1458
		 * this is CONTROLLER ERROR; I don't know the proper way to
1578
		 * this is CONTROLLER ERROR; I don't know the proper way to
1459
		 * recover from this error...
1579
		 * recover from this error...
1460
		 */
1580
		 */
1461
		restore_controller(sc->kbdc, command_byte);
1581
		if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1582
			restore_controller(sc->kbdc, command_byte);
1462
		printf("psm%d: unable to set the command byte.\n", unit);
1583
		printf("psm%d: unable to set the command byte.\n", unit);
1463
		endprobe(ENXIO);
1584
		endprobe(ENXIO);
1464
	}
1585
	}
Lines 1505-1510 Link Here
1505
	case MOUSE_MODEL_SYNAPTICS:
1626
	case MOUSE_MODEL_SYNAPTICS:
1506
	case MOUSE_MODEL_GLIDEPOINT:
1627
	case MOUSE_MODEL_GLIDEPOINT:
1507
	case MOUSE_MODEL_VERSAPAD:
1628
	case MOUSE_MODEL_VERSAPAD:
1629
	case MOUSE_MODEL_ELANTECH:
1508
		sc->config |= PSM_CONFIG_INITAFTERSUSPEND;
1630
		sc->config |= PSM_CONFIG_INITAFTERSUSPEND;
1509
		break;
1631
		break;
1510
	default:
1632
	default:
Lines 2166-2171 Link Here
2166
		    (*(int *)addr > PSM_LEVEL_MAX))
2288
		    (*(int *)addr > PSM_LEVEL_MAX))
2167
			return (EINVAL);
2289
			return (EINVAL);
2168
		sc->mode.level = *(int *)addr;
2290
		sc->mode.level = *(int *)addr;
2291
2292
		if (sc->hw.model == MOUSE_MODEL_SYNAPTICS) {
2293
			/*
2294
			 * If we are entering PSM_LEVEL_NATIVE, we want to
2295
			 * enable sending of "extended W mode" packets to
2296
			 * userland. Reset the mode of the touchpad so that the
2297
			 * change in the level is picked up.
2298
			 */
2299
			error = block_mouse_data(sc, &command_byte);
2300
			if (error)
2301
				return (error);
2302
			synaptics_set_mode(sc, synaptics_preferred_mode(sc));
2303
			unblock_mouse_data(sc, command_byte);
2304
		}
2169
		break;
2305
		break;
2170
2306
2171
	case MOUSE_GETSTATUS:
2307
	case MOUSE_GETSTATUS:
Lines 2614-2620 Link Here
2614
{
2750
{
2615
	static int touchpad_buttons;
2751
	static int touchpad_buttons;
2616
	static int guest_buttons;
2752
	static int guest_buttons;
2617
	int w, x0, y0;
2753
	finger_t f;
2754
	int w, nfingers;
2618
2755
2619
	/* TouchPad PS/2 absolute mode message format with capFourButtons:
2756
	/* TouchPad PS/2 absolute mode message format with capFourButtons:
2620
	 *
2757
	 *
Lines 2793-2799 Link Here
2793
			pb->ipacket[4] &= ~(mask);
2930
			pb->ipacket[4] &= ~(mask);
2794
			pb->ipacket[5] &= ~(mask);
2931
			pb->ipacket[5] &= ~(mask);
2795
		} else	if (!sc->syninfo.directional_scrolls &&
2932
		} else	if (!sc->syninfo.directional_scrolls &&
2796
		    !sc->synaction.in_vscroll) {
2933
		    !sc->synaction[0].in_vscroll) {
2797
			/*
2934
			/*
2798
			 * Keep reporting MOUSE DOWN until we get a new packet
2935
			 * Keep reporting MOUSE DOWN until we get a new packet
2799
			 * indicating otherwise.
2936
			 * indicating otherwise.
Lines 2801-2819 Link Here
2801
			touchpad_buttons |= sc->extended_buttons;
2938
			touchpad_buttons |= sc->extended_buttons;
2802
		}
2939
		}
2803
	}
2940
	}
2941
2942
	f.x = ((pb->ipacket[3] & 0x10) << 8) |
2943
	    ((pb->ipacket[1] & 0x0f) << 8) |
2944
	    pb->ipacket[4];
2945
	f.y = ((pb->ipacket[3] & 0x20) << 7) |
2946
	    ((pb->ipacket[1] & 0xf0) << 4) |
2947
	    pb->ipacket[5];
2948
	f.p = *z;
2949
	f.w = w;
2950
	f.flags |= w == 2 ? PSM_FINGER_IS_PEN : 0;
2951
	f.flags |= w < 2 ? PSM_FINGER_FUZZY : 0;
2952
	nfingers = w < 2 ? w + 2 : 1;
2953
2804
	/* Handle ClickPad. */
2954
	/* Handle ClickPad. */
2805
	if (sc->synhw.capClickPad &&
2955
	if (sc->synhw.capClickPad)
2806
	    ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01))
2956
		touchpad_buttons |= psmsoftbuttons(sc, f,
2807
		touchpad_buttons |= MOUSE_BUTTON1DOWN;
2957
		    (pb->ipacket[0] ^ pb->ipacket[3]) & 0x01);
2808
2958
2809
	ms->button = touchpad_buttons | guest_buttons;
2959
	ms->button = touchpad_buttons | guest_buttons;
2810
2960
2961
	psmgestures(sc, &sc->synaction[0], f, nfingers, ms, x, y);
2962
2963
SYNAPTICS_END:
2811
	/*
2964
	/*
2965
	 * Use the extra buttons as a scrollwheel
2966
	 *
2967
	 * XXX X.Org uses the Z axis for vertical wheel only,
2968
	 * whereas moused(8) understands special values to differ
2969
	 * vertical and horizontal wheels.
2970
	 *
2971
	 * xf86-input-mouse needs therefore a small patch to
2972
	 * understand these special values. Without it, the
2973
	 * horizontal wheel acts as a vertical wheel in X.Org.
2974
	 *
2975
	 * That's why the horizontal wheel is disabled by
2976
	 * default for now.
2977
	 */
2978
	if (ms->button & MOUSE_BUTTON4DOWN) {
2979
		*z = -1;
2980
		ms->button &= ~MOUSE_BUTTON4DOWN;
2981
	} else if (ms->button & MOUSE_BUTTON5DOWN) {
2982
		*z = 1;
2983
		ms->button &= ~MOUSE_BUTTON5DOWN;
2984
	} else if (ms->button & MOUSE_BUTTON6DOWN) {
2985
		*z = -2;
2986
		ms->button &= ~MOUSE_BUTTON6DOWN;
2987
	} else if (ms->button & MOUSE_BUTTON7DOWN) {
2988
		*z = 2;
2989
		ms->button &= ~MOUSE_BUTTON7DOWN;
2990
	} else
2991
		*z = 0;
2992
2993
	return (0);
2994
}
2995
2996
static void
2997
psmgestures(struct psm_softc *sc, synapticsaction_t *synaction, finger_t f,
2998
    int nfingers, mousestatus_t *ms, int *x, int *y)
2999
{
3000
	*x = *y = 0;
3001
3002
	/*
2812
	 * Check pressure to detect a real wanted action on the
3003
	 * Check pressure to detect a real wanted action on the
2813
	 * touchpad.
3004
	 * touchpad.
2814
	 */
3005
	 */
2815
	if (*z >= sc->syninfo.min_pressure) {
3006
	if (f.p >= sc->syninfo.min_pressure) {
2816
		synapticsaction_t *synaction;
3007
		int x0, y0;
2817
		int cursor, peer, window;
3008
		int cursor, peer, window;
2818
		int dx, dy, dxp, dyp;
3009
		int dx, dy, dxp, dyp;
2819
		int max_width, max_pressure;
3010
		int max_width, max_pressure;
Lines 2825-2832 Link Here
2825
		int div_min, div_max, div_len;
3016
		int div_min, div_max, div_len;
2826
		int vscroll_hor_area, vscroll_ver_area;
3017
		int vscroll_hor_area, vscroll_ver_area;
2827
		int two_finger_scroll;
3018
		int two_finger_scroll;
3019
		int max_x, max_y;
2828
		int len, weight_prev_x, weight_prev_y;
3020
		int len, weight_prev_x, weight_prev_y;
2829
		int div_max_x, div_max_y, div_x, div_y;
3021
		int div_max_x, div_max_y, div_x, div_y;
3022
		int exiting_scroll;
2830
3023
2831
		/* Read sysctl. */
3024
		/* Read sysctl. */
2832
		/* XXX Verify values? */
3025
		/* XXX Verify values? */
Lines 2852-2890 Link Here
2852
		vscroll_hor_area = sc->syninfo.vscroll_hor_area;
3045
		vscroll_hor_area = sc->syninfo.vscroll_hor_area;
2853
		vscroll_ver_area = sc->syninfo.vscroll_ver_area;
3046
		vscroll_ver_area = sc->syninfo.vscroll_ver_area;
2854
		two_finger_scroll = sc->syninfo.two_finger_scroll;
3047
		two_finger_scroll = sc->syninfo.two_finger_scroll;
3048
		max_x = sc->synhw.maximumXCoord;
3049
		max_y = sc->synhw.maximumYCoord;
2855
3050
3051
		exiting_scroll = 0;
3052
2856
		/* Palm detection. */
3053
		/* Palm detection. */
2857
		if (!(
3054
		if (!(
2858
		    (sc->synhw.capMultiFinger && (w == 0 || w == 1)) ||
3055
		    ((sc->synhw.capMultiFinger ||
2859
		    (sc->synhw.capPalmDetect && w >= 4 && w <= max_width) ||
3056
		      sc->synhw.capAdvancedGestures) && nfingers > 1) ||
2860
		    (!sc->synhw.capPalmDetect && *z <= max_pressure) ||
3057
		    (sc->synhw.capPalmDetect && f.w <= max_width) ||
2861
		    (sc->synhw.capPen && w == 2))) {
3058
		    (!sc->synhw.capPalmDetect && f.p <= max_pressure) ||
3059
		    (sc->synhw.capPen && f.flags & PSM_FINGER_IS_PEN))) {
2862
			/*
3060
			/*
2863
			 * We consider the packet irrelevant for the current
3061
			 * We consider the packet irrelevant for the current
2864
			 * action when:
3062
			 * action when:
2865
			 *  - the width isn't comprised in:
3063
			 *  - the width isn't comprised in:
2866
			 *    [4; max_width]
3064
			 *    [1; max_width]
2867
			 *  - the pressure isn't comprised in:
3065
			 *  - the pressure isn't comprised in:
2868
			 *    [min_pressure; max_pressure]
3066
			 *    [min_pressure; max_pressure]
2869
			 *  - pen aren't supported but w is 2
3067
			 *  - pen aren't supported but PSM_FiNGER_IS_PEN is set
2870
			 *
3068
			 *
2871
			 *  Note that this doesn't terminate the current action.
3069
			 *  Note that this doesn't terminate the current action.
2872
			 */
3070
			 */
2873
			VLOG(2, (LOG_DEBUG,
3071
			VLOG(2, (LOG_DEBUG,
2874
			    "synaptics: palm detected! (%d)\n", w));
3072
			    "synaptics: palm detected! (%d)\n", f.w));
2875
			goto SYNAPTICS_END;
3073
			return;
2876
		}
3074
		}
2877
3075
2878
		/* Read current absolute position. */
3076
		/* Read current absolute position. */
2879
		x0 = ((pb->ipacket[3] & 0x10) << 8) |
3077
		x0 = f.x;
2880
		    ((pb->ipacket[1] & 0x0f) << 8) |
3078
		y0 = f.y;
2881
		    pb->ipacket[4];
2882
		y0 = ((pb->ipacket[3] & 0x20) << 7) |
2883
		    ((pb->ipacket[1] & 0xf0) << 4) |
2884
		    pb->ipacket[5];
2885
3079
2886
		synaction = &(sc->synaction);
2887
2888
		/*
3080
		/*
2889
		 * If the action is just beginning, init the structure and
3081
		 * If the action is just beginning, init the structure and
2890
		 * compute tap timeout.
3082
		 * compute tap timeout.
Lines 2947-2961 Link Here
2947
		 */
3139
		 */
2948
		if (x0 <= margin_left)
3140
		if (x0 <= margin_left)
2949
			x0 = margin_left;
3141
			x0 = margin_left;
2950
		else if (x0 >= 6143 - margin_right)
3142
		else if (x0 >= max_x - margin_right)
2951
			x0 = 6143 - margin_right;
3143
			x0 = max_x - margin_right;
2952
		if (y0 <= margin_bottom)
3144
		if (y0 <= margin_bottom)
2953
			y0 = margin_bottom;
3145
			y0 = margin_bottom;
2954
		else if (y0 >= 6143 - margin_top)
3146
		else if (y0 >= max_y - margin_top)
2955
			y0 = 6143 - margin_top;
3147
			y0 = max_y - margin_top;
2956
3148
2957
		VLOG(3, (LOG_DEBUG, "synaptics: ipacket: [%d, %d], %d, %d\n",
3149
		VLOG(3, (LOG_DEBUG, "synaptics: ipacket: [%d, %d], %d, %d\n",
2958
		    x0, y0, *z, w));
3150
		    x0, y0, f.p, f.w));
2959
3151
2960
		/* Queue this new packet. */
3152
		/* Queue this new packet. */
2961
		cursor = SYNAPTICS_QUEUE_CURSOR(synaction->queue_cursor - 1);
3153
		cursor = SYNAPTICS_QUEUE_CURSOR(synaction->queue_cursor - 1);
Lines 2973-2998 Link Here
2973
		 * pressure peak. Also with multiple fingers, we increase
3165
		 * pressure peak. Also with multiple fingers, we increase
2974
		 * the minimum window.
3166
		 * the minimum window.
2975
		 */
3167
		 */
2976
		switch (w) {
3168
		if (nfingers > 1)
2977
		case 1: /* Three or more fingers. */
2978
			synaction->fingers_nb = imax(3, synaction->fingers_nb);
2979
			synaction->window_min = window_max;
3169
			synaction->window_min = window_max;
2980
			break;
3170
		synaction->fingers_nb = imax(nfingers, synaction->fingers_nb);
2981
		case 0: /* Two fingers. */
3171
		sc->zmax = imax(f.p, sc->zmax);
2982
			synaction->fingers_nb = imax(2, synaction->fingers_nb);
2983
			synaction->window_min = window_max;
2984
			break;
2985
		default: /* One finger or undetectable. */
2986
			synaction->fingers_nb = imax(1, synaction->fingers_nb);
2987
		}
2988
		sc->zmax = imax(*z, sc->zmax);
2989
3172
2990
		/* Do we have enough packets to consider this a movement? */
3173
		/* Do we have enough packets to consider this a movement? */
2991
		if (synaction->queue_len < synaction->window_min)
3174
		if (synaction->queue_len < synaction->window_min)
2992
			goto SYNAPTICS_END;
3175
			return;
2993
3176
2994
		/* Is a scrolling action occuring? */
3177
		/* Is a scrolling action occuring? */
2995
		if (!synaction->in_taphold && !synaction->in_vscroll) {
3178
		if (!synaction->in_taphold &&
3179
		    (!synaction->in_vscroll || two_finger_scroll)) {
2996
			/*
3180
			/*
2997
			 * A scrolling action must not conflict with a tap
3181
			 * A scrolling action must not conflict with a tap
2998
			 * action. Here are the conditions to consider a
3182
			 * action. Here are the conditions to consider a
Lines 3017-3023 Link Here
3017
				 * as that keeps the maximum number of fingers.
3201
				 * as that keeps the maximum number of fingers.
3018
				 */
3202
				 */
3019
				if (two_finger_scroll) {
3203
				if (two_finger_scroll) {
3020
					if (w == 0) {
3204
					if (nfingers == 2) {
3021
						synaction->in_vscroll +=
3205
						synaction->in_vscroll +=
3022
						    dyp ? 2 : 0;
3206
						    dyp ? 2 : 0;
3023
						synaction->in_vscroll +=
3207
						synaction->in_vscroll +=
Lines 3030-3036 Link Here
3030
					        vscroll_hor_area) ||
3214
					        vscroll_hor_area) ||
3031
					    (vscroll_hor_area < 0 &&
3215
					    (vscroll_hor_area < 0 &&
3032
					     synaction->start_y >=
3216
					     synaction->start_y >=
3033
					     6143 + vscroll_hor_area))
3217
					     max_y + vscroll_hor_area))
3034
						synaction->in_vscroll += 2;
3218
						synaction->in_vscroll += 2;
3035
3219
3036
					/* Check for vertical scrolling. */
3220
					/* Check for vertical scrolling. */
Lines 3039-3045 Link Here
3039
						vscroll_ver_area) ||
3223
						vscroll_ver_area) ||
3040
					    (vscroll_ver_area < 0 &&
3224
					    (vscroll_ver_area < 0 &&
3041
					     synaction->start_x >=
3225
					     synaction->start_x >=
3042
					     6143 + vscroll_ver_area))
3226
					     max_x + vscroll_ver_area))
3043
						synaction->in_vscroll += 1;
3227
						synaction->in_vscroll += 1;
3044
				}
3228
				}
3045
3229
Lines 3053-3060 Link Here
3053
		 * Reset two finger scrolling when the number of fingers
3237
		 * Reset two finger scrolling when the number of fingers
3054
		 * is different from two.
3238
		 * is different from two.
3055
		 */
3239
		 */
3056
		if (two_finger_scroll && w != 0)
3240
		if (two_finger_scroll && nfingers != 2 && synaction->in_vscroll != 0) {
3057
			synaction->in_vscroll = 0;
3241
			synaction->in_vscroll = 0;
3242
			exiting_scroll = 1;
3243
		}
3058
3244
3059
		VLOG(5, (LOG_DEBUG,
3245
		VLOG(5, (LOG_DEBUG,
3060
			"synaptics: virtual scrolling: %s "
3246
			"synaptics: virtual scrolling: %s "
Lines 3077-3088 Link Here
3077
			 * using this area, we apply a special weight and
3263
			 * using this area, we apply a special weight and
3078
			 * div.
3264
			 * div.
3079
			 */
3265
			 */
3080
			if (x0 <= na_left || x0 >= 6143 - na_right) {
3266
			if (x0 <= na_left || x0 >= max_x - na_right) {
3081
				weight_prev_x = sc->syninfo.weight_previous_na;
3267
				weight_prev_x = sc->syninfo.weight_previous_na;
3082
				div_max_x = sc->syninfo.div_max_na;
3268
				div_max_x = sc->syninfo.div_max_na;
3083
			}
3269
			}
3084
3270
3085
			if (y0 <= na_bottom || y0 >= 6143 - na_top) {
3271
			if (y0 <= na_bottom || y0 >= max_y - na_top) {
3086
				weight_prev_y = sc->syninfo.weight_previous_na;
3272
				weight_prev_y = sc->syninfo.weight_previous_na;
3087
				div_max_y = sc->syninfo.div_max_na;
3273
				div_max_y = sc->syninfo.div_max_na;
3088
			}
3274
			}
Lines 3162-3167 Link Here
3162
			/* The pointer is not moved. */
3348
			/* The pointer is not moved. */
3163
			*x = *y = 0;
3349
			*x = *y = 0;
3164
		} else {
3350
		} else {
3351
			/* On exit the x/y pos may jump, ignore this */
3352
			if (exiting_scroll)
3353
				*x = *y = 0;
3354
3165
			VLOG(3, (LOG_DEBUG, "synaptics: [%d, %d] -> [%d, %d]\n",
3355
			VLOG(3, (LOG_DEBUG, "synaptics: [%d, %d] -> [%d, %d]\n",
3166
			    dx, dy, *x, *y));
3356
			    dx, dy, *x, *y));
3167
		}
3357
		}
Lines 3170-3179 Link Here
3170
		 * An action is currently taking place but the pressure
3360
		 * An action is currently taking place but the pressure
3171
		 * dropped under the minimum, putting an end to it.
3361
		 * dropped under the minimum, putting an end to it.
3172
		 */
3362
		 */
3173
		synapticsaction_t *synaction;
3174
		int taphold_timeout, dx, dy, tap_max_delta;
3363
		int taphold_timeout, dx, dy, tap_max_delta;
3175
3364
3176
		synaction = &(sc->synaction);
3177
		dx = abs(synaction->queue[synaction->queue_cursor].x -
3365
		dx = abs(synaction->queue[synaction->queue_cursor].x -
3178
		    synaction->start_x);
3366
		    synaction->start_x);
3179
		dy = abs(synaction->queue[synaction->queue_cursor].y -
3367
		dy = abs(synaction->queue[synaction->queue_cursor].y -
Lines 3224-3229 Link Here
3224
				    "synaptics: button RELEASE: %d\n",
3412
				    "synaptics: button RELEASE: %d\n",
3225
				    synaction->tap_button));
3413
				    synaction->tap_button));
3226
				sc->flags |= PSM_FLAGS_FINGERDOWN;
3414
				sc->flags |= PSM_FLAGS_FINGERDOWN;
3415
3416
				/* Schedule button press on next interrupt */
3417
				sc->idletimeout.tv_sec  = psmhz > 1 ?
3418
				    0 : 1;
3419
				sc->idletimeout.tv_usec = psmhz > 1 ?
3420
				    1000000 / psmhz : 0;
3227
			} else {
3421
			} else {
3228
				/*
3422
				/*
3229
				 * This is the first tap: we set the
3423
				 * This is the first tap: we set the
Lines 3236-3241 Link Here
3236
				    1000000;
3430
				    1000000;
3237
				sc->taptimeout.tv_usec = taphold_timeout %
3431
				sc->taptimeout.tv_usec = taphold_timeout %
3238
				    1000000;
3432
				    1000000;
3433
				sc->idletimeout = sc->taptimeout;
3239
				timevaladd(&sc->taptimeout, &sc->lastsoftintr);
3434
				timevaladd(&sc->taptimeout, &sc->lastsoftintr);
3240
3435
3241
				switch (synaction->fingers_nb) {
3436
				switch (synaction->fingers_nb) {
Lines 3272-3278 Link Here
3272
			}
3467
			}
3273
		}
3468
		}
3274
	} else if (!(sc->flags & PSM_FLAGS_FINGERDOWN) &&
3469
	} else if (!(sc->flags & PSM_FLAGS_FINGERDOWN) &&
3275
	    sc->synaction.in_taphold) {
3470
	    synaction->in_taphold) {
3276
		/*
3471
		/*
3277
		 * For a tap-hold to work, the button must remain down at
3472
		 * For a tap-hold to work, the button must remain down at
3278
		 * least until timeout (where the in_taphold flags will be
3473
		 * least until timeout (where the in_taphold flags will be
Lines 3279-3323 Link Here
3279
		 * cleared) or during the next action.
3474
		 * cleared) or during the next action.
3280
		 */
3475
		 */
3281
		if (timevalcmp(&sc->lastsoftintr, &sc->taptimeout, <=)) {
3476
		if (timevalcmp(&sc->lastsoftintr, &sc->taptimeout, <=)) {
3282
			ms->button |= sc->synaction.tap_button;
3477
			ms->button |= synaction->tap_button;
3283
		} else {
3478
		} else {
3284
			VLOG(2, (LOG_DEBUG,
3479
			VLOG(2, (LOG_DEBUG,
3285
			    "synaptics: button RELEASE: %d\n",
3480
			    "synaptics: button RELEASE: %d\n",
3286
			    sc->synaction.tap_button));
3481
			    synaction->tap_button));
3287
			sc->synaction.in_taphold = 0;
3482
			synaction->in_taphold = 0;
3288
		}
3483
		}
3289
	}
3484
	}
3290
3485
3291
SYNAPTICS_END:
3486
	return;
3487
}
3488
3489
static int
3490
psmsoftbuttons(struct psm_softc *sc, finger_t f, int pressed)
3491
{
3492
	static int button = 0;
3493
	int y_ok, center_button, center_x, right_button, right_x;
3494
3495
	/* Dont change clickpad softbutton after pressing */
3496
	if (pressed && !button) {
3497
		y_ok = sc->syninfo.softbuttons_y >= 0 ?
3498
		    f.y < sc->syninfo.softbuttons_y :
3499
		    f.y > sc->synhw.maximumYCoord - sc->syninfo.softbuttons_y;
3500
3501
		center_button = MOUSE_BUTTON2DOWN;
3502
		center_x = sc->syninfo.softbutton2_x;
3503
		right_button = MOUSE_BUTTON3DOWN;
3504
		right_x = sc->syninfo.softbutton3_x;
3505
3506
		if (center_x > 0 && right_x > 0 && center_x > right_x) {
3507
			center_button = MOUSE_BUTTON3DOWN;
3508
			center_x = sc->syninfo.softbutton3_x;
3509
			right_button = MOUSE_BUTTON2DOWN;
3510
			right_x = sc->syninfo.softbutton2_x;
3511
		}
3512
3513
		if (right_x > 0 && f.x > right_x && y_ok)
3514
			button = right_button;
3515
		else if (center_x > 0 && f.x > center_x && y_ok)
3516
			button = center_button;
3517
		else
3518
			button = MOUSE_BUTTON1DOWN;
3519
		VLOG(2, (LOG_DEBUG, "softbutton: PRESS: %d\n", button));
3520
	}
3521
3522
	/* Clickpad releases */
3523
	if (!pressed && button) {
3524
		VLOG(2, (LOG_DEBUG, "softbutton: RELEASE: %d\n", button));
3525
		button = 0;
3526
	}
3527
3528
	return (button);
3529
}
3530
3531
static int
3532
proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
3533
    int *x, int *y, int *z)
3534
{
3535
	static int touchpad_button, trackpoint_button;
3536
	static int v4nfingers = 0;
3537
	finger_t fn, f[PSM_GESTURE_FINGERS];
3538
	int pkt, id, scale, i, nfingers, reset_queue;
3539
3540
	if (!elantech_support)
3541
		return (0);
3542
3543
	/* Determine packet format and do a sanity check for out of sync packets. */
3544
	if (ELANTECH_PKT_IS_DEBOUNCE(pb, sc->elanhw.hwversion))
3545
		pkt = ELANTECH_PKT_NOP;
3546
	else if (ELANTECH_PKT_IS_TRACKPOINT(pb))
3547
		pkt = ELANTECH_PKT_TRACKPOINT;
3548
	else
3549
	switch (sc->elanhw.hwversion) {
3550
	case 2:
3551
		if (!ELANTECH_PKT_IS_V2(pb))
3552
			return (-1);
3553
3554
		pkt = (pb->ipacket[0] & 0xc0) == 0x80 ?
3555
		    ELANTECH_PKT_V2_2FINGER : ELANTECH_PKT_V2_COMMON;
3556
		break;
3557
	case 3:
3558
		if (!ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc) &&
3559
		    !ELANTECH_PKT_IS_V3_TAIL(pb, sc->elanhw.hascrc))
3560
			return (-1);
3561
3562
		pkt = ELANTECH_PKT_V3;
3563
		break;
3564
	case 4:
3565
		if (!ELANTECH_PKT_IS_V4(pb, sc->elanhw.hascrc))
3566
			return (-1);
3567
3568
		switch (pb->ipacket[3] & 0x03) {
3569
		case 0x00:
3570
			pkt = ELANTECH_PKT_V4_STATUS;
3571
			break;
3572
		case 0x01:
3573
			pkt = ELANTECH_PKT_V4_HEAD;
3574
			break;
3575
		case 0x02:
3576
			pkt = ELANTECH_PKT_V4_MOTION;
3577
			break;
3578
		default:
3579
			return (-1);
3580
		}
3581
		break;
3582
	default:
3583
		return (-1);
3584
	}
3585
3586
	VLOG(5, (LOG_DEBUG, "elantech: ipacket format: %d\n", pkt));
3587
3588
	for (id = 0; id < PSM_GESTURE_FINGERS; id++)
3589
		PSM_FINGER_RESET(f[id]);
3590
3591
	*x = *y = *z = 0;
3592
	ms->button = ms->obutton;
3593
3594
	if (sc->syninfo.touchpad_off)
3595
		return (0);
3596
3597
	/* Common legend
3598
	 * L: Left mouse button pressed
3599
	 * R: Right mouse button pressed
3600
	 * N: number of fingers on touchpad
3601
	 * X: absolute x value (horizontal)
3602
	 * Y: absolute y value (vertical)
3603
	 * W; width of the finger touch
3604
	 * P: pressure
3605
	 */
3606
	switch (pkt) {
3607
	case ELANTECH_PKT_V2_COMMON:	/* HW V2. One/Three finger touch */
3608
		/*               7   6   5   4   3   2   1   0 (LSB)
3609
		 * -------------------------------------------
3610
		 * ipacket[0]:  N1  N0  W3  W2   .   .   R   L
3611
		 * ipacket[1]:  P7  P6  P5  P4 X11 X10  X9  X8
3612
		 * ipacket[2]:  X7  X6  X5  X4  X3  X2  X1  X0
3613
		 * ipacket[3]:  N4  VF  W1  W0   .   .   .  B2
3614
		 * ipacket[4]:  P3  P1  P2  P0 Y11 Y10  Y9  Y8
3615
		 * ipacket[5]:  Y7  Y6  Y5  Y4  Y3  Y2  Y1  Y0
3616
		 * -------------------------------------------
3617
		 * N4: set if more than 3 fingers (only in 3 fingers mode)
3618
		 * VF: a kind of flag? (only on EF123, 0 when finger
3619
		 *     is over one of the buttons, 1 otherwise)
3620
		 * B2: (on EF113 only, 0 otherwise), one button pressed
3621
		 * P & W is not reported on EF113 touchpads
3622
		 */
3623
		nfingers = (pb->ipacket[0] & 0xc0) >> 6;
3624
3625
		fn = ELANTECH_FINGER_SET_XYP(pb);
3626
		if (sc->elanhw.haspressure) {
3627
			fn.w = ((pb->ipacket[0] & 0x30) >> 2) |
3628
			    ((pb->ipacket[3] & 0x30) >> 4);
3629
		} else {
3630
			fn.p = ELANTECH_FINGER_DEFAULT_P;
3631
			fn.w = ELANTECH_FINGER_DEFAULT_W;
3632
		}
3633
3634
		/*
3635
		 * HW v2 dont report exact finger positions when 3 or more
3636
		 * fingers are on touchpad. Use reported value as fingers
3637
		 * position as it is required for tap detection
3638
		 */
3639
		if (nfingers > 2) {
3640
			fn.flags = PSM_FINGER_FUZZY;
3641
			f[0] = f[1] = fn;
3642
		}
3643
3644
		id = nfingers - 1;
3645
		if (id >= 0 && id < PSM_GESTURE_FINGERS)
3646
			f[id] = fn;
3647
		break;
3648
3649
	case ELANTECH_PKT_V2_2FINGER:	/*HW V2. Two finger touch */
3650
		/*               7   6   5   4   3   2   1   0 (LSB)
3651
		 * -------------------------------------------
3652
		 * ipacket[0]:  N1  N0 AY8 AX8   .   .   R   L
3653
		 * ipacket[1]: AX7 AX6 AX5 AX4 AX3 AX2 AX1 AX0
3654
		 * ipacket[2]: AY7 AY6 AY5 AY4 AY3 AY2 AY1 AY0
3655
		 * ipacket[3]:   .   . BY8 BX8   .   .   .   .
3656
		 * ipacket[4]: BX7 BX6 BX5 BX4 BX3 BX2 BX1 BX0
3657
		 * ipacket[5]: BY7 BY6 BY5 BY4 BY3 BY2 BY1 BY0
3658
		 * -------------------------------------------
3659
		 * AX: lower-left finger absolute x value
3660
		 * AY: lower-left finger absolute y value
3661
		 * BX: upper-right finger absolute x value
3662
		 * BY: upper-right finger absolute y value
3663
		 */
3664
		nfingers = 2;
3665
3666
		VLOG(5, (LOG_DEBUG, "elantech: v2 BBX: [%d, %d] [%d, %d]\n",
3667
		    ((pb->ipacket[0] & 0x10) << 4) | pb->ipacket[1],
3668
		    ((pb->ipacket[0] & 0x20) << 3) | pb->ipacket[2],
3669
		    ((pb->ipacket[3] & 0x10) << 4) | pb->ipacket[4],
3670
		    ((pb->ipacket[3] & 0x20) << 3) | pb->ipacket[5]
3671
		));
3672
		for (id = 0; id < imin(2, PSM_GESTURE_FINGERS); id ++)
3673
			f[id] = (finger_t) {
3674
				.x = (((pb->ipacket[id * 3] & 0x10) << 4) |
3675
				    pb->ipacket[id * 3 + 1]) << 2,
3676
				.y = (((pb->ipacket[id * 3] & 0x20) << 3) |
3677
				    pb->ipacket[id * 3 + 2]) << 2,
3678
				.p = ELANTECH_FINGER_DEFAULT_P,
3679
				.w = ELANTECH_FINGER_DEFAULT_W,
3680
				/* HW ver.2 sends bounding box */
3681
				.flags = PSM_FINGER_FUZZY
3682
			};
3683
		break;
3684
3685
	case ELANTECH_PKT_V3:	/* HW Version 3 */
3686
		/*               7   6   5   4   3   2   1   0 (LSB)
3687
		 * -------------------------------------------
3688
		 * ipacket[0]:  N1  N0  W3  W2   0   1   R   L
3689
		 * ipacket[1]:  P7  P6  P5  P4 X11 X10  X9  X8
3690
		 * ipacket[2]:  X7  X6  X5  X4  X3  X2  X1  X0
3691
		 * ipacket[3]:   0   0  W1  W0   0   0   1   0
3692
		 * ipacket[4]:  P3  P1  P2  P0 Y11 Y10  Y9  Y8
3693
		 * ipacket[5]:  Y7  Y6  Y5  Y4  Y3  Y2  Y1  Y0
3694
		 * -------------------------------------------
3695
		 */
3696
		nfingers = (pb->ipacket[0] & 0xc0) >> 6;
3697
		id = nfingers - 1;
3698
3699
		fn = ELANTECH_FINGER_SET_XYP(pb);
3700
		fn.w = ((pb->ipacket[0] & 0x30) >> 2) |
3701
		    ((pb->ipacket[3] & 0x30) >> 4);
3702
3703
		/*
3704
		 * HW v3 dont report exact finger positions when 3 or more
3705
		 * fingers are on touchpad. Use reported value as fingers
3706
		 * position as it is required for tap detection
3707
		 */
3708
		if (nfingers > 2) {
3709
			fn.flags = PSM_FINGER_FUZZY;
3710
			f[0] = f[1] = fn;
3711
		}
3712
3713
		if (nfingers == 2 &&
3714
		    ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc))
3715
			id = 0;
3716
3717
		if (id >= 0 && id < PSM_GESTURE_FINGERS) {
3718
			f[id] = fn;
3719
		}
3720
		break;
3721
3722
	case ELANTECH_PKT_V4_STATUS:	/* HW Version 4. Status packet */
3723
		/*               7   6   5   4   3   2   1   0 (LSB)
3724
		 * -------------------------------------------
3725
		 * ipacket[0]:   .   .   .   .   0   1   R   L
3726
		 * ipacket[1]:   .   .   .  F4  F3  F2  F1  F0
3727
		 * ipacket[2]:   .   .   .   .   .   .   .   .
3728
		 * ipacket[3]:   .   .   .   1   0   0   0   0
3729
		 * ipacket[4]:  PL   .   .   .   .   .   .   .
3730
		 * ipacket[5]:   .   .   .   .   .   .   .   .
3731
		 * -------------------------------------------
3732
		 * Fn: finger n is on touchpad
3733
		 * PL: palm
3734
		 * HV ver4 sends a status packet to indicate that the numbers
3735
		 * or identities of the fingers has been changed
3736
		 */
3737
3738
		v4nfingers = fls(pb->ipacket[1] & 0x1f);
3739
3740
		if (v4nfingers > sc->elanaction.nfingers)
3741
			return (0);
3742
3743
		nfingers = v4nfingers;
3744
3745
		break;
3746
3747
	case ELANTECH_PKT_V4_HEAD:	/* HW Version 4. Head packet */
3748
		/*               7   6   5   4   3   2   1   0 (LSB)
3749
		 * -------------------------------------------
3750
		 * ipacket[0]:  W3  W2  W1  W0   0   1   R   L
3751
		 * ipacket[1]:  P7  P6  P5  P4 X11 X10  X9  X8
3752
		 * ipacket[2]:  X7  X6  X5  X4  X3  X2  X1  X0
3753
		 * ipacket[3]: ID2 ID1 ID0   1   0   0   0   1
3754
		 * ipacket[4]:  P3  P1  P2  P0 Y11 Y10  Y9  Y8
3755
		 * ipacket[5]:  Y7  Y6  Y5  Y4  Y3  Y2  Y1  Y0
3756
		 * -------------------------------------------
3757
		 * ID: finger id
3758
		 * HW ver 4 sends head packets in two cases:
3759
		 * 1. One finger touch and movement.
3760
		 * 2. Next after status packet to tell new finger positions.
3761
		 */
3762
		nfingers = v4nfingers;
3763
		id = ((pb->ipacket[3] & 0xe0) >> 5) - 1;
3764
3765
		if (id >= 0 && id < PSM_GESTURE_FINGERS) {
3766
			f[id] = ELANTECH_FINGER_SET_XYP(pb);
3767
			f[id].w = (pb->ipacket[0] & 0xf0) >> 4;
3768
		}
3769
		break;
3770
3771
	case ELANTECH_PKT_V4_MOTION:	/* HW Version 4. Motion packet */
3772
		/*               7   6   5   4   3   2   1   0 (LSB)
3773
		 * -------------------------------------------
3774
		 * ipacket[0]: ID2 ID1 ID0  OF   0   1   R   L
3775
		 * ipacket[1]: DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0
3776
		 * ipacket[2]: DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0
3777
		 * ipacket[3]: ID2 ID1 ID0   1   0   0   1   0
3778
		 * ipacket[4]: DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0
3779
		 * ipacket[5]: DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0
3780
		 * -------------------------------------------
3781
		 * OF: delta overflows (> 127 or < -128), in this case
3782
		 *     firmware sends us (delta x / 5) and (delta y / 5)
3783
		 * ID: finger id
3784
		 * DX: delta x (two's complement)
3785
		 * XY: delta y (two's complement)
3786
		 * byte 0 ~ 2 for one finger
3787
		 * byte 3 ~ 5 for another finger
3788
		 */
3789
		nfingers = v4nfingers;
3790
3791
		scale = (pb->ipacket[0] & 0x10) ? 5 : 1;
3792
		for (i = 0; i <= 3; i += 3) {
3793
			id = ((pb->ipacket[i] & 0xe0) >> 5) - 1;
3794
			if (id < 0 || id >= PSM_GESTURE_FINGERS)
3795
				continue;
3796
3797
			if (PSM_FINGER_IS_SET(sc->elanaction.fingers[id])) {
3798
				f[id] = sc->elanaction.fingers[id];
3799
				f[id].x += imax(-f[id].x,
3800
				    (signed char)pb->ipacket[i+1] * scale);
3801
				f[id].y += imax(-f[id].y,
3802
				    (signed char)pb->ipacket[i+2] * scale);
3803
			} else {
3804
				VLOG(3, (LOG_DEBUG, "elantech: "
3805
				    "HW v4 motion packet skipped\n"));
3806
			}
3807
		}
3808
3809
		break;
3810
3811
	case ELANTECH_PKT_TRACKPOINT:
3812
		/*               7   6   5   4   3   2   1   0 (LSB)
3813
		 * -------------------------------------------
3814
		 * ipacket[0]:   0   0  SX  SY   0   M   R   L
3815
		 * ipacket[1]: ~SX   0   0   0   0   0   0   0
3816
		 * ipacket[2]: ~SY   0   0   0   0   0   0   0
3817
		 * ipacket[3]:   0   0 ~SY ~SX   0   1   1   0
3818
		 * ipacket[4]:  X7  X6  X5  X4  X3  X2  X1  X0
3819
		 * ipacket[5]:  Y7  Y6  Y5  Y4  Y3  Y2  Y1  Y0
3820
		 * -------------------------------------------
3821
		 * X and Y are written in two's complement spread
3822
		 * over 9 bits with SX/SY the relative top bit and
3823
		 * X7..X0 and Y7..Y0 the lower bits.
3824
		 */
3825
		*x = (pb->ipacket[0] & 0x20) ?
3826
		    pb->ipacket[4] - 256 : pb->ipacket[4];
3827
		*y = (pb->ipacket[0] & 0x10) ?
3828
		    pb->ipacket[5] - 256 : pb->ipacket[5];
3829
3830
		trackpoint_button =
3831
		    ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) |
3832
		    ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) |
3833
		    ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0);
3834
3835
		ms->button = touchpad_button | trackpoint_button;
3836
		return (0);
3837
3838
	case ELANTECH_PKT_NOP:
3839
		return (0);
3840
3841
	default:
3842
		return (-1);
3843
	}
3844
3845
	for (id = 0; id < PSM_GESTURE_FINGERS; id++)
3846
		if (PSM_FINGER_IS_SET(f[id]))
3847
			VLOG(2, (LOG_DEBUG, "elantech: "
3848
			    "finger %d: down [%d, %d], %d, %d, %d\n", id + 1,
3849
			    f[id].x, f[id].y, f[id].p, f[id].w, f[id].flags));
3850
3851
	/* Touchpad button presses */
3852
	if (sc->elanhw.isclickpad) {
3853
		touchpad_button =
3854
		    psmsoftbuttons(sc, f[0], pb->ipacket[0] & 0x03);
3855
	} else {
3856
		touchpad_button =
3857
		    ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) |
3858
		    ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0);
3859
	}
3860
3861
	ms->button = touchpad_button | trackpoint_button;
3862
3292
	/*
3863
	/*
3293
	 * Use the extra buttons as a scrollwheel
3864
	 * Send finger positions to movement smoother.
3294
	 *
3865
	 * Try to avoid nonreenterable code paths of movement smoother
3295
	 * XXX X.Org uses the Z axis for vertical wheel only,
3866
	 * like initialization and tap processing for 2nd finger.
3296
	 * whereas moused(8) understands special values to differ
3297
	 * vertical and horizontal wheels.
3298
	 *
3299
	 * xf86-input-mouse needs therefore a small patch to
3300
	 * understand these special values. Without it, the
3301
	 * horizontal wheel acts as a vertical wheel in X.Org.
3302
	 *
3303
	 * That's why the horizontal wheel is disabled by
3304
	 * default for now.
3305
	 */
3867
	 */
3868
	for (id = 0; id < PSM_GESTURE_FINGERS; id++) {
3306
3869
3307
	if (ms->button & MOUSE_BUTTON4DOWN) {
3870
		if (!(PSM_FINGER_IS_SET(f[id]) || (id == 0 && nfingers == 0)))
3871
			continue;
3872
		if (id == 1 && sc->syninfo.two_finger_scroll == 0)
3873
			continue;
3874
3875
		reset_queue = 0;
3876
3877
		/* Avoid cursor jumping on switching real<->fuzzy position */
3878
		if (PSM_FINGER_IS_SET(f[id]) &&
3879
		    ((f[id].flags & PSM_FINGER_FUZZY) !=
3880
		     (sc->elanaction.fingers[id].flags & PSM_FINGER_FUZZY)))
3881
			reset_queue = 1;
3882
3883
		/* Reset 2-nd finger synaction queue on action start */
3884
		if (id > 0 && !PSM_FINGER_IS_SET(sc->elanaction.fingers[id])) {
3885
			reset_queue = 1;
3886
		}
3887
3888
		if (reset_queue) {
3889
			VLOG(3, (LOG_DEBUG, "elantech: "
3890
			    "finger %d: reset synaptics queue\n", id + 1));
3891
			sc->synaction[id].queue_cursor = 0;
3892
			sc->synaction[id].queue_len = 0;
3893
			sc->synaction[id].queue[0].x = f[id].x;
3894
			sc->synaction[id].queue[0].y = f[id].y;
3895
			sc->synaction[id].start_x = f[id].x;
3896
			sc->synaction[id].start_y = f[id].y;
3897
			sc->synaction[id].window_min = sc->syninfo.window_min;
3898
			sc->synaction[id].squelch_x = 0;
3899
			sc->synaction[id].squelch_y = 0;
3900
			sc->synaction[id].avg_dx = 0;
3901
			sc->synaction[id].avg_dy = 0;
3902
			sc->synaction[id].fingers_nb = 0;
3903
			sc->synaction[id].in_vscroll = 0;
3904
		}
3905
3906
		/* prevent palm detection for fuzzy finger touches */
3907
		if (f[id].flags & PSM_FINGER_FUZZY) {
3908
			f[id].p = ELANTECH_FINGER_DEFAULT_P;
3909
			f[id].w = ELANTECH_FINGER_DEFAULT_W;
3910
		}
3911
3912
		psmgestures(sc, &sc->synaction[id], f[id], imin(nfingers, 3),
3913
		    ms, x, y);
3914
	}
3915
3916
	/* Store current finger positions in action context */
3917
	sc->elanaction.nfingers = nfingers;
3918
	for (id = 0; id < PSM_GESTURE_FINGERS; id++) {
3919
		if (PSM_FINGER_IS_SET(f[id]))
3920
			sc->elanaction.fingers[id] = f[id];
3921
		if (id >= nfingers)
3922
			PSM_FINGER_RESET(sc->elanaction.fingers[id]);
3923
	}
3924
3925
	/* Use the extra buttons as a scrollwheel */
3926
	if (ms->button & MOUSE_BUTTON4DOWN)
3308
		*z = -1;
3927
		*z = -1;
3309
		ms->button &= ~MOUSE_BUTTON4DOWN;
3928
	else if (ms->button & MOUSE_BUTTON5DOWN)
3310
	} else if (ms->button & MOUSE_BUTTON5DOWN) {
3311
		*z = 1;
3929
		*z = 1;
3312
		ms->button &= ~MOUSE_BUTTON5DOWN;
3930
	else if (ms->button & MOUSE_BUTTON6DOWN)
3313
	} else if (ms->button & MOUSE_BUTTON6DOWN) {
3314
		*z = -2;
3931
		*z = -2;
3315
		ms->button &= ~MOUSE_BUTTON6DOWN;
3932
	else if (ms->button & MOUSE_BUTTON7DOWN)
3316
	} else if (ms->button & MOUSE_BUTTON7DOWN) {
3317
		*z = 2;
3933
		*z = 2;
3318
		ms->button &= ~MOUSE_BUTTON7DOWN;
3934
	else
3319
	} else
3320
		*z = 0;
3935
		*z = 0;
3936
	ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN |
3937
	    MOUSE_BUTTON6DOWN | MOUSE_BUTTON7DOWN);
3321
3938
3322
	return (0);
3939
	return (0);
3323
}
3940
}
Lines 3390-3395 Link Here
3390
}
4007
}
3391
4008
3392
static void
4009
static void
4010
psmsoftintridle(void *arg)
4011
{
4012
	struct psm_softc *sc = arg;
4013
	packetbuf_t *pb;
4014
4015
	/* Invoke soft handler only when pqueue is empty. Otherwise it will be
4016
	 * invoked from psmintr soon with pqueue filled with real data */
4017
	if (sc->pqueue_start == sc->pqueue_end &&
4018
	    sc->idlepacket.inputbytes > 0) {
4019
		/* Grow circular queue backwards to avoid race with psmintr */
4020
		if (--sc->pqueue_start < 0)
4021
			sc->pqueue_start = PSM_PACKETQUEUE - 1;
4022
4023
		pb = &sc->pqueue[sc->pqueue_start];
4024
		memcpy(pb, &sc->idlepacket, sizeof(packetbuf_t));
4025
		VLOG(4, (LOG_DEBUG,
4026
		    "psmsoftintridle: %02x %02x %02x %02x %02x %02x\n",
4027
		    pb->ipacket[0], pb->ipacket[1], pb->ipacket[2],
4028
		    pb->ipacket[3], pb->ipacket[4], pb->ipacket[5]));
4029
4030
		psmsoftintr(arg);
4031
	}
4032
}
4033
4034
static void
3393
psmsoftintr(void *arg)
4035
psmsoftintr(void *arg)
3394
{
4036
{
3395
	/*
4037
	/*
Lines 3442-3447 Link Here
3442
		if (sc->config & PSM_CONFIG_FORCETAP)
4084
		if (sc->config & PSM_CONFIG_FORCETAP)
3443
			ms.button |= ((c & MOUSE_PS2_TAP)) ?
4085
			ms.button |= ((c & MOUSE_PS2_TAP)) ?
3444
			    0 : MOUSE_BUTTON4DOWN;
4086
			    0 : MOUSE_BUTTON4DOWN;
4087
		timevalclear(&sc->idletimeout);
4088
		sc->idlepacket.inputbytes = 0;
3445
4089
3446
		switch (sc->hw.model) {
4090
		switch (sc->hw.model) {
3447
4091
Lines 3580-3585 Link Here
3580
				goto next;
4224
				goto next;
3581
			break;
4225
			break;
3582
4226
4227
		case MOUSE_MODEL_ELANTECH:
4228
			if (proc_elantech(sc, pb, &ms, &x, &y, &z) != 0)
4229
				goto next;
4230
			break;
4231
3583
		case MOUSE_MODEL_TRACKPOINT:
4232
		case MOUSE_MODEL_TRACKPOINT:
3584
		case MOUSE_MODEL_GENERIC:
4233
		case MOUSE_MODEL_GENERIC:
3585
		default:
4234
		default:
Lines 3604-3609 Link Here
3604
		}
4253
		}
3605
	}
4254
	}
3606
4255
4256
	/* Store last packet for reinjection if it has not been set already */
4257
	if (timevalisset(&sc->idletimeout) && sc->idlepacket.inputbytes == 0)
4258
		sc->idlepacket = *pb;
4259
3607
	ms.dx = x;
4260
	ms.dx = x;
3608
	ms.dy = y;
4261
	ms.dy = y;
3609
	ms.dz = z;
4262
	ms.dz = z;
Lines 3650-3655 Link Here
3650
		pgsigio(&sc->async, SIGIO, 0);
4303
		pgsigio(&sc->async, SIGIO, 0);
3651
	}
4304
	}
3652
	sc->state &= ~PSM_SOFTARMED;
4305
	sc->state &= ~PSM_SOFTARMED;
4306
4307
	/* schedule injection of predefined packet after idletimeout
4308
	 * if no data packets have been received from psmintr */
4309
	if (timevalisset(&sc->idletimeout)) {
4310
		sc->state |= PSM_SOFTARMED;
4311
		callout_reset(&sc->softcallout, tvtohz(&sc->idletimeout),
4312
		    psmsoftintridle, sc);
4313
		VLOG(2, (LOG_DEBUG, "softintr: callout set: %d ticks\n",
4314
		    tvtohz(&sc->idletimeout)));
4315
	}
3653
	splx(s);
4316
	splx(s);
3654
}
4317
}
3655
4318
Lines 3710-3717 Link Here
3710
#ifdef notyet
4373
#ifdef notyet
3711
/* Logitech MouseMan Cordless II */
4374
/* Logitech MouseMan Cordless II */
3712
static int
4375
static int
3713
enable_lcordless(KDBC kbdc, struct psm_softc *sc)
4376
enable_lcordless(struct psm_softc *sc, enum probearg arg)
3714
{
4377
{
4378
	KBDC kbdc = sc->kbdc;
3715
	int status[3];
4379
	int status[3];
3716
	int ch;
4380
	int ch;
3717
4381
Lines 3732-3739 Link Here
3732
4396
3733
/* Genius NetScroll Mouse, MouseSystems SmartScroll Mouse */
4397
/* Genius NetScroll Mouse, MouseSystems SmartScroll Mouse */
3734
static int
4398
static int
3735
enable_groller(KBDC kbdc, struct psm_softc *sc)
4399
enable_groller(struct psm_softc *sc, enum probearg arg)
3736
{
4400
{
4401
	KBDC kbdc = sc->kbdc;
3737
	int status[3];
4402
	int status[3];
3738
4403
3739
	/*
4404
	/*
Lines 3762-3768 Link Here
3762
	if ((status[1] != '3') || (status[2] != 'D'))
4427
	if ((status[1] != '3') || (status[2] != 'D'))
3763
		return (FALSE);
4428
		return (FALSE);
3764
	/* FIXME: SmartScroll Mouse has 5 buttons! XXX */
4429
	/* FIXME: SmartScroll Mouse has 5 buttons! XXX */
3765
	if (sc != NULL)
4430
	if (arg == PROBE)
3766
		sc->hw.buttons = 4;
4431
		sc->hw.buttons = 4;
3767
	return (TRUE);
4432
	return (TRUE);
3768
}
4433
}
Lines 3769-3776 Link Here
3769
4434
3770
/* Genius NetMouse/NetMouse Pro, ASCII Mie Mouse, NetScroll Optical */
4435
/* Genius NetMouse/NetMouse Pro, ASCII Mie Mouse, NetScroll Optical */
3771
static int
4436
static int
3772
enable_gmouse(KBDC kbdc, struct psm_softc *sc)
4437
enable_gmouse(struct psm_softc *sc, enum probearg arg)
3773
{
4438
{
4439
	KBDC kbdc = sc->kbdc;
3774
	int status[3];
4440
	int status[3];
3775
4441
3776
	/*
4442
	/*
Lines 3792-3799 Link Here
3792
4458
3793
/* ALPS GlidePoint */
4459
/* ALPS GlidePoint */
3794
static int
4460
static int
3795
enable_aglide(KBDC kbdc, struct psm_softc *sc)
4461
enable_aglide(struct psm_softc *sc, enum probearg arg)
3796
{
4462
{
4463
	KBDC kbdc = sc->kbdc;
3797
	int status[3];
4464
	int status[3];
3798
4465
3799
	/*
4466
	/*
Lines 3814-3822 Link Here
3814
4481
3815
/* Kensington ThinkingMouse/Trackball */
4482
/* Kensington ThinkingMouse/Trackball */
3816
static int
4483
static int
3817
enable_kmouse(KBDC kbdc, struct psm_softc *sc)
4484
enable_kmouse(struct psm_softc *sc, enum probearg arg)
3818
{
4485
{
3819
	static u_char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 };
4486
	static u_char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 };
4487
	KBDC kbdc = sc->kbdc;
3820
	int status[3];
4488
	int status[3];
3821
	int id1;
4489
	int id1;
3822
	int id2;
4490
	int id2;
Lines 3867-3874 Link Here
3867
4535
3868
/* Logitech MouseMan+/FirstMouse+, IBM ScrollPoint Mouse */
4536
/* Logitech MouseMan+/FirstMouse+, IBM ScrollPoint Mouse */
3869
static int
4537
static int
3870
enable_mmanplus(KBDC kbdc, struct psm_softc *sc)
4538
enable_mmanplus(struct psm_softc *sc, enum probearg arg)
3871
{
4539
{
4540
	KBDC kbdc = sc->kbdc;
3872
	int data[3];
4541
	int data[3];
3873
4542
3874
	/* the special sequence to enable the fourth button and the roller. */
4543
	/* the special sequence to enable the fourth button and the roller. */
Lines 3909-3915 Link Here
3909
	if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0)
4578
	if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0)
3910
		return (FALSE);
4579
		return (FALSE);
3911
4580
3912
	if (sc != NULL) {
4581
	if (arg == PROBE) {
3913
		sc->hw.hwid &= 0x00ff;
4582
		sc->hw.hwid &= 0x00ff;
3914
		sc->hw.hwid |= data[2] << 8;	/* save model ID */
4583
		sc->hw.hwid |= data[2] << 8;	/* save model ID */
3915
	}
4584
	}
Lines 3925-3932 Link Here
3925
4594
3926
/* MS IntelliMouse Explorer */
4595
/* MS IntelliMouse Explorer */
3927
static int
4596
static int
3928
enable_msexplorer(KBDC kbdc, struct psm_softc *sc)
4597
enable_msexplorer(struct psm_softc *sc, enum probearg arg)
3929
{
4598
{
4599
	KBDC kbdc = sc->kbdc;
3930
	static u_char rate0[] = { 200, 100, 80, };
4600
	static u_char rate0[] = { 200, 100, 80, };
3931
	static u_char rate1[] = { 200, 200, 80, };
4601
	static u_char rate1[] = { 200, 200, 80, };
3932
	int id;
4602
	int id;
Lines 3937-3943 Link Here
3937
	 * straight to Explorer mode, but need to be set to Intelli mode
4607
	 * straight to Explorer mode, but need to be set to Intelli mode
3938
	 * first.
4608
	 * first.
3939
	 */
4609
	 */
3940
	enable_msintelli(kbdc, sc);
4610
	enable_msintelli(sc, arg);
3941
4611
3942
	/* the special sequence to enable the extra buttons and the roller. */
4612
	/* the special sequence to enable the extra buttons and the roller. */
3943
	for (i = 0; i < sizeof(rate1)/sizeof(rate1[0]); ++i)
4613
	for (i = 0; i < sizeof(rate1)/sizeof(rate1[0]); ++i)
Lines 3948-3954 Link Here
3948
	if (id != PSM_EXPLORER_ID)
4618
	if (id != PSM_EXPLORER_ID)
3949
		return (FALSE);
4619
		return (FALSE);
3950
4620
3951
	if (sc != NULL) {
4621
	if (arg == PROBE) {
3952
		sc->hw.buttons = 5;	/* IntelliMouse Explorer XXX */
4622
		sc->hw.buttons = 5;	/* IntelliMouse Explorer XXX */
3953
		sc->hw.hwid = id;
4623
		sc->hw.hwid = id;
3954
	}
4624
	}
Lines 3971-3985 Link Here
3971
	return (TRUE);
4641
	return (TRUE);
3972
}
4642
}
3973
4643
3974
/* MS IntelliMouse */
4644
/*
4645
 * MS IntelliMouse
4646
 * Logitech MouseMan+ and FirstMouse+ will also respond to this
4647
 * probe routine and act like IntelliMouse.
4648
 */
3975
static int
4649
static int
3976
enable_msintelli(KBDC kbdc, struct psm_softc *sc)
4650
enable_msintelli(struct psm_softc *sc, enum probearg arg)
3977
{
4651
{
3978
	/*
4652
	KBDC kbdc = sc->kbdc;
3979
	 * Logitech MouseMan+ and FirstMouse+ will also respond to this
3980
	 * probe routine and act like IntelliMouse.
3981
	 */
3982
3983
	static u_char rate[] = { 200, 100, 80, };
4653
	static u_char rate[] = { 200, 100, 80, };
3984
	int id;
4654
	int id;
3985
	int i;
4655
	int i;
Lines 3993-3999 Link Here
3993
	if (id != PSM_INTELLI_ID)
4663
	if (id != PSM_INTELLI_ID)
3994
		return (FALSE);
4664
		return (FALSE);
3995
4665
3996
	if (sc != NULL) {
4666
	if (arg == PROBE) {
3997
		sc->hw.buttons = 3;
4667
		sc->hw.buttons = 3;
3998
		sc->hw.hwid = id;
4668
		sc->hw.hwid = id;
3999
	}
4669
	}
Lines 4001-4015 Link Here
4001
	return (TRUE);
4671
	return (TRUE);
4002
}
4672
}
4003
4673
4004
/* A4 Tech 4D Mouse */
4674
/*
4675
 * A4 Tech 4D Mouse
4676
 * Newer wheel mice from A4 Tech may use the 4D+ protocol.
4677
 */
4005
static int
4678
static int
4006
enable_4dmouse(KBDC kbdc, struct psm_softc *sc)
4679
enable_4dmouse(struct psm_softc *sc, enum probearg arg)
4007
{
4680
{
4008
	/*
4009
	 * Newer wheel mice from A4 Tech may use the 4D+ protocol.
4010
	 */
4011
4012
	static u_char rate[] = { 200, 100, 80, 60, 40, 20 };
4681
	static u_char rate[] = { 200, 100, 80, 60, 40, 20 };
4682
	KBDC kbdc = sc->kbdc;
4013
	int id;
4683
	int id;
4014
	int i;
4684
	int i;
4015
4685
Lines 4025-4031 Link Here
4025
	if (id != PSM_4DMOUSE_ID)
4695
	if (id != PSM_4DMOUSE_ID)
4026
		return (FALSE);
4696
		return (FALSE);
4027
4697
4028
	if (sc != NULL) {
4698
	if (arg == PROBE) {
4029
		sc->hw.buttons = 3;	/* XXX some 4D mice have 4? */
4699
		sc->hw.buttons = 3;	/* XXX some 4D mice have 4? */
4030
		sc->hw.hwid = id;
4700
		sc->hw.hwid = id;
4031
	}
4701
	}
Lines 4033-4046 Link Here
4033
	return (TRUE);
4703
	return (TRUE);
4034
}
4704
}
4035
4705
4036
/* A4 Tech 4D+ Mouse */
4706
/*
4707
 * A4 Tech 4D+ Mouse
4708
 * Newer wheel mice from A4 Tech seem to use this protocol.
4709
 * Older models are recognized as either 4D Mouse or IntelliMouse.
4710
 */
4037
static int
4711
static int
4038
enable_4dplus(KBDC kbdc, struct psm_softc *sc)
4712
enable_4dplus(struct psm_softc *sc, enum probearg arg)
4039
{
4713
{
4040
	/*
4714
	KBDC kbdc = sc->kbdc;
4041
	 * Newer wheel mice from A4 Tech seem to use this protocol.
4042
	 * Older models are recognized as either 4D Mouse or IntelliMouse.
4043
	 */
4044
	int id;
4715
	int id;
4045
4716
4046
	/*
4717
	/*
Lines 4063-4069 Link Here
4063
		return (FALSE);
4734
		return (FALSE);
4064
	}
4735
	}
4065
4736
4066
	if (sc != NULL) {
4737
	if (arg == PROBE) {
4067
		sc->hw.buttons = (id == PSM_4DPLUS_ID) ? 4 : 3;
4738
		sc->hw.buttons = (id == PSM_4DPLUS_ID) ? 4 : 3;
4068
		sc->hw.hwid = id;
4739
		sc->hw.hwid = id;
4069
	}
4740
	}
Lines 4075-4084 Link Here
4075
static int
4746
static int
4076
synaptics_sysctl(SYSCTL_HANDLER_ARGS)
4747
synaptics_sysctl(SYSCTL_HANDLER_ARGS)
4077
{
4748
{
4749
	struct psm_softc *sc;
4078
	int error, arg;
4750
	int error, arg;
4079
4751
4752
	if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 ||
4753
	    oidp->oid_arg2 > SYNAPTICS_SYSCTL_SOFTBUTTON_NOMOVE)
4754
		return (EINVAL);
4755
4756
	sc = oidp->oid_arg1;
4757
4080
	/* Read the current value. */
4758
	/* Read the current value. */
4081
	arg = *(int *)oidp->oid_arg1;
4759
	arg = *(int *)((char *)sc + oidp->oid_arg2);
4082
	error = sysctl_handle_int(oidp, &arg, 0, req);
4760
	error = sysctl_handle_int(oidp, &arg, 0, req);
4083
4761
4084
	/* Sanity check. */
4762
	/* Sanity check. */
Lines 4100-4113 Link Here
4100
			return (EINVAL);
4778
			return (EINVAL);
4101
		break;
4779
		break;
4102
	case SYNAPTICS_SYSCTL_MARGIN_TOP:
4780
	case SYNAPTICS_SYSCTL_MARGIN_TOP:
4781
	case SYNAPTICS_SYSCTL_MARGIN_BOTTOM:
4782
	case SYNAPTICS_SYSCTL_NA_TOP:
4783
	case SYNAPTICS_SYSCTL_NA_BOTTOM:
4784
		if (arg < 0 || arg > sc->synhw.maximumYCoord)
4785
			return (EINVAL);
4786
		break;
4103
	case SYNAPTICS_SYSCTL_MARGIN_RIGHT:
4787
	case SYNAPTICS_SYSCTL_MARGIN_RIGHT:
4104
	case SYNAPTICS_SYSCTL_MARGIN_BOTTOM:
4105
	case SYNAPTICS_SYSCTL_MARGIN_LEFT:
4788
	case SYNAPTICS_SYSCTL_MARGIN_LEFT:
4106
	case SYNAPTICS_SYSCTL_NA_TOP:
4107
	case SYNAPTICS_SYSCTL_NA_RIGHT:
4789
	case SYNAPTICS_SYSCTL_NA_RIGHT:
4108
	case SYNAPTICS_SYSCTL_NA_BOTTOM:
4109
	case SYNAPTICS_SYSCTL_NA_LEFT:
4790
	case SYNAPTICS_SYSCTL_NA_LEFT:
4110
		if (arg < 0 || arg > 6143)
4791
	case SYNAPTICS_SYSCTL_SOFTBUTTON2_X:
4792
	case SYNAPTICS_SYSCTL_SOFTBUTTON3_X:
4793
		if (arg < 0 || arg > sc->synhw.maximumXCoord)
4111
			return (EINVAL);
4794
			return (EINVAL);
4112
		break;
4795
		break;
4113
	case SYNAPTICS_SYSCTL_WINDOW_MIN:
4796
	case SYNAPTICS_SYSCTL_WINDOW_MIN:
Lines 4137-4162 Link Here
4137
			return (EINVAL);
4820
			return (EINVAL);
4138
		break;
4821
		break;
4139
	case SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA:
4822
	case SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA:
4823
		if (arg < -sc->synhw.maximumXCoord ||
4824
		    arg > sc->synhw.maximumXCoord)
4825
			return (EINVAL);
4826
		break;
4140
	case SYNAPTICS_SYSCTL_VSCROLL_VER_AREA:
4827
	case SYNAPTICS_SYSCTL_VSCROLL_VER_AREA:
4141
		if (arg < -6143 || arg > 6143)
4828
	case SYNAPTICS_SYSCTL_SOFTBUTTONS_Y:
4829
		if (arg < -sc->synhw.maximumYCoord ||
4830
		    arg > sc->synhw.maximumYCoord)
4142
			return (EINVAL);
4831
			return (EINVAL);
4143
		break;
4832
		break;
4144
        case SYNAPTICS_SYSCTL_TOUCHPAD_OFF:
4833
        case SYNAPTICS_SYSCTL_TOUCHPAD_OFF:
4834
	case SYNAPTICS_SYSCTL_SOFTBUTTON_NOMOVE:
4145
		if (arg < 0 || arg > 1)
4835
		if (arg < 0 || arg > 1)
4146
			return (EINVAL);
4836
			return (EINVAL);
4147
		break;
4837
		break;
4838
	case SYNAPTICS_SYSCTL_SOFTBUTTONS:
4839
		/* Softbuttons is clickpad only feature */
4840
		if (!sc->synhw.capClickPad && arg != 0)
4841
			return (EINVAL);
4842
		/* Set predefined sizes for softbuttons */
4843
		switch (arg) {
4844
		case 3:
4845
			sc->syninfo.softbutton3_x =
4846
			    sc->synhw.maximumXCoord * 2 / 3;
4847
			sc->syninfo.softbutton2_x =
4848
			    sc->synhw.maximumXCoord / 3;
4849
			sc->syninfo.softbuttons_y =
4850
			    sc->synhw.maximumYCoord / 4;
4851
			break;
4852
		case 2:
4853
			sc->syninfo.softbutton3_x =
4854
			    sc->synhw.maximumXCoord / 2;
4855
			sc->syninfo.softbutton2_x = 0;
4856
			sc->syninfo.softbuttons_y =
4857
			    sc->synhw.maximumYCoord / 4;
4858
			break;
4859
		case 1:
4860
		case 0:
4861
			sc->syninfo.softbutton3_x = 0;
4862
			sc->syninfo.softbutton2_x = 0;
4863
			sc->syninfo.softbuttons_y = 0;
4864
			break;
4865
		default:
4866
			return (EINVAL);
4867
		}
4868
		break;
4148
	default:
4869
	default:
4149
		return (EINVAL);
4870
		return (EINVAL);
4150
	}
4871
	}
4151
4872
4152
	/* Update. */
4873
	/* Update. */
4153
	*(int *)oidp->oid_arg1 = arg;
4874
	*(int *)((char *)sc + oidp->oid_arg2) = arg;
4154
4875
4155
	return (error);
4876
	return (error);
4156
}
4877
}
4157
4878
4158
static void
4879
static void
4159
synaptics_sysctl_create_tree(struct psm_softc *sc)
4880
synaptics_sysctl_create_tree(struct psm_softc *sc, const char *name,
4881
    const char *descr)
4160
{
4882
{
4161
4883
4162
	if (sc->syninfo.sysctl_tree != NULL)
4884
	if (sc->syninfo.sysctl_tree != NULL)
Lines 4165-4172 Link Here
4165
	/* Attach extra synaptics sysctl nodes under hw.psm.synaptics */
4887
	/* Attach extra synaptics sysctl nodes under hw.psm.synaptics */
4166
	sysctl_ctx_init(&sc->syninfo.sysctl_ctx);
4888
	sysctl_ctx_init(&sc->syninfo.sysctl_ctx);
4167
	sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx,
4889
	sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx,
4168
	    SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, "synaptics", CTLFLAG_RD,
4890
	    SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, name, CTLFLAG_RD,
4169
	    0, "Synaptics TouchPad");
4891
	    0, descr);
4170
4892
4171
	/* hw.psm.synaptics.directional_scrolls. */
4893
	/* hw.psm.synaptics.directional_scrolls. */
4172
	sc->syninfo.directional_scrolls = 0;
4894
	sc->syninfo.directional_scrolls = 0;
Lines 4182-4188 Link Here
4182
	 * physical area reserved for scrolling or when
4904
	 * physical area reserved for scrolling or when
4183
	 * there's no multi finger support.
4905
	 * there's no multi finger support.
4184
	 */
4906
	 */
4185
	if (sc->synhw.verticalScroll || sc->synhw.capMultiFinger == 0)
4907
	if (sc->synhw.verticalScroll || (sc->synhw.capMultiFinger == 0 &&
4908
					 sc->synhw.capAdvancedGestures == 0))
4186
		sc->syninfo.two_finger_scroll = 0;
4909
		sc->syninfo.two_finger_scroll = 0;
4187
	else
4910
	else
4188
		sc->syninfo.two_finger_scroll = 1;
4911
		sc->syninfo.two_finger_scroll = 1;
Lines 4198-4204 Link Here
4198
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4921
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4199
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4922
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4200
	    "min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4923
	    "min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4201
	    &sc->syninfo.min_pressure, SYNAPTICS_SYSCTL_MIN_PRESSURE,
4924
	    sc, SYNAPTICS_SYSCTL_MIN_PRESSURE,
4202
	    synaptics_sysctl, "I",
4925
	    synaptics_sysctl, "I",
4203
	    "Minimum pressure required to start an action");
4926
	    "Minimum pressure required to start an action");
4204
4927
Lines 4207-4213 Link Here
4207
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4930
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4208
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4931
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4209
	    "max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4932
	    "max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4210
	    &sc->syninfo.max_pressure, SYNAPTICS_SYSCTL_MAX_PRESSURE,
4933
	    sc, SYNAPTICS_SYSCTL_MAX_PRESSURE,
4211
	    synaptics_sysctl, "I",
4934
	    synaptics_sysctl, "I",
4212
	    "Maximum pressure to detect palm");
4935
	    "Maximum pressure to detect palm");
4213
4936
Lines 4216-4222 Link Here
4216
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4939
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4217
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4940
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4218
	    "max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4941
	    "max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4219
	    &sc->syninfo.max_width, SYNAPTICS_SYSCTL_MAX_WIDTH,
4942
	    sc, SYNAPTICS_SYSCTL_MAX_WIDTH,
4220
	    synaptics_sysctl, "I",
4943
	    synaptics_sysctl, "I",
4221
	    "Maximum finger width to detect palm");
4944
	    "Maximum finger width to detect palm");
4222
4945
Lines 4225-4231 Link Here
4225
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4948
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4226
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4949
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4227
	    "margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4950
	    "margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4228
	    &sc->syninfo.margin_top, SYNAPTICS_SYSCTL_MARGIN_TOP,
4951
	    sc, SYNAPTICS_SYSCTL_MARGIN_TOP,
4229
	    synaptics_sysctl, "I",
4952
	    synaptics_sysctl, "I",
4230
	    "Top margin");
4953
	    "Top margin");
4231
4954
Lines 4234-4240 Link Here
4234
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4957
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4235
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4958
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4236
	    "margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4959
	    "margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4237
	    &sc->syninfo.margin_right, SYNAPTICS_SYSCTL_MARGIN_RIGHT,
4960
	    sc, SYNAPTICS_SYSCTL_MARGIN_RIGHT,
4238
	    synaptics_sysctl, "I",
4961
	    synaptics_sysctl, "I",
4239
	    "Right margin");
4962
	    "Right margin");
4240
4963
Lines 4243-4249 Link Here
4243
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4966
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4244
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4967
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4245
	    "margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4968
	    "margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4246
	    &sc->syninfo.margin_bottom, SYNAPTICS_SYSCTL_MARGIN_BOTTOM,
4969
	    sc, SYNAPTICS_SYSCTL_MARGIN_BOTTOM,
4247
	    synaptics_sysctl, "I",
4970
	    synaptics_sysctl, "I",
4248
	    "Bottom margin");
4971
	    "Bottom margin");
4249
4972
Lines 4252-4258 Link Here
4252
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4975
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4253
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4976
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4254
	    "margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4977
	    "margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4255
	    &sc->syninfo.margin_left, SYNAPTICS_SYSCTL_MARGIN_LEFT,
4978
	    sc, SYNAPTICS_SYSCTL_MARGIN_LEFT,
4256
	    synaptics_sysctl, "I",
4979
	    synaptics_sysctl, "I",
4257
	    "Left margin");
4980
	    "Left margin");
4258
4981
Lines 4261-4267 Link Here
4261
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4984
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4262
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4985
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4263
	    "na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4986
	    "na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4264
	    &sc->syninfo.na_top, SYNAPTICS_SYSCTL_NA_TOP,
4987
	    sc, SYNAPTICS_SYSCTL_NA_TOP,
4265
	    synaptics_sysctl, "I",
4988
	    synaptics_sysctl, "I",
4266
	    "Top noisy area, where weight_previous_na is used instead "
4989
	    "Top noisy area, where weight_previous_na is used instead "
4267
	    "of weight_previous");
4990
	    "of weight_previous");
Lines 4271-4277 Link Here
4271
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4994
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4272
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4995
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4273
	    "na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4996
	    "na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4274
	    &sc->syninfo.na_right, SYNAPTICS_SYSCTL_NA_RIGHT,
4997
	    sc, SYNAPTICS_SYSCTL_NA_RIGHT,
4275
	    synaptics_sysctl, "I",
4998
	    synaptics_sysctl, "I",
4276
	    "Right noisy area, where weight_previous_na is used instead "
4999
	    "Right noisy area, where weight_previous_na is used instead "
4277
	    "of weight_previous");
5000
	    "of weight_previous");
Lines 4281-4287 Link Here
4281
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5004
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4282
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5005
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4283
	    "na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5006
	    "na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4284
	    &sc->syninfo.na_bottom, SYNAPTICS_SYSCTL_NA_BOTTOM,
5007
	    sc, SYNAPTICS_SYSCTL_NA_BOTTOM,
4285
	    synaptics_sysctl, "I",
5008
	    synaptics_sysctl, "I",
4286
	    "Bottom noisy area, where weight_previous_na is used instead "
5009
	    "Bottom noisy area, where weight_previous_na is used instead "
4287
	    "of weight_previous");
5010
	    "of weight_previous");
Lines 4291-4297 Link Here
4291
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5014
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4292
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5015
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4293
	    "na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5016
	    "na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4294
	    &sc->syninfo.na_left, SYNAPTICS_SYSCTL_NA_LEFT,
5017
	    sc, SYNAPTICS_SYSCTL_NA_LEFT,
4295
	    synaptics_sysctl, "I",
5018
	    synaptics_sysctl, "I",
4296
	    "Left noisy area, where weight_previous_na is used instead "
5019
	    "Left noisy area, where weight_previous_na is used instead "
4297
	    "of weight_previous");
5020
	    "of weight_previous");
Lines 4301-4307 Link Here
4301
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5024
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4302
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5025
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4303
	    "window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5026
	    "window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4304
	    &sc->syninfo.window_min, SYNAPTICS_SYSCTL_WINDOW_MIN,
5027
	    sc, SYNAPTICS_SYSCTL_WINDOW_MIN,
4305
	    synaptics_sysctl, "I",
5028
	    synaptics_sysctl, "I",
4306
	    "Minimum window size to start an action");
5029
	    "Minimum window size to start an action");
4307
5030
Lines 4310-4316 Link Here
4310
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5033
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4311
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5034
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4312
	    "window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5035
	    "window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4313
	    &sc->syninfo.window_max, SYNAPTICS_SYSCTL_WINDOW_MAX,
5036
	    sc, SYNAPTICS_SYSCTL_WINDOW_MAX,
4314
	    synaptics_sysctl, "I",
5037
	    synaptics_sysctl, "I",
4315
	    "Maximum window size");
5038
	    "Maximum window size");
4316
5039
Lines 4319-4325 Link Here
4319
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5042
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4320
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5043
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4321
	    "multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5044
	    "multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4322
	    &sc->syninfo.multiplicator, SYNAPTICS_SYSCTL_MULTIPLICATOR,
5045
	    sc, SYNAPTICS_SYSCTL_MULTIPLICATOR,
4323
	    synaptics_sysctl, "I",
5046
	    synaptics_sysctl, "I",
4324
	    "Multiplicator to increase precision in averages and divisions");
5047
	    "Multiplicator to increase precision in averages and divisions");
4325
5048
Lines 4328-4334 Link Here
4328
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5051
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4329
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5052
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4330
	    "weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5053
	    "weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4331
	    &sc->syninfo.weight_current, SYNAPTICS_SYSCTL_WEIGHT_CURRENT,
5054
	    sc, SYNAPTICS_SYSCTL_WEIGHT_CURRENT,
4332
	    synaptics_sysctl, "I",
5055
	    synaptics_sysctl, "I",
4333
	    "Weight of the current movement in the new average");
5056
	    "Weight of the current movement in the new average");
4334
5057
Lines 4337-4343 Link Here
4337
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5060
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4338
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5061
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4339
	    "weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5062
	    "weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4340
	    &sc->syninfo.weight_previous, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS,
5063
	    sc, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS,
4341
	    synaptics_sysctl, "I",
5064
	    synaptics_sysctl, "I",
4342
	    "Weight of the previous average");
5065
	    "Weight of the previous average");
4343
5066
Lines 4346-4353 Link Here
4346
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5069
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4347
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5070
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4348
	    "weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5071
	    "weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4349
	    &sc->syninfo.weight_previous_na,
5072
	    sc, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA,
4350
	    SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA,
4351
	    synaptics_sysctl, "I",
5073
	    synaptics_sysctl, "I",
4352
	    "Weight of the previous average (inside the noisy area)");
5074
	    "Weight of the previous average (inside the noisy area)");
4353
5075
Lines 4356-4363 Link Here
4356
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5078
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4357
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5079
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4358
	    "weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5080
	    "weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4359
	    &sc->syninfo.weight_len_squared,
5081
	    sc, SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED,
4360
	    SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED,
4361
	    synaptics_sysctl, "I",
5082
	    synaptics_sysctl, "I",
4362
	    "Length (squared) of segments where weight_previous "
5083
	    "Length (squared) of segments where weight_previous "
4363
	    "starts to decrease");
5084
	    "starts to decrease");
Lines 4367-4373 Link Here
4367
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5088
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4368
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5089
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4369
	    "div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5090
	    "div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4370
	    &sc->syninfo.div_min, SYNAPTICS_SYSCTL_DIV_MIN,
5091
	    sc, SYNAPTICS_SYSCTL_DIV_MIN,
4371
	    synaptics_sysctl, "I",
5092
	    synaptics_sysctl, "I",
4372
	    "Divisor for fast movements");
5093
	    "Divisor for fast movements");
4373
5094
Lines 4376-4382 Link Here
4376
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5097
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4377
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5098
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4378
	    "div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5099
	    "div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4379
	    &sc->syninfo.div_max, SYNAPTICS_SYSCTL_DIV_MAX,
5100
	    sc, SYNAPTICS_SYSCTL_DIV_MAX,
4380
	    synaptics_sysctl, "I",
5101
	    synaptics_sysctl, "I",
4381
	    "Divisor for slow movements");
5102
	    "Divisor for slow movements");
4382
5103
Lines 4385-4391 Link Here
4385
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5106
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4386
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5107
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4387
	    "div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5108
	    "div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4388
	    &sc->syninfo.div_max_na, SYNAPTICS_SYSCTL_DIV_MAX_NA,
5109
	    sc, SYNAPTICS_SYSCTL_DIV_MAX_NA,
4389
	    synaptics_sysctl, "I",
5110
	    synaptics_sysctl, "I",
4390
	    "Divisor with slow movements (inside the noisy area)");
5111
	    "Divisor with slow movements (inside the noisy area)");
4391
5112
Lines 4394-4400 Link Here
4394
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5115
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4395
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5116
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4396
	    "div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5117
	    "div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4397
	    &sc->syninfo.div_len, SYNAPTICS_SYSCTL_DIV_LEN,
5118
	    sc, SYNAPTICS_SYSCTL_DIV_LEN,
4398
	    synaptics_sysctl, "I",
5119
	    synaptics_sysctl, "I",
4399
	    "Length of segments where div_max starts to decrease");
5120
	    "Length of segments where div_max starts to decrease");
4400
5121
Lines 4403-4409 Link Here
4403
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5124
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4404
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5125
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4405
	    "tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5126
	    "tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4406
	    &sc->syninfo.tap_max_delta, SYNAPTICS_SYSCTL_TAP_MAX_DELTA,
5127
	    sc, SYNAPTICS_SYSCTL_TAP_MAX_DELTA,
4407
	    synaptics_sysctl, "I",
5128
	    synaptics_sysctl, "I",
4408
	    "Length of segments above which a tap is ignored");
5129
	    "Length of segments above which a tap is ignored");
4409
5130
Lines 4412-4428 Link Here
4412
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5133
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4413
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5134
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4414
	    "tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5135
	    "tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4415
	    &sc->syninfo.tap_min_queue, SYNAPTICS_SYSCTL_TAP_MIN_QUEUE,
5136
	    sc, SYNAPTICS_SYSCTL_TAP_MIN_QUEUE,
4416
	    synaptics_sysctl, "I",
5137
	    synaptics_sysctl, "I",
4417
	    "Number of packets required to consider a tap");
5138
	    "Number of packets required to consider a tap");
4418
5139
4419
	/* hw.psm.synaptics.taphold_timeout. */
5140
	/* hw.psm.synaptics.taphold_timeout. */
4420
	sc->synaction.in_taphold = 0;
5141
	sc->synaction[0].in_taphold = 0;
4421
	sc->syninfo.taphold_timeout = tap_timeout;
5142
	sc->syninfo.taphold_timeout = tap_timeout;
4422
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5143
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4423
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5144
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4424
	    "taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5145
	    "taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4425
	    &sc->syninfo.taphold_timeout, SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT,
5146
	    sc, SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT,
4426
	    synaptics_sysctl, "I",
5147
	    synaptics_sysctl, "I",
4427
	    "Maximum elapsed time between two taps to consider a tap-hold "
5148
	    "Maximum elapsed time between two taps to consider a tap-hold "
4428
	    "action");
5149
	    "action");
Lines 4432-4438 Link Here
4432
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5153
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4433
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5154
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4434
	    "vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5155
	    "vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4435
	    &sc->syninfo.vscroll_hor_area, SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA,
5156
	    sc, SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA,
4436
	    synaptics_sysctl, "I",
5157
	    synaptics_sysctl, "I",
4437
	    "Area reserved for horizontal virtual scrolling");
5158
	    "Area reserved for horizontal virtual scrolling");
4438
5159
Lines 4441-4447 Link Here
4441
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5162
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4442
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5163
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4443
	    "vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5164
	    "vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4444
	    &sc->syninfo.vscroll_ver_area, SYNAPTICS_SYSCTL_VSCROLL_VER_AREA,
5165
	    sc, SYNAPTICS_SYSCTL_VSCROLL_VER_AREA,
4445
	    synaptics_sysctl, "I",
5166
	    synaptics_sysctl, "I",
4446
	    "Area reserved for vertical virtual scrolling");
5167
	    "Area reserved for vertical virtual scrolling");
4447
5168
Lines 4450-4457 Link Here
4450
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5171
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4451
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5172
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4452
	    "vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5173
	    "vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4453
	    &sc->syninfo.vscroll_min_delta,
5174
	    sc, SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA,
4454
	    SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA,
4455
	    synaptics_sysctl, "I",
5175
	    synaptics_sysctl, "I",
4456
	    "Minimum movement to consider virtual scrolling");
5176
	    "Minimum movement to consider virtual scrolling");
4457
5177
Lines 4460-4466 Link Here
4460
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5180
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4461
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5181
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4462
	    "vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5182
	    "vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4463
	    &sc->syninfo.vscroll_div_min, SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN,
5183
	    sc, SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN,
4464
	    synaptics_sysctl, "I",
5184
	    synaptics_sysctl, "I",
4465
	    "Divisor for fast scrolling");
5185
	    "Divisor for fast scrolling");
4466
5186
Lines 4469-4475 Link Here
4469
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5189
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4470
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5190
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4471
	    "vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5191
	    "vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4472
	    &sc->syninfo.vscroll_div_max, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX,
5192
	    sc, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX,
4473
	    synaptics_sysctl, "I",
5193
	    synaptics_sysctl, "I",
4474
	    "Divisor for slow scrolling");
5194
	    "Divisor for slow scrolling");
4475
5195
Lines 4478-4491 Link Here
4478
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5198
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4479
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5199
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4480
	    "touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5200
	    "touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4481
	    &sc->syninfo.touchpad_off, SYNAPTICS_SYSCTL_TOUCHPAD_OFF,
5201
	    sc, SYNAPTICS_SYSCTL_TOUCHPAD_OFF,
4482
	    synaptics_sysctl, "I",
5202
	    synaptics_sysctl, "I",
4483
	    "Turn off touchpad");
5203
	    "Turn off touchpad");
5204
5205
	sc->syninfo.softbuttons = 0;
5206
	sc->syninfo.softbuttons_y = 0;
5207
	sc->syninfo.softbutton2_x = 0;
5208
	sc->syninfo.softbutton3_x = 0;
5209
	sc->syninfo.softbutton_nomove = 0;
5210
5211
	/* skip softbuttons sysctl on not clickpads */
5212
	if (!sc->synhw.capClickPad)
5213
		return;
5214
5215
	/* hw.psm.synaptics.softbuttons */
5216
	sc->syninfo.softbuttons = 3;
5217
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5218
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5219
	    "softbuttons", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5220
	    sc, SYNAPTICS_SYSCTL_SOFTBUTTONS,
5221
	    synaptics_sysctl, "I",
5222
	    "Enables top or bottom edges to be a softbuttons on clickpads");
5223
5224
	/* hw.psm.synaptics.softbuttons_y */
5225
	sc->syninfo.softbuttons_y = sc->synhw.maximumYCoord / 4;
5226
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5227
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5228
	    "softbuttons_y", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5229
	    sc, SYNAPTICS_SYSCTL_SOFTBUTTONS_Y,
5230
	    synaptics_sysctl, "I",
5231
	    "Vertical size of softbuttons area");
5232
5233
	/* hw.psm.synaptics.softbutton2_x */
5234
	sc->syninfo.softbutton2_x = sc->synhw.maximumXCoord / 3;
5235
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5236
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5237
	    "softbutton2_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5238
	    sc, SYNAPTICS_SYSCTL_SOFTBUTTON2_X,
5239
	    synaptics_sysctl, "I",
5240
	    "Horisontal position of 2-nd softbutton left edge (0-disable)");
5241
5242
	/* hw.psm.synaptics.softbutton3_x */
5243
	sc->syninfo.softbutton3_x = sc->synhw.maximumXCoord * 2 / 3;
5244
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5245
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5246
	    "softbutton3_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5247
	    sc, SYNAPTICS_SYSCTL_SOFTBUTTON3_X,
5248
	    synaptics_sysctl, "I",
5249
	    "Horisontal position of 3-rd softbutton left edge (0-disable)");
5250
5251
	/* hw.psm.synaptics.softbutton_nomove */
5252
	sc->syninfo.softbutton_nomove = 0;
5253
	SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5254
	    SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5255
	    "softbutton_nomove", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
5256
	    sc, SYNAPTICS_SYSCTL_SOFTBUTTON_NOMOVE,
5257
	    synaptics_sysctl, "I",
5258
	    "Disable movement on the bottom edge area so it works as buttons");
4484
}
5259
}
4485
5260
4486
static int
5261
static int
4487
enable_synaptics(KBDC kbdc, struct psm_softc *sc)
5262
synaptics_preferred_mode(struct psm_softc *sc) {
5263
	int mode_byte;
5264
5265
	mode_byte = 0xc0;
5266
5267
	/* request wmode where available */
5268
	if (sc->synhw.capExtended)
5269
		mode_byte |= 1;
5270
5271
	/*
5272
	 * Disable gesture processing when native packets are requested. This
5273
	 * enables sending of encapsulated "extended W mode" packets.
5274
	 */
5275
	if (sc->mode.level == PSM_LEVEL_NATIVE)
5276
		mode_byte |= (1 << 2);
5277
5278
	return mode_byte;
5279
}
5280
5281
static void
5282
synaptics_set_mode(struct psm_softc *sc, int mode_byte) {
5283
	mouse_ext_command(sc->kbdc, mode_byte);
5284
5285
	/* "Commit" the Set Mode Byte command sent above. */
5286
	set_mouse_sampling_rate(sc->kbdc, 20);
5287
5288
	/*
5289
	 * Enable advanced gestures mode if supported and we are not entering
5290
	 * passthrough mode.
5291
	 */
5292
	if (sc->synhw.capAdvancedGestures && !(mode_byte & (1 << 5))) {
5293
		mouse_ext_command(sc->kbdc, 3);
5294
		set_mouse_sampling_rate(sc->kbdc, 0xc8);
5295
	}
5296
}
5297
5298
static int
5299
enable_synaptics(struct psm_softc *sc, enum probearg arg)
4488
{
5300
{
5301
	KBDC kbdc = sc->kbdc;
4489
	synapticshw_t synhw;
5302
	synapticshw_t synhw;
4490
	int status[3];
5303
	int status[3];
4491
	int buttons;
5304
	int buttons;
Lines 4566-4579 Link Here
4566
	buttons = 0;
5379
	buttons = 0;
4567
	synhw.capExtended = (status[0] & 0x80) != 0;
5380
	synhw.capExtended = (status[0] & 0x80) != 0;
4568
	if (synhw.capExtended) {
5381
	if (synhw.capExtended) {
4569
		synhw.nExtendedQueries = (status[0] & 0x70) != 0;
5382
		synhw.nExtendedQueries = (status[0] & 0x70) >> 4;
4570
		synhw.capMiddle        = (status[0] & 0x04) != 0;
5383
		synhw.capMiddle        = (status[0] & 0x04) != 0;
4571
		synhw.capPassthrough   = (status[2] & 0x80) != 0;
5384
		synhw.capPassthrough   = (status[2] & 0x80) != 0;
5385
		synhw.capLowPower      = (status[2] & 0x40) != 0;
5386
		synhw.capMultiFingerReport =
5387
					 (status[2] & 0x20) != 0;
4572
		synhw.capSleep         = (status[2] & 0x10) != 0;
5388
		synhw.capSleep         = (status[2] & 0x10) != 0;
4573
		synhw.capFourButtons   = (status[2] & 0x08) != 0;
5389
		synhw.capFourButtons   = (status[2] & 0x08) != 0;
5390
		synhw.capBallistics    = (status[2] & 0x04) != 0;
4574
		synhw.capMultiFinger   = (status[2] & 0x02) != 0;
5391
		synhw.capMultiFinger   = (status[2] & 0x02) != 0;
4575
		synhw.capPalmDetect    = (status[2] & 0x01) != 0;
5392
		synhw.capPalmDetect    = (status[2] & 0x01) != 0;
4576
5393
5394
		if (!set_mouse_scaling(kbdc, 1))
5395
			return (FALSE);
5396
		if (mouse_ext_command(kbdc, 0x08) == 0)
5397
			return (FALSE);
5398
		if (get_mouse_status(kbdc, status, 0, 3) != 3)
5399
			return (FALSE);
5400
5401
		synhw.infoXupmm = status[0];
5402
		synhw.infoYupmm = status[2];
5403
4577
		if (verbose >= 2) {
5404
		if (verbose >= 2) {
4578
			printf("  Extended capabilities:\n");
5405
			printf("  Extended capabilities:\n");
4579
			printf("   capExtended: %d\n", synhw.capExtended);
5406
			printf("   capExtended: %d\n", synhw.capExtended);
Lines 4581-4590 Link Here
4581
			printf("   nExtendedQueries: %d\n",
5408
			printf("   nExtendedQueries: %d\n",
4582
			    synhw.nExtendedQueries);
5409
			    synhw.nExtendedQueries);
4583
			printf("   capPassthrough: %d\n", synhw.capPassthrough);
5410
			printf("   capPassthrough: %d\n", synhw.capPassthrough);
5411
			printf("   capLowPower: %d\n", synhw.capLowPower);
5412
			printf("   capMultiFingerReport: %d\n",
5413
			    synhw.capMultiFingerReport);
4584
			printf("   capSleep: %d\n", synhw.capSleep);
5414
			printf("   capSleep: %d\n", synhw.capSleep);
4585
			printf("   capFourButtons: %d\n", synhw.capFourButtons);
5415
			printf("   capFourButtons: %d\n", synhw.capFourButtons);
5416
			printf("   capBallistics: %d\n", synhw.capBallistics);
4586
			printf("   capMultiFinger: %d\n", synhw.capMultiFinger);
5417
			printf("   capMultiFinger: %d\n", synhw.capMultiFinger);
4587
			printf("   capPalmDetect: %d\n", synhw.capPalmDetect);
5418
			printf("   capPalmDetect: %d\n", synhw.capPalmDetect);
5419
			printf("   infoXupmm: %d\n", synhw.infoXupmm);
5420
			printf("   infoYupmm: %d\n", synhw.infoYupmm);
4588
		}
5421
		}
4589
5422
4590
		/*
5423
		/*
Lines 4592-4598 Link Here
4592
		 * supports this number of extended queries. We can load
5425
		 * supports this number of extended queries. We can load
4593
		 * more information about buttons using query 0x09.
5426
		 * more information about buttons using query 0x09.
4594
		 */
5427
		 */
4595
		if (synhw.capExtended && synhw.nExtendedQueries) {
5428
		if (synhw.nExtendedQueries >= 1) {
5429
			if (!set_mouse_scaling(kbdc, 1))
5430
				return (FALSE);
4596
			if (mouse_ext_command(kbdc, 0x09) == 0)
5431
			if (mouse_ext_command(kbdc, 0x09) == 0)
4597
				return (FALSE);
5432
				return (FALSE);
4598
			if (get_mouse_status(kbdc, status, 0, 3) != 3)
5433
			if (get_mouse_status(kbdc, status, 0, 3) != 3)
Lines 4601-4606 Link Here
4601
			synhw.horizontalScroll = (status[0] & 0x02) != 0;
5436
			synhw.horizontalScroll = (status[0] & 0x02) != 0;
4602
			synhw.verticalWheel    = (status[0] & 0x08) != 0;
5437
			synhw.verticalWheel    = (status[0] & 0x08) != 0;
4603
			synhw.nExtendedButtons = (status[1] & 0xf0) >> 4;
5438
			synhw.nExtendedButtons = (status[1] & 0xf0) >> 4;
5439
			synhw.capEWmode        = (status[0] & 0x04) != 0;
4604
			if (verbose >= 2) {
5440
			if (verbose >= 2) {
4605
				printf("  Extended model ID:\n");
5441
				printf("  Extended model ID:\n");
4606
				printf("   verticalScroll: %d\n",
5442
				printf("   verticalScroll: %d\n",
Lines 4611-4616 Link Here
4611
				    synhw.verticalWheel);
5447
				    synhw.verticalWheel);
4612
				printf("   nExtendedButtons: %d\n",
5448
				printf("   nExtendedButtons: %d\n",
4613
				    synhw.nExtendedButtons);
5449
				    synhw.nExtendedButtons);
5450
				printf("   capEWmode: %d\n",
5451
				    synhw.capEWmode);
4614
			}
5452
			}
4615
			/*
5453
			/*
4616
			 * Add the number of extended buttons to the total
5454
			 * Add the number of extended buttons to the total
Lines 4624-4630 Link Here
4624
			 * add a fourth button to the total button count.
5462
			 * add a fourth button to the total button count.
4625
			 */
5463
			 */
4626
			buttons = synhw.capFourButtons ? 1 : 0;
5464
			buttons = synhw.capFourButtons ? 1 : 0;
5465
5466
		/* Read the continued capabilities bits. */
5467
		if (synhw.nExtendedQueries >= 4) {
5468
			if (!set_mouse_scaling(kbdc, 1))
5469
				return (FALSE);
5470
			if (mouse_ext_command(kbdc, 0x0c) == 0)
5471
				return (FALSE);
5472
			if (get_mouse_status(kbdc, status, 0, 3) != 3)
5473
				return (FALSE);
5474
5475
			synhw.capClickPad         = (status[1] & 0x01) << 1;
5476
			synhw.capClickPad        |= (status[0] & 0x10) != 0;
5477
			synhw.capDeluxeLEDs       = (status[1] & 0x02) != 0;
5478
			synhw.noAbsoluteFilter    = (status[1] & 0x04) != 0;
5479
			synhw.capReportsV         = (status[1] & 0x08) != 0;
5480
			synhw.capUniformClickPad  = (status[1] & 0x10) != 0;
5481
			synhw.capReportsMin       = (status[1] & 0x20) != 0;
5482
			synhw.capInterTouch       = (status[1] & 0x40) != 0;
5483
			synhw.capReportsMax       = (status[0] & 0x02) != 0;
5484
			synhw.capClearPad         = (status[0] & 0x04) != 0;
5485
			synhw.capAdvancedGestures = (status[0] & 0x08) != 0;
5486
			synhw.capCoveredPad       = (status[0] & 0x80) != 0;
5487
5488
			if (synhw.capReportsMax) {
5489
				if (!set_mouse_scaling(kbdc, 1))
5490
					return (FALSE);
5491
				if (mouse_ext_command(kbdc, 0x0d) == 0)
5492
					return (FALSE);
5493
				if (get_mouse_status(kbdc, status, 0, 3) != 3)
5494
					return (FALSE);
5495
5496
				synhw.maximumXCoord = (status[0] << 5) |
5497
						     ((status[1] & 0x0f) << 1);
5498
				synhw.maximumYCoord = (status[2] << 5) |
5499
						     ((status[1] & 0xf0) >> 3);
5500
			} else
5501
				synhw.maximumXCoord = synhw.maximumYCoord =
5502
				    6143;
5503
5504
			if (synhw.capReportsMin) {
5505
				if (!set_mouse_scaling(kbdc, 1))
5506
					return (FALSE);
5507
				if (mouse_ext_command(kbdc, 0x0f) == 0)
5508
					return (FALSE);
5509
				if (get_mouse_status(kbdc, status, 0, 3) != 3)
5510
					return (FALSE);
5511
5512
				synhw.minimumXCoord = (status[0] << 5) |
5513
						     ((status[1] & 0x0f) << 1);
5514
				synhw.minimumYCoord = (status[2] << 5) |
5515
						     ((status[1] & 0xf0) >> 3);
5516
			} else
5517
				synhw.minimumXCoord = synhw.minimumYCoord = 0;
5518
5519
			if (verbose >= 2) {
5520
				printf("  Continued capabilities:\n");
5521
				printf("   capClickPad: %d\n",
5522
				       synhw.capClickPad);
5523
				printf("   capDeluxeLEDs: %d\n",
5524
				       synhw.capDeluxeLEDs);
5525
				printf("   noAbsoluteFilter: %d\n",
5526
				       synhw.noAbsoluteFilter);
5527
				printf("   capReportsV: %d\n",
5528
				       synhw.capReportsV);
5529
				printf("   capUniformClickPad: %d\n",
5530
				       synhw.capUniformClickPad);
5531
				printf("   capReportsMin: %d\n",
5532
				       synhw.capReportsMin);
5533
				printf("   capInterTouch: %d\n",
5534
				       synhw.capInterTouch);
5535
				printf("   capReportsMax: %d\n",
5536
				       synhw.capReportsMax);
5537
				printf("   capClearPad: %d\n",
5538
				       synhw.capClearPad);
5539
				printf("   capAdvancedGestures: %d\n",
5540
				       synhw.capAdvancedGestures);
5541
				printf("   capCoveredPad: %d\n",
5542
				       synhw.capCoveredPad);
5543
				if (synhw.capReportsMax) {
5544
					printf("   maximumXCoord: %d\n",
5545
					       synhw.maximumXCoord);
5546
					printf("   maximumYCoord: %d\n",
5547
					       synhw.maximumYCoord);
5548
				}
5549
				if (synhw.capReportsMin) {
5550
					printf("   minimumXCoord: %d\n",
5551
					       synhw.minimumXCoord);
5552
					printf("   minimumYCoord: %d\n",
5553
					       synhw.minimumYCoord);
5554
				}
5555
			}
5556
			buttons += synhw.capClickPad;
5557
		}
4627
	}
5558
	}
5559
4628
	if (verbose >= 2) {
5560
	if (verbose >= 2) {
4629
		if (synhw.capExtended)
5561
		if (synhw.capExtended)
4630
			printf("  Additional Buttons: %d\n", buttons);
5562
			printf("  Additional Buttons: %d\n", buttons);
Lines 4632-4673 Link Here
4632
			printf("  No extended capabilities\n");
5564
			printf("  No extended capabilities\n");
4633
	}
5565
	}
4634
5566
4635
	/* Read the continued capabilities bits. */
4636
	if (mouse_ext_command(kbdc, 0xc) != 0 &&
4637
	    get_mouse_status(kbdc, status, 0, 3) == 3) {
4638
		synhw.capClickPad         = (status[1] & 0x01) << 1;
4639
		synhw.capClickPad        |= (status[0] & 0x10) != 0;
4640
		synhw.capDeluxeLEDs       = (status[1] & 0x02) != 0;
4641
		synhw.noAbsoluteFilter    = (status[1] & 0x04) != 0;
4642
		synhw.capReportsV         = (status[1] & 0x08) != 0;
4643
		synhw.capUniformClickPad  = (status[1] & 0x10) != 0;
4644
		synhw.capReportsMin       = (status[1] & 0x20) != 0;
4645
		synhw.capInterTouch       = (status[1] & 0x40) != 0;
4646
		synhw.capReportsMax       = (status[2] & 0x02) != 0;
4647
		synhw.capClearPad         = (status[2] & 0x04) != 0;
4648
		synhw.capAdvancedGestures = (status[2] & 0x08) != 0;
4649
		synhw.capCoveredPad       = (status[2] & 0x80) != 0;
4650
4651
		if (verbose >= 2) {
4652
			printf("  Continued capabilities:\n");
4653
			printf("   capClickPad: %d\n", synhw.capClickPad);
4654
			printf("   capDeluxeLEDs: %d\n", synhw.capDeluxeLEDs);
4655
			printf("   noAbsoluteFilter: %d\n",
4656
			    synhw.noAbsoluteFilter);
4657
			printf("   capReportsV: %d\n", synhw.capReportsV);
4658
			printf("   capUniformClickPad: %d\n",
4659
			    synhw.capUniformClickPad);
4660
			printf("   capReportsMin: %d\n", synhw.capReportsMin);
4661
			printf("   capInterTouch: %d\n", synhw.capInterTouch);
4662
			printf("   capReportsMax: %d\n", synhw.capReportsMax);
4663
			printf("   capClearPad: %d\n", synhw.capClearPad);
4664
			printf("   capAdvancedGestures: %d\n",
4665
			    synhw.capAdvancedGestures);
4666
			printf("   capCoveredPad: %d\n", synhw.capCoveredPad);
4667
		}
4668
		buttons += synhw.capClickPad;
4669
	}
4670
4671
	/*
5567
	/*
4672
	 * Add the default number of 3 buttons to the total
5568
	 * Add the default number of 3 buttons to the total
4673
	 * count of supported buttons reported above.
5569
	 * count of supported buttons reported above.
Lines 4690-4716 Link Here
4690
		return (FALSE);
5586
		return (FALSE);
4691
	}
5587
	}
4692
5588
4693
	if (sc != NULL)
5589
	if (arg == PROBE)
4694
		sc->synhw = synhw;
5590
		sc->synhw = synhw;
4695
	if (!synaptics_support)
5591
	if (!synaptics_support)
4696
		return (FALSE);
5592
		return (FALSE);
4697
5593
4698
	/* Set the mode byte; request wmode where available. */
5594
	synaptics_set_mode(sc, synaptics_preferred_mode(sc));
4699
	mouse_ext_command(kbdc, synhw.capExtended ? 0xc1 : 0xc0);
4700
5595
4701
	/* "Commit" the Set Mode Byte command sent above. */
5596
	if (trackpoint_support && synhw.capPassthrough) {
4702
	set_mouse_sampling_rate(kbdc, 20);
5597
		enable_trackpoint(sc, arg);
5598
	}
4703
5599
4704
	VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons));
5600
	VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons));
4705
5601
4706
	if (sc != NULL) {
5602
	if (arg == PROBE) {
4707
		if (trackpoint_support && synhw.capPassthrough) {
4708
			synaptics_passthrough_on(sc);
4709
			enable_trackpoint(kbdc, sc);
4710
			synaptics_passthrough_off(sc);
4711
		}
4712
		/* Create sysctl tree. */
5603
		/* Create sysctl tree. */
4713
		synaptics_sysctl_create_tree(sc);
5604
		synaptics_sysctl_create_tree(sc, "synaptics",
5605
		    "Synaptics TouchPad");
4714
		sc->hw.buttons = buttons;
5606
		sc->hw.buttons = buttons;
4715
	}
5607
	}
4716
5608
Lines 4720-4749 Link Here
4720
static void
5612
static void
4721
synaptics_passthrough_on(struct psm_softc *sc)
5613
synaptics_passthrough_on(struct psm_softc *sc)
4722
{
5614
{
4723
	int mode_byte;
5615
	VLOG(2, (LOG_NOTICE, "psm: setting pass-through mode.\n"));
4724
5616
	synaptics_set_mode(sc, synaptics_preferred_mode(sc) | (1 << 5));
4725
	mode_byte = 0xc1 | (1 << 5);
4726
	VLOG(2, (LOG_NOTICE, "psm: setting pass-through mode. %d\n",
4727
		mode_byte));
4728
	mouse_ext_command(sc->kbdc, mode_byte);
4729
4730
	/* "Commit" the Set Mode Byte command sent above. */
4731
	set_mouse_sampling_rate(sc->kbdc, 20);
4732
}
5617
}
4733
5618
4734
static void
5619
static void
4735
synaptics_passthrough_off(struct psm_softc *sc)
5620
synaptics_passthrough_off(struct psm_softc *sc)
4736
{
5621
{
4737
	int mode_byte;
4738
4739
	mode_byte = 0xc1;
4740
	VLOG(2, (LOG_NOTICE, "psm: turning pass-through mode off.\n"));
5622
	VLOG(2, (LOG_NOTICE, "psm: turning pass-through mode off.\n"));
4741
	set_mouse_scaling(sc->kbdc, 2);
5623
	set_mouse_scaling(sc->kbdc, 2);
4742
	set_mouse_scaling(sc->kbdc, 1);
5624
	set_mouse_scaling(sc->kbdc, 1);
4743
	mouse_ext_command(sc->kbdc, mode_byte);
5625
	synaptics_set_mode(sc, synaptics_preferred_mode(sc));
4744
4745
	/* "Commit" the Set Mode Byte command sent above. */
4746
	set_mouse_sampling_rate(sc->kbdc, 20);
4747
}
5626
}
4748
5627
4749
/* IBM/Lenovo TrackPoint */
5628
/* IBM/Lenovo TrackPoint */
Lines 4966-4990 Link Here
4966
}
5845
}
4967
5846
4968
static int
5847
static int
4969
enable_trackpoint(KBDC kbdc, struct psm_softc *sc)
5848
enable_trackpoint(struct psm_softc *sc, enum probearg arg)
4970
{
5849
{
5850
	KBDC kbdc = sc->kbdc;
4971
	int id;
5851
	int id;
4972
5852
5853
	/*
5854
	 * If called from enable_synaptics(), make sure that passthrough
5855
	 * mode is enabled so we can reach the trackpoint.
5856
	 * However, passthrough mode must be disabled before setting the
5857
	 * trackpoint parameters, as rackpoint_command() enables and disables
5858
	 * passthrough mode on its own.
5859
	 */
5860
	if (sc->synhw.capPassthrough)
5861
		synaptics_passthrough_on(sc);
5862
4973
	if (send_aux_command(kbdc, 0xe1) != PSM_ACK ||
5863
	if (send_aux_command(kbdc, 0xe1) != PSM_ACK ||
4974
	    read_aux_data(kbdc) != 0x01)
5864
	    read_aux_data(kbdc) != 0x01)
4975
		return (FALSE);
5865
		goto no_trackpoint;
4976
	id = read_aux_data(kbdc);
5866
	id = read_aux_data(kbdc);
4977
	if (id < 0x01)
5867
	if (id < 0x01)
4978
		return (FALSE);
5868
		goto no_trackpoint;
4979
	if (sc != NULL)
5869
	if (arg == PROBE)
4980
		sc->tphw = id;
5870
		sc->tphw = id;
4981
	if (!trackpoint_support)
5871
	if (!trackpoint_support)
4982
		return (FALSE);
5872
		goto no_trackpoint;
4983
5873
4984
	if (sc != NULL) {
5874
	if (sc->synhw.capPassthrough)
4985
		/* Create sysctl tree. */
5875
		synaptics_passthrough_off(sc);
5876
5877
	if (arg == PROBE) {
4986
		trackpoint_sysctl_create_tree(sc);
5878
		trackpoint_sysctl_create_tree(sc);
4987
4988
		/*
5879
		/*
4989
		 * Don't overwrite hwid and buttons when we are
5880
		 * Don't overwrite hwid and buttons when we are
4990
		 * a guest device.
5881
		 * a guest device.
Lines 4995-5007 Link Here
4995
		}
5886
		}
4996
	}
5887
	}
4997
5888
5889
	set_trackpoint_parameters(sc);
5890
4998
	return (TRUE);
5891
	return (TRUE);
5892
5893
no_trackpoint:
5894
	if (sc->synhw.capPassthrough)
5895
		synaptics_passthrough_off(sc);
5896
5897
	return (FALSE);
4999
}
5898
}
5000
5899
5001
/* Interlink electronics VersaPad */
5900
/* Interlink electronics VersaPad */
5002
static int
5901
static int
5003
enable_versapad(KBDC kbdc, struct psm_softc *sc)
5902
enable_versapad(struct psm_softc *sc, enum probearg arg)
5004
{
5903
{
5904
	KBDC kbdc = sc->kbdc;
5005
	int data[3];
5905
	int data[3];
5006
5906
5007
	set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */
5907
	set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */
Lines 5019-5024 Link Here
5019
	return (TRUE);				/* PS/2 absolute mode */
5919
	return (TRUE);				/* PS/2 absolute mode */
5020
}
5920
}
5021
5921
5922
/* Elantech Touchpad */
5923
static int
5924
elantech_read_1(KBDC kbdc, int hwversion, int reg, int *val)
5925
{
5926
	int res, readcmd, retidx;
5927
	int resp[3];
5928
5929
	readcmd = hwversion == 2 ? ELANTECH_REG_READ : ELANTECH_REG_RDWR;
5930
	retidx = hwversion == 4 ? 1 : 0;
5931
5932
	res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK;
5933
	res |= send_aux_command(kbdc, readcmd) != PSM_ACK;
5934
	res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK;
5935
	res |= send_aux_command(kbdc, reg) != PSM_ACK;
5936
	res |= get_mouse_status(kbdc, resp, 0, 3) != 3;
5937
5938
	if (res == 0)
5939
		*val = resp[retidx];
5940
5941
	return (res);
5942
}
5943
5944
static int
5945
elantech_write_1(KBDC kbdc, int hwversion, int reg, int val)
5946
{
5947
	int res, writecmd;
5948
5949
	writecmd = hwversion == 2 ? ELANTECH_REG_WRITE : ELANTECH_REG_RDWR;
5950
5951
	res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK;
5952
	res |= send_aux_command(kbdc, writecmd) != PSM_ACK;
5953
	res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK;
5954
	res |= send_aux_command(kbdc, reg) != PSM_ACK;
5955
	if (hwversion == 4) {
5956
		res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK;
5957
		res |= send_aux_command(kbdc, writecmd) != PSM_ACK;
5958
	}
5959
	res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK;
5960
	res |= send_aux_command(kbdc, val) != PSM_ACK;
5961
	res |= set_mouse_scaling(kbdc, 1) == 0;
5962
5963
	return (res);
5964
}
5965
5966
static int
5967
elantech_cmd(KBDC kbdc, int hwversion, int cmd, int *resp)
5968
{
5969
	int res;
5970
5971
	if (hwversion == 2) {
5972
		res = set_mouse_scaling(kbdc, 1) == 0;
5973
		res |= mouse_ext_command(kbdc, cmd) == 0;
5974
	} else {
5975
		res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK;
5976
		res |= send_aux_command(kbdc, cmd) != PSM_ACK;
5977
	}
5978
	res |= get_mouse_status(kbdc, resp, 0, 3) != 3;
5979
5980
	return (res);
5981
}
5982
5983
static int
5984
elantech_init(KBDC kbdc, elantechhw_t *elanhw)
5985
{
5986
	int i, val, res, hwversion, reg10;
5987
5988
	/* set absolute mode */
5989
	hwversion = elanhw->hwversion;
5990
	reg10 = -1;
5991
	switch (hwversion) {
5992
	case 2:
5993
		reg10 = elanhw->fwversion == 0x020030 ? 0x54 : 0xc4;
5994
		res = elantech_write_1(kbdc, hwversion, 0x10, reg10);
5995
		if (res)
5996
			break;
5997
		res = elantech_write_1(kbdc, hwversion, 0x11, 0x8A);
5998
		break;
5999
	case 3:
6000
		reg10 = 0x0b;
6001
		res = elantech_write_1(kbdc, hwversion, 0x10, reg10);
6002
		break;
6003
	case 4:
6004
		res = elantech_write_1(kbdc, hwversion, 0x07, 0x01);
6005
		break;
6006
	default:
6007
		res = 1;
6008
	}
6009
6010
	/* Read back reg 0x10 to ensure hardware is ready. */
6011
	if (res == 0 && reg10 >= 0) {
6012
		for (i = 0; i < 5; i++) {
6013
			if (elantech_read_1(kbdc, hwversion, 0x10, &val) == 0)
6014
				break;
6015
			pause("elan", 1);
6016
		}
6017
		if (i == 5)
6018
			res = 1;
6019
	}
6020
6021
	if (res)
6022
		printf("couldn't set absolute mode\n");
6023
6024
	return (res);
6025
}
6026
6027
static void
6028
elantech_init_synaptics(struct psm_softc *sc)
6029
{
6030
6031
	/* Set capabilites required by movement smother */
6032
	sc->synhw.infoMajor = sc->elanhw.hwversion;
6033
	sc->synhw.infoMinor = sc->elanhw.fwversion;
6034
	sc->synhw.infoXupmm = (sc->elanhw.dpix * 10 + 5) / 254;
6035
	sc->synhw.infoYupmm = (sc->elanhw.dpiy * 10 + 5) / 254;
6036
	sc->synhw.verticalScroll = 0;
6037
	sc->synhw.nExtendedQueries = 4;
6038
	sc->synhw.capExtended = 1;
6039
	sc->synhw.capPassthrough = sc->elanhw.hastrackpad;
6040
	sc->synhw.capClickPad = sc->elanhw.isclickpad;
6041
	sc->synhw.capMultiFinger = 1;
6042
	sc->synhw.capPalmDetect = 1;
6043
	sc->synhw.capPen = 0;
6044
	sc->synhw.capReportsMax = 1;
6045
	sc->synhw.maximumXCoord = sc->elanhw.sizex;
6046
	sc->synhw.maximumYCoord = sc->elanhw.sizey;
6047
	sc->synhw.capReportsMin = 1;
6048
	sc->synhw.minimumXCoord = 0;
6049
	sc->synhw.minimumYCoord = 0;
6050
6051
	if (sc->syninfo.sysctl_tree == NULL) {
6052
		synaptics_sysctl_create_tree(sc, "elantech",
6053
		    "Elantech Touchpad");
6054
6055
		/*
6056
		 * Adjust synaptic smoother tunables
6057
		 * 1. Disable finger detection pressure threshold. Unlike
6058
		 *    synaptics we assume the finger is acting when packet with
6059
		 *    its X&Y arrives not when pressure exceedes some threshold
6060
		 * 2. Disable unrelated features like margins and noisy areas
6061
		 * 3. Disable virtual scroll areas as 2nd finger is preferable
6062
		 * 4. Scale down divisors and movement lengths by a factor of 3
6063
		 *    where 3 is Synaptics to Elantech (~2200/800) dpi ratio
6064
		 */
6065
6066
		/* Disable finger detection pressure threshold */
6067
		sc->syninfo.min_pressure = 1;
6068
6069
		/* Use full area of touchpad */
6070
		sc->syninfo.margin_top = 0;
6071
		sc->syninfo.margin_right = 0;
6072
		sc->syninfo.margin_bottom = 0;
6073
		sc->syninfo.margin_left = 0;
6074
		/* Disable noisy area */
6075
		sc->syninfo.na_top = 0;
6076
		sc->syninfo.na_right = 0;
6077
		sc->syninfo.na_bottom = 0;
6078
		sc->syninfo.na_left = 0;
6079
6080
		/* tune divisors and movement lengths */
6081
		sc->syninfo.weight_len_squared = 200;
6082
		sc->syninfo.div_min = 3;
6083
		sc->syninfo.div_max = 6;
6084
		sc->syninfo.div_max_na = 10;
6085
		sc->syninfo.div_len = 30;
6086
		sc->syninfo.tap_max_delta = 25;
6087
6088
		/* disable virtual scrolling areas and tune its divisors */
6089
		sc->syninfo.vscroll_hor_area = 0;
6090
		sc->syninfo.vscroll_ver_area = 0;
6091
		sc->syninfo.vscroll_min_delta = 15;
6092
		sc->syninfo.vscroll_div_min = 30;
6093
		sc->syninfo.vscroll_div_max = 50;
6094
	}
6095
6096
	return;
6097
}
6098
6099
static int
6100
enable_elantech(struct psm_softc *sc, enum probearg arg)
6101
{
6102
	static const int ic2hw[] =
6103
	/*IC: 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
6104
	    { 0, 0, 2, 0, 2, 3, 4, 4, 4, 4, 4, 0, 0, 4, 4, 0 };
6105
	elantechhw_t elanhw;
6106
	int icversion, hwversion, dptracex, dptracey, id, resp[3];
6107
	KBDC kbdc = sc->kbdc;
6108
6109
	VLOG(3, (LOG_DEBUG, "elantech: BEGIN init\n"));
6110
6111
	set_mouse_scaling(kbdc, 1);
6112
	set_mouse_scaling(kbdc, 1);
6113
	set_mouse_scaling(kbdc, 1);
6114
	if (get_mouse_status(kbdc, resp, 0, 3) != 3)
6115
		return (FALSE);
6116
6117
	if (!ELANTECH_MAGIC(resp))
6118
		return (FALSE);
6119
6120
	/* Identify the Touchpad version. */
6121
	if (elantech_cmd(kbdc, 2, ELANTECH_FW_VERSION, resp))
6122
		return (FALSE);
6123
6124
	bzero(&elanhw, sizeof(elanhw));
6125
6126
	elanhw.fwversion = (resp[0] << 16) | (resp[1] << 8) | resp[2];
6127
	icversion = resp[0] & 0x0f;
6128
	hwversion = ic2hw[icversion];
6129
6130
	if (verbose >= 2)
6131
		printf("Elantech touchpad hardware v.%d firmware v.0x%06x\n",
6132
		    hwversion, elanhw.fwversion);
6133
6134
	if (ELANTECH_HW_IS_V1(elanhw.fwversion)) {
6135
		printf ("  Unsupported touchpad hardware (v1)\n");
6136
		return (FALSE);
6137
	}
6138
	if (hwversion == 0) {
6139
		printf ("  Unknown touchpad hardware (firmware v.0x%06x)\n",
6140
		    elanhw.fwversion);
6141
		return (FALSE);
6142
	}
6143
6144
	/* Get the Touchpad model information. */
6145
	elanhw.hwversion = hwversion;
6146
	elanhw.isclickpad = (resp[1] & 0x10) != 0;
6147
	elanhw.hascrc = (resp[1] & 0x40) != 0;
6148
	elanhw.haspressure = elanhw.fwversion >= 0x020800;
6149
6150
	/* Read the capability bits. */
6151
	if (elantech_cmd(kbdc, hwversion, ELANTECH_CAPABILITIES, resp) != 0) {
6152
		printf("  Failed to read capability bits\n");
6153
		return (FALSE);
6154
	}
6155
6156
	elanhw.ntracesx = resp[1] - 1;
6157
	elanhw.ntracesy = resp[2] - 1;
6158
	elanhw.hastrackpad = (resp[0] & 0x80) != 0;
6159
6160
	/* Get the touchpad resolution */
6161
	switch (hwversion) {
6162
	case 2:
6163
		elanhw.dpix = elanhw.dpiy = 400;
6164
		break;
6165
	case 4:
6166
		if (elantech_cmd(kbdc, hwversion, ELANTECH_RESOLUTION, resp)
6167
		    == 0) {
6168
			elanhw.dpix = (resp[1] & 0x0f) * 10 + 790;
6169
			elanhw.dpiy = ((resp[1] & 0xf0) >> 4) * 10 + 790;
6170
			break;
6171
		}
6172
		/* FALLTHROUGH */
6173
	case 3:
6174
		elanhw.dpix = elanhw.dpiy = 800;
6175
		break;
6176
	}
6177
6178
	if (!elantech_support)
6179
		return (FALSE);
6180
6181
	if (elantech_init(kbdc, &elanhw)) {
6182
		printf("couldn't initialize elantech touchpad\n");
6183
		return (FALSE);
6184
	}
6185
6186
	/*
6187
	 * Get the touchpad reporting range.
6188
	 * On HW v.3 touchpads it should be done after switching hardware
6189
	 * to real resolution mode (by setting bit 3 of reg10)
6190
	 */
6191
	if (elantech_cmd(kbdc, hwversion, ELANTECH_FW_ID, resp) != 0) {
6192
		printf("  Failed to read touchpad size\n");
6193
		elanhw.sizex = 10000; /* Arbitrary high values to     */
6194
		elanhw.sizey = 10000; /* prevent clipping in smoother */
6195
	} else if (hwversion == 2) {
6196
		dptracex = dptracey = 64;
6197
		if ((elanhw.fwversion >> 16) == 0x14 && (resp[1] & 0x10) &&
6198
		    !elantech_cmd(kbdc, hwversion, ELANTECH_SAMPLE, resp)) {
6199
			dptracex = resp[1] / 2;
6200
			dptracey = resp[2] / 2;
6201
		}
6202
		elanhw.sizex = (elanhw.ntracesx - 1) * dptracex;
6203
		elanhw.sizey = (elanhw.ntracesy - 1) * dptracey;
6204
	} else {
6205
		elanhw.sizex = (resp[0] & 0x0f) << 8 | resp[1];
6206
		elanhw.sizey = (resp[0] & 0xf0) << 4 | resp[2];
6207
	}
6208
6209
	if (verbose >= 2) {
6210
		printf("  Model information:\n");
6211
		printf("   MaxX:     %d\n", elanhw.sizex);
6212
		printf("   MaxY:     %d\n", elanhw.sizey);
6213
		printf("   DpiX:     %d\n", elanhw.dpix);
6214
		printf("   DpiY:     %d\n", elanhw.dpiy);
6215
		printf("   TracesX:  %d\n", elanhw.ntracesx);
6216
		printf("   TracesY:  %d\n", elanhw.ntracesy);
6217
		printf("   Clickpad: %d\n", elanhw.isclickpad);
6218
		printf("   Trackpad: %d\n", elanhw.hastrackpad);
6219
		printf("   CRC:      %d\n", elanhw.hascrc);
6220
		printf("   Pressure: %d\n", elanhw.haspressure);
6221
	}
6222
6223
	VLOG(3, (LOG_DEBUG, "elantech: END init\n"));
6224
6225
	if (arg == PROBE) {
6226
		sc->elanhw = elanhw;
6227
		sc->hw.buttons = 3;
6228
6229
		/* Initialize synaptics movement smoother */
6230
		elantech_init_synaptics(sc);
6231
6232
		for (id = 0; id < PSM_GESTURE_FINGERS; id++)
6233
			PSM_FINGER_RESET(sc->elanaction.fingers[id]);
6234
6235
		if (elanhw.hascrc)
6236
			sc->config |= PSM_CONFIG_NOCHECKSYNC;
6237
	}
6238
6239
	return (TRUE);
6240
}
6241
5022
/*
6242
/*
5023
 * Return true if 'now' is earlier than (start + (secs.usecs)).
6243
 * Return true if 'now' is earlier than (start + (secs.usecs)).
5024
 * Now may be NULL and the function will fetch the current time from
6244
 * Now may be NULL and the function will fetch the current time from
(-)sys/sys/mouse.h (+14 lines)
Lines 108-113 Link Here
108
	int capPalmDetect;
108
	int capPalmDetect;
109
	int capPassthrough;
109
	int capPassthrough;
110
	int capMiddle;
110
	int capMiddle;
111
	int capLowPower;
112
	int capMultiFingerReport;
113
	int capBallistics;
111
	int nExtendedButtons;
114
	int nExtendedButtons;
112
	int nExtendedQueries;
115
	int nExtendedQueries;
113
	int capClickPad;
116
	int capClickPad;
Lines 125-130 Link Here
125
	int verticalScroll;
128
	int verticalScroll;
126
	int horizontalScroll;
129
	int horizontalScroll;
127
	int verticalWheel;
130
	int verticalWheel;
131
	int capEWmode;
132
	int minimumXCoord;
133
	int minimumYCoord;
134
	int maximumXCoord;
135
	int maximumYCoord;
136
	int infoXupmm;
137
	int infoYupmm;
128
} synapticshw_t;
138
} synapticshw_t;
129
139
130
/* iftype */
140
/* iftype */
Lines 160-165 Link Here
160
#define MOUSE_MODEL_4DPLUS		12
170
#define MOUSE_MODEL_4DPLUS		12
161
#define MOUSE_MODEL_SYNAPTICS		13
171
#define MOUSE_MODEL_SYNAPTICS		13
162
#define	MOUSE_MODEL_TRACKPOINT		14
172
#define	MOUSE_MODEL_TRACKPOINT		14
173
#define MOUSE_MODEL_ELANTECH		15
163
174
164
typedef struct mousemode {
175
typedef struct mousemode {
165
	int protocol;		/* MOUSE_PROTO_XXX */
176
	int protocol;		/* MOUSE_PROTO_XXX */
Lines 230-235 Link Here
230
/* Synaptics Touchpad */
241
/* Synaptics Touchpad */
231
#define MOUSE_SYNAPTICS_PACKETSIZE	6	/* '3' works better */
242
#define MOUSE_SYNAPTICS_PACKETSIZE	6	/* '3' works better */
232
243
244
/* Elantech Touchpad */
245
#define MOUSE_ELANTECH_PACKETSIZE	6
246
233
/* Microsoft Serial mouse data packet */
247
/* Microsoft Serial mouse data packet */
234
#define MOUSE_MSS_PACKETSIZE	3
248
#define MOUSE_MSS_PACKETSIZE	3
235
#define MOUSE_MSS_SYNCMASK	0x40
249
#define MOUSE_MSS_SYNCMASK	0x40
(-)usr.sbin/moused/moused.c (+1 lines)
Lines 246-251 Link Here
246
    { "4D+ Mouse",		MOUSE_MODEL_4DPLUS,		0 },
246
    { "4D+ Mouse",		MOUSE_MODEL_4DPLUS,		0 },
247
    { "Synaptics Touchpad",	MOUSE_MODEL_SYNAPTICS,		0 },
247
    { "Synaptics Touchpad",	MOUSE_MODEL_SYNAPTICS,		0 },
248
    { "TrackPoint",		MOUSE_MODEL_TRACKPOINT,		0 },
248
    { "TrackPoint",		MOUSE_MODEL_TRACKPOINT,		0 },
249
    { "Elantech Touchpad",	MOUSE_MODEL_ELANTECH,		0 },
249
    { "generic",		MOUSE_MODEL_GENERIC,		0 },
250
    { "generic",		MOUSE_MODEL_GENERIC,		0 },
250
    { NULL,			MOUSE_MODEL_UNKNOWN,		0 },
251
    { NULL,			MOUSE_MODEL_UNKNOWN,		0 },
251
};
252
};

Return to bug 205690