root/kernel/chr_drv/busmouse.c

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

DEFINITIONS

This source file includes following definitions.
  1. mouse_interrupt
  2. ms_mouse_interrupt
  3. release_mouse
  4. open_mouse
  5. write_mouse
  6. read_mouse
  7. mouse_select
  8. bus_mouse_init
  9. ms_bus_mouse_init

   1 /*
   2  * Logitech Bus Mouse Driver for Linux
   3  * by James Banks
   4  * 
   5  * Heavily modified by David Giller
   6  *   changed from queue- to counter- driven
   7  *   hacked out a (probably incorrect) mouse_select
   8  *
   9  * Modified again by Nathan Laredo to interface with
  10  *   0.96c-pl1 IRQ handling changes (13JUL92)
  11  *   didn't bother touching select code.
  12  *
  13  * Modified the select() code blindly to conform to the VFS
  14  *   requirements. 92.07.14 - Linus. Somebody should test it out.
  15  *
  16  * Modified by Johan Myreen to make room for other mice (9AUG92)
  17  *   removed assignment chr_fops[10] = &mouse_fops; see mouse.c
  18  *   renamed mouse_fops => bus_mouse_fops, made bus_mouse_fops public.
  19  *   renamed this file mouse.c => busmouse.c
  20  *
  21  * Microsoft BusMouse support by Teemu Rantanen (tvr@cs.hut.fi) (02AUG92)
  22  *
  23  * Microsoft Bus Mouse support modified by Derrick Cole (cole@concert.net)
  24  *    8/28/92
  25  *
  26  * Microsoft Bus Mouse support folded into 0.97pl4 code
  27  *    by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
  28  * Changes:  Logitech and Microsoft support in the same kernel.
  29  *           Defined new constants in busmouse.h for MS mice.
  30  *           Added int mse_busmouse_type to distinguish busmouse types
  31  *           Added a couple of new functions to handle differences in using
  32  *             MS vs. Logitech (where the int variable wasn't appropriate).
  33  *
  34  * version 0.2
  35  */
  36 
  37 #include        <linux/kernel.h>
  38 #include        <linux/sched.h>
  39 #include        <linux/busmouse.h>
  40 #include        <linux/tty.h>
  41 #include        <linux/signal.h>
  42 #include        <linux/errno.h>
  43 
  44 #include        <asm/io.h>
  45 #include        <asm/segment.h>
  46 #include        <asm/system.h>
  47 #include        <asm/irq.h>
  48 
  49 
  50 static struct mouse_status mouse;
  51 
  52 static void mouse_interrupt(int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54         char dx, dy, buttons;
  55 
  56         MSE_INT_OFF();
  57         
  58         outb(MSE_READ_X_LOW, MSE_CONTROL_PORT);
  59         dx = (inb(MSE_DATA_PORT) & 0xf);
  60         
  61         outb(MSE_READ_X_HIGH, MSE_CONTROL_PORT);
  62         dx |= (inb(MSE_DATA_PORT) & 0xf) << 4;
  63         
  64         outb(MSE_READ_Y_LOW, MSE_CONTROL_PORT );
  65         dy = (inb(MSE_DATA_PORT) & 0xf);
  66         
  67         outb(MSE_READ_Y_HIGH, MSE_CONTROL_PORT);
  68         buttons = inb(MSE_DATA_PORT);
  69 
  70         dy |= (buttons & 0xf) << 4;
  71         buttons = ((buttons >> 5) & 0x07);
  72 
  73         mouse.buttons = buttons;
  74         mouse.latch_buttons |= buttons;
  75         mouse.dx += dx;
  76         mouse.dy += dy;
  77         mouse.ready = 1;
  78         if (mouse.inode && mouse.inode->i_wait)
  79                  wake_up(&mouse.inode->i_wait);
  80         
  81         MSE_INT_ON();
  82         
  83 }
  84 
  85 /*  Use separate function for MS mice - keep both short & fast */
  86 static void ms_mouse_interrupt(int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
  87 {
  88         char dx, dy, buttons;
  89 
  90         outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT);
  91         outb((inb(MS_MSE_DATA_PORT) | 0x20), MS_MSE_DATA_PORT);
  92 
  93         outb(MS_MSE_READ_X, MS_MSE_CONTROL_PORT);
  94         dx = inb(MS_MSE_DATA_PORT);
  95 
  96         outb(MS_MSE_READ_Y, MS_MSE_CONTROL_PORT);
  97         dy = inb(MS_MSE_DATA_PORT);
  98 
  99         outb(MS_MSE_READ_BUTTONS, MS_MSE_CONTROL_PORT);
 100         buttons = ~(inb(MS_MSE_DATA_PORT)) & 0x07;
 101 
 102         outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT);
 103         outb((inb(MS_MSE_DATA_PORT) & 0xdf), MS_MSE_DATA_PORT);
 104 
 105         mouse.buttons = buttons;
 106         mouse.latch_buttons |= buttons;
 107         mouse.dx += dx;
 108         mouse.dy += dy;
 109         mouse.ready = 1;
 110         if (mouse.inode && mouse.inode->i_wait)
 111                  wake_up(&mouse.inode->i_wait);
 112         
 113 }
 114 
 115 static void release_mouse(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
 118           MSE_INT_OFF();
 119         } else if (mse_busmouse_type == MICROSOFT_BUSMOUSE) {
 120           MS_MSE_INT_OFF();
 121         } /* else if next mouse type, etc. */
 122 
 123         mouse.active = 0;
 124         mouse.ready = 0; 
 125         mouse.inode = NULL;
 126         free_irq(MOUSE_IRQ);
 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.active)
 132                 return -EBUSY;
 133         if (!mouse.present)
 134                 return -EINVAL;
 135         mouse.active = 1;
 136         mouse.ready = 0;
 137         mouse.inode = inode;
 138         mouse.dx = 0;
 139         mouse.dy = 0;   
 140         mouse.buttons = mouse.latch_buttons = 0x80;
 141 
 142         if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
 143           if (request_irq(MOUSE_IRQ, mouse_interrupt)) {
 144             /* once we get to here mouse is unused, IRQ is busy */
 145             mouse.active = 0;  /* it's not active, fix it */
 146             return -EBUSY;     /* IRQ is busy, so we're BUSY */
 147           } /* if we can't get the IRQ and mouse not active */
 148           MSE_INT_ON();
 149 
 150         } else if (mse_busmouse_type == MICROSOFT_BUSMOUSE) {
 151 
 152           if (request_irq(MOUSE_IRQ, ms_mouse_interrupt)) {
 153             /* once we get to here mouse is unused, IRQ is busy */
 154             mouse.active = 0;  /* it's not active, fix it */
 155             return -EBUSY;     /* IRQ is busy, so we're BUSY */
 156           } /* if we can't get the IRQ and mouse not active */
 157           outb(MS_MSE_START, MS_MSE_CONTROL_PORT);
 158           MS_MSE_INT_ON();      
 159 
 160         }
 161 
 162         return 0;
 163 }
 164 
 165 
 166 static int write_mouse(struct inode * inode, struct file * file, char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168         return -EINVAL;
 169 }
 170 
 171 static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         int i;
 174 
 175         if (count < 3) return -EINVAL;
 176         if (!mouse.ready) return -EAGAIN;
 177 
 178         if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
 179           MSE_INT_OFF();
 180         }
 181                 
 182         put_fs_byte(mouse.latch_buttons | 0x80, buffer);
 183         
 184         if (mouse.dx < -127) mouse.dx = -127;
 185         if (mouse.dx >  127) mouse.dx =  127;
 186         
 187         put_fs_byte((char)mouse.dx, buffer + 1);
 188         
 189         if (mouse.dy < -127) mouse.dy = -127;
 190         if (mouse.dy >  127) mouse.dy =  127;
 191         
 192         put_fs_byte((char) -mouse.dy, buffer + 2);
 193         
 194         for (i = 3; i < count; i++)
 195                 put_fs_byte(0x00, buffer + i);
 196                 
 197         mouse.dx = 0;
 198         mouse.dy = 0;
 199         mouse.latch_buttons = mouse.buttons;
 200         mouse.ready = 0;
 201         
 202         if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
 203           MSE_INT_ON();
 204         }
 205 
 206         return i;       
 207 }
 208 
 209 static int mouse_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211         if (sel_type != SEL_IN)
 212                 return 0;
 213         if (mouse.ready) 
 214                 return 1;
 215         select_wait(&inode->i_wait,wait);
 216         return 0;
 217 }
 218 
 219 struct file_operations bus_mouse_fops = {
 220         NULL,           /* mouse_seek */
 221         read_mouse,
 222         write_mouse,
 223         NULL,           /* mouse_readdir */
 224         mouse_select,   /* mouse_select */
 225         NULL,           /* mouse_ioctl */
 226         open_mouse,
 227         release_mouse,
 228 };
 229 
 230 long bus_mouse_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {       
 232         int i;
 233 
 234         outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT);
 235         outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT);
 236         
 237         for (i = 0; i < 100000; i++); /* busy loop */
 238         if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) {
 239                 printk("No Logitech bus mouse detected.\n");
 240                 mouse.present = 0;
 241                 return kmem_start;
 242         }
 243         outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT);
 244         
 245         MSE_INT_OFF();
 246         
 247         mouse.present = 1;
 248         mouse.active = 0;
 249         mouse.ready = 0;
 250         mouse.buttons = mouse.latch_buttons = 0x80;
 251         mouse.dx = 0;
 252         mouse.dy = 0;
 253         printk("Logitech Bus mouse detected and installed.\n");
 254         return kmem_start;
 255 }
 256 
 257 long ms_bus_mouse_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {       
 259         
 260         MS_MSE_INT_OFF();
 261         
 262         mouse.present = 1;
 263         mouse.active = mouse.ready = 0;
 264         mouse.buttons = mouse.latch_buttons = 0x80;
 265         mouse.dx = mouse.dy = 0;
 266         printk("Microsoft Bus mouse detected and installed.\n");
 267         return kmem_start;
 268 }

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