diff --git a/src/lib/ebus/port.cpp b/src/lib/ebus/port.cpp index e338a220..c9adc96c 100644 --- a/src/lib/ebus/port.cpp +++ b/src/lib/ebus/port.cpp @@ -69,7 +69,7 @@ ssize_t Device::sendBytes(const unsigned char* buffer, size_t nbytes) return write(m_fd, buffer, nbytes); } -ssize_t Device::recvBytes(const long timeout, size_t maxCount) +ssize_t Device::recvBytes(const long timeout, size_t maxCount, unsigned char* buffer) { if (isValid() == false) return RESULT_ERR_DEVICE; @@ -102,16 +102,26 @@ ssize_t Device::recvBytes(const long timeout, size_t maxCount) ret = pselect(m_fd + 1, &readfds, NULL, NULL, &tdiff, NULL); #endif #endif - if (ret == -1) return RESULT_ERR_DEVICE; if (ret == 0) return RESULT_ERR_TIMEOUT; } + if (buffer != NULL) { + // read bytes from device directly into provided buffer + ssize_t nbytes = read(m_fd, buffer, maxCount); + if (nbytes == 0) + return RESULT_ERR_EOF; + + return nbytes; + } + if (maxCount > sizeof(m_buffer)) maxCount = sizeof(m_buffer); - // read bytes from device + // read bytes from device into temporary buffer ssize_t nbytes = read(m_fd, m_buffer, maxCount); + if (nbytes == 0) + return RESULT_ERR_EOF; for (int i = 0; i < nbytes; i++) m_recvBuffer.push(m_buffer[i]); @@ -154,10 +164,11 @@ result_t DeviceSerial::openDevice(const string deviceName, const bool noDeviceCh memset(&newSettings, '\0', sizeof(newSettings)); newSettings.c_cflag |= (B2400 | CS8 | CLOCAL | CREAD); - newSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); - newSettings.c_iflag |= IGNPAR; + newSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // non-canonical mode + newSettings.c_iflag |= IGNPAR; // ignore parity errors newSettings.c_oflag &= ~OPOST; + // non-canonical mode: read() blocks until at least one byte is available newSettings.c_cc[VMIN] = 1; newSettings.c_cc[VTIME] = 0; @@ -251,7 +262,8 @@ void DeviceNetwork::closeDevice() } -Port::Port(const string deviceName, const bool noDeviceCheck, const bool logRaw, void (*logRawFunc)(const unsigned char byte), +Port::Port(const string deviceName, const bool noDeviceCheck, + const bool logRaw, void (*logRawFunc)(const unsigned char byte, bool received), const bool dumpRaw, const char* dumpRawFile, const long dumpRawMaxSize) : m_deviceName(deviceName), m_noDeviceCheck(noDeviceCheck), m_logRaw(logRaw), m_logRawFunc(logRawFunc), @@ -275,7 +287,7 @@ unsigned char Port::byte() unsigned char byte = m_device->getByte(); if (m_logRaw == true && m_logRawFunc != NULL) - (*m_logRawFunc)(byte); + (*m_logRawFunc)(byte, true); if (m_dumpRaw == true && m_dumpRawStream.is_open() == true) { m_dumpRawStream.write((char*)&byte, 1); diff --git a/src/lib/ebus/port.h b/src/lib/ebus/port.h index 124dd147..a81fdb28 100644 --- a/src/lib/ebus/port.h +++ b/src/lib/ebus/port.h @@ -92,9 +92,10 @@ public: * @brief recvBytes read bytes from opened file descriptor. * @param timeout time for new input data [usec]. * @param maxCount max size of receive buffer. + * @param buffer optional direct buffer to write to (instead of queuing the data). * @return number of read bytes or -1 if an error has occured. */ - ssize_t recvBytes(const long timeout, size_t maxCount); + ssize_t recvBytes(const long timeout, size_t maxCount, unsigned char* buffer=NULL); /** * @brief fetch first byte from receive buffer. @@ -208,7 +209,8 @@ public: * @param dumpRawFile the name of the file to dump raw data to. * @param dumpRawMaxSize the maximum size of @a m_dumpFile. */ - Port(const string deviceName, const bool noDeviceCheck, const bool logRaw, void (*logRawFunc)(const unsigned char byte), + Port(const string deviceName, const bool noDeviceCheck, + const bool logRaw, void (*logRawFunc)(const unsigned char byte, bool received), const bool dumpRaw, const char* dumpRawFile, const long dumpRawMaxSize); /** @@ -239,16 +241,27 @@ public: * @return number of written bytes or -1 if an error has occured. */ ssize_t send(const unsigned char* buffer, size_t nbytes = MAX_WRITE_SIZE) - { return m_device->sendBytes(buffer, nbytes); } + { + ssize_t ret = m_device->sendBytes(buffer, nbytes); + if (ret>0 && m_logRaw == true && m_logRawFunc != NULL) + (*m_logRawFunc)(buffer[0], false); + return ret; + } /** * @brief recv read bytes from opened file descriptor. - * @param timeout max time out for new input data [usec]. + * @param timeout max time out for new input data [usec], or 0 for infinite. * @param maxCount max size of receive buffer. - * @return number of read bytes or -1 if an error has occured. + * @param buffer optional direct buffer to write to (instead of queuing the data). + * @return number of read bytes (never 0) or a negative result_t code. */ - ssize_t recv(const long timeout, size_t maxCount = MAX_READ_SIZE) - { return m_device->recvBytes(timeout, maxCount); } + ssize_t recv(const long timeout, size_t maxCount = MAX_READ_SIZE, unsigned char* buffer=NULL) + { + ssize_t ret = m_device->recvBytes(timeout, maxCount, buffer); + if (buffer && ret>0 && m_logRaw == true && m_logRawFunc != NULL) + (*m_logRawFunc)(buffer[0], true); + return ret; + } /** * @brief fetch first byte from receive buffer. @@ -312,7 +325,7 @@ private: bool m_logRaw; /** a function to call for logging raw data, or NULL. */ - void (*m_logRawFunc)(const unsigned char byte); + void (*m_logRawFunc)(const unsigned char byte, bool received); /** whether dumping of raw data to a file is enabled. */ bool m_dumpRaw;