Documented GVF_SAVE_VAR alongside other flags, and removed a query/doubt
[AROS.git] / rom / usb / classes / serialpl2303 / serialpl2303.class.c
blob894aa32a09b911a00b74952ff186edb81e94f4f4
1 /*
2 *----------------------------------------------------------------------------
3 * serialpl2303 class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "serialpl2303.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 NepSerialBase *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 NepSerDevBase *) MakeLibrary((APTR) DevFuncTable, NULL, (APTR) devInit,
42 sizeof(struct NepSerDevBase), 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 serialpl2303.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 libExpunge(LIBBASETYPEPTR nh)
67 struct NepClassSerial *ncp;
69 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh));
71 if(nh->nh_DevBase->np_Library.lib_OpenCnt == 1)
73 KPRINTF(1, ("libExpunge: closelibrary utilitybase 0x%08lx\n",
74 UtilityBase));
75 CloseLibrary((struct Library *) UtilityBase);
77 ncp = (struct NepClassSerial *) nh->nh_Units.lh_Head;
78 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
80 Remove((struct Node *) ncp);
81 FreeVec(ncp);
82 ncp = (struct NepClassSerial *) nh->nh_Units.lh_Head;
85 nh->nh_DevBase->np_Library.lib_OpenCnt--;
86 RemDevice((struct Device *) nh->nh_DevBase);
88 KPRINTF(5, ("libExpunge: Unloading done! serialpl2303.class expunged!\n\n"));
89 } else {
90 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
91 return(FALSE);
94 return(TRUE);
97 ADD2INITLIB(libInit, 0)
98 ADD2EXPUNGELIB(libExpunge, 0)
99 /* \\\ */
102 * ***********************************************************************
103 * * Library functions *
104 * ***********************************************************************
107 struct AutoBindData
109 UWORD abd_VendID;
110 UWORD abd_ProdID;
113 struct AutoBindData ClassBinds[] =
115 { PL2303_VENDOR_ID , PL2303_PRODUCT_ID },
116 { PL2303_VENDOR_ID , PL2303_PRODUCT_ID_RSAQ2 },
117 { PL2303_VENDOR_ID , PL2303_PRODUCT_ID_RSAQ3 },
118 { PL2303_VENDOR_ID , PL2303_PRODUCT_ID_DCU11 },
119 { PL2303_VENDOR_ID , PL2303_PRODUCT_ID_PHAROS },
120 { PL2303_VENDOR_ID , PL2303_PRODUCT_ID_ALDIGA },
121 { ATEN_VENDOR_ID , ATEN_PRODUCT_ID },
122 { ATEN_VENDOR_ID2 , ATEN_PRODUCT_ID },
123 { IODATA_VENDOR_ID , IODATA_PRODUCT_ID },
124 { IODATA_VENDOR_ID , IODATA_PRODUCT_ID_RSAQ5 },
125 { ELCOM_VENDOR_ID , ELCOM_PRODUCT_ID },
126 { ELCOM_VENDOR_ID , ELCOM_PRODUCT_ID_UCSGT },
127 { ITEGNO_VENDOR_ID , ITEGNO_PRODUCT_ID },
128 { ITEGNO_VENDOR_ID , ITEGNO_PRODUCT_ID_2 },
129 { MA620_VENDOR_ID , MA620_PRODUCT_ID },
130 { RATOC_VENDOR_ID , RATOC_PRODUCT_ID },
131 { RATOC_VENDOR_ID , RATOC_PRODUCT_ID_USB60F },
132 { TRIPP_VENDOR_ID , TRIPP_PRODUCT_ID },
133 { RADIOSHACK_VENDOR_ID , RADIOSHACK_PRODUCT_ID },
134 { DCU10_VENDOR_ID , DCU10_PRODUCT_ID },
135 { ALCATEL_VENDOR_ID , ALCATEL_PRODUCT_ID },
136 { SITECOM_VENDOR_ID , SITECOM_PRODUCT_ID },
137 { SAMSUNG_VENDOR_ID , SAMSUNG_PRODUCT_ID },
138 { SIEMENS_VENDOR_ID , SIEMENS_PRODUCT_ID_SX1 },
139 { SIEMENS_VENDOR_ID , SIEMENS_PRODUCT_ID_X65 },
140 { SIEMENS_VENDOR_ID , SIEMENS_PRODUCT_ID_X75 },
141 { SIEMENS_VENDOR_ID , SIEMENS_PRODUCT_ID_EF81 },
142 { SYNTECH_VENDOR_ID , SYNTECH_PRODUCT_ID },
143 { NOKIA_CA42_VENDOR_ID , NOKIA_CA42_PRODUCT_ID },
144 { CA_42_CA42_VENDOR_ID , CA_42_CA42_PRODUCT_ID },
145 { SAGEM_VENDOR_ID , SAGEM_PRODUCT_ID },
146 { LEADTEK_VENDOR_ID , LEADTEK_9531_PRODUCT_ID },
147 { SPEEDDRAGON_VENDOR_ID , SPEEDDRAGON_PRODUCT_ID },
148 { OTI_VENDOR_ID , OTI_PRODUCT_ID },
149 { DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID },
150 { BELKIN_VENDOR_ID , BELKIN_PRODUCT_ID },
151 { ALCOR_VENDOR_ID , ALCOR_PRODUCT_ID },
152 { WS002IN_VENDOR_ID , WS002IN_PRODUCT_ID },
153 { COREGA_VENDOR_ID , COREGA_PRODUCT_ID },
154 { HL340_VENDOR_ID , HL340_PRODUCT_ID },
155 { YCCABLE_VENDOR_ID , YCCABLE_PRODUCT_ID },
156 { 0, 0 }
159 /* /// "usbAttemptDeviceBinding()" */
160 struct NepClassSerial * usbAttemptDeviceBinding(struct NepSerialBase *nh, struct PsdDevice *pd)
162 struct Library *ps;
163 struct AutoBindData *abd = ClassBinds;
164 IPTR prodid;
165 IPTR vendid;
167 KPRINTF(1, ("nepSerialAttemptDeviceBinding(%08lx)\n", pd));
168 if((ps = OpenLibrary("poseidon.library", 4)))
170 psdGetAttrs(PGA_DEVICE, pd,
171 DA_VendorID, &vendid,
172 DA_ProductID, &prodid,
173 TAG_END);
174 CloseLibrary(ps);
175 while(abd->abd_VendID)
177 if((vendid == abd->abd_VendID) && (prodid == abd->abd_ProdID))
179 return(usbForceDeviceBinding(nh, pd));
181 abd++;
184 return(NULL);
186 /* \\\ */
188 /* /// "usbForceDeviceBinding()" */
189 struct NepClassSerial * usbForceDeviceBinding(struct NepSerialBase *nh, struct PsdDevice *pd)
191 struct Library *ps;
192 struct NepClassSerial *ncp;
193 STRPTR devname;
194 IPTR prodid;
195 IPTR vendid;
196 ULONG unitno;
197 BOOL unitfound;
198 UBYTE buf[64];
199 struct Task *tmptask;
201 KPRINTF(1, ("nepSerialForceDeviceBinding(%08lx)\n", pd));
202 if((ps = OpenLibrary("poseidon.library", 4)))
204 psdGetAttrs(PGA_DEVICE, pd,
205 DA_ProductID, &prodid,
206 DA_VendorID, &vendid,
207 DA_ProductName, &devname,
208 TAG_END);
209 Forbid();
210 /* Find next free unit number */
211 unitno = 0;
212 ncp = (struct NepClassSerial *) nh->nh_Units.lh_Head;
213 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
215 if(ncp->ncp_UnitNo == unitno)
217 unitno++;
218 ncp = (struct NepClassSerial *) nh->nh_Units.lh_Head;
219 } else {
220 ncp = (struct NepClassSerial *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
223 unitfound = FALSE;
224 ncp = (struct NepClassSerial *) nh->nh_Units.lh_Head;
225 while(ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ)
227 if((ncp->ncp_UnitProdID == prodid) && (ncp->ncp_UnitVendorID == vendid))
229 unitno = ncp->ncp_UnitNo;
230 unitfound = TRUE;
231 break;
233 ncp = (struct NepClassSerial *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
235 if(!unitfound)
237 /* as units are freed in the expunge-vector, the memory is
238 outside the scope of the poseidon library */
239 if(!(ncp = AllocVec(sizeof(struct NepClassSerial), MEMF_PUBLIC|MEMF_CLEAR)))
241 Permit();
242 CloseLibrary(ps);
243 return(NULL);
245 /* IORequests may be queued even if the task is gone. */
246 NewList(&ncp->ncp_Unit.unit_MsgPort.mp_MsgList);
247 NewList(&ncp->ncp_ReadQueue);
248 NewList(&ncp->ncp_WriteQueue);
249 AddTail(&nh->nh_Units, &ncp->ncp_Unit.unit_MsgPort.mp_Node);
250 ncp->ncp_DenyRequests = TRUE;
252 ncp->ncp_UnitNo = unitno;
253 ncp->ncp_Device = pd;
254 ncp->ncp_UnitProdID = prodid;
255 ncp->ncp_UnitVendorID = vendid;
256 Permit();
258 psdSafeRawDoFmt(buf, 64, "serialpl2303.class<%08lx>", ncp);
259 ncp->ncp_ReadySignal = SIGB_SINGLE;
260 ncp->ncp_ReadySigTask = FindTask(NULL);
261 SetSignal(0, SIGF_SINGLE);
262 if((tmptask = psdSpawnSubTask(buf, nSerialTask, ncp)))
264 psdBorrowLocksWait(tmptask, 1UL<<ncp->ncp_ReadySignal);
265 if(ncp->ncp_Task)
267 ncp->ncp_ReadySigTask = NULL;
268 //FreeSignal(ncp->ncp_ReadySignal);
269 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
270 "Another serial killer '%s' at %s unit %ld!",
271 devname, nh->nh_DevBase->np_Library.lib_Node.ln_Name,
272 ncp->ncp_UnitNo);
274 CloseLibrary(ps);
275 return(ncp);
278 ncp->ncp_ReadySigTask = NULL;
279 //FreeSignal(ncp->ncp_ReadySignal);
280 /* Get rid of unit structure */
281 /*Forbid();
282 Remove((struct Node *) ncp);
283 FreeVec(ncp);
284 Permit();*/
285 CloseLibrary(ps);
287 return(NULL);
289 /* \\\ */
291 /* /// "usbReleaseDeviceBinding()" */
292 void usbReleaseDeviceBinding(struct NepSerialBase *nh, struct NepClassSerial *ncp)
294 struct Library *ps;
295 STRPTR devname;
297 KPRINTF(1, ("nepSerialReleaseDeviceBinding(%08lx)\n", ncp));
298 if((ps = OpenLibrary("poseidon.library", 4)))
300 Forbid();
301 ncp->ncp_ReadySignal = SIGB_SINGLE;
302 ncp->ncp_ReadySigTask = FindTask(NULL);
303 if(ncp->ncp_Task)
305 Signal(ncp->ncp_Task, SIGBREAKF_CTRL_C);
307 Permit();
308 while(ncp->ncp_Task)
310 Wait(1L<<ncp->ncp_ReadySignal);
312 //FreeSignal(ncp->ncp_ReadySignal);
313 psdGetAttrs(PGA_DEVICE, ncp->ncp_Device, DA_ProductName, &devname, TAG_END);
314 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
315 "Lost the wire on '%s'.",
316 devname);
317 /*psdFreeVec(ncp);*/
318 CloseLibrary(ps);
321 /* \\\ */
323 /* /// "usbGetAttrsA()" */
324 AROS_LH3(LONG, usbGetAttrsA,
325 AROS_LHA(ULONG, type, D0),
326 AROS_LHA(APTR, usbstruct, A0),
327 AROS_LHA(struct TagItem *, tags, A1),
328 LIBBASETYPEPTR, nh, 5, nep)
330 AROS_LIBFUNC_INIT
332 struct TagItem *ti;
333 LONG count = 0;
335 KPRINTF(1, ("nepHidGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
336 switch(type)
338 case UGA_CLASS:
339 if((ti = FindTagItem(UCCA_Priority, tags)))
341 *((SIPTR *) ti->ti_Data) = 0;
342 count++;
344 if((ti = FindTagItem(UCCA_Description, tags)))
346 *((STRPTR *) ti->ti_Data) = "PL2303 serial adapter via serialpl2303.device";
347 count++;
349 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
351 *((IPTR *) ti->ti_Data) = FALSE;
352 count++;
354 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
356 *((IPTR *) ti->ti_Data) = FALSE;
357 count++;
359 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
361 *((IPTR *) ti->ti_Data) = FALSE;
362 count++;
364 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
366 *((IPTR *) ti->ti_Data) = TRUE;
367 count++;
369 break;
371 case UGA_BINDING:
372 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
374 *((IPTR *) ti->ti_Data) = TRUE;
375 count++;
377 break;
379 return(count);
380 AROS_LIBFUNC_EXIT
382 /* \\\ */
384 /* /// "usbSetAttrsA()" */
385 AROS_LH3(LONG, usbSetAttrsA,
386 AROS_LHA(ULONG, type, D0),
387 AROS_LHA(APTR, usbstruct, A0),
388 AROS_LHA(struct TagItem *, tags, A1),
389 LIBBASETYPEPTR, nh, 6, nep)
391 AROS_LIBFUNC_INIT
392 return(0);
393 AROS_LIBFUNC_EXIT
395 /* \\\ */
397 /* /// "usbDoMethodA()" */
398 AROS_LH2(IPTR, usbDoMethodA,
399 AROS_LHA(ULONG, methodid, D0),
400 AROS_LHA(IPTR *, methoddata, A1),
401 LIBBASETYPEPTR, nh, 7, nep)
403 AROS_LIBFUNC_INIT
405 KPRINTF(10, ("Do Method %ld\n", methodid));
406 switch(methodid)
408 case UCM_AttemptDeviceBinding:
409 return((IPTR) usbAttemptDeviceBinding(nh, (struct PsdDevice *) methoddata[0]));
411 case UCM_ForceDeviceBinding:
412 return((IPTR) usbForceDeviceBinding(nh, (struct PsdDevice *) methoddata[0]));
414 case UCM_ReleaseDeviceBinding:
415 usbReleaseDeviceBinding(nh, (struct NepClassSerial *) methoddata[0]);
416 return(TRUE);
418 default:
419 break;
421 return(0);
422 AROS_LIBFUNC_EXIT
424 /* \\\ */
426 /**************************************************************************/
428 #undef ps
429 #define ps ncp->ncp_Base
431 /* /// "nSetSerialMode()" */
432 void nSetSerialMode(struct NepClassSerial *ncp, struct IOExtSer *ioreq)
434 struct UsbCDCLineCoding ulc;
435 LONG ioerr;
436 ULONG bufsize = ioreq->io_RBufLen / NUMREADPIPES;
438 if(bufsize < 1024)
440 bufsize = 1024;
442 bufsize = (bufsize + 127) & (~127);
444 psdSetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
445 PSA_BufferSize, bufsize,
446 TAG_END);
447 if(ioreq->io_SerFlags & SERF_EOFMODE)
449 psdSetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
450 PSA_TermArray, &ioreq->io_TermArray,
451 TAG_END);
452 psdSetAttrs(PGA_PIPESTREAM, ncp->ncp_EPOutStream,
453 PSA_TermArray, &ioreq->io_TermArray,
454 TAG_END);
455 } else {
456 psdSetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
457 PSA_TermArray, NULL,
458 TAG_END);
459 psdSetAttrs(PGA_PIPESTREAM, ncp->ncp_EPOutStream,
460 PSA_TermArray, NULL,
461 TAG_END);
463 ulc.dwDTERate = AROS_LONG2LE(ioreq->io_Baud);
464 if(ioreq->io_StopBits == 1)
466 ulc.bCharFormat = 0;
468 else if(ioreq->io_StopBits == 2)
470 ulc.bCharFormat = 2;
471 } else {
472 ioreq->IOSer.io_Error = SerErr_InvParam;
473 ulc.bCharFormat = 0;
475 ulc.bParityType = 0; /* no parity */
476 if(ioreq->io_SerFlags & SERF_PARTY_ON)
478 if(ioreq->io_SerFlags & SERF_PARTY_ODD)
480 ulc.bParityType = 1; /* odd parity */
481 } else {
482 ulc.bParityType = 2; /* even parity */
485 if(ioreq->io_ExtFlags & SEXTF_MSPON)
487 ioreq->io_SerFlags |= SERF_PARTY_ON;
488 if(ioreq->io_ExtFlags & SEXTF_MARK)
490 ulc.bParityType = 3; /* mark parity */
491 } else {
492 ulc.bParityType = 4; /* space parity */
495 ulc.bDataBits = ioreq->io_ReadLen;
496 if(ioreq->io_SerFlags & SERF_RAD_BOOGIE)
498 ulc.bCharFormat = 0; /* 1 stop bit */
499 ulc.bParityType = 0; /* no parity */
500 ulc.bDataBits = 8; /* 8 data bits */
503 if(ncp->ncp_SiemensCrap)
505 // the siemens thing supports none of these...
506 return;
509 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
510 UCDCR_SET_LINE_CODING, 0, 0);
511 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, &ulc, 7);
512 if(ioerr)
514 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
515 "SET_LINE_CODING failed: %s (%ld)",
516 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
517 ioreq->IOSer.io_Error = SerErr_LineErr;
519 /* Activate RTS/CTS */
520 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
521 UCDCR_SET_CONTROL_LINE_STATE, (ULONG) ((ioreq->io_SerFlags & SERF_7WIRE) ? 0 : UPLF_CONTROL_RTS|UPLF_CONTROL_DTR), 0);
522 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
523 if(ioerr)
525 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
526 "SET_CONTROL_LINE_STATE failed: %s (%ld)",
527 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
528 ioreq->IOSer.io_Error = SerErr_LineErr;
530 if(ioreq->io_SerFlags & SERF_7WIRE) /* Activate RTS/CTS */
532 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_VENDOR|URTF_DEVICE,
533 UPLR_WRITE, 0, (ULONG) (ncp->ncp_HXChipset ? 0x61 : 0x41));
534 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
535 if(ioerr)
537 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
538 "SET_RTS/CTS failed: %s (%ld)",
539 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
540 ioreq->IOSer.io_Error = SerErr_LineErr;
544 /* \\\ */
546 /* /// "nSerialTask()" */
547 AROS_UFH0(void, nSerialTask)
549 AROS_USERFUNC_INIT
551 struct NepClassSerial *ncp;
552 struct PsdPipe *pp;
553 ULONG sigmask;
554 ULONG sigs;
555 LONG ioerr;
556 LONG len;
557 struct IOExtSer *ioreq;
558 struct IOExtSer *ioreq2;
559 UWORD serstate;
560 IPTR pending;
561 UBYTE buf[8];
562 ULONG seqnr;
563 UWORD *seqptr;
564 UWORD initseq[] = { URTF_IN , 0x8484, 0,
565 URTF_OUT, 0x0404, 0,
566 URTF_IN , 0x8484, 0,
567 URTF_IN , 0x8383, 0,
568 URTF_IN , 0x8484, 0,
569 URTF_OUT, 0x0404, 1,
570 URTF_IN , 0x8484, 0,
571 URTF_IN , 0x8383, 0,
572 URTF_OUT, 0x0000, 1,
573 URTF_OUT, 0x0001, 0,
574 //URTF_OUT, 0x0001, 0xc0,
575 URTF_OUT, 0x0002, 0x24,
576 0xffff };
578 UWORD inithxs[] = { URTF_IN , 0x8484, 0,
579 URTF_OUT, 0x0404, 0,
580 URTF_IN , 0x8484, 0,
581 URTF_IN , 0x8383, 0,
582 URTF_IN , 0x8484, 0,
583 URTF_OUT, 0x0404, 1,
584 URTF_IN , 0x8484, 0,
585 URTF_IN , 0x8383, 0,
586 URTF_OUT, 0x0000, 1,
587 URTF_OUT, 0x0002, 0x44,
588 URTF_OUT, 0x0008, 0,
589 URTF_OUT, 0x0009, 0,
590 0xffff };
592 if((ncp = nAllocSerial()))
594 Forbid();
595 if(ncp->ncp_ReadySigTask)
597 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
599 Permit();
601 /* HX Chipset speciality: clear endpoint stalls */
602 if(!ncp->ncp_HXChipset)
604 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
605 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncp->ncp_EPInNum|URTF_IN);
606 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
607 if(ioerr)
609 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
610 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
611 ncp->ncp_EPInNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
613 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
614 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) ncp->ncp_EPOutNum);
615 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
616 if(ioerr)
618 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
619 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
620 ncp->ncp_EPOutNum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
622 seqptr = initseq;
623 } else {
624 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
625 "Using HX chipset init sequence...");
626 seqptr = inithxs;
629 pp = ncp->ncp_EP0Pipe;
630 if(ncp->ncp_SiemensCrap)
632 /* The siemens thing is probably not even a PL2303 chipset, it needs
633 very different initalisation! */
634 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
635 "Using Siemens chipset init sequence...");
636 psdPipeSetup(pp, URTF_OUT|URTF_VENDOR|URTF_INTERFACE, 0x02, 0, 0);
637 ioerr = psdDoPipe(pp, NULL, 0);
638 if(ioerr)
640 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
641 "Error during Siemens sequence cmd %ld: %s (%ld)",
643 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
645 psdPipeSetup(pp, URTF_IN|URTF_VENDOR|URTF_INTERFACE, 0x01, 0, 0);
646 ioerr = psdDoPipe(pp, buf, 1);
647 if(ioerr)
649 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
650 "Error during Siemens sequence cmd %ld: %s (%ld)",
652 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
655 psdPipeSetup(pp, URTF_IN|URTF_VENDOR|URTF_INTERFACE, 0x04, 0x0800, 0);
656 ioerr = psdDoPipe(pp, buf, 2);
657 if(ioerr)
659 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
660 "Error during Siemens sequence cmd %ld: %s (%ld)",
662 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
664 psdSendPipe(ncp->ncp_EPIntPipe, ncp->ncp_SerialStateReq, 10);
665 } else {
666 /* Output init sequence */
667 seqnr = 1;
668 while(*seqptr != 0xffff)
670 UWORD dir, idx, val;
671 dir = *seqptr++;
672 val = *seqptr++;
673 idx = *seqptr++;
674 if(dir == URTF_IN)
676 psdPipeSetup(pp, URTF_IN|URTF_VENDOR|URTF_DEVICE, UPLR_READ,
677 (ULONG) val, (ULONG) idx);
678 ioerr = psdDoPipe(pp, buf, 1);
679 } else {
680 psdPipeSetup(pp, URTF_OUT|URTF_VENDOR|URTF_DEVICE, UPLR_WRITE,
681 (ULONG) val, (ULONG) idx);
682 ioerr = psdDoPipe(pp, NULL, 0);
684 if(ioerr)
686 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
687 "Error during init sequence cmd %ld: %s (%ld)",
688 seqnr,
689 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
691 seqnr++;
693 psdSendPipe(ncp->ncp_EPIntPipe, &ncp->ncp_SerialStateReq[UART_STATE], 1);
696 sigmask = (1UL<<ncp->ncp_Unit.unit_MsgPort.mp_SigBit)|(1UL<<ncp->ncp_TaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
698 struct MsgPort *tmpmp = NULL;
699 psdGetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream, PSA_MessagePort, &tmpmp, TAG_END);
700 if(tmpmp)
702 sigmask |= (1UL<<tmpmp->mp_SigBit);
707 psdStreamRead(ncp->ncp_EPInStream, NULL, 0);
708 while((pp = (struct PsdPipe *) GetMsg(ncp->ncp_TaskMsgPort)))
710 KPRINTF(1, ("Pipe back %08lx\n", pp));
711 if(pp == ncp->ncp_EPIntPipe)
713 KPRINTF(5, ("Int serial state back %04lx\n", ncp->ncp_SerialStateReq[UART_STATE]));
714 ioerr = psdGetPipeError(pp);
715 len = psdGetPipeActual(pp);
716 if(ioerr && (ioerr != UHIOERR_RUNTPACKET))
718 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
719 "Serial state failed: %s (%ld), len=%d",
720 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr, (int)len);
721 psdDelayMS(100);
723 if(ncp->ncp_SiemensCrap)
725 psdSendPipe(ncp->ncp_EPIntPipe, &ncp->ncp_SerialStateReq[UART_STATE], 1);
726 } else {
727 psdSendPipe(ncp->ncp_EPIntPipe, ncp->ncp_SerialStateReq, 10);
729 break;
732 while((ioreq = (struct IOExtSer *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
734 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
735 ioreq, ioreq->IOSer.io_Command, ioreq->IOSer.io_Length));
736 switch(ioreq->IOSer.io_Command)
738 case CMD_CLEAR:
739 psdStreamFlush(ncp->ncp_EPOutStream);
740 ReplyMsg((struct Message *) ioreq);
741 break;
743 case CMD_RESET:
744 /* Reset does a flush too */
745 case CMD_FLUSH:
746 Forbid();
747 ioreq2 = (struct IOExtSer *) ncp->ncp_WriteQueue.lh_Head;
748 while(ioreq2->IOSer.io_Message.mn_Node.ln_Succ)
750 Remove((struct Node *) ioreq2);
751 ioreq2->IOSer.io_Error = IOERR_ABORTED;
752 ReplyMsg((struct Message *) ioreq2);
753 ioreq2 = (struct IOExtSer *) ncp->ncp_WriteQueue.lh_Head;
755 ioreq2 = (struct IOExtSer *) ncp->ncp_ReadQueue.lh_Head;
756 while(ioreq2->IOSer.io_Message.mn_Node.ln_Succ)
758 Remove((struct Node *) ioreq2);
759 ioreq2->IOSer.io_Error = IOERR_ABORTED;
760 ReplyMsg((struct Message *) ioreq2);
761 ioreq2 = (struct IOExtSer *) ncp->ncp_ReadQueue.lh_Head;
763 ReplyMsg((struct Message *) ioreq);
764 Permit();
765 break;
767 case SDCMD_QUERY:
768 serstate = 0;
769 if(!(ncp->ncp_SerialStateReq[UART_STATE] & UART_DCD)) /* Carrier Detect */
770 serstate |= (1<<5);
771 if(!(ncp->ncp_SerialStateReq[UART_STATE] & UART_DSR)) /* DSR */
772 serstate |= (1<<3);
773 if(!(ncp->ncp_SerialStateReq[UART_STATE] & UART_CTS)) /* ClearToSend */
774 serstate |= (1<<4);
775 if(ncp->ncp_SerialStateReq[UART_STATE] & UART_BREAK) /* Break */
776 serstate |= (1<<10);
777 if(ncp->ncp_SerialStateReq[UART_STATE] & UART_RING) /* Ring */
778 serstate |= (1<<2);
779 if(ncp->ncp_SerialStateReq[UART_STATE] & (UART_FRAME_ERROR|UART_PARITY_ERROR|UART_OVERRUN_ERROR)) /* Framing, Parity, Hardware error */
780 serstate |= (1<<8);
782 ioreq->io_Status = serstate;
783 pending = 0;
784 psdGetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
785 PSA_BytesPending, &pending,
786 TAG_END);
787 ioreq->IOSer.io_Actual = pending;
788 ReplyMsg((struct Message *) ioreq);
789 break;
791 case SDCMD_SETPARAMS:
792 nSetSerialMode(ncp, ioreq);
793 ReplyMsg((struct Message *) ioreq);
794 break;
796 case SDCMD_BREAK:
797 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
798 UCDCR_SEND_BREAK, ioreq->io_BrkTime, (ULONG) ncp->ncp_UnitIfNum);
799 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
800 if(ioerr)
802 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
803 "SEND_BREAK failed: %s (%ld)",
804 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
805 ioreq->IOSer.io_Error = SerErr_LineErr;
807 ReplyMsg((struct Message *) ioreq);
808 break;
810 default:
811 ioreq->IOSer.io_Error = IOERR_NOCMD;
812 ReplyMsg((struct Message *) ioreq);
813 break;
816 if(!ncp->ncp_DevSuspend)
818 pending = 0;
819 psdGetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
820 PSA_BytesPending, &pending,
821 TAG_END);
822 Forbid();
823 ioreq = (struct IOExtSer *) ncp->ncp_ReadQueue.lh_Head;
824 while(ioreq->IOSer.io_Message.mn_Node.ln_Succ && pending)
826 Remove((struct Node *) ioreq);
827 Permit();
828 ioreq->IOSer.io_Actual = psdStreamRead(ncp->ncp_EPInStream, ioreq->IOSer.io_Data, ioreq->IOSer.io_Length);
829 ioerr = psdGetStreamError(ncp->ncp_EPInStream);
830 if(ioerr == UHIOERR_NAKTIMEOUT)
832 Forbid();
833 AddHead(&ncp->ncp_ReadQueue, &ioreq->IOSer.io_Message.mn_Node);
834 break;
835 } else {
836 if(ioerr > 0)
838 ioreq->IOSer.io_Error = SerErr_LineErr;
839 } else {
840 ioreq->IOSer.io_Error = ioerr;
842 ReplyMsg((struct Message *) ioreq);
844 psdGetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
845 PSA_BytesPending, &pending,
846 TAG_END);
847 Forbid();
848 ioreq = (struct IOExtSer *) ncp->ncp_ReadQueue.lh_Head;
850 ioreq = (struct IOExtSer *) ncp->ncp_WriteQueue.lh_Head;
851 while(ioreq->IOSer.io_Message.mn_Node.ln_Succ)
853 Remove((struct Node *) ioreq);
854 ncp->ncp_WritePending = ioreq;
855 Permit();
856 ioreq->IOSer.io_Actual = psdStreamWrite(ncp->ncp_EPOutStream, ioreq->IOSer.io_Data, ioreq->IOSer.io_Length);
857 ncp->ncp_WritePending = NULL;
858 ioerr = psdGetStreamError(ncp->ncp_EPInStream);
859 if(ioerr > 0)
861 ioreq->IOSer.io_Error = SerErr_LineErr;
862 } else {
863 ioreq->IOSer.io_Error = ioerr;
865 ReplyMsg((struct Message *) ioreq);
866 Forbid();
867 ioreq = (struct IOExtSer *) ncp->ncp_WriteQueue.lh_Head;
869 Permit();
871 sigs = Wait(sigmask);
872 } while(!(sigs & SIGBREAKF_CTRL_C));
873 KPRINTF(1, ("Going down...\n"));
874 /* Now remove all requests still pending *anywhere* */
875 ncp->ncp_DenyRequests = TRUE;
877 psdAbortPipe(ncp->ncp_EPIntPipe);
878 psdWaitPipe(ncp->ncp_EPIntPipe);
880 /* Read/Write queues */
881 Forbid();
882 ioreq = (struct IOExtSer *) ncp->ncp_WriteQueue.lh_Head;
883 while(ioreq->IOSer.io_Message.mn_Node.ln_Succ)
885 Remove((struct Node *) ioreq);
886 ioreq->IOSer.io_Error = IOERR_ABORTED;
887 ReplyMsg((struct Message *) ioreq);
888 ioreq = (struct IOExtSer *) ncp->ncp_WriteQueue.lh_Head;
890 ioreq = (struct IOExtSer *) ncp->ncp_ReadQueue.lh_Head;
891 while(ioreq->IOSer.io_Message.mn_Node.ln_Succ)
893 Remove((struct Node *) ioreq);
894 ioreq->IOSer.io_Error = IOERR_ABORTED;
895 ReplyMsg((struct Message *) ioreq);
896 ioreq = (struct IOExtSer *) ncp->ncp_ReadQueue.lh_Head;
898 /* Command queue */
899 while((ioreq = (struct IOExtSer *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
901 ioreq->IOSer.io_Error = IOERR_ABORTED;
902 ReplyMsg((struct Message *) ioreq);
904 Permit();
905 KPRINTF(20, ("Going down the river!\n"));
906 nFreeSerial(ncp);
909 AROS_USERFUNC_EXIT
911 /* \\\ */
913 /* /// "nAllocSerial()" */
914 struct NepClassSerial * nAllocSerial(void)
916 struct Task *thistask;
917 struct NepClassSerial *ncp;
918 IPTR maxpkt0 = 0;
919 IPTR epnum;
921 thistask = FindTask(NULL);
922 ncp = thistask->tc_UserData;
925 if(!(ncp->ncp_Base = OpenLibrary("poseidon.library", 4)))
927 Alert(AG_OpenLib);
928 break;
931 ncp->ncp_Interface = psdFindInterface(ncp->ncp_Device, NULL, TAG_END);
933 if(!ncp->ncp_Interface)
935 KPRINTF(1, ("Ooops!?! No interfaces defined?\n"));
936 break;
939 ncp->ncp_EPInt = psdFindEndpoint(ncp->ncp_Interface, NULL,
940 EA_IsIn, TRUE,
941 EA_TransferType, USEAF_INTERRUPT,
942 TAG_END);
943 if(!ncp->ncp_EPInt)
945 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "No notify endpoint?!?");
946 KPRINTF(1, ("Ooops!?! No notify endpoint defined?\n"));
947 break;
950 ncp->ncp_EPIn = psdFindEndpoint(ncp->ncp_Interface, NULL,
951 EA_IsIn, TRUE,
952 EA_TransferType, USEAF_BULK,
953 TAG_END);
954 ncp->ncp_EPOut = psdFindEndpoint(ncp->ncp_Interface, NULL,
955 EA_IsIn, FALSE,
956 EA_TransferType, USEAF_BULK,
957 TAG_END);
959 if(!(ncp->ncp_EPIn && ncp->ncp_EPOut))
961 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "IN or OUT endpoint missing!");
962 break;
965 psdGetAttrs(PGA_ENDPOINT, ncp->ncp_EPIn,
966 EA_EndpointNum, &epnum,
967 TAG_END);
968 ncp->ncp_EPInNum = epnum;
969 psdGetAttrs(PGA_ENDPOINT, ncp->ncp_EPOut,
970 EA_EndpointNum, &epnum,
971 TAG_END);
972 ncp->ncp_EPOutNum = epnum;
974 ncp->ncp_Unit.unit_MsgPort.mp_SigBit = AllocSignal(-1);
975 ncp->ncp_Unit.unit_MsgPort.mp_SigTask = thistask;
976 ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
977 ncp->ncp_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
978 ncp->ncp_WritePending = NULL;
980 if((ncp->ncp_TaskMsgPort = CreateMsgPort()))
982 if((ncp->ncp_EP0Pipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, NULL)))
985 /* Check for HX Chipset */
986 psdGetAttrs(PGA_PIPE, ncp->ncp_EP0Pipe, PPA_MaxPktSize, &maxpkt0, TAG_END);
987 if(maxpkt0 == 64)
989 ncp->ncp_HXChipset = TRUE;
991 if(ncp->ncp_UnitVendorID == SIEMENS_VENDOR_ID)
993 ncp->ncp_SiemensCrap = TRUE;
996 ncp->ncp_AbortSignal = AllocSignal(-1);
997 if((ncp->ncp_EPOutStream = psdOpenStream(ncp->ncp_EPOut,
998 PSA_BufferedWrite, FALSE,
999 PSA_NoZeroPktTerm, FALSE,
1000 PSA_NakTimeout, TRUE,
1001 PSA_NakTimeoutTime, 5000,
1002 PSA_AbortSigMask, (1UL<<ncp->ncp_AbortSignal)|SIGBREAKF_CTRL_C,
1003 TAG_END)))
1005 if((ncp->ncp_EPInStream = psdOpenStream(ncp->ncp_EPIn,
1006 PSA_ReadAhead, TRUE,
1007 PSA_BufferedRead, TRUE,
1008 PSA_NumPipes, NUMREADPIPES,
1009 PSA_BufferSize, DEFREADBUFLEN,
1010 PSA_AllowRuntPackets, TRUE,
1011 PSA_DoNotWait, TRUE,
1012 PSA_AbortSigMask, SIGBREAKF_CTRL_C,
1013 TAG_END)))
1015 if((ncp->ncp_EPIntPipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, ncp->ncp_EPInt)))
1017 ncp->ncp_Task = thistask;
1018 return(ncp);
1020 psdCloseStream(ncp->ncp_EPInStream);
1022 psdCloseStream(ncp->ncp_EPOutStream);
1024 FreeSignal(ncp->ncp_AbortSignal);
1025 psdFreePipe(ncp->ncp_EP0Pipe);
1027 DeleteMsgPort(ncp->ncp_TaskMsgPort);
1029 FreeSignal((LONG) ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
1030 } while(FALSE);
1031 CloseLibrary(ncp->ncp_Base);
1032 Forbid();
1033 ncp->ncp_Task = NULL;
1034 if(ncp->ncp_ReadySigTask)
1036 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
1038 return(NULL);
1040 /* \\\ */
1042 /* /// "nFreeSerial()" */
1043 void nFreeSerial(struct NepClassSerial *ncp)
1045 struct IOStdReq *ioreq;
1046 Forbid();
1047 FreeSignal(ncp->ncp_AbortSignal);
1048 ncp->ncp_AbortSignal = -1;
1049 /* Disable the message port, messages may still be queued */
1050 ncp->ncp_Unit.unit_MsgPort.mp_SigTask = NULL;
1051 ncp->ncp_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
1052 FreeSignal((LONG) ncp->ncp_Unit.unit_MsgPort.mp_SigBit);
1053 // get rid of all messages that still have appeared here
1054 while((ioreq = (struct IOStdReq *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
1056 ioreq->io_Error = IOERR_ABORTED;
1057 ReplyMsg((struct Message *) ioreq);
1059 Permit();
1061 psdCloseStream(ncp->ncp_EPInStream);
1062 psdCloseStream(ncp->ncp_EPOutStream);
1063 psdFreePipe(ncp->ncp_EPIntPipe);
1064 psdFreePipe(ncp->ncp_EP0Pipe);
1066 DeleteMsgPort(ncp->ncp_TaskMsgPort);
1067 CloseLibrary(ncp->ncp_Base);
1068 Forbid();
1069 ncp->ncp_Task = NULL;
1070 if(ncp->ncp_ReadySigTask)
1072 Signal(ncp->ncp_ReadySigTask, 1UL<<ncp->ncp_ReadySignal);
1075 /* \\\ */