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

Collapse All | Expand All

(-)b/sys/dev/atkbdc/psm.c (-27 / +134 lines)
Lines 132-137 __FBSDID("$FreeBSD$"); Link Here
132
132
133
#define	PSMCPNP_DRIVER_NAME	"psmcpnp"
133
#define	PSMCPNP_DRIVER_NAME	"psmcpnp"
134
134
135
struct psmcpnp_softc {
136
	enum {
137
		PSMCPNP_GENERIC,
138
		PSMCPNP_FORCEPAD,
139
		PSMCPNP_HPSYN81,
140
	} type;		/* Based on PnP ID */
141
};
142
135
/* input queue */
143
/* input queue */
136
#define	PSM_BUFSIZE		960
144
#define	PSM_BUFSIZE		960
137
#define	PSM_SMALLBUFSIZE	240
145
#define	PSM_SMALLBUFSIZE	240
Lines 167-172 typedef struct packetbuf { Link Here
167
#define	PSM_PACKETQUEUE	128
175
#define	PSM_PACKETQUEUE	128
168
#endif
176
#endif
169
177
178
/*
179
 * Typical bezel limits. Taken from 'Synaptics
180
 * PS/2 TouchPad Interfacing Guide' p.3.2.3.
181
 */
182
#define	SYNAPTICS_DEFAULT_MAX_X	5472
183
#define	SYNAPTICS_DEFAULT_MAX_Y	4448
184
#define	SYNAPTICS_DEFAULT_MIN_X	1472
185
#define	SYNAPTICS_DEFAULT_MIN_Y	1408
186
170
typedef struct synapticsinfo {
187
typedef struct synapticsinfo {
171
	struct sysctl_ctx_list	 sysctl_ctx;
188
	struct sysctl_ctx_list	 sysctl_ctx;
172
	struct sysctl_oid	*sysctl_tree;
189
	struct sysctl_oid	*sysctl_tree;
Lines 416-421 struct psm_softc { /* Driver status information */ Link Here
416
	int		squelch; /* level to filter movement at low speed */
433
	int		squelch; /* level to filter movement at low speed */
417
	int		syncerrors; /* # of bytes discarded to synchronize */
434
	int		syncerrors; /* # of bytes discarded to synchronize */
418
	int		pkterrors;  /* # of packets failed during quaranteen. */
435
	int		pkterrors;  /* # of packets failed during quaranteen. */
436
	int		fpcount;	/* forcePad valid packet counter */
419
	struct timeval	inputtimeout;
437
	struct timeval	inputtimeout;
420
	struct timeval	lastsoftintr;	/* time of last soft interrupt */
438
	struct timeval	lastsoftintr;	/* time of last soft interrupt */
421
	struct timeval	lastinputerr;	/* time last sync error happened */
439
	struct timeval	lastinputerr;	/* time last sync error happened */
Lines 1088-1094 doopen(struct psm_softc *sc, int command_byte) Link Here
1088
		mouse_ext_command(sc->kbdc, 1);
1106
		mouse_ext_command(sc->kbdc, 1);
1089
		get_mouse_status(sc->kbdc, stat, 0, 3);
1107
		get_mouse_status(sc->kbdc, stat, 0, 3);
1090
		if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) ||
1108
		if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) ||
1091
		     stat[1] == 0x47) &&
1109
		     stat[1] == 0x46 || stat[1] == 0x47) &&
