From ed8b3aded1e88d1e7e27d6e05a1eee27531e10e8 Mon Sep 17 00:00:00 2001 From: zimoch Date: Fri, 30 Nov 2007 15:23:13 +0000 Subject: [PATCH] disconnect callback --- src/AsynDriverInterface.cc | 58 +++++++++++++++++--------------------- src/StreamBusInterface.cc | 7 ++++- src/StreamBusInterface.h | 7 +++-- src/StreamCore.cc | 43 ++++++++++++++++++++++------ src/StreamCore.h | 1 + 5 files changed, 73 insertions(+), 43 deletions(-) diff --git a/src/AsynDriverInterface.cc b/src/AsynDriverInterface.cc index 33d63b4..6acba89 100644 --- a/src/AsynDriverInterface.cc +++ b/src/AsynDriverInterface.cc @@ -186,7 +186,7 @@ class AsynDriverInterface : StreamBusInterface bool supportsEvent(); bool supportsAsyncRead(); bool connectRequest(unsigned long connecttimeout_ms); - bool disconnect(); + bool disconnectRequest(); void finish(); #ifdef EPICS_3_14 @@ -462,11 +462,6 @@ lockRequest(unsigned long lockTimeout_ms) clientName(), lockTimeout_ms); asynStatus status; lockTimeout = lockTimeout_ms ? lockTimeout_ms*0.001 : -1.0; - if (!lockTimeout_ms) - { - if (!connectToAsynPort()) return false; - } - ioAction = Lock; status = pasynManager->queueRequest(pasynUser, priority(), lockTimeout); @@ -497,6 +492,8 @@ connectToAsynPort() clientName(), pasynUser->errorMessage); return false; } + debug("AsynDriverInterface::connectToAsynPort(%s) is %s connected\n", + clientName(), connected ? "already" : "not yet"); if (!connected) { status = pasynCommon->connect(pvtCommon, pasynUser); @@ -510,6 +507,12 @@ connectToAsynPort() return false; } } +// We probably should set REN=1 prior to sending but this +// seems to hang up the device every other time. +// if (pasynGpib) +// { +// pasynGpib->ren(pvtGpib, pasynUser, 1); +// } return true; } @@ -517,10 +520,12 @@ connectToAsynPort() void AsynDriverInterface:: lockHandler() { + int connected; debug("AsynDriverInterface::lockHandler(%s)\n", clientName()); pasynManager->blockProcessCallback(pasynUser, false); - lockCallback(StreamIoSuccess); + connected = connectToAsynPort(); + lockCallback(connected ? StreamIoSuccess : StreamIoFault); } // interface function: we don't need exclusive access any more @@ -1202,46 +1207,27 @@ connectRequest(unsigned long connecttimeout_ms) void AsynDriverInterface:: connectHandler() { - int connected; - asynStatus status; - - pasynManager->isConnected(pasynUser, &connected); - debug("AsynDriverInterface::connectHandler %s is %s connected\n", - clientName(), connected ? "already" : "not yet"); - if (!connected) - { - status = pasynCommon->connect(pvtCommon, pasynUser); - if (status != asynSuccess) - { - error("%s connectRequest: pasynCommon->connect() failed: %s\n", - clientName(), pasynUser->errorMessage); - connectCallback(StreamIoFault); - return; - } - } - connectCallback(StreamIoSuccess); + connectCallback(connectToAsynPort() ? StreamIoSuccess : StreamIoFault); } bool AsynDriverInterface:: -disconnect() +disconnectRequest() { asynStatus status; ioAction = Disconnect; - debug("AsynDriverInterface::disconnect %s\n", + debug("AsynDriverInterface::disconnectRequest %s\n", clientName()); status = pasynManager->queueRequest(pasynUser, asynQueuePriorityConnect, 0.0); if (status != asynSuccess) { - error("%s disconnect: pasynManager->queueRequest() failed: %s\n", + error("%s disconnectRequest: pasynManager->queueRequest() failed: %s\n", clientName(), pasynUser->errorMessage); return false; } // continues with: // handleRequest() -> disconnectHandler() - // or handleTimeout() - // (does not expect callback) return true; } @@ -1261,9 +1247,11 @@ disconnectHandler() { error("%s connectRequest: pasynCommon->disconnect() failed: %s\n", clientName(), pasynUser->errorMessage); + disconnectCallback(StreamIoFault); return; } } + disconnectCallback(StreamIoSuccess); } void AsynDriverInterface:: @@ -1273,6 +1261,12 @@ finish() clientName()); cancelTimer(); ioAction = None; +// if (pasynGpib) +// { +// // Release GPIB device the the end of the protocol +// // to re-enable local buttons. +// pasynGpib->ren(pvtGpib, pasynUser, 0); +// } debug("AsynDriverInterface::finish(%s) done\n", clientName()); } @@ -1335,9 +1329,9 @@ void handleTimeout(asynUser* pasynUser) interface->connectCallback(StreamIoTimeout); break; case Disconnect: - debug ("AsynDriverInterface %s: disconnect timeout\n", + error("AsynDriverInterface %s: disconnect timeout\n", interface->clientName()); - // not interested in callback + // should not happen because of infinite timeout break; // No AsyncRead here because we don't use timeout when polling default: diff --git a/src/StreamBusInterface.cc b/src/StreamBusInterface.cc index d3d7f8d..56e90e7 100644 --- a/src/StreamBusInterface.cc +++ b/src/StreamBusInterface.cc @@ -89,7 +89,7 @@ connectRequest (unsigned long) } bool StreamBusInterface:: -disconnect () +disconnectRequest () { return false; } @@ -137,6 +137,11 @@ connectCallback(StreamIoStatus) { } +void StreamBusInterface::Client:: +disconnectCallback(StreamIoStatus) +{ +} + long StreamBusInterface::Client:: priority() { diff --git a/src/StreamBusInterface.h b/src/StreamBusInterface.h index 17f0c66..5f0b3d2 100644 --- a/src/StreamBusInterface.h +++ b/src/StreamBusInterface.h @@ -42,6 +42,7 @@ public: const void* input, long size); virtual void eventCallback(StreamIoStatus status); virtual void connectCallback(StreamIoStatus status); + virtual void disconnectCallback(StreamIoStatus status); virtual long priority(); virtual const char* name() = 0; virtual const char* getInTerminator(size_t& length) = 0; @@ -86,7 +87,7 @@ public: return businterface->connectRequest(timeout_ms); } bool busDisconnect() { - return businterface->disconnect(); + return businterface->disconnectRequest(); } }; @@ -113,6 +114,8 @@ protected: { client->eventCallback(status); } void connectCallback(StreamIoStatus status) { client->connectCallback(status); } + void disconnectCallback(StreamIoStatus status) + { client->disconnectCallback(status); } const char* getInTerminator(size_t& length) { return client->getInTerminator(length); } const char* getOutTerminator(size_t& length) @@ -132,7 +135,7 @@ protected: unsigned long replytimeout_ms); // supportsEvents() returns true virtual void release(); virtual bool connectRequest(unsigned long connecttimeout_ms); - virtual bool disconnect(); + virtual bool disconnectRequest(); virtual void finish(); // pure virtual diff --git a/src/StreamCore.cc b/src/StreamCore.cc index 2c85381..117ee5e 100644 --- a/src/StreamCore.cc +++ b/src/StreamCore.cc @@ -23,6 +23,12 @@ #include #include +#include +int showAsyncErrors = 0; +extern "C" { +epicsExportAddress(int, showAsyncErrors); +} + enum Commands { end_cmd, in_cmd, out_cmd, wait_cmd, event_cmd, exec_cmd, connect_cmd, disconnect_cmd }; const char* commandStr[] = { "end", "in", "out", "wait", "event", "exec", @@ -801,6 +807,8 @@ writeCallback(StreamIoStatus status) flags &= ~WritePending; if (status != StreamIoSuccess) { + error("%s: write failed: %s\n", + name(), StreamIoStatusStr[status]); finishProtocol(WriteTimeout); return; } @@ -921,7 +929,11 @@ readCallback(StreamIoStatus status, finishProtocol(ReplyTimeout); return 0; case StreamIoFault: - error("%s: I/O error when reading from device\n", name()); + error("%s: I/O error after reading %ld byte%s: \"%s%s\"\n", + name(), + inputBuffer.length(), inputBuffer.length()==1 ? "" : "s", + inputBuffer.length() > 20 ? "..." : "", + inputBuffer.expand(-20,20)()); finishProtocol(Fault); return 0; } @@ -985,7 +997,7 @@ readCallback(StreamIoStatus status, } // try to parse what we got end = inputBuffer.length(); - if (!(flags & AsyncMode)) + if (!(flags & AsyncMode)||showAsyncErrors) { error("%s: Timeout after reading %ld byte%s \"%s%s\"\n", name(), end, end==1 ? "" : "s", end > 20 ? "..." : "", @@ -1115,7 +1127,7 @@ matchInput() } if (consumed < 0) { - if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) + if ((!(flags & AsyncMode)||showAsyncErrors) && onMismatch[0] != in_cmd) { error("%s: Input \"%s%s\" does not match format %%%s\n", name(), inputLine.expand(consumedInput, 20)(), @@ -1130,7 +1142,7 @@ matchInput() flags &= ~Separator; if (!matchValue(fmt, fieldAddress ? fieldAddress() : NULL)) { - if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) + if ((!(flags & AsyncMode)||showAsyncErrors) && onMismatch[0] != in_cmd) { if (flags & ScanTried) error("%s: Input \"%s%s\" does not match format %%%s\n", @@ -1160,7 +1172,7 @@ matchInput() { int i = 0; while (commandIndex[i] >= ' ') i++; - if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) + if ((!(flags & AsyncMode)||showAsyncErrors) && onMismatch[0] != in_cmd) { error("%s: Input \"%s%s\" too short." " No match for \"%s\"\n", @@ -1173,7 +1185,7 @@ matchInput() } if (command != inputLine[consumedInput]) { - if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) + if ((!(flags & AsyncMode)||showAsyncErrors) && onMismatch[0] != in_cmd) { int i = 0; while (commandIndex[i] >= ' ') i++; @@ -1198,7 +1210,7 @@ matchInput() long surplus = inputLine.length()-consumedInput; if (surplus > 0 && !(flags & IgnoreExtraInput)) { - if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) + if ((!(flags & AsyncMode)||showAsyncErrors) && onMismatch[0] != in_cmd) { error("%s: %ld byte%s surplus input \"%s%s\"\n", name(), surplus, surplus==1 ? "" : "s", @@ -1510,8 +1522,23 @@ bool StreamCore::evalDisconnect() finishProtocol(Fault); return false; } - evalCommand(); return true; } +void StreamCore:: +disconnectCallback(StreamIoStatus status) +{ + switch (status) + { + case StreamIoSuccess: + evalCommand(); + return; + default: + error("%s: Disconnect failed\n", + name()); + finishProtocol(Fault); + return; + } +} + #include "streamReferences" diff --git a/src/StreamCore.h b/src/StreamCore.h index 2fe078c..090ae33 100644 --- a/src/StreamCore.h +++ b/src/StreamCore.h @@ -200,6 +200,7 @@ protected: void eventCallback(StreamIoStatus status); void execCallback(StreamIoStatus status); void connectCallback(StreamIoStatus status); + void disconnectCallback(StreamIoStatus status); const char* getInTerminator(size_t& length); const char* getOutTerminator(size_t& length);