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