xref: /openbsd/sys/dev/i2c/iatp.c (revision 73910b96)
1 /* $OpenBSD: iatp.c,v 1.11 2024/08/19 14:24:24 deraadt 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 const struct wsmouse_accessops iatp_accessops = {
216 	iatp_enable,
217 	iatp_ioctl,
218 	iatp_disable,
219 };
220 
221 const struct cfattach iatp_ca = {
222 	sizeof(struct iatp_softc),
223 	iatp_match,
224 	iatp_attach,
225 	iatp_detach,
226 	iatp_activate
227 };
228 
229 struct cfdriver iatp_cd = {
230 	NULL, "iatp", DV_DULL
231 };
232 
233 int
iatp_match(struct device * parent,void * match,void * aux)234 iatp_match(struct device *parent, void *match, void *aux)
235 {
236 	struct i2c_attach_args *ia = aux;
237 
238 	if (strcmp(ia->ia_name, "iatp") == 0)
239 		return 1;
240 
241 	return 0;
242 }
243 
244 void
iatp_attach(struct device * parent,struct device * self,void * aux)245 iatp_attach(struct device *parent, struct device *self, void *aux)
246 {
247 	struct iatp_softc *sc = (struct iatp_softc *)self;
248 	struct i2c_attach_args *ia = aux;
249 	struct wsmousedev_attach_args wsmaa;
250 
251 	sc->sc_tag = ia->ia_tag;
252 	sc->sc_addr = ia->ia_addr;
253 
254 	if (ia->ia_cookie != NULL)
255 		memcpy(&sc->sc_hid, ia->ia_cookie, sizeof(sc->sc_hid));
256 
257 	if (!iatp_init(sc))
258 		return;
259 
260 	if (ia->ia_intr) {
261 		printf(" %s", iic_intr_string(sc->sc_tag, ia->ia_intr));
262 
263 		sc->sc_ih = iic_intr_establish(sc->sc_tag, ia->ia_intr,
264 		    IPL_TTY, iatp_intr, sc, sc->sc_dev.dv_xname);
265 		if (sc->sc_ih == NULL) {
266 			printf(", can't establish interrupt\n");
267 			return;
268 		}
269 	}
270 
271 	printf(": Atmel maXTouch Touch%s (%dx%d)\n",
272 	    sc->sc_touchpad ? "pad" : "screen", sc->max_x, sc->max_y);
273 
274 	wsmaa.accessops = &iatp_accessops;
275 	wsmaa.accesscookie = sc;
276 	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
277 }
278 
279 int
iatp_detach(struct device * self,int flags)280 iatp_detach(struct device *self, int flags)
281 {
282 	struct iatp_softc *sc = (struct iatp_softc *)self;
283 
284 	if (sc->sc_ih != NULL) {
285 		intr_disestablish(sc->sc_ih);
286 		sc->sc_ih = NULL;
287 	}
288 
289 	sc->sc_enabled = 0;
290 
291 	return 0;
292 }
293 
294 int
iatp_activate(struct device * self,int act)295 iatp_activate(struct device *self, int act)
296 {
297 	struct iatp_softc *sc = (struct iatp_softc *)self;
298 	int rv;
299 
300 	switch (act) {
301 	case DVACT_QUIESCE:
302 		rv = config_activate_children(self, act);
303 		iatp_t7_set_power_mode(sc, MXT_T7_POWER_MODE_DEEP_SLEEP);
304 		break;
305 	case DVACT_WAKEUP:
306 		sc->sc_busy = 1;
307 		iatp_init(sc);
308 		sc->sc_busy = 0;
309 		rv = config_activate_children(self, act);
310 		break;
311 	default:
312 		rv = config_activate_children(self, act);
313 		break;
314 	}
315 	return rv;
316 }
317 
318 int
iatp_configure(struct iatp_softc * sc)319 iatp_configure(struct iatp_softc *sc)
320 {
321 	struct wsmousehw *hw;
322 
323 	hw = wsmouse_get_hw(sc->sc_wsmousedev);
324 	if (sc->sc_touchpad) {
325 		hw->type = WSMOUSE_TYPE_TOUCHPAD;
326 		hw->hw_type = WSMOUSEHW_CLICKPAD;
327 	} else {
328 		hw->type = WSMOUSE_TYPE_TPANEL;
329 		hw->hw_type = WSMOUSEHW_TPANEL;
330 	}
331 	hw->x_min = sc->sc_tsscale.minx;
332 	hw->x_max = sc->sc_tsscale.maxx;
333 	hw->y_min = sc->sc_tsscale.miny;
334 	hw->y_max = sc->sc_tsscale.maxy;
335 	hw->h_res = sc->sc_tsscale.resx;
336 	hw->v_res = sc->sc_tsscale.resy;
337 	hw->mt_slots = sc->num_touchids;
338 
339 	return (wsmouse_configure(sc->sc_wsmousedev, NULL, 0));
340 }
341 
342 int
iatp_enable(void * v)343 iatp_enable(void *v)
344 {
345 	struct iatp_softc *sc = v;
346 
347 	if (sc->sc_busy &&
348 	    tsleep_nsec(&sc->sc_busy, PRIBIO, "iatp", SEC_TO_NSEC(1)) != 0) {
349 		printf("%s: trying to enable but we're busy\n",
350 		    sc->sc_dev.dv_xname);
351 		return 1;
352 	}
353 
354 	sc->sc_busy = 1;
355 
356 	DPRINTF(("%s: enabling\n", sc->sc_dev.dv_xname));
357 
358 	if (iatp_configure(sc)) {
359 		printf("%s: failed wsmouse_configure\n", sc->sc_dev.dv_xname);
360 		return 1;
361 	}
362 
363 	/* force a read of any pending messages so we start getting new
364 	 * interrupts */
365 	iatp_t5_read_msgs(sc, sc->info.max_report_id);
366 
367 	sc->sc_enabled = 1;
368 	sc->sc_busy = 0;
369 
370 	return 0;
371 }
372 
373 void
iatp_disable(void * v)374 iatp_disable(void *v)
375 {
376 	struct iatp_softc *sc = v;
377 
378 	DPRINTF(("%s: disabling\n", sc->sc_dev.dv_xname));
379 
380 	if (sc->sc_touchpad)
381 		wsmouse_set_mode(sc->sc_wsmousedev, WSMOUSE_COMPAT);
382 
383 	sc->sc_enabled = 0;
384 }
385 
386 int
iatp_ioctl(void * v,u_long cmd,caddr_t data,int flag,struct proc * p)387 iatp_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
388 {
389 	struct iatp_softc *sc = v;
390 	struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
391 	int wsmode;
392 
393 	DPRINTF(("%s: %s: cmd %ld\n", sc->sc_dev.dv_xname, __func__, cmd));
394 
395 	switch (cmd) {
396 	case WSMOUSEIO_SCALIBCOORDS:
397 		sc->sc_tsscale.minx = wsmc->minx;
398 		sc->sc_tsscale.maxx = wsmc->maxx;
399 		sc->sc_tsscale.miny = wsmc->miny;
400 		sc->sc_tsscale.maxy = wsmc->maxy;
401 		sc->sc_tsscale.swapxy = wsmc->swapxy;
402 		sc->sc_tsscale.resx = wsmc->resx;
403 		sc->sc_tsscale.resy = wsmc->resy;
404 		break;
405 
406 	case WSMOUSEIO_GCALIBCOORDS:
407 		wsmc->minx = sc->sc_tsscale.minx;
408 		wsmc->maxx = sc->sc_tsscale.maxx;
409 		wsmc->miny = sc->sc_tsscale.miny;
410 		wsmc->maxy = sc->sc_tsscale.maxy;
411 		wsmc->swapxy = sc->sc_tsscale.swapxy;
412 		wsmc->resx = sc->sc_tsscale.resx;
413 		wsmc->resy = sc->sc_tsscale.resy;
414 		break;
415 
416 	case WSMOUSEIO_GTYPE: {
417 		struct wsmousehw *hw = wsmouse_get_hw(sc->sc_wsmousedev);
418 		*(u_int *)data = hw->type;
419 		break;
420 	}
421 
422 	case WSMOUSEIO_SETMODE:
423 		if (!sc->sc_touchpad)
424 			return -1;
425 
426 		wsmode = *(u_int *)data;
427 		if (wsmode != WSMOUSE_COMPAT && wsmode != WSMOUSE_NATIVE) {
428 			printf("%s: invalid mode %d\n", sc->sc_dev.dv_xname,
429 			    wsmode);
430 			return EINVAL;
431 		}
432 		wsmouse_set_mode(sc->sc_wsmousedev, wsmode);
433 		break;
434 
435 	default:
436 		return -1;
437 	}
438 
439 	return 0;
440 }
441 
442 int
iatp_init(struct iatp_softc * sc)443 iatp_init(struct iatp_softc *sc)
444 {
445 	uint8_t reportid;
446 	int i;
447 
448 	sc->sc_enabled = 0;
449 
450 	/* some sane defaults */
451 	sc->num_touchids = 10;
452 	sc->max_x = 1023;
453 	sc->max_y = 1023;
454 	sc->sc_touchpad = 0;
455 
456 	/*
457 	 * AT42QT1085 Information block:
458 	 *
459 	 * ID information (struct mxt_id_info)
460 	 *	0 Family ID
461 	 *	1 Variant ID
462 	 *	2 Version
463 	 *	3 Build
464 	 *	4 Number of Keys
465 	 *	5 1
466 	 *	6 Number of Object Table Elements
467 	 * Object Table Element 1 (struct mxt_object)
468 	 *	7 Object Type
469 	 *	8-9 Object Start Address
470 	 *	10 Size - 1
471 	 *	11 Instances - 1
472 	 *	12 Number of report IDs per instance
473 	 * Object Table Element 2 (struct mxt_object)
474 	 * 	...
475 	 * Information Block Checksum
476 	 * [ Object 1 ]
477 	 * ...
478 	 */
479 
480 	/* read table header */
481 	if (iatp_read_reg(sc, 0, sizeof(struct mxt_id_info), &sc->info.id) ||
482 	    !sc->info.id.num_objects) {
483 		printf("%s: failed reading main memory map\n",
484 		    sc->sc_dev.dv_xname);
485 		return 0;
486 	}
487 
488 	sc->table_size = sc->info.id.num_objects * sizeof(struct mxt_object);
489 	sc->table = malloc(sc->table_size, M_DEVBUF, M_NOWAIT | M_ZERO);
490 
491 	/* read all table objects */
492 	if (iatp_read_reg(sc, sizeof(struct mxt_id_info), sc->table_size,
493 	    sc->table)) {
494 		printf("%s: failed reading info table of size %zu\n",
495 		    sc->sc_dev.dv_xname, sc->table_size);
496 		return 0;
497 	}
498 
499 	reportid = 1;
500 	for (i = 0; i < sc->info.id.num_objects; i++) {
501 		struct mxt_object *object = (void *)(sc->table +
502 		    (sizeof(struct mxt_object) * i));
503 		int min_id = 0, max_id = 0;
504 
505 		if (object->num_report_ids) {
506 			min_id = reportid;
507 			reportid += (object->num_report_ids *
508 			    (uint8_t)MXT_INSTANCES(object));
509 			max_id = reportid - 1;
510 		}
511 
512 		DPRINTF(("%s: object[%d] T%d at 0x%x, %d report ids (%d-%d)\n",
513 		    sc->sc_dev.dv_xname, i, object->type,
514 		    le16toh(object->start_pos), object->num_report_ids, min_id,
515 		    max_id));
516 
517 		switch (object->type) {
518 		case MXT_GEN_MESSAGEPROCESSOR_T5:
519 			/*
520 			 * 4.2 - message processor is what interrupts and
521 			 * relays new messages to us
522 			 */
523 
524 			if (sc->info.id.family == 0x80 &&
525 			    sc->info.id.version < 0x20)
526 				/*
527 				 * from linux: "On mXT224 firmware versions
528 				 * prior to V2.0 read and discard unused CRC
529 				 * byte otherwise DMA reads are misaligned."
530 				 */
531 				sc->t5_msg_size = MXT_SIZE(object);
532 			else
533 				sc->t5_msg_size = MXT_SIZE(object) - 1;
534 
535 			sc->t5_address = le16toh(object->start_pos);
536 			break;
537 
538 		case MXT_GEN_COMMANDPROCESSOR_T6:
539 			/*
540 			 * 4.3 - command processor receives commands from us
541 			 * and reports command status messages
542 			 */
543 			sc->t6_address = le16toh(object->start_pos);
544 			sc->t6_reportid = min_id;
545 			break;
546 
547 		case MXT_GEN_POWERCONFIG_T7:
548 			/*
549 			 * 4.4 - power configuration, number of milliseconds
550 			 * between sampling in each mode
551 			 */
552 			sc->t7_address = le16toh(object->start_pos);
553 
554 			iatp_read_reg(sc, sc->t7_address,
555 			    sizeof(sc->t7_config), &sc->t7_config);
556 
557 			break;
558 
559 		case MXT_SPT_GPIOPWM_T19: {
560 			/*
561 			 * generic gpio pin, mapped to touchpad button(s)
562 			 */
563 			const struct mxt_t19_button_map *m;
564 
565 			sc->t19_reportid = min_id;
566 
567 			/* find this machine's button config */
568 			sc->t19_button_bit = -1;
569 			if (hw_vendor == NULL || hw_prod == NULL)
570 				break;
571 
572 			for (m = mxt_t19_button_map_devs; m->vendor != NULL;
573 			    m++) {
574 				if (strncmp(hw_vendor, m->vendor,
575 				    strlen(m->vendor)) != 0 ||
576 				    strncmp(hw_prod, m->product,
577 				    strlen(m->product)) != 0 ||
578 				    strncmp(sc->sc_hid, m->hid,
579 				    strlen(m->hid)) != 0)
580 					continue;
581 
582 				DPRINTF(("%s: found matching t19 "
583 				    "button map device \"%s\"/\"%s\" on %s: "
584 				    "bit %d\n", sc->sc_dev.dv_xname,
585 				    m->vendor, m->product, m->hid, m->bit));
586 				sc->t19_button_bit = m->bit;
587 				break;
588 			}
589 
590 			if (sc->t19_button_bit > -1)
591 				sc->sc_touchpad = 1;
592 
593 			break;
594 		}
595 
596 		case MXT_SPT_MESSAGECOUNT_T44:
597 			sc->t44_address = le16toh(object->start_pos);
598 			break;
599 
600 		case MXT_TOUCH_MULTITOUCHSCREEN_T100: {
601 			uint16_t range_x, range_y;
602 			uint8_t orient, tchaux;
603 			int aux;
604 
605 			sc->t100_reportid_min = min_id;
606 			sc->t100_reportid_max = max_id;
607 			sc->num_touchids = object->num_report_ids - 2;
608 			sc->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100;
609 
610 			if (iatp_read_reg(sc, object->start_pos +
611 			    MXT_T100_XRANGE, sizeof(range_x), &range_x) ||
612 			    iatp_read_reg(sc, object->start_pos +
613 			    MXT_T100_YRANGE, sizeof(range_y), &range_y) ||
614 			    iatp_read_reg(sc, object->start_pos +
615 			    MXT_T100_CFG1, 1, &orient) ||
616 			    iatp_read_reg(sc, object->start_pos +
617 			    MXT_T100_TCHAUX, 1, &tchaux)) {
618 				printf("%s: failed reading t100 settings\n",
619 				    sc->sc_dev.dv_xname);
620 				continue;
621 			}
622 
623 			/*
624 			 * orient just affects the size we read, not the x/y
625 			 * values we read per-packet later.
626 			 */
627 			if (orient & MXT_T100_CFG_SWITCHXY) {
628 				sc->max_x = le16toh(range_y);
629 				sc->max_y = le16toh(range_x);
630 			} else {
631 				sc->max_x = le16toh(range_x);
632 				sc->max_y = le16toh(range_y);
633 			}
634 
635 			aux = 6;
636 			if (tchaux & MXT_T100_TCHAUX_VECT)
637 				sc->t100_aux_vect = aux++;
638 			if (tchaux & MXT_T100_TCHAUX_AMPL)
639 				sc->t100_aux_ampl = aux++;
640 			if (tchaux & MXT_T100_TCHAUX_AREA)
641 				sc->t100_aux_area = aux++;
642 			break;
643 		}
644 		}
645 	}
646 
647 	sc->info.max_report_id = reportid;
648 
649 	sc->sc_tsscale.minx = 0;
650 	sc->sc_tsscale.maxx = sc->max_x;
651 	sc->sc_tsscale.miny = 0;
652 	sc->sc_tsscale.maxy = sc->max_y;
653 	sc->sc_tsscale.swapxy = 0;
654 	sc->sc_tsscale.resx = 0;
655 	sc->sc_tsscale.resy = 0;
656 
657 	/*
658 	 * iatp_t44_read_count expects t5 message processor to immediately
659 	 * follow t44 message count byte
660 	 */
661 	if (sc->t44_address && (sc->t5_address != sc->t44_address + 1)) {
662 		printf("%s: t5 address (0x%x) != t44 (0x%x + 1)\n",
663 		    sc->sc_dev.dv_xname, sc->t5_address, sc->t44_address);
664 		return 0;
665 	}
666 
667 	sc->msg_buf = mallocarray(sc->info.max_report_id, sc->t5_msg_size,
668 	    M_DEVBUF, M_NOWAIT | M_ZERO);
669 
670 	/* flush queue of any pending messages */
671 	iatp_t5_read_msgs(sc, sc->info.max_report_id);
672 
673 	return 1;
674 }
675 
676 int
iatp_read_reg(struct iatp_softc * sc,uint16_t reg,size_t len,void * val)677 iatp_read_reg(struct iatp_softc *sc, uint16_t reg, size_t len, void *val)
678 {
679 	uint8_t cmd[2] = { reg & 0xff, (reg >> 8) & 0xff };
680 	int ret;
681 
682 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
683 
684 	ret = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd,
685 	    sizeof(cmd), val, len, I2C_F_POLL);
686 
687 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
688 
689 	return ret;
690 }
691 
692 int
iatp_write_reg(struct iatp_softc * sc,uint16_t reg,size_t len,void * val)693 iatp_write_reg(struct iatp_softc *sc, uint16_t reg, size_t len, void *val)
694 {
695 	int ret;
696 	uint8_t *cmd;
697 
698 	cmd = malloc(len + 2, M_DEVBUF, M_NOWAIT | M_ZERO);
699 	cmd[0] = reg & 0xff;
700 	cmd[1] = (reg >> 8) & 0xff;
701 	memcpy(&cmd[2], val, len);
702 
703 	iic_acquire_bus(sc->sc_tag, 0);
704 
705 	ret = iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_addr, cmd, len + 2,
706 	    NULL, 0, I2C_F_POLL);
707 
708 	iic_release_bus(sc->sc_tag, 0);
709 
710 	free(cmd, M_DEVBUF, len + 2);
711 
712 	return ret;
713 }
714 
715 int
iatp_intr(void * arg)716 iatp_intr(void *arg)
717 {
718 	struct iatp_softc *sc = arg;
719 	int count;
720 
721 	DPRINTF(("%s: %s (busy:%d enabled:%d)\n", sc->sc_dev.dv_xname,
722 	    __func__, sc->sc_busy, sc->sc_enabled));
723 
724 	if (sc->sc_busy)
725 		return 1;
726 
727 	sc->sc_busy = 1;
728 
729 	if (sc->t44_address)
730 		count = iatp_t44_read_count(sc);
731 	else
732 		count = 1;
733 
734 	if (count)
735 		iatp_t5_read_msgs(sc, count);
736 
737 	sc->sc_busy = 0;
738 	wakeup(&sc->sc_busy);
739 
740 	return 1;
741 }
742 
743 int
iatp_proc_msg(struct iatp_softc * sc,uint8_t * msg)744 iatp_proc_msg(struct iatp_softc *sc, uint8_t *msg)
745 {
746 	uint8_t report_id = msg[0];
747 	int i;
748 
749 	/* process a single message that has already been read off the wire */
750 
751 	if (report_id == 0xff)
752 		/*
753 		 * this is usually when we've intentionally over-read just to
754 		 * clear any pending data to keep interrupts flowing
755 		 */
756 		return 0;
757 
758 	DPRINTF(("%s: %s: report id %d\n", sc->sc_dev.dv_xname, __func__,
759 	    report_id));
760 
761 	if (report_id == sc->t19_reportid)
762 		iatp_t19_proc_msg(sc, msg);
763 	else if (report_id >= sc->t100_reportid_min &&
764 	    report_id <= sc->t100_reportid_max)
765 		iatp_t100_proc_msg(sc, msg);
766 	else {
767 		DPRINTF(("%s: unknown message (report id %d)",
768 		    sc->sc_dev.dv_xname, report_id));
769 		for (i = 0; i < sc->t5_msg_size; i++)
770 			DPRINTF((" %02x", msg[i]));
771 		DPRINTF(("\n"));
772 	}
773 
774 	return 1;
775 }
776 
777 int
iatp_t5_read_msgs(struct iatp_softc * sc,int count)778 iatp_t5_read_msgs(struct iatp_softc *sc, int count)
779 {
780 	int i;
781 
782 	if (count > sc->info.max_report_id) {
783 		DPRINTF(("%s: clamping count %d to max_report_id %d\n",
784 		    sc->sc_dev.dv_xname, count, sc->info.max_report_id));
785 		count = sc->info.max_report_id;
786 	}
787 
788 	DPRINTF(("%s: %s: %d message(s) to read\n", sc->sc_dev.dv_xname,
789 	    __func__, count));
790 
791 	if (iatp_read_reg(sc, sc->t5_address, sc->t5_msg_size * count,
792 	    sc->msg_buf)) {
793 		printf("%s: failed reading %d\n", sc->sc_dev.dv_xname,
794 		    sc->t5_msg_size * count);
795 		return 0;
796 	}
797 
798 	for (i = 0;  i < count; i++)
799 		iatp_proc_msg(sc, sc->msg_buf + (sc->t5_msg_size * i));
800 
801 	return 1;
802 }
803 
804 void
iatp_t6_proc_msg(struct iatp_softc * sc,uint8_t * msg)805 iatp_t6_proc_msg(struct iatp_softc *sc, uint8_t *msg)
806 {
807 	uint8_t status = msg[1];
808 
809 	if (status & MXT_T6_STATUS_RESET)
810 		DPRINTF(("%s: completed reset\n", sc->sc_dev.dv_xname));
811 	else
812 		DPRINTF(("%s: other status report 0x%x\n", sc->sc_dev.dv_xname,
813 		    status));
814 }
815 
816 int
iatp_t7_set_power_mode(struct iatp_softc * sc,int mode)817 iatp_t7_set_power_mode(struct iatp_softc *sc, int mode)
818 {
819 	struct mxt_t7_config new_config;
820 
821 	if (mode == MXT_T7_POWER_MODE_DEEP_SLEEP) {
822 		new_config.idle = 0;
823 		new_config.active = 0;
824 		new_config.atoi_timeout = 0;
825 	} else
826 		new_config = sc->t7_config;
827 
828 	DPRINTF(("%s: setting power mode to %d\n", sc->sc_dev.dv_xname, mode));
829 
830 	if (iatp_write_reg(sc, sc->t7_address, sizeof(new_config),
831 	    &new_config)) {
832 		printf("%s: failed setting power mode to %d\n",
833 		    sc->sc_dev.dv_xname, mode);
834 		return 1;
835 	}
836 
837 	return 0;
838 }
839 
840 void
iatp_t19_proc_msg(struct iatp_softc * sc,uint8_t * msg)841 iatp_t19_proc_msg(struct iatp_softc *sc, uint8_t *msg)
842 {
843 	int s;
844 
845 	if (!sc->sc_enabled)
846 		return;
847 
848 	/* active-low switch */
849 	sc->button = !(msg[1] & (1 << sc->t19_button_bit));
850 
851 	DPRINTF(("%s: button is %d\n", sc->sc_dev.dv_xname, sc->button));
852 
853 	s = spltty();
854 	wsmouse_buttons(sc->sc_wsmousedev, sc->button);
855 	wsmouse_input_sync(sc->sc_wsmousedev);
856 	splx(s);
857 }
858 
859 int
iatp_t44_read_count(struct iatp_softc * sc)860 iatp_t44_read_count(struct iatp_softc *sc)
861 {
862 	int ret, count;
863 
864 	/* read t44 count byte and t5 message data in one shot */
865 	ret = iatp_read_reg(sc, sc->t44_address, 1 + sc->t5_msg_size,
866 	    sc->msg_buf);
867 	if (ret) {
868 		printf("%s: failed reading t44 and t5\n", sc->sc_dev.dv_xname);
869 		return 0;
870 	}
871 
872 	count = sc->msg_buf[0];
873 	if (count == 0) {
874 		DPRINTF(("%s: %s: no messages\n", sc->sc_dev.dv_xname,
875 		    __func__));
876 		/* flush so we keep getting interrupts */
877 		iatp_t5_read_msgs(sc, sc->info.max_report_id);
878 		return 0;
879 	}
880 
881 	count--;
882 	iatp_proc_msg(sc, sc->msg_buf + 1);
883 
884 	return count;
885 }
886 
887 void
iatp_t100_proc_msg(struct iatp_softc * sc,uint8_t * msg)888 iatp_t100_proc_msg(struct iatp_softc *sc, uint8_t *msg)
889 {
890 	int id = msg[0] - sc->t100_reportid_min - 2;
891 	int s;
892 	uint8_t status, type = 0, pressure = 0;
893 	uint16_t x, y;
894 
895 	if (id < 0 || !sc->sc_enabled)
896 		return;
897 
898 	status = msg[1];
899 	x = (msg[3] << 8) | msg[2];
900 	y = (msg[5] << 8) | msg[4];
901 
902 	if (status & MXT_T100_DETECT) {
903 		type = (status & MXT_T100_TYPE_MASK) >> 4;
904 
905 		if (sc->t100_aux_ampl)
906 			pressure = msg[sc->t100_aux_ampl];
907 
908 		if (!pressure && type != MXT_T100_TYPE_HOVERING_FINGER)
909 			pressure = 50; /* large enough for synaptics driver */
910 
911 		DPRINTF(("%s: type=%d x=%d y=%d finger=%d pressure=%d "
912 		    "button=%d\n", sc->sc_dev.dv_xname, type, x, y, id,
913 		    pressure, sc->button));
914 	} else {
915 		DPRINTF(("%s: closing slot for finger=%d\n",
916 		    sc->sc_dev.dv_xname, id));
917 
918 		if (sc->sc_touchpad)
919 			x = y = 0;
920 
921 		pressure = 0;
922 	}
923 
924 	if (sc->sc_touchpad)
925 		y = (sc->max_y - y);
926 
927 	/* TODO: adjust to sc_tsscale? */
928 
929 	s = spltty();
930 
931 	wsmouse_mtstate(sc->sc_wsmousedev, id, x, y, pressure);
932 
933 	/* on the touchscreen, assume any finger down is clicking */
934 	if (!sc->sc_touchpad)
935 		wsmouse_buttons(sc->sc_wsmousedev, pressure ? 1 : 0);
936 
937 	wsmouse_input_sync(sc->sc_wsmousedev);
938 
939 	splx(s);
940 }
941