OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [mw/] [src/] [drivers/] [mou_ser.c] - Blame information for rev 770

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
/*
2
 * Copyright (c) 1999, 2000 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 supported by using the /dev/psaux device.
12
 *
13
 * The following environment variables control the mouse type expected
14
 * and the serial port to open.
15
 *
16
 * Environment Var      Default         Allowed
17
 * MOUSE_TYPE           pc              ms, pc, logi, ps2
18
 * MOUSE_PORT           /dev/ttyS1      any serial port or /dev/psaux
19
 */
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <unistd.h>
23
#include <errno.h>
24
#include <fcntl.h>
25
#include <string.h>
26
#include "device.h"
27
 
28
#define TERMIOS         1       /* set to use termios serial port control*/
29
#define SGTTY           0        /* set to use sgtty serial port control*/
30
 
31
#define SCALE           3       /* default scaling factor for acceleration */
32
#define THRESH          5       /* default threshhold for acceleration */
33
 
34
#if TERMIOS
35
#include <termios.h>
36
#endif
37
#if SGTTY
38
#include <sgtty.h>
39
#endif
40
 
41
/* default settings*/
42
#if _MINIX
43
#define MOUSE_PORT      "/dev/mouse"
44
#define MOUSE_TYPE      "ms"
45
#else
46
#if ELKS
47
#define MOUSE_PORT      "/dev/ttys0"    /* default mouse tty port */
48
#else
49
#define MOUSE_PORT      "/dev/ttyS1"    /* default mouse tty port */
50
#endif
51 716 simons
#define MOUSE_TYPE      "ms"            /* default mouse type "ms","pc","ps2" */
52 673 markom
#endif
53
#define MAX_BYTES       128             /* number of bytes for buffer */
54
 
55
/* states for the mouse*/
56
#define IDLE                    0                /* start of byte sequence */
57
#define XSET                    1               /* setting x delta */
58
#define YSET                    2               /* setting y delta */
59
#define XADD                    3               /* adjusting x delta */
60
#define YADD                    4               /* adjusting y delta */
61
 
62
/* values in the bytes returned by the mouse for the buttons*/
63
#define PC_LEFT_BUTTON          4
64
#define PC_MIDDLE_BUTTON        2
65
#define PC_RIGHT_BUTTON         1
66
 
67
#define MS_LEFT_BUTTON          2
68
#define MS_RIGHT_BUTTON         1
69
 
70
#define PS2_CTRL_BYTE           0x08
71
#define PS2_LEFT_BUTTON         1
72
#define PS2_RIGHT_BUTTON        2
73
 
74
/* Bit fields in the bytes sent by the mouse.*/
75
#define TOP_FIVE_BITS           0xf8
76
#define BOTTOM_THREE_BITS       0x07
77
#define TOP_BIT                 0x80
78
#define SIXTH_BIT               0x40
79
#define BOTTOM_TWO_BITS         0x03
80
#define THIRD_FOURTH_BITS       0x0c
81
#define BOTTOM_SIX_BITS         0x3f
82
 
83
/* local data*/
84
static int              mouse_fd;       /* file descriptor for mouse */
85
static int              state;          /* IDLE, XSET, ... */
86
static int              buttons;        /* current mouse buttons pressed*/
87
static int              availbuttons;   /* which buttons are available */
88
static MWCOORD          xd;             /* change in x */
89
static MWCOORD          yd;             /* change in y */
90
 
91
static int              left;           /* because the button values change */
92
static int              middle;         /* between mice, the buttons are */
93
static int              right;          /* redefined */
94
 
95
static unsigned char    *bp;            /* buffer pointer */
96
static int              nbytes;         /* number of bytes left */
97
static unsigned char    buffer[MAX_BYTES];      /* data bytes read */
98
static int              (*parse)();     /* parse routine */
99
 
