amijoy.c 3.6 KB

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