mgorny created this revision. mgorny added reviewers: labath, krytarowski, emaste, teemperor. mgorny requested review of this revision.
https://reviews.llvm.org/D112365 Files: 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
Index: lldb/unittests/Host/posix/TerminalTest.cpp =================================================================== --- lldb/unittests/Host/posix/TerminalTest.cpp +++ lldb/unittests/Host/posix/TerminalTest.cpp @@ -190,6 +190,36 @@ #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; Index: lldb/source/Host/common/Terminal.cpp =================================================================== --- lldb/source/Host/common/Terminal.cpp +++ lldb/source/Host/common/Terminal.cpp @@ -335,6 +335,26 @@ #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) Index: lldb/source/Host/common/File.cpp =================================================================== --- lldb/source/Host/common/File.cpp +++ lldb/source/Host/common/File.cpp @@ -794,6 +794,21 @@ 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 @@ 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())) Index: lldb/include/lldb/Host/Terminal.h =================================================================== --- lldb/include/lldb/Host/Terminal.h +++ lldb/include/lldb/Host/Terminal.h @@ -28,6 +28,18 @@ 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 @@ llvm::Error SetParity(Parity parity); + llvm::Error SetParityCheck(ParityCheck parity_check); + llvm::Error SetHardwareFlowControl(bool enabled); protected: Index: lldb/include/lldb/Host/File.h =================================================================== --- lldb/include/lldb/Host/File.h +++ lldb/include/lldb/Host/File.h @@ -439,6 +439,7 @@ 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; };
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits