| 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. |