Serial Port Communications via C Program

Serial Port Communications via C Program

Post by Mark Nightingal » Fri, 28 Jun 1996 04:00:00



I am writing a program to interface to a serial device attached to "/dev/cua1".  I would like to control the
serial port parameters, i.e. baud rate, number of stop bits, start bits, etc. from within the program but can't
see anything in the man pages that will accomplish this.  So far I have opened two streams to the device, one
for reading and one for writing using the following syntax, "fdRead = open ( "/dev/cua1", O_RDONLY ); fdWrite =
open ( "/dev/cua1", O_WRONLY )".  Using "gdb" I can see data passing across the serial port, however, I can
alos tell that it isn't correct, probably wrong buad rate, etc.  I have looked at the man pages for setserial
and don't think it will do what I want unless I am missing something.  I have also looked at stty and was
hopefull until a man 2 stty showed that it was an unimplemented system call meaning I can't use it.  I would
appreciate any help anyone can give me.

I have also looked at the serial HOWTO and didn't find anything usefull.  BTW, if I run minicom from one of the
virtual terminals using device /dev/cua1 I can communicate with the device.  However, when I go back to run my
program, it looks nothing has changed.

Thanks in advance.
Mark Nightingale

 
 
 

Serial Port Communications via C Program

Post by Danny ter Ha » Sat, 29 Jun 1996 04:00:00


NOTE:
please stop at 80 chars, otherwise non-windloss users have trouble
reading it.



Quote:>I am writing a program to interface to a serial device attached to "/dev/cua1".  I would like to control the

[deleted]

Quote:>I have also looked at the serial HOWTO and didn't find anything usefull.  BTW, if I run minicom from one of the
>virtual terminals using device /dev/cua1 I can communicate with the device.  However, when I go back to run my
>program, it looks nothing has changed.

Did you ever think about looking into the source of minicom
how it is done ? :-))

Danny

 
 
 

Serial Port Communications via C Program

Post by Paul D. Boy » Mon, 01 Jul 1996 04:00:00


: I am writing a program to interface to a serial device attached to
: "/dev/cua1".  I would like to control the
: serial port parameters, i.e. baud rate, number of stop bits, start bits,
: etc. from within the program but can't
: see anything in the man pages that will accomplish this.

This more of a unix systems programming question and would have been better
asked in comp.unix.programmer.  Anyway try typing on your command line:

man 2 termios

Therein you will find the tc*() functions which are in the programming
interface for terminals.  While you are at it it would be *well* worth
your while to pick up:

1) W. Richard Stevens, Advanced Programming in the UNIX Environment,
Addison-Wesley, ISBN 0-201-56317-7

2) Donald Lewine, POSIX Programmer's Guide, O'Reilly & Associates,
ISBN 0-937175-73-0

Both of these books have sections dealing with terminal programming.
Both books are extremely well written and informative, and worth thier
weight in gold.

Hope this helps.

Paul

__

Director, X-ray Structural Facility |   phone: (919) 515-7362
Department of Chemistry - Box 8204  |   FAX:   (919) 515-5079
North Carolina State University     |
Raleigh, NC, 27695-8204
http://laue.chem.ncsu.edu/web/xray.welcome.html

 
 
 

Serial Port Communications via C Program

Post by Vern Hox » Thu, 04 Jul 1996 04:00:00




Reformatted to 80 character lines for clarity.  vch

Quote:>I am writing a program to interface to a serial device attached to
>"/dev/cua1".  I would like to control the serial port parameters, i.e.
>baud rate, number of stop bits, start bits, etc. from within the program
>but can't see anything in the man pages that will accomplish this.  So far
>I have opened two streams to the device, one for reading and one for
>writing using the following syntax, "fdRead = open ( "/dev/cua1", O_RDONLY;

) fdWrite = open ( "/dev/cua1", O_WRONLY )".

Quote:

>Using "gdb" I can see data passing across the serial port, however, I can
>also tell that it isn't correct, probably wrong buad rate, etc.  I have
>looked at the man pages for setserial and don't think it will do what I
>want unless I am missing something.  I have also looked at stty and was
>hopefull until a man 2 stty showed that it was an unimplemented system
>call meaning I can't use it.  I would appreciate any help anyone can give
>me.

>I have also looked at the serial HOWTO and didn't find anything usefull.
>BTW, if I run minicom from one of the virtual terminals using device
>/dev/cua1 I can communicate with the device.  However, when I go back to
>run my program, it looks nothing has changed.

