Author: Michał Górny Date: 2021-10-25T10:51:46+02:00 New Revision: 21bb808eb4867b35b08fa962c7c25e812fcc8836
URL: https://github.com/llvm/llvm-project/commit/21bb808eb4867b35b08fa962c7c25e812fcc8836 DIFF: https://github.com/llvm/llvm-project/commit/21bb808eb4867b35b08fa962c7c25e812fcc8836.diff LOG: [lldb] Support serial port parity checking Differential Revision: https://reviews.llvm.org/D112365 Added: Modified: lldb/include/lldb/Host/File.h lldb/include/lldb/Host/Terminal.h lldb/source/Host/common/File.cpp lldb/source/Host/common/Terminal.cpp lldb/unittests/Host/posix/TerminalTest.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Host/File.h b/lldb/include/lldb/Host/File.h index c192700590a30..d10ec1fe282a1 100644 --- a/lldb/include/lldb/Host/File.h +++ b/lldb/include/lldb/Host/File.h @@ -439,6 +439,7 @@ class SerialPort : public NativeFile { struct Options { llvm::Optional<unsigned int> BaudRate = llvm::None; llvm::Optional<Terminal::Parity> Parity = llvm::None; + llvm::Optional<Terminal::ParityCheck> ParityCheck = llvm::None; llvm::Optional<unsigned int> StopBits = llvm::None; }; diff --git a/lldb/include/lldb/Host/Terminal.h b/lldb/include/lldb/Host/Terminal.h index ff5db4c6b9b05..81930cdf02361 100644 --- a/lldb/include/lldb/Host/Terminal.h +++ b/lldb/include/lldb/Host/Terminal.h @@ -28,6 +28,18 @@ class Terminal { Mark, }; + enum class ParityCheck { + // No parity checking + No, + // Replace erraneous bytes with NUL + ReplaceWithNUL, + // Ignore erraneous bytes + Ignore, + // Mark erraneous bytes by prepending them with \xFF\x00; real \xFF + // is escaped to \xFF\xFF + Mark, + }; + Terminal(int fd = -1) : m_fd(fd) {} ~Terminal() = default; @@ -54,6 +66,8 @@ class Terminal { llvm::Error SetParity(Parity parity); + llvm::Error SetParityCheck(ParityCheck parity_check); + llvm::Error SetHardwareFlowControl(bool enabled); protected: diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp index 27a47cab78925..daac1fef2f36d 100644 --- a/lldb/source/Host/common/File.cpp +++ b/lldb/source/Host/common/File.cpp @@ -794,6 +794,21 @@ SerialPort::OptionsFromURL(llvm::StringRef urlqs) { llvm::inconvertibleErrorCode(), "Invalid parity (must be no, even, odd, mark or space): %s", x.str().c_str()); + } else if (x.consume_front("parity-check=")) { + serial_options.ParityCheck = + llvm::StringSwitch<llvm::Optional<Terminal::ParityCheck>>(x) + .Case("no", Terminal::ParityCheck::No) + .Case("replace", Terminal::ParityCheck::ReplaceWithNUL) + .Case("ignore", Terminal::ParityCheck::Ignore) + // "mark" mode is not currently supported as it requires special + // input processing + // .Case("mark", Terminal::ParityCheck::Mark) + .Default(llvm::None); + if (!serial_options.ParityCheck) + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Invalid parity-check (must be no, replace, ignore or mark): %s", + x.str().c_str()); } else if (x.consume_front("stop-bits=")) { unsigned int stop_bits; if (!llvm::to_integer(x, stop_bits, 10) || @@ -831,6 +846,11 @@ SerialPort::Create(int fd, OpenOptions options, Options serial_options, if (llvm::Error error = term.SetParity(serial_options.Parity.getValue())) return std::move(error); } + if (serial_options.ParityCheck) { + if (llvm::Error error = + term.SetParityCheck(serial_options.ParityCheck.getValue())) + return std::move(error); + } if (serial_options.StopBits) { if (llvm::Error error = term.SetStopBits(serial_options.StopBits.getValue())) diff --git a/lldb/source/Host/common/Terminal.cpp b/lldb/source/Host/common/Terminal.cpp index 23cd1dea114bf..1efd1bb9139d3 100644 --- a/lldb/source/Host/common/Terminal.cpp +++ b/lldb/source/Host/common/Terminal.cpp @@ -335,6 +335,26 @@ llvm::Error Terminal::SetParity(Terminal::Parity parity) { #endif // #if LLDB_ENABLE_TERMIOS } +llvm::Error Terminal::SetParityCheck(Terminal::ParityCheck parity_check) { + llvm::Expected<Data> data = GetData(); + if (!data) + return data.takeError(); + +#if LLDB_ENABLE_TERMIOS + struct termios &fd_termios = data->m_termios; + fd_termios.c_iflag &= ~(IGNPAR | PARMRK | INPCK); + + if (parity_check != ParityCheck::No) { + fd_termios.c_iflag |= INPCK; + if (parity_check == ParityCheck::Ignore) + fd_termios.c_iflag |= IGNPAR; + else if (parity_check == ParityCheck::Mark) + fd_termios.c_iflag |= PARMRK; + } + return SetData(data.get()); +#endif // #if LLDB_ENABLE_TERMIOS +} + llvm::Error Terminal::SetHardwareFlowControl(bool enabled) { llvm::Expected<Data> data = GetData(); if (!data) diff --git a/lldb/unittests/Host/posix/TerminalTest.cpp b/lldb/unittests/Host/posix/TerminalTest.cpp index 0313007f89e12..1cf7b9bc8f3b0 100644 --- a/lldb/unittests/Host/posix/TerminalTest.cpp +++ b/lldb/unittests/Host/posix/TerminalTest.cpp @@ -190,6 +190,36 @@ TEST_F(TerminalTest, SetParity) { #endif } +TEST_F(TerminalTest, SetParityCheck) { + struct termios terminfo; + + ASSERT_THAT_ERROR(m_term.SetParityCheck(Terminal::ParityCheck::No), + llvm::Succeeded()); + ASSERT_EQ(tcgetattr(m_fd, &terminfo), 0); + EXPECT_EQ(terminfo.c_iflag & (IGNPAR | PARMRK | INPCK), 0U); + + ASSERT_THAT_ERROR( + m_term.SetParityCheck(Terminal::ParityCheck::ReplaceWithNUL), + llvm::Succeeded()); + ASSERT_EQ(tcgetattr(m_fd, &terminfo), 0); + EXPECT_NE(terminfo.c_iflag & INPCK, 0U); + EXPECT_EQ(terminfo.c_iflag & (IGNPAR | PARMRK), 0U); + + ASSERT_THAT_ERROR(m_term.SetParityCheck(Terminal::ParityCheck::Ignore), + llvm::Succeeded()); + ASSERT_EQ(tcgetattr(m_fd, &terminfo), 0); + EXPECT_NE(terminfo.c_iflag & IGNPAR, 0U); + EXPECT_EQ(terminfo.c_iflag & PARMRK, 0U); + EXPECT_NE(terminfo.c_iflag & INPCK, 0U); + + ASSERT_THAT_ERROR(m_term.SetParityCheck(Terminal::ParityCheck::Mark), + llvm::Succeeded()); + ASSERT_EQ(tcgetattr(m_fd, &terminfo), 0); + EXPECT_EQ(terminfo.c_iflag & IGNPAR, 0U); + EXPECT_NE(terminfo.c_iflag & PARMRK, 0U); + EXPECT_NE(terminfo.c_iflag & INPCK, 0U); +} + TEST_F(TerminalTest, SetHardwareFlowControl) { #if defined(CRTSCTS) struct termios terminfo; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits