Fixed compatibility of output.
[AROS.git] / rom / usb / classes / serialcp210x / serialcp210x.class.c
blob9f3f4a7d34af96c620985de1cbac1680aebc281d
1 /*
2 *----------------------------------------------------------------------------
3 * serialcp210x class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "serialcp210x.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 serialcp210x.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! serialcp210x.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 { 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 */
148 { 0, 0 }
151 /* /// "usbAttemptDeviceBinding()" */
152 struct NepClassSerial * usbAttemptDeviceBinding(struct NepSerialBase *nh, struct PsdDevice *pd)
154 struct Library *ps;
155 struct AutoBindData *abd = ClassBinds;
156 IPTR prodid;
157 IPTR vendid;
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,
165 TAG_END);
166 CloseLibrary(ps);
167 while(abd->abd_VendID)
169 if((vendid == abd->abd_VendID) && (prodid == abd->abd_ProdID))
171 return(usbForceDeviceBinding(nh, pd));
173 abd++;
176 return(NULL);
178 /* \\\ */
180 /* /// "usbForceDeviceBinding()" */
181 struct NepClassSerial * usbForceDeviceBinding(struct NepSerialBase *nh, struct PsdDevice *pd)
183 struct Library *ps;
184 struct NepClassSerial *ncp;
185 STRPTR devname;
186 IPTR prodid;
187 IPTR vendid;
188 ULONG unitno;
189 BOOL unitfound;
190 UBYTE buf[64];
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,
200 TAG_END);
201 Forbid();
202 /* Find next free unit number */
203 unitno = 0;
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)
209 unitno++;
210 ncp = (struct NepClassSerial *) nh->nh_Units.lh_Head;
211 } else {
212 ncp = (struct NepClassSerial *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
215 unitfound = FALSE;
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;
222 unitfound = TRUE;
223 break;
225 ncp = (struct NepClassSerial *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
227 if(!unitfound)
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)))
233 Permit();
234 CloseLibrary(ps);
235 return(NULL);
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;
248 Permit();
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);
257 if(ncp->ncp_Task)
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,
264 ncp->ncp_UnitNo);
266 CloseLibrary(ps);
267 return(ncp);
270 ncp->ncp_ReadySigTask = NULL;
271 //FreeSignal(ncp->ncp_ReadySignal);
272 /* Get rid of unit structure */
273 /*Forbid();
274 Remove((struct Node *) ncp);
275 FreeVec(ncp);
276 Permit();*/
277 CloseLibrary(ps);
279 return(NULL);
281 /* \\\ */
283 /* /// "usbReleaseDeviceBinding()" */
284 void usbReleaseDeviceBinding(struct NepSerialBase *nh, struct NepClassSerial *ncp)
286 struct Library *ps;
287 STRPTR devname;
289 KPRINTF(1, ("nepSerialReleaseDeviceBinding(%08lx)\n", ncp));
290 if((ps = OpenLibrary("poseidon.library", 4)))
292 Forbid();
293 ncp->ncp_ReadySignal = SIGB_SINGLE;
294 ncp->ncp_ReadySigTask = FindTask(NULL);
295 if(ncp->ncp_Task)
297 Signal(ncp->ncp_Task, SIGBREAKF_CTRL_C);
299 Permit();
300 while(ncp->ncp_Task)
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'.",
308 devname);
309 /*psdFreeVec(ncp);*/
310 CloseLibrary(ps);
313 /* \\\ */
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)
322 AROS_LIBFUNC_INIT
324 struct TagItem *ti;
325 LONG count = 0;
327 KPRINTF(1, ("nepHidGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
328 switch(type)
330 case UGA_CLASS:
331 if((ti = FindTagItem(UCCA_Priority, tags)))
333 *((SIPTR *) ti->ti_Data) = 0;
334 count++;
336 if((ti = FindTagItem(UCCA_Description, tags)))
338 *((STRPTR *) ti->ti_Data) = "CP210x serial adapter via serialcp210x.device";
339 count++;
341 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
343 *((IPTR *) ti->ti_Data) = FALSE;
344 count++;
346 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
348 *((IPTR *) ti->ti_Data) = FALSE;
349 count++;
351 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
353 *((IPTR *) ti->ti_Data) = FALSE;
354 count++;
356 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
358 *((IPTR *) ti->ti_Data) = TRUE;
359 count++;
361 break;
363 case UGA_BINDING:
364 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
366 *((IPTR *) ti->ti_Data) = TRUE;
367 count++;
369 break;
371 return(count);
372 AROS_LIBFUNC_EXIT
374 /* \\\ */
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)
383 AROS_LIBFUNC_INIT
384 return(0);
385 AROS_LIBFUNC_EXIT
387 /* \\\ */
389 /* /// "usbDoMethodA()" */
390 AROS_LH2(IPTR, usbDoMethodA,
391 AROS_LHA(ULONG, methodid, D0),
392 AROS_LHA(IPTR *, methoddata, A1),
393 LIBBASETYPEPTR, nh, 7, nep)
395 AROS_LIBFUNC_INIT
397 KPRINTF(10, ("Do Method %ld\n", methodid));
398 switch(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]);
408 return(TRUE);
410 default:
411 break;
413 return(0);
414 AROS_LIBFUNC_EXIT
416 /* \\\ */
418 /**************************************************************************/
420 #undef ps
421 #define ps ncp->ncp_Base
423 /* /// "nSetRegister()" */
424 void nSetRegister(struct NepClassSerial *ncp, ULONG reg, ULONG value)
426 LONG ioerr;
427 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_VENDOR|URTF_INTERFACE,
428 reg, value, 0);
429 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, NULL, 0);
430 if(ioerr)
432 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
433 "Could not set register %ld to %08lx: %s (%ld)",
434 reg, value,
435 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
438 /* \\\ */
440 /* /// "nGetRegister()" */
441 ULONG nGetRegister(struct NepClassSerial *ncp, ULONG reg)
443 LONG ioerr;
444 UBYTE buf[1];
445 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_IN|URTF_VENDOR|URTF_INTERFACE,
446 reg, 0, 0);
447 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, buf, 1);
448 if(ioerr)
450 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
451 "Could not get register %ld: %s (%ld)",
452 reg,
453 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
454 return 0;
455 } else {
456 return buf[0]; // although returned in UWORDs, fields are bytes!
459 /* \\\ */
461 /* /// "nSetRegisters()" */
462 void nSetRegisters(struct NepClassSerial *ncp, ULONG regstart, UBYTE *values, ULONG len)
464 LONG ioerr;
465 psdPipeSetup(ncp->ncp_EP0Pipe, URTF_VENDOR|URTF_INTERFACE,
466 regstart, 0, 0);
467 ioerr = psdDoPipe(ncp->ncp_EP0Pipe, values, len);
468 if(ioerr)
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);
476 /* \\\ */
478 /* /// "nSetSerialMode()" */
479 void nSetSerialMode(struct NepClassSerial *ncp, struct IOExtSer *ioreq)
481 ULONG bufsize = ioreq->io_RBufLen / NUMREADPIPES;
482 ULONG cfg = 0;
483 UBYTE modemdata[16];
484 LONG ioerr;
486 if(bufsize < 1024)
488 bufsize = 1024;
490 bufsize = (bufsize + 127) & (~127);
492 psdSetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
493 PSA_BufferSize, bufsize,
494 TAG_END);
495 if(ioreq->io_SerFlags & SERF_EOFMODE)
497 psdSetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
498 PSA_TermArray, &ioreq->io_TermArray,
499 TAG_END);
500 psdSetAttrs(PGA_PIPESTREAM, ncp->ncp_EPOutStream,
501 PSA_TermArray, &ioreq->io_TermArray,
502 TAG_END);
503 } else {
504 psdSetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
505 PSA_TermArray, NULL,
506 TAG_END);
507 psdSetAttrs(PGA_PIPESTREAM, ncp->ncp_EPOutStream,
508 PSA_TermArray, NULL,
509 TAG_END);
511 nSetRegister(ncp, UCPR_SET_BAUDRATE, BAUD_RATE_GEN_FREQ / ioreq->io_Baud);
513 if(ioreq->io_StopBits == 1)
515 cfg = BITS_STOP_1;
517 else if(ioreq->io_StopBits == 2)
519 cfg = BITS_STOP_2;
520 } else {
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 */
529 } else {
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 */
539 } else {
540 cfg |= BITS_PARITY_SPACE; /* space parity */
543 cfg |= ioreq->io_ReadLen<<8;
545 if(ioreq->io_SerFlags & SERF_RAD_BOOGIE)
547 cfg = 0x0800;
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);
557 if(ioerr)
559 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
560 "Could not get modem data: %s (%ld)",
561 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
562 return;
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;
570 modemdata[4] = 0x80;
571 nSetRegisters(ncp, UCPR_SET_MODEMCTL, modemdata, 16);
572 } else {
573 nSetRegister(ncp, UCPR_SET_CONTROL, UART_WRITE_RTS|UART_WRITE_DTR);
574 modemdata[0] &= ~0x7b;
575 modemdata[0] |= 0x01;
576 modemdata[4] = 0x40;
577 nSetRegisters(ncp, UCPR_SET_MODEMCTL, modemdata, 16);
580 /* \\\ */
582 /* /// "nSerialTask()" */
583 AROS_UFH0(void, nSerialTask)
585 AROS_USERFUNC_INIT
587 struct NepClassSerial *ncp;
588 ULONG sigmask;
589 ULONG sigs;
590 LONG ioerr;
591 struct IOExtSer *ioreq;
592 struct IOExtSer *ioreq2;
593 ULONG control;
594 UWORD serstate;
595 IPTR pending;
597 if((ncp = nAllocSerial()))
599 Forbid();
600 if(ncp->ncp_ReadySigTask)
602 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
604 Permit();
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);
612 if(tmpmp)
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)
626 case CMD_CLEAR:
627 psdStreamFlush(ncp->ncp_EPOutStream);
628 ReplyMsg((struct Message *) ioreq);
629 break;
631 case CMD_RESET:
632 /* Reset does a flush too */
633 case CMD_FLUSH:
634 Forbid();
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);
652 Permit();
653 break;
655 case SDCMD_QUERY:
656 serstate = 0;
657 control = nGetRegister(ncp, UCPR_GET_CONTROL);
659 if(!(control & UART_DCD)) /* Carrier Detect */
660 serstate |= (1<<5);
661 if(!(control & UART_DSR)) /* DSR */
662 serstate |= (1<<3);
663 if(!(control & UART_CTS)) /* ClearToSend */
664 serstate |= (1<<4);
665 if(!(control & UART_RTS)) /* ReadyToSend */
666 serstate |= (1<<6);
667 if(!(control & UART_DTR)) /* DTR */
668 serstate |= (1<<7);
669 if(control & UART_RING) /* Ring */
670 serstate |= (1<<2);
672 ioreq->io_Status = serstate;
673 pending = 0;
674 psdGetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
675 PSA_BytesPending, &pending,
676 TAG_END);
677 ioreq->IOSer.io_Actual = pending;
678 ReplyMsg((struct Message *) ioreq);
679 break;
681 case SDCMD_SETPARAMS:
682 nSetSerialMode(ncp, ioreq);
683 ReplyMsg((struct Message *) ioreq);
684 break;
686 default:
687 ioreq->IOSer.io_Error = IOERR_NOCMD;
688 ReplyMsg((struct Message *) ioreq);
689 break;
692 if(!ncp->ncp_DevSuspend)
694 pending = 0;
695 psdGetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
696 PSA_BytesPending, &pending,
697 TAG_END);
698 Forbid();
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);
703 Permit();
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)
708 Forbid();
709 AddHead(&ncp->ncp_ReadQueue, &ioreq->IOSer.io_Message.mn_Node);
710 break;
711 } else {
712 if(ioerr > 0)
714 ioreq->IOSer.io_Error = SerErr_LineErr;
715 } else {
716 ioreq->IOSer.io_Error = ioerr;
718 ReplyMsg((struct Message *) ioreq);
720 psdGetAttrs(PGA_PIPESTREAM, ncp->ncp_EPInStream,
721 PSA_BytesPending, &pending,
722 TAG_END);
723 Forbid();
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;
731 Permit();
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);
735 if(ioerr > 0)
737 ioreq->IOSer.io_Error = SerErr_LineErr;
738 } else {
739 ioreq->IOSer.io_Error = ioerr;
741 ReplyMsg((struct Message *) ioreq);
742 Forbid();
743 ioreq = (struct IOExtSer *) ncp->ncp_WriteQueue.lh_Head;
745 Permit();
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 */
756 Forbid();
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;
773 /* Command queue */
774 while((ioreq = (struct IOExtSer *) GetMsg(&ncp->ncp_Unit.unit_MsgPort)))
776 ioreq->IOSer.io_Error = IOERR_ABORTED;
777 ReplyMsg((struct Message *) ioreq);
779 Permit();
780 KPRINTF(20, ("Going down the river!\n"));
781 nFreeSerial(ncp);
784 AROS_USERFUNC_EXIT
786 /* \\\ */
788 /* /// "nAllocSerial()" */
789 struct NepClassSerial * nAllocSerial(void)
791 struct Task *thistask;
792 struct NepClassSerial *ncp;
793 IPTR epnum;
795 thistask = FindTask(NULL);
796 ncp = thistask->tc_UserData;
799 if(!(ncp->ncp_Base = OpenLibrary("poseidon.library", 4)))
801 Alert(AG_OpenLib);
802 break;
805 ncp->ncp_Interface = psdFindInterface(ncp->ncp_Device, NULL, TAG_END);
807 if(!ncp->ncp_Interface)
809 KPRINTF(1, ("Ooops!?! No interfaces defined?\n"));
810 break;
813 ncp->ncp_EPIn = psdFindEndpoint(ncp->ncp_Interface, NULL,
814 EA_IsIn, TRUE,
815 EA_TransferType, USEAF_BULK,
816 TAG_END);
817 ncp->ncp_EPOut = psdFindEndpoint(ncp->ncp_Interface, NULL,
818 EA_IsIn, FALSE,
819 EA_TransferType, USEAF_BULK,
820 TAG_END);
822 if(!(ncp->ncp_EPIn && ncp->ncp_EPOut))
824 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "IN or OUT endpoint missing!");
825 break;
828 psdGetAttrs(PGA_ENDPOINT, ncp->ncp_EPIn,
829 EA_EndpointNum, &epnum,
830 TAG_END);
831 ncp->ncp_EPInNum = epnum;
832 psdGetAttrs(PGA_ENDPOINT, ncp->ncp_EPOut,
833 EA_EndpointNum, &epnum,
834 TAG_END);
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,
855 TAG_END)))
857 if((ncp->ncp_EPInStream = psdOpenStream(ncp->ncp_EPIn,
858 PSA_ReadAhead, TRUE,
859 PSA_BufferedRead, TRUE,
860 PSA_NumPipes, NUMREADPIPES,
861 PSA_BufferSize, DEFREADBUFLEN,
862 PSA_AllowRuntPackets, TRUE,
863 PSA_DoNotWait, TRUE,
864 PSA_AbortSigMask, SIGBREAKF_CTRL_C,
865 TAG_END)))
867 ncp->ncp_Task = thistask;
868 return(ncp);
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);
878 } while(FALSE);
879 CloseLibrary(ncp->ncp_Base);
880 Forbid();
881 ncp->ncp_Task = NULL;
882 if(ncp->ncp_ReadySigTask)
884 Signal(ncp->ncp_ReadySigTask, 1L<<ncp->ncp_ReadySignal);
886 return(NULL);
888 /* \\\ */
890 /* /// "nFreeSerial()" */
891 void nFreeSerial(struct NepClassSerial *ncp)
893 struct IOStdReq *ioreq;
894 Forbid();
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);
907 Permit();
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);
915 Forbid();
916 ncp->ncp_Task = NULL;
917 if(ncp->ncp_ReadySigTask)
919 Signal(ncp->ncp_ReadySigTask, 1UL<<ncp->ncp_ReadySignal);
922 /* \\\ */