[Lcdproc] Serial port programming

Markus Dolze bsdfan at nurfuerspam.de
Wed Dec 2 19:39:22 UTC 2009

Hi everyone,

during the last days I had a look at the way we initialize serial ports
to track down the remaining issues with QNX.

I found that most drivers initialize a serial port smiliar to this:

  p->fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
  tcgetattr(p->fd, &portset);
  portset.c_iflag &= ~( IGNBRK | BRKINT | PARMRK | ISTRIP
            | INLCR | IGNCR | ICRNL | IXON );
  portset.c_oflag &= ~OPOST;
  portset.c_lflag &= ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN );
  portset.c_cflag &= ~( CSIZE | PARENB | CRTSCTS );
  portset.c_cflag |= CS8 | CREAD | CLOCAL ;
  cfsetospeed(&portset, speed);
  cfsetispeed(&portset, speed);
  tcsetattr(p->fd, TCSANOW, &portset);

Now what's wrong with that?

In our own implementation we clear CRTSCTS and set CREAD and CLOCAL. I
looked at cfmakeraw() from glibc, FreeBSD, NetBSD and QNX and none of it
modifies CRTSCTS and CLOCAL. Only FreeBSD sets CREAD.

Therefore these flags may not be in the desired state after cfmakeraw,
depending how they are configured at the time tcgetattr is used. While
CRTSCTS may be off by default, CLOCAL is usually not set. As most
drivers currently work, I suspect that neither CRTSCTS nor CLOCAL are
really needed.

Additionally it is a mistake to believe /portset/ cannot be modified
after using cfmakeraw - it can be modified, especially to set the
timeout values! Some drivers (serialPOS, MtxOrb) refuse to use cfmakeraw
(by commenting it out) because the author wanted to set timeouts. In the
CrystalFontz drivers, the complete init routine if contained even twice:
One time for serial ports using the above code and a second time for USB
connected displays.

O_NDELAY should probably read O_NONBLOCK, but it seems to work fine on
our supported platforms.

Therefore, I am short to re-writing the drivers which don't use
cfmakeraw correctly.



More information about the LCDproc mailing list