11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Amiga mouse driver for Linux/m68k 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (c) 2000-2002 Vojtech Pavlik 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Based on the work of: 71da177e4SLinus Torvalds * Michael Rausch James Banks 81da177e4SLinus Torvalds * Matther Dillon David Giller 91da177e4SLinus Torvalds * Nathan Laredo Linus Torvalds 101da177e4SLinus Torvalds * Johan Myreen Jes Sorensen 111da177e4SLinus Torvalds * Russell King 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds /* 151da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify it 161da177e4SLinus Torvalds * under the terms of the GNU General Public License version 2 as published by 171da177e4SLinus Torvalds * the Free Software Foundation 181da177e4SLinus Torvalds */ 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds #include <linux/module.h> 211da177e4SLinus Torvalds #include <linux/init.h> 221da177e4SLinus Torvalds #include <linux/input.h> 231da177e4SLinus Torvalds #include <linux/interrupt.h> 24314c926fSGeert Uytterhoeven #include <linux/platform_device.h> 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds #include <asm/irq.h> 271da177e4SLinus Torvalds #include <asm/setup.h> 281da177e4SLinus Torvalds #include <asm/system.h> 291da177e4SLinus Torvalds #include <asm/uaccess.h> 301da177e4SLinus Torvalds #include <asm/amigahw.h> 311da177e4SLinus Torvalds #include <asm/amigaints.h> 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 341da177e4SLinus Torvalds MODULE_DESCRIPTION("Amiga mouse driver"); 351da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds static int amimouse_lastx, amimouse_lasty; 381da177e4SLinus Torvalds 39314c926fSGeert Uytterhoeven static irqreturn_t amimouse_interrupt(int irq, void *data) 401da177e4SLinus Torvalds { 41314c926fSGeert Uytterhoeven struct input_dev *dev = data; 421da177e4SLinus Torvalds unsigned short joy0dat, potgor; 431da177e4SLinus Torvalds int nx, ny, dx, dy; 441da177e4SLinus Torvalds 45b4290a23SAl Viro joy0dat = amiga_custom.joy0dat; 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds nx = joy0dat & 0xff; 481da177e4SLinus Torvalds ny = joy0dat >> 8; 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds dx = nx - amimouse_lastx; 511da177e4SLinus Torvalds dy = ny - amimouse_lasty; 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds if (dx < -127) dx = (256 + nx) - amimouse_lastx; 541da177e4SLinus Torvalds if (dx > 127) dx = (nx - 256) - amimouse_lastx; 551da177e4SLinus Torvalds if (dy < -127) dy = (256 + ny) - amimouse_lasty; 561da177e4SLinus Torvalds if (dy > 127) dy = (ny - 256) - amimouse_lasty; 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds amimouse_lastx = nx; 591da177e4SLinus Torvalds amimouse_lasty = ny; 601da177e4SLinus Torvalds 61b4290a23SAl Viro potgor = amiga_custom.potgor; 621da177e4SLinus Torvalds 63314c926fSGeert Uytterhoeven input_report_rel(dev, REL_X, dx); 64314c926fSGeert Uytterhoeven input_report_rel(dev, REL_Y, dy); 651da177e4SLinus Torvalds 66314c926fSGeert Uytterhoeven input_report_key(dev, BTN_LEFT, ciaa.pra & 0x40); 67314c926fSGeert Uytterhoeven input_report_key(dev, BTN_MIDDLE, potgor & 0x0100); 68314c926fSGeert Uytterhoeven input_report_key(dev, BTN_RIGHT, potgor & 0x0400); 691da177e4SLinus Torvalds 70314c926fSGeert Uytterhoeven input_sync(dev); 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds return IRQ_HANDLED; 731da177e4SLinus Torvalds } 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds static int amimouse_open(struct input_dev *dev) 761da177e4SLinus Torvalds { 771da177e4SLinus Torvalds unsigned short joy0dat; 78314c926fSGeert Uytterhoeven int error; 791da177e4SLinus Torvalds 80b4290a23SAl Viro joy0dat = amiga_custom.joy0dat; 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds amimouse_lastx = joy0dat & 0xff; 831da177e4SLinus Torvalds amimouse_lasty = joy0dat >> 8; 841da177e4SLinus Torvalds 85314c926fSGeert Uytterhoeven error = request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", 86314c926fSGeert Uytterhoeven dev); 87314c926fSGeert Uytterhoeven if (error) 88314c926fSGeert Uytterhoeven dev_err(&dev->dev, "Can't allocate irq %d\n", IRQ_AMIGA_VERTB); 891da177e4SLinus Torvalds 90314c926fSGeert Uytterhoeven return error; 911da177e4SLinus Torvalds } 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds static void amimouse_close(struct input_dev *dev) 941da177e4SLinus Torvalds { 95314c926fSGeert Uytterhoeven free_irq(IRQ_AMIGA_VERTB, dev); 961da177e4SLinus Torvalds } 971da177e4SLinus Torvalds 98314c926fSGeert Uytterhoeven static int __init amimouse_probe(struct platform_device *pdev) 991da177e4SLinus Torvalds { 10072155615SDmitry Torokhov int err; 101314c926fSGeert Uytterhoeven struct input_dev *dev; 10272155615SDmitry Torokhov 103314c926fSGeert Uytterhoeven dev = input_allocate_device(); 104314c926fSGeert Uytterhoeven if (!dev) 1052e5b636bSDmitry Torokhov return -ENOMEM; 1061da177e4SLinus Torvalds 107314c926fSGeert Uytterhoeven dev->name = pdev->name; 108314c926fSGeert Uytterhoeven dev->phys = "amimouse/input0"; 109314c926fSGeert Uytterhoeven dev->id.bustype = BUS_AMIGA; 110314c926fSGeert Uytterhoeven dev->id.vendor = 0x0001; 111314c926fSGeert Uytterhoeven dev->id.product = 0x0002; 112314c926fSGeert Uytterhoeven dev->id.version = 0x0100; 1131da177e4SLinus Torvalds 114314c926fSGeert Uytterhoeven dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 115314c926fSGeert Uytterhoeven dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); 116314c926fSGeert Uytterhoeven dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | 1177b19ada2SJiri Slaby BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); 118314c926fSGeert Uytterhoeven dev->open = amimouse_open; 119314c926fSGeert Uytterhoeven dev->close = amimouse_close; 120314c926fSGeert Uytterhoeven dev->dev.parent = &pdev->dev; 1211da177e4SLinus Torvalds 122314c926fSGeert Uytterhoeven err = input_register_device(dev); 12372155615SDmitry Torokhov if (err) { 124314c926fSGeert Uytterhoeven input_free_device(dev); 12572155615SDmitry Torokhov return err; 12672155615SDmitry Torokhov } 1272e5b636bSDmitry Torokhov 128314c926fSGeert Uytterhoeven platform_set_drvdata(pdev, dev); 129314c926fSGeert Uytterhoeven 1301da177e4SLinus Torvalds return 0; 1311da177e4SLinus Torvalds } 1321da177e4SLinus Torvalds 133314c926fSGeert Uytterhoeven static int __exit amimouse_remove(struct platform_device *pdev) 1341da177e4SLinus Torvalds { 135314c926fSGeert Uytterhoeven struct input_dev *dev = platform_get_drvdata(pdev); 136314c926fSGeert Uytterhoeven 137314c926fSGeert Uytterhoeven platform_set_drvdata(pdev, NULL); 138314c926fSGeert Uytterhoeven input_unregister_device(dev); 139314c926fSGeert Uytterhoeven return 0; 140314c926fSGeert Uytterhoeven } 141314c926fSGeert Uytterhoeven 142314c926fSGeert Uytterhoeven static struct platform_driver amimouse_driver = { 143314c926fSGeert Uytterhoeven .remove = __exit_p(amimouse_remove), 144314c926fSGeert Uytterhoeven .driver = { 145314c926fSGeert Uytterhoeven .name = "amiga-mouse", 146314c926fSGeert Uytterhoeven .owner = THIS_MODULE, 147314c926fSGeert Uytterhoeven }, 148314c926fSGeert Uytterhoeven }; 149314c926fSGeert Uytterhoeven 150314c926fSGeert Uytterhoeven static int __init amimouse_init(void) 151314c926fSGeert Uytterhoeven { 152314c926fSGeert Uytterhoeven return platform_driver_probe(&amimouse_driver, amimouse_probe); 1531da177e4SLinus Torvalds } 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds module_init(amimouse_init); 156314c926fSGeert Uytterhoeven 157314c926fSGeert Uytterhoeven static void __exit amimouse_exit(void) 158314c926fSGeert Uytterhoeven { 159314c926fSGeert Uytterhoeven platform_driver_unregister(&amimouse_driver); 160314c926fSGeert Uytterhoeven } 161314c926fSGeert Uytterhoeven 1621da177e4SLinus Torvalds module_exit(amimouse_exit); 163314c926fSGeert Uytterhoeven 164314c926fSGeert Uytterhoeven MODULE_ALIAS("platform:amiga-mouse"); 165