Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | /* * Atari Joystick Driver for Linux * by Robert de Vries (robert@and.nl) 19Jul93 * * 16 Nov 1994 Andreas Schwab * Support for three button mouse (shamelessly stolen from MiNT) * third button wired to one of the joystick directions on joystick 1 */ #include <linux/sched.h> #include <linux/errno.h> #include <linux/major.h> #include <linux/poll.h> #include <linux/init.h> #include <linux/devfs_fs_kernel.h> #include <linux/smp_lock.h> #include <asm/atarikb.h> #include <asm/atari_joystick.h> #include <asm/uaccess.h> #define MAJOR_NR JOYSTICK_MAJOR #define ANALOG_JOY(n) (!(n & 0x80)) #define DIGITAL_JOY(n) (n & 0x80) #define DEVICE_NR(n) (MINOR(n) & 0x7f) static struct joystick_status joystick[2]; int atari_mouse_buttons; /* for three-button mouse */ void atari_joystick_interrupt(char *buf) { int j; /* ikbd_joystick_disable(); */ j = buf[0] & 0x1; joystick[j].dir = buf[1] & 0xF; joystick[j].fire = (buf[1] & 0x80) >> 7; joystick[j].ready = 1; wake_up_interruptible(&joystick[j].wait); /* For three-button mouse emulation fake a mouse packet */ if (atari_mouse_interrupt_hook && j == 1 && (buf[1] & 1) != ((atari_mouse_buttons & 2) >> 1)) { char faked_packet[3]; atari_mouse_buttons = (atari_mouse_buttons & 5) | ((buf[1] & 1) << 1); faked_packet[0] = (atari_mouse_buttons & 1) | (atari_mouse_buttons & 4 ? 2 : 0); faked_packet[1] = 0; faked_packet[2] = 0; atari_mouse_interrupt_hook (faked_packet); } /* ikbd_joystick_event_on(); */ } static int release_joystick(struct inode *inode, struct file *file) { int minor = DEVICE_NR(inode->i_rdev); lock_kernel(); joystick[minor].active = 0; joystick[minor].ready = 0; if ((joystick[0].active == 0) && (joystick[1].active == 0)) ikbd_joystick_disable(); unlock_kernel(); return 0; } static int open_joystick(struct inode *inode, struct file *file) { int minor = DEVICE_NR(inode->i_rdev); if (!DIGITAL_JOY(inode->i_rdev) || minor > 1) return -ENODEV; if (joystick[minor].active) return -EBUSY; joystick[minor].active = 1; joystick[minor].ready = 0; ikbd_joystick_event_on(); return 0; } static ssize_t write_joystick(struct file *file, const char *buffer, size_t count, loff_t *ppos) { return -EINVAL; } static ssize_t read_joystick(struct file *file, char *buffer, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; int minor = DEVICE_NR(inode->i_rdev); if (count < 2) return -EINVAL; if (!joystick[minor].ready) return -EAGAIN; joystick[minor].ready = 0; if (put_user(joystick[minor].fire, buffer++) || put_user(joystick[minor].dir, buffer++)) return -EFAULT; if (count > 2) if (clear_user(buffer, count - 2)) return -EFAULT; return count; } static unsigned int joystick_poll(struct file *file, poll_table *wait) { int minor = DEVICE_NR(file->f_dentry->d_inode->i_rdev); poll_wait(file, &joystick[minor].wait, wait); if (joystick[minor].ready) return POLLIN | POLLRDNORM; return 0; } struct file_operations atari_joystick_fops = { read: read_joystick, write: write_joystick, poll: joystick_poll, open: open_joystick, release: release_joystick, }; int __init atari_joystick_init(void) { joystick[0].active = joystick[1].active = 0; joystick[0].ready = joystick[1].ready = 0; init_waitqueue_head(&joystick[0].wait); init_waitqueue_head(&joystick[1].wait); if (devfs_register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops)) printk("unable to get major %d for joystick devices\n", MAJOR_NR); devfs_register_series (NULL, "joysticks/digital%u", 2, DEVFS_FL_DEFAULT, MAJOR_NR, 128, S_IFCHR | S_IRUSR | S_IWUSR, &atari_joystick_fops, NULL); return 0; } |