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