amijoy.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 1998-2001 Vojtech Pavlik
  4. */
  5. /*
  6. * Driver for Amiga joysticks for Linux/m68k
  7. */
  8. /*
  9. */
  10. #include <linux/types.h>
  11. #include <linux/errno.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/init.h>
  15. #include <linux/input.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/mutex.h>
  18. #include <asm/amigahw.h>
  19. #include <asm/amigaints.h>
  20. MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
  21. MODULE_DESCRIPTION("Driver for Amiga joysticks");
  22. MODULE_LICENSE("GPL");
  23. static int amijoy[2] = { 0, 1 };
  24. module_param_array_named(map, amijoy, uint, NULL, 0);
  25. MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is 0,1)");
  26. static int amijoy_used;
  27. static DEFINE_MUTEX(amijoy_mutex);
  28. static struct input_dev *amijoy_dev[2];
  29. static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
  30. static irqreturn_t amijoy_interrupt(int irq, void *dummy)
  31. {
  32. int i, data = 0, button = 0;
  33. for (i = 0; i < 2; i++)
  34. if (amijoy[i]) {
  35. switch (i) {
  36. case 0: data = ~amiga_custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
  37. case 1: data = ~amiga_custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
  38. }
  39. input_report_key(amijoy_dev[i], BTN_TRIGGER, button);
  40. input_report_abs(amijoy_dev[i], ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
  41. data = ~(data ^ (data << 1));
  42. input_report_abs(amijoy_dev[i], ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
  43. input_sync(amijoy_dev[i]);
  44. }
  45. return IRQ_HANDLED;
  46. }
  47. static int amijoy_open(struct input_dev *dev)
  48. {
  49. int err;
  50. err = mutex_lock_interruptible(&amijoy_mutex);
  51. if (err)
  52. return err;
  53. if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) {
  54. printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
  55. err = -EBUSY;
  56. goto out;
  57. }
  58. amijoy_used++;
  59. out:
  60. mutex_unlock(&amijoy_mutex);
  61. return err;
  62. }
  63. static void amijoy_close(struct input_dev *dev)
  64. {
  65. mutex_lock(&amijoy_mutex);
  66. if (!--amijoy_used)
  67. free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
  68. mutex_unlock(&amijoy_mutex);
  69. }
  70. static int __init amijoy_init(void)
  71. {
  72. int i, j;
  73. int err;
  74. if (!MACH_IS_AMIGA)
  75. return -ENODEV;
  76. for (i = 0; i < 2; i++) {
  77. if (!amijoy[i])
  78. continue;
  79. amijoy_dev[i] = input_allocate_device();
  80. if (!amijoy_dev[i]) {
  81. err = -ENOMEM;
  82. goto fail;
  83. }
  84. if (!request_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2, "amijoy [Denise]")) {
  85. input_free_device(amijoy_dev[i]);
  86. err = -EBUSY;
  87. goto fail;
  88. }
  89. amijoy_dev[i]->name = "Amiga joystick";
  90. amijoy_dev[i]->phys = amijoy_phys[i];
  91. amijoy_dev[i]->id.bustype = BUS_AMIGA;
  92. amijoy_dev[i]->id.vendor = 0x0001;
  93. amijoy_dev[i]->id.product = 0x0003;
  94. amijoy_dev[i]->id.version = 0x0100;
  95. amijoy_dev[i]->open = amijoy_open;
  96. amijoy_dev[i]->close = amijoy_close;
  97. amijoy_dev[i]->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
  98. amijoy_dev[i]->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
  99. amijoy_dev[i]->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
  100. BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
  101. for (j = 0; j < 2; j++) {
  102. input_set_abs_params(amijoy_dev[i], ABS_X + j,
  103. -1, 1, 0, 0);
  104. }
  105. err = input_register_device(amijoy_dev[i]);
  106. if (err) {
  107. input_free_device(amijoy_dev[i]);
  108. goto fail;
  109. }
  110. }
  111. return 0;
  112. fail: while (--i >= 0)
  113. if (amijoy[i]) {
  114. input_unregister_device(amijoy_dev[i]);
  115. release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
  116. }
  117. return err;
  118. }
  119. static void __exit amijoy_exit(void)
  120. {
  121. int i;
  122. for (i = 0; i < 2; i++)
  123. if (amijoy[i]) {
  124. input_unregister_device(amijoy_dev[i]);
  125. release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
  126. }
  127. }
  128. module_init(amijoy_init);
  129. module_exit(amijoy_exit);