Import 2.3.1pre2
[davej-history.git] / drivers / usb / mouse.c
blob59b93bd82f6c2369181d49a9944515ee6ac200ea
1 /*
2 * USB HID boot protocol mouse support based on MS BusMouse driver, psaux
3 * driver, and Linus's skeleton USB mouse driver. Fixed up a lot by Linus.
5 * Brad Keryan 4/3/1999
7 * version 0.20: Linus rewrote read_mouse() to do PS/2 and do it
8 * correctly. Events are added together, not queued, to keep the rodent sober.
10 * version 0.02: Hmm, the mouse seems drunk because I'm queueing the events.
11 * This is wrong: when an application (like X or gpm) reads the mouse device,
12 * it wants to find out the mouse's current position, not its recent history.
13 * The button thing turned out to be UHCI not flipping data toggle, so half the
14 * packets were thrown out.
16 * version 0.01: Switched over to busmouse protocol, and changed the minor
17 * number to 32 (same as uusbd's hidbp driver). Buttons work more sanely now,
18 * but it still doesn't generate button events unless you move the mouse.
20 * version 0.0: Driver emulates a PS/2 mouse, stealing /dev/psaux (sorry, I
21 * know that's not very nice). Moving in the X and Y axes works. Buttons don't
22 * work right yet: X sees a lot of MotionNotify/ButtonPress/ButtonRelease
23 * combos when you hold down a button and drag the mouse around. Probably has
24 * some additional bugs on an SMP machine.
27 #include <linux/kernel.h>
28 #include <linux/sched.h>
29 #include <linux/signal.h>
30 #include <linux/errno.h>
31 #include <linux/miscdevice.h>
32 #include <linux/random.h>
33 #include <linux/poll.h>
34 #include <linux/init.h>
35 #include <linux/malloc.h>
37 #include <asm/spinlock.h>
39 #include "usb.h"
41 #define USB_MOUSE_MINOR 32
43 struct mouse_state {
44 unsigned char buttons; /* current button state */
45 long dx; /* dx, dy, dz are change since last read */
46 long dy;
47 long dz;
48 int present; /* this mouse is plugged in */
49 int active; /* someone is has this mouse's device open */
50 int ready; /* the mouse has changed state since the last read */
51 wait_queue_head_t wait; /* for polling */
52 struct fasync_struct *fasync;
53 /* later, add a list here to support multiple mice */
54 /* but we will also need a list of file pointers to identify it */
57 static struct mouse_state static_mouse_state = {
58 0, 0, 0, 0,
59 0, 0, 0,
60 __WAIT_QUEUE_HEAD_INITIALIZER(static_mouse_state.wait),
63 spinlock_t usb_mouse_lock = SPIN_LOCK_UNLOCKED;
65 static int mouse_irq(int state, void *__buffer, void *dev_id)
67 signed char *data = __buffer;
68 /* finding the mouse is easy when there's only one */
69 struct mouse_state *mouse = &static_mouse_state;
71 /* if a mouse moves with no one listening, do we care? no */
72 if(!mouse->active)
73 return 1;
75 /* if the USB mouse sends an interrupt, then something noteworthy
76 must have happened */
77 mouse->buttons = data[0] & 0x07;
78 mouse->dx += data[1]; /* data[] is signed, so this works */
79 mouse->dy -= data[2]; /* y-axis is reversed */
80 mouse->dz += data[3];
81 mouse->ready = 1;
83 add_mouse_randomness((mouse->buttons << 24) + (mouse->dz << 16 ) +
84 (mouse->dy << 8) + mouse->dx);
86 wake_up_interruptible(&mouse->wait);
87 if (mouse->fasync)
88 kill_fasync(mouse->fasync, SIGIO);
90 return 1;
93 static int fasync_mouse(int fd, struct file *filp, int on)
95 int retval;
96 struct mouse_state *mouse = &static_mouse_state;
98 retval = fasync_helper(fd, filp, on, &mouse->fasync);
99 if (retval < 0)
100 return retval;
101 return 0;
104 static int release_mouse(struct inode * inode, struct file * file)
106 struct mouse_state *mouse = &static_mouse_state;
108 fasync_mouse(-1, file, 0);
109 if (--mouse->active)
110 return 0;
111 return 0;
114 static int open_mouse(struct inode * inode, struct file * file)
116 struct mouse_state *mouse = &static_mouse_state;
118 if (!mouse->present)
119 return -EINVAL;
120 if (mouse->active++)
121 return 0;
122 /* flush state */
123 mouse->buttons = mouse->dx = mouse->dy = mouse->dz = 0;
124 return 0;
127 static ssize_t write_mouse(struct file * file,
128 const char * buffer, size_t count, loff_t *ppos)
130 return -EINVAL;
134 * Look like a PS/2 mouse, please..
136 * The PS/2 protocol is fairly strange, but
137 * oh, well, it's at least common..
139 static ssize_t read_mouse(struct file * file, char * buffer, size_t count, loff_t *ppos)
141 int retval = 0;
142 static int state = 0;
143 struct mouse_state *mouse = &static_mouse_state;
145 if (count) {
146 mouse->ready = 0;
147 switch (state) {
148 case 0: { /* buttons and sign */
149 int buttons = mouse->buttons;
150 mouse->buttons = 0;
151 if (mouse->dx < 0)
152 buttons |= 0x10;
153 if (mouse->dy < 0)
154 buttons |= 0x20;
155 put_user(buttons, buffer);
156 buffer++;
157 retval++;
158 state = 1;
159 if (!--count)
160 break;
162 case 1: { /* dx */
163 int dx = mouse->dx;
164 mouse->dx = 0;
165 put_user(dx, buffer);
166 buffer++;
167 retval++;
168 state = 2;
169 if (!--count)
170 break;
172 case 2: { /* dy */
173 int dy = mouse->dy;
174 mouse->dy = 0;
175 put_user(dy, buffer);
176 buffer++;
177 retval++;
178 state = 0;
180 break;
183 return retval;
186 static unsigned int mouse_poll(struct file *file, poll_table * wait)
188 struct mouse_state *mouse = &static_mouse_state;
190 poll_wait(file, &mouse->wait, wait);
191 if (mouse->ready)
192 return POLLIN | POLLRDNORM;
193 return 0;
196 struct file_operations usb_mouse_fops = {
197 NULL, /* mouse_seek */
198 read_mouse,
199 write_mouse,
200 NULL, /* mouse_readdir */
201 mouse_poll, /* mouse_poll */
202 NULL, /* mouse_ioctl */
203 NULL, /* mouse_mmap */
204 open_mouse,
205 NULL, /* flush */
206 release_mouse,
207 NULL,
208 fasync_mouse,
211 static struct miscdevice usb_mouse = {
212 USB_MOUSE_MINOR, "USB mouse", &usb_mouse_fops
215 static int mouse_probe(struct usb_device *dev)
217 struct usb_interface_descriptor *interface;
218 struct usb_endpoint_descriptor *endpoint;
219 struct mouse_state *mouse = &static_mouse_state;
221 /* We don't handle multi-config mice */
222 if (dev->descriptor.bNumConfigurations != 1)
223 return -1;
225 /* We don't handle multi-interface mice */
226 if (dev->config[0].bNumInterfaces != 1)
227 return -1;
229 /* Is it a mouse interface? */
230 interface = &dev->config[0].interface[0];
231 if (interface->bInterfaceClass != 3)
232 return -1;
233 if (interface->bInterfaceSubClass != 1)
234 return -1;
235 if (interface->bInterfaceProtocol != 2)
236 return -1;
238 /* Multiple endpoints? What kind of mutant ninja-mouse is this? */
239 if (interface->bNumEndpoints != 1)
240 return -1;
242 endpoint = &interface->endpoint[0];
244 /* Output endpoint? Curiousier and curiousier.. */
245 if (!(endpoint->bEndpointAddress & 0x80))
246 return -1;
248 /* If it's not an interrupt endpoint, we'd better punt! */
249 if ((endpoint->bmAttributes & 3) != 3)
250 return -1;
252 printk("USB mouse found\n");
254 usb_set_configuration(dev, dev->config[0].bConfigurationValue);
256 usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), mouse_irq, endpoint->bInterval, NULL);
258 mouse->present = 1;
259 return 0;
262 static void mouse_disconnect(struct usb_device *dev)
264 struct mouse_state *mouse = &static_mouse_state;
266 /* this might need work */
267 mouse->present = 0;
270 static struct usb_driver mouse_driver = {
271 "mouse",
272 mouse_probe,
273 mouse_disconnect,
274 { NULL, NULL }
277 int usb_mouse_init(void)
279 struct mouse_state *mouse = &static_mouse_state;
281 misc_register(&usb_mouse);
283 mouse->present = mouse->active = 0;
284 mouse->wait = NULL;
285 mouse->fasync = NULL;
287 usb_register(&mouse_driver);
288 printk(KERN_INFO "USB HID boot protocol mouse registered.\n");
289 return 0;
292 void usb_mouse_cleanup(void)
294 /* this, too, probably needs work */
295 usb_deregister(&mouse_driver);
296 misc_deregister(&usb_mouse);