diff options
Diffstat (limited to 'cpukit/libmisc/mouse/mouse_parser.c')
-rw-r--r-- | cpukit/libmisc/mouse/mouse_parser.c | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/cpukit/libmisc/mouse/mouse_parser.c b/cpukit/libmisc/mouse/mouse_parser.c new file mode 100644 index 0000000000..9d78bbd979 --- /dev/null +++ b/cpukit/libmisc/mouse/mouse_parser.c @@ -0,0 +1,311 @@ +/* + * This code is derived from a UNIX Serial Port Mouse Driver with + * the following notice: + * + * ================================================================== + * Copyright (c) 1999 Greg Haerr <greg@censoft.com> + * Portions Copyright (c) 1991 David I. Bell + * Permission is granted to use, distribute, or modify this source, + * provided that this copyright notice remains intact. + * + * UNIX Serial Port Mouse Driver + * + * This driver opens a serial port directly, and interprets serial data. + * Microsoft, PC, Logitech and PS/2 mice are supported. The PS/2 mouse + * is only supported if the OS runs the mouse byte codes through the + * serial port. + * + * Mouse Types Supported: pc ms, logi, ps2 + * ================================================================== + * + * It has been modified to support the concept of being just a parser + * fed data from an arbitrary source. It is independent of either + * a PS/2 driver or a serial port. + * + * It was moved to cpukit/libmisc/mouse by Joel Sherrill. + * + * $Id$ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> /* strcmp */ +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#include <rtems.h> +#include <rtems/mouse_parser.h> +#include <rtems/mw_uid.h> + +/* states for the mouse */ +#define IDLE 0 /* start of byte sequence */ +#define XSET 1 /* setting x delta */ +#define YSET 2 /* setting y delta */ +#define XADD 3 /* adjusting x delta */ +#define YADD 4 /* adjusting y delta */ + +/* values in the bytes returned by the mouse for the buttons*/ +#define PC_LEFT_BUTTON 4 +#define PC_MIDDLE_BUTTON 2 +#define PC_RIGHT_BUTTON 1 + +#define MS_LEFT_BUTTON 2 +#define MS_RIGHT_BUTTON 1 + +#define PS2_CTRL_BYTE 0x08 +#define PS2_LEFT_BUTTON 1 +#define PS2_RIGHT_BUTTON 2 + +/* Bit fields in the bytes sent by the mouse.*/ +#define TOP_FIVE_BITS 0xf8 +#define BOTTOM_THREE_BITS 0x07 +#define TOP_BIT 0x80 +#define SIXTH_BIT 0x40 +#define BOTTOM_TWO_BITS 0x03 +#define THIRD_FOURTH_BITS 0x0c +#define BOTTOM_SIX_BITS 0x3f + +/* local data */ +static int state; /* IDLE, XSET, ... */ +static BUTTON buttons; /* current mouse buttons pressed*/ +static BUTTON availbuttons; /* which buttons are available */ +static COORD xd; /* change in x */ +static COORD yd; /* change in y */ + +static int left; /* because the button values change */ +static int middle; /* between mice, the buttons are */ +static int right; /* redefined */ + +static int (*parse)( int ); /* parse routine */ + +/* local routines*/ +static int ParsePC(int); /* routine to interpret PC mouse */ +static int ParseMS(int); /* routine to interpret MS mouse */ +static int ParsePS2(int); /* routine to interpret PS/2 mouse */ + +/* + * Open up the mouse device. + * Returns the fd if successful, or negative if unsuccessful. + */ +int mouse_parser_initialize(const char *type) +{ + /* set button bits and parse procedure*/ + if (!strcmp(type, "pc") || !strcmp(type, "logi")) { + /* pc or logitech mouse*/ + left = PC_LEFT_BUTTON; + middle = PC_MIDDLE_BUTTON; + right = PC_RIGHT_BUTTON; + parse = ParsePC; + } else if (strcmp(type, "ms") == 0) { + /* microsoft mouse*/ + left = MS_LEFT_BUTTON; + right = MS_RIGHT_BUTTON; + middle = 0; + parse = ParseMS; + } else if (strcmp(type, "ps2") == 0) { + /* PS/2 mouse*/ + left = PS2_LEFT_BUTTON; + right = PS2_RIGHT_BUTTON; + middle = 0; + parse = ParsePS2; + } else + return -1; + + printk("Device: /dev/mouse -- mouse type is: %s\n", type ); + + /* initialize data*/ + availbuttons = left | middle | right; + state = IDLE; + buttons = 0; + xd = 0; + yd = 0; + return 0; +} + +/* + * Attempt to read bytes from the mouse and interpret them. + * Returns -1 on error, 0 if either no bytes were read or not enough + * was read for a complete state, or 1 if the new state was read. + * When a new state is read, the current buttons and x and y deltas + * are returned. This routine does not block. + */ +int MOU_Data( int ch, COORD *dx, COORD *dy, COORD *dz, BUTTON *bptr) +{ + int b; + + if ( !parse ) { + printk( "Mouse parser is not initialized!\n" ); + return -1; + } + + /* + * Loop over all the bytes read in the buffer, parsing them. + * When a complete state has been read, return the results, + * leaving further bytes in the buffer for later calls. + */ + if ( (*parse)( ch ) ) { + *dx = xd; + *dy = yd; + *dz = 0; + b = 0; + if (buttons & left) + b |= LBUTTON; + if (buttons & right) + b |= RBUTTON; + if (buttons & middle) + b |= MBUTTON; + *bptr = b; + return 1; + } + return 0; +} + +/* + * Input routine for PC mouse. + * Returns nonzero when a new mouse state has been completed. + */ +static int ParsePC(int byte) +{ + int sign; /* sign of movement */ + + switch (state) { + case IDLE: + if ((byte & TOP_FIVE_BITS) == TOP_BIT) { + buttons = ~byte & BOTTOM_THREE_BITS; + state = XSET; + } + break; + + case XSET: + sign = 1; + if (byte > 127) { + byte = 256 - byte; + sign = -1; + } + xd = byte * sign; + state = YSET; + break; + + case YSET: + sign = 1; + if (byte > 127) { + byte = 256 - byte; + sign = -1; + } + yd = -byte * sign; + state = XADD; + break; + + case XADD: + sign = 1; + if (byte > 127) { + byte = 256 - byte; + sign = -1; + } + xd += byte * sign; + state = YADD; + break; + + case YADD: + sign = 1; + if (byte > 127) { + byte = 256 - byte; + sign = -1; + } + yd -= byte * sign; + state = IDLE; + return 1; + } + return 0; +} + +/* + * Input routine for Microsoft mouse. + * Returns nonzero when a new mouse state has been completed. + */ +static int ParseMS(int byte) +{ + switch (state) { + case IDLE: + if (byte & SIXTH_BIT) { + buttons = (byte >> 4) & BOTTOM_TWO_BITS; + yd = ((byte & THIRD_FOURTH_BITS) << 4); + xd = ((byte & BOTTOM_TWO_BITS) << 6); + state = XADD; + } + break; + + case XADD: + xd |= (byte & BOTTOM_SIX_BITS); + state = YADD; + break; + + case YADD: + yd |= (byte & BOTTOM_SIX_BITS); + state = IDLE; + if (xd > 127) + xd -= 256; + if (yd > 127) + yd -= 256; + return 1; + } + return 0; +} + +/* + * Input routine for PS/2 mouse. + * Returns nonzero when a new mouse state has been completed. + */ +static int ParsePS2(int byte) +{ + switch (state) { + case IDLE: + if (byte & PS2_CTRL_BYTE) { + buttons = byte & + (PS2_LEFT_BUTTON|PS2_RIGHT_BUTTON); + state = XSET; + } + break; + + case XSET: + if(byte > 127) + byte -= 256; + xd = byte; + state = YSET; + break; + + case YSET: + if(byte > 127) + byte -= 256; + yd = -byte; + state = IDLE; + return 1; + } + return 0; +} + +/* generic mouse parser */ +void mouse_parser_enqueue( unsigned char *buffer, size_t size ) +{ + COORD dx; + COORD dy; + COORD dz; + BUTTON bptr; + + while( size-- ) { + if ( MOU_Data( *buffer++, &dx, &dy, &dz, &bptr ) ) { + struct MW_UID_MESSAGE m; + + m.type = MV_UID_REL_POS; + /* buttons definitons have been selected to match */ + m.m.pos.btns = bptr; + m.m.pos.x = dx; + m.m.pos.y = dy; + m.m.pos.z = dz; + /* printk( "Mouse: msg: dx=%d, dy=%d, btn=%X\n", dx, dy, bptr ); */ + uid_send_message( &m ); + } + } +} + |