From 6860aed85bf9cb91e11c3730c33388d38df98f71 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 15 Nov 2017 11:10:12 +0000 Subject: [PATCH] Fixes for OSX serial writing. --- Modem.cpp | 4 +++ SerialController.cpp | 68 ++++++++++++++++++++++++++++++++++++++++---- SerialController.h | 6 ++++ 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/Modem.cpp b/Modem.cpp index 7f87c33..9265879 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -906,6 +906,10 @@ bool CModem::readVersion() if (ret != 3) return false; +#if defined(__APPLE__) + m_serial.setNonblock(true); +#endif + for (unsigned int count = 0U; count < MAX_RESPONSES; count++) { CThread::sleep(10U); RESP_TYPE_MMDVM resp = getResponse(); diff --git a/SerialController.cpp b/SerialController.cpp index 67310c8..7856c24 100644 --- a/SerialController.cpp +++ b/SerialController.cpp @@ -237,8 +237,11 @@ CSerialController::~CSerialController() bool CSerialController::open() { assert(m_fd == -1); - +#if defined(__APPLE__) + m_fd = ::open(m_device.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); /*open in block mode under OSX*/ +#else m_fd = ::open(m_device.c_str(), O_RDWR | O_NOCTTY | O_NDELAY, 0); +#endif if (m_fd < 0) { LogError("Cannot open device - %s", m_device.c_str()); return false; @@ -257,6 +260,23 @@ bool CSerialController::open() return false; } + #if defined(__APPLE__) + termios.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */ + termios.c_cflag &= ~CSIZE; + termios.c_cflag |= CS8; /* 8-bit characters */ + termios.c_cflag &= ~PARENB; /* no parity bit */ + termios.c_cflag &= ~CSTOPB; /* only need 1 stop bit */ + termios.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */ + + /* setup for non-canonical mode */ + termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); + termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + termios.c_oflag &= ~OPOST; + + /* fetch bytes as they become available */ + termios.c_cc[VMIN] = 1; + termios.c_cc[VTIME] = 1; +#else termios.c_lflag &= ~(ECHO | ECHOE | ICANON | IEXTEN | ISIG); termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF | IXANY); termios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS); @@ -264,6 +284,7 @@ bool CSerialController::open() termios.c_oflag &= ~(OPOST); termios.c_cc[VMIN] = 0; termios.c_cc[VTIME] = 10; +#endif switch (m_speed) { case SERIAL_1200: @@ -327,9 +348,27 @@ bool CSerialController::open() } } +#if defined(__APPLE__) + setNonblock(false); +#endif + return true; } +#if defined(__APPLE__) +int CSerialController::setNonblock(bool nonblock) +{ + int flag = ::fcntl(m_fd, F_GETFD, 0); + + if (nonblock) + flag |= O_NONBLOCK; + else + flag &= ~O_NONBLOCK; + + return ::fcntl(m_fd, F_SETFL, flag); +} +#endif + int CSerialController::read(unsigned char* buffer, unsigned int length) { assert(buffer != NULL); @@ -344,13 +383,11 @@ int CSerialController::read(unsigned char* buffer, unsigned int length) fd_set fds; FD_ZERO(&fds); FD_SET(m_fd, &fds); - int n; if (offset == 0U) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 0; - n = ::select(m_fd + 1, &fds, NULL, NULL, &tv); if (n == 0) return 0; @@ -380,6 +417,26 @@ int CSerialController::read(unsigned char* buffer, unsigned int length) return length; } +bool CSerialController::canWrite(){ +#if defined(__APPLE__) + fd_set wset; + FD_ZERO(&wset); + FD_SET(m_fd, &wset); + + struct timeval timeo; + timeo.tv_sec = 0; + timeo.tv_usec = 0; + + int rc = select(m_fd + 1, NULL, &wset, NULL, &timeo); + if (rc >0 && FD_ISSET(m_fd, &wset)) + return true; + + return false; +#else + return true; +#endif +} + int CSerialController::write(const unsigned char* buffer, unsigned int length) { assert(buffer != NULL); @@ -389,9 +446,10 @@ int CSerialController::write(const unsigned char* buffer, unsigned int length) return 0; unsigned int ptr = 0U; - while (ptr < length) { - ssize_t n = ::write(m_fd, buffer + ptr, length - ptr); + ssize_t n = 0U; + if (canWrite()) + n = ::write(m_fd, buffer + ptr, length - ptr); if (n < 0) { if (errno != EAGAIN) { LogError("Error returned from write(), errno=%d", errno); diff --git a/SerialController.h b/SerialController.h index edb8e2b..63bd8be 100644 --- a/SerialController.h +++ b/SerialController.h @@ -53,6 +53,10 @@ public: virtual void close(); +#if defined(__APPLE__) + virtual int setNonblock(bool nonblock); +#endif + private: std::string m_device; SERIAL_SPEED m_speed; @@ -65,6 +69,8 @@ private: #if defined(_WIN32) || defined(_WIN64) int readNonblock(unsigned char* buffer, unsigned int length); +#else + bool canWrite(); #endif };