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

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