Commit c04cb856e20a8bf68762d60737b84328c1ab5900
Committed by
Linus Torvalds
1 parent
3130d905ba
Exists in
master
and in
7 other branches
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>
Showing 11 changed files with 1059 additions and 0 deletions Side-by-side Diff
- arch/m68k/Kconfig
- arch/m68k/atari/Makefile
- arch/m68k/atari/atakeyb.c
- drivers/input/keyboard/Kconfig
- drivers/input/keyboard/Makefile
- drivers/input/keyboard/atakbd.c
- drivers/input/mouse/Kconfig
- drivers/input/mouse/Makefile
- drivers/input/mouse/atarimouse.c
- include/asm-m68k/atarikb.h
- include/linux/input.h
arch/m68k/Kconfig
... | ... | @@ -409,6 +409,9 @@ |
409 | 409 | help |
410 | 410 | Say Y here to report ST-RAM usage statistics in /proc/stram. |
411 | 411 | |
412 | +config ATARI_KBD_CORE | |
413 | + bool | |
414 | + | |
412 | 415 | config HEARTBEAT |
413 | 416 | bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40 |
414 | 417 | default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300 |
arch/m68k/atari/Makefile
arch/m68k/atari/atakeyb.c
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 | +} |
drivers/input/keyboard/Kconfig
... | ... | @@ -164,6 +164,17 @@ |
164 | 164 | To compile this driver as a module, choose M here: the |
165 | 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 | 178 | config KEYBOARD_HIL_OLD |
168 | 179 | tristate "HP HIL keyboard support (simple driver)" |
169 | 180 | depends on GSC || HP300 |
drivers/input/keyboard/Makefile
... | ... | @@ -9,6 +9,7 @@ |
9 | 9 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o |
10 | 10 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
11 | 11 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
12 | +obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | |
12 | 13 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o |
13 | 14 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o |
14 | 15 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
drivers/input/keyboard/atakbd.c
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); |
drivers/input/mouse/Kconfig
... | ... | @@ -96,6 +96,17 @@ |
96 | 96 | To compile this driver as a module, choose M here: the |
97 | 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 | 110 | config MOUSE_RISCPC |
100 | 111 | tristate "Acorn RiscPC mouse" |
101 | 112 | depends on ARCH_ACORN |
drivers/input/mouse/Makefile
... | ... | @@ -5,6 +5,7 @@ |
5 | 5 | # Each configuration option enables a list of files. |
6 | 6 | |
7 | 7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o |
8 | +obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o | |
8 | 9 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o |
9 | 10 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
10 | 11 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o |
drivers/input/mouse/atarimouse.c
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); |
include/asm-m68k/atarikb.h
... | ... | @@ -36,6 +36,12 @@ |
36 | 36 | extern void (*atari_MIDI_interrupt_hook) (void); |
37 | 37 | /* Hook for mouse driver */ |
38 | 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 | 46 | #endif /* _LINUX_ATARIKB_H */ |