1092
		     stat[2] == 0x40) {
1110
		     stat[2] == 0x40) {
1093
			synaptics_set_mode(sc, synaptics_preferred_mode(sc));
1111
			synaptics_set_mode(sc, synaptics_preferred_mode(sc));
1094
			VLOG(5, (LOG_DEBUG, "psm%d: Synaptis Absolute Mode "
1112
			VLOG(5, (LOG_DEBUG, "psm%d: Synaptis Absolute Mode "
Lines 3183-3189 proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, Link Here
3183
	static int touchpad_buttons;
3201
	static int touchpad_buttons;
3184
	static int guest_buttons;
3202
	static int guest_buttons;
3185
	static finger_t f[PSM_FINGERS];
3203
	static finger_t f[PSM_FINGERS];
3186
	int w, id, nfingers, ewcode, extended_buttons;
3204
	int w, id, nfingers, ewcode, extended_buttons, clickpad_pressed;
3187
3205
3188
	extended_buttons = 0;
3206
	extended_buttons = 0;
3189
3207
Lines 3445-3454 proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, Link Here
3445
			extended_buttons |= sc->extended_buttons;
3463
			extended_buttons |= sc->extended_buttons;
3446
		}
3464
		}
3447
	}
3465
	}
3448
	/* Handle ClickPad */
3449
	if (sc->synhw.capClickPad &&
3450
	    ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01))
3451
		touchpad_buttons |= MOUSE_BUTTON1DOWN;
3452
3466
3453
	if (sc->synhw.capReportsV && nfingers > 1)
3467
	if (sc->synhw.capReportsV && nfingers > 1)
3454
		f[0] = (finger_t) {
3468
		f[0] = (finger_t) {
Lines 3481-3486 proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, Link Here
3481
	if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2)
3495
	if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2)
3482
		nfingers = 0;
3496
		nfingers = 0;
3483
3497
3498
	/* Handle ClickPad */
3499
	if (sc->synhw.capClickPad) {
3500
		clickpad_pressed = (pb->ipacket[0] ^ pb->ipacket[3]) & 0x01;
3501
		if (sc->synhw.forcePad) {
3502
			/*
3503
			 * Forcepads erroneously report button click if there
3504
			 * are 2 or more fingers on the touchpad breaking
3505
			 * multifinger gestures. To workaround this start
3506
			 * reporting a click only after 4 consecutive single
3507
			 * touch packets has been received.
3508
			 * Skip these packets in case more contacts appear.
3509
			 */
3510
			switch (nfingers) {
3511
			case 0:
3512
				sc->fpcount = 0;
3513
				break;
3514
			case 1:
3515
				if (clickpad_pressed && sc->fpcount < INT_MAX)
3516
					++sc->fpcount;
3517
				/* FALLTHROUGH */
3518
			default:
3519
				if (!clickpad_pressed)
3520
					sc->fpcount = 0;
3521
				if (sc->fpcount >= sc->syninfo.window_min)
3522
					touchpad_buttons |= MOUSE_BUTTON1DOWN;
3523
			}
3524
		} else if (clickpad_pressed)
3525
			touchpad_buttons |= MOUSE_BUTTON1DOWN;
3526
	}
3527
3484
	for (id = 0; id < PSM_FINGERS; id++)
3528
	for (id = 0; id < PSM_FINGERS; id++)
3485
		if (id >= nfingers)
3529
		if (id >= nfingers)
3486
			PSM_FINGER_RESET(f[id]);
3530
			PSM_FINGER_RESET(f[id]);
