diff --git a/linux/uart/UartComIF.cpp b/linux/uart/UartComIF.cpp index 95ff46b..62c1a81 100644 --- a/linux/uart/UartComIF.cpp +++ b/linux/uart/UartComIF.cpp @@ -14,7 +14,7 @@ UartComIF::UartComIF(object_id_t objectId): SystemObject(objectId){ UartComIF::~UartComIF() {} -ReturnValue_t UartComIF::initializeInterface(CookieIF * cookie) { +ReturnValue_t UartComIF::initializeInterface(CookieIF* cookie) { std::string deviceFile; UartDeviceMapIter uartDeviceMapIter; @@ -305,7 +305,6 @@ ReturnValue_t UartComIF::requestReceiveMessage(CookieIF *cookie, size_t requestL int fd = 0; std::string deviceFile; UartDeviceMapIter uartDeviceMapIter; - uint8_t* bufferPtr; if(requestLen == 0) { return RETURN_OK; @@ -326,57 +325,49 @@ ReturnValue_t UartComIF::requestReceiveMessage(CookieIF *cookie, size_t requestL return RETURN_FAILED; } - fd = uartDeviceMapIter->second.fileDescriptor; - bufferPtr = uartDeviceMapIter->second.replyBuffer.data(); if (uartMode == UartModes::CANONICAL) { - uint8_t maxReadCycles = uartCookie->getReadCycles(); - uint8_t currentReadCycles = 0; - int bytesRead = 0; - size_t currentBytesRead = 0; - size_t maxReplySize = uartCookie->getMaxReplyLen(); - do { - size_t allowedReadSize = 0; - if(currentBytesRead >= maxReplySize) { - // Overflow risk. Emit warning, trigger event and break. If this happens, - // the reception buffer is not large enough or data is not polled often enough. - // TODO: Emit event - // TODO: Return error? -#if OBSW_VERBOSE_LEVEL >= 1 - sif::warning << "UartComIF::requestReceiveMessage: Next read would cause overflow!" - << std::endl; -#endif - break; - } - else { - allowedReadSize = maxReplySize - currentBytesRead; - } - - bytesRead = read(fd, bufferPtr, allowedReadSize); - if (bytesRead < 0) { - return RETURN_FAILED; - } - else if (bytesRead != static_cast(requestLen)) { - sif::debug << "UartComIF::requestReceiveMessage: Only read " << bytesRead << - " of " << requestLen << " bytes" << std::endl; - return RETURN_FAILED; - } - else if(bytesRead > 0) { - uartDeviceMapIter->second.replyLen += bytesRead; - bufferPtr += bytesRead; - currentBytesRead += bytesRead; - } - currentReadCycles++; - } while(bytesRead > 0 and currentReadCycles < maxReadCycles); + return handleCanonicalRead(*uartCookie, uartDeviceMapIter, requestLen); } else if (uartMode == UartModes::NON_CANONICAL) { - // Size check to prevent buffer overflow - if(requestLen > uartCookie->getMaxReplyLen()) { - // TODO: Emit warning - // TODO: Emit event - // TODO: Better returnvalue - return HasReturnvaluesIF::RETURN_FAILED; + return handleNoncanonicalRead(*uartCookie, uartDeviceMapIter, requestLen); + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t UartComIF::handleCanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter, + size_t requestLen) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + uint8_t maxReadCycles = uartCookie.getReadCycles(); + uint8_t currentReadCycles = 0; + int bytesRead = 0; + size_t currentBytesRead = 0; + size_t maxReplySize = uartCookie.getMaxReplyLen(); + int fd = iter->second.fileDescriptor; + auto bufferPtr = iter->second.replyBuffer.data(); + do { + size_t allowedReadSize = 0; + if(currentBytesRead >= maxReplySize) { + // Overflow risk. Emit warning, trigger event and break. If this happens, + // the reception buffer is not large enough or data is not polled often enough. +#if OBSW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "UartComIF::requestReceiveMessage: Next read would cause overflow!" + << std::endl; +#else + sif::printWarning("UartComIF::requestReceiveMessage: " + "Next read would cause overflow!"); +#endif +#endif + result = UART_RX_BUFFER_TOO_SMALL; + break; } - int bytesRead = read(fd, bufferPtr, requestLen); + else { + allowedReadSize = maxReplySize - currentBytesRead; + } + + bytesRead = read(fd, bufferPtr, allowedReadSize); if (bytesRead < 0) { return RETURN_FAILED; } @@ -385,11 +376,46 @@ ReturnValue_t UartComIF::requestReceiveMessage(CookieIF *cookie, size_t requestL " of " << requestLen << " bytes" << std::endl; return RETURN_FAILED; } - else { - uartDeviceMapIter->second.replyLen = bytesRead; + else if(bytesRead > 0) { + iter->second.replyLen += bytesRead; + bufferPtr += bytesRead; + currentBytesRead += bytesRead; } + currentReadCycles++; + } while(bytesRead > 0 and currentReadCycles < maxReadCycles); + return result; +} + +ReturnValue_t UartComIF::handleNoncanonicalRead(UartCookie &uartCookie, UartDeviceMapIter &iter, + size_t requestLen) { + int fd = iter->second.fileDescriptor; + auto bufferPtr = iter->second.replyBuffer.data(); + // Size check to prevent buffer overflow + if(requestLen > uartCookie.getMaxReplyLen()) { +#if OBSW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "UartComIF::requestReceiveMessage: Next read would cause overflow!" + << std::endl; +#else + sif::printWarning("UartComIF::requestReceiveMessage: " + "Next read would cause overflow!"); +#endif +#endif + return UART_RX_BUFFER_TOO_SMALL; } - return RETURN_OK; + int bytesRead = read(fd, bufferPtr, requestLen); + if (bytesRead < 0) { + return RETURN_FAILED; + } + else if (bytesRead != static_cast(requestLen)) { + sif::debug << "UartComIF::requestReceiveMessage: Only read " << bytesRead << + " of " << requestLen << " bytes" << std::endl; + return RETURN_FAILED; + } + else { + iter->second.replyLen = bytesRead; + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t UartComIF::readReceivedMessage(CookieIF *cookie, diff --git a/linux/uart/UartComIF.h b/linux/uart/UartComIF.h index b4fad48..e364c48 100644 --- a/linux/uart/UartComIF.h +++ b/linux/uart/UartComIF.h @@ -26,6 +26,10 @@ public: HasReturnvaluesIF::makeReturnCode(uartRetvalId, 1); static constexpr ReturnValue_t UART_READ_SIZE_MISSMATCH = HasReturnvaluesIF::makeReturnCode(uartRetvalId, 2); + static constexpr ReturnValue_t UART_RX_BUFFER_TOO_SMALL = + HasReturnvaluesIF::makeReturnCode(uartRetvalId, 3); + + static constexpr uint8_t uartSubsystemId = SUBSYSTEM_ID::HAL_UART; UartComIF(object_id_t objectId); @@ -99,6 +103,11 @@ private: void setUartMode(struct termios* options, UartCookie& uartCookie); + ReturnValue_t handleCanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter, + size_t requestLen); + ReturnValue_t handleNoncanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter, + size_t requestLen); + }; #endif /* BSP_Q7S_COMIF_UARTCOMIF_H_ */ diff --git a/linux/uart/UartCookie.cpp b/linux/uart/UartCookie.cpp index f06790b..8e4f7f9 100644 --- a/linux/uart/UartCookie.cpp +++ b/linux/uart/UartCookie.cpp @@ -2,9 +2,10 @@ #include -UartCookie::UartCookie(std::string deviceFile, UartModes uartMode, uint32_t baudrate, - size_t maxReplyLen) : - deviceFile(deviceFile), uartMode(uartMode), baudrate(baudrate), maxReplyLen(maxReplyLen) { +UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode, + uint32_t baudrate, size_t maxReplyLen): + handlerId(handlerId), deviceFile(deviceFile), uartMode(uartMode), baudrate(baudrate), + maxReplyLen(maxReplyLen) { } UartCookie::~UartCookie() {} @@ -82,3 +83,7 @@ uint8_t UartCookie::getReadCycles() const { bool UartCookie::getInputShouldBeFlushed() { return this->flushInput; } + +object_id_t UartCookie::getHandlerId() const { + return this->handlerId; +} diff --git a/linux/uart/UartCookie.h b/linux/uart/UartCookie.h index a26a5de..b0d2ade 100644 --- a/linux/uart/UartCookie.h +++ b/linux/uart/UartCookie.h @@ -45,7 +45,8 @@ public: * 8 databits (number of bits transfered with one uart frame) * One stop bit */ - UartCookie(std::string deviceFile, UartModes uartMode, uint32_t baudrate, size_t maxReplyLen); + UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode, + uint32_t baudrate, size_t maxReplyLen); virtual ~UartCookie(); @@ -56,6 +57,8 @@ public: uint8_t getBitsPerWord() const; StopBits getStopBits() const; UartModes getUartMode() const; + object_id_t getHandlerId() const; + /** * The UART ComIF will only perform a specified number of read cycles for the canonical mode. * The user can specify how many of those read cycles are performed for one device handler @@ -92,6 +95,7 @@ public: private: + const object_id_t handlerId; std::string deviceFile; const UartModes uartMode; bool flushInput = false;