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