From bd40512b9484de5d7c10bb156ca613ffe32acf94 Mon Sep 17 00:00:00 2001 From: nickchan2 Date: Tue, 26 Mar 2024 18:00:55 -0400 Subject: [PATCH] vserial tweaks --- vserial/examples/vserial_print.cc | 53 ++++++++++++++------------ vserial/vserial.cc | 63 +++++++++++++++++-------------- vserial/vserial.h | 43 ++++++++++----------- 3 files changed, 85 insertions(+), 74 deletions(-) diff --git a/vserial/examples/vserial_print.cc b/vserial/examples/vserial_print.cc index 2392d04..e779f96 100644 --- a/vserial/examples/vserial_print.cc +++ b/vserial/examples/vserial_print.cc @@ -4,30 +4,31 @@ */ #include "../vserial.h" -#include -#include -#include + #include +#include +#include #include - +#include /** * @brief A program that shows how the creat_psudeo_serial() function can be used. * To compile, run g++ -std=c++20 vserial.cc ./examples/vserial_print.cc * */ -int main(){ - std::variant pseudo_terminal_return = agi::vserial::create_pseudo_serial(); - if(std::holds_alternative(pseudo_terminal_return)){ - agi::vserial::Res pseudo_terminal = std::get(pseudo_terminal_return); - std::cout<<"The serial port can be found at "<(pt_return)) { + auto const pt_info = std::get(pt_return); + std::cout << "The serial port can be found at " << pt_info.file_path << std::endl; char buffer[256]; while (true) { - ssize_t bytesRead = read(pseudo_terminal.fd, buffer, sizeof(buffer)); - if (bytesRead > 0) { + ssize_t const bytes_read = read(pt_info.fd, buffer, sizeof(buffer)); + if (bytes_read > 0) { // Data received, do something with it - std::cout<(pseudo_terminal_return); - if(pseudo_terminal_error.open_pt != 0){ - std::cout<<"Error opening /dev/ptmx"<(pt_return); + switch (pt_error.sys_call) { + case agi::vserial::Error::SysCall::OPEN: + std::cout << "Error opening /dev/ptmx" << std::endl; + break; + case agi::vserial::Error::SysCall::GRANTPT: + std::cout << "Error calling grantpt" << std::endl; + break; + case agi::vserial::Error::SysCall::UNLOCKPT: + std::cout << "Error calling unlockpt" << std::endl; + break; + case agi::vserial::Error::SysCall::PTSNAME: + std::cout << "Error calling ptsname" << std::endl; } } return 0; diff --git a/vserial/vserial.cc b/vserial/vserial.cc index 31f3805..40b4e9c 100644 --- a/vserial/vserial.cc +++ b/vserial/vserial.cc @@ -5,48 +5,53 @@ #include "vserial.h" - - -std::variant agi::vserial::create_pseudo_serial(){ - agi::vserial::Res return_value; - - int pt_fd = open("/dev/ptmx", O_RDWR | O_NOCTTY); - if (pt_fd < 0) { - agi::vserial::Error_Res error_return_value; - error_return_value.open_pt = pt_fd; - return error_return_value; +#include +#include +#include +#include + +std::variant agi::vserial::create_pseudo_serial() +{ + int const pt_fd = open("/dev/ptmx", O_RDWR | O_NOCTTY); // NOLINT(*-signed-bitwise) + if (pt_fd < 0) { + return agi::vserial::Error{ + .sys_call = agi::vserial::Error::SysCall::OPEN, + .errno_val = errno + }; } // Grant access to the slave pseudo-terminal - if (grantpt(pt_fd) == -1) { + if (grantpt(pt_fd) < 0) { close(pt_fd); - agi::vserial::Error_Res error_return_value; - error_return_value.grantpt = -1; - return return_value; + return agi::vserial::Error{ + .sys_call = agi::vserial::Error::SysCall::GRANTPT, + .errno_val = errno + }; } // Unlock the pseudo-terminal - if (unlockpt(pt_fd) == -1) { + if (unlockpt(pt_fd) < 0) { close(pt_fd); - agi::vserial::Error_Res error_return_value; - error_return_value.unlockpt = -1; - return return_value; + return agi::vserial::Error{ + .sys_call = agi::vserial::Error::SysCall::UNLOCKPT, + .errno_val = errno + }; } // Get the name of the slave pseudo-terminal - const char* pts_name = ptsname(pt_fd); + constexpr int MAX_PTSNAME_LEN = 100; + std::array pts_name{}; - // Check if ptsname returned a valid string - if (pts_name == nullptr) { - // Return empty values if ptsname failed + if (ptsname_r(pt_fd, pts_name.data(), pts_name.size()) < 0) { close(pt_fd); - agi::vserial::Error_Res error_return_value; - error_return_value.ptsname = true; - return error_return_value; + return agi::vserial::Error{ + .sys_call = agi::vserial::Error::SysCall::PTSNAME, + .errno_val = errno + }; } - // Convert the C-style string to a C++ std::string - return_value.file_path = std::string(pts_name); - return_value.fd = pt_fd; - return return_value; + return agi::vserial::PtInfo{ + .file_path = pts_name.data(), + .fd = pt_fd + }; } diff --git a/vserial/vserial.h b/vserial/vserial.h index 319f837..08eacc7 100644 --- a/vserial/vserial.h +++ b/vserial/vserial.h @@ -4,33 +4,34 @@ */ #pragma once -#include -#include -#include + #include #include namespace agi::vserial { - /** - * @brief A function to open a pseudo terminal. - * - * @return Struct containing the fd and the filePath - */ - - struct Res { - std::string file_path; - int fd; - }; - - - struct Error_Res { - int open_pt = 0; - int grantpt = 0; - int unlockpt = 0; - bool ptsname = false; +/** + * @brief A function to open a pseudo terminal. + * + * @return Struct containing the fd and the file path + */ + +struct PtInfo { + std::string file_path; + int fd; +}; + +struct Error { + enum class SysCall { + OPEN, + GRANTPT, + UNLOCKPT, + PTSNAME }; + SysCall sys_call; + int errno_val; +}; +std::variant create_pseudo_serial(); - std::variant create_pseudo_serial(); } // namespace agi::vserial