root/drivers/input/mouse/logibm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. logibm_interrupt
  2. logibm_open
  3. logibm_close
  4. logibm_init
  5. logibm_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Copyright (c) 1999-2001 Vojtech Pavlik
   4  *
   5  *  Based on the work of:
   6  *      James Banks             Matthew Dillon
   7  *      David Giller            Nathan Laredo
   8  *      Linus Torvalds          Johan Myreen
   9  *      Cliff Matthews          Philip Blundell
  10  *      Russell King
  11  */
  12 
  13 /*
  14  * Logitech Bus Mouse Driver for Linux
  15  */
  16 
  17 /*
  18  */
  19 
  20 #include <linux/module.h>
  21 #include <linux/delay.h>
  22 #include <linux/ioport.h>
  23 #include <linux/init.h>
  24 #include <linux/input.h>
  25 #include <linux/interrupt.h>
  26 
  27 #include <asm/io.h>
  28 #include <asm/irq.h>
  29 
  30 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
  31 MODULE_DESCRIPTION("Logitech busmouse driver");
  32 MODULE_LICENSE("GPL");
  33 
  34 #define LOGIBM_BASE             0x23c
  35 #define LOGIBM_EXTENT           4
  36 
  37 #define LOGIBM_DATA_PORT        LOGIBM_BASE + 0
  38 #define LOGIBM_SIGNATURE_PORT   LOGIBM_BASE + 1
  39 #define LOGIBM_CONTROL_PORT     LOGIBM_BASE + 2
  40 #define LOGIBM_CONFIG_PORT      LOGIBM_BASE + 3
  41 
  42 #define LOGIBM_ENABLE_IRQ       0x00
  43 #define LOGIBM_DISABLE_IRQ      0x10
  44 #define LOGIBM_READ_X_LOW       0x80
  45 #define LOGIBM_READ_X_HIGH      0xa0
  46 #define LOGIBM_READ_Y_LOW       0xc0
  47 #define LOGIBM_READ_Y_HIGH      0xe0
  48 
  49 #define LOGIBM_DEFAULT_MODE     0x90
  50 #define LOGIBM_CONFIG_BYTE      0x91
  51 #define LOGIBM_SIGNATURE_BYTE   0xa5
  52 
  53 #define LOGIBM_IRQ              5
  54 
  55 static int logibm_irq = LOGIBM_IRQ;
  56 module_param_hw_named(irq, logibm_irq, uint, irq, 0);
  57 MODULE_PARM_DESC(irq, "IRQ number (5=default)");
  58 
  59 static struct input_dev *logibm_dev;
  60 
  61 static irqreturn_t logibm_interrupt(int irq, void *dev_id)
  62 {
  63         char dx, dy;
  64         unsigned char buttons;
  65 
  66         outb(LOGIBM_READ_X_LOW, LOGIBM_CONTROL_PORT);
  67         dx = (inb(LOGIBM_DATA_PORT) & 0xf);
  68         outb(LOGIBM_READ_X_HIGH, LOGIBM_CONTROL_PORT);
  69         dx |= (inb(LOGIBM_DATA_PORT) & 0xf) << 4;
  70         outb(LOGIBM_READ_Y_LOW, LOGIBM_CONTROL_PORT);
  71         dy = (inb(LOGIBM_DATA_PORT) & 0xf);
  72         outb(LOGIBM_READ_Y_HIGH, LOGIBM_CONTROL_PORT);
  73         buttons = inb(LOGIBM_DATA_PORT);
  74         dy |= (buttons & 0xf) << 4;
  75         buttons = ~buttons >> 5;
  76 
  77         input_report_rel(logibm_dev, REL_X, dx);
  78         input_report_rel(logibm_dev, REL_Y, dy);
  79         input_report_key(logibm_dev, BTN_RIGHT,  buttons & 1);
  80         input_report_key(logibm_dev, BTN_MIDDLE, buttons & 2);
  81         input_report_key(logibm_dev, BTN_LEFT,   buttons & 4);
  82         input_sync(logibm_dev);
  83 
  84         outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
  85         return IRQ_HANDLED;
  86 }
  87 
  88 static int logibm_open(struct input_dev *dev)
  89 {
  90         if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
  91                 printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
  92                 return -EBUSY;
  93         }
  94         outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
  95         return 0;
  96 }
  97 
  98 static void logibm_close(struct input_dev *dev)
  99 {
 100         outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
 101         free_irq(logibm_irq, NULL);
 102 }
 103 
 104 static int __init logibm_init(void)
 105 {
 106         int err;
 107 
 108         if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
 109                 printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE);
 110                 return -EBUSY;
 111         }
 112 
 113         outb(LOGIBM_CONFIG_BYTE, LOGIBM_CONFIG_PORT);
 114         outb(LOGIBM_SIGNATURE_BYTE, LOGIBM_SIGNATURE_PORT);
 115         udelay(100);
 116 
 117         if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) {
 118                 printk(KERN_INFO "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
 119                 err = -ENODEV;
 120                 goto err_release_region;
 121         }
 122 
 123         outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
 124         outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
 125 
 126         logibm_dev = input_allocate_device();
 127         if (!logibm_dev) {
 128                 printk(KERN_ERR "logibm.c: Not enough memory for input device\n");
 129                 err = -ENOMEM;
 130                 goto err_release_region;
 131         }
 132 
 133         logibm_dev->name = "Logitech bus mouse";
 134         logibm_dev->phys = "isa023c/input0";
 135         logibm_dev->id.bustype = BUS_ISA;
 136         logibm_dev->id.vendor  = 0x0003;
 137         logibm_dev->id.product = 0x0001;
 138         logibm_dev->id.version = 0x0100;
 139 
 140         logibm_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
 141         logibm_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
 142                 BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
 143         logibm_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
 144 
 145         logibm_dev->open  = logibm_open;
 146         logibm_dev->close = logibm_close;
 147 
 148         err = input_register_device(logibm_dev);
 149         if (err)
 150                 goto err_free_dev;
 151 
 152         return 0;
 153 
 154  err_free_dev:
 155         input_free_device(logibm_dev);
 156  err_release_region:
 157         release_region(LOGIBM_BASE, LOGIBM_EXTENT);
 158 
 159         return err;
 160 }
 161 
 162 static void __exit logibm_exit(void)
 163 {
 164         input_unregister_device(logibm_dev);
 165         release_region(LOGIBM_BASE, LOGIBM_EXTENT);
 166 }
 167 
 168 module_init(logibm_init);
 169 module_exit(logibm_exit);

/* [<][>][^][v][top][bottom][index][help] */