2 * Copyright (C) 2012, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
7 * This file handles the creation of the per-unit driver task,
8 * and the creation of the per-unit 'struct PrinterData',
9 * and the pd_PWrite()/pd_PRead() etc IO functions.
12 #include <aros/debug.h>
13 #include <aros/printertag.h>
15 #include <exec/errors.h>
17 #include <proto/exec.h>
18 #include <proto/dos.h>
19 #include <proto/intuition.h>
21 #include <devices/printer.h>
22 #include <datatypes/datatypesclass.h>
24 #define CMD_OPENDEVICE (0x100)
25 #define CMD_CLOSEDEVICE (0x101)
27 #include LC_LIBDEFS_FILE
29 #include "printer_intern.h"
32 #define PDF_IOREQ (1 << 0) /* IORequest 0 or 1 */
33 #define PDF_NOIO (1 << 1) /* PRTA_NoIO was true */
34 #define PDF_CONVERT (1 << 2) /* PRTA_ConvertSource was true */
35 #define PDF_8BITGUNS (1 << 3) /* PRTA_8BitGuns was true */
37 const TEXT driverID
[] = "printer.driver";
39 const struct EasyStruct driverMisuse
= { \
40 .es_StructSize
= sizeof(struct EasyStruct
),
42 .es_Title
= "Improper use of printer.device",
43 .es_TextFormat
= "\"%s\" attempted to use the private\n"
44 "printer.driver method %s.\n"
45 "Only CMD_RAWWRITE is supported.\n",
46 .es_GadgetFormat
= "Ok",
49 #define TASK_PRINTERDATA(pd) \
50 struct PrinterData *pd =(struct PrinterData *)FindTask(NULL)->tc_UserData; \
52 pd->pd_Device.dd_Device.lib_Node.ln_Type != NT_DEVICE || \
53 pd->pd_Device.dd_Device.lib_IdString != driverID) { \
54 struct Library *IntuitionBase; \
55 if ((IntuitionBase = TaggedOpenLibrary(TAGGEDOPEN_INTUITION))) { \
56 IPTR args[] = { (IPTR)FindTask(NULL)->tc_Node.ln_Name, \
58 EasyRequestArgs(NULL, (struct EasyStruct *)&driverMisuse, \
60 CloseLibrary(IntuitionBase); \
66 static BOOL
initMsgPort(struct MsgPort
*port
)
68 BYTE sb
= AllocSignal(-1);
74 port
->mp_SigTask
= FindTask(NULL
);
75 port
->mp_Flags
= PA_SIGNAL
;
76 port
->mp_Node
.ln_Type
= NT_MSGPORT
;
77 NEWLIST(&port
->mp_MsgList
);
82 STATIC
AROS_LH3(LONG
, OpenDevice
,
83 AROS_LHA(struct IORequest
*, io
, A1
),
84 AROS_LHA(IPTR
, unitNumber
, D0
),
85 AROS_LHA(ULONG
, flags
, D1
),
86 struct PrinterUnit
*, pu
, 1, PrinterUnit
)
91 LONG ret
= IOERR_OPENFAIL
;
93 if ((mp
= CreateMsgPort())) {
94 struct IORequest ior
= *io
;
95 ior
.io_Message
.mn_ReplyPort
= mp
;
96 ior
.io_Command
= CMD_OPENDEVICE
;
106 STATIC
AROS_LH1(BPTR
, CloseDevice
,
107 AROS_LCA(struct IORequest
*,io
, A1
),
108 struct PrinterUnit
*, pu
, 2, PrinterUnit
)
115 if ((mp
= CreateMsgPort())) {
116 struct IORequest ior
= *io
;
117 ior
.io_Message
.mn_ReplyPort
= mp
;
118 ior
.io_Command
= CMD_CLOSEDEVICE
;
120 ret
= AROS_LC1(BPTR
, Expunge
,
121 AROS_LCA(struct PrinterUnit
*, pu
, D0
),
122 struct PrinterUnit
*, pu
, 3, PrinterUnit
);
131 STATIC
AROS_LH1(BPTR
, Expunge
,
132 AROS_LHA(struct Library
*, extralib
, D0
),
133 struct PrinterUnit
*, pu
, 3, PrinterUnit
)
137 struct Library
*lib
= (struct Library
*)pu
;
139 if (lib
->lib_OpenCnt
== 0) {
140 BPTR seg
= pu
->pu_PrinterData
.pd_PrinterSegment
;
142 Remove((struct Node
*)lib
);
143 FreeMem((UBYTE
*)lib
- lib
->lib_NegSize
,
144 (ULONG
) (lib
->lib_NegSize
+
147 D(bug("%s: Return segment %p\n", __func__
, BADDR(seg
)));
151 lib
->lib_Flags
|= LIBF_DELEXP
;
159 STATIC
AROS_LH1(void, BeginIO
,
160 AROS_LHA(union printerIO
*, pio
, A1
),
161 struct PrinterUnit
*, pu
, 5, PrinterUnit
)
165 struct IOStdReq
*io
= &pio
->ios
;
166 struct PrinterData
*pd
= &pu
->pu_PrinterData
;
168 D(bug("BeginIO: io_Command = %d, Unit Port %p\n", io
->io_Command
, &pd
->pd_Unit
));
170 io
->io_Flags
&= ~IOF_QUICK
;
171 PutMsg(&pd
->pd_Unit
, &io
->io_Message
);
178 STATIC
AROS_LH1(LONG
, AbortIO
,
179 AROS_LHA(struct IORequest
*, pio
, A1
),
180 struct PrinterUnit
*, pd
, 6, PrinterUnit
)
187 /* These wrappers make sure that we don't
188 * make WaitIO() hang or corrupt memory
189 * if called on an already completed IO
191 static inline LONG
WaitIOStd(struct IOStdReq
*io
)
193 WaitIO((struct IORequest
*)io
);
194 io
->io_Message
.mn_Node
.ln_Type
= 0;
198 static inline LONG
DoIOStd(struct IOStdReq
*io
)
200 DoIO((struct IORequest
*)io
);
201 io
->io_Message
.mn_Node
.ln_Type
= 0;
205 static LONG
pd_PWrite(APTR data
, LONG len
)
208 TASK_PRINTERDATA(pd
);
210 if (pd
->pd_Flags
& PDF_NOIO
)
211 return IOERR_OPENFAIL
;
213 io
= (pd
->pd_Flags
& PDF_IOREQ
) ?
214 (struct IOStdReq
*)&pd
->pd_ior1
:
215 (struct IOStdReq
*)&pd
->pd_ior0
;
217 /* TODO: Call error hook if there is an error */
218 io
->io_Command
= CMD_WRITE
;
224 io
->io_Message
.mn_Length
= sizeof(*io
);
225 SendIO((struct IORequest
*)io
);
227 pd
->pd_Flags
^= PDF_IOREQ
;
232 static LONG
pd_PBothReady(VOID
)
234 TASK_PRINTERDATA(pd
);
236 D(bug("%s:\n", __func__
));
237 if (pd
->pd_Flags
& PDF_NOIO
)
238 return IOERR_OPENFAIL
;
240 WaitIOStd((struct IOStdReq
*)&pd
->pd_ior0
);
241 WaitIOStd((struct IOStdReq
*)&pd
->pd_ior1
);
246 static LONG
pd_PRead(char * buffer
, LONG
*length
, struct timeval
*tv
)
251 TASK_PRINTERDATA(pd
);
253 if (pd
->pd_Flags
& PDF_NOIO
)
254 return IOERR_OPENFAIL
;
256 D(bug("%s:\n", __func__
));
257 io
= (pd
->pd_Flags
& PDF_IOREQ
) ?
258 (struct IOStdReq
*)&pd
->pd_ior1
:
259 (struct IOStdReq
*)&pd
->pd_ior0
;
261 /* TODO: Call error hook if there is an error */
262 pd
->pd_TIOR
.tr_node
.io_Command
= TR_ADDREQUEST
;
263 pd
->pd_TIOR
.tr_node
.io_Flags
= 0;
264 pd
->pd_TIOR
.tr_node
.io_Message
.mn_Length
= sizeof(pd
->pd_TIOR
);
265 pd
->pd_TIOR
.tr_time
= *tv
;
266 SendIO((struct IORequest
*)&pd
->pd_TIOR
);
268 io
->io_Command
= CMD_READ
;
271 io
->io_Length
= *length
;
272 io
->io_Data
= buffer
;
274 io
->io_Message
.mn_Length
= sizeof(*io
);
275 SendIO((struct IORequest
*)io
);
276 sigs
= Wait((1 << io
->io_Message
.mn_ReplyPort
->mp_SigBit
) |
277 (1 << pd
->pd_IORPort
.mp_SigBit
));
278 if (sigs
& (1 << pd
->pd_IORPort
.mp_SigBit
)) {
279 WaitIO((struct IORequest
*)&pd
->pd_TIOR
);
280 if (!CheckIO((struct IORequest
*)io
))
281 AbortIO((struct IORequest
*)io
);
286 *length
= io
->io_Actual
;
288 /* No need to swap units, as this one has been completed */
293 static LONG
pd_CallErrHook(struct Hook
*hook
, union printerIO
*ior
, struct PrtErrMsg
*pem
)
299 /* Only designed to work on the serial port. */
300 static LONG
pd_PQuery(LONG
*numofchars
)
305 TASK_PRINTERDATA(pd
);
307 if (pd
->pd_Flags
& PDF_NOIO
)
308 return IOERR_OPENFAIL
;
310 D(bug("%s:\n", __func__
));
311 io
= (pd
->pd_Flags
& PDF_IOREQ
) ?
312 (struct IOStdReq
*)&pd
->pd_ior1
:
313 (struct IOStdReq
*)&pd
->pd_ior0
;
315 /* TODO: Call error hook if there is an error */
316 io
->io_Command
= SDCMD_QUERY
;
322 io
->io_Message
.mn_Length
= sizeof(*io
);
325 *numofchars
= io
->io_Actual
;
329 /* No need to swap units, as this one has been completed */
334 /* Only designed to work on the serial and parallel port. */
335 static LONG
pd_Query(struct IOStdReq
*sio
)
340 TASK_PRINTERDATA(pd
);
342 D(bug("%s:\n", __func__
));
343 if (pd
->pd_PUnit
->pu_Prefs
.pp_Unit
.pu_DeviceName
[0] != 0 ||
344 (pd
->pd_Flags
& PDF_NOIO
)) {
346 return IOERR_OPENFAIL
;
349 io
= (pd
->pd_Flags
& PDF_IOREQ
) ?
350 (struct IOStdReq
*)&pd
->pd_ior1
:
351 (struct IOStdReq
*)&pd
->pd_ior0
;
353 /* TODO: Call error hook if there is an error */
354 io
->io_Command
= SDCMD_QUERY
;
360 io
->io_Message
.mn_Length
= sizeof(*io
);
363 UBYTE
*data
= sio
->io_Data
;
367 switch (pd
->pd_PUnit
->pu_Prefs
.pp_Txt
.pt_Port
) {
369 status
= ((struct IOExtSer
*)io
)->io_Status
;
372 status
= ((struct IOExtPar
*)io
)->io_Status
;
378 data
[0] = (status
>> 0) & 0xff;
379 data
[1] = (status
>> 8) & 0xff;
381 sio
->io_Actual
= pd
->pd_PUnit
->pu_Prefs
.pp_Txt
.pt_Port
+ 1;
384 /* No need to swap units, as this one has been completed */
389 static LONG
pd_Init(struct PrinterData
*pd
)
391 struct PrinterExtendedData
*ped
= &pd
->pd_SegmentData
->ps_PED
;
392 TEXT devname
[sizeof(pd
->pd_Preferences
.PrtDevName
) + 7 + 1];
394 /* Initialize the unit */
395 strcpy(devname
, pd
->pd_Preferences
.PrtDevName
);
396 strcat(devname
, ".device");
398 D(bug("%s: create msgport %p\n", __func__
, &pd
->pd_Unit
));
399 if (initMsgPort(&pd
->pd_Unit
)) {
400 D(bug("%s: Call ped_Init => %p\n", __func__
, pd
->pd_SegmentData
->ps_PED
.ped_Init
));
401 if (0 == pd
->pd_SegmentData
->ps_PED
.ped_Init(pd
)) {
402 if (pd
->pd_Flags
& PDF_NOIO
)
405 if ((pd
->pd_ior0
.pd_p0
.IOPar
.io_Message
.mn_ReplyPort
=CreateMsgPort())) {
406 if (0 == OpenDevice(devname
,
407 pd
->pd_Preferences
.DefaultPrtUnit
,
408 (struct IORequest
*)&pd
->pd_ior0
, 0)) {
409 D(bug("%s: open %s %d for io 0\n", __func__
, devname
, pd
->pd_Preferences
.DefaultPrtUnit
));
410 pd
->pd_ior0
.pd_p0
.IOPar
.io_Message
.mn_Node
.ln_Type
= 0;
411 if ((pd
->pd_ior1
.pd_p1
.IOPar
.io_Message
.mn_ReplyPort
=CreateMsgPort())) {
412 if (0 == OpenDevice(devname
,
413 pd
->pd_Preferences
.DefaultPrtUnit
,
414 (struct IORequest
*)&pd
->pd_ior1
, 0)) {
415 pd
->pd_ior1
.pd_p1
.IOPar
.io_Message
.mn_Node
.ln_Type
= 0;
416 D(bug("%s: open %s %d for io 1\n", __func__
, devname
, pd
->pd_Preferences
.DefaultPrtUnit
));
417 if (initMsgPort(&pd
->pd_IORPort
)) {
418 pd
->pd_TIOR
.tr_node
.io_Message
.mn_ReplyPort
=&pd
->pd_IORPort
;
419 pd
->pd_TIOR
.tr_node
.io_Message
.mn_Length
= sizeof(pd
->pd_TIOR
);
420 if (0 == OpenDevice("timer.device", UNIT_VBLANK
,
421 (struct IORequest
*)&pd
->pd_TIOR
, 0)) {
422 D(bug("%s: open timer.device %d\n", __func__
, UNIT_VBLANK
));
423 if (ped
->ped_Render
) {
424 LONG err
= ped
->ped_Render(0, 0, 0, PRS_PREINIT
);
431 FreeSignal(pd
->pd_IORPort
.mp_SigBit
);
433 CloseDevice((struct IORequest
*)&pd
->pd_ior1
);
435 DeleteMsgPort(pd
->pd_ior1
.pd_p1
.IOPar
.io_Message
.mn_ReplyPort
);
437 CloseDevice((struct IORequest
*)&pd
->pd_ior0
);
439 DeleteMsgPort(pd
->pd_ior0
.pd_p0
.IOPar
.io_Message
.mn_ReplyPort
);
441 pd
->pd_SegmentData
->ps_PED
.ped_Expunge();
443 FreeSignal(pd
->pd_Unit
.mp_SigBit
);
449 static VOID
pd_Close(struct PrinterData
*pd
, union printerIO
*pio
)
451 struct PrinterBase
*PrinterBase
= pd
->pd_PUnit
->pu_PrinterBase
;
452 struct PrinterExtendedData
*ped
= &pd
->pd_SegmentData
->ps_PED
;
453 LONG unitnum
= pd
->pd_PUnit
->pu_Prefs
.pp_DeviceUnit
.pd_UnitNum
;
457 if (!(pd
->pd_Flags
& PDF_NOIO
)) {
458 CloseDevice((struct IORequest
*)&pd
->pd_TIOR
);
459 FreeSignal(pd
->pd_IORPort
.mp_SigBit
);
460 CloseDevice((struct IORequest
*)&pd
->pd_ior1
);
461 DeleteMsgPort(pd
->pd_ior1
.pd_p1
.IOPar
.io_Message
.mn_ReplyPort
);
462 CloseDevice((struct IORequest
*)&pd
->pd_ior0
);
463 DeleteMsgPort(pd
->pd_ior0
.pd_p0
.IOPar
.io_Message
.mn_ReplyPort
);
465 FreeSignal(pd
->pd_Unit
.mp_SigBit
);
469 /* Remove from the parent printer.device */
470 ObtainSemaphore(&PrinterBase
->pb_UnitLock
[unitnum
]);
471 PrinterBase
->pb_Unit
[unitnum
] = NULL
;
473 PrinterBase
->pb_Device
.dd_Library
.lib_OpenCnt
--;
475 ReleaseSemaphore(&PrinterBase
->pb_UnitLock
[unitnum
]);
478 static LONG
pd_DoPreferences(const union printerIO
*pio
, LONG command
)
482 TASK_PRINTERDATA(pd
);
484 if (pd
->pd_SegmentData
->ps_Version
>= 44 &&
485 (pd
->pd_SegmentData
->ps_PED
.ped_PrinterClass
& PPCF_EXTENDED
) &&
486 pd
->pd_SegmentData
->ps_PED
.ped_DoPreferences
!= NULL
) {
487 err
= pd
->pd_SegmentData
->ps_PED
.ped_DoPreferences((union printerIO
*)pio
, command
);
506 /* A driver task is created on an OpenDevice() call,
507 * and is killed by a CloseDevice() call.
509 static LONG
pd_DriverTask(VOID
)
511 TASK_PRINTERDATA(pd
);
513 struct Process
*me
= (struct Process
*)FindTask(NULL
);
514 struct PrinterExtendedData
*ped
= &pd
->pd_SegmentData
->ps_PED
;
515 struct MagicMessage
*msg
= NULL
;
516 union printerIO
*pio
;
518 BOOL stopped
= FALSE
;
521 /* Wait for startup message -
522 * we use the DOS port because the
523 * pd_Unit has not been created yet
525 D(bug("%s: Waiting for startup. pd=%p\n", __func__
, pd
));
526 WaitPort(&me
->pr_MsgPort
);
527 msg
= (struct MagicMessage
*)GetMsg(&me
->pr_MsgPort
);
529 D(bug("%s: Initializing driver, Unit Port %p\n", __func__
, &pd
->pd_Unit
));
532 D(bug("%s: Replying with %d\n", __func__
, ret
));
533 msg
->mn_Version
= ret
;
534 ReplyMsg((struct Message
*)msg
);
539 /* Wait for unit messages on the pd_Unit */
543 D(bug("%s: Waiting for command on port %p\n", __func__
, &pd
->pd_Unit
));
544 WaitPort(&pd
->pd_Unit
);
545 pio
= (union printerIO
*)GetMsg(&pd
->pd_Unit
);
546 cmd
= pio
->ios
.io_Command
;
548 D(bug("%s: Command = %d\n", __func__
, cmd
));
551 err
= ped
->ped_Open(pio
);
553 Printer_Text_Write(pd
, "\033#1", 3); /* aRIN */
555 case CMD_CLOSEDEVICE
:
559 AbortIO((struct IORequest
*)&pd
->pd_ior0
);
560 WaitIOStd((struct IOStdReq
*)&pd
->pd_ior0
);
561 AbortIO((struct IORequest
*)&pd
->pd_ior1
);
562 WaitIOStd((struct IOStdReq
*)&pd
->pd_ior1
);
568 err
= Printer_Text_Command(pd
, aRIN
, 0, 0, 0, 0);
581 err
= Printer_Text_Write(pd
, pio
->ios
.io_Data
, pio
->ios
.io_Length
);
583 pio
->ios
.io_Actual
= pio
->ios
.io_Length
;
590 err
= pd_PWrite(pio
->ios
.io_Data
, pio
->ios
.io_Length
);
592 pio
->ios
.io_Actual
= pio
->ios
.io_Length
;
601 err
= pd_DoPreferences(pio
, pio
->ios
.io_Command
);
604 pd
->pd_PUnit
->pu_ErrHook
= ((struct IOPrtErrReq
*)pio
)->io_Hook
;
606 case PRD_DUMPRPORTTAGS
:
610 err
= Printer_Gfx_DumpRPort((struct IODRPReq
*)pio
, ((struct IODRPTagsReq
*)pio
)->io_TagList
);
616 err
= Printer_Gfx_DumpRPort((struct IODRPReq
*)pio
, NULL
);
619 err
= pd_Query(&pio
->ios
);
625 pio
->ios
.io_Error
= err
;
626 D(bug("%s: Command = %d, Result = %d\n", __func__
, cmd
, err
));
628 ReplyMsg((struct Message
*)pio
);
629 } while (cmd
!= CMD_CLOSEDEVICE
);
631 D(bug("%s: Shutting down\n", __func__
));
636 /* Synchronize old-style prefs with new style prefs
638 static void pd_SyncPrefs(struct PrinterData
*pd
)
640 struct Preferences
*dprefs
= &pd
->pd_Preferences
;
641 struct PrinterPrefs
*uprefs
= &pd
->pd_PUnit
->pu_Prefs
;
643 dprefs
->PrinterType
= pd
->pd_PrinterType
;
645 strncpy(dprefs
->PrinterFilename
, uprefs
->pp_Txt
.pt_Driver
,
646 sizeof(dprefs
->PrinterFilename
));
647 dprefs
->PrinterFilename
[sizeof(dprefs
->PrinterFilename
)-1] = 0;
649 dprefs
->PrintPitch
= uprefs
->pp_Txt
.pt_Pitch
;
650 dprefs
->PrintQuality
= uprefs
->pp_Txt
.pt_Quality
;
651 dprefs
->PrintSpacing
= uprefs
->pp_Txt
.pt_Spacing
;
652 dprefs
->PrintLeftMargin
= uprefs
->pp_Txt
.pt_LeftMargin
;
653 dprefs
->PrintRightMargin
= uprefs
->pp_Txt
.pt_RightMargin
;
654 dprefs
->PrintImage
= uprefs
->pp_Gfx
.pg_Image
;
655 dprefs
->PrintAspect
= uprefs
->pp_Gfx
.pg_Aspect
;
656 dprefs
->PrintShade
= uprefs
->pp_Gfx
.pg_Shade
;
657 dprefs
->PrintThreshold
= uprefs
->pp_Gfx
.pg_Threshold
;
658 dprefs
->PaperSize
= uprefs
->pp_Txt
.pt_PaperSize
;
659 dprefs
->PaperType
= uprefs
->pp_Txt
.pt_PaperType
;
660 dprefs
->PaperLength
= uprefs
->pp_Txt
.pt_PaperLength
;
662 if (uprefs
->pp_Unit
.pu_DeviceName
[0] == 0) {
663 if (uprefs
->pp_Txt
.pt_Port
== PP_PARALLEL
) {
664 strcpy(dprefs
->PrtDevName
, "parallel");
665 } else if (uprefs
->pp_Txt
.pt_Port
== PP_SERIAL
) {
666 strcpy(dprefs
->PrtDevName
, "serial");
668 strcpy(dprefs
->PrtDevName
, "printtofile");
671 strncpy(dprefs
->PrtDevName
, uprefs
->pp_Unit
.pu_DeviceName
, sizeof(dprefs
->PrtDevName
));
672 dprefs
->PrtDevName
[sizeof(dprefs
->PrtDevName
)-1]=0;
675 if (strcmp(dprefs
->PrtDevName
, "parallel") == 0 ||
676 strcmp(dprefs
->PrtDevName
, "usbparallel") == 0) {
677 pd
->pd_ior0
.pd_p0
.IOPar
.io_Message
.mn_Length
= sizeof(pd
->pd_ior0
.pd_p0
);
678 pd
->pd_ior0
.pd_p0
.io_ParFlags
= PARF_SHARED
;
679 pd
->pd_ior1
.pd_p1
.IOPar
.io_Message
.mn_Length
= sizeof(pd
->pd_ior1
.pd_p1
);
680 pd
->pd_ior1
.pd_p1
.io_ParFlags
= PARF_SHARED
;
681 } else if (strcmp(dprefs
->PrtDevName
, "serial") == 0) {
682 pd
->pd_ior0
.pd_s0
.IOSer
.io_Message
.mn_Length
= sizeof(pd
->pd_ior0
.pd_s0
);
683 pd
->pd_ior0
.pd_s0
.io_SerFlags
= SERF_SHARED
;
684 pd
->pd_ior1
.pd_s1
.IOSer
.io_Message
.mn_Length
= sizeof(pd
->pd_ior1
.pd_s1
);
685 pd
->pd_ior1
.pd_s1
.io_SerFlags
= SERF_SHARED
;
687 pd
->pd_ior0
.pd_i0
.io_Message
.mn_Length
= sizeof(pd
->pd_ior0
.pd_i0
);
688 pd
->pd_ior1
.pd_i1
.io_Message
.mn_Length
= sizeof(pd
->pd_ior1
.pd_i1
);
691 dprefs
->DefaultPrtUnit
= uprefs
->pp_Unit
.pu_UnitNum
;
692 dprefs
->PrintFlags
= uprefs
->pp_Gfx
.pg_GraphicFlags
;
693 dprefs
->PrintMaxWidth
= uprefs
->pp_Gfx
.pg_PrintMaxWidth
;
694 dprefs
->PrintMaxHeight
= uprefs
->pp_Gfx
.pg_PrintMaxHeight
;
695 dprefs
->PrintDensity
= uprefs
->pp_Gfx
.pg_PrintDensity
;
696 dprefs
->PrintXOffset
= uprefs
->pp_Gfx
.pg_PrintXOffset
;
699 /* Create a PrinterData plugin
701 struct PrinterUnit
*Printer_Unit(struct PrinterBase
*PrinterBase
, LONG unitnum
)
703 struct PrinterUnit
*pu
;
704 struct PrinterPrefs prefs
;
705 BPTR olddir
, dir
, driverseg
;
707 if (!Printer_LoadPrefs(PrinterBase
, unitnum
, &prefs
) || prefs
.pp_Txt
.pt_Driver
[0] == 0) {
708 D(bug("%s: No valid prefs for printer.device %d\n", __func__
, unitnum
));
712 if ((dir
= Lock("DEVS:Printers", SHARED_LOCK
)) != BNULL
) {
713 olddir
= CurrentDir(dir
);
714 driverseg
= LoadSeg(prefs
.pp_Txt
.pt_Driver
);
718 D(bug("%s: %s => %p\n", __func__
, prefs
.pp_Txt
.pt_Driver
, BADDR(driverseg
)));
721 struct PrinterSegment
*prtseg
= BADDR(driverseg
);
723 D(bug("%s: magic 0x%08x, expect 0x%08x\n", __func__
, prtseg
->ps_runAlert
, AROS_PRINTER_MAGIC
));
724 if (prtseg
->ps_runAlert
== AROS_PRINTER_MAGIC
) {
726 AROS_SLIB_ENTRY(OpenDevice
,PrinterUnit
,1),
727 AROS_SLIB_ENTRY(CloseDevice
,PrinterUnit
,2),
728 AROS_SLIB_ENTRY(Expunge
,PrinterUnit
,3),
730 AROS_SLIB_ENTRY(BeginIO
,PrinterUnit
,5),
731 AROS_SLIB_ENTRY(AbortIO
,PrinterUnit
,6),
735 if ((pu
= (struct PrinterUnit
*)MakeLibrary(funcs
, NULL
, NULL
, sizeof(*pu
), driverseg
))) {
736 struct Process
*proc
;
737 struct PrinterData
*pd
= &pu
->pu_PrinterData
;
738 struct Device
*dev
= (struct Device
*)pu
;
740 /* Loop back to self */
741 pu
->pu_PrinterBase
= PrinterBase
;
744 /* Duplicate the prefs */
745 CopyMem(&prefs
, &pu
->pu_Prefs
, sizeof(prefs
));
747 /* Update pd->pd_Preferences from pu->pu_Prefs */
750 dev
->dd_Library
.lib_Node
.ln_Name
= pu
->pu_Prefs
.pp_DeviceUnit
.pd_UnitName
;
751 dev
->dd_Library
.lib_Version
= prtseg
->ps_Version
;
752 dev
->dd_Library
.lib_Revision
= prtseg
->ps_Revision
;
753 /* Magic token for TASK_PRINTERDATA() macro */
754 dev
->dd_Library
.lib_IdString
= (APTR
)driverID
;
756 pd
->pd_Device
.dd_Segment
= BADDR(driverseg
);
757 pd
->pd_Device
.dd_ExecBase
= SysBase
;
758 pd
->pd_Device
.dd_CmdVectors
= prtseg
->ps_PED
.ped_Commands
;
759 pd
->pd_Device
.dd_CmdBytes
= NULL
;
760 pd
->pd_Device
.dd_NumCommands
= aRAW
+ 1;
761 pd
->pd_PrinterSegment
= driverseg
;
762 pd
->pd_PrinterType
= 0;
763 pd
->pd_SegmentData
= prtseg
;
764 pd
->pd_PWrite
= pd_PWrite
;
765 pd
->pd_PBothReady
= pd_PBothReady
;
766 pd
->pd_PRead
= pd_PRead
;
767 pd
->pd_CallErrHook
= (APTR
)pd_CallErrHook
;
768 pd
->pd_PQuery
= pd_PQuery
;
769 pd
->pd_UnitNumber
= unitnum
;
770 pd
->pd_DriverName
= &pd
->pd_Preferences
.PrinterFilename
[0];
772 /* Make RemDevice() and friends happy */
775 proc
= CreateNewProcTags(NP_Entry
, pd_DriverTask
,
776 NP_Name
, prefs
.pp_DeviceUnit
.pd_UnitName
,
781 D(bug("%s: Driver process %p\n", __func__
, proc
));
783 struct MsgPort
*port
;
785 /* Store the process here... */
786 pu
->pu_Process
= proc
;
789 if ((port
= CreateMsgPort())) {
790 struct MagicMessage startup
, *reply
;
792 D(bug("%s: Driver unit port %p\n", __func__
, port
));
793 startup
.mn_ReplyPort
=port
;
794 startup
.mn_Length
= sizeof(startup
);
795 startup
.mn_Magic
= AROS_MAKE_ID('p','r','u','n');
796 startup
.mn_Version
= 0;
797 PutMsg(&proc
->pr_MsgPort
, (struct Message
*)&startup
);
799 D(bug("%s: Driver replied\n", __func__
));
800 reply
= (struct MagicMessage
*)GetMsg(port
);
801 D(bug("%s: Driver reply = %p\n", __func__
, reply
));
803 D(bug("%s: Driver port %p gone\n", __func__
, port
));
804 if (reply
== &startup
&&
805 reply
->mn_Length
== sizeof(*reply
) &&
806 reply
->mn_Magic
== AROS_MAKE_ID('p','r','u','n') &&
807 reply
->mn_Version
== 0) {
809 D(bug("%s: Driver started\n", __func__
));
812 D(bug("%s: Driver startup failed\n", __func__
));
814 /* pd_DriverTask will kill itself on failure */
816 /* pd_Expunge() calls UnLoadSeg() automatically */
817 RemDevice((struct Device
*)pd
);
822 UnLoadSeg(driverseg
);