root/drivers/char/busmouse.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bmouse_setup
  2. mouse_interrupt
  3. fasync_mouse
  4. close_mouse
  5. open_mouse
  6. write_mouse
  7. read_mouse
  8. mouse_select
  9. bus_mouse_init
  10. init_module
  11. cleanup_module

   1 /*
   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 
  31 #include <linux/module.h>
  32 
  33 #include <linux/kernel.h>
  34 #include <linux/sched.h>
  35 #include <linux/busmouse.h>
  36 #include <linux/signal.h>
  37 #include <linux/errno.h>
  38 #include <linux/mm.h>
  39 #include <linux/mouse.h>
  40 #include <linux/random.h>
  41 
  42 #include <asm/io.h>
  43 #include <asm/segment.h>
  44 #include <asm/system.h>
  45 #include <asm/irq.h>
  46 
  47 static struct mouse_status mouse;
  48 static int mouse_irq = MOUSE_IRQ;
  49 
  50 void bmouse_setup(char *str, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52         if (ints[0] > 0)
  53                 mouse_irq=ints[1];
  54 }
  55 
  56 static void mouse_interrupt(int irq, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  57 {
  58         char dx, dy;
  59         unsigned char buttons;
  60 
  61         MSE_INT_OFF();
  62         outb(MSE_READ_X_LOW, MSE_CONTROL_PORT);
  63         dx = (inb(MSE_DATA_PORT) & 0xf);
  64         outb(MSE_READ_X_HIGH, MSE_CONTROL_PORT);
  65         dx |= (inb(MSE_DATA_PORT) & 0xf) << 4;
  66         outb(MSE_READ_Y_LOW, MSE_CONTROL_PORT );
  67         dy = (inb(MSE_DATA_PORT) & 0xf);
  68         outb(MSE_READ_Y_HIGH, MSE_CONTROL_PORT);
  69         buttons = inb(MSE_DATA_PORT);
  70         dy |= (buttons & 0xf) << 4;
  71         buttons = ((buttons >> 5) & 0x07);
  72         if (dx != 0 || dy != 0 || buttons != mouse.buttons) {
  73           add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
  74           mouse.buttons = buttons;
  75           mouse.dx += dx;
  76           mouse.dy -= dy;
  77           mouse.ready = 1;
  78           wake_up_interruptible(&mouse.wait);
  79 
  80           /*
  81            * keep dx/dy reasonable, but still able to track when X (or
  82            * whatever) must page or is busy (i.e. long waits between
  83            * reads)
  84            */
  85           if (mouse.dx < -2048)
  86               mouse.dx = -2048;
  87           if (mouse.dx >  2048)
  88               mouse.dx =  2048;
  89 
  90           if (mouse.dy < -2048)
  91               mouse.dy = -2048;
  92           if (mouse.dy >  2048)
  93               mouse.dy =  2048;
  94 
  95           if (mouse.fasyncptr)
  96               kill_fasync(mouse.fasyncptr, SIGIO);
  97         }
  98         MSE_INT_ON();
  99 }
 100 
 101 static int fasync_mouse(struct inode *inode, struct file *filp, int on)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103         int retval;
 104 
 105         retval = fasync_helper(inode, filp, on, &mouse.fasyncptr);
 106         if (retval < 0)
 107                 return retval;
 108         return 0;
 109 }
 110 
 111 /*
 112  * close access to the mouse
 113  */
 114 
 115 static void close_mouse(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         fasync_mouse(inode, file, 0);
 118         if (--mouse.active)
 119                 return;
 120         MSE_INT_OFF();
 121         free_irq(mouse_irq);
 122         MOD_DEC_USE_COUNT;
 123 }
 124 
 125 /*
 126  * open access to the mouse
 127  */
 128 
 129 static int open_mouse(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         if (!mouse.present)
 132                 return -EINVAL;
 133         if (mouse.active++)
 134                 return 0;
 135         if (request_irq(mouse_irq, mouse_interrupt, 0, "Busmouse")) {
 136                 mouse.active--;
 137                 return -EBUSY;
 138         }
 139         mouse.ready = 0;
 140         mouse.dx = 0;
 141         mouse.dy = 0;
 142         mouse.buttons = 0x87;
 143         MOD_INC_USE_COUNT;
 144         MSE_INT_ON();
 145         return 0;
 146 }
 147 
 148 /*
 149  * writes are disallowed
 150  */
 151 
 152 static int write_mouse(struct inode * inode, struct file * file, const char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 153 {
 154         return -EINVAL;
 155 }
 156 
 157 /*
 158  * read mouse data.  Currently never blocks.
 159  */
 160 
 161 static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163         int r;
 164         int dx;
 165         int dy;
 166         unsigned char buttons; 
 167 
 168         if (count < 3)
 169                 return -EINVAL;
 170         if ((r = verify_area(VERIFY_WRITE, buffer, count)))
 171                 return r;
 172         if (!mouse.ready)
 173                 return -EAGAIN;
 174 
 175         /*
 176          * Obtain the current mouse parameters and limit as appropriate for
 177          * the return data format.  Interrupts are only disabled while 
 178          * obtaining the parameters, NOT during the puts_fs_byte() calls,
 179          * so paging in put_user() does not effect mouse tracking.
 180          */
 181 
 182         MSE_INT_OFF();
 183         dx = mouse.dx;
 184         dy = mouse.dy;
 185         if (dx < -127)
 186             dx = -127;
 187         if (dx > 127)
 188             dx = 127;
 189         if (dy < -127)
 190             dy = -127;
 191         if (dy > 127)
 192             dy = 127;
 193         buttons = mouse.buttons;
 194         mouse.dx -= dx;
 195         mouse.dy -= dy;
 196         mouse.ready = 0;
 197         MSE_INT_ON();
 198 
 199         put_user(buttons | 0x80, buffer);
 200         put_user((char)dx, buffer + 1);
 201         put_user((char)dy, buffer + 2);
 202         for (r = 3; r < count; r++)
 203             put_user(0x00, buffer + r);
 204         return r;
 205 }
 206 
 207 /*
 208  * select for mouse input
 209  */
 210 static int mouse_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212         if (sel_type == SEL_IN) {
 213                 if (mouse.ready)
 214                         return 1;
 215                 select_wait(&mouse.wait, wait);
 216         }
 217         return 0;
 218 }
 219 
 220 struct file_operations bus_mouse_fops = {
 221         NULL,           /* mouse_seek */
 222         read_mouse,
 223         write_mouse,
 224         NULL,           /* mouse_readdir */
 225         mouse_select,   /* mouse_select */
 226         NULL,           /* mouse_ioctl */
 227         NULL,           /* mouse_mmap */
 228         open_mouse,
 229         close_mouse,
 230         NULL,
 231         fasync_mouse,
 232 };
 233 
 234 static struct mouse bus_mouse = {
 235         LOGITECH_BUSMOUSE, "busmouse", &bus_mouse_fops
 236 };
 237 
 238 int bus_mouse_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 239 {
 240         int i;
 241 
 242         outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT);
 243         outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT);
 244         for (i = 0; i < 100000; i++)
 245                 /* busy loop */;
 246         if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) {
 247                 mouse.present = 0;
 248                 return -EIO;
 249         }
 250         outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT);
 251         MSE_INT_OFF();
 252         mouse.present = 1;
 253         mouse.active = 0;
 254         mouse.ready = 0;
 255         mouse.buttons = 0x87;
 256         mouse.dx = 0;
 257         mouse.dy = 0;
 258         mouse.wait = NULL;
 259         printk("Logitech Bus mouse detected and installed with IRQ %d.\n",
 260                mouse_irq);
 261         mouse_register(&bus_mouse);
 262         return 0;
 263 }
 264 
 265 #ifdef MODULE
 266 
 267 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 268 {
 269         return bus_mouse_init();
 270 }
 271 
 272 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 273 {
 274         mouse_deregister(&bus_mouse);
 275 }
 276 #endif

/* [previous][next][first][last][top][bottom][index][help] */