2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
9 /*****************************************************************************/
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
39 #include <aros/debug.h>
41 /*****************************************************************************/
43 #define NEWSTYLE_DEVICE 1
45 /*****************************************************************************/
48 /*****************************************************************************/
52 static const UWORD SupportedCommands
[] = {
61 /*****************************************************************************/
63 static int GM_UNIQUENAME(Init
) (LIBBASETYPEPTR ConsoleDevice
)
65 ConsoleDevice
->cb_IntuitionBase
=
66 TaggedOpenLibrary(TAGGEDOPEN_INTUITION
);
67 if (!ConsoleDevice
->cb_IntuitionBase
)
69 ConsoleDevice
->cb_KeymapBase
= TaggedOpenLibrary(TAGGEDOPEN_KEYMAP
);
70 if (!ConsoleDevice
->cb_KeymapBase
)
72 CloseLibrary(ConsoleDevice
->cb_IntuitionBase
);
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
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
);
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 */
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
136 ioreq
->io_Unit
= (struct Unit
*)CONU_LIBRARY
;
141 Class
*classptr
= NULL
; /* Keep compiler happy */
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"));
151 struct TagItem conunit_tags
[] = {
152 {A_Console_Window
, 0},
158 conunit_tags
[0].ti_Data
= (IPTR
) ioreq
->io_Data
; /* Window */
160 /* Select class of which to create console object */
164 D(bug("Opening CONU_STANDARD console\n"));
165 classptr
= STDCONCLASSPTR
;
169 classptr
= CHARMAPCLASSPTR
;
173 classptr
= SNIPMAPCLASSPTR
;
180 /* Create console object */
182 (struct Unit
*)NewObjectA(classptr
, NULL
, conunit_tags
);
185 struct opAddTail add_msg
;
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) */
206 ioreq
->io_Error
= IOERR_OPENFAIL
;
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
);
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
)
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
)
254 case NSCMD_DEVICEQUERY
:
255 if (ioreq
->io_Length
< ((LONG
) OFFSET(NSDeviceQueryResult
,
256 SupportedCommands
)) + sizeof(UWORD
*))
258 ioreq
->io_Error
= IOERR_BADLENGTH
;
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
);
280 D(bug("CMD_WRITE %p,%d\n", ioreq
->io_Data
, ioreq
->io_Length
));
285 str
= ioreq
->io_Data
;
286 for (i
= 0; i
< ioreq
->io_Length
; i
++)
288 kprintf("%c", *str
++);
293 if (ioreq
->io_Length
== -1)
295 towrite
= strlen((STRPTR
) ioreq
->io_Data
);
299 towrite
= ioreq
->io_Length
;
303 writeToConsole((struct ConUnit
*)ioreq
->io_Unit
,
304 ioreq
->io_Data
, towrite
, ConsoleDevice
);
310 D(bug("CMD_READ %p,%d\n", ioreq
->io_Data
, ioreq
->io_Length
));
315 str
= ioreq
->io_Data
;
316 for (i
= 0; i
< ioreq
->io_Length
; i
++)
318 kprintf("%c", *str
++);
328 /* FIXME: Returns always default keymap */
329 if (ioreq
->io_Length
< sizeof(struct KeyMap
))
330 error
= IOERR_BADLENGTH
;
332 CopyMem(AskKeyMapDefault(), ioreq
->io_Data
,
333 sizeof(struct KeyMap
));
336 D(bug("CD_SETKEYMAP\n"));
339 case CD_ASKDEFAULTKEYMAP
:
340 if (ioreq
->io_Length
< sizeof(struct KeyMap
))
341 error
= IOERR_BADLENGTH
;
343 CopyMem(AskKeyMapDefault(), ioreq
->io_Data
,
344 sizeof(struct KeyMap
));
346 case CD_SETDEFAULTKEYMAP
:
347 D(bug("CD_SETDEFAULTKEYMAP\n"));
352 D(bug("IOERR_NOCMD %d\n", ioreq
->io_Command
));
355 } /* switch (ioreq->io_Command) */
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
);
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");
380 /*****************************************************************************/
382 AROS_LH1(LONG
, abortio
,
383 AROS_LHA(struct IORequest
*, ioreq
, A1
),
384 struct ConsoleBase
*, ConsoleDevice
, 6, Console
)
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
);
413 ReleaseSemaphore(&ConsoleDevice
->consoleTaskLock
);
420 /*****************************************************************************/