2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Code executed by the console.device task.
11 #include <exec/lists.h>
13 #include <proto/exec.h>
14 #include <proto/intuition.h>
15 #include <proto/console.h>
17 #include <exec/alerts.h>
21 #include <devices/input.h>
23 #include "console_gcc.h"
24 #include "consoleif.h"
27 #include <aros/debug.h>
30 static BOOL
checkconunit(Object
*unit
, struct ConsoleBase
*ConsoleDevice
);
31 static void answer_read_request(struct IOStdReq
*req
, struct ConsoleBase
*ConsoleDevice
);
33 VOID
consoleTaskEntry(struct ConsoleBase
*ConsoleDevice
)
36 LONG waitsigs
= 0L, wakeupsig
, commandsig
, inputsig
;
39 /* CD input handler puts data into this port */
40 struct MsgPort
*inputport
;
43 /* Used for input.device */
44 struct MsgPort
*inputmp
;
46 /* Add the CDInputHandler to input.device's list of input handlers */
47 inputmp
= CreateMsgPort();
50 struct IOStdReq
*inputio
;
51 inputio
= (struct IOStdReq
*)CreateIORequest(inputmp
, sizeof (struct IOStdReq
));
54 /* Open the input.device */
55 if (!OpenDevice("input.device", -1, (struct IORequest
*)inputio
, 0UL))
57 /* Initialize the inputhandler itself */
58 ConsoleDevice
->inputHandler
= initCDIH(ConsoleDevice
);
59 if (ConsoleDevice
->inputHandler
)
61 inputio
->io_Data
= ConsoleDevice
->inputHandler
;
62 inputio
->io_Command
= IND_ADDHANDLER
;
64 DoIO((struct IORequest
*)inputio
);
67 CloseDevice((struct IORequest
*)inputio
);
71 DeleteIORequest((struct IORequest
*)inputio
);
74 DeleteMsgPort(inputmp
);
77 NEWLIST(&ConsoleDevice
->readRequests
);
79 /* if not successfull, throw an alert */
82 Alert(AT_DeadEnd
| AN_ConsoleDev
| AG_OpenDev
| AO_Unknown
);
85 D(bug("Console task initialized\n"));
88 /* Get console.device input handler's port */
89 inputport
= ((struct cdihData
*)ConsoleDevice
->inputHandler
->is_Data
)->inputPort
;
91 inputsig
= 1 << inputport
->mp_SigBit
;
92 commandsig
= 1 << ConsoleDevice
->commandPort
.mp_SigBit
;
94 waitsigs
= inputsig
|commandsig
|SIGBREAKF_CTRL_C
;
98 wakeupsig
= Wait(waitsigs
);
100 /* Anyone wanting to kill us ? */
101 if (wakeupsig
& SIGBREAKF_CTRL_C
)
106 ObtainSemaphore(&ConsoleDevice
->consoleTaskLock
);
108 if (wakeupsig
& inputsig
)
110 /* A message from the console device input handler */
111 struct cdihMessage
*cdihmsg
;
113 while ( (cdihmsg
= (struct cdihMessage
*)GetMsg(inputport
)) )
116 D(bug("GOT MESSAGE FROM CONSOLE INPUT HANDLER: "));
117 /* Check that the ConUnit has not been disposed,
118 while the message was passed
120 if (checkconunit(cdihmsg
->unit
, ConsoleDevice
))
122 switch(cdihmsg
->ie
.ie_Class
)
124 case IECLASS_CLOSEWINDOW
:
125 #warning this is a hack. It would actually be up to the
126 #warning console.device user (CON: handler for example) to
127 #warning activate CLOSEWINDOW raw events (SET RAW EVENTS cmd)
128 #warning and then look out for this in the input stream (CMD_READ)
133 #define MAPRAWKEY_BUFSIZE 80
135 struct IOStdReq
*req
, *nextreq
;
136 UBYTE inputBuf
[MAPRAWKEY_BUFSIZE
+ 1];
140 /* Convert it to ANSI chars */
142 if (cdihmsg
->ie
.ie_Class
== IECLASS_CLOSEWINDOW
)
145 inputBuf
[0] = 28; /* CTRL-\ */
151 actual
= RawKeyConvert(&cdihmsg
->ie
157 D(bug("RawKeyConvert returned %ld\n", actual
));
162 /* Copy received characters to the console unit input buffer.
163 If the buffer is full, then console input will be lost
165 tocopy
= MIN(actual
, CON_INPUTBUF_SIZE
- ICU(cdihmsg
->unit
)->numStoredChars
);
166 /* Copy the input over to the unit's buffer */
168 , ICU(cdihmsg
->unit
)->inputBuf
+ ICU(cdihmsg
->unit
)->numStoredChars
172 ICU(cdihmsg
->unit
)->numStoredChars
+= tocopy
;
174 /* See if there are any queued io read requests that wants to be replied */
175 ForeachNodeSafe(&ConsoleDevice
->readRequests
, req
, nextreq
)
178 if ((APTR
)req
->io_Unit
== (APTR
)cdihmsg
->unit
)
181 if (0 != ICU(req
->io_Unit
)->numStoredChars
)
183 Remove((struct Node
*)req
);
184 answer_read_request(req
, ConsoleDevice
);
188 } /* if (actual > 0) */
190 } /* IECLASS_RAWKEY */
193 case IECLASS_SIZEWINDOW
:
195 Console_NewWindowSize(cdihmsg
->unit
);
196 } /* IECLASS_NEWSIZE */
199 } /* switch(cdihmsg->ie.ie_Class) */
202 } /* if (checkconunit(cdihmsg->unit, ConsoleDevice)) */
204 /* Tell the input handler we're done */
205 ReplyMsg((struct Message
*)cdihmsg
);
207 } /* while ( (cdihmsg = (struct cdihMessage *)GetMsg(inputport)) ) */
209 } /* if (wakeupsig & inputsig) */
211 if (wakeupsig
& commandsig
)
213 /* We got a command from the outside. Investigate it */
214 struct IOStdReq
*req
;
217 while ((req
= (struct IOStdReq
*)GetMsg(&ConsoleDevice
->commandPort
)))
219 switch (req
->io_Command
)
222 if (0 != ICU(req
->io_Unit
)->numStoredChars
)
224 answer_read_request(req
, ConsoleDevice
);
228 /* Not enough bytes in the buffer to fill the request, put it on hold */
230 /* ioReq allready removed from the queue qith GetMsg() */
232 AddTail((struct List
*)&ConsoleDevice
->readRequests
, (struct Node
*)req
);
237 kprintf("!!! UNKNOWN COMMAND RECEIVED BY CONSOLE TASK !!!\n");
238 kprintf("!!! THIS SHOULD NEVER HAPPEN !!!\n");
242 } /* while ((req = (struct IOStdReq *)GetMsg(ConsoleDevice->commandPort))) */
244 } /* if (wakeupsig & commandsig) */
246 ReleaseSemaphore(&ConsoleDevice
->consoleTaskLock
);
250 #warning FIXME: Do cleanup here
254 /********** checkconunit() *******************************/
256 /* Checks that the supplied unit has not been disposed */
257 static BOOL
checkconunit(Object
*unit
, struct ConsoleBase
*ConsoleDevice
)
262 ObtainSemaphoreShared(&ConsoleDevice
->unitListLock
);
264 ostate
= (Object
*)ConsoleDevice
->unitList
.mlh_Head
;
265 while ( (o
= NextObject(&ostate
)) && (!found
) )
273 ReleaseSemaphore(&ConsoleDevice
->unitListLock
);
277 /******** answer_read_request() ***************************/
279 static void answer_read_request(struct IOStdReq
*req
, struct ConsoleBase
*ConsoleDevice
)
283 D(bug("answer_read_request\n"));
284 /* This function assumes that there are at least one character
285 available in the unitsinput buffer
288 unit
= (Object
*)req
->io_Unit
;
290 req
->io_Actual
= MIN(ICU(unit
)->numStoredChars
, req
->io_Length
);
292 /* Copy characters from the buffer into the request */
293 CopyMem( (APTR
)ICU(unit
)->inputBuf
298 if (ICU(unit
)->numStoredChars
> req
->io_Length
)
302 ICU(unit
)->numStoredChars
-= req
->io_Actual
;
304 /* We have to move the rest of the bytes to the start
307 NOTE: we could alternatively use a circular buffer
310 for (i
= 0; i
< ICU(unit
)->numStoredChars
; i
++)
312 ICU(unit
)->inputBuf
[i
] = ICU(unit
)->inputBuf
[i
+ req
->io_Actual
];
317 /* No more unread characters in the buffer */
318 ICU(unit
)->numStoredChars
= 0;
323 /* All done. Just reply the request */
325 /* stegerg: the caller of answer_read_request is responsible for the Remove,
326 because the Remove must be used only if the req was in
327 the readrequests list
328 Remove((struct Node *)req);
333 /* kprintf("receiving task=%s, sigbit=%d\n, mode=%d"
334 , ((struct Task *)req->io_Message.mn_ReplyPort->mp_SigTask)->tc_Node.ln_Name
335 , req->io_Message.mn_ReplyPort->mp_SigBit
336 , req->io_Message.mn_ReplyPort->mp_Flags
339 ReplyMsg((struct Message
*)req
);