1 /* 2 * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 /* 35 * CYAPA - Cypress APA trackpad with I2C Interface driver 36 * 37 * Written from scratch but referenced the linux cyapa.c driver to 38 * figure out the bootstrapping and commands. 39 * 40 * Unable to locate any datasheet for the device. 41 * 42 * Attaches under smbus but uses an I2C protocol (no count field). 43 * This driver should override the "smb" device for the specific unit 44 * we validate against (smb0-67). 45 * 46 * xorg.conf: 47 * 48 * Section "InputDevice" 49 * Identifier "Mouse0" 50 * Driver "mouse" 51 * Option "Protocol" "imps/2" (slider) 52 * # Option "Protocol" "ps/2" (basic mouse) 53 * # Option "Protocol" "explorerps/2" (not working well yet) 54 * (for b4/b5) 55 * Option "Device" "/dev/cyapa0-67" 56 * EndSection 57 * 58 * NOTE: In explorerps/2 mode the slider has only 4 bits of delta resolution 59 * and may not work as smoothly. Buttons are recognized as button 60 * 8 and button 9. 61 * 62 * FEATURES 63 * 64 * Jitter supression - Implements 2-pixel hysteresis with memory. 65 * 66 * False-finger supression- Two-fingers-down does not emulate anything, 67 * on purpose. 68 * 69 * False-emulated button handling- 70 * Buttons are emulated when three fingers are 71 * placed on the pad. If you place all three 72 * fingers down simultaniously, this condition 73 * is detected and will not emulate any button. 74 * 75 * Slider jesture - Tap right hand side and slide up or down. 76 * 77 * (Three finger jestures) 78 * left button jesture - Two fingers down on the left, tap/hold right 79 * middle button jesture- Two fingers down left & right, tap/hold middle 80 * right button jesture - Two fingers down on the right, tap/hold left 81 * 82 * track-pad button - Tap/push physical button, left, middle, or right 83 * side of the trackpad will issue a LEFT, MIDDLE, or 84 * RIGHT button event. 85 * 86 * track-pad button - Any tap/slide of more than 32 pixels and pushing 87 * harder to articulate the trackpad physical button 88 * always issues a LEFT button event. 89 * 90 * first-finger tracking- The X/Y coordinates always track the first finger 91 * down. If you have multiple fingers down and lift 92 * up the designated first finger, a new designated 93 * first finger will be selected without causing the 94 * mouse to jump (delta's are reset). 95 * 96 * WARNINGS 97 * 98 * These trackpads get confused when three or more fingers are down on the 99 * same horizontal axis and will start to glitch the finger detection. 100 * Removing your hand for a few seconds will allow the trackpad to 101 * recalibrate. Generally speaking, when using three or more fingers 102 * please try to place at least one finger off-axis (a little above or 103 * below) the other two. 104 * 105 * button-4/button-5 'claw' (4 and 5-finger) sequences have similar 106 * problems. 107 */ 108 #include <sys/kernel.h> 109 #include <sys/param.h> 110 #include <sys/systm.h> 111 #include <sys/device.h> 112 #include <sys/module.h> 113 #include <sys/bus.h> 114 #include <sys/conf.h> 115 #include <sys/uio.h> 116 #include <sys/fcntl.h> 117 #include <sys/vnode.h> 118 #include <sys/sysctl.h> 119 #include <sys/event.h> 120 #include <sys/devfs.h> 121 122 #include <bus/smbus/smbconf.h> 123 #include <bus/smbus/smbus.h> 124 #include "cyapa.h" 125 126 #include "smbus_if.h" 127 #include "bus_if.h" 128 #include "device_if.h" 129 130 #define CYAPA_BUFSIZE 128 /* power of 2 */ 131 #define CYAPA_BUFMASK (CYAPA_BUFSIZE - 1) 132 133 #define ZSCALE 10 134 135 #define TIME_TO_IDLE (hz * 10) 136 #define TIME_TO_RESET (hz * 3) 137 138 struct cyapa_fifo { 139 int rindex; 140 int windex; 141 char buf[CYAPA_BUFSIZE]; 142 }; 143 144 struct cyapa_softc { 145 device_t dev; 146 int count; /* >0 if device opened */ 147 int unit; 148 int addr; 149 cdev_t devnode; 150 struct kqinfo kqinfo; 151 struct lock lk; 152 153 int cap_resx; 154 int cap_resy; 155 int cap_phyx; 156 int cap_phyy; 157 uint8_t cap_buttons; 158 159 int poll_flags; 160 thread_t poll_td; 161 #if 0 162 struct inputev iev; /* subr_input.c */ 163 #endif 164 165 /* 166 * PS/2 mouse emulation 167 */ 168 short track_x; /* current tracking */ 169 short track_y; 170 short track_z; 171 uint16_t track_but; 172 char track_id1; /* first finger id */ 173 char track_id2; /* second finger id */ 174 int track_nfingers; 175 short delta_x; /* accumulation -> report */ 176 short delta_y; 177 short delta_z; 178 short fuzz_x; 179 short fuzz_y; 180 short fuzz_z; 181 short touch_x; /* touch down coordinates */ 182 short touch_y; 183 short touch_z; 184 int finger1_ticks; 185 int finger2_ticks; 186 int finger3_ticks; 187 uint16_t reported_but; 188 189 struct cyapa_fifo rfifo; /* device->host */ 190 struct cyapa_fifo wfifo; /* host->device */ 191 uint8_t ps2_cmd; /* active p2_cmd waiting for data */ 192 uint8_t ps2_acked; 193 int active_tick; 194 int data_signal; 195 int blocked; 196 int reporting_mode; /* 0=disabled 1=enabled */ 197 int scaling_mode; /* 0=1:1 1=2:1 */ 198 int remote_mode; /* 0 for streaming mode */ 199 int resolution; /* count/mm */ 200 int sample_rate; /* samples/sec */ 201 int zenabled; /* z-axis enabled (mode 1 or 2) */ 202 int poll_ticks; 203 }; 204 205 #define CYPOLL_SHUTDOWN 0x0001 206 207 #define SIMULATE_BUT4 0x0100 208 #define SIMULATE_BUT5 0x0200 209 #define SIMULATE_LOCK 0x8000 210 211 static void cyapa_poll_thread(void *arg); 212 static int cyapa_raw_input(struct cyapa_softc *sc, struct cyapa_regs *regs); 213 static void cyapa_set_power_mode(struct cyapa_softc *sc, int mode); 214 215 static int fifo_empty(struct cyapa_fifo *fifo); 216 static size_t fifo_ready(struct cyapa_fifo *fifo); 217 #if 0 218 static size_t fifo_total_ready(struct cyapa_fifo *fifo); 219 #endif 220 static char *fifo_read(struct cyapa_fifo *fifo, size_t n); 221 static char *fifo_write(struct cyapa_fifo *fifo, size_t n); 222 static uint8_t fifo_read_char(struct cyapa_fifo *fifo); 223 static void fifo_write_char(struct cyapa_fifo *fifo, uint8_t c); 224 static size_t fifo_space(struct cyapa_fifo *fifo); 225 static void fifo_reset(struct cyapa_fifo *fifo); 226 227 static short cyapa_fuzz(short delta, short *fuzz); 228 229 static int cyapa_idle_freq = 1; 230 SYSCTL_INT(_debug, OID_AUTO, cyapa_idle_freq, CTLFLAG_RW, 231 &cyapa_idle_freq, 0, ""); 232 static int cyapa_slow_freq = 20; 233 SYSCTL_INT(_debug, OID_AUTO, cyapa_slow_freq, CTLFLAG_RW, 234 &cyapa_slow_freq, 0, ""); 235 static int cyapa_norm_freq = 100; 236 SYSCTL_INT(_debug, OID_AUTO, cyapa_norm_freq, CTLFLAG_RW, 237 &cyapa_norm_freq, 0, ""); 238 static int cyapa_minpressure = 16; 239 SYSCTL_INT(_debug, OID_AUTO, cyapa_minpressure, CTLFLAG_RW, 240 &cyapa_minpressure, 0, ""); 241 242 static int cyapa_debug = 0; 243 SYSCTL_INT(_debug, OID_AUTO, cyapa_debug, CTLFLAG_RW, 244 &cyapa_debug, 0, ""); 245 static int cyapa_reset = 0; 246 SYSCTL_INT(_debug, OID_AUTO, cyapa_reset, CTLFLAG_RW, 247 &cyapa_reset, 0, ""); 248 249 static 250 void 251 cyapa_lock(struct cyapa_softc *sc) 252 { 253 lockmgr(&sc->lk, LK_EXCLUSIVE); 254 } 255 256 static 257 void 258 cyapa_unlock(struct cyapa_softc *sc) 259 { 260 lockmgr(&sc->lk, LK_RELEASE); 261 } 262 263 /* 264 * Notify if possible receive data ready. Must be called 265 * without the lock held to avoid deadlocking in kqueue. 266 */ 267 static 268 void 269 cyapa_notify(struct cyapa_softc *sc) 270 { 271 if (sc->data_signal || !fifo_empty(&sc->rfifo)) { 272 KNOTE(&sc->kqinfo.ki_note, 0); 273 if (sc->blocked) { 274 cyapa_lock(sc); 275 sc->blocked = 0; 276 wakeup(&sc->blocked); 277 cyapa_unlock(sc); 278 } 279 } 280 } 281 282 /* 283 * Initialize the device 284 */ 285 static 286 int 287 init_device(device_t dev, struct cyapa_cap *cap, int addr, int probe) 288 { 289 static char bl_exit[] = { 290 0x00, 0xff, 0xa5, 0x00, 0x01, 291 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; 292 static char bl_deactivate[] = { 293 0x00, 0xff, 0x3b, 0x00, 0x01, 294 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; 295 device_t bus; 296 struct cyapa_boot_regs boot; 297 int error; 298 int retries; 299 300 bus = device_get_parent(dev); /* smbus */ 301 302 /* 303 * Get status 304 */ 305 error = smbus_trans(bus, addr, CMD_BOOT_STATUS, 306 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 307 NULL, 0, (void *)&boot, sizeof(boot), NULL); 308 if (error) 309 goto done; 310 311 /* 312 * Bootstrap the device if necessary. It can take up to 2 seconds 313 * for the device to fully initialize. 314 */ 315 retries = 2 * 10; 316 while ((boot.stat & CYAPA_STAT_RUNNING) == 0 && retries > 0) { 317 if (boot.boot & CYAPA_BOOT_BUSY) { 318 /* 319 * Busy, wait loop. 320 */ 321 } else if (boot.error & CYAPA_ERROR_BOOTLOADER) { 322 /* 323 * Magic 324 */ 325 error = smbus_trans(bus, addr, CMD_BOOT_STATUS, 326 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 327 bl_deactivate, 328 sizeof(bl_deactivate), 329 NULL, 0, NULL); 330 if (error) 331 goto done; 332 } else { 333 /* 334 * Magic 335 */ 336 error = smbus_trans(bus, addr, CMD_BOOT_STATUS, 337 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 338 bl_exit, 339 sizeof(bl_exit), 340 NULL, 0, NULL); 341 if (error) 342 goto done; 343 } 344 tsleep(&error, 0, "cyapab1", hz / 10); 345 --retries; 346 error = smbus_trans(bus, addr, CMD_BOOT_STATUS, 347 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 348 NULL, 0, (void *)&boot, sizeof(boot), NULL); 349 if (error) 350 goto done; 351 } 352 353 if (retries == 0) { 354 device_printf(dev, "Unable to bring device out of bootstrap\n"); 355 error = ENXIO; 356 goto done; 357 } 358 359 /* 360 * Check identity 361 */ 362 if (cap) { 363 error = smbus_trans(bus, addr, CMD_QUERY_CAPABILITIES, 364 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 365 NULL, 0, (void *)cap, sizeof(*cap), NULL); 366 367 if (strncmp(cap->prod_ida, "CYTRA", 5) != 0) { 368 device_printf(dev, "Product ID \"%5.5s\" mismatch\n", 369 cap->prod_ida); 370 error = ENXIO; 371 } 372 } 373 error = smbus_trans(bus, addr, CMD_BOOT_STATUS, 374 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 375 NULL, 0, (void *)&boot, sizeof(boot), NULL); 376 377 if (probe == 0) /* official init */ 378 device_printf(dev, "cyapa init status %02x\n", boot.stat); 379 else if (probe == 2) 380 device_printf(dev, "cyapa reset status %02x\n", boot.stat); 381 382 done: 383 if (error) 384 device_printf(dev, "Unable to initialize\n"); 385 return error; 386 } 387 388 /* 389 * Device infrastructure 390 */ 391 #define CYAPA_SOFTC(unit) \ 392 ((struct cyapa_softc *)devclass_get_softc(cyapa_devclass, (unit))) 393 394 static void cyapa_identify(driver_t *driver, device_t parent); 395 static int cyapa_probe(device_t); 396 static int cyapa_attach(device_t); 397 static int cyapa_detach(device_t); 398 399 static devclass_t cyapa_devclass; 400 401 static device_method_t cyapa_methods[] = { 402 /* device interface */ 403 DEVMETHOD(device_identify, cyapa_identify), 404 DEVMETHOD(device_probe, cyapa_probe), 405 DEVMETHOD(device_attach, cyapa_attach), 406 DEVMETHOD(device_detach, cyapa_detach), 407 408 #if 0 409 /* smbus interface */ 410 DEVMETHOD(smbus_intr, smbus_generic_intr), 411 #endif 412 413 DEVMETHOD_END 414 }; 415 416 static driver_t cyapa_driver = { 417 "cyapa", 418 cyapa_methods, 419 sizeof(struct cyapa_softc), 420 }; 421 422 static d_open_t cyapaopen; 423 static d_close_t cyapaclose; 424 static d_ioctl_t cyapaioctl; 425 static d_read_t cyaparead; 426 static d_write_t cyapawrite; 427 static d_kqfilter_t cyapakqfilter; 428 429 static struct dev_ops cyapa_ops = { 430 { "cyapa", 0, 0 }, 431 .d_open = cyapaopen, 432 .d_close = cyapaclose, 433 .d_ioctl = cyapaioctl, 434 .d_read = cyaparead, 435 .d_write = cyapawrite, 436 .d_kqfilter = cyapakqfilter, 437 }; 438 439 static void 440 cyapa_identify(driver_t *driver, device_t parent) 441 { 442 if (device_find_child(parent, "cyapa", -1) == NULL) 443 BUS_ADD_CHILD(parent, parent, 0, "cyapa", -1); 444 } 445 446 static int 447 cyapa_probe(device_t dev) 448 { 449 struct cyapa_cap cap; 450 int unit; 451 int addr; 452 int error; 453 int dummy = 0; 454 455 unit = device_get_unit(dev); 456 457 /* 458 * Only match against specific addresses to avoid blowing up 459 * other I2C devices (?). At least for now. 460 * 461 * 0x400 (from smbus) - means specific device address probe, 462 * rather than generic. 463 * 464 * 0x67 - cypress trackpad on the acer c720. 465 */ 466 if ((unit & 0x04FF) != (0x0400 | 0x067)) 467 return ENXIO; 468 tsleep(&dummy, 0, "cyastab", hz); 469 addr = unit & 0x3FF; 470 error = init_device(dev, &cap, addr, 1); 471 if (error) 472 return ENXIO; 473 474 device_set_desc(dev, "Cypress APA I2C Trackpad"); 475 476 return (BUS_PROBE_VENDOR); 477 } 478 479 static int 480 cyapa_attach(device_t dev) 481 { 482 struct cyapa_softc *sc = (struct cyapa_softc *)device_get_softc(dev); 483 struct cyapa_cap cap; 484 int unit; 485 int addr; 486 487 if (!sc) 488 return ENOMEM; 489 490 bzero(sc, sizeof(struct cyapa_softc *)); 491 492 lockinit(&sc->lk, "cyapa", 0, 0); 493 sc->reporting_mode = 1; 494 495 unit = device_get_unit(dev); 496 if ((unit & 0x04FF) != (0x0400 | 0x067)) 497 return ENXIO; 498 addr = unit & 0x3FF; 499 if (init_device(dev, &cap, addr, 0)) 500 return ENXIO; 501 502 sc->dev = dev; 503 sc->unit = unit; 504 sc->addr = addr; 505 506 if (unit & 0x0400) { 507 sc->devnode = make_dev(&cyapa_ops, unit, 508 UID_ROOT, GID_WHEEL, 0600, 509 "cyapa%d-%02x", unit >> 11, unit & 1023); 510 } else { 511 sc->devnode = make_dev(&cyapa_ops, unit, 512 UID_ROOT, GID_WHEEL, 0600, "cyapa%d", unit); 513 } 514 515 sc->cap_resx = ((cap.max_abs_xy_high << 4) & 0x0F00) | 516 cap.max_abs_x_low; 517 sc->cap_resy = ((cap.max_abs_xy_high << 8) & 0x0F00) | 518 cap.max_abs_y_low; 519 sc->cap_phyx = ((cap.phy_siz_xy_high << 4) & 0x0F00) | 520 cap.phy_siz_x_low; 521 sc->cap_phyy = ((cap.phy_siz_xy_high << 8) & 0x0F00) | 522 cap.phy_siz_y_low; 523 sc->cap_buttons = cap.buttons; 524 525 device_printf(dev, "%5.5s-%6.6s-%2.2s buttons=%c%c%c res=%dx%d\n", 526 cap.prod_ida, cap.prod_idb, cap.prod_idc, 527 ((cap.buttons & CYAPA_FNGR_LEFT) ? 'L' : '-'), 528 ((cap.buttons & CYAPA_FNGR_MIDDLE) ? 'M' : '-'), 529 ((cap.buttons & CYAPA_FNGR_RIGHT) ? 'R' : '-'), 530 sc->cap_resx, 531 sc->cap_resy); 532 533 /* 534 * Setup input event tracking 535 */ 536 cyapa_set_power_mode(sc, CMD_POWER_MODE_IDLE); 537 538 /* 539 * Start the polling thread. 540 */ 541 lwkt_create(cyapa_poll_thread, sc, 542 &sc->poll_td, NULL, 0, -1, "cyapa-poll"); 543 544 return (0); 545 } 546 547 static int 548 cyapa_detach(device_t dev) 549 { 550 struct cyapa_softc *sc = (struct cyapa_softc *)device_get_softc(dev); 551 552 #if 0 553 /* 554 * Cleanup input event tracking 555 */ 556 inputev_deregister(&sc->iev); 557 #endif 558 559 /* 560 * Cleanup our poller thread 561 */ 562 atomic_set_int(&sc->poll_flags, CYPOLL_SHUTDOWN); 563 while (sc->poll_td) { 564 wakeup(&sc->poll_flags); 565 tsleep(&sc->poll_td, 0, "cyapadet", hz); 566 } 567 568 if (sc->devnode) 569 dev_ops_remove_minor(&cyapa_ops, device_get_unit(dev)); 570 if (sc->devnode) 571 devfs_assume_knotes(sc->devnode, &sc->kqinfo); 572 573 return (0); 574 } 575 576 /* 577 * USER DEVICE I/O FUNCTIONS 578 */ 579 static int 580 cyapaopen (struct dev_open_args *ap) 581 { 582 cdev_t dev = ap->a_head.a_dev; 583 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev)); 584 585 if (sc == NULL) 586 return (ENXIO); 587 588 if (sc->count != 0) 589 return (EBUSY); 590 591 sc->count++; 592 593 return (0); 594 } 595 596 static int 597 cyapaclose(struct dev_close_args *ap) 598 { 599 cdev_t dev = ap->a_head.a_dev; 600 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev)); 601 602 if (sc == NULL) 603 return (ENXIO); 604 605 if (sc->count == 0) 606 /* This is not supposed to happen. */ 607 return (0); 608 609 sc->count--; 610 611 return (0); 612 } 613 614 static int 615 cyaparead(struct dev_read_args *ap) 616 { 617 cdev_t dev = ap->a_head.a_dev; 618 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev)); 619 int error; 620 struct uio *uio = ap->a_uio; 621 int ioflag = ap->a_ioflag; 622 int didread; 623 size_t n; 624 625 /* 626 * If buffer is empty, load a new event if it is ready 627 */ 628 cyapa_lock(sc); 629 again: 630 if (fifo_empty(&sc->rfifo) && 631 (sc->data_signal || sc->delta_x || sc->delta_y || 632 sc->track_but != sc->reported_but)) { 633 uint8_t c0; 634 uint16_t but; 635 short delta_x; 636 short delta_y; 637 short delta_z; 638 639 /* 640 * Accumulate delta_x, delta_y. 641 */ 642 sc->data_signal = 0; 643 delta_x = sc->delta_x; 644 delta_y = sc->delta_y; 645 delta_z = sc->delta_z; 646 if (delta_x > 255) { 647 delta_x = 255; 648 sc->data_signal = 1; 649 } 650 if (delta_x < -256) { 651 delta_x = -256; 652 sc->data_signal = 1; 653 } 654 if (delta_y > 255) { 655 delta_y = 255; 656 sc->data_signal = 1; 657 } 658 if (delta_y < -256) { 659 delta_y = -256; 660 sc->data_signal = 1; 661 } 662 if (delta_z > 255) { 663 delta_z = 255; 664 sc->data_signal = 1; 665 } 666 if (delta_z < -256) { 667 delta_z = -256; 668 sc->data_signal = 1; 669 } 670 but = sc->track_but; 671 672 /* 673 * Adjust baseline for next calculation 674 */ 675 sc->delta_x -= delta_x; 676 sc->delta_y -= delta_y; 677 sc->delta_z -= delta_z; 678 sc->reported_but = but; 679 680 /* 681 * Fuzz reduces movement jitter by introducing some 682 * hysteresis. It operates without cumulative error so 683 * if you swish around quickly and return your finger to 684 * where it started, so to will the mouse. 685 */ 686 delta_x = cyapa_fuzz(delta_x, &sc->fuzz_x); 687 delta_y = cyapa_fuzz(delta_y, &sc->fuzz_y); 688 delta_z = cyapa_fuzz(delta_z, &sc->fuzz_z); 689 690 /* 691 * Generate report 692 */ 693 c0 = 0; 694 if (delta_x < 0) 695 c0 |= 0x10; 696 if (delta_y < 0) 697 c0 |= 0x20; 698 c0 |= 0x08; 699 if (but & CYAPA_FNGR_LEFT) 700 c0 |= 0x01; 701 if (but & CYAPA_FNGR_MIDDLE) 702 c0 |= 0x04; 703 if (but & CYAPA_FNGR_RIGHT) 704 c0 |= 0x02; 705 706 fifo_write_char(&sc->rfifo, c0); 707 fifo_write_char(&sc->rfifo, (uint8_t)delta_x); 708 fifo_write_char(&sc->rfifo, (uint8_t)delta_y); 709 switch(sc->zenabled) { 710 case 1: 711 /* 712 * Z axis all 8 bits 713 */ 714 fifo_write_char(&sc->rfifo, (uint8_t)delta_z); 715 break; 716 case 2: 717 /* 718 * Z axis low 4 bits + 4th button and 5th button 719 * (high 2 bits must be left 0). Auto-scale 720 * delta_z to fit to avoid a wrong-direction 721 * overflow (don't try to retain the remainder). 722 */ 723 while (delta_z > 7 || delta_z < -8) 724 delta_z >>= 1; 725 c0 = (uint8_t)delta_z & 0x0F; 726 if (but & SIMULATE_BUT4) 727 c0 |= 0x10; 728 if (but & SIMULATE_BUT5) 729 c0 |= 0x20; 730 fifo_write_char(&sc->rfifo, c0); 731 break; 732 default: 733 /* basic PS/2 */ 734 break; 735 } 736 cyapa_unlock(sc); 737 cyapa_notify(sc); 738 cyapa_lock(sc); 739 } 740 741 /* 742 * Blocking / Non-blocking 743 */ 744 error = 0; 745 didread = (uio->uio_resid == 0); 746 747 while ((ioflag & IO_NDELAY) == 0 && fifo_empty(&sc->rfifo)) { 748 if (sc->data_signal) 749 goto again; 750 sc->blocked = 1; 751 error = lksleep(&sc->blocked, &sc->lk, PCATCH, "cyablk", 0); 752 if (error) 753 break; 754 } 755 756 /* 757 * Return any buffered data 758 */ 759 while (error == 0 && uio->uio_resid && 760 (n = fifo_ready(&sc->rfifo)) > 0) { 761 if (n > uio->uio_resid) 762 n = uio->uio_resid; 763 #if 0 764 { 765 uint8_t *ptr = fifo_read(&sc->rfifo, 0); 766 size_t v; 767 kprintf("read: "); 768 for (v = 0; v < n; ++v) 769 kprintf(" %02x", ptr[v]); 770 kprintf("\n"); 771 } 772 #endif 773 error = uiomove(fifo_read(&sc->rfifo, 0), n, uio); 774 if (error) 775 break; 776 fifo_read(&sc->rfifo, n); 777 didread = 1; 778 } 779 cyapa_unlock(sc); 780 781 if (error == 0 && didread == 0) 782 error = EWOULDBLOCK; 783 784 return error; 785 } 786 787 static int 788 cyapawrite(struct dev_write_args *ap) 789 { 790 cdev_t dev = ap->a_head.a_dev; 791 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev)); 792 struct uio *uio = ap->a_uio; 793 int error; 794 int cmd_completed; 795 size_t n; 796 uint8_t c0; 797 798 again: 799 /* 800 * Copy data from userland. This will also cross-over the end 801 * of the fifo and keep filling. 802 */ 803 cyapa_lock(sc); 804 while ((n = fifo_space(&sc->wfifo)) > 0 && uio->uio_resid) { 805 if (n > uio->uio_resid) 806 n = uio->uio_resid; 807 error = uiomove(fifo_write(&sc->wfifo, 0), n, uio); 808 if (error) 809 break; 810 fifo_write(&sc->wfifo, n); 811 } 812 813 /* 814 * Handle commands 815 */ 816 cmd_completed = (fifo_ready(&sc->wfifo) != 0); 817 while (fifo_ready(&sc->wfifo) && cmd_completed && error == 0) { 818 if (sc->ps2_cmd == 0) 819 sc->ps2_cmd = fifo_read_char(&sc->wfifo); 820 switch(sc->ps2_cmd) { 821 case 0xE6: 822 /* 823 * SET SCALING 1:1 824 */ 825 sc->scaling_mode = 0; 826 fifo_write_char(&sc->rfifo, 0xFA); 827 break; 828 case 0xE7: 829 /* 830 * SET SCALING 2:1 831 */ 832 sc->scaling_mode = 1; 833 fifo_write_char(&sc->rfifo, 0xFA); 834 break; 835 case 0xE8: 836 /* 837 * SET RESOLUTION +1 byte 838 */ 839 if (sc->ps2_acked == 0) { 840 sc->ps2_acked = 1; 841 fifo_write_char(&sc->rfifo, 0xFA); 842 } 843 if (fifo_ready(&sc->wfifo) == 0) { 844 cmd_completed = 0; 845 break; 846 } 847 sc->resolution = fifo_read_char(&sc->wfifo); 848 fifo_write_char(&sc->rfifo, 0xFA); 849 break; 850 case 0xE9: 851 /* 852 * STATUS REQUEST 853 * 854 * byte1: 855 * bit 7 0 856 * bit 6 Mode (1=remote mode, 0=stream mode) 857 * bit 5 Enable (data reporting enabled) 858 * bit 4 Scaling (0=1:1 1=2:1) 859 * bit 3 0 860 * bit 2 LEFT BUTTON (1 if pressed) 861 * bit 1 MIDDLE BUTTON (1 if pressed) 862 * bit 0 RIGHT BUTTON (1 if pressed) 863 * 864 * byte2: resolution counts/mm 865 * byte3: sample rate 866 */ 867 c0 = 0; 868 if (sc->remote_mode) 869 c0 |= 0x40; 870 if (sc->reporting_mode) 871 c0 |= 0x20; 872 if (sc->scaling_mode) 873 c0 |= 0x10; 874 if (sc->track_but & CYAPA_FNGR_LEFT) 875 c0 |= 0x04; 876 if (sc->track_but & CYAPA_FNGR_MIDDLE) 877 c0 |= 0x02; 878 if (sc->track_but & CYAPA_FNGR_RIGHT) 879 c0 |= 0x01; 880 fifo_write_char(&sc->rfifo, 0xFA); 881 fifo_write_char(&sc->rfifo, c0); 882 fifo_write_char(&sc->rfifo, 0x00); 883 fifo_write_char(&sc->rfifo, 100); 884 break; 885 case 0xEA: 886 /* 887 * Set stream mode and reset movement counters 888 */ 889 sc->remote_mode = 0; 890 fifo_write_char(&sc->rfifo, 0xFA); 891 sc->delta_x = 0; 892 sc->delta_y = 0; 893 sc->delta_z = 0; 894 break; 895 case 0xEB: 896 /* 897 * Read Data (if in remote mode). If not in remote 898 * mode force an event. 899 */ 900 fifo_write_char(&sc->rfifo, 0xFA); 901 sc->data_signal = 1; 902 break; 903 case 0xEC: 904 /* 905 * Reset Wrap Mode (ignored) 906 */ 907 fifo_write_char(&sc->rfifo, 0xFA); 908 break; 909 case 0xEE: 910 /* 911 * Set Wrap Mode (ignored) 912 */ 913 fifo_write_char(&sc->rfifo, 0xFA); 914 break; 915 case 0xF0: 916 /* 917 * Set Remote Mode 918 */ 919 sc->remote_mode = 1; 920 fifo_write_char(&sc->rfifo, 0xFA); 921 sc->delta_x = 0; 922 sc->delta_y = 0; 923 sc->delta_z = 0; 924 break; 925 case 0xF2: 926 /* 927 * Get Device ID 928 * 929 * If we send 0x00 - normal PS/2 mouse, no Z-axis 930 * 931 * If we send 0x03 - Intellimouse, data packet has 932 * an additional Z movement byte (8 bits signed). 933 * (also reset movement counters) 934 * 935 * If we send 0x04 - Now includes z-axis and the 936 * 4th and 5th mouse buttons. 937 */ 938 fifo_write_char(&sc->rfifo, 0xFA); 939 switch(sc->zenabled) { 940 case 1: 941 fifo_write_char(&sc->rfifo, 0x03); 942 break; 943 case 2: 944 fifo_write_char(&sc->rfifo, 0x04); 945 break; 946 default: 947 fifo_write_char(&sc->rfifo, 0x00); 948 break; 949 } 950 sc->delta_x = 0; 951 sc->delta_y = 0; 952 sc->delta_z = 0; 953 break; 954 case 0xF3: 955 /* 956 * Set Sample Rate 957 * 958 * byte1: the sample rate 959 */ 960 if (sc->ps2_acked == 0) { 961 sc->ps2_acked = 1; 962 fifo_write_char(&sc->rfifo, 0xFA); 963 } 964 if (fifo_ready(&sc->wfifo) == 0) { 965 cmd_completed = 0; 966 break; 967 } 968 sc->sample_rate = fifo_read_char(&sc->wfifo); 969 fifo_write_char(&sc->rfifo, 0xFA); 970 971 /* 972 * zenabling sequence: 200,100,80 (device id 0x03) 973 * 200,200,80 (device id 0x04) 974 * 975 * We support id 0x03 (no 4th or 5th button). 976 * We support id 0x04 (w/ 4th and 5th button). 977 */ 978 if (sc->zenabled == 0 && sc->sample_rate == 200) 979 sc->zenabled = -1; 980 else if (sc->zenabled == -1 && sc->sample_rate == 100) 981 sc->zenabled = -2; 982 else if (sc->zenabled == -1 && sc->sample_rate == 200) 983 sc->zenabled = -3; 984 else if (sc->zenabled == -2 && sc->sample_rate == 80) 985 sc->zenabled = 1; /* z-axis mode */ 986 else if (sc->zenabled == -3 && sc->sample_rate == 80) 987 sc->zenabled = 2; /* z-axis+but4/5 */ 988 break; 989 case 0xF4: 990 /* 991 * Enable data reporting. Only effects stream mode. 992 */ 993 fifo_write_char(&sc->rfifo, 0xFA); 994 sc->reporting_mode = 1; 995 break; 996 case 0xF5: 997 /* 998 * Disable data reporting. Only effects stream mode. 999 */ 1000 fifo_write_char(&sc->rfifo, 0xFA); 1001 sc->reporting_mode = 1; 1002 break; 1003 case 0xF6: 1004 /* 1005 * SET DEFAULTS 1006 * 1007 * (reset sampling rate, resolution, scaling and 1008 * enter stream mode) 1009 */ 1010 fifo_write_char(&sc->rfifo, 0xFA); 1011 sc->sample_rate = 100; 1012 sc->resolution = 4; 1013 sc->scaling_mode = 0; 1014 sc->reporting_mode = 0; 1015 sc->remote_mode = 0; 1016 sc->delta_x = 0; 1017 sc->delta_y = 0; 1018 sc->delta_z = 0; 1019 /* signal */ 1020 break; 1021 case 0xFE: 1022 /* 1023 * RESEND 1024 * 1025 * Force a resend by guaranteeing that reported_but 1026 * differs from track_but. 1027 */ 1028 fifo_write_char(&sc->rfifo, 0xFA); 1029 sc->data_signal = 1; 1030 break; 1031 case 0xFF: 1032 /* 1033 * RESET 1034 */ 1035 fifo_reset(&sc->rfifo); /* should we do this? */ 1036 fifo_reset(&sc->wfifo); /* should we do this? */ 1037 fifo_write_char(&sc->rfifo, 0xFA); 1038 sc->delta_x = 0; 1039 sc->delta_y = 0; 1040 sc->delta_z = 0; 1041 sc->zenabled = 0; 1042 break; 1043 default: 1044 kprintf("unknown command %02x\n", sc->ps2_cmd); 1045 break; 1046 } 1047 if (cmd_completed) { 1048 sc->ps2_cmd = 0; 1049 sc->ps2_acked = 0; 1050 } 1051 cyapa_unlock(sc); 1052 cyapa_notify(sc); 1053 cyapa_lock(sc); 1054 } 1055 cyapa_unlock(sc); 1056 if (error == 0 && (cmd_completed || uio->uio_resid)) 1057 goto again; 1058 return error; 1059 } 1060 1061 static void cyapa_filt_detach(struct knote *); 1062 static int cyapa_filt(struct knote *, long); 1063 1064 static struct filterops cyapa_filtops = 1065 { FILTEROP_ISFD, NULL, cyapa_filt_detach, cyapa_filt }; 1066 1067 static int 1068 cyapakqfilter(struct dev_kqfilter_args *ap) 1069 { 1070 cdev_t dev = ap->a_head.a_dev; 1071 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev)); 1072 struct knote *kn = ap->a_kn; 1073 struct klist *klist; 1074 1075 switch(kn->kn_filter) { 1076 case EVFILT_READ: 1077 kn->kn_fop = &cyapa_filtops; 1078 kn->kn_hook = (void *)sc; 1079 ap->a_result = 0; 1080 break; 1081 default: 1082 ap->a_result = EOPNOTSUPP; 1083 return (0); 1084 } 1085 klist = &sc->kqinfo.ki_note; 1086 knote_insert(klist, kn); 1087 1088 return (0); 1089 } 1090 1091 static void 1092 cyapa_filt_detach(struct knote *kn) 1093 { 1094 struct cyapa_softc *sc = (struct cyapa_softc *)kn->kn_hook; 1095 struct klist *klist; 1096 1097 klist = &sc->kqinfo.ki_note; 1098 knote_remove(klist, kn); 1099 } 1100 1101 static int 1102 cyapa_filt(struct knote *kn, long hint) 1103 { 1104 struct cyapa_softc *sc = (struct cyapa_softc *)kn->kn_hook; 1105 int ready; 1106 1107 cyapa_lock(sc); 1108 if (fifo_ready(&sc->rfifo) || sc->data_signal) 1109 ready = 1; 1110 else 1111 ready = 0; 1112 cyapa_unlock(sc); 1113 1114 return (ready); 1115 } 1116 1117 static int 1118 cyapaioctl(struct dev_ioctl_args *ap) 1119 { 1120 cdev_t dev = ap->a_head.a_dev; 1121 device_t bus; /* smbbus */ 1122 /*struct cyapacmd *s = (struct cyapacmd *)ap->a_data;*/ 1123 void *s = NULL; 1124 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev)); 1125 int error; 1126 1127 if (sc == NULL) 1128 return (ENXIO); 1129 if (s == NULL) 1130 return (EINVAL); 1131 1132 /* 1133 * NOTE: smbus_*() functions automatically recurse the parent to 1134 * get to the actual device driver. 1135 */ 1136 bus = device_get_parent(sc->dev); /* smbus */ 1137 1138 /* Allocate the bus. */ 1139 if ((error = smbus_request_bus(bus, sc->dev, 1140 (ap->a_fflag & O_NONBLOCK) ? 1141 SMB_DONTWAIT : (SMB_WAIT | SMB_INTR)))) 1142 return (error); 1143 1144 switch (ap->a_cmd) { 1145 default: 1146 #if 0 1147 error = inputev_ioctl(&sc->iev, ap->a_cmd, ap->a_data); 1148 #endif 1149 error = ENOTTY; 1150 break; 1151 } 1152 1153 smbus_release_bus(bus, sc->dev); 1154 1155 return (error); 1156 } 1157 1158 /* 1159 * MAJOR SUPPORT FUNCTIONS 1160 */ 1161 static 1162 void 1163 cyapa_poll_thread(void *arg) 1164 { 1165 struct cyapa_softc *sc = arg; 1166 struct cyapa_regs regs; 1167 device_t bus; /* smbbus */ 1168 int error; 1169 int freq = cyapa_norm_freq; 1170 int isidle = 0; 1171 int pstate = CMD_POWER_MODE_IDLE; 1172 int npstate; 1173 int last_reset = ticks; 1174 1175 bus = device_get_parent(sc->dev); 1176 1177 while ((sc->poll_flags & CYPOLL_SHUTDOWN) == 0) { 1178 error = smbus_request_bus(bus, sc->dev, SMB_WAIT); 1179 if (error == 0) { 1180 error = smbus_trans(bus, sc->addr, CMD_DEV_STATUS, 1181 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 1182 NULL, 0, 1183 (void *)®s, sizeof(regs), NULL); 1184 if (error == 0) { 1185 isidle = cyapa_raw_input(sc, ®s); 1186 } 1187 1188 /* 1189 * For some reason the device can crap-out. If it 1190 * drops back into bootstrap mode try to reinitialize 1191 * it. 1192 */ 1193 if (cyapa_reset || 1194 ((regs.stat & CYAPA_STAT_RUNNING) == 0 && 1195 (unsigned)(ticks - last_reset) > TIME_TO_RESET)) { 1196 cyapa_reset = 0; 1197 last_reset = ticks; 1198 init_device(sc->dev, NULL, sc->addr, 2); 1199 } 1200 smbus_release_bus(bus, sc->dev); 1201 } 1202 tsleep(&sc->poll_flags, 0, "cyapw", (hz + freq - 1) / freq); 1203 ++sc->poll_ticks; 1204 if (sc->count == 0) { 1205 freq = cyapa_idle_freq; 1206 npstate = CMD_POWER_MODE_IDLE; 1207 } else if (isidle) { 1208 freq = cyapa_slow_freq; 1209 npstate = CMD_POWER_MODE_IDLE; 1210 } else { 1211 freq = cyapa_norm_freq; 1212 npstate = CMD_POWER_MODE_FULL; 1213 } 1214 if (pstate != npstate) { 1215 pstate = npstate; 1216 cyapa_set_power_mode(sc, pstate); 1217 if (cyapa_debug) { 1218 switch(pstate) { 1219 case CMD_POWER_MODE_OFF: 1220 kprintf("cyapa: power off\n"); 1221 break; 1222 case CMD_POWER_MODE_IDLE: 1223 kprintf("cyapa: power idle\n"); 1224 break; 1225 case CMD_POWER_MODE_FULL: 1226 kprintf("cyapa: power full\n"); 1227 break; 1228 } 1229 } 1230 } 1231 } 1232 sc->poll_td = NULL; 1233 wakeup(&sc->poll_td); 1234 } 1235 1236 static 1237 int 1238 cyapa_raw_input(struct cyapa_softc *sc, struct cyapa_regs *regs) 1239 { 1240 int nfingers; 1241 int afingers; /* actual fingers after culling */ 1242 int i; 1243 int j; 1244 int k; 1245 int isidle; 1246 short x; 1247 short y; 1248 short z; 1249 short x1; 1250 short x2; 1251 uint16_t but; /* high bits used for simulated but4/but5 */ 1252 1253 /* 1254 * If the device is not running the rest of the status 1255 * means something else, set fingers to 0. 1256 */ 1257 if ((regs->stat & CYAPA_STAT_RUNNING) == 0) { 1258 regs->fngr = 0; 1259 } 1260 1261 /* 1262 * Process fingers/movement 1263 */ 1264 nfingers = CYAPA_FNGR_NUMFINGERS(regs->fngr); 1265 afingers = nfingers; 1266 1267 if (cyapa_debug) { 1268 kprintf("stat %02x buttons %c%c%c nfngrs=%d ", 1269 regs->stat, 1270 ((regs->fngr & CYAPA_FNGR_LEFT) ? 'L' : '-'), 1271 ((regs->fngr & CYAPA_FNGR_MIDDLE) ? 'L' : '-'), 1272 ((regs->fngr & CYAPA_FNGR_RIGHT) ? 'L' : '-'), 1273 nfingers 1274 ); 1275 } 1276 for (i = 0; i < nfingers; ++i) { 1277 if (cyapa_debug) { 1278 kprintf(" [x=%04d y=%04d p=%d]", 1279 CYAPA_TOUCH_X(regs, i), 1280 CYAPA_TOUCH_Y(regs, i), 1281 CYAPA_TOUCH_P(regs, i)); 1282 } 1283 if (CYAPA_TOUCH_P(regs, i) < cyapa_minpressure) 1284 --afingers; 1285 } 1286 1287 /* 1288 * Tracking for local solutions 1289 */ 1290 cyapa_lock(sc); 1291 1292 /* 1293 * Track timing for finger-downs. Used to detect false-3-finger 1294 * button-down. 1295 */ 1296 switch(afingers) { 1297 case 0: 1298 break; 1299 case 1: 1300 if (sc->track_nfingers == 0) 1301 sc->finger1_ticks = sc->poll_ticks; 1302 break; 1303 case 2: 1304 if (sc->track_nfingers <= 0) 1305 sc->finger1_ticks = sc->poll_ticks; 1306 if (sc->track_nfingers <= 1) 1307 sc->finger2_ticks = sc->poll_ticks; 1308 break; 1309 case 3: 1310 default: 1311 if (sc->track_nfingers <= 0) 1312 sc->finger1_ticks = sc->poll_ticks; 1313 if (sc->track_nfingers <= 1) 1314 sc->finger2_ticks = sc->poll_ticks; 1315 if (sc->track_nfingers <= 2) 1316 sc->finger3_ticks = sc->poll_ticks; 1317 break; 1318 } 1319 sc->track_nfingers = afingers; 1320 1321 /* 1322 * Lookup and track finger indexes in the touch[] array. 1323 */ 1324 if (afingers == 0) { 1325 sc->track_x = -1; 1326 sc->track_y = -1; 1327 sc->track_z = -1; 1328 sc->fuzz_x = 0; 1329 sc->fuzz_y = 0; 1330 sc->fuzz_z = 0; 1331 sc->touch_x = -1; 1332 sc->touch_y = -1; 1333 sc->touch_z = -1; 1334 sc->track_id1 = -1; 1335 sc->track_id2 = -1; 1336 sc->track_but = 0; 1337 i = 0; 1338 j = 0; 1339 k = 0; 1340 } else { 1341 /* 1342 * The id assigned on touch can move around in the array, 1343 * find it. If that finger is lifted up, assign some other 1344 * finger for mouse tracking and reset track_x and track_y 1345 * to avoid a mouse jump. 1346 * 1347 * If >= 2 fingers are down be sure not to assign i and 1348 * j to the same index. 1349 */ 1350 for (i = 0; i < nfingers; ++i) { 1351 if (sc->track_id1 == regs->touch[i].id) 1352 break; 1353 } 1354 if (i == nfingers || 1355 CYAPA_TOUCH_P(regs, i) < cyapa_minpressure) { 1356 i = 0; 1357 sc->track_x = -1; 1358 sc->track_y = -1; 1359 sc->track_z = -1; 1360 sc->track_id1 = regs->touch[i].id; 1361 if (sc->track_id2 == sc->track_id1) 1362 sc->track_id2 = -1; 1363 } 1364 1365 /* 1366 * A second finger. 1367 */ 1368 for (j = 0; j < nfingers; ++j) { 1369 if (sc->track_id2 == regs->touch[j].id) 1370 break; 1371 } 1372 if (j == nfingers || 1373 CYAPA_TOUCH_P(regs, j) < cyapa_minpressure) { 1374 if (afingers >= 2) { 1375 if (i == 0) 1376 j = 1; 1377 else 1378 j = 0; 1379 sc->track_id2 = regs->touch[j].id; 1380 } else { 1381 sc->track_id2 = -1; 1382 j = 0; 1383 } 1384 } 1385 1386 /* 1387 * The third finger is used to tap or tap-hold to simulate 1388 * a button, we don't have to record it persistently. 1389 */ 1390 if (afingers >= 3) { 1391 k = 0; 1392 if (i == 0 || j == 0) 1393 k = 1; 1394 if (i == 1 || j == 1) 1395 k = 2; 1396 } else { 1397 k = 0; 1398 } 1399 } 1400 1401 /* 1402 * On initial touch determine if we are in the slider area. Setting 1403 * track_z conditionalizes the delta calculations later on. 1404 */ 1405 if (afingers && sc->zenabled > 0 && 1406 sc->track_x == -1 && sc->track_z == -1) { 1407 x = CYAPA_TOUCH_X(regs, i); 1408 z = CYAPA_TOUCH_Y(regs, i); 1409 if (x > sc->cap_resx * 9 / 10) 1410 sc->track_z = z; 1411 } 1412 1413 if (afingers && sc->track_z != -1) { 1414 /* 1415 * Slider emulation (right side of trackpad). Z is tracked 1416 * based on the Y position. X and Y tracking are disabled. 1417 * 1418 * Because we are emulating a mouse-wheel, we do not want 1419 * to shove events out at the maximum resolution. 1420 */ 1421 z = CYAPA_TOUCH_Y(regs, i); 1422 sc->delta_z += z / ZSCALE - sc->track_z; 1423 if (sc->touch_z == -1) 1424 sc->touch_z = z; /* not used atm */ 1425 sc->track_z = z / ZSCALE; 1426 } else if (afingers) { 1427 /* 1428 * Normal pad position reporting (track_z is left -1) 1429 */ 1430 x = CYAPA_TOUCH_X(regs, i); 1431 y = CYAPA_TOUCH_Y(regs, i); 1432 if (sc->track_x != -1) { 1433 sc->delta_x += x - sc->track_x; 1434 sc->delta_y -= y - sc->track_y; 1435 if (sc->delta_x > sc->cap_resx) 1436 sc->delta_x = sc->cap_resx; 1437 if (sc->delta_x < -sc->cap_resx) 1438 sc->delta_x = -sc->cap_resx; 1439 if (sc->delta_y > sc->cap_resx) 1440 sc->delta_y = sc->cap_resy; 1441 if (sc->delta_y < -sc->cap_resy) 1442 sc->delta_y = -sc->cap_resy; 1443 } 1444 if (sc->touch_x == -1) { 1445 sc->touch_x = x; 1446 sc->touch_y = y; 1447 } 1448 sc->track_x = x; 1449 sc->track_y = y; 1450 } 1451 if (afingers >= 5 && sc->zenabled > 1 && sc->track_z < 0) { 1452 /* 1453 * Simulate the 5th button (when not in slider mode) 1454 */ 1455 but = SIMULATE_BUT5; 1456 } else if (afingers >= 4 && sc->zenabled > 1 && sc->track_z < 0) { 1457 /* 1458 * Simulate the 4th button (when not in slider mode) 1459 */ 1460 but = SIMULATE_BUT4; 1461 } else if (afingers >= 3 && sc->track_z < 0) { 1462 /* 1463 * Simulate the left, middle, or right button with 3 1464 * fingers when not in slider mode. 1465 * 1466 * This makes it ultra easy to hit GUI buttons and move 1467 * windows with a light touch, without having to apply the 1468 * pressure required to articulate the button. 1469 * 1470 * However, if we are coming down from 4 or 5 fingers, 1471 * do NOT simulate the left button and instead just release 1472 * button 4 or button 5. Leave SIMULATE_LOCK set to 1473 * placemark the condition. We must go down to 2 fingers 1474 * to release the lock. 1475 * 1476 * LEFT BUTTON: Fingers arranged left-to-right 1 2 3, 1477 * move mouse with fingers 2 and 3 and tap 1478 * or hold with finger 1 (to the left of fingers 1479 * 2 and 3). 1480 * 1481 * RIGHT BUTTON: Move mouse with fingers 1 and 2 and tap 1482 * or hold with finger 3. 1483 * 1484 * MIDDLE BUTTON: Move mouse with fingers 1 and 3 and tap 1485 * or hold with finger 2. 1486 * 1487 * Finally, detect when all three fingers were placed down 1488 * within one tick of each other. 1489 */ 1490 x1 = CYAPA_TOUCH_X(regs, i); /* 1st finger down */ 1491 x2 = CYAPA_TOUCH_X(regs, j); /* 2nd finger down */ 1492 x = CYAPA_TOUCH_X(regs, k); /* 3rd finger (button) down */ 1493 if (sc->track_but & (SIMULATE_BUT4 | 1494 SIMULATE_BUT5 | 1495 SIMULATE_LOCK)) { 1496 but = SIMULATE_LOCK; 1497 } else if (sc->track_but & ~SIMULATE_LOCK) { 1498 but = sc->track_but; 1499 } else if ((int)(sc->finger3_ticks - sc->finger1_ticks) < 1500 cyapa_norm_freq / 25 + 1) { 1501 /* 1502 * False 3-finger button detection (but still detect 1503 * if the actual physical button is held down). 1504 */ 1505 if (regs->fngr & CYAPA_FNGR_LEFT) 1506 but = CYAPA_FNGR_LEFT; 1507 else 1508 but = 0; 1509 } else if (x < x1 && x < x2) { 1510 but = CYAPA_FNGR_LEFT; 1511 } else if (x > x1 && x < x2) { 1512 but = CYAPA_FNGR_MIDDLE; 1513 } else if (x > x2 && x < x1) { 1514 but = CYAPA_FNGR_MIDDLE; 1515 } else { 1516 but = CYAPA_FNGR_RIGHT; 1517 } 1518 } else if (afingers == 2 || (afingers >= 2 && sc->track_z >= 0)) { 1519 /* 1520 * If 2 fingers are held down or 2 or more fingers are held 1521 * down and we are in slider mode, any key press is 1522 * interpreted as a left mouse button press. 1523 * 1524 * If a keypress is already active we retain the active 1525 * keypress instead. 1526 * 1527 * The high-button state is unconditionally cleared with <= 2 1528 * fingers. 1529 */ 1530 if (regs->fngr & CYAPA_FNGR_LEFT) { 1531 but = sc->track_but & ~SIMULATE_LOCK; 1532 if (but == 0) 1533 but = CYAPA_FNGR_LEFT; 1534 } else { 1535 but = 0; 1536 } 1537 } else if (afingers == 1 && 1538 (abs(sc->touch_x - sc->track_x) > 32 || 1539 abs(sc->touch_y - sc->track_y) > 32)) { 1540 /* 1541 * When using one finger, any significant mouse movement 1542 * will lock you to the left mouse button if you push the 1543 * button, regardless of where you are on the pad. 1544 * 1545 * If a keypress is already active we retain the active 1546 * keypress instead. 1547 * 1548 * The high-button state is unconditionally cleared with <= 2 1549 * fingers. 1550 */ 1551 if (regs->fngr & CYAPA_FNGR_LEFT) { 1552 but = sc->track_but & ~SIMULATE_LOCK; 1553 if (but == 0) 1554 but = CYAPA_FNGR_LEFT; 1555 } else { 1556 but = 0; 1557 } 1558 } else if (afingers == 1 && (regs->fngr & CYAPA_FNGR_LEFT)) { 1559 /* 1560 * If you are swiping while holding a button down, the 1561 * button registration does not change. Otherwise the 1562 * registered button depends on where you are on the pad. 1563 * 1564 * Since no significant movement occurred we allow the 1565 * button to be pressed while within the slider area 1566 * and still be properly registered as the right button. 1567 * 1568 * The high-button state is unconditionally cleared with <= 2 1569 * fingers. 1570 */ 1571 if (sc->track_but & ~SIMULATE_LOCK) 1572 but = sc->track_but & ~SIMULATE_LOCK; 1573 else if (sc->track_x < sc->cap_resx * 1 / 3) 1574 but = CYAPA_FNGR_LEFT; 1575 else if (sc->track_x < sc->cap_resx * 2 / 3) 1576 but = CYAPA_FNGR_MIDDLE; 1577 else 1578 but = CYAPA_FNGR_RIGHT; 1579 } else if (afingers == 1) { 1580 /* 1581 * Clear all finger state if 1 finger is down and nothing 1582 * is pressed. 1583 */ 1584 but = 0; 1585 } else { 1586 /* 1587 * Clear all finger state if no fingers are down. 1588 */ 1589 but = 0; 1590 } 1591 1592 /* 1593 * Detect state change from last reported state and 1594 * determine if we have gone idle. 1595 */ 1596 sc->track_but = but; 1597 if (sc->delta_x || sc->delta_y || sc->delta_z || 1598 sc->track_but != sc->reported_but) { 1599 sc->active_tick = ticks; 1600 if (sc->remote_mode == 0 && sc->reporting_mode) 1601 sc->data_signal = 1; 1602 isidle = 0; 1603 } else if ((unsigned)(ticks - sc->active_tick) >= TIME_TO_IDLE) { 1604 sc->active_tick = ticks - TIME_TO_IDLE; /* prevent overflow */ 1605 isidle = 1; 1606 } else { 1607 isidle = 0; 1608 } 1609 cyapa_unlock(sc); 1610 cyapa_notify(sc); 1611 1612 if (cyapa_debug) 1613 kprintf("\n"); 1614 return(isidle); 1615 } 1616 1617 static 1618 void 1619 cyapa_set_power_mode(struct cyapa_softc *sc, int mode) 1620 { 1621 uint8_t data; 1622 device_t bus; 1623 int error; 1624 1625 bus = device_get_parent(sc->dev); 1626 error = smbus_request_bus(bus, sc->dev, SMB_WAIT); 1627 if (error == 0) { 1628 error = smbus_trans(bus, sc->addr, CMD_POWER_MODE, 1629 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 1630 NULL, 0, (void *)&data, 1, NULL); 1631 data = (data & ~0xFC) | mode; 1632 if (error == 0) { 1633 error = smbus_trans(bus, sc->addr, CMD_POWER_MODE, 1634 SMB_TRANS_NOCNT | SMB_TRANS_7BIT, 1635 (void *)&data, 1, NULL, 0, NULL); 1636 } 1637 smbus_release_bus(bus, sc->dev); 1638 } 1639 } 1640 1641 /* 1642 * FIFO FUNCTIONS 1643 */ 1644 1645 /* 1646 * Returns non-zero if the fifo is empty 1647 */ 1648 static 1649 int 1650 fifo_empty(struct cyapa_fifo *fifo) 1651 { 1652 return(fifo->rindex == fifo->windex); 1653 } 1654 1655 /* 1656 * Returns the number of characters available for reading from 1657 * the fifo without wrapping the fifo buffer. 1658 */ 1659 static 1660 size_t 1661 fifo_ready(struct cyapa_fifo *fifo) 1662 { 1663 size_t n; 1664 1665 n = CYAPA_BUFSIZE - (fifo->rindex & CYAPA_BUFMASK); 1666 if (n > (size_t)(fifo->windex - fifo->rindex)) 1667 n = (size_t)(fifo->windex - fifo->rindex); 1668 return n; 1669 } 1670 1671 #if 0 1672 /* 1673 * Returns the number of characters available for reading from 1674 * the fifo including wrapping the fifo buffer. 1675 */ 1676 static 1677 size_t 1678 fifo_total_ready(struct cyapa_fifo *fifo) 1679 { 1680 return ((size_t)(fifo->windex - fifo->rindex)); 1681 } 1682 #endif 1683 1684 /* 1685 * Returns a read pointer into the fifo and then bumps 1686 * rindex. The FIFO must have at least 'n' characters in 1687 * it. The value (n) can cause the index to wrap but users 1688 * of the buffer should never supply a value for (n) that wraps 1689 * the buffer. 1690 */ 1691 static 1692 char * 1693 fifo_read(struct cyapa_fifo *fifo, size_t n) 1694 { 1695 char *ptr; 1696 1697 if (n > (CYAPA_BUFSIZE - (fifo->rindex & CYAPA_BUFMASK))) { 1698 kprintf("fifo_read: overflow\n"); 1699 return (fifo->buf); 1700 } 1701 ptr = fifo->buf + (fifo->rindex & CYAPA_BUFMASK); 1702 fifo->rindex += n; 1703 1704 return (ptr); 1705 } 1706 1707 static 1708 uint8_t 1709 fifo_read_char(struct cyapa_fifo *fifo) 1710 { 1711 uint8_t c; 1712 1713 if (fifo->rindex == fifo->windex) { 1714 kprintf("fifo_read_char: overflow\n"); 1715 c = 0; 1716 } else { 1717 c = fifo->buf[fifo->rindex & CYAPA_BUFMASK]; 1718 ++fifo->rindex; 1719 } 1720 return c; 1721 } 1722 1723 1724 /* 1725 * Write a character to the FIFO. The character will be discarded 1726 * if the FIFO is full. 1727 */ 1728 static 1729 void 1730 fifo_write_char(struct cyapa_fifo *fifo, uint8_t c) 1731 { 1732 if (fifo->windex - fifo->rindex < CYAPA_BUFSIZE) { 1733 fifo->buf[fifo->windex & CYAPA_BUFMASK] = c; 1734 ++fifo->windex; 1735 } 1736 } 1737 1738 /* 1739 * Return the amount of space available for writing without wrapping 1740 * the fifo. 1741 */ 1742 static 1743 size_t 1744 fifo_space(struct cyapa_fifo *fifo) 1745 { 1746 size_t n; 1747 1748 n = CYAPA_BUFSIZE - (fifo->windex & CYAPA_BUFMASK); 1749 if (n > (size_t)(CYAPA_BUFSIZE - (fifo->windex - fifo->rindex))) 1750 n = (size_t)(CYAPA_BUFSIZE - (fifo->windex - fifo->rindex)); 1751 return n; 1752 } 1753 1754 static 1755 char * 1756 fifo_write(struct cyapa_fifo *fifo, size_t n) 1757 { 1758 char *ptr; 1759 1760 ptr = fifo->buf + (fifo->windex & CYAPA_BUFMASK); 1761 fifo->windex += n; 1762 1763 return(ptr); 1764 } 1765 1766 static 1767 void 1768 fifo_reset(struct cyapa_fifo *fifo) 1769 { 1770 fifo->rindex = 0; 1771 fifo->windex = 0; 1772 } 1773 1774 /* 1775 * Fuzz handling 1776 */ 1777 static 1778 short 1779 cyapa_fuzz(short delta, short *fuzzp) 1780 { 1781 short fuzz; 1782 1783 fuzz = *fuzzp; 1784 if (fuzz >= 0 && delta < 0) { 1785 ++delta; 1786 --fuzz; 1787 } else if (fuzz <= 0 && delta > 0) { 1788 --delta; 1789 ++fuzz; 1790 } 1791 *fuzzp = fuzz; 1792 1793 return delta; 1794 } 1795 1796 DRIVER_MODULE(cyapa, smbus, cyapa_driver, cyapa_devclass, NULL, NULL); 1797 MODULE_DEPEND(cyapa, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 1798 MODULE_VERSION(cyapa, 1); 1799