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  * Modified by Peter Cervasio (address above) (26SEP92)
  35  * Changes:  Included code to (properly?) detect when a Microsoft mouse is
  36  *           really attached to the machine.  Don't know what this does to
  37  *           Logitech bus mice, but all it does is read ports.
  38  *
  39  * version 0.3
  40  */
  41 
  42 #include        <linux/kernel.h>
  43 #include        <linux/sched.h>
  44 #include        <linux/busmouse.h>
  45 #include        <linux/tty.h>
  46 #include        <linux/signal.h>
  47 #include        <linux/errno.h>
  48 
  49 #include        <asm/io.h>
  50 #include        <asm/segment.h>
  51 #include        <asm/system.h>
  52 #include        <asm/irq.h>
  53 
  54 
  55 static struct mouse_status mouse;
  56 
  57 static void mouse_interrupt(int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59         char dx, dy, buttons;
  60 
  61         MSE_INT_OFF();
  62         
  63         outb(MSE_READ_X_LOW, MSE_CONTROL_PORT);
  64         dx = (inb(MSE_DATA_PORT) & 0xf);
  65         
  66         outb(MSE_READ_X_HIGH, MSE_CONTROL_PORT);
  67         dx |= (inb(MSE_DATA_PORT) & 0xf) << 4;
  68         
  69         outb(MSE_READ_Y_LOW, MSE_CONTROL_PORT );
  70         dy = (inb(MSE_DATA_PORT) & 0xf);
  71         
  72         outb(MSE_READ_Y_HIGH, MSE_CONTROL_PORT);
  73         buttons = inb(MSE_DATA_PORT);
  74 
  75         dy |= (buttons & 0xf) << 4;
  76         buttons = ((buttons >> 5) & 0x07);
  77 
  78         mouse.buttons = buttons;
  79         mouse.latch_buttons |= buttons;
  80         mouse.dx += dx;
  81         mouse.dy += dy;
  82         mouse.ready = 1;
  83         if (mouse.inode && mouse.inode->i_wait)
  84                  wake_up(&mouse.inode->i_wait);
  85         
  86         MSE_INT_ON();
  87         
  88 }
  89 
  90 /*  Use separate function for MS mice - keep both short & fast */
  91 static void ms_mouse_interrupt(int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
  92 {
  93         char dx, dy, buttons;
  94 
  95         outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT);
  96         outb((inb(MS_MSE_DATA_PORT) | 0x20), MS_MSE_DATA_PORT);
  97 
  98         outb(MS_MSE_READ_X, MS_MSE_CONTROL_PORT);
  99         dx = inb(MS_MSE_DATA_PORT);
 100 
 101         outb(MS_MSE_READ_Y, MS_MSE_CONTROL_PORT);
 102         dy = inb(MS_MSE_DATA_PORT);
 103 
 104         outb(MS_MSE_READ_BUTTONS, MS_MSE_CONTROL_PORT);
 105         buttons = ~(inb(MS_MSE_DATA_PORT)) & 0x07;
 106 
 107         outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT);
 108         outb((inb(MS_MSE_DATA_PORT) & 0xdf), MS_MSE_DATA_PORT);
 109 
 110         mouse.buttons = buttons;
 111         mouse.latch_buttons |= buttons;
 112         mouse.dx += dx;
 113         mouse.dy += dy;
 114         mouse.ready = 1;
 115         if (mouse.inode && mouse.inode->i_wait)
 116                  wake_up(&mouse.inode->i_wait);
 117         
 118 }
 119 
 120 static void release_mouse(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122         if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
 123           MSE_INT_OFF();
 124         } else if (mse_busmouse_type == MICROSOFT_BUSMOUSE) {
 125           MS_MSE_INT_OFF();
 126         } /* else if next mouse type, etc. */
 127 
 128         mouse.active = 0;
 129         mouse.ready = 0; 
 130         mouse.inode = NULL;
 131         free_irq(MOUSE_IRQ);
 132 }
 133 
 134 static int open_mouse(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136         if (mouse.active)
 137                 return -EBUSY;
 138         if (!mouse.present)
 139                 return -EINVAL;
 140         mouse.active = 1;
 141         mouse.ready = 0;
 142         mouse.inode = inode;
 143         mouse.dx = 0;
 144         mouse.dy = 0;   
 145         mouse.buttons = mouse.latch_buttons = 0x80;
 146 
 147         if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
 148           if (request_irq(MOUSE_IRQ, mouse_interrupt)) {
 149             /* once we get to here mouse is unused, IRQ is busy */
 150             mouse.active = 0;  /* it's not active, fix it */
 151             return -EBUSY;     /* IRQ is busy, so we're BUSY */
 152           } /* if we can't get the IRQ and mouse not active */
 153           MSE_INT_ON();
 154 
 155         } else if (mse_busmouse_type == MICROSOFT_BUSMOUSE) {
 156 
 157           if (request_irq(MOUSE_IRQ, ms_mouse_interrupt)) {
 158             /* once we get to here mouse is unused, IRQ is busy */
 159             mouse.active = 0;  /* it's not active, fix it */
 160             return -EBUSY;     /* IRQ is busy, so we're BUSY */
 161           } /* if we can't get the IRQ and mouse not active */
 162           outb(MS_MSE_START, MS_MSE_CONTROL_PORT);
 163           MS_MSE_INT_ON();      
 164 
 165         }
 166 
 167         return 0;
 168 }
 169 
 170 
 171 static int write_mouse(struct inode * inode, struct file * file, char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         return -EINVAL;
 174 }
 175 
 176 static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 177 {
 178         int i;
 179 
 180         if (count < 3) return -EINVAL;
 181         if (!mouse.ready) return -EAGAIN;
 182 
 183         if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
 184           MSE_INT_OFF();
 185         }
 186                 
 187         put_fs_byte(mouse.latch_buttons | 0x80, buffer);
 188         
 189         if (mouse.dx < -127) mouse.dx = -127;
 190         if (mouse.dx >  127) mouse.dx =  127;
 191         
 192         put_fs_byte((char)mouse.dx, buffer + 1);
 193         
 194         if (mouse.dy < -127) mouse.dy = -127;
 195         if (mouse.dy >  127) mouse.dy =  127;
 196         
 197         put_fs_byte((char) -mouse.dy, buffer + 2);
 198         
 199         for (i = 3; i < count; i++)
 200                 put_fs_byte(0x00, buffer + i);
 201                 
 202         mouse.dx = 0;
 203         mouse.dy = 0;
 204         mouse.latch_buttons = mouse.buttons;
 205         mouse.ready = 0;
 206         
 207         if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
 208           MSE_INT_ON();
 209         }
 210 
 211         return i;       
 212 }
 213 
 214 static int mouse_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 215 {
 216         if (sel_type != SEL_IN)
 217                 return 0;
 218         if (mouse.ready) 
 219                 return 1;
 220         select_wait(&inode->i_wait,wait);
 221         return 0;
 222 }
 223 
 224 struct file_operations bus_mouse_fops = {
 225         NULL,           /* mouse_seek */
 226         read_mouse,
 227         write_mouse,
 228         NULL,           /* mouse_readdir */
 229         mouse_select,   /* mouse_select */
 230         NULL,           /* mouse_ioctl */
 231         open_mouse,
 232         release_mouse,
 233 };
 234 
 235 long bus_mouse_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 236 {       
 237         int i;
 238 
 239         outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT);
 240         outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT);
 241         
 242         for (i = 0; i < 100000; i++); /* busy loop */
 243         if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) {
 244                 printk("No Logitech bus mouse detected.\n");
 245                 mouse.present = 0;
 246                 return kmem_start;
 247         }
 248         outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT);
 249         
 250         MSE_INT_OFF();
 251         
 252         mouse.present = 1;
 253         mouse.active = 0;
 254         mouse.ready = 0;
 255         mouse.buttons = mouse.latch_buttons = 0x80;
 256         mouse.dx = 0;
 257         mouse.dy = 0;
 258         printk("Logitech Bus mouse detected and installed.\n");
 259         return kmem_start;
 260 }
 261 
 262 #define MS_DELAY 100000
 263 
 264 long ms_bus_mouse_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 265 {
 266         register int mse_byte;
 267         int i, delay_val, msfound = 1;
 268 
 269         if (inb(MS_MSE_SIGNATURE_PORT) == 0xde) {
 270             for (delay_val=0; delay_val<MS_DELAY;) delay_val++;
 271 
 272             mse_byte = inb(MS_MSE_SIGNATURE_PORT);
 273             for (delay_val=0; delay_val<MS_DELAY; ) delay_val++;
 274 
 275             for (i = 0; i < 4; i++) {
 276                 for (delay_val=0; delay_val<MS_DELAY;) delay_val++;
 277                 if (inb(MS_MSE_SIGNATURE_PORT) == 0xde) {
 278 
 279                     for (delay_val=0; delay_val<MS_DELAY; ) delay_val++;
 280                     if (inb(MS_MSE_SIGNATURE_PORT) == mse_byte)
 281                         msfound = 0;
 282                     else
 283                         msfound = 1;
 284                 }
 285                 else
 286                     msfound = 1;
 287             }
 288         }
 289 
 290         if (msfound == 1) {
 291             printk("No Microsoft bus mouse detected.\n");
 292             mouse.present = 0;
 293             return kmem_start;
 294         }
 295 
 296         MS_MSE_INT_OFF();
 297         
 298         mouse.present = 1;
 299         mouse.active = mouse.ready = 0;
 300         mouse.buttons = mouse.latch_buttons = 0x80;
 301         mouse.dx = mouse.dy = 0;
 302         printk("Microsoft Bus mouse detected and installed.\n");
 303         return kmem_start;
 304 }

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