source: rtems/c/src/lib/libbsp/i386/pc386/console/mouse_parser.c @ 3cbb63a

4.104.114.84.95
Last change on this file since 3cbb63a was 3cbb63a, checked in by Joel Sherrill <joel.sherrill@…>, on 08/30/00 at 08:15:30

2000-08-26 Rosimildo da Silva <rdasilva@…>

  • 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
  • Property mode set to 100644
File size: 9.2 KB
Line 
1/*
2 * Copyright (c) 1999 Greg Haerr <greg@censoft.com>
3 * Portions Copyright (c) 1991 David I. Bell
4 * Permission is granted to use, distribute, or modify this source,
5 * provided that this copyright notice remains intact.
6 *
7 * UNIX Serial Port Mouse Driver
8 *
9 * This driver opens a serial port directly, and interprets serial data.
10 * Microsoft, PC, Logitech and PS/2 mice are supported.
11 * The PS/2 mouse is only supported if the OS runs the mouse
12 * byte codes through the serial port.
13 *
14 * The following environment variables control the mouse type expected
15 * and the serial port to open.
16 *
17 * Environment Var      Default         Allowed
18 * MOUSE_TYPE           pc              ms, pc, logi, ps2
19 */
20#include <stdio.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <errno.h>
25
26#include <rtems.h>
27#include <bsp.h>
28#include "keyboard.h"
29#include "mouse_parser.h"
30#include "serial_mouse.h"
31
32
33/* NOTE NOTE NOTE NOTE:
34   Select here the mouse type !!!!!
35*/
36#ifndef  MOUSE_TYPE
37#define MOUSE_TYPE      "ms"  /* default mouse type "ms","pc","ps2" */
38#endif
39
40/* states for the mouse*/
41#define IDLE                    0               /* start of byte sequence */
42#define XSET                    1               /* setting x delta */
43#define YSET                    2               /* setting y delta */
44#define XADD                    3               /* adjusting x delta */
45#define YADD                    4               /* adjusting y delta */
46
47/* values in the bytes returned by the mouse for the buttons*/
48#define PC_LEFT_BUTTON          4
49#define PC_MIDDLE_BUTTON        2
50#define PC_RIGHT_BUTTON         1
51
52#define MS_LEFT_BUTTON          2
53#define MS_RIGHT_BUTTON         1
54
55#define PS2_CTRL_BYTE           0x08
56#define PS2_LEFT_BUTTON         1
57#define PS2_RIGHT_BUTTON        2
58
59/* Bit fields in the bytes sent by the mouse.*/
60#define TOP_FIVE_BITS           0xf8
61#define BOTTOM_THREE_BITS       0x07
62#define TOP_BIT                 0x80
63#define SIXTH_BIT               0x40
64#define BOTTOM_TWO_BITS         0x03
65#define THIRD_FOURTH_BITS       0x0c
66#define BOTTOM_SIX_BITS         0x3f
67
68/* local data*/
69static int              state;          /* IDLE, XSET, ... */
70static BUTTON   buttons;        /* current mouse buttons pressed*/
71static BUTTON   availbuttons;   /* which buttons are available */
72static COORD    xd;             /* change in x */
73static COORD    yd;             /* change in y */
74
75static int              left;              /* because the button values change */
76static int              middle;         /* between mice, the buttons are */
77static int              right;          /* redefined */
78
79static int              (*parse)( int );        /* parse routine */
80
81/* local routines*/
82static int      ParsePC(int);           /* routine to interpret PC mouse */
83static int      ParseMS(int);           /* routine to interpret MS mouse */
84static int      ParsePS2(int);          /* routine to interpret PS/2 mouse */
85
86extern void uart_set_driver_handler( int port, void ( *handler )( void *,  char *, int ) );
87extern void kbd_set_driver_handler( void ( *handler )( void *,  unsigned short, unsigned long ) );
88extern void ps2_set_driver_handler( int port, void ( *handler )( void *,  char *, int ) );
89
90/*
91 * Open up the mouse device.
92 * Returns the fd if successful, or negative if unsuccessful.
93 */
94int MOU_Init()
95{
96        char    *type;
97
98        /* get mouse type and port*/
99        type = MOUSE_TYPE;
100
101        /* set button bits and parse procedure*/
102        if(!strcmp(type, "pc") || !strcmp(type, "logi")) {
103                /* pc or logitech mouse*/
104                left = PC_LEFT_BUTTON;
105                middle = PC_MIDDLE_BUTTON;
106                right = PC_RIGHT_BUTTON;
107                parse = ParsePC;
108        } else if (strcmp(type, "ms") == 0) {
109                /* microsoft mouse*/
110                left = MS_LEFT_BUTTON;
111                right = MS_RIGHT_BUTTON;
112                middle = 0;
113                parse = ParseMS;
114        } else if (strcmp(type, "ps2") == 0) {
115                /* PS/2 mouse*/
116                left = PS2_LEFT_BUTTON;
117                right = PS2_RIGHT_BUTTON;
118                middle = 0;
119                parse = ParsePS2;
120        } else
121                return -1;
122
123   printk("Device: /dev/mouse -- mouse type is: %s\n", MOUSE_TYPE );
124
125        /* initialize data*/
126        availbuttons = left | middle | right;
127        state = IDLE;
128        buttons = 0;
129        xd = 0;
130        yd = 0;
131        return 0;
132}
133
134/*
135 * Attempt to read bytes from the mouse and interpret them.
136 * Returns -1 on error, 0 if either no bytes were read or not enough
137 * was read for a complete state, or 1 if the new state was read.
138 * When a new state is read, the current buttons and x and y deltas
139 * are returned.  This routine does not block.
140 */
141int MOU_Data( int ch, COORD *dx, COORD *dy, COORD *dz, BUTTON *bptr)
142{
143        int b;
144
145        /*
146         * Loop over all the bytes read in the buffer, parsing them.
147         * When a complete state has been read, return the results,
148         * leaving further bytes in the buffer for later calls.
149         */
150        if( (*parse)( ch ) )
151        {
152                *dx = xd;
153                *dy = yd;
154                *dz = 0;
155                b = 0;
156                if(buttons & left)
157                        b |= LBUTTON;
158                if(buttons & right)
159                        b |= RBUTTON;
160                if(buttons & middle)
161                        b |= MBUTTON;
162                *bptr = b;
163                return 1;
164        }
165        return 0;
166}
167
168/*
169 * Input routine for PC mouse.
170 * Returns nonzero when a new mouse state has been completed.
171 */
172static int ParsePC(int byte)
173{
174        int     sign;                   /* sign of movement */
175
176        switch (state) {
177                case IDLE:
178                        if ((byte & TOP_FIVE_BITS) == TOP_BIT) {
179                                buttons = ~byte & BOTTOM_THREE_BITS;
180                                state = XSET;
181                        }
182                        break;
183
184                case XSET:
185                        sign = 1;
186                        if (byte > 127) {
187                                byte = 256 - byte;
188                                sign = -1;
189                        }
190                        xd = byte * sign;
191                        state = YSET;
192                        break;
193
194                case YSET:
195                        sign = 1;
196                        if (byte > 127) {
197                                byte = 256 - byte;
198                                sign = -1;
199                        }
200                        yd = -byte * sign;
201                        state = XADD;
202                        break;
203
204                case XADD:
205                        sign = 1;
206                        if (byte > 127) {
207                                byte = 256 - byte;
208                                sign = -1;
209                        }
210                        xd += byte * sign;
211                        state = YADD;
212                        break;
213
214                case YADD:
215                        sign = 1;
216                        if (byte > 127) {
217                                byte = 256 - byte;
218                                sign = -1;
219                        }
220                        yd -= byte * sign;
221                        state = IDLE;
222                        return 1;
223        }
224        return 0;
225}
226
227
228/*
229 * Input routine for Microsoft mouse.
230 * Returns nonzero when a new mouse state has been completed.
231 */
232static int ParseMS(int byte)
233{
234        switch (state) {
235                case IDLE:
236                        if (byte & SIXTH_BIT) {
237                                buttons = (byte >> 4) & BOTTOM_TWO_BITS;
238                                yd = ((byte & THIRD_FOURTH_BITS) << 4);
239                                xd = ((byte & BOTTOM_TWO_BITS) << 6);
240                                state = XADD;
241                        }
242                        break;
243
244                case XADD:
245                        xd |= (byte & BOTTOM_SIX_BITS);
246                        state = YADD;
247                        break;
248
249                case YADD:
250                        yd |= (byte & BOTTOM_SIX_BITS);
251                        state = IDLE;
252                        if (xd > 127)
253                                xd -= 256;
254                        if (yd > 127)
255                                yd -= 256;
256                        return 1;
257        }
258        return 0;
259}
260
261/*
262 * Input routine for PS/2 mouse.
263 * Returns nonzero when a new mouse state has been completed.
264 */
265static int ParsePS2(int byte)
266{
267        switch (state) {
268                case IDLE:
269                        if (byte & PS2_CTRL_BYTE) {
270                                buttons = byte &
271                                        (PS2_LEFT_BUTTON|PS2_RIGHT_BUTTON);
272                                state = XSET;
273                        }
274                        break;
275
276                case XSET:
277                        if(byte > 127)
278                                byte -= 256;
279                        xd = byte;
280                        state = YSET;
281                        break;
282
283                case YSET:
284                        if(byte > 127)
285                                byte -= 256;
286                        yd = -byte;
287                        state = IDLE;
288                        return 1;
289        }
290        return 0;
291}
292
293static rtems_id queue_id = 0;
294
295/* generic keyboard parser */
296static void mouse_parser( void *ptr, char *buffer, int size )
297{
298   COORD dx;
299   COORD dy;
300   COORD dz;
301   BUTTON bptr;
302   while( size-- )
303   {
304      if( MOU_Data( *buffer++, &dx, &dy, &dz, &bptr ) )
305      {
306         struct MW_UID_MESSAGE m;
307         m.type = MV_UID_REL_POS;
308         /* buttons definitons have been selected to match */
309         m.m.pos.btns = bptr;
310         m.m.pos.x  = dx;
311         m.m.pos.y  = dy;
312         m.m.pos.z  = dz;
313/*       printk( "Mouse: msg: dx=%d, dy=%d, btn=%X\n", dx, dy, bptr ); */
314         rtems_message_queue_send( queue_id, ( void * )&m, sizeof( struct MW_UID_MESSAGE ) );
315      }
316   }
317}
318
319/* enable the mouse to add messages to the queue */
320void register_mou_msg_queue( char * q_name, int port )
321{
322   rtems_name queue_name;
323   rtems_status_code status;
324   queue_name = rtems_build_name( q_name[0],
325                                  q_name[1],
326                                  q_name[2],
327                                  q_name[3] );
328   status = rtems_message_queue_ident( queue_name, RTEMS_LOCAL, &queue_id );
329   if( status != RTEMS_SUCCESSFUL )
330   {
331      printk( "UID_Queue: error open queue: %d\n", status );
332      return;
333   }
334   MOU_Init();
335   if( port == -1 )
336   {
337      /* we know the mouse type in this case, let's initialize everything */
338                left = PS2_LEFT_BUTTON;
339                right = PS2_RIGHT_BUTTON;
340                middle = 0;
341                parse = ParsePS2;
342      ps2_set_driver_handler( port, mouse_parser );
343   }
344   else
345   {
346      uart_set_driver_handler( port, mouse_parser );
347   }
348}
349
350/* stop the mouse from adding messages to the queue */
351void unregister_mou_msg_queue( int port )
352{
353   if( port == -1 )
354   {
355      ps2_set_driver_handler( port, NULL );
356   }
357   else
358   {
359      uart_set_driver_handler( port, NULL );
360   }
361}
362
363/* adds a kbd message to the queue */
364static void kbd_parser( void *ptr, unsigned short keycode, unsigned long mods )
365{
366    struct MW_UID_MESSAGE m;
367    struct kbd_struct * kbd = ( struct kbd_struct *)ptr;
368
369    m.type = MV_UID_KBD;
370    m.m.kbd.code       = keycode;
371    m.m.kbd.modifiers  = kbd->ledflagstate;
372    m.m.kbd.mode       = kbd->kbdmode;
373    /*  printk( "kbd: msg: keycode=%X, mod=%X\n", keycode, mods );  */
374    rtems_message_queue_send( queue_id, ( void * )&m,
375                              sizeof( struct MW_UID_MESSAGE ) );
376}
377
378void register_kbd_msg_queue( char *q_name, int port )
379{
380   rtems_name queue_name;
381   rtems_status_code status;
382
383   queue_name = rtems_build_name( q_name[0],
384                                  q_name[1],
385                                  q_name[2],
386                                  q_name[3] );
387   status = rtems_message_queue_ident( queue_name, RTEMS_LOCAL, &queue_id );
388   if( status != RTEMS_SUCCESSFUL )
389   {
390      printk( "UID_Queue: error open queue: %d\n", status );
391      return;
392   }
393   kbd_set_driver_handler( kbd_parser );
394}
395
396
397void unregister_kbd_msg_queue( int port )
398{
399   kbd_set_driver_handler( NULL );
400}
Note: See TracBrowser for help on using the repository browser.