Lines 6004-6013 synaptics_set_mode(struct psm_softc *sc, int mode_byte) { Link Here
6004
static int
6048
static int
6005
enable_synaptics(struct psm_softc *sc, enum probearg arg)
6049
enable_synaptics(struct psm_softc *sc, enum probearg arg)
6006
{
6050
{
6051
	device_t psmcpnp;
6052
	struct psmcpnp_softc *psmcpnp_sc;
6007
	KBDC kbdc = sc->kbdc;
6053
	KBDC kbdc = sc->kbdc;
6008
	synapticshw_t synhw;
6054
	synapticshw_t synhw;
6009
	int status[3];
6055
	int status[3];
6010
	int buttons;
6056
	int buttons, middle_byte;
6011
6057
6012
	VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n"));
6058
	VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n"));
6013
6059
Lines 6024-6030 enable_synaptics(struct psm_softc *sc, enum probearg arg) Link Here
6024
		return (FALSE);
6070
		return (FALSE);
6025
	if (get_mouse_status(kbdc, status, 0, 3) != 3)
6071
	if (get_mouse_status(kbdc, status, 0, 3) != 3)
6026
		return (FALSE);
6072
		return (FALSE);
6027
	if (status[1] != 0x47)
6073
	middle_byte = status[1];
6074
	if (middle_byte != 0x46 && middle_byte != 0x47)
6028
		return (FALSE);
6075
		return (FALSE);
6029
6076
6030
	bzero(&synhw, sizeof(synhw));
6077
	bzero(&synhw, sizeof(synhw));
Lines 6035-6041 enable_synaptics(struct psm_softc *sc, enum probearg arg) Link Here
6035
		printf("Synaptics Touchpad v%d.%d\n", synhw.infoMajor,
6082
		printf("Synaptics Touchpad v%d.%d\n", synhw.infoMajor,
6036
		    synhw.infoMinor);
6083
		    synhw.infoMinor);
6037
6084
6038
	if (synhw.infoMajor < 4) {
6085
	/*
6086
	 * Most synaptics touchpads return 0x47 in middle byte in responce to
6087
	 * identify command as stated in p.4.4 of "Synaptics PS/2 TouchPad
6088
	 * Interfacing Guide" and we only support v4.0 or better. But some
6089
	 * devices return 0x46 here and have a different numbering scheme.
6090
	 * In the case of 0x46, we allow versions as low as v2.0
6091
	 */
6092
	if ((middle_byte == 0x47 && synhw.infoMajor < 4) ||
6093
	    (middle_byte == 0x46 && synhw.infoMajor < 2)) {
6039
		printf("  Unsupported (pre-v4) Touchpad detected\n");
6094
		printf("  Unsupported (pre-v4) Touchpad detected\n");
6040
		return (FALSE);
6095
		return (FALSE);
6041
	}
6096
	}
Lines 6076-6090 enable_synaptics(struct psm_softc *sc, enum probearg arg) Link Here
6076
		return (FALSE);
6131
		return (FALSE);
6077
	if (get_mouse_status(kbdc, status, 0, 3) != 3)
6132
	if (get_mouse_status(kbdc, status, 0, 3) != 3)
6078
		return (FALSE);
6133
		return (FALSE);
6079
	if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != 0x47) {
6134
	if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != middle_byte) {
6080
		printf("  Failed to read extended capability bits\n");
6135
		printf("  Failed to read extended capability bits\n");
6081
		return (FALSE);
6136
		return (FALSE);
6082
	}
6137
	}
6083
6138
6139
	psmcpnp = devclass_get_device(devclass_find(PSMCPNP_DRIVER_NAME),
6140
	    sc->unit);
6141
	psmcpnp_sc = (psmcpnp != NULL) ? device_get_softc(psmcpnp) : NULL;
6142
6143
	/*
6144
	 * Set conservative defaults for 0x46 middle byte touchpads
6145
	 * as ExtendedQueries return bogus data.
6146
	 */
6147
	if (middle_byte == 0x46) {
6148
		synhw.capExtended = 1;
6149
		synhw.capPalmDetect = 1;
6150
		synhw.capPassthrough = 1;
6151
		synhw.capMultiFinger = 1;
6152
		synhw.maximumXCoord = SYNAPTICS_DEFAULT_MAX_X;
6153
		synhw.maximumYCoord = SYNAPTICS_DEFAULT_MAX_Y;
6154
		synhw.minimumXCoord = SYNAPTICS_DEFAULT_MIN_X;
6155
		synhw.minimumYCoord = SYNAPTICS_DEFAULT_MIN_Y;
6156
		/* Enable multitouch mode for HW v8.1 devices */
6157
		if (psmcpnp_sc != NULL &&
6158
		    psmcpnp_sc->type == PSMCPNP_HPSYN81)
6159
			synhw.capReportsV = 1;
6160
	} else
6161
		synhw.capExtended = (status[0] & 0x80) != 0;
6162
6084
	/* Set the different capabilities when they exist. */
6163
	/* Set the different capabilities when they exist. */
6085
	buttons = 0;
6164
	buttons = 0;
6086
	synhw.capExtended = (status[0] & 0x80) != 0;
6165
	if (synhw.capExtended && middle_byte == 0x47) {
6087
	if (synhw.capExtended) {
6088
		synhw.nExtendedQueries = (status[0] & 0x70) >> 4;
6166
		synhw.nExtendedQueries = (status[0] & 0x70) >> 4;
6089
		synhw.capMiddle        = (status[0] & 0x04) != 0;
6167
		synhw.capMiddle        = (status[0] & 0x04) != 0;
6090
		synhw.capPassthrough   = (status[2] & 0x80) != 0;
6168
		synhw.capPassthrough   = (status[2] & 0x80) != 0;
Lines 6206-6217 enable_synaptics(struct psm_softc *sc, enum probearg arg) Link Here
6206
				synhw.maximumYCoord = (status[2] << 5) |
6284
				synhw.maximumYCoord = (status[2] << 5) |
6207
						     ((status[1] & 0xf0) >> 3);
6285
						     ((status[1] & 0xf0) >> 3);
6208
			} else {
6286
			} else {
6209
				/*
6287
				synhw.maximumXCoord = SYNAPTICS_DEFAULT_MAX_X;
6210
				 * Typical bezel limits. Taken from 'Synaptics
6288
				synhw.maximumYCoord = SYNAPTICS_DEFAULT_MAX_Y;
6211
				 * PS/2 * TouchPad Interfacing Guide' p.3.2.3.
6212
				 */
6213
				synhw.maximumXCoord = 5472;
6214
				synhw.maximumYCoord = 4448;
6215
			}
6289
			}
6216
6290
6217
			if (synhw.capReportsMin) {
6291
			if (synhw.capReportsMin) {
Lines 6227-6238 enable_synaptics(struct psm_softc *sc, enum probearg arg) Link Here
6227
				synhw.minimumYCoord = (status[2] << 5) |
6301
				synhw.minimumYCoord = (status[2] << 5) |
6228
						     ((status[1] & 0xf0) >> 3);
6302
						     ((status[1] & 0xf0) >> 3);
6229
			} else {
6303
			} else {
6230
				/*
6304
				synhw.minimumXCoord = SYNAPTICS_DEFAULT_MIN_X;
6231
				 * Typical bezel limits. Taken from 'Synaptics
6305
				synhw.minimumYCoord = SYNAPTICS_DEFAULT_MIN_Y;
6232
				 * PS/2 * TouchPad Interfacing Guide' p.3.2.3.
6306
			}
6233
				 */
6307
6234
				synhw.minimumXCoord = 1472;
6308
			/*
6235
				synhw.minimumYCoord = 1408;
6309
			 * ClickPad properties are not exported through PS/2
6310
			 * protocol. Detection is based on controller's PnP ID.
6311
			 */
6312
			if (synhw.capClickPad && psmcpnp_sc != NULL) {
6313
				switch (psmcpnp_sc->type) {
6314
				case PSMCPNP_FORCEPAD:
6315
					synhw.forcePad = 1;
6316
					break;
6317
				default:
6318
					break;
6319
				}
6236
			}
6320
			}
6237
6321
6238
			if (verbose >= 2) {
6322
			if (verbose >= 2) {
Lines 6271-6276 enable_synaptics(struct psm_softc *sc, enum probearg arg) Link Here
6271
					printf("   minimumYCoord: %d\n",
6355
					printf("   minimumYCoord: %d\n",
6272
					       synhw.minimumYCoord);
6356
					       synhw.minimumYCoord);
6273
				}
6357
				}
6358
				if (synhw.capClickPad) {
6359
					printf("   forcePad: %d\n",
6360
					       synhw.forcePad);
6361
				}
6274
			}
6362
			}
