1 /* $OpenBSD: iatp.c,v 1.8 2020/08/26 03:29:06 visa 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 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 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 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 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 295 iatp_activate(struct device *self, int act) 296 { 297 struct iatp_softc *sc = (struct iatp_softc *)self; 298 299 switch (act) { 300 case DVACT_QUIESCE: 301 #if 0 302 /* XXX: causes dwiic troubles */ 303 iatp_t7_set_power_mode(sc, MXT_T7_POWER_MODE_DEEP_SLEEP); 304 #endif 305 break; 306 case DVACT_WAKEUP: 307 sc->sc_busy = 1; 308 iatp_init(sc); 309 sc->sc_busy = 0; 310 break; 311 } 312 313 config_activate_children(self, act); 314 315 return 0; 316 } 317 318 int 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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