|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ********************************************************************** ! 27: File: kd_mouse.c ! 28: Description: mouse driver as part of keyboard/display driver ! 29: ! 30: $ Header: $ ! 31: ! 32: Copyright Ing. C. Olivetti & C. S.p.A. 1989. ! 33: All rights reserved. ! 34: ********************************************************************** */ ! 35: /* ! 36: Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc., ! 37: Cupertino, California. ! 38: ! 39: All Rights Reserved ! 40: ! 41: Permission to use, copy, modify, and distribute this software and ! 42: its documentation for any purpose and without fee is hereby ! 43: granted, provided that the above copyright notice appears in all ! 44: copies and that both the copyright notice and this permission notice ! 45: appear in supporting documentation, and that the name of Olivetti ! 46: not be used in advertising or publicity pertaining to distribution ! 47: of the software without specific, written prior permission. ! 48: ! 49: OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ! 50: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, ! 51: IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR ! 52: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ! 53: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, ! 54: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION ! 55: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ! 56: */ ! 57: ! 58: /* ! 59: * Hacked up support for serial mouse connected to COM1, using Mouse ! 60: * Systems 5-byte protocol at 1200 baud. This should work for ! 61: * Mouse Systems, SummaMouse, and Logitek C7 mice. ! 62: * ! 63: * The interface provided by /dev/mouse is a series of events as ! 64: * described in i386at/kd.h. ! 65: */ ! 66: ! 67: #include <mach/boolean.h> ! 68: #include <sys/types.h> ! 69: #ifdef MACH_KERNEL ! 70: #include <device/errno.h> ! 71: #include <device/io_req.h> ! 72: #else MACH_KERNEL ! 73: #include <sys/file.h> ! 74: #include <sys/errno.h> ! 75: #include <kern/thread.h> ! 76: #include <sys/user.h> ! 77: #include <sys/proc.h> ! 78: #include <sys/kernel.h> ! 79: #include <sys/ioctl.h> ! 80: #include <sys/tty.h> ! 81: #endif MACH_KERNEL ! 82: #include <i386/ipl.h> ! 83: #include <chips/busses.h> ! 84: #include <i386at/kd.h> ! 85: #include <i386at/kd_queue.h> ! 86: #include <i386at/i8250.h> ! 87: ! 88: static int (*oldvect)(); /* old interrupt vector */ ! 89: static int oldunit; ! 90: static spl_t oldspl; ! 91: extern struct bus_device *cominfo[]; ! 92: ! 93: kd_event_queue mouse_queue; /* queue of mouse events */ ! 94: boolean_t mouse_in_use = FALSE; ! 95: #ifdef MACH_KERNEL ! 96: queue_head_t mouse_read_queue = { &mouse_read_queue, &mouse_read_queue }; ! 97: #else MACH_KERNEL ! 98: struct proc *mouse_sel = 0; /* selecting process, if any */ ! 99: short mousepgrp = 0; /* process group leader when dev is open */ ! 100: #endif MACH_KERNEL ! 101: ! 102: #ifdef MACH_KERNEL ! 103: #else MACH_KERNEL ! 104: int mouseflag = 0; ! 105: #define MOUSE_COLL 1 /* select collision */ ! 106: #define MOUSE_ASYNC 2 /* user wants asynch notification */ ! 107: #define MOUSE_NBIO 4 /* user wants non-blocking I/O */ ! 108: #endif MACH_KERNEL ! 109: ! 110: /* ! 111: * The state of the 3 buttons is encoded in the low-order 3 bits (both ! 112: * here and in other variables in the driver). ! 113: */ ! 114: u_char lastbuttons; /* previous state of mouse buttons */ ! 115: #define MOUSE_UP 1 ! 116: #define MOUSE_DOWN 0 ! 117: #define MOUSE_ALL_UP 0x7 ! 118: ! 119: int mouseintr(); ! 120: void mouse_enqueue(); ! 121: int mouse_baud = BCNT1200; ! 122: ! 123: boolean_t mouse_char_cmd = FALSE; /* mouse response is to cmd */ ! 124: boolean_t mouse_char_wanted = FALSE; /* want mouse response */ ! 125: boolean_t mouse_char_in = FALSE; /* have mouse response */ ! 126: unsigned char mouse_char; /* mouse response */ ! 127: ! 128: ! 129: /* ! 130: * init_mouse_hw - initialize the serial port. ! 131: */ ! 132: init_mouse_hw(unit, mode) ! 133: { ! 134: caddr_t base_addr = (caddr_t)cominfo[unit]->address; ! 135: ! 136: outb(base_addr + RIE, 0); ! 137: outb(base_addr + RLC, LCDLAB); ! 138: outb(base_addr + RDLSB, mouse_baud & 0xff); ! 139: outb(base_addr + RDMSB, (mouse_baud >> 8) & 0xff); ! 140: outb(base_addr + RLC, mode); ! 141: outb(base_addr + RMC, MCDTR | MCRTS | MCOUT2); ! 142: outb(base_addr + RIE, IERD | IELS); ! 143: } ! 144: ! 145: ! 146: /* ! 147: * mouseopen - Verify that the request is read-only, initialize, ! 148: * and remember process group leader. ! 149: */ ! 150: /* ! 151: * Low 3 bits of minor are the com port #. ! 152: * The high 5 bits of minor are the mouse type ! 153: */ ! 154: #define MOUSE_SYSTEM_MOUSE 0 ! 155: #define MICROSOFT_MOUSE 1 ! 156: #define IBM_MOUSE 2 ! 157: #define NO_MOUSE 3 ! 158: #define LOGITECH_TRACKMAN 4 ! 159: #define MICROSOFT_MOUSE7 5 ! 160: static int mouse_type; ! 161: static int mousebufsize; ! 162: static int mousebufindex = 0; ! 163: int track_man[10]; ! 164: ! 165: /*ARGSUSED*/ ! 166: mouseopen(dev, flags) ! 167: dev_t dev; ! 168: int flags; ! 169: { ! 170: #ifdef MACH_KERNEL ! 171: #else MACH_KERNEL ! 172: if (flags & FWRITE) ! 173: return(ENODEV); ! 174: #endif MACH_KERNEL ! 175: if (mouse_in_use) ! 176: return(EBUSY); ! 177: mouse_in_use = TRUE; /* locking? */ ! 178: kdq_reset(&mouse_queue); ! 179: lastbuttons = MOUSE_ALL_UP; ! 180: #ifdef MACH_KERNEL ! 181: #else MACH_KERNEL ! 182: mousepgrp = u.u_procp->p_pgrp; ! 183: #endif MACH_KERNEL ! 184: ! 185: switch (mouse_type = ((minor(dev) & 0xf8) >> 3)) { ! 186: case MICROSOFT_MOUSE7: ! 187: mousebufsize = 3; ! 188: serial_mouse_open(dev); ! 189: init_mouse_hw(dev&7, LC7); ! 190: case MICROSOFT_MOUSE: ! 191: mousebufsize = 3; ! 192: serial_mouse_open(dev); ! 193: init_mouse_hw(dev&7, LC8); ! 194: break; ! 195: case MOUSE_SYSTEM_MOUSE: ! 196: mousebufsize = 5; ! 197: serial_mouse_open(dev); ! 198: init_mouse_hw(dev&7, LC8); ! 199: break; ! 200: case LOGITECH_TRACKMAN: ! 201: mousebufsize = 3; ! 202: serial_mouse_open(dev); ! 203: init_mouse_hw(dev&7, LC7); ! 204: track_man[0] = comgetc(dev&7); ! 205: track_man[1] = comgetc(dev&7); ! 206: if (track_man[0] != 0x4d && ! 207: track_man[1] != 0x33) { ! 208: printf("LOGITECH_TRACKMAN: NOT M3"); ! 209: } ! 210: break; ! 211: case IBM_MOUSE: ! 212: mousebufsize = 3; ! 213: kd_mouse_open(dev, 12); ! 214: ibm_ps2_mouse_open(dev); ! 215: break; ! 216: case NO_MOUSE: ! 217: break; ! 218: } ! 219: mousebufindex = 0; ! 220: return(0); ! 221: } ! 222: ! 223: serial_mouse_open(dev) ! 224: { ! 225: int unit = minor(dev) & 0x7; ! 226: int mouse_pic = cominfo[unit]->sysdep1; ! 227: ! 228: spl_t s = splhi(); /* disable interrupts */ ! 229: ! 230: oldvect = ivect[mouse_pic]; ! 231: ivect[mouse_pic] = mouseintr; ! 232: ! 233: oldunit = iunit[mouse_pic]; ! 234: iunit[mouse_pic] = unit; ! 235: ! 236: /* XXX other arrays to init? */ ! 237: splx(s); /* XXX - should come after init? */ ! 238: } ! 239: ! 240: int mouse_packets = 0; ! 241: kd_mouse_open(dev, mouse_pic) ! 242: { ! 243: spl_t s = splhi(); /* disable interrupts */ ! 244: extern int kdintr(); ! 245: ! 246: oldvect = ivect[mouse_pic]; ! 247: ivect[mouse_pic] = kdintr; ! 248: oldspl = intpri[mouse_pic]; ! 249: intpri[mouse_pic] = SPL6; ! 250: form_pic_mask(); ! 251: splx(s); ! 252: } ! 253: ! 254: /* ! 255: * mouseclose - Disable interrupts on the serial port, reset driver flags, ! 256: * and restore the serial port interrupt vector. ! 257: */ ! 258: mouseclose(dev, flags) ! 259: { ! 260: switch (mouse_type) { ! 261: case MICROSOFT_MOUSE: ! 262: case MICROSOFT_MOUSE7: ! 263: case MOUSE_SYSTEM_MOUSE: ! 264: case LOGITECH_TRACKMAN: ! 265: serial_mouse_close(dev); ! 266: break; ! 267: case IBM_MOUSE: ! 268: ibm_ps2_mouse_close(dev); ! 269: kd_mouse_close(dev, 12); ! 270: {int i = 20000; for (;i--;); } ! 271: kd_mouse_drain(); ! 272: break; ! 273: case NO_MOUSE: ! 274: break; ! 275: } ! 276: ! 277: kdq_reset(&mouse_queue); /* paranoia */ ! 278: mouse_in_use = FALSE; ! 279: #ifdef MACH_KERNEL ! 280: #else MACH_KERNEL ! 281: mousepgrp = 0; ! 282: mouseflag = 0; ! 283: mouse_sel = 0; ! 284: #endif MACH_KERNEL ! 285: } ! 286: ! 287: /*ARGSUSED*/ ! 288: serial_mouse_close(dev, flags) ! 289: dev_t dev; ! 290: int flags; ! 291: { ! 292: spl_t o_pri = splhi(); /* mutex with open() */ ! 293: int unit = minor(dev) & 0x7; ! 294: int mouse_pic = cominfo[unit]->sysdep1; ! 295: caddr_t base_addr = (caddr_t)cominfo[unit]->address; ! 296: ! 297: assert(ivect[mouse_pic] == mouseintr); ! 298: outb(base_addr + RIE, 0); /* disable serial port */ ! 299: outb(base_addr + RMC, 0); /* no rts */ ! 300: ivect[mouse_pic] = oldvect; ! 301: iunit[mouse_pic] = oldunit; ! 302: ! 303: (void)splx(o_pri); ! 304: } ! 305: ! 306: kd_mouse_close(dev, mouse_pic) ! 307: { ! 308: spl_t s = splhi(); ! 309: ! 310: ivect[mouse_pic] = oldvect; ! 311: intpri[mouse_pic] = oldspl; ! 312: form_pic_mask(); ! 313: splx(s); ! 314: } ! 315: ! 316: #ifdef MACH_KERNEL ! 317: #else MACH_KERNEL ! 318: /* ! 319: * mouseioctl - handling for asynch & non-blocking I/O. ! 320: */ ! 321: ! 322: /*ARGSUSED*/ ! 323: mouseioctl(dev, cmd, data, flag) ! 324: dev_t dev; ! 325: int cmd; ! 326: caddr_t data; ! 327: int flag; ! 328: { ! 329: int s = SPLKD(); ! 330: int err = 0; ! 331: ! 332: switch (cmd) { ! 333: case FIONBIO: ! 334: if (*(int *)data) ! 335: mouseflag |= MOUSE_NBIO; ! 336: else ! 337: mouseflag &= ~MOUSE_NBIO; ! 338: break; ! 339: case FIOASYNC: ! 340: if (*(int *)data) ! 341: mouseflag |= MOUSE_ASYNC; ! 342: else ! 343: mouseflag &= ~MOUSE_ASYNC; ! 344: break; ! 345: default: ! 346: err = ENOTTY; ! 347: break; ! 348: } ! 349: ! 350: splx(s); ! 351: return(err); ! 352: } ! 353: ! 354: ! 355: /* ! 356: * mouseselect - check for pending events, etc. ! 357: */ ! 358: ! 359: /*ARGSUSED*/ ! 360: mouseselect(dev, rw) ! 361: { ! 362: int s = SPLKD(); ! 363: ! 364: if (!kdq_empty(&mouse_queue)) { ! 365: splx(s); ! 366: return(1); ! 367: } ! 368: ! 369: if (mouse_sel) ! 370: mouseflag |= MOUSE_COLL; ! 371: else ! 372: mouse_sel = (struct proc *)current_thread(); ! 373: /* eeeyuck */ ! 374: ! 375: splx(s); ! 376: return(0); ! 377: } ! 378: #endif MACH_KERNEL ! 379: ! 380: /* ! 381: * mouseread - dequeue and return any queued events. ! 382: */ ! 383: #ifdef MACH_KERNEL ! 384: boolean_t mouse_read_done(); /* forward */ ! 385: ! 386: mouseread(dev, ior) ! 387: dev_t dev; ! 388: register io_req_t ior; ! 389: { ! 390: register int err, count; ! 391: register spl_t s; ! 392: ! 393: err = device_read_alloc(ior, (vm_size_t)ior->io_count); ! 394: if (err != KERN_SUCCESS) ! 395: return (err); ! 396: ! 397: s = SPLKD(); ! 398: if (kdq_empty(&mouse_queue)) { ! 399: if (ior->io_mode & D_NOWAIT) { ! 400: splx(s); ! 401: return (D_WOULD_BLOCK); ! 402: } ! 403: ior->io_done = mouse_read_done; ! 404: enqueue_tail(&mouse_read_queue, (queue_entry_t)ior); ! 405: splx(s); ! 406: return (D_IO_QUEUED); ! 407: } ! 408: count = 0; ! 409: while (!kdq_empty(&mouse_queue) && count < ior->io_count) { ! 410: register kd_event *ev; ! 411: ! 412: ev = kdq_get(&mouse_queue); ! 413: *(kd_event *)(&ior->io_data[count]) = *ev; ! 414: count += sizeof(kd_event); ! 415: } ! 416: splx(s); ! 417: ior->io_residual = ior->io_count - count; ! 418: return (D_SUCCESS); ! 419: } ! 420: ! 421: boolean_t mouse_read_done(ior) ! 422: register io_req_t ior; ! 423: { ! 424: register int count; ! 425: register spl_t s; ! 426: ! 427: s = SPLKD(); ! 428: if (kdq_empty(&mouse_queue)) { ! 429: ior->io_done = mouse_read_done; ! 430: enqueue_tail(&mouse_read_queue, (queue_entry_t)ior); ! 431: splx(s); ! 432: return (FALSE); ! 433: } ! 434: ! 435: count = 0; ! 436: while (!kdq_empty(&mouse_queue) && count < ior->io_count) { ! 437: register kd_event *ev; ! 438: ! 439: ev = kdq_get(&mouse_queue); ! 440: *(kd_event *)(&ior->io_data[count]) = *ev; ! 441: count += sizeof(kd_event); ! 442: } ! 443: splx(s); ! 444: ! 445: ior->io_residual = ior->io_count - count; ! 446: ds_read_done(ior); ! 447: ! 448: return (TRUE); ! 449: } ! 450: ! 451: #else MACH_KERNEL ! 452: /*ARGSUSED*/ ! 453: mouseread(dev, uio) ! 454: dev_t dev; ! 455: struct uio *uio; ! 456: { ! 457: int s = SPLKD(); ! 458: int err = 0; ! 459: kd_event *ev; ! 460: int i; ! 461: char *cp; ! 462: ! 463: if (kdq_empty(&mouse_queue)) ! 464: if (mouseflag & MOUSE_NBIO) { ! 465: err = EWOULDBLOCK; ! 466: goto done; ! 467: } else ! 468: while (kdq_empty(&mouse_queue)) { ! 469: splx(s); ! 470: sleep((caddr_t)&mouse_queue, TTIPRI); ! 471: s = SPLKD(); ! 472: } ! 473: ! 474: while (!kdq_empty(&mouse_queue) && uio->uio_resid >= sizeof(kd_event)) { ! 475: ev = kdq_get(&mouse_queue); ! 476: for (cp = (char *)ev, i = 0; i < sizeof(kd_event); ! 477: ++i, ++cp) { ! 478: err = ureadc(*cp, uio); ! 479: if (err) ! 480: goto done; ! 481: } ! 482: } ! 483: ! 484: done: ! 485: splx(s); ! 486: return(err); ! 487: } ! 488: #endif MACH_KERNEL ! 489: ! 490: ! 491: /* ! 492: * mouseintr - Get a byte and pass it up for handling. Called at SPLKD. ! 493: */ ! 494: mouseintr(unit) ! 495: { ! 496: caddr_t base_addr = (caddr_t)cominfo[unit]->address; ! 497: unsigned char id, ls; ! 498: ! 499: /* get reason for interrupt and line status */ ! 500: id = inb(base_addr + RID); ! 501: ls = inb(base_addr + RLS); ! 502: ! 503: /* handle status changes */ ! 504: if (id == IDLS) { ! 505: if (ls & LSDR) { ! 506: inb(base_addr + RDAT); /* flush bad character */ ! 507: } ! 508: return; /* ignore status change */ ! 509: } ! 510: ! 511: if (id & IDRD) { ! 512: mouse_handle_byte((u_char)(inb(base_addr + RDAT) & 0xff)); ! 513: } ! 514: } ! 515: ! 516: ! 517: /* ! 518: * handle_byte - Accumulate bytes until we have an entire packet. ! 519: * If the mouse has moved or any of the buttons have changed state (up ! 520: * or down), enqueue the corresponding events. ! 521: * Called at SPLKD. ! 522: * XXX - magic numbers. ! 523: */ ! 524: int show_mouse_byte = 0; ! 525: /* ! 526: X down; middle down; middle up; X up 50 0 0; 50 0 0 22; 50 0 0 02; 40 0 0 ! 527: X down; middle down; X up; middle up 50 0 0; 50 0 0 22; 40 0 0 22; 40 0 0 2 ! 528: * ! 529: * The trick here is that all the while the middle button is down you get 4 byte ! 530: * packets with the last byte 0x22. When the middle button goes up you get a ! 531: * last packet with 0x02. ! 532: */ ! 533: int lastgitech = 0x40; /* figure whether the first 3 bytes imply */ ! 534: /* its time to expect a fourth */ ! 535: int fourthgitech = 0; /* look for the 4th byte; we must process it */ ! 536: int middlegitech = 0; /* what should the middle button be */ ! 537: ! 538: #define MOUSEBUFSIZE 5 /* num bytes def'd by protocol */ ! 539: static u_char mousebuf[MOUSEBUFSIZE]; /* 5-byte packet from mouse */ ! 540: ! 541: mouse_handle_byte(ch) ! 542: u_char ch; ! 543: { ! 544: if (show_mouse_byte) { ! 545: printf("%x(%c) ", ch, ch); ! 546: } ! 547: ! 548: if (mouse_char_cmd) { ! 549: /* ! 550: * Mouse character is response to command ! 551: */ ! 552: mouse_char = ch; ! 553: mouse_char_in = TRUE; ! 554: if (mouse_char_wanted) { ! 555: mouse_char_wanted = FALSE; ! 556: wakeup(&mouse_char); ! 557: } ! 558: return; ! 559: } ! 560: ! 561: if (mousebufindex == 0) { ! 562: switch (mouse_type) { ! 563: case MICROSOFT_MOUSE7: ! 564: if ((ch & 0x40) != 0x40) ! 565: return; ! 566: break; ! 567: case MICROSOFT_MOUSE: ! 568: if ((ch & 0xc0) != 0xc0) ! 569: return; ! 570: break; ! 571: case MOUSE_SYSTEM_MOUSE: ! 572: if ((ch & 0xf8) != 0x80) ! 573: return; ! 574: break; ! 575: case LOGITECH_TRACKMAN: ! 576: if (fourthgitech == 1) { ! 577: fourthgitech = 0; ! 578: if (ch & 0xf0) ! 579: middlegitech = 0x4; ! 580: else ! 581: middlegitech = 0x0; ! 582: mouse_packet_microsoft_mouse(mousebuf); ! 583: return; ! 584: } else if ((ch & 0xc0) != 0x40) ! 585: return; ! 586: break; ! 587: case IBM_MOUSE: ! 588: break; ! 589: } ! 590: } ! 591: ! 592: mousebuf[mousebufindex++] = ch; ! 593: if (mousebufindex < mousebufsize) ! 594: return; ! 595: ! 596: /* got a packet */ ! 597: mousebufindex = 0; ! 598: ! 599: switch (mouse_type) { ! 600: case MICROSOFT_MOUSE7: ! 601: case MICROSOFT_MOUSE: ! 602: mouse_packet_microsoft_mouse(mousebuf); ! 603: break; ! 604: case MOUSE_SYSTEM_MOUSE: ! 605: mouse_packet_mouse_system_mouse(mousebuf); ! 606: break; ! 607: case LOGITECH_TRACKMAN: ! 608: if ( mousebuf[1] || mousebuf[2] || ! 609: mousebuf[0] != lastgitech) { ! 610: mouse_packet_microsoft_mouse(mousebuf); ! 611: lastgitech = mousebuf[0] & 0xf0; ! 612: } else { ! 613: fourthgitech = 1; ! 614: } ! 615: break; ! 616: case IBM_MOUSE: ! 617: mouse_packet_ibm_ps2_mouse(mousebuf); ! 618: break; ! 619: } ! 620: } ! 621: ! 622: mouse_packet_mouse_system_mouse(mousebuf) ! 623: u_char mousebuf[MOUSEBUFSIZE]; ! 624: { ! 625: u_char buttons, buttonchanges; ! 626: struct mouse_motion moved; ! 627: ! 628: buttons = mousebuf[0] & 0x7; /* get current state of buttons */ ! 629: buttonchanges = buttons ^ lastbuttons; ! 630: moved.mm_deltaX = (char)mousebuf[1] + (char)mousebuf[3]; ! 631: moved.mm_deltaY = (char)mousebuf[2] + (char)mousebuf[4]; ! 632: ! 633: if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0) ! 634: mouse_moved(moved); ! 635: ! 636: if (buttonchanges != 0) { ! 637: lastbuttons = buttons; ! 638: if (buttonchanges & 1) ! 639: mouse_button(MOUSE_RIGHT, buttons & 1); ! 640: if (buttonchanges & 2) ! 641: mouse_button(MOUSE_MIDDLE, (buttons & 2) >> 1); ! 642: if (buttonchanges & 4) ! 643: mouse_button(MOUSE_LEFT, (buttons & 4) >> 2); ! 644: } ! 645: } ! 646: ! 647: /* same as above for microsoft mouse */ ! 648: /* ! 649: * 3 byte microsoft format used ! 650: * ! 651: * 7 6 5 4 3 2 1 0 ! 652: * 1 1 L R Y7 Y6 X7 X6 ! 653: * 1 0 X5 X4 X3 X3 X1 X0 ! 654: * 1 0 Y5 Y4 Y3 Y2 Y1 Y0 ! 655: * ! 656: */ ! 657: mouse_packet_microsoft_mouse(mousebuf) ! 658: u_char mousebuf[MOUSEBUFSIZE]; ! 659: { ! 660: u_char buttons, buttonchanges; ! 661: struct mouse_motion moved; ! 662: ! 663: buttons = ((mousebuf[0] & 0x30) >> 4); ! 664: buttons |= middlegitech; ! 665: /* get current state of buttons */ ! 666: #ifdef gross_hack ! 667: if (buttons == 0x03) /* both buttons down */ ! 668: buttons = 0x04; ! 669: #endif /* gross_hack */ ! 670: buttons = (~buttons) & 0x07; /* convert to not pressed */ ! 671: ! 672: buttonchanges = buttons ^ lastbuttons; ! 673: moved.mm_deltaX = ((mousebuf[0] & 0x03) << 6) | (mousebuf[1] & 0x3F); ! 674: moved.mm_deltaY = ((mousebuf[0] & 0x0c) << 4) | (mousebuf[2] & 0x3F); ! 675: if (moved.mm_deltaX & 0x80) /* negative, in fact */ ! 676: moved.mm_deltaX = moved.mm_deltaX - 0x100; ! 677: if (moved.mm_deltaY & 0x80) /* negative, in fact */ ! 678: moved.mm_deltaY = moved.mm_deltaY - 0x100; ! 679: /* and finally the Y orientation is different for the microsoft mouse */ ! 680: moved.mm_deltaY = -moved.mm_deltaY; ! 681: ! 682: if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0) ! 683: mouse_moved(moved); ! 684: ! 685: if (buttonchanges != 0) { ! 686: lastbuttons = buttons; ! 687: if (buttonchanges & 1) ! 688: mouse_button(MOUSE_RIGHT, (buttons & 1) ? ! 689: MOUSE_UP : MOUSE_DOWN); ! 690: if (buttonchanges & 2) ! 691: mouse_button(MOUSE_LEFT, (buttons & 2) ? ! 692: MOUSE_UP : MOUSE_DOWN); ! 693: if (buttonchanges & 4) ! 694: mouse_button(MOUSE_MIDDLE, (buttons & 4) ? ! 695: MOUSE_UP : MOUSE_DOWN); ! 696: } ! 697: } ! 698: ! 699: /* ! 700: * AUX device (PS2) open/close ! 701: */ ! 702: ! 703: /* ! 704: * Write character to mouse. Called at spltty. ! 705: */ ! 706: void kd_mouse_write( ! 707: unsigned char ch) ! 708: { ! 709: while (inb(K_STATUS) & K_IBUF_FUL) ! 710: continue; /* wait for 'input' port empty */ ! 711: outb(K_CMD, 0xd4); /* send next character to mouse */ ! 712: ! 713: while (inb(K_STATUS) & K_IBUF_FUL) ! 714: continue; /* wait for 'input' port empty */ ! 715: outb(K_RDWR, ch); /* send command to mouse */ ! 716: } ! 717: ! 718: /* ! 719: * Read next character from mouse, waiting for interrupt ! 720: * to deliver it. Called at spltty. ! 721: */ ! 722: int kd_mouse_read(void) ! 723: { ! 724: int ch; ! 725: ! 726: while (!mouse_char_in) { ! 727: mouse_char_wanted = TRUE; ! 728: #ifdef MACH_KERNEL ! 729: assert_wait((event_t) &mouse_char, FALSE); ! 730: thread_block((void (*)()) 0); ! 731: #else MACH_KERNEL ! 732: sleep(&mouse_char, PZERO); ! 733: #endif MACH_KERNEL ! 734: } ! 735: ! 736: ch = mouse_char; ! 737: mouse_char_in = FALSE; ! 738: ! 739: return ch; ! 740: } ! 741: ! 742: ibm_ps2_mouse_open(dev) ! 743: { ! 744: spl_t s = spltty(); ! 745: ! 746: lastbuttons = 0; ! 747: mouse_char_cmd = TRUE; /* responses are to commands */ ! 748: ! 749: kd_sendcmd(0xa8); /* enable mouse in kbd */ ! 750: ! 751: kd_cmdreg_write(0x47); /* allow mouse interrupts */ ! 752: /* magic number for ibm? */ ! 753: ! 754: kd_mouse_write(0xff); /* reset mouse */ ! 755: if (kd_mouse_read() != 0xfa) { ! 756: splx(s); ! 757: return; /* need ACK */ ! 758: } ! 759: ! 760: (void) kd_mouse_read(); /* discard 2-character mouse ID */ ! 761: (void) kd_mouse_read(); ! 762: ! 763: kd_mouse_write(0xea); /* set stream mode */ ! 764: if (kd_mouse_read() != 0xfa) { ! 765: splx(s); ! 766: return; /* need ACK */ ! 767: } ! 768: ! 769: kd_mouse_write(0xf4); /* enable */ ! 770: if (kd_mouse_read() != 0xfa) { ! 771: splx(s); ! 772: return; /* need ACK */ ! 773: } ! 774: ! 775: mouse_char_cmd = FALSE; /* now we get mouse packets */ ! 776: ! 777: splx(s); ! 778: } ! 779: ! 780: ibm_ps2_mouse_close(dev) ! 781: { ! 782: spl_t s = spltty(); ! 783: ! 784: mouse_char_cmd = TRUE; /* responses are to commands */ ! 785: ! 786: kd_mouse_write(0xff); /* reset mouse */ ! 787: if (kd_mouse_read() == 0xfa) { ! 788: /* got ACK: discard 2-char mouse ID */ ! 789: (void) kd_mouse_read(); ! 790: (void) kd_mouse_read(); ! 791: } ! 792: ! 793: kd_sendcmd(0xa7); /* disable mouse in kbd */ ! 794: kd_cmdreg_write(0x65); /* disallow mouse interrupts */ ! 795: /* magic number for ibm? */ ! 796: ! 797: splx(s); ! 798: } ! 799: ! 800: /* ! 801: * 3 byte ibm ps2 format used ! 802: * ! 803: * 7 6 5 4 3 2 1 0 ! 804: * YO XO YS XS 1 M R L ! 805: * X7 X6 X5 X4 X3 X3 X1 X0 ! 806: * Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 ! 807: * ! 808: */ ! 809: mouse_packet_ibm_ps2_mouse(mousebuf) ! 810: u_char mousebuf[MOUSEBUFSIZE]; ! 811: { ! 812: u_char buttons, buttonchanges; ! 813: struct mouse_motion moved; ! 814: ! 815: buttons = mousebuf[0] & 0x7; /* get current state of buttons */ ! 816: buttonchanges = buttons ^ lastbuttons; ! 817: moved.mm_deltaX = ((mousebuf[0]&0x10) ? 0xffffff00 : 0 ) | (u_char)mousebuf[1]; ! 818: moved.mm_deltaY = ((mousebuf[0]&0x20) ? 0xffffff00 : 0 ) | (u_char)mousebuf[2]; ! 819: if (mouse_packets) { ! 820: printf("(%x:%x:%x)", mousebuf[0], mousebuf[1], mousebuf[2]); ! 821: return; ! 822: } ! 823: ! 824: if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0) ! 825: mouse_moved(moved); ! 826: ! 827: if (buttonchanges != 0) { ! 828: lastbuttons = buttons; ! 829: if (buttonchanges & 1) ! 830: mouse_button(MOUSE_LEFT, !(buttons & 1)); ! 831: if (buttonchanges & 2) ! 832: mouse_button(MOUSE_RIGHT, !((buttons & 2) >> 1)); ! 833: if (buttonchanges & 4) ! 834: mouse_button(MOUSE_MIDDLE, !((buttons & 4) >> 2)); ! 835: } ! 836: } ! 837: ! 838: /* ! 839: * Enqueue a mouse-motion event. Called at SPLKD. ! 840: */ ! 841: mouse_moved(where) ! 842: struct mouse_motion where; ! 843: { ! 844: kd_event ev; ! 845: ! 846: ev.type = MOUSE_MOTION; ! 847: ev.time = time; ! 848: ev.value.mmotion = where; ! 849: mouse_enqueue(&ev); ! 850: } ! 851: ! 852: ! 853: /* ! 854: * Enqueue an event for mouse button press or release. Called at SPLKD. ! 855: */ ! 856: mouse_button(which, direction) ! 857: kev_type which; ! 858: u_char direction; ! 859: { ! 860: kd_event ev; ! 861: ! 862: ev.type = which; ! 863: ev.time = time; ! 864: ev.value.up = (direction == MOUSE_UP) ? TRUE : FALSE; ! 865: mouse_enqueue(&ev); ! 866: } ! 867: ! 868: ! 869: /* ! 870: * mouse_enqueue - enqueue an event and wake up selecting processes, if ! 871: * any. Called at SPLKD. ! 872: */ ! 873: ! 874: void ! 875: mouse_enqueue(ev) ! 876: kd_event *ev; ! 877: { ! 878: if (kdq_full(&mouse_queue)) ! 879: printf("mouse: queue full\n"); ! 880: else ! 881: kdq_put(&mouse_queue, ev); ! 882: ! 883: #ifdef MACH_KERNEL ! 884: { ! 885: register io_req_t ior; ! 886: while ((ior = (io_req_t)dequeue_head(&mouse_read_queue)) != 0) ! 887: iodone(ior); ! 888: } ! 889: #else MACH_KERNEL ! 890: if (mouse_sel) { ! 891: selwakeup(mouse_sel, mouseflag & MOUSE_COLL); ! 892: mouse_sel = 0; ! 893: mouseflag &= ~MOUSE_COLL; ! 894: } ! 895: if (mouseflag & MOUSE_ASYNC) ! 896: gsignal(mousepgrp, SIGIO); ! 897: wakeup((caddr_t)&mouse_queue); ! 898: #endif MACH_KERNEL ! 899: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.