allow initsend for enhanced as well, cleaner separation

This commit is contained in:
John
2023-10-14 16:23:04 +02:00
parent f2a845d462
commit 5e2509b60c
9 changed files with 179 additions and 115 deletions
+35 -10
View File
@@ -350,8 +350,32 @@ result_t BusHandler::readFromBus(Message* message, const string& inputStr, symbo
return ret;
}
void BusHandler::notifyProtocolStatus(bool signal) {
// ignored
void BusHandler::notifyProtocolStatus(ProtocolState state) {
if (state == ps_empty && m_pollInterval > 0) { // check for poll/scan
time_t now;
time(&now);
if (m_lastPoll == 0 || difftime(now, m_lastPoll) > m_pollInterval) {
Message* message = m_messages->getNextPoll();
if (message != nullptr) {
m_lastPoll = now;
if (difftime(now, message->getLastUpdateTime()) > m_pollInterval) {
// only poll this message if it was not updated already by other means within the interval
auto request = new PollRequest(message);
result_t ret = request->prepare(m_protocol->getOwnMasterAddress());
if (ret != RESULT_OK) {
logError(lf_bus, "prepare poll message: %s", getResultCode(ret));
delete request;
} else {
ret = m_protocol->addRequest(request, false);
if (ret != RESULT_OK) {
logError(lf_bus, "push poll message: %s", getResultCode(ret));
delete request;
}
}
}
}
}
}
}
result_t BusHandler::notifyProtocolAnswer(const MasterSymbolString& command, SlaveSymbolString* response) {
@@ -494,7 +518,7 @@ result_t BusHandler::prepareScan(symbol_t slave, bool full, const string& levels
if (scanMessage == nullptr) {
return RESULT_ERR_NOTFOUND;
}
if (m_protocol->getDevice()->isReadOnly()) {
if (m_protocol->isReadOnly()) {
return RESULT_OK;
}
deque<Message*> messages;
@@ -564,9 +588,8 @@ result_t BusHandler::startScan(bool full, const string& levels) {
}
m_scanResults.clear();
m_runningScans++;
m_protocol->addRequest(request, false);
// request is deleted by ProtocolHandler after finish
return RESULT_OK;
return m_protocol->addRequest(request, false);
}
void BusHandler::setScanResult(symbol_t dstAddress, size_t index, const string& str) {
@@ -704,7 +727,7 @@ void BusHandler::formatUpdateInfo(ostringstream* output) const {
}
*output << ",\"c\":" << m_protocol->getMasterCount()
<< ",\"m\":" << m_messages->size()
<< ",\"ro\":" << (m_protocol->getDevice()->isReadOnly() ? 1 : 0)
<< ",\"ro\":" << (m_protocol->isReadOnly() ? 1 : 0)
<< ",\"an\":" << (m_protocol->isAnswering() ? 1 : 0)
<< ",\"co\":" << (m_protocol->isAddressConflict(SYN) ? 1 : 0);
if (m_grabMessages) {
@@ -727,8 +750,7 @@ void BusHandler::formatUpdateInfo(ostringstream* output) const {
}
unsigned char address = 0;
for (int index = 0; index < 256; index++, address++) {
bool ownAddress = !m_protocol->getDevice()->isReadOnly()
&& (address == m_protocol->getOwnMasterAddress() || address == m_protocol->getOwnSlaveAddress());
bool ownAddress = !m_protocol->isOwnAddress(address);
if (!isValidAddress(address, false) || ((m_seenAddresses[address]&SEEN) == 0 && !ownAddress)) {
continue;
}
@@ -815,8 +837,11 @@ result_t BusHandler::scanAndWait(symbol_t dstAddress, bool loadScanConfig, bool
m_scanResults[dstAddress].resize(1);
}
m_runningScans++;
requestExecuted = m_protocol->addRequest(request, true);
result = requestExecuted ? request->m_result : RESULT_ERR_TIMEOUT;
result = m_protocol->addRequest(request, true);
requestExecuted = result == RESULT_OK;
if (requestExecuted) {
result = request->m_result;
}
delete request;
request = nullptr;
}
+1 -1
View File
@@ -410,7 +410,7 @@ class BusHandler : public ProtocolListener {
void setScanConfigLoaded(symbol_t address, const string& file);
// @copydoc
void notifyProtocolStatus(bool signal) override;
void notifyProtocolStatus(ProtocolState state) override;
// @copydoc
result_t notifyProtocolAnswer(const MasterSymbolString& master, SlaveSymbolString* slave) override;
+9 -9
View File
@@ -363,8 +363,7 @@ int main(int argc, char* argv[], char* envp[]) {
}
// open the device
Device *device = Device::create(s_opt.device, s_opt.extraLatency, !s_opt.noDeviceCheck, s_opt.readOnly,
s_opt.initialSend);
Device *device = Device::create(s_opt.device, s_opt.extraLatency, !s_opt.noDeviceCheck);
if (device == nullptr) {
logWrite(lf_main, ll_error, "unable to create device %s", s_opt.device); // force logging on exit
cleanup();
@@ -385,8 +384,14 @@ int main(int argc, char* argv[], char* envp[]) {
signal(SIGINT, signalHandler);
signal(SIGTERM, signalHandler);
// create the MainLoop
s_requestQueue = new Queue<Request*>();
s_mainLoop = new MainLoop(s_opt, device, s_messageMap, s_scanHelper, s_requestQueue);
BusHandler* busHandler = s_mainLoop->getBusHandler();
ProtocolHandler* protocol = busHandler->getProtocol();
ostringstream ostream;
device->formatInfo(&ostream, false, false, true);
protocol->formatInfo(&ostream, false, true);
string deviceInfoStr = ostream.str();
logNotice(lf_main, PACKAGE_STRING "." REVISION " started%s on device: %s",
s_opt.scanConfig ? s_opt.initialScan == ESC ? " with auto scan"
@@ -397,12 +402,7 @@ int main(int argc, char* argv[], char* envp[]) {
// load configuration files
s_scanHelper->loadConfigFiles(!s_opt.scanConfig);
s_requestQueue = new Queue<Request*>();
// create the MainLoop and start it
s_mainLoop = new MainLoop(s_opt, device, s_messageMap, s_scanHelper, s_requestQueue);
BusHandler* busHandler = s_mainLoop->getBusHandler();
ProtocolHandler* protocol = busHandler->getProtocol();
// start the MainLoop
if (s_opt.injectMessages) {
int scanAdrCount = 0;
bool scanAddresses[256] = {};
+5 -3
View File
@@ -152,6 +152,7 @@ MainLoop::MainLoop(const struct options& opt, Device *device, MessageMap* messag
}
// create BusHandler
ebus_protocol_config_t config = {
.readOnly = opt.readOnly,
.ownAddress = m_address,
.answer = opt.answer,
.busLostRetries = opt.acquireRetries,
@@ -160,6 +161,7 @@ MainLoop::MainLoop(const struct options& opt, Device *device, MessageMap* messag
.slaveRecvTimeout = opt.receiveTimeout,
.lockCount = opt.masterCount,
.generateSyn = opt.generateSyn,
.initialSend = opt.initialSend,
};
m_busHandler = new BusHandler(m_device, m_messages, scanHelper,
config, opt.pollInterval);
@@ -377,7 +379,7 @@ void MainLoop::run() {
<< ",\"a\":\"other\""
#endif
<< ",\"u\":" << (now-start);
m_device->formatInfo(&ostr, false, true, true);
m_protocol->formatInfoJson(&ostr);
if (m_reconnectCount) {
ostr << ",\"rc\":" << m_reconnectCount;
}
@@ -1935,7 +1937,7 @@ result_t MainLoop::executeInfo(const vector<string>& args, const string& user, o
*ostream << "update check: " << m_updateCheck << "\n";
}
*ostream << "device: ";
m_device->formatInfo(ostream, verbose);
m_protocol->formatInfo(ostream, verbose, false);
*ostream << "\n";
if (!user.empty()) {
*ostream << "user: " << user << "\n";
@@ -2226,7 +2228,7 @@ result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostri
<< ",\n \"maxsymbollatency\": " << m_protocol->getMaxSymbolLatency();
}
}
if (!m_device->isReadOnly()) {
if (!m_protocol->isReadOnly()) {
*ostream << ",\n \"qq\": " << static_cast<unsigned>(m_address);
}
*ostream << ",\n \"reconnects\": " << m_reconnectCount
+28 -39
View File
@@ -88,11 +88,11 @@ namespace ebusd {
#define DEBUG_RAW_TRAFFIC(format, args...)
#endif
Device::Device(const char* name, bool readOnly, bool initialSend)
: m_name(name), m_readOnly(readOnly), m_initialSend(initialSend), m_listener(nullptr) {
Device::Device(const char* name)
: m_name(name), m_listener(nullptr) {
}
Device* Device::create(const char* name, unsigned int extraLatency, bool checkDevice, bool readOnly, bool initialSend) {
Device* Device::create(const char* name, unsigned int extraLatency, bool checkDevice) {
bool highSpeed = strncmp(name, "ens:", 4) == 0;
bool enhanced = highSpeed || strncmp(name, "enh:", 4) == 0;
if (enhanced) {
@@ -128,23 +128,17 @@ Device* Device::create(const char* name, unsigned int extraLatency, bool checkDe
*portpos = 0;
char* hostOrIp = strdup(addrpos);
free(in);
return new NetworkDevice(name, hostOrIp, port, extraLatency, readOnly, initialSend, udp, enhanced);
return new NetworkDevice(name, hostOrIp, port, extraLatency, udp, enhanced);
}
// support enh:/dev/<device>, ens:/dev/<device>, and /dev/<device>
return new SerialDevice(name, checkDevice, extraLatency, readOnly, initialSend, enhanced, highSpeed);
}
result_t Device::afterOpen() {
if (m_initialSend && !send(ESC)) {
return RESULT_ERR_SEND;
}
return RESULT_OK;
return new SerialDevice(name, checkDevice, extraLatency, enhanced, highSpeed);
}
FileDevice::FileDevice(const char* name, bool checkDevice, unsigned int latency, bool readOnly, bool initialSend,
FileDevice::FileDevice(const char* name, bool checkDevice, unsigned int latency,
bool enhancedProto)
: Device(name, readOnly, initialSend),
: Device(name),
m_checkDevice(checkDevice),
m_latency(HOST_LATENCY_MS+(enhancedProto?ENHANCED_LATENCY_MS:0)+latency),
m_enhancedProto(enhancedProto), m_fd(-1), m_resetRequested(false),
@@ -164,33 +158,24 @@ FileDevice::~FileDevice() {
}
}
void FileDevice::formatInfo(ostringstream* ostream, bool verbose, bool asJson, bool noWait) {
if (asJson) {
if (m_enhancedProto) {
string ver = getEnhancedVersion();
if (!ver.empty()) {
*ostream << ",\"dv\":\"" << ver << "\"";
}
void FileDevice::formatInfo(ostringstream* ostream, bool verbose, bool prefix) {
if (prefix) {
*ostream << m_name;
string info = getEnhancedProtoInfo();
if (!info.empty()) {
*ostream << ", " << info;
}
return;
}
*ostream << m_name;
string info = getEnhancedProtoInfo();
if (!info.empty()) {
*ostream << ", " << info;
}
if (isReadOnly()) {
*ostream << ", readonly";
}
if (noWait) {
return;
}
if (!isValid()) {
*ostream << ", invalid";
}
if (!m_enhancedProto) {
return;
}
bool infoAdded = false;
if (verbose) {
info = getEnhancedInfos();
string info = getEnhancedInfos();
if (!info.empty()) {
*ostream << ", " << info;
infoAdded = true;
@@ -204,6 +189,15 @@ void FileDevice::formatInfo(ostringstream* ostream, bool verbose, bool asJson, b
}
}
void FileDevice::formatInfoJson(ostringstream* ostream) {
if (m_enhancedProto) {
string ver = getEnhancedVersion();
if (!ver.empty()) {
*ostream << ",\"dv\":\"" << ver << "\"";
}
}
}
result_t FileDevice::open() {
close();
return m_bufSize == 0 ? RESULT_ERR_DEVICE : RESULT_OK;
@@ -220,8 +214,6 @@ result_t FileDevice::afterOpen() {
m_listener->notifyStatus(false, "resetting");
}
m_resetRequested = true;
} else if (m_initialSend && !write(ESC)) {
return RESULT_ERR_SEND;
}
return RESULT_OK;
}
@@ -339,7 +331,7 @@ result_t FileDevice::send(symbol_t value) {
if (!isValid()) {
return RESULT_ERR_DEVICE;
}
if (m_readOnly || !write(value)) {
if (!write(value)) {
return RESULT_ERR_SEND;
}
if (m_listener != nullptr) {
@@ -496,9 +488,6 @@ result_t FileDevice::startArbitration(symbol_t masterAddress) {
}
return RESULT_OK;
}
if (m_readOnly) {
return RESULT_ERR_SEND;
}
m_arbitrationMaster = masterAddress;
if (m_enhancedProto && masterAddress != SYN) {
if (!write(masterAddress, true)) {
+23 -37
View File
@@ -99,10 +99,8 @@ class Device {
/**
* Construct a new instance.
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
* @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open().
*/
Device(const char* name, bool readOnly, bool initialSend);
explicit Device(const char* name);
public:
/**
@@ -115,13 +113,10 @@ class Device {
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
* @param extraLatency the extra bus transfer latency in milliseconds.
* @param checkDevice whether to regularly check the device availability (only for serial devices).
* @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open().
* @return the new @a Device, or nullptr on error.
* Note: the caller needs to free the created instance.
*/
static Device* create(const char* name, unsigned int extraLatency = 0, bool checkDevice = true,
bool readOnly = false, bool initialSend = false);
static Device* create(const char* name, unsigned int extraLatency = 0, bool checkDevice = true);
/**
* Get the device name.
@@ -129,12 +124,6 @@ class Device {
*/
const char* getName() const { return m_name; }
/**
* Return whether to allow read access to the device only.
* @return whether to allow read access to the device only.
*/
bool isReadOnly() const { return m_readOnly; }
/**
* Set the @a DeviceListener.
* @param listener the @a DeviceListener.
@@ -142,13 +131,18 @@ class Device {
void setListener(DeviceListener* listener) { m_listener = listener; }
/**
* Format device infos in plain text or JSON format.
* Format device infos in plain text.
* @param output the @a ostringstream to append the infos to.
* @param verbose whether to add verbose infos.
* @param asJson whether to format as JSON rather than plain text.
* @param noWait true to not wait for any response asynchronously and return immediately.
* @param prefix true for the synchronously retrievable prefix, false for the potentially asynchronous suffix.
*/
virtual void formatInfo(ostringstream* output, bool verbose, bool asJson = false, bool noWait = false) = 0;
virtual void formatInfo(ostringstream* output, bool verbose, bool prefix) = 0;
/**
* Format device infos in JSON format.
* @param output the @a ostringstream to append the infos to.
*/
virtual void formatInfoJson(ostringstream* output) = 0;
/**
* Open the file descriptor.
@@ -160,7 +154,7 @@ class Device {
* Has to be called by subclasses upon successful opening the device as last action in open().
* @return the @a result_t code.
*/
virtual result_t afterOpen();
virtual result_t afterOpen() { return RESULT_OK; }
/**
* Close the file descriptor if opened.
@@ -213,12 +207,6 @@ class Device {
/** the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network). */
const char* m_name;
/** whether to allow read access to the device only. */
const bool m_readOnly;
/** whether to send an initial @a ESC symbol in @a open(). */
const bool m_initialSend;
/** the @a DeviceListener, or nullptr. */
DeviceListener* m_listener;
};
@@ -234,11 +222,9 @@ class FileDevice : public Device {
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
* @param checkDevice whether to regularly check the device availability.
* @param latency the bus transfer latency in milliseconds.
* @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open().
* @param enhancedProto whether to use the ebusd enhanced protocol.
*/
FileDevice(const char* name, bool checkDevice, unsigned int latency, bool readOnly, bool initialSend,
FileDevice(const char* name, bool checkDevice, unsigned int latency,
bool enhancedProto = false);
public:
@@ -248,7 +234,10 @@ class FileDevice : public Device {
virtual ~FileDevice();
// @copydoc
void formatInfo(ostringstream* output, bool verbose, bool asJson = false, bool noWait = false) override;
void formatInfo(ostringstream* output, bool verbose, bool prefix) override;
// @copydoc
void formatInfoJson(ostringstream* output) override;
// @copydoc
result_t open() override;
@@ -450,14 +439,12 @@ class SerialDevice : public FileDevice {
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
* @param checkDevice whether to regularly check the device availability.
* @param extraLatency the extra bus transfer latency in milliseconds.
* @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open().
* @param enhancedProto whether to use the ebusd enhanced protocol.
* @param enhancedHighSpeed whether to use ebusd enhanced protocol in high speed mode.
*/
SerialDevice(const char* name, bool checkDevice, unsigned int extraLatency, bool readOnly, bool initialSend,
SerialDevice(const char* name, bool checkDevice, unsigned int extraLatency,
bool enhancedProto = false, bool enhancedHighSpeed = false)
: FileDevice(name, checkDevice, extraLatency, readOnly, initialSend, enhancedProto),
: FileDevice(name, checkDevice, extraLatency, enhancedProto),
m_enhancedHighSpeed(enhancedHighSpeed) {
}
@@ -498,14 +485,12 @@ class NetworkDevice : public FileDevice {
* @param hostOrIp the host name or IP address of the device.
* @param port the TCP or UDP port of the device.
* @param extraLatency the extra bus transfer latency in milliseconds.
* @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open().
* @param udp true for UDP, false to TCP.
* @param enhancedProto whether to use the ebusd enhanced protocol.
*/
NetworkDevice(const char* name, const char* hostOrIp, uint16_t port, unsigned int extraLatency, bool readOnly,
bool initialSend, bool udp, bool enhancedProto = false)
: FileDevice(name, true, NETWORK_LATENCY_MS+extraLatency, readOnly, initialSend, enhancedProto),
NetworkDevice(const char* name, const char* hostOrIp, uint16_t port, unsigned int extraLatency,
bool udp, bool enhancedProto = false)
: FileDevice(name, true, NETWORK_LATENCY_MS+extraLatency, enhancedProto),
m_hostOrIp(hostOrIp), m_port(port), m_udp(udp) {}
/**
@@ -514,6 +499,7 @@ class NetworkDevice : public FileDevice {
~NetworkDevice() override {
if (m_hostOrIp) {
free((void*)m_hostOrIp);
m_hostOrIp = nullptr;
}
}
+30 -6
View File
@@ -43,14 +43,35 @@ ProtocolHandler* ProtocolHandler::create(const ebus_protocol_config_t config,
return new DirectProtocolHandler(config, device, listener);
}
void ProtocolHandler::formatInfo(ostringstream* ostream, bool verbose, bool noWait) {
m_device->formatInfo(ostream, verbose, true);
if (isReadOnly()) {
*ostream << ", readonly";
}
if (noWait) {
return;
}
m_device->formatInfo(ostream, verbose, false);
}
void ProtocolHandler::formatInfoJson(ostringstream* ostream) {
m_device->formatInfoJson(ostream);
}
void ProtocolHandler::clear() {
memset(m_seenAddresses, 0, sizeof(m_seenAddresses));
m_masterCount = 1;
}
bool ProtocolHandler::addRequest(BusRequest* request, bool wait) {
result_t ProtocolHandler::addRequest(BusRequest* request, bool wait) {
if (m_config.readOnly) {
return RESULT_ERR_DEVICE;
}
m_nextRequests.push(request);
return !wait || m_finishedRequests.remove(request, true);
if (!wait || m_finishedRequests.remove(request, true)) {
return RESULT_OK;
}
return RESULT_ERR_TIMEOUT;
}
result_t ProtocolHandler::sendAndWait(const MasterSymbolString& master, SlaveSymbolString* slave) {
@@ -63,8 +84,11 @@ result_t ProtocolHandler::sendAndWait(const MasterSymbolString& master, SlaveSym
logInfo(lf_bus, "send message: %s", master.getStr().c_str());
for (int sendRetries = m_config.failedSendRetries + 1; sendRetries > 0; sendRetries--) {
bool success = addRequest(&request, true);
result = success ? request.m_result : RESULT_ERR_TIMEOUT;
result = addRequest(&request, true);
bool success = result == RESULT_OK;
if (success) {
result = request.m_result;
}
if (result == RESULT_OK) {
break;
}
@@ -103,7 +127,7 @@ bool ProtocolHandler::addSeenAddress(symbol_t address) {
return false;
}
if (!isMaster(address)) {
if (!m_device->isReadOnly() && address == m_ownSlaveAddress) {
if (!m_config.readOnly && address == m_ownSlaveAddress) {
if (!m_addressConflict) {
m_addressConflict = true;
logError(lf_bus, "own slave address %2.2x is used by another participant", address);
@@ -122,7 +146,7 @@ bool ProtocolHandler::addSeenAddress(symbol_t address) {
return false;
}
bool ret = false;
if (!m_device->isReadOnly() && address == m_ownMasterAddress) {
if (!m_config.readOnly && address == m_ownMasterAddress) {
if (!m_addressConflict) {
m_addressConflict = true;
logError(lf_bus, "own master address %2.2x is used by another participant", address);
+37 -6
View File
@@ -52,6 +52,8 @@ namespace ebusd {
/** settings for the eBUS protocol handler. */
typedef struct ebus_protocol_config {
/** whether to allow read access to the device only. */
bool readOnly;
/** the own master address. */
symbol_t ownAddress;
/** whether to answer queries for the own master/slave address. */
@@ -68,9 +70,19 @@ typedef struct ebus_protocol_config {
unsigned int lockCount;
/** whether to enable AUTO-SYN symbol generation. */
bool generateSyn;
/** whether to send an initial escape symbol after connecting device. */
bool initialSend;
} ebus_protocol_config_t;
/** the possible protocol states. */
enum ProtocolState {
ps_noSignal, //!< no signal on the bus
ps_idle, //!< idle (after @a SYN symbol)
ps_empty, //!< idle, no more lock remaining, and no other request queued
};
class ProtocolHandler;
/**
@@ -185,9 +197,9 @@ class ProtocolListener {
/**
* Called to notify a status update from the protocol.
* @param signal true when signal is acquired, false otherwise.
* @param state the current protocol state.
*/
virtual void notifyProtocolStatus(bool signal) = 0; // abstract
virtual void notifyProtocolStatus(ProtocolState state) = 0; // abstract
/**
* Called to notify a new valid seen address on the bus.
@@ -234,7 +246,7 @@ class ProtocolHandler : public WaitThread {
m_reconnect(false),
m_ownMasterAddress(config.ownAddress), m_ownSlaveAddress(getSlaveAddress(config.ownAddress)),
m_addressConflict(false),
m_masterCount(device->isReadOnly()?0:1),
m_masterCount(config.readOnly ? 0 : 1),
m_symbolLatencyMin(-1), m_symbolLatencyMax(-1), m_arbitrationDelayMin(-1),
m_arbitrationDelayMax(-1), m_lastReceive(0),
m_symPerSec(0), m_maxSymPerSec(0) {
@@ -266,6 +278,25 @@ class ProtocolHandler : public WaitThread {
*/
static ProtocolHandler* create(const ebus_protocol_config_t config, Device* device, ProtocolListener* listener);
/**
* Format device/protocol infos in plain text.
* @param output the @a ostringstream to append the infos to.
* @param verbose whether to add verbose infos.
* @param noWait true to not wait for any response asynchronously and return immediately.
*/
virtual void formatInfo(ostringstream* output, bool verbose, bool noWait);
/**
* Format device/protocol infos in JSON format.
* @param output the @a ostringstream to append the infos to.
*/
virtual void formatInfoJson(ostringstream* output);
/**
* @return whether to allow read access to the device only.
*/
bool isReadOnly() const { return m_config.readOnly; }
/**
* @return the own master address.
*/
@@ -286,7 +317,7 @@ class ProtocolHandler : public WaitThread {
* @return @p true when the address is the own master or slave address (if not readonly).
*/
bool isOwnAddress(symbol_t address) const {
return !m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress);
return !m_config.readOnly && (address == m_ownMasterAddress || address == m_ownSlaveAddress);
}
/**
@@ -324,9 +355,9 @@ class ProtocolHandler : public WaitThread {
* Add a @a BusRequest to the internal queue and optionally wait for it to complete.
* @param request the @a BusRequest to add.
* @param wait true to wait for it to complete, false to return immediately.
* @return true when it was not waited for or when it was completed.
* @return the result code of adding the request (i.e. RESULT_OK when it was not waited for or when it was completed).
*/
virtual bool addRequest(BusRequest* request, bool wait);
virtual result_t addRequest(BusRequest* request, bool wait);
/**
* Send a message on the bus and wait for the answer.
+11 -4
View File
@@ -91,6 +91,9 @@ void DirectProtocolHandler::run() {
result_t result = m_device->open();
if (result == RESULT_OK) {
logNotice(lf_bus, "re-opened %s", m_device->getName());
if (m_config.initialSend && !m_config.readOnly) {
m_device->send(ESC);
}
} else {
logError(lf_bus, "unable to open %s: %s", m_device->getName(), getResultCode(result));
setState(bs_noSignal, result);
@@ -131,6 +134,10 @@ result_t DirectProtocolHandler::handleSymbol() {
}
if (!m_device->isArbitrating() && m_currentRequest == nullptr && m_remainLockCount == 0) {
BusRequest* startRequest = m_nextRequests.peek();
if (startRequest == nullptr) {
m_listener->notifyProtocolStatus(ps_empty);
startRequest = m_nextRequests.peek();
}
if (startRequest != nullptr) { // initiate arbitration
symbol_t master = startRequest->getMaster()[0];
logDebug(lf_bus, "start request %2.2x", master);
@@ -220,7 +227,7 @@ result_t DirectProtocolHandler::handleSymbol() {
// send symbol if necessary
result_t result;
struct timespec sentTime, recvTime;
if (sending) {
if (sending && !m_config.readOnly) {
if (m_state != bs_sendSyn && (sendSymbol == ESC || sendSymbol == SYN)) {
if (m_escape) {
sendSymbol = (symbol_t)(sendSymbol == ESC ? 0x00 : 0x01);
@@ -254,7 +261,7 @@ result_t DirectProtocolHandler::handleSymbol() {
clockGettime(&recvTime);
}
bool sentAutoSyn = false;
if (!sending && result == RESULT_ERR_TIMEOUT && m_generateSynInterval > 0
if (!sending && !m_config.readOnly && result == RESULT_ERR_TIMEOUT && m_generateSynInterval > 0
&& timeout >= m_generateSynInterval && (m_state == bs_noSignal || m_state == bs_skip)) {
// check if acting as AUTO-SYN generator is required
result = m_device->send(SYN);
@@ -671,7 +678,7 @@ result_t DirectProtocolHandler::setState(BusState state, result_t result, bool f
if (state == bs_noSignal) { // notify all requests
if (m_state != bs_noSignal) {
m_listener->notifyProtocolStatus(false);
m_listener->notifyProtocolStatus(ps_idle);
}
m_response.clear(); // notify with empty response
while ((m_currentRequest = m_nextRequests.pop()) != nullptr) {
@@ -686,7 +693,7 @@ result_t DirectProtocolHandler::setState(BusState state, result_t result, bool f
}
}
} else if (m_state == bs_noSignal) {
m_listener->notifyProtocolStatus(true);
m_listener->notifyProtocolStatus(ps_noSignal);
}
m_escape = 0;