Neppomuk
Neppomuk

Reputation: 1210

How do I prevent libserial to eat up characters like 0x0A, 0x0D, or 0x0F coming from my serial device?

When communicating with a serial-over-USB device (a GNS FM9 receiver for getting road traffic alerts) by using libserial's SerialStream object, I found out that not all characters coming from the device are in fact being read. This is what I always get served:

3F 00 56 08 37 3F

When using the same device with the RDS Surveyor app (which is written in Java and uses a com.fazecast.jSerialComm.SerialPort), the same response looks like this:

3F 00 00 56 08 0A 37 0C 0D 3F

After some research, I stumbled over this posting: Wrong newline character over the serial port (CR instead of LF). The poster does not use libserial (but some ready-to-use serial port comm app), but his issue is exactly the same as mine.

This is the system-side config of the port in question:

pi@autoradio:~ $ stty -a
speed 38400 baud; rows 40; columns 80; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U;
eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0; -parenb -parodd -cmspar
cs8 -hupcl -cstopb cread -clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr
-igncr icrnl ixon ixoff -iuclc -ixany -imaxbel iutf8 opost -olcuc -ocrnl onlcr -onocr -onlret
-ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten echo echoe echok -echonl -noflsh
-xcase -tostop -echoprt echoctl echoke -flusho -extproc

The system is a Raspbery Pi 3B with the latest production version of Raspbian running. On the system-side, the device looks like this:

pi@autoradio:~ $ ls -al /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 0 Jun  7 17:11 /dev/ttyUSB0

Now, my question is: How can I make my SerialStream read all characters without any transformations, just as they come from the port? I don't really wanna use stty in this context because its settings might get overwritten when removing and reattaching the device. Thank you.

Upvotes: 0

Views: 303

Answers (2)

Neppomuk
Neppomuk

Reputation: 1210

OK, I opened an issue with the maintainers of libserial and got the answer that the C++ std::iostream (NOT even LibSerial::SerialStream!) kicks out whitespace characters by default. CR, LF, and FF are regarded as such.

They proposed me this solution:

SerialStream tmc_receiver_handler ("/dev/ttyUSB0", ios::in | ios::out);
char c = 0x00;

tmc_receiver_handler.SetBaudRate      (SerialStreamBuf::BAUD_38400);
tmc_receiver_handler.SetCharSize      (SerialStreamBuf::CHAR_SIZE_8);
tmc_receiver_handler.SetFlowControl   (SerialStreamBuf::FLOW_CONTROL_NONE);
tmc_receiver_handler.SetParity        (SerialStreamBuf::PARITY_NONE);
tmc_receiver_handler.SetNumOfStopBits (SerialPort::STOP_BITS_1);

tmc_receiver_handler >> noskipws >> c;

noskipws switches off whitespace suppression. After applying this, everything works fine.

Upvotes: 0

janm
janm

Reputation: 18349

You need to make sure the port is in "raw" mode.

From a quick look at the libserial documentation, it seems it doesn't have a parameter to set a raw mode. Some options:

  • Modify libserial to set raw mode.
  • Don't use libserial, and use something else.
  • Change the port defaults for your operating system.

The implementation of libserial seems quite basic; you are probably better off using something like Boost.asio.

Upvotes: 1

Related Questions