add serial HOWTO doc
authorDenis Vlasenko <vda.linux@googlemail.com>
Wed, 5 Nov 2008 12:19:39 +0000 (12:19 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Wed, 5 Nov 2008 12:19:39 +0000 (12:19 -0000)
loginutils/Serial-Programming-HOWTO.txt [new file with mode: 0644]

diff --git a/loginutils/Serial-Programming-HOWTO.txt b/loginutils/Serial-Programming-HOWTO.txt
new file mode 100644 (file)
index 0000000..0dfc8aa
--- /dev/null
@@ -0,0 +1,424 @@
+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 quanitified 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.