100
/* local routines*/
101
static int      MOU_Open(MOUSEDEVICE *pmd);
102
static void     MOU_Close(void);
103
static int      MOU_GetButtonInfo(void);
104
static void     MOU_GetDefaultAccel(int *pscale,int *pthresh);
105
static int      MOU_Read(MWCOORD *dx, MWCOORD *dy, MWCOORD *dz, int *bptr);
106
static int      MOU_Poll(void);
107
static int      ParsePC(int);           /* routine to interpret PC mouse */
108
static int      ParseMS(int);           /* routine to interpret MS mouse */
109
static int      ParsePS2(int);          /* routine to interpret PS/2 mouse */
110
 
111
MOUSEDEVICE mousedev = {
112
        MOU_Open,
113
        MOU_Close,
114
        MOU_GetButtonInfo,
115
        MOU_GetDefaultAccel,
116
        MOU_Read,
117
#if _MINIX
118
        MOU_Poll
119
#else
120
        NULL
121
#endif
122
};
123
 
124 770 simons
extern void _print(char *, ...);
125 673 markom
/*
126
 * Open up the mouse device.
127
 * Returns the fd if successful, or negative if unsuccessful.
128
 */
129
static int
130
MOU_Open(MOUSEDEVICE *pmd)
131
{
132
        char    *type;
133
        char    *port;
134
        struct termios termios;
135
 
136
        /* get mouse type and port*/
137
        if( !(type = getenv("MOUSE_TYPE")))
138
                type = MOUSE_TYPE;
139
 
140
        if( !(port = getenv("MOUSE_PORT")))
141
                port = MOUSE_PORT;
142
 
143
        /* set button bits and parse procedure*/
144
        if(!strcmp(type, "pc") || !strcmp(type, "logi")) {
145
                /* pc or logitech mouse*/
146
                left = PC_LEFT_BUTTON;
147
                middle = PC_MIDDLE_BUTTON;
148
                right = PC_RIGHT_BUTTON;
149
                parse = ParsePC;
150
        } else if (strcmp(type, "ms") == 0) {
151
                /* microsoft mouse*/
152
                left = MS_LEFT_BUTTON;
153
                right = MS_RIGHT_BUTTON;
154
                middle = 0;
155
                parse = ParseMS;
156
        } else if (strcmp(type, "ps2") == 0) {
157
                /* PS/2 mouse*/
158
                left = PS2_LEFT_BUTTON;
159
                right = PS2_RIGHT_BUTTON;
160
                middle = 0;
161
                parse = ParsePS2;
162
        } else
163
                return -1;
164
 
165
        /* open mouse port*/
166
        mouse_fd = open(port, O_NONBLOCK);
167
        if (mouse_fd < 0) {
168
                EPRINTF("Error %d opening serial mouse type %s on port %s.\n",
169
                        errno, type, port);
170
                return -1;
171
        }
172
 
173
#if SGTTY
174
        /* set rawmode serial port using sgtty*/
175
        struct sgttyb sgttyb;
176
 
177
        if (ioctl(fd, TIOCGETP, &sgttyb) == -1)
178
                goto err;
179
        sgttyb.sg_flags |= RAW;
180
        sgttyb.sg_flags &= ~(EVENP | ODDP | ECHO | XTABS | CRMOD);
181
 
182
        if (ioctl(fd, TIOCSETP, &sgttyb) == -1)
183
                goto err;
184
        if (ioctl(fd, TIOCFLUSH, 0) < 0)
185
                goto err;
186
#endif
187
 
188
#if TERMIOS
189
        /*
190
         * Note we don't check success for the tcget/setattr calls,
191
         * some kernels don't support them for certain devices
192
         * (like /dev/psaux).
193
         */
194
 
195
        /* set rawmode serial port using termios*/
196
        tcgetattr(mouse_fd, &termios);
197
 
198
        /* These functions appear to be broken in ELKS Dev86 */
199
        if(cfgetispeed(&termios) != B1200)
200
                cfsetispeed(&termios, B1200);
201
#if _MINIX
202
        if(cfgetospeed(&termios) != B1200)
203
                cfsetospeed(&termios, B1200);
204
#endif
205
 
206
#if !_MINIX
207
        termios.c_cflag &= ~CBAUD;
208
        termios.c_cflag |= B1200;
209
#endif
210
        termios.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
211
        termios.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON | BRKINT | IGNBRK);
