Home | History | Annotate | Download | only in src
      1 #ifndef SRC_UTIL_H
      2 #define SRC_UTIL_H
      3 
      4 #include <chrono>
      5 #include <iostream>
      6 #include <memory>
      7 #include <thread>
      8 #include <vector>
      9 
     10 #include <google/protobuf/message.h>
     11 
     12 #ifdef ANDROID
     13 #define CONFIG_NO_UART 1
     14 #endif  // ANDROID
     15 
     16 #ifndef CONFIG_NO_UART
     17 #include <termios.h>
     18 
     19 #include "src/lib/inc/frame_layer.h"
     20 #include "src/lib/inc/frame_layer_types.h"
     21 #endif  // CONFIG_NO_UART
     22 #include "nugget_tools.h"
     23 
     24 using std::string;
     25 using std::vector;
     26 using std::unique_ptr;
     27 
     28 namespace test_harness {
     29 
     30 /** The approximate time it takes to transmit one bit over UART at 115200
     31  * baud. */
     32 const auto BIT_TIME = std::chrono::microseconds(10000 / 1152);
     33 /** The approximate time it takes to transmit one byte over UART at 115200
     34  * baud. */
     35 const auto BYTE_TIME = std::chrono::microseconds(80000 / 1152);
     36 
     37 const size_t PROTO_BUFFER_MAX_LEN = 512;
     38 
     39 enum error_codes : int {
     40   NO_ERROR = 0,
     41   GENERIC_ERROR = 1,
     42   TIMEOUT = 2,
     43   TRANSPORT_ERROR = 3,
     44   OVERFLOW_ERROR = 4,
     45   SERIALIZE_ERROR = 5,
     46 };
     47 
     48 const char* error_codes_name(int code);
     49 
     50 struct raw_message {
     51   uint16_t type;  // The "magic number" used to identify the contents of data[].
     52   uint16_t data_len;  // How much data is in the buffer data[].
     53   uint8_t data[PROTO_BUFFER_MAX_LEN - 2];  // The payload of the message.
     54 };
     55 
     56 class TestHarness {
     57  public:
     58   enum VerbosityLevels : int {
     59     SILENT = 0,
     60     CRITICAL = 10,
     61     ERROR = 20,
     62     WARNING = 30,
     63     INFO = 40,
     64   };
     65 
     66   static std::unique_ptr<TestHarness> MakeUnique();
     67 
     68   TestHarness();
     69   /**
     70    * @param path The device path to the tty (e.g. "/dev/tty1"). */
     71   TestHarness(const char* path);
     72 
     73   ~TestHarness();
     74 
     75   /**
     76    * @return true if data can be sent and received over the tty. */
     77   bool ttyState() const;
     78 
     79   int getVerbosity() const;
     80   int setVerbosity(int v);
     81 
     82   /** Reads from tty until it would block. */
     83   void flushConsole();
     84   /** Reads from tty until the specified duration has passed. */
     85   string ReadUntil(std::chrono::microseconds end);
     86   void PrintUntilClosed();
     87 
     88   bool RebootNugget();
     89 
     90   int SendData(const raw_message& msg);
     91   int SendOneofProto(uint16_t type, uint16_t subtype,
     92                      const google::protobuf::Message& message);
     93   int SendProto(uint16_t type, const google::protobuf::Message& message);
     94 
     95   int GetData(raw_message* msg, std::chrono::microseconds timeout);
     96 
     97   bool UsingSpi() const;
     98 
     99 #ifndef CONFIG_NO_UART
    100   bool SwitchFromConsoleToProtoApi();
    101 
    102   bool SwitchFromProtoApiToConsole(raw_message* out_msg);
    103 #endif  // CONFIG_NO_UART
    104 
    105  protected:
    106   int verbosity;
    107   vector<uint8_t> output_buffer;
    108   vector<uint8_t> input_buffer;
    109 
    110   void Init(const char* path);
    111 
    112   /** Writes @len bytes from @data until complete. */
    113   void BlockingWrite(const char* data, size_t len);
    114 
    115   /** Reads raw bytes from the tty until either an end of line is reached or
    116    * the input would block.
    117    *
    118    * @return a single line with the '\n' character unless the last read() would
    119    * have blocked.*/
    120   string ReadLineUntilBlock();
    121 
    122   // Needed for AHDLC / UART.
    123 #ifndef CONFIG_NO_UART
    124   struct termios tty_state;
    125   ahdlc_frame_encoder_t encoder;
    126   ahdlc_frame_decoder_t decoder;
    127   int SendAhdlc(const raw_message& msg);
    128   int GetAhdlc(raw_message* msg, std::chrono::microseconds timeout);
    129 #endif  // CONFIG_NO_UART
    130   int tty_fd;
    131 
    132   // Needed for libnos / SPI.
    133   unique_ptr<nos::NuggetClientInterface> client;
    134   int SendSpi(const raw_message& msg);
    135   int GetSpi(raw_message* msg, std::chrono::microseconds timeout);
    136 
    137   std::unique_ptr<std::thread> print_uart_worker;
    138 };
    139 
    140 void FatalError(const string& msg);
    141 
    142 }  // namespace test_harness
    143 
    144 #endif  // SRC_UTIL_H
    145