1184299Snwhitehorn/*- 2184299Snwhitehorn * Copyright (C) 2008 Nathan Whitehorn 3184299Snwhitehorn * All rights reserved. 4184299Snwhitehorn * 5184299Snwhitehorn * Redistribution and use in source and binary forms, with or without 6184299Snwhitehorn * modification, are permitted provided that the following conditions 7184299Snwhitehorn * are met: 8184299Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9184299Snwhitehorn * notice, this list of conditions and the following disclaimer. 10184299Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11184299Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12184299Snwhitehorn * documentation and/or other materials provided with the distribution. 13184299Snwhitehorn * 14184299Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15184299Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16184299Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17184299Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18184299Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19184299Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20184299Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21184299Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22184299Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23184299Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24184299Snwhitehorn * 25184299Snwhitehorn * $FreeBSD: stable/11/sys/dev/adb/adb_mouse.c 316369 2017-04-01 19:27:06Z jhibbits $ 26184299Snwhitehorn */ 27184299Snwhitehorn 28184299Snwhitehorn#include <sys/cdefs.h> 29184299Snwhitehorn#include <sys/param.h> 30184299Snwhitehorn#include <sys/systm.h> 31184299Snwhitehorn#include <sys/module.h> 32184299Snwhitehorn#include <sys/bus.h> 33184299Snwhitehorn#include <sys/conf.h> 34184299Snwhitehorn#include <sys/mouse.h> 35184299Snwhitehorn#include <sys/poll.h> 36184299Snwhitehorn#include <sys/condvar.h> 37184299Snwhitehorn#include <sys/selinfo.h> 38199888Snwhitehorn#include <sys/sysctl.h> 39184299Snwhitehorn#include <sys/uio.h> 40184299Snwhitehorn#include <sys/fcntl.h> 41184299Snwhitehorn#include <sys/kernel.h> 42184299Snwhitehorn 43184299Snwhitehorn#include <machine/bus.h> 44184299Snwhitehorn 45184299Snwhitehorn#include <vm/vm.h> 46184299Snwhitehorn#include <vm/pmap.h> 47184299Snwhitehorn 48184299Snwhitehorn#include "adb.h" 49184299Snwhitehorn 50187893Sjhb#define CDEV_GET_SOFTC(x) (x)->si_drv1 51184299Snwhitehorn 52184299Snwhitehornstatic int adb_mouse_probe(device_t dev); 53184299Snwhitehornstatic int adb_mouse_attach(device_t dev); 54184299Snwhitehornstatic int adb_mouse_detach(device_t dev); 55199888Snwhitehornstatic void adb_init_trackpad(device_t dev); 56199888Snwhitehornstatic int adb_tapping_sysctl(SYSCTL_HANDLER_ARGS); 57184299Snwhitehorn 58184299Snwhitehornstatic d_open_t ams_open; 59184299Snwhitehornstatic d_close_t ams_close; 60184299Snwhitehornstatic d_read_t ams_read; 61184299Snwhitehornstatic d_ioctl_t ams_ioctl; 62184299Snwhitehornstatic d_poll_t ams_poll; 63184299Snwhitehorn 64184299Snwhitehornstatic u_int adb_mouse_receive_packet(device_t dev, u_char status, 65184299Snwhitehorn u_char command, u_char reg, int len, u_char *data); 66184299Snwhitehorn 67184299Snwhitehornstruct adb_mouse_softc { 68184299Snwhitehorn device_t sc_dev; 69184299Snwhitehorn 70184299Snwhitehorn struct mtx sc_mtx; 71184299Snwhitehorn struct cv sc_cv; 72184299Snwhitehorn 73184565Sed int flags; 74184565Sed#define AMS_EXTENDED 0x1 75184565Sed#define AMS_TOUCHPAD 0x2 76184299Snwhitehorn uint16_t dpi; 77184299Snwhitehorn 78184299Snwhitehorn mousehw_t hw; 79184299Snwhitehorn mousemode_t mode; 80184299Snwhitehorn u_char id[4]; 81184299Snwhitehorn 82184299Snwhitehorn int buttons; 83199888Snwhitehorn u_int sc_tapping; 84199888Snwhitehorn int button_buf; 85184299Snwhitehorn int last_buttons; 86184299Snwhitehorn int xdelta, ydelta; 87184299Snwhitehorn 88184299Snwhitehorn int8_t packet[8]; 89184299Snwhitehorn size_t packet_read_len; 90184299Snwhitehorn 91184299Snwhitehorn struct cdev *cdev; 92184299Snwhitehorn struct selinfo rsel; 93184299Snwhitehorn}; 94184299Snwhitehorn 95184299Snwhitehornstatic device_method_t adb_mouse_methods[] = { 96184299Snwhitehorn /* Device interface */ 97184299Snwhitehorn DEVMETHOD(device_probe, adb_mouse_probe), 98184299Snwhitehorn DEVMETHOD(device_attach, adb_mouse_attach), 99184299Snwhitehorn DEVMETHOD(device_detach, adb_mouse_detach), 100184299Snwhitehorn DEVMETHOD(device_shutdown, bus_generic_shutdown), 101184299Snwhitehorn DEVMETHOD(device_suspend, bus_generic_suspend), 102184299Snwhitehorn DEVMETHOD(device_resume, bus_generic_resume), 103184299Snwhitehorn 104184299Snwhitehorn /* ADB interface */ 105184299Snwhitehorn DEVMETHOD(adb_receive_packet, adb_mouse_receive_packet), 106184299Snwhitehorn 107184299Snwhitehorn { 0, 0 } 108184299Snwhitehorn}; 109184299Snwhitehorn 110184299Snwhitehornstatic driver_t adb_mouse_driver = { 111184299Snwhitehorn "ams", 112184299Snwhitehorn adb_mouse_methods, 113184299Snwhitehorn sizeof(struct adb_mouse_softc), 114184299Snwhitehorn}; 115184299Snwhitehorn 116184299Snwhitehornstatic devclass_t adb_mouse_devclass; 117184299Snwhitehorn 118184299SnwhitehornDRIVER_MODULE(ams, adb, adb_mouse_driver, adb_mouse_devclass, 0, 0); 119184299Snwhitehorn 120184299Snwhitehornstatic struct cdevsw ams_cdevsw = { 121184299Snwhitehorn .d_version = D_VERSION, 122184299Snwhitehorn .d_flags = 0, 123184299Snwhitehorn .d_open = ams_open, 124184299Snwhitehorn .d_close = ams_close, 125184299Snwhitehorn .d_read = ams_read, 126184299Snwhitehorn .d_ioctl = ams_ioctl, 127184299Snwhitehorn .d_poll = ams_poll, 128184299Snwhitehorn .d_name = "ams", 129184299Snwhitehorn}; 130184299Snwhitehorn 131184299Snwhitehornstatic int 132184299Snwhitehornadb_mouse_probe(device_t dev) 133184299Snwhitehorn{ 134184299Snwhitehorn uint8_t type; 135184299Snwhitehorn 136184299Snwhitehorn type = adb_get_device_type(dev); 137184299Snwhitehorn 138184299Snwhitehorn if (type != ADB_DEVICE_MOUSE) 139184299Snwhitehorn return (ENXIO); 140184299Snwhitehorn 141184299Snwhitehorn device_set_desc(dev,"ADB Mouse"); 142184299Snwhitehorn return (0); 143184299Snwhitehorn} 144184299Snwhitehorn 145184299Snwhitehornstatic int 146184299Snwhitehornadb_mouse_attach(device_t dev) 147184299Snwhitehorn{ 148184299Snwhitehorn struct adb_mouse_softc *sc; 149184299Snwhitehorn char *description = "Unknown Pointing Device"; 150184299Snwhitehorn 151184299Snwhitehorn size_t r1_len; 152184299Snwhitehorn u_char r1[8]; 153184299Snwhitehorn 154184299Snwhitehorn sc = device_get_softc(dev); 155184299Snwhitehorn sc->sc_dev = dev; 156184299Snwhitehorn 157261068Sjhibbits mtx_init(&sc->sc_mtx, "ams", NULL, MTX_DEF); 158184299Snwhitehorn cv_init(&sc->sc_cv,"ams"); 159184299Snwhitehorn 160184565Sed sc->flags = 0; 161184299Snwhitehorn 162184299Snwhitehorn sc->hw.buttons = 2; 163184299Snwhitehorn sc->hw.iftype = MOUSE_IF_UNKNOWN; 164184299Snwhitehorn sc->hw.type = MOUSE_UNKNOWN; 165184299Snwhitehorn sc->hw.model = sc->hw.hwid = 0; 166184299Snwhitehorn 167184299Snwhitehorn sc->mode.protocol = MOUSE_PROTO_SYSMOUSE; 168184299Snwhitehorn sc->mode.rate = -1; 169184299Snwhitehorn sc->mode.resolution = 100; 170184299Snwhitehorn sc->mode.accelfactor = 0; 171184299Snwhitehorn sc->mode.level = 0; 172184299Snwhitehorn sc->mode.packetsize = 5; 173184299Snwhitehorn 174184299Snwhitehorn sc->buttons = 0; 175199888Snwhitehorn sc->sc_tapping = 0; 176199888Snwhitehorn sc->button_buf = 0; 177184299Snwhitehorn sc->last_buttons = 0; 178184299Snwhitehorn sc->packet_read_len = 0; 179184299Snwhitehorn 180184299Snwhitehorn /* Try to switch to extended protocol */ 181184299Snwhitehorn adb_set_device_handler(dev,4); 182184299Snwhitehorn 183184299Snwhitehorn switch(adb_get_device_handler(dev)) { 184184299Snwhitehorn case 1: 185184299Snwhitehorn sc->mode.resolution = 100; 186184299Snwhitehorn break; 187184299Snwhitehorn case 2: 188184299Snwhitehorn sc->mode.resolution = 200; 189184299Snwhitehorn break; 190184299Snwhitehorn case 4: 191185724Snwhitehorn r1_len = adb_read_register(dev,1,r1); 192184299Snwhitehorn if (r1_len < 8) 193184299Snwhitehorn break; 194184299Snwhitehorn 195184565Sed sc->flags |= AMS_EXTENDED; 196184299Snwhitehorn memcpy(&sc->hw.hwid,r1,4); 197184299Snwhitehorn sc->mode.resolution = (r1[4] << 8) | r1[5]; 198184299Snwhitehorn 199184299Snwhitehorn switch (r1[6]) { 200184299Snwhitehorn case 0: 201184299Snwhitehorn sc->hw.type = MOUSE_PAD; 202184299Snwhitehorn description = "Tablet"; 203184299Snwhitehorn break; 204184299Snwhitehorn case 1: 205184299Snwhitehorn sc->hw.type = MOUSE_MOUSE; 206184299Snwhitehorn description = "Mouse"; 207184299Snwhitehorn break; 208184299Snwhitehorn case 2: 209184299Snwhitehorn sc->hw.type = MOUSE_TRACKBALL; 210184299Snwhitehorn description = "Trackball"; 211184299Snwhitehorn break; 212184565Sed case 3: 213184565Sed sc->flags |= AMS_TOUCHPAD; 214184565Sed sc->hw.type = MOUSE_PAD; 215199888Snwhitehorn adb_init_trackpad(dev); 216184565Sed description = "Touchpad"; 217184565Sed break; 218184299Snwhitehorn } 219184299Snwhitehorn 220184299Snwhitehorn sc->hw.buttons = r1[7]; 221184299Snwhitehorn 222184299Snwhitehorn device_printf(dev,"%d-button %d-dpi %s\n", 223184299Snwhitehorn sc->hw.buttons, sc->mode.resolution,description); 224184299Snwhitehorn 225184299Snwhitehorn /* 226184299Snwhitehorn * Check for one of MacAlly's non-compliant 2-button mice. 227184299Snwhitehorn * These claim to speak the extended mouse protocol, but 228184299Snwhitehorn * instead speak the standard protocol and only when their 229184299Snwhitehorn * handler is set to 0x42. 230184299Snwhitehorn */ 231184299Snwhitehorn 232184299Snwhitehorn if (sc->hw.hwid == 0x4b4f4954) { 233184299Snwhitehorn adb_set_device_handler(dev,0x42); 234184299Snwhitehorn 235184299Snwhitehorn if (adb_get_device_handler(dev) == 0x42) { 236184299Snwhitehorn device_printf(dev, "MacAlly 2-Button Mouse\n"); 237184565Sed sc->flags &= ~AMS_EXTENDED; 238184299Snwhitehorn } 239184299Snwhitehorn } 240184299Snwhitehorn 241184299Snwhitehorn break; 242184299Snwhitehorn } 243184299Snwhitehorn 244184299Snwhitehorn sc->cdev = make_dev(&ams_cdevsw, device_get_unit(dev), 245184299Snwhitehorn UID_ROOT, GID_OPERATOR, 0644, "ams%d", 246184299Snwhitehorn device_get_unit(dev)); 247187893Sjhb sc->cdev->si_drv1 = sc; 248184299Snwhitehorn 249184299Snwhitehorn adb_set_autopoll(dev,1); 250184299Snwhitehorn 251184299Snwhitehorn return (0); 252184299Snwhitehorn} 253184299Snwhitehorn 254184299Snwhitehornstatic int 255184299Snwhitehornadb_mouse_detach(device_t dev) 256184299Snwhitehorn{ 257184299Snwhitehorn struct adb_mouse_softc *sc; 258184299Snwhitehorn 259184299Snwhitehorn adb_set_autopoll(dev,0); 260184299Snwhitehorn 261184299Snwhitehorn sc = device_get_softc(dev); 262184299Snwhitehorn destroy_dev(sc->cdev); 263184299Snwhitehorn 264184299Snwhitehorn mtx_destroy(&sc->sc_mtx); 265184299Snwhitehorn cv_destroy(&sc->sc_cv); 266184299Snwhitehorn 267184299Snwhitehorn return (0); 268184299Snwhitehorn} 269184299Snwhitehorn 270199888Snwhitehornstatic void 271199888Snwhitehornadb_init_trackpad(device_t dev) 272199888Snwhitehorn{ 273199888Snwhitehorn struct adb_mouse_softc *sc; 274199888Snwhitehorn struct sysctl_ctx_list *ctx; 275199888Snwhitehorn struct sysctl_oid *tree; 276199888Snwhitehorn 277199888Snwhitehorn size_t r1_len; 278199888Snwhitehorn u_char r1[8]; 279199888Snwhitehorn u_char r2[8]; 280199888Snwhitehorn 281199888Snwhitehorn sc = device_get_softc(dev); 282199888Snwhitehorn 283199888Snwhitehorn r1_len = adb_read_register(dev, 1, r1); 284199888Snwhitehorn 285199888Snwhitehorn /* An Extended Mouse register1 must return 8 bytes. */ 286199888Snwhitehorn if (r1_len != 8) 287199888Snwhitehorn return; 288199888Snwhitehorn 289199888Snwhitehorn if((r1[6] != 0x0d)) 290199888Snwhitehorn { 291199888Snwhitehorn r1[6] = 0x0d; 292199888Snwhitehorn 293199888Snwhitehorn adb_write_register(dev, 1, 8, r1); 294199888Snwhitehorn 295199888Snwhitehorn r1_len = adb_read_register(dev, 1, r1); 296199888Snwhitehorn 297199888Snwhitehorn if (r1[6] != 0x0d) 298199888Snwhitehorn { 299199888Snwhitehorn device_printf(dev, "ADB Mouse = 0x%x " 300199888Snwhitehorn "(non-Extended Mode)\n", r1[6]); 301199888Snwhitehorn return; 302199888Snwhitehorn } else { 303199888Snwhitehorn device_printf(dev, "ADB Mouse = 0x%x " 304199888Snwhitehorn "(Extended Mode)\n", r1[6]); 305199888Snwhitehorn 306199888Snwhitehorn /* Set ADB Extended Features to default values, 307199888Snwhitehorn enabled. */ 308199888Snwhitehorn r2[0] = 0x19; /* Clicking: 0x19 disabled 0x99 enabled */ 309199888Snwhitehorn r2[1] = 0x94; /* Dragging: 0x14 disabled 0x94 enabled */ 310199888Snwhitehorn r2[2] = 0x19; 311199888Snwhitehorn r2[3] = 0xff; /* DragLock: 0xff disabled 0xb2 enabled */ 312199888Snwhitehorn r2[4] = 0xb2; 313199888Snwhitehorn r2[5] = 0x8a; 314199888Snwhitehorn r2[6] = 0x1b; 315199888Snwhitehorn 316199888Snwhitehorn r2[7] = 0x57; /* 0x57 bits 3:0 for W mode */ 317199888Snwhitehorn 318199888Snwhitehorn adb_write_register(dev, 2, 8, r2); 319199888Snwhitehorn 320199888Snwhitehorn } 321199888Snwhitehorn } 322199888Snwhitehorn 323199888Snwhitehorn /* 324199888Snwhitehorn * Set up sysctl 325199888Snwhitehorn */ 326199888Snwhitehorn ctx = device_get_sysctl_ctx(dev); 327199888Snwhitehorn tree = device_get_sysctl_tree(dev); 328199888Snwhitehorn SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "tapping", 329199888Snwhitehorn CTLTYPE_INT | CTLFLAG_RW, sc, 0, adb_tapping_sysctl, 330199888Snwhitehorn "I", "Tapping the pad causes button events"); 331199888Snwhitehorn return; 332199888Snwhitehorn} 333199888Snwhitehorn 334184299Snwhitehornstatic u_int 335184299Snwhitehornadb_mouse_receive_packet(device_t dev, u_char status, u_char command, 336184299Snwhitehorn u_char reg, int len, u_char *data) 337184299Snwhitehorn{ 338184299Snwhitehorn struct adb_mouse_softc *sc; 339184299Snwhitehorn int i = 0; 340184299Snwhitehorn int xdelta, ydelta; 341199888Snwhitehorn int buttons, tmp_buttons; 342184299Snwhitehorn 343184299Snwhitehorn sc = device_get_softc(dev); 344184299Snwhitehorn 345184299Snwhitehorn if (command != ADB_COMMAND_TALK || reg != 0 || len < 2) 346184299Snwhitehorn return (0); 347184299Snwhitehorn 348184299Snwhitehorn ydelta = data[0] & 0x7f; 349184299Snwhitehorn xdelta = data[1] & 0x7f; 350184299Snwhitehorn 351184299Snwhitehorn buttons = 0; 352184299Snwhitehorn buttons |= !(data[0] & 0x80); 353184299Snwhitehorn buttons |= !(data[1] & 0x80) << 1; 354184299Snwhitehorn 355184565Sed if (sc->flags & AMS_EXTENDED) { 356184299Snwhitehorn for (i = 2; i < len && i < 5; i++) { 357184299Snwhitehorn xdelta |= (data[i] & 0x07) << (3*i + 1); 358184299Snwhitehorn ydelta |= (data[i] & 0x70) << (3*i - 3); 359184299Snwhitehorn 360184299Snwhitehorn buttons |= !(data[i] & 0x08) << (2*i - 2); 361184299Snwhitehorn buttons |= !(data[i] & 0x80) << (2*i - 1); 362184299Snwhitehorn } 363184299Snwhitehorn } else { 364184299Snwhitehorn len = 2; /* Ignore extra data */ 365184299Snwhitehorn } 366184299Snwhitehorn 367184299Snwhitehorn /* Do sign extension as necessary */ 368184299Snwhitehorn if (xdelta & (0x40 << 3*(len-2))) 369184299Snwhitehorn xdelta |= 0xffffffc0 << 3*(len - 2); 370184299Snwhitehorn if (ydelta & (0x40 << 3*(len-2))) 371184299Snwhitehorn ydelta |= 0xffffffc0 << 3*(len - 2); 372184299Snwhitehorn 373199888Snwhitehorn if ((sc->flags & AMS_TOUCHPAD) && (sc->sc_tapping == 1)) { 374199888Snwhitehorn tmp_buttons = buttons; 375199888Snwhitehorn if (buttons == 0x12) { 376199888Snwhitehorn /* Map a double tap on button 3. 377199888Snwhitehorn Keep the button state for the next sequence. 378199888Snwhitehorn A double tap sequence is followed by a single tap 379199888Snwhitehorn sequence. 380199888Snwhitehorn */ 381199888Snwhitehorn tmp_buttons = 0x3; 382199888Snwhitehorn sc->button_buf = tmp_buttons; 383199888Snwhitehorn } else if (buttons == 0x2) { 384199888Snwhitehorn /* Map a single tap on button 2. But only if it is 385199888Snwhitehorn not a successor from a double tap. 386199888Snwhitehorn */ 387199888Snwhitehorn if (sc->button_buf != 0x3) 388199888Snwhitehorn tmp_buttons = 0x2; 389199888Snwhitehorn else 390199888Snwhitehorn tmp_buttons = 0; 391199888Snwhitehorn 392199888Snwhitehorn sc->button_buf = 0; 393199888Snwhitehorn } 394199888Snwhitehorn buttons = tmp_buttons; 395199888Snwhitehorn } 396199888Snwhitehorn 397184299Snwhitehorn /* 398184299Snwhitehorn * Some mice report high-numbered buttons on the wrong button number, 399184299Snwhitehorn * so set the highest-numbered real button as pressed if there are 400184299Snwhitehorn * mysterious high-numbered ones set. 401184565Sed * 402184565Sed * Don't do this for touchpads, because touchpads also trigger 403184565Sed * high button events when they are touched. 404184299Snwhitehorn */ 405184299Snwhitehorn 406298433Spfg if (rounddown2(buttons, 1 << sc->hw.buttons) 407184565Sed && !(sc->flags & AMS_TOUCHPAD)) { 408184299Snwhitehorn buttons |= 1 << (sc->hw.buttons - 1); 409184299Snwhitehorn } 410184565Sed buttons &= (1 << sc->hw.buttons) - 1; 411184299Snwhitehorn 412184299Snwhitehorn mtx_lock(&sc->sc_mtx); 413184299Snwhitehorn 414184299Snwhitehorn /* Add in our new deltas, and take into account 415184299Snwhitehorn Apple's opposite meaning for Y axis motion */ 416184299Snwhitehorn 417184299Snwhitehorn sc->xdelta += xdelta; 418184299Snwhitehorn sc->ydelta -= ydelta; 419184299Snwhitehorn 420184299Snwhitehorn sc->buttons = buttons; 421184299Snwhitehorn 422184299Snwhitehorn mtx_unlock(&sc->sc_mtx); 423184299Snwhitehorn 424184299Snwhitehorn cv_broadcast(&sc->sc_cv); 425184299Snwhitehorn selwakeuppri(&sc->rsel, PZERO); 426184299Snwhitehorn 427184299Snwhitehorn return (0); 428184299Snwhitehorn} 429184299Snwhitehorn 430184299Snwhitehornstatic int 431184299Snwhitehornams_open(struct cdev *dev, int flag, int fmt, struct thread *p) 432184299Snwhitehorn{ 433184299Snwhitehorn struct adb_mouse_softc *sc; 434184299Snwhitehorn 435184299Snwhitehorn sc = CDEV_GET_SOFTC(dev); 436184299Snwhitehorn if (sc == NULL) 437184299Snwhitehorn return (ENXIO); 438184299Snwhitehorn 439184299Snwhitehorn mtx_lock(&sc->sc_mtx); 440184299Snwhitehorn sc->packet_read_len = 0; 441184299Snwhitehorn sc->xdelta = 0; 442184299Snwhitehorn sc->ydelta = 0; 443184299Snwhitehorn sc->buttons = 0; 444184299Snwhitehorn mtx_unlock(&sc->sc_mtx); 445184299Snwhitehorn 446184299Snwhitehorn return (0); 447184299Snwhitehorn} 448184299Snwhitehorn 449184299Snwhitehornstatic int 450184299Snwhitehornams_close(struct cdev *dev, int flag, int fmt, struct thread *p) 451184299Snwhitehorn{ 452184299Snwhitehorn struct adb_mouse_softc *sc; 453184299Snwhitehorn 454184299Snwhitehorn sc = CDEV_GET_SOFTC(dev); 455184299Snwhitehorn 456184299Snwhitehorn cv_broadcast(&sc->sc_cv); 457184299Snwhitehorn selwakeuppri(&sc->rsel, PZERO); 458184299Snwhitehorn return (0); 459184299Snwhitehorn} 460184299Snwhitehorn 461184299Snwhitehornstatic int 462184299Snwhitehornams_poll(struct cdev *dev, int events, struct thread *p) 463184299Snwhitehorn{ 464184299Snwhitehorn struct adb_mouse_softc *sc; 465184299Snwhitehorn 466184299Snwhitehorn sc = CDEV_GET_SOFTC(dev); 467184299Snwhitehorn if (sc == NULL) 468184299Snwhitehorn return (EIO); 469184299Snwhitehorn 470184299Snwhitehorn if (events & (POLLIN | POLLRDNORM)) { 471184299Snwhitehorn mtx_lock(&sc->sc_mtx); 472184299Snwhitehorn 473184299Snwhitehorn if (sc->xdelta == 0 && sc->ydelta == 0 && 474255921Sjhibbits sc->buttons == sc->last_buttons && 475255921Sjhibbits sc->packet_read_len == 0) { 476184299Snwhitehorn selrecord(p, &sc->rsel); 477184299Snwhitehorn events = 0; 478184299Snwhitehorn } else { 479184299Snwhitehorn events &= (POLLIN | POLLRDNORM); 480184299Snwhitehorn } 481184299Snwhitehorn 482184299Snwhitehorn mtx_unlock(&sc->sc_mtx); 483184299Snwhitehorn } 484184299Snwhitehorn 485184299Snwhitehorn return events; 486184299Snwhitehorn} 487184299Snwhitehorn 488184299Snwhitehornstatic int 489184299Snwhitehornams_read(struct cdev *dev, struct uio *uio, int flag) 490184299Snwhitehorn{ 491184299Snwhitehorn struct adb_mouse_softc *sc; 492184299Snwhitehorn size_t len; 493184299Snwhitehorn int8_t outpacket[8]; 494184520Sed int error; 495184299Snwhitehorn 496184299Snwhitehorn sc = CDEV_GET_SOFTC(dev); 497184299Snwhitehorn if (sc == NULL) 498184299Snwhitehorn return (EIO); 499184299Snwhitehorn 500184299Snwhitehorn if (uio->uio_resid <= 0) 501184299Snwhitehorn return (0); 502184299Snwhitehorn 503184299Snwhitehorn mtx_lock(&sc->sc_mtx); 504184299Snwhitehorn 505184299Snwhitehorn if (!sc->packet_read_len) { 506184299Snwhitehorn if (sc->xdelta == 0 && sc->ydelta == 0 && 507184299Snwhitehorn sc->buttons == sc->last_buttons) { 508184299Snwhitehorn 509184299Snwhitehorn if (flag & O_NONBLOCK) { 510184299Snwhitehorn mtx_unlock(&sc->sc_mtx); 511184299Snwhitehorn return EWOULDBLOCK; 512184299Snwhitehorn } 513184299Snwhitehorn 514184299Snwhitehorn 515184299Snwhitehorn /* Otherwise, block on new data */ 516184520Sed error = cv_wait_sig(&sc->sc_cv, &sc->sc_mtx); 517184520Sed if (error) { 518184520Sed mtx_unlock(&sc->sc_mtx); 519184520Sed return (error); 520184520Sed } 521184299Snwhitehorn } 522184299Snwhitehorn 523316369Sjhibbits sc->packet[0] = 1U << 7; 524184299Snwhitehorn sc->packet[0] |= (!(sc->buttons & 1)) << 2; 525184299Snwhitehorn sc->packet[0] |= (!(sc->buttons & 4)) << 1; 526184299Snwhitehorn sc->packet[0] |= (!(sc->buttons & 2)); 527184299Snwhitehorn 528184299Snwhitehorn if (sc->xdelta > 127) { 529184299Snwhitehorn sc->packet[1] = 127; 530184299Snwhitehorn sc->packet[3] = sc->xdelta - 127; 531184299Snwhitehorn } else if (sc->xdelta < -127) { 532184299Snwhitehorn sc->packet[1] = -127; 533184299Snwhitehorn sc->packet[3] = sc->xdelta + 127; 534184299Snwhitehorn } else { 535184299Snwhitehorn sc->packet[1] = sc->xdelta; 536184299Snwhitehorn sc->packet[3] = 0; 537184299Snwhitehorn } 538184299Snwhitehorn 539184299Snwhitehorn if (sc->ydelta > 127) { 540184299Snwhitehorn sc->packet[2] = 127; 541184299Snwhitehorn sc->packet[4] = sc->ydelta - 127; 542184299Snwhitehorn } else if (sc->ydelta < -127) { 543184299Snwhitehorn sc->packet[2] = -127; 544184299Snwhitehorn sc->packet[4] = sc->ydelta + 127; 545184299Snwhitehorn } else { 546184299Snwhitehorn sc->packet[2] = sc->ydelta; 547184299Snwhitehorn sc->packet[4] = 0; 548184299Snwhitehorn } 549184299Snwhitehorn 550184299Snwhitehorn /* No Z movement */ 551184299Snwhitehorn sc->packet[5] = 0; 552184299Snwhitehorn sc->packet[6] = 0; 553184299Snwhitehorn 554184299Snwhitehorn sc->packet[7] = ~((uint8_t)(sc->buttons >> 3)) & 0x7f; 555184299Snwhitehorn 556184299Snwhitehorn 557184299Snwhitehorn sc->last_buttons = sc->buttons; 558184299Snwhitehorn sc->xdelta = 0; 559184299Snwhitehorn sc->ydelta = 0; 560184299Snwhitehorn 561184299Snwhitehorn sc->packet_read_len = sc->mode.packetsize; 562184299Snwhitehorn } 563184299Snwhitehorn 564184299Snwhitehorn len = (sc->packet_read_len > uio->uio_resid) ? 565184299Snwhitehorn uio->uio_resid : sc->packet_read_len; 566184299Snwhitehorn 567184299Snwhitehorn memcpy(outpacket,sc->packet + 568184299Snwhitehorn (sc->mode.packetsize - sc->packet_read_len),len); 569184299Snwhitehorn sc->packet_read_len -= len; 570184299Snwhitehorn 571184299Snwhitehorn mtx_unlock(&sc->sc_mtx); 572184299Snwhitehorn 573242948Skevlo error = uiomove(outpacket,len,uio); 574184299Snwhitehorn 575242948Skevlo return (error); 576184299Snwhitehorn} 577184299Snwhitehorn 578184299Snwhitehorn 579184299Snwhitehornstatic int 580184299Snwhitehornams_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, 581184299Snwhitehorn struct thread *p) 582184299Snwhitehorn{ 583184299Snwhitehorn struct adb_mouse_softc *sc; 584184299Snwhitehorn mousemode_t mode; 585184299Snwhitehorn 586184299Snwhitehorn sc = CDEV_GET_SOFTC(dev); 587184299Snwhitehorn if (sc == NULL) 588184299Snwhitehorn return (EIO); 589184299Snwhitehorn 590184299Snwhitehorn switch (cmd) { 591184299Snwhitehorn case MOUSE_GETHWINFO: 592184299Snwhitehorn *(mousehw_t *)addr = sc->hw; 593184299Snwhitehorn break; 594184299Snwhitehorn case MOUSE_GETMODE: 595184299Snwhitehorn *(mousemode_t *)addr = sc->mode; 596184299Snwhitehorn break; 597184299Snwhitehorn case MOUSE_SETMODE: 598184299Snwhitehorn mode = *(mousemode_t *)addr; 599184299Snwhitehorn addr = (caddr_t)&mode.level; 600184299Snwhitehorn 601184299Snwhitehorn /* Fallthrough */ 602184299Snwhitehorn 603184299Snwhitehorn case MOUSE_SETLEVEL: 604184299Snwhitehorn if (*(int *)addr == -1) 605184299Snwhitehorn break; 606184299Snwhitehorn else if (*(int *)addr == 1) { 607184299Snwhitehorn sc->mode.level = 1; 608184299Snwhitehorn sc->mode.packetsize = 8; 609184299Snwhitehorn break; 610184299Snwhitehorn } else if (*(int *)addr == 0) { 611184299Snwhitehorn sc->mode.level = 0; 612184299Snwhitehorn sc->mode.packetsize = 5; 613184299Snwhitehorn break; 614184299Snwhitehorn } 615184299Snwhitehorn 616184299Snwhitehorn return EINVAL; 617184299Snwhitehorn case MOUSE_GETLEVEL: 618184299Snwhitehorn *(int *)addr = sc->mode.level; 619184299Snwhitehorn break; 620184299Snwhitehorn 621184299Snwhitehorn case MOUSE_GETSTATUS: { 622184299Snwhitehorn mousestatus_t *status = (mousestatus_t *) addr; 623184299Snwhitehorn 624184299Snwhitehorn mtx_lock(&sc->sc_mtx); 625184299Snwhitehorn 626184299Snwhitehorn status->button = sc->buttons; 627184299Snwhitehorn status->obutton = sc->last_buttons; 628184299Snwhitehorn 629184299Snwhitehorn status->flags = status->button ^ status->obutton; 630184299Snwhitehorn 631184299Snwhitehorn if (sc->xdelta != 0 || sc->ydelta) 632184299Snwhitehorn status->flags |= MOUSE_POSCHANGED; 633184299Snwhitehorn if (status->button != status->obutton) 634184299Snwhitehorn status->flags |= MOUSE_BUTTONSCHANGED; 635184299Snwhitehorn 636184299Snwhitehorn status->dx = sc->xdelta; 637184299Snwhitehorn status->dy = sc->ydelta; 638184299Snwhitehorn status->dz = 0; 639184299Snwhitehorn 640184299Snwhitehorn sc->xdelta = 0; 641184299Snwhitehorn sc->ydelta = 0; 642184299Snwhitehorn sc->last_buttons = sc->buttons; 643184299Snwhitehorn 644184299Snwhitehorn mtx_unlock(&sc->sc_mtx); 645184299Snwhitehorn 646184299Snwhitehorn break; } 647184299Snwhitehorn default: 648184299Snwhitehorn return ENOTTY; 649184299Snwhitehorn } 650184299Snwhitehorn 651184299Snwhitehorn return (0); 652184299Snwhitehorn} 653184299Snwhitehorn 654199888Snwhitehornstatic int 655199888Snwhitehornadb_tapping_sysctl(SYSCTL_HANDLER_ARGS) 656199888Snwhitehorn{ 657199888Snwhitehorn struct adb_mouse_softc *sc = arg1; 658199888Snwhitehorn device_t dev; 659199888Snwhitehorn int error; 660199888Snwhitehorn u_char r2[8]; 661199888Snwhitehorn u_int tapping; 662199888Snwhitehorn 663199888Snwhitehorn dev = sc->sc_dev; 664199888Snwhitehorn tapping = sc->sc_tapping; 665199888Snwhitehorn 666199888Snwhitehorn error = sysctl_handle_int(oidp, &tapping, 0, req); 667199888Snwhitehorn 668199888Snwhitehorn if (error || !req->newptr) 669199888Snwhitehorn return (error); 670199888Snwhitehorn 671199888Snwhitehorn if (tapping == 1) { 672199888Snwhitehorn adb_read_register(dev, 2, r2); 673199888Snwhitehorn r2[0] = 0x99; /* enable tapping. */ 674199888Snwhitehorn adb_write_register(dev, 2, 8, r2); 675199888Snwhitehorn sc->sc_tapping = 1; 676199888Snwhitehorn } else if (tapping == 0) { 677199888Snwhitehorn adb_read_register(dev, 2, r2); 678199888Snwhitehorn r2[0] = 0x19; /* disable tapping. */ 679199888Snwhitehorn adb_write_register(dev, 2, 8, r2); 680199888Snwhitehorn sc->sc_tapping = 0; 681199888Snwhitehorn } 682199888Snwhitehorn else 683199888Snwhitehorn return (EINVAL); 684199888Snwhitehorn 685199888Snwhitehorn return (0); 686199888Snwhitehorn} 687