revert between 56095 -> 55830 in arch
[AROS.git] / rom / usb / classes / printer / printer.class.c
blob7804d0645e78bda4bd5ad53865d14993d4b403f9
1 /*
2 *----------------------------------------------------------------------------
3 * printer class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "printer.class.h"
12 /* /// "Lib Stuff" */
13 static const STRPTR libname = MOD_NAME_STRING;
15 static
16 const APTR DevFuncTable[] =
18 &AROS_SLIB_ENTRY(devOpen, dev, 1),
19 &AROS_SLIB_ENTRY(devClose, dev, 2),
20 &AROS_SLIB_ENTRY(devExpunge, dev, 3),
21 &AROS_SLIB_ENTRY(devReserved, dev, 4),
22 &AROS_SLIB_ENTRY(devBeginIO, dev, 5),
23 &AROS_SLIB_ENTRY(devAbortIO, dev, 6),
24 (APTR) -1,
27 static int libInit(LIBBASETYPEPTR nh)
29 struct NepPrinterBase *ret = NULL;
31 KPRINTF(10, ("libInit nh: 0x%08lx SysBase: 0x%08lx\n", nh, SysBase));
33 nh->nh_UtilityBase = OpenLibrary("utility.library", 39);
35 #define UtilityBase nh->nh_UtilityBase
37 if(UtilityBase)
39 NewList(&nh->nh_Units);
41 if((nh->nh_DevBase = (struct NepPrtDevBase *) MakeLibrary((APTR) DevFuncTable, NULL, (APTR) devInit,
42 sizeof(struct NepPrtDevBase), NULL)))
44 nh->nh_DevBase->np_ClsBase = nh;
45 Forbid();
46 AddDevice((struct Device *) nh->nh_DevBase);
47 nh->nh_DevBase->np_Library.lib_OpenCnt++;
48 Permit();
49 ret = nh;
50 } else {
51 KPRINTF(20, ("failed to create usbparallel.device\n"));
53 if(!ret)
55 CloseLibrary(UtilityBase);
57 } else {
58 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
61 KPRINTF(10, ("libInit: Ok\n"));
62 return(ret ? TRUE : FALSE);
65 static int libOpen(LIBBASETYPEPTR nh)
67 KPRINTF(10, ("libOpen nh: 0x%08lx\n", nh));
68 nLoadClassConfig(nh);
69 return(TRUE);
72 static int libExpunge(LIBBASETYPEPTR nh)
74 struct NepClassPrinter *ncp;
76 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh));
78 if(nh->nh_DevBase->np_Library.lib_OpenCnt == 1)
80 KPRINTF(1, ("libExpunge: closelibrary utilitybase 0x%08lx\n",
81 UtilityBase));
82 CloseLibrary((struct Library *) UtilityBase);
84 ncp = (struct NepClassPrinter *) nh->nh_Units.lh_Head;
85 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
87 Remove((struct Node *) ncp);
88 FreeVec(ncp);
89 ncp = (struct NepClassPrinter *) nh->nh_Units.lh_Head;
92 nh->nh_DevBase->np_Library.lib_OpenCnt--;
93 RemDevice((struct Device *) nh->nh_DevBase);
95 KPRINTF(5, ("libExpunge: Unloading done! printer.class expunged!\n\n"));
96 } else {
97 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
98 return(FALSE);
101 return(TRUE);
104 ADD2INITLIB(libInit, 0)
105 ADD2OPENLIB(libOpen, 0)
106 ADD2EXPUNGELIB(libExpunge, 0)
107 /* \\\ */
110 * ***********************************************************************
111 * * Library functions *
112 * ***********************************************************************
115 /* /// "usbAttemptInterfaceBinding()" */
116 struct NepClassPrinter * usbAttemptInterfaceBinding(struct NepPrinterBase *nh, struct PsdInterface *pif)
118 struct Library *ps;
119 IPTR ifclass;
120 IPTR subclass;
121 IPTR proto;
123 KPRINTF(1, ("nepPrinterAttemptInterfaceBinding(%08lx)\n", pif));
124 if((ps = OpenLibrary("poseidon.library", 4)))
126 psdGetAttrs(PGA_INTERFACE, pif,
127 IFA_Class, &ifclass,
128 IFA_SubClass, &subclass,
129 IFA_Protocol, &proto,
130 TAG_DONE);
131 CloseLibrary(ps);
132 if((ifclass == PRINTER_CLASSCODE) && (subclass == 0x01) &&
133 ((proto == PRT_PROTO_BIDIR) || (proto == PRT_PROTO_UNIDIR)))// || (proto == PRT_PROTO_IEEE1284)))
135 return(usbForceInterfaceBinding(nh, pif));
138 return(NULL);
140 /* \\\ */
142 /* /// "usbForceInterfaceBinding()" */
143 struct NepClassPrinter * usbForceInterfaceBinding(struct NepPrinterBase *nh, struct PsdInterface *pif)
145 struct Library *ps;
146 struct NepClassPrinter *ncp;
147 struct PsdConfig *pc;
148 struct PsdDevice *pd;
149 STRPTR devname;
150 IPTR altifnum;
151 IPTR ifnum;
152 IPTR cfgnum;
153 IPTR prodid;
154 IPTR vendid;
155 ULONG unitno;
156 BOOL unitfound;
157 UBYTE buf[64];
158 struct Task *tmptask;
160 KPRINTF(1, ("nepPrinterAttemptInterfaceBinding(%08lx)\n", pif));
161 if((ps = OpenLibrary("poseidon.library", 4)))
163 psdGetAttrs(PGA_INTERFACE, pif,
164 IFA_InterfaceNum, &ifnum,
165 IFA_AlternateNum, &altifnum,
166 IFA_Config, &pc,
167 TAG_DONE);
168 psdGetAttrs(PGA_CONFIG, pc,
169 CA_Device, &pd,
170 CA_ConfigNum, &cfgnum,
171 TAG_END);
172 psdGetAttrs(PGA_DEVICE, pd,
173 DA_ProductID, &prodid,
174 DA_VendorID, &vendid,
175 DA_ProductName, &devname,
176 TAG_END);
177 Forbid();
178 /* Find next free unit number */
179 unitno = 0;
180 ncp = (struct NepClassPrinter *) nh->nh_Units.lh_Head;
181 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
183 if(ncp->ncp_UnitNo == unitno)
185 unitno++;
186 ncp = (struct NepClassPrinter *) nh->nh_Units.lh_Head;
187 } else {
188 ncp = (struct NepClassPrinter *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
191 unitfound = FALSE;
192 ncp = (struct NepClassPrinter *) nh->nh_Units.lh_Head;
193 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
195 if((ncp->ncp_UnitAltIfNum == altifnum) && (ncp->ncp_UnitIfNum == ifnum) &&
196 (ncp->ncp_UnitProdID == prodid) && (ncp->ncp_UnitVendorID == vendid))
198 unitno = ncp->ncp_UnitNo;
199 unitfound = TRUE;
200 break;
202 ncp = (struct NepClassPrinter *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
204 if(!unitfound)
206 /* as units are freed in the expunge-vector, the memory is
207 outside the scope of the poseidon library */
208 if(!(ncp = AllocVec(sizeof(struct NepClassPrinter), MEMF_PUBLIC|MEMF_CLEAR)))
210 Permit();
211 CloseLibrary(ps);
212 return(NULL);
214 /* IORequests may be queued even if the task is gone. */
215 NewList(&ncp->ncp_Unit.unit_MsgPort.mp_MsgList);
216 NewList(&ncp->ncp_ReadQueue);
217 NewList(&ncp->ncp_WriteQueue);
218 AddTail(&nh->nh_Units, &ncp->ncp_Unit.unit_MsgPort.mp_Node);
220 ncp->ncp_ClsBase = nh;
221 ncp->ncp_UnitNo = unitno;
222 ncp->ncp_Interface = pif;
223 ncp->ncp_Device = pd;
224 ncp->ncp_Config = pc;
225 ncp->ncp_UnitAltIfNum = altifnum;
226 ncp->ncp_UnitIfNum = ifnum;
227 ncp->ncp_UnitCfgNum = cfgnum;
228 ncp->ncp_UnitProdID = prodid;
229 ncp->ncp_UnitVendorID = vendid;
231 Permit();
233 nLoadClassConfig(nh);
235 psdSafeRawDoFmt(buf, 64, "printer.class<%08lx>", ncp);
236 ncp->ncp_ReadySignal = SIGB_SINGLE;
237 ncp->ncp_ReadySigTask = FindTask(NULL);
238 SetSignal(0, SIGF_SINGLE);
239 if((tmptask = psdSpawnSubTask(buf, nPrinterTask, ncp)))
241 psdBorrowLocksWait(tmptask, 1UL<<ncp->ncp_ReadySignal);
242 if(ncp->ncp_Task)
244 ncp->ncp_ReadySigTask = NULL;
245 //FreeSignal(ncp->ncp_ReadySignal);
246 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
247 "Please welcome '%s' to the family at %s unit %ld!",
248 devname, nh->nh_DevBase->np_Library.lib_Node.ln_Name,
249 ncp->ncp_UnitNo);
251 CloseLibrary(ps);
252 return(ncp);
255 ncp->ncp_ReadySigTask = NULL;
256 //FreeSignal(ncp->ncp_ReadySignal);
257 /* Get rid of unit structure */
258 /*Forbid();
259 Remove((struct Node *) ncp);
260 FreeVec(ncp);
261 Permit();*/
262 CloseLibrary(ps);
264 return(NULL);
266 /* \\\ */
268 /* /// "usbReleaseInterfaceBinding()" */
269 void usbReleaseInterfaceBinding(struct NepPrinterBase *nh, struct NepClassPrinter *ncp)
271 struct Library *ps;
272 STRPTR devname;
274 KPRINTF(1, ("nepPrinterReleaseInterfaceBinding(%08lx)\n", ncp));
275 if((ps = OpenLibrary("poseidon.library", 4)))
277 Forbid();
278 ncp->ncp_ReadySignal = SIGB_SINGLE;
279 ncp->ncp_ReadySigTask = FindTask(NULL);
280 if(ncp->ncp_Task)
282 Signal(ncp->ncp_Task, SIGBREAKF_CTRL_C);
284 Permit();
285 while(ncp->ncp_Task)
287 Wait(1UL<<ncp->ncp_ReadySignal);
289 //FreeSignal(ncp->ncp_ReadySignal);
290 psdGetAttrs(PGA_DEVICE, ncp->ncp_Device, DA_ProductName, &devname, TAG_END);
291 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
292 "'%s' died of boredom.",
293 devname);
294 /*psdFreeVec(ncp);*/
295 CloseLibrary(ps);
298 /* \\\ */
300 /* /// "usbGetAttrsA()" */
301 AROS_LH3(LONG, usbGetAttrsA,
302 AROS_LHA(ULONG, type, D0),
303 AROS_LHA(APTR, usbstruct, A0),
304 AROS_LHA(struct TagItem *, tags, A1),
305 LIBBASETYPEPTR, nh, 5, nep)
307 AROS_LIBFUNC_INIT
309 struct TagItem *ti;
310 LONG count = 0;
312 KPRINTF(1, ("nepHidGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
313 switch(type)
315 case UGA_CLASS:
316 if((ti = FindTagItem(UCCA_Priority, tags)))
318 *((SIPTR *) ti->ti_Data) = 0;
319 count++;
321 if((ti = FindTagItem(UCCA_Description, tags)))
323 *((STRPTR *) ti->ti_Data) = "Bidirectional printer driver via usbparallel.device";
324 count++;
326 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
328 *((IPTR *) ti->ti_Data) = TRUE;
329 count++;
331 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
333 *((IPTR *) ti->ti_Data) = FALSE;
334 count++;
336 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
338 *((IPTR *) ti->ti_Data) = FALSE;
339 count++;
341 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
343 *((IPTR *) ti->ti_Data) = nh->nh_UsingDefaultCfg;
344 count++;
346 break;
348 case UGA_BINDING:
349 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
351 *((IPTR *) ti->ti_Data) = FALSE;
352 count++;
354 break;
356 return(count);
357 AROS_LIBFUNC_EXIT
359 /* \\\ */
361 /* /// "usbSetAttrsA()" */
362 AROS_LH3(LONG, usbSetAttrsA,
363 AROS_LHA(ULONG, type, D0),
364 AROS_LHA(APTR, usbstruct, A0),
365 AROS_LHA(struct TagItem *, tags, A1),
366 LIBBASETYPEPTR, nh, 6, nep)
368 AROS_LIBFUNC_INIT
369 return(0);
370 AROS_LIBFUNC_EXIT
372 /* \\\ */
374 /* /// "usbDoMethodA()" */
375 AROS_LH2(IPTR, usbDoMethodA,
376 AROS_LHA(ULONG, methodid, D0),
377 AROS_LHA(IPTR *, methoddata, A1),
378 LIBBASETYPEPTR, nh, 7, nep)
380 AROS_LIBFUNC_INIT
382 KPRINTF(10, ("Do Method %ld\n", methodid));
383 switch(methodid)
385 case UCM_AttemptInterfaceBinding:
386 return((IPTR) usbAttemptInterfaceBinding(nh, (struct PsdInterface *) methoddata[0]));
388 case UCM_ForceInterfaceBinding:
389 return((IPTR) usbForceInterfaceBinding(nh, (struct PsdInterface *) methoddata[0]));
391 case UCM_ReleaseInterfaceBinding:
392 usbReleaseInterfaceBinding(nh, (struct NepClassPrinter *) methoddata[0]);
393 return(TRUE);
395 case UCM_OpenCfgWindow:
396 return(nOpenCfgWindow(nh));
398 case UCM_ConfigChangedEvent:
399 nLoadClassConfig(nh);
400 return(TRUE);
402 default:
403 break;
405 return(0);
406 AROS_LIBFUNC_EXIT
408 /* \\\ */
410 /* /// "nLoadClassConfig()" */
411 BOOL nLoadClassConfig(struct NepPrinterBase *nh)
413 struct Library *ps;
414 struct ClsGlobalCfg *cgc;
415 struct PsdIFFContext *pic;
417 KPRINTF(10, ("Loading Class Config...\n"));
418 if(nh->nh_GUITask)
420 return(FALSE);
422 if(!(ps = OpenLibrary("poseidon.library", 4)))
424 return(FALSE);
426 Forbid();
427 /* Create default config */
428 nh->nh_CurrentCGC.cgc_ChunkID = AROS_LONG2BE(MAKE_ID('U','P','R','T'));
429 nh->nh_CurrentCGC.cgc_Length = AROS_LONG2BE(sizeof(struct ClsGlobalCfg)-8);
430 nh->nh_CurrentCGC.cgc_EpsonInit = TRUE;
431 nh->nh_CurrentCGC.cgc_SoftReset = TRUE;
432 nh->nh_UsingDefaultCfg = TRUE;
433 pic = psdGetClsCfg(libname);
434 if(pic)
436 if((cgc = psdGetCfgChunk(pic, AROS_LONG2BE(nh->nh_CurrentCGC.cgc_ChunkID))))
438 CopyMem(((UBYTE *) cgc) + 8, ((UBYTE *) &nh->nh_CurrentCGC) + 8, min(AROS_LONG2BE(cgc->cgc_Length), AROS_LONG2BE(nh->nh_CurrentCGC.cgc_Length)));
439 psdFreeVec(cgc);
440 nh->nh_UsingDefaultCfg = FALSE;
443 Permit();
444 CloseLibrary(ps);
445 return(FALSE);
447 /* \\\ */
449 /* /// "nOpenCfgWindow()" */
450 LONG nOpenCfgWindow(struct NepPrinterBase *nh)
452 struct Library *ps;
453 KPRINTF(10, ("Opening GUI...\n"));
454 if(!(ps = OpenLibrary("poseidon.library", 4)))
456 return(FALSE);
458 Forbid();
459 if(!nh->nh_GUITask)
461 if((nh->nh_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", nGUITask, nh)))
463 Permit();
464 CloseLibrary(ps);
465 return(TRUE);
468 Permit();
469 CloseLibrary(ps);
470 return(FALSE);
472 /* \\\ */
474 /**************************************************************************/
476 #undef ps
477 #define ps ncp->ncp_Base
479 /* /// "nPrinterTask()" */
480 AROS_UFH0(void, nPrinterTask)
482 AROS_USERFUNC_INIT
484 struct NepClassPrinter *ncp;
485 ULONG sigmask;
486 ULONG sigs;
487 LONG ioerr;
488 struct PsdConfig *pc;
489 IPTR confignum;
490 UWORD len;
491 BOOL epsonmode = FALSE;
492 UBYTE *tmpbuf;
493 UBYTE portstatus;
494 char *epsonid = "MFG:EPSON";//;CMD:ESCPL2,BDC,D4;MDL:Stylus Photo 870;CLS:PRINTER;DES:EPSON Stylus Photo 870;";
495 struct IOExtPar *ioreq;
496 struct IOExtPar *ioreq2;
497 char epsonusbinit[] = { 0x00, 0x00, 0x00, 0x1b, 0x01, 0x40, 0x45, 0x4a,
498 0x4c, 0x20, 0x31, 0x32, 0x38, 0x34, 0x2e, 0x34,
499 0x0a, 0x40, 0x45, 0x4a, 0x4c, 0x20, 0x20, 0x20,
500 0x20, 0x20, 0x0a };
502 if((ncp = nAllocPrinter()))
504 Forbid();
505 if(ncp->ncp_ReadySigTask)
507 Signal(ncp->ncp_ReadySigTask, 1UL<<ncp->ncp_ReadySignal);
509 Permit();
511 psdGetAttrs(PGA_INTERFACE, ncp->ncp_Interface, IFA_Config, &pc, TAG_END);
512 psdGetAttrs(PGA_CONFIG, pc, CA_ConfigNum, &confignum, TAG_END);
514 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_CLASS|URTF_INTERFACE,
515 UPR_GET_DEVICE_ID, confignum-1, (ULONG) ((ncp->ncp_UnitIfNum<<8)|ncp->ncp_UnitAltIfNum));
517 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, &len, 2);
518 if(ioerr)
520 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_CLASS|URTF_INTERFACE,
521 UPR_GET_DEVICE_ID, 0, (ULONG) (ncp->ncp_UnitIfNum<<8));
523 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, &len, 2);
525 if(!ioerr)
527 len = AROS_BE2WORD(len);
528 if((tmpbuf = psdAllocVec((ULONG) len+1)))
530 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, tmpbuf, (ULONG) len);
531 if(!ioerr)
533 tmpbuf[len] = 0;
534 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
535 "Look at this: '%s'", &tmpbuf[2]);
536 if(!strncmp(&tmpbuf[2], epsonid, 9))
538 epsonmode = TRUE;
540 } else {
541 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
542 "GET_DEVICE_ID (len %ld) failed: %s (%ld)",
543 len, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
545 psdFreeVec(tmpbuf);
547 } else {
548 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
549 "GET_DEVICE_ID (len %ld) failed: %s (%ld)",
550 2, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
553 if(ncp->ncp_ClsBase->nh_CurrentCGC.cgc_SoftReset)
555 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
556 UPR_SOFT_RESET, 0, ((ULONG) ncp->ncp_UnitIfNum)<<8);
557 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
558 if(ioerr)
560 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
561 "SOFT_RESET(USB1.1) failed: %s (%ld)",
562 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
563 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_CLASS|URTF_OTHER,
564 UPR_SOFT_RESET, 0, ((ULONG) ncp->ncp_UnitIfNum)<<8);
565 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
566 if(ioerr)
568 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
569 "SOFT_RESET(USB1.0) failed: %s (%ld)",
570 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
574 if(epsonmode && ncp->ncp_ClsBase->nh_CurrentCGC.cgc_EpsonInit)
576 psdStreamWrite(ncp->ncp_EPOutStream, epsonusbinit, 27);
577 psdStreamFlush(ncp->ncp_EPOutStream);
578 psdAddErrorMsg(RETURN_OK, (STRPTR) libname, "Inserted special Epson init sequence...");
581 /* Main task */
582 sigmask = (1UL<<ncp->ncp_Unit.unit_MsgPort.mp_SigBit)|(1UL<<ncp->ncp_TaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
583 if(ncp->ncp_EPInStream)
585 struct MsgPort *tmpmp = NULL;
586 psdGetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream, PSA_MessagePort, &tmpmp, TAG_END);
587 if(tmpmp)
589 sigmask |= (1UL<<tmpmp->mp_SigBit);
594 while((ioreq = (struct IOExtPar *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
596 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
597 ioreq, ioreq->IOPar.io_Command, ioreq->IOPar.io_Length));
598 switch(ioreq->IOPar.io_Command)
600 case CMD_CLEAR:
601 psdStreamFlush(ncp->ncp_EPOutStream);
602 ReplyMsg((struct Message *) ioreq);
603 break;
605 case CMD_RESET:
606 psdStreamFlush(ncp->ncp_EPOutStream);
607 if(ncp->ncp_ClsBase->nh_CurrentCGC.cgc_SoftReset)
609 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
610 UPR_SOFT_RESET, 0, ((ULONG) ncp->ncp_UnitIfNum)<<8);
611 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
612 if(ioerr)
614 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_CLASS|URTF_OTHER,
615 UPR_SOFT_RESET, 0, ((ULONG) ncp->ncp_UnitIfNum)<<8);
616 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
618 if(ioerr)
620 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
621 "SOFT_RESET failed: %s (%ld)",
622 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
623 ioreq->IOPar.io_Error = ParErr_LineErr;
626 /* Reset does a flush too */
628 case CMD_FLUSH:
629 Forbid();
630 ioreq2 = (struct IOExtPar *) ncp->ncp_WriteQueue.lh_Head;
631 while(ioreq2->IOPar.io_Message.mn_Node.ln_Succ)
633 Remove((struct Node *) ioreq2);
634 ioreq2->IOPar.io_Error = IOERR_ABORTED;
635 ReplyMsg((struct Message *) ioreq2);
636 ioreq2 = (struct IOExtPar *) ncp->ncp_WriteQueue.lh_Head;
638 ioreq2 = (struct IOExtPar *) ncp->ncp_ReadQueue.lh_Head;
639 while(ioreq2->IOPar.io_Message.mn_Node.ln_Succ)
641 Remove((struct Node *) ioreq2);
642 ioreq2->IOPar.io_Error = IOERR_ABORTED;
643 ReplyMsg((struct Message *) ioreq2);
644 ioreq2 = (struct IOExtPar *) ncp->ncp_ReadQueue.lh_Head;
646 ReplyMsg((struct Message *) ioreq);
647 Permit();
648 break;
650 case PDCMD_QUERY:
651 ioreq->io_Status = 0;
652 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
653 UPR_GET_PORT_STATUS, 0, ((ULONG) ncp->ncp_UnitIfNum)<<8);
654 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, &portstatus, 1);
655 if(ioerr)
657 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
658 "GET_PORT_STATUS failed: %s (%ld)",
659 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
660 ioreq->IOPar.io_Error = ParErr_LineErr;
662 if(portstatus & 0x10) ioreq->io_Status |= IOPTF_PARSEL;
663 if(portstatus & 0x20) ioreq->io_Status |= IOPTF_PAPEROUT;
664 ReplyMsg((struct Message *) ioreq);
665 break;
667 /*case PDCMD_SETPARAMS:
668 ReplyMsg((struct Message *) ioreq);
669 break;*/
671 default:
672 ioreq->IOPar.io_Error = IOERR_NOCMD;
673 ReplyMsg((struct Message *) ioreq);
674 break;
677 if(!ncp->ncp_DevSuspend)
679 Forbid();
680 ioreq = (struct IOExtPar *) ncp->ncp_ReadQueue.lh_Head;
681 while(ioreq->IOPar.io_Message.mn_Node.ln_Succ)
683 Remove((struct Node *) ioreq);
684 Permit();
685 ioreq->IOPar.io_Actual = psdStreamRead(ncp->ncp_EPInStream, ioreq->IOPar.io_Data, ioreq->IOPar.io_Length);
686 ioerr = psdGetStreamError(ncp->ncp_EPInStream);
687 if(ioerr == UHIOERR_NAKTIMEOUT)
689 Forbid();
690 AddHead(&ncp->ncp_ReadQueue, &ioreq->IOPar.io_Message.mn_Node);
691 break;
692 } else {
693 if(ioerr > 0)
695 ioreq->IOPar.io_Error = ParErr_LineErr;
696 } else {
697 ioreq->IOPar.io_Error = ioerr;
699 ReplyMsg((struct Message *) ioreq);
701 Forbid();
702 ioreq = (struct IOExtPar *) ncp->ncp_ReadQueue.lh_Head;
704 ioreq = (struct IOExtPar *) ncp->ncp_WriteQueue.lh_Head;
705 while(ioreq->IOPar.io_Message.mn_Node.ln_Succ)
707 Remove((struct Node *) ioreq);
708 ncp->ncp_WritePending = ioreq;
709 Permit();
710 ioreq->IOPar.io_Actual = psdStreamWrite(ncp->ncp_EPOutStream, ioreq->IOPar.io_Data, ioreq->IOPar.io_Length);
711 ncp->ncp_WritePending = NULL;
712 ioerr = psdGetStreamError(ncp->ncp_EPInStream);
713 if(ioerr > 0)
715 ioreq->IOPar.io_Error = ParErr_LineErr;
716 } else {
717 ioreq->IOPar.io_Error = ioerr;
719 ReplyMsg((struct Message *) ioreq);
720 Forbid();
721 ioreq = (struct IOExtPar *) ncp->ncp_WriteQueue.lh_Head;
723 Permit();
725 if(ncp->ncp_FlushBuffer)
727 psdStreamFlush(ncp->ncp_EPOutStream);
728 ncp->ncp_FlushBuffer = FALSE;
730 sigs = Wait(sigmask);
731 } while(!(sigs & SIGBREAKF_CTRL_C));
732 /* Now remove all requests still pending *anywhere* */
733 ncp->ncp_DenyRequests = TRUE;
734 /* Current transfers */
735 psdStreamFlush(ncp->ncp_EPOutStream);
736 /* Read/Write queues */
737 Forbid();
738 ioreq = (struct IOExtPar *) ncp->ncp_WriteQueue.lh_Head;
739 while(ioreq->IOPar.io_Message.mn_Node.ln_Succ)
741 Remove((struct Node *) ioreq);
742 ioreq->IOPar.io_Error = IOERR_ABORTED;
743 ReplyMsg((struct Message *) ioreq);
744 ioreq = (struct IOExtPar *) ncp->ncp_WriteQueue.lh_Head;
746 ioreq = (struct IOExtPar *) ncp->ncp_ReadQueue.lh_Head;
747 while(ioreq->IOPar.io_Message.mn_Node.ln_Succ)
749 Remove((struct Node *) ioreq);
750 ioreq->IOPar.io_Error = IOERR_ABORTED;
751 ReplyMsg((struct Message *) ioreq);
752 ioreq = (struct IOExtPar *) ncp->ncp_ReadQueue.lh_Head;
754 /* Command queue */
755 while((ioreq = (struct IOExtPar *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
757 ioreq->IOPar.io_Error = IOERR_ABORTED;
758 ReplyMsg((struct Message *) ioreq);
760 Permit();
761 KPRINTF(20, ("Going down the river!\n"));
762 nFreePrinter(ncp);
765 AROS_USERFUNC_EXIT
767 /* \\\ */
769 /* /// "nAllocPrinter()" */
770 struct NepClassPrinter * nAllocPrinter(void)
772 struct Task *thistask;
773 struct NepClassPrinter *ncp;
775 thistask = FindTask(NULL);
776 ncp = thistask->tc_UserData;
779 if(!(ncp->ncp_Base = OpenLibrary("poseidon.library", 4)))
781 Alert(AG_OpenLib);
782 break;
784 ncp->ncp_EPIn = psdFindEndpoint(ncp->ncp_Interface, NULL,
785 EA_IsIn, TRUE,
786 EA_TransferType, USEAF_BULK,
787 TAG_END);
788 ncp->ncp_EPOut = psdFindEndpoint(ncp->ncp_Interface, NULL,
789 EA_IsIn, FALSE,
790 EA_TransferType, USEAF_BULK,
791 TAG_END);
792 if(!ncp->ncp_EPOut)
794 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "OUT endpoint missing!");
795 break;
798 ncp->ncp_Unit.unit_MsgPort.mp_SigBit = AllocSignal(-1);
799 ncp->ncp_Unit.unit_MsgPort.mp_SigTask = thistask;
800 ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
801 ncp->ncp_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
802 if((ncp->ncp_TaskMsgPort = CreateMsgPort()))
804 if((ncp->ncp_EP0Pipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, NULL)))
806 psdSetAttrs(PGA_PIPE, ncp->ncp_EP0Pipe,
807 PPA_NakTimeout, TRUE,
808 PPA_NakTimeoutTime, 5000,
809 TAG_END);
810 ncp->ncp_AbortSignal = AllocSignal(-1);
811 if((ncp->ncp_EPOutStream = psdOpenStream(ncp->ncp_EPOut,
812 PSA_BufferSize, 1024,
813 PSA_BufferedWrite, TRUE,
814 PSA_AbortSigMask, 1UL<<ncp->ncp_AbortSignal,
815 TAG_END)))
817 /* EPIn is only optional! */
818 if(!ncp->ncp_EPIn)
820 ncp->ncp_Task = thistask;
821 return(ncp);
823 if((ncp->ncp_EPInStream = psdOpenStream(ncp->ncp_EPIn,
824 PSA_BufferSize, 1024,
825 PSA_ReadAhead, FALSE,
826 PSA_BufferedRead, TRUE,
827 PSA_ShortPktTerm, TRUE,
828 PSA_NakTimeout, TRUE,
829 PSA_NakTimeoutTime, 1000,
830 TAG_END)))
832 ncp->ncp_Task = thistask;
833 return(ncp);
835 psdCloseStream(ncp->ncp_EPOutStream);
837 FreeSignal(ncp->ncp_AbortSignal);
838 psdFreePipe(ncp->ncp_EP0Pipe);
840 DeleteMsgPort(ncp->ncp_TaskMsgPort);
842 FreeSignal((LONG) ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
843 } while(FALSE);
844 CloseLibrary(ncp->ncp_Base);
845 Forbid();
846 ncp->ncp_Task = NULL;
847 if(ncp->ncp_ReadySigTask)
849 Signal(ncp->ncp_ReadySigTask, 1UL<<ncp->ncp_ReadySignal);
851 return(NULL);
853 /* \\\ */
855 /* /// "nFreePrinter()" */
856 void nFreePrinter(struct NepClassPrinter *ncp)
858 struct IOStdReq *ioreq;
859 Forbid();
860 FreeSignal(ncp->ncp_AbortSignal);
861 ncp->ncp_AbortSignal = -1;
862 /* Disable the message port, messages may still be queued */
863 ncp->ncp_Unit.unit_MsgPort.mp_SigTask = NULL;
864 ncp->ncp_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
865 FreeSignal((LONG) ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
866 // get rid of all messages that still have appeared here
867 while((ioreq = (struct IOStdReq *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
869 ioreq->io_Error = IOERR_ABORTED;
870 ReplyMsg((struct Message *) ioreq);
872 Permit();
874 if(ncp->ncp_EPInStream)
876 psdCloseStream(ncp->ncp_EPInStream);
877 ncp->ncp_EPInStream = NULL;
879 psdCloseStream(ncp->ncp_EPOutStream);
880 psdFreePipe(ncp->ncp_EP0Pipe);
881 DeleteMsgPort(ncp->ncp_TaskMsgPort);
882 CloseLibrary(ncp->ncp_Base);
883 Forbid();
884 ncp->ncp_Task = NULL;
885 if(ncp->ncp_ReadySigTask)
887 Signal(ncp->ncp_ReadySigTask, 1UL<<ncp->ncp_ReadySignal);
890 /* \\\ */
892 /**************************************************************************/
894 /* /// "nGUITask()" */
895 AROS_UFH0(void, nGUITask)
897 AROS_USERFUNC_INIT
899 struct Task *thistask;
900 struct NepPrinterBase *nh;
901 APTR pic;
903 thistask = FindTask(NULL);
904 #undef ps
905 #define ps nh->nh_PsdBase
906 #undef IntuitionBase
907 #define IntuitionBase nh->nh_IntBase
908 #undef MUIMasterBase
909 #define MUIMasterBase nh->nh_MUIBase
911 nh = thistask->tc_UserData;
912 ++nh->nh_Library.lib_OpenCnt;
913 if(!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN)))
915 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
916 nGUITaskCleanup(nh);
917 return;
920 if(!(IntuitionBase = OpenLibrary("intuition.library", 39)))
922 KPRINTF(10, ("Couldn't open intuition.library.\n"));
923 nGUITaskCleanup(nh);
924 return;
926 if(!(ps = OpenLibrary("poseidon.library", 4)))
928 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
929 nGUITaskCleanup(nh);
930 return;
933 nh->nh_App = ApplicationObject,
934 MUIA_Application_Title , (IPTR)libname,
935 MUIA_Application_Version , (IPTR)VERSION_STRING,
936 MUIA_Application_Copyright , (IPTR)"©2002-2009 Chris Hodges",
937 MUIA_Application_Author , (IPTR)"Chris Hodges <chrisly@platon42.de>",
938 MUIA_Application_Description, (IPTR)"Settings for the printer.class",
939 MUIA_Application_Base , (IPTR)"PRINTER",
940 MUIA_Application_HelpFile , (IPTR)"HELP:Poseidon.guide",
941 MUIA_Application_Menustrip , (IPTR)MenustripObject,
942 Child, (IPTR)MenuObjectT((IPTR)"Project"),
943 Child, (IPTR)(nh->nh_AboutMI = MenuitemObject,
944 MUIA_Menuitem_Title, (IPTR)"About...",
945 MUIA_Menuitem_Shortcut, (IPTR)"?",
946 End),
947 End,
948 Child, (IPTR)MenuObjectT((IPTR)"Settings"),
949 Child, (IPTR)(nh->nh_UseMI = MenuitemObject,
950 MUIA_Menuitem_Title, (IPTR)"Save",
951 MUIA_Menuitem_Shortcut, (IPTR)"S",
952 End),
953 Child, (IPTR)MenuitemObject,
954 MUIA_Menuitem_Title, (IPTR)NM_BARLABEL,
955 End,
956 Child, (IPTR)(nh->nh_MUIPrefsMI = MenuitemObject,
957 MUIA_Menuitem_Title, (IPTR)"MUI Settings",
958 MUIA_Menuitem_Shortcut, (IPTR)"M",
959 End),
960 End,
961 End,
963 SubWindow, (IPTR)(nh->nh_MainWindow = WindowObject,
964 MUIA_Window_ID , MAKE_ID('M','A','I','N'),
965 MUIA_Window_Title, (IPTR)libname,
966 MUIA_HelpNode, (IPTR)libname,
968 WindowContents, (IPTR)VGroup,
969 /* Child, actionobj = NewObject(ActionClass->mcc_Class, 0,
970 MUIA_ShowMe, FALSE,
971 End, */
972 Child, (IPTR)ColGroup(2), GroupFrameT((IPTR) "Global Settings"),
973 Child, (IPTR)Label((IPTR) "Epson Init Sequence:"),
974 Child, (IPTR)HGroup,
975 Child, (IPTR)(nh->nh_EpsonInitObj = ImageObject, ImageButtonFrame,
976 MUIA_Background, MUII_ButtonBack,
977 MUIA_CycleChain, 1,
978 MUIA_InputMode, MUIV_InputMode_Toggle,
979 MUIA_Image_Spec, MUII_CheckMark,
980 MUIA_Image_FreeVert, TRUE,
981 MUIA_Selected, nh->nh_CurrentCGC.cgc_EpsonInit,
982 MUIA_ShowSelState, FALSE,
983 End),
984 Child, (IPTR)HSpace(0),
985 End,
986 Child, (IPTR)Label((IPTR) "Enable SoftReset:"),
987 Child, (IPTR)HGroup,
988 Child, (IPTR)(nh->nh_SoftResetObj = ImageObject, ImageButtonFrame,
989 MUIA_Background, MUII_ButtonBack,
990 MUIA_CycleChain, 1,
991 MUIA_InputMode, MUIV_InputMode_Toggle,
992 MUIA_Image_Spec, MUII_CheckMark,
993 MUIA_Image_FreeVert, TRUE,
994 MUIA_Selected, nh->nh_CurrentCGC.cgc_SoftReset,
995 MUIA_ShowSelState, FALSE,
996 End),
997 Child, (IPTR)HSpace(0),
998 End,
999 End,
1000 Child, (IPTR)VSpace(0),
1001 Child, (IPTR)HGroup,
1002 MUIA_Group_SameWidth, TRUE,
1003 Child, (IPTR)(nh->nh_UseObj = TextObject, ButtonFrame,
1004 MUIA_Background, MUII_ButtonBack,
1005 MUIA_CycleChain, 1,
1006 MUIA_InputMode, MUIV_InputMode_RelVerify,
1007 MUIA_Text_Contents, (IPTR)"\33c Save ",
1008 End),
1009 Child, (IPTR)(nh->nh_CloseObj = TextObject, ButtonFrame,
1010 MUIA_Background, MUII_ButtonBack,
1011 MUIA_CycleChain, 1,
1012 MUIA_InputMode, MUIV_InputMode_RelVerify,
1013 MUIA_Text_Contents, (IPTR)"\33c Use ",
1014 End),
1015 End,
1016 End,
1017 End),
1018 End;
1020 if(!nh->nh_App)
1022 KPRINTF(10, ("Couldn't create application\n"));
1023 nGUITaskCleanup(nh);
1024 return;
1026 DoMethod(nh->nh_MainWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
1027 nh->nh_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
1028 DoMethod(nh->nh_UseObj, MUIM_Notify, MUIA_Pressed, FALSE,
1029 nh->nh_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
1030 DoMethod(nh->nh_CloseObj, MUIM_Notify, MUIA_Pressed, FALSE,
1031 nh->nh_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
1033 DoMethod(nh->nh_AboutMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1034 nh->nh_App, 2, MUIM_Application_ReturnID, ID_ABOUT);
1035 DoMethod(nh->nh_UseMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1036 nh->nh_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
1037 DoMethod(nh->nh_MUIPrefsMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
1038 nh->nh_App, 2, MUIM_Application_OpenConfigWindow, 0);
1041 IPTR isopen = 0;
1042 IPTR iconify = 0;
1043 ULONG sigs;
1044 ULONG sigmask;
1045 LONG retid;
1047 get(nh->nh_App, MUIA_Application_Iconified, &iconify);
1048 set(nh->nh_MainWindow, MUIA_Window_Open, TRUE);
1049 get(nh->nh_MainWindow, MUIA_Window_Open, &isopen);
1050 if(!(isopen || iconify))
1052 nGUITaskCleanup(nh);
1053 return;
1055 sigmask = 0;
1058 retid = DoMethod(nh->nh_App, MUIM_Application_NewInput, &sigs);
1059 switch(retid)
1061 case ID_STORE_CONFIG:
1062 case MUIV_Application_ReturnID_Quit:
1063 get(nh->nh_EpsonInitObj, MUIA_Selected, &nh->nh_CurrentCGC.cgc_EpsonInit);
1064 get(nh->nh_SoftResetObj, MUIA_Selected, &nh->nh_CurrentCGC.cgc_SoftReset);
1065 pic = psdGetClsCfg(libname);
1066 if(!pic)
1068 psdSetClsCfg(libname, NULL);
1069 pic = psdGetClsCfg(libname);
1071 if(pic)
1073 if(psdAddCfgEntry(pic, &nh->nh_CurrentCGC))
1075 if(retid != MUIV_Application_ReturnID_Quit)
1077 psdSaveCfgToDisk(NULL, FALSE);
1079 retid = MUIV_Application_ReturnID_Quit;
1082 break;
1084 case ID_ABOUT:
1085 MUI_RequestA(nh->nh_App, nh->nh_MainWindow, 0, NULL, "I'm utterly squished!", VERSION_STRING, NULL);
1086 break;
1088 if(retid == MUIV_Application_ReturnID_Quit)
1090 break;
1092 if(sigs)
1094 sigs = Wait(sigs | sigmask | SIGBREAKF_CTRL_C);
1095 if(sigs & SIGBREAKF_CTRL_C)
1097 break;
1100 } while(TRUE);
1101 set(nh->nh_MainWindow, MUIA_Window_Open, FALSE);
1103 nGUITaskCleanup(nh);
1105 AROS_USERFUNC_EXIT
1107 /* \\\ */
1109 /* /// "nGUITaskCleanup()" */
1110 void nGUITaskCleanup(struct NepPrinterBase *nh)
1112 if(nh->nh_App)
1114 MUI_DisposeObject(nh->nh_App);
1115 nh->nh_App = NULL;
1117 if(MUIMasterBase)
1119 CloseLibrary(MUIMasterBase);
1120 MUIMasterBase = NULL;
1122 if(IntuitionBase)
1124 CloseLibrary(IntuitionBase);
1125 IntuitionBase = NULL;
1127 if(ps)
1129 CloseLibrary(ps);
1130 ps = NULL;
1132 Forbid();
1133 nh->nh_GUITask = NULL;
1134 --nh->nh_Library.lib_OpenCnt;
1136 /* \\\ */