6275
			buttons += synhw.capClickPad;
6363
			buttons += synhw.capClickPad;
6276
		}
6364
		}
Lines 6300-6306 enable_synaptics(struct psm_softc *sc, enum probearg arg) Link Here
6300
		return (FALSE);
6388
		return (FALSE);
6301
	if (get_mouse_status(kbdc, status, 0, 3) != 3)
6389
	if (get_mouse_status(kbdc, status, 0, 3) != 3)
6302
		return (FALSE);
6390
		return (FALSE);
6303
	if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != 0x47) {
6391
	if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != middle_byte) {
6304
		printf("  Failed to read mode byte\n");
6392
		printf("  Failed to read mode byte\n");
6305
		return (FALSE);
6393
		return (FALSE);
6306
	}
6394
	}
Lines 7096-7102 static device_method_t psmcpnp_methods[] = { Link Here
7096
static driver_t psmcpnp_driver = {
7184
static driver_t psmcpnp_driver = {
7097
	PSMCPNP_DRIVER_NAME,
7185
	PSMCPNP_DRIVER_NAME,
7098
	psmcpnp_methods,
7186
	psmcpnp_methods,
7099
	1,			/* no softc */
7187
	sizeof(struct psmcpnp_softc),
7100
};
7188
};
7101
7189
7102
static struct isa_pnp_id psmcpnp_ids[] = {
7190
static struct isa_pnp_id psmcpnp_ids[] = {
Lines 7116-7121 static struct isa_pnp_id psmcpnp_ids[] = { Link Here
7116
	{ 0 }
7204
	{ 0 }
7117
};
7205
};
7118
7206
7207
static struct isa_pnp_id forcepad_ids[] = {
7208
	{ 0x0d302e4f, "HP PS/2 forcepad port" },	/* SYN300D, EB 1040 */
7209
	{ 0x14302e4f, "HP PS/2 forcepad port" },	/* SYN3014, EB 1040 */
7210
	{ 0 }
7211
};
7212
7213
/* List of HW v8.1 synaptics touchpads erroneously detected as HW v2.0 */
7214
static struct isa_pnp_id hpsyn81_ids[] = {
7215
	{ 0x9e012e4f, "HP PS/2 trackpad port" },	/* SYN019E, EB 9470 */
7216
	{ 0 }
7217
};
7218
7119
static int
7219
static int
7120
create_a_copy(device_t atkbdc, device_t me)
7220
create_a_copy(device_t atkbdc, device_t me)
7121
{
7221
{
Lines 7142-7152 create_a_copy(device_t atkbdc, device_t me) Link Here
7142
static int
7242
static int
7143
psmcpnp_probe(device_t dev)
7243
psmcpnp_probe(device_t dev)
7144
{
7244
{
7245
	struct psmcpnp_softc *sc = device_get_softc(dev);
7145
	struct resource *res;
7246
	struct resource *res;
7146
	u_long irq;
7247
	u_long irq;
7147
	int rid;
7248
	int rid;
7148
7249
7149
	if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids))
7250
	if (ISA_PNP_PROBE(device_get_parent(dev), dev, forcepad_ids) == 0)
7251
		sc->type = PSMCPNP_FORCEPAD;
7252
	else if(ISA_PNP_PROBE(device_get_parent(dev), dev, hpsyn81_ids) == 0)
7253
		sc->type = PSMCPNP_HPSYN81;
7254
	else if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids) == 0)
7255
		sc->type = PSMCPNP_GENERIC;
7256
	else
7150
		return (ENXIO);
7257
		return (ENXIO);
7151
7258
7152
	/*
7259
	/*
(-)b/sys/sys/mouse.h (+1 lines)
Lines 135-140 typedef struct synapticshw { Link Here
135
	int maximumYCoord;
135
	int maximumYCoord;
136
	int infoXupmm;
136
	int infoXupmm;
137
	int infoYupmm;
137
	int infoYupmm;
138
	int forcePad;
138
} synapticshw_t;
139
} synapticshw_t;
139
140
140
/* iftype */
141
/* iftype */

Return to bug 222667