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. close_mouse
  4. open_mouse
  5. write_mouse
  6. read_mouse
  7. mouse_select
  8. bus_mouse_init

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

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