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

4.104.114.84.95
Last change on this file since b88e366 was b88e366, checked in by Ralf Corsepius <ralf.corsepius@…>, on 08/29/02 at 15:54:25

2002-08-29 Ralf Corsepius <corsepiu@…>

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