2 * Copyright (c) 2014 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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
35 * CYAPA - Cypress APA trackpad with I2C Interface driver
37 * Written from scratch but referenced the linux cyapa.c driver to
38 * figure out the bootstrapping and commands.
40 * Unable to locate any datasheet for the device.
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).
48 * Section "InputDevice"
51 * Option "Protocol" "imps/2" (slider)
52 * # Option "Protocol" "ps/2" (basic mouse)
53 * # Option "Protocol" "explorerps/2" (not working well yet)
55 * Option "Device" "/dev/cyapa0-67"
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
64 * Jitter supression - Implements 2-pixel hysteresis with memory.
66 * False-finger supression- Two-fingers-down does not emulate anything,
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.
75 * Slider jesture - Tap right hand side and slide up or down.
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
82 * track-pad button - Tap/push physical button, left, middle, or right
83 * side of the trackpad will issue a LEFT, MIDDLE, or
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.
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).
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.
105 * button-4/button-5 'claw' (4 and 5-finger) sequences have similar
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>
114 #include <sys/conf.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>
123 #include <bus/smbus/smbconf.h>
124 #include <bus/smbus/smbus.h>
127 #include "smbus_if.h"
129 #include "device_if.h"
131 #define CYAPA_BUFSIZE 128 /* power of 2 */
132 #define CYAPA_BUFMASK (CYAPA_BUFSIZE - 1)
139 char buf[CYAPA_BUFSIZE];
144 int count; /* >0 if device opened */
148 struct kqinfo kqinfo;
160 struct inputev iev; /* subr_input.c */
164 * PS/2 mouse emulation
166 short track_x; /* current tracking */
170 char track_id1; /* first finger id */
171 char track_id2; /* second finger id */
173 short delta_x; /* accumulation -> report */
179 short touch_x; /* touch down coordinates */
185 uint16_t reported_but;
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 */
194 int reporting_mode; /* 0=disabled 1=enabled */
195 int scaling_mode; /* 0=1:1 1=2:1 */
196 int remote_mode; /* 0 for streaming mode */
197 int resolution; /* count/mm */
198 int sample_rate; /* samples/sec */
199 int zenabled; /* z-axis enabled (mode 1 or 2) */
203 #define CYPOLL_SHUTDOWN 0x0001
205 #define SIMULATE_BUT4 0x0100
206 #define SIMULATE_BUT5 0x0200
207 #define SIMULATE_LOCK 0x8000
209 static void cyapa_poll_thread(void *arg);
210 static int cyapa_raw_input(struct cyapa_softc *sc, struct cyapa_regs *regs);
212 static int fifo_empty(struct cyapa_fifo *fifo);
213 static size_t fifo_ready(struct cyapa_fifo *fifo);
215 static size_t fifo_total_ready(struct cyapa_fifo *fifo);
217 static char *fifo_read(struct cyapa_fifo *fifo, size_t n);
218 static char *fifo_write(struct cyapa_fifo *fifo, size_t n);
219 static uint8_t fifo_read_char(struct cyapa_fifo *fifo);
220 static void fifo_write_char(struct cyapa_fifo *fifo, uint8_t c);
221 static size_t fifo_space(struct cyapa_fifo *fifo);
222 static void fifo_reset(struct cyapa_fifo *fifo);
224 static short cyapa_fuzz(short delta, short *fuzz);
226 static int cyapa_idle_freq = 1;
227 SYSCTL_INT(_debug, OID_AUTO, cyapa_idle_freq, CTLFLAG_RW,
228 &cyapa_idle_freq, 0, "");
229 static int cyapa_slow_freq = 20;
230 SYSCTL_INT(_debug, OID_AUTO, cyapa_slow_freq, CTLFLAG_RW,
231 &cyapa_slow_freq, 0, "");
232 static int cyapa_norm_freq = 100;
233 SYSCTL_INT(_debug, OID_AUTO, cyapa_norm_freq, CTLFLAG_RW,
234 &cyapa_norm_freq, 0, "");
236 static int cyapa_debug = 0;
237 SYSCTL_INT(_debug, OID_AUTO, cyapa_debug, CTLFLAG_RW,
238 &cyapa_debug, 0, "");
242 cyapa_lock(struct cyapa_softc *sc)
244 lockmgr(&sc->lk, LK_EXCLUSIVE);
249 cyapa_unlock(struct cyapa_softc *sc)
251 lockmgr(&sc->lk, LK_RELEASE);
255 * Notify if possible receive data ready. Must be called
256 * without the lock held to avoid deadlocking in kqueue.
260 cyapa_notify(struct cyapa_softc *sc)
262 if (sc->data_signal || !fifo_empty(&sc->rfifo)) {
263 KNOTE(&sc->kqinfo.ki_note, 0);
267 wakeup(&sc->blocked);
274 * Initialize the device
278 init_device(device_t dev, struct cyapa_cap *cap, int addr, int probe)
280 static char bl_exit[] = {
281 0x00, 0xff, 0xa5, 0x00, 0x01,
282 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
283 static char bl_deactivate[] = {
284 0x00, 0xff, 0x3b, 0x00, 0x01,
285 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
287 struct cyapa_boot_regs boot;
292 bus = device_get_parent(dev); /* smbus */
297 error = smbus_trans(bus, addr, CMD_BOOT_STATUS,
298 SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
299 NULL, 0, (void *)&boot, sizeof(boot), NULL);
304 * Bootstrap the device if necessary. It can take up to 2 seconds
305 * for the device to fully initialize.
308 while ((boot.stat & CYAPA_STAT_RUNNING) == 0 && retries > 0) {
309 if (boot.boot & CYAPA_BOOT_BUSY) {
313 } else if (boot.error & CYAPA_ERROR_BOOTLOADER) {
317 error = smbus_trans(bus, addr, CMD_BOOT_STATUS,
318 SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
320 sizeof(bl_deactivate),
328 error = smbus_trans(bus, addr, CMD_BOOT_STATUS,
329 SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
336 tsleep(&error, 0, "cyapabt", hz / 10);
338 error = smbus_trans(bus, addr, CMD_BOOT_STATUS,
339 SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
340 NULL, 0, (void *)&boot, sizeof(boot), NULL);
346 device_printf(dev, "Unable to bring device out of bootstrap\n");
354 error = smbus_trans(bus, addr, CMD_QUERY_CAPABILITIES,
355 SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
356 NULL, 0, (void *)cap, sizeof(*cap), NULL);
358 if (strncmp(cap->prod_ida, "CYTRA", 5) != 0) {
359 device_printf(dev, "Product ID \"%5.5s\" mismatch\n",
366 device_printf(dev, "Unable to initialize\n");
371 * Device infrastructure
373 #define CYAPA_SOFTC(unit) \
374 ((struct cyapa_softc *)devclass_get_softc(cyapa_devclass, (unit)))
376 static void cyapa_identify(driver_t *driver, device_t parent);
377 static int cyapa_probe(device_t);
378 static int cyapa_attach(device_t);
379 static int cyapa_detach(device_t);
381 static devclass_t cyapa_devclass;
383 static device_method_t cyapa_methods[] = {
384 /* device interface */
385 DEVMETHOD(device_identify, cyapa_identify),
386 DEVMETHOD(device_probe, cyapa_probe),
387 DEVMETHOD(device_attach, cyapa_attach),
388 DEVMETHOD(device_detach, cyapa_detach),
391 /* smbus interface */
392 DEVMETHOD(smbus_intr, smbus_generic_intr),
398 static driver_t cyapa_driver = {
401 sizeof(struct cyapa_softc),
404 static d_open_t cyapaopen;
405 static d_close_t cyapaclose;
406 static d_ioctl_t cyapaioctl;
407 static d_read_t cyaparead;
408 static d_write_t cyapawrite;
409 static d_kqfilter_t cyapakqfilter;
411 static struct dev_ops cyapa_ops = {
414 .d_close = cyapaclose,
415 .d_ioctl = cyapaioctl,
417 .d_write = cyapawrite,
418 .d_kqfilter = cyapakqfilter,
422 cyapa_identify(driver_t *driver, device_t parent)
424 if (device_find_child(parent, "cyapa", -1) == NULL)
425 BUS_ADD_CHILD(parent, parent, 0, "cyapa", -1);
429 cyapa_probe(device_t dev)
431 struct cyapa_cap cap;
436 unit = device_get_unit(dev);
439 * Only match against specific addresses to avoid blowing up
440 * other I2C devices (?). At least for now.
442 * 0x400 (from smbus) - means specific device address probe,
443 * rather than generic.
445 * 0x67 - cypress trackpad on the acer c720.
447 if ((unit & 0x04FF) != (0x0400 | 0x067))
450 error = init_device(dev, &cap, addr, 1);
454 device_set_desc(dev, "Cypress APA I2C Trackpad");
456 return (BUS_PROBE_VENDOR);
460 cyapa_attach(device_t dev)
462 struct cyapa_softc *sc = (struct cyapa_softc *)device_get_softc(dev);
463 struct cyapa_cap cap;
470 bzero(sc, sizeof(struct cyapa_softc *));
472 lockinit(&sc->lk, "cyapa", 0, 0);
473 sc->reporting_mode = 1;
475 unit = device_get_unit(dev);
476 if ((unit & 0x04FF) != (0x0400 | 0x067))
479 if (init_device(dev, &cap, addr, 0))
487 sc->devnode = make_dev(&cyapa_ops, unit,
488 UID_ROOT, GID_WHEEL, 0600,
489 "cyapa%d-%02x", unit >> 11, unit & 1023);
491 sc->devnode = make_dev(&cyapa_ops, unit,
492 UID_ROOT, GID_WHEEL, 0600, "cyapa%d", unit);
495 sc->cap_resx = ((cap.max_abs_xy_high << 4) & 0x0F00) |
497 sc->cap_resy = ((cap.max_abs_xy_high << 8) & 0x0F00) |
499 sc->cap_phyx = ((cap.phy_siz_xy_high << 4) & 0x0F00) |
501 sc->cap_phyy = ((cap.phy_siz_xy_high << 8) & 0x0F00) |
503 sc->cap_buttons = cap.buttons;
505 device_printf(dev, "%5.5s-%6.6s-%2.2s buttons=%c%c%c res=%dx%d\n",
506 cap.prod_ida, cap.prod_idb, cap.prod_idc,
507 ((cap.buttons & CYAPA_FNGR_LEFT) ? 'L' : '-'),
508 ((cap.buttons & CYAPA_FNGR_MIDDLE) ? 'M' : '-'),
509 ((cap.buttons & CYAPA_FNGR_RIGHT) ? 'R' : '-'),
514 * Setup input event tracking
517 inputev_init(&sc->iev, "Cypress APA Trackpad (cyapa)");
518 inputev_set_evbit(&sc->iev, EV_ABS);
519 inputev_set_abs_params(&sc->iev, ABS_MT_POSITION_X,
520 0, sc->cap_resx, 0, 0);
521 inputev_set_abs_params(&sc->iev, ABS_MT_POSITION_Y,
522 0, sc->cap_resy, 0, 0);
523 inputev_set_abs_params(&sc->iev, ABS_MT_PRESSURE,
526 inputev_set_res(&sc->iev, ABS_MT_POSITION_X,
527 sc->cap_resx / sc->cap_phyx);
529 inputev_set_res(&sc->iev, ABS_MT_POSITION_Y,
530 sc->cap_resy / sc->cap_phyy);
531 if (cap.buttons & CYAPA_FNGR_LEFT) {
532 inputev_set_keybit(&sc->iev, BTN_LEFT);
533 inputev_set_propbit(&sc->iev, INPUT_PROP_BUTTONPAD);
535 if (cap.buttons & CYAPA_FNGR_MIDDLE)
536 inputev_set_keybit(&sc->iev, BTN_MIDDLE);
537 if (cap.buttons & CYAPA_FNGR_RIGHT)
538 inputev_set_keybit(&sc->iev, BTN_RIGHT);
540 inputev_register(&sc->iev);
544 * Start the polling thread.
546 lwkt_create(cyapa_poll_thread, sc,
547 &sc->poll_td, NULL, 0, -1, "cyapa-poll");
553 cyapa_detach(device_t dev)
555 struct cyapa_softc *sc = (struct cyapa_softc *)device_get_softc(dev);
559 * Cleanup input event tracking
561 inputev_deregister(&sc->iev);
565 * Cleanup our poller thread
567 atomic_set_int(&sc->poll_flags, CYPOLL_SHUTDOWN);
568 while (sc->poll_td) {
569 wakeup(&sc->poll_flags);
570 tsleep(&sc->poll_td, 0, "cyapadet", hz);
574 dev_ops_remove_minor(&cyapa_ops, device_get_unit(dev));
576 devfs_assume_knotes(sc->devnode, &sc->kqinfo);
582 * USER DEVICE I/O FUNCTIONS
585 cyapaopen (struct dev_open_args *ap)
587 cdev_t dev = ap->a_head.a_dev;
588 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev));
602 cyapaclose(struct dev_close_args *ap)
604 cdev_t dev = ap->a_head.a_dev;
605 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev));
611 /* This is not supposed to happen. */
620 cyaparead(struct dev_read_args *ap)
622 cdev_t dev = ap->a_head.a_dev;
623 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev));
625 struct uio *uio = ap->a_uio;
626 int ioflag = ap->a_ioflag;
631 * If buffer is empty, load a new event if it is ready
635 if (fifo_empty(&sc->rfifo) &&
636 (sc->data_signal || sc->delta_x || sc->delta_y ||
637 sc->track_but != sc->reported_but)) {
645 * Accumulate delta_x, delta_y.
648 delta_x = sc->delta_x;
649 delta_y = sc->delta_y;
650 delta_z = sc->delta_z;
655 if (delta_x < -256) {
663 if (delta_y < -256) {
671 if (delta_z < -256) {
678 * Adjust baseline for next calculation
680 sc->delta_x -= delta_x;
681 sc->delta_y -= delta_y;
682 sc->delta_z -= delta_z;
683 sc->reported_but = but;
686 * Fuzz reduces movement jitter by introducing some
687 * hysteresis. It operates without cumulative error so
688 * if you swish around quickly and return your finger to
689 * where it started, so to will the mouse.
691 delta_x = cyapa_fuzz(delta_x, &sc->fuzz_x);
692 delta_y = cyapa_fuzz(delta_y, &sc->fuzz_y);
693 delta_z = cyapa_fuzz(delta_z, &sc->fuzz_z);
704 if (but & CYAPA_FNGR_LEFT)
706 if (but & CYAPA_FNGR_MIDDLE)
708 if (but & CYAPA_FNGR_RIGHT)
711 fifo_write_char(&sc->rfifo, c0);
712 fifo_write_char(&sc->rfifo, (uint8_t)delta_x);
713 fifo_write_char(&sc->rfifo, (uint8_t)delta_y);
714 switch(sc->zenabled) {
719 fifo_write_char(&sc->rfifo, (uint8_t)delta_z);
723 * Z axis low 4 bits + 4th button and 5th button
724 * (high 2 bits must be left 0). Auto-scale
725 * delta_z to fit to avoid a wrong-direction
726 * overflow (don't try to retain the remainder).
728 while (delta_z > 7 || delta_z < -8)
730 c0 = (uint8_t)delta_z & 0x0F;
731 if (but & SIMULATE_BUT4)
733 if (but & SIMULATE_BUT5)
735 fifo_write_char(&sc->rfifo, c0);
747 * Blocking / Non-blocking
750 didread = (uio->uio_resid == 0);
752 while ((ioflag & IO_NDELAY) == 0 && fifo_empty(&sc->rfifo)) {
756 error = lksleep(&sc->blocked, &sc->lk, PCATCH, "cyablk", 0);
762 * Return any buffered data
764 while (error == 0 && uio->uio_resid &&
765 (n = fifo_ready(&sc->rfifo)) > 0) {
766 if (n > uio->uio_resid)
770 uint8_t *ptr = fifo_read(&sc->rfifo, 0);
773 for (v = 0; v < n; ++v)
774 kprintf(" %02x", ptr[v]);
778 error = uiomove(fifo_read(&sc->rfifo, 0), n, uio);
781 fifo_read(&sc->rfifo, n);
786 if (error == 0 && didread == 0)
793 cyapawrite(struct dev_write_args *ap)
795 cdev_t dev = ap->a_head.a_dev;
796 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev));
797 struct uio *uio = ap->a_uio;
805 * Copy data from userland. This will also cross-over the end
806 * of the fifo and keep filling.
809 while ((n = fifo_space(&sc->wfifo)) > 0 && uio->uio_resid) {
810 if (n > uio->uio_resid)
812 error = uiomove(fifo_write(&sc->wfifo, 0), n, uio);
815 fifo_write(&sc->wfifo, n);
821 cmd_completed = (fifo_ready(&sc->wfifo) != 0);
822 while (fifo_ready(&sc->wfifo) && cmd_completed && error == 0) {
823 if (sc->ps2_cmd == 0)
824 sc->ps2_cmd = fifo_read_char(&sc->wfifo);
825 switch(sc->ps2_cmd) {
830 sc->scaling_mode = 0;
831 fifo_write_char(&sc->rfifo, 0xFA);
837 sc->scaling_mode = 1;
838 fifo_write_char(&sc->rfifo, 0xFA);
842 * SET RESOLUTION +1 byte
844 if (sc->ps2_acked == 0) {
846 fifo_write_char(&sc->rfifo, 0xFA);
848 if (fifo_ready(&sc->wfifo) == 0) {
852 sc->resolution = fifo_read_char(&sc->wfifo);
853 fifo_write_char(&sc->rfifo, 0xFA);
861 * bit 6 Mode (1=remote mode, 0=stream mode)
862 * bit 5 Enable (data reporting enabled)
863 * bit 4 Scaling (0=1:1 1=2:1)
865 * bit 2 LEFT BUTTON (1 if pressed)
866 * bit 1 MIDDLE BUTTON (1 if pressed)
867 * bit 0 RIGHT BUTTON (1 if pressed)
869 * byte2: resolution counts/mm
875 if (sc->reporting_mode)
877 if (sc->scaling_mode)
879 if (sc->track_but & CYAPA_FNGR_LEFT)
881 if (sc->track_but & CYAPA_FNGR_MIDDLE)
883 if (sc->track_but & CYAPA_FNGR_RIGHT)
885 fifo_write_char(&sc->rfifo, 0xFA);
886 fifo_write_char(&sc->rfifo, c0);
887 fifo_write_char(&sc->rfifo, 0x00);
888 fifo_write_char(&sc->rfifo, 100);
892 * Set stream mode and reset movement counters
895 fifo_write_char(&sc->rfifo, 0xFA);
902 * Read Data (if in remote mode). If not in remote
903 * mode force an event.
905 fifo_write_char(&sc->rfifo, 0xFA);
910 * Reset Wrap Mode (ignored)
912 fifo_write_char(&sc->rfifo, 0xFA);
916 * Set Wrap Mode (ignored)
918 fifo_write_char(&sc->rfifo, 0xFA);
925 fifo_write_char(&sc->rfifo, 0xFA);
934 * If we send 0x00 - normal PS/2 mouse, no Z-axis
936 * If we send 0x03 - Intellimouse, data packet has
937 * an additional Z movement byte (8 bits signed).
938 * (also reset movement counters)
940 * If we send 0x04 - Now includes z-axis and the
941 * 4th and 5th mouse buttons.
943 fifo_write_char(&sc->rfifo, 0xFA);
944 switch(sc->zenabled) {
946 fifo_write_char(&sc->rfifo, 0x03);
949 fifo_write_char(&sc->rfifo, 0x04);
952 fifo_write_char(&sc->rfifo, 0x00);
963 * byte1: the sample rate
965 if (sc->ps2_acked == 0) {
967 fifo_write_char(&sc->rfifo, 0xFA);
969 if (fifo_ready(&sc->wfifo) == 0) {
973 sc->sample_rate = fifo_read_char(&sc->wfifo);
974 fifo_write_char(&sc->rfifo, 0xFA);
977 * zenabling sequence: 200,100,80 (device id 0x03)
978 * 200,200,80 (device id 0x04)
980 * We support id 0x03 (no 4th or 5th button).
981 * We support id 0x04 (w/ 4th and 5th button).
983 if (sc->zenabled == 0 && sc->sample_rate == 200)
985 else if (sc->zenabled == -1 && sc->sample_rate == 100)
987 else if (sc->zenabled == -1 && sc->sample_rate == 200)
989 else if (sc->zenabled == -2 && sc->sample_rate == 80)
990 sc->zenabled = 1; /* z-axis mode */
991 else if (sc->zenabled == -3 && sc->sample_rate == 80)
992 sc->zenabled = 2; /* z-axis+but4/5 */
996 * Enable data reporting. Only effects stream mode.
998 fifo_write_char(&sc->rfifo, 0xFA);
999 sc->reporting_mode = 1;
1003 * Disable data reporting. Only effects stream mode.
1005 fifo_write_char(&sc->rfifo, 0xFA);
1006 sc->reporting_mode = 1;
1012 * (reset sampling rate, resolution, scaling and
1013 * enter stream mode)
1015 fifo_write_char(&sc->rfifo, 0xFA);
1016 sc->sample_rate = 100;
1018 sc->scaling_mode = 0;
1019 sc->reporting_mode = 0;
1020 sc->remote_mode = 0;
1030 * Force a resend by guaranteeing that reported_but
1031 * differs from track_but.
1033 fifo_write_char(&sc->rfifo, 0xFA);
1034 sc->data_signal = 1;
1040 fifo_reset(&sc->rfifo); /* should we do this? */
1041 fifo_reset(&sc->wfifo); /* should we do this? */
1042 fifo_write_char(&sc->rfifo, 0xFA);
1049 kprintf("unknown command %02x\n", sc->ps2_cmd);
1052 if (cmd_completed) {
1061 if (error == 0 && (cmd_completed || uio->uio_resid))
1066 static void cyapa_filt_detach(struct knote *);
1067 static int cyapa_filt(struct knote *, long);
1069 static struct filterops cyapa_filtops =
1070 { FILTEROP_ISFD, NULL, cyapa_filt_detach, cyapa_filt };
1073 cyapakqfilter(struct dev_kqfilter_args *ap)
1075 cdev_t dev = ap->a_head.a_dev;
1076 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev));
1077 struct knote *kn = ap->a_kn;
1078 struct klist *klist;
1080 switch(kn->kn_filter) {
1082 kn->kn_fop = &cyapa_filtops;
1083 kn->kn_hook = (void *)sc;
1087 ap->a_result = EOPNOTSUPP;
1090 klist = &sc->kqinfo.ki_note;
1091 knote_insert(klist, kn);
1097 cyapa_filt_detach(struct knote *kn)
1099 struct cyapa_softc *sc = (struct cyapa_softc *)kn->kn_hook;
1100 struct klist *klist;
1102 klist = &sc->kqinfo.ki_note;
1103 knote_remove(klist, kn);
1107 cyapa_filt(struct knote *kn, long hint)
1109 struct cyapa_softc *sc = (struct cyapa_softc *)kn->kn_hook;
1113 if (fifo_ready(&sc->rfifo) || sc->data_signal)
1123 cyapaioctl(struct dev_ioctl_args *ap)
1125 cdev_t dev = ap->a_head.a_dev;
1126 device_t bus; /* smbbus */
1127 /*struct cyapacmd *s = (struct cyapacmd *)ap->a_data;*/
1129 struct cyapa_softc *sc = CYAPA_SOFTC(minor(dev));
1138 * NOTE: smbus_*() functions automatically recurse the parent to
1139 * get to the actual device driver.
1141 bus = device_get_parent(sc->dev); /* smbus */
1143 /* Allocate the bus. */
1144 if ((error = smbus_request_bus(bus, sc->dev,
1145 (ap->a_fflag & O_NONBLOCK) ?
1146 SMB_DONTWAIT : (SMB_WAIT | SMB_INTR))))
1149 switch (ap->a_cmd) {
1152 error = inputev_ioctl(&sc->iev, ap->a_cmd, ap->a_data);
1158 smbus_release_bus(bus, sc->dev);
1164 * MAJOR SUPPORT FUNCTIONS
1168 cyapa_poll_thread(void *arg)
1170 struct cyapa_softc *sc = arg;
1171 struct cyapa_regs regs;
1172 device_t bus; /* smbbus */
1174 int freq = cyapa_norm_freq;
1177 bus = device_get_parent(sc->dev);
1179 while ((sc->poll_flags & CYPOLL_SHUTDOWN) == 0) {
1180 error = smbus_request_bus(bus, sc->dev, SMB_WAIT);
1182 error = smbus_trans(bus, sc->addr, CMD_DEV_STATUS,
1183 SMB_TRANS_NOCNT | SMB_TRANS_7BIT,
1185 (void *)®s, sizeof(regs), NULL);
1187 isidle = cyapa_raw_input(sc, ®s);
1189 smbus_release_bus(bus, sc->dev);
1191 tsleep(&sc->poll_flags, 0, "cyapw", (hz + freq - 1) / freq);
1194 freq = cyapa_idle_freq;
1196 freq = cyapa_slow_freq;
1198 freq = cyapa_norm_freq;
1201 wakeup(&sc->poll_td);
1206 cyapa_raw_input(struct cyapa_softc *sc, struct cyapa_regs *regs)
1218 uint16_t but; /* high bits used for simulated but4/but5 */
1220 nfingers = CYAPA_FNGR_NUMFINGERS(regs->fngr);
1223 kprintf("stat %02x buttons %c%c%c nfngrs=%d ",
1225 ((regs->fngr & CYAPA_FNGR_LEFT) ? 'L' : '-'),
1226 ((regs->fngr & CYAPA_FNGR_MIDDLE) ? 'L' : '-'),
1227 ((regs->fngr & CYAPA_FNGR_RIGHT) ? 'L' : '-'),
1231 for (i = 0; i < nfingers; ++i) {
1233 kprintf(" [x=%04d y=%04d p=%d]",
1234 CYAPA_TOUCH_X(regs, i),
1235 CYAPA_TOUCH_Y(regs, i),
1236 CYAPA_TOUCH_P(regs, i));
1239 inputev_mt_slot(&sc->iev, regs->touch[i].id - 1);
1240 inputev_mt_report_slot_state(&sc->iev, MT_TOOL_FINGER, 1);
1241 inputev_report_abs(&sc->iev, ABS_MT_POSITION_X,
1242 CYAPA_TOUCH_X(regs, i));
1243 inputev_report_abs(&sc->iev, ABS_MT_POSITION_Y,
1244 CYAPA_TOUCH_Y(regs, i));
1245 inputev_report_abs(&sc->iev, ABS_MT_PRESSURE,
1246 CYAPA_TOUCH_P(regs, i));
1250 inputev_mt_sync_frame(&sc->iev);
1252 if (sc->cap_buttons & CYAPA_FNGR_LEFT)
1253 inputev_report_key(&sc->iev, BTN_LEFT,
1254 regs->fngr & CYAPA_FNGR_LEFT);
1255 if (sc->cap_buttons & CYAPA_FNGR_MIDDLE)
1256 inputev_report_key(&sc->iev, BTN_LEFT,
1257 regs->fngr & CYAPA_FNGR_MIDDLE);
1258 if (sc->cap_buttons & CYAPA_FNGR_RIGHT)
1259 inputev_report_key(&sc->iev, BTN_LEFT,
1260 regs->fngr & CYAPA_FNGR_RIGHT);
1263 * Tracking for local solutions
1268 * Track timing for finger-downs. Used to detect false-3-finger
1275 if (sc->track_nfingers == 0)
1276 sc->finger1_ticks = sc->poll_ticks;
1279 if (sc->track_nfingers <= 0)
1280 sc->finger1_ticks = sc->poll_ticks;
1281 if (sc->track_nfingers <= 1)
1282 sc->finger2_ticks = sc->poll_ticks;
1286 if (sc->track_nfingers <= 0)
1287 sc->finger1_ticks = sc->poll_ticks;
1288 if (sc->track_nfingers <= 1)
1289 sc->finger2_ticks = sc->poll_ticks;
1290 if (sc->track_nfingers <= 2)
1291 sc->finger3_ticks = sc->poll_ticks;
1295 kprintf("%d->%d %d (%d) (%d)\n",
1296 sc->track_nfingers, nfingers,
1297 (nfingers >= 1 ? sc->finger1_ticks : 0),
1298 (nfingers >= 2 ? sc->finger2_ticks - sc->finger1_ticks : 0),
1299 (nfingers >= 3 ? sc->finger3_ticks - sc->finger1_ticks : 0));
1301 sc->track_nfingers = nfingers;
1304 * Lookup and track finger indexes in the touch[] array.
1306 if (nfingers == 0) {
1324 * The id assigned on touch can move around in the array,
1325 * find it. If that finger is lifted up, assign some other
1326 * finger for mouse tracking and reset track_x and track_y
1327 * to avoid a mouse jump.
1329 * If >= 2 fingers are down be sure not to assign i and
1330 * j to the same index.
1332 for (i = 0; i < nfingers; ++i) {
1333 if (sc->track_id1 == regs->touch[i].id)
1336 if (i == nfingers) {
1341 sc->track_id1 = regs->touch[i].id;
1342 if (sc->track_id2 == sc->track_id1)
1349 for (j = 0; j < nfingers; ++j) {
1350 if (sc->track_id2 == regs->touch[j].id)
1353 if (j == nfingers) {
1354 if (nfingers >= 2) {
1359 sc->track_id2 = regs->touch[j].id;
1367 * The third finger is used to tap or tap-hold to simulate
1368 * a button, we don't have to record it persistently.
1370 if (nfingers >= 3) {
1372 if (i == 0 || j == 0)
1374 if (i == 1 || j == 1)
1382 * On initial touch determine if we are in the slider area. Setting
1383 * track_z conditionalizes the delta calculations later on.
1385 if (nfingers && sc->zenabled > 0 &&
1386 sc->track_x == -1 && sc->track_z == -1) {
1387 x = CYAPA_TOUCH_X(regs, i);
1388 z = CYAPA_TOUCH_Y(regs, i);
1389 if (x > sc->cap_resx * 9 / 10)
1393 if (nfingers && sc->track_z != -1) {
1395 * Slider emulation (right side of trackpad). Z is tracked
1396 * based on the Y position. X and Y tracking are disabled.
1398 * Because we are emulating a mouse-wheel, we do not want
1399 * to shove events out at the maximum resolution.
1401 z = CYAPA_TOUCH_Y(regs, i);
1402 sc->delta_z += z / ZSCALE - sc->track_z;
1403 if (sc->touch_z == -1)
1404 sc->touch_z = z; /* not used atm */
1405 sc->track_z = z / ZSCALE;
1406 } else if (nfingers) {
1408 * Normal pad position reporting (track_z is left -1)
1410 x = CYAPA_TOUCH_X(regs, i);
1411 y = CYAPA_TOUCH_Y(regs, i);
1412 if (sc->track_x != -1) {
1413 sc->delta_x += x - sc->track_x;
1414 sc->delta_y -= y - sc->track_y;
1415 if (sc->delta_x > sc->cap_resx)
1416 sc->delta_x = sc->cap_resx;
1417 if (sc->delta_x < -sc->cap_resx)
1418 sc->delta_x = -sc->cap_resx;
1419 if (sc->delta_y > sc->cap_resx)
1420 sc->delta_y = sc->cap_resy;
1421 if (sc->delta_y < -sc->cap_resy)
1422 sc->delta_y = -sc->cap_resy;
1424 if (sc->touch_x == -1) {
1431 if (nfingers >= 5 && sc->zenabled > 1 && sc->track_z < 0) {
1433 * Simulate the 5th button (when not in slider mode)
1435 but = SIMULATE_BUT5;
1436 } else if (nfingers >= 4 && sc->zenabled > 1 && sc->track_z < 0) {
1438 * Simulate the 4th button (when not in slider mode)
1440 but = SIMULATE_BUT4;
1441 } else if (nfingers >= 3 && sc->track_z < 0) {
1443 * Simulate the left, middle, or right button with 3
1444 * fingers when not in slider mode.
1446 * This makes it ultra easy to hit GUI buttons and move
1447 * windows with a light touch, without having to apply the
1448 * pressure required to articulate the button.
1450 * However, if we are coming down from 4 or 5 fingers,
1451 * do NOT simulate the left button and instead just release
1452 * button 4 or button 5. Leave SIMULATE_LOCK set to
1453 * placemark the condition. We must go down to 2 fingers
1454 * to release the lock.
1456 * LEFT BUTTON: Fingers arranged left-to-right 1 2 3,
1457 * move mouse with fingers 2 and 3 and tap
1458 * or hold with finger 1 (to the left of fingers
1461 * RIGHT BUTTON: Move mouse with fingers 1 and 2 and tap
1462 * or hold with finger 3.
1464 * MIDDLE BUTTON: Move mouse with fingers 1 and 3 and tap
1465 * or hold with finger 2.
1467 * Finally, detect when all three fingers were placed down
1468 * within one tick of each other.
1470 x1 = CYAPA_TOUCH_X(regs, i); /* 1st finger down */
1471 x2 = CYAPA_TOUCH_X(regs, j); /* 2nd finger down */
1472 x = CYAPA_TOUCH_X(regs, k); /* 3rd finger (button) down */
1473 if (sc->track_but & (SIMULATE_BUT4 |
1476 but = SIMULATE_LOCK;
1477 } else if (sc->track_but & ~SIMULATE_LOCK) {
1478 but = sc->track_but;
1479 } else if ((int)(sc->finger3_ticks - sc->finger1_ticks) <
1480 cyapa_norm_freq / 25 + 1) {
1482 * False 3-finger button detection (but still detect
1483 * if the actual physical button is held down).
1485 if (regs->fngr & CYAPA_FNGR_LEFT)
1486 but = CYAPA_FNGR_LEFT;
1489 } else if (x < x1 && x < x2) {
1490 but = CYAPA_FNGR_LEFT;
1491 } else if (x > x1 && x < x2) {
1492 but = CYAPA_FNGR_MIDDLE;
1493 } else if (x > x2 && x < x1) {
1494 but = CYAPA_FNGR_MIDDLE;
1496 but = CYAPA_FNGR_RIGHT;
1498 } else if (nfingers == 2 || (nfingers >= 2 && sc->track_z >= 0)) {
1500 * If 2 fingers are held down or 2 or more fingers are held
1501 * down and we are in slider mode, any key press is
1502 * interpreted as a left mouse button press.
1504 * If a keypress is already active we retain the active
1507 * The high-button state is unconditionally cleared with <= 2
1510 if (regs->fngr & CYAPA_FNGR_LEFT) {
1511 but = sc->track_but & ~SIMULATE_LOCK;
1513 but = CYAPA_FNGR_LEFT;
1517 } else if (nfingers == 1 &&
1518 (abs(sc->touch_x - sc->track_x) > 32 ||
1519 abs(sc->touch_y - sc->track_y) > 32)) {
1521 * When using one finger, any significant mouse movement
1522 * will lock you to the left mouse button if you push the
1523 * button, regardless of where you are on the pad.
1525 * If a keypress is already active we retain the active
1528 * The high-button state is unconditionally cleared with <= 2
1531 if (regs->fngr & CYAPA_FNGR_LEFT) {
1532 but = sc->track_but & ~SIMULATE_LOCK;
1534 but = CYAPA_FNGR_LEFT;
1538 } else if (nfingers == 1 && (regs->fngr & CYAPA_FNGR_LEFT)) {
1540 * If you are swiping while holding a button down, the
1541 * button registration does not change. Otherwise the
1542 * registered button depends on where you are on the pad.
1544 * Since no significant movement occurred we allow the
1545 * button to be pressed while within the slider area
1546 * and still be properly registered as the right button.
1548 * The high-button state is unconditionally cleared with <= 2
1551 if (sc->track_but & ~SIMULATE_LOCK)
1552 but = sc->track_but & ~SIMULATE_LOCK;
1553 else if (sc->track_x < sc->cap_resx * 1 / 3)
1554 but = CYAPA_FNGR_LEFT;
1555 else if (sc->track_x < sc->cap_resx * 2 / 3)
1556 but = CYAPA_FNGR_MIDDLE;
1558 but = CYAPA_FNGR_RIGHT;
1559 } else if (nfingers == 1) {
1561 * Clear all finger state if 1 finger is down and nothing
1567 * Clear all finger state if no fingers are down.
1573 * Detect state change from last reported state and
1574 * determine if we have gone idle.
1576 sc->track_but = but;
1577 if (sc->delta_x || sc->delta_y || sc->delta_z ||
1578 sc->track_but != sc->reported_but) {
1579 sc->active_tick = ticks;
1580 if (sc->remote_mode == 0 && sc->reporting_mode)
1581 sc->data_signal = 1;
1583 } else if ((unsigned)(ticks - sc->active_tick) > hz) {
1584 sc->active_tick = ticks - hz; /* prevent overflow */
1602 * Returns non-zero if the fifo is empty
1606 fifo_empty(struct cyapa_fifo *fifo)
1608 return(fifo->rindex == fifo->windex);
1612 * Returns the number of characters available for reading from
1613 * the fifo without wrapping the fifo buffer.
1617 fifo_ready(struct cyapa_fifo *fifo)
1621 n = CYAPA_BUFSIZE - (fifo->rindex & CYAPA_BUFMASK);
1622 if (n > (size_t)(fifo->windex - fifo->rindex))
1623 n = (size_t)(fifo->windex - fifo->rindex);
1629 * Returns the number of characters available for reading from
1630 * the fifo including wrapping the fifo buffer.
1634 fifo_total_ready(struct cyapa_fifo *fifo)
1636 return ((size_t)(fifo->windex - fifo->rindex));
1641 * Returns a read pointer into the fifo and then bumps
1642 * rindex. The FIFO must have at least 'n' characters in
1643 * it. The value (n) can cause the index to wrap but users
1644 * of the buffer should never supply a value for (n) that wraps
1649 fifo_read(struct cyapa_fifo *fifo, size_t n)
1653 if (n > (CYAPA_BUFSIZE - (fifo->rindex & CYAPA_BUFMASK))) {
1654 kprintf("fifo_read: overflow\n");
1657 ptr = fifo->buf + (fifo->rindex & CYAPA_BUFMASK);
1665 fifo_read_char(struct cyapa_fifo *fifo)
1669 if (fifo->rindex == fifo->windex) {
1670 kprintf("fifo_read_char: overflow\n");
1673 c = fifo->buf[fifo->rindex & CYAPA_BUFMASK];
1681 * Write a character to the FIFO. The character will be discarded
1682 * if the FIFO is full.
1686 fifo_write_char(struct cyapa_fifo *fifo, uint8_t c)
1688 if (fifo->windex - fifo->rindex < CYAPA_BUFSIZE) {
1689 fifo->buf[fifo->windex & CYAPA_BUFMASK] = c;
1695 * Return the amount of space available for writing without wrapping
1700 fifo_space(struct cyapa_fifo *fifo)
1704 n = CYAPA_BUFSIZE - (fifo->windex & CYAPA_BUFMASK);
1705 if (n > (size_t)(CYAPA_BUFSIZE - (fifo->windex - fifo->rindex)))
1706 n = (size_t)(CYAPA_BUFSIZE - (fifo->windex - fifo->rindex));
1712 fifo_write(struct cyapa_fifo *fifo, size_t n)
1716 ptr = fifo->buf + (fifo->windex & CYAPA_BUFMASK);
1724 fifo_reset(struct cyapa_fifo *fifo)
1735 cyapa_fuzz(short delta, short *fuzzp)
1740 if (fuzz >= 0 && delta < 0) {
1743 } else if (fuzz <= 0 && delta > 0) {
1752 DRIVER_MODULE(cyapa, smbus, cyapa_driver, cyapa_devclass, NULL, NULL);
1753 MODULE_DEPEND(cyapa, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
1754 MODULE_VERSION(cyapa, 1);