2 * Microsoft busmouse driver based on Logitech driver (see busmouse.c)
4 * Microsoft BusMouse support by Teemu Rantanen (tvr@cs.hut.fi) (02AUG92)
6 * Microsoft Bus Mouse support modified by Derrick Cole (cole@concert.net)
9 * Microsoft Bus Mouse support folded into 0.97pl4 code
10 * by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
11 * Changes: Logitech and Microsoft support in the same kernel.
12 * Defined new constants in busmouse.h for MS mice.
13 * Added int mse_busmouse_type to distinguish busmouse types
14 * Added a couple of new functions to handle differences in using
15 * MS vs. Logitech (where the int variable wasn't appropriate).
17 * Modified by Peter Cervasio (address above) (26SEP92)
18 * Changes: Included code to (properly?) detect when a Microsoft mouse is
19 * really attached to the machine. Don't know what this does to
20 * Logitech bus mice, but all it does is read ports.
22 * Modified by Christoph Niemann (niemann@rubdv15.etdv.ruhr-uni-bochum.de)
23 * Changes: Better interrupt-handler (like in busmouse.c).
24 * Some changes to reduce code-size.
25 * Changed detection code to use inb_p() instead of doing empty
28 * Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
33 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/ioport.h>
37 #include <linux/sched.h>
38 #include <linux/busmouse.h>
39 #include <linux/signal.h>
40 #include <linux/errno.h>
41 #include <linux/miscdevice.h>
42 #include <linux/random.h>
43 #include <linux/poll.h>
44 #include <linux/init.h>
47 #include <asm/uaccess.h>
48 #include <asm/system.h>
51 static struct mouse_status mouse
;
52 static int mouse_irq
= MOUSE_IRQ
;
54 __initfunc(void msmouse_setup(char *str
, int *ints
))
60 static void ms_mouse_interrupt(int irq
, void *dev_id
, struct pt_regs
* regs
)
63 unsigned char buttons
;
65 outb(MS_MSE_COMMAND_MODE
, MS_MSE_CONTROL_PORT
);
66 outb((inb(MS_MSE_DATA_PORT
) | 0x20), MS_MSE_DATA_PORT
);
68 outb(MS_MSE_READ_X
, MS_MSE_CONTROL_PORT
);
69 dx
= inb(MS_MSE_DATA_PORT
);
71 outb(MS_MSE_READ_Y
, MS_MSE_CONTROL_PORT
);
72 dy
= inb(MS_MSE_DATA_PORT
);
74 outb(MS_MSE_READ_BUTTONS
, MS_MSE_CONTROL_PORT
);
75 buttons
= ~(inb(MS_MSE_DATA_PORT
)) & 0x07;
77 outb(MS_MSE_COMMAND_MODE
, MS_MSE_CONTROL_PORT
);
78 outb((inb(MS_MSE_DATA_PORT
) & 0xdf), MS_MSE_DATA_PORT
);
80 if (dx
!= 0 || dy
!= 0 || buttons
!= mouse
.buttons
|| ((~buttons
) & 0x07)) {
81 add_mouse_randomness((buttons
<< 16) + (dy
<< 8) + dx
);
82 mouse
.buttons
= buttons
;
86 wake_up_interruptible(&mouse
.wait
);
88 kill_fasync(mouse
.fasyncptr
, SIGIO
);
92 static int fasync_mouse(int fd
, struct file
*filp
, int on
)
96 retval
= fasync_helper(fd
, filp
, on
, &mouse
.fasyncptr
);
102 static int release_mouse(struct inode
* inode
, struct file
* file
)
104 fasync_mouse(-1, file
, 0);
109 free_irq(mouse_irq
, NULL
);
114 static int open_mouse(struct inode
* inode
, struct file
* file
)
120 if (request_irq(mouse_irq
, ms_mouse_interrupt
, 0, "MS Busmouse", NULL
)) {
124 mouse
.ready
= mouse
.dx
= mouse
.dy
= 0;
125 mouse
.buttons
= 0x80;
126 outb(MS_MSE_START
, MS_MSE_CONTROL_PORT
);
132 static ssize_t
write_mouse(struct file
* file
,
133 const char * buffer
, size_t count
, loff_t
*ppos
)
138 static ssize_t
read_mouse(struct file
* file
,
139 char * buffer
, size_t count
, loff_t
*ppos
)
147 put_user(mouse
.buttons
| 0x80, buffer
);
148 dx
= mouse
.dx
< -127 ? -127 : mouse
.dx
> 127 ? 127 : mouse
.dx
;
149 dy
= mouse
.dy
< -127 ? 127 : mouse
.dy
> 127 ? -127 : -mouse
.dy
;
150 put_user((char)dx
, buffer
+ 1);
151 put_user((char)dy
, buffer
+ 2);
152 for (i
= 3; i
< count
; i
++)
153 put_user(0x00, buffer
+ i
);
160 static unsigned int mouse_poll(struct file
*file
, poll_table
* wait
)
162 poll_wait(file
, &mouse
.wait
, wait
);
164 return POLLIN
| POLLRDNORM
;
168 struct file_operations ms_bus_mouse_fops
= {
169 NULL
, /* mouse_seek */
172 NULL
, /* mouse_readdir */
173 mouse_poll
, /* mouse_poll */
174 NULL
, /* mouse_ioctl */
175 NULL
, /* mouse_mmap */
183 static struct miscdevice ms_bus_mouse
= {
184 MICROSOFT_BUSMOUSE
, "msbusmouse", &ms_bus_mouse_fops
187 __initfunc(int ms_bus_mouse_init(void))
191 mouse
.present
= mouse
.active
= mouse
.ready
= 0;
192 mouse
.buttons
= 0x80;
193 mouse
.dx
= mouse
.dy
= 0;
196 if (check_region(MS_MSE_CONTROL_PORT
, 0x04))
199 if (inb_p(MS_MSE_SIGNATURE_PORT
) == 0xde) {
201 mse_byte
= inb_p(MS_MSE_SIGNATURE_PORT
);
203 for (i
= 0; i
< 4; i
++) {
204 if (inb_p(MS_MSE_SIGNATURE_PORT
) == 0xde) {
205 if (inb_p(MS_MSE_SIGNATURE_PORT
) == mse_byte
)
213 if (mouse
.present
== 0)
216 request_region(MS_MSE_CONTROL_PORT
, 0x04, "MS Busmouse");
217 printk(KERN_INFO
"Microsoft BusMouse detected and installed.\n");
218 misc_register(&ms_bus_mouse
);
223 int init_module(void)
225 return ms_bus_mouse_init();
228 void cleanup_module(void)
230 misc_deregister(&ms_bus_mouse
);
231 release_region(MS_MSE_CONTROL_PORT
, 0x04);