#include "icsneo/communication/driver.h" //#define ICSNEO_DRIVER_DEBUG_PRINTS #ifdef ICSNEO_DRIVER_DEBUG_PRINTS #include #include #endif using namespace icsneo; bool Driver::pushRx(const uint8_t* buf, size_t numReceived) { bool ret = readBuffer.write(buf, numReceived); rxWaitCv.notify_all(); return ret; } void Driver::clearBuffers() { WriteOperation flushop; readBuffer.clear(); rxWaitCv.notify_all(); while (writeQueue.try_dequeue(flushop)) {} } bool Driver::waitForRx(size_t limit, std::chrono::milliseconds timeout) { return waitForRx([limit, this]() { return readBuffer.size() >= limit; }, timeout); } bool Driver::waitForRx(std::function predicate, std::chrono::milliseconds timeout) { std::unique_lock lk(rxWaitMutex); return rxWaitCv.wait_for(lk, timeout, predicate); } bool Driver::readWait(std::vector& bytes, std::chrono::milliseconds timeout, size_t limit) { // wait until we have enough data, or the timeout occurs waitForRx(limit, timeout); size_t actuallyRead = readBuffer.size(); bytes.resize(actuallyRead); readBuffer.read(bytes.data(), 0, actuallyRead); readBuffer.pop(actuallyRead); bytes.resize(actuallyRead); #ifdef ICSNEO_DRIVER_DEBUG_PRINTS if(actuallyRead > 0) { std::cout << "Read data: (" << actuallyRead << ')' << std::hex << std::endl; for(int i = 0; i < actuallyRead; i += 16) { for(int j = 0; j < std::min(actuallyRead - i, 16); j++) std::cout << std::setw(2) << std::setfill('0') << uint32_t(bytes[i+j]) << ' '; std::cout << std::endl; } std::cout << std::dec << std::endl; } #endif return actuallyRead > 0; } bool Driver::write(const std::vector& bytes) { if(!isOpen()) { report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error); return false; } if(writeBlocks) { if(writeQueueFull()) { while(writeQueueAlmostFull() && !isDisconnected() && !isClosing()) // Wait until we have some decent amount of space std::this_thread::sleep_for(std::chrono::milliseconds(10)); if(isDisconnected() || isClosing()) { return false; } } } else { if(writeQueueFull()) { report(APIEvent::Type::TransmitBufferFull, APIEvent::Severity::Error); return false; } } const bool ret = writeInternal(bytes); if(!ret) report(APIEvent::Type::Unknown, APIEvent::Severity::Error); return ret; }