blob: fe1c5269575b3eff47d8e8046bfeafa1f005e985 [file] [log] [blame]
Brian Silvermanf6b68842013-12-20 12:34:58 -08001#include "bbb/uart_reader.h"
Brian Silverman1662a0e2013-12-19 17:50:01 -08002
Daniel Pettia4fe7bc2013-12-22 12:57:50 -08003#include <errno.h>
Daniel Pettib36f5b82013-12-15 08:55:04 -08004#include <fcntl.h>
5#include <linux/serial.h>
Daniel Pettib36f5b82013-12-15 08:55:04 -08006#include <unistd.h>
Daniel Petti059be422013-12-14 19:47:42 -08007
Brian Silverman1662a0e2013-12-19 17:50:01 -08008#include "aos/common/logging/logging.h"
Brian Silverman53f29182013-12-21 15:16:27 -08009
Brian Silverman0117dbc2014-03-24 17:08:38 -070010#include "bbb/export_uart.h"
11
Daniel Petti059be422013-12-14 19:47:42 -080012// This is the code for receiving data from the cape via UART.
Brian Silverman04fac622014-01-26 18:32:15 -080013// fragment active.
14// `su -c "echo BB-UART1 > /sys/devices/bone_capemgr.*/slots"` works, but
15// you have to do it every time. It is also possible to set it up to do that
16// every time it boots.
Daniel Pettib36f5b82013-12-15 08:55:04 -080017
Daniel Petti059be422013-12-14 19:47:42 -080018namespace bbb {
Brian Silverman1662a0e2013-12-19 17:50:01 -080019namespace {
Brian Silverman0b882522014-02-16 15:47:34 -080020
Brian Silverman0b882522014-02-16 15:47:34 -080021int open_device() {
Brian Silverman0117dbc2014-03-24 17:08:38 -070022 ExportUart();
Brian Silverman0b882522014-02-16 15:47:34 -080023
Brian Silverman0117dbc2014-03-24 17:08:38 -070024 return open(UartDevice(), O_RDWR | O_NOCTTY | O_NONBLOCK);
Brian Silverman0b882522014-02-16 15:47:34 -080025}
26
Brian Silverman1662a0e2013-12-19 17:50:01 -080027} // namespace
Daniel Petti059be422013-12-14 19:47:42 -080028
Brian Silverman0b6d9f42013-12-23 22:03:57 -080029extern "C" {
30
31// Sets all of the weird, annoying TTY flags on fd. In a separate file because
32// the structure it uses is so weird and annoying and carries so much baggage it
33// messes up all the #includes in whatever file it's used in.
Brian Silvermanc82c5122013-12-25 15:53:44 -080034// Defined in uart_reader_termios2.c.
Brian Silverman0b6d9f42013-12-23 22:03:57 -080035extern int aos_uart_reader_set_tty_options(int fd, int baud_rate);
36
37} // extern "C"
38
Brian Silvermanf6b68842013-12-20 12:34:58 -080039UartReader::UartReader(int32_t baud_rate)
Brian Silverman0b882522014-02-16 15:47:34 -080040 : fd_(open_device()) {
Daniel Pettia4fe7bc2013-12-22 12:57:50 -080041
Brian Silverman1662a0e2013-12-19 17:50:01 -080042 if (fd_ < 0) {
Brian Silverman50a9d032014-02-16 17:20:57 -080043 LOG(FATAL, "open(%s, O_RDWR | O_NOCTTY | O_NOBLOCK) failed with %d: %s\n",
Brian Silverman0117dbc2014-03-24 17:08:38 -070044 UartDevice(), errno, strerror(errno));
Daniel Petti059be422013-12-14 19:47:42 -080045 }
Brian Silvermaned030062013-12-20 21:03:47 -080046
Brian Silverman0b6d9f42013-12-23 22:03:57 -080047 if (aos_uart_reader_set_tty_options(fd_, baud_rate) != 0) {
48 LOG(FATAL, "aos_uart_reader_set_tty_options(%d) failed with %d: %s\n",
Brian Silverman1662a0e2013-12-19 17:50:01 -080049 fd_, errno, strerror(errno));
50 }
Daniel Petti059be422013-12-14 19:47:42 -080051}
52
Brian Silvermanf6b68842013-12-20 12:34:58 -080053UartReader::~UartReader() {
Brian Silverman1662a0e2013-12-19 17:50:01 -080054 if (fd_ > 0) close(fd_);
55}
Daniel Petti059be422013-12-14 19:47:42 -080056
Brian Silverman04fac622014-01-26 18:32:15 -080057ssize_t UartReader::ReadBytes(uint8_t *dest, size_t max_bytes,
Brian Silverman7d16c572014-01-03 20:27:57 -080058 const ::aos::time::Time &timeout_time) {
Brian Silvermanb407c672014-04-09 11:58:37 -070059 fd_set fds;
60 FD_ZERO(&fds);
Brian Silverman803b7a52014-01-01 13:21:18 -080061 do {
Brian Silverman7d16c572014-01-03 20:27:57 -080062 ::aos::time::Time timeout = timeout_time - ::aos::time::Time::Now();
63 if (timeout < ::aos::time::Time(0, 0)) return -2;
Brian Silvermanff1218b2014-01-03 14:47:39 -080064 struct timeval timeout_timeval = timeout.ToTimeval();
Brian Silvermanb407c672014-04-09 11:58:37 -070065 FD_SET(fd_, &fds);
Brian Silverman0fc4ca72014-03-02 17:26:06 -080066 switch (select(fd_ + 1, &fds, NULL, NULL, &timeout_timeval)) {
Brian Silvermanff1218b2014-01-03 14:47:39 -080067 case 0:
68 return -2;
69 case -1:
70 continue;
71 case 1:
72 break;
73 default:
74 LOG(WARNING, "unknown select return value\n");
75 return -1;
76 }
Brian Silverman803b7a52014-01-01 13:21:18 -080077 ssize_t r = read(fd_, dest, max_bytes);
78 if (r != -1) return r;
79 } while (errno == EINTR);
80 return -1;
Brian Silverman1662a0e2013-12-19 17:50:01 -080081}
Daniel Petti059be422013-12-14 19:47:42 -080082
Brian Silverman04fac622014-01-26 18:32:15 -080083bool UartReader::WriteBytes(uint8_t *bytes, size_t number_bytes) {
84 size_t written = 0;
85 while (written < number_bytes) {
86 ssize_t r = write(fd_, &bytes[written], number_bytes - written);
87 if (r == -1) return false;
88 written += r;
89 }
90 return true;
91}
92
Brian Silvermanffeef3f2013-12-22 14:06:23 -080093} // namespace bbb