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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [char/] [busmouse.c] - Blame information for rev 199

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

Line No. Rev Author Line
1 199 simons
/*
2
 * Logitech Bus Mouse Driver for Linux
3
 * by James Banks
4
 *
5
 * Mods by Matthew Dillon
6
 *   calls verify_area()
7
 *   tracks better when X is busy or paging
8
 *
9
 * Heavily modified by David Giller
10
 *   changed from queue- to counter- driven
11
 *   hacked out a (probably incorrect) mouse_select
12
 *
13
 * Modified again by Nathan Laredo to interface with
14
 *   0.96c-pl1 IRQ handling changes (13JUL92)
15
 *   didn't bother touching select code.
16
 *
17
 * Modified the select() code blindly to conform to the VFS
18
 *   requirements. 92.07.14 - Linus. Somebody should test it out.
19
 *
20
 * Modified by Johan Myreen to make room for other mice (9AUG92)
21
 *   removed assignment chr_fops[10] = &mouse_fops; see mouse.c
22
 *   renamed mouse_fops => bus_mouse_fops, made bus_mouse_fops public.
23
 *   renamed this file mouse.c => busmouse.c
24
 *
25
 * Minor addition by Cliff Matthews
26
 *   added fasync support
27
 *
28
 * Modularised 6-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
29
 *
30
 * Replaced dumb busy loop with udelay()  16 Nov 95
31
 *   Nathan Laredo <laredo@gnu.ai.mit.edu>
32
 *
33
 * Track I/O ports with request_region().  12 Dec 95 Philip Blundell
34
 */
35
 
36
#include <linux/module.h>
37
 
38
#include <linux/kernel.h>
39
#include <linux/sched.h>
40
#include <linux/busmouse.h>
41
#include <linux/signal.h>
42
#include <linux/errno.h>
43
#include <linux/mm.h>
44
#include <linux/miscdevice.h>
45
#include <linux/random.h>
46
#include <linux/delay.h>
47
#include <linux/ioport.h>
48
 
49
#include <asm/io.h>
50
#include <asm/segment.h>
51
#include <asm/system.h>
52
#include <asm/irq.h>
53
 
54
static struct mouse_status mouse;
55
static int mouse_irq = MOUSE_IRQ;
56
 
57
void bmouse_setup(char *str, int *ints)
58
{
59
        if (ints[0] > 0)
60
                mouse_irq=ints[1];
61
}
62
 
63
static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
64
{
65
        char dx, dy;
66
        unsigned char buttons;
67
 
68
        outb(MSE_READ_X_LOW, MSE_CONTROL_PORT);
69
        dx = (inb(MSE_DATA_PORT) & 0xf);
70
        outb(MSE_READ_X_HIGH, MSE_CONTROL_PORT);
71
        dx |= (inb(MSE_DATA_PORT) & 0xf) << 4;
72
        outb(MSE_READ_Y_LOW, MSE_CONTROL_PORT );
73
        dy = (inb(MSE_DATA_PORT) & 0xf);
74
        outb(MSE_READ_Y_HIGH, MSE_CONTROL_PORT);
75
        buttons = inb(MSE_DATA_PORT);
76
        dy |= (buttons & 0xf) << 4;
77
        buttons = ((buttons >> 5) & 0x07);
78
        if (dx != 0 || dy != 0 || buttons != mouse.buttons) {
79
          add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
80
          mouse.buttons = buttons;
81
          mouse.dx += dx;
82
          mouse.dy -= dy;
83
          mouse.ready = 1;
84
          wake_up_interruptible(&mouse.wait);
85
 
86
          /*
87
           * keep dx/dy reasonable, but still able to track when X (or
88
           * whatever) must page or is busy (i.e. long waits between
89
           * reads)
90
           */
91
          if (mouse.dx < -2048)
92
              mouse.dx = -2048;
93
          if (mouse.dx >  2048)
94
              mouse.dx =  2048;
95
 
96
          if (mouse.dy < -2048)
97
              mouse.dy = -2048;
98
          if (mouse.dy >  2048)
99
              mouse.dy =  2048;
100
 
101
          if (mouse.fasyncptr)
102
              kill_fasync(mouse.fasyncptr, SIGIO);
103
        }
104
        MSE_INT_ON();
105
}
106
 
107
static int fasync_mouse(struct inode *inode, struct file *filp, int on)
108
{
109
        int retval;
110
 
111
        retval = fasync_helper(inode, filp, on, &mouse.fasyncptr);
112
        if (retval < 0)
113
                return retval;
114
        return 0;
115
}
116
 
117
/*
118
 * close access to the mouse
119
 */
120
 
121
static void close_mouse(struct inode * inode, struct file * file)
122
{
123
        fasync_mouse(inode, file, 0);
124
        if (--mouse.active)
125
                return;
126
        MSE_INT_OFF();
127
        free_irq(mouse_irq, NULL);
128
        MOD_DEC_USE_COUNT;
129
}
130
 
