From 3cbb63ac774a21e13f5f75271810754b70ff311d Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 30 Aug 2000 08:15:30 +0000 Subject: 2000-08-26 Rosimildo da Silva * Major rework of the "/dev/console" driver. * Added termios support for stdin ( keyboard ). * Added ioctls() to support modes similar to Linux( XLATE, RAW, MEDIUMRAW ). * Added Keyboard mapping and handling of the keyboard's leds. * Added Micro FrameBuffer driver ( "/dev/fb0" ) for bare VGA controller ( 16 colors ). * Added PS/2 and Serial mouse support for PC386 BSP. * console/defkeymap.c: New file. * console/fb_vga.c: New file. * console/fb_vga.h: New file. * console/i386kbd.h: New file. * console/kd.h: New file. * console/keyboard.c: New file. * console/keyboard.h: New file. * console/mouse_parser.c: New file. * console/mouse_parser.h: New file. * console/pc_keyb.c: New file. * console/ps2_drv.h: New file. * console/ps2_mouse.c: New file. * console/ps2_mouse.h: New file. * console/serial_mouse.c: New file. * console/serial_mouse.h: New file. * console/vgainit.c: New file. * console/vt.c: New file. * console/Makefile.am: Reflect new files. * console/console.c, console/inch.c, console/outch.c: Console functionality modifications. * startup/Makefile.am: Pick up tty_drv.c and gdb_glue.c --- c/src/lib/libbsp/i386/pc386/console/mouse_parser.c | 400 +++++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 c/src/lib/libbsp/i386/pc386/console/mouse_parser.c (limited to 'c/src/lib/libbsp/i386/pc386/console/mouse_parser.c') diff --git a/c/src/lib/libbsp/i386/pc386/console/mouse_parser.c b/c/src/lib/libbsp/i386/pc386/console/mouse_parser.c new file mode 100644 index 0000000000..ca068df87d --- /dev/null +++ b/c/src/lib/libbsp/i386/pc386/console/mouse_parser.c @@ -0,0 +1,400 @@ +/* + * Copyright (c) 1999 Greg Haerr + * 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. + * + * The following environment variables control the mouse type expected + * and the serial port to open. + * + * Environment Var Default Allowed + * MOUSE_TYPE pc ms, pc, logi, ps2 + */ +#include +#include +#include +#include +#include + +#include +#include +#include "keyboard.h" +#include "mouse_parser.h" +#include "serial_mouse.h" + + +/* NOTE NOTE NOTE NOTE: + Select here the mouse type !!!!! +*/ +#ifndef MOUSE_TYPE +#define MOUSE_TYPE "ms" /* default mouse type "ms","pc","ps2" */ +#endif + +/* 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 */ + +extern void uart_set_driver_handler( int port, void ( *handler )( void *, char *, int ) ); +extern void kbd_set_driver_handler( void ( *handler )( void *, unsigned short, unsigned long ) ); +extern void ps2_set_driver_handler( int port, void ( *handler )( void *, char *, int ) ); + +/* + * Open up the mouse device. + * Returns the fd if successful, or negative if unsuccessful. + */ +int MOU_Init() +{ + char *type; + + /* get mouse type and port*/ + type = MOUSE_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", MOUSE_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; + + /* + * 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; +} + +static rtems_id queue_id = 0; + +/* generic keyboard parser */ +static void mouse_parser( void *ptr, char *buffer, int 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 ); */ + rtems_message_queue_send( queue_id, ( void * )&m, sizeof( struct MW_UID_MESSAGE ) ); + } + } +} + +/* enable the mouse to add messages to the queue */ +void register_mou_msg_queue( char * q_name, int port ) +{ + rtems_name queue_name; + rtems_status_code status; + queue_name = rtems_build_name( q_name[0], + q_name[1], + q_name[2], + q_name[3] ); + status = rtems_message_queue_ident( queue_name, RTEMS_LOCAL, &queue_id ); + if( status != RTEMS_SUCCESSFUL ) + { + printk( "UID_Queue: error open queue: %d\n", status ); + return; + } + MOU_Init(); + if( port == -1 ) + { + /* we know the mouse type in this case, let's initialize everything */ + left = PS2_LEFT_BUTTON; + right = PS2_RIGHT_BUTTON; + middle = 0; + parse = ParsePS2; + ps2_set_driver_handler( port, mouse_parser ); + } + else + { + uart_set_driver_handler( port, mouse_parser ); + } +} + +/* stop the mouse from adding messages to the queue */ +void unregister_mou_msg_queue( int port ) +{ + if( port == -1 ) + { + ps2_set_driver_handler( port, NULL ); + } + else + { + uart_set_driver_handler( port, NULL ); + } +} + +/* adds a kbd message to the queue */ +static void kbd_parser( void *ptr, unsigned short keycode, unsigned long mods ) +{ + struct MW_UID_MESSAGE m; + struct kbd_struct * kbd = ( struct kbd_struct *)ptr; + + m.type = MV_UID_KBD; + m.m.kbd.code = keycode; + m.m.kbd.modifiers = kbd->ledflagstate; + m.m.kbd.mode = kbd->kbdmode; + /* printk( "kbd: msg: keycode=%X, mod=%X\n", keycode, mods ); */ + rtems_message_queue_send( queue_id, ( void * )&m, + sizeof( struct MW_UID_MESSAGE ) ); +} + +void register_kbd_msg_queue( char *q_name, int port ) +{ + rtems_name queue_name; + rtems_status_code status; + + queue_name = rtems_build_name( q_name[0], + q_name[1], + q_name[2], + q_name[3] ); + status = rtems_message_queue_ident( queue_name, RTEMS_LOCAL, &queue_id ); + if( status != RTEMS_SUCCESSFUL ) + { + printk( "UID_Queue: error open queue: %d\n", status ); + return; + } + kbd_set_driver_handler( kbd_parser ); +} + + +void unregister_kbd_msg_queue( int port ) +{ + kbd_set_driver_handler( NULL ); +} -- cgit v1.2.3