Try getting my 'serial_suite.tgz' via ftp from 'scicom.alphacdc.com'.  It
is a collection of serial port utilities.  There are also some blurbs about
setting up and using Unix/Linux serial ports.  Of most concern to you is
the blurb about the 'struct termios'.

Here is a blurb under construction and not included in the 'serial_suite'
collection.  It is being presented here for comments.

------------------

Two different methods have been developed in an attempt to avoid having
more than one process running on the same serial port at a time.  One
method was developed at AT&T by their uucico developers.  The other was
apparently developed at Berkely for the BSD system.  This method was
adopted by Sun and others including Linux.

Under the AT&T Unix, the problem was solved by using 'lockfiles'.  These
are simple files which contain the PID of the process using the port.  The
idea is that if the PID which created the lockfile is still active, other
processes should wait.  On Linux. these lockfiles are kept in the
/var/lock/uucp directory.  The names are 'LCK..ttyS0' etc.  Under this
system, only one device driver is used per port.

When a process wants to use the port, it first checks for a lockfile on the
device it wants to use.  If it find a file, it reads the PID recorded
therein and checks if the process is still active or not.  If the process
still exists, the new process quits.  If the old process has died, the
lockfile is removed and a new one created.

The technique for creating lockfiles is to first create a temporary file
complete with the PID written to it.  This file is then linked to the
desired 'LCK..ttySN' name.  If some other process also wants this port and
has created their own lockfile, our link will fail.

Under the BSD/Sun versions of Unix, two device drivers are provided for
each port.  Presumably one is for 'outgoing' calls and the other for
'incoming' calls.  Under Linux, these drivers use the same coding and are
identical except for a kernel lock.  The operation of this locking method
is very complicated and I am not sure I know all the side effects even
though I have studied the code extensively.

First, it is necessary to understand that the 'open(2)' system call has a
special flag when the file is a bolck special or character special device
driver.  This flag is 'O_NONBLOCK' or 'O_NDELAY'.  With respect to serial
devices, this means that a normal 'open' will block and not return until
the Data Carrier Detect (DCD) line is asserted.  If 'O_NONBLOCK' flag is
included in the open command, the call will return immediately regardless
of the status of the DCD line.

If the struct termios CLOCAL (see termios.blurb) option has been selected,
the O_NONBLOCK flag is ignored.

In Linux, whenever the NORMAL (ttySN) device is neither open nor blocking
on an open and an attempt is made to open the CALLOUT (cuaN) device, it
will open immediately regardless of the presence or absence of the
O_NOBLOCK flag.  However if the NORMAL device is active or blocking on a
read (see VMIN=1, VTIM=0 in 'termios.blurb'), an open on the CALLOUT device
will fail and return an EBUSY error code.

On the other hand, if the CALLOUT device is open (O_NONBLOCK doesn't
appear to a factor), an attempt to open the NORMAL driver will fail and
return the EBUSY error code.

Thus, if you have a 'getty' listening on the 'incoming' line, it is
impossible to place a call on the 'outgoing' driver.  However, if you place
your outgoing call on the 'incoming' driver, it will open and proceed
normally.  That is 'normally', if the 'getty' is smart enough to get off
the line.  The AT&T 'uugetty' (not the Linux uugetty) expect that the first
characters received on incoming calls are either newlines or carriage
returns.  If any other characters are received, they are assumed to be
outgoing characters and the 'getty' graciously exits.

I have been carrying on a discussion for the last couple of months about the
need for 'cuaN and ttySN' drivers and so far I haven't received a
convincing reason that there is an need for the 'cuaN' series.  All the
communication software provided with Linux, recognize the /var/lock/uucp
lockfiles anyhow.

I hope that this clarifies the situation somewhat.  As far as I am
concerned, the only value the 'cuaN' and the 'Serial-HOWTO' is to confuse
immigrants from DOS.  I immigrated from AT&T SYSV and it confused me.

If you try to open a callout driver when the associated 'callin' driver is
opened, the open returns EBUSY.  If the normal driver is opened in blocking
mode, and the callout driver is busy, the attempt to open will fail with
EBUSY.  However, if it opened in standard (blocking) mode, the open will
block until the ports DCD line is asserted.  For non-blocking mode and the
cuaN port is inactive, the open will succeed immediately.  

The problem is partly cultural and partly an attempt to state a complex
situation in simply words.

The problem is "How to prevent incoming call and outgoing calls on a single
port from colliding".

---------------------------

vern

--
Vernon C. Hoxie                                           scicom!zebra!vern

Denver, Colo., 80212        uucp: 303-455-2670          voice: 303-477-1780
               Unix is what MSDOS will be when it grows up.