2 Copyright © 1995-2001, 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) SEND_INPUT_REQUEST(kbdio, kbdie, KBD_READEVENT)
35 #define SEND_GPD_REQUEST(gpdio, gpdie) SEND_INPUT_REQUEST(gpdio, gpdie, GPD_READEVENT)
37 #define SEND_TIMER_REQUEST(timerio) \
38 timerio->tr_node.io_Command = TR_ADDREQUEST; \
39 timerio->tr_time.tv_secs = 0; \
40 timerio->tr_time.tv_micro = 100000; \
41 SendIO((struct IORequest *)timerio)
43 #define SEND_KEYTIMER_REQUEST(timerio,time) \
44 timerio->tr_node.io_Command = TR_ADDREQUEST; \
45 timerio->tr_time = time; \
46 SendIO((struct IORequest *)timerio)
48 #define ABORT_KEYTIMER_REQUEST \
49 if (!CheckIO(&keytimerio->tr_node)) AbortIO(&keytimerio->tr_node); \
50 WaitIO(&keytimerio->tr_node); \
51 SetSignal(0, keytimersig);
53 #define KEY_QUALIFIERS (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | \
54 IEQUALIFIER_CAPSLOCK | IEQUALIFIER_CONTROL | \
55 IEQUALIFIER_RALT | IEQUALIFIER_LALT | \
56 IEQUALIFIER_RCOMMAND | IEQUALIFIER_RCOMMAND | \
57 IEQUALIFIER_NUMERICPAD /* | IEQUALIFIER_REPEAT */)
59 #define MOUSE_QUALIFIERS (IEQUALIFIER_LEFTBUTTON | IEQUALIFIER_RBUTTON | \
60 IEQUALIFIER_MIDBUTTON)
64 #include <aros/debug.h>
66 AROS_UFH3S(void, ResetHandler
,
67 AROS_UFHA(struct inputbase
*, InputDevice
, A1
),
68 AROS_UFHA(APTR
, code
, A5
),
69 AROS_UFHA(struct ExecBase
*, sysBase
, A6
))
73 if (InputDevice
->ResetSig
)
75 Signal(InputDevice
->InputTask
, InputDevice
->ResetSig
);
81 /**********************
83 **********************/
84 /* Forwards a chain of events to the inputhandlers */
85 VOID
ForwardQueuedEvents(struct inputbase
*InputDevice
)
87 struct InputEvent
*ie_chain
;
88 struct Interrupt
*ihiterator
;
90 ie_chain
= GetEventsFromQueue(InputDevice
);
93 ForeachNode(&(InputDevice
->HandlerList
), ihiterator
)
95 D(bug("ipe: calling inputhandler %s at %p\n",
96 ihiterator
->is_Node
.ln_Name
, ihiterator
->is_Code
));
98 ie_chain
= AROS_UFC2(struct InputEvent
*, ihiterator
->is_Code
,
99 AROS_UFCA(struct InputEvent
*, ie_chain
, A0
),
100 AROS_UFCA(APTR
, ihiterator
->is_Data
, A1
));
102 D(bug("ipe: returned from inputhandler\n"));
104 } /* for each input handler */
112 /***********************************
113 ** Input device task entry point **
114 ***********************************/
115 void ProcessEvents (struct inputbase
*InputDevice
)
117 ULONG commandsig
, kbdsig
, wakeupsigs
;
118 ULONG gpdsig
, timersig
, keytimersig
;
119 struct MsgPort
*timermp
, *keytimermp
;
120 struct timerequest
*timerio
, *keytimerio
;
122 struct MsgPort
*kbdmp
, *gpdmp
;
123 struct IOStdReq
*kbdio
, *gpdio
;
124 struct InputEvent
*kbdie
, *gpdie
, keyrepeatie
;
125 struct Interrupt resethandler
;
126 struct Library
*TimerBase
;
128 struct GamePortTrigger mouseTrigger
=
130 GPTF_DOWNKEYS
| GPTF_UPKEYS
,
131 9999, /* We dont really care about time triggers */
132 0, /* Report any mouse change */
136 BYTE controllerType
= GPCT_MOUSE
;
137 BYTE keyrepeat_state
= 0;
139 /************** Open timer.device *******************/
141 timermp
= CreateMsgPort();
142 keytimermp
= CreateMsgPort();
144 if (!timermp
|| !keytimermp
)
145 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
147 timerio
= (struct timerequest
*)CreateIORequest(timermp
, sizeof(struct timerequest
));
148 keytimerio
= (struct timerequest
*)CreateIORequest(keytimermp
, sizeof(struct timerequest
));
149 if (!timerio
|| !keytimerio
)
150 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
152 if ( 0 != OpenDevice(TIMERNAME
, UNIT_VBLANK
, (struct IORequest
*)timerio
, 0))
153 Alert(AT_DeadEnd
| AG_OpenDev
| AN_Unknown
);
155 TimerBase
= (struct Library
*)timerio
->tr_node
.io_Device
;
157 *keytimerio
= *timerio
;
158 keytimerio
->tr_node
.io_Message
.mn_ReplyPort
= keytimermp
;
160 /************** Open keyboard.device *******************/
161 kbdmp
= CreateMsgPort();
163 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
165 kbdio
= (struct IOStdReq
*)CreateIORequest(kbdmp
, sizeof(struct IOStdReq
));
167 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
169 if ( 0 != OpenDevice("keyboard.device", 0, (struct IORequest
*)kbdio
, 0))
170 Alert(AT_DeadEnd
| AG_OpenDev
| AN_Unknown
);
172 /* Install RESET Handler */
174 InputDevice
->ResetSig
= 1L << AllocSignal(-1);
176 resethandler
.is_Node
.ln_Name
= "input.device reset handler";
177 resethandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
178 resethandler
.is_Node
.ln_Pri
= -128;
180 resethandler
.is_Code
= (VOID (*)())ResetHandler
;
181 resethandler
.is_Data
= InputDevice
;
183 kbdio
->io_Command
= KBD_ADDRESETHANDLER
;
184 kbdio
->io_Data
= &resethandler
;
185 DoIO((struct IORequest
*)kbdio
);
187 kbdie
= AllocMem(sizeof (struct InputEvent
), MEMF_PUBLIC
| MEMF_CLEAR
);
189 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
192 /************** Open gameport.device *******************/
193 gpdmp
= CreateMsgPort();
195 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
197 gpdio
= (struct IOStdReq
*)CreateIORequest(gpdmp
, sizeof(struct IOStdReq
));
199 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
201 if ( 0 != OpenDevice("gameport.device", 0, (struct IORequest
*)gpdio
, 0))
202 Alert(AT_DeadEnd
| AG_OpenDev
| AN_Unknown
);
204 /* Set the controller type */
205 gpdio
->io_Command
= GPD_SETCTYPE
;
206 gpdio
->io_Data
= (APTR
)&controllerType
;
207 gpdio
->io_Length
= sizeof(BYTE
);
208 DoIO((struct IORequest
*)gpdio
);
210 /* Set the gameport trigger */
211 gpdio
->io_Command
= GPD_SETTRIGGER
;
212 gpdio
->io_Data
= &mouseTrigger
;
213 gpdio
->io_Length
= sizeof(struct GamePortTrigger
);
214 DoIO((struct IORequest
*)gpdio
);
216 gpdie
= AllocMem(sizeof (struct InputEvent
), MEMF_PUBLIC
| MEMF_CLEAR
);
218 Alert(AT_DeadEnd
| AG_NoMemory
| AN_Unknown
);
221 /* Send an initial request to the keyboard device */
222 SEND_KBD_REQUEST(kbdio
, kbdie
);
224 /* .. and to the gameport.device */
225 SEND_GPD_REQUEST(gpdio
, gpdie
);
227 /* .. and to the timer device */
228 SEND_TIMER_REQUEST(timerio
);
230 commandsig
= 1 << InputDevice
->CommandPort
.mp_SigBit
;
232 kbdsig
= 1 << kbdmp
->mp_SigBit
;
233 gpdsig
= 1 << gpdmp
->mp_SigBit
;
234 timersig
= 1 << timermp
->mp_SigBit
;
235 keytimersig
= 1 << keytimermp
->mp_SigBit
;
239 wakeupsigs
= Wait (commandsig
|
244 InputDevice
->ResetSig
|
247 D(bug("Wakeup sig: %x, cmdsig: %x, kbdsig: %x\n, timersig: %x"
248 , wakeupsigs
, commandsig
, kbdsig
, timersig
));
250 if (wakeupsigs
& SIGBREAKF_CTRL_F
)
252 struct InputEvent null_ie
;
254 null_ie
.ie_NextEvent
= NULL
;
255 null_ie
.ie_Class
= IECLASS_NULL
;
256 null_ie
.ie_SubClass
= 0;
258 null_ie
.ie_Qualifier
= 0;
259 null_ie
.ie_position
.ie_addr
= 0;
261 /* Add a timestamp to the event */
262 GetSysTime( &(null_ie
.ie_TimeStamp
));
263 AddEQTail(&null_ie
, InputDevice
);
264 ForwardQueuedEvents(InputDevice
);
267 if (wakeupsigs
& timersig
)
269 struct InputEvent timer_ie
;
273 timer_ie
.ie_NextEvent
= NULL
;
274 timer_ie
.ie_Class
= IECLASS_TIMER
;
275 timer_ie
.ie_SubClass
= 0;
276 timer_ie
.ie_Code
= 0;
277 timer_ie
.ie_Qualifier
= InputDevice
->ActQualifier
;
278 timer_ie
.ie_position
.ie_addr
= 0;
280 /* Add a timestamp to the event */
281 GetSysTime( &(timer_ie
.ie_TimeStamp
));
283 AddEQTail(&timer_ie
, InputDevice
);
284 ForwardQueuedEvents(InputDevice
);
286 SEND_TIMER_REQUEST(timerio
);
289 if (wakeupsigs
& commandsig
)
291 struct IOStdReq
*ioreq
;
293 /* Get all commands from the port */
294 while ((ioreq
= (struct IOStdReq
*)GetMsg(&InputDevice
->CommandPort
)))
297 switch (ioreq
->io_Command
)
300 Enqueue((struct List
*)&(InputDevice
->HandlerList
),
301 (struct Node
*)ioreq
->io_Data
);
305 Remove((struct Node
*)ioreq
->io_Data
);
316 * IND_ADDEVENT command allows client to send multiple RAWKEY or RAWMOUSE
317 * events to the input.device. All other classes will be ignored.
319 struct InputEvent
*ie
= (struct InputEvent
*)ioreq
->io_Data
;
320 ULONG ie_cnt
= ioreq
->io_Length
/ sizeof(struct InputEvent
);
322 D(bug("[input.device] ie_cnt=%d, ie=%d\n", ie_cnt
, ie
));
324 /* Update the current qualifier */
325 InputDevice
->ActQualifier
= ie
->ie_Qualifier
;
327 /* For each event... */
328 for (; ie_cnt
; ie_cnt
--, ie
++)
330 D(bug("[input.device] ie_Class=%02x ie_Code=%04x ie_Qualifier=%04x\n",
331 ie
->ie_Class
, ie
->ie_Code
, ie
->ie_Qualifier
));
333 /* Of class RAWMOUSE or RAWKEY... */
334 if (ie
->ie_Class
== IECLASS_RAWMOUSE
|| ie
->ie_Class
== IECLASS_RAWKEY
)
336 ie
->ie_NextEvent
= NULL
;
338 if (ie
->ie_Class
== IECLASS_RAWKEY
)
340 if (!IsQualifierKey(ie
->ie_Code
))
342 if (keyrepeat_state
> 0)
344 ABORT_KEYTIMER_REQUEST
;
348 if (!(ie
->ie_Code
& IECODE_UP_PREFIX
))
350 if (IsRepeatableKey(ie
->ie_Code
))
354 SEND_KEYTIMER_REQUEST(keytimerio
, InputDevice
->KeyRepeatThreshold
);
359 } /* if (!IsQualifierKey(ie->ie_Code)) */
362 /* If the event's qualifier differs from the current one, fire the events */
363 if (InputDevice
->ActQualifier
== ie
->ie_Qualifier
) {
364 UWORD q
= ie
->ie_Qualifier
;
365 ForwardQueuedEvents(InputDevice
);
367 /* And set new qualifier */
368 InputDevice
->ActQualifier
= q
;
371 /* Set the timestamp */
372 GetSysTime( &(ie
->ie_TimeStamp
));
375 AddEQTail(ie
, InputDevice
);
378 /* In case some events are still in the queue, fire them all up */
379 ForwardQueuedEvents(InputDevice
);
382 case IND_WRITEEVENT
: {
383 struct InputEvent
*ie
;
385 ie
= (struct InputEvent
*)ioreq
->io_Data
;
387 ie
->ie_NextEvent
= NULL
;
388 /* Add a timestamp to the event */
389 GetSysTime( &(ie
->ie_TimeStamp
));
391 D(bug("id: %d\n", ie
->ie_Class
));
393 /* Add event to queue */
394 AddEQTail((struct InputEvent
*)ioreq
->io_Data
,
397 /* Forward event (and possible others in the queue) */
398 ForwardQueuedEvents(InputDevice
);
402 InputDevice
->KeyRepeatThreshold
= ((struct timerequest
*)ioreq
)->tr_time
;
406 InputDevice
->KeyRepeatInterval
= ((struct timerequest
*)ioreq
)->tr_time
;
409 } /* switch (IO command) */
411 ReplyMsg((struct Message
*)ioreq
);
413 } /* while (messages in the command port) */
415 } /* if (IO command received) */
417 if (wakeupsigs
& keytimersig
)
419 struct InputEvent ie
;
425 ie
= keyrepeatie
; /* InputHandlers can change inputevents, so send a clone!! */
426 ie
.ie_NextEvent
= NULL
; /* !! */
427 ie
.ie_Qualifier
|= IEQUALIFIER_REPEAT
;
428 GetSysTime(&ie
.ie_TimeStamp
);
430 AddEQTail(&ie
, InputDevice
);
432 /* Forward event (and possible others in the queue) */
433 ForwardQueuedEvents(InputDevice
);
435 SEND_KEYTIMER_REQUEST(keytimerio
, InputDevice
->KeyRepeatInterval
);
437 } /* if (wakeupsigs & keytimersig) */
439 if (wakeupsigs
& kbdsig
)
441 GetMsg(kbdmp
); /* Only one message */
442 if (kbdio
->io_Error
!= 0)
445 InputDevice
->ActQualifier
&= ~KEY_QUALIFIERS
;
446 InputDevice
->ActQualifier
|= (kbdie
->ie_Qualifier
& KEY_QUALIFIERS
);
448 kbdie
->ie_Qualifier
&= ~MOUSE_QUALIFIERS
;
449 kbdie
->ie_Qualifier
|= (InputDevice
->ActQualifier
& MOUSE_QUALIFIERS
);
451 /* Add event to queue */
452 AddEQTail(kbdie
, InputDevice
);
454 if (!IsQualifierKey(kbdie
->ie_Code
))
456 if (keyrepeat_state
> 0)
458 ABORT_KEYTIMER_REQUEST
;
462 if (!(kbdie
->ie_Code
& IECODE_UP_PREFIX
))
464 if (IsRepeatableKey(kbdie
->ie_Code
))
466 keyrepeatie
= *kbdie
;
468 SEND_KEYTIMER_REQUEST(keytimerio
, InputDevice
->KeyRepeatThreshold
);
473 } /* if (!IsQualifierKey(kbdie->ie_Code)) */
475 /* New event from keyboard device */
476 D(bug("id: Keyboard event\n"));
477 D(bug("id: Events forwarded\n"));
479 /* Forward event (and possible others in the queue) */
480 ForwardQueuedEvents(InputDevice
);
481 D(bug("id: Events forwarded\n"));
483 /* Wit for some more events */
484 SEND_KBD_REQUEST(kbdio
, kbdie
);
486 } /* if (wakeupsigs & kbdsig) */
488 if (wakeupsigs
& gpdsig
)
490 GetMsg(gpdmp
); /* Only one message */
491 if (gpdio
->io_Error
!= 0)
494 InputDevice
->ActQualifier
&= ~MOUSE_QUALIFIERS
;
495 InputDevice
->ActQualifier
|= (gpdie
->ie_Qualifier
& MOUSE_QUALIFIERS
);
497 gpdie
->ie_Qualifier
&= ~KEY_QUALIFIERS
;
498 gpdie
->ie_Qualifier
|= (InputDevice
->ActQualifier
& KEY_QUALIFIERS
);
500 /* Gameport just returns the frame count since the last
501 report in ie_TimeStamp.tv_secs; we therefore must add
502 a real timestamp ourselves */
503 GetSysTime(&gpdie
->ie_TimeStamp
);
505 /* Wheel events come in as IECLASS_NEWMOUSE, so fix ie_Class and ie_Qualifier) */
506 if (gpdie
->ie_Class
== IECLASS_NEWMOUSE
)
508 #warning "The NewMouse standard seems to send both a IECLASS_NEWMOUSE and a IECLASS_RAWKEY event"
509 gpdie
->ie_Class
= IECLASS_RAWKEY
;
510 gpdie
->ie_Qualifier
= InputDevice
->ActQualifier
& KEY_QUALIFIERS
;
513 /* Add event to queue */
514 AddEQTail(gpdie
, InputDevice
);
516 /* New event from gameport device */
517 D(bug("id: Gameport event\n"));
518 D(bug("id: Forwarding events\n"));
520 /* Forward event (and possible others in the queue) */
521 ForwardQueuedEvents(InputDevice
);
522 D(bug("id: Events forwarded\n"));
524 /* Wit for some more events */
525 SEND_GPD_REQUEST(gpdio
, gpdie
);
527 } /* if (wakeupsigs & gpdsig) */
529 if (wakeupsigs
& InputDevice
->ResetSig
)
531 struct IOStdReq resetio
= *kbdio
;
533 InputDevice
->ResetSig
= 0;
537 resetio
.io_Command
= KBD_RESETHANDLERDONE
;
538 resetio
.io_Data
= &resethandler
;
540 /* Relying on this cmd being done quick, here */
542 DoIO((struct IORequest
*)&resetio
);
548 } /* ProcessEvents */