2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
9 #include <proto/exec.h>
10 #include <proto/timer.h>
11 #include <proto/graphics.h>
13 #include <exec/lists.h>
14 #include <exec/interrupts.h>
15 #include <exec/alerts.h>
16 #include <exec/memory.h>
17 #include <devices/inputevent.h>
18 #include <devices/input.h>
19 #include <devices/timer.h>
20 #include <devices/keyboard.h>
21 #include <devices/gameport.h>
22 #include <intuition/intuition.h>
23 #include <aros/asmcall.h>
25 #include "input_intern.h"
27 #define SEND_INPUT_REQUEST(io, ie, cmd) \
28 io->io_Command = cmd; \
29 io->io_Data = (APTR)ie; \
30 io->io_Length = sizeof (struct InputEvent); \
31 SendIO((struct IORequest *)io)
34 #define SEND_KBD_REQUEST(kbdio, kbdie) \
35 SEND_INPUT_REQUEST(kbdio, kbdie, KBD_READEVENT)
36 #define SEND_GPD_REQUEST(gpdio, gpdie) \
37 SEND_INPUT_REQUEST(gpdio, gpdie, GPD_READEVENT)
39 #define SEND_TIMER_REQUEST(timerio) \
40 timerio->tr_node.io_Command = TR_ADDREQUEST; \
41 timerio->tr_time.tv_secs = 0; \
42 timerio->tr_time.tv_micro = 100000; \
43 SendIO((struct IORequest *)timerio)
45 #define SEND_KEYTIMER_REQUEST(timerio,time) \
46 timerio->tr_node.io_Command = TR_ADDREQUEST; \
47 timerio->tr_time = time; \
48 SendIO((struct IORequest *)timerio)
50 #define ABORT_KEYTIMER_REQUEST \
51 if (!CheckIO(&keytimerio->tr_node)) AbortIO(&keytimerio->tr_node); \
52 WaitIO(&keytimerio->tr_node); \
53 SetSignal(0, keytimersig);
55 #define KEY_QUALIFIERS (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | \
56 IEQUALIFIER_CAPSLOCK | IEQUALIFIER_CONTROL | \
57 IEQUALIFIER_RALT | IEQUALIFIER_LALT | \
58 IEQUALIFIER_RCOMMAND | IEQUALIFIER_RCOMMAND | \
59 IEQUALIFIER_NUMERICPAD /* | IEQUALIFIER_REPEAT */)
61 #define MOUSE_QUALIFIERS (IEQUALIFIER_LEFTBUTTON | IEQUALIFIER_RBUTTON | \
62 IEQUALIFIER_MIDBUTTON)
66 #include <aros/debug.h>
68 AROS_INTH1(ResetHandler
, struct inputbase
*, InputDevice
)
72 if (InputDevice
->ResetSig
)
74 Signal(InputDevice
->InputTask
, InputDevice
->ResetSig
);
82 /**********************
84 **********************/
87 extern APTR
is_Code_Wrapper(void);
88 asm(".global is_Code_Wrapper\n"
90 "movem.l %d2-%d4/%a2,%sp@-\n"
91 "jsr (%a2)\n" "movem.l %sp@+,%d2-%d4/%a2\n" "rts\n");
94 /* Forwards a chain of events to the inputhandlers */
95 VOID
ForwardQueuedEvents(struct inputbase
*InputDevice
)
97 struct InputEvent
*ie_chain
;
98 struct Interrupt
*ihiterator
;
100 ie_chain
= GetEventsFromQueue(InputDevice
);
103 ForeachNode(&(InputDevice
->HandlerList
), ihiterator
)
105 D(bug("ipe: calling inputhandler %s at %p\n",
106 ihiterator
->is_Node
.ln_Name
, ihiterator
->is_Code
));
109 /* There are many m68k applications that expect to be able
110 * to clobber a number of registers in their code.
112 * We need the wrapper to save/restore those registers.
114 ie_chain
= AROS_UFC3(struct InputEvent
*, is_Code_Wrapper
,
115 AROS_UFCA(struct InputEvent
*, ie_chain
, A0
),
116 AROS_UFCA(APTR
, ihiterator
->is_Data
, A1
),
117 AROS_UFCA(APTR
, ihiterator
->is_Code
, A2
))
119 ie_chain
= AROS_UFC2(struct InputEvent
*, ihiterator
->is_Code
,
120 AROS_UFCA(struct InputEvent
*, ie_chain
, A0
),
121 AROS_UFCA(APTR
, ihiterator
->is_Data
, A1
));
123 D(bug("ipe: returned from inputhandler\n"));
132 /***********************************
133 ** Input device task entry point **
134 ***********************************/
135 void ProcessEvents(struct inputbase
*InputDevice
)
137 ULONG commandsig
, kbdsig
, wakeupsigs
;
138 ULONG gpdsig
, timersig
, keytimersig
;
139 struct MsgPort
*timermp
, *keytimermp
;
140 struct timerequest
*timerio
, *keytimerio
;
142 struct MsgPort
*kbdmp
, *gpdmp
;
143 struct IOStdReq
*kbdio
, *gpdio
;
144 struct InputEvent
*kbdie
, *gpdie
, keyrepeatie
;
145 struct Interrupt resethandler
;
146 struct Library
*TimerBase
;
148 struct GamePortTrigger mouseTrigger
= {
149 GPTF_DOWNKEYS
| GPTF_UPKEYS
,
150 9999, /* We don't really care about time triggers */
151 0, /* Report any mouse change */
155 BYTE controllerType
= GPCT_MOUSE
;
156 BYTE keyrepeat_state
= 0;
158 /************** Open timer.device *******************/
160 timermp
= CreateMsgPort();
161 keytimermp
= CreateMsgPort();
163 if (!timermp
|| !keytimermp
)
164 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
167 (struct timerequest
*)CreateIORequest(timermp
,
168 sizeof(struct timerequest
));
170 (struct timerequest
*)CreateIORequest(keytimermp
,
171 sizeof(struct timerequest
));
172 if (!timerio
|| !keytimerio
)
173 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
175 if (0 != OpenDevice(TIMERNAME
, UNIT_VBLANK
, (struct IORequest
*)timerio
,
177 Alert(AT_DeadEnd
| AG_OpenDev
| AN_Unknown
);
179 TimerBase
= (struct Library
*)timerio
->tr_node
.io_Device
;
181 *keytimerio
= *timerio
;
182 keytimerio
->tr_node
.io_Message
.mn_ReplyPort
= keytimermp
;
184 /************** Open keyboard.device *******************/
185 kbdmp
= CreateMsgPort();
187 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
190 (struct IOStdReq
*)CreateIORequest(kbdmp
, sizeof(struct IOStdReq
));
192 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
194 if (0 != OpenDevice("keyboard.device", 0, (struct IORequest
*)kbdio
, 0))
195 Alert(AT_DeadEnd
| AG_OpenDev
| AN_Unknown
);
197 /* Install RESET Handler */
199 InputDevice
->ResetSig
= 1L << AllocSignal(-1);
201 resethandler
.is_Node
.ln_Name
= "input.device reset handler";
202 resethandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
203 resethandler
.is_Node
.ln_Pri
= -128;
205 resethandler
.is_Code
= (VOID_FUNC
) ResetHandler
;
206 resethandler
.is_Data
= InputDevice
;
208 kbdio
->io_Command
= KBD_ADDRESETHANDLER
;
209 kbdio
->io_Data
= &resethandler
;
210 DoIO((struct IORequest
*)kbdio
);
212 kbdie
= AllocMem(sizeof(struct InputEvent
), MEMF_PUBLIC
| MEMF_CLEAR
);
214 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
217 /************** Open gameport.device *******************/
218 gpdmp
= CreateMsgPort();
220 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
223 (struct IOStdReq
*)CreateIORequest(gpdmp
, sizeof(struct IOStdReq
));
225 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
227 if (0 != OpenDevice("gameport.device", 0, (struct IORequest
*)gpdio
, 0))
228 Alert(AT_DeadEnd
| AG_OpenDev
| AN_Unknown
);
230 /* Set the controller type */
231 gpdio
->io_Command
= GPD_SETCTYPE
;
232 gpdio
->io_Data
= (APTR
) &controllerType
;
233 gpdio
->io_Length
= sizeof(BYTE
);
234 DoIO((struct IORequest
*)gpdio
);
236 /* Set the gameport trigger */
237 gpdio
->io_Command
= GPD_SETTRIGGER
;
238 gpdio
->io_Data
= &mouseTrigger
;
239 gpdio
->io_Length
= sizeof(struct GamePortTrigger
);
240 DoIO((struct IORequest
*)gpdio
);
242 gpdie
= AllocMem(sizeof(struct InputEvent
), MEMF_PUBLIC
| MEMF_CLEAR
);
244 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
247 /* Send an initial request to the keyboard device */
248 SEND_KBD_REQUEST(kbdio
, kbdie
);
250 /* ...and to gameport.device */
251 SEND_GPD_REQUEST(gpdio
, gpdie
);
253 /* ...and to timer.device */
254 SEND_TIMER_REQUEST(timerio
);
256 commandsig
= 1 << InputDevice
->CommandPort
->mp_SigBit
;
258 kbdsig
= 1 << kbdmp
->mp_SigBit
;
259 gpdsig
= 1 << gpdmp
->mp_SigBit
;
260 timersig
= 1 << timermp
->mp_SigBit
;
261 keytimersig
= 1 << keytimermp
->mp_SigBit
;
265 wakeupsigs
= Wait(commandsig
|
267 gpdsig
| timersig
| keytimersig
| InputDevice
->ResetSig
);
269 D(bug("Wakeup sig: %x, cmdsig: %x, kbdsig: %x\n, timersig: %x",
270 wakeupsigs
, commandsig
, kbdsig
, timersig
));
272 if (wakeupsigs
& timersig
)
274 struct InputEvent timer_ie
;
278 timer_ie
.ie_NextEvent
= NULL
;
279 timer_ie
.ie_Class
= IECLASS_TIMER
;
280 timer_ie
.ie_SubClass
= 0;
281 timer_ie
.ie_Code
= 0;
282 timer_ie
.ie_Qualifier
= InputDevice
->ActQualifier
;
283 timer_ie
.ie_position
.ie_addr
= 0;
285 /* Add a timestamp to the event */
286 GetSysTime(&(timer_ie
.ie_TimeStamp
));
288 AddEQTail(&timer_ie
, InputDevice
);
289 ForwardQueuedEvents(InputDevice
);
291 SEND_TIMER_REQUEST(timerio
);
294 if (wakeupsigs
& commandsig
)
296 struct IOStdReq
*ioreq
;
298 /* Get all commands from the port */
300 (struct IOStdReq
*)GetMsg(InputDevice
->CommandPort
)))
303 switch (ioreq
->io_Command
)
307 /* Older m68k programs copied input handler code without
308 * flushing caches, causing crashes on 68040/060.
312 Enqueue((struct List
*)&(InputDevice
->HandlerList
),
313 (struct Node
*)ioreq
->io_Data
);
317 Remove((struct Node
*)ioreq
->io_Data
);
329 * IND_ADDEVENT command allows client to send multiple
330 * RAWKEY or RAWMOUSE events to the input.device. All
331 * other classes will be ignored.
333 struct InputEvent
*ie
=
334 (struct InputEvent
*)ioreq
->io_Data
;
336 ioreq
->io_Length
/ sizeof(struct InputEvent
);
338 D(bug("[input.device] ie_cnt=%d, ie=%d\n", ie_cnt
,
341 /* Update the current qualifier */
342 InputDevice
->ActQualifier
= ie
->ie_Qualifier
;
344 /* For each event... */
345 for (; ie_cnt
; ie_cnt
--, ie
++)
347 D(bug("[input.device] ie_Class=%02x ie_Code=%04x"
348 " ie_Qualifier=%04x\n",
349 ie
->ie_Class
, ie
->ie_Code
,
352 /* Of class RAWMOUSE or RAWKEY... */
353 if (ie
->ie_Class
== IECLASS_RAWMOUSE
354 || ie
->ie_Class
== IECLASS_RAWKEY
)
356 ie
->ie_NextEvent
= NULL
;
358 if (ie
->ie_Class
== IECLASS_RAWKEY
)
360 if (!IsQualifierKey(ie
->ie_Code
))
362 if (keyrepeat_state
> 0)
364 ABORT_KEYTIMER_REQUEST
;
368 if (!(ie
->ie_Code
& IECODE_UP_PREFIX
))
370 if (IsRepeatableKey(ie
->
375 SEND_KEYTIMER_REQUEST
386 /* If the event's qualifier differs from the
387 current one, fire the events */
388 if (InputDevice
->ActQualifier
==
391 UWORD q
= ie
->ie_Qualifier
;
392 ForwardQueuedEvents(InputDevice
);
394 /* And set new qualifier */
395 InputDevice
->ActQualifier
= q
;
398 /* Set the timestamp */
399 GetSysTime(&(ie
->ie_TimeStamp
));
402 AddEQTail(ie
, InputDevice
);
405 /* In case some events are still in the queue, fire
407 ForwardQueuedEvents(InputDevice
);
413 struct InputEvent
*ie
;
415 ie
= (struct InputEvent
*)ioreq
->io_Data
;
417 ie
->ie_NextEvent
= NULL
;
418 /* Add a timestamp to the event */
419 GetSysTime(&(ie
->ie_TimeStamp
));
421 D(bug("id: %d\n", ie
->ie_Class
));
423 /* Add event to queue */
424 AddEQTail((struct InputEvent
*)ioreq
->io_Data
,
427 /* Forward event (and possible others in the queue) */
428 ForwardQueuedEvents(InputDevice
);
432 InputDevice
->KeyRepeatThreshold
=
433 ((struct timerequest
*)ioreq
)->tr_time
;
437 InputDevice
->KeyRepeatInterval
=
438 ((struct timerequest
*)ioreq
)->tr_time
;
443 ReplyMsg((struct Message
*)ioreq
);
447 if (wakeupsigs
& keytimersig
)
449 struct InputEvent ie
;
455 /* InputHandlers can change inputevents, so send a clone */
457 ie
.ie_NextEvent
= NULL
; /* !! */
458 ie
.ie_Qualifier
|= IEQUALIFIER_REPEAT
;
459 GetSysTime(&ie
.ie_TimeStamp
);
461 AddEQTail(&ie
, InputDevice
);
463 /* Forward event (and possible others in the queue) */
464 ForwardQueuedEvents(InputDevice
);
466 SEND_KEYTIMER_REQUEST(keytimerio
,
467 InputDevice
->KeyRepeatInterval
);
470 if (wakeupsigs
& kbdsig
)
472 GetMsg(kbdmp
); /* Only one message */
473 if (kbdio
->io_Error
!= 0)
476 InputDevice
->ActQualifier
&= ~KEY_QUALIFIERS
;
477 InputDevice
->ActQualifier
|=
478 (kbdie
->ie_Qualifier
& KEY_QUALIFIERS
);
480 kbdie
->ie_Qualifier
&= ~MOUSE_QUALIFIERS
;
481 kbdie
->ie_Qualifier
|=
482 (InputDevice
->ActQualifier
& MOUSE_QUALIFIERS
);
484 /* Add event to queue */
485 AddEQTail(kbdie
, InputDevice
);
487 if (!IsQualifierKey(kbdie
->ie_Code
))
489 if (keyrepeat_state
> 0)
491 ABORT_KEYTIMER_REQUEST
;
495 if (!(kbdie
->ie_Code
& IECODE_UP_PREFIX
))
497 if (IsRepeatableKey(kbdie
->ie_Code
))
499 keyrepeatie
= *kbdie
;
501 SEND_KEYTIMER_REQUEST(keytimerio
,
502 InputDevice
->KeyRepeatThreshold
);
509 /* New event from keyboard device */
510 D(bug("id: Keyboard event\n"));
511 D(bug("id: Events forwarded\n"));
513 /* Forward event (and possible others in the queue) */
514 ForwardQueuedEvents(InputDevice
);
515 D(bug("id: Events forwarded\n"));
517 /* Wait for some more events */
518 SEND_KBD_REQUEST(kbdio
, kbdie
);
521 if (wakeupsigs
& gpdsig
)
523 GetMsg(gpdmp
); /* Only one message */
524 if (gpdio
->io_Error
!= 0)
527 InputDevice
->ActQualifier
&= ~MOUSE_QUALIFIERS
;
528 InputDevice
->ActQualifier
|=
529 (gpdie
->ie_Qualifier
& MOUSE_QUALIFIERS
);
531 gpdie
->ie_Qualifier
&= ~KEY_QUALIFIERS
;
532 gpdie
->ie_Qualifier
|=
533 (InputDevice
->ActQualifier
& KEY_QUALIFIERS
);
535 /* Gameport just returns the frame count since the last
536 report in ie_TimeStamp.tv_secs; we therefore must add
537 a real timestamp ourselves */
538 GetSysTime(&gpdie
->ie_TimeStamp
);
540 /* Wheel events come in as IECLASS_NEWMOUSE, so fix ie_Class
542 if (gpdie
->ie_Class
== IECLASS_NEWMOUSE
)
544 /* The NewMouse standard seems to send both an
545 IECLASS_NEWMOUSE and an IECLASS_RAWKEY event */
546 gpdie
->ie_Class
= IECLASS_RAWKEY
;
547 gpdie
->ie_Qualifier
=
548 InputDevice
->ActQualifier
& KEY_QUALIFIERS
;
551 /* Add event to queue */
552 AddEQTail(gpdie
, InputDevice
);
554 /* New event from gameport device */
555 D(bug("id: Gameport event\n"));
556 D(bug("id: Forwarding events\n"));
558 /* Forward event (and possible others in the queue) */
559 ForwardQueuedEvents(InputDevice
);
560 D(bug("id: Events forwarded\n"));
562 /* Wait for some more events */
563 SEND_GPD_REQUEST(gpdio
, gpdie
);
566 if (wakeupsigs
& InputDevice
->ResetSig
)
568 struct IOStdReq resetio
= *kbdio
;
569 struct Library
*GfxBase
=
570 TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS
);
572 InputDevice
->ResetSig
= 0;
574 /* Blank screen(s) in order to indicate upcoming machine reset.
575 Don't blank on m68k because we have programs that show status
576 information while waiting for reset. */
582 CloseLibrary(GfxBase
);
585 resetio
.io_Command
= KBD_RESETHANDLERDONE
;
586 resetio
.io_Data
= &resethandler
;
588 /* Relying on this cmd being done quick, here */
590 DoIO((struct IORequest
*)&resetio
);