source: rtems/cpukit/libmisc/mouse/mouse_parser.c @ 3d6c1bb

4.11
Last change on this file since 3d6c1bb was 3d6c1bb, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 14, 2011 at 2:56:08 PM

2011-03-14 Joel Sherrill <joel.sherrill@…>

PR 1762/cpukit

  • Makefile.am, preinstall.am, libmisc/Makefile.am, wrapup/Makefile.am: Add generic serial mouse driver and mouse parser. The parser code was in the pc386 BSP but was generic so cleaned up and placed here. Serial mouse driver itself is new.
  • libmisc/mouse/README, libmisc/mouse/mouse_parser.c, libmisc/mouse/mouse_parser.h, libmisc/mouse/serial_mouse.c, libmisc/mouse/serial_mouse.h: New files.
  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 * This code is derived from a UNIX Serial Port Mouse Driver with
3 * the following notice:
4 *
5 * ==================================================================
6 * Copyright (c) 1999 Greg Haerr <greg@censoft.com>
7 * Portions Copyright (c) 1991 David I. Bell
8 * Permission is granted to use, distribute, or modify this source,
9 * provided that this copyright notice remains intact.
10 *
11 * UNIX Serial Port Mouse Driver
12 *
13 * This driver opens a serial port directly, and interprets serial data.
14 * Microsoft, PC, Logitech and PS/2 mice are supported.  The PS/2 mouse
15 * is only supported if the OS runs the mouse byte codes through the
16 * serial port.
17 *
18 * Mouse Types Supported: pc  ms, logi, ps2
19 * ==================================================================
20 *
21 * It has been modified to support the concept of being just a parser
22 * fed data from an arbitrary source.  It is independent of either
23 * a PS/2 driver or a serial port.
24 *
25 * It was moved to cpukit/libmisc/mouse by Joel Sherrill.
26 *
27 * $Id$
28 */
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>  /* strcmp */
33#include <unistd.h>
34#include <fcntl.h>
35#include <errno.h>
36
37#include <rtems.h>
38#include <bsp.h>
39#include <rtems/mouse_parser.h>
40#include <rtems/mw_uid.h>
41
42/* states for the mouse */
43#define IDLE   0  /* start of byte sequence */
44#define XSET   1  /* setting x delta */
45#define YSET   2  /* setting y delta */
46#define XADD   3  /* adjusting x delta */
47#define YADD   4  /* adjusting y delta */
48
49/* values in the bytes returned by the mouse for the buttons*/
50#define PC_LEFT_BUTTON   4
51#define PC_MIDDLE_BUTTON 2
52#define PC_RIGHT_BUTTON  1
53
54#define MS_LEFT_BUTTON   2
55#define MS_RIGHT_BUTTON  1
56
57#define PS2_CTRL_BYTE    0x08
58#define PS2_LEFT_BUTTON    1
59#define PS2_RIGHT_BUTTON  2
60
61/* Bit fields in the bytes sent by the mouse.*/
62#define TOP_FIVE_BITS      0xf8
63#define BOTTOM_THREE_BITS  0x07
64#define TOP_BIT            0x80
65#define SIXTH_BIT          0x40
66#define BOTTOM_TWO_BITS    0x03
67#define THIRD_FOURTH_BITS  0x0c
68#define BOTTOM_SIX_BITS    0x3f
69
70/* local data */
71static int     state;            /* IDLE, XSET, ... */
72static BUTTON  buttons;          /* current mouse buttons pressed*/
73static BUTTON  availbuttons;     /* which buttons are available */
74static COORD   xd;               /* change in x */
75static COORD   yd;               /* change in y */
76
77static int     left;             /* because the button values change */
78static int     middle;           /* between mice, the buttons are */
79static int     right;            /* redefined */
80
81static int     (*parse)( int );  /* parse routine */
82
83/* local routines*/
84static int ParsePC(int);    /* routine to interpret PC mouse */
85static int ParseMS(int);    /* routine to interpret MS mouse */
86static int ParsePS2(int);    /* routine to interpret PS/2 mouse */
87
88/*
89 * Open up the mouse device.
90 * Returns the fd if successful, or negative if unsuccessful.
91 */
92int mouse_parser_initialize(const char *type)
93{
94  /* set button bits and parse procedure*/
95  if (!strcmp(type, "pc") || !strcmp(type, "logi")) {
96    /* pc or logitech mouse*/
97    left = PC_LEFT_BUTTON;
98    middle = PC_MIDDLE_BUTTON;
99    right = PC_RIGHT_BUTTON;
100    parse = ParsePC;
101  } else if (strcmp(type, "ms") == 0) {
102    /* microsoft mouse*/
103    left = MS_LEFT_BUTTON;
104    right = MS_RIGHT_BUTTON;
105    middle = 0;
106    parse = ParseMS;
107  } else if (strcmp(type, "ps2") == 0) {
108    /* PS/2 mouse*/
109    left = PS2_LEFT_BUTTON;
110    right = PS2_RIGHT_BUTTON;
111    middle = 0;
112    parse = ParsePS2;
113  } else
114    return -1;
115
116  printk("Device: /dev/mouse -- mouse type is: %s\n", type );
117
118  /* initialize data*/
119  availbuttons = left | middle | right;
120  state = IDLE;
121  buttons = 0;
122  xd = 0;
123  yd = 0;
124  return 0;
125}
126
127/*
128 * Attempt to read bytes from the mouse and interpret them.
129 * Returns -1 on error, 0 if either no bytes were read or not enough
130 * was read for a complete state, or 1 if the new state was read.
131 * When a new state is read, the current buttons and x and y deltas
132 * are returned.  This routine does not block.
133 */
134int MOU_Data( int ch, COORD *dx, COORD *dy, COORD *dz, BUTTON *bptr)
135{
136  int b;
137
138  if ( !parse ) {
139    printk( "Mouse parser is not initialized!\n" );
140    return -1;
141  } 
142
143  /*
144   * Loop over all the bytes read in the buffer, parsing them.
145   * When a complete state has been read, return the results,
146   * leaving further bytes in the buffer for later calls.
147   */
148  if ( (*parse)( ch ) ) {
149    *dx = xd;
150    *dy = yd;
151    *dz = 0;
152    b = 0;
153    if (buttons & left)
154      b |= LBUTTON;
155    if (buttons & right)
156      b |= RBUTTON;
157    if (buttons & middle)
158      b |= MBUTTON;
159    *bptr = b;
160    return 1;
161  }
162  return 0;
163}
164
165/*
166 * Input routine for PC mouse.
167 * Returns nonzero when a new mouse state has been completed.
168 */
169static int ParsePC(int byte)
170{
171  int  sign;      /* sign of movement */
172
173  switch (state) {
174    case IDLE:
175      if ((byte & TOP_FIVE_BITS) == TOP_BIT) {
176        buttons = ~byte & BOTTOM_THREE_BITS;
177        state = XSET;
178      }
179      break;
180
181    case XSET:
182      sign = 1;
183      if (byte > 127) {
184        byte = 256 - byte;
185        sign = -1;
186      }
187      xd = byte * sign;
188      state = YSET;
189      break;
190
191    case YSET:
192      sign = 1;
193      if (byte > 127) {
194        byte = 256 - byte;
195        sign = -1;
196      }
197      yd = -byte * sign;
198      state = XADD;
199      break;
200
201    case XADD:
202      sign = 1;
203      if (byte > 127) {
204        byte = 256 - byte;
205        sign = -1;
206      }
207      xd += byte * sign;
208      state = YADD;
209      break;
210
211    case YADD:
212      sign = 1;
213      if (byte > 127) {
214        byte = 256 - byte;
215        sign = -1;
216      }
217      yd -= byte * sign;
218      state = IDLE;
219      return 1;
220  }
221  return 0;
222}
223
224/*
225 * Input routine for Microsoft mouse.
226 * Returns nonzero when a new mouse state has been completed.
227 */
228static int ParseMS(int byte)
229{
230  switch (state) {
231    case IDLE:
232      if (byte & SIXTH_BIT) {
233        buttons = (byte >> 4) & BOTTOM_TWO_BITS;
234        yd = ((byte & THIRD_FOURTH_BITS) << 4);
235        xd = ((byte & BOTTOM_TWO_BITS) << 6);
236        state = XADD;
237      }
238      break;
239
240    case XADD:
241      xd |= (byte & BOTTOM_SIX_BITS);
242      state = YADD;
243      break;
244
245    case YADD:
246      yd |= (byte & BOTTOM_SIX_BITS);
247      state = IDLE;
248      if (xd > 127)
249        xd -= 256;
250      if (yd > 127)
251        yd -= 256;
252      return 1;
253  }
254  return 0;
255}
256
257/*
258 * Input routine for PS/2 mouse.
259 * Returns nonzero when a new mouse state has been completed.
260 */
261static int ParsePS2(int byte)
262{
263  switch (state) {
264    case IDLE:
265      if (byte & PS2_CTRL_BYTE) {
266        buttons = byte &
267          (PS2_LEFT_BUTTON|PS2_RIGHT_BUTTON);
268        state = XSET;
269      }
270      break;
271
272    case XSET:
273      if(byte > 127)
274        byte -= 256;
275      xd = byte;
276      state = YSET;
277      break;
278
279    case YSET:
280      if(byte > 127)
281        byte -= 256;
282      yd = -byte;
283      state = IDLE;
284      return 1;
285  }
286  return 0;
287}
288
289/* generic mouse parser */
290void mouse_parser_enqueue( unsigned char *buffer, size_t size )
291{
292  COORD dx;
293  COORD dy;
294  COORD dz;
295  BUTTON bptr;
296
297  while( size-- ) {
298    if ( MOU_Data( *buffer++, &dx, &dy, &dz, &bptr ) ) {
299       struct MW_UID_MESSAGE m;
300
301        m.type = MV_UID_REL_POS;
302        /* buttons definitons have been selected to match */
303        m.m.pos.btns = bptr;
304        m.m.pos.= dx;
305        m.m.pos.= dy;
306        m.m.pos.= dz;
307        /* printk( "Mouse: msg: dx=%d, dy=%d, btn=%X\n", dx, dy, bptr ); */
308        uid_send_message( &m );
309    }
310  }
311}
312
Note: See TracBrowser for help on using the repository browser.