[Lldb-commits] [lldb] 21bb808 - [lldb] Support serial port parity checking

Michał Górny via lldb-commits lldb-commits at lists.llvm.org
Mon Oct 25 01:51:54 PDT 2021


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;


        


More information about the lldb-commits mailing list