Sometimes I just need to read from a serial device, so I skip the complexities of minicom or screen and just cat. However, this only works if I first set the baud rate of the terminal using stty <baud> before attempting to open the file.

This data is likely already (or can be) buffered in the kernel and, in this case, was received using a UART to USB bridge. USB transfer rates are fixed for a given standard, so setting the baud rate can only affect the interpretation of the data. Given my lack of insight into what this data might look like wrapped in USB packets, I am unsure how to visualize the "interpretation" of USB packet data at some fixed read rate (baud rate).

$ stty 115200
$ cat /dev/ttyACM0

What is really going on here? I understand the implications of this setting in hardware, but what does it mean in userspace software?


It looks like you might be a bit confused about how this all works.

First, /dev/ttyACM0 does not represent the USB link, or even the USB endpoint for whatever serial adapter you have connected, it represents the UART inside the adapter that handles the serial communications. Data you read from it will not include any USB headers or framing, just like data you read from /dev/ttyS0 will not include any PCI Express headers or framing. Setting the baud rate on these affects the hardware that it represents, not the bus it's connected to, so this won't do anything to the USB connection.

Second, the baud rate is a hardware setting, not a software one. When you call stty to set it on a serial port, that is telling the kernel to tell the hardware to change what baud rate it is trying to receive data at. This means in particular that any data that was received prior to this change will either be bogus (because it wasn't interpreted correctly by the hardware, sometimes the case if the baud rates are close to each other or exact harmonics), or completely lost (because the hardware just didn't accept it, the more likely case on modern hardware).

If you plan on reading data from a serial line, you need to have the baud rate set correctly prior to any data being transmitted by the other end. This also means that changing the baud rate won't change how the kernel interprets the data. If the data is already buffered in the kernel, then it's not going to change just because you change the baud rate (although it is good practice after changing the baud rate to drain the kernel buffers so that you know any future data is good).

So, to clarify, the correct method to get data out of a USB to serial adapter without using special software is to:

  1. Set the baud rate during system startup. For a USB to serial adapter, this should probably be a udev rule so that it gets set when the device gets plugged in too.
  2. Use cat (or od if you need the byte values instead of text) to read data. This will return the exact data that is received by the USB to serial adapter (assuing the adapter doesn't do special processing).
  • Of course. I made the mistaken of thinking all of these settings remained on the receiving machine. It makes sense that stty baud settings would get propagated downstream to the UART hardware. It is still interesting that setting the baud rate of the terminal (before ever opening a particular device node) will cause the hardware device to be reconfigured once opened (as opposed to a udev rule when inserted). Linux must consider the current settings of the process that is requesting a read/open call on a device node before honoring the request. Such transparency is elegant.
    – sherrellbc
    Aug 29 '17 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.