Tabs to spaces; more consistent formatting.
[AROS.git] / rom / devs / console / console.c
blobf81498424006dcc88d2951c4abcc935c266f544a
1 /*
2 Copyright © 1995-2014, 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[] = {
53 CMD_READ,
54 CMD_WRITE,
55 NSCMD_DEVICEQUERY,
59 #endif
61 /*****************************************************************************/
63 static int GM_UNIQUENAME(Init) (LIBBASETYPEPTR ConsoleDevice)
65 ConsoleDevice->cb_IntuitionBase =
66 TaggedOpenLibrary(TAGGEDOPEN_INTUITION);
67 if (!ConsoleDevice->cb_IntuitionBase)
68 return FALSE;
69 ConsoleDevice->cb_KeymapBase = TaggedOpenLibrary(TAGGEDOPEN_KEYMAP);
70 if (!ConsoleDevice->cb_KeymapBase)
72 CloseLibrary(ConsoleDevice->cb_IntuitionBase);
73 return FALSE;
76 NEWLIST(&ConsoleDevice->unitList);
77 NEWLIST(&ConsoleDevice->sniphooks);
78 InitSemaphore(&ConsoleDevice->unitListLock);
79 InitSemaphore(&ConsoleDevice->consoleTaskLock);
80 InitSemaphore(&ConsoleDevice->copyBufferLock);
82 ConsoleDevice->copyBuffer = 0;
83 ConsoleDevice->copyBufferSize = 0;
85 /* Create the console classes */
86 CONSOLECLASSPTR = makeConsoleClass(ConsoleDevice);
87 STDCONCLASSPTR = makeStdConClass(ConsoleDevice);
88 CHARMAPCLASSPTR = makeCharMapConClass(ConsoleDevice);
89 SNIPMAPCLASSPTR = makeSnipMapConClass(ConsoleDevice);
91 if (!CONSOLECLASSPTR || !STDCONCLASSPTR || !CHARMAPCLASSPTR
92 || !SNIPMAPCLASSPTR)
93 Alert(AT_DeadEnd | AN_ConsoleDev | AG_NoMemory);
95 /* Create the console.device task. */
96 ConsoleDevice->consoleTask =
97 NewCreateTask(TASKTAG_NAME, "console.device", TASKTAG_PRI,
98 COTASK_PRIORITY, TASKTAG_STACKSIZE, COTASK_STACKSIZE,
99 TASKTAG_TASKMSGPORT, &ConsoleDevice->commandPort, TASKTAG_PC,
100 consoleTaskEntry, TASKTAG_ARG1, ConsoleDevice, 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)
117 (LIBBASETYPEPTR ConsoleDevice,
118 struct IOStdReq *ioreq, ULONG unitnum, ULONG flags)
120 BOOL success = FALSE;
122 /* Keep compiler happy */
123 flags = 0;
125 EnterFunc(bug("OpenConsole()\n"));
127 if (((LONG) unitnum) == CONU_LIBRARY)
128 /* unitnum is ULONG while CONU_LIBRARY is -1 :-( */
130 D(bug("Opening CONU_LIBRARY unit\n"));
131 ioreq->io_Device = (struct Device *)ConsoleDevice;
133 /* Set io_Unit so that CloseDevice knows this is a CONU_LIBRARY unit.
134 * WB1.3 Setmap sets io_Unit to CONU_LIBRARY (-1) before closing
135 * console.device */
136 ioreq->io_Unit = (struct Unit *)CONU_LIBRARY;
137 success = TRUE;
139 else
141 Class *classptr = NULL; /* Keep compiler happy */
142 #ifndef __mc68000
143 /* AOS programs don't always initialize mn_Length. */
144 if (ioreq->io_Message.mn_Length < sizeof(struct IOStdReq))
146 D(bug("console.device/open: IORequest structure passed to"
147 " OpenDevice is too small!\n"));
148 goto open_fail;
150 #endif
151 struct TagItem conunit_tags[] = {
152 {A_Console_Window, 0},
153 {TAG_DONE, 0}
156 /* Init tags */
158 conunit_tags[0].ti_Data = (IPTR) ioreq->io_Data; /* Window */
160 /* Select class of which to create console object */
161 switch (unitnum)
163 case CONU_STANDARD:
164 D(bug("Opening CONU_STANDARD console\n"));
165 classptr = STDCONCLASSPTR;
166 break;
168 case CONU_CHARMAP:
169 classptr = CHARMAPCLASSPTR;
170 break;
172 case CONU_SNIPMAP:
173 classptr = SNIPMAPCLASSPTR;
174 break;
176 default:
177 goto open_fail;
180 /* Create console object */
181 ioreq->io_Unit =
182 (struct Unit *)NewObjectA(classptr, NULL, conunit_tags);
183 if (ioreq->io_Unit)
185 struct opAddTail add_msg;
186 success = TRUE;
188 /* Add the newly created unit to console's list of units */
189 ObtainSemaphore(&ConsoleDevice->unitListLock);
191 add_msg.MethodID = OM_ADDTAIL;
192 add_msg.opat_List = (struct List *)&ConsoleDevice->unitList;
193 DoMethodA((Object *) ioreq->io_Unit, (Msg) &add_msg);
195 ReleaseSemaphore(&ConsoleDevice->unitListLock);
196 } /* if (console unit created) */
197 } /* if (not CONU_LIBRARY) */
199 if (!success)
200 goto open_fail;
202 return TRUE;
204 open_fail:
206 ioreq->io_Error = IOERR_OPENFAIL;
208 return FALSE;
211 /*****************************************************************************/
213 static int GM_UNIQUENAME(Close)
214 (LIBBASETYPEPTR ConsoleDevice, struct IORequest *ioreq)
216 if (ioreq->io_Unit && ioreq->io_Unit != (struct Unit *)CONU_LIBRARY)
218 ULONG mid = OM_REMOVE;
220 /* Remove the consoe from the console list */
221 ObtainSemaphore(&ConsoleDevice->unitListLock);
222 DoMethodA((Object *) ioreq->io_Unit, (Msg) &mid);
223 ReleaseSemaphore(&ConsoleDevice->unitListLock);
225 DisposeObject((Object *) ioreq->io_Unit);
228 return TRUE;
231 /*****************************************************************************/
233 ADD2INITLIB(GM_UNIQUENAME(Init), 0)
234 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge), 0)
235 ADD2OPENDEV(GM_UNIQUENAME(Open), 0) ADD2CLOSEDEV(GM_UNIQUENAME(Close), 0)
236 /*****************************************************************************/
237 AROS_LH1(void, beginio,
238 AROS_LHA(struct IOStdReq *, ioreq, A1),
239 struct ConsoleBase *, ConsoleDevice, 5, Console)
241 AROS_LIBFUNC_INIT
243 LONG error = 0;
244 BOOL done_quick = TRUE;
246 /* WaitIO will look into this */
247 ioreq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
249 EnterFunc(bug("BeginIO(ioreq=%p)\n", ioreq));
251 switch (ioreq->io_Command)
253 #if NEWSTYLE_DEVICE
254 case NSCMD_DEVICEQUERY:
255 if (ioreq->io_Length < ((LONG) OFFSET(NSDeviceQueryResult,
256 SupportedCommands)) + sizeof(UWORD *))
258 ioreq->io_Error = IOERR_BADLENGTH;
260 else
262 struct NSDeviceQueryResult *d;
264 d = (struct NSDeviceQueryResult *)ioreq->io_Data;
266 d->DevQueryFormat = 0;
267 d->SizeAvailable = sizeof(struct NSDeviceQueryResult);
268 d->DeviceType = NSDEVTYPE_CONSOLE;
269 d->DeviceSubType = 0;
270 d->SupportedCommands = (UWORD *) SupportedCommands;
272 ioreq->io_Actual = sizeof(struct NSDeviceQueryResult);
274 break;
275 #endif
277 case CMD_WRITE:
279 ULONG towrite;
280 D(bug("CMD_WRITE %p,%d\n", ioreq->io_Data, ioreq->io_Length));
281 #if DEBUG
283 char *str;
284 int i;
285 str = ioreq->io_Data;
286 for (i = 0; i < ioreq->io_Length; i++)
288 kprintf("%c", *str++);
290 kprintf("\n");
292 #endif
293 if (ioreq->io_Length == -1)
295 towrite = strlen((STRPTR) ioreq->io_Data);
297 else
299 towrite = ioreq->io_Length;
302 ioreq->io_Actual =
303 writeToConsole((struct ConUnit *)ioreq->io_Unit,
304 ioreq->io_Data, towrite, ConsoleDevice);
306 break;
309 case CMD_READ:
310 D(bug("CMD_READ %p,%d\n", ioreq->io_Data, ioreq->io_Length));
311 #if DEBUG
313 char *str;
314 int i;
315 str = ioreq->io_Data;
316 for (i = 0; i < ioreq->io_Length; i++)
318 kprintf("%c", *str++);
320 kprintf("\n");
322 #endif
323 done_quick = FALSE;
325 break;
327 case CD_ASKKEYMAP:
328 /* FIXME: Returns always default keymap */
329 if (ioreq->io_Length < sizeof(struct KeyMap))
330 error = IOERR_BADLENGTH;
331 else
332 CopyMem(AskKeyMapDefault(), ioreq->io_Data,
333 sizeof(struct KeyMap));
334 break;
335 case CD_SETKEYMAP:
336 D(bug("CD_SETKEYMAP\n"));
337 error = IOERR_NOCMD;
338 break;
339 case CD_ASKDEFAULTKEYMAP:
340 if (ioreq->io_Length < sizeof(struct KeyMap))
341 error = IOERR_BADLENGTH;
342 else
343 CopyMem(AskKeyMapDefault(), ioreq->io_Data,
344 sizeof(struct KeyMap));
345 break;
346 case CD_SETDEFAULTKEYMAP:
347 D(bug("CD_SETDEFAULTKEYMAP\n"));
348 error = IOERR_NOCMD;
349 break;
351 default:
352 D(bug("IOERR_NOCMD %d\n", ioreq->io_Command));
353 error = IOERR_NOCMD;
354 break;
355 } /* switch (ioreq->io_Command) */
357 if (!done_quick)
359 /* Mark IO request to be done non-quick */
360 ioreq->io_Flags &= ~IOF_QUICK;
361 /* Send to input device task */
362 PutMsg(ConsoleDevice->commandPort, &ioreq->io_Message);
364 else
367 /* If the quick bit is not set but the IO request was done quick,
368 * reply the message to tell we're through
370 ioreq->io_Error = error;
371 if (!(ioreq->io_Flags & IOF_QUICK))
372 ReplyMsg(&ioreq->io_Message);
375 ReturnVoid("BeginIO");
377 AROS_LIBFUNC_EXIT
380 /*****************************************************************************/
382 AROS_LH1(LONG, abortio,
383 AROS_LHA(struct IORequest *, ioreq, A1),
384 struct ConsoleBase *, ConsoleDevice, 6, Console)
386 AROS_LIBFUNC_INIT
388 LONG ret = -1;
390 ObtainSemaphore(&ConsoleDevice->consoleTaskLock);
392 /* The ioreq can either be in the ConsoleDevice->commandPort MsgPort,
393 or be in the ConsoleDevice->readRequests List, or be already done.
395 In the first two cases ln_Type will be NT_MESSAGE (= it can be
396 aborted), in the last case ln_Type will be NT_REPLYMSG (cannot
397 abort, because already done)
399 The consoleTaskLock Semaphore hopefully makes sure that there are no
400 other/"in-between" cases.
404 if (ioreq->io_Message.mn_Node.ln_Type != NT_REPLYMSG)
406 ioreq->io_Error = IOERR_ABORTED;
407 Remove(&ioreq->io_Message.mn_Node);
408 ReplyMsg(&ioreq->io_Message);
410 ret = 0;
413 ReleaseSemaphore(&ConsoleDevice->consoleTaskLock);
415 return ret;
417 AROS_LIBFUNC_EXIT
420 /*****************************************************************************/