home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!europa.asd.contel.com!darwin.sura.net!uvaarpa!adastra!mbs
- From: mbs@adastra.cvl.va.us (Michael B. Smith)
- Newsgroups: comp.sys.amiga.programmer
- Subject: A serial.device example (LONG) (was Re: SERIAL.DEVICE HEEEEELLLLLPPPPPPP)
- Distribution: world
- Message-ID: <mbs.0x9d@adastra.cvl.va.us>
- References: <u895762.715081138@bruny> <Vic.00yf@angband.delfax.OCunix.On.Ca>
- X-NewsSoftware: GRn 1.16f (beta) by Mike Schwartz & Michael B. Smith
- Date: 1 Sep 92 19:00:10 EDT
- Organization: Private UUCP Node
- Lines: 544
-
- In article <Vic.00yf@angband.delfax.OCunix.On.Ca> Vic@angband.delfax.OCunix.On.Ca (Vic Lewington) writes:
- > In article <u895762.715081138@bruny> u895762@bruny.cc.utas.edu.au (Paul S.E.) writes:
- > > I have a problem that has been driving me mad for the past 5 hours.
- > > 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.
- > > HELP, anybody?!
- >
- > Having just spent a few hours going nuts myself, here, try this...
-
- [example deleted]
-
- Apologies for posting this to a non-source group. However, I spent a couple
- of days looking for a simple, working example, before writing this, and it
- wasn't to be found. This may do someone else some good...
-
- Here is a piece of working code that comes with the next release of GRn. No
- warranties, and you get what you pay for. It was written to be clear, not
- extremely efficient. This requires 2.0+, due to the use of PrintFault().
- Remove that, and it should work on 1.3.
-
- This is DICE code, but the only place it should matter is the declaration of
- InputHandler(), which is currently:
- __geta4 void InputHandler (void);
- I think SAS/C will require this to be:
- void __saveds InputHandler (void);
- but I'm not sure...
-
- Flames to NIL:
-
- /*
- GRn-Term.c
-
- GRn - Gadtools Read News
-
- Copyright 1992 by Michael B. Smith.
-
- All Rights Reserved.
-
- No warranties, express or implied, are available. Use at your own risk.
- The authors have taken pains to attempt to produce quality software,
- but by no means are we liable for anything it does to your system.
-
- Feel free to modify the source for your own use, but do NOT distribute
- unauthorized sources or binaries as part of GRn. You may distribute
- the source and binaries in unmodified form.
- */
-
- #define _GRNTERM_
-
- #include <stdlib.h>
- #include <stdarg.h>
-
- #include <exec/types.h>
- #include <devices/serial.h>
- #include <dos/dosextens.h>
- #include <dos/dostags.h>
- #include <clib/dos_protos.h>
-
- #ifndef _GRNTERM_
- extern void Abort (void);
- extern void panic (const char *, ...);
- #endif
-
- static struct MsgPort *NNTP_in_mp = NULL;
- static struct MsgPort *NNTP_out_mp = NULL;
-
- static int NNTP_in_ip = 0; // input IO in-process
- static int NNTP_out_ip = 0; // output IO in-process
-
- struct IOExtSer *NNTP_in_io = NULL;
- struct IOExtSer *NNTP_out_io = NULL;
-
- int serial_error = 0;
-
- void ShutDownSerialPort (void);
- void KillSerialPort (const int, const char *);
- void SetupSerialPort (const int, const char *, const int);
- int reads (struct IOExtSer *, char *, int);
- int writes (struct IOExtSer *, char *, int);
-
- void ShutDownSerialPort (void)
- {
- static int in_sdsp = 0; // use as a semaphore
-
- if (in_sdsp)
- return;
-
- in_sdsp = 1;
-
- if (NNTP_out_io && NNTP_out_ip) {
- AbortIO (NNTP_out_io);
- WaitIO (NNTP_out_io);
- NNTP_out_ip = 0;
- }
- if (NNTP_in_io && NNTP_in_ip) {
- AbortIO (NNTP_in_io);
- WaitIO (NNTP_in_io);
- NNTP_in_ip = 0;
- }
-
- if (NNTP_in_io && !serial_error)
- CloseDevice (NNTP_in_io);
-
- if (NNTP_out_io) {
- DeleteExtIO (NNTP_out_io, sizeof (struct IOExtSer));
- NNTP_out_io = NULL;
- }
-
- if (NNTP_in_io) {
- DeleteExtIO (NNTP_in_io, sizeof (struct IOExtSer));
- NNTP_in_io = NULL;
- }
-
- if (NNTP_out_mp) {
- DeletePort (NNTP_out_mp);
- NNTP_out_mp = NULL;
- }
-
- if (NNTP_in_mp) {
- DeletePort (NNTP_in_mp);
- NNTP_in_mp = NULL;
- }
-
- in_sdsp = 0;
- return;
- }
-
- void KillSerialPort (const int errno, const char *msg)
- {
- #ifdef _GRNTERM_
- if (errno)
- PrintFault (errno, msg);
- else {
- PutStr (msg);
- PutStr ("\n");
- }
- ShutDownSerialPort ();
- exit (20);
- #else
- ShutDownSerialPort ();
- panic (msg);
- Abort ();
- #endif
- /* NOTREACHED */
- return;
- }
-
- int SendQuery (struct IOExtSer *iorequest)
- {
- int error;
-
- iorequest->IOSer.io_Command = SDCMD_QUERY;
- if (error = DoIO (iorequest)) {
- PrintFault (error, "SendQuery error");
- return -1;
- }
-
- return iorequest->IOSer.io_Actual;
- }
-
- void SiphonIO (struct IOExtSer *iorequest)
- {
- int i;
- char buf [16];
-
- while ((i = SendQuery (iorequest)) > 0) {
- iorequest->IOSer.io_Command = CMD_READ;
- iorequest->IOSer.io_Data = buf;
- iorequest->IOSer.io_Length = i > 16 ? 16 : i;
- iorequest->IOSer.io_Flags = IOF_QUICK;
-
- if (i = DoIO (iorequest))
- PrintFault (i, "SiphonIO error");
- }
- return;
- }
-
- void SetupSerialPort (const int eofmode, const char *device, const int unit)
- {
- int errno;
-
- if(!(NNTP_in_mp = (struct MsgPort *) CreatePort (NULL, 0)))
- KillSerialPort (0, "cannot create msgport for input");
-
- if (!(NNTP_out_mp = (struct MsgPort *) CreatePort (NULL, 0)))
- KillSerialPort (0, "cannot create msgport for output");
-
- if (!(NNTP_in_io = (struct IOExtSer *) CreateExtIO (NNTP_in_mp, sizeof (struct IOExtSer))))
- KillSerialPort (0, "cannot createExtIO() for input");
-
- if (!(NNTP_out_io = (struct IOExtSer *) CreateExtIO (NNTP_out_mp, sizeof (struct IOExtSer))))
- KillSerialPort (0, "cannot createExtIO() for output");
-
- NNTP_in_io->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
- if (eofmode) {
- NNTP_in_io->io_SerFlags |= SERF_EOFMODE;
- NNTP_in_io->io_TermArray.TermArray0 = 0x1615120c;
- NNTP_in_io->io_TermArray.TermArray1 = 0x0a030000;
- }
-
- if (serial_error = OpenDevice (device, unit, NNTP_in_io, 0)) {
- printf ("device %s unit %ld IoErr = %ld\n", device, unit, IoErr ());
- KillSerialPort (serial_error, "OpenDevice() failed");
- }
-
- SendQuery (NNTP_in_io);
-
- NNTP_in_io->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
- if (eofmode) {
- NNTP_in_io->io_SerFlags |= SERF_EOFMODE;
- NNTP_in_io->io_TermArray.TermArray0 = 0x1615120c;
- NNTP_in_io->io_TermArray.TermArray1 = 0x0a030000;
- }
- if (NNTP_in_io->io_RBufLen < 32768)
- NNTP_in_io->io_RBufLen = 32768;
-
- NNTP_in_io->IOSer.io_Command = SDCMD_SETPARAMS;
-
- if (errno = DoIO (NNTP_in_io))
- KillSerialPort (errno, "setparams error");
-
- SiphonIO (NNTP_in_io);
-
- memcpy ((void *) NNTP_out_io, (void *) NNTP_in_io, sizeof (struct IOExtSer));
- NNTP_out_io->IOSer.io_Message.mn_ReplyPort = NNTP_out_mp;
-
- return;
- }
-
- int reads (struct IOExtSer *iorequest, char *buf, int len)
- {
- int errno;
- int mask;
- //
- // reads: Get input from "iorequest". We DO NOT HANG. If
- // no bytes are available, we immediately return.
- // This is not an error. The caller should deal
- // with this.
- //
- // Otherwise, we read UP TO len bytes.
- //
- // Note that efficiency and high transfer rates will
- // require len to be much greater than 1!!!
- //
- // Note that if len == -1, serial.device will build
- // the result string based on the TermArrays passed
- // when it was opened.
- //
- if (len >= 0) {
- if ((errno = SendQuery (iorequest)) == 0)
- return 0;
- if (len > errno)
- len = errno;
- }
-
- iorequest->IOSer.io_Command = CMD_READ;
- iorequest->IOSer.io_Data = buf;
- iorequest->IOSer.io_Length = len;
- iorequest->IOSer.io_Flags = IOF_QUICK;
- iorequest->IOSer.io_Actual = 0;
-
- BeginIO (iorequest); // in amiga.lib
-
- if ((iorequest->IOSer.io_Flags & IOF_QUICK) == 0) {
-
- NNTP_in_ip = 1;
- mask = 1L << iorequest->IOSer.io_Message.mn_ReplyPort->mp_SigBit;
- mask = Wait (mask | SIGBREAKF_CTRL_C);
-
- if (mask & SIGBREAKF_CTRL_C) {
- AbortIO (iorequest);
- WaitIO (iorequest);
- NNTP_in_ip = 0;
-
- // PutStr ("reads: terminated outstanding IO\n");
- return -1;
- }
- WaitIO (iorequest);
- NNTP_in_ip = 0;
- }
-
- if (errno = iorequest->IOSer.io_Error) {
- PrintFault (errno, "reads IO error");
- return -1;
- }
-
- return iorequest->IOSer.io_Actual;
- }
-
- int writes (struct IOExtSer *iorequest, char *buf, int len)
- {
- int errno;
- //
- // writes: Output 'len' bytes in 'buf' to 'iorequest'.
- //
- // Return an error if one occurs.
- //
- // Much simpler than reads().
- //
- iorequest->IOSer.io_Command = CMD_WRITE;
- iorequest->IOSer.io_Data = buf;
- iorequest->IOSer.io_Length = len;
- NNTP_out_ip = 1;
-
- DoIO (iorequest);
- NNTP_out_ip = 0;
-
- if (errno = iorequest->IOSer.io_Error) {
- PrintFault (errno, "writes: IO error");
- return -1;
- }
-
- return iorequest->IOSer.io_Actual;
- }
-
- #ifdef DEBUG
- void DebugIoRequest (struct IOExtSer * iorequest)
- {
- int mask = iorequest->io_SerFlags;
-
- printf ("CtlChar 0x%lx \n", iorequest->io_CtlChar);
- printf ("RBufLen %ld \n", iorequest->io_RBufLen);
- printf ("ExtFlags 0x%lx \n", iorequest->io_ExtFlags);
- printf ("Baud %ld \n", iorequest->io_Baud);
- printf ("BrkTime %ld \n", iorequest->io_BrkTime);
- printf ("ReadLen %ld \n", iorequest->io_ReadLen);
- printf ("WriteLen %ld \n", iorequest->io_WriteLen);
- printf ("StopBits %ld \n", iorequest->io_StopBits);
- printf ("SerFlags 0x%lx \n", iorequest->io_SerFlags);
- if (mask) {
- printf (" ");
- if (mask & SERF_XDISABLED)
- printf ("XDISABLED ");
- if (mask & SERF_EOFMODE)
- printf ("EOFMODE ");
- if (mask & SERF_SHARED)
- printf ("SHARED ");
- if (mask & SERF_RAD_BOOGIE)
- printf ("RAD_BOOGIE ");
- if (mask & SERF_QUEUEDBRK)
- printf ("QUEUEDBRK ");
- if (mask & SERF_7WIRE)
- printf ("7WIRE ");
- if (mask & SERF_PARTY_ODD)
- printf ("PARTY_ODD ");
- if (mask & SERF_PARTY_ON)
- printf ("PARTY_ON");
- printf ("\n");
- }
- printf ("Status 0x%lx \n", iorequest->io_Status);
- printf ("\n");
-
- return;
- }
- #endif
-
- int done = 0;
- int ih_done = 0;
-
- __geta4 void InputHandler (void)
- {
- int ih_len;
- char ih_inbuf [256];
-
- struct MsgPort *myport = (struct MsgPort *) CreatePort (NULL, 0);
- struct MsgPort *saveport = NULL;
-
- // NO ONE touch NNTP_in_io after I've been entered, until I'm done.
- // Under pain of GURU.
-
- if (!myport) {
- PutStr ("InputHandler: CreatePort() failure\n");
-
- ih_done = 1;
- done = 3;
- return;
- }
-
- saveport = NNTP_in_io->IOSer.io_Message.mn_ReplyPort;
- NNTP_in_io->IOSer.io_Message.mn_ReplyPort = myport;
-
- while (!done) {
-
- ih_len = reads (NNTP_in_io, ih_inbuf, 256);
-
- if (ih_len <= 0)
- continue;
-
- ih_len = Write (Output (), ih_inbuf, ih_len);
- if (ih_len < 1)
- PrintFault (IoErr (), "InputHandler Write error");
- Flush (Output ());
- }
-
- DeletePort (myport);
- NNTP_in_io->IOSer.io_Message.mn_ReplyPort = saveport;
-
- ih_done = 1;
- return;
- }
-
- int main (int argc, char **argv)
- {
- char *device;
- int unit;
- unsigned long pid;
- char *cmd;
- char chr;
- char main_inbuf [128];
- char outbuf [128];
- int len;
- int in_command = 0;
- int last_was_newline = 0;
-
- if (argc <= 1) {
- device = "serial.device";
- unit = 0;
- }
- else
- if (argc != 3) {
- PutStr ("GRn-Term <device> <unit>\n");
- exit (20);
- }
-
- device = argv [1];
- unit = atoi (argv [2]);
-
- SetupSerialPort (0, device, unit);
-
- pid = CreateNewProcTags (
- NP_Entry, InputHandler,
- NP_Input, Input(),
- NP_Output, Output(),
- NP_CloseInput, DOSFALSE,
- NP_CloseOutput, DOSFALSE,
- NP_Name, "InputHandler",
- TAG_DONE);
-
- if (!pid)
- KillSerialPort (0, "CreateNewProc() failed\n");
-
- PutStr ("\nGRn-Term Initialized\n\n");
-
- cmd = outbuf;
- while (!done) {
-
- len = Read (Input (), main_inbuf, 1);
-
- if (len < 0) {
- PrintFault (IoErr (), "CONSOLE: input error");
- continue;
- }
- if (len == 0) {
- // EOF on input
- done = 1;
- Signal ((struct Task *) pid, SIGBREAKF_CTRL_C);
- continue;
- }
-
- chr = main_inbuf [0];
-
- if (cmd == outbuf && chr == '\\')
- in_command = 1;
- if (!in_command)
- if (chr == '\n')
- writes (NNTP_out_io, "\r", 1);
- else
- writes (NNTP_out_io, main_inbuf, 1);
-
- *cmd++ = main_inbuf [0];
-
- if (chr == '\n') {
- last_was_newline = 1;
- *cmd = '\0';
- cmd = outbuf;
-
- if (!in_command)
- continue;
-
- if (strnicmp (outbuf, "\\quit", 5) == 0) {
- done = 2;
- Signal ((struct Task *) pid, SIGBREAKF_CTRL_C);
- }
- else if (strncmp (outbuf, "\\dial ", 6) == 0) {
- char *p = outbuf + 6;
-
- writes (NNTP_out_io, "\rAT\r", 4);
- Delay (50);
- *(p + strlen (p) - 1) = '\r';
- writes (NNTP_out_io, p, strlen (p));
- }
- else if (strncmp (outbuf, "\\hangup", 7) == 0) {
- Delay (110);
- writes (NNTP_out_io, "+", 1);
- Delay (5);
- writes (NNTP_out_io, "+", 1);
- Delay (5);
- writes (NNTP_out_io, "+", 1);
- Delay (150);
- writes (NNTP_out_io, "ATH0\r\n", 6);
- Delay (110);
- }
- #if 0
- // FIXME: get InputHandler() off the serial port
- else if (strncmp (outbuf, "\\grn", 4) == 0) {
- int rslt;
-
- ShutDownSerialPort ();
- rslt = SystemTagList (outbuf + 1, TAG_DONE);
- if (rslt == -1)
- PutStr ("GRn failed\n");
- else
- PutStr ("GRn complete\n");
- SetupSerialPort (0, device, unit);
- }
- #endif
- else {
- PutStr ("Unknown control command '");
- PutStr (outbuf);
- PutStr ("'\n");
- }
- in_command = 0;
- }
- else
- last_was_newline = 0;
- *cmd = '\0';
- }
-
- len = 0;
- while (!ih_done) {
- len++;
- if (len > 10) {
- len = 0;
- PutStr ("Waiting on InputHandler to terminate\n");
- }
- Delay (10);
- }
-
- ShutDownSerialPort ();
-
- PutStr ("\nGRn-Term closing down\n\n");
- }
- --
- // Michael B. Smith
- \X/ mbs@adastra.cvl.va.us -or- uunet.uu.net!virginia.edu!adastra!mbs
-