#ifndef __DRIVER_H_ #define __DRIVER_H_ #ifdef __cplusplus #include #include #include #include #include #include #include "icsneo/api/eventmanager.h" #include "icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h" #include "icsneo/core/ringbuffer.h" #include "icsneo/device/founddevice.h" namespace icsneo { typedef std::function&)> driver_finder_t; #define ICSNEO_DRIVER_RINGBUFFER_SIZE (512 * 1024) class Driver { public: Driver(const device_eventhandler_t& handler) : report(handler) {} virtual ~Driver() {} virtual bool open() = 0; virtual bool isOpen() = 0; virtual void modeChangeIncoming() {} virtual void awaitModeChangeComplete() {} virtual bool close() = 0; virtual driver_finder_t getFinder() = 0; inline bool isDisconnected() const { return disconnected; }; inline bool isClosing() const { return closing; } bool waitForRx(size_t limit, std::chrono::milliseconds timeout); bool waitForRx(std::function predicate, std::chrono::milliseconds timeout); bool readWait(std::vector& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 1); bool write(const std::vector& bytes); virtual bool isEthernet() const { return false; } bool readAvailable() { return readBuffer.size() > 0; } RingBuffer& getReadBuffer() { return readBuffer; } virtual bool enableCommunication(bool /* enable */, bool& sendMsg) { sendMsg = true; return true; } device_eventhandler_t report; size_t writeQueueSize = 50; bool writeBlocks = true; // Otherwise it just fails when the queue is full protected: class WriteOperation { public: WriteOperation() {} WriteOperation(const std::vector& b) : bytes(b) {} std::vector bytes; }; enum IOTaskState { LAUNCH, WAIT }; inline void setIsClosing(bool isClosing) { closing = isClosing; } inline void setIsDisconnected(bool isDisconnected) { disconnected = isDisconnected; } // Overridable in case the driver doesn't want to use writeTask and writeQueue virtual bool writeQueueFull() { return writeQueue.size_approx() > writeQueueSize; } virtual bool writeQueueAlmostFull() { return writeQueue.size_approx() > (writeQueueSize * 3 / 4); } virtual bool writeInternal(const std::vector& b) { return writeQueue.enqueue(WriteOperation(b)); } bool pushRx(const uint8_t* buf, size_t numReceived); void clearBuffers(); moodycamel::BlockingConcurrentQueue writeQueue; private: RingBuffer readBuffer = RingBuffer(ICSNEO_DRIVER_RINGBUFFER_SIZE); std::condition_variable rxWaitCv; std::mutex rxWaitMutex; std::atomic closing{false}; std::atomic disconnected{false}; }; } #endif // __cplusplus #endif