Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) 1998-2001 Vojtech Pavlik
0004  */
0005 
0006 /*
0007  * Driver for Amiga joysticks for Linux/m68k
0008  */
0009 
0010 /*
0011  */
0012 
0013 #include <linux/types.h>
0014 #include <linux/errno.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/init.h>
0018 #include <linux/input.h>
0019 #include <linux/interrupt.h>
0020 #include <linux/mutex.h>
0021 
0022 #include <asm/amigahw.h>
0023 #include <asm/amigaints.h>
0024 
0025 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0026 MODULE_DESCRIPTION("Driver for Amiga joysticks");
0027 MODULE_LICENSE("GPL");
0028 
0029 static int amijoy[2] = { 0, 1 };
0030 module_param_array_named(map, amijoy, uint, NULL, 0);
0031 MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is 0,1)");
0032 
0033 static int amijoy_used;
0034 static DEFINE_MUTEX(amijoy_mutex);
0035 static struct input_dev *amijoy_dev[2];
0036 static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
0037 
0038 static irqreturn_t amijoy_interrupt(int irq, void *dummy)
0039 {
0040     int i, data = 0, button = 0;
0041 
0042     for (i = 0; i < 2; i++)
0043         if (amijoy[i]) {
0044 
0045             switch (i) {
0046                 case 0: data = ~amiga_custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
0047                 case 1: data = ~amiga_custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
0048             }
0049 
0050             input_report_key(amijoy_dev[i], BTN_TRIGGER, button);
0051 
0052             input_report_abs(amijoy_dev[i], ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
0053             data = ~(data ^ (data << 1));
0054             input_report_abs(amijoy_dev[i], ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
0055 
0056             input_sync(amijoy_dev[i]);
0057         }
0058     return IRQ_HANDLED;
0059 }
0060 
0061 static int amijoy_open(struct input_dev *dev)
0062 {
0063     int err;
0064 
0065     err = mutex_lock_interruptible(&amijoy_mutex);
0066     if (err)
0067         return err;
0068 
0069     if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) {
0070         printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
0071         err = -EBUSY;
0072         goto out;
0073     }
0074 
0075     amijoy_used++;
0076 out:
0077     mutex_unlock(&amijoy_mutex);
0078     return err;
0079 }
0080 
0081 static void amijoy_close(struct input_dev *dev)
0082 {
0083     mutex_lock(&amijoy_mutex);
0084     if (!--amijoy_used)
0085         free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
0086     mutex_unlock(&amijoy_mutex);
0087 }
0088 
0089 static int __init amijoy_init(void)
0090 {
0091     int i, j;
0092     int err;
0093 
0094     if (!MACH_IS_AMIGA)
0095         return -ENODEV;
0096 
0097     for (i = 0; i < 2; i++) {
0098         if (!amijoy[i])
0099             continue;
0100 
0101         amijoy_dev[i] = input_allocate_device();
0102         if (!amijoy_dev[i]) {
0103             err = -ENOMEM;
0104             goto fail;
0105         }
0106 
0107         if (!request_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2, "amijoy [Denise]")) {
0108             input_free_device(amijoy_dev[i]);
0109             err = -EBUSY;
0110             goto fail;
0111         }
0112 
0113         amijoy_dev[i]->name = "Amiga joystick";
0114         amijoy_dev[i]->phys = amijoy_phys[i];
0115         amijoy_dev[i]->id.bustype = BUS_AMIGA;
0116         amijoy_dev[i]->id.vendor = 0x0001;
0117         amijoy_dev[i]->id.product = 0x0003;
0118         amijoy_dev[i]->id.version = 0x0100;
0119 
0120         amijoy_dev[i]->open = amijoy_open;
0121         amijoy_dev[i]->close = amijoy_close;
0122 
0123         amijoy_dev[i]->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
0124         amijoy_dev[i]->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
0125         amijoy_dev[i]->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
0126             BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
0127         for (j = 0; j < 2; j++) {
0128             input_set_abs_params(amijoy_dev[i], ABS_X + j,
0129                          -1, 1, 0, 0);
0130         }
0131 
0132         err = input_register_device(amijoy_dev[i]);
0133         if (err) {
0134             input_free_device(amijoy_dev[i]);
0135             goto fail;
0136         }
0137     }
0138     return 0;
0139 
0140  fail:  while (--i >= 0)
0141         if (amijoy[i]) {
0142             input_unregister_device(amijoy_dev[i]);
0143             release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
0144         }
0145     return err;
0146 }
0147 
0148 static void __exit amijoy_exit(void)
0149 {
0150     int i;
0151 
0152     for (i = 0; i < 2; i++)
0153         if (amijoy[i]) {
0154             input_unregister_device(amijoy_dev[i]);
0155             release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
0156         }
0157 }
0158 
0159 module_init(amijoy_init);
0160 module_exit(amijoy_exit);