The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386at/kd_mouse.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 94cb8773d75521b97ad9e59d0ac90541


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.