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/pc/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 #include "u.h"
    2 #include "../port/lib.h"
    3 #include "mem.h"
    4 #include "dat.h"
    5 #include "fns.h"
    6 #include "../port/error.h"
    7 #include "io.h"
    8 
    9 #define Image   IMAGE
   10 #include <draw.h>
   11 #include <memdraw.h>
   12 #include <cursor.h>
   13 #include "screen.h"
   14 
   15 /*
   16  *  mouse types
   17  */
   18 enum
   19 {
   20         Mouseother=     0,
   21         Mouseserial=    1,
   22         MousePS2=       2,
   23 };
   24 
   25 extern int mouseshifted;
   26 
   27 static QLock mousectlqlock;
   28 static int mousetype;
   29 static int intellimouse;
   30 static int packetsize;
   31 static int resolution;
   32 static int accelerated;
   33 static int mousehwaccel;
   34 static char mouseport[5];
   35 
   36 enum
   37 {
   38         CMaccelerated,
   39         CMhwaccel,
   40         CMintellimouse,
   41         CMlinear,
   42         CMps2,
   43         CMps2intellimouse,
   44         CMres,
   45         CMreset,
   46         CMserial,
   47 };
   48 
   49 static Cmdtab mousectlmsg[] =
   50 {
   51         CMaccelerated,          "accelerated",          0,
   52         CMhwaccel,              "hwaccel",              2,
   53         CMintellimouse,         "intellimouse",         1,
   54         CMlinear,               "linear",               1,
   55         CMps2,                  "ps2",                  1,
   56         CMps2intellimouse,      "ps2intellimouse",      1,
   57         CMres,                  "res",                  0,
   58         CMreset,                "reset",                1,
   59         CMserial,               "serial",               0,
   60 };
   61 
   62 /*
   63  *  ps/2 mouse message is three bytes
   64  *
   65  *      byte 0 -        0 0 SDY SDX 1 M R L
   66  *      byte 1 -        DX
   67  *      byte 2 -        DY
   68  *
   69  *  shift & right button is the same as middle button
   70  *
   71  * Intellimouse and AccuPoint with extra buttons deliver
   72  *      byte 3 -        00 or 01 or FF according to extra button state.
   73  * extra buttons are mapped in this code to buttons 4 and 5.
   74  * AccuPoint generates repeated events for these buttons;
   75 *  it and Intellimouse generate 'down' events only, so
   76  * user-level code is required to generate button 'up' events
   77  * if they are needed by the application.
   78  * Also on laptops with AccuPoint AND external mouse, the
   79  * controller may deliver 3 or 4 bytes according to the type
   80  * of the external mouse; code must adapt.
   81  *
   82  * On the NEC Versa series (and perhaps others?) we seem to
   83  * lose a byte from the packet every once in a while, which
   84  * means we lose where we are in the instruction stream.
   85  * To resynchronize, if we get a byte more than two seconds
   86  * after the previous byte, we assume it's the first in a packet.
   87  */
   88 static void
   89 ps2mouseputc(int c, int shift)
   90 {
   91         static short msg[4];
   92         static int nb;
   93         static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 3, 2, 3, 6, 7 };
   94         static ulong lasttick;
   95         ulong m;
   96         int buttons, dx, dy;
   97 
   98         /*
   99          * non-ps2 keyboards might not set shift
  100          * but still set mouseshifted.
  101          */
  102         shift |= mouseshifted;
  103         /*
  104          * Resynchronize in stream with timing; see comment above.
  105          */
  106         m = MACHP(0)->ticks;
  107         if(TK2SEC(m - lasttick) > 2)
  108                 nb = 0;
  109         lasttick = m;
  110 
  111         /* 
  112          *  check byte 0 for consistency
  113          */
  114         if(nb==0 && (c&0xc8)!=0x08)
  115                 if(intellimouse && (c==0x00 || c==0x01 || c==0xFF)){
  116                         /* last byte of 4-byte packet */
  117                         packetsize = 4;
  118                         return;
  119                 }
  120 
  121         msg[nb] = c;
  122         if(++nb == packetsize){
  123                 nb = 0;
  124                 if(msg[0] & 0x10)
  125                         msg[1] |= 0xFF00;
  126                 if(msg[0] & 0x20)
  127                         msg[2] |= 0xFF00;
  128 
  129                 buttons = b[(msg[0]&7) | (shift ? 8 : 0)];
  130                 if(intellimouse && packetsize==4){
  131                         if((msg[3]&0xc8) == 0x08){
  132                                 /* first byte of 3-byte packet */
  133                                 packetsize = 3;
  134                                 msg[0] = msg[3];
  135                                 nb = 1;
  136                                 /* fall through to emit previous packet */
  137                         }else{
  138                                 /* The AccuPoint on the Toshiba 34[48]0CT
  139                                  * encodes extra buttons as 4 and 5. They repeat
  140                                  * and don't release, however, so user-level
  141                                  * timing code is required. Furthermore,
  142                                  * intellimice with 3buttons + scroll give a
  143                                  * two's complement number in the lower 4 bits
  144                                  * (bit 4 is sign extension) that describes
  145                                  * the amount the scroll wheel has moved during
  146                                  * the last sample. Here we use only the sign to
  147                                  * decide whether the wheel is moving up or down
  148                                  * and generate a single button 4 or 5 click
  149                                  * accordingly.
  150                                  */
  151                                 if((msg[3] >> 3) & 1) 
  152                                         buttons |= 1<<3;
  153                                 else if(msg[3] & 0x7) 
  154                                         buttons |= 1<<4;
  155                         }
  156                 }
  157                 dx = msg[1];
  158                 dy = -msg[2];
  159                 mousetrack(dx, dy, buttons, TK2MS(MACHP(0)->ticks));
  160         }
  161         return;
  162 }
  163 
  164 /*
  165  *  set up a ps2 mouse
  166  */
  167 static void
  168 ps2mouse(void)
  169 {
  170         if(mousetype == MousePS2)
  171                 return;
  172 
  173         i8042auxenable(ps2mouseputc);
  174         /* make mouse streaming, enabled */
  175         i8042auxcmd(0xEA);
  176         i8042auxcmd(0xF4);
  177 
  178         mousetype = MousePS2;
  179         packetsize = 3;
  180         mousehwaccel = 1;
  181 }
  182 
  183 /*
  184  * The PS/2 Trackpoint multiplexor on the IBM Thinkpad T23 ignores
  185  * acceleration commands.  It is supposed to pass them on
  186  * to the attached device, but my Logitech mouse is simply
  187  * not behaving any differently.  For such devices, we allow
  188  * the user to use "hwaccel off" to tell us to back off to
  189  * software acceleration even if we're using the PS/2 port.
  190  * (Serial mice are always software accelerated.)
  191  * For more information on the Thinkpad multiplexor, see
  192  * http://wwwcssrv.almaden.ibm.com/trackpoint/
  193  */
  194 static void
  195 setaccelerated(int x)
  196 {
  197         accelerated = x;
  198         if(mousehwaccel){
  199                 switch(mousetype){
  200                 case MousePS2:
  201                         i8042auxcmd(0xE7);
  202                         return;
  203                 }
  204         }
  205         mouseaccelerate(x);
  206 }
  207 
  208 static void
  209 setlinear(void)
  210 {
  211         accelerated = 0;
  212         if(mousehwaccel){
  213                 switch(mousetype){
  214                 case MousePS2:
  215                         i8042auxcmd(0xE6);
  216                         return;
  217                 }
  218         }
  219         mouseaccelerate(0);
  220 }
  221 
  222 static void
  223 setres(int n)
  224 {
  225         resolution = n;
  226         switch(mousetype){
  227         case MousePS2:
  228                 i8042auxcmd(0xE8);
  229                 i8042auxcmd(n);
  230                 break;
  231         }
  232 }
  233 
  234 static void
  235 setintellimouse(void)
  236 {
  237         intellimouse = 1;
  238         packetsize = 4;
  239         switch(mousetype){
  240         case MousePS2:
  241                 i8042auxcmd(0xF3);      /* set sample */
  242                 i8042auxcmd(0xC8);
  243                 i8042auxcmd(0xF3);      /* set sample */
  244                 i8042auxcmd(0x64);
  245                 i8042auxcmd(0xF3);      /* set sample */
  246                 i8042auxcmd(0x50);
  247                 break;
  248         case Mouseserial:
  249                 i8250setmouseputc(mouseport, m5mouseputc);
  250                 break;
  251         }
  252 }
  253 
  254 static void
  255 resetmouse(void)
  256 {
  257         packetsize = 3;
  258         switch(mousetype){
  259         case MousePS2:
  260                 i8042auxcmd(0xF6);
  261                 i8042auxcmd(0xEA);      /* streaming */
  262                 i8042auxcmd(0xE8);      /* set resolution */
  263                 i8042auxcmd(3);
  264                 i8042auxcmd(0xF4);      /* enabled */
  265                 break;
  266         }
  267 }
  268 
  269 void
  270 mousectl(Cmdbuf *cb)
  271 {
  272         Cmdtab *ct;
  273 
  274         qlock(&mousectlqlock);
  275         if(waserror()){
  276                 qunlock(&mousectlqlock);
  277                 nexterror();
  278         }
  279 
  280         ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg));
  281         switch(ct->index){
  282         case CMaccelerated:
  283                 setaccelerated(cb->nf == 1 ? 1 : atoi(cb->f[1]));
  284                 break;
  285         case CMintellimouse:
  286                 setintellimouse();
  287                 break;
  288         case CMlinear:
  289                 setlinear();
  290                 break;
  291         case CMps2:
  292                 intellimouse = 0;
  293                 ps2mouse();
  294                 break;
  295         case CMps2intellimouse:
  296                 ps2mouse();
  297                 setintellimouse();
  298                 break;
  299         case CMres:
  300                 if(cb->nf >= 2)
  301                         setres(atoi(cb->f[1]));
  302                 else
  303                         setres(1);
  304                 break;
  305         case CMreset:
  306                 resetmouse();
  307                 if(accelerated)
  308                         setaccelerated(accelerated);
  309                 if(resolution)
  310                         setres(resolution);
  311                 if(intellimouse)
  312                         setintellimouse();
  313                 break;
  314         case CMserial:
  315                 if(mousetype == Mouseserial)
  316                         error(Emouseset);
  317 
  318                 if(cb->nf > 2){
  319                         if(strcmp(cb->f[2], "M") == 0)
  320                                 i8250mouse(cb->f[1], m3mouseputc, 0);
  321                         else if(strcmp(cb->f[2], "MI") == 0)
  322                                 i8250mouse(cb->f[1], m5mouseputc, 0);
  323                         else
  324                                 i8250mouse(cb->f[1], mouseputc, cb->nf == 1);
  325                 } else
  326                         i8250mouse(cb->f[1], mouseputc, cb->nf == 1);
  327 
  328                 mousetype = Mouseserial;
  329                 strncpy(mouseport, cb->f[1], sizeof(mouseport)-1);
  330                 packetsize = 3;
  331                 break;
  332         case CMhwaccel:
  333                 if(strcmp(cb->f[1], "on")==0)
  334                         mousehwaccel = 1;
  335                 else if(strcmp(cb->f[1], "off")==0)
  336                         mousehwaccel = 0;
  337                 else
  338                         cmderror(cb, "bad mouse control message");
  339         }
  340 
  341         qunlock(&mousectlqlock);
  342         poperror();
  343 }

Cache object: 1a23d251b1330db1571fbf1a6d1b71b3


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