2 *----------------------------------------------------------------------------
3 * serialcp210x class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include "serialcp210x.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 serialcp210x.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! serialcp210x.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 { 0x08e6, 0x5501 }, /* Gemalto Prox-PU/CU contactless smartcard reader */
116 { 0x0fcf, 0x1003 }, /* Dynastream ANT development board */
117 { 0x0fcf, 0x1004 }, /* Dynastream ANT2USB */
118 { 0x10a6, 0xaa26 }, /* Knock-off DCU-11 cable */
119 { 0x10ab, 0x10c5 }, /* Siemens MC60 Cable */
120 { 0x10b5, 0xac70 }, /* Nokia CA-42 USB */
121 { 0x10c4, 0x800a }, /* SPORTident BSM7-D-USB main station */
122 { 0x10c4, 0x803b }, /* Pololu USB-serial converter */
123 { 0x10c4, 0x8053 }, /* Enfora EDG1228 */
124 { 0x10c4, 0x8066 }, /* Argussoft In-System Programmer */
125 { 0x10c4, 0x807a }, /* Crumb128 board */
126 { 0x10c4, 0x80ca }, /* Degree Controls Inc */
127 { 0x10c4, 0x80dd }, /* Tracient RFID */
128 { 0x10c4, 0x80f6 }, /* Suunto sports instrument */
129 { 0x10c4, 0x813d }, /* Burnside Telecom Deskmobile */
130 { 0x10c4, 0x814a }, /* West Mountain Radio RIGblaster P&P */
131 { 0x10c4, 0x814b }, /* West Mountain Radio RIGtalk */
132 { 0x10c4, 0x815e }, /* Helicomm IP-Link 1220-DVM */
133 { 0x10c4, 0x81c8 }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
134 { 0x10c4, 0x81e2 }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
135 { 0x10c4, 0x81e7 }, /* Aerocomm Radio */
136 { 0x10c4, 0x8218 }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
137 { 0x10c4, 0x8293 }, /* Telegesys ETRX2USB */
138 { 0x10c4, 0xea60 }, /* Silicon Labs factory default */
139 { 0x10c4, 0xea61 }, /* Silicon Labs factory default */
140 { 0x10c4, 0xf001 }, /* Elan Digital Systems USBscope50 */
141 { 0x10c4, 0xf002 }, /* Elan Digital Systems USBwave12 */
142 { 0x10c4, 0xf003 }, /* Elan Digital Systems USBpulse100 */
143 { 0x10c4, 0xf004 }, /* Elan Digital Systems USBcount50 */
144 { 0x10c5, 0xea61 }, /* Silicon Labs MobiData GPRS USB Modem */
145 { 0x13ad, 0x9999 }, /* Baltech card reader */
146 { 0x166a, 0x0303 }, /* Clipsal 5500PCU C-Bus USB interface */
147 { 0x16d6, 0x0001 }, /* Jablotron serial interface */
151 /* /// "usbAttemptDeviceBinding()" */
152 struct NepClassSerial
* usbAttemptDeviceBinding(struct NepSerialBase
*nh
, struct PsdDevice
*pd
)
155 struct AutoBindData
*abd
= ClassBinds
;
159 KPRINTF(1, ("nepSerialAttemptDeviceBinding(%08lx)\n", pd
));
160 if((ps
= OpenLibrary("poseidon.library", 4)))
162 psdGetAttrs(PGA_DEVICE
, pd
,
163 DA_VendorID
, &vendid
,
164 DA_ProductID
, &prodid
,
167 while(abd
->abd_VendID
)
169 if((vendid
== abd
->abd_VendID
) && (prodid
== abd
->abd_ProdID
))
171 return(usbForceDeviceBinding(nh
, pd
));
180 /* /// "usbForceDeviceBinding()" */
181 struct NepClassSerial
* usbForceDeviceBinding(struct NepSerialBase
*nh
, struct PsdDevice
*pd
)
184 struct NepClassSerial
*ncp
;
191 struct Task
*tmptask
;
193 KPRINTF(1, ("nepSerialForceDeviceBinding(%08lx)\n", pd
));
194 if((ps
= OpenLibrary("poseidon.library", 4)))
196 psdGetAttrs(PGA_DEVICE
, pd
,
197 DA_ProductID
, &prodid
,
198 DA_VendorID
, &vendid
,
199 DA_ProductName
, &devname
,
202 /* Find next free unit number */
204 ncp
= (struct NepClassSerial
*) nh
->nh_Units
.lh_Head
;
205 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
207 if(ncp
->ncp_UnitNo
== unitno
)
210 ncp
= (struct NepClassSerial
*) nh
->nh_Units
.lh_Head
;
212 ncp
= (struct NepClassSerial
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
216 ncp
= (struct NepClassSerial
*) nh
->nh_Units
.lh_Head
;
217 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
219 if((ncp
->ncp_UnitProdID
== prodid
) && (ncp
->ncp_UnitVendorID
== vendid
))
221 unitno
= ncp
->ncp_UnitNo
;
225 ncp
= (struct NepClassSerial
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
229 /* as units are freed in the expunge-vector, the memory is
230 outside the scope of the poseidon library */
231 if(!(ncp
= AllocVec(sizeof(struct NepClassSerial
), MEMF_PUBLIC
|MEMF_CLEAR
)))
237 /* IORequests may be queued even if the task is gone. */
238 NewList(&ncp
->ncp_Unit
.unit_MsgPort
.mp_MsgList
);
239 NewList(&ncp
->ncp_ReadQueue
);
240 NewList(&ncp
->ncp_WriteQueue
);
241 AddTail(&nh
->nh_Units
, &ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
);
242 ncp
->ncp_DenyRequests
= TRUE
;
244 ncp
->ncp_UnitNo
= unitno
;
245 ncp
->ncp_Device
= pd
;
246 ncp
->ncp_UnitProdID
= prodid
;
247 ncp
->ncp_UnitVendorID
= vendid
;
250 psdSafeRawDoFmt(buf
, 64, "serialcp210x.class<%08lx>", ncp
);
251 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
252 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
253 SetSignal(0, SIGF_SINGLE
);
254 if((tmptask
= psdSpawnSubTask(buf
, nSerialTask
, ncp
)))
256 psdBorrowLocksWait(tmptask
, 1UL<<ncp
->ncp_ReadySignal
);
259 ncp
->ncp_ReadySigTask
= NULL
;
260 //FreeSignal(ncp->ncp_ReadySignal);
261 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
262 "Another serial killer '%s' at %s unit %ld!",
263 devname
, nh
->nh_DevBase
->np_Library
.lib_Node
.ln_Name
,
270 ncp
->ncp_ReadySigTask
= NULL
;
271 //FreeSignal(ncp->ncp_ReadySignal);
272 /* Get rid of unit structure */
274 Remove((struct Node *) ncp);
283 /* /// "usbReleaseDeviceBinding()" */
284 void usbReleaseDeviceBinding(struct NepSerialBase
*nh
, struct NepClassSerial
*ncp
)
289 KPRINTF(1, ("nepSerialReleaseDeviceBinding(%08lx)\n", ncp
));
290 if((ps
= OpenLibrary("poseidon.library", 4)))
293 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
294 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
297 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
302 Wait(1L<<ncp
->ncp_ReadySignal
);
304 //FreeSignal(ncp->ncp_ReadySignal);
305 psdGetAttrs(PGA_DEVICE
, ncp
->ncp_Device
, DA_ProductName
, &devname
, TAG_END
);
306 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
307 "Lost the wire on '%s'.",
315 /* /// "usbGetAttrsA()" */
316 AROS_LH3(LONG
, usbGetAttrsA
,
317 AROS_LHA(ULONG
, type
, D0
),
318 AROS_LHA(APTR
, usbstruct
, A0
),
319 AROS_LHA(struct TagItem
*, tags
, A1
),
320 LIBBASETYPEPTR
, nh
, 5, nep
)
327 KPRINTF(1, ("nepHidGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
331 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
333 *((SIPTR
*) ti
->ti_Data
) = 0;
336 if((ti
= FindTagItem(UCCA_Description
, tags
)))
338 *((STRPTR
*) ti
->ti_Data
) = "CP210x serial adapter via serialcp210x.device";
341 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
343 *((IPTR
*) ti
->ti_Data
) = FALSE
;
346 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
348 *((IPTR
*) ti
->ti_Data
) = FALSE
;
351 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
353 *((IPTR
*) ti
->ti_Data
) = FALSE
;
356 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
358 *((IPTR
*) ti
->ti_Data
) = TRUE
;
364 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
366 *((IPTR
*) ti
->ti_Data
) = TRUE
;
376 /* /// "usbSetAttrsA()" */
377 AROS_LH3(LONG
, usbSetAttrsA
,
378 AROS_LHA(ULONG
, type
, D0
),
379 AROS_LHA(APTR
, usbstruct
, A0
),
380 AROS_LHA(struct TagItem
*, tags
, A1
),
381 LIBBASETYPEPTR
, nh
, 6, nep
)
389 /* /// "usbDoMethodA()" */
390 AROS_LH2(IPTR
, usbDoMethodA
,
391 AROS_LHA(ULONG
, methodid
, D0
),
392 AROS_LHA(IPTR
*, methoddata
, A1
),
393 LIBBASETYPEPTR
, nh
, 7, nep
)
397 KPRINTF(10, ("Do Method %ld\n", methodid
));
400 case UCM_AttemptDeviceBinding
:
401 return((IPTR
) usbAttemptDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
403 case UCM_ForceDeviceBinding
:
404 return((IPTR
) usbForceDeviceBinding(nh
, (struct PsdDevice
*) methoddata
[0]));
406 case UCM_ReleaseDeviceBinding
:
407 usbReleaseDeviceBinding(nh
, (struct NepClassSerial
*) methoddata
[0]);
418 /**************************************************************************/
421 #define ps ncp->ncp_Base
423 /* /// "nSetRegister()" */
424 void nSetRegister(struct NepClassSerial
*ncp
, ULONG reg
, ULONG value
)
427 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_VENDOR
|URTF_INTERFACE
,
429 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, NULL
, 0);
432 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
433 "Could not set register %ld to %08lx: %s (%ld)",
435 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
440 /* /// "nGetRegister()" */
441 ULONG
nGetRegister(struct NepClassSerial
*ncp
, ULONG reg
)
445 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_VENDOR
|URTF_INTERFACE
,
447 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, buf
, 1);
450 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
451 "Could not get register %ld: %s (%ld)",
453 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
456 return buf
[0]; // although returned in UWORDs, fields are bytes!
461 /* /// "nSetRegisters()" */
462 void nSetRegisters(struct NepClassSerial
*ncp
, ULONG regstart
, UBYTE
*values
, ULONG len
)
465 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_VENDOR
|URTF_INTERFACE
,
467 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, values
, len
);
470 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
471 "Could not set registers %ld-%ld: %s (%ld)",
472 regstart
, regstart
+ len
- 1,
473 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
478 /* /// "nSetSerialMode()" */
479 void nSetSerialMode(struct NepClassSerial
*ncp
, struct IOExtSer
*ioreq
)
481 ULONG bufsize
= ioreq
->io_RBufLen
/ NUMREADPIPES
;
490 bufsize
= (bufsize
+ 127) & (~127);
492 psdSetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
493 PSA_BufferSize
, bufsize
,
495 if(ioreq
->io_SerFlags
& SERF_EOFMODE
)
497 psdSetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
498 PSA_TermArray
, &ioreq
->io_TermArray
,
500 psdSetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPOutStream
,
501 PSA_TermArray
, &ioreq
->io_TermArray
,
504 psdSetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
507 psdSetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPOutStream
,
511 nSetRegister(ncp
, UCPR_SET_BAUDRATE
, BAUD_RATE_GEN_FREQ
/ ioreq
->io_Baud
);
513 if(ioreq
->io_StopBits
== 1)
517 else if(ioreq
->io_StopBits
== 2)
521 ioreq
->IOSer
.io_Error
= SerErr_InvParam
;
523 /* no parity by default */
524 if(ioreq
->io_SerFlags
& SERF_PARTY_ON
)
526 if(ioreq
->io_SerFlags
& SERF_PARTY_ODD
)
528 cfg
|= BITS_PARITY_ODD
; /* odd parity */
530 cfg
|= BITS_PARITY_EVEN
; /* even parity */
533 if(ioreq
->io_ExtFlags
& SEXTF_MSPON
)
535 ioreq
->io_SerFlags
|= SERF_PARTY_ON
;
536 if(ioreq
->io_ExtFlags
& SEXTF_MARK
)
538 cfg
|= BITS_PARITY_MARK
; /* mark parity */
540 cfg
|= BITS_PARITY_SPACE
; /* space parity */
543 cfg
|= ioreq
->io_ReadLen
<<8;
545 if(ioreq
->io_SerFlags
& SERF_RAD_BOOGIE
)
550 nSetRegister(ncp
, UCPR_SET_BITS
, cfg
);
552 /* Activate RTS/CTS */
554 psdPipeSetup(ncp
->ncp_EP0Pipe
, URTF_IN
|URTF_VENDOR
|URTF_INTERFACE
,
555 UCPR_GET_MODEMCTL
, 0, 0);
556 ioerr
= psdDoPipe(ncp
->ncp_EP0Pipe
, modemdata
, 16);
559 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
560 "Could not get modem data: %s (%ld)",
561 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
565 if(ioreq
->io_SerFlags
& SERF_7WIRE
)
567 nSetRegister(ncp
, UCPR_SET_CONTROL
, UART_RTS
|UART_WRITE_RTS
|UART_DTR
|UART_WRITE_DTR
);
568 modemdata
[0] &= ~0x7b;
569 modemdata
[0] |= 0x09;
571 nSetRegisters(ncp
, UCPR_SET_MODEMCTL
, modemdata
, 16);
573 nSetRegister(ncp
, UCPR_SET_CONTROL
, UART_WRITE_RTS
|UART_WRITE_DTR
);
574 modemdata
[0] &= ~0x7b;
575 modemdata
[0] |= 0x01;
577 nSetRegisters(ncp
, UCPR_SET_MODEMCTL
, modemdata
, 16);
582 /* /// "nSerialTask()" */
583 AROS_UFH0(void, nSerialTask
)
587 struct NepClassSerial
*ncp
;
591 struct IOExtSer
*ioreq
;
592 struct IOExtSer
*ioreq2
;
597 if((ncp
= nAllocSerial()))
600 if(ncp
->ncp_ReadySigTask
)
602 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
606 nSetRegister(ncp
, UCPR_SET_STATE
, UART_ENABLE
);
608 sigmask
= (1UL<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
)|(1UL<<ncp
->ncp_TaskMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
610 struct MsgPort
*tmpmp
= NULL
;
611 psdGetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
, PSA_MessagePort
, &tmpmp
, TAG_END
);
614 sigmask
|= (1UL<<tmpmp
->mp_SigBit
);
619 psdStreamRead(ncp
->ncp_EPInStream
, NULL
, 0);
620 while((ioreq
= (struct IOExtSer
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
622 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
623 ioreq
, ioreq
->IOSer
.io_Command
, ioreq
->IOSer
.io_Length
));
624 switch(ioreq
->IOSer
.io_Command
)
627 psdStreamFlush(ncp
->ncp_EPOutStream
);
628 ReplyMsg((struct Message
*) ioreq
);
632 /* Reset does a flush too */
635 ioreq2
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
636 while(ioreq2
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
638 Remove((struct Node
*) ioreq2
);
639 ioreq2
->IOSer
.io_Error
= IOERR_ABORTED
;
640 ReplyMsg((struct Message
*) ioreq2
);
641 ioreq2
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
643 ioreq2
= (struct IOExtSer
*) ncp
->ncp_ReadQueue
.lh_Head
;
644 while(ioreq2
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
646 Remove((struct Node
*) ioreq2
);
647 ioreq2
->IOSer
.io_Error
= IOERR_ABORTED
;
648 ReplyMsg((struct Message
*) ioreq2
);
649 ioreq2
= (struct IOExtSer
*) ncp
->ncp_ReadQueue
.lh_Head
;
651 ReplyMsg((struct Message
*) ioreq
);
657 control
= nGetRegister(ncp
, UCPR_GET_CONTROL
);
659 if(!(control
& UART_DCD
)) /* Carrier Detect */
661 if(!(control
& UART_DSR
)) /* DSR */
663 if(!(control
& UART_CTS
)) /* ClearToSend */
665 if(!(control
& UART_RTS
)) /* ReadyToSend */
667 if(!(control
& UART_DTR
)) /* DTR */
669 if(control
& UART_RING
) /* Ring */
672 ioreq
->io_Status
= serstate
;
674 psdGetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
675 PSA_BytesPending
, &pending
,
677 ioreq
->IOSer
.io_Actual
= pending
;
678 ReplyMsg((struct Message
*) ioreq
);
681 case SDCMD_SETPARAMS
:
682 nSetSerialMode(ncp
, ioreq
);
683 ReplyMsg((struct Message
*) ioreq
);
687 ioreq
->IOSer
.io_Error
= IOERR_NOCMD
;
688 ReplyMsg((struct Message
*) ioreq
);
692 if(!ncp
->ncp_DevSuspend
)
695 psdGetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
696 PSA_BytesPending
, &pending
,
699 ioreq
= (struct IOExtSer
*) ncp
->ncp_ReadQueue
.lh_Head
;
700 while(ioreq
->IOSer
.io_Message
.mn_Node
.ln_Succ
&& pending
)
702 Remove((struct Node
*) ioreq
);
704 ioreq
->IOSer
.io_Actual
= psdStreamRead(ncp
->ncp_EPInStream
, ioreq
->IOSer
.io_Data
, ioreq
->IOSer
.io_Length
);
705 ioerr
= psdGetStreamError(ncp
->ncp_EPInStream
);
706 if(ioerr
== UHIOERR_NAKTIMEOUT
)
709 AddHead(&ncp
->ncp_ReadQueue
, &ioreq
->IOSer
.io_Message
.mn_Node
);
714 ioreq
->IOSer
.io_Error
= SerErr_LineErr
;
716 ioreq
->IOSer
.io_Error
= ioerr
;
718 ReplyMsg((struct Message
*) ioreq
);
720 psdGetAttrs(PGA_PIPESTREAM
, ncp
->ncp_EPInStream
,
721 PSA_BytesPending
, &pending
,
724 ioreq
= (struct IOExtSer
*) ncp
->ncp_ReadQueue
.lh_Head
;
726 ioreq
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
727 while(ioreq
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
729 Remove((struct Node
*) ioreq
);
730 ncp
->ncp_WritePending
= ioreq
;
732 ioreq
->IOSer
.io_Actual
= psdStreamWrite(ncp
->ncp_EPOutStream
, ioreq
->IOSer
.io_Data
, ioreq
->IOSer
.io_Length
);
733 ncp
->ncp_WritePending
= NULL
;
734 ioerr
= psdGetStreamError(ncp
->ncp_EPInStream
);
737 ioreq
->IOSer
.io_Error
= SerErr_LineErr
;
739 ioreq
->IOSer
.io_Error
= ioerr
;
741 ReplyMsg((struct Message
*) ioreq
);
743 ioreq
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
747 sigs
= Wait(sigmask
);
748 } while(!(sigs
& SIGBREAKF_CTRL_C
));
749 KPRINTF(1, ("Going down...\n"));
750 /* Now remove all requests still pending *anywhere* */
751 ncp
->ncp_DenyRequests
= TRUE
;
753 nSetRegister(ncp
, UCPR_SET_STATE
, UART_DISABLE
);
755 /* Read/Write queues */
757 ioreq
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
758 while(ioreq
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
760 Remove((struct Node
*) ioreq
);
761 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
762 ReplyMsg((struct Message
*) ioreq
);
763 ioreq
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
765 ioreq
= (struct IOExtSer
*) ncp
->ncp_ReadQueue
.lh_Head
;
766 while(ioreq
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
768 Remove((struct Node
*) ioreq
);
769 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
770 ReplyMsg((struct Message
*) ioreq
);
771 ioreq
= (struct IOExtSer
*) ncp
->ncp_ReadQueue
.lh_Head
;
774 while((ioreq
= (struct IOExtSer
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
776 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
777 ReplyMsg((struct Message
*) ioreq
);
780 KPRINTF(20, ("Going down the river!\n"));
788 /* /// "nAllocSerial()" */
789 struct NepClassSerial
* nAllocSerial(void)
791 struct Task
*thistask
;
792 struct NepClassSerial
*ncp
;
795 thistask
= FindTask(NULL
);
796 ncp
= thistask
->tc_UserData
;
799 if(!(ncp
->ncp_Base
= OpenLibrary("poseidon.library", 4)))
805 ncp
->ncp_Interface
= psdFindInterface(ncp
->ncp_Device
, NULL
, TAG_END
);
807 if(!ncp
->ncp_Interface
)
809 KPRINTF(1, ("Ooops!?! No interfaces defined?\n"));
813 ncp
->ncp_EPIn
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
815 EA_TransferType
, USEAF_BULK
,
817 ncp
->ncp_EPOut
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
819 EA_TransferType
, USEAF_BULK
,
822 if(!(ncp
->ncp_EPIn
&& ncp
->ncp_EPOut
))
824 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "IN or OUT endpoint missing!");
828 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPIn
,
829 EA_EndpointNum
, &epnum
,
831 ncp
->ncp_EPInNum
= epnum
;
832 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPOut
,
833 EA_EndpointNum
, &epnum
,
835 ncp
->ncp_EPOutNum
= epnum
;
837 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
= AllocSignal(-1);
838 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= thistask
;
839 ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
840 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_SIGNAL
;
841 ncp
->ncp_WritePending
= NULL
;
843 if((ncp
->ncp_TaskMsgPort
= CreateMsgPort()))
845 if((ncp
->ncp_EP0Pipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, NULL
)))
848 ncp
->ncp_AbortSignal
= AllocSignal(-1);
849 if((ncp
->ncp_EPOutStream
= psdOpenStream(ncp
->ncp_EPOut
,
850 PSA_BufferedWrite
, FALSE
,
851 PSA_NoZeroPktTerm
, TRUE
,
852 PSA_NakTimeout
, TRUE
,
853 PSA_NakTimeoutTime
, 5000,
854 PSA_AbortSigMask
, (1UL<<ncp
->ncp_AbortSignal
)|SIGBREAKF_CTRL_C
,
857 if((ncp
->ncp_EPInStream
= psdOpenStream(ncp
->ncp_EPIn
,
859 PSA_BufferedRead
, TRUE
,
860 PSA_NumPipes
, NUMREADPIPES
,
861 PSA_BufferSize
, DEFREADBUFLEN
,
862 PSA_AllowRuntPackets
, TRUE
,
864 PSA_AbortSigMask
, SIGBREAKF_CTRL_C
,
867 ncp
->ncp_Task
= thistask
;
870 psdCloseStream(ncp
->ncp_EPOutStream
);
872 FreeSignal(ncp
->ncp_AbortSignal
);
873 psdFreePipe(ncp
->ncp_EP0Pipe
);
875 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
877 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
879 CloseLibrary(ncp
->ncp_Base
);
881 ncp
->ncp_Task
= NULL
;
882 if(ncp
->ncp_ReadySigTask
)
884 Signal(ncp
->ncp_ReadySigTask
, 1L<<ncp
->ncp_ReadySignal
);
890 /* /// "nFreeSerial()" */
891 void nFreeSerial(struct NepClassSerial
*ncp
)
893 struct IOStdReq
*ioreq
;
895 FreeSignal(ncp
->ncp_AbortSignal
);
896 ncp
->ncp_AbortSignal
= -1;
897 /* Disable the message port, messages may still be queued */
898 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= NULL
;
899 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_IGNORE
;
900 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
901 // get rid of all messages that still have appeared here
902 while((ioreq
= (struct IOStdReq
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
904 ioreq
->io_Error
= IOERR_ABORTED
;
905 ReplyMsg((struct Message
*) ioreq
);
909 psdCloseStream(ncp
->ncp_EPInStream
);
910 psdCloseStream(ncp
->ncp_EPOutStream
);
911 psdFreePipe(ncp
->ncp_EP0Pipe
);
913 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
914 CloseLibrary(ncp
->ncp_Base
);
916 ncp
->ncp_Task
= NULL
;
917 if(ncp
->ncp_ReadySigTask
)
919 Signal(ncp
->ncp_ReadySigTask
, 1UL<<ncp
->ncp_ReadySignal
);