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

Cache object: 6dca7cd89497aa604d3722651f387185


[ 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.