📄 mouse_parser.c
字号:
/* * 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. * * 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 <stdio.h>#include <stdlib.h>#include <string.h> /* strcmp */#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <rtems.h>#include <bsp.h>#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 );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -