diff options
| author | Michael Schmitz <schmitz@opal.biophys.uni-duesseldorf.de> | 2007-05-01 16:32:38 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-04 20:59:05 -0400 |
| commit | c04cb856e20a8bf68762d60737b84328c1ab5900 (patch) | |
| tree | c8046787b2fa708b0a5a0972444bac9df67fadff | |
| parent | 3130d905ba86d5f2636b2f45d5beefe82cb03df6 (diff) | |
m68k: Atari keyboard and mouse support.
Atari keyboard and mouse support.
(reformating and Kconfig fixes by Roman Zippel)
Signed-off-by: Michael Schmitz <schmitz@debian.org>
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | arch/m68k/Kconfig | 3 | ||||
| -rw-r--r-- | arch/m68k/atari/Makefile | 1 | ||||
| -rw-r--r-- | arch/m68k/atari/atakeyb.c | 730 | ||||
| -rw-r--r-- | drivers/input/keyboard/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/input/keyboard/Makefile | 1 | ||||
| -rw-r--r-- | drivers/input/keyboard/atakbd.c | 134 | ||||
| -rw-r--r-- | drivers/input/mouse/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/input/mouse/Makefile | 1 | ||||
| -rw-r--r-- | drivers/input/mouse/atarimouse.c | 160 | ||||
| -rw-r--r-- | include/asm-m68k/atarikb.h | 6 | ||||
| -rw-r--r-- | include/linux/input.h | 1 |
11 files changed, 1059 insertions, 0 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index a8e1e604dfa8..b8536c7c0877 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig | |||
| @@ -409,6 +409,9 @@ config STRAM_PROC | |||
| 409 | help | 409 | help |
| 410 | Say Y here to report ST-RAM usage statistics in /proc/stram. | 410 | Say Y here to report ST-RAM usage statistics in /proc/stram. |
| 411 | 411 | ||
| 412 | config ATARI_KBD_CORE | ||
| 413 | bool | ||
| 414 | |||
| 412 | config HEARTBEAT | 415 | config HEARTBEAT |
| 413 | bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40 | 416 | bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40 |
| 414 | default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300 | 417 | default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300 |
diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile index 8cb6236b39db..2cb86191f0aa 100644 --- a/arch/m68k/atari/Makefile +++ b/arch/m68k/atari/Makefile | |||
| @@ -8,3 +8,4 @@ obj-y := config.o time.o debug.o ataints.o stdma.o \ | |||
| 8 | ifeq ($(CONFIG_PCI),y) | 8 | ifeq ($(CONFIG_PCI),y) |
| 9 | obj-$(CONFIG_HADES) += hades-pci.o | 9 | obj-$(CONFIG_HADES) += hades-pci.o |
| 10 | endif | 10 | endif |
| 11 | obj-$(CONFIG_ATARI_KBD_CORE) += atakeyb.o | ||
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c new file mode 100644 index 000000000000..1c29603b16b3 --- /dev/null +++ b/arch/m68k/atari/atakeyb.c | |||
| @@ -0,0 +1,730 @@ | |||
| 1 | /* | ||
| 2 | * linux/atari/atakeyb.c | ||
| 3 | * | ||
| 4 | * Atari Keyboard driver for 680x0 Linux | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 7 | * License. See the file COPYING in the main directory of this archive | ||
| 8 | * for more details. | ||
| 9 | */ | ||
| 10 | |||
| 11 | /* | ||
| 12 | * Atari support by Robert de Vries | ||
| 13 | * enhanced by Bjoern Brauel and Roman Hodek | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/sched.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/errno.h> | ||
| 20 | #include <linux/keyboard.h> | ||
| 21 | #include <linux/delay.h> | ||
| 22 | #include <linux/timer.h> | ||
| 23 | #include <linux/kd.h> | ||
| 24 | #include <linux/random.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/kbd_kern.h> | ||
| 27 | |||
| 28 | #include <asm/atariints.h> | ||
| 29 | #include <asm/atarihw.h> | ||
| 30 | #include <asm/atarikb.h> | ||
| 31 | #include <asm/atari_joystick.h> | ||
| 32 | #include <asm/irq.h> | ||
| 33 | |||
| 34 | static void atakeyb_rep(unsigned long ignore); | ||
| 35 | extern unsigned int keymap_count; | ||
| 36 | |||
| 37 | /* Hook for MIDI serial driver */ | ||
| 38 | void (*atari_MIDI_interrupt_hook) (void); | ||
| 39 | /* Hook for mouse driver */ | ||
| 40 | void (*atari_mouse_interrupt_hook) (char *); | ||
| 41 | /* Hook for keyboard inputdev driver */ | ||
| 42 | void (*atari_input_keyboard_interrupt_hook) (unsigned char, char); | ||
| 43 | /* Hook for mouse inputdev driver */ | ||
| 44 | void (*atari_input_mouse_interrupt_hook) (char *); | ||
| 45 | |||
| 46 | /* variables for IKBD self test: */ | ||
| 47 | |||
| 48 | /* state: 0: off; >0: in progress; >1: 0xf1 received */ | ||
| 49 | static volatile int ikbd_self_test; | ||
| 50 | /* timestamp when last received a char */ | ||
| 51 | static volatile unsigned long self_test_last_rcv; | ||
| 52 | /* bitmap of keys reported as broken */ | ||
| 53 | static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, }; | ||
| 54 | |||
| 55 | #define BREAK_MASK (0x80) | ||
| 56 | |||
| 57 | /* | ||
| 58 | * ++roman: The following changes were applied manually: | ||
| 59 | * | ||
| 60 | * - The Alt (= Meta) key works in combination with Shift and | ||
| 61 | * Control, e.g. Alt+Shift+a sends Meta-A (0xc1), Alt+Control+A sends | ||
| 62 | * Meta-Ctrl-A (0x81) ... | ||
| 63 | * | ||
| 64 | * - The parentheses on the keypad send '(' and ')' with all | ||
| 65 | * modifiers (as would do e.g. keypad '+'), but they cannot be used as | ||
| 66 | * application keys (i.e. sending Esc O c). | ||
| 67 | * | ||
| 68 | * - HELP and UNDO are mapped to be F21 and F24, resp, that send the | ||
| 69 | * codes "\E[M" and "\E[P". (This is better than the old mapping to | ||
| 70 | * F11 and F12, because these codes are on Shift+F1/2 anyway.) This | ||
| 71 | * way, applications that allow their own keyboard mappings | ||
| 72 | * (e.g. tcsh, X Windows) can be configured to use them in the way | ||
| 73 | * the label suggests (providing help or undoing). | ||
| 74 | * | ||
| 75 | * - Console switching is done with Alt+Fx (consoles 1..10) and | ||
| 76 | * Shift+Alt+Fx (consoles 11..20). | ||
| 77 | * | ||
| 78 | * - The misc. special function implemented in the kernel are mapped | ||
| 79 | * to the following key combinations: | ||
| 80 | * | ||
| 81 | * ClrHome -> Home/Find | ||
| 82 | * Shift + ClrHome -> End/Select | ||
| 83 | * Shift + Up -> Page Up | ||
| 84 | * Shift + Down -> Page Down | ||
| 85 | * Alt + Help -> show system status | ||
| 86 | * Shift + Help -> show memory info | ||
| 87 | * Ctrl + Help -> show registers | ||
| 88 | * Ctrl + Alt + Del -> Reboot | ||
| 89 | * Alt + Undo -> switch to last console | ||
| 90 | * Shift + Undo -> send interrupt | ||
| 91 | * Alt + Insert -> stop/start output (same as ^S/^Q) | ||
| 92 | * Alt + Up -> Scroll back console (if implemented) | ||
| 93 | * Alt + Down -> Scroll forward console (if implemented) | ||
| 94 | * Alt + CapsLock -> NumLock | ||
| 95 | * | ||
| 96 | * ++Andreas: | ||
| 97 | * | ||
| 98 | * - Help mapped to K_HELP | ||
| 99 | * - Undo mapped to K_UNDO (= K_F246) | ||
| 100 | * - Keypad Left/Right Parenthesis mapped to new K_PPAREN[LR] | ||
| 101 | */ | ||
| 102 | |||
| 103 | static u_short ataplain_map[NR_KEYS] __initdata = { | ||
| 104 | 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, | ||
| 105 | 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009, | ||
| 106 | 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, | ||
| 107 | 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73, | ||
| 108 | 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, | ||
| 109 | 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76, | ||
| 110 | 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf200, | ||
| 111 | 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, | ||
| 112 | 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, | ||
| 113 | 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, | ||
| 114 | 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, | ||
| 115 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | ||
| 116 | 0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, | ||
| 117 | 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303, | ||
| 118 | 0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | ||
| 119 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 | ||
| 120 | }; | ||
| 121 | |||
| 122 | typedef enum kb_state_t { | ||
| 123 | KEYBOARD, AMOUSE, RMOUSE, JOYSTICK, CLOCK, RESYNC | ||
| 124 | } KB_STATE_T; | ||
| 125 | |||
| 126 | #define IS_SYNC_CODE(sc) ((sc) >= 0x04 && (sc) <= 0xfb) | ||
| 127 | |||
| 128 | typedef struct keyboard_state { | ||
| 129 | unsigned char buf[6]; | ||
| 130 | int len; | ||
| 131 | KB_STATE_T state; | ||
| 132 | } KEYBOARD_STATE; | ||
| 133 | |||
| 134 | KEYBOARD_STATE kb_state; | ||
| 135 | |||
| 136 | #define DEFAULT_KEYB_REP_DELAY (HZ/4) | ||
| 137 | #define DEFAULT_KEYB_REP_RATE (HZ/25) | ||
| 138 | |||
| 139 | /* These could be settable by some ioctl() in future... */ | ||
| 140 | static unsigned int key_repeat_delay = DEFAULT_KEYB_REP_DELAY; | ||
| 141 | static unsigned int key_repeat_rate = DEFAULT_KEYB_REP_RATE; | ||
| 142 | |||
| 143 | static unsigned char rep_scancode; | ||
| 144 | static struct timer_list atakeyb_rep_timer = { | ||
| 145 | .function = atakeyb_rep, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static void atakeyb_rep(unsigned long ignore) | ||
| 149 | { | ||
| 150 | /* Disable keyboard for the time we call handle_scancode(), else a race | ||
| 151 | * in the keyboard tty queue may happen */ | ||
| 152 | atari_disable_irq(IRQ_MFP_ACIA); | ||
| 153 | del_timer(&atakeyb_rep_timer); | ||
| 154 | |||
| 155 | /* A keyboard int may have come in before we disabled the irq, so | ||
| 156 | * double-check whether rep_scancode is still != 0 */ | ||
| 157 | if (rep_scancode) { | ||
| 158 | init_timer(&atakeyb_rep_timer); | ||
| 159 | atakeyb_rep_timer.expires = jiffies + key_repeat_rate; | ||
| 160 | add_timer(&atakeyb_rep_timer); | ||
| 161 | |||
| 162 | //handle_scancode(rep_scancode, 1); | ||
| 163 | if (atari_input_keyboard_interrupt_hook) | ||
| 164 | atari_input_keyboard_interrupt_hook(rep_scancode, 1); | ||
| 165 | } | ||
| 166 | |||
| 167 | atari_enable_irq(IRQ_MFP_ACIA); | ||
| 168 | } | ||
| 169 | |||
| 170 | |||
| 171 | /* ++roman: If a keyboard overrun happened, we can't tell in general how much | ||
| 172 | * bytes have been lost and in which state of the packet structure we are now. | ||
| 173 | * This usually causes keyboards bytes to be interpreted as mouse movements | ||
| 174 | * and vice versa, which is very annoying. It seems better to throw away some | ||
| 175 | * bytes (that are usually mouse bytes) than to misinterpret them. Therefor I | ||
| 176 | * introduced the RESYNC state for IKBD data. In this state, the bytes up to | ||
| 177 | * one that really looks like a key event (0x04..0xf2) or the start of a mouse | ||
| 178 | * packet (0xf8..0xfb) are thrown away, but at most 2 bytes. This at least | ||
| 179 | * speeds up the resynchronization of the event structure, even if maybe a | ||
| 180 | * mouse movement is lost. However, nothing is perfect. For bytes 0x01..0x03, | ||
| 181 | * it's really hard to decide whether they're mouse or keyboard bytes. Since | ||
| 182 | * overruns usually occur when moving the Atari mouse rapidly, they're seen as | ||
| 183 | * mouse bytes here. If this is wrong, only a make code of the keyboard gets | ||
| 184 | * lost, which isn't too bad. Loosing a break code would be disastrous, | ||
| 185 | * because then the keyboard repeat strikes... | ||
| 186 | */ | ||
| 187 | |||
| 188 | static irqreturn_t atari_keyboard_interrupt(int irq, void *dummy) | ||
| 189 | { | ||
| 190 | u_char acia_stat; | ||
| 191 | int scancode; | ||
| 192 | int break_flag; | ||
| 193 | |||
| 194 | repeat: | ||
| 195 | if (acia.mid_ctrl & ACIA_IRQ) | ||
| 196 | if (atari_MIDI_interrupt_hook) | ||
| 197 | atari_MIDI_interrupt_hook(); | ||
| 198 | acia_stat = acia.key_ctrl; | ||
| 199 | /* check out if the interrupt came from this ACIA */ | ||
| 200 | if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ)) | ||
| 201 | return IRQ_HANDLED; | ||
| 202 | |||
| 203 | if (acia_stat & ACIA_OVRN) { | ||
| 204 | /* a very fast typist or a slow system, give a warning */ | ||
| 205 | /* ...happens often if interrupts were disabled for too long */ | ||
| 206 | printk(KERN_DEBUG "Keyboard overrun\n"); | ||
| 207 | scancode = acia.key_data; | ||
| 208 | /* Turn off autorepeating in case a break code has been lost */ | ||
| 209 | del_timer(&atakeyb_rep_timer); | ||
| 210 | rep_scancode = 0; | ||
| 211 | if (ikbd_self_test) | ||
| 212 | /* During self test, don't do resyncing, just process the code */ | ||
| 213 | goto interpret_scancode; | ||
| 214 | else if (IS_SYNC_CODE(scancode)) { | ||
| 215 | /* This code seem already to be the start of a new packet or a | ||
| 216 | * single scancode */ | ||
| 217 | kb_state.state = KEYBOARD; | ||
| 218 | goto interpret_scancode; | ||
| 219 | } else { | ||
| 220 | /* Go to RESYNC state and skip this byte */ | ||
| 221 | kb_state.state = RESYNC; | ||
| 222 | kb_state.len = 1; /* skip max. 1 another byte */ | ||
| 223 | goto repeat; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | if (acia_stat & ACIA_RDRF) { | ||
| 228 | /* received a character */ | ||
| 229 | scancode = acia.key_data; /* get it or reset the ACIA, I'll get it! */ | ||
| 230 | tasklet_schedule(&keyboard_tasklet); | ||
| 231 | interpret_scancode: | ||
| 232 | switch (kb_state.state) { | ||
| 233 | case KEYBOARD: | ||
| 234 | switch (scancode) { | ||
| 235 | case 0xF7: | ||
| 236 | kb_state.state = AMOUSE; | ||
| 237 | kb_state.len = 0; | ||
| 238 | break; | ||
| 239 | |||
| 240 | case 0xF8: | ||
| 241 | case 0xF9: | ||
| 242 | case 0xFA: | ||
| 243 | case 0xFB: | ||
| 244 | kb_state.state = RMOUSE; | ||
| 245 | kb_state.len = 1; | ||
| 246 | kb_state.buf[0] = scancode; | ||
| 247 | break; | ||
| 248 | |||
| 249 | case 0xFC: | ||
| 250 | kb_state.state = CLOCK; | ||
| 251 | kb_state.len = 0; | ||
| 252 | break; | ||
| 253 | |||
| 254 | case 0xFE: | ||
| 255 | case 0xFF: | ||
| 256 | kb_state.state = JOYSTICK; | ||
| 257 | kb_state.len = 1; | ||
| 258 | kb_state.buf[0] = scancode; | ||
| 259 | break; | ||
| 260 | |||
| 261 | case 0xF1: | ||
| 262 | /* during self-test, note that 0xf1 received */ | ||
| 263 | if (ikbd_self_test) { | ||
| 264 | ++ikbd_self_test; | ||
| 265 | self_test_last_rcv = jiffies; | ||
| 266 | break; | ||
| 267 | } | ||
| 268 | /* FALL THROUGH */ | ||
| 269 | |||
| 270 | default: | ||
| 271 | break_flag = scancode & BREAK_MASK; | ||
| 272 | scancode &= ~BREAK_MASK; | ||
| 273 | if (ikbd_self_test) { | ||
| 274 | /* Scancodes sent during the self-test stand for broken | ||
| 275 | * keys (keys being down). The code *should* be a break | ||
| 276 | * code, but nevertheless some AT keyboard interfaces send | ||
| 277 | * make codes instead. Therefore, simply ignore | ||
| 278 | * break_flag... | ||
| 279 | */ | ||
| 280 | int keyval = plain_map[scancode], keytyp; | ||
| 281 | |||
| 282 | set_bit(scancode, broken_keys); | ||
| 283 | self_test_last_rcv = jiffies; | ||
| 284 | keyval = plain_map[scancode]; | ||
| 285 | keytyp = KTYP(keyval) - 0xf0; | ||
| 286 | keyval = KVAL(keyval); | ||
| 287 | |||
| 288 | printk(KERN_WARNING "Key with scancode %d ", scancode); | ||
| 289 | if (keytyp == KT_LATIN || keytyp == KT_LETTER) { | ||
| 290 | if (keyval < ' ') | ||
| 291 | printk("('^%c') ", keyval + '@'); | ||
| 292 | else | ||
| 293 | printk("('%c') ", keyval); | ||
| 294 | } | ||
| 295 | printk("is broken -- will be ignored.\n"); | ||
| 296 | break; | ||
| 297 | } else if (test_bit(scancode, broken_keys)) | ||
| 298 | break; | ||
| 299 | |||
| 300 | #if 0 // FIXME; hangs at boot | ||
| 301 | if (break_flag) { | ||
| 302 | del_timer(&atakeyb_rep_timer); | ||
| 303 | rep_scancode = 0; | ||
| 304 | } else { | ||
| 305 | del_timer(&atakeyb_rep_timer); | ||
| 306 | rep_scancode = scancode; | ||
| 307 | atakeyb_rep_timer.expires = jiffies + key_repeat_delay; | ||
| 308 | add_timer(&atakeyb_rep_timer); | ||
| 309 | } | ||
| 310 | #endif | ||
| 311 | |||
| 312 | // handle_scancode(scancode, !break_flag); | ||
| 313 | if (atari_input_keyboard_interrupt_hook) | ||
| 314 | atari_input_keyboard_interrupt_hook((unsigned char)scancode, !break_flag); | ||
| 315 | break; | ||
| 316 | } | ||
| 317 | break; | ||
| 318 | |||
| 319 | case AMOUSE: | ||
| 320 | kb_state.buf[kb_state.len++] = scancode; | ||
| 321 | if (kb_state.len == 5) { | ||
| 322 | kb_state.state = KEYBOARD; | ||
| 323 | /* not yet used */ | ||
| 324 | /* wake up someone waiting for this */ | ||
| 325 | } | ||
| 326 | break; | ||
| 327 | |||
| 328 | case RMOUSE: | ||
| 329 | kb_state.buf[kb_state.len++] = scancode; | ||
| 330 | if (kb_state.len == 3) { | ||
| 331 | kb_state.state = KEYBOARD; | ||
| 332 | if (atari_mouse_interrupt_hook) | ||
| 333 | atari_mouse_interrupt_hook(kb_state.buf); | ||
| 334 | } | ||
| 335 | break; | ||
| 336 | |||
| 337 | case JOYSTICK: | ||
| 338 | kb_state.buf[1] = scancode; | ||
| 339 | kb_state.state = KEYBOARD; | ||
| 340 | #ifdef FIXED_ATARI_JOYSTICK | ||
| 341 | atari_joystick_interrupt(kb_state.buf); | ||
| 342 | #endif | ||
| 343 | break; | ||
| 344 | |||
| 345 | case CLOCK: | ||
| 346 | kb_state.buf[kb_state.len++] = scancode; | ||
| 347 | if (kb_state.len == 6) { | ||
| 348 | kb_state.state = KEYBOARD; | ||
| 349 | /* wake up someone waiting for this. | ||
| 350 | But will this ever be used, as Linux keeps its own time. | ||
| 351 | Perhaps for synchronization purposes? */ | ||
| 352 | /* wake_up_interruptible(&clock_wait); */ | ||
| 353 | } | ||
| 354 | break; | ||
| 355 | |||
| 356 | case RESYNC: | ||
| 357 | if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) { | ||
| 358 | kb_state.state = KEYBOARD; | ||
| 359 | goto interpret_scancode; | ||
| 360 | } | ||
| 361 | kb_state.len--; | ||
| 362 | break; | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | #if 0 | ||
| 367 | if (acia_stat & ACIA_CTS) | ||
| 368 | /* cannot happen */; | ||
| 369 | #endif | ||
| 370 | |||
| 371 | if (acia_stat & (ACIA_FE | ACIA_PE)) { | ||
| 372 | printk("Error in keyboard communication\n"); | ||
| 373 | } | ||
| 374 | |||
| 375 | /* handle_scancode() can take a lot of time, so check again if | ||
| 376 | * some character arrived | ||
| 377 | */ | ||
| 378 | goto repeat; | ||
| 379 | } | ||
| 380 | |||
| 381 | /* | ||
| 382 | * I write to the keyboard without using interrupts, I poll instead. | ||
| 383 | * This takes for the maximum length string allowed (7) at 7812.5 baud | ||
| 384 | * 8 data 1 start 1 stop bit: 9.0 ms | ||
| 385 | * If this takes too long for normal operation, interrupt driven writing | ||
| 386 | * is the solution. (I made a feeble attempt in that direction but I | ||
| 387 | * kept it simple for now.) | ||
| 388 | */ | ||
| 389 | void ikbd_write(const char *str, int len) | ||
| 390 | { | ||
| 391 | u_char acia_stat; | ||
| 392 | |||
| 393 | if ((len < 1) || (len > 7)) | ||
| 394 | panic("ikbd: maximum string length exceeded"); | ||
| 395 | while (len) { | ||
| 396 | acia_stat = acia.key_ctrl; | ||
| 397 | if (acia_stat & ACIA_TDRE) { | ||
| 398 | acia.key_data = *str++; | ||
| 399 | len--; | ||
| 400 | } | ||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 404 | /* Reset (without touching the clock) */ | ||
| 405 | void ikbd_reset(void) | ||
| 406 | { | ||
| 407 | static const char cmd[2] = { 0x80, 0x01 }; | ||
| 408 | |||
| 409 | ikbd_write(cmd, 2); | ||
| 410 | |||
| 411 | /* | ||
| 412 | * if all's well code 0xF1 is returned, else the break codes of | ||
| 413 | * all keys making contact | ||
| 414 | */ | ||
| 415 | } | ||
| 416 | |||
| 417 | /* Set mouse button action */ | ||
| 418 | void ikbd_mouse_button_action(int mode) | ||
| 419 | { | ||
| 420 | char cmd[2] = { 0x07, mode }; | ||
| 421 | |||
| 422 | ikbd_write(cmd, 2); | ||
| 423 | } | ||
| 424 | |||
| 425 | /* Set relative mouse position reporting */ | ||
| 426 | void ikbd_mouse_rel_pos(void) | ||
| 427 | { | ||
| 428 | static const char cmd[1] = { 0x08 }; | ||
| 429 | |||
| 430 | ikbd_write(cmd, 1); | ||
| 431 | } | ||
| 432 | |||
| 433 | /* Set absolute mouse position reporting */ | ||
| 434 | void ikbd_mouse_abs_pos(int xmax, int ymax) | ||
| 435 | { | ||
| 436 | char cmd[5] = { 0x09, xmax>>8, xmax&0xFF, ymax>>8, ymax&0xFF }; | ||
| 437 | |||
| 438 | ikbd_write(cmd, 5); | ||
| 439 | } | ||
| 440 | |||
| 441 | /* Set mouse keycode mode */ | ||
| 442 | void ikbd_mouse_kbd_mode(int dx, int dy) | ||
| 443 | { | ||
| 444 | char cmd[3] = { 0x0A, dx, dy }; | ||
| 445 | |||
| 446 | ikbd_write(cmd, 3); | ||
| 447 | } | ||
| 448 | |||
| 449 | /* Set mouse threshold */ | ||
| 450 | void ikbd_mouse_thresh(int x, int y) | ||
| 451 | { | ||
| 452 | char cmd[3] = { 0x0B, x, y }; | ||
| 453 | |||
| 454 | ikbd_write(cmd, 3); | ||
| 455 | } | ||
| 456 | |||
| 457 | /* Set mouse scale */ | ||
| 458 | void ikbd_mouse_scale(int x, int y) | ||
| 459 | { | ||
| 460 | char cmd[3] = { 0x0C, x, y }; | ||
| 461 | |||
| 462 | ikbd_write(cmd, 3); | ||
| 463 | } | ||
| 464 | |||
| 465 | /* Interrogate mouse position */ | ||
| 466 | void ikbd_mouse_pos_get(int *x, int *y) | ||
| 467 | { | ||
| 468 | static const char cmd[1] = { 0x0D }; | ||
| 469 | |||
| 470 | ikbd_write(cmd, 1); | ||
| 471 | |||
| 472 | /* wait for returning bytes */ | ||
| 473 | } | ||
| 474 | |||
| 475 | /* Load mouse position */ | ||
| 476 | void ikbd_mouse_pos_set(int x, int y) | ||
| 477 | { | ||
| 478 | char cmd[6] = { 0x0E, 0x00, x>>8, x&0xFF, y>>8, y&0xFF }; | ||
| 479 | |||
| 480 | ikbd_write(cmd, 6); | ||
| 481 | } | ||
| 482 | |||
| 483 | /* Set Y=0 at bottom */ | ||
| 484 | void ikbd_mouse_y0_bot(void) | ||
| 485 | { | ||
| 486 | static const char cmd[1] = { 0x0F }; | ||
| 487 | |||
| 488 | ikbd_write(cmd, 1); | ||
| 489 | } | ||
| 490 | |||
| 491 | /* Set Y=0 at top */ | ||
| 492 | void ikbd_mouse_y0_top(void) | ||
| 493 | { | ||
| 494 | static const char cmd[1] = { 0x10 }; | ||
| 495 | |||
| 496 | ikbd_write(cmd, 1); | ||
| 497 | } | ||
| 498 | |||
| 499 | /* Resume */ | ||
| 500 | void ikbd_resume(void) | ||
| 501 | { | ||
| 502 | static const char cmd[1] = { 0x11 }; | ||
| 503 | |||
| 504 | ikbd_write(cmd, 1); | ||
| 505 | } | ||
| 506 | |||
| 507 | /* Disable mouse */ | ||
| 508 | void ikbd_mouse_disable(void) | ||
| 509 | { | ||
| 510 | static const char cmd[1] = { 0x12 }; | ||
| 511 | |||
| 512 | ikbd_write(cmd, 1); | ||
| 513 | } | ||
| 514 | |||
| 515 | /* Pause output */ | ||
| 516 | void ikbd_pause(void) | ||
| 517 | { | ||
| 518 | static const char cmd[1] = { 0x13 }; | ||
| 519 | |||
| 520 | ikbd_write(cmd, 1); | ||
| 521 | } | ||
| 522 | |||
| 523 | /* Set joystick event reporting */ | ||
| 524 | void ikbd_joystick_event_on(void) | ||
| 525 | { | ||
| 526 | static const char cmd[1] = { 0x14 }; | ||
| 527 | |||
| 528 | ikbd_write(cmd, 1); | ||
| 529 | } | ||
| 530 | |||
| 531 | /* Set joystick interrogation mode */ | ||
| 532 | void ikbd_joystick_event_off(void) | ||
| 533 | { | ||
| 534 | static const char cmd[1] = { 0x15 }; | ||
| 535 | |||
| 536 | ikbd_write(cmd, 1); | ||
| 537 | } | ||
| 538 | |||
| 539 | /* Joystick interrogation */ | ||
| 540 | void ikbd_joystick_get_state(void) | ||
| 541 | { | ||
| 542 | static const char cmd[1] = { 0x16 }; | ||
| 543 | |||
| 544 | ikbd_write(cmd, 1); | ||
| 545 | } | ||
| 546 | |||
| 547 | #if 0 | ||
| 548 | /* This disables all other ikbd activities !!!! */ | ||
| 549 | /* Set joystick monitoring */ | ||
| 550 | void ikbd_joystick_monitor(int rate) | ||
| 551 | { | ||
| 552 | static const char cmd[2] = { 0x17, rate }; | ||
| 553 | |||
| 554 | ikbd_write(cmd, 2); | ||
| 555 | |||
| 556 | kb_state.state = JOYSTICK_MONITOR; | ||
| 557 | } | ||
| 558 | #endif | ||
| 559 | |||
| 560 | /* some joystick routines not in yet (0x18-0x19) */ | ||
| 561 | |||
| 562 | /* Disable joysticks */ | ||
| 563 | void ikbd_joystick_disable(void) | ||
| 564 | { | ||
| 565 | static const char cmd[1] = { 0x1A }; | ||
| 566 | |||
| 567 | ikbd_write(cmd, 1); | ||
| 568 | } | ||
| 569 | |||
| 570 | /* Time-of-day clock set */ | ||
| 571 | void ikbd_clock_set(int year, int month, int day, int hour, int minute, int second) | ||
| 572 | { | ||
| 573 | char cmd[7] = { 0x1B, year, month, day, hour, minute, second }; | ||
| 574 | |||
| 575 | ikbd_write(cmd, 7); | ||
| 576 | } | ||
| 577 | |||
| 578 | /* Interrogate time-of-day clock */ | ||
| 579 | void ikbd_clock_get(int *year, int *month, int *day, int *hour, int *minute, int second) | ||
| 580 | { | ||
| 581 | static const char cmd[1] = { 0x1C }; | ||
| 582 | |||
| 583 | ikbd_write(cmd, 1); | ||
| 584 | } | ||
| 585 | |||
| 586 | /* Memory load */ | ||
| 587 | void ikbd_mem_write(int address, int size, char *data) | ||
| 588 | { | ||
| 589 | panic("Attempt to write data into keyboard memory"); | ||
| 590 | } | ||
| 591 | |||
| 592 | /* Memory read */ | ||
| 593 | void ikbd_mem_read(int address, char data[6]) | ||
| 594 | { | ||
| 595 | char cmd[3] = { 0x21, address>>8, address&0xFF }; | ||
| 596 | |||
| 597 | ikbd_write(cmd, 3); | ||
| 598 | |||
| 599 | /* receive data and put it in data */ | ||
| 600 | } | ||
| 601 | |||
| 602 | /* Controller execute */ | ||
| 603 | void ikbd_exec(int address) | ||
| 604 | { | ||
| 605 | char cmd[3] = { 0x22, address>>8, address&0xFF }; | ||
| 606 | |||
| 607 | ikbd_write(cmd, 3); | ||
| 608 | } | ||
| 609 | |||
| 610 | /* Status inquiries (0x87-0x9A) not yet implemented */ | ||
| 611 | |||
| 612 | /* Set the state of the caps lock led. */ | ||
| 613 | void atari_kbd_leds(unsigned int leds) | ||
| 614 | { | ||
| 615 | char cmd[6] = {32, 0, 4, 1, 254 + ((leds & 4) != 0), 0}; | ||
| 616 | |||
| 617 | ikbd_write(cmd, 6); | ||
| 618 | } | ||
| 619 | |||
| 620 | /* | ||
| 621 | * The original code sometimes left the interrupt line of | ||
| 622 | * the ACIAs low forever. I hope, it is fixed now. | ||
| 623 | * | ||
| 624 | * Martin Rogge, 20 Aug 1995 | ||
| 625 | */ | ||
| 626 | |||
| 627 | static int atari_keyb_done = 0; | ||
| 628 | |||
| 629 | int __init atari_keyb_init(void) | ||
| 630 | { | ||
| 631 | if (atari_keyb_done) | ||
| 632 | return 0; | ||
| 633 | |||
| 634 | /* setup key map */ | ||
| 635 | memcpy(key_maps[0], ataplain_map, sizeof(plain_map)); | ||
| 636 | |||
| 637 | kb_state.state = KEYBOARD; | ||
| 638 | kb_state.len = 0; | ||
| 639 | |||
| 640 | request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW, | ||
| 641 | "keyboard/mouse/MIDI", atari_keyboard_interrupt); | ||
| 642 | |||
| 643 | atari_turnoff_irq(IRQ_MFP_ACIA); | ||
| 644 | do { | ||
| 645 | /* reset IKBD ACIA */ | ||
| 646 | acia.key_ctrl = ACIA_RESET | | ||
| 647 | (atari_switches & ATARI_SWITCH_IKBD) ? ACIA_RHTID : 0; | ||
| 648 | (void)acia.key_ctrl; | ||
| 649 | (void)acia.key_data; | ||
| 650 | |||
| 651 | /* reset MIDI ACIA */ | ||
| 652 | acia.mid_ctrl = ACIA_RESET | | ||
| 653 | (atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0; | ||
| 654 | (void)acia.mid_ctrl; | ||
| 655 | (void)acia.mid_data; | ||
| 656 | |||
| 657 | /* divide 500kHz by 64 gives 7812.5 baud */ | ||
| 658 | /* 8 data no parity 1 start 1 stop bit */ | ||
| 659 | /* receive interrupt enabled */ | ||
| 660 | /* RTS low (except if switch selected), transmit interrupt disabled */ | ||
| 661 | acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RIE) | | ||
| 662 | ((atari_switches & ATARI_SWITCH_IKBD) ? | ||
| 663 | ACIA_RHTID : ACIA_RLTID); | ||
| 664 | |||
| 665 | acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | | ||
| 666 | (atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0; | ||
| 667 | |||
| 668 | /* make sure the interrupt line is up */ | ||
| 669 | } while ((mfp.par_dt_reg & 0x10) == 0); | ||
| 670 | |||
| 671 | /* enable ACIA Interrupts */ | ||
| 672 | mfp.active_edge &= ~0x10; | ||
| 673 | atari_turnon_irq(IRQ_MFP_ACIA); | ||
| 674 | |||
| 675 | ikbd_self_test = 1; | ||
| 676 | ikbd_reset(); | ||
| 677 | /* wait for a period of inactivity (here: 0.25s), then assume the IKBD's | ||
| 678 | * self-test is finished */ | ||
| 679 | self_test_last_rcv = jiffies; | ||
| 680 | while (time_before(jiffies, self_test_last_rcv + HZ/4)) | ||
| 681 | barrier(); | ||
| 682 | /* if not incremented: no 0xf1 received */ | ||
| 683 | if (ikbd_self_test == 1) | ||
| 684 | printk(KERN_ERR "WARNING: keyboard self test failed!\n"); | ||
| 685 | ikbd_self_test = 0; | ||
| 686 | |||
| 687 | ikbd_mouse_disable(); | ||
| 688 | ikbd_joystick_disable(); | ||
| 689 | |||
| 690 | #ifdef FIXED_ATARI_JOYSTICK | ||
| 691 | atari_joystick_init(); | ||
| 692 | #endif | ||
| 693 | |||
| 694 | // flag init done | ||
| 695 | atari_keyb_done = 1; | ||
| 696 | return 0; | ||
| 697 | } | ||
| 698 | |||
| 699 | |||
| 700 | int atari_kbdrate(struct kbd_repeat *k) | ||
| 701 | { | ||
| 702 | if (k->delay > 0) { | ||
| 703 | /* convert from msec to jiffies */ | ||
| 704 | key_repeat_delay = (k->delay * HZ + 500) / 1000; | ||
| 705 | if (key_repeat_delay < 1) | ||
| 706 | key_repeat_delay = 1; | ||
| 707 | } | ||
| 708 | if (k->period > 0) { | ||
| 709 | key_repeat_rate = (k->period * HZ + 500) / 1000; | ||
| 710 | if (key_repeat_rate < 1) | ||
| 711 | key_repeat_rate = 1; | ||
| 712 | } | ||
| 713 | |||
| 714 | k->delay = key_repeat_delay * 1000 / HZ; | ||
| 715 | k->period = key_repeat_rate * 1000 / HZ; | ||
| 716 | |||
| 717 | return 0; | ||
| 718 | } | ||
| 719 | |||
| 720 | int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode) | ||
| 721 | { | ||
| 722 | #ifdef CONFIG_MAGIC_SYSRQ | ||
| 723 | /* ALT+HELP pressed? */ | ||
| 724 | if ((keycode == 98) && ((shift_state & 0xff) == 8)) | ||
| 725 | *keycodep = 0xff; | ||
| 726 | else | ||
| 727 | #endif | ||
| 728 | *keycodep = keycode; | ||
| 729 | return 1; | ||
| 730 | } | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index f17e9c7d4b36..c845d5c4cbba 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
| @@ -164,6 +164,17 @@ config KEYBOARD_AMIGA | |||
| 164 | To compile this driver as a module, choose M here: the | 164 | To compile this driver as a module, choose M here: the |
| 165 | module will be called amikbd. | 165 | module will be called amikbd. |
| 166 | 166 | ||
| 167 | config KEYBOARD_ATARI | ||
| 168 | tristate "Atari keyboard" | ||
| 169 | depends on ATARI | ||
| 170 | select ATARI_KBD_CORE | ||
| 171 | help | ||
| 172 | Say Y here if you are running Linux on any Atari and have a keyboard | ||
| 173 | attached. | ||
| 174 | |||
| 175 | To compile this driver as a module, choose M here: the | ||
| 176 | module will be called atakbd. | ||
| 177 | |||
| 167 | config KEYBOARD_HIL_OLD | 178 | config KEYBOARD_HIL_OLD |
| 168 | tristate "HP HIL keyboard support (simple driver)" | 179 | tristate "HP HIL keyboard support (simple driver)" |
| 169 | depends on GSC || HP300 | 180 | depends on GSC || HP300 |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 586a0fe53be6..7aa59ee5a0b6 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
| @@ -9,6 +9,7 @@ obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | |||
| 9 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o | 9 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o |
| 10 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 10 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
| 11 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 11 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
| 12 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | ||
| 12 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | 13 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o |
| 13 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | 14 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o |
| 14 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 15 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
diff --git a/drivers/input/keyboard/atakbd.c b/drivers/input/keyboard/atakbd.c new file mode 100644 index 000000000000..ded1d6ac6ff3 --- /dev/null +++ b/drivers/input/keyboard/atakbd.c | |||
| @@ -0,0 +1,134 @@ | |||
| 1 | /* | ||
| 2 | * atakbd.c | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Michael Schmitz | ||
| 5 | * | ||
| 6 | * Based on amikbd.c, which is | ||
| 7 | * | ||
| 8 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
| 9 | * | ||
| 10 | * Based on the work of: | ||
| 11 | * Hamish Macdonald | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* | ||
| 15 | * Atari keyboard driver for Linux/m68k | ||
| 16 | * | ||
| 17 | * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c | ||
| 18 | * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard | ||
| 19 | * interrupt is shared with the MIDI ACIA so MIDI data also get handled there). | ||
| 20 | * This driver only deals with handing key events off to the input layer. | ||
| 21 | */ | ||
| 22 | |||
| 23 | /* | ||
| 24 | * This program is free software; you can redistribute it and/or modify | ||
| 25 | * it under the terms of the GNU General Public License as published by | ||
| 26 | * the Free Software Foundation; either version 2 of the License, or | ||
| 27 | * (at your option) any later version. | ||
| 28 | * | ||
| 29 | * This program is distributed in the hope that it will be useful, | ||
| 30 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 31 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 32 | * GNU General Public License for more details. | ||
| 33 | * | ||
| 34 | * You should have received a copy of the GNU General Public License | ||
| 35 | * along with this program; if not, write to the Free Software | ||
| 36 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 37 | * | ||
| 38 | * Should you need to contact me, the author, you can do so either by | ||
| 39 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
| 40 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
| 41 | */ | ||
| 42 | |||
| 43 | #include <linux/module.h> | ||
| 44 | #include <linux/init.h> | ||
| 45 | #include <linux/input.h> | ||
| 46 | #include <linux/delay.h> | ||
| 47 | #include <linux/interrupt.h> | ||
| 48 | |||
| 49 | #include <asm/atariints.h> | ||
| 50 | #include <asm/atarihw.h> | ||
| 51 | #include <asm/atarikb.h> | ||
| 52 | #include <asm/irq.h> | ||
| 53 | |||
| 54 | MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>"); | ||
| 55 | MODULE_DESCRIPTION("Atari keyboard driver"); | ||
| 56 | MODULE_LICENSE("GPL"); | ||
| 57 | |||
| 58 | static unsigned char atakbd_keycode[0x72]; | ||
| 59 | |||
| 60 | static struct input_dev *atakbd_dev; | ||
| 61 | |||
| 62 | static void atakbd_interrupt(unsigned char scancode, char down) | ||
| 63 | { | ||
| 64 | |||
| 65 | if (scancode < 0x72) { /* scancodes < 0xf2 are keys */ | ||
| 66 | |||
| 67 | // report raw events here? | ||
| 68 | |||
| 69 | scancode = atakbd_keycode[scancode]; | ||
| 70 | |||
| 71 | if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */ | ||
| 72 | input_report_key(atakbd_dev, scancode, 1); | ||
| 73 | input_report_key(atakbd_dev, scancode, 0); | ||
| 74 | input_sync(atakbd_dev); | ||
| 75 | } else { | ||
| 76 | input_report_key(atakbd_dev, scancode, down); | ||
| 77 | input_sync(atakbd_dev); | ||
| 78 | } | ||
| 79 | } else /* scancodes >= 0xf2 are mouse data, most likely */ | ||
| 80 | printk(KERN_INFO "atakbd: unhandled scancode %x\n", scancode); | ||
| 81 | |||
| 82 | return; | ||
| 83 | } | ||
| 84 | |||
| 85 | static int __init atakbd_init(void) | ||
| 86 | { | ||
| 87 | int i; | ||
| 88 | |||
| 89 | if (!ATARIHW_PRESENT(ST_MFP)) | ||
| 90 | return -EIO; | ||
| 91 | |||
| 92 | // TODO: request_mem_region if not done in arch code | ||
| 93 | |||
| 94 | if (!(atakbd_dev = input_allocate_device())) | ||
| 95 | return -ENOMEM; | ||
| 96 | |||
| 97 | // need to init core driver if not already done so | ||
| 98 | if (atari_keyb_init()) | ||
| 99 | return -ENODEV; | ||
| 100 | |||
| 101 | atakbd_dev->name = "Atari Keyboard"; | ||
| 102 | atakbd_dev->phys = "atakbd/input0"; | ||
| 103 | atakbd_dev->id.bustype = BUS_ATARI; | ||
| 104 | atakbd_dev->id.vendor = 0x0001; | ||
| 105 | atakbd_dev->id.product = 0x0001; | ||
| 106 | atakbd_dev->id.version = 0x0100; | ||
| 107 | |||
| 108 | atakbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
| 109 | atakbd_dev->keycode = atakbd_keycode; | ||
| 110 | atakbd_dev->keycodesize = sizeof(unsigned char); | ||
| 111 | atakbd_dev->keycodemax = ARRAY_SIZE(atakbd_keycode); | ||
| 112 | |||
| 113 | for (i = 1; i < 0x72; i++) { | ||
| 114 | atakbd_keycode[i] = i; | ||
| 115 | set_bit(atakbd_keycode[i], atakbd_dev->keybit); | ||
| 116 | } | ||
| 117 | |||
| 118 | input_register_device(atakbd_dev); | ||
| 119 | |||
| 120 | atari_input_keyboard_interrupt_hook = atakbd_interrupt; | ||
| 121 | |||
| 122 | printk(KERN_INFO "input: %s at IKBD ACIA\n", atakbd_dev->name); | ||
| 123 | |||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | static void __exit atakbd_exit(void) | ||
| 128 | { | ||
| 129 | atari_input_keyboard_interrupt_hook = NULL; | ||
| 130 | input_unregister_device(atakbd_dev); | ||
| 131 | } | ||
| 132 | |||
| 133 | module_init(atakbd_init); | ||
| 134 | module_exit(atakbd_exit); | ||
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 35d998c3e578..b40784a60aa1 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
| @@ -96,6 +96,17 @@ config MOUSE_AMIGA | |||
| 96 | To compile this driver as a module, choose M here: the | 96 | To compile this driver as a module, choose M here: the |
| 97 | module will be called amimouse. | 97 | module will be called amimouse. |
| 98 | 98 | ||
| 99 | config MOUSE_ATARI | ||
| 100 | tristate "Atari mouse" | ||
| 101 | depends on ATARI | ||
| 102 | select ATARI_KBD_CORE | ||
| 103 | help | ||
| 104 | Say Y here if you have an Atari and want its native mouse | ||
| 105 | supported by the kernel. | ||
| 106 | |||
| 107 | To compile this driver as a module, choose M here: the | ||
| 108 | module will be called atarimouse. | ||
| 109 | |||
| 99 | config MOUSE_RISCPC | 110 | config MOUSE_RISCPC |
| 100 | tristate "Acorn RiscPC mouse" | 111 | tristate "Acorn RiscPC mouse" |
| 101 | depends on ARCH_ACORN | 112 | depends on ARCH_ACORN |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 21a1de61a79b..700f61200dfc 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o | 7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o |
| 8 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o | ||
| 8 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o | 9 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o |
| 9 | obj-$(CONFIG_MOUSE_INPORT) += inport.o | 10 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
| 10 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o | 11 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o |
diff --git a/drivers/input/mouse/atarimouse.c b/drivers/input/mouse/atarimouse.c new file mode 100644 index 000000000000..43ab6566fb65 --- /dev/null +++ b/drivers/input/mouse/atarimouse.c | |||
| @@ -0,0 +1,160 @@ | |||
| 1 | /* | ||
| 2 | * Atari mouse driver for Linux/m68k | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Michael Schmitz | ||
| 5 | * | ||
| 6 | * Based on: | ||
| 7 | * Amiga mouse driver for Linux/m68k | ||
| 8 | * | ||
| 9 | * Copyright (c) 2000-2002 Vojtech Pavlik | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | /* | ||
| 13 | * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c | ||
| 14 | * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard | ||
| 15 | * interrupt is shared with the MIDI ACIA so MIDI data also get handled there). | ||
| 16 | * This driver only deals with handing key events off to the input layer. | ||
| 17 | * | ||
| 18 | * Largely based on the old: | ||
| 19 | * | ||
| 20 | * Atari Mouse Driver for Linux | ||
| 21 | * by Robert de Vries (robert@and.nl) 19Jul93 | ||
| 22 | * | ||
| 23 | * 16 Nov 1994 Andreas Schwab | ||
| 24 | * Compatibility with busmouse | ||
| 25 | * Support for three button mouse (shamelessly stolen from MiNT) | ||
| 26 | * third button wired to one of the joystick directions on joystick 1 | ||
| 27 | * | ||
| 28 | * 1996/02/11 Andreas Schwab | ||
| 29 | * Module support | ||
| 30 | * Allow multiple open's | ||
| 31 | * | ||
| 32 | * Converted to use new generic busmouse code. 5 Apr 1998 | ||
| 33 | * Russell King <rmk@arm.uk.linux.org> | ||
| 34 | */ | ||
| 35 | |||
| 36 | |||
| 37 | /* | ||
| 38 | * This program is free software; you can redistribute it and/or modify it | ||
| 39 | * under the terms of the GNU General Public License version 2 as published by | ||
| 40 | * the Free Software Foundation | ||
| 41 | */ | ||
| 42 | |||
| 43 | #include <linux/module.h> | ||
| 44 | #include <linux/init.h> | ||
| 45 | #include <linux/input.h> | ||
| 46 | #include <linux/interrupt.h> | ||
| 47 | |||
| 48 | #include <asm/irq.h> | ||
| 49 | #include <asm/setup.h> | ||
| 50 | #include <asm/system.h> | ||
| 51 | #include <asm/uaccess.h> | ||
| 52 | #include <asm/atarihw.h> | ||
| 53 | #include <asm/atarikb.h> | ||
| 54 | #include <asm/atariints.h> | ||
| 55 | |||
| 56 | MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>"); | ||
| 57 | MODULE_DESCRIPTION("Atari mouse driver"); | ||
| 58 | MODULE_LICENSE("GPL"); | ||
| 59 | |||
| 60 | static int mouse_threshold[2] = {2,2}; | ||
| 61 | |||
| 62 | #ifdef __MODULE__ | ||
| 63 | MODULE_PARM(mouse_threshold, "2i"); | ||
| 64 | #endif | ||
| 65 | #ifdef FIXED_ATARI_JOYSTICK | ||
| 66 | extern int atari_mouse_buttons; | ||
| 67 | #endif | ||
| 68 | static int atamouse_used = 0; | ||
| 69 | |||
| 70 | static struct input_dev *atamouse_dev; | ||
| 71 | |||
| 72 | static void atamouse_interrupt(char *buf) | ||
| 73 | { | ||
| 74 | int buttons, dx, dy; | ||
| 75 | |||
| 76 | /* ikbd_mouse_disable(); */ | ||
| 77 | |||
| 78 | buttons = (buf[0] & 1) | ((buf[0] & 2) << 1); | ||
| 79 | #ifdef FIXED_ATARI_JOYSTICK | ||
| 80 | buttons |= atari_mouse_buttons & 2; | ||
| 81 | atari_mouse_buttons = buttons; | ||
| 82 | #endif | ||
| 83 | /* ikbd_mouse_rel_pos(); */ | ||
| 84 | |||
| 85 | /* only relative events get here */ | ||
| 86 | dx = buf[1]; | ||
| 87 | dy = -buf[2]; | ||
| 88 | |||
| 89 | input_report_rel(atamouse_dev, REL_X, dx); | ||
| 90 | input_report_rel(atamouse_dev, REL_Y, dy); | ||
| 91 | |||
| 92 | input_report_key(atamouse_dev, BTN_LEFT, buttons & 0x1); | ||
| 93 | input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2); | ||
| 94 | input_report_key(atamouse_dev, BTN_RIGHT, buttons & 0x4); | ||
| 95 | |||
| 96 | input_sync(atamouse_dev); | ||
| 97 | |||
| 98 | return; | ||
| 99 | } | ||
| 100 | |||
| 101 | static int atamouse_open(struct input_dev *dev) | ||
| 102 | { | ||
| 103 | if (atamouse_used++) | ||
| 104 | return 0; | ||
| 105 | |||
| 106 | #ifdef FIXED_ATARI_JOYSTICK | ||
| 107 | atari_mouse_buttons = 0; | ||
| 108 | #endif | ||
| 109 | ikbd_mouse_y0_top(); | ||
| 110 | ikbd_mouse_thresh(mouse_threshold[0], mouse_threshold[1]); | ||
| 111 | ikbd_mouse_rel_pos(); | ||
| 112 | atari_input_mouse_interrupt_hook = atamouse_interrupt; | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static void atamouse_close(struct input_dev *dev) | ||
| 117 | { | ||
| 118 | if (!--atamouse_used) { | ||
| 119 | ikbd_mouse_disable(); | ||
| 120 | atari_mouse_interrupt_hook = NULL; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | static int __init atamouse_init(void) | ||
| 125 | { | ||
| 126 | if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP)) | ||
| 127 | return -ENODEV; | ||
| 128 | |||
| 129 | if (!(atamouse_dev = input_allocate_device())) | ||
| 130 | return -ENOMEM; | ||
| 131 | |||
| 132 | if (!(atari_keyb_init())) | ||
| 133 | return -ENODEV; | ||
| 134 | |||
| 135 | atamouse_dev->name = "Atari mouse"; | ||
| 136 | atamouse_dev->phys = "atamouse/input0"; | ||
| 137 | atamouse_dev->id.bustype = BUS_ATARI; | ||
| 138 | atamouse_dev->id.vendor = 0x0001; | ||
| 139 | atamouse_dev->id.product = 0x0002; | ||
| 140 | atamouse_dev->id.version = 0x0100; | ||
| 141 | |||
| 142 | atamouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
| 143 | atamouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
| 144 | atamouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
| 145 | atamouse_dev->open = atamouse_open; | ||
| 146 | atamouse_dev->close = atamouse_close; | ||
| 147 | |||
| 148 | input_register_device(atamouse_dev); | ||
| 149 | |||
| 150 | printk(KERN_INFO "input: %s at keyboard ACIA\n", atamouse_dev->name); | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static void __exit atamouse_exit(void) | ||
| 155 | { | ||
| 156 | input_unregister_device(atamouse_dev); | ||
| 157 | } | ||
| 158 | |||
| 159 | module_init(atamouse_init); | ||
| 160 | module_exit(atamouse_exit); | ||
diff --git a/include/asm-m68k/atarikb.h b/include/asm-m68k/atarikb.h index 18926058fde7..546e7da5804f 100644 --- a/include/asm-m68k/atarikb.h +++ b/include/asm-m68k/atarikb.h | |||
| @@ -36,5 +36,11 @@ void ikbd_joystick_disable(void); | |||
| 36 | extern void (*atari_MIDI_interrupt_hook) (void); | 36 | extern void (*atari_MIDI_interrupt_hook) (void); |
| 37 | /* Hook for mouse driver */ | 37 | /* Hook for mouse driver */ |
| 38 | extern void (*atari_mouse_interrupt_hook) (char *); | 38 | extern void (*atari_mouse_interrupt_hook) (char *); |
| 39 | /* Hook for keyboard inputdev driver */ | ||
| 40 | extern void (*atari_input_keyboard_interrupt_hook) (unsigned char, char); | ||
| 41 | /* Hook for mouse inputdev driver */ | ||
| 42 | extern void (*atari_input_mouse_interrupt_hook) (char *); | ||
| 43 | |||
| 44 | int atari_keyb_init(void); | ||
| 39 | 45 | ||
| 40 | #endif /* _LINUX_ATARIKB_H */ | 46 | #endif /* _LINUX_ATARIKB_H */ |
diff --git a/include/linux/input.h b/include/linux/input.h index bde65c8a3519..327122548c4d 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
| @@ -676,6 +676,7 @@ struct input_absinfo { | |||
| 676 | #define BUS_I2C 0x18 | 676 | #define BUS_I2C 0x18 |
| 677 | #define BUS_HOST 0x19 | 677 | #define BUS_HOST 0x19 |
| 678 | #define BUS_GSC 0x1A | 678 | #define BUS_GSC 0x1A |
| 679 | #define BUS_ATARI 0x1B | ||
| 679 | 680 | ||
| 680 | /* | 681 | /* |
| 681 | * Values describing the status of a force-feedback effect | 682 | * Values describing the status of a force-feedback effect |
