2 *----------------------------------------------------------------------------
3 * serialpl2303 class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include "serialpl2303.class.h"
13 static const STRPTR libname
= MOD_NAME_STRING
;
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),
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
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
;
46 AddDevice((struct Device
*) nh
->nh_DevBase
);
47 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
++;
51 KPRINTF(20, ("failed to create serialpl2303.device\n"));
55 CloseLibrary(UtilityBase
);
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",
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
);
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"));
90 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
97 ADD2INITLIB(libInit
, 0)
98 ADD2EXPUNGELIB(libExpunge
, 0)
102 * ***********************************************************************
103 * * Library functions *
104 * ***********************************************************************
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
},
159 /* /// "usbAttemptDeviceBinding()" */
160 struct NepClassSerial
* usbAttemptDeviceBinding(struct NepSerialBase
*nh
, struct PsdDevice
*pd
)
163 struct AutoBindData
*abd
= ClassBinds
;
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
,
175 while(abd
->abd_VendID
)
177 if((vendid
== abd
->abd_VendID
) && (prodid
== abd
->abd_ProdID
))
179 return(usbForceDeviceBinding(nh
, pd
));
188 /* /// "usbForceDeviceBinding()" */
189 struct NepClassSerial
* usbForceDeviceBinding(struct NepSerialBase
*nh
, struct PsdDevice
*pd
)
192 struct NepClassSerial
*ncp
;
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
,
210 /* Find next free unit number */
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
)
218 ncp
= (struct NepClassSerial
*) nh
->nh_Units
.lh_Head
;
220 ncp
= (struct NepClassSerial
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
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
;
233 ncp
= (struct NepClassSerial
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
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
)))
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
;
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
);
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
,
278 ncp
->ncp_ReadySigTask
= NULL
;
279 //FreeSignal(ncp->ncp_ReadySignal);
280 /* Get rid of unit structure */
282 Remove((struct Node *) ncp);
291 /* /// "usbReleaseDeviceBinding()" */
292 void usbReleaseDeviceBinding(struct NepSerialBase
*nh
, struct NepClassSerial
*ncp
)
297 KPRINTF(1, ("nepSerialReleaseDeviceBinding(%08lx)\n", ncp
));
298 if((ps
= OpenLibrary("poseidon.library", 4)))
301 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
302 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
305 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
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'.",
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
)
335 KPRINTF(1, ("nepHidGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
339 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
341 *((SIPTR
*) ti
->ti_Data
) = 0;
344 if((ti
= FindTagItem(UCCA_Description
, tags
)))
346 *((STRPTR
*) ti
->ti_Data
) = "PL2303 serial adapter via serialpl2303.device";
349 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
351 *((IPTR
*) ti
->ti_Data
) = FALSE
;
354 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
356 *((IPTR
*) ti
->ti_Data
) = FALSE
;
359 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
361 *((IPTR
*) ti
->ti_Data
) = FALSE
;
364 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
366 *((IPTR
*) ti
->ti_Data
) = TRUE
;
372 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
374 *((IPTR
*) ti
->ti_Data
) = TRUE
;
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
)
397 /* /// "usbDoMethodA()" */
398 AROS_LH2(IPTR
, usbDoMethodA
,
399 AROS_LHA(ULONG
, methodid
, D0
),
400 AROS_LHA(IPTR
*, methoddata
, A1
),
401 LIBBASETYPEPTR
, nh
, 7, nep
)
405 KPRINTF(10, ("Do Method %ld\n", 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]);
426 /**************************************************************************/
429 #define ps ncp->ncp_Base
431 /* /// "nSetSerialMode()" */
432 void nSetSerialMode(struct NepClassSerial
*ncp
, struct IOExtSer
*ioreq
)
434 struct UsbCDCLineCoding ulc
;
436 ULONG bufsize
= ioreq
->io_RBufLen
/ NUMREADPIPES
;
442 bufsize
= (bufsize
+ 127) & (~127);
444 psdSetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
445 PSA_BufferSize
, bufsize
,
447 if(ioreq
->io_SerFlags
& SERF_EOFMODE
)
449 psdSetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
450 PSA_TermArray
, &ioreq
->io_TermArray
,
452 psdSetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPOutStream
,
453 PSA_TermArray
, &ioreq
->io_TermArray
,
456 psdSetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
459 psdSetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPOutStream
,
463 ulc
.dwDTERate
= AROS_LONG2LE(ioreq
->io_Baud
);
464 if(ioreq
->io_StopBits
== 1)
468 else if(ioreq
->io_StopBits
== 2)
472 ioreq
->IOSer
.io_Error
= SerErr_InvParam
;
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 */
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 */
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...
509 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_CLASS
|URTF_INTERFACE
,
510 UCDCR_SET_LINE_CODING
, 0, 0);
511 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, &ulc
, 7);
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);
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);
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
;
546 /* /// "nSerialTask()" */
547 AROS_UFH0(void, nSerialTask
)
551 struct NepClassSerial
*ncp
;
557 struct IOExtSer
*ioreq
;
558 struct IOExtSer
*ioreq2
;
564 UWORD initseq
[] = { URTF_IN
, 0x8484, 0,
574 //URTF_OUT, 0x0001, 0xc0,
575 URTF_OUT
, 0x0002, 0x24,
578 UWORD inithxs
[] = { URTF_IN
, 0x8484, 0,
587 URTF_OUT
, 0x0002, 0x44,
592 if((ncp
= nAllocSerial()))
595 if(ncp
->ncp_ReadySigTask
)
597 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
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);
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);
618 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
619 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
620 ncp
->ncp_EPOutNum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
624 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
625 "Using HX chipset init sequence...");
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);
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);
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);
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);
666 /* Output init sequence */
668 while(*seqptr
!= 0xffff)
676 psdPipeSetup(pp
, URTF_IN
|URTF_VENDOR
|URTF_DEVICE
, UPLR_READ
,
677 (ULONG
) val
, (ULONG
) idx
);
678 ioerr
= psdDoPipe(pp
, buf
, 1);
680 psdPipeSetup(pp
, URTF_OUT
|URTF_VENDOR
|URTF_DEVICE
, UPLR_WRITE
,
681 (ULONG
) val
, (ULONG
) idx
);
682 ioerr
= psdDoPipe(pp
, NULL
, 0);
686 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
687 "Error during init sequence cmd %ld: %s (%ld)",
689 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
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
);
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
);
723 if(ncp
->ncp_SiemensCrap
)
725 psdSendPipe(ncp
->ncp_EPIntPipe
, &ncp
->ncp_SerialStateReq
[UART_STATE
], 1);
727 psdSendPipe(ncp
->ncp_EPIntPipe
, ncp
->ncp_SerialStateReq
, 10);
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
)
739 psdStreamFlush(ncp
->ncp_EPOutStream
);
740 ReplyMsg((struct Message
*) ioreq
);
744 /* Reset does a flush too */
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
);
769 if(!(ncp
->ncp_SerialStateReq
[UART_STATE
] & UART_DCD
)) /* Carrier Detect */
771 if(!(ncp
->ncp_SerialStateReq
[UART_STATE
] & UART_DSR
)) /* DSR */
773 if(!(ncp
->ncp_SerialStateReq
[UART_STATE
] & UART_CTS
)) /* ClearToSend */
775 if(ncp
->ncp_SerialStateReq
[UART_STATE
] & UART_BREAK
) /* Break */
777 if(ncp
->ncp_SerialStateReq
[UART_STATE
] & UART_RING
) /* Ring */
779 if(ncp
->ncp_SerialStateReq
[UART_STATE
] & (UART_FRAME_ERROR
|UART_PARITY_ERROR
|UART_OVERRUN_ERROR
)) /* Framing, Parity, Hardware error */
782 ioreq
->io_Status
= serstate
;
784 psdGetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
785 PSA_BytesPending
, &pending
,
787 ioreq
->IOSer
.io_Actual
= pending
;
788 ReplyMsg((struct Message
*) ioreq
);
791 case SDCMD_SETPARAMS
:
792 nSetSerialMode(ncp
, ioreq
);
793 ReplyMsg((struct Message
*) ioreq
);
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);
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
);
811 ioreq
->IOSer
.io_Error
= IOERR_NOCMD
;
812 ReplyMsg((struct Message
*) ioreq
);
816 if(!ncp
->ncp_DevSuspend
)
819 psdGetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
820 PSA_BytesPending
, &pending
,
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
);
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
)
833 AddHead(&ncp
->ncp_ReadQueue
, &ioreq
->IOSer
.io_Message
.mn_Node
);
838 ioreq
->IOSer
.io_Error
= SerErr_LineErr
;
840 ioreq
->IOSer
.io_Error
= ioerr
;
842 ReplyMsg((struct Message
*) ioreq
);
844 psdGetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
845 PSA_BytesPending
, &pending
,
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
;
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
);
861 ioreq
->IOSer
.io_Error
= SerErr_LineErr
;
863 ioreq
->IOSer
.io_Error
= ioerr
;
865 ReplyMsg((struct Message
*) ioreq
);
867 ioreq
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
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 */
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
;
899 while((ioreq
= (struct IOExtSer
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
901 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
902 ReplyMsg((struct Message
*) ioreq
);
905 KPRINTF(20, ("Going down the river!\n"));
913 /* /// "nAllocSerial()" */
914 struct NepClassSerial
* nAllocSerial(void)
916 struct Task
*thistask
;
917 struct NepClassSerial
*ncp
;
921 thistask
= FindTask(NULL
);
922 ncp
= thistask
->tc_UserData
;
925 if(!(ncp
->ncp_Base
= OpenLibrary("poseidon.library", 4)))
931 ncp
->ncp_Interface
= psdFindInterface(ncp
->ncp_Device
, NULL
, TAG_END
);
933 if(!ncp
->ncp_Interface
)
935 KPRINTF(1, ("Ooops!?! No interfaces defined?\n"));
939 ncp
->ncp_EPInt
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
941 EA_TransferType
, USEAF_INTERRUPT
,
945 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "No notify endpoint?!?");
946 KPRINTF(1, ("Ooops!?! No notify endpoint defined?\n"));
950 ncp
->ncp_EPIn
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
952 EA_TransferType
, USEAF_BULK
,
954 ncp
->ncp_EPOut
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
956 EA_TransferType
, USEAF_BULK
,
959 if(!(ncp
->ncp_EPIn
&& ncp
->ncp_EPOut
))
961 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "IN or OUT endpoint missing!");
965 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPIn
,
966 EA_EndpointNum
, &epnum
,
968 ncp
->ncp_EPInNum
= epnum
;
969 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPOut
,
970 EA_EndpointNum
, &epnum
,
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
);
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
,
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
,
1015 if((ncp
->ncp_EPIntPipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPInt
)))
1017 ncp
->ncp_Task
= thistask
;
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
);
1031 CloseLibrary(ncp
->ncp_Base
);
1033 ncp
->ncp_Task
= NULL
;
1034 if(ncp
->ncp_ReadySigTask
)
1036 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
1042 /* /// "nFreeSerial()" */
1043 void nFreeSerial(struct NepClassSerial
*ncp
)
1045 struct IOStdReq
*ioreq
;
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
);
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
);
1069 ncp
->ncp_Task
= NULL
;
1070 if(ncp
->ncp_ReadySigTask
)
1072 Signal(ncp
->ncp_ReadySigTask
, 1UL<<ncp
->ncp_ReadySignal
);