212
        termios.c_cflag &= ~(CSIZE | PARENB);
213 770 simons
        termios.c_cflag |= CS7;
214 673 markom
        termios.c_cc[VMIN] = 0;
215
        termios.c_cc[VTIME] = 0;
216
 
217
        tcsetattr(mouse_fd, TCSAFLUSH, &termios);
218
#endif /* TERMIOS*/
219
 
220
        /* initialize data*/
221
        availbuttons = left | middle | right;
222
        state = IDLE;
223
        nbytes = 0;
224
        buttons = 0;
225
        xd = 0;
226
        yd = 0;
227
        return mouse_fd;
228
err:
229
        close(mouse_fd);
230
        mouse_fd = 0;
231
        return -1;
232
}
233
 
234
/*
235
 * Close the mouse device.
236
 */
237
static void
238
MOU_Close(void)
239
{
240
        if (mouse_fd > 0) {
241
                close(mouse_fd);
242
        }
243
        mouse_fd = 0;
244
}
245
 
246
/*
247
 * Get mouse buttons supported
248
 */
249
static int
250
MOU_GetButtonInfo(void)
251
{
252
        return availbuttons;
253
}
254
 
255
/*
256
 * Get default mouse acceleration settings
257
 */
258
static void
259
MOU_GetDefaultAccel(int *pscale,int *pthresh)
260
{
261
        *pscale = SCALE;
262
        *pthresh = THRESH;
263
}
264
 
265
/*
266
 * Attempt to read bytes from the mouse and interpret them.
267
 * Returns -1 on error, 0 if either no bytes were read or not enough
268
 * was read for a complete state, or 1 if the new state was read.
269
 * When a new state is read, the current buttons and x and y deltas
270
 * are returned.  This routine does not block.
271
 */
272
static int
273
MOU_Read(MWCOORD *dx, MWCOORD *dy, MWCOORD *dz, int *bptr)
274
{
275
        int     b;
276
 
277
        /*
278
         * If there are no more bytes left, then read some more,
279
         * waiting for them to arrive.  On a signal or a non-blocking
280
         * error, return saying there is no new state available yet.
281
         */
282
        if (nbytes <= 0) {
283
                bp = buffer;
284
                nbytes = read(mouse_fd, bp, MAX_BYTES);
285
                if (nbytes < 0) {
286
                        if (errno == EINTR || errno == EAGAIN)
287
                                return 0;
288
#if _MINIX
289
                        return 0;
290
#else
291
                        return -1;
292
#endif
293
                }
294
        }
295
 
296
        /*
297
         * Loop over all the bytes read in the buffer, parsing them.
298
         * When a complete state has been read, return the results,
299
         * leaving further bytes in the buffer for later calls.
300
         */
301
        while (nbytes-- > 0) {
302
                if ((*parse)((int) *bp++)) {
303
                        *dx = xd;
304
                        *dy = yd;
305
                        *dz = 0;
306
                        b = 0;
307
                        if(buttons & left)
308
                                b |= MWBUTTON_L;
309
                        if(buttons & right)
310
                                b |= MWBUTTON_R;
311
                        if(buttons & middle)
312
                                b |= MWBUTTON_M;
313
                        *bptr = b;
314
                        return 1;
315
                }
316
        }
317
        return 0;
318
}
319
 
320
/*
321
 * Input routine for PC mouse.
322
 * Returns nonzero when a new mouse state has been completed.
323
 */