131
/*
132
 * open access to the mouse
133
 */
134
 
135
static int open_mouse(struct inode * inode, struct file * file)
136
{
137
        if (!mouse.present)
138
                return -EINVAL;
139
        if (mouse.active++)
140
                return 0;
141
        if (request_irq(mouse_irq, mouse_interrupt, 0, "busmouse", NULL)) {
142
                mouse.active--;
143
                return -EBUSY;
144
        }
145
        mouse.ready = 0;
146
        mouse.dx = 0;
147
        mouse.dy = 0;
148
        mouse.buttons = 0x87;
149
        MOD_INC_USE_COUNT;
150
        MSE_INT_ON();
151
        return 0;
152
}
153
 
154
/*
155
 * writes are disallowed
156
 */
157
 
158
static int write_mouse(struct inode * inode, struct file * file, const char * buffer, int count)
159
{
160
        return -EINVAL;
161
}
162
 
163
/*
164
 * read mouse data.  Currently never blocks.
165
 */
166
 
167
static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count)
168
{
169
        int r;
170
        int dx;
171
        int dy;
172
        unsigned char buttons;
173
        /* long flags; */
174
 
175
        if (count < 3)
176
                return -EINVAL;
177
        if ((r = verify_area(VERIFY_WRITE, buffer, count)))
178
                return r;
179
        if (!mouse.ready)
180
                return -EAGAIN;
181
 
182
        /*
183
         * Obtain the current mouse parameters and limit as appropriate for
184
         * the return data format.  Interrupts are only disabled while
185
         * obtaining the parameters, NOT during the puts_fs_byte() calls,
186
         * so paging in put_user() does not effect mouse tracking.
187
         */
188
 
189
        /* save_flags(flags); cli(); */
190
        disable_irq(mouse_irq);
191
        dx = mouse.dx;
192
        dy = mouse.dy;
193
        if (dx < -127)
194
            dx = -127;
195
        if (dx > 127)
196
            dx = 127;
197
        if (dy < -127)
198
            dy = -127;
199
        if (dy > 127)
200
            dy = 127;
201
        buttons = mouse.buttons;
202
        mouse.dx -= dx;
203
        mouse.dy -= dy;
204
        mouse.ready = 0;
205
        enable_irq(mouse_irq);
206
        /* restore_flags(flags); */
207
 
208
        put_user(buttons | 0x80, buffer);
209
        put_user((char)dx, buffer + 1);
210
        put_user((char)dy, buffer + 2);
211
        for (r = 3; r < count; r++)
212
            put_user(0x00, buffer + r);
213
        return r;
214
}
215
 
216
/*
217
 * select for mouse input
218
 */
219
static int mouse_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
220
{
221
        if (sel_type == SEL_IN) {
222
                if (mouse.ready)
223
                        return 1;
224
                select_wait(&mouse.wait, wait);
225
        }
226
        return 0;
227
}
228
 
229
struct file_operations bus_mouse_fops = {
230
        NULL,           /* mouse_seek */
231
        read_mouse,
232
        write_mouse,
233
        NULL,           /* mouse_readdir */
234
        mouse_select,   /* mouse_select */
235
        NULL,           /* mouse_ioctl */
236
        NULL,           /* mouse_mmap */
237
        open_mouse,
238
        close_mouse,
239
        NULL,
240
        fasync_mouse,
241
};
242
 
243
static struct miscdevice bus_mouse = {
244
        LOGITECH_BUSMOUSE, "busmouse", &bus_mouse_fops
245
};
246
 
247
int bus_mouse_init(void)
248
{
249
        if (check_region(LOGIBM_BASE, LOGIBM_EXTENT)) {
250
          mouse.present = 0;
251
          return -EIO;
252
        }
253
 
254
        outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT);
255
        outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT);
256
        udelay(100L);   /* wait for reply from mouse */
257
        if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) {
258
                mouse.present = 0;
259
                return -EIO;
260
        }
261
        outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT);
262
        MSE_INT_OFF();
263
 
264
        request_region(LOGIBM_BASE, LOGIBM_EXTENT, "busmouse");
265
 
266
        mouse.present = 1;
267
        mouse.active = 0;
268
        mouse.ready = 0;
269
        mouse.buttons = 0x87;
270
        mouse.dx = 0;
271
        mouse.dy = 0;
272
        mouse.wait = NULL;
273
        printk(KERN_INFO "Logitech bus mouse detected, using IRQ %d.\n",
274
               mouse_irq);
275
        misc_register(&bus_mouse);
276
        return 0;
277
}
278
 
279
#ifdef MODULE
280
 
281
int init_module(void)
282
{
283
        return bus_mouse_init();
284
}
285
 
286
void cleanup_module(void)
287
{
288
        misc_deregister(&bus_mouse);
289
        release_region(LOGIBM_BASE, LOGIBM_EXTENT);
290
}
291
#endif

powered by: WebSVN 2.1.0

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