Writing Xenix serial I/O routine
Karl Denninger
karl at ddsw1.MCS.COM
Tue Feb 13 15:16:31 AEST 1990
In article <890 at holin.ATT.COM> sws at holin.ATT.COM (Steve Spear) writes:
>I've been trying to write a simple single character I/O routine for Xenix
>serial ports to port a FIDO-net bbs package to Xenix. Unfortunately I've
>only been sucessfull with writing out the port - I never see anything come
>back. I open the modem line with open( "/dev/tty1A", O_RDWR | O_NDELAY )
>and the handle comes back just fine. Then I set the line settings with IOCTL
>and do a write( handle, "ATZ\r", 4 ). I see the data go out the port on the
>data scope and the modem flashes and returns OK on the data scope, but when
>I do a read( handle, &ch, 1 ) I never get anything. Does someone have a small
>sample program I could look at to get this working?
>
>Also just out of curiosity what do the devices /dev/ttyp0 - /dev/ttyp7 do?
>
>Any help would be greatly appreciated.
Don't use "O_NDELAY" except to open the port initially.
Then, turn it OFF with a fcntl() call (turn on CLOCAL with an ioctl()
first). Now you can read/write to the port, and have it block correctly for
input.
Once you have a connection (ie: "CONNECT" from a modem), turn off CLOCAL
with another ioctl so you can sense the carrier detect.
A rough order of operations is:
#include <fcntl.h>
#include <termio.h>
struct termio tbuf;
int oldflag, x;
x = open("/dev/tty1A", O_RDWR|O_NDELAY); /* It's a good idea to check */
/* and make sure you do open! */
ioctl(x, TCGETA, &tbuf);
tbuf.c_cflag |= CLOCAL;
ioctl(x, TCSETAW, &tbuf); /* Turn on CLOCAL, no carrier detect */
oldflag = fcntl(x, F_GETFL, 0); /* Disable NDELAY */
fcntl(x, F_SETFL, oldflag & ~O_NDELAY);
..... (read/write the port you just opened)
Once you detect a carrier from the modem (ie: "CONNECT"), you do:
ioctl(x, TCGETA, &tbuf);
tbuf.c_cflag &= ~CLOCAL; /* Clear CLOCAL */
ioctl(x, TCSETAW, &tbuf); /* Now carrier is sensed */
..... continue onward .....
This ensures that you will get a signal if the carrier drops (ie: the modem
hangs up for no good reason). You MUST be sure you have a connection before
you turn the CLOCAL off, else you'll get that signal immediately (which if
not trapped terminates your process!)
It's a good idea to do the clocal thing, although not strictly necessary --
if you don't mind the line hanging for a nice long time (until your program
either times out or you find it hung :-).
Do be aware that at least one "smart" board manufacturer (name deleted to
protect the guilty) botches the handling of this particular sequence....
If you don't turn off O_NDELAY, you should effectively be "busy-waiting";
the reads will return zero unless there is a character in the buffer right
>now<. Then, you should get the character. O_NDELAY means literally "no
delay", and you get exactly that -- no waiting for the characters to enter
the stream.
Sometimes this is what you want. Most (95+%) of the time it is NOT what you
want, as you effectively are busy-waiting (which is a very bad programming
practice under a multitasking operating system!)
--
Karl Denninger (karl at ddsw1.MCS.COM, <well-connected>!ddsw1!karl)
Public Access Data Line: [+1 708 566-8911], Voice: [+1 708 566-8910]
Macro Computer Solutions, Inc. "Quality Solutions at a Fair Price"
More information about the Comp.unix.xenix
mailing list