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