home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / sys / amiga / programm / 12976 < prev    next >
Encoding:
Text File  |  1992-09-01  |  17.4 KB  |  557 lines

  1. Path: sparky!uunet!europa.asd.contel.com!darwin.sura.net!uvaarpa!adastra!mbs
  2. From: mbs@adastra.cvl.va.us (Michael B. Smith)
  3. Newsgroups: comp.sys.amiga.programmer
  4. Subject: A serial.device example (LONG) (was Re: SERIAL.DEVICE HEEEEELLLLLPPPPPPP)
  5. Distribution: world
  6. Message-ID: <mbs.0x9d@adastra.cvl.va.us>
  7. References:  <u895762.715081138@bruny> <Vic.00yf@angband.delfax.OCunix.On.Ca>
  8. X-NewsSoftware: GRn 1.16f (beta) by Mike Schwartz & Michael B. Smith
  9. Date: 1 Sep 92 19:00:10 EDT
  10. Organization: Private UUCP Node
  11. Lines: 544
  12.  
  13. In article <Vic.00yf@angband.delfax.OCunix.On.Ca> Vic@angband.delfax.OCunix.On.Ca (Vic Lewington) writes:
  14. > In article <u895762.715081138@bruny> u895762@bruny.cc.utas.edu.au (Paul S.E.) writes:
  15. > > I have a problem that has been driving me mad for the past 5 hours.
  16. > > I am trying to read data from serial.device, one character at a time. (i.e. in real time), but the 512 byte buffer prevents me from doing it.
  17. > > HELP, anybody?!
  18. >
  19. >     Having just spent a few hours going nuts myself, here, try this...
  20.  
  21. [example deleted]
  22.  
  23. Apologies for posting this to a non-source group. However, I spent a couple
  24. of days looking for a simple, working example, before writing this, and it
  25. wasn't to be found. This may do someone else some good...
  26.  
  27. Here is a piece of working code that comes with the next release of GRn. No
  28. warranties, and you get what you pay for. It was written to be clear, not
  29. extremely efficient. This requires 2.0+, due to the use of PrintFault().
  30. Remove that, and it should work on 1.3.
  31.  
  32. This is DICE code, but the only place it should matter is the declaration of
  33. InputHandler(), which is currently:
  34.              __geta4 void InputHandler (void);
  35. I think SAS/C will require this to be:
  36.              void __saveds InputHandler (void);
  37. but I'm not sure...
  38.  
  39. Flames to NIL:
  40.  
  41. /*
  42.         GRn-Term.c
  43.  
  44.         GRn - Gadtools Read News
  45.  
  46.         Copyright 1992 by Michael B. Smith.
  47.  
  48.         All Rights Reserved.
  49.  
  50.         No warranties, express or implied, are available. Use at your own risk.
  51.         The authors have taken pains to attempt to produce quality software,
  52.         but by no means are we liable for anything it does to your system.
  53.  
  54.         Feel free to modify the source for your own use, but do NOT distribute
  55.         unauthorized sources or binaries as part of GRn. You may distribute
  56.         the source and binaries in unmodified form.
  57. */
  58.  
  59. #define _GRNTERM_
  60.  
  61. #include <stdlib.h>
  62. #include <stdarg.h>
  63.  
  64. #include <exec/types.h>
  65. #include <devices/serial.h>
  66. #include <dos/dosextens.h>
  67. #include <dos/dostags.h>
  68. #include <clib/dos_protos.h>
  69.  
  70. #ifndef _GRNTERM_
  71. extern void Abort (void);
  72. extern void panic (const char *, ...);
  73. #endif
  74.  
  75. static struct MsgPort *NNTP_in_mp  = NULL;
  76. static struct MsgPort *NNTP_out_mp = NULL;
  77.  
  78. static int NNTP_in_ip  = 0; // input  IO in-process
  79. static int NNTP_out_ip = 0; // output IO in-process
  80.  
  81. struct IOExtSer *NNTP_in_io  = NULL;
  82. struct IOExtSer *NNTP_out_io = NULL;
  83.  
  84. int serial_error = 0;
  85.  
  86. void ShutDownSerialPort (void);
  87. void KillSerialPort     (const int, const char *);
  88. void SetupSerialPort    (const int, const char *, const int);
  89. int reads               (struct IOExtSer *, char *, int);
  90. int writes              (struct IOExtSer *, char *, int);
  91.  
  92. void ShutDownSerialPort (void)
  93. {
  94.         static int in_sdsp = 0;  // use as a semaphore
  95.  
  96.         if (in_sdsp)
  97.                 return;
  98.  
  99.         in_sdsp = 1;
  100.  
  101.         if (NNTP_out_io && NNTP_out_ip) {
  102.                 AbortIO (NNTP_out_io);
  103.                 WaitIO (NNTP_out_io);
  104.                 NNTP_out_ip = 0;
  105.         }
  106.         if (NNTP_in_io && NNTP_in_ip) {
  107.                 AbortIO (NNTP_in_io);
  108.                 WaitIO (NNTP_in_io);
  109.                 NNTP_in_ip = 0;
  110.         }
  111.  
  112.         if (NNTP_in_io && !serial_error)
  113.                 CloseDevice (NNTP_in_io);
  114.  
  115.         if (NNTP_out_io) {
  116.                 DeleteExtIO (NNTP_out_io, sizeof (struct IOExtSer));
  117.                 NNTP_out_io = NULL;
  118.         }
  119.  
  120.         if (NNTP_in_io) {
  121.                 DeleteExtIO (NNTP_in_io, sizeof (struct IOExtSer));
  122.                 NNTP_in_io = NULL;
  123.         }
  124.  
  125.         if (NNTP_out_mp) {
  126.                 DeletePort (NNTP_out_mp);
  127.                 NNTP_out_mp = NULL;
  128.         }
  129.  
  130.         if (NNTP_in_mp) {
  131.                 DeletePort (NNTP_in_mp);
  132.                 NNTP_in_mp = NULL;
  133.         }
  134.  
  135.         in_sdsp = 0;
  136.         return;
  137. }
  138.  
  139. void KillSerialPort (const int errno, const char *msg)
  140. {
  141. #ifdef _GRNTERM_
  142.         if (errno)
  143.                 PrintFault (errno, msg);
  144.         else {
  145.                 PutStr (msg);
  146.                 PutStr ("\n");
  147.         }
  148.         ShutDownSerialPort ();
  149.         exit (20);
  150. #else
  151.         ShutDownSerialPort ();
  152.         panic (msg);
  153.         Abort ();
  154. #endif
  155.         /* NOTREACHED */
  156.         return;
  157. }
  158.  
  159. int SendQuery (struct IOExtSer *iorequest)
  160. {
  161.         int error;
  162.  
  163.         iorequest->IOSer.io_Command = SDCMD_QUERY;
  164.         if (error = DoIO (iorequest)) {
  165.                 PrintFault (error, "SendQuery error");
  166.                 return -1;
  167.         }
  168.  
  169.         return iorequest->IOSer.io_Actual;
  170. }
  171.  
  172. void SiphonIO (struct IOExtSer *iorequest)
  173. {
  174.         int i;
  175.         char buf [16];
  176.  
  177.         while ((i = SendQuery (iorequest)) > 0) {
  178.                 iorequest->IOSer.io_Command = CMD_READ;
  179.                 iorequest->IOSer.io_Data    = buf;
  180.                 iorequest->IOSer.io_Length  = i > 16 ? 16 : i;
  181.                 iorequest->IOSer.io_Flags   = IOF_QUICK;
  182.  
  183.                 if (i = DoIO (iorequest))
  184.                         PrintFault (i, "SiphonIO error");
  185.         }
  186.         return;
  187. }
  188.  
  189. void SetupSerialPort (const int eofmode, const char *device, const int unit)
  190. {
  191.         int errno;
  192.  
  193.         if(!(NNTP_in_mp = (struct MsgPort *) CreatePort (NULL, 0)))
  194.                 KillSerialPort (0, "cannot create msgport for input");
  195.  
  196.         if (!(NNTP_out_mp = (struct MsgPort *) CreatePort (NULL, 0)))
  197.                 KillSerialPort (0, "cannot create msgport for output");
  198.  
  199.         if (!(NNTP_in_io = (struct IOExtSer *) CreateExtIO (NNTP_in_mp, sizeof (struct IOExtSer))))
  200.                 KillSerialPort (0, "cannot createExtIO() for input");
  201.  
  202.         if (!(NNTP_out_io = (struct IOExtSer *) CreateExtIO (NNTP_out_mp, sizeof (struct IOExtSer))))
  203.                 KillSerialPort (0, "cannot createExtIO() for output");
  204.  
  205.         NNTP_in_io->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  206.         if (eofmode) {
  207.                 NNTP_in_io->io_SerFlags |= SERF_EOFMODE;
  208.                 NNTP_in_io->io_TermArray.TermArray0 = 0x1615120c;
  209.                 NNTP_in_io->io_TermArray.TermArray1 = 0x0a030000;
  210.         }
  211.  
  212.         if (serial_error = OpenDevice (device, unit, NNTP_in_io, 0)) {
  213.                 printf ("device %s unit %ld IoErr = %ld\n", device, unit, IoErr ());
  214.                 KillSerialPort (serial_error, "OpenDevice() failed");
  215.         }
  216.  
  217.         SendQuery (NNTP_in_io);
  218.  
  219.         NNTP_in_io->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  220.         if (eofmode) {
  221.                 NNTP_in_io->io_SerFlags |= SERF_EOFMODE;
  222.                 NNTP_in_io->io_TermArray.TermArray0 = 0x1615120c;
  223.                 NNTP_in_io->io_TermArray.TermArray1 = 0x0a030000;
  224.         }
  225.         if (NNTP_in_io->io_RBufLen < 32768)
  226.                 NNTP_in_io->io_RBufLen = 32768;
  227.  
  228.         NNTP_in_io->IOSer.io_Command  = SDCMD_SETPARAMS;
  229.  
  230.         if (errno = DoIO (NNTP_in_io))
  231.                 KillSerialPort (errno, "setparams error");
  232.  
  233.         SiphonIO (NNTP_in_io);
  234.  
  235.         memcpy ((void *) NNTP_out_io, (void *) NNTP_in_io, sizeof (struct IOExtSer));
  236.         NNTP_out_io->IOSer.io_Message.mn_ReplyPort = NNTP_out_mp;
  237.  
  238.         return;
  239. }
  240.  
  241. int reads (struct IOExtSer *iorequest, char *buf, int len)
  242. {
  243.         int errno;
  244.         int mask;
  245.         //
  246.         // reads:   Get input from "iorequest". We DO NOT HANG. If
  247.         //          no bytes are available, we immediately return.
  248.         //          This is not an error. The caller should deal
  249.         //          with this.
  250.         //
  251.         //          Otherwise, we read UP TO len bytes.
  252.         //
  253.         //          Note that efficiency and high transfer rates will
  254.         //          require len to be much greater than 1!!!
  255.         //
  256.         //          Note that if len == -1, serial.device will build
  257.         //          the result string based on the TermArrays passed
  258.         //          when it was opened.
  259.         //
  260.         if (len >= 0) {
  261.                 if ((errno = SendQuery (iorequest)) == 0)
  262.                         return 0;
  263.                 if (len > errno)
  264.                         len = errno;
  265.         }
  266.  
  267.         iorequest->IOSer.io_Command = CMD_READ;
  268.         iorequest->IOSer.io_Data    = buf;
  269.         iorequest->IOSer.io_Length  = len;
  270.         iorequest->IOSer.io_Flags   = IOF_QUICK;
  271.         iorequest->IOSer.io_Actual  = 0;
  272.  
  273.         BeginIO (iorequest); // in amiga.lib
  274.  
  275.         if ((iorequest->IOSer.io_Flags & IOF_QUICK) == 0) {
  276.  
  277.                 NNTP_in_ip = 1;
  278.                 mask = 1L << iorequest->IOSer.io_Message.mn_ReplyPort->mp_SigBit;
  279.                 mask = Wait (mask | SIGBREAKF_CTRL_C);
  280.  
  281.                 if (mask & SIGBREAKF_CTRL_C) {
  282.                         AbortIO (iorequest);
  283.                         WaitIO (iorequest);
  284.                         NNTP_in_ip = 0;
  285.  
  286.                         // PutStr ("reads: terminated outstanding IO\n");
  287.                         return -1;
  288.                 }
  289.                 WaitIO (iorequest);
  290.                 NNTP_in_ip = 0;
  291.         }
  292.  
  293.         if (errno = iorequest->IOSer.io_Error) {
  294.                 PrintFault (errno, "reads IO error");
  295.                 return -1;
  296.         }
  297.  
  298.         return iorequest->IOSer.io_Actual;
  299. }
  300.  
  301. int writes (struct IOExtSer *iorequest, char *buf, int len)
  302. {
  303.         int errno;
  304.         //
  305.         //  writes: Output 'len' bytes in 'buf' to 'iorequest'.
  306.         //
  307.         //          Return an error if one occurs.
  308.         //
  309.         //          Much simpler than reads().
  310.         //
  311.         iorequest->IOSer.io_Command = CMD_WRITE;
  312.         iorequest->IOSer.io_Data    = buf;
  313.         iorequest->IOSer.io_Length  = len;
  314.         NNTP_out_ip = 1;
  315.  
  316.         DoIO (iorequest);
  317.         NNTP_out_ip = 0;
  318.  
  319.         if (errno = iorequest->IOSer.io_Error) {
  320.                 PrintFault (errno, "writes: IO error");
  321.                 return -1;
  322.         }
  323.  
  324.         return iorequest->IOSer.io_Actual;
  325. }
  326.  
  327. #ifdef DEBUG
  328. void DebugIoRequest (struct IOExtSer * iorequest)
  329. {
  330.         int mask = iorequest->io_SerFlags;
  331.  
  332.         printf ("CtlChar    0x%lx \n", iorequest->io_CtlChar);
  333.         printf ("RBufLen    %ld   \n", iorequest->io_RBufLen);
  334.         printf ("ExtFlags   0x%lx \n", iorequest->io_ExtFlags);
  335.         printf ("Baud       %ld   \n", iorequest->io_Baud);
  336.         printf ("BrkTime    %ld   \n", iorequest->io_BrkTime);
  337.         printf ("ReadLen    %ld   \n", iorequest->io_ReadLen);
  338.         printf ("WriteLen   %ld   \n", iorequest->io_WriteLen);
  339.         printf ("StopBits   %ld   \n", iorequest->io_StopBits);
  340.         printf ("SerFlags   0x%lx \n", iorequest->io_SerFlags);
  341.         if (mask) {
  342.                 printf ("           ");
  343.                 if (mask & SERF_XDISABLED)
  344.                         printf ("XDISABLED ");
  345.                 if (mask & SERF_EOFMODE)
  346.                         printf ("EOFMODE ");
  347.                 if (mask & SERF_SHARED)
  348.                         printf ("SHARED ");
  349.                 if (mask & SERF_RAD_BOOGIE)
  350.                         printf ("RAD_BOOGIE ");
  351.                 if (mask & SERF_QUEUEDBRK)
  352.                         printf ("QUEUEDBRK ");
  353.                 if (mask & SERF_7WIRE)
  354.                         printf ("7WIRE ");
  355.                 if (mask & SERF_PARTY_ODD)
  356.                         printf ("PARTY_ODD ");
  357.                 if (mask & SERF_PARTY_ON)
  358.                         printf ("PARTY_ON");
  359.                 printf ("\n");
  360.         }
  361.         printf ("Status     0x%lx \n", iorequest->io_Status);
  362.         printf ("\n");
  363.  
  364.         return;
  365. }
  366. #endif
  367.  
  368. int done = 0;
  369. int ih_done = 0;
  370.  
  371. __geta4 void InputHandler (void)
  372. {
  373.     int ih_len;
  374.     char ih_inbuf [256];
  375.  
  376.     struct MsgPort *myport = (struct MsgPort *) CreatePort (NULL, 0);
  377.     struct MsgPort *saveport = NULL;
  378.  
  379.     // NO ONE touch NNTP_in_io after I've been entered, until I'm done.
  380.     // Under pain of GURU.
  381.  
  382.     if (!myport) {
  383.             PutStr ("InputHandler: CreatePort() failure\n");
  384.  
  385.             ih_done = 1;
  386.             done = 3;
  387.             return;
  388.     }
  389.  
  390.     saveport = NNTP_in_io->IOSer.io_Message.mn_ReplyPort;
  391.     NNTP_in_io->IOSer.io_Message.mn_ReplyPort = myport;
  392.  
  393.     while (!done) {
  394.  
  395.             ih_len = reads (NNTP_in_io, ih_inbuf, 256);
  396.  
  397.             if (ih_len <= 0)
  398.                     continue;
  399.  
  400.             ih_len = Write (Output (), ih_inbuf, ih_len);
  401.             if (ih_len < 1)
  402.                     PrintFault (IoErr (), "InputHandler Write error");
  403.             Flush (Output ());
  404.     }
  405.  
  406.     DeletePort (myport);
  407.     NNTP_in_io->IOSer.io_Message.mn_ReplyPort = saveport;
  408.  
  409.     ih_done = 1;
  410.     return;
  411. }
  412.  
  413. int main (int argc, char **argv)
  414. {
  415.         char *device;
  416.         int unit;
  417.         unsigned long pid;
  418.         char *cmd;
  419.         char chr;
  420.         char main_inbuf [128];
  421.         char outbuf [128];
  422.         int len;
  423.         int in_command = 0;
  424.         int last_was_newline = 0;
  425.  
  426.         if (argc <= 1) {
  427.                 device = "serial.device";
  428.                 unit = 0;
  429.         }
  430.         else
  431.                 if (argc != 3) {
  432.                         PutStr ("GRn-Term <device> <unit>\n");
  433.                         exit (20);
  434.                 }
  435.  
  436.         device = argv [1];
  437.         unit = atoi (argv [2]);
  438.  
  439.         SetupSerialPort (0, device, unit);
  440.  
  441.         pid = CreateNewProcTags (
  442.                 NP_Entry,       InputHandler,
  443.                 NP_Input,       Input(),
  444.                 NP_Output,      Output(),
  445.                 NP_CloseInput,  DOSFALSE,
  446.                 NP_CloseOutput, DOSFALSE,
  447.                 NP_Name,        "InputHandler",
  448.                 TAG_DONE);
  449.  
  450.         if (!pid)
  451.                 KillSerialPort (0, "CreateNewProc() failed\n");
  452.  
  453.         PutStr ("\nGRn-Term Initialized\n\n");
  454.  
  455.         cmd = outbuf;
  456.         while (!done) {
  457.  
  458.                 len = Read (Input (), main_inbuf, 1);
  459.  
  460.                 if (len < 0) {
  461.                         PrintFault (IoErr (), "CONSOLE: input error");
  462.                         continue;
  463.                 }
  464.                 if (len == 0) {
  465.                         // EOF on input
  466.                         done = 1;
  467.                         Signal ((struct Task *) pid, SIGBREAKF_CTRL_C);
  468.                         continue;
  469.                 }
  470.  
  471.                 chr = main_inbuf [0];
  472.  
  473.                 if (cmd == outbuf && chr == '\\')
  474.                         in_command = 1;
  475.                 if (!in_command)
  476.                         if (chr == '\n')
  477.                                 writes (NNTP_out_io, "\r", 1);
  478.                         else
  479.                                 writes (NNTP_out_io, main_inbuf, 1);
  480.  
  481.                 *cmd++ = main_inbuf [0];
  482.  
  483.                 if (chr == '\n') {
  484.                         last_was_newline = 1;
  485.                         *cmd = '\0';
  486.                         cmd = outbuf;
  487.  
  488.                         if (!in_command)
  489.                                 continue;
  490.  
  491.                         if (strnicmp (outbuf, "\\quit", 5) == 0) {
  492.                                 done = 2;
  493.                                 Signal ((struct Task *) pid, SIGBREAKF_CTRL_C);
  494.                         }
  495.                         else if (strncmp (outbuf, "\\dial ", 6) == 0) {
  496.                                 char *p = outbuf + 6;
  497.  
  498.                                 writes (NNTP_out_io, "\rAT\r", 4);
  499.                                 Delay (50);
  500.                                 *(p + strlen (p) - 1) = '\r';
  501.                                 writes (NNTP_out_io, p, strlen (p));
  502.                         }
  503.                         else if (strncmp (outbuf, "\\hangup", 7) == 0) {
  504.                                 Delay (110);
  505.                                 writes (NNTP_out_io, "+", 1);
  506.                                 Delay (5);
  507.                                 writes (NNTP_out_io, "+", 1);
  508.                                 Delay (5);
  509.                                 writes (NNTP_out_io, "+", 1);
  510.                                 Delay (150);
  511.                                 writes (NNTP_out_io, "ATH0\r\n", 6);
  512.                                 Delay (110);
  513.                         }
  514. #if 0
  515.                         // FIXME: get InputHandler() off the serial port
  516.                         else if (strncmp (outbuf, "\\grn", 4) == 0) {
  517.                                 int rslt;
  518.  
  519.                                 ShutDownSerialPort ();
  520.                                 rslt = SystemTagList (outbuf + 1, TAG_DONE);
  521.                                 if (rslt == -1)
  522.                                         PutStr ("GRn failed\n");
  523.                                 else
  524.                                         PutStr ("GRn complete\n");
  525.                                 SetupSerialPort (0, device, unit);
  526.                         }
  527. #endif
  528.                         else {
  529.                                 PutStr ("Unknown control command '");
  530.                                 PutStr (outbuf);
  531.                                 PutStr ("'\n");
  532.                         }
  533.                         in_command = 0;
  534.                 }
  535.                 else
  536.                         last_was_newline = 0;
  537.                 *cmd = '\0';
  538.         }
  539.  
  540.         len = 0;
  541.         while (!ih_done) {
  542.                 len++;
  543.                 if (len > 10) {
  544.                         len = 0;
  545.                         PutStr ("Waiting on InputHandler to terminate\n");
  546.                 }
  547.                 Delay (10);
  548.         }
  549.  
  550.         ShutDownSerialPort ();
  551.  
  552.         PutStr ("\nGRn-Term closing down\n\n");
  553. }
  554. --
  555.   //   Michael B. Smith
  556. \X/    mbs@adastra.cvl.va.us  -or-  uunet.uu.net!virginia.edu!adastra!mbs
  557.