xref: /openbsd/sys/dev/i2c/iatp.c (revision 09467b48)
1 /* $OpenBSD: iatp.c,v 1.7 2020/01/09 14:35:19 mpi Exp $ */
2 /*
3  * Atmel maXTouch i2c touchscreen/touchpad driver
4  * Copyright (c) 2016 joshua stein <jcs@openbsd.org>
5  *
6  * AT421085 datasheet:
7  * http://www.atmel.com/images/Atmel-9626-AT42-QTouch-BSW-AT421085-Object-Protocol-Guide_Datasheet.pdf
8  *
9  * Uses code from libmaxtouch <https://github.com/atmel-maxtouch/mxt-app>
10  * Copyright 2011 Atmel Corporation. All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  *    1. Redistributions of source code must retain the above copyright notice,
16  *    this list of conditions and the following disclaimer.
17  *
18  *    2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY ATMEL ''AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
25  * EVENT SHALL ATMEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
28  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/device.h>
38 #include <sys/malloc.h>
39 #include <sys/stdint.h>
40 
41 #include <dev/i2c/i2cvar.h>
42 
43 #include <dev/wscons/wsconsio.h>
44 #include <dev/wscons/wsmousevar.h>
45 #include <dev/hid/hid.h>
46 #include <dev/hid/hidmsvar.h>
47 
48 /* #define IATP_DEBUG */
49 
50 #ifdef IATP_DEBUG
51 #define DPRINTF(x) printf x
52 #else
53 #define DPRINTF(x)
54 #endif
55 
56 struct mxt_object {
57 	uint8_t type;
58 	uint16_t start_pos;
59 	uint8_t size_minus_one;
60 #define MXT_SIZE(o)		((uint16_t)((o)->size_minus_one) + 1)
61 	uint8_t instances_minus_one;
62 #define MXT_INSTANCES(o)	((uint16_t)((o)->instances_minus_one) + 1)
63 	uint8_t num_report_ids;
64 } __packed;
65 
66 struct mxt_id_info {
67 	uint8_t family;
68 	uint8_t variant;
69 	uint8_t version;
70 	uint8_t build;
71 	uint8_t matrix_x_size;
72 	uint8_t matrix_y_size;
73 	uint8_t num_objects;
74 } __packed;
75 
76 struct mxt_info {
77 	struct mxt_id_info id;
78 	struct mxt_object *objects;
79 	uint32_t crc;
80 	uint8_t *raw_info;
81 	uint8_t max_report_id;
82 };
83 
84 /* object types we care about (of 117 total!) */
85 
86 #define MXT_GEN_MESSAGEPROCESSOR_T5	5
87 
88 #define MXT_GEN_COMMANDPROCESSOR_T6	6
89 # define MXT_T6_STATUS_RESET		(1 << 7)
90 # define MXT_T6_STATUS_OFL		(1 << 6)
91 # define MXT_T6_STATUS_SIGERR		(1 << 5)
92 # define MXT_T6_STATUS_CAL		(1 << 4)
93 # define MXT_T6_STATUS_CFGERR		(1 << 3)
94 # define MXT_T6_STATUS_COMSERR		(1 << 2)
95 # define MXT_T6_CMD_RESET		0
96 # define MXT_T6_CMD_BACKUPNV		1
97 # define MXT_T6_CMD_CALIBRATE		2
98 # define MXT_T6_CMD_REPORTALL		3
99 # define MXT_T6_CMD_DIAGNOSTIC		5
100 
101 #define MXT_GEN_POWERCONFIG_T7		7
102 # define MXT_T7_POWER_MODE_DEFAULT	1
103 # define MXT_T7_POWER_MODE_DEEP_SLEEP	2
104 struct mxt_t7_config {
105 	uint8_t idle;
106 	uint8_t active;
107 	uint8_t atoi_timeout;
108 } __packed;
109 
110 #define MXT_SPT_GPIOPWM_T19		19
111 static const struct mxt_t19_button_map {
112 	const char *vendor;
113 	const char *product;
114 	const char *hid;
115 	int bit;
116 } mxt_t19_button_map_devs[] = {
117 	/* Chromebook Pixel 2015 */
118 	{ "GOOGLE", "Samus", "ATML0000", 3 },
119 	/* Other Google Chromebooks */
120 	{ "GOOGLE", "", "ATML0000", 5 },
121 	{ NULL }
122 };
123 
124 #define MXT_SPT_MESSAGECOUNT_T44	44
125 
126 #define MXT_TOUCH_MULTITOUCHSCREEN_T100	100
127 # define MXT_T100_CTRL			0
128 # define MXT_T100_CFG1			1
129 # define MXT_T100_TCHAUX		3
130 # define MXT_T100_XRANGE		13
131 # define MXT_T100_YRANGE		24
132 # define MXT_T100_CFG_SWITCHXY		(1 << 5)
133 # define MXT_T100_TCHAUX_VECT		(1 << 0)
134 # define MXT_T100_TCHAUX_AMPL		(1 << 1)
135 # define MXT_T100_TCHAUX_AREA		(1 << 2)
136 # define MXT_T100_DETECT		(1 << 7)
137 # define MXT_T100_TYPE_MASK		0x70
138 
139 enum t100_type {
140 	MXT_T100_TYPE_FINGER		= 1,
141 	MXT_T100_TYPE_PASSIVE_STYLUS	= 2,
142 	MXT_T100_TYPE_HOVERING_FINGER	= 4,
143 	MXT_T100_TYPE_GLOVE		= 5,
144 	MXT_T100_TYPE_LARGE_TOUCH	= 6,
145 };
146 
147 #define MXT_DISTANCE_ACTIVE_TOUCH	0
148 #define MXT_DISTANCE_HOVERING		1
149 
150 #define MXT_TOUCH_MAJOR_DEFAULT		1
151 
152 struct iatp_softc {
153 	struct device		sc_dev;
154 	i2c_tag_t		sc_tag;
155 
156 	i2c_addr_t		sc_addr;
157 	void			*sc_ih;
158 
159 	struct device		*sc_wsmousedev;
160 	char			sc_hid[16];
161 	int			sc_busy;
162 	int			sc_enabled;
163 	int			sc_touchpad;
164 	struct tsscale		sc_tsscale;
165 
166 	uint8_t			*table;
167 	size_t			table_size;
168 
169 	struct mxt_info		info;
170 	uint8_t			*msg_buf;
171 	uint8_t			multitouch;
172 	uint8_t			num_touchids;
173 	uint32_t		max_x;
174 	uint32_t		max_y;
175 	uint8_t			button;
176 
177 	uint16_t		t5_address;
178 	uint8_t			t5_msg_size;
179 	uint16_t		t6_address;
180 	uint8_t			t6_reportid;
181 	uint16_t		t7_address;
182 	struct mxt_t7_config	t7_config;
183 	uint8_t			t19_reportid;
184 	int			t19_button_bit;
185 	uint16_t		t44_address;
186 	uint8_t			t100_reportid_min;
187 	uint8_t			t100_reportid_max;
188 	uint8_t			t100_aux_ampl;
189 	uint8_t			t100_aux_area;
190 	uint8_t			t100_aux_vect;
191 };
192 
193 int	iatp_match(struct device *, void *, void *);
194 void	iatp_attach(struct device *, struct device *, void *);
195 int	iatp_detach(struct device *, int);
196 int	iatp_activate(struct device *, int);
197 
198 int	iatp_ioctl(void *, u_long, caddr_t, int, struct proc *);
199 int	iatp_enable(void *);
200 void	iatp_disable(void *);
201 
202 int	iatp_read_reg(struct iatp_softc *, uint16_t, size_t, void *);
203 int	iatp_write_reg(struct iatp_softc *, uint16_t, size_t, void *);
204 int	iatp_init(struct iatp_softc *);
205 int	iatp_intr(void *);
206 
207 int	iatp_proc_msg(struct iatp_softc *, uint8_t *);
208 int	iatp_t5_read_msgs(struct iatp_softc *, int);
209 void	iatp_t6_proc_msg(struct iatp_softc *, uint8_t *);
210 int	iatp_t7_set_power_mode(struct iatp_softc *, int);
211 void	iatp_t19_proc_msg(struct iatp_softc *, uint8_t *);
212 int	iatp_t44_read_count(struct iatp_softc *);
213 void	iatp_t100_proc_msg(struct iatp_softc *, uint8_t *);
214 
215 /* for gpio pin mapping */
216 extern char *hw_vendor, *hw_prod;
217 
218 const struct wsmouse_accessops iatp_accessops = {
219 	iatp_enable,
220 	iatp_ioctl,
221 	iatp_disable,
222 };
223 
224 struct cfattach iatp_ca = {
225 	sizeof(struct iatp_softc),
226 	iatp_match,
227 	iatp_attach,
228 	iatp_detach,
229 	iatp_activate
230 };
231 
232 struct cfdriver iatp_cd = {
233 	NULL, "iatp", DV_DULL
234 };
235 
236 int
237 iatp_match(struct device *parent, void *match, void *aux)
238 {
239 	struct i2c_attach_args *ia = aux;
240 
241 	if (strcmp(ia->ia_name, "iatp") == 0)
242 		return 1;
243 
244 	return 0;
245 }
246 
247 void
248 iatp_attach(struct device *parent, struct device *self, void *aux)
249 {
250 	struct iatp_softc *sc = (struct iatp_softc *)self;
251 	struct i2c_attach_args *ia = aux;
252 	struct wsmousedev_attach_args wsmaa;
253 
254 	sc->sc_tag = ia->ia_tag;
255 	sc->sc_addr = ia->ia_addr;
256 
257 	if (ia->ia_cookie != NULL)
258 		memcpy(&sc->sc_hid, ia->ia_cookie, sizeof(sc->sc_hid));
259 
260 	if (!iatp_init(sc))
261 		return;
262 
263 	if (ia->ia_intr) {
264 		printf(" %s", iic_intr_string(sc->sc_tag, ia->ia_intr));
265 
266 		sc->sc_ih = iic_intr_establish(sc->sc_tag, ia->ia_intr,
267 		    IPL_TTY, iatp_intr, sc, sc->sc_dev.dv_xname);
268 		if (sc->sc_ih == NULL) {
269 			printf(", can't establish interrupt\n");
270 			return;
271 		}
272 	}
273 
274 	printf(": Atmel maXTouch Touch%s (%dx%d)\n",
275 	    sc->sc_touchpad ? "pad" : "screen", sc->max_x, sc->max_y);
276 
277 	wsmaa.accessops = &iatp_accessops;
278 	wsmaa.accesscookie = sc;
279 	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
280 }
281 
282 int
283 iatp_detach(struct device *self, int flags)
284 {
285 	struct iatp_softc *sc = (struct iatp_softc *)self;
286 
287 	if (sc->sc_ih != NULL) {
288 		intr_disestablish(sc->sc_ih);
289 		sc->sc_ih = NULL;
290 	}
291 
292 	sc->sc_enabled = 0;
293 
294 	return 0;
295 }
296 
297 int
298 iatp_activate(struct device *self, int act)
299 {
300 	struct iatp_softc *sc = (struct iatp_softc *)self;
301 
302 	switch (act) {
303 	case DVACT_QUIESCE:
304 #if 0
305 		/* XXX: causes dwiic troubles */
306 		iatp_t7_set_power_mode(sc, MXT_T7_POWER_MODE_DEEP_SLEEP);
307 #endif
308 		break;
309 	case DVACT_WAKEUP:
310 		sc->sc_busy = 1;
311 		iatp_init(sc);
312 		sc->sc_busy = 0;
313 		break;
314 	}
315 
316 	config_activate_children(self, act);
317 
318 	return 0;
319 }
320 
321 int
322 iatp_configure(struct iatp_softc *sc)
323 {
324 	struct wsmousehw *hw;
325 
326 	hw = wsmouse_get_hw(sc->sc_wsmousedev);
327 	if (sc->sc_touchpad) {
328 		hw->type = WSMOUSE_TYPE_TOUCHPAD;
329 		hw->hw_type = WSMOUSEHW_CLICKPAD;
330 	} else {
331 		hw->type = WSMOUSE_TYPE_TPANEL;
332 		hw->hw_type = WSMOUSEHW_TPANEL;
333 	}
334 	hw->x_min = sc->sc_tsscale.minx;
335 	hw->x_max = sc->sc_tsscale.maxx;
336 	hw->y_min = sc->sc_tsscale.miny;
337 	hw->y_max = sc->sc_tsscale.maxy;
338 	hw->h_res = sc->sc_tsscale.resx;
339 	hw->v_res = sc->sc_tsscale.resy;
340 	hw->mt_slots = sc->num_touchids;
341 
342 	return (wsmouse_configure(sc->sc_wsmousedev, NULL, 0));
343 }
344 
345 int
346 iatp_enable(void *v)
347 {
348 	struct iatp_softc *sc = v;
349 
350 	if (sc->sc_busy &&
351 	    tsleep_nsec(&sc->sc_busy, PRIBIO, "iatp", SEC_TO_NSEC(1)) != 0) {
352 		printf("%s: trying to enable but we're busy\n",
353 		    sc->sc_dev.dv_xname);
354 		return 1;
355 	}
356 
357 	sc->sc_busy = 1;
358 
359 	DPRINTF(("%s: enabling\n", sc->sc_dev.dv_xname));
360 
361 	if (iatp_configure(sc)) {
362 		printf("%s: failed wsmouse_configure\n", sc->sc_dev.dv_xname);
363 		return 1;
364 	}
365 
366 	/* force a read of any pending messages so we start getting new
367 	 * interrupts */
368 	iatp_t5_read_msgs(sc, sc->info.max_report_id);
369 
370 	sc->sc_enabled = 1;
371 	sc->sc_busy = 0;
372 
373 	return 0;
374 }
375 
376 void
377 iatp_disable(void *v)
378 {
379 	struct iatp_softc *sc = v;
380 
381 	DPRINTF(("%s: disabling\n", sc->sc_dev.dv_xname));
382 
383 	if (sc->sc_touchpad)
384 		wsmouse_set_mode(sc->sc_wsmousedev, WSMOUSE_COMPAT);
385 
386 	sc->sc_enabled = 0;
387 }
388 
389 int
390 iatp_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
391 {
392 	struct iatp_softc *sc = v;
393 	struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
394 	int wsmode;
395 
396 	DPRINTF(("%s: %s: cmd %ld\n", sc->sc_dev.dv_xname, __func__, cmd));
397 
398 	switch (cmd) {
399 	case WSMOUSEIO_SCALIBCOORDS:
400 		sc->sc_tsscale.minx = wsmc->minx;
401 		sc->sc_tsscale.maxx = wsmc->maxx;
402 		sc->sc_tsscale.miny = wsmc->miny;
403 		sc->sc_tsscale.maxy = wsmc->maxy;
404 		sc->sc_tsscale.swapxy = wsmc->swapxy;
405 		sc->sc_tsscale.resx = wsmc->resx;
406 		sc->sc_tsscale.resy = wsmc->resy;
407 		break;
408 
409 	case WSMOUSEIO_GCALIBCOORDS:
410 		wsmc->minx = sc->sc_tsscale.minx;
411 		wsmc->maxx = sc->sc_tsscale.maxx;
412 		wsmc->miny = sc->sc_tsscale.miny;
413 		wsmc->maxy = sc->sc_tsscale.maxy;
414 		wsmc->swapxy = sc->sc_tsscale.swapxy;
415 		wsmc->resx = sc->sc_tsscale.resx;
416 		wsmc->resy = sc->sc_tsscale.resy;
417 		break;
418 
419 	case WSMOUSEIO_GTYPE: {
420 		struct wsmousehw *hw = wsmouse_get_hw(sc->sc_wsmousedev);
421 		*(u_int *)data = hw->type;
422 		break;
423 	}
424 
425 	case WSMOUSEIO_SETMODE:
426 		if (!sc->sc_touchpad)
427 			return -1;
428 
429 		wsmode = *(u_int *)data;
430 		if (wsmode != WSMOUSE_COMPAT && wsmode != WSMOUSE_NATIVE) {
431 			printf("%s: invalid mode %d\n", sc->sc_dev.dv_xname,
432 			    wsmode);
433 			return EINVAL;
434 		}
435 		wsmouse_set_mode(sc->sc_wsmousedev, wsmode);
436 		break;
437 
438 	default:
439 		return -1;
440 	}
441 
442 	return 0;
443 }
444 
445 int
446 iatp_init(struct iatp_softc *sc)
447 {
448 	uint8_t reportid;
449 	int i;
450 
451 	sc->sc_enabled = 0;
452 
453 	/* some sane defaults */
454 	sc->num_touchids = 10;
455 	sc->max_x = 1023;
456 	sc->max_y = 1023;
457 	sc->sc_touchpad = 0;
458 
459 	/*
460 	 * AT42QT1085 Information block:
461 	 *
462 	 * ID information (struct mxt_id_info)
463 	 *	0 Family ID
464 	 *	1 Variant ID
465 	 *	2 Version
466 	 *	3 Build
467 	 *	4 Number of Keys
468 	 *	5 1
469 	 *	6 Number of Object Table Elements
470 	 * Object Table Element 1 (struct mxt_object)
471 	 *	7 Object Type
472 	 *	8-9 Object Start Address
473 	 *	10 Size - 1
474 	 *	11 Instances - 1
475 	 *	12 Number of report IDs per instance
476 	 * Object Table Element 2 (struct mxt_object)
477 	 * 	...
478 	 * Information Block Checksum
479 	 * [ Object 1 ]
480 	 * ...
481 	 */
482 
483 	/* read table header */
484 	if (iatp_read_reg(sc, 0, sizeof(struct mxt_id_info), &sc->info.id) ||
485 	    !sc->info.id.num_objects) {
486 		printf("%s: failed reading main memory map\n",
487 		    sc->sc_dev.dv_xname);
488 		return 0;
489 	}
490 
491 	sc->table_size = sc->info.id.num_objects * sizeof(struct mxt_object);
492 	sc->table = malloc(sc->table_size, M_DEVBUF, M_NOWAIT | M_ZERO);
493 
494 	/* read all table objects */
495 	if (iatp_read_reg(sc, sizeof(struct mxt_id_info), sc->table_size,
496 	    sc->table)) {
497 		printf("%s: failed reading info table of size %zu\n",
498 		    sc->sc_dev.dv_xname, sc->table_size);
499 		return 0;
500 	}
501 
502 	reportid = 1;
503 	for (i = 0; i < sc->info.id.num_objects; i++) {
504 		struct mxt_object *object = (void *)(sc->table +
505 		    (sizeof(struct mxt_object) * i));
506 		int min_id = 0, max_id = 0;
507 
508 		if (object->num_report_ids) {
509 			min_id = reportid;
510 			reportid += (object->num_report_ids *
511 			    (uint8_t)MXT_INSTANCES(object));
512 			max_id = reportid - 1;
513 		}
514 
515 		DPRINTF(("%s: object[%d] T%d at 0x%x, %d report ids (%d-%d)\n",
516 		    sc->sc_dev.dv_xname, i, object->type,
517 		    le16toh(object->start_pos), object->num_report_ids, min_id,
518 		    max_id));
519 
520 		switch (object->type) {
521 		case MXT_GEN_MESSAGEPROCESSOR_T5:
522 			/*
523 			 * 4.2 - message processor is what interrupts and
524 			 * relays new messages to us
525 			 */
526 
527 			if (sc->info.id.family == 0x80 &&
528 			    sc->info.id.version < 0x20)
529 				/*
530 				 * from linux: "On mXT224 firmware versions
531 				 * prior to V2.0 read and discard unused CRC
532 				 * byte otherwise DMA reads are misaligned."
533 				 */
534 				sc->t5_msg_size = MXT_SIZE(object);
535 			else
536 				sc->t5_msg_size = MXT_SIZE(object) - 1;
537 
538 			sc->t5_address = le16toh(object->start_pos);
539 			break;
540 
541 		case MXT_GEN_COMMANDPROCESSOR_T6:
542 			/*
543 			 * 4.3 - command processor receives commands from us
544 			 * and reports command status messages
545 			 */
546 			sc->t6_address = le16toh(object->start_pos);
547 			sc->t6_reportid = min_id;
548 			break;
549 
550 		case MXT_GEN_POWERCONFIG_T7:
551 			/*
552 			 * 4.4 - power configuration, number of milliseconds
553 			 * between sampling in each mode
554 			 */
555 			sc->t7_address = le16toh(object->start_pos);
556 
557 			iatp_read_reg(sc, sc->t7_address,
558 			    sizeof(sc->t7_config), &sc->t7_config);
559 
560 			break;
561 
562 		case MXT_SPT_GPIOPWM_T19: {
563 			/*
564 			 * generic gpio pin, mapped to touchpad button(s)
565 			 */
566 			const struct mxt_t19_button_map *m;
567 
568 			sc->t19_reportid = min_id;
569 
570 			/* find this machine's button config */
571 			sc->t19_button_bit = -1;
572 			if (hw_vendor == NULL || hw_prod == NULL)
573 				break;
574 
575 			for (m = mxt_t19_button_map_devs; m->vendor != NULL;
576 			    m++) {
577 				if (strncmp(hw_vendor, m->vendor,
578 				    strlen(m->vendor)) != 0 ||
579 				    strncmp(hw_prod, m->product,
580 				    strlen(m->product)) != 0 ||
581 				    strncmp(sc->sc_hid, m->hid,
582 				    strlen(m->hid)) != 0)
583 					continue;
584 
585 				DPRINTF(("%s: found matching t19 "
586 				    "button map device \"%s\"/\"%s\" on %s: "
587 				    "bit %d\n", sc->sc_dev.dv_xname,
588 				    m->vendor, m->product, m->hid, m->bit));
589 				sc->t19_button_bit = m->bit;
590 				break;
591 			}
592 
593 			if (sc->t19_button_bit > -1)
594 				sc->sc_touchpad = 1;
595 
596 			break;
597 		}
598 
599 		case MXT_SPT_MESSAGECOUNT_T44:
600 			sc->t44_address = le16toh(object->start_pos);
601 			break;
602 
603 		case MXT_TOUCH_MULTITOUCHSCREEN_T100: {
604 			uint16_t range_x, range_y;
605 			uint8_t orient, tchaux;
606 			int aux;
607 
608 			sc->t100_reportid_min = min_id;
609 			sc->t100_reportid_max = max_id;
610 			sc->num_touchids = object->num_report_ids - 2;
611 			sc->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100;
612 
613 			if (iatp_read_reg(sc, object->start_pos +
614 			    MXT_T100_XRANGE, sizeof(range_x), &range_x) ||
615 			    iatp_read_reg(sc, object->start_pos +
616 			    MXT_T100_YRANGE, sizeof(range_y), &range_y) ||
617 			    iatp_read_reg(sc, object->start_pos +
618 			    MXT_T100_CFG1, 1, &orient) ||
619 			    iatp_read_reg(sc, object->start_pos +
620 			    MXT_T100_TCHAUX, 1, &tchaux)) {
621 				printf("%s: failed reading t100 settings\n",
622 				    sc->sc_dev.dv_xname);
623 				continue;
624 			}
625 
626 			/*
627 			 * orient just affects the size we read, not the x/y
628 			 * values we read per-packet later.
629 			 */
630 			if (orient & MXT_T100_CFG_SWITCHXY) {
631 				sc->max_x = le16toh(range_y);
632 				sc->max_y = le16toh(range_x);
633 			} else {
634 				sc->max_x = le16toh(range_x);
635 				sc->max_y = le16toh(range_y);
636 			}
637 
638 			aux = 6;
639 			if (tchaux & MXT_T100_TCHAUX_VECT)
640 				sc->t100_aux_vect = aux++;
641 			if (tchaux & MXT_T100_TCHAUX_AMPL)
642 				sc->t100_aux_ampl = aux++;
643 			if (tchaux & MXT_T100_TCHAUX_AREA)
644 				sc->t100_aux_area = aux++;
645 			break;
646 		}
647 		}
648 	}
649 
650 	sc->info.max_report_id = reportid;
651 
652 	sc->sc_tsscale.minx = 0;
653 	sc->sc_tsscale.maxx = sc->max_x;
654 	sc->sc_tsscale.miny = 0;
655 	sc->sc_tsscale.maxy = sc->max_y;
656 	sc->sc_tsscale.swapxy = 0;
657 	sc->sc_tsscale.resx = 0;
658 	sc->sc_tsscale.resy = 0;
659 
660 	/*
661 	 * iatp_t44_read_count expects t5 message processor to immediately
662 	 * follow t44 message count byte
663 	 */
664 	if (sc->t44_address && (sc->t5_address != sc->t44_address + 1)) {
665 		printf("%s: t5 address (0x%x) != t44 (0x%x + 1)\n",
666 		    sc->sc_dev.dv_xname, sc->t5_address, sc->t44_address);
667 		return 0;
668 	}
669 
670 	sc->msg_buf = mallocarray(sc->info.max_report_id, sc->t5_msg_size,
671 	    M_DEVBUF, M_NOWAIT | M_ZERO);
672 
673 	/* flush queue of any pending messages */
674 	iatp_t5_read_msgs(sc, sc->info.max_report_id);
675 
676 	return 1;
677 }
678 
679 int
680 iatp_read_reg(struct iatp_softc *sc, uint16_t reg, size_t len, void *val)
681 {
682 	uint8_t cmd[2] = { reg & 0xff, (reg >> 8) & 0xff };
683 	int ret;
684 
685 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
686 
687 	ret = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd,
688 	    sizeof(cmd), val, len, I2C_F_POLL);
689 
690 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
691 
692 	return ret;
693 }
694 
695 int
696 iatp_write_reg(struct iatp_softc *sc, uint16_t reg, size_t len, void *val)
697 {
698 	int ret;
699 	uint8_t *cmd;
700 
701 	cmd = malloc(len + 2, M_DEVBUF, M_NOWAIT | M_ZERO);
702 	cmd[0] = reg & 0xff;
703 	cmd[1] = (reg >> 8) & 0xff;
704 	memcpy(&cmd[2], val, len);
705 
706 	iic_acquire_bus(sc->sc_tag, 0);
707 
708 	ret = iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_addr, cmd, len + 2,
709 	    NULL, 0, I2C_F_POLL);
710 
711 	iic_release_bus(sc->sc_tag, 0);
712 
713 	free(cmd, M_DEVBUF, len + 2);
714 
715 	return ret;
716 }
717 
718 int
719 iatp_intr(void *arg)
720 {
721 	struct iatp_softc *sc = arg;
722 	int count;
723 
724 	DPRINTF(("%s: %s (busy:%d enabled:%d)\n", sc->sc_dev.dv_xname,
725 	    __func__, sc->sc_busy, sc->sc_enabled));
726 
727 	if (sc->sc_busy)
728 		return 1;
729 
730 	sc->sc_busy = 1;
731 
732 	if (sc->t44_address)
733 		count = iatp_t44_read_count(sc);
734 	else
735 		count = 1;
736 
737 	if (count)
738 		iatp_t5_read_msgs(sc, count);
739 
740 	sc->sc_busy = 0;
741 	wakeup(&sc->sc_busy);
742 
743 	return 1;
744 }
745 
746 int
747 iatp_proc_msg(struct iatp_softc *sc, uint8_t *msg)
748 {
749 	uint8_t report_id = msg[0];
750 	int i;
751 
752 	/* process a single message that has already been read off the wire */
753 
754 	if (report_id == 0xff)
755 		/*
756 		 * this is usually when we've intentionally over-read just to
757 		 * clear any pending data to keep interrupts flowing
758 		 */
759 		return 0;
760 
761 	DPRINTF(("%s: %s: report id %d\n", sc->sc_dev.dv_xname, __func__,
762 	    report_id));
763 
764 	if (report_id == sc->t19_reportid)
765 		iatp_t19_proc_msg(sc, msg);
766 	else if (report_id >= sc->t100_reportid_min &&
767 	    report_id <= sc->t100_reportid_max)
768 		iatp_t100_proc_msg(sc, msg);
769 	else {
770 		DPRINTF(("%s: unknown message (report id %d)",
771 		    sc->sc_dev.dv_xname, report_id));
772 		for (i = 0; i < sc->t5_msg_size; i++)
773 			DPRINTF((" %02x", msg[i]));
774 		DPRINTF(("\n"));
775 	}
776 
777 	return 1;
778 }
779 
780 int
781 iatp_t5_read_msgs(struct iatp_softc *sc, int count)
782 {
783 	int i;
784 
785 	if (count > sc->info.max_report_id) {
786 		DPRINTF(("%s: clamping count %d to max_report_id %d\n",
787 		    sc->sc_dev.dv_xname, count, sc->info.max_report_id));
788 		count = sc->info.max_report_id;
789 	}
790 
791 	DPRINTF(("%s: %s: %d message(s) to read\n", sc->sc_dev.dv_xname,
792 	    __func__, count));
793 
794 	if (iatp_read_reg(sc, sc->t5_address, sc->t5_msg_size * count,
795 	    sc->msg_buf)) {
796 		printf("%s: failed reading %d\n", sc->sc_dev.dv_xname,
797 		    sc->t5_msg_size * count);
798 		return 0;
799 	}
800 
801 	for (i = 0;  i < count; i++)
802 		iatp_proc_msg(sc, sc->msg_buf + (sc->t5_msg_size * i));
803 
804 	return 1;
805 }
806 
807 void
808 iatp_t6_proc_msg(struct iatp_softc *sc, uint8_t *msg)
809 {
810 	uint8_t status = msg[1];
811 
812 	if (status & MXT_T6_STATUS_RESET)
813 		DPRINTF(("%s: completed reset\n", sc->sc_dev.dv_xname));
814 	else
815 		DPRINTF(("%s: other status report 0x%x\n", sc->sc_dev.dv_xname,
816 		    status));
817 }
818 
819 int
820 iatp_t7_set_power_mode(struct iatp_softc *sc, int mode)
821 {
822 	struct mxt_t7_config new_config;
823 
824 	if (mode == MXT_T7_POWER_MODE_DEEP_SLEEP) {
825 		new_config.idle = 0;
826 		new_config.active = 0;
827 		new_config.atoi_timeout = 0;
828 	} else
829 		new_config = sc->t7_config;
830 
831 	DPRINTF(("%s: setting power mode to %d\n", sc->sc_dev.dv_xname, mode));
832 
833 	if (iatp_write_reg(sc, sc->t7_address, sizeof(new_config),
834 	    &new_config)) {
835 		printf("%s: failed setting power mode to %d\n",
836 		    sc->sc_dev.dv_xname, mode);
837 		return 1;
838 	}
839 
840 	return 0;
841 }
842 
843 void
844 iatp_t19_proc_msg(struct iatp_softc *sc, uint8_t *msg)
845 {
846 	int s;
847 
848 	if (!sc->sc_enabled)
849 		return;
850 
851 	/* active-low switch */
852 	sc->button = !(msg[1] & (1 << sc->t19_button_bit));
853 
854 	DPRINTF(("%s: button is %d\n", sc->sc_dev.dv_xname, sc->button));
855 
856 	s = spltty();
857 	wsmouse_buttons(sc->sc_wsmousedev, sc->button);
858 	wsmouse_input_sync(sc->sc_wsmousedev);
859 	splx(s);
860 }
861 
862 int
863 iatp_t44_read_count(struct iatp_softc *sc)
864 {
865 	int ret, count;
866 
867 	/* read t44 count byte and t5 message data in one shot */
868 	ret = iatp_read_reg(sc, sc->t44_address, 1 + sc->t5_msg_size,
869 	    sc->msg_buf);
870 	if (ret) {
871 		printf("%s: failed reading t44 and t5\n", sc->sc_dev.dv_xname);
872 		return 0;
873 	}
874 
875 	count = sc->msg_buf[0];
876 	if (count == 0) {
877 		DPRINTF(("%s: %s: no messages\n", sc->sc_dev.dv_xname,
878 		    __func__));
879 		/* flush so we keep getting interrupts */
880 		iatp_t5_read_msgs(sc, sc->info.max_report_id);
881 		return 0;
882 	}
883 
884 	count--;
885 	iatp_proc_msg(sc, sc->msg_buf + 1);
886 
887 	return count;
888 }
889 
890 void
891 iatp_t100_proc_msg(struct iatp_softc *sc, uint8_t *msg)
892 {
893 	int id = msg[0] - sc->t100_reportid_min - 2;
894 	int s;
895 	uint8_t status, type = 0, pressure = 0;
896 	uint16_t x, y;
897 
898 	if (id < 0 || !sc->sc_enabled)
899 		return;
900 
901 	status = msg[1];
902 	x = (msg[3] << 8) | msg[2];
903 	y = (msg[5] << 8) | msg[4];
904 
905 	if (status & MXT_T100_DETECT) {
906 		type = (status & MXT_T100_TYPE_MASK) >> 4;
907 
908 		if (sc->t100_aux_ampl)
909 			pressure = msg[sc->t100_aux_ampl];
910 
911 		if (!pressure && type != MXT_T100_TYPE_HOVERING_FINGER)
912 			pressure = 50; /* large enough for synaptics driver */
913 
914 		DPRINTF(("%s: type=%d x=%d y=%d finger=%d pressure=%d "
915 		    "button=%d\n", sc->sc_dev.dv_xname, type, x, y, id,
916 		    pressure, sc->button));
917 	} else {
918 		DPRINTF(("%s: closing slot for finger=%d\n",
919 		    sc->sc_dev.dv_xname, id));
920 
921 		if (sc->sc_touchpad)
922 			x = y = 0;
923 
924 		pressure = 0;
925 	}
926 
927 	if (sc->sc_touchpad)
928 		y = (sc->max_y - y);
929 
930 	/* TODO: adjust to sc_tsscale? */
931 
932 	s = spltty();
933 
934 	wsmouse_mtstate(sc->sc_wsmousedev, id, x, y, pressure);
935 
936 	/* on the touchscreen, assume any finger down is clicking */
937 	if (!sc->sc_touchpad)
938 		wsmouse_buttons(sc->sc_wsmousedev, pressure ? 1 : 0);
939 
940 	wsmouse_input_sync(sc->sc_wsmousedev);
941 
942 	splx(s);
943 }
944