6

I wrote an application that must use serial ports on Linux, especially ttyUSB ones. Reading and writing operations are performed with standard select()/read() loop and write(), and there is probably nothing wrong in them, but initialization code (or absence of some part of it) damages something in the tty subsystem. Here it is:


  vuxboot(string filename, unsigned baud = B115200) : _debug(false) {
    _fd = open(filename.c_str(), O_RDWR | O_NOCTTY);
    if(_fd < 0) throw new io_error("cannot open port");

    // Serial initialization was written with FTDI USB-to-serial converters
    // in mind. Anyway, who wants to use non-8n1 protocol?

    tcgetattr(_fd, &_termios);

    termios tio = {0};
    tio.c_iflag = IGNPAR;
    tio.c_oflag = 0;
    tio.c_cflag = baud | CLOCAL | CREAD | CS8;
    tio.c_lflag = 0;

    tcflush(_fd, TCIFLUSH);
    tcsetattr(_fd, TCSANOW, &tio);
  }

Another tcsetattr(_fd, TCSANOW, &_termios) sits in the destructor, but it is irrelevant.

With or without this termios initialization, strange things happen in system after the application exits. Sometimes plain cat (or hd) exits immediately printing nothing or same stuff each time, sometimes it is waiting and not displaying any of the data that is surely sent onto the port; and close() (read() too, but not every time) emits a strange WARNING to dmesg referring to usb-serial.c.

I checked the hardware and firmware tens of times (even on different machines) and I am sure it is working as intended; moreover, I stripped the firmware to just print same message over and over.

How can I use serial port without destroying anything? Thanks.

Catherine
  • 22,492
  • 3
  • 32
  • 47

5 Answers5

2

Hitting a WARN_ON line might mean that you've hit a kernel bug. I know that there has been much work on improving the USB-serial driver lately; I suggest trying a newer kernel, and/or asking on the linux-usb@vger.kernel.org mailing list.

caf
  • 233,326
  • 40
  • 323
  • 462
  • This problem is hit quite often by people using Beagle Boards, where almost everything connected is connected via USB. I'm also quite sure he's hitting one of several possible bugs in that subsystem. – Tim Post Jun 06 '10 at 02:57
  • 1
    History for the stable kernel suggests that no changes were made after ca. 2009-10. Also, when I use `minicom` or similar tools, the "bug" doesn't arise. – Catherine Jun 06 '10 at 13:00
1

I am not sure what is wrong with your snippet of code there but this might come in handy, if you haven't already seen it: Serial Programming Guide for POSIX Operating Systems

I had to do some serial port interfacing quite recently and this library worked fine, that might serve as another example.

dasup
  • 3,815
  • 1
  • 16
  • 25
Hamza
  • 2,313
  • 7
  • 25
  • 33
  • I just copied most of the above code from that guide. It is just _not that good_, or am I missing something?.. I'll check that library, but it is GPL'd, and my app uses Expat (aka MIT); and also it's interface is not good at all. E.g. I'd like to specify ttyUSB as a string: it might get different names with different udev config or sometimes. – Catherine Jun 05 '10 at 23:47
  • Yeah, I must admit there were a few confusing bits in that guide but still that was the most comprehensive resource I could find. Regarding the library: Perhaps you can use it as a 'sanity check', just to see if that will break your system too? – Hamza Jun 05 '10 at 23:51
  • Yeah, I checked and can confirm that the initialization code is same in that library and in my code, except for `O_NDELAY` (=`O_NONBLOCK`). I had that option set in the past, and results were even more weird: complete nonsense was sent to and received from the device, errors were returned by `read()`, and even more `WARNING`'s in syslog. – Catherine Jun 05 '10 at 23:52
  • Not sure if this is relevant to your problem, but I seem to remember I had a hell of a time trying to get a PL-2303 chipset based device working a couple of months back and it used to cause all sorts of random behaviour in the system. All the other devices (including the one I used the mentioned library with) were all FT232 based devices. – Hamza Jun 06 '10 at 00:03
  • My device **is** FT232RL-based. – Catherine Jun 06 '10 at 13:00
0

Just as a side note really, your error check on open isn't quite right - error conditions are signalled by a return value of -1. (0 is a perfectly valid fd, usually connected to stdin.)

crazyscot
  • 11,819
  • 2
  • 39
  • 40
0

You might want to try:

  vuxboot(string filename, unsigned baud = B115200) : _debug(false) {
    _fd = open(filename.c_str(), O_RDWR | O_NOCTTY);
    if(_fd < 0) throw new io_error("cannot open port");

    // Serial initialization was written with FTDI USB-to-serial converters
    // in mind. Anyway, who wants to use non-8n1 protocol?

    tcgetattr(_fd, &_termios);

-   termios tio;
+   termios tio;
+   memcpy(&tio, &_termios, sizeof(struct termios)); 

    tio.c_iflag = IGNPAR;
    tio.c_oflag = 0;
    tio.c_cflag = baud | CLOCAL | CREAD | CS8;
    tio.c_lflag = 0;

    tcflush(_fd, TCIFLUSH);
    tcsetattr(_fd, TCSANOW, &tio);
}

This makes it so that any unexpected fields of termios on your system get somewhat reasonable values.

nategoose
  • 12,054
  • 27
  • 42
0

Okay. This may not be a perfect solution... it definitely isn't. I just threw out FT232 converter (fried it, actually), and used CP2102-based one. It just works now (and also is 6 times cheaper).

Catherine
  • 22,492
  • 3
  • 32
  • 47