re-run @init in iocRun after iocPause and streamReload
This commit is contained in:
@ -55,21 +55,22 @@ its <code>SEVR</code> field set to <code>INVALID</code> and its
|
|||||||
<dt><code>TIMEOUT</code></dt>
|
<dt><code>TIMEOUT</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
The device could not be locked (<code>LockTimeout</code>) or the
|
The device could not be locked (<code>LockTimeout</code>) or the
|
||||||
device did not reply (<code>ReplyTimeout</code>).
|
device did not reply in time
|
||||||
|
(<a href="protocol.html#sysvar"><code>ReplyTimeout</code></a>).
|
||||||
</dd>
|
</dd>
|
||||||
<dt><code>WRITE</code></dt>
|
<dt><code>WRITE</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
Output could not be written to the device (<code>WriteTimeout</code>).
|
Output could not be written to the device in time
|
||||||
|
(<a href="protocol.html#sysvar"><code>WriteTimeout</code></a>).
|
||||||
</dd>
|
</dd>
|
||||||
<dt><code>READ</code></dt>
|
<dt><code>READ</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
Input from the device started but stopped unexpectedly
|
Input from the device started but stopped unexpectedly
|
||||||
(<code>ReadTimeout</code>).
|
(<a href="protocol.html#sysvar"><code>ReadTimeout</code></a>).
|
||||||
</dd>
|
</dd>
|
||||||
<dt><code>COMM</code></dt>
|
<dt><code>COMM</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
The device driver reported some other communication error (e.g.
|
The device driver reported that the device is disconnected.
|
||||||
unplugged cable).
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt><code>CALC</code></dt>
|
<dt><code>CALC</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
@ -146,6 +147,19 @@ read from a constant <code>INP</code> or <code>DOL</code> field,
|
|||||||
or restored from a bump-less reboot system
|
or restored from a bump-less reboot system
|
||||||
(e.g. <em>autosave</em> from the <em>synApps</em> package).
|
(e.g. <em>autosave</em> from the <em>synApps</em> package).
|
||||||
</p>
|
</p>
|
||||||
|
<p class="new">
|
||||||
|
The <code>@init</code> handler is called again in the following situations:
|
||||||
|
</p>
|
||||||
|
<ul class="new">
|
||||||
|
<li>The device driver informs <em>StreamDevice</em> that the device has
|
||||||
|
reconnected after it had been disconnected. This is only detectable for
|
||||||
|
some types of busses.
|
||||||
|
<li>The IOC is resumed with <code>iocRun</code> after it had
|
||||||
|
been paused with <code>iocPause</code>. This requires EPICS 3.14.11 or higher.
|
||||||
|
<li>The record protocol has been <a href="setup.html#reload">reloaded</a>
|
||||||
|
using the shell function <code>streamReload</code> or the subroutine
|
||||||
|
record funtion <code>streamReloadSub</code>.
|
||||||
|
</ul>
|
||||||
|
|
||||||
<a name="iointr"></a>
|
<a name="iointr"></a>
|
||||||
<h2>3. I/O Intr</h2>
|
<h2>3. I/O Intr</h2>
|
||||||
|
@ -557,8 +557,10 @@ There is a fixed set of exception handler names starting with
|
|||||||
<dd>
|
<dd>
|
||||||
Not really an exception but formally specified in the same syntax.
|
Not really an exception but formally specified in the same syntax.
|
||||||
This handler is called from <code>iocInit</code> during record
|
This handler is called from <code>iocInit</code> during record
|
||||||
initialization <span class="new">and again whenever it is detected
|
initialization <span class="new">and again whenever <em>StreamDevice</em>
|
||||||
that the device was disconnected and has reconnected</span>.
|
detects that the device has reconnected after a disconnect or when the
|
||||||
|
ioc is resumed with <code>iocRun</code> after beeing paused or
|
||||||
|
when the protocol has been <a href="setup.html#reload">reloaded</a></span>.
|
||||||
It can be used to initialize an output record with a value read from
|
It can be used to initialize an output record with a value read from
|
||||||
the device.
|
the device.
|
||||||
Also see chapter <a href="processing.html#init">Record Processing</a>.
|
Also see chapter <a href="processing.html#init">Record Processing</a>.
|
||||||
|
@ -322,8 +322,13 @@ During development, the protocol files might change frequently.
|
|||||||
To prevent restarting the IOC all the time, it is possible to reload
|
To prevent restarting the IOC all the time, it is possible to reload
|
||||||
the protocol file of one or all records with the shell function
|
the protocol file of one or all records with the shell function
|
||||||
<code>streamReload("<var>record</var>")</code>.
|
<code>streamReload("<var>record</var>")</code>.
|
||||||
If <code>"<var>record</var>"</code> is not given, all records using
|
If <code>"<var>record</var>"</code> is not given
|
||||||
|
<span class="new">or empty</span>, all records using
|
||||||
<em>StreamDevice</em> reload their protocols.
|
<em>StreamDevice</em> reload their protocols.
|
||||||
|
<span class="new">In EPICS 3.14 or higher,
|
||||||
|
<code><var>record</var></code> can be a glob pattern.</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
Furthermore, the <code>streamReloadSub</code> function can be used
|
Furthermore, the <code>streamReloadSub</code> function can be used
|
||||||
with a subroutine record to reload all protocols.
|
with a subroutine record to reload all protocols.
|
||||||
</p>
|
</p>
|
||||||
@ -336,6 +341,8 @@ protocol is loaded.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
<span class="new">Reloading triggers an <code>@init</code>
|
||||||
|
<a href="protocol.html#except">handler</a>.</span>
|
||||||
See the <a href="protocol.html">next chapter</a> for protocol files in depth.
|
See the <a href="protocol.html">next chapter</a> for protocol files in depth.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -66,7 +66,12 @@ extern DBBASE *pdbbase;
|
|||||||
#include "epicsStdioRedirect.h"
|
#include "epicsStdioRedirect.h"
|
||||||
#include "iocsh.h"
|
#include "iocsh.h"
|
||||||
|
|
||||||
#if (!defined VERSION_INT && EPICS_MODIFICATION<9)
|
#if defined(VERSION_INT) || EPICS_MODIFICATION >= 11
|
||||||
|
#include "initHooks.h"
|
||||||
|
#define WITH_IOC_RUN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(VERSION_INT) && EPICS_MODIFICATION < 9
|
||||||
// iocshCmd() is missing in iocsh.h (up to R3.14.8.2)
|
// iocshCmd() is missing in iocsh.h (up to R3.14.8.2)
|
||||||
// To build with win32-x86, you MUST fix iocsh.h.
|
// To build with win32-x86, you MUST fix iocsh.h.
|
||||||
// Move the declaration below to iocsh.h and rebuild base.
|
// Move the declaration below to iocsh.h and rebuild base.
|
||||||
@ -168,6 +173,10 @@ class Stream : protected StreamCore
|
|||||||
ssize_t scan(format_t *format, void* pvalue, size_t maxStringSize);
|
ssize_t scan(format_t *format, void* pvalue, size_t maxStringSize);
|
||||||
bool process();
|
bool process();
|
||||||
|
|
||||||
|
#ifdef WITH_IOC_RUN
|
||||||
|
static void initHook(initHookState);
|
||||||
|
#endif
|
||||||
|
|
||||||
// device support functions
|
// device support functions
|
||||||
friend long streamInitRecord(dbCommon *record, const struct link *ioLink,
|
friend long streamInitRecord(dbCommon *record, const struct link *ioLink,
|
||||||
streamIoFunction readData, streamIoFunction writeData);
|
streamIoFunction readData, streamIoFunction writeData);
|
||||||
@ -201,10 +210,8 @@ long streamReloadSub()
|
|||||||
|
|
||||||
long streamReload(const char* recordname)
|
long streamReload(const char* recordname)
|
||||||
{
|
{
|
||||||
DBENTRY dbentry;
|
Stream* stream;
|
||||||
dbCommon* record;
|
|
||||||
long status;
|
long status;
|
||||||
|
|
||||||
int oldStreamError = streamError;
|
int oldStreamError = streamError;
|
||||||
streamError = 1;
|
streamError = 1;
|
||||||
|
|
||||||
@ -214,38 +221,24 @@ long streamReload(const char* recordname)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
debug("streamReload(%s)\n", recordname);
|
debug("streamReload(%s)\n", recordname);
|
||||||
dbInitEntry(pdbbase,&dbentry);
|
for (stream = static_cast<Stream*>(Stream::first); stream;
|
||||||
for (status = dbFirstRecordType(&dbentry); status == OK;
|
stream = static_cast<Stream*>(stream->next))
|
||||||
status = dbNextRecordType(&dbentry))
|
|
||||||
{
|
{
|
||||||
for (status = dbFirstRecord(&dbentry); status == OK;
|
if (recordname && recordname[0] &&
|
||||||
status = dbNextRecord(&dbentry))
|
#ifdef EPICS_3_13
|
||||||
{
|
strcmp(stream->name(), recordname) == 0)
|
||||||
char* value;
|
#else
|
||||||
if (dbFindField(&dbentry, "DTYP") != OK)
|
!epicsStrGlobMatch(stream->name(), recordname))
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
if ((value = dbGetString(&dbentry)) == NULL)
|
|
||||||
continue;
|
|
||||||
if (strcmp(value, "stream") != 0)
|
|
||||||
continue;
|
|
||||||
record=(dbCommon*)dbentry.precnode->precord;
|
|
||||||
if (recordname && strcmp(recordname, record->name) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// This cancels any running protocol and reloads
|
// This cancels any running protocol and reloads
|
||||||
// the protocol file
|
// the protocol file
|
||||||
status = record->dset->init_record(record);
|
status = stream->record->dset->init_record(stream->record);
|
||||||
if (status == OK || status == DO_NOT_CONVERT)
|
if (status == OK || status == DO_NOT_CONVERT)
|
||||||
{
|
printf("%s: Protocol reloaded\n", stream->name());
|
||||||
printf("%s: Protocol reloaded\n", record->name);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
error("%s: Protocol reload failed\n", stream->name());
|
||||||
error("%s: Protocol reload failed\n", record->name);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
dbFinishEntry(&dbentry);
|
|
||||||
StreamProtocolParser::free();
|
StreamProtocolParser::free();
|
||||||
streamError = oldStreamError;
|
streamError = oldStreamError;
|
||||||
return OK;
|
return OK;
|
||||||
@ -388,25 +381,25 @@ report(int interest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream* pstream;
|
Stream* stream;
|
||||||
printf(" connected records:\n");
|
printf(" connected records:\n");
|
||||||
for (pstream = static_cast<Stream*>(first); pstream;
|
for (stream = static_cast<Stream*>(first); stream;
|
||||||
pstream = static_cast<Stream*>(pstream->next))
|
stream = static_cast<Stream*>(stream->next))
|
||||||
{
|
{
|
||||||
if (interest == 2)
|
if (interest == 2)
|
||||||
{
|
{
|
||||||
printf("\n%s: %s\n", pstream->name(),
|
printf("\n%s: %s\n", stream->name(),
|
||||||
pstream->ioLink->value.instio.string);
|
stream->ioLink->value.instio.string);
|
||||||
pstream->printProtocol();
|
stream->printProtocol();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf(" %s: %s\n", pstream->name(),
|
printf(" %s: %s\n", stream->name(),
|
||||||
pstream->ioLink->value.instio.string);
|
stream->ioLink->value.instio.string);
|
||||||
if (interest == 3)
|
if (interest == 3)
|
||||||
{
|
{
|
||||||
StreamBuffer buffer;
|
StreamBuffer buffer;
|
||||||
pstream->printStatus(buffer);
|
stream->printStatus(buffer);
|
||||||
printf(" %s\n", buffer());
|
printf(" %s\n", buffer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -416,23 +409,23 @@ report(int interest)
|
|||||||
|
|
||||||
long streamReportRecord(const char* recordname)
|
long streamReportRecord(const char* recordname)
|
||||||
{
|
{
|
||||||
Stream* pstream;
|
Stream* stream;
|
||||||
for (pstream = static_cast<Stream*>(Stream::first); pstream;
|
for (stream = static_cast<Stream*>(Stream::first); stream;
|
||||||
pstream = static_cast<Stream*>(pstream->next))
|
stream = static_cast<Stream*>(stream->next))
|
||||||
{
|
{
|
||||||
if (!recordname ||
|
if (!recordname ||
|
||||||
#ifdef EPICS_3_13
|
#ifdef EPICS_3_13
|
||||||
strcmp(pstream->name(), recordname) == 0)
|
strcmp(stream->name(), recordname) == 0)
|
||||||
#else
|
#else
|
||||||
epicsStrGlobMatch(pstream->name(), recordname))
|
epicsStrGlobMatch(stream->name(), recordname))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
printf("%s: %s\n", pstream->name(),
|
printf("%s: %s\n", stream->name(),
|
||||||
pstream->ioLink->value.instio.string);
|
stream->ioLink->value.instio.string);
|
||||||
StreamBuffer buffer;
|
StreamBuffer buffer;
|
||||||
pstream->printStatus(buffer);
|
stream->printStatus(buffer);
|
||||||
printf("%s\n", buffer());
|
printf("%s\n", buffer());
|
||||||
pstream->printProtocol();
|
stream->printProtocol();
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -453,33 +446,64 @@ drvInit()
|
|||||||
SYM_TYPE type;
|
SYM_TYPE type;
|
||||||
if (symFindByName(sysSymTbl,
|
if (symFindByName(sysSymTbl,
|
||||||
"STREAM_PROTOCOL_PATH", &symbol, &type) == OK)
|
"STREAM_PROTOCOL_PATH", &symbol, &type) == OK)
|
||||||
{
|
|
||||||
path = *(char**)symbol;
|
path = *(char**)symbol;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
if (symFindByName(sysSymTbl,
|
if (symFindByName(sysSymTbl,
|
||||||
"STREAM_PROTOCOL_DIR", &symbol, &type) == OK)
|
"STREAM_PROTOCOL_DIR", &symbol, &type) == OK)
|
||||||
{
|
|
||||||
path = *(char**)symbol;
|
path = *(char**)symbol;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (!path)
|
if (!path)
|
||||||
{
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"drvStreamInit: Warning! STREAM_PROTOCOL_PATH not set. "
|
"drvStreamInit: Warning! STREAM_PROTOCOL_PATH not set. "
|
||||||
"Defaults to \"%s\"\n", StreamProtocolParser::path);
|
"Defaults to \"%s\"\n", StreamProtocolParser::path);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
StreamProtocolParser::path = path;
|
StreamProtocolParser::path = path;
|
||||||
}
|
|
||||||
debug("StreamProtocolParser::path = %s\n",
|
debug("StreamProtocolParser::path = %s\n",
|
||||||
StreamProtocolParser::path);
|
StreamProtocolParser::path);
|
||||||
StreamPrintTimestampFunction = streamEpicsPrintTimestamp;
|
StreamPrintTimestampFunction = streamEpicsPrintTimestamp;
|
||||||
|
|
||||||
|
#ifdef WITH_IOC_RUN
|
||||||
|
initHookRegister(initHook);
|
||||||
|
#endif
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_IOC_RUN
|
||||||
|
void Stream::
|
||||||
|
initHook(initHookState state)
|
||||||
|
{
|
||||||
|
Stream* stream;
|
||||||
|
|
||||||
|
if (state == initHookAtIocRun)
|
||||||
|
{
|
||||||
|
debug("Stream::initHook(initHookAtIocRun) interruptAccept=%d\n", interruptAccept);
|
||||||
|
|
||||||
|
static int inIocInit = 1;
|
||||||
|
if (inIocInit)
|
||||||
|
{
|
||||||
|
// We don't want to run @init twice in iocInit
|
||||||
|
inIocInit = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (stream = static_cast<Stream*>(first); stream;
|
||||||
|
stream = static_cast<Stream*>(stream->next))
|
||||||
|
{
|
||||||
|
if (!stream->onInit) continue;
|
||||||
|
debug("Stream::initHook(initHookAtIocRun) Re-inititializing %s\n", stream->name());
|
||||||
|
if (!stream->startProtocol(StartInit))
|
||||||
|
{
|
||||||
|
error("%s: Re-initialization failed.\n",
|
||||||
|
stream->name());
|
||||||
|
}
|
||||||
|
stream->initDone.wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// device support (C interface) //////////////////////////////////////////
|
// device support (C interface) //////////////////////////////////////////
|
||||||
|
|
||||||
long streamInit(int after)
|
long streamInit(int after)
|
||||||
@ -490,6 +514,7 @@ long streamInit(int after)
|
|||||||
static int first = 1;
|
static int first = 1;
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
|
// restore error filtering to previous setting
|
||||||
streamError = oldStreamError;
|
streamError = oldStreamError;
|
||||||
StreamProtocolParser::free();
|
StreamProtocolParser::free();
|
||||||
first = 0;
|
first = 0;
|
||||||
@ -500,6 +525,7 @@ long streamInit(int after)
|
|||||||
static int first = 1;
|
static int first = 1;
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
|
// enable errors while reading protocol files
|
||||||
oldStreamError = streamError;
|
oldStreamError = streamError;
|
||||||
streamError = 1;
|
streamError = 1;
|
||||||
first = 0;
|
first = 0;
|
||||||
@ -520,38 +546,38 @@ long streamInitRecord(dbCommon* record, const struct link *ioLink,
|
|||||||
memset(busparam, 0 ,sizeof(busparam));
|
memset(busparam, 0 ,sizeof(busparam));
|
||||||
|
|
||||||
debug("streamInitRecord(%s): SEVR=%d\n", record->name, record->sevr);
|
debug("streamInitRecord(%s): SEVR=%d\n", record->name, record->sevr);
|
||||||
Stream* pstream = (Stream*)record->dpvt;
|
Stream* stream = static_cast<Stream*>(record->dpvt);
|
||||||
if (!pstream)
|
if (!stream)
|
||||||
{
|
{
|
||||||
// initialize the first time
|
// initialize the first time
|
||||||
debug("streamInitRecord(%s): create new Stream object\n",
|
debug("streamInitRecord(%s): create new Stream object\n",
|
||||||
record->name);
|
record->name);
|
||||||
pstream = new Stream(record, ioLink, readData, writeData);
|
stream = new Stream(record, ioLink, readData, writeData);
|
||||||
record->dpvt = pstream;
|
record->dpvt = stream;
|
||||||
} else {
|
} else {
|
||||||
// stop any running protocol
|
// stop any running protocol
|
||||||
debug("streamInitRecord(%s): stop running protocol\n",
|
debug("streamInitRecord(%s): stop running protocol\n",
|
||||||
record->name);
|
record->name);
|
||||||
pstream->finishProtocol(Stream::Abort);
|
stream->finishProtocol(Stream::Abort);
|
||||||
}
|
}
|
||||||
// scan the i/o link
|
// scan the i/o link
|
||||||
debug("streamInitRecord(%s): parse link \"%s\"\n",
|
debug("streamInitRecord(%s): parse link \"%s\"\n",
|
||||||
record->name, ioLink->value.instio.string);
|
record->name, ioLink->value.instio.string);
|
||||||
status = pstream->parseLink(ioLink, filename, protocol,
|
status = stream->parseLink(ioLink, filename, protocol,
|
||||||
busname, &addr, busparam);
|
busname, &addr, busparam);
|
||||||
// (re)initialize bus and protocol
|
// (re)initialize bus and protocol
|
||||||
debug("streamInitRecord(%s): calling initRecord\n",
|
debug("streamInitRecord(%s): calling initRecord\n",
|
||||||
record->name);
|
record->name);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
status = pstream->initRecord(filename, protocol,
|
status = stream->initRecord(filename, protocol,
|
||||||
busname, addr, busparam);
|
busname, addr, busparam);
|
||||||
if (status != OK && status != DO_NOT_CONVERT)
|
if (status != OK && status != DO_NOT_CONVERT)
|
||||||
{
|
{
|
||||||
error("%s: Record initialization failed\n", record->name);
|
error("%s: Record initialization failed\n", record->name);
|
||||||
}
|
}
|
||||||
else if (!pstream->ioscanpvt)
|
else if (!stream->ioscanpvt)
|
||||||
{
|
{
|
||||||
scanIoInit(&pstream->ioscanpvt);
|
scanIoInit(&stream->ioscanpvt);
|
||||||
}
|
}
|
||||||
debug("streamInitRecord(%s) done status=%#lx\n", record->name, status);
|
debug("streamInitRecord(%s) done status=%#lx\n", record->name, status);
|
||||||
return status;
|
return status;
|
||||||
@ -559,33 +585,33 @@ long streamInitRecord(dbCommon* record, const struct link *ioLink,
|
|||||||
|
|
||||||
long streamReadWrite(dbCommon *record)
|
long streamReadWrite(dbCommon *record)
|
||||||
{
|
{
|
||||||
Stream* pstream = (Stream*)record->dpvt;
|
Stream* stream = static_cast<Stream*>(record->dpvt);
|
||||||
if (!pstream || pstream->status == ERROR)
|
if (!stream || stream->status == ERROR)
|
||||||
{
|
{
|
||||||
(void) recGblSetSevr(record, UDF_ALARM, INVALID_ALARM);
|
(void) recGblSetSevr(record, UDF_ALARM, INVALID_ALARM);
|
||||||
error("%s: Record not initialised correctly\n", record->name);
|
error("%s: Record not initialised correctly\n", record->name);
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
return pstream->process() ? pstream->convert : ERROR;
|
return stream->process() ? stream->convert : ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
long streamGetIointInfo(int cmd, dbCommon *record, IOSCANPVT *ppvt)
|
long streamGetIointInfo(int cmd, dbCommon *record, IOSCANPVT *ppvt)
|
||||||
{
|
{
|
||||||
Stream* pstream = (Stream*)record->dpvt;
|
Stream* stream = static_cast<Stream*>(record->dpvt);
|
||||||
debug("streamGetIointInfo(%s,cmd=%d): pstream=%p, ioscanpvt=%p\n",
|
debug("streamGetIointInfo(%s,cmd=%d): stream=%p, ioscanpvt=%p\n",
|
||||||
record->name, cmd,
|
record->name, cmd,
|
||||||
(void*)pstream, pstream ? pstream->ioscanpvt : NULL);
|
(void*)stream, stream ? stream->ioscanpvt : NULL);
|
||||||
if (!pstream)
|
if (!stream)
|
||||||
{
|
{
|
||||||
error("streamGetIointInfo called without stream instance\n");
|
error("streamGetIointInfo called without stream instance\n");
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
*ppvt = pstream->ioscanpvt;
|
*ppvt = stream->ioscanpvt;
|
||||||
if (cmd == 0)
|
if (cmd == 0)
|
||||||
{
|
{
|
||||||
debug("streamGetIointInfo: starting protocol\n");
|
debug("streamGetIointInfo: starting protocol\n");
|
||||||
// SCAN has been set to "I/O Intr"
|
// SCAN has been set to "I/O Intr"
|
||||||
if (!pstream->startProtocol(Stream::StartAsync))
|
if (!stream->startProtocol(Stream::StartAsync))
|
||||||
{
|
{
|
||||||
error("%s: Can't start \"I/O Intr\" protocol\n",
|
error("%s: Can't start \"I/O Intr\" protocol\n",
|
||||||
record->name);
|
record->name);
|
||||||
@ -594,7 +620,7 @@ long streamGetIointInfo(int cmd, dbCommon *record, IOSCANPVT *ppvt)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// SCAN is no longer "I/O Intr"
|
// SCAN is no longer "I/O Intr"
|
||||||
pstream->finishProtocol(Stream::Abort);
|
stream->finishProtocol(Stream::Abort);
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -603,11 +629,11 @@ long streamPrintf(dbCommon *record, format_t *format, ...)
|
|||||||
{
|
{
|
||||||
debug("streamPrintf(%s,format=%%%c)\n",
|
debug("streamPrintf(%s,format=%%%c)\n",
|
||||||
record->name, format->priv->conv);
|
record->name, format->priv->conv);
|
||||||
Stream* pstream = (Stream*)record->dpvt;
|
Stream* stream = static_cast<Stream*>(record->dpvt);
|
||||||
if (!pstream) return ERROR;
|
if (!stream) return ERROR;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
bool success = pstream->print(format, ap);
|
bool success = stream->print(format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return success ? OK : ERROR;
|
return success ? OK : ERROR;
|
||||||
}
|
}
|
||||||
@ -616,9 +642,9 @@ ssize_t streamScanfN(dbCommon* record, format_t *format,
|
|||||||
void* value, size_t maxStringSize)
|
void* value, size_t maxStringSize)
|
||||||
{
|
{
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
Stream* pstream = (Stream*)record->dpvt;
|
Stream* stream = static_cast<Stream*>(record->dpvt);
|
||||||
if (!pstream) return ERROR;
|
if (!stream) return ERROR;
|
||||||
size = pstream->scan(format, value, maxStringSize);
|
size = stream->scan(format, value, maxStringSize);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -753,11 +779,12 @@ initRecord(const char* filename, const char* protocol,
|
|||||||
name());
|
name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
debug("Stream::initRecord %s: initialize the first time\n",
|
debug("Stream::initRecord %s: initialize the first time\n",
|
||||||
name());
|
name());
|
||||||
|
}
|
||||||
|
|
||||||
if (!onInit) return DO_NOT_CONVERT; // no @init handler, keep DOL
|
if (!onInit) return DO_NOT_CONVERT; // no @init handler, keep DOL
|
||||||
|
|
||||||
@ -899,8 +926,7 @@ scan(format_t *format, void* value, size_t maxStringSize)
|
|||||||
void Stream::
|
void Stream::
|
||||||
expire(CALLBACK *pcallback)
|
expire(CALLBACK *pcallback)
|
||||||
{
|
{
|
||||||
Stream* pstream = static_cast<Stream*>(pcallback->user);
|
static_cast<Stream*>(pcallback->user)->timerCallback();
|
||||||
pstream->timerCallback();
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
epicsTimerNotify::expireStatus Stream::
|
epicsTimerNotify::expireStatus Stream::
|
||||||
|
Reference in New Issue
Block a user