home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / internet-tools / ipdial / source / serial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-10  |  17.2 KB  |  766 lines

  1. /**
  2. ***  IPDial - Serial.c
  3. ***
  4. ***  This file implements the communication with the serial.device.
  5. ***
  6. ***
  7. ***  This program is free software; you can redistribute it and/or modify
  8. ***  it under the terms of the GNU General Public License as published by
  9. ***  the Free Software Foundation; either version 2 of the License, or
  10. ***  (at your option) any later version.
  11. ***
  12. ***  This program is distributed in the hope that it will be useful,
  13. ***  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ***  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. ***  GNU General Public License for more details.
  16. ***
  17. ***  You should have received a copy of the GNU General Public License
  18. ***  along with this program; if not, write to the Free Software
  19. ***  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. ***
  21. ***  Authors: Jochen Wiedmann <wiedmann@neckar-alb.de>
  22. ***           Stefan Gybas <cab@studbox.uni-stuttgart.de>
  23. **/
  24.  
  25.  
  26.  
  27.  
  28. /**
  29. ***  Include files
  30. **/
  31. #ifndef IPDIAL_H
  32. #include "IPDial.h"
  33. #endif
  34. #include <ctype.h>
  35. #include <devices/serial.h>
  36. #include <devices/timer.h>
  37.  
  38. #ifndef MIN
  39. #define MIN(a,b) (((a)>(b))?(b):(a))
  40. #endif
  41.  
  42.  
  43.  
  44.  
  45.  
  46. /**
  47. ***  Local variables.
  48. **/
  49. STATIC APTR MySerReq            = NULL;
  50. STATIC APTR MyTimeReq           = NULL;
  51. STATIC UBYTE SerBuffer[4096];
  52.  
  53.  
  54.  
  55.  
  56. /**
  57. ***  Cleanup function.
  58. **/
  59. VOID SerialCleanup(VOID)
  60.  
  61. { DeviceIODelete(MySerReq);
  62.   DeviceIODelete(MyTimeReq);
  63. }
  64.  
  65.  
  66.  
  67.  
  68.  
  69. /**
  70. ***  Table of error messages created by the serial.device.
  71. **/
  72. STATIC VOID SerialShowError(ULONG Error)
  73.  
  74. { STRPTR ptr;
  75.  
  76.   switch(Error)
  77.   { case 1:
  78.       ptr = (STRPTR) "Serial device busy";
  79.       break;
  80.     case 2:
  81.       ptr = (STRPTR) "Baud rate not supported";
  82.       break;
  83.     case 4:
  84.       ptr = (STRPTR) "Memory error";
  85.       break;
  86.     case 5:
  87.       ptr = (STRPTR) "Invalid parameters";
  88.       break;
  89.     case 6:
  90.       ptr = (STRPTR) "Line error";
  91.       break;
  92.     case 9:
  93.       ptr = (STRPTR) "Parity error";
  94.       break;
  95.     case 11:
  96.       ptr = (STRPTR) "Timer error";
  97.       break;
  98.     case 12:
  99.       ptr = (STRPTR) "Buffer overflow";
  100.       break;
  101.     case 13:
  102.       ptr = (STRPTR) "No DSR";
  103.       break;
  104.     case 15:
  105.       ptr = (STRPTR) "Break detected";
  106.       break;
  107.     default:
  108.       ptr = (STRPTR) "Unknown error";
  109.       break;
  110.   }
  111.  
  112.   fprintf(stderr, "\nserial error: %s\n", ptr);
  113.   CleanupAndExit(10);
  114. }
  115.  
  116.  
  117.  
  118.  
  119.  
  120. /**
  121. ***  This function opens the serial device. It can be closed
  122. ***  using DeviceIODelete().
  123. **/
  124. STATIC ULONG SerialDecodeProtocol(struct IOExtSer *SerReq, STRPTR Protocol)
  125.  
  126. { if (stricmp((char *) Protocol, "XONXOFF") == 0)
  127.   { SerReq->io_SerFlags &= ~(SERF_XDISABLED|SERF_7WIRE);
  128.   }
  129.   else if (stricmp((char *) Protocol, "NONE") == 0)
  130.   { SerReq->io_SerFlags |= SERF_XDISABLED;
  131.     SerReq->io_SerFlags &= ~SERF_7WIRE;
  132.   }
  133.   else if (stricmp((char *) Protocol, "RTSCTS") == 0  ||
  134.            stricmp((char *) Protocol, "7WIRE") == 0)
  135.   { SerReq->io_SerFlags |= (SERF_XDISABLED|SERF_7WIRE);
  136.   }
  137.   else
  138.   { return(FALSE);
  139.   }
  140.   return(TRUE);
  141. }
  142.  
  143. ULONG SerialOpen(STRPTR DeviceName, LONG Unit, LONG Baud, STRPTR Protocol)
  144.  
  145. { ULONG error;
  146.   struct IOExtSer *RealSerReq;
  147.  
  148.   if (VerboseMode)
  149.   { printf(">>> Trying to open %s unit %ld at %ld baud (protocol \"%s\")\n",
  150.                 DeviceName, Unit, Baud, Protocol);
  151.   }
  152.  
  153.   if (!(MySerReq = DeviceIOCreate(sizeof(struct IOExtSer))))
  154.   { PrintError(0, "not enough memory");
  155.   }
  156.  
  157.   RealSerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  158.   RealSerReq->io_SerFlags = 0;
  159.  
  160.   if (!SerialDecodeProtocol(RealSerReq, Protocol))
  161.   { return(FALSE);
  162.   }
  163.  
  164.   if ((error = DeviceIOOpen(DeviceName, Unit, MySerReq, 0)))
  165.   { SerialShowError(error);
  166.   }
  167.  
  168.   /* SerialSetProtocol(Protocol); */
  169.   SerialSetBaud(Baud);
  170.   SerialSetBufSize(DEFAULT_BUFSIZE);
  171.  
  172.   if (!(MyTimeReq = DeviceIOCreate(sizeof(struct timerequest))))
  173.   { PrintError(0, "failed to create timer request: not enough memory");
  174.   }
  175.  
  176.   if ((error = DeviceIOOpen((STRPTR) "timer.device", UNIT_VBLANK,
  177.                                      MyTimeReq, 0)))
  178.   { PrintError(0, "failed to open timer.device");
  179.   }
  180.   return(TRUE);
  181. }
  182.  
  183.  
  184.  
  185.  
  186.  
  187. /**
  188. ***  This function sends a string to the serial device.
  189. **/
  190. VOID SerialSend(STRPTR str)
  191.  
  192. { struct IOExtSer *req;
  193.   if (VerboseMode)
  194.   { printf(">>> Sending\n");
  195.   }
  196.  
  197.   req = (struct IOExtSer *) DeviceIOReq(MySerReq);
  198.   req->IOSer.io_Length = strlen((char*) str);
  199.   req->IOSer.io_Data = str;
  200.   DeviceIODo(MySerReq, CMD_WRITE);
  201. }
  202.  
  203.  
  204.  
  205.  
  206.  
  207. /**
  208. ***  This function is used to wait for a certain string.
  209. ***
  210. ***  The function will return if either a timeout occurs
  211. ***  (never happens, if timeout == -1) or if one of the
  212. ***  strings in the args array is read from the serial.device.
  213. ***
  214. ***  Result is the number of the string or -1.
  215. **/
  216. STATIC APTR waitBuffer = NULL;
  217. LONG SerialWait(STRPTR *args, LONG timeout)
  218.  
  219. { ULONG sigs;
  220.   ULONG rsigs;
  221.   BYTE error;
  222.   struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  223.  
  224.   if (VerboseMode)
  225.   { printf(">>> Waiting\n");
  226.   }
  227.  
  228.   /**
  229.   ***  Be sure, that the buffer is valid.
  230.   **/
  231.   if (!waitBuffer  &&  !(waitBuffer = BufferCreate()))
  232.   { PrintError(0, "not enough memory");
  233.   }
  234.  
  235.   /**
  236.   ***  Clear the buffer.
  237.   **/
  238.   BufferClear(waitBuffer);
  239.  
  240.   sigs = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | DeviceIOSignal(MySerReq);
  241.  
  242.   if (timeout != -1)
  243.   { struct timerequest *tr = (struct timerequest *) DeviceIOReq(MyTimeReq);
  244.  
  245.     tr->tr_time.tv_secs = timeout;
  246.     tr->tr_time.tv_micro = 0;
  247.     DeviceIOSend(MyTimeReq, TR_ADDREQUEST);
  248.     sigs |= DeviceIOSignal(MyTimeReq);
  249.   }
  250.  
  251.   for(;;)
  252.   { LONG result;
  253.  
  254.     /**
  255.     ***  First ask, if any data is present on the serial line.
  256.     ***  Maybe the string we are waiting for is already present?
  257.     **/
  258.     do
  259.     { DeviceIODo(MySerReq, SDCMD_QUERY);
  260.       if ((result = SerReq->IOSer.io_Actual))
  261.       { SerReq->IOSer.io_Data = SerBuffer;
  262.         SerReq->IOSer.io_Length = MIN(sizeof(SerBuffer)-1,
  263.                                       SerReq->IOSer.io_Actual);
  264.         if ((error = DeviceIODo(MySerReq, CMD_READ)))
  265.         { SerialShowError(error);
  266.         }
  267.         if (EchoMode)
  268.         { int i;
  269.  
  270.           for (i = 0;  i < SerReq->IOSer.io_Actual;  i++)
  271.           { putchar(SerBuffer[i]);
  272.           }
  273.           fflush(stdout);
  274.         }
  275.         BufferExtend(waitBuffer, SerBuffer, SerReq->IOSer.io_Actual);
  276.       }
  277.     }
  278.     while (result);
  279.  
  280.  
  281.     if ((result = BufferCheck(waitBuffer, args)) >= 0)
  282.     { DeviceIOAbort(MyTimeReq);
  283.       if (VerboseMode)
  284.       { printf(">>> Found \"%s\"\n", args[result]);
  285.       }
  286.       return(result);
  287.     }
  288.  
  289.     /**
  290.     ***  It isn't, send a request for one byte.
  291.     **/
  292.     SerReq->IOSer.io_Length = 1;
  293.     SerReq->IOSer.io_Data = SerBuffer;
  294.     DeviceIOSend(MySerReq, CMD_READ);
  295.  
  296.     rsigs = Wait(sigs);
  297.  
  298.     if (rsigs & SIGBREAKF_CTRL_F)
  299.     { printf("\nCtrl-F\n");
  300.       DeviceIOAbort(MySerReq);
  301.       SerialTerminal(NULL, FALSE, FALSE);
  302.       return(0);                       /*  has anyone a better idea?  */
  303.     }
  304.  
  305.     if (rsigs & SIGBREAKF_CTRL_C)
  306.     { printf("\nCtrl-C\n");
  307.       DeviceIOAbort(MySerReq);
  308.       SerialSend( (STRPTR) "\r\n");    /*  hangup modem if dialing  */
  309.       CleanupAndExit(10);
  310.     }
  311.     else if (rsigs & DeviceIOSignal(MySerReq))
  312.     { BYTE error;
  313.  
  314.       /**
  315.       ***  Data received, add it to the buffer and check for more.
  316.       **/
  317.       if ((error = DeviceIOWait(MySerReq)))
  318.       { SerialShowError(error);
  319.       }
  320.       if (EchoMode)
  321.       { putchar(*SerBuffer);
  322.         fflush(stdout);
  323.       }
  324.       BufferExtend(waitBuffer, SerBuffer, 1);
  325.     }
  326.     else
  327.     { /**
  328.       ***  Timeout
  329.       **/
  330.       DeviceIOWait(MyTimeReq);
  331.       DeviceIOAbort(MySerReq);
  332.       return(-1);
  333.     }
  334.   }
  335. }
  336.  
  337.  
  338.  
  339.  
  340. /**
  341. ***  Return buffer read by the last "Wait" command.
  342. **/
  343. STRPTR SerialWaitBuffer(VOID)
  344.  
  345. { if (!(waitBuffer))
  346.   { return((STRPTR) "");
  347.   }
  348.   else
  349.   { return(BufferBuffer(waitBuffer));
  350.   }
  351. }
  352.  
  353.  
  354.  
  355.  
  356.  
  357.  
  358. /**
  359. ***  This function implements a terminal mode. It gives the users input
  360. ***  to the modem and likewise the modems output to the user, as long as
  361. ***  the user doesn't enter Ctrl-\.
  362. **/
  363. VOID SerialTerminal(STRPTR eof, ULONG echo, ULONG lineMode)
  364.  
  365. { struct DosPacket *dp;
  366.   struct MsgPort *port = NULL;
  367.   struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  368.   APTR SerSendReq = NULL;
  369.   struct IOExtSer *serSendReq;
  370.   static char buffer[128];
  371.   static char sendBuffer[256]; /* Twice the size of buffer */
  372.   ULONG bufSize = sizeof(buffer);
  373.   LONG status = 10;
  374.   BPTR cis = Input();
  375.   ULONG sigs;
  376.  
  377.   if (VerboseMode)
  378.   { printf(">>> Entering terminal mode\n");
  379.   }
  380.  
  381.   if (!cis)
  382.   { PrintError(0, "invalid input device");
  383.   }
  384.  
  385.   if (!echo) {
  386.       lineMode = FALSE;
  387.   }
  388.   if (!lineMode) {
  389.       if (!SetMode(cis, TRUE))
  390.       { PrintError(0, "can't put console into character (raw) mode");
  391.       }
  392.   }
  393.  
  394.   if ((dp = AllocDosObject(DOS_STDPKT, NULL)))
  395.   { if ((port = CreateMsgPort()))
  396.     { if ((SerSendReq = DeviceIOCreate(sizeof(struct IOExtSer))))
  397.       { serSendReq = (struct IOExtSer *) DeviceIOReq(SerSendReq);
  398.         serSendReq->IOSer.io_Device = SerReq->IOSer.io_Device;
  399.         serSendReq->IOSer.io_Unit = SerReq->IOSer.io_Unit;
  400.         status = 0;
  401.       }
  402.     }
  403.   }
  404.  
  405.   if (status)
  406.   { fprintf(stderr, "Memory error.\n");
  407.     goto ExitSerialTerminal;
  408.   }
  409.  
  410.   dp->dp_Type = ACTION_READ;
  411.   dp->dp_Arg1 = ((struct FileHandle *) BADDR(cis))->fh_Arg1;
  412.   dp->dp_Arg2 = (ULONG) buffer;
  413.   dp->dp_Arg3 = bufSize;
  414.   SendPkt(dp, (struct MsgPort *) ((struct FileHandle *) BADDR(cis))->fh_Type, port);
  415.  
  416.   SerReq->IOSer.io_Length = 1;
  417.   SerReq->IOSer.io_Data = SerBuffer;
  418.   DeviceIOSend(MySerReq, CMD_READ);
  419.  
  420.   sigs = (1 << port->mp_SigBit) | SIGBREAKF_CTRL_C
  421.          | SIGBREAKF_CTRL_F | DeviceIOSignal(MySerReq);
  422.  
  423.   for(;;)
  424.   { LONG rsigs;
  425.  
  426.     rsigs = Wait(sigs);
  427.  
  428.     if (rsigs & SIGBREAKF_CTRL_C)      /*  CTRL-C: quite with RC 5  */
  429.     { printf("\nCtrl-C\n");
  430. #ifdef USE_ABORTPKT
  431.       AbortPkt(port, dp);
  432.       WaitPort(port);
  433. #endif
  434.       status = 5;
  435.       goto ExitSerialTerminal;
  436.     }
  437.  
  438.     if (rsigs & SIGBREAKF_CTRL_F)      /*  CTRL-F: quite with RC 0  */
  439.     { printf("\nCtrl-F\n");
  440. #ifdef USE_ABORTPKT
  441.       AbortPkt(port, dp);
  442.       WaitPort(port);
  443. #endif
  444.       status = 0;
  445.       goto ExitSerialTerminal;
  446.     }
  447.  
  448.     if (rsigs & (1 << port->mp_SigBit))
  449.     { int eofSeen = FALSE;
  450.  
  451.       GetMsg(port);
  452.       if (dp->dp_Res1 == -1)
  453.       { fprintf(stderr, "Error %ld while reading input.\n", dp->dp_Res2);
  454.         status = 10;
  455.         goto ExitSerialTerminal;
  456.       }
  457.       if (dp->dp_Res1 == 0)
  458.       { eofSeen = TRUE;
  459.       }
  460.       else
  461.       { int i, bufLen;  /*  Extend LF to CR/LF and send resulting string.   */
  462.  
  463.         bufLen = 0;
  464.         for (i = 0;  i < dp->dp_Res1;  i++)
  465.         { if ((eof  &&  *eof == buffer[i])  ||
  466.               (!eof  &&  !lineMode  &&  buffer[i] == 0x1c))
  467.           { eofSeen = TRUE;
  468.           }
  469.           if (lineMode  &&  buffer[i] == '\n')
  470.           { sendBuffer[bufLen++] = '\r';
  471.             sendBuffer[bufLen++] = '\n';
  472.           }
  473.           else
  474.           { sendBuffer[bufLen++] = buffer[i];
  475.           }
  476.         }
  477.  
  478.         if (bufLen > 0)
  479.         { serSendReq->IOSer.io_Length = bufLen;
  480.           serSendReq->IOSer.io_Data = sendBuffer;
  481.           DeviceIODo(SerSendReq, CMD_WRITE);
  482.         }
  483.  
  484.         if (!lineMode  &&  echo)
  485.         { fwrite(sendBuffer, bufLen, 1, stdout);
  486.           fflush(stdout);
  487.         }
  488.       }
  489.  
  490.       if (eofSeen)
  491.       { DeviceIOAbort(MySerReq);
  492.         status = -1;                   /*  don't quit IPDial  */
  493.         goto ExitSerialTerminal;
  494.       }
  495.  
  496.       dp->dp_Type = ACTION_READ;
  497.       dp->dp_Arg1 = ((struct FileHandle *) BADDR(cis))->fh_Arg1;
  498.       dp->dp_Arg2 = (ULONG) buffer;
  499.       dp->dp_Arg3 = bufSize;
  500.       SendPkt(dp, (struct MsgPort *) ((struct FileHandle *) BADDR(cis))->fh_Type, port);
  501.     }
  502.  
  503.     if (rsigs & DeviceIOSignal(MySerReq))
  504.     { LONG error;
  505.       LONG result;
  506.  
  507.       if ((error = DeviceIOWait(MySerReq)))
  508.       { SerialShowError(error);
  509. #ifdef USE_ABORTPKT
  510.         AbortPkt(port, dp);
  511.         WaitPort(port);
  512. #endif
  513.         status = 10;
  514.         goto ExitSerialTerminal;
  515.       }
  516.       putchar(*SerBuffer);
  517.       fflush(stdout);
  518.  
  519.       do
  520.       { DeviceIODo(MySerReq, SDCMD_QUERY);
  521.         if ((result = SerReq->IOSer.io_Actual))
  522.         { SerReq->IOSer.io_Data = SerBuffer;
  523.           SerReq->IOSer.io_Length = MIN(sizeof(SerBuffer)-1, SerReq->IOSer.io_Actual);
  524.           if ((error = DeviceIODo(MySerReq, CMD_READ)))
  525.           { SerialShowError(error);
  526.           }
  527.           fwrite(SerBuffer, SerReq->IOSer.io_Actual, 1, stdout);
  528.           fflush(stdout);
  529.         }
  530.       }
  531.       while (result);
  532.  
  533.       SerReq->IOSer.io_Length = 1;
  534.       SerReq->IOSer.io_Data = SerBuffer;
  535.       DeviceIOSend(MySerReq, CMD_READ);
  536.     }
  537.   }
  538.  
  539.  
  540. ExitSerialTerminal:
  541.   if (SerSendReq)
  542.   { DeviceIODelete(SerSendReq);
  543.   }
  544.   if (port)
  545.   { DeleteMsgPort(port);
  546.   }
  547.   if (dp)
  548.   { FreeDosObject(DOS_STDPKT, dp);
  549.   }
  550.   if (!lineMode)
  551.   { SetMode(cis, FALSE);
  552.   }
  553.   if (status >= 0)
  554.   { CleanupAndExit(status);
  555.   }
  556.   if (VerboseMode)
  557.   { printf(">>> Leaving terminal mode\n");
  558.   }
  559. }
  560.  
  561.  
  562.  
  563.  
  564. #ifdef SHOWPARMSCMD
  565.  
  566. /**
  567. ***  This function shows the current serial parameters.
  568. **/
  569. VOID SerialShowParms(VOID)
  570.  
  571. { STRPTR Parity, Protocol;
  572.   struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  573.  
  574.   printf("\tBaud     = %ld\n", SerReq->io_Baud);
  575.   printf("\tDataBits = %ld\n", (ULONG) SerReq->io_ReadLen);
  576.   printf("\tStopBits = %ld\n", (ULONG) SerReq->io_StopBits);
  577.   printf("\tBufSize  = %ld\n", SerReq->io_RBufLen);
  578.   if (SerReq->io_SerFlags & SERF_PARTY_ON)
  579.   { if (SerReq->io_SerFlags & SERF_PARTY_ODD)
  580.     { Parity = (STRPTR) "Odd";
  581.     }
  582.     else
  583.     { Parity = (STRPTR) "Even";
  584.     }
  585.   }
  586.   else
  587.   { Parity = (STRPTR) "None";
  588.   }
  589.   printf("\tParity   = %s\n", Parity);
  590.   if (SerReq->io_SerFlags & SERF_7WIRE)
  591.   { if (SerReq->io_SerFlags & SERF_XDISABLED)
  592.     { Protocol = (STRPTR) "RTS/CTS";
  593.     }
  594.     else
  595.     { Protocol = (STRPTR) "RTS/CTS, XON/XOFF";
  596.     }
  597.   }
  598.   else
  599.   { if (SerReq->io_SerFlags & SERF_XDISABLED)
  600.     { Protocol = (STRPTR) "None";
  601.     }
  602.     else
  603.     { Protocol = (STRPTR) "XON/XOFF";
  604.     }
  605.   }
  606.   printf("\tProtocol = %s\n\n", Protocol);
  607. }
  608.  
  609. #endif /* SHOWPARMSCMD */
  610.  
  611.  
  612.  
  613.  
  614. /**
  615. ***  Some functions for setting serial parameters.
  616. **/
  617. VOID SerialSetBaud(ULONG Baud)
  618.  
  619. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  620.   BYTE error;
  621.  
  622.   if (VerboseMode)
  623.   { printf(">>> Setting serial baud to %ld\n", Baud);
  624.   }
  625.  
  626.   SerReq->io_Baud = Baud;
  627.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  628.   { SerialShowError(error);
  629.   }
  630. }
  631. VOID SerialSetBufSize(ULONG BufSize)
  632.  
  633. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  634.   BYTE error;
  635.  
  636.   if (VerboseMode)
  637.   { printf(">>> Setting serial buffer size to %ld\n", BufSize);
  638.   }
  639.  
  640.   if (BufSize & 0x3f)
  641.   { fprintf(stderr,
  642.             "Warning: BufSize must be a multiple of 64, rounding up.\n");
  643.     BufSize = (BufSize & 0x3f) + 0x40;
  644.   }
  645.   SerReq->io_RBufLen = BufSize;
  646.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  647.   { SerialShowError(error);
  648.   }
  649. }
  650.  
  651. #ifdef SETCMD
  652.  
  653. VOID SerialSetDataBits(UBYTE DataBits)
  654.  
  655. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  656.   BYTE error;
  657.  
  658.   if (VerboseMode)
  659.   { printf(">>> Setting serial data bits to %ld\n", DataBits);
  660.   }
  661.  
  662.   SerReq->io_ReadLen = SerReq->io_WriteLen = DataBits;
  663.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  664.   { SerialShowError(error);
  665.   }
  666. }
  667. VOID SerialSetStopBits(UBYTE StopBits)
  668.  
  669. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  670.   BYTE error;
  671.  
  672.   if (VerboseMode)
  673.   { printf(">>> Setting serial stop bits to %ld\n", StopBits);
  674.   }
  675.  
  676.   SerReq->io_StopBits = StopBits;
  677.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  678.   { SerialShowError(error);
  679.   }
  680. }
  681. ULONG SerialSetParity(STRPTR Parity)
  682.  
  683. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  684.   BYTE error;
  685.  
  686.   if (VerboseMode)
  687.   { printf(">>> Setting serial parity to %s\n", Parity);
  688.   }
  689.  
  690.   if (stricmp((char *) Parity, "NONE") == 0)
  691.   { SerReq->io_SerFlags &= ~SERF_PARTY_ON;
  692.   }
  693.   else if (stricmp((char *) Parity, "EVEN") == 0)
  694.   { SerReq->io_SerFlags |= SERF_PARTY_ON;
  695.     SerReq->io_SerFlags &= ~SERF_PARTY_ODD;
  696.   }
  697.   else if (stricmp((char *) Parity, "ODD") == 0)
  698.   { SerReq->io_SerFlags |= (SERF_PARTY_ON|SERF_PARTY_ODD);
  699.   }
  700.   else
  701.   { return(FALSE);
  702.   }
  703.  
  704.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  705.   { SerialShowError(error);
  706.   }
  707.   return(TRUE);
  708. }
  709. ULONG SerialSetProtocol(STRPTR Protocol)
  710.  
  711. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  712.   BYTE error;
  713.  
  714.   if (!(SerialDecodeProtocol(SerReq, Protocol)))
  715.   { return(FALSE);
  716.   }
  717.  
  718.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  719.   { SerialShowError(error);
  720.   }
  721.   return(TRUE);
  722. }
  723.  
  724. #endif /* SETCMD */
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731. /**
  732. ***  This function is used to wait for a certain amount of time.
  733. ***
  734. ***  This function has nothing to do with serial I/O but it's placed
  735. ***  here so we can use the same timer request as in SerialWait().
  736. ***
  737. **/
  738. LONG TimerWait(LONG secs, LONG millisecs)
  739.  
  740. { ULONG rsigs;
  741.   struct timerequest *tr = (struct timerequest *) DeviceIOReq(MyTimeReq);
  742.  
  743.   tr->tr_time.tv_secs = secs;
  744.   tr->tr_time.tv_micro = 1000 * millisecs;
  745.   DeviceIOSend(MyTimeReq, TR_ADDREQUEST);
  746.  
  747.   rsigs = Wait( SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | DeviceIOSignal(MyTimeReq) );
  748.  
  749.   if (rsigs & SIGBREAKF_CTRL_F)
  750.   { printf("\nCtrl-F\n");
  751.     DeviceIOAbort(MyTimeReq);
  752.     DeviceIOWait(MyTimeReq);
  753.     SerialTerminal(NULL, FALSE, FALSE);
  754.     return(0);                         /*  don't wait any more  */
  755.   }
  756.  
  757.   if (rsigs & SIGBREAKF_CTRL_C)
  758.   { printf("\nCtrl-C\n");
  759.     CleanupAndExit(10);
  760.   }
  761.  
  762.   DeviceIOWait(MyTimeReq);
  763.   return(0);
  764. }
  765.  
  766.