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 |