Minor fixes to comments.
[AROS.git] / rom / devs / console / consoletask.c
blobc72a1b6096b8afaf46f81d36a2ef0b38e585a0b9
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Code executed by the console.device task.
6 Lang: english
7 */
9 #include <exec/lists.h>
10 #include <proto/exec.h>
11 #include <proto/intuition.h>
12 #include <proto/console.h>
13 #include <exec/io.h>
14 #include <exec/alerts.h>
15 #include <dos/dos.h>
16 #include <devices/input.h>
17 #include <devices/rawkeycodes.h>
19 #include "console_gcc.h"
20 #include "consoleif.h"
22 #define DEBUG 0
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);
29 if (data && size)
31 struct intPasteData *p = AllocMem(sizeof(struct intPasteData), MEMF_ANY);
32 if (p)
34 if (size < 0)
35 size = strlen(data);
36 p->pasteBuffer = AllocMem(size, MEMF_ANY);
37 if (p->pasteBuffer)
39 CopyMem((APTR)data, p->pasteBuffer, size);
40 p->pasteBufferSize = size;
41 p->unit = icu;
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));
44 } else {
45 FreeMem(p, sizeof(struct intPasteData));
49 ReleaseSemaphore(&ConsoleDevice->consoleTaskLock);
50 /* Wake up possible waiting CMD_READs */
51 Signal(ConsoleDevice->consoleTask, SIGBREAKF_CTRL_D);
54 /* Protos */
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)
66 /* Paranoia */
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);
80 if (pd)
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
88 , tocopy
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);
102 return tocopy;
104 return 0;
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();
122 if (inputmp)
124 struct IOStdReq *inputio;
125 inputio = (struct IOStdReq *)CreateIORequest(inputmp, sizeof (struct IOStdReq));
126 if (inputio)
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);
139 success = TRUE;
141 CloseDevice((struct IORequest *)inputio);
145 DeleteIORequest((struct IORequest *)inputio);
148 DeleteMsgPort(inputmp);
151 NEWLIST(&ConsoleDevice->readRequests);
153 /* if not successfull, throw an alert */
154 if (!success)
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;
170 for (;;)
172 wakeupsig = Wait(waitsigs);
174 /* Anyone wanting to kill us ? */
175 if (wakeupsig & SIGBREAKF_CTRL_C)
177 break;
180 ObtainSemaphore(&ConsoleDevice->consoleTaskLock);
182 if (wakeupsig & SIGBREAKF_CTRL_D) {
183 struct IOStdReq *req;
184 BOOL active = TRUE;
185 D(bug("SIGBREAKF_CTRL_D\n"));
186 /* console.device pasted data? */
187 while (active) {
188 active = FALSE;
189 ForeachNode(&ConsoleDevice->readRequests, req) {
190 if (pasteData(ICU(req->io_Unit), ConsoleDevice)) {
191 answer_requests(NULL, ConsoleDevice);
192 active = TRUE;
193 break;
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) */
219 /* fall through */
221 case IECLASS_RAWKEY:
223 #define MAPRAWKEY_BUFSIZE 80
225 UBYTE inputBuf[MAPRAWKEY_BUFSIZE + 1];
226 LONG actual;
227 ULONG tocopy;
228 struct InputEvent e;
230 /* Mouse wheel support */
231 if (cdihmsg->ie.ie_Code == RAWKEY_NM_WHEEL_UP ||
232 cdihmsg->ie.ie_Code == RAWKEY_NM_WHEEL_DOWN)
234 e.ie_EventAddress =
235 (cdihmsg->ie.ie_Code == RAWKEY_NM_WHEEL_UP) ?
236 (APTR)1 : (APTR)2;
237 e.ie_Class = IECLASS_GADGETDOWN;
238 Console_HandleGadgets(cdihmsg->unit, &e);
239 e.ie_Class = IECLASS_GADGETUP;
240 Console_HandleGadgets(cdihmsg->unit, &e);
242 else
245 /* Convert it to ANSI chars */
247 if (cdihmsg->ie.ie_Class == IECLASS_CLOSEWINDOW)
249 /* HACK */
250 inputBuf[0] = 28; /* CTRL-\ */
251 actual = 1;
252 /* HACK */
254 else
256 actual = RawKeyConvert(&cdihmsg->ie
257 ,inputBuf
258 ,MAPRAWKEY_BUFSIZE
259 ,NULL);
261 if (cdihmsg->ie.ie_Qualifier == IEQUALIFIER_RCOMMAND && actual == 1)
263 switch(inputBuf[0])
265 case 'c':
266 D(bug("Console_Copy\n"));
267 Console_Copy(cdihmsg->unit);
268 actual = 0;
269 break;
270 case 'v':
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);
275 actual = 0;
276 break;
281 D(bug("RawKeyConvert returned %ld\n", actual));
284 if (actual > 0)
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 */
291 CopyMem(inputBuf
292 , ICU(cdihmsg->unit)->inputBuf + ICU(cdihmsg->unit)->numStoredChars
293 , tocopy
296 ICU(cdihmsg->unit)->numStoredChars += tocopy;
298 answer_requests(cdihmsg->unit,ConsoleDevice);
299 } /* if (actual > 0) */
302 } /* IECLASS_RAWKEY */
303 break;
305 case IECLASS_GADGETDOWN:
306 case IECLASS_GADGETUP:
307 case IECLASS_TIMER:
308 case IECLASS_RAWMOUSE:
309 Console_HandleGadgets(cdihmsg->unit,&(cdihmsg->ie));
310 //.ie_Class, (APTR)cdihmsg->ie.ie_EventAddress);
311 break;
313 case IECLASS_REFRESHWINDOW: /* Intentional fallthrough */
314 case IECLASS_SIZEWINDOW:
316 Console_NewWindowSize(cdihmsg->unit);
317 } /* IECLASS_NEWSIZE */
318 break;
319 default:
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)
345 case CMD_READ:
346 if (0 != ICU(req->io_Unit)->numStoredChars)
348 answer_read_request(req, ConsoleDevice);
350 else
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);
358 break;
360 default:
361 kprintf("!!! UNKNOWN COMMAND RECEIVED BY CONSOLE TASK !!!\n");
362 kprintf("!!! THIS SHOULD NEVER HAPPEN !!!\n");
363 break;
366 } /* while ((req = (struct IOStdReq *)GetMsg(ConsoleDevice->commandPort))) */
368 } /* if (wakeupsig & commandsig) */
370 ReleaseSemaphore(&ConsoleDevice->consoleTaskLock);
372 } /* forever */
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)
383 Object *o, *ostate;
384 BOOL found = FALSE;
386 ObtainSemaphoreShared(&ConsoleDevice->unitListLock);
388 ostate = (Object *)ConsoleDevice->unitList.mlh_Head;
389 while ( (o = NextObject(&ostate)) && (!found) )
391 if (o == unit)
393 found = TRUE;
397 ReleaseSemaphore(&ConsoleDevice->unitListLock);
398 return found;
401 /******** answer_read_request() ***************************/
403 static void answer_read_request(struct IOStdReq *req, struct ConsoleBase *ConsoleDevice)
405 Object *unit;
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
418 , req->io_Data
419 , req->io_Actual
422 if (ICU(unit)->numStoredChars > req->io_Length)
424 ULONG i;
426 ICU(unit)->numStoredChars -= req->io_Actual;
428 /* We have to move the rest of the bytes to the start
429 of the buffer.
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];
439 else
441 /* No more unread characters in the buffer */
442 ICU(unit)->numStoredChars = 0;
446 req->io_Error = 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);
465 return;