2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Code executed by the console.device task.
9 #include <exec/lists.h>
10 #include <proto/exec.h>
11 #include <proto/intuition.h>
12 #include <proto/console.h>
14 #include <exec/alerts.h>
16 #include <devices/input.h>
17 #include <devices/rawkeycodes.h>
19 #include "console_gcc.h"
20 #include "consoleif.h"
23 #include <aros/debug.h>
25 VOID
con_inject(struct ConsoleBase
*ConsoleDevice
, struct ConUnit
*cu
, const UBYTE
*data
, LONG size
)
27 struct intConUnit
*icu
= ICU(cu
);
28 ObtainSemaphore(&ConsoleDevice
->consoleTaskLock
);
31 struct intPasteData
*p
= AllocMem(sizeof(struct intPasteData
), MEMF_ANY
);
36 p
->pasteBuffer
= AllocMem(size
, MEMF_ANY
);
39 CopyMem((APTR
)data
, p
->pasteBuffer
, size
);
40 p
->pasteBufferSize
= size
;
42 AddTail((struct List
*)&icu
->pasteData
, (struct Node
*)p
);
43 D(bug("con_inject(%x %x %x %d)\n", icu
, p
, p
->pasteBuffer
, p
->pasteBufferSize
));
45 FreeMem(p
, sizeof(struct intPasteData
));
49 ReleaseSemaphore(&ConsoleDevice
->consoleTaskLock
);
50 /* Wake up possible waiting CMD_READs */
51 Signal(ConsoleDevice
->consoleTask
, SIGBREAKF_CTRL_D
);
55 static BOOL
checkconunit(Object
*unit
, struct ConsoleBase
*ConsoleDevice
);
56 static void answer_read_request(struct IOStdReq
*req
, struct ConsoleBase
*ConsoleDevice
);
58 static VOID
answer_requests(APTR unit
,struct ConsoleBase
*ConsoleDevice
)
60 struct IOStdReq
*req
, *nextreq
;
61 /* See if there are any queued io read requests that wants to be replied */
62 ForeachNodeSafe(&ConsoleDevice
->readRequests
, req
, nextreq
)
64 if ((APTR
)req
->io_Unit
== (APTR
)unit
)
67 if (0 != ICU(req
->io_Unit
)->numStoredChars
)
69 Remove((struct Node
*)req
);
70 answer_read_request(req
, ConsoleDevice
);
76 static ULONG
pasteData(struct intConUnit
* icu
, struct ConsoleBase
* ConsoleDevice
)
78 /* Check if we have data to paste to the input buffer */
79 struct intPasteData
* pd
= (struct intPasteData
*)GetHead(&icu
->pasteData
);
82 ULONG tocopy
= MIN(pd
->pasteBufferSize
- icu
->pasteBufferPos
83 , CON_INPUTBUF_SIZE
- icu
->numStoredChars
);
85 D(bug("Pasting %ld bytes\n",tocopy
));
86 CopyMem(pd
->pasteBuffer
+ icu
->pasteBufferPos
87 , icu
->inputBuf
+ icu
->numStoredChars
90 icu
->numStoredChars
+= tocopy
;
91 icu
->pasteBufferPos
+= tocopy
;
93 if (icu
->pasteBufferPos
>= pd
->pasteBufferSize
)
95 FreeMem(pd
->pasteBuffer
, pd
->pasteBufferSize
);
96 Remove((struct Node
*)pd
);
97 FreeMem(pd
,sizeof(struct intPasteData
));
98 icu
->pasteBufferPos
= 0;
101 answer_requests((APTR
)icu
, ConsoleDevice
);
107 VOID
consoleTaskEntry(struct ConsoleBase
*ConsoleDevice
)
109 BOOL success
= FALSE
;
110 LONG waitsigs
= 0L, wakeupsig
, commandsig
, inputsig
;
113 /* CD input handler puts data into this port */
114 struct MsgPort
*inputport
;
117 /* Used for input.device */
118 struct MsgPort
*inputmp
;
120 /* Add the CDInputHandler to input.device's list of input handlers */
121 inputmp
= CreateMsgPort();
124 struct IOStdReq
*inputio
;
125 inputio
= (struct IOStdReq
*)CreateIORequest(inputmp
, sizeof (struct IOStdReq
));
128 /* Open the input.device */
129 if (!OpenDevice("input.device", -1, (struct IORequest
*)inputio
, 0UL))
131 /* Initialize the inputhandler itself */
132 ConsoleDevice
->inputHandler
= initCDIH(ConsoleDevice
);
133 if (ConsoleDevice
->inputHandler
)
135 inputio
->io_Data
= ConsoleDevice
->inputHandler
;
136 inputio
->io_Command
= IND_ADDHANDLER
;
138 DoIO((struct IORequest
*)inputio
);
141 CloseDevice((struct IORequest
*)inputio
);
145 DeleteIORequest((struct IORequest
*)inputio
);
148 DeleteMsgPort(inputmp
);
151 NEWLIST(&ConsoleDevice
->readRequests
);
153 /* if not successfull, throw an alert */
156 Alert(AT_DeadEnd
| AN_ConsoleDev
| AG_OpenDev
| AO_Unknown
);
159 D(bug("Console task initialized\n"));
162 /* Get console.device input handler's port */
163 inputport
= ((struct cdihData
*)ConsoleDevice
->inputHandler
->is_Data
)->inputPort
;
165 inputsig
= 1 << inputport
->mp_SigBit
;
166 commandsig
= 1 << ConsoleDevice
->commandPort
->mp_SigBit
;
168 waitsigs
= inputsig
|commandsig
|SIGBREAKF_CTRL_C
|SIGBREAKF_CTRL_D
;
172 wakeupsig
= Wait(waitsigs
);
174 /* Anyone wanting to kill us ? */
175 if (wakeupsig
& SIGBREAKF_CTRL_C
)
180 ObtainSemaphore(&ConsoleDevice
->consoleTaskLock
);
182 if (wakeupsig
& SIGBREAKF_CTRL_D
) {
183 struct IOStdReq
*req
;
185 D(bug("SIGBREAKF_CTRL_D\n"));
186 /* console.device pasted data? */
189 ForeachNode(&ConsoleDevice
->readRequests
, req
) {
190 if (pasteData(ICU(req
->io_Unit
), ConsoleDevice
)) {
191 answer_requests(NULL
, ConsoleDevice
);
199 if (wakeupsig
& inputsig
)
201 /* A message from the console device input handler */
202 struct cdihMessage
*cdihmsg
;
204 while ( (cdihmsg
= (struct cdihMessage
*)GetMsg(inputport
)) )
207 /* Check that the ConUnit has not been disposed,
208 while the message was passed
210 if (checkconunit(cdihmsg
->unit
, ConsoleDevice
))
212 switch(cdihmsg
->ie
.ie_Class
)
214 case IECLASS_CLOSEWINDOW
:
215 /* this is a hack. It would actually be up to the */
216 /* console.device user (CON: handler for example) to */
217 /* activate CLOSEWINDOW raw events (SET RAW EVENTS cmd) */
218 /* and then look out for this in the input stream (CMD_READ) */
223 #define MAPRAWKEY_BUFSIZE 80
225 UBYTE inputBuf
[MAPRAWKEY_BUFSIZE
+ 1];
230 /* Mouse wheel support */
231 if (cdihmsg
->ie
.ie_Code
== RAWKEY_NM_WHEEL_UP
||
232 cdihmsg
->ie
.ie_Code
== RAWKEY_NM_WHEEL_DOWN
)
235 (cdihmsg
->ie
.ie_Code
== RAWKEY_NM_WHEEL_UP
) ?
237 e
.ie_Class
= IECLASS_GADGETDOWN
;
238 Console_HandleGadgets(cdihmsg
->unit
, &e
);
239 e
.ie_Class
= IECLASS_GADGETUP
;
240 Console_HandleGadgets(cdihmsg
->unit
, &e
);
245 /* Convert it to ANSI chars */
247 if (cdihmsg
->ie
.ie_Class
== IECLASS_CLOSEWINDOW
)
250 inputBuf
[0] = 28; /* CTRL-\ */
256 actual
= RawKeyConvert(&cdihmsg
->ie
261 if (cdihmsg
->ie
.ie_Qualifier
== IEQUALIFIER_RCOMMAND
&& actual
== 1)
266 D(bug("Console_Copy\n"));
267 Console_Copy(cdihmsg
->unit
);
271 D(bug("Console_Paste\n"));
272 Console_Paste(cdihmsg
->unit
);
273 /* We have likely put something into the input buffer */
274 if (ICU(cdihmsg
->unit
)->numStoredChars
) answer_requests(cdihmsg
->unit
,ConsoleDevice
);
281 D(bug("RawKeyConvert returned %ld\n", actual
));
286 /* Copy received characters to the console unit input buffer.
287 If the buffer is full, then console input will be lost
289 tocopy
= MIN(actual
, CON_INPUTBUF_SIZE
- ICU(cdihmsg
->unit
)->numStoredChars
);
290 /* Copy the input over to the unit's buffer */
292 , ICU(cdihmsg
->unit
)->inputBuf
+ ICU(cdihmsg
->unit
)->numStoredChars
296 ICU(cdihmsg
->unit
)->numStoredChars
+= tocopy
;
298 answer_requests(cdihmsg
->unit
,ConsoleDevice
);
299 } /* if (actual > 0) */
302 } /* IECLASS_RAWKEY */
305 case IECLASS_GADGETDOWN
:
306 case IECLASS_GADGETUP
:
308 case IECLASS_RAWMOUSE
:
309 Console_HandleGadgets(cdihmsg
->unit
,&(cdihmsg
->ie
));
310 //.ie_Class, (APTR)cdihmsg->ie.ie_EventAddress);
313 case IECLASS_REFRESHWINDOW
: /* Intentional fallthrough */
314 case IECLASS_SIZEWINDOW
:
316 Console_NewWindowSize(cdihmsg
->unit
);
317 } /* IECLASS_NEWSIZE */
320 D(bug("cdihmsg->ie.ie_Class = %d\n", cdihmsg
->ie
.ie_Class
));
321 } /* switch(cdihmsg->ie.ie_Class) */
324 } /* if (checkconunit(cdihmsg->unit, ConsoleDevice)) */
326 /* Tell the input handler we're done */
327 ReplyMsg((struct Message
*)cdihmsg
);
329 } /* while ( (cdihmsg = (struct cdihMessage *)GetMsg(inputport)) ) */
331 } /* if (wakeupsig & inputsig) */
333 if (wakeupsig
& commandsig
)
335 /* We got a command from the outside. Investigate it */
336 struct IOStdReq
*req
;
339 while ((req
= (struct IOStdReq
*)GetMsg(ConsoleDevice
->commandPort
)))
341 pasteData(ICU(req
->io_Unit
), ConsoleDevice
);
343 switch (req
->io_Command
)
346 if (0 != ICU(req
->io_Unit
)->numStoredChars
)
348 answer_read_request(req
, ConsoleDevice
);
352 /* Not enough bytes in the buffer to fill the request, put it on hold */
354 /* ioReq allready removed from the queue qith GetMsg() */
356 AddTail((struct List
*)&ConsoleDevice
->readRequests
, (struct Node
*)req
);
361 kprintf("!!! UNKNOWN COMMAND RECEIVED BY CONSOLE TASK !!!\n");
362 kprintf("!!! THIS SHOULD NEVER HAPPEN !!!\n");
366 } /* while ((req = (struct IOStdReq *)GetMsg(ConsoleDevice->commandPort))) */
368 } /* if (wakeupsig & commandsig) */
370 ReleaseSemaphore(&ConsoleDevice
->consoleTaskLock
);
374 /* FIXME: Do cleanup here */
378 /********** checkconunit() *******************************/
380 /* Checks that the supplied unit has not been disposed */
381 static BOOL
checkconunit(Object
*unit
, struct ConsoleBase
*ConsoleDevice
)
386 ObtainSemaphoreShared(&ConsoleDevice
->unitListLock
);
388 ostate
= (Object
*)ConsoleDevice
->unitList
.mlh_Head
;
389 while ( (o
= NextObject(&ostate
)) && (!found
) )
397 ReleaseSemaphore(&ConsoleDevice
->unitListLock
);
401 /******** answer_read_request() ***************************/
403 static void answer_read_request(struct IOStdReq
*req
, struct ConsoleBase
*ConsoleDevice
)
407 D(bug("answer_read_request\n"));
408 /* This function assumes that there are at least one character
409 available in the unitsinput buffer
412 unit
= (Object
*)req
->io_Unit
;
414 req
->io_Actual
= MIN(ICU(unit
)->numStoredChars
, req
->io_Length
);
416 /* Copy characters from the buffer into the request */
417 CopyMem( (APTR
)ICU(unit
)->inputBuf
422 if (ICU(unit
)->numStoredChars
> req
->io_Length
)
426 ICU(unit
)->numStoredChars
-= req
->io_Actual
;
428 /* We have to move the rest of the bytes to the start
431 NOTE: we could alternatively use a circular buffer
434 for (i
= 0; i
< ICU(unit
)->numStoredChars
; i
++)
436 ICU(unit
)->inputBuf
[i
] = ICU(unit
)->inputBuf
[i
+ req
->io_Actual
];
441 /* No more unread characters in the buffer */
442 ICU(unit
)->numStoredChars
= 0;
447 /* All done. Just reply the request */
449 /* stegerg: the caller of answer_read_request is responsible for the Remove,
450 because the Remove must be used only if the req was in
451 the readrequests list
452 Remove((struct Node *)req);
457 /* kprintf("receiving task=%s, sigbit=%d\n, mode=%d"
458 , ((struct Task *)req->io_Message.mn_ReplyPort->mp_SigTask)->tc_Node.ln_Name
459 , req->io_Message.mn_ReplyPort->mp_SigBit
460 , req->io_Message.mn_ReplyPort->mp_Flags
463 ReplyMsg((struct Message
*)req
);