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