2 Copyright © 1995-2014, 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
,
26 const UBYTE
*data
, LONG size
)
28 struct intConUnit
*icu
= ICU(cu
);
29 ObtainSemaphore(&ConsoleDevice
->consoleTaskLock
);
32 struct intPasteData
*p
=
33 AllocMem(sizeof(struct intPasteData
), MEMF_ANY
);
38 p
->pasteBuffer
= AllocMem(size
, MEMF_ANY
);
41 CopyMem((APTR
) data
, p
->pasteBuffer
, size
);
42 p
->pasteBufferSize
= size
;
44 AddTail((struct List
*)&icu
->pasteData
, (struct Node
*)p
);
45 D(bug("con_inject(%x %x %x %d)\n", icu
, p
, p
->pasteBuffer
,
50 FreeMem(p
, sizeof(struct intPasteData
));
54 ReleaseSemaphore(&ConsoleDevice
->consoleTaskLock
);
55 /* Wake up possible waiting CMD_READs */
56 Signal(ConsoleDevice
->consoleTask
, SIGBREAKF_CTRL_D
);
60 static BOOL
checkconunit(Object
*unit
, struct ConsoleBase
*ConsoleDevice
);
61 static void answer_read_request(struct IOStdReq
*req
,
62 struct ConsoleBase
*ConsoleDevice
);
64 static VOID
answer_requests(APTR unit
, struct ConsoleBase
*ConsoleDevice
)
66 struct IOStdReq
*req
, *nextreq
;
67 /* See if there are any queued io read requests that wants to be replied */
68 ForeachNodeSafe(&ConsoleDevice
->readRequests
, req
, nextreq
)
70 if ((APTR
) req
->io_Unit
== (APTR
) unit
)
73 if (0 != ICU(req
->io_Unit
)->numStoredChars
)
75 Remove((struct Node
*)req
);
76 answer_read_request(req
, ConsoleDevice
);
82 static ULONG
pasteData(struct intConUnit
*icu
,
83 struct ConsoleBase
*ConsoleDevice
)
85 /* Check if we have data to paste to the input buffer */
86 struct intPasteData
*pd
=
87 (struct intPasteData
*)GetHead(&icu
->pasteData
);
91 MIN(pd
->pasteBufferSize
- icu
->pasteBufferPos
,
92 CON_INPUTBUF_SIZE
- icu
->numStoredChars
);
94 D(bug("Pasting %ld bytes\n", tocopy
));
95 CopyMem(pd
->pasteBuffer
+ icu
->pasteBufferPos
,
96 icu
->inputBuf
+ icu
->numStoredChars
, tocopy
);
97 icu
->numStoredChars
+= tocopy
;
98 icu
->pasteBufferPos
+= tocopy
;
100 if (icu
->pasteBufferPos
>= pd
->pasteBufferSize
)
102 FreeMem(pd
->pasteBuffer
, pd
->pasteBufferSize
);
103 Remove((struct Node
*)pd
);
104 FreeMem(pd
, sizeof(struct intPasteData
));
105 icu
->pasteBufferPos
= 0;
108 answer_requests((APTR
) icu
, ConsoleDevice
);
114 VOID
consoleTaskEntry(struct ConsoleBase
*ConsoleDevice
)
116 BOOL success
= FALSE
;
117 LONG waitsigs
= 0L, wakeupsig
, commandsig
, inputsig
;
120 /* CD input handler puts data into this port */
121 struct MsgPort
*inputport
;
124 /* Used for input.device */
125 struct MsgPort
*inputmp
;
127 /* Add the CDInputHandler to input.device's list of input handlers */
128 inputmp
= CreateMsgPort();
131 struct IOStdReq
*inputio
;
133 (struct IOStdReq
*)CreateIORequest(inputmp
,
134 sizeof(struct IOStdReq
));
137 /* Open the input.device */
138 if (!OpenDevice("input.device", -1, (struct IORequest
*)inputio
,
141 /* Initialize the inputhandler itself */
142 ConsoleDevice
->inputHandler
= initCDIH(ConsoleDevice
);
143 if (ConsoleDevice
->inputHandler
)
145 inputio
->io_Data
= ConsoleDevice
->inputHandler
;
146 inputio
->io_Command
= IND_ADDHANDLER
;
148 DoIO((struct IORequest
*)inputio
);
151 CloseDevice((struct IORequest
*)inputio
);
155 DeleteIORequest((struct IORequest
*)inputio
);
158 DeleteMsgPort(inputmp
);
161 NEWLIST(&ConsoleDevice
->readRequests
);
163 /* if not successful, throw an alert */
166 Alert(AT_DeadEnd
| AN_ConsoleDev
| AG_OpenDev
| AO_Unknown
);
169 D(bug("Console task initialized\n"));
172 /* Get console.device input handler's port */
174 ((struct cdihData
*)ConsoleDevice
->inputHandler
->is_Data
)->
177 inputsig
= 1 << inputport
->mp_SigBit
;
178 commandsig
= 1 << ConsoleDevice
->commandPort
->mp_SigBit
;
180 waitsigs
= inputsig
| commandsig
| SIGBREAKF_CTRL_C
| SIGBREAKF_CTRL_D
;
184 wakeupsig
= Wait(waitsigs
);
186 /* Anyone wanting to kill us ? */
187 if (wakeupsig
& SIGBREAKF_CTRL_C
)
192 ObtainSemaphore(&ConsoleDevice
->consoleTaskLock
);
194 if (wakeupsig
& SIGBREAKF_CTRL_D
)
196 struct IOStdReq
*req
;
198 D(bug("SIGBREAKF_CTRL_D\n"));
199 /* console.device pasted data? */
203 ForeachNode(&ConsoleDevice
->readRequests
, req
)
205 if (pasteData(ICU(req
->io_Unit
), ConsoleDevice
))
207 answer_requests(NULL
, ConsoleDevice
);
215 if (wakeupsig
& inputsig
)
217 /* A message from the console device input handler */
218 struct cdihMessage
*cdihmsg
;
220 while ((cdihmsg
= (struct cdihMessage
*)GetMsg(inputport
)))
222 /* Check that the ConUnit has not been disposed,
223 while the message was passed
225 if (checkconunit(cdihmsg
->unit
, ConsoleDevice
))
227 switch (cdihmsg
->ie
.ie_Class
)
229 case IECLASS_CLOSEWINDOW
:
230 /* this is a hack. It would actually be up to the
231 * console.device user (CON: handler for example) to
232 * activate CLOSEWINDOW raw events (SET RAW EVENTS cmd)
233 * and then look out for this in the input stream
239 #define MAPRAWKEY_BUFSIZE 80
241 UBYTE inputBuf
[MAPRAWKEY_BUFSIZE
+ 1];
246 /* Mouse wheel support */
247 if (cdihmsg
->ie
.ie_Code
== RAWKEY_NM_WHEEL_UP
||
248 cdihmsg
->ie
.ie_Code
== RAWKEY_NM_WHEEL_DOWN
)
251 (cdihmsg
->ie
.ie_Code
==
252 RAWKEY_NM_WHEEL_UP
) ? (APTR
) 1 : (APTR
)
254 e
.ie_Class
= IECLASS_GADGETDOWN
;
255 Console_HandleGadgets(cdihmsg
->unit
, &e
);
256 e
.ie_Class
= IECLASS_GADGETUP
;
257 Console_HandleGadgets(cdihmsg
->unit
, &e
);
261 /* Convert it to ANSI chars */
263 if (cdihmsg
->ie
.ie_Class
==
267 inputBuf
[0] = 28; /* CTRL-\ */
274 RawKeyConvert(&cdihmsg
->ie
,
275 inputBuf
, MAPRAWKEY_BUFSIZE
, NULL
);
277 if (cdihmsg
->ie
.ie_Qualifier
==
278 IEQUALIFIER_RCOMMAND
&& actual
== 1)
283 D(bug("Console_Copy\n"));
284 Console_Copy(cdihmsg
->unit
);
288 D(bug("Console_Paste\n"));
289 Console_Paste(cdihmsg
->unit
);
290 /* We have likely put something
291 * into the input buffer */
292 if (ICU(cdihmsg
->unit
)->
294 answer_requests(cdihmsg
->
295 unit
, ConsoleDevice
);
302 D(bug("RawKeyConvert returned %ld\n",
308 /* Copy received characters to the console
309 * unit input buffer. If the buffer is
310 * full, then console input will be lost
315 ICU(cdihmsg
->unit
)->numStoredChars
);
317 /* Copy the input over to the unit's
320 ICU(cdihmsg
->unit
)->inputBuf
+
321 ICU(cdihmsg
->unit
)->numStoredChars
,
324 ICU(cdihmsg
->unit
)->numStoredChars
+=
327 answer_requests(cdihmsg
->unit
,
329 } /* if (actual > 0) */
334 case IECLASS_GADGETDOWN
:
335 case IECLASS_GADGETUP
:
337 case IECLASS_RAWMOUSE
:
338 Console_HandleGadgets(cdihmsg
->unit
,
340 //.ie_Class, (APTR)cdihmsg->ie.ie_EventAddress);
343 case IECLASS_REFRESHWINDOW
:
344 case IECLASS_SIZEWINDOW
:
346 /* Intentionally empty (Begin|End)Refresh() pair,
347 * as we are required to call them to keep
348 * Intuition informed, but we don't want to be
349 * restricted to rendering just in the damaged
350 * area (WFLG_NOCAREREFRESH is another possibility,
351 * but it's not our window). */
352 BeginRefresh(WINDOW(cdihmsg
->unit
));
353 EndRefresh(WINDOW(cdihmsg
->unit
), TRUE
);
355 /* Refresh window contents */
356 Console_NewWindowSize(cdihmsg
->unit
);
360 D(bug("cdihmsg->ie.ie_Class = %d\n",
361 cdihmsg
->ie
.ie_Class
));
362 } /* switch(cdihmsg->ie.ie_Class) */
363 } /* if (checkconunit(cdihmsg->unit, ConsoleDevice)) */
365 /* Tell the input handler we're done */
366 ReplyMsg((struct Message
*)cdihmsg
);
367 } /* while ((cdihmsg = (struct cdihMessage *)GetMsg(inputport))) */
368 } /* if (wakeupsig & inputsig) */
370 if (wakeupsig
& commandsig
)
372 /* We got a command from the outside. Investigate it */
373 struct IOStdReq
*req
;
376 (struct IOStdReq
*)GetMsg(ConsoleDevice
->commandPort
)))
378 pasteData(ICU(req
->io_Unit
), ConsoleDevice
);
380 switch (req
->io_Command
)
383 if (0 != ICU(req
->io_Unit
)->numStoredChars
)
385 answer_read_request(req
, ConsoleDevice
);
389 /* Not enough bytes in the buffer to fill the request,
390 * put it on hold. ioReq already removed from the
391 * queue with GetMsg() */
392 AddTail((struct List
*)&ConsoleDevice
->readRequests
,
399 ("!!! UNKNOWN COMMAND RECEIVED BY CONSOLE TASK !!!\n");
400 kprintf("!!! THIS SHOULD NEVER HAPPEN !!!\n");
404 } /* while ((req = (struct IOStdReq *)GetMsg(ConsoleDevice->commandPort))) */
406 } /* if (wakeupsig & commandsig) */
408 ReleaseSemaphore(&ConsoleDevice
->consoleTaskLock
);
411 /* FIXME: Do cleanup here */
414 /********** checkconunit() *******************************/
416 /* Checks that the supplied unit has not been disposed */
417 static BOOL
checkconunit(Object
*unit
, struct ConsoleBase
*ConsoleDevice
)
422 ObtainSemaphoreShared(&ConsoleDevice
->unitListLock
);
424 ostate
= (Object
*) ConsoleDevice
->unitList
.mlh_Head
;
425 while ((o
= NextObject(&ostate
)) && (!found
))
433 ReleaseSemaphore(&ConsoleDevice
->unitListLock
);
437 /******** answer_read_request() ***************************/
439 static void answer_read_request(struct IOStdReq
*req
,
440 struct ConsoleBase
*ConsoleDevice
)
444 D(bug("answer_read_request\n"));
445 /* This function assumes that there are at least one character
446 available in the unitsinput buffer
449 unit
= (Object
*) req
->io_Unit
;
451 req
->io_Actual
= MIN(ICU(unit
)->numStoredChars
, req
->io_Length
);
453 /* Copy characters from the buffer into the request */
454 CopyMem((APTR
) ICU(unit
)->inputBuf
, req
->io_Data
, req
->io_Actual
);
456 if (ICU(unit
)->numStoredChars
> req
->io_Length
)
460 ICU(unit
)->numStoredChars
-= req
->io_Actual
;
462 /* We have to move the rest of the bytes to the start
465 NOTE: we could alternatively use a circular buffer
468 for (i
= 0; i
< ICU(unit
)->numStoredChars
; i
++)
470 ICU(unit
)->inputBuf
[i
] =
471 ICU(unit
)->inputBuf
[i
+ req
->io_Actual
];
476 /* No more unread characters in the buffer */
477 ICU(unit
)->numStoredChars
= 0;
482 /* All done. Just reply the request */
484 /* stegerg: caller of answer_read_request is responsible for the Remove,
485 because the Remove must be used only if the req was in
486 the readrequests list
487 Remove((struct Node *)req);
491 /* kprintf("receiving task=%s, sigbit=%d\n, mode=%d"
492 , ((struct Task *)req->io_Message.mn_ReplyPort->mp_SigTask)->tc_Node.ln_Name
493 , req->io_Message.mn_ReplyPort->mp_SigBit
494 , req->io_Message.mn_ReplyPort->mp_Flags
497 ReplyMsg((struct Message
*)req
);