Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:18

0001 /**
0002  * @file
0003  *
0004  * @ingroup libmisc_mouse Mouse Parser Engine
0005  *
0006  * @brief Opens a Serial Port Directly, and Interprets Serial Data
0007  */
0008 
0009 /*
0010  * This code is derived from a UNIX Serial Port Mouse Driver with
0011  * the following notice:
0012  *
0013  * ==================================================================
0014  * Copyright (c) 1999 Greg Haerr <greg@censoft.com>
0015  * Portions Copyright (c) 1991 David I. Bell
0016  * Permission is granted to use, distribute, or modify this source,
0017  * provided that this copyright notice remains intact.
0018  *
0019  * UNIX Serial Port Mouse Driver
0020  *
0021  * This driver opens a serial port directly, and interprets serial data.
0022  * Microsoft, PC, Logitech and PS/2 mice are supported.  The PS/2 mouse
0023  * is only supported if the OS runs the mouse byte codes through the
0024  * serial port.
0025  *
0026  * Mouse Types Supported: pc  ms, logi, ps2
0027  * ==================================================================
0028  *
0029  * It has been modified to support the concept of being just a parser
0030  * fed data from an arbitrary source.  It is independent of either
0031  * a PS/2 driver or a serial port.
0032  *
0033  * It was moved to cpukit/libmisc/mouse by Joel Sherrill.
0034  */
0035 
0036 #include <stdio.h>
0037 #include <stdlib.h>
0038 #include <string.h>  /* strcmp */
0039 #include <unistd.h>
0040 #include <fcntl.h>
0041 #include <errno.h>
0042 
0043 #include <rtems.h>
0044 #include <rtems/bspIo.h>
0045 #include <rtems/mouse_parser.h>
0046 #include <rtems/mw_uid.h>
0047 
0048 /* states for the mouse */
0049 #define IDLE   0  /* start of byte sequence */
0050 #define XSET   1  /* setting x delta */
0051 #define YSET   2  /* setting y delta */
0052 #define XADD   3  /* adjusting x delta */
0053 #define YADD   4  /* adjusting y delta */
0054 
0055 /* values in the bytes returned by the mouse for the buttons*/
0056 #define PC_LEFT_BUTTON   4
0057 #define PC_MIDDLE_BUTTON 2
0058 #define PC_RIGHT_BUTTON  1
0059 
0060 #define MS_LEFT_BUTTON   2
0061 #define MS_RIGHT_BUTTON  1
0062 
0063 #define PS2_CTRL_BYTE    0x08
0064 #define PS2_LEFT_BUTTON    1
0065 #define PS2_RIGHT_BUTTON  2
0066 
0067 /* Bit fields in the bytes sent by the mouse.*/
0068 #define TOP_FIVE_BITS      0xf8
0069 #define BOTTOM_THREE_BITS  0x07
0070 #define TOP_BIT            0x80
0071 #define SIXTH_BIT          0x40
0072 #define BOTTOM_TWO_BITS    0x03
0073 #define THIRD_FOURTH_BITS  0x0c
0074 #define BOTTOM_SIX_BITS    0x3f
0075 
0076 /* local data */
0077 static int     state;            /* IDLE, XSET, ... */
0078 static BUTTON  buttons;          /* current mouse buttons pressed*/
0079 static BUTTON  availbuttons;     /* which buttons are available */
0080 static COORD   xd;               /* change in x */
0081 static COORD   yd;               /* change in y */
0082 
0083 static int     left;             /* because the button values change */
0084 static int     middle;           /* between mice, the buttons are */
0085 static int     right;            /* redefined */
0086 
0087 static int     (*parse)( int );  /* parse routine */
0088 
0089 /* local routines*/
0090 static int ParsePC(int);    /* routine to interpret PC mouse */
0091 static int ParseMS(int);    /* routine to interpret MS mouse */
0092 static int ParsePS2(int);    /* routine to interpret PS/2 mouse */
0093 
0094 /*
0095  * Open up the mouse device.
0096  * Returns the fd if successful, or negative if unsuccessful.
0097  */
0098 int mouse_parser_initialize(const char *type)
0099 {
0100   /* set button bits and parse procedure*/
0101   if (!strcmp(type, "pc") || !strcmp(type, "logi")) {
0102     /* pc or logitech mouse*/
0103     left = PC_LEFT_BUTTON;
0104     middle = PC_MIDDLE_BUTTON;
0105     right = PC_RIGHT_BUTTON;
0106     parse = ParsePC;
0107   } else if (strcmp(type, "ms") == 0) {
0108     /* microsoft mouse*/
0109     left = MS_LEFT_BUTTON;
0110     right = MS_RIGHT_BUTTON;
0111     middle = 0;
0112     parse = ParseMS;
0113   } else if (strcmp(type, "ps2") == 0) {
0114     /* PS/2 mouse*/
0115     left = PS2_LEFT_BUTTON;
0116     right = PS2_RIGHT_BUTTON;
0117     middle = 0;
0118     parse = ParsePS2;
0119   } else
0120     return -1;
0121 
0122   printk("Device: /dev/mouse -- mouse type is: %s\n", type );
0123 
0124   /* initialize data*/
0125   availbuttons = left | middle | right;
0126   state = IDLE;
0127   buttons = 0;
0128   xd = 0;
0129   yd = 0;
0130   return 0;
0131 }
0132 
0133 /*
0134  * Attempt to read bytes from the mouse and interpret them.
0135  * Returns -1 on error, 0 if either no bytes were read or not enough
0136  * was read for a complete state, or 1 if the new state was read.
0137  * When a new state is read, the current buttons and x and y deltas
0138  * are returned.  This routine does not block.
0139  */
0140 static int MOU_Data( int ch, COORD *dx, COORD *dy, COORD *dz, BUTTON *bptr)
0141 {
0142   int b;
0143 
0144   if ( !parse ) {
0145     printk( "Mouse parser is not initialized!\n" );
0146     return -1;
0147   }
0148 
0149   /*
0150    * Loop over all the bytes read in the buffer, parsing them.
0151    * When a complete state has been read, return the results,
0152    * leaving further bytes in the buffer for later calls.
0153    */
0154   if ( (*parse)( ch ) ) {
0155     *dx = xd;
0156     *dy = yd;
0157     *dz = 0;
0158     b = 0;
0159     if (buttons & left)
0160       b |= LBUTTON;
0161     if (buttons & right)
0162       b |= RBUTTON;
0163     if (buttons & middle)
0164       b |= MBUTTON;
0165     *bptr = b;
0166     return 1;
0167   }
0168   return 0;
0169 }
0170 
0171 /*
0172  * Input routine for PC mouse.
0173  * Returns nonzero when a new mouse state has been completed.
0174  */
0175 static int ParsePC(int byte)
0176 {
0177   int  sign;      /* sign of movement */
0178 
0179   switch (state) {
0180     case IDLE:
0181       if ((byte & TOP_FIVE_BITS) == TOP_BIT) {
0182         buttons = ~byte & BOTTOM_THREE_BITS;
0183         state = XSET;
0184       }
0185       break;
0186 
0187     case XSET:
0188       sign = 1;
0189       if (byte > 127) {
0190         byte = 256 - byte;
0191         sign = -1;
0192       }
0193       xd = byte * sign;
0194       state = YSET;
0195       break;
0196 
0197     case YSET:
0198       sign = 1;
0199       if (byte > 127) {
0200         byte = 256 - byte;
0201         sign = -1;
0202       }
0203       yd = -byte * sign;
0204       state = XADD;
0205       break;
0206 
0207     case XADD:
0208       sign = 1;
0209       if (byte > 127) {
0210         byte = 256 - byte;
0211         sign = -1;
0212       }
0213       xd += byte * sign;
0214       state = YADD;
0215       break;
0216 
0217     case YADD:
0218       sign = 1;
0219       if (byte > 127) {
0220         byte = 256 - byte;
0221         sign = -1;
0222       }
0223       yd -= byte * sign;
0224       state = IDLE;
0225       return 1;
0226   }
0227   return 0;
0228 }
0229 
0230 /*
0231  * Input routine for Microsoft mouse.
0232  * Returns nonzero when a new mouse state has been completed.
0233  */
0234 static int ParseMS(int byte)
0235 {
0236   switch (state) {
0237     case IDLE:
0238       if (byte & SIXTH_BIT) {
0239         buttons = (byte >> 4) & BOTTOM_TWO_BITS;
0240         yd = ((byte & THIRD_FOURTH_BITS) << 4);
0241         xd = ((byte & BOTTOM_TWO_BITS) << 6);
0242         state = XADD;
0243       }
0244       break;
0245 
0246     case XADD:
0247       xd |= (byte & BOTTOM_SIX_BITS);
0248       state = YADD;
0249       break;
0250 
0251     case YADD:
0252       yd |= (byte & BOTTOM_SIX_BITS);
0253       state = IDLE;
0254       if (xd > 127)
0255         xd -= 256;
0256       if (yd > 127)
0257         yd -= 256;
0258       return 1;
0259   }
0260   return 0;
0261 }
0262 
0263 /*
0264  * Input routine for PS/2 mouse.
0265  * Returns nonzero when a new mouse state has been completed.
0266  */
0267 static int ParsePS2(int byte)
0268 {
0269   switch (state) {
0270     case IDLE:
0271       if (byte & PS2_CTRL_BYTE) {
0272         buttons = byte &
0273           (PS2_LEFT_BUTTON|PS2_RIGHT_BUTTON);
0274         state = XSET;
0275       }
0276       break;
0277 
0278     case XSET:
0279       if(byte > 127)
0280         byte -= 256;
0281       xd = byte;
0282       state = YSET;
0283       break;
0284 
0285     case YSET:
0286       if(byte > 127)
0287         byte -= 256;
0288       yd = -byte;
0289       state = IDLE;
0290       return 1;
0291   }
0292   return 0;
0293 }
0294 
0295 /* generic mouse parser */
0296 void mouse_parser_enqueue( unsigned char *buffer, size_t size )
0297 {
0298   COORD dx;
0299   COORD dy;
0300   COORD dz;
0301   BUTTON bptr;
0302 
0303   while( size-- ) {
0304     if ( MOU_Data( *buffer++, &dx, &dy, &dz, &bptr ) == 1 ) {
0305        struct MW_UID_MESSAGE m;
0306 
0307         m.type = MV_UID_REL_POS;
0308         /* buttons definitons have been selected to match */
0309         m.m.pos.btns = bptr;
0310         m.m.pos.x  = dx;
0311         m.m.pos.y  = dy;
0312         m.m.pos.z  = dz;
0313         /* printk( "Mouse: msg: dx=%d, dy=%d, btn=%X\n", dx, dy, bptr ); */
0314         uid_send_message( &m );
0315     }
0316   }
0317 }
0318