Minor fixes to comments.
[AROS.git] / rom / devs / console / console.c
blob1df9c48a75f833d94fff40616faa995a8a298bea
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Console.device
6 Lang: English
7 */
9 /****************************************************************************************/
11 #include <string.h>
13 #include <proto/exec.h>
14 #include <proto/console.h>
15 #include <proto/intuition.h>
16 #include <proto/keymap.h>
17 #include <exec/resident.h>
18 #include <exec/errors.h>
19 #include <exec/memory.h>
20 #include <exec/initializers.h>
21 #include <devices/inputevent.h>
22 #include <devices/conunit.h>
23 #include <devices/newstyle.h>
24 #include <intuition/intuition.h>
25 #include <intuition/screens.h>
26 #include <intuition/classusr.h>
27 #include <graphics/rastport.h>
28 #include <aros/libcall.h>
29 #include <aros/symbolsets.h>
30 #include <graphics/rastport.h>
32 #include "console_gcc.h"
33 #include "consoleif.h"
35 #include LC_LIBDEFS_FILE
37 #define SDEBUG 0
38 #define DEBUG 0
39 #include <aros/debug.h>
41 /****************************************************************************************/
43 #define NEWSTYLE_DEVICE 1
45 /****************************************************************************************/
48 /****************************************************************************************/
50 #if NEWSTYLE_DEVICE
52 static const UWORD SupportedCommands[] =
54 CMD_READ,
55 CMD_WRITE,
56 NSCMD_DEVICEQUERY,
60 #endif
62 /****************************************************************************************/
64 static int GM_UNIQUENAME(Init)(LIBBASETYPEPTR ConsoleDevice)
66 ConsoleDevice->cb_IntuitionBase = TaggedOpenLibrary(TAGGEDOPEN_INTUITION);
67 if (!ConsoleDevice->cb_IntuitionBase)
68 return FALSE;
69 ConsoleDevice->cb_KeymapBase = TaggedOpenLibrary(TAGGEDOPEN_KEYMAP);
70 if (!ConsoleDevice->cb_KeymapBase) {
71 CloseLibrary(ConsoleDevice->cb_IntuitionBase);
72 return FALSE;
75 NEWLIST(&ConsoleDevice->unitList);
76 NEWLIST(&ConsoleDevice->sniphooks);
77 InitSemaphore(&ConsoleDevice->unitListLock);
78 InitSemaphore(&ConsoleDevice->consoleTaskLock);
79 InitSemaphore(&ConsoleDevice->copyBufferLock);
81 ConsoleDevice->copyBuffer = 0;
82 ConsoleDevice->copyBufferSize = 0;
84 /* Create the console classes */
85 CONSOLECLASSPTR = makeConsoleClass(ConsoleDevice);
86 STDCONCLASSPTR = makeStdConClass(ConsoleDevice);
87 CHARMAPCLASSPTR = makeCharMapConClass(ConsoleDevice);
88 SNIPMAPCLASSPTR = makeSnipMapConClass(ConsoleDevice);
90 if (!CONSOLECLASSPTR || !STDCONCLASSPTR || !CHARMAPCLASSPTR || !SNIPMAPCLASSPTR)
91 Alert(AT_DeadEnd | AN_ConsoleDev | AG_NoMemory);
93 /* Create the console.device task. */
94 ConsoleDevice->consoleTask = NewCreateTask(TASKTAG_NAME , "console.device",
95 TASKTAG_PRI , COTASK_PRIORITY,
96 TASKTAG_STACKSIZE , COTASK_STACKSIZE,
97 TASKTAG_TASKMSGPORT, &ConsoleDevice->commandPort,
98 TASKTAG_PC , consoleTaskEntry,
99 TASKTAG_ARG1 , ConsoleDevice,
100 TAG_DONE);
102 return ConsoleDevice->consoleTask ? TRUE : FALSE;
105 /****************************************************************************************/
107 static int GM_UNIQUENAME(Expunge)(LIBBASETYPEPTR ConsoleDevice)
109 CloseLibrary(ConsoleDevice->cb_IntuitionBase);
110 CloseLibrary(ConsoleDevice->cb_KeymapBase);
111 return TRUE;
114 /****************************************************************************************/
116 static int GM_UNIQUENAME(Open)
118 LIBBASETYPEPTR ConsoleDevice,
119 struct IOStdReq *ioreq,
120 ULONG unitnum,
121 ULONG flags
124 BOOL success = FALSE;
126 /* Keep compiler happy */
127 flags=0;
129 EnterFunc(bug("OpenConsole()\n"));
131 if (((LONG)unitnum) == CONU_LIBRARY) /* unitnum is ULONG while CONU_LIBRARY is -1 :-( */
133 D(bug("Opening CONU_LIBRARY unit\n"));
134 ioreq->io_Device = (struct Device *)ConsoleDevice;
136 /* Set io_Unit so that CloseDevice knows this is a CONU_LIBRARY unit */
137 /* WB1.3 Setmap sets io_Unit to CONU_LIBRARY (-1) before closing console.device */
138 ioreq->io_Unit = (struct Unit*)CONU_LIBRARY;
139 success = TRUE;
141 else
143 Class *classptr = NULL; /* Keep compiler happy */
144 #ifndef __mc68000
145 /* AOS programs don't always initialize mn_Length. */
146 if (ioreq->io_Message.mn_Length < sizeof(struct IOStdReq))
148 D(bug("console.device/open: IORequest structure passed to OpenDevice is too small!\n"));
149 goto open_fail;
151 #endif
152 struct TagItem conunit_tags[] =
154 {A_Console_Window, 0},
155 {TAG_DONE, 0}
158 /* Init tags */
160 conunit_tags[0].ti_Data = (IPTR)ioreq->io_Data; /* Window */
163 /* Select class of which to create console object */
164 switch (unitnum)
166 case CONU_STANDARD:
167 D(bug("Opening CONU_STANDARD console\n"));
168 classptr = STDCONCLASSPTR;
169 break;
171 case CONU_CHARMAP:
172 classptr = CHARMAPCLASSPTR;
173 break;
175 case CONU_SNIPMAP:
176 classptr = SNIPMAPCLASSPTR;
177 break;
179 default:
180 goto open_fail;
184 /* Create console object */
185 ioreq->io_Unit = (struct Unit *)NewObjectA(classptr, NULL, conunit_tags);
186 if (ioreq->io_Unit)
188 struct opAddTail add_msg;
189 success = TRUE;
191 /* Add the newly created unit to console's list of units */
192 ObtainSemaphore(&ConsoleDevice->unitListLock);
194 add_msg.MethodID = OM_ADDTAIL;
195 add_msg.opat_List = (struct List *)&ConsoleDevice->unitList;
196 DoMethodA((Object *)ioreq->io_Unit, (Msg)&add_msg);
198 ReleaseSemaphore(&ConsoleDevice->unitListLock);
199 } /* if (console unit created) */
201 } /* if (not CONU_LIBRARY) */
203 if (!success)
204 goto open_fail;
206 return TRUE;
208 open_fail:
210 ioreq->io_Error = IOERR_OPENFAIL;
212 return FALSE;
215 /****************************************************************************************/
217 static int GM_UNIQUENAME(Close)
219 LIBBASETYPEPTR ConsoleDevice,
220 struct IORequest *ioreq
223 if (ioreq->io_Unit && ioreq->io_Unit != (struct Unit*)CONU_LIBRARY)
225 ULONG mid = OM_REMOVE;
227 /* Remove the consoe from the console list */
228 ObtainSemaphore(&ConsoleDevice->unitListLock);
229 DoMethodA((Object *)ioreq->io_Unit, (Msg)&mid);
230 ReleaseSemaphore(&ConsoleDevice->unitListLock);
232 DisposeObject((Object *)ioreq->io_Unit);
235 return TRUE;
238 /****************************************************************************************/
240 ADD2INITLIB(GM_UNIQUENAME(Init),0)
241 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge),0)
242 ADD2OPENDEV(GM_UNIQUENAME(Open),0)
243 ADD2CLOSEDEV(GM_UNIQUENAME(Close),0)
245 /****************************************************************************************/
247 AROS_LH1(void, beginio,
248 AROS_LHA(struct IOStdReq *, ioreq, A1),
249 struct ConsoleBase *, ConsoleDevice, 5, Console)
251 AROS_LIBFUNC_INIT
252 LONG error=0;
254 BOOL done_quick = TRUE;
256 /* WaitIO will look into this */
257 ioreq->io_Message.mn_Node.ln_Type=NT_MESSAGE;
259 EnterFunc(bug("BeginIO(ioreq=%p)\n", ioreq));
261 switch (ioreq->io_Command)
263 #if NEWSTYLE_DEVICE
264 case NSCMD_DEVICEQUERY:
265 if(ioreq->io_Length < ((LONG)OFFSET(NSDeviceQueryResult, SupportedCommands)) + sizeof(UWORD *))
267 ioreq->io_Error = IOERR_BADLENGTH;
269 else
271 struct NSDeviceQueryResult *d;
273 d = (struct NSDeviceQueryResult *)ioreq->io_Data;
275 d->DevQueryFormat = 0;
276 d->SizeAvailable = sizeof(struct NSDeviceQueryResult);
277 d->DeviceType = NSDEVTYPE_CONSOLE;
278 d->DeviceSubType = 0;
279 d->SupportedCommands = (UWORD *)SupportedCommands;
281 ioreq->io_Actual = sizeof(struct NSDeviceQueryResult);
283 break;
284 #endif
287 case CMD_WRITE: {
288 ULONG towrite;
289 D(bug("CMD_WRITE %p,%d\n", ioreq->io_Data, ioreq->io_Length));
290 #if DEBUG
292 char *str;
293 int i;
294 str = ioreq->io_Data;
295 for (i = 0; i < ioreq->io_Length; i ++)
297 kprintf("%c", *str ++);
299 kprintf("\n");
301 #endif
302 if (ioreq->io_Length == -1) {
303 towrite = strlen((STRPTR)ioreq->io_Data);
304 } else {
305 towrite = ioreq->io_Length;
309 ioreq->io_Actual = writeToConsole((struct ConUnit *)ioreq->io_Unit
310 , ioreq->io_Data
311 , towrite
312 , ConsoleDevice
315 break; }
317 case CMD_READ:
318 D(bug("CMD_READ %p,%d\n", ioreq->io_Data, ioreq->io_Length));
319 #if DEBUG
321 char *str;
322 int i;
323 str = ioreq->io_Data;
324 for (i = 0; i < ioreq->io_Length; i ++)
326 kprintf("%c", *str ++);
328 kprintf("\n");
330 #endif
331 done_quick = FALSE;
333 break;
335 case CD_ASKKEYMAP:
336 /* FIXME: Returns always default keymap */
337 if (ioreq->io_Length < sizeof(struct KeyMap))
338 error = IOERR_BADLENGTH;
339 else
340 CopyMem(AskKeyMapDefault(), ioreq->io_Data, sizeof(struct KeyMap));
341 break;
342 case CD_SETKEYMAP:
343 D(bug("CD_SETKEYMAP\n"));
344 error = IOERR_NOCMD;
345 break;
346 case CD_ASKDEFAULTKEYMAP:
347 if (ioreq->io_Length < sizeof(struct KeyMap))
348 error = IOERR_BADLENGTH;
349 else
350 CopyMem(AskKeyMapDefault(), ioreq->io_Data, sizeof(struct KeyMap));
351 break;
352 case CD_SETDEFAULTKEYMAP:
353 D(bug("CD_SETDEFAULTKEYMAP\n"));
354 error = IOERR_NOCMD;
355 break;
357 default:
358 D(bug("IOERR_NOCMD %d\n", ioreq->io_Command));
359 error = IOERR_NOCMD;
360 break;
362 } /* switch (ioreq->io_Command) */
364 if (!done_quick)
366 /* Mark IO request to be done non-quick */
367 ioreq->io_Flags &= ~IOF_QUICK;
368 /* Send to input device task */
369 PutMsg(ConsoleDevice->commandPort, &ioreq->io_Message);
371 else
374 /* If the quick bit is not set but the IO request was done quick,
375 ** reply the message to tell we're throgh
377 ioreq->io_Error = error;
378 if (!(ioreq->io_Flags & IOF_QUICK))
379 ReplyMsg (&ioreq->io_Message);
382 ReturnVoid("BeginIO");
383 AROS_LIBFUNC_EXIT
386 /****************************************************************************************/
388 AROS_LH1(LONG, abortio,
389 AROS_LHA(struct IORequest *, ioreq, A1),
390 struct ConsoleBase *, ConsoleDevice, 6, Console)
392 AROS_LIBFUNC_INIT
394 LONG ret = -1;
396 ObtainSemaphore(&ConsoleDevice->consoleTaskLock);
398 /* The ioreq can either be in the ConsoleDevice->commandPort MsgPort,
399 or be in the ConsoleDevice->readRequests List, or be already done.
401 In the first two cases ln_Type will be NT_MESSAGE (= it can be
402 aborted), in the last case ln_Type will be NT_REPLYMSG (cannot
403 abort, because already done)
405 The consoleTaskLock Semaphore hopefully makes sure that there are no
406 other/"in-between" cases.
410 if (ioreq->io_Message.mn_Node.ln_Type != NT_REPLYMSG)
412 ioreq->io_Error = IOERR_ABORTED;
413 Remove(&ioreq->io_Message.mn_Node);
414 ReplyMsg(&ioreq->io_Message);
416 ret = 0;
419 ReleaseSemaphore(&ConsoleDevice->consoleTaskLock);
421 return ret;
423 AROS_LIBFUNC_EXIT
426 /****************************************************************************************/