324
static int
325
ParsePC(int byte)
326
{
327
        int     sign;                   /* sign of movement */
328
 
329 770 simons
_print("ParsePS2: %.2x\n", byte);
330 673 markom
        switch (state) {
331
                case IDLE:
332
                        if ((byte & TOP_FIVE_BITS) == TOP_BIT) {
333
                                buttons = ~byte & BOTTOM_THREE_BITS;
334
                                state = XSET;
335
                        }
336
                        break;
337
 
338
                case XSET:
339
                        sign = 1;
340
                        if (byte > 127) {
341
                                byte = 256 - byte;
342
                                sign = -1;
343
                        }
344
                        xd = byte * sign;
345
                        state = YSET;
346
                        break;
347
 
348
                case YSET:
349
                        sign = 1;
350
                        if (byte > 127) {
351
                                byte = 256 - byte;
352
                                sign = -1;
353
                        }
354
                        yd = -byte * sign;
355
                        state = XADD;
356
                        break;
357
 
358
                case XADD:
359
                        sign = 1;
360
                        if (byte > 127) {
361
                                byte = 256 - byte;
362
                                sign = -1;
363
                        }
364
                        xd += byte * sign;
365
                        state = YADD;
366
                        break;
367
 
368
                case YADD:
369
                        sign = 1;
370
                        if (byte > 127) {
371
                                byte = 256 - byte;
372
                                sign = -1;
373
                        }
374
                        yd -= byte * sign;
375
                        state = IDLE;
376
                        return 1;
377
        }
378
        return 0;
379
}
380
 
381
 
382
/*
383
 * Input routine for Microsoft mouse.
384
 * Returns nonzero when a new mouse state has been completed.
385
 */
386
static int
387
ParseMS(int byte)
388
{
389 770 simons
_print("ParseMS: %.2x\n", byte);
390 673 markom
        switch (state) {
391
                case IDLE:
392
                        if (byte & SIXTH_BIT) {
393
                                buttons = (byte >> 4) & BOTTOM_TWO_BITS;
394
                                yd = ((byte & THIRD_FOURTH_BITS) << 4);
395
                                xd = ((byte & BOTTOM_TWO_BITS) << 6);
396
                                state = XADD;
397
                        }
398
                        break;
399
 
400
                case XADD:
401
                        xd |= (byte & BOTTOM_SIX_BITS);
402
                        state = YADD;
403
                        break;
404
 
405
                case YADD:
406
                        yd |= (byte & BOTTOM_SIX_BITS);
407
                        state = IDLE;
408
                        if (xd > 127)
409
                                xd -= 256;
410
                        if (yd > 127)
411
                                yd -= 256;
412
                        return 1;
413
        }
414
        return 0;
415
}
416
 
417
/*
418
 * Input routine for PS/2 mouse.
419
 * Returns nonzero when a new mouse state has been completed.
420
 */
421
static int
422
ParsePS2(int byte)
423
{
424 770 simons
_print("ParsePS2: %.2x\n", byte);
425 673 markom
        switch (state) {
426
                case IDLE:
427
                        if (byte & PS2_CTRL_BYTE) {
428
                                buttons = byte &
429
                                        (PS2_LEFT_BUTTON|PS2_RIGHT_BUTTON);
430
                                state = XSET;
431
                        }
432
                        break;
433
 
434
                case XSET:
435
                        if(byte > 127)
436
                                byte -= 256;
437
                        xd = byte;
438
                        state = YSET;
439
                        break;
440
 
441
                case YSET:
442
                        if(byte > 127)
443
                                byte -= 256;
444
                        yd = -byte;
445
                        state = IDLE;
446
                        return 1;
447
        }
448
        return 0;
449
}
450
 
451
static int
452
MOU_Poll(void)
453
{
454
        return 1;       /* used by _MINIX only*/
455
}
456
 
457
/*  #define TEST 1  */
458
#if TEST
459
main()
460
{
461
        MWCOORD x, y, z;
462
        int     b;
463
 
464
        DPRINTF("Open Mouse\n");
465
        if( MOU_Open(0) < 0)
466
                DPRINTF("open failed mouse\n" );
467
 
468
        while(1)
469
        {
470
                if(MOU_Read(&x, &y, &z, &b) == 1)
471
                {
472
                        DPRINTF("%d,%d,%d\n", x, y, b);
473
                }
474
        }
475
}
476
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.