1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Amiga mouse driver for Linux/m68k 4 * 5 * Copyright (c) 2000-2002 Vojtech Pavlik 6 * 7 * Based on the work of: 8 * Michael Rausch James Banks 9 * Matther Dillon David Giller 10 * Nathan Laredo Linus Torvalds 11 * Johan Myreen Jes Sorensen 12 * Russell King 13 */ 14 15 16 #include <linux/module.h> 17 #include <linux/init.h> 18 #include <linux/input.h> 19 #include <linux/interrupt.h> 20 #include <linux/platform_device.h> 21 22 #include <asm/irq.h> 23 #include <asm/setup.h> 24 #include <linux/uaccess.h> 25 #include <asm/amigahw.h> 26 #include <asm/amigaints.h> 27 28 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 29 MODULE_DESCRIPTION("Amiga mouse driver"); 30 MODULE_LICENSE("GPL"); 31 32 static int amimouse_lastx, amimouse_lasty; 33 34 static irqreturn_t amimouse_interrupt(int irq, void *data) 35 { 36 struct input_dev *dev = data; 37 unsigned short joy0dat, potgor; 38 int nx, ny, dx, dy; 39 40 joy0dat = amiga_custom.joy0dat; 41 42 nx = joy0dat & 0xff; 43 ny = joy0dat >> 8; 44 45 dx = nx - amimouse_lastx; 46 dy = ny - amimouse_lasty; 47 48 if (dx < -127) dx = (256 + nx) - amimouse_lastx; 49 if (dx > 127) dx = (nx - 256) - amimouse_lastx; 50 if (dy < -127) dy = (256 + ny) - amimouse_lasty; 51 if (dy > 127) dy = (ny - 256) - amimouse_lasty; 52 53 amimouse_lastx = nx; 54 amimouse_lasty = ny; 55 56 potgor = amiga_custom.potgor; 57 58 input_report_rel(dev, REL_X, dx); 59 input_report_rel(dev, REL_Y, dy); 60 61 input_report_key(dev, BTN_LEFT, ciaa.pra & 0x40); 62 input_report_key(dev, BTN_MIDDLE, potgor & 0x0100); 63 input_report_key(dev, BTN_RIGHT, potgor & 0x0400); 64 65 input_sync(dev); 66 67 return IRQ_HANDLED; 68 } 69 70 static int amimouse_open(struct input_dev *dev) 71 { 72 unsigned short joy0dat; 73 int error; 74 75 joy0dat = amiga_custom.joy0dat; 76 77 amimouse_lastx = joy0dat & 0xff; 78 amimouse_lasty = joy0dat >> 8; 79 80 error = request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", 81 dev); 82 if (error) 83 dev_err(&dev->dev, "Can't allocate irq %d\n", IRQ_AMIGA_VERTB); 84 85 return error; 86 } 87 88 static void amimouse_close(struct input_dev *dev) 89 { 90 free_irq(IRQ_AMIGA_VERTB, dev); 91 } 92 93 static int __init amimouse_probe(struct platform_device *pdev) 94 { 95 int err; 96 struct input_dev *dev; 97 98 dev = input_allocate_device(); 99 if (!dev) 100 return -ENOMEM; 101 102 dev->name = pdev->name; 103 dev->phys = "amimouse/input0"; 104 dev->id.bustype = BUS_AMIGA; 105 dev->id.vendor = 0x0001; 106 dev->id.product = 0x0002; 107 dev->id.version = 0x0100; 108 109 dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 110 dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); 111 dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | 112 BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); 113 dev->open = amimouse_open; 114 dev->close = amimouse_close; 115 dev->dev.parent = &pdev->dev; 116 117 err = input_register_device(dev); 118 if (err) { 119 input_free_device(dev); 120 return err; 121 } 122 123 platform_set_drvdata(pdev, dev); 124 125 return 0; 126 } 127 128 static int __exit amimouse_remove(struct platform_device *pdev) 129 { 130 struct input_dev *dev = platform_get_drvdata(pdev); 131 132 input_unregister_device(dev); 133 return 0; 134 } 135 136 static struct platform_driver amimouse_driver = { 137 .remove = __exit_p(amimouse_remove), 138 .driver = { 139 .name = "amiga-mouse", 140 }, 141 }; 142 143 module_platform_driver_probe(amimouse_driver, amimouse_probe); 144 145 MODULE_ALIAS("platform:amiga-mouse"); 146