2 Copyright © 1995-2011, 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
[] =
62 /****************************************************************************************/
64 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR ConsoleDevice
)
66 ConsoleDevice
->cb_IntuitionBase
= TaggedOpenLibrary(TAGGEDOPEN_INTUITION
);
67 if (!ConsoleDevice
->cb_IntuitionBase
)
69 ConsoleDevice
->cb_KeymapBase
= TaggedOpenLibrary(TAGGEDOPEN_KEYMAP
);
70 if (!ConsoleDevice
->cb_KeymapBase
) {
71 CloseLibrary(ConsoleDevice
->cb_IntuitionBase
);
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
,
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
)
118 LIBBASETYPEPTR ConsoleDevice
,
119 struct IOStdReq
*ioreq
,
124 BOOL success
= FALSE
;
126 /* Keep compiler happy */
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
;
143 Class
*classptr
= NULL
; /* Keep compiler happy */
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"));
152 struct TagItem conunit_tags
[] =
154 {A_Console_Window
, 0},
160 conunit_tags
[0].ti_Data
= (IPTR
)ioreq
->io_Data
; /* Window */
163 /* Select class of which to create console object */
167 D(bug("Opening CONU_STANDARD console\n"));
168 classptr
= STDCONCLASSPTR
;
172 classptr
= CHARMAPCLASSPTR
;
176 classptr
= SNIPMAPCLASSPTR
;
184 /* Create console object */
185 ioreq
->io_Unit
= (struct Unit
*)NewObjectA(classptr
, NULL
, conunit_tags
);
188 struct opAddTail add_msg
;
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) */
210 ioreq
->io_Error
= IOERR_OPENFAIL
;
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
);
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
)
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
)
264 case NSCMD_DEVICEQUERY
:
265 if(ioreq
->io_Length
< ((LONG
)OFFSET(NSDeviceQueryResult
, SupportedCommands
)) + sizeof(UWORD
*))
267 ioreq
->io_Error
= IOERR_BADLENGTH
;
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
);
289 D(bug("CMD_WRITE %p,%d\n", ioreq
->io_Data
, ioreq
->io_Length
));
294 str
= ioreq
->io_Data
;
295 for (i
= 0; i
< ioreq
->io_Length
; i
++)
297 kprintf("%c", *str
++);
302 if (ioreq
->io_Length
== -1) {
303 towrite
= strlen((STRPTR
)ioreq
->io_Data
);
305 towrite
= ioreq
->io_Length
;
309 ioreq
->io_Actual
= writeToConsole((struct ConUnit
*)ioreq
->io_Unit
318 D(bug("CMD_READ %p,%d\n", ioreq
->io_Data
, ioreq
->io_Length
));
323 str
= ioreq
->io_Data
;
324 for (i
= 0; i
< ioreq
->io_Length
; i
++)
326 kprintf("%c", *str
++);
336 /* FIXME: Returns always default keymap */
337 if (ioreq
->io_Length
< sizeof(struct KeyMap
))
338 error
= IOERR_BADLENGTH
;
340 CopyMem(AskKeyMapDefault(), ioreq
->io_Data
, sizeof(struct KeyMap
));
343 D(bug("CD_SETKEYMAP\n"));
346 case CD_ASKDEFAULTKEYMAP
:
347 if (ioreq
->io_Length
< sizeof(struct KeyMap
))
348 error
= IOERR_BADLENGTH
;
350 CopyMem(AskKeyMapDefault(), ioreq
->io_Data
, sizeof(struct KeyMap
));
352 case CD_SETDEFAULTKEYMAP
:
353 D(bug("CD_SETDEFAULTKEYMAP\n"));
358 D(bug("IOERR_NOCMD %d\n", ioreq
->io_Command
));
362 } /* switch (ioreq->io_Command) */
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
);
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");
386 /****************************************************************************************/
388 AROS_LH1(LONG
, abortio
,
389 AROS_LHA(struct IORequest
*, ioreq
, A1
),
390 struct ConsoleBase
*, ConsoleDevice
, 6, Console
)
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
);
419 ReleaseSemaphore(&ConsoleDevice
->consoleTaskLock
);
426 /****************************************************************************************/