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

Subversion Repositories or1k

[/] [or1k/] [tags/] [before_ORP/] [uclinux/] [uClinux-2.0.x/] [drivers/] [sbus/] [char/] [sunmouse.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/* sunmouse.c: Sun mouse driver for the Sparc
2
 *
3
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
4
 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
5
 *
6
 * Parts based on the psaux.c driver written by:
7
 * Johan Myreen.
8
 *
9
 * Dec/19/95 Added SunOS mouse ioctls - miguel.
10
 * Jan/5/96  Added VUID support, sigio support - miguel.
11
 * Mar/5/96  Added proper mouse stream support - miguel.
12
 */
13
 
14
/* The mouse is run off of one of the Zilog serial ports.  On
15
 * that port is the mouse and the keyboard, each gets a zs channel.
16
 * The mouse itself is mouse-systems in nature.  So the protocol is:
17
 *
18
 * Byte 1) Button state which is bit-encoded as
19
 *            0x4 == left-button down, else up
20
 *            0x2 == middle-button down, else up
21
 *            0x1 == right-button down, else up
22
 *
23
 * Byte 2) Delta-x
24
 * Byte 3) Delta-y
25
 * Byte 4) Delta-x again
26
 * Byte 5) Delta-y again
27
 *
28
 * One day this driver will have to support more than one mouse in the system.
29
 *
30
 * This driver has two modes of operation: the default VUID_NATIVE is
31
 * set when the device is opened and allows the application to see the
32
 * mouse character stream as we get it from the serial (for gpm for
33
 * example).  The second method, VUID_FIRM_EVENT will provide cooked
34
 * events in Firm_event records.
35
 * */
36
 
37
#include <linux/kernel.h>
38
#include <linux/sched.h>
39
#include <linux/fcntl.h>
40
#include <linux/signal.h>
41
#include <linux/timer.h>
42
#include <linux/errno.h>
43
#include <linux/miscdevice.h>
44
#include <linux/mm.h>
45
#include <asm/segment.h>
46
#include <asm/system.h>
47
#include <asm/vuid_event.h>
48
#include <linux/random.h>
49
/* The following keeps track of software state for the Sun
50
 * mouse.
51
 */
52
#define STREAM_SIZE   2048
53
#define EV_SIZE       (STREAM_SIZE/sizeof (Firm_event))
54
#define BUTTON_LEFT   4
55
#define BUTTON_MIDDLE 2
56
#define BUTTON_RIGHT  1
57
 
58
struct sun_mouse {
59
        unsigned char transaction[5];  /* Each protocol transaction */
60
        unsigned char byte;            /* Counter, starts at 0 */
61
        unsigned char button_state;    /* Current button state */
62
        unsigned char prev_state;      /* Previous button state */
63
        int delta_x;                   /* Current delta-x */
64
        int delta_y;                   /* Current delta-y */
65
        int present;
66
        int ready;                     /* set if there if data is available */
67
        int active;                    /* set if device is open */
68
        int vuid_mode;                 /* VUID_NATIVE or VUID_FIRM_EVENT */
69
        struct wait_queue *proc_list;
70
        struct fasync_struct *fasync;
71
 
72
        /* The event/stream queue */
73
        unsigned int head;
74
        unsigned int tail;
75
        union {
76
                char stream [STREAM_SIZE];
77
                Firm_event ev [0];
78
        } queue;
79
};
80
 
81
static struct sun_mouse sunmouse;
82
#define gen_events (sunmouse.vuid_mode != VUID_NATIVE)
83
#define bstate sunmouse.button_state
84
#define pstate sunmouse.prev_state
85
 
86
extern void mouse_put_char(char ch);
87
 
88
/* #define SMOUSE_DEBUG */
89
 
90
static void
91
push_event (Firm_event *ev)
92
{
93
        int next = (sunmouse.head + 1) % EV_SIZE;
94
 
95
        if (next != sunmouse.tail){
96
                sunmouse.queue.ev [sunmouse.head] = *ev;
97
                sunmouse.head = next;
98
        }
99
}
100
 
101
static int
102
queue_empty (void)
103
{
104
        return sunmouse.head == sunmouse.tail;
105
}
106
 
107
static Firm_event *
108
get_from_queue (void)
109
{
110
        Firm_event *result;
111
 
112
        result = &sunmouse.queue.ev [sunmouse.tail];
113
        sunmouse.tail = (sunmouse.tail + 1) % EV_SIZE;
114
        return result;
115
}
116
 
117
static void
118
push_char (char c)
119
{
120
        int next = (sunmouse.head + 1) % STREAM_SIZE;
121
 
122
        if (next != sunmouse.tail){
123
                sunmouse.queue.stream [sunmouse.head] = c;
124
                sunmouse.head = next;
125
        }
126
        sunmouse.ready = 1;
127
        if (sunmouse.fasync)
128
                kill_fasync (sunmouse.fasync, SIGIO);
129
        wake_up_interruptible (&sunmouse.proc_list);
130
}
131
 
132
/* The following is called from the zs driver when bytes are received on
133
 * the Mouse zs8530 channel.
134
 */
135
void
136
sun_mouse_inbyte(unsigned char byte, unsigned char status)
137
{
138
        signed char mvalue;
139
        int d;
140
        Firm_event ev;
141
 
142
        add_mouse_randomness (byte);
143
        if(!sunmouse.active)
144
                return;
145
 
146
        if (!gen_events){
147
                push_char (byte);
148
                return;
149
        }
150
        /* Check for framing errors and parity errors */
151
        /* XXX TODO XXX */
152
 
153
        /* If the mouse sends us a byte from 0x80 to 0x87
154
         * we are starting at byte zero in the transaction
155
         * protocol.
156
         */
157
        if(byte >= 0x80 && byte <= 0x87)
158
                sunmouse.byte = 0;
159
 
160
        mvalue = (signed char) byte;
161
        switch(sunmouse.byte) {
162
        case 0:
163
                /* Button state */
164
                sunmouse.button_state = (~byte) & 0x7;
165
#ifdef SMOUSE_DEBUG
166
                printk("B<Left %s, Middle %s, Right %s>",
167
                       ((sunmouse.button_state & 0x4) ? "DOWN" : "UP"),
168
                       ((sunmouse.button_state & 0x2) ? "DOWN" : "UP"),
169
                       ((sunmouse.button_state & 0x1) ? "DOWN" : "UP"));
170
#endif
171
                sunmouse.byte++;
172
                return;
173
        case 1:
174
                /* Delta-x 1 */
175
#ifdef SMOUSE_DEBUG
176
                printk("DX1<%d>", mvalue);
177
#endif
178
                sunmouse.delta_x = mvalue;
179
                sunmouse.byte++;
180
                return;
181
        case 2:
182
                /* Delta-y 1 */
183
#ifdef SMOUSE_DEBUG
184
                printk("DY1<%d>", mvalue);
185
#endif
186
                sunmouse.delta_y = mvalue;
187
                sunmouse.byte++;
188
                return;
189
        case 3:
190
                /* Delta-x 2 */
191
#ifdef SMOUSE_DEBUG
192
                printk("DX2<%d>", mvalue);
193
#endif
194
                sunmouse.delta_x += mvalue;
195
                sunmouse.byte++;
196
                return;
197
        case 4:
198
                /* Last byte, Delta-y 2 */
199
#ifdef SMOUSE_DEBUG
200
                printk("DY2<%d>", mvalue);
201
#endif
202
                sunmouse.delta_y += mvalue;
203
                sunmouse.byte = 69;  /* Some ridiculous value */
204
                break;
205
        case 69:
206
                /* Until we get the (0x80 -> 0x87) value we aren't
207
                 * in the middle of a real transaction, so just
208
                 * return.
209
                 */
210
                return;
211
        default:
212
                printk("sunmouse: bogon transaction state\n");
213
                sunmouse.byte = 69;  /* What could cause this? */
214
                return;
215
        };
216
        d = bstate ^ pstate;
217
        pstate = bstate;
218
        if (d){
219
                if (d & BUTTON_LEFT){
220
                        ev.id = MS_LEFT;
221
                        ev.value = bstate & BUTTON_LEFT;
222
                }
223
                if (d & BUTTON_RIGHT){
224
                        ev.id = MS_RIGHT;
225
                        ev.value = bstate & BUTTON_RIGHT;
226
                }
227
                if (d & BUTTON_MIDDLE){
228
                        ev.id = MS_MIDDLE;
229
                        ev.value = bstate & BUTTON_MIDDLE;
230
                }
231
                ev.time = xtime;
232
                ev.value = ev.value ? VKEY_DOWN : VKEY_UP;
233
                push_event (&ev);
234
        }
235
        if (sunmouse.delta_x){
236
                ev.id = LOC_X_DELTA;
237
                ev.time = xtime;
238
                ev.value = sunmouse.delta_x;
239
                push_event (&ev);
240
                sunmouse.delta_x = 0;
241
        }
242
        if (sunmouse.delta_y){
243
                ev.id = LOC_Y_DELTA;
244
                ev.time = xtime;
245
                ev.value = sunmouse.delta_y;
246
                push_event (&ev);
247
        }
248
 
249
        /* We just completed a transaction, wake up whoever is awaiting
250
         * this event.
251
         */
252
        sunmouse.ready = 1;
253
        if (sunmouse.fasync)
254
                kill_fasync (sunmouse.fasync, SIGIO);
255
        wake_up_interruptible(&sunmouse.proc_list);
256
        return;
257
}
258
 
259
static int
260
sun_mouse_open(struct inode * inode, struct file * file)
261
{
262
        if(!sunmouse.present)
263
                return -EINVAL;
264
        if(sunmouse.active)
265
                return -EBUSY;
266
        sunmouse.active = 1;
267
        sunmouse.ready = sunmouse.delta_x = sunmouse.delta_y = 0;
268
        sunmouse.button_state = 0x80;
269
        sunmouse.vuid_mode = VUID_NATIVE;
270
        return 0;
271
}
272
 
273
static int
274
sun_mouse_fasync (struct inode *inode, struct file *filp, int on)
275
{
276
        int retval;
277
 
278
        retval = fasync_helper (inode, filp, on, &sunmouse.fasync);
279
        if (retval < 0)
280
                return retval;
281
        return 0;
282
}
283
 
284
static void
285
sun_mouse_close(struct inode *inode, struct file *file)
286
{
287
        sunmouse.active = sunmouse.ready = 0;
288
        sun_mouse_fasync (inode, file, 0);
289
}
290
 
291
static int
292
sun_mouse_write(struct inode *inode, struct file *file, const char *buffer,
293
                int count)
294
{
295
        return -EINVAL;  /* foo on you */
296
}
297
 
298
static int
299
sun_mouse_read(struct inode *inode, struct file *file, char *buffer,
300
               int count)
301
{
302
        struct wait_queue wait = { current, NULL };
303
 
304
        if (queue_empty ()){
305
                if (file->f_flags & O_NONBLOCK)
306
                        return -EWOULDBLOCK;
307
                add_wait_queue (&sunmouse.proc_list, &wait);
308
                while (queue_empty () && !(current->signal & ~current->blocked)){
309
                        current->state = TASK_INTERRUPTIBLE;
310
                        schedule ();
311
                }
312
                current->state = TASK_RUNNING;
313
                remove_wait_queue (&sunmouse.proc_list, &wait);
314
        }
315
        if (gen_events){
316
                char *p = buffer, *end = buffer+count;
317
 
318
                while (p < end && !queue_empty ()){
319
                        *(Firm_event *)p = *get_from_queue ();
320
                        p += sizeof (Firm_event);
321
                }
322
                sunmouse.ready = !queue_empty ();
323
                inode->i_atime = CURRENT_TIME;
324
                return p-buffer;
325
        } else {
326
                int c;
327
 
328
                for (c = count; !queue_empty () && c; c--){
329
                        *buffer++ = sunmouse.queue.stream [sunmouse.tail];
330
                        sunmouse.tail = (sunmouse.tail + 1) % STREAM_SIZE;
331
                }
332
                sunmouse.ready = !queue_empty ();
333
                inode->i_atime = CURRENT_TIME;
334
                return count-c;
335
        }
336
        /* Only called if nothing was sent */
337
        if (current->signal & ~current->blocked)
338
                return -ERESTARTSYS;
339
        return 0;
340
}
341
 
342
static int
343
sun_mouse_select(struct inode *inode, struct file *file, int sel_type,
344
                            select_table *wait)
345
{
346
        if(sel_type != SEL_IN)
347
                return 0;
348
        if(sunmouse.ready)
349
                return 1;
350
        select_wait(&sunmouse.proc_list, wait);
351
        return 0;
352
}
353
int
354
sun_mouse_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
355
{
356
        int i;
357
 
358
        switch (cmd){
359
                /* VUIDGFORMAT - Get input device byte stream format */
360
        case _IOR('v', 2, int):
361
                i = verify_area (VERIFY_WRITE, (void *)arg, sizeof (int));
362
                if (i) return i;
363
                *(int *)arg = sunmouse.vuid_mode;
364
                break;
365
 
366
                /* VUIDSFORMAT - Set input device byte stream format*/
367
        case _IOW('v', 1, int):
368
                i = verify_area (VERIFY_READ, (void *)arg, sizeof (int));
369
                if (i) return i;
370
                i = *(int *) arg;
371
                if (i == VUID_NATIVE || i == VUID_FIRM_EVENT){
372
                        sunmouse.vuid_mode = *(int *)arg;
373
                        sunmouse.head = sunmouse.tail = 0;
374
                } else
375
                        return -EINVAL;
376
                break;
377
 
378
        default:
379
                printk ("[MOUSE-ioctl: %8.8x]\n", cmd);
380
                return -1;
381
        }
382
        return 0;
383
}
384
 
385
struct file_operations sun_mouse_fops = {
386
        NULL,
387
        sun_mouse_read,
388
        sun_mouse_write,
389
        NULL,
390
        sun_mouse_select,
391
        sun_mouse_ioctl,
392
        NULL,
393
        sun_mouse_open,
394
        sun_mouse_close,
395
        NULL,
396
        sun_mouse_fasync,
397
};
398
 
399
static struct miscdevice sun_mouse_mouse = {
400
        SUN_MOUSE_MINOR, "sunmouse", &sun_mouse_fops
401
};
402
 
403
int
404
sun_mouse_init(void)
405
{
406
        printk("Sun Mouse-Systems mouse driver version 1.00\n");
407
        sunmouse.present = 1;
408
        sunmouse.ready = sunmouse.active = 0;
409
        misc_register (&sun_mouse_mouse);
410
        sunmouse.delta_x = sunmouse.delta_y = 0;
411
        sunmouse.button_state = 0x80;
412
        sunmouse.proc_list = NULL;
413
        return 0;
414
}
415
 
416
void
417
sun_mouse_zsinit(void)
418
{
419
        sunmouse.ready = 1;
420
}

powered by: WebSVN 2.1.0

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