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