[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6 How to handle a serial port or modem?

The handling of serial devices under Unix is heavily influenced by the traditional use of serial terminals. Historically, various combinations of ioctls and other hacks were necessary to control the precise behaviour of a serial device, but fortunately this is one of the areas that POSIX made some efforts to standardise.

If you're using a system that doesn't understand <termios.h>, tcsetattr() and related functions, then you'll have to go elsewhere for information (or upgrade your system to something less archaeological).

There are still significant differences between systems, however, mainly in the area of device names, handling of hardware flow control, and modem signalling. (Whenever possible, leave the device driver to do all the handshaking work, and don't attempt to manipulate handshaking signals directly.)

The basic steps for opening and initialising a serial device are:

Once you have opened and set up the port, you can then use read() and write() normally. Note that the behaviour of read() will be controlled by the flag settings you gave to tcsetattr().

tcflush(), tcdrain(), tcsendbreak() and tcflow() are additional useful functions that you should be aware of.

When you're done with the port, and want to close it, be aware of a very nasty little hazard on some systems; if there's any pending output waiting to be written to the device (e.g. if output flow is stopped by hardware or software handshaking), your process can hang unkillably in the close() call until the output drains. Calling tcflush() to discard any pending output is probably a wise move.

(Blocked output on tty devices is by far the most common cause of "unkillable" processes in my experience.)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6.1 Serial device names and types

The device names used for serial port devices vary quite widely between systems. Some examples from different systems are:

The precise interaction between the device name used, and the effect on any hardware handshake lines is system-, configuration- and hardware-dependant, but will usually follow approximately these rules (assuming that the hardware is RS-232 DTE):


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6.2 Setting up termios flags

Some hints on setting up the termios flags when using a serial device that you've opened yourself (as opposed to using your existing control tty):


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6.2.1 c_iflag

You probably want to set all the bits in c_iflag to 0, unless you want to use software flow control (ick) in which case you set IXON and IXOFF.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6.2.2 c_oflag

Most of the bits of c_oflag are hacks of one sort or another to make output to slow terminals work, and as such some newer systems have dropped almost all of them as obsolete (especially all the gory output-padding options). As with c_iflag, setting everything to 0 is reasonable for most applications.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6.2.3 c_cflag

When setting the character size, remember to mask using CSIZE first; e.g. to set 8-bit characters, use:

 
    attr.c_cflag &= ~CSIZE;
    attr.c_cflag |= CS8;

Other important flags found in c_cflag that you probably want to turn on and CREAD and HUPCL.

If you need to generate even parity, then set PARENB and clear PARODD; if you need to generate odd parity then set both PARENB and PARODD. If you don't want parity at all, then make sure PARENB is clear.

Clear CSTOPB unless you actually need to generate two stop bits.

Flags for enabling hardware flow control may also be found in c_cflag, but they aren't standardised (pity).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6.2.4 c_lflag

Most applications will probably want to turn off ICANON (canonical, i.e. line-based, input processing), ECHO, and ISIG.

IEXTEN is a more complex issue. If you don't turn it off, the implementation is allowed to do nonstandard things (like define additional control characters in c_cc) that might cause unexpected results, but you might need to leave IEXTEN enabled on some systems to get useful features like hardware flow control.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6.2.5 c_cc

This is an array of characters that have special meanings on input. These characters are given names like VINTR, VSTOP etc.; the names are indexes into the array.

(Two of these "characters" are not really characters at all, but control the behaviour of read() when ICANON is disabled; these are VMIN and VTIME.)

The indexes are often referred to as though they were actual variables, e.g. "set VMIN to 1" actually means "set c_cc[VMIN] to 1". The shorthand is useful and only occasionally confusing.

Many of the slots in c_cc are only used if some other combination of flags is set:

Used only if ICANON is set

VEOF, VEOL, VERASE, VKILL (and also VEOL2, VSTATUS and VWERASE if defined and IEXTEN is set)

Used only if ISIG is set

VINTR, VQUIT, VSUSP (and also VDSUSP if defined and IEXTEN is set)

Used only if IXON or IXOFF is set

VSTOP, VSTART

Used only if ICANON is not set

VMIN, VTIME

Implementations may define additional entries in c_cc. It may be prudent to initialise all the entries to _POSIX_VDISABLE (the constant NCCS gives the array size) before setting the specific values you wish to use.

VMIN and VTIME (which may share slots with VEOF and VEOL respectively, depending on the implementation) have the following meaning. The value of VTIME is (if not 0) always interpreted as a timer in tenths of seconds.

c_cc[VMIN] > 0, c_cc[VTIME] > 0

read() will return when either VMIN bytes of input are available, or if at least one character has been read and VTIME has expired between characters, or if interrupted by a signal.

c_cc[VMIN] > 0, c_cc[VTIME] == 0

read() will return when VMIN bytes of input are available, or if interrupted. Otherwise it will wait indefinitely.

c_cc[VMIN] == 0, c_cc[VTIME] > 0

read() will return as soon as any input is available; if VTIME expires with no data arriving, it will return with no characters read. (This conflicts slightly with the end-of-file indication received in the event of modem hangup; using 1 for VMIN and either alarm() or select() for a timeout avoids this particular problem.)

c_cc[VMIN] == 0, c_cc[VTIME] == 0

read() will always return immediately; if no data is available it will return with no characters read (with the same problem as above).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated on September, 10 2007 using texi2html 1.77.