425 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			425 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
Downloaded from http://www.lafn.org/~dave/linux/Serial-Programming-HOWTO.txt
 | 
						|
Seems to be somewhat old, but contains useful bits for getty.c hacking
 | 
						|
============================================================================
 | 
						|
 | 
						|
  The Linux Serial Programming HOWTO, Part 1 of 2
 | 
						|
  By Vernon C. Hoxie
 | 
						|
  v2.0 10 September 1999
 | 
						|
 | 
						|
  This document describes how to program communications with devices
 | 
						|
  over a serial port on a Linux box.
 | 
						|
  ______________________________________________________________________
 | 
						|
 | 
						|
  Table of Contents
 | 
						|
 | 
						|
  1. Copyright
 | 
						|
 | 
						|
  2. Introduction
 | 
						|
 | 
						|
  3. Opening
 | 
						|
 | 
						|
  4. Commands
 | 
						|
 | 
						|
  5. Changing Baud Rates
 | 
						|
 | 
						|
  6. Additional Control Calls
 | 
						|
 | 
						|
     6.1 Sending a "break".
 | 
						|
     6.2 Hardware flow control.
 | 
						|
     6.3 Flushing I/O buffers.
 | 
						|
 | 
						|
  7. Modem control
 | 
						|
 | 
						|
  8. Process Groups
 | 
						|
 | 
						|
     8.1 Sessions
 | 
						|
     8.2 Process Groups
 | 
						|
     8.3 Controlling Terminal
 | 
						|
        8.3.1 Get the foreground group process id.
 | 
						|
        8.3.2 Set the foreground process group id of a terminal.
 | 
						|
        8.3.3 Get process group id.
 | 
						|
 | 
						|
  9. Lockfiles
 | 
						|
 | 
						|
  10. Additional Information
 | 
						|
 | 
						|
  11. Feedback
 | 
						|
 | 
						|
  ______________________________________________________________________
 | 
						|
 | 
						|
  1.  Copyright
 | 
						|
 | 
						|
  The Linux Serial-Programming-HOWTO is copyright (C) 1997 by Vernon
 | 
						|
  Hoxie.  Linux HOWTO documents may be reproduced and distributed in
 | 
						|
  whole or in part, in any medium physical or electronic, as long as
 | 
						|
  this copyright notice is retained on all copies. Commercial
 | 
						|
  redistribution is allowed and encouraged; however, the author would
 | 
						|
  like to be notified of any such distributions.
 | 
						|
 | 
						|
  All translations, derivative works, or aggregate works incorporating
 | 
						|
  this Linux HOWTO document must be covered under this copyright notice.
 | 
						|
  That is, you may not produce a derivative work from this HOWTO and
 | 
						|
  impose additional restrictions on its distribution.
 | 
						|
 | 
						|
  This version is a complete rewrite of the previous Serial-Programming-
 | 
						|
  HOWTO  by Peter H. Baumann,  <mailto:Peter.Baumann@dlr.de>
 | 
						|
 | 
						|
  2.  Introduction
 | 
						|
 | 
						|
  This HOWTO will attempt to give hints about how to write a program
 | 
						|
  which needs to access a serial port.  Its principal focus will be on
 | 
						|
  the Linux implementation and what the meaning of the various library
 | 
						|
  functions available.
 | 
						|
 | 
						|
  Someone asked about which of several sequences of operations was
 | 
						|
  right.  There is no absolute right way to accomplish an outcome.  The
 | 
						|
  options available are too numerous.  If your sequences produces the
 | 
						|
  desired results, then that is the right way for you.  Another
 | 
						|
  programmer may select another set of options and get the same results.
 | 
						|
  His method is right for him.
 | 
						|
 | 
						|
  Neither of these methods may operate properly with some other
 | 
						|
  implementation of UNIX.  It is strange that many of the concepts which
 | 
						|
  were implemented in the SYSV version have been dumped.  Because UNIX
 | 
						|
  was developed by AT&T and much code has been generated on those
 | 
						|
  concepts, the AT&T version should be the standard to which others
 | 
						|
  should emulate.
 | 
						|
 | 
						|
  Now the standard is POSIX.
 | 
						|
 | 
						|
  It was once stated that the popularity of UNIX and C was that they
 | 
						|
  were created by programmers for programmers.  Not by scholars who
 | 
						|
  insist on purity of style in deference to results and simplicity of
 | 
						|
  use.  Not by committees with people who have diverse personal or
 | 
						|
  proprietary agenda.  Now ANSI and POSIX have strayed from those
 | 
						|
  original clear and simply concepts.
 | 
						|
 | 
						|
  3.  Opening
 | 
						|
 | 
						|
  The various serial devices are opened just as any other file.
 | 
						|
  Although, the fopen(3) command may be used, the plain open(2) is
 | 
						|
  preferred.  This call returns the file descriptor which is required
 | 
						|
  for the various commands that configure the interface.
 | 
						|
 | 
						|
  Open(2) has the format:
 | 
						|
 | 
						|
       #include <fcntl.h>
 | 
						|
       int open(char *path, int flags, [int mode]);
 | 
						|
 | 
						|
  In addition to the obvious O_RDWR, O_WRONLY and O_RDONLY, two
 | 
						|
  additional flags are available.  These are O_NONBLOCK and O_NOCTTY.
 | 
						|
  Other flags listed in the open(2) manual page are not applicable to
 | 
						|
  serial devices.
 | 
						|
 | 
						|
  Normally, a serial device opens in "blocking" mode.  This means that
 | 
						|
  the open() will not return until the Carrier Detect line from the port
 | 
						|
  is active, e.g. modem, is active.  When opened with the O_NONBLOCK
 | 
						|
  flag set, the open() will return immediately regardless of the status
 | 
						|
  of the DCD line.  The "blocking" mode also affects the read() call.
 | 
						|
 | 
						|
  The fcntl(2) command can be used to change the O_NONBLOCK flag anytime
 | 
						|
  after the device has been opened.
 | 
						|
 | 
						|
  The device driver and the data passing through it are controlled
 | 
						|
  according to settings in the struct termios.  This structure is
 | 
						|
  defined in "/usr/include/termios.h".  In the Linux tree, further
 | 
						|
  reference is made to "/usr/include/asm/termbits.h".
 | 
						|
  In blocking mode, a read(2) will block until data is available or a
 | 
						|
  signal is received.  It is still subject to state of the ICANON flag.
 | 
						|
 | 
						|
  When the termios.c_lflag ICANON bit is set, input data is collected
 | 
						|
  into strings until a NL, EOF or EOL character is received.  You can
 | 
						|
  define these in the termios.c_cc[] array.  Also, ERASE and KILL
 | 
						|
  characters will operate on the incoming data before it is delivered to
 | 
						|
  the user.
 | 
						|
 | 
						|
  In non-canonical mode, incoming data is quantified by use of the
 | 
						|
  c_cc[VMIN and c_cc[VTIME] values in termios.c_cc[].
 | 
						|
 | 
						|
  Some programmers use the select() call to detect the completion of a
 | 
						|
  read().  This is not the best way of checking for incoming data.
 | 
						|
  Select() is part of the SOCKETS scheme and too complex for most
 | 
						|
  applications.
 | 
						|
 | 
						|
  A full explanation of the fields of the termios structure is contained
 | 
						|
  in termios(7) of the Users Manual.  A version is included in Part 2 of
 | 
						|
  this HOWTO document.
 | 
						|
 | 
						|
  4.  Commands
 | 
						|
 | 
						|
  Changes to the struct termios are made by retrieving the current
 | 
						|
  settings, making the desired changes and transmitting the modified
 | 
						|
  structure back to the kernel.
 | 
						|
 | 
						|
  The historic means of communicating with the kernel was by use of the
 | 
						|
  ioctl(fd, COMMAND, arg) system call.  Then the purists in the
 | 
						|
  computer industry decided that this was not genetically consistent.
 | 
						|
  Their argument was that the argument changed its stripes.  Sometimes
 | 
						|
  it was an int, sometimes it was a pointer to int and other times it
 | 
						|
  was a pointer to struct termios.  Then there were those times it was
 | 
						|
  empty or NULL.  These variations are dependent upon the COMMAND.
 | 
						|
 | 
						|
  As a alternative, the tc* series of functions were concocted.
 | 
						|
 | 
						|
  These are:
 | 
						|
 | 
						|
       int tcgetattr(int filedes, struct termios *termios_p);
 | 
						|
       int tcsetattr(int filedes, int optional_actions,
 | 
						|
                     const struct termios *termios_p);
 | 
						|
 | 
						|
  instead of:
 | 
						|
 | 
						|
       int ioctl(int filedes, int command,
 | 
						|
                 struct termios *termios_p);
 | 
						|
 | 
						|
  where command is TCGETS or one of TCSETS, TCSETSW or TCSETSF.
 | 
						|
 | 
						|
  The TCSETS command is comparable to the TCSANOW optional_action for
 | 
						|
  the tc* version.  These direct the kernel to adopt the changes
 | 
						|
  immediately.  Other pairs are:
 | 
						|
 | 
						|
    command   optional_action   Meaning
 | 
						|
    TCSETSW   TCSADRAIN         Change after all output has drained.
 | 
						|
    TCSETSF   TCSAFLUSH         Change after all output has drained
 | 
						|
                                then discard any input characters
 | 
						|
                                not read.
 | 
						|
 | 
						|
  Since the return code from either the ioctl(2) or the tcsetattr(2)
 | 
						|
  commands only indicate that the command was processed by the kernel.
 | 
						|
  These do not indicate whether or not the changes were actually
 | 
						|
  accomplished.  Either of these commands should be followed by a call
 | 
						|
  to:
 | 
						|
 | 
						|
       ioctl(fd, TCGETS, &new_termios);
 | 
						|
 | 
						|
  or:
 | 
						|
 | 
						|
       tcgetattr(fd, &new_termios);
 | 
						|
 | 
						|
  A user function which makes changes to the termios structure should
 | 
						|
  define two struct termios variables.  One of these variables should
 | 
						|
  contain the desired configuration.  The other should contain a copy of
 | 
						|
  the kernels version.  Then after the desired configuration has been
 | 
						|
  sent to the kernel, another call should be made to retrieve the
 | 
						|
  kernels version.  Then the two compared.
 | 
						|
 | 
						|
  Here is an example of how to add RTS/CTS flow control:
 | 
						|
 | 
						|
       struct termios my_termios;
 | 
						|
       struct termios new_termios;
 | 
						|
 | 
						|
       tcgetattr(fd, &my_termios);
 | 
						|
       my_termios.c_flag |= CRTSCTS;
 | 
						|
       tcsetattr(fd, TCSANOW, &my_termios);
 | 
						|
       tcgetattr(fd, &new_termios);
 | 
						|
       if (memcmp(my_termios, new_termios,
 | 
						|
            sizeof(my_termios)) != 0) {
 | 
						|
           /* do some error handling */
 | 
						|
       }
 | 
						|
 | 
						|
  5.  Changing Baud Rates
 | 
						|
 | 
						|
  With Linux, the baud rate can be changed using a technique similar to
 | 
						|
  add/delete RTS/CTS.
 | 
						|
 | 
						|
  struct termios my_termios;
 | 
						|
  struct termios new_termios;
 | 
						|
 | 
						|
  tcgetattr(fd, &my_termios);
 | 
						|
  my_termios.c_flag &= ~CBAUD;
 | 
						|
  my_termios.c_flag |= B19200;
 | 
						|
  tcsetattr(fd, TCSANOW, &my_termios);
 | 
						|
  tcgetattr(fd, &new_termios);
 | 
						|
  if (memcmp(my_termios, new_termios,
 | 
						|
       sizeof(my_termios)) != 0) {
 | 
						|
      /* do some error handling */
 | 
						|
  }
 | 
						|
 | 
						|
  POSIX adds another method.  They define:
 | 
						|
 | 
						|
       speed_t cfgetispeed(const struct termios *termios_p);
 | 
						|
       speed_t cfgetospeed(const struct termios *termios_p);
 | 
						|
 | 
						|
  library calls to extract the current input or output speed from the
 | 
						|
  struct termios pointed to with *termio_p.  This is a variable defined
 | 
						|
  in the calling process.  In practice, the data contained in this
 | 
						|
  termios, should be obtained by the tcgetattr() call or an ioctl() call
 | 
						|
  using the TCGETS command.
 | 
						|
 | 
						|
  The companion library calls are:
 | 
						|
 | 
						|
       int cfsetispeed(struct termios *termios_p, speed_t speed);
 | 
						|
       int cfsetospeed(struct termios *termios_p, speed_t speed);
 | 
						|
 | 
						|
  which are used to change the value of the baud rate in the locally
 | 
						|
  defined *termios_p.  Following either of these calls, either a call to
 | 
						|
  tcsetattr() or ioctl() with one of TCSETS, TCSETSW or TCSETSF as the
 | 
						|
  command to transmit the change to the kernel.
 | 
						|
 | 
						|
  The cf* commands are preferred for portability.  Some weird Unices use
 | 
						|
  a considerably different format of termios.
 | 
						|
 | 
						|
  Most implementations of Linux use only the input speed for both input
 | 
						|
  and output.  These functions are defined in the application program by
 | 
						|
  reference to <termios.h>.  In reality, they are in
 | 
						|
  /usr/include/asm/termbits.h.
 | 
						|
 | 
						|
  6.  Additional Control Calls
 | 
						|
 | 
						|
  6.1.  Sending a "break".
 | 
						|
 | 
						|
       int ioctl(fd, TCSBRK, int arg);
 | 
						|
       int tcsendbreak(fd, int arg);
 | 
						|
 | 
						|
  Send a break:  Here the action differs between the conventional
 | 
						|
  ioctl() call and the POSIX call.  For the conventional call, an arg of
 | 
						|
  '0' sets the break control line of the UART for 0.25 seconds.  For the
 | 
						|
  POSIX command, the break line is set for arg times 0.1 seconds.
 | 
						|
 | 
						|
  6.2.  Hardware flow control.
 | 
						|
 | 
						|
       int ioctl(fd, TCXONC, int action);
 | 
						|
       int tcflow(fd, int action);
 | 
						|
 | 
						|
  The action flags are:
 | 
						|
 | 
						|
  o  TCOOFF  0  suspend output
 | 
						|
 | 
						|
  o  TCOON   1  restart output
 | 
						|
 | 
						|
  o  TCIOFF  2  transmit STOP character to suspend input
 | 
						|
 | 
						|
  o  TCION   3  transmit START character to restart input
 | 
						|
 | 
						|
  6.3.  Flushing I/O buffers.
 | 
						|
 | 
						|
       int ioctl(fd, TCFLSH, queue_selector);
 | 
						|
       int tcflush(fd, queue_selector);
 | 
						|
 | 
						|
  The queue_selector flags are:
 | 
						|
 | 
						|
  o  TCIFLUSH  0  flush any data not yet read from the input buffer
 | 
						|
 | 
						|
  o  TCOFLUSH  1  flush any data written to the output buffer but not
 | 
						|
     yet transmitted
 | 
						|
 | 
						|
  o  TCIOFLUSH 2  flush both buffers
 | 
						|
 | 
						|
  7.  Modem control
 | 
						|
 | 
						|
  The hardware modem control lines can be monitored or modified by the
 | 
						|
  ioctl(2) system call.  A set of comparable tc* calls apparently do not
 | 
						|
  exist.  The form of this call is:
 | 
						|
 | 
						|
       int ioctl(fd, COMMAND, (int *)flags);
 | 
						|
 | 
						|
  The COMMANDS and their action are:
 | 
						|
 | 
						|
  o  TIOCMBIS  turn on control lines depending upon which bits are set
 | 
						|
     in flags.
 | 
						|
 | 
						|
  o  TIOCMBIC  turn off control lines depending upon which bits are
 | 
						|
     unset in flags.
 | 
						|
  o  TIOCMGET  the appropriate bits are set in flags according to the
 | 
						|
     current status
 | 
						|
 | 
						|
  o  TIOCMSET  the state of the UART is changed according to which bits
 | 
						|
     are set/unset in 'flags'
 | 
						|
 | 
						|
     The bit pattern of flags refer to the following control lines:
 | 
						|
 | 
						|
  o  TIOCM_LE      Line enable
 | 
						|
 | 
						|
  o  TIOCM_DTR     Data Terminal Ready
 | 
						|
 | 
						|
  o  TIOCM_RTS     Request to send
 | 
						|
 | 
						|
  o  TIOCM_ST      Secondary transmit
 | 
						|
 | 
						|
  o  TIOCM_SR      Secondary receive
 | 
						|
 | 
						|
  o  TIOCM_CTS     Clear to send
 | 
						|
 | 
						|
  o  TIOCM_CAR     Carrier detect
 | 
						|
 | 
						|
  o  TIOCM_RNG     Ring
 | 
						|
 | 
						|
  o  TIOCM_DSR     Data set ready
 | 
						|
 | 
						|
  It should be noted that some of these bits are controlled by the modem
 | 
						|
  and the UART cannot change them but their status can be sensed by
 | 
						|
  TIOCMGET.  Also, most Personal Computers do not provide hardware for
 | 
						|
  secondary transmit and receive.
 | 
						|
 | 
						|
  There are also a pair of ioctl() to monitor these lines.  They are
 | 
						|
  undocumented as far as I have learned.  The commands are TIOCMIWAIT
 | 
						|
  and TCIOGICOUNT.  They also differ between versions of the Linux
 | 
						|
  kernel.
 | 
						|
 | 
						|
  See the lines.c file in my "serial_suite" for an example of how these
 | 
						|
  can be used see  <ftp://scicom.alphacd.com/pub/linux/serial_suite>
 | 
						|
 | 
						|
  8.  Process Groups
 | 
						|
 | 
						|
  8.1.  Sessions
 | 
						|
 | 
						|
  8.2.  Process Groups
 | 
						|
 | 
						|
  Any newly created process inherits the Process Group of its creator.
 | 
						|
  The Process Group leader has the same PID as PGID.
 | 
						|
 | 
						|
  8.3.  Controlling Terminal
 | 
						|
 | 
						|
  There are a series of ioctl(2) and tc*(2) calls which can be used to
 | 
						|
  monitor or to change the process group to which the device is
 | 
						|
  attached.
 | 
						|
 | 
						|
  8.3.1.  Get the foreground group process id.
 | 
						|
 | 
						|
  If there is no foreground group, a number not representing an existing
 | 
						|
  process group is returned.  On error, a -1 is returned and errno is
 | 
						|
  set.
 | 
						|
 | 
						|
       int ioctl(fd, TIOCGPGRP, (pid_t *)pid);
 | 
						|
       int tcgetpgrp(fd, (pid_t *)pid);
 | 
						|
 | 
						|
  8.3.2.  Set the foreground process group id of a terminal.
 | 
						|
 | 
						|
  The fd must be the controlling terminal and be associated with the
 | 
						|
  session of the calling process.
 | 
						|
 | 
						|
       int ioctl(fd, TIOCSPGRP, (pid_t *)pid);
 | 
						|
       int tcsetpgrp(fd, (pid_t *)pid);
 | 
						|
 | 
						|
  8.3.3.  Get process group id.
 | 
						|
 | 
						|
       int ioctl(fd, TIOCGPGRP, &(pid_t)pid);
 | 
						|
       int tcgetpgrp(fd, &(pid_t)pid);
 | 
						|
 | 
						|
  9.  Lockfiles
 | 
						|
 | 
						|
  Any process which accesses a serial device should first check for the
 | 
						|
  existence of lock file for the desired device.  If such a lock lock
 | 
						|
  file exists, this means that the device may be in use by another
 | 
						|
  process.
 | 
						|
 | 
						|
  Check my "libdevlocks-x.x.tgz" at
 | 
						|
  <ftp://scicom.alphacdc.com/pub/linux> for an example of how these lock
 | 
						|
  files should be utilized.
 | 
						|
 | 
						|
  10.  Additional Information
 | 
						|
 | 
						|
  Check out my "serial_suite.tgz" for more information about programming
 | 
						|
  the serial ports at   <mailto:vern@zebra.alphacdc.com>.  There some
 | 
						|
  examples and some blurbs about setting up modems and comments about
 | 
						|
  some general considerations.
 | 
						|
 | 
						|
  11.  Feedback
 | 
						|
 | 
						|
  Please send me any corrections, questions, comments, suggestions, or
 | 
						|
  additional material. I would like to improve this HOWTO!  Tell me
 | 
						|
  exactly what you don't understand, or what could be clearer.  You can
 | 
						|
  reach me at  <mailto:vern@zebra.alphacdc.com> via email.  Please
 | 
						|
  include the version number of the Serial-Programming-HOWTO when
 | 
						|
  writing.
 |