linux/drivers/input/joystick/amijoy.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) 1998-2001 Vojtech Pavlik
   3 */
   4
   5/*
   6 * Driver for Amiga joysticks for Linux/m68k
   7 */
   8
   9/*
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2 of the License, or
  13 * (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23 *
  24 * Should you need to contact me, the author, you can do so either by
  25 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
  26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  27 */
  28
  29#include <linux/types.h>
  30#include <linux/errno.h>
  31#include <linux/kernel.h>
  32#include <linux/module.h>
  33#include <linux/init.h>
  34#include <linux/input.h>
  35#include <linux/interrupt.h>
  36#include <linux/mutex.h>
  37
  38#include <asm/amigahw.h>
  39#include <asm/amigaints.h>
  40
  41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
  42MODULE_DESCRIPTION("Driver for Amiga joysticks");
  43MODULE_LICENSE("GPL");
  44
  45static int amijoy[2] = { 0, 1 };
  46module_param_array_named(map, amijoy, uint, NULL, 0);
  47MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is 0,1)");
  48
  49static int amijoy_used;
  50static DEFINE_MUTEX(amijoy_mutex);
  51static struct input_dev *amijoy_dev[2];
  52static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
  53
  54static irqreturn_t amijoy_interrupt(int irq, void *dummy)
  55{
  56        int i, data = 0, button = 0;
  57
  58        for (i = 0; i < 2; i++)
  59                if (amijoy[i]) {
  60
  61                        switch (i) {
  62                                case 0: data = ~amiga_custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
  63                                case 1: data = ~amiga_custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
  64                        }
  65
  66                        input_report_key(amijoy_dev[i], BTN_TRIGGER, button);
  67
  68                        input_report_abs(amijoy_dev[i], ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
  69                        data = ~(data ^ (data << 1));
  70                        input_report_abs(amijoy_dev[i], ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
  71
  72                        input_sync(amijoy_dev[i]);
  73                }
  74        return IRQ_HANDLED;
  75}
  76
  77static int amijoy_open(struct input_dev *dev)
  78{
  79        int err;
  80
  81        err = mutex_lock_interruptible(&amijoy_mutex);
  82        if (err)
  83                return err;
  84
  85        if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) {
  86                printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
  87                err = -EBUSY;
  88                goto out;
  89        }
  90
  91        amijoy_used++;
  92out:
  93        mutex_unlock(&amijoy_mutex);
  94        return err;
  95}
  96
  97static void amijoy_close(struct input_dev *dev)
  98{
  99        mutex_lock(&amijoy_mutex);
 100        if (!--amijoy_used)
 101                free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
 102        mutex_unlock(&amijoy_mutex);
 103}
 104
 105static int __init amijoy_init(void)
 106{
 107        int i, j;
 108        int err;
 109
 110        if (!MACH_IS_AMIGA)
 111                return -ENODEV;
 112
 113        for (i = 0; i < 2; i++) {
 114                if (!amijoy[i])
 115                        continue;
 116
 117                amijoy_dev[i] = input_allocate_device();
 118                if (!amijoy_dev[i]) {
 119                        err = -ENOMEM;
 120                        goto fail;
 121                }
 122
 123                if (!request_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2, "amijoy [Denise]")) {
 124                        input_free_device(amijoy_dev[i]);
 125                        err = -EBUSY;
 126                        goto fail;
 127                }
 128
 129                amijoy_dev[i]->name = "Amiga joystick";
 130                amijoy_dev[i]->phys = amijoy_phys[i];
 131                amijoy_dev[i]->id.bustype = BUS_AMIGA;
 132                amijoy_dev[i]->id.vendor = 0x0001;
 133                amijoy_dev[i]->id.product = 0x0003;
 134                amijoy_dev[i]->id.version = 0x0100;
 135
 136                amijoy_dev[i]->open = amijoy_open;
 137                amijoy_dev[i]->close = amijoy_close;
 138
 139                amijoy_dev[i]->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 140                amijoy_dev[i]->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
 141                amijoy_dev[i]->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
 142                        BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
 143                for (j = 0; j < 2; j++) {
 144                        input_set_abs_params(amijoy_dev[i], ABS_X + j,
 145                                             -1, 1, 0, 0);
 146                }
 147
 148                err = input_register_device(amijoy_dev[i]);
 149                if (err) {
 150                        input_free_device(amijoy_dev[i]);
 151                        goto fail;
 152                }
 153        }
 154        return 0;
 155
 156 fail:  while (--i >= 0)
 157                if (amijoy[i]) {
 158                        input_unregister_device(amijoy_dev[i]);
 159                        release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
 160                }
 161        return err;
 162}
 163
 164static void __exit amijoy_exit(void)
 165{
 166        int i;
 167
 168        for (i = 0; i < 2; i++)
 169                if (amijoy[i]) {
 170                        input_unregister_device(amijoy_dev[i]);
 171                        release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
 172                }
 173}
 174
 175module_init(amijoy_init);
 176module_exit(amijoy_exit);
 177