Reputation: 23071
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.
Upvotes: 6
Views: 5623
Reputation: 2413
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.
Upvotes: 1
Reputation: 23071
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).
Upvotes: 0
Reputation: 12392
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.
Upvotes: 0
Reputation: 12019
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.)
Upvotes: 0
Reputation: 239331
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 [email protected] mailing list.
Upvotes: 2