From e70e474dceb2de7b73fa05277f1f48cb4b6bc16e Mon Sep 17 00:00:00 2001 From: John-Michael Baier Date: Sun, 29 Nov 2020 19:13:52 +0100 Subject: [PATCH] fix for cancelling arbitration --- src/lib/ebus/device.cpp | 43 +++++++++++++++++++++++++++++++---------- src/lib/ebus/device.h | 7 +++++++ 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/lib/ebus/device.cpp b/src/lib/ebus/device.cpp index 8f941858..db0dc091 100755 --- a/src/lib/ebus/device.cpp +++ b/src/lib/ebus/device.cpp @@ -192,11 +192,29 @@ result_t Device::send(symbol_t value) { #define ENHANCED_COMPLETE_WAIT_DURATION 3 +bool Device::cancelRunningArbitration(ArbitrationState* arbitrationState) { + if (m_enhancedProto && m_arbitrationMaster != SYN) { + *arbitrationState = as_error; + m_arbitrationMaster = SYN; + m_arbitrationCheck = false; + write(SYN, true); + return true; + } + if (m_enhancedProto || m_arbitrationMaster == SYN) { + return false; + } + *arbitrationState = as_error; + m_arbitrationMaster = SYN; + m_arbitrationCheck = false; + return true; +} + result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* arbitrationState) { if (m_arbitrationMaster!=SYN) { *arbitrationState = as_running; } if (!isValid()) { + cancelRunningArbitration(arbitrationState); return RESULT_ERR_DEVICE; } bool repeat = false; @@ -246,6 +264,7 @@ result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* a fprintf(stdout, "poll error %d\n", errno); #endif close(); + cancelRunningArbitration(arbitrationState); return RESULT_ERR_DEVICE; } if (ret == 0) { @@ -287,9 +306,7 @@ result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* a m_listener->notifyDeviceData(*value, true); } if (!wrote) { - *arbitrationState = as_error; - m_arbitrationMaster = SYN; - m_arbitrationCheck = false; + cancelRunningArbitration(arbitrationState); return RESULT_OK; } if (m_listener != nullptr) { @@ -302,13 +319,23 @@ result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* a result_t Device::startArbitration(symbol_t masterAddress) { if (m_arbitrationCheck) { - return RESULT_ERR_ARB_RUNNING; // should not occur + if (masterAddress != SYN) { + return RESULT_ERR_ARB_RUNNING; // should not occur + } + m_arbitrationCheck = false; + m_arbitrationMaster = SYN; + if (m_enhancedProto) { + // cancel running arbitration + if (!write(SYN, true)) { + return RESULT_ERR_SEND; + } + } + return RESULT_OK; } if (m_readOnly) { return RESULT_ERR_SEND; } m_arbitrationMaster = masterAddress; - m_arbitrationCheck = false; if (m_enhancedProto && masterAddress != SYN) { if (!write(masterAddress, true)) { m_arbitrationMaster = SYN; @@ -515,11 +542,7 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati string str = stream.str(); m_listener->notifyStatus(true, str.c_str()); } - if (*arbitrationState != as_none) { - *arbitrationState = as_error; - m_arbitrationMaster = SYN; - m_arbitrationCheck = false; - } + cancelRunningArbitration(arbitrationState); break; default: if (m_listener != nullptr) { diff --git a/src/lib/ebus/device.h b/src/lib/ebus/device.h index d698ad7b..270643ce 100755 --- a/src/lib/ebus/device.h +++ b/src/lib/ebus/device.h @@ -207,6 +207,13 @@ class Device { */ virtual void checkDevice() = 0; // abstract + /** + * Cancel a running arbitration. + * @param arbitrationState the reference in which @a as_error is stored when cancelled. + * @return true if it was cancelled, false if not. + */ + bool cancelRunningArbitration(ArbitrationState* arbitrationState); + /** * Write a single byte. * @param value the byte value to write.