fixed the way uart_reader sets baud rates
The way it did it before was nasty and messy and so is the new way. The
big difference is that the new way works with the OMAP UART driver.
diff --git a/bbb_cape/src/bbb/bbb.gyp b/bbb_cape/src/bbb/bbb.gyp
index b40bcad..82f328a 100644
--- a/bbb_cape/src/bbb/bbb.gyp
+++ b/bbb_cape/src/bbb/bbb.gyp
@@ -30,6 +30,7 @@
'sources': [
'uart_reader.cc',
'packet_finder.cc',
+ 'uart_reader_termios2.c',
],
},
#{
diff --git a/bbb_cape/src/bbb/uart_reader.cc b/bbb_cape/src/bbb/uart_reader.cc
index ceea78a..9439774 100644
--- a/bbb_cape/src/bbb/uart_reader.cc
+++ b/bbb_cape/src/bbb/uart_reader.cc
@@ -1,9 +1,10 @@
#include "bbb/uart_reader.h"
+#define OLD_CUSTOM_SPEED 0
+
#include <errno.h>
#include <fcntl.h>
#include <linux/serial.h>
-#include <termio.h>
#include <unistd.h>
#include "aos/common/logging/logging.h"
@@ -12,18 +13,25 @@
// NOTE: In order for this to work, you MUST HAVE
// "capemgr.enable_partno=BB_UART1"
// in your BBB's /media/BEAGLEBONE/uEnv.txt file!
-
-// Implementation for setting custom serial baud rates based on this code:
-// <http://jim.sh/ftx/files/linux-custom-baudrate.c>
+// `su -c "echo BB-UART1 > /sys/devices/bone_capemgr.*/slots"` works too, but
+// you have to do it every time.
namespace bbb {
namespace {
// TODO(brians): Determine this in some way that allows easy switching for
// testing with /dev/ttyUSB0 for example.
-// TODO(brians): Change back to /dev/ttyO1.
-const char *device = "/dev/ttyUSB0";
+const char *device = "/dev/ttyO1";
} // namespace
+extern "C" {
+
+// Sets all of the weird, annoying TTY flags on fd. In a separate file because
+// the structure it uses is so weird and annoying and carries so much baggage it
+// messes up all the #includes in whatever file it's used in.
+extern int aos_uart_reader_set_tty_options(int fd, int baud_rate);
+
+} // extern "C"
+
UartReader::UartReader(int32_t baud_rate)
: fd_(open(device, O_RDWR | O_NOCTTY)) {
@@ -33,74 +41,8 @@
device, errno, strerror(errno));
}
- {
- termios options;
- if (tcgetattr(fd_, &options) != 0) {
- LOG(FATAL, "tcgetattr(%d, %p) failed with %d: %s\n",
- fd_, &options, errno, strerror(errno));
- }
- if (cfsetispeed(&options, B38400) != 0) {
- LOG(FATAL, "cfsetispeed(%p, B38400) failed with %d: %s\n",
- &options, errno, strerror(errno));
- }
- if (cfsetospeed(&options, B38400) != 0) {
- LOG(FATAL, "cfsetospeed(%p, B38400) failed with %d: %s\n",
- &options, errno, strerror(errno));
- }
- cfmakeraw(&options);
- options.c_cflag |= CLOCAL; // ignore modem flow control
- options.c_cflag |= CREAD; // enable receiver
- options.c_cflag &= ~CRTSCTS; // disable flow control
- //options.c_cflag |= PARENB; // enable parity; defaults to even
- options.c_cflag = (options.c_cflag & ~CSIZE) | CS8; // 8 bits
- options.c_cflag &= ~CSTOPB; // 1 stop bit
- options.c_iflag = 0;
- // Replace any received characters with parity or framing errors with 0s.
- options.c_iflag = (options.c_iflag & ~(IGNPAR | PARMRK)) | INPCK;
- //options.c_iflag |= IGNCR | PARMRK;
- options.c_oflag = 0;
- options.c_lflag = 0;
- options.c_cc[VMIN] = 20;
- options.c_cc[VTIME] = 0;
- if (tcsetattr(fd_, TCSANOW, &options) != 0) {
- LOG(FATAL, "tcsetattr(%d, TCSANOW, %p) failed with %d: %s\n",
- fd_, &options, errno, strerror(errno));
- }
- }
-
- {
- serial_struct serinfo;
- if (ioctl(fd_, TIOCGSERIAL, &serinfo) != 0) {
- LOG(FATAL, "ioctl(%d, TIOCGSERIAL, %p) failed with %d: %s\n",
- fd_, &serinfo, errno, strerror(errno));
- }
- serinfo.reserved_char[0] = 0;
- serinfo.flags &= ~ASYNC_SPD_MASK;
- serinfo.flags |= ASYNC_SPD_CUST;
- //serinfo.flags |= ASYNC_LOW_LATENCY;
- serinfo.custom_divisor = static_cast<int>(
- static_cast<double>(serinfo.baud_base) / baud_rate + 0.5);
- if (serinfo.custom_divisor < 1) serinfo.custom_divisor = 1;
- if (ioctl(fd_, TIOCSSERIAL, &serinfo) < 0) {
- LOG(FATAL, "ioctl(%d, TIOCSSERIAL, %p) failed with %d: %s\n",
- fd_, &serinfo, errno, strerror(errno));
- }
- if (ioctl(fd_, TIOCGSERIAL, &serinfo) < 0) {
- LOG(FATAL, "ioctl(%d, TIOCGSERIAL, %p) failed with %d: %s\n",
- fd_, &serinfo, errno, strerror(errno));
- }
- if ((serinfo.flags & ASYNC_SPD_CUST) == 0) {
- LOG(FATAL, "Cannot set custom baud rate\n");
- }
- if (serinfo.custom_divisor * baud_rate != serinfo.baud_base) {
- LOG(WARNING, "actual baudrate is %d / %d = %f\n",
- serinfo.baud_base, serinfo.custom_divisor,
- static_cast<double>(serinfo.baud_base) / serinfo.custom_divisor);
- }
- }
-
- if (fcntl(fd_, F_SETFL, 0) != 0) {
- LOG(FATAL, "fcntl(%d, F_SETFL, 0) failed with %d: %s\n",
+ if (aos_uart_reader_set_tty_options(fd_, baud_rate) != 0) {
+ LOG(FATAL, "aos_uart_reader_set_tty_options(%d) failed with %d: %s\n",
fd_, errno, strerror(errno));
}
}
diff --git a/bbb_cape/src/bbb/uart_reader_termios2.c b/bbb_cape/src/bbb/uart_reader_termios2.c
new file mode 100644
index 0000000..4ee609f
--- /dev/null
+++ b/bbb_cape/src/bbb/uart_reader_termios2.c
@@ -0,0 +1,46 @@
+// This file is to work around #include conflicts when including the kernel's
+// termios.h file to get the new termios2 struct.
+
+#include <asm/termios.h>
+
+// We can't even #include <sys/ioctl.h>...
+extern int ioctl(int d, int request, ...);
+
+int aos_uart_reader_set_tty_options(int fd, int baud_rate) {
+ struct termios2 options;
+ if (ioctl(fd, TCGETS2, &options) != 0) {
+ return -1;
+ }
+
+ options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR |
+ ICRNL | IXON);
+ options.c_oflag &= ~OPOST;
+ options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ options.c_cflag &= ~(CSIZE | PARENB);
+ options.c_cflag |= CS8;
+
+ options.c_ispeed = baud_rate;
+ options.c_ospeed = baud_rate;
+ options.c_cflag = (options.c_cflag & ~CBAUD) | BOTHER;
+
+ options.c_cflag |= CLOCAL; // ignore modem flow control
+ options.c_cflag |= CREAD; // enable receiver
+ options.c_cflag &= ~CRTSCTS; // disable flow control
+ //options.c_cflag |= PARENB; // enable parity; defaults to even
+ options.c_cflag = (options.c_cflag & ~CSIZE) | CS8; // 8 bits
+ options.c_cflag &= ~CSTOPB; // 1 stop bit
+ options.c_iflag = 0;
+ // Replace any received characters with parity or framing errors with 0s.
+ options.c_iflag = (options.c_iflag & ~(IGNPAR | PARMRK)) | INPCK;
+ //options.c_iflag |= IGNCR | PARMRK;
+ options.c_oflag = 0;
+ options.c_lflag = 0;
+ options.c_cc[VMIN] = 20;
+ options.c_cc[VTIME] = 0;
+
+ if (ioctl(fd, TCSETS2, &options) != 0) {
+ return -1;
+ }
+
+ return 0;
+}