Compare commits
77 Commits
stream_2_5
...
stream_2_6
Author | SHA1 | Date | |
---|---|---|---|
9b9726b800 | |||
b139221f0b | |||
b0ab8a7a8b | |||
ddac589676 | |||
5b380cdaad | |||
cc9adc77fa | |||
2b38f7bcfa | |||
0ceada70b5 | |||
7bf91b403d | |||
bf5c359649 | |||
c41ac44bd1 | |||
e36013d64e | |||
9e48ad3e61 | |||
054e74d04a | |||
5f6319ed3d | |||
2f39622a57 | |||
7801119215 | |||
a6696cae49 | |||
40b52167aa | |||
814e3d53a3 | |||
6bd46e0470 | |||
d5cda13f6f | |||
bfc8e6a9cd | |||
73cba130c3 | |||
c09bc44aa4 | |||
b907e3f469 | |||
8c3bed09e4 | |||
4c99b82bb7 | |||
a6d72761b9 | |||
6c504d30cf | |||
1c814a451b | |||
daafc125c3 | |||
63f680bdc1 | |||
e88a327957 | |||
223c71bc68 | |||
14a04fd200 | |||
dc85511fe9 | |||
d0b8d3f585 | |||
97652917c9 | |||
c171a62f93 | |||
c7c28e7fa2 | |||
79a17788f2 | |||
9f0a2d2fb6 | |||
66f6ce9bd2 | |||
e5dfe7b816 | |||
6efb17be64 | |||
0310b30446 | |||
863cdf3d7f | |||
e51bb2555e | |||
9e0157d679 | |||
3e91eb4fc1 | |||
caf811c23a | |||
de116c9e5a | |||
eef38b0557 | |||
0057899476 | |||
0148e6e27e | |||
c6af859f9d | |||
01f0761ca8 | |||
d7770846aa | |||
0e76ba6464 | |||
fcb44ec845 | |||
cec8195e5e | |||
6c0eb32d75 | |||
9ae5f1d583 | |||
3b60bb9420 | |||
db50c35ad6 | |||
4f05d4e254 | |||
c5a17b217d | |||
fdccb0c5a9 | |||
ccbafef55a | |||
c594134317 | |||
11cfaf44ee | |||
a34678cbcc | |||
26fd99823c | |||
42c305c79b | |||
9585506644 | |||
4317ae0f75 |
@ -132,6 +132,7 @@ Thus, data type modifiers like <code>l</code> or <code>h</code> do not
|
||||
exist in <em>StreamDevice</em> formats.
|
||||
</p>
|
||||
|
||||
<a name="redirection"></a>
|
||||
<h3>Redirection</h3>
|
||||
<p>
|
||||
To use other fields of the record or even fields of other records on the
|
||||
|
@ -88,11 +88,11 @@ many process variables distributed over many records.
|
||||
|
||||
<h2>Recommended Readings</h2>
|
||||
<p>
|
||||
<a href="http://www.aps.anl.gov/epics/base/R3-14/8-docs/AppDevGuide.pdf"
|
||||
target="ex">IOC Application Developer's Guide (PDF)</a>
|
||||
<a href="http://www.aps.anl.gov/epics/base/R3-14/12-docs/AppDevGuide"
|
||||
target="ex">IOC Application Developer's Guide</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="http://www.aps.anl.gov/asd/controls/epics/EpicsDocumentation/AppDevManuals/RecordRef/Recordref-1.html"
|
||||
<a href="https://wiki-ext.aps.anl.gov/epics/index.php/RRM_3-14"
|
||||
target="ex">EPICS Record Reference Manual</a>
|
||||
</p>
|
||||
|
||||
|
@ -178,6 +178,7 @@ div div div a {list-style-type:circle;}
|
||||
<a target="_parent" href="tipsandtricks.html#writemany">Write more than one value in one message</a>
|
||||
<a target="_parent" href="tipsandtricks.html#readmany">Read more than one value from one message</a>
|
||||
<a target="_parent" href="tipsandtricks.html#mixed">Read values of mixed data type</a>
|
||||
<a target="_parent" href="tipsandtricks.html#web">Read a web page</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -261,7 +261,7 @@ number in the range of <code>-128</code> to <code>255</code>,
|
||||
or <code>-0200</code> to <code>0377</code>, respectively.
|
||||
</p>
|
||||
<p>
|
||||
<em>StreamDevice</em> also recordgnizes the ASCII symbolic names
|
||||
<em>StreamDevice</em> also recognizes the ASCII symbolic names
|
||||
(not case sensitive) for several byte codes:<br>
|
||||
<code>NUL </code>(= <code>0x00</code>) <em>null</em><br>
|
||||
<code>SOH </code>(= <code>0x01</code>) <em>start of heading</em><br>
|
||||
|
@ -103,7 +103,7 @@ an array: (3.14, 17.30, -12.34)
|
||||
<h3>B) We have up to 12 numeric values</h3>
|
||||
<p>
|
||||
Use a <a href="calcout.html">calcout</a> record and
|
||||
<a href="formats.html#types">field references</a> in the format.
|
||||
<a href="formats.html#redirection">redirection to fields</a>.
|
||||
</p>
|
||||
<p>
|
||||
<code>
|
||||
@ -128,7 +128,7 @@ record (calcout, "$(RECORD)") {<br>
|
||||
</p>
|
||||
<h3>C) Values are in other records on the same IOC</h3>
|
||||
<p>
|
||||
Use <a href="formats.html#types">record references</a> in the format.
|
||||
Use <a href="formats.html#redirection">redirection to records</a>.
|
||||
</p>
|
||||
<p>
|
||||
<code>
|
||||
@ -216,7 +216,7 @@ Any non-matching input is ignored by record B.
|
||||
</p>
|
||||
<h3>C) Values should be stored in other records on the same IOC</h3>
|
||||
<p>
|
||||
Use <a href="formats.html#types">record references</a> in the format.
|
||||
Use <a href="formats.html#redirection">redirection to records</a>.
|
||||
To avoid record names in protocol files, use
|
||||
<a href="protocol.html#argvar">protocol arguments</a>.
|
||||
</p>
|
||||
@ -244,11 +244,11 @@ processes record B.
|
||||
</p>
|
||||
|
||||
<a name="mixed"></a>
|
||||
<h2>I have a device that sends mixed data types: numbers and strings</h2>
|
||||
<h2>I have a device that sends mixed data types: numbers or strings</h2>
|
||||
<p>
|
||||
Use a <code>@mismatch</code>
|
||||
<a href="protocol.html#except">exception handler</a> and
|
||||
<a href="formats.html#types">record references</a> in the format.
|
||||
<a href="formats.html#redirection">redirection to records</a>.
|
||||
To avoid record names in protocol files, use
|
||||
<a href="protocol.html#argvar">protocol arguments</a>.
|
||||
</p>
|
||||
@ -289,9 +289,124 @@ record (stringout, "$(DEVICE):clean_2") {<br>
|
||||
field (VAL, "OK")<br>
|
||||
field (OUT, "$(DEVICE):message PP")<br>
|
||||
}<br>
|
||||
|
||||
</code>
|
||||
<a name="web"></a>
|
||||
<h2>I need to read a web page</h2>
|
||||
<p>
|
||||
First you have to send a correctly formatted HTML request.
|
||||
Note that this request must contain the full URL like
|
||||
"http://server/page" and must be terminated with <u>two</u> newlines.
|
||||
The server should be the same as in the
|
||||
<a href="setup.html#sta"><code>drvAsynIPPortConfigure</code></a>
|
||||
command (if not using a http proxy).
|
||||
|
||||
The web page you get often contains much more information than you need.
|
||||
<a href="formats.html#regex">Regular expressions</a> are great
|
||||
to find what you are looking for.
|
||||
</p>
|
||||
<h3>Example 1</h3>
|
||||
<p>
|
||||
Read the title of a web page.
|
||||
</p>
|
||||
<p>
|
||||
<code>
|
||||
get_title {<br>
|
||||
extrainput = ignore;<br>
|
||||
replyTimeout = 1000;<br>
|
||||
out "GET http://\$1\n\n";<br>
|
||||
in "%+.1/(?im)<title>(.*)<\/title>/";<br>
|
||||
}
|
||||
</code>
|
||||
</p>
|
||||
<p>
|
||||
Terminate the request with two newlines, either explicit like here
|
||||
<u>or</u> using an
|
||||
<a href="protocol.html#sysvar"><code>outTerminator</code></a>.
|
||||
The URI (without http:// but including the web server host name)
|
||||
is passed as <a href="protocol.html#argvar">argument</a> 1 to <code>\$1</code>.
|
||||
Note that web servers may be slow, so allow some
|
||||
<a href="protocol.html#argvar"><code>replyTimeout</code></a>.
|
||||
</p>
|
||||
<p>
|
||||
If you don't use an <code>inTerminator</code> then the whole page is
|
||||
read as one "line" to the <code>in</code> command and can be parsed easily
|
||||
with a regular expression.
|
||||
We want to see the string between <code><title></code> and
|
||||
<code></title></code>, so we put it into a subexpression in
|
||||
<code>()</code> and request the first subexpression with <code>.1</code>.
|
||||
Note that the <code>/</code> in the closing tag has be be escaped
|
||||
to avoid a misinterpretation as the closing <code>/</code> of the regular
|
||||
expression.
|
||||
</p>
|
||||
<p>
|
||||
The tags may be upper or lower case like <code><TITLE></code> or
|
||||
<code><Title></code>, so we ask for case insensitive matching with
|
||||
<code>(?i)</code>.
|
||||
</p>
|
||||
<p>
|
||||
The string should be terminated with the first closing
|
||||
<code></title></code>, not the last one in the file.
|
||||
(There should not be more than one title but you never know.)
|
||||
Thus we ask not to be greedy with <code>(?m)</code>.
|
||||
<code>(?i)</code> and <code>(?m)</code> can be combined to <code>(?im)</code>.
|
||||
See the PCRE documentation for more regexp syntax.
|
||||
</p>
|
||||
<p>
|
||||
The regular expression matcher ignores and discards any content before the
|
||||
matching section.
|
||||
Content after the match is discarded with <code>extrainput = ignore</code>
|
||||
so that it does not trigger errors reporting "surplus input".
|
||||
</p>
|
||||
<p>
|
||||
Finally, the title may be too long for the record.
|
||||
The <code>+</code> tells the format matcher not to fail in this case
|
||||
but to truncate the string instead.
|
||||
You can read the string with a stringin record or for longer strings with
|
||||
a waveform record with data type CHAR.
|
||||
</p>
|
||||
<p>
|
||||
<code>
|
||||
record (stringin, "$(DEVICE):title") {<br>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@$(DEVICETYPE).proto get_title($(PAGE)) $(BUS)")<br>
|
||||
}<br>
|
||||
record (waveform, "$(DEVICE):longtitle") {<br>
|
||||
field (DTYP, "stream")<br>
|
||||
field (INP, "@$(DEVICETYPE).proto get_title($(PAGE)) $(BUS)")<br>
|
||||
field (FTVL, "CHAR")<br>
|
||||
field (NELM, "100")<br>
|
||||
}<br>
|
||||
</code>
|
||||
</p>
|
||||
|
||||
<h3>Example 2</h3>
|
||||
<p>
|
||||
Read a number from a web page. First we have to locate the number.
|
||||
For that we match against any known string right before the number
|
||||
(and <a href="formats.html#syntax">discard the match</a> with <code>*</code>).
|
||||
Then we read the number.
|
||||
</p>
|
||||
<code>
|
||||
get_title {<br>
|
||||
extrainput = ignore;<br>
|
||||
replyTimeout = 1000;<br>
|
||||
out "GET http://\$1\n\n";<br>
|
||||
in "%*/Interesting value:/%f more text";<br>
|
||||
}
|
||||
</code>
|
||||
<p>
|
||||
When using <code>extrainput = ignore;</code>, it is always a good idea to
|
||||
match a few bytes after the value, too.
|
||||
This catches errors where loading of the page is interrupted in the middle
|
||||
of the number. (You don't want to miss the exponent from something like 1.23E-14).
|
||||
</p>
|
||||
<p>
|
||||
You can read more than one value from a file with successive regular expressions
|
||||
and <a href="formats.html#redirection">redirections</a>.
|
||||
But this only works if the order of the values is predictible.
|
||||
<i>StreamDevice</i> is not an XML parser! It always reads sequentially.
|
||||
</p>
|
||||
<hr>
|
||||
<p><small>Dirk Zimoch, 2007</small></p>
|
||||
<p><small>Dirk Zimoch, 2012</small></p>
|
||||
</body>
|
||||
</html>
|
||||
|
1
makefile
1
makefile
@ -35,6 +35,7 @@ SOURCES += $(BUSSES:%=src/%Interface.cc)
|
||||
SOURCES += $(wildcard src/Stream*.cc)
|
||||
SOURCES += src/StreamVersion.c
|
||||
|
||||
HEADERS += devStream.h
|
||||
HEADERS += StreamFormat.h
|
||||
HEADERS += StreamFormatConverter.h
|
||||
HEADERS += StreamBuffer.h
|
||||
|
@ -22,14 +22,14 @@
|
||||
#include "StreamError.h"
|
||||
#include "StreamBuffer.h"
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
#include <epicsAssert.h>
|
||||
#include <epicsTime.h>
|
||||
#include <epicsTimer.h>
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
#include <assert.h>
|
||||
#include <wdLib.h>
|
||||
#include <sysLib.h>
|
||||
#else
|
||||
#include <epicsAssert.h>
|
||||
#include <epicsTime.h>
|
||||
#include <epicsTimer.h>
|
||||
extern "C" {
|
||||
#include <callback.h>
|
||||
}
|
||||
@ -126,7 +126,7 @@ static const char* ioActionStr[] = {
|
||||
};
|
||||
|
||||
static const char* asynStatusStr[] = {
|
||||
"asynSuccess", "asynTimeout", "asynOverflow", "asynError"
|
||||
"asynSuccess", "asynTimeout", "asynOverflow", "asynError", "asynDisconnected", "asynDisabled"
|
||||
};
|
||||
|
||||
static const char* eomReasonStr[] = {
|
||||
@ -134,7 +134,7 @@ static const char* eomReasonStr[] = {
|
||||
};
|
||||
|
||||
class AsynDriverInterface : StreamBusInterface
|
||||
#ifdef EPICS_3_14
|
||||
#ifndef EPICS_3_13
|
||||
, epicsTimerNotify
|
||||
#endif
|
||||
{
|
||||
@ -164,12 +164,12 @@ class AsynDriverInterface : StreamBusInterface
|
||||
const char* outputBuffer;
|
||||
size_t outputSize;
|
||||
int peeksize;
|
||||
#ifdef EPICS_3_14
|
||||
epicsTimerQueueActive* timerQueue;
|
||||
epicsTimer* timer;
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
WDOG_ID timer;
|
||||
CALLBACK timeoutCallback;
|
||||
#else
|
||||
epicsTimerQueueActive* timerQueue;
|
||||
epicsTimer* timer;
|
||||
#endif
|
||||
|
||||
AsynDriverInterface(Client* client);
|
||||
@ -189,16 +189,16 @@ class AsynDriverInterface : StreamBusInterface
|
||||
bool disconnectRequest();
|
||||
void finish();
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
#ifdef EPICS_3_13
|
||||
static void expire(CALLBACK *pcallback);
|
||||
#else
|
||||
// epicsTimerNotify methods
|
||||
epicsTimerNotify::expireStatus expire(const epicsTime &);
|
||||
#else
|
||||
static void expire(CALLBACK *pcallback);
|
||||
#endif
|
||||
|
||||
// local methods
|
||||
void timerExpired();
|
||||
bool connectToBus(const char* busname, int addr);
|
||||
bool connectToBus(const char* portname, int addr);
|
||||
void lockHandler();
|
||||
void writeHandler();
|
||||
void readHandler();
|
||||
@ -211,20 +211,22 @@ class AsynDriverInterface : StreamBusInterface
|
||||
(StreamBusInterface::priority());
|
||||
}
|
||||
void startTimer(double timeout) {
|
||||
#ifdef EPICS_3_14
|
||||
timer->start(*this, timeout);
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
callbackSetPriority(priority(), &timeoutCallback);
|
||||
wdStart(timer, (int)((timeout+1)*sysClkRateGet())-1,
|
||||
reinterpret_cast<FUNCPTR>(callbackRequest),
|
||||
reinterpret_cast<int>(&timeoutCallback));
|
||||
#else
|
||||
timer->start(*this, timeout
|
||||
+epicsThreadSleepQuantum()*0.5
|
||||
);
|
||||
#endif
|
||||
}
|
||||
void cancelTimer() {
|
||||
#ifdef EPICS_3_14
|
||||
timer->cancel();
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
wdCancel(timer);
|
||||
#else
|
||||
timer->cancel();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -240,7 +242,7 @@ class AsynDriverInterface : StreamBusInterface
|
||||
public:
|
||||
// static creator method
|
||||
static StreamBusInterface* getBusInterface(Client* client,
|
||||
const char* busname, int addr, const char* param);
|
||||
const char* portname, int addr, const char* param);
|
||||
};
|
||||
|
||||
RegisterStreamBusInterface(AsynDriverInterface);
|
||||
@ -248,6 +250,7 @@ RegisterStreamBusInterface(AsynDriverInterface);
|
||||
AsynDriverInterface::
|
||||
AsynDriverInterface(Client* client) : StreamBusInterface(client)
|
||||
{
|
||||
debug ("AsynDriverInterface(%s)\n", client->name());
|
||||
pasynCommon = NULL;
|
||||
pasynOctet = NULL;
|
||||
intrPvtOctet = NULL;
|
||||
@ -259,20 +262,25 @@ AsynDriverInterface(Client* client) : StreamBusInterface(client)
|
||||
eventMask = 0;
|
||||
receivedEvent = 0;
|
||||
peeksize = 1;
|
||||
debug ("AsynDriverInterface(%s) createAsynUser\n", client->name());
|
||||
pasynUser = pasynManager->createAsynUser(handleRequest,
|
||||
handleTimeout);
|
||||
assert(pasynUser);
|
||||
pasynUser->userPvt = this;
|
||||
#ifdef EPICS_3_14
|
||||
timerQueue = &epicsTimerQueueActive::allocate(true);
|
||||
assert(timerQueue);
|
||||
timer = &timerQueue->createTimer();
|
||||
assert(timer);
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
debug ("AsynDriverInterface(%s) wdCreate()\n", client->name());
|
||||
timer = wdCreate();
|
||||
callbackSetCallback(expire, &timeoutCallback);
|
||||
callbackSetUser(this, &timeoutCallback);
|
||||
#else
|
||||
debug ("AsynDriverInterface(%s) epicsTimerQueueActive::allocate(true)\n", client->name());
|
||||
timerQueue = &epicsTimerQueueActive::allocate(true);
|
||||
assert(timerQueue);
|
||||
debug ("AsynDriverInterface(%s) timerQueue->createTimer()\n", client->name());
|
||||
timer = &timerQueue->createTimer();
|
||||
assert(timer);
|
||||
#endif
|
||||
debug ("AsynDriverInterface(%s) done\n", client->name());
|
||||
}
|
||||
|
||||
AsynDriverInterface::
|
||||
@ -306,11 +314,11 @@ AsynDriverInterface::
|
||||
}
|
||||
// Now, no handler is running any more and none will start.
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
#ifdef EPICS_3_13
|
||||
wdDelete(timer);
|
||||
#else
|
||||
timer->destroy();
|
||||
timerQueue->release();
|
||||
#else
|
||||
wdDelete(timer);
|
||||
#endif
|
||||
pasynManager->disconnect(pasynUser);
|
||||
pasynManager->freeAsynUser(pasynUser);
|
||||
@ -318,17 +326,19 @@ AsynDriverInterface::
|
||||
}
|
||||
|
||||
// interface function getBusInterface():
|
||||
// do we have this bus/addr ?
|
||||
// do we have this port/addr ?
|
||||
StreamBusInterface* AsynDriverInterface::
|
||||
getBusInterface(Client* client,
|
||||
const char* busname, int addr, const char*)
|
||||
const char* portname, int addr, const char*)
|
||||
{
|
||||
debug ("AsynDriverInterface::getBusInterface(%s, %s, %d)\n",
|
||||
client->name(), portname, addr);
|
||||
AsynDriverInterface* interface = new AsynDriverInterface(client);
|
||||
if (interface->connectToBus(busname, addr))
|
||||
if (interface->connectToBus(portname, addr))
|
||||
{
|
||||
debug ("AsynDriverInterface::getBusInterface(%s, %d): "
|
||||
"new Interface allocated\n",
|
||||
busname, addr);
|
||||
"new interface allocated\n",
|
||||
portname, addr);
|
||||
return interface;
|
||||
}
|
||||
delete interface;
|
||||
@ -340,7 +350,66 @@ getBusInterface(Client* client,
|
||||
bool AsynDriverInterface::
|
||||
supportsEvent()
|
||||
{
|
||||
return (pasynInt32 != NULL) || (pasynUInt32 != NULL);
|
||||
if (intrPvtInt32 || intrPvtUInt32) return true;
|
||||
|
||||
// look for interfaces for events
|
||||
asynInterface* pasynInterface;
|
||||
|
||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||
asynInt32Type, true);
|
||||
if (pasynInterface)
|
||||
{
|
||||
pasynInt32 = static_cast<asynInt32*>(pasynInterface->pinterface);
|
||||
pvtInt32 = pasynInterface->drvPvt;
|
||||
pasynUser->reason = ASYN_REASON_SIGNAL; // required for GPIB
|
||||
if (pasynInt32->registerInterruptUser(pvtInt32, pasynUser,
|
||||
intrCallbackInt32, this, &intrPvtInt32) == asynSuccess)
|
||||
{
|
||||
printf ("%s: AsynDriverInterface::supportsEvent: "
|
||||
"pasynInt32->registerInterruptUser(%p, %p, %p, %p, %p)\n",
|
||||
clientName(), pvtInt32, pasynUser,
|
||||
intrCallbackInt32, this, &intrPvtInt32);
|
||||
return true;
|
||||
}
|
||||
const char *portname;
|
||||
pasynManager->getPortName(pasynUser, &portname);
|
||||
error("%s: port %s does not allow to register for "
|
||||
"Int32 interrupts: %s\n",
|
||||
clientName(), portname, pasynUser->errorMessage);
|
||||
pasynInt32 = NULL;
|
||||
intrPvtInt32 = NULL;
|
||||
}
|
||||
|
||||
// no asynInt32 available, thus try asynUInt32
|
||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||
asynUInt32DigitalType, true);
|
||||
if (pasynInterface)
|
||||
{
|
||||
pasynUInt32 =
|
||||
static_cast<asynUInt32Digital*>(pasynInterface->pinterface);
|
||||
pvtUInt32 = pasynInterface->drvPvt;
|
||||
pasynUser->reason = ASYN_REASON_SIGNAL;
|
||||
if (pasynUInt32->registerInterruptUser(pvtUInt32,
|
||||
pasynUser, intrCallbackUInt32, this, 0xFFFFFFFF,
|
||||
&intrPvtUInt32) == asynSuccess)
|
||||
{
|
||||
printf ("%s: AsynDriverInterface::supportsEvent: "
|
||||
"pasynUInt32->registerInterruptUser(%p, %p, %p, %p, %#X, %p)\n",
|
||||
clientName(), pvtUInt32, pasynUser,
|
||||
intrCallbackUInt32, this, 0xFFFFFFFF, &intrPvtInt32);
|
||||
return true;
|
||||
}
|
||||
const char *portname;
|
||||
pasynManager->getPortName(pasynUser, &portname);
|
||||
error("%s: port %s does not allow to register for "
|
||||
"UInt32 interrupts: %s\n",
|
||||
clientName(), portname, pasynUser->errorMessage);
|
||||
pasynUInt32 = NULL;
|
||||
intrPvtUInt32 = NULL;
|
||||
}
|
||||
|
||||
// no event interface available
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AsynDriverInterface::
|
||||
@ -352,20 +421,32 @@ supportsAsyncRead()
|
||||
if (pasynOctet->registerInterruptUser(pvtOctet, pasynUser,
|
||||
intrCallbackOctet, this, &intrPvtOctet) != asynSuccess)
|
||||
{
|
||||
error("%s: bus does not support asynchronous input: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
const char *portname;
|
||||
int addr;
|
||||
pasynManager->getPortName(pasynUser, &portname);
|
||||
pasynManager->getAddr(pasynUser, &addr);
|
||||
if (addr >= 0)
|
||||
error("%s: asyn port %s addr %d does not support asynchronous input: %s\n",
|
||||
clientName(), portname, addr, pasynUser->errorMessage);
|
||||
else
|
||||
error("%s: asyn port %s does not support asynchronous input: %s\n",
|
||||
clientName(), portname, pasynUser->errorMessage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AsynDriverInterface::
|
||||
connectToBus(const char* busname, int addr)
|
||||
connectToBus(const char* portname, int addr)
|
||||
{
|
||||
if (pasynManager->connectDevice(pasynUser, busname, addr) !=
|
||||
asynSuccess)
|
||||
asynStatus status = pasynManager->connectDevice(pasynUser, portname, addr);
|
||||
debug("%s: AsynDriverInterface::connectToBus(%s, %d): "
|
||||
"pasynManager->connectDevice(%p, %s, %d) = %s\n",
|
||||
clientName(), portname, addr, pasynUser,portname, addr,
|
||||
asynStatusStr[status]);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
// asynDriver does not know this busname/address
|
||||
// asynDriver does not know this portname/address
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -374,10 +455,10 @@ connectToBus(const char* busname, int addr)
|
||||
// find the asynCommon interface
|
||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||
asynCommonType, true);
|
||||
if(!pasynInterface)
|
||||
if (!pasynInterface)
|
||||
{
|
||||
error("%s: bus %s does not support asynCommon interface\n",
|
||||
clientName(), busname);
|
||||
error("%s: asyn port %s does not support asynCommon interface\n",
|
||||
clientName(), portname);
|
||||
return false;
|
||||
}
|
||||
pasynCommon = static_cast<asynCommon*>(pasynInterface->pinterface);
|
||||
@ -386,10 +467,10 @@ connectToBus(const char* busname, int addr)
|
||||
// find the asynOctet interface
|
||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||
asynOctetType, true);
|
||||
if(!pasynInterface)
|
||||
if (!pasynInterface)
|
||||
{
|
||||
error("%s: bus %s does not support asynOctet interface\n",
|
||||
clientName(), busname);
|
||||
error("%s: asyn port %s does not support asynOctet interface\n",
|
||||
clientName(), portname);
|
||||
return false;
|
||||
}
|
||||
pasynOctet = static_cast<asynOctet*>(pasynInterface->pinterface);
|
||||
@ -398,7 +479,7 @@ connectToBus(const char* busname, int addr)
|
||||
// is it a GPIB interface ?
|
||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||
asynGpibType, true);
|
||||
if(pasynInterface)
|
||||
if (pasynInterface)
|
||||
{
|
||||
pasynGpib = static_cast<asynGpib*>(pasynInterface->pinterface);
|
||||
pvtGpib = pasynInterface->drvPvt;
|
||||
@ -406,50 +487,6 @@ connectToBus(const char* busname, int addr)
|
||||
// (read only one byte first).
|
||||
peeksize = inputBuffer.capacity();
|
||||
}
|
||||
|
||||
// look for interfaces for events
|
||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||
asynInt32Type, true);
|
||||
if(pasynInterface)
|
||||
{
|
||||
pasynInt32 = static_cast<asynInt32*>(pasynInterface->pinterface);
|
||||
pvtInt32 = pasynInterface->drvPvt;
|
||||
pasynUser->reason = ASYN_REASON_SIGNAL; // required for GPIB
|
||||
if (pasynInt32->registerInterruptUser(pvtInt32, pasynUser,
|
||||
intrCallbackInt32, this, &intrPvtInt32) == asynSuccess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
error("%s: bus %s does not allow to register for "
|
||||
"Int32 interrupts: %s\n",
|
||||
clientName(), busname, pasynUser->errorMessage);
|
||||
pasynInt32 = NULL;
|
||||
intrPvtInt32 = NULL;
|
||||
}
|
||||
|
||||
// no asynInt32 available, thus try asynUInt32
|
||||
pasynInterface = pasynManager->findInterface(pasynUser,
|
||||
asynUInt32DigitalType, true);
|
||||
if(pasynInterface)
|
||||
{
|
||||
pasynUInt32 =
|
||||
static_cast<asynUInt32Digital*>(pasynInterface->pinterface);
|
||||
pvtUInt32 = pasynInterface->drvPvt;
|
||||
pasynUser->reason = ASYN_REASON_SIGNAL;
|
||||
if (pasynUInt32->registerInterruptUser(pvtUInt32,
|
||||
pasynUser, intrCallbackUInt32, this, 0xFFFFFFFF,
|
||||
&intrPvtUInt32) == asynSuccess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
error("%s: bus %s does not allow to register for "
|
||||
"UInt32 interrupts: %s\n",
|
||||
clientName(), busname, pasynUser->errorMessage);
|
||||
pasynUInt32 = NULL;
|
||||
intrPvtUInt32 = NULL;
|
||||
}
|
||||
|
||||
// no event interface available, never mind
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -458,23 +495,14 @@ connectToBus(const char* busname, int addr)
|
||||
bool AsynDriverInterface::
|
||||
lockRequest(unsigned long lockTimeout_ms)
|
||||
{
|
||||
int connected;
|
||||
asynStatus status;
|
||||
|
||||
debug("AsynDriverInterface::lockRequest(%s, %ld msec)\n",
|
||||
clientName(), lockTimeout_ms);
|
||||
lockTimeout = lockTimeout_ms ? lockTimeout_ms*0.001 : -1.0;
|
||||
ioAction = Lock;
|
||||
status = pasynManager->isConnected(pasynUser, &connected);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
error("%s: pasynManager->isConnected() failed: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
return false;
|
||||
}
|
||||
status = pasynManager->queueRequest(pasynUser,
|
||||
connected ? priority() : asynQueuePriorityConnect,
|
||||
lockTimeout);
|
||||
priority(), lockTimeout);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
error("%s lockRequest: pasynManager->queueRequest() failed: %s\n",
|
||||
@ -496,9 +524,13 @@ connectToAsynPort()
|
||||
debug("AsynDriverInterface::connectToAsynPort(%s)\n",
|
||||
clientName());
|
||||
status = pasynManager->isConnected(pasynUser, &connected);
|
||||
debug("%s: AsynDriverInterface::connectToAsynPort: "
|
||||
"pasynManager->isConnected(%p, %p) = %s => %s\n",
|
||||
clientName(), pasynUser, &connected, asynStatusStr[status],
|
||||
connected ? "yes" : "no");
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
error("%s: pasynManager->isConnected() failed: %s\n",
|
||||
error("%s connectToAsynPort: pasynManager->isConnected() failed: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
return false;
|
||||
}
|
||||
@ -516,7 +548,7 @@ connectToAsynPort()
|
||||
status = pasynOctet->read(pvtOctet, pasynUser,
|
||||
buffer, 0, &received, &eomReason);
|
||||
debug("AsynDriverInterface::connectToAsynPort(%s): "
|
||||
"read(..., 0, ...) [timeout=%f seconds] = %s\n",
|
||||
"read(..., 0, ...) [timeout=%g sec] = %s\n",
|
||||
clientName(), pasynUser->timeout,
|
||||
asynStatusStr[status]);
|
||||
pasynManager->isConnected(pasynUser, &connected);
|
||||
@ -530,13 +562,19 @@ connectToAsynPort()
|
||||
clientName(), connected ? "already" : "not yet");
|
||||
if (!connected)
|
||||
{
|
||||
printf ("%s: AsynDriverInterface::connectToAsynPort: "
|
||||
"pasynCommon->connect(%p, %p)\n",
|
||||
clientName(), pvtCommon, pasynUser);
|
||||
status = pasynCommon->connect(pvtCommon, pasynUser);
|
||||
printf ("%s: AsynDriverInterface::connectToAsynPort: "
|
||||
"pasynCommon->connect(%p, %p) = %s\n",
|
||||
clientName(), pvtCommon, pasynUser, asynStatusStr[status]);
|
||||
debug("AsynDriverInterface::connectToAsynPort(%s): "
|
||||
"status=%s\n",
|
||||
clientName(), asynStatusStr[status]);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
error("%s: pasynCommon->connect() failed: %s\n",
|
||||
error("%s connectToAsynPort: pasynCommon->connect() failed: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
return false;
|
||||
}
|
||||
@ -554,21 +592,37 @@ connectToAsynPort()
|
||||
void AsynDriverInterface::
|
||||
lockHandler()
|
||||
{
|
||||
int connected;
|
||||
asynStatus status;
|
||||
|
||||
debug("AsynDriverInterface::lockHandler(%s)\n",
|
||||
clientName());
|
||||
pasynManager->blockProcessCallback(pasynUser, false);
|
||||
connected = connectToAsynPort();
|
||||
lockCallback(connected ? StreamIoSuccess : StreamIoFault);
|
||||
|
||||
status = pasynManager->blockProcessCallback(pasynUser, false);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
error("%s lockHandler: pasynManager->blockProcessCallback() failed: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
lockCallback(StreamIoFault);
|
||||
return;
|
||||
}
|
||||
lockCallback(StreamIoSuccess);
|
||||
}
|
||||
|
||||
// interface function: we don't need exclusive access any more
|
||||
bool AsynDriverInterface::
|
||||
unlock()
|
||||
{
|
||||
asynStatus status;
|
||||
|
||||
debug("AsynDriverInterface::unlock(%s)\n",
|
||||
clientName());
|
||||
pasynManager->unblockProcessCallback(pasynUser, false);
|
||||
status = pasynManager->unblockProcessCallback(pasynUser, false);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
error("%s unlock: pasynManager->unblockProcessCallback() failed: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -610,19 +664,39 @@ writeHandler()
|
||||
clientName());
|
||||
asynStatus status;
|
||||
size_t written = 0;
|
||||
pasynUser->timeout = writeTimeout;
|
||||
|
||||
// discard any early input or early events
|
||||
status = pasynOctet->flush(pvtOctet, pasynUser);
|
||||
receivedEvent = 0;
|
||||
|
||||
if (status != asynSuccess)
|
||||
pasynUser->timeout = 0;
|
||||
if (!pasynGpib)
|
||||
// discard any early input, but forward it to potential async records
|
||||
// thus do not use pasynOctet->flush()
|
||||
// unfortunately we cannot do this with GPIB because addressing a device as talker
|
||||
// when it has nothing to say is an error. Also timeout=0 does not help here (would need
|
||||
// a change in asynGPIB), thus use flush() for GPIB.
|
||||
do {
|
||||
char buffer [256];
|
||||
size_t received = 0;
|
||||
int eomReason = 0;
|
||||
debug("AsynDriverInterface::writeHandler(%s): reading old input\n",
|
||||
clientName());
|
||||
status = pasynOctet->read(pvtOctet, pasynUser,
|
||||
buffer, sizeof(buffer), &received, &eomReason);
|
||||
if (received == 0) break;
|
||||
#ifndef NO_TEMPORARY
|
||||
if (received) debug("AsynDriverInterface::writeHandler(%s): flushing %ld bytes: \"%s\"\n",
|
||||
clientName(), (long)received, StreamBuffer(buffer, received).expand()());
|
||||
#endif
|
||||
} while (status == asynSuccess);
|
||||
else
|
||||
{
|
||||
error("%s: pasynOctet->flush() failed: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
debug("AsynDriverInterface::writeHandler(%s): flushing old input\n",
|
||||
clientName());
|
||||
pasynOctet->flush(pvtOctet, pasynUser);
|
||||
}
|
||||
|
||||
// discard any early events
|
||||
receivedEvent = 0;
|
||||
|
||||
pasynUser->timeout = writeTimeout;
|
||||
|
||||
// has stream already added a terminator or should
|
||||
// asyn do so?
|
||||
@ -648,10 +722,16 @@ writeHandler()
|
||||
outputBuffer, outputSize, &written);
|
||||
debug("AsynDriverInterface::writeHandler(%s): "
|
||||
"write(..., outputSize=%ld, written=%ld) "
|
||||
"[timeout=%f seconds] = %s\n",
|
||||
"[timeout=%g sec] = %s\n",
|
||||
clientName(), (long)outputSize, (long)written,
|
||||
pasynUser->timeout, asynStatusStr[status]);
|
||||
|
||||
if (oldeoslen >= 0) // restore asyn terminator
|
||||
{
|
||||
pasynOctet->setOutputEos(pvtOctet, pasynUser,
|
||||
oldeos, oldeoslen);
|
||||
}
|
||||
|
||||
// Up to asyn 4.17 I can't see when the server has disconnected. Why?
|
||||
int connected;
|
||||
pasynManager->isConnected(pasynUser, &connected);
|
||||
@ -659,17 +739,12 @@ writeHandler()
|
||||
"device is %sconnected\n",
|
||||
clientName(),connected?"":"dis");
|
||||
if (!connected) {
|
||||
error("%s: connection closed in write\n",
|
||||
error("%s: write failed because connection was closed by device\n",
|
||||
clientName());
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldeoslen >= 0) // restore asyn terminator
|
||||
{
|
||||
pasynOctet->setOutputEos(pvtOctet, pasynUser,
|
||||
oldeos, oldeoslen);
|
||||
}
|
||||
switch (status)
|
||||
{
|
||||
case asynSuccess:
|
||||
@ -694,32 +769,34 @@ writeHandler()
|
||||
writeCallback(StreamIoSuccess);
|
||||
return;
|
||||
case asynTimeout:
|
||||
error("%s: asynTimeout (%g sec) in write. Asyn says: %s\n",
|
||||
clientName(), pasynUser->timeout, pasynUser->errorMessage);
|
||||
writeCallback(StreamIoTimeout);
|
||||
return;
|
||||
case asynOverflow:
|
||||
error("%s: asynOverflow in write: %s\n",
|
||||
error("%s: asynOverflow in write. Asyn driver says: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
case asynError:
|
||||
error("%s: asynError in write: %s\n",
|
||||
error("%s: asynError in write. Asyn driver says: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
#ifdef ASYN_VERSION // asyn >= 4.14
|
||||
case asynDisconnected:
|
||||
error("%s: asynDisconnected in write: %s\n",
|
||||
error("%s: asynDisconnected in write. Asyn driver says: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
case asynDisabled:
|
||||
error("%s: asynDisconnected in write: %s\n",
|
||||
error("%s: asynDisconnected in write. Asyn driver says: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
error("%s: unknown asyn error in write: %s\n",
|
||||
error("%s: unknown asyn error in write. Asyn driver says: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
writeCallback(StreamIoFault);
|
||||
return;
|
||||
@ -732,7 +809,7 @@ readRequest(unsigned long replyTimeout_ms, unsigned long readTimeout_ms,
|
||||
long _expectedLength, bool async)
|
||||
{
|
||||
debug("AsynDriverInterface::readRequest(%s, %ld msec reply, "
|
||||
"%ld msec read, expect %ld bytes, asyn=%s)\n",
|
||||
"%ld msec read, expect %ld bytes, async=%s)\n",
|
||||
clientName(), replyTimeout_ms, readTimeout_ms,
|
||||
_expectedLength, async?"yes":"no");
|
||||
|
||||
@ -756,8 +833,20 @@ readRequest(unsigned long replyTimeout_ms, unsigned long readTimeout_ms,
|
||||
}
|
||||
status = pasynManager->queueRequest(pasynUser,
|
||||
priority(), queueTimeout);
|
||||
if (status != asynSuccess && !async)
|
||||
debug("AsynDriverInterface::readRequest %s: "
|
||||
"queueRequest(..., priority=%d, queueTimeout=%g sec) = %s [async=%s] %s\n",
|
||||
clientName(), priority(), queueTimeout,
|
||||
asynStatusStr[status], async? "true" : "false",
|
||||
status!=asynSuccess ? pasynUser->errorMessage : "");
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
// Not queued for some reason (e.g. disconnected / already queued)
|
||||
if (async)
|
||||
{
|
||||
// silently try again later
|
||||
startTimer(replyTimeout);
|
||||
return true;
|
||||
}
|
||||
error("%s readRequest: pasynManager->queueRequest() failed: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
return false;
|
||||
@ -863,27 +952,26 @@ readHandler()
|
||||
received = 0;
|
||||
eomReason = 0;
|
||||
|
||||
debug("AsynDriverInterface::readHandler(%s): ioAction=%s "
|
||||
"read(..., bytesToRead=%ld, ...) "
|
||||
"[timeout=%g sec]\n",
|
||||
clientName(), ioActionStr[ioAction],
|
||||
bytesToRead, pasynUser->timeout);
|
||||
status = pasynOctet->read(pvtOctet, pasynUser,
|
||||
buffer, bytesToRead, &received, &eomReason);
|
||||
if (ioAction == Read || status != asynTimeout)
|
||||
{
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"read(..., bytesToRead=%ld, received=%ld...) "
|
||||
"[timeout=%f seconds] = %s\n",
|
||||
clientName(), bytesToRead, (long)received,
|
||||
pasynUser->timeout, asynStatusStr[status]);
|
||||
}
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"read returned %s: ioAction=%s received=%ld, eomReason=%s, buffer=\"%s\"\n",
|
||||
clientName(), asynStatusStr[status], ioActionStr[ioAction],
|
||||
(long)received,eomReasonStr[eomReason&0x7],
|
||||
StreamBuffer(buffer, received).expand()());
|
||||
|
||||
pasynManager->isConnected(pasynUser, &connected);
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"device is %sconnected\n",
|
||||
clientName(),connected?"":"dis");
|
||||
if (!connected) {
|
||||
error("%s: connection closed in read\n",
|
||||
clientName());
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
}
|
||||
// pasynOctet->read() has already cut off terminator.
|
||||
"device is now %sconnected\n",
|
||||
clientName(),connected?"":"dis");
|
||||
// asyn 4.16 sets reason to ASYN_EOM_END when device disconnects.
|
||||
// What about earlier versions?
|
||||
if (!connected) eomReason |= ASYN_EOM_END;
|
||||
|
||||
if (status == asynTimeout &&
|
||||
pasynUser->timeout == 0.0 &&
|
||||
@ -910,6 +998,7 @@ readHandler()
|
||||
#endif
|
||||
// ignore what we got from here.
|
||||
// input was already handeled by asynReadHandler()
|
||||
|
||||
// read until no more input is available
|
||||
readMore = -1;
|
||||
break;
|
||||
@ -959,6 +1048,9 @@ readHandler()
|
||||
// reply timeout
|
||||
if (ioAction == AsyncRead)
|
||||
{
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"no async input, retry in in %g seconds\n",
|
||||
clientName(), replyTimeout);
|
||||
// start next poll after timer expires
|
||||
if (replyTimeout != 0.0) startTimer(replyTimeout);
|
||||
// continues with:
|
||||
@ -975,7 +1067,7 @@ readHandler()
|
||||
// read timeout
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("AsynDriverInterface::readHandler(%s): "
|
||||
"ioAction=%s, timeout [%f seconds] "
|
||||
"ioAction=%s, timeout [%g sec] "
|
||||
"after %ld of %ld bytes \"%s\"\n",
|
||||
clientName(), ioActionStr[ioAction], pasynUser->timeout,
|
||||
(long)received, bytesToRead,
|
||||
@ -1002,29 +1094,29 @@ readHandler()
|
||||
}
|
||||
peeksize = inputBuffer.capacity();
|
||||
// deliver whatever we could save
|
||||
error("%s: asynOverflow in read: %s\n",
|
||||
error("%s: asynOverflow in read. Asyn driver says: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
readCallback(StreamIoFault, buffer, received);
|
||||
break;
|
||||
case asynError:
|
||||
error("%s: asynError in read: %s\n",
|
||||
error("%s: asynError in read. Asyn driver says: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
readCallback(StreamIoFault, buffer, received);
|
||||
break;
|
||||
#ifdef ASYN_VERSION // asyn >= 4.14
|
||||
case asynDisconnected:
|
||||
error("%s: asynDisconnected in read: %s\n",
|
||||
error("%s: asynDisconnected in read. Asyn driver says: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
case asynDisabled:
|
||||
error("%s: asynDisconnected in read: %s\n",
|
||||
error("%s: asynDisconnected in read. Asyn driver says: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
error("%s: unknown asyn error in read: %s\n",
|
||||
error("%s: unknown asyn error in read. Asyn driver says: %s\n",
|
||||
clientName(), pasynUser->errorMessage);
|
||||
readCallback(StreamIoFault);
|
||||
return;
|
||||
@ -1187,7 +1279,7 @@ acceptEvent(unsigned long mask, unsigned long replytimeout_ms)
|
||||
}
|
||||
eventMask = mask;
|
||||
ioAction = ReceiveEvent;
|
||||
startTimer(replytimeout_ms*0.001);
|
||||
if (replytimeout_ms) startTimer(replytimeout_ms*0.001);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1236,6 +1328,9 @@ timerExpired()
|
||||
int autoconnect, connected;
|
||||
switch (ioAction)
|
||||
{
|
||||
case None:
|
||||
// Timeout of async poll crossed with parasitic input
|
||||
return;
|
||||
case ReceiveEvent:
|
||||
// timeout while waiting for event
|
||||
ioAction = None;
|
||||
@ -1254,6 +1349,8 @@ timerExpired()
|
||||
// queueRequest might fail if another request was just queued
|
||||
pasynManager->isAutoConnect(pasynUser, &autoconnect);
|
||||
pasynManager->isConnected(pasynUser, &connected);
|
||||
debug("%s: polling for I/O Intr: autoconnected: %d, connect: %d\n",
|
||||
clientName(), autoconnect, connected);
|
||||
if (autoconnect && !connected)
|
||||
{
|
||||
// has explicitely been disconnected
|
||||
@ -1264,8 +1361,14 @@ timerExpired()
|
||||
else
|
||||
{
|
||||
// queue for read poll (no timeout)
|
||||
pasynManager->queueRequest(pasynUser,
|
||||
asynStatus status = pasynManager->queueRequest(pasynUser,
|
||||
asynQueuePriorityLow, -1.0);
|
||||
// if this fails, we are already queued by another thread
|
||||
debug("AsynDriverInterface::timerExpired %s: "
|
||||
"queueRequest(..., priority=Low, queueTimeout=-1) = %s %s\n",
|
||||
clientName(), asynStatusStr[status],
|
||||
status!=asynSuccess ? pasynUser->errorMessage : "");
|
||||
if (status != asynSuccess) startTimer(replyTimeout);
|
||||
// continues with:
|
||||
// handleRequest() -> readHandler() -> readCallback()
|
||||
}
|
||||
@ -1277,14 +1380,7 @@ timerExpired()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
epicsTimerNotify::expireStatus AsynDriverInterface::
|
||||
expire(const epicsTime &)
|
||||
{
|
||||
timerExpired();
|
||||
return noRestart;
|
||||
}
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
void AsynDriverInterface::
|
||||
expire(CALLBACK *pcallback)
|
||||
{
|
||||
@ -1292,6 +1388,13 @@ expire(CALLBACK *pcallback)
|
||||
static_cast<AsynDriverInterface*>(pcallback->user);
|
||||
interface->timerExpired();
|
||||
}
|
||||
#else
|
||||
epicsTimerNotify::expireStatus AsynDriverInterface::
|
||||
expire(const epicsTime &)
|
||||
{
|
||||
timerExpired();
|
||||
return noRestart;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool AsynDriverInterface::
|
||||
@ -1390,6 +1493,7 @@ void handleRequest(asynUser* pasynUser)
|
||||
{
|
||||
AsynDriverInterface* interface =
|
||||
static_cast<AsynDriverInterface*>(pasynUser->userPvt);
|
||||
interface->cancelTimer();
|
||||
debug("AsynDriverInterface::handleRequest(%s) %s\n",
|
||||
interface->clientName(), ioActionStr[interface->ioAction]);
|
||||
switch (interface->ioAction)
|
||||
|
@ -130,9 +130,10 @@ scanLong(const StreamFormat& format, const char* input, long& value)
|
||||
int width = format.width;
|
||||
if (width == 0) width = -1;
|
||||
int length = 0;
|
||||
while (isspace(input[length])) length++; // skip whitespaces
|
||||
char zero = format.info[0];
|
||||
char one = format.info[1];
|
||||
if (!isspace(zero) && !isspace(one))
|
||||
while (isspace(input[length])) length++; // skip whitespaces
|
||||
if (input[length] != zero && input[length] != one) return -1;
|
||||
if (format.flags & alt_flag)
|
||||
{
|
||||
|
@ -27,12 +27,9 @@
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned int (*checksumFunc)(const unsigned char* data, unsigned int len, unsigned int init);
|
||||
|
||||
typedef ulong (*checksumFunc)(const uchar* data, ulong len, ulong init);
|
||||
|
||||
static ulong sum(const uchar* data, ulong len, ulong sum)
|
||||
static unsigned int sum(const unsigned char* data, unsigned int len, unsigned int sum)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
@ -41,7 +38,7 @@ static ulong sum(const uchar* data, ulong len, ulong sum)
|
||||
return sum;
|
||||
}
|
||||
|
||||
static ulong xor8(const uchar* data, ulong len, ulong sum)
|
||||
static unsigned int xor8(const unsigned char* data, unsigned int len, unsigned int sum)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
@ -50,15 +47,15 @@ static ulong xor8(const uchar* data, ulong len, ulong sum)
|
||||
return sum;
|
||||
}
|
||||
|
||||
static ulong xor7(const uchar* data, ulong len, ulong sum)
|
||||
static unsigned int xor7(const unsigned char* data, unsigned int len, unsigned int sum)
|
||||
{
|
||||
return xor8(data, len, sum) & 0x7F;
|
||||
}
|
||||
|
||||
static ulong crc_0x07(const uchar* data, ulong len, ulong crc)
|
||||
static unsigned int crc_0x07(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||
{
|
||||
// x^8 + x^2 + x^1 + x^0 (0x07)
|
||||
const static uchar table[256] = {
|
||||
const static unsigned char table[256] = {
|
||||
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
|
||||
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
|
||||
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
|
||||
@ -96,10 +93,10 @@ static ulong crc_0x07(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x31(const uchar* data, ulong len, ulong crc)
|
||||
static unsigned int crc_0x31(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||
{
|
||||
// x^8 + x^5 + x^4 + x^0 (0x31)
|
||||
const static uchar table[256] = {
|
||||
const static unsigned char table[256] = {
|
||||
0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83,
|
||||
0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
|
||||
0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e,
|
||||
@ -137,7 +134,7 @@ static ulong crc_0x31(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x8005(const uchar* data, ulong len, ulong crc)
|
||||
static unsigned int crc_0x8005(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||
{
|
||||
// x^16 + x^15 + x^2 + x^0 (0x8005)
|
||||
const static unsigned short table[256] = {
|
||||
@ -178,7 +175,7 @@ static ulong crc_0x8005(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x8005_r(const uchar* data, ulong len, ulong crc)
|
||||
static unsigned int crc_0x8005_r(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||
{
|
||||
// x^16 + x^15 + x^2 + x^0 (0x8005)
|
||||
// reflected
|
||||
@ -220,7 +217,7 @@ static ulong crc_0x8005_r(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x1021(const uchar* data, ulong len, ulong crc)
|
||||
static unsigned int crc_0x1021(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||
{
|
||||
// x^16 + x^12 + x^5 + x^0 (0x1021)
|
||||
const static unsigned short table[256] = {
|
||||
@ -261,7 +258,7 @@ static ulong crc_0x1021(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x04C11DB7(const uchar* data, ulong len, ulong crc)
|
||||
static unsigned int crc_0x04C11DB7(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||
{
|
||||
// x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 +
|
||||
// x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0 (0x04C11DB7)
|
||||
@ -335,7 +332,7 @@ static ulong crc_0x04C11DB7(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong crc_0x04C11DB7_r(const uchar* data, ulong len, ulong crc)
|
||||
static unsigned int crc_0x04C11DB7_r(const unsigned char* data, unsigned int len, unsigned int crc)
|
||||
{
|
||||
// x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 +
|
||||
// x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0 (0x04C11DB7)
|
||||
@ -410,13 +407,13 @@ static ulong crc_0x04C11DB7_r(const uchar* data, ulong len, ulong crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
static ulong adler32(const uchar* data, ulong len, ulong init)
|
||||
static unsigned int adler32(const unsigned char* data, unsigned int len, unsigned int init)
|
||||
{
|
||||
ulong a = init & 0xFFFF;
|
||||
ulong b = (init >> 16) & 0xFFFF;
|
||||
unsigned int a = init & 0xFFFF;
|
||||
unsigned int b = (init >> 16) & 0xFFFF;
|
||||
|
||||
while (len) {
|
||||
ulong tlen = len > 5550 ? 5550 : len;
|
||||
unsigned int tlen = len > 5550 ? 5550 : len;
|
||||
len -= tlen;
|
||||
do {
|
||||
a += *data++;
|
||||
@ -431,10 +428,10 @@ static ulong adler32(const uchar* data, ulong len, ulong init)
|
||||
return b << 16 | a;
|
||||
}
|
||||
|
||||
static ulong hexsum(const uchar* data, ulong len, ulong sum)
|
||||
static unsigned int hexsum(const unsigned char* data, unsigned int len, unsigned int sum)
|
||||
{
|
||||
// Add all hex digits, ignore all other bytes.
|
||||
ulong d;
|
||||
unsigned int d;
|
||||
while (len--)
|
||||
{
|
||||
d = toupper(*data++);
|
||||
@ -452,8 +449,8 @@ struct checksum
|
||||
{
|
||||
const char* name;
|
||||
checksumFunc func;
|
||||
ulong init;
|
||||
ulong xorout;
|
||||
unsigned int init;
|
||||
unsigned int xorout;
|
||||
signed char bytes;
|
||||
};
|
||||
|
||||
@ -465,20 +462,6 @@ static checksum checksumMap[] =
|
||||
{"sum8", sum, 0x00, 0x00, 1}, // 0xDD
|
||||
{"sum16", sum, 0x0000, 0x0000, 2}, // 0x01DD
|
||||
{"sum32", sum, 0x00000000, 0x00000000, 4}, // 0x000001DD
|
||||
{"nsum", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"negsum", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"-sum", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"nsum8", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"negsum8", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"-sum8", sum, 0xFF, 0xFF, 1}, // 0x23
|
||||
{"nsum16", sum, 0xFFFF, 0xFFFF, 2}, // 0xFE23
|
||||
{"negsum16",sum, 0xFFFF, 0xFFFF, 2}, // 0xFE23
|
||||
{"-sum16", sum, 0xFFFF, 0xFFFF, 2}, // 0xFE23
|
||||
{"nsum32", sum, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xFFFFFE23
|
||||
{"negsum32",sum, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xFFFFFE23
|
||||
{"-sum32", sum, 0xFFFFFFFF, 0xFFFFFFFF, 4}, // 0xFFFFFE23
|
||||
{"notsum", sum, 0x00, 0xFF, 1}, // 0x22
|
||||
{"~sum", sum, 0x00, 0xFF, 1}, // 0x22
|
||||
{"xor", xor8, 0x00, 0x00, 1}, // 0x31
|
||||
{"xor8", xor8, 0x00, 0x00, 1}, // 0x31
|
||||
{"xor7", xor7, 0x00, 0x00, 1}, // 0x31
|
||||
@ -498,7 +481,7 @@ static checksum checksumMap[] =
|
||||
{"hexsum8", hexsum, 0x00, 0x00, 1} // 0x2D
|
||||
};
|
||||
|
||||
static ulong mask[5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
|
||||
static unsigned int mask[5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
|
||||
|
||||
class ChecksumConverter : public StreamFormatConverter
|
||||
{
|
||||
@ -517,39 +500,80 @@ parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool)
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t fnum;
|
||||
bool negflag=false;
|
||||
bool notflag=false;
|
||||
if (*source == '-')
|
||||
{
|
||||
source++;
|
||||
negflag = true;
|
||||
}
|
||||
if (strncasecmp(source, "neg", 3) == 0)
|
||||
{
|
||||
source+=3;
|
||||
negflag = true;
|
||||
}
|
||||
if (*source == '~')
|
||||
{
|
||||
source++;
|
||||
notflag = true;
|
||||
}
|
||||
if (strncasecmp(source, "not", 3) == 0)
|
||||
{
|
||||
source+=3;
|
||||
notflag = true;
|
||||
}
|
||||
unsigned fnum;
|
||||
int len = p-source;
|
||||
unsigned int init, xorout;
|
||||
for (fnum = 0; fnum < sizeof(checksumMap)/sizeof(checksum); fnum++)
|
||||
{
|
||||
if (strncasecmp(source, checksumMap[fnum].name, p-source) == 0)
|
||||
if ((strncasecmp(source, checksumMap[fnum].name, len) == 0) ||
|
||||
(*source == 'n' && len > 1 && strncasecmp(source+1, checksumMap[fnum].name, len-1) == 0 && (negflag = true)))
|
||||
{
|
||||
init = checksumMap[fnum].init;
|
||||
xorout = checksumMap[fnum].xorout;
|
||||
if (negflag)
|
||||
{
|
||||
init = ~init;
|
||||
xorout = ~xorout;
|
||||
}
|
||||
if (notflag)
|
||||
{
|
||||
xorout = ~xorout;
|
||||
}
|
||||
info.append(&init, sizeof(init));
|
||||
info.append(&xorout, sizeof(xorout));
|
||||
info.append(fnum);
|
||||
source = p+1;
|
||||
return pseudo_format;
|
||||
}
|
||||
}
|
||||
|
||||
error ("Unknown checksum algorithm \"%.*s\"\n",
|
||||
static_cast<int>(p-source), source);
|
||||
error ("Unknown checksum algorithm \"%.*s\"\n", len, source);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChecksumConverter::
|
||||
printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||
{
|
||||
ulong sum;
|
||||
int fnum = format.info[0];
|
||||
unsigned int sum;
|
||||
const char* info = format.info;
|
||||
unsigned int init = extract<unsigned int>(info);
|
||||
unsigned int xorout = extract<unsigned int>(info);
|
||||
int fnum = extract<char>(info);
|
||||
|
||||
int start = format.width;
|
||||
int length = output.length()-format.width;
|
||||
if (format.prec > 0) length -= format.prec;
|
||||
|
||||
debug("ChecksumConverter %s: output to check: \"%s\"\n",
|
||||
checksumMap[fnum].name, output.expand(start,length)());
|
||||
|
||||
sum = (xorout ^ checksumMap[fnum].func(
|
||||
reinterpret_cast<unsigned char*>(output(start)), length, init))
|
||||
& mask[checksumMap[fnum].bytes];
|
||||
|
||||
sum = (checksumMap[fnum].xorout ^ checksumMap[fnum].func(
|
||||
reinterpret_cast<uchar*>(output(start)), length,
|
||||
checksumMap[fnum].init)) & mask[checksumMap[fnum].bytes];
|
||||
|
||||
debug("ChecksumConverter %s: output checksum is 0x%lX\n",
|
||||
debug("ChecksumConverter %s: output checksum is 0x%X\n",
|
||||
checksumMap[fnum].name, sum);
|
||||
|
||||
int i;
|
||||
@ -559,13 +583,11 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||
{
|
||||
// get number of decimal digits from number of bytes: ceil(xbytes*2.5)
|
||||
i = (checksumMap[fnum].bytes+1)*25/10-2;
|
||||
output.print("%0*ld", i, sum);
|
||||
debug("ChecksumConverter %s: decimal appending %0*ld\n",
|
||||
output.print("%0*d", i, sum);
|
||||
debug("ChecksumConverter %s: decimal appending %0*d\n",
|
||||
checksumMap[fnum].name, i, sum);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if (format.flags & alt_flag) // lsb first (little endian)
|
||||
{
|
||||
for (i = 0; i < checksumMap[fnum].bytes; i++)
|
||||
@ -575,6 +597,10 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||
checksumMap[fnum].name, outchar);
|
||||
if (format.flags & zero_flag) // ASCII
|
||||
output.print("%02X", outchar);
|
||||
else
|
||||
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||
output.print("%c%c",
|
||||
((outchar>>4)&0x0f)|0x30, (outchar&0x0f)|0x30);
|
||||
else // binary
|
||||
output.append(outchar);
|
||||
sum >>= 8;
|
||||
@ -590,6 +616,10 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||
checksumMap[fnum].name, outchar);
|
||||
if (format.flags & zero_flag) // ASCII
|
||||
output.print("%02X", outchar);
|
||||
else
|
||||
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||
output.print("%c%c",
|
||||
((outchar>>4)&0x0f)|0x30, (outchar&0x0f)|0x30);
|
||||
else // binary
|
||||
output.append(outchar);
|
||||
sum <<= 8;
|
||||
@ -601,57 +631,88 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||
int ChecksumConverter::
|
||||
scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
||||
{
|
||||
int fnum = format.info[0];
|
||||
ulong sum;
|
||||
unsigned int sum;
|
||||
const char* info = format.info;
|
||||
unsigned int init = extract<unsigned int>(info);
|
||||
unsigned int xorout = extract<unsigned int>(info);
|
||||
int start = format.width;
|
||||
int fnum = extract<char>(info);
|
||||
int length = cursor-format.width;
|
||||
|
||||
if (format.prec > 0) length -= format.prec;
|
||||
|
||||
debug("ChecksumConverter %s: input to check: \"%s\n",
|
||||
checksumMap[fnum].name, input.expand(start,length)());
|
||||
|
||||
if (input.length() - cursor <
|
||||
(format.flags & zero_flag ? 2 : 1) * checksumMap[fnum].bytes)
|
||||
int expectedLength =
|
||||
// get number of decimal digits from number of bytes: ceil(bytes*2.5)
|
||||
format.flags & sign_flag ? (checksumMap[fnum].bytes + 1) * 25 / 10 - 2 :
|
||||
format.flags & (zero_flag|left_flag) ? 2 * checksumMap[fnum].bytes :
|
||||
checksumMap[fnum].bytes;
|
||||
|
||||
if (input.length() - cursor < expectedLength)
|
||||
{
|
||||
error("Input too short for checksum\n");
|
||||
debug("ChecksumConverter %s: Input '%s' too short for checksum\n",
|
||||
checksumMap[fnum].name, input.expand(cursor)());
|
||||
return -1;
|
||||
}
|
||||
|
||||
sum = (checksumMap[fnum].xorout ^ checksumMap[fnum].func(
|
||||
reinterpret_cast<uchar*>(input(start)), length,
|
||||
checksumMap[fnum].init)) & mask[checksumMap[fnum].bytes];
|
||||
sum = (xorout ^ checksumMap[fnum].func(
|
||||
reinterpret_cast<unsigned char*>(input(start)), length, init))
|
||||
& mask[checksumMap[fnum].bytes];
|
||||
|
||||
debug("ChecksumConverter %s: input checksum is 0x%0*lX\n",
|
||||
debug("ChecksumConverter %s: input checksum is 0x%0*X\n",
|
||||
checksumMap[fnum].name, 2*checksumMap[fnum].bytes, sum);
|
||||
|
||||
int i,j;
|
||||
int i, j;
|
||||
unsigned inchar;
|
||||
|
||||
if (format.flags & sign_flag) // decimal
|
||||
{
|
||||
ulong sumin = 0;
|
||||
// get number of decimal digits from number of bytes: ceil(xbytes*2.5)
|
||||
j = (checksumMap[fnum].bytes+1)*25/10-2;
|
||||
for (i = 0; i < j; i++)
|
||||
unsigned int sumin = 0;
|
||||
for (i = 0; i < expectedLength; i++)
|
||||
{
|
||||
inchar = input[cursor+i];
|
||||
if (isdigit(inchar)) sumin = sumin*10+inchar-'0';
|
||||
else break;
|
||||
}
|
||||
if (sumin==sum) return i;
|
||||
error("Input %0*lu does not match checksum %0*lu\n",
|
||||
i, sumin, j, sum);
|
||||
return -1;
|
||||
if (sumin != sum)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input %0*u does not match checksum %0*u\n",
|
||||
checksumMap[fnum].name, i, sumin, expectedLength, sum);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else
|
||||
if (format.flags & alt_flag) // lsb first (little endian)
|
||||
{
|
||||
for (i = 0; i < checksumMap[fnum].bytes; i++)
|
||||
{
|
||||
if (format.flags & zero_flag) // ASCII
|
||||
{
|
||||
sscanf(input(cursor+2*i), "%2X", &inchar);
|
||||
if (sscanf(input(cursor+2*i), "%2X", &inchar) != 1)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input byte '%s' is not a hex byte\n",
|
||||
checksumMap[fnum].name, input.expand(cursor+2*i,2)());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||
{
|
||||
if ((input[cursor+2*i] & 0xf0) != 0x30)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input byte 0x%02X is not in range 0x30 - 0x3F\n",
|
||||
checksumMap[fnum].name, input[cursor+2*i]);
|
||||
return -1;
|
||||
}
|
||||
if ((input[cursor+2*i+1] & 0xf0) != 0x30)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input byte 0x%02X is not in range 0x30 - 0x3F\n",
|
||||
checksumMap[fnum].name, input[cursor+2*i+1]);
|
||||
return -1;
|
||||
}
|
||||
inchar = ((input[cursor+2*i] & 0x0f) << 4) | (input[cursor+2*i+1] & 0x0f);
|
||||
}
|
||||
else // binary
|
||||
{
|
||||
@ -659,8 +720,8 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
||||
}
|
||||
if (inchar != ((sum >> 8*i) & 0xff))
|
||||
{
|
||||
error("Input byte 0x%02X does not match checksum 0x%0*lX\n",
|
||||
inchar, 2*checksumMap[fnum].bytes, sum);
|
||||
debug("ChecksumConverter %s: Input byte 0x%02X does not match checksum 0x%0*X\n",
|
||||
checksumMap[fnum].name, inchar, 2*checksumMap[fnum].bytes, sum);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -673,21 +734,36 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
||||
{
|
||||
sscanf(input(cursor+2*i), "%2x", &inchar);
|
||||
}
|
||||
else
|
||||
if (format.flags & left_flag) // poor man's hex: 0x30 - 0x3F
|
||||
{
|
||||
if ((input[cursor+2*i] & 0xf0) != 0x30)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input byte 0x%02X is not in range 0x30 - 0x3F\n",
|
||||
checksumMap[fnum].name, input[cursor+2*i]);
|
||||
return -1;
|
||||
}
|
||||
if ((input[cursor+2*i+1] & 0xf0) != 0x30)
|
||||
{
|
||||
debug("ChecksumConverter %s: Input byte 0x%02X is not in range 0x30 - 0x3F\n",
|
||||
checksumMap[fnum].name, input[cursor+2*i+1]);
|
||||
return -1;
|
||||
}
|
||||
inchar = ((input[cursor+2*i] & 0x0f) << 4) | (input[cursor+2*i+1] & 0x0f);
|
||||
}
|
||||
else // binary
|
||||
{
|
||||
inchar = input[cursor+i] & 0xff;
|
||||
}
|
||||
if (inchar != ((sum >> 8*j) & 0xff))
|
||||
{
|
||||
error("Input byte 0x%02X does not match checksum 0x%0*lX\n",
|
||||
inchar, 2*checksumMap[fnum].bytes, sum);
|
||||
debug("ChecksumConverter %s: Input byte 0x%02X does not match checksum 0x%0*X\n",
|
||||
checksumMap[fnum].name, inchar, 2*checksumMap[fnum].bytes, sum);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (format.flags & zero_flag) // ASCII
|
||||
return 2*checksumMap[fnum].bytes;
|
||||
return checksumMap[fnum].bytes;
|
||||
return expectedLength;
|
||||
}
|
||||
|
||||
RegisterConverter (ChecksumConverter, "<");
|
||||
|
@ -79,12 +79,11 @@ include $(TOP)/configure/RULES
|
||||
|
||||
# Update version string (contains __DATE__ and __TIME__)
|
||||
# each time make runs.
|
||||
StreamVersion$(OBJ): FORCE
|
||||
FORCE:
|
||||
StreamVersion$(OBJ): ../*.c ../*.h ../*.cc ../CONFIG_STREAM ../Makefile
|
||||
|
||||
# Add references to all registrars to main file to avoid
|
||||
# missing initialization.
|
||||
StreamCore$(OBJ): streamReferences
|
||||
StreamCore$(OBJ) StreamCore$(DEP): streamReferences
|
||||
|
||||
streamReferences: ../CONFIG_STREAM
|
||||
$(PERL) ../makeref.pl Interface $(BUSSES) > $@
|
||||
@ -94,4 +93,7 @@ streamReferences: ../CONFIG_STREAM
|
||||
$(COMMON_DIR)/$(LIBRARY_DEFAULT).dbd: ../CONFIG_STREAM
|
||||
$(PERL) ../makedbd.pl $(RECORDS) > $@
|
||||
|
||||
$(LIBRARY_DEFAULT).dbd$(DEP): ../CONFIG_STREAM
|
||||
echo $(LIBRARY_DEFAULT).dbd: $< > $@
|
||||
|
||||
endif
|
||||
|
@ -39,7 +39,4 @@ include $(TOP)/config/RULES.Host
|
||||
|
||||
# create stream.dbd from all RECORDS
|
||||
stream.dbd: ../CONFIG_STREAM
|
||||
@for r in $(RECORDS_3_13); \
|
||||
do echo "device($$r,INST_IO,dev$${r}Stream,\"stream\")"; \
|
||||
done > $@
|
||||
@echo "driver(stream)" >> $@
|
||||
$(PERL) ../makedbd.pl -3.13 $(RECORDS_3_13) > $@
|
||||
|
@ -110,7 +110,7 @@ scanString(const StreamFormat& fmt, const char* input,
|
||||
len = ovector[subexpr*2+1] - ovector[subexpr*2];
|
||||
if (len >= maxlen) {
|
||||
if (!(fmt.flags & sign_flag)) {
|
||||
debug("Matching string \"%s\" too long (%d>%d bytes)\n",
|
||||
error("Regexp: Matching string \"%s\" too long (%d>%d bytes). You may want to try the + flag: \"%%+/.../\"\n",
|
||||
StreamBuffer(input+ovector[subexpr*2], len).expand()(),
|
||||
(int)len, (int)maxlen-1);
|
||||
return -1;
|
||||
|
@ -30,15 +30,17 @@
|
||||
#define vsnprintf epicsVsnprintf
|
||||
#endif
|
||||
|
||||
#define P PRINTF_SIZE_T_PREFIX
|
||||
|
||||
void StreamBuffer::
|
||||
init(const void* s, long minsize)
|
||||
init(const void* s, ssize_t minsize)
|
||||
{
|
||||
len = 0;
|
||||
offs = 0;
|
||||
buffer = local;
|
||||
cap = sizeof(local);
|
||||
if (minsize < 0) minsize = 0;
|
||||
if (minsize >= cap)
|
||||
if ((size_t)minsize >= cap)
|
||||
{
|
||||
// use allocated buffer
|
||||
grow(minsize);
|
||||
@ -55,18 +57,18 @@ init(const void* s, long minsize)
|
||||
}
|
||||
|
||||
// How the buffer looks like:
|
||||
// |----free-----|####used####|-------free-------|
|
||||
// |----free-----|####used####|--------00--------|
|
||||
///|<--- offs -->|<-- len --->|<- cap-offs-len ->|
|
||||
// 0 offs offs+len cap
|
||||
// |<-------------- minsize --------------->
|
||||
|
||||
|
||||
void StreamBuffer::
|
||||
grow(long minsize)
|
||||
grow(size_t minsize)
|
||||
{
|
||||
// make space for minsize + 1 (for termination) bytes
|
||||
char* newbuffer;
|
||||
long newcap;
|
||||
size_t newcap;
|
||||
#ifdef EXPLODE
|
||||
if (minsize > 1000000)
|
||||
{
|
||||
@ -117,12 +119,12 @@ grow(long minsize)
|
||||
}
|
||||
|
||||
StreamBuffer& StreamBuffer::
|
||||
append(const void* s, long size)
|
||||
append(const void* s, ssize_t size)
|
||||
{
|
||||
if (size <= 0)
|
||||
{
|
||||
// append negative number of bytes? let's delete some
|
||||
if (size < -len) size = -len;
|
||||
if (size < -(ssize_t)len) size = -(ssize_t)len;
|
||||
memset (buffer+offs+len+size, 0, -size);
|
||||
}
|
||||
else
|
||||
@ -134,8 +136,8 @@ append(const void* s, long size)
|
||||
return *this;
|
||||
}
|
||||
|
||||
long int StreamBuffer::
|
||||
find(const void* m, long size, long start) const
|
||||
ssize_t StreamBuffer::
|
||||
find(const void* m, size_t size, ssize_t start) const
|
||||
{
|
||||
if (start < 0)
|
||||
{
|
||||
@ -147,7 +149,7 @@ find(const void* m, long size, long start) const
|
||||
const char* s = static_cast<const char*>(m);
|
||||
char* b = buffer+offs;
|
||||
char* p = b+start;
|
||||
long i;
|
||||
size_t i;
|
||||
while ((p = static_cast<char*>(memchr(p, s[0], b-p+len-size+1))))
|
||||
{
|
||||
for (i = 1; i < size; i++)
|
||||
@ -161,7 +163,7 @@ next: p++;
|
||||
}
|
||||
|
||||
StreamBuffer& StreamBuffer::
|
||||
replace(long remstart, long remlen, const void* ins, long inslen)
|
||||
replace(ssize_t remstart, ssize_t remlen, const void* ins, ssize_t inslen)
|
||||
{
|
||||
if (remstart < 0)
|
||||
{
|
||||
@ -187,12 +189,12 @@ replace(long remstart, long remlen, const void* ins, long inslen)
|
||||
remlen += remstart;
|
||||
remstart = 0;
|
||||
}
|
||||
if (remstart > len)
|
||||
if ((size_t)remstart > len)
|
||||
{
|
||||
// remove begins after bufferend
|
||||
remstart = len;
|
||||
}
|
||||
if (remlen >= len-remstart)
|
||||
if ((size_t)remlen >= len-remstart)
|
||||
{
|
||||
// truncate remove after bufferend
|
||||
remlen = len-remstart;
|
||||
@ -205,12 +207,12 @@ replace(long remstart, long remlen, const void* ins, long inslen)
|
||||
return *this;
|
||||
}
|
||||
if (inslen < 0) inslen = 0;
|
||||
long remend = remstart+remlen;
|
||||
long newlen = len+inslen-remlen;
|
||||
size_t remend = remstart+remlen;
|
||||
size_t newlen = len+inslen-remlen;
|
||||
if (cap <= newlen)
|
||||
{
|
||||
// buffer too short
|
||||
long newcap;
|
||||
size_t newcap;
|
||||
for (newcap = sizeof(local)*2; newcap <= newlen; newcap *= 2);
|
||||
char* newbuffer = new char[newcap];
|
||||
memcpy(newbuffer, buffer+offs, remstart);
|
||||
@ -251,13 +253,13 @@ StreamBuffer& StreamBuffer::
|
||||
print(const char* fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
int printed;
|
||||
ssize_t printed;
|
||||
while (1)
|
||||
{
|
||||
va_start(va, fmt);
|
||||
printed = vsnprintf(buffer+offs+len, cap-offs-len, fmt, va);
|
||||
va_end(va);
|
||||
if (printed > -1 && printed < (int)(cap-offs-len))
|
||||
if (printed > -1 && printed < (ssize_t)(cap-offs-len))
|
||||
{
|
||||
len += printed;
|
||||
return *this;
|
||||
@ -267,9 +269,9 @@ print(const char* fmt, ...)
|
||||
}
|
||||
}
|
||||
|
||||
StreamBuffer StreamBuffer::expand(long start, long length) const
|
||||
StreamBuffer StreamBuffer::expand(ssize_t start, ssize_t length) const
|
||||
{
|
||||
long end;
|
||||
size_t end;
|
||||
if (start < 0)
|
||||
{
|
||||
start += len;
|
||||
@ -289,7 +291,7 @@ StreamBuffer StreamBuffer::expand(long start, long length) const
|
||||
StreamBuffer result((end-start)*2);
|
||||
start += offs;
|
||||
end += offs;
|
||||
long i;
|
||||
size_t i;
|
||||
char c;
|
||||
for (i = start; i < end; i++)
|
||||
{
|
||||
@ -311,8 +313,8 @@ dump() const
|
||||
{
|
||||
StreamBuffer result(256+cap*5);
|
||||
result.append("\033[0m");
|
||||
long i;
|
||||
result.print("%ld,%ld,%ld:\033[37m", offs, len, cap);
|
||||
size_t i;
|
||||
result.print("%"P"d,%"P"d,%"P"d:\033[37m", offs, len, cap);
|
||||
for (i = 0; i < cap; i++)
|
||||
{
|
||||
if (i == offs) result.append("\033[34m[\033[0m");
|
||||
|
@ -21,29 +21,34 @@
|
||||
#define StreamBuffer_h
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ssize_t ptrdiff_t
|
||||
#endif
|
||||
|
||||
class StreamBuffer
|
||||
{
|
||||
char local[64];
|
||||
long len;
|
||||
long cap;
|
||||
long offs;
|
||||
size_t len;
|
||||
size_t cap;
|
||||
size_t offs;
|
||||
char* buffer;
|
||||
|
||||
void init(const void* s, long minsize);
|
||||
void init(const void* s, ssize_t minsize);
|
||||
|
||||
void check(long size)
|
||||
void check(size_t size)
|
||||
{if (len+offs+size >= cap) grow(len+size);}
|
||||
|
||||
void grow(long minsize);
|
||||
void grow(size_t minsize);
|
||||
|
||||
public:
|
||||
// Hints:
|
||||
// * Any index parameter (long) can be negative
|
||||
// * Any index parameter (ssize_t) can be negative
|
||||
// meaning "count from end" (-1 is the last byte)
|
||||
// * Appending negative count deletes from end
|
||||
// * Any returned char* pointer becomes invalid when
|
||||
@ -54,7 +59,7 @@ public:
|
||||
StreamBuffer()
|
||||
{init(NULL, 0);}
|
||||
|
||||
StreamBuffer(const void* s, long size)
|
||||
StreamBuffer(const void* s, ssize_t size)
|
||||
{init(s, size);}
|
||||
|
||||
StreamBuffer(const char* s)
|
||||
@ -63,24 +68,24 @@ public:
|
||||
StreamBuffer(const StreamBuffer& s)
|
||||
{init(s.buffer+s.offs, s.len);}
|
||||
|
||||
StreamBuffer(long size)
|
||||
StreamBuffer(ssize_t size)
|
||||
{init(NULL, size);}
|
||||
|
||||
~StreamBuffer()
|
||||
{if (buffer != local) delete buffer;}
|
||||
|
||||
// operator (): get char* pointing to index
|
||||
const char* operator()(long index=0) const
|
||||
const char* operator()(ssize_t index=0) const
|
||||
{return buffer+offs+(index<0?index+len:index);}
|
||||
|
||||
char* operator()(long index=0)
|
||||
char* operator()(ssize_t index=0)
|
||||
{return buffer+offs+(index<0?index+len:index);}
|
||||
|
||||
// operator []: get byte at index
|
||||
char operator[](long index) const
|
||||
char operator[](ssize_t index) const
|
||||
{return buffer[offs+(index<0?index+len:index)];}
|
||||
|
||||
char& operator[](long index)
|
||||
char& operator[](ssize_t index)
|
||||
{return buffer[offs+(index<0?index+len:index)];}
|
||||
|
||||
// cast to bool: not empty?
|
||||
@ -88,11 +93,11 @@ public:
|
||||
{return len>0;}
|
||||
|
||||
// length: get current data length
|
||||
long length() const
|
||||
ssize_t length() const
|
||||
{return len;}
|
||||
|
||||
// capacity: get current max data length (spare one byte for end)
|
||||
long capacity() const
|
||||
ssize_t capacity() const
|
||||
{return cap-1;}
|
||||
|
||||
// end: get pointer to byte after last data byte
|
||||
@ -105,19 +110,19 @@ public:
|
||||
|
||||
// reserve: reserve size bytes of memory and return
|
||||
// pointer to that memory (for copying something to it)
|
||||
char* reserve(long size)
|
||||
char* reserve(size_t size)
|
||||
{check(size); char* p=buffer+offs+len; len+=size; return p;}
|
||||
|
||||
// append: append data at the end of the buffer
|
||||
StreamBuffer& append(char c)
|
||||
{check(1); buffer[offs+len++]=c; return *this;}
|
||||
|
||||
StreamBuffer& append(char c, long count)
|
||||
StreamBuffer& append(char c, ssize_t count)
|
||||
{if (count < 0) truncate(count);
|
||||
else {check(count); memset(buffer+offs+len, c, count); len+=count;}
|
||||
return *this;}
|
||||
|
||||
StreamBuffer& append(const void* s, long size);
|
||||
StreamBuffer& append(const void* s, ssize_t size);
|
||||
|
||||
StreamBuffer& append(const char* s)
|
||||
{return append(s, s?strlen(s):0);}
|
||||
@ -125,7 +130,7 @@ public:
|
||||
StreamBuffer& append(const StreamBuffer& s)
|
||||
{return append(s.buffer+s.offs, s.len);}
|
||||
|
||||
// operator += alias for set
|
||||
// operator += alias for append
|
||||
StreamBuffer& operator+=(char c)
|
||||
{return append(c);}
|
||||
|
||||
@ -136,7 +141,7 @@ public:
|
||||
{return append(s);}
|
||||
|
||||
// set: clear buffer and fill with new data
|
||||
StreamBuffer& set(const void* s, long size)
|
||||
StreamBuffer& set(const void* s, size_t size)
|
||||
{clear(); return append(s, size);}
|
||||
|
||||
StreamBuffer& set(const char* s)
|
||||
@ -154,61 +159,61 @@ public:
|
||||
|
||||
// replace: delete part of buffer (pos/length) and insert new data
|
||||
StreamBuffer& replace(
|
||||
long pos, long length, const void* s, long size);
|
||||
ssize_t pos, ssize_t length, const void* s, ssize_t size);
|
||||
|
||||
StreamBuffer& replace(long pos, long length, const char* s)
|
||||
StreamBuffer& replace(ssize_t pos, ssize_t length, const char* s)
|
||||
{return replace(pos, length, s, s?strlen(s):0);}
|
||||
|
||||
StreamBuffer& replace(long pos, long length, const StreamBuffer& s)
|
||||
StreamBuffer& replace(ssize_t pos, ssize_t length, const StreamBuffer& s)
|
||||
{return replace(pos, length, s.buffer+s.offs, s.len);}
|
||||
|
||||
// remove: delete from start/pos
|
||||
StreamBuffer& remove(long pos, long length)
|
||||
StreamBuffer& remove(ssize_t pos, ssize_t length)
|
||||
{return replace(pos, length, NULL, 0);}
|
||||
|
||||
// remove from start: no memset, no function call, fast!
|
||||
StreamBuffer& remove(long length)
|
||||
StreamBuffer& remove(size_t length)
|
||||
{if (length>len) length=len;
|
||||
offs+=length; len-=length; return *this;}
|
||||
|
||||
// truncate: delete end of buffer
|
||||
StreamBuffer& truncate(long pos)
|
||||
StreamBuffer& truncate(ssize_t pos)
|
||||
{return replace(pos, len, NULL, 0);}
|
||||
|
||||
// insert: insert new data into buffer
|
||||
StreamBuffer& insert(long pos, const void* s, long size)
|
||||
StreamBuffer& insert(ssize_t pos, const void* s, ssize_t size)
|
||||
{return replace(pos, 0, s, size);}
|
||||
|
||||
StreamBuffer& insert(long pos, const char* s)
|
||||
StreamBuffer& insert(ssize_t pos, const char* s)
|
||||
{return replace(pos, 0, s, s?strlen(s):0);}
|
||||
|
||||
StreamBuffer& insert(long pos, const StreamBuffer& s)
|
||||
StreamBuffer& insert(ssize_t pos, const StreamBuffer& s)
|
||||
{return replace(pos, 0, s.buffer+s.offs, s.len);}
|
||||
|
||||
StreamBuffer& insert(long pos, char c)
|
||||
StreamBuffer& insert(ssize_t pos, char c)
|
||||
{return replace(pos, 0, &c, 1);}
|
||||
|
||||
StreamBuffer& print(const char* fmt, ...)
|
||||
__attribute__ ((format(printf,2,3)));
|
||||
|
||||
// find: get index of data in buffer or -1
|
||||
long find(char c, long start=0) const
|
||||
ssize_t find(char c, ssize_t start=0) const
|
||||
{char* p;
|
||||
return (p = static_cast<char*>(
|
||||
memchr(buffer+offs+(start<0?start+len:start),
|
||||
c, start<0?-start:len-start)))?
|
||||
p-(buffer+offs) : -1;}
|
||||
|
||||
long find(const void* s, long size, long start=0) const;
|
||||
ssize_t find(const void* s, size_t size, ssize_t start=0) const;
|
||||
|
||||
long find(const char* s, long start=0) const
|
||||
ssize_t find(const char* s, ssize_t start=0) const
|
||||
{return find(s, s?strlen(s):0, start);}
|
||||
|
||||
long int find(const StreamBuffer& s, long start=0) const
|
||||
ssize_t find(const StreamBuffer& s, ssize_t start=0) const
|
||||
{return find(s.buffer+s.offs, s.len, start);}
|
||||
|
||||
// startswith: returns true if first size bytes are equal
|
||||
bool startswith(const void* s, long size) const
|
||||
bool startswith(const void* s, size_t size) const
|
||||
{return len>=size ? memcmp(buffer+offs, s, size) == 0 : false;}
|
||||
|
||||
// startswith: returns true if first string is equal (empty string matches)
|
||||
@ -217,9 +222,9 @@ public:
|
||||
|
||||
// expand: create copy of StreamBuffer where all nonprintable characters
|
||||
// are replaced by <xx> with xx being the hex code of the characters
|
||||
StreamBuffer expand(long start, long length) const;
|
||||
StreamBuffer expand(ssize_t start, ssize_t length) const;
|
||||
|
||||
StreamBuffer expand(long start=0) const
|
||||
StreamBuffer expand(ssize_t start=0) const
|
||||
{return expand(start, len);}
|
||||
|
||||
// dump: debug function, like expand but also show the 'hidden' memory
|
||||
@ -227,4 +232,13 @@ public:
|
||||
StreamBuffer dump() const;
|
||||
};
|
||||
|
||||
// printf size prefix for size_t and ssize_t
|
||||
#if defined (__GNUC__) && __GNUC__ >= 3
|
||||
#define PRINTF_SIZE_T_PREFIX "z"
|
||||
#elif defined (_WIN32)
|
||||
#define PRINTF_SIZE_T_PREFIX "I"
|
||||
#else
|
||||
#define PRINTF_SIZE_T_PREFIX ""
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -18,14 +18,9 @@
|
||||
***************************************************************/
|
||||
|
||||
#include "StreamBusInterface.h"
|
||||
#include "StreamError.h"
|
||||
|
||||
const char* StreamIoStatusStr[] = {
|
||||
"StreamIoSuccess",
|
||||
"StreamIoTimeout",
|
||||
"StreamIoNoReply",
|
||||
"StreamIoEnd",
|
||||
"StreamIoFault"
|
||||
};
|
||||
StreamIoStatusStrClass StreamIoStatusStr;
|
||||
|
||||
StreamBusInterfaceRegistrarBase* StreamBusInterfaceRegistrarBase::first;
|
||||
|
||||
@ -64,11 +59,17 @@ supportsAsyncRead()
|
||||
StreamBusInterface* StreamBusInterface::
|
||||
find(Client* client, const char* busname, int addr, const char* param)
|
||||
{
|
||||
debug("StreamBusInterface::find(%s, %s, %d, \"%s\")\n",
|
||||
client->name(), busname, addr, param);
|
||||
StreamBusInterfaceRegistrarBase* r;
|
||||
StreamBusInterface* bus;
|
||||
for (r = r->first; r; r = r->next)
|
||||
for (r = StreamBusInterfaceRegistrarBase::first; r; r = r->next)
|
||||
{
|
||||
debug("StreamBusInterface::find %s check %s\n",
|
||||
client->name(), r->name);
|
||||
bus = r->find(client, busname, addr, param);
|
||||
debug("StreamBusInterface::find %s %s\n",
|
||||
r->name, bus ? "matches" : "does not match");
|
||||
if (bus) return bus;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -21,13 +21,26 @@
|
||||
#define StreamBusInterface_h
|
||||
|
||||
#include <stddef.h>
|
||||
#include <StreamBuffer.h>
|
||||
|
||||
enum StreamIoStatus {
|
||||
StreamIoSuccess, StreamIoTimeout, StreamIoNoReply,
|
||||
StreamIoEnd, StreamIoFault
|
||||
};
|
||||
|
||||
extern const char* StreamIoStatusStr[];
|
||||
class StreamIoStatusStrClass {
|
||||
public:
|
||||
const char* operator [] (int index) {
|
||||
switch (index) {
|
||||
case StreamIoSuccess: return "StreamIoSuccess";
|
||||
case StreamIoTimeout: return "StreamIoTimeout";
|
||||
case StreamIoNoReply: return "StreamIoNoReply";
|
||||
case StreamIoEnd: return "StreamIoEnd";
|
||||
case StreamIoFault: return "StreamIoFault";
|
||||
default: return "illegal status";
|
||||
}
|
||||
}
|
||||
} extern StreamIoStatusStr;
|
||||
|
||||
class StreamBusInterface
|
||||
{
|
||||
@ -44,50 +57,53 @@ public:
|
||||
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;
|
||||
virtual const char* getOutTerminator(size_t& length) = 0;
|
||||
public:
|
||||
virtual const char* name() = 0;
|
||||
virtual ~Client();
|
||||
protected:
|
||||
StreamBusInterface* businterface;
|
||||
bool busSupportsEvent() {
|
||||
return businterface->supportsEvent();
|
||||
return businterface && businterface->supportsEvent();
|
||||
}
|
||||
bool busSupportsAsyncRead() {
|
||||
return businterface->supportsAsyncRead();
|
||||
return businterface && businterface->supportsAsyncRead();
|
||||
}
|
||||
bool busAcceptEvent(unsigned long mask,
|
||||
unsigned long replytimeout_ms) {
|
||||
return businterface->acceptEvent(mask, replytimeout_ms);
|
||||
return businterface && businterface->acceptEvent(mask, replytimeout_ms);
|
||||
}
|
||||
void busRelease() {
|
||||
businterface->release();
|
||||
if (businterface) businterface->release();
|
||||
}
|
||||
bool busLockRequest(unsigned long timeout_ms) {
|
||||
return businterface->lockRequest(timeout_ms);
|
||||
return businterface && businterface->lockRequest(timeout_ms);
|
||||
}
|
||||
bool busUnlock() {
|
||||
return businterface->unlock();
|
||||
return businterface && businterface->unlock();
|
||||
}
|
||||
bool busWriteRequest(const void* output, size_t size,
|
||||
unsigned long timeout_ms) {
|
||||
return businterface->writeRequest(output, size, timeout_ms);
|
||||
return businterface && businterface->writeRequest(output, size, timeout_ms);
|
||||
}
|
||||
bool busReadRequest(unsigned long replytimeout_ms,
|
||||
unsigned long readtimeout_ms, long expectedLength,
|
||||
bool async) {
|
||||
return businterface->readRequest(replytimeout_ms,
|
||||
readtimeout_ms, expectedLength, async);
|
||||
return businterface && businterface->readRequest(replytimeout_ms,
|
||||
readtimeout_ms, expectedLength, async);
|
||||
}
|
||||
void busFinish() {
|
||||
businterface->finish();
|
||||
if (businterface) businterface->finish();
|
||||
}
|
||||
bool busConnectRequest(unsigned long timeout_ms) {
|
||||
return businterface->connectRequest(timeout_ms);
|
||||
return businterface && businterface->connectRequest(timeout_ms);
|
||||
}
|
||||
bool busDisconnect() {
|
||||
return businterface->disconnectRequest();
|
||||
return businterface && businterface->disconnectRequest();
|
||||
}
|
||||
void busPrintStatus(StreamBuffer& buffer) {
|
||||
if (businterface) businterface->printStatus(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
@ -137,6 +153,7 @@ protected:
|
||||
virtual bool connectRequest(unsigned long connecttimeout_ms);
|
||||
virtual bool disconnectRequest();
|
||||
virtual void finish();
|
||||
virtual void printStatus(StreamBuffer& buffer) {};
|
||||
|
||||
// pure virtual
|
||||
virtual bool lockRequest(unsigned long timeout_ms) = 0;
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define P PRINTF_SIZE_T_PREFIX
|
||||
|
||||
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",
|
||||
@ -57,7 +59,7 @@ static char* printCommands(StreamBuffer& buffer, const char* c)
|
||||
break;
|
||||
case wait_cmd:
|
||||
timeout = extract<unsigned long>(c);
|
||||
buffer.print(" wait %ld;\n # ms", timeout);
|
||||
buffer.print(" wait %ld; # ms\n", timeout);
|
||||
break;
|
||||
case event_cmd:
|
||||
eventnumber = extract<unsigned long>(c);
|
||||
@ -118,7 +120,6 @@ printProtocol()
|
||||
if (onMismatch)
|
||||
printf(" @Mismatch {\n%s }\n",
|
||||
printCommands(buffer.clear(), onMismatch()));
|
||||
debug("StreamCore::printProtocol: commands=%s\n", commands.expand()());
|
||||
printf("\n%s}\n",
|
||||
printCommands(buffer.clear(), commands()));
|
||||
}
|
||||
@ -164,7 +165,7 @@ attachBus(const char* busname, int addr, const char* param)
|
||||
businterface = StreamBusInterface::find(this, busname, addr, param);
|
||||
if (!businterface)
|
||||
{
|
||||
error("Businterface '%s' not found for '%s'\n",
|
||||
error("Cannot find a bus named '%s' for '%s'\n",
|
||||
busname, name());
|
||||
return false;
|
||||
}
|
||||
@ -342,6 +343,7 @@ compileCommand(StreamProtocolParser::Protocol* protocol,
|
||||
return false;
|
||||
}
|
||||
args++;
|
||||
while (isspace(*args)) args++;
|
||||
}
|
||||
buffer.append(&eventmask, sizeof(eventmask));
|
||||
if (*args)
|
||||
@ -816,7 +818,7 @@ lockCallback(StreamIoStatus status)
|
||||
{
|
||||
MutexLock lock(this);
|
||||
debug("StreamCore::lockCallback(%s, status=%s)\n",
|
||||
name(), status ? "Timeout" : "Success");
|
||||
name(), StreamIoStatusStr[status]);
|
||||
if (!(flags & LockPending))
|
||||
{
|
||||
error("StreamCore::lockCallback(%s) called unexpectedly\n",
|
||||
@ -830,9 +832,21 @@ lockCallback(StreamIoStatus status)
|
||||
case StreamIoSuccess:
|
||||
break;
|
||||
case StreamIoTimeout:
|
||||
error("%s: Cannot lock device within %ld ms, device seems to be busy\n",
|
||||
name(), lockTimeout);
|
||||
flags &= ~BusOwner;
|
||||
finishProtocol(LockTimeout);
|
||||
return;
|
||||
case StreamIoFault:
|
||||
error("%s: Locking failed because of a device fault\n",
|
||||
name());
|
||||
flags &= ~BusOwner;
|
||||
finishProtocol(LockTimeout);
|
||||
return;
|
||||
default:
|
||||
error("StreamCore::lockCallback(%s) unexpected status %s\n",
|
||||
name(), StreamIoStatusStr[status]);
|
||||
flags &= ~BusOwner;
|
||||
finishProtocol(Fault);
|
||||
return;
|
||||
}
|
||||
@ -983,7 +997,7 @@ readCallback(StreamIoStatus status,
|
||||
finishProtocol(ReplyTimeout);
|
||||
return 0;
|
||||
case StreamIoFault:
|
||||
error("%s: I/O error after reading %ld byte%s: \"%s%s\"\n",
|
||||
error("%s: I/O error after reading %"P"d byte%s: \"%s%s\"\n",
|
||||
name(),
|
||||
inputBuffer.length(), inputBuffer.length()==1 ? "" : "s",
|
||||
inputBuffer.length() > 20 ? "..." : "",
|
||||
@ -992,7 +1006,7 @@ readCallback(StreamIoStatus status,
|
||||
return 0;
|
||||
}
|
||||
inputBuffer.append(input, size);
|
||||
debug("StreamCore::readCallback(%s) inputBuffer=\"%s\", size %ld\n",
|
||||
debug("StreamCore::readCallback(%s) inputBuffer=\"%s\", size %"P"d\n",
|
||||
name(), inputBuffer.expand()(), inputBuffer.length());
|
||||
if (*activeCommand != in_cmd)
|
||||
{
|
||||
@ -1159,8 +1173,7 @@ matchInput()
|
||||
*/
|
||||
char command;
|
||||
const char* fieldName = NULL;
|
||||
const char* formatstring;
|
||||
int formatstringlen;
|
||||
StreamBuffer formatstring;
|
||||
|
||||
consumedInput = 0;
|
||||
|
||||
@ -1186,22 +1199,15 @@ normal_format:
|
||||
int consumed;
|
||||
// code layout:
|
||||
// formatstring <eos> StreamFormat [info]
|
||||
formatstring = commandIndex;
|
||||
// jump after <eos>
|
||||
while (*commandIndex)
|
||||
{
|
||||
if (*commandIndex == esc) commandIndex++;
|
||||
commandIndex++;
|
||||
}
|
||||
formatstringlen = commandIndex-formatstring;
|
||||
commandIndex++;
|
||||
formatstring.clear();
|
||||
commandIndex = StreamProtocolParser::printString(formatstring, commandIndex);
|
||||
|
||||
StreamFormat fmt = extract<StreamFormat>(commandIndex);
|
||||
fmt.info = commandIndex; // point to info string
|
||||
commandIndex += fmt.infolen;
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("StreamCore::matchInput(%s): format = %%%s\n",
|
||||
name(), StreamBuffer(formatstring, formatstringlen).expand()());
|
||||
debug("StreamCore::matchInput(%s): format = \"%%%s\"\n",
|
||||
name(), formatstring());
|
||||
#endif
|
||||
|
||||
if (fmt.flags & skip_flag || fmt.type == pseudo_format)
|
||||
@ -1243,10 +1249,10 @@ normal_format:
|
||||
{
|
||||
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd)
|
||||
{
|
||||
error("%s: Input \"%s%s\" does not match format %%%s\n",
|
||||
error("%s: Input \"%s%s\" does not match format \"%%%s\"\n",
|
||||
name(), inputLine.expand(consumedInput, 20)(),
|
||||
inputLine.length()-consumedInput > 20 ? "..." : "",
|
||||
formatstring);
|
||||
formatstring());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1260,13 +1266,12 @@ normal_format:
|
||||
flags &= ~Separator;
|
||||
if (!formatValue(fmt, fieldAddress ? fieldAddress() : NULL))
|
||||
{
|
||||
StreamBuffer formatstr(formatstring, formatstringlen);
|
||||
if (fieldAddress)
|
||||
error("%s: Cannot format field '%s' with '%%%s'\n",
|
||||
name(), fieldName, formatstr.expand()());
|
||||
error("%s: Cannot format variable \"%s\" with \"%%%s\"\n",
|
||||
name(), fieldName, formatstring());
|
||||
else
|
||||
error("%s: Cannot format value with '%%%s'\n",
|
||||
name(), formatstr.expand()());
|
||||
error("%s: Cannot format value with \"%%%s\"\n",
|
||||
name(), formatstring());
|
||||
return false;
|
||||
}
|
||||
#ifndef NO_TEMPORARY
|
||||
@ -1279,11 +1284,11 @@ normal_format:
|
||||
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd)
|
||||
{
|
||||
error("%s: Input \"%s%s\" too short."
|
||||
" No match for format %%%s (\"%s\")\n",
|
||||
" No match for format \"%%%s\" (\"%s\")\n",
|
||||
name(),
|
||||
inputLine.length() > 20 ? "..." : "",
|
||||
inputLine.expand(-20)(),
|
||||
formatstring,
|
||||
formatstring(),
|
||||
outputLine.expand()());
|
||||
}
|
||||
return false;
|
||||
@ -1292,11 +1297,10 @@ normal_format:
|
||||
{
|
||||
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd)
|
||||
{
|
||||
error("%s: Input \"%s%s\" does not match"
|
||||
" format %%%s (\"%s\")\n",
|
||||
error("%s: Input \"%s%s\" does not match format \"%%%s\" (\"%s\")\n",
|
||||
name(), inputLine.expand(consumedInput, 20)(),
|
||||
inputLine.length()-consumedInput > 20 ? "..." : "",
|
||||
formatstring,
|
||||
formatstring(),
|
||||
outputLine.expand()());
|
||||
}
|
||||
return false;
|
||||
@ -1310,13 +1314,13 @@ normal_format:
|
||||
if (!(flags & AsyncMode) && onMismatch[0] != in_cmd)
|
||||
{
|
||||
if (flags & ScanTried)
|
||||
error("%s: Input \"%s%s\" does not match format %%%s\n",
|
||||
error("%s: Input \"%s%s\" does not match format \"%%%s\"\n",
|
||||
name(), inputLine.expand(consumedInput, 20)(),
|
||||
inputLine.length()-consumedInput > 20 ? "..." : "",
|
||||
formatstring);
|
||||
formatstring());
|
||||
else
|
||||
error("%s: Format %%%s has data type %s which does not match this variable.\n",
|
||||
name(), formatstring, StreamFormatTypeStr[fmt.type] );
|
||||
error("%s: Format \"%%%s\" has data type %s which does not match the type of \"%s\".\n",
|
||||
name(), formatstring(), StreamFormatTypeStr[fmt.type], fieldAddress ? fieldName : name());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1746,4 +1750,25 @@ disconnectCallback(StreamIoStatus status)
|
||||
}
|
||||
}
|
||||
|
||||
void StreamCore::
|
||||
printStatus(StreamBuffer& buffer)
|
||||
{
|
||||
buffer.print("active command=%s ",
|
||||
activeCommand ? commandName(*activeCommand) : "NULL");
|
||||
buffer.print("flags=0x%04lx ", flags);
|
||||
if (flags & IgnoreExtraInput) buffer.append("IgnoreExtraInput ");
|
||||
if (flags & InitRun) buffer.append("InitRun ");
|
||||
if (flags & AsyncMode) buffer.append("AsyncMode ");
|
||||
if (flags & GotValue) buffer.append("GotValue ");
|
||||
if (flags & BusOwner) buffer.append("BusOwner ");
|
||||
if (flags & Separator) buffer.append("Separator ");
|
||||
if (flags & ScanTried) buffer.append("ScanTried ");
|
||||
if (flags & AcceptInput) buffer.append("AcceptInput ");
|
||||
if (flags & AcceptEvent) buffer.append("AcceptEvent ");
|
||||
if (flags & LockPending) buffer.append("LockPending ");
|
||||
if (flags & WritePending) buffer.append("WritePending ");
|
||||
if (flags & WaitPending) buffer.append("WaitPending ");
|
||||
busPrintStatus(buffer);
|
||||
}
|
||||
|
||||
#include "streamReferences"
|
||||
|
@ -219,6 +219,7 @@ public:
|
||||
bool parse(const char* filename, const char* protocolname);
|
||||
void printProtocol();
|
||||
const char* name() { return streamname; }
|
||||
void printStatus(StreamBuffer& buffer);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -18,14 +18,24 @@
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "devStream.h"
|
||||
#undef epicsExportSharedSymbols
|
||||
#include "StreamCore.h"
|
||||
#include "StreamError.h"
|
||||
#include "devStream.h"
|
||||
|
||||
#ifndef EPICS_3_14
|
||||
#include <epicsVersion.h>
|
||||
#ifdef BASE_VERSION
|
||||
#define EPICS_3_13
|
||||
#endif
|
||||
|
||||
#ifdef EPICS_3_13
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define epicsAlarmGLOBAL
|
||||
#include <alarm.h>
|
||||
#undef epicsAlarmGLOBAL
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
@ -34,10 +44,9 @@ extern "C" {
|
||||
#include <recSup.h>
|
||||
#include <recGbl.h>
|
||||
#include <devLib.h>
|
||||
#include <alarm.h>
|
||||
#include <callback.h>
|
||||
|
||||
#ifndef EPICS_3_14
|
||||
#ifdef EPICS_3_13
|
||||
|
||||
#include <semLib.h>
|
||||
#include <wdLib.h>
|
||||
@ -87,24 +96,24 @@ extern "C" void streamRecordProcessCallback(CALLBACK *pcallback);
|
||||
extern "C" long streamReload(char* recordname);
|
||||
|
||||
class Stream : protected StreamCore
|
||||
#ifdef EPICS_3_14
|
||||
#ifndef EPICS_3_13
|
||||
, epicsTimerNotify
|
||||
#endif
|
||||
{
|
||||
dbCommon* record;
|
||||
struct link *ioLink;
|
||||
const struct link *ioLink;
|
||||
streamIoFunction readData;
|
||||
streamIoFunction writeData;
|
||||
#ifdef EPICS_3_14
|
||||
epicsTimerQueueActive* timerQueue;
|
||||
epicsTimer* timer;
|
||||
epicsMutex mutex;
|
||||
epicsEvent initDone;
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
WDOG_ID timer;
|
||||
CALLBACK timeoutCallback;
|
||||
SEM_ID mutex;
|
||||
SEM_ID initDone;
|
||||
#else
|
||||
epicsTimerQueueActive* timerQueue;
|
||||
epicsTimer* timer;
|
||||
epicsMutex mutex;
|
||||
epicsEvent initDone;
|
||||
#endif
|
||||
StreamBuffer fieldBuffer;
|
||||
int status;
|
||||
@ -115,11 +124,11 @@ class Stream : protected StreamCore
|
||||
CALLBACK processCallback;
|
||||
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
#ifdef EPICS_3_13
|
||||
static void expire(CALLBACK *pcallback);
|
||||
#else
|
||||
// epicsTimerNotify method
|
||||
expireStatus expire(const epicsTime&);
|
||||
#else
|
||||
static void expire(CALLBACK *pcallback);
|
||||
#endif
|
||||
|
||||
// StreamCore methods
|
||||
@ -139,16 +148,19 @@ class Stream : protected StreamCore
|
||||
friend void streamRecordProcessCallback(CALLBACK *pcallback);
|
||||
|
||||
// Stream Epics methods
|
||||
long initRecord();
|
||||
Stream(dbCommon* record, struct link *ioLink,
|
||||
Stream(dbCommon* record, const struct link *ioLink,
|
||||
streamIoFunction readData, streamIoFunction writeData);
|
||||
~Stream();
|
||||
long parseLink(const struct link *ioLink, char* filename, char* protocol,
|
||||
char* busname, int* addr, char* busparam);
|
||||
long initRecord(const char* filename, const char* protocol,
|
||||
const char* busname, int addr, const char* busparam);
|
||||
bool print(format_t *format, va_list ap);
|
||||
bool scan(format_t *format, void* pvalue, size_t maxStringSize);
|
||||
bool process();
|
||||
|
||||
// device support functions
|
||||
friend long streamInitRecord(dbCommon *record, struct link *ioLink,
|
||||
friend long streamInitRecord(dbCommon *record, const struct link *ioLink,
|
||||
streamIoFunction readData, streamIoFunction writeData);
|
||||
friend long streamReadWrite(dbCommon *record);
|
||||
friend long streamGetIointInfo(int cmd, dbCommon *record,
|
||||
@ -166,7 +178,7 @@ public:
|
||||
|
||||
|
||||
// shell functions ///////////////////////////////////////////////////////
|
||||
#ifdef EPICS_3_14
|
||||
#ifndef EPICS_3_13
|
||||
extern "C" {
|
||||
epicsExportAddress(int, streamDebug);
|
||||
}
|
||||
@ -225,7 +237,7 @@ extern "C" long streamReload(char* recordname)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
#ifndef EPICS_3_13
|
||||
static const iocshArg streamReloadArg0 =
|
||||
{ "recordname", iocshArgString };
|
||||
static const iocshArg * const streamReloadArgs[] =
|
||||
@ -251,7 +263,7 @@ static void streamRegistrar ()
|
||||
extern "C" {
|
||||
epicsExportRegistrar(streamRegistrar);
|
||||
}
|
||||
#endif // EPICS_3_14
|
||||
#endif
|
||||
|
||||
// driver support ////////////////////////////////////////////////////////
|
||||
|
||||
@ -265,19 +277,13 @@ struct stream_drvsup {
|
||||
Stream::drvInit
|
||||
};
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
#ifndef EPICS_3_13
|
||||
extern "C" {
|
||||
epicsExportAddress(drvet, stream);
|
||||
}
|
||||
#endif
|
||||
|
||||
void streamEpicsPrintTimestamp(char* buffer, int size)
|
||||
{
|
||||
int tlen;
|
||||
epicsTime tm = epicsTime::getCurrent();
|
||||
tlen = tm.strftime(buffer, size, "%Y/%m/%d %H:%M:%S.%03f");
|
||||
sprintf(buffer+tlen, " %.*s", size-tlen-2, epicsThreadGetNameSelf());
|
||||
}
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
void streamEpicsPrintTimestamp(char* buffer, int size)
|
||||
{
|
||||
int tlen;
|
||||
@ -292,6 +298,14 @@ void streamEpicsPrintTimestamp(char* buffer, int size)
|
||||
tlen = strlen(buffer);
|
||||
sprintf(buffer+tlen, " %.*s", size-tlen-2, taskName(0));
|
||||
}
|
||||
#else
|
||||
void streamEpicsPrintTimestamp(char* buffer, int size)
|
||||
{
|
||||
int tlen;
|
||||
epicsTime tm = epicsTime::getCurrent();
|
||||
tlen = tm.strftime(buffer, size, "%Y/%m/%d %H:%M:%S.%06f");
|
||||
sprintf(buffer+tlen, " %.*s", size-tlen-2, epicsThreadGetNameSelf());
|
||||
}
|
||||
#endif
|
||||
|
||||
long Stream::
|
||||
@ -336,6 +350,12 @@ report(int interest)
|
||||
{
|
||||
printf(" %s: %s\n", pstream->name(),
|
||||
pstream->ioLink->value.instio.string);
|
||||
if (interest == 3)
|
||||
{
|
||||
StreamBuffer buffer;
|
||||
pstream->printStatus(buffer);
|
||||
printf(" %s\n", buffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
@ -393,30 +413,50 @@ long streamInit(int after)
|
||||
return OK;
|
||||
}
|
||||
|
||||
long streamInitRecord(dbCommon* record, struct link *ioLink,
|
||||
long streamInitRecord(dbCommon* record, const struct link *ioLink,
|
||||
streamIoFunction readData, streamIoFunction writeData)
|
||||
{
|
||||
char filename[80];
|
||||
char protocol[80];
|
||||
char busname[80];
|
||||
int addr = -1;
|
||||
char busparam[80];
|
||||
memset(busparam, 0 ,sizeof(busparam));
|
||||
|
||||
debug("streamInitRecord(%s): SEVR=%d\n", record->name, record->sevr);
|
||||
Stream* pstream = (Stream*)record->dpvt;
|
||||
if (!pstream)
|
||||
{
|
||||
// initialize the first time
|
||||
debug("streamInitRecord(%s): create new Stream object\n",
|
||||
record->name);
|
||||
pstream = new Stream(record, ioLink, readData, writeData);
|
||||
record->dpvt = pstream;
|
||||
} else {
|
||||
// stop any running protocol
|
||||
debug("streamInitRecord(%s): stop running protocol\n",
|
||||
record->name);
|
||||
pstream->finishProtocol(Stream::Abort);
|
||||
}
|
||||
// scan the i/o link
|
||||
debug("streamInitRecord(%s): parse link \"%s\"\n",
|
||||
record->name, ioLink->value.instio.string);
|
||||
pstream->parseLink(ioLink, filename, protocol,
|
||||
busname, &addr, busparam);
|
||||
// (re)initialize bus and protocol
|
||||
long status = pstream->initRecord();
|
||||
debug("streamInitRecord(%s): calling initRecord\n",
|
||||
record->name);
|
||||
long status = pstream->initRecord(filename, protocol,
|
||||
busname, addr, busparam);
|
||||
if (status != OK && status != DO_NOT_CONVERT)
|
||||
{
|
||||
error("%s: Record initialization failed\n", record->name);
|
||||
}
|
||||
if (!pstream->ioscanpvt)
|
||||
else if (!pstream->ioscanpvt)
|
||||
{
|
||||
scanIoInit(&pstream->ioscanpvt);
|
||||
}
|
||||
debug("streamInitRecord(%s) done status=%#lx\n", record->name, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -436,7 +476,8 @@ long streamGetIointInfo(int cmd, dbCommon *record, IOSCANPVT *ppvt)
|
||||
{
|
||||
Stream* pstream = (Stream*)record->dpvt;
|
||||
debug("streamGetIointInfo(%s,cmd=%d): pstream=%p, ioscanpvt=%p\n",
|
||||
record->name, cmd, (void*)pstream, pstream ? pstream->ioscanpvt : NULL);
|
||||
record->name, cmd,
|
||||
(void*)pstream, pstream ? pstream->ioscanpvt : NULL);
|
||||
if (!pstream)
|
||||
{
|
||||
error("streamGetIointInfo called without stream instance\n");
|
||||
@ -495,20 +536,20 @@ long streamScanfN(dbCommon* record, format_t *format,
|
||||
// Stream methods ////////////////////////////////////////////////////////
|
||||
|
||||
Stream::
|
||||
Stream(dbCommon* _record, struct link *ioLink,
|
||||
Stream(dbCommon* _record, const struct link *ioLink,
|
||||
streamIoFunction readData, streamIoFunction writeData)
|
||||
:record(_record), ioLink(ioLink), readData(readData), writeData(writeData)
|
||||
{
|
||||
streamname = record->name;
|
||||
#ifdef EPICS_3_14
|
||||
timerQueue = &epicsTimerQueueActive::allocate(true);
|
||||
timer = &timerQueue->createTimer();
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
timer = wdCreate();
|
||||
mutex = semMCreate(SEM_INVERSION_SAFE | SEM_Q_PRIORITY);
|
||||
initDone = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
|
||||
callbackSetCallback(expire, &timeoutCallback);
|
||||
callbackSetUser(this, &timeoutCallback);
|
||||
#else
|
||||
timerQueue = &epicsTimerQueueActive::allocate(true);
|
||||
timer = &timerQueue->createTimer();
|
||||
#endif
|
||||
callbackSetCallback(streamExecuteCommand, &commandCallback);
|
||||
callbackSetUser(this, &commandCallback);
|
||||
@ -532,59 +573,61 @@ Stream::
|
||||
record->dpvt = NULL;
|
||||
debug("~Stream(%s): dpvt cleared\n", name());
|
||||
}
|
||||
#ifdef EPICS_3_14
|
||||
#ifdef EPICS_3_13
|
||||
wdDelete(timer);
|
||||
debug("~Stream(%s): watchdog destroyed\n", name());
|
||||
#else
|
||||
timer->destroy();
|
||||
debug("~Stream(%s): timer destroyed\n", name());
|
||||
timerQueue->release();
|
||||
debug("~Stream(%s): timer queue released\n", name());
|
||||
#else
|
||||
wdDelete(timer);
|
||||
debug("~Stream(%s): watchdog destroyed\n", name());
|
||||
#endif
|
||||
releaseMutex();
|
||||
}
|
||||
|
||||
long Stream::
|
||||
initRecord()
|
||||
parseLink(const struct link *ioLink, char* filename,
|
||||
char* protocol, char* busname, int* addr, char* busparam)
|
||||
{
|
||||
// scan link parameters: filename protocol busname addr busparam
|
||||
// It is safe to call this function again with different
|
||||
// link text or different protocol file.
|
||||
|
||||
char filename[80];
|
||||
char protocol[80];
|
||||
char busname[80];
|
||||
int addr = -1;
|
||||
char busparam[80];
|
||||
// parse link parameters: filename protocol busname addr busparam
|
||||
int n;
|
||||
|
||||
if (ioLink->type != INST_IO)
|
||||
{
|
||||
error("%s: Wrong link type %s\n", name(),
|
||||
error("%s: Wrong I/O link type %s\n", name(),
|
||||
pamaplinkType[ioLink->type].strvalue);
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
int items = sscanf(ioLink->value.instio.string, "%79s%79s%79s%n%i%n",
|
||||
filename, protocol, busname, &n, &addr, &n);
|
||||
int items = sscanf(ioLink->value.instio.string, "%s%s%s%n%i%n",
|
||||
filename, protocol, busname, &n, addr, &n);
|
||||
if (items <= 0)
|
||||
{
|
||||
error("%s: Empty link. Forgot the leading '@' or confused INP with OUT ?\n",
|
||||
error("%s: Empty I/O link. "
|
||||
"Forgot the leading '@' or confused INP with OUT ?\n",
|
||||
name());
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
if (items < 3)
|
||||
{
|
||||
error("%s: Wrong link format\n"
|
||||
error("%s: Wrong I/O link format\n"
|
||||
" expect \"@file protocol bus addr params\"\n"
|
||||
" in \"@%s\"\n", name(),
|
||||
ioLink->value.instio.string);
|
||||
return S_dev_badInitRet;
|
||||
}
|
||||
memset(busparam, 0 ,80);
|
||||
for (n = 0; isspace((unsigned char)ioLink->value.instio.string[n]); n++);
|
||||
strncpy (busparam, ioLink->value.constantStr+n, 79);
|
||||
while (isspace((unsigned char)ioLink->value.instio.string[n])) n++;
|
||||
strcpy (busparam, ioLink->value.constantStr+n);
|
||||
return OK;
|
||||
}
|
||||
|
||||
long Stream::
|
||||
initRecord(const char* filename, const char* protocol,
|
||||
const char* busname, int addr, const char* busparam)
|
||||
{
|
||||
// It is safe to call this function again with different arguments
|
||||
|
||||
// attach to bus interface
|
||||
debug("Stream::initRecord %s: attachBus(%s, %d, \"%s\")\n",
|
||||
name(), busname, addr, busparam);
|
||||
if (!attachBus(busname, addr, busparam))
|
||||
{
|
||||
error("%s: Can't attach to bus %s %d\n",
|
||||
@ -593,6 +636,8 @@ initRecord()
|
||||
}
|
||||
|
||||
// parse protocol file
|
||||
debug("Stream::initRecord %s: parse(%s, %s)\n",
|
||||
name(), filename, protocol);
|
||||
if (!parse(filename, protocol))
|
||||
{
|
||||
error("%s: Protocol parse error\n",
|
||||
@ -610,7 +655,8 @@ initRecord()
|
||||
name());
|
||||
if (record->scan == SCAN_IO_EVENT)
|
||||
{
|
||||
debug("Stream::initRecord %s: restarting \"I/O Intr\" after reload\n",
|
||||
debug("Stream::initRecord %s: "
|
||||
"restarting \"I/O Intr\" after reload\n",
|
||||
name());
|
||||
if (!startProtocol(StartAsync))
|
||||
{
|
||||
@ -635,10 +681,10 @@ initRecord()
|
||||
}
|
||||
debug("Stream::initRecord %s: waiting for initDone\n",
|
||||
name());
|
||||
#ifdef EPICS_3_14
|
||||
initDone.wait();
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
semTake(initDone, WAIT_FOREVER);
|
||||
#else
|
||||
initDone.wait();
|
||||
#endif
|
||||
debug("Stream::initRecord %s: initDone\n",
|
||||
name());
|
||||
@ -664,8 +710,11 @@ process()
|
||||
{
|
||||
if (status != NO_ALARM)
|
||||
{
|
||||
debug("Stream::process(%s) error status=%d\n",
|
||||
name(), status);
|
||||
debug("Stream::process(%s) error status=%s (%d)\n",
|
||||
name(),
|
||||
status >= 0 && status < ALARM_NSTATUS ?
|
||||
epicsAlarmConditionStrings[status] : "ERROR",
|
||||
status);
|
||||
(void) recGblSetSevr(record, status, INVALID_ALARM);
|
||||
return false;
|
||||
}
|
||||
@ -744,7 +793,8 @@ scan(format_t *format, void* value, size_t maxStringSize)
|
||||
break;
|
||||
case DBF_STRING:
|
||||
sptr = (char*)value;
|
||||
currentValueLength = scanValue(*format->priv, sptr, maxStringSize);
|
||||
currentValueLength = scanValue(*format->priv, sptr,
|
||||
maxStringSize);
|
||||
break;
|
||||
default:
|
||||
error("INTERNAL ERROR (%s): Illegal format type\n", name());
|
||||
@ -762,20 +812,20 @@ scan(format_t *format, void* value, size_t maxStringSize)
|
||||
|
||||
// epicsTimerNotify virtual method ///////////////////////////////////////
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
epicsTimerNotify::expireStatus Stream::
|
||||
expire(const epicsTime&)
|
||||
{
|
||||
timerCallback();
|
||||
return noRestart;
|
||||
}
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
void Stream::
|
||||
expire(CALLBACK *pcallback)
|
||||
{
|
||||
Stream* pstream = static_cast<Stream*>(pcallback->user);
|
||||
pstream->timerCallback();
|
||||
}
|
||||
#else
|
||||
epicsTimerNotify::expireStatus Stream::
|
||||
expire(const epicsTime&)
|
||||
{
|
||||
timerCallback();
|
||||
return noRestart;
|
||||
}
|
||||
#endif
|
||||
|
||||
// StreamCore virtual methods ////////////////////////////////////////////
|
||||
@ -835,10 +885,10 @@ protocolFinishHook(ProtocolResult result)
|
||||
}
|
||||
if (flags & InitRun)
|
||||
{
|
||||
#ifdef EPICS_3_14
|
||||
initDone.signal();
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
semGive(initDone);
|
||||
#else
|
||||
initDone.signal();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@ -891,13 +941,13 @@ startTimer(unsigned long timeout)
|
||||
{
|
||||
debug("Stream::startTimer(stream=%s, timeout=%lu) = %f seconds\n",
|
||||
name(), timeout, timeout * 0.001);
|
||||
#ifdef EPICS_3_14
|
||||
timer->start(*this, timeout * 0.001);
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
callbackSetPriority(priority(), &timeoutCallback);
|
||||
wdStart(timer, (timeout+1)*sysClkRateGet()/1000-1,
|
||||
reinterpret_cast<FUNCPTR>(callbackRequest),
|
||||
reinterpret_cast<int>(&timeoutCallback));
|
||||
#else
|
||||
timer->start(*this, timeout * 0.001);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -957,7 +1007,8 @@ formatValue(const StreamFormat& format, const void* fieldaddress)
|
||||
|
||||
if (format.type != double_format)
|
||||
{
|
||||
error ("%s: can only read double values from TIME field\n", name());
|
||||
error ("%s: can only read double values from TIME field\n",
|
||||
name());
|
||||
return false;
|
||||
}
|
||||
if (pdbaddr->precord == record)
|
||||
@ -965,8 +1016,10 @@ formatValue(const StreamFormat& format, const void* fieldaddress)
|
||||
/* if getting time from own record, update timestamp first */
|
||||
recGblGetTimeStamp(record);
|
||||
}
|
||||
time = pdbaddr->precord->time.secPastEpoch + 631152000u + pdbaddr->precord->time.nsec * 1e-9;
|
||||
debug("Stream::formatValue(%s): read %f from TIME field\n", name(), time);
|
||||
time = pdbaddr->precord->time.secPastEpoch +
|
||||
631152000u + pdbaddr->precord->time.nsec * 1e-9;
|
||||
debug("Stream::formatValue(%s): read %f from TIME field\n",
|
||||
name(), time);
|
||||
return printValue(format, time);
|
||||
}
|
||||
|
||||
@ -1004,7 +1057,8 @@ formatValue(const StreamFormat& format, const void* fieldaddress)
|
||||
return false;
|
||||
break;
|
||||
case pseudo_format:
|
||||
error("%s: %%(FIELD) syntax not allowed with pseudo formats\n",
|
||||
error("%s: %%(FIELD) syntax not allowed "
|
||||
"with pseudo formats\n",
|
||||
name());
|
||||
default:
|
||||
error("INTERNAL ERROR %s: Illegal format.type=%d\n",
|
||||
@ -1054,7 +1108,8 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
buffer = fieldBuffer.clear().reserve(size);
|
||||
for (nord = 0; nord < nelem; nord++)
|
||||
{
|
||||
debug("Stream::matchValue(%s): buffer before: %s\n", name(), fieldBuffer.expand()());
|
||||
debug("Stream::matchValue(%s): buffer before: %s\n",
|
||||
name(), fieldBuffer.expand()());
|
||||
switch (format.type)
|
||||
{
|
||||
case long_format:
|
||||
@ -1068,7 +1123,8 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
case enum_format:
|
||||
{
|
||||
consumed = scanValue(format, lval);
|
||||
if (consumed >= 0) ((epicsUInt16*)buffer)[nord] = (epicsUInt16)lval;
|
||||
if (consumed >= 0)
|
||||
((epicsUInt16*)buffer)[nord] = (epicsUInt16)lval;
|
||||
debug("Stream::matchValue(%s): %s[%li] = %li\n",
|
||||
name(), pdbaddr->precord->name, nord, lval);
|
||||
break;
|
||||
@ -1076,10 +1132,13 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
case double_format:
|
||||
{
|
||||
consumed = scanValue(format, dval);
|
||||
// Direct assignment to buffer fails fith gcc 3.4.3 for xscale_be
|
||||
// Direct assignment to buffer fails with
|
||||
// gcc 3.4.3 for xscale_be
|
||||
// Optimization bug?
|
||||
epicsFloat64 f64=dval;
|
||||
if (consumed >= 0) memcpy(((epicsFloat64*)buffer)+nord, &f64, sizeof(f64));
|
||||
if (consumed >= 0)
|
||||
memcpy(((epicsFloat64*)buffer)+nord,
|
||||
&f64, sizeof(f64));
|
||||
debug("Stream::matchValue(%s): %s[%li] = %#g %#g\n",
|
||||
name(), pdbaddr->precord->name, nord, dval,
|
||||
((epicsFloat64*)buffer)[nord]);
|
||||
@ -1090,7 +1149,8 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
consumed = scanValue(format,
|
||||
buffer+MAX_STRING_SIZE*nord, MAX_STRING_SIZE);
|
||||
debug("Stream::matchValue(%s): %s[%li] = \"%.*s\"\n",
|
||||
name(), pdbaddr->precord->name, nord, MAX_STRING_SIZE, buffer+MAX_STRING_SIZE*nord);
|
||||
name(), pdbaddr->precord->name, nord,
|
||||
MAX_STRING_SIZE, buffer+MAX_STRING_SIZE*nord);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1098,7 +1158,8 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
"Illegal format type\n", name());
|
||||
return false;
|
||||
}
|
||||
debug("Stream::matchValue(%s): buffer after: %s\n", name(), fieldBuffer.expand()());
|
||||
debug("Stream::matchValue(%s): buffer after: %s\n",
|
||||
name(), fieldBuffer.expand()());
|
||||
if (consumed < 0) break;
|
||||
consumedInput += consumed;
|
||||
}
|
||||
@ -1107,7 +1168,8 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
// scan error: set other record to alarm status
|
||||
if (pdbaddr->precord != record)
|
||||
{
|
||||
(void) recGblSetSevr(pdbaddr->precord, CALC_ALARM, INVALID_ALARM);
|
||||
(void) recGblSetSevr(pdbaddr->precord,
|
||||
CALC_ALARM, INVALID_ALARM);
|
||||
if (!INIT_RUN)
|
||||
{
|
||||
// process other record to send alarm monitor
|
||||
@ -1121,19 +1183,24 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
#ifdef epicsTimeEventDeviceTime
|
||||
if (format.type != double_format)
|
||||
{
|
||||
error ("%s: can only write double values to TIME field\n", name());
|
||||
error ("%s: can only write double values to TIME field\n",
|
||||
name());
|
||||
return false;
|
||||
}
|
||||
dval = dval-631152000u;
|
||||
pdbaddr->precord->time.secPastEpoch = (long)dval;
|
||||
/* rouding: we don't have 9 digits precision in a double of today's number of seconds */
|
||||
// rouding: we don't have 9 digits precision
|
||||
// in a double of today's number of seconds
|
||||
pdbaddr->precord->time.nsec = (long)((dval-(long)dval)*1e6)*1000;
|
||||
debug("Stream::matchValue(%s): writing %i.%i to TIME field\n", name(),
|
||||
pdbaddr->precord->time.secPastEpoch, pdbaddr->precord->time.nsec);
|
||||
debug("Stream::matchValue(%s): writing %i.%i to TIME field\n",
|
||||
name(),
|
||||
pdbaddr->precord->time.secPastEpoch,
|
||||
pdbaddr->precord->time.nsec);
|
||||
pdbaddr->precord->tse = epicsTimeEventDeviceTime;
|
||||
return true;
|
||||
#else
|
||||
error ("%s: writing TIME field is not supported in this EPICS version\n", name());
|
||||
error ("%s: writing TIME field is not supported "
|
||||
"in this EPICS version\n", name());
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@ -1166,7 +1233,8 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||
fieldBuffer.expand()());
|
||||
putfunc = "dbPutField";
|
||||
status = dbPutField(pdbaddr, dbfMapping[format.type], buffer, nord);
|
||||
status = dbPutField(pdbaddr, dbfMapping[format.type],
|
||||
buffer, nord);
|
||||
}
|
||||
if (status != 0)
|
||||
{
|
||||
@ -1229,13 +1297,15 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
// Pass command to iocsh
|
||||
#ifdef EPICS_3_13
|
||||
// Pass command to vxWorks shell
|
||||
extern "C" int execute(const char *cmd);
|
||||
|
||||
void streamExecuteCommand(CALLBACK *pcallback)
|
||||
{
|
||||
Stream* pstream = static_cast<Stream*>(pcallback->user);
|
||||
|
||||
if (iocshCmd(pstream->outputLine()) != OK)
|
||||
if (execute(pstream->outputLine()) != OK)
|
||||
{
|
||||
pstream->execCallback(StreamIoFault);
|
||||
}
|
||||
@ -1245,14 +1315,12 @@ void streamExecuteCommand(CALLBACK *pcallback)
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Pass command to vxWorks shell
|
||||
extern "C" int execute(const char *cmd);
|
||||
|
||||
// Pass command to iocsh
|
||||
void streamExecuteCommand(CALLBACK *pcallback)
|
||||
{
|
||||
Stream* pstream = static_cast<Stream*>(pcallback->user);
|
||||
|
||||
if (execute(pstream->outputLine()) != OK)
|
||||
if (iocshCmd(pstream->outputLine()) != OK)
|
||||
{
|
||||
pstream->execCallback(StreamIoFault);
|
||||
}
|
||||
@ -1274,19 +1342,19 @@ execute()
|
||||
void Stream::
|
||||
lockMutex()
|
||||
{
|
||||
#ifdef EPICS_3_14
|
||||
mutex.lock();
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
semTake(mutex, WAIT_FOREVER);
|
||||
#else
|
||||
mutex.lock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Stream::
|
||||
releaseMutex()
|
||||
{
|
||||
#ifdef EPICS_3_14
|
||||
mutex.unlock();
|
||||
#else
|
||||
#ifdef EPICS_3_13
|
||||
semGive(mutex);
|
||||
#else
|
||||
mutex.unlock();
|
||||
#endif
|
||||
}
|
||||
|
@ -1037,7 +1037,7 @@ compileNumber(unsigned long& number, const char*& source, unsigned long max)
|
||||
"Garbage after numeric value: %s\n", buffer());
|
||||
return false;
|
||||
}
|
||||
if (n < 0 || n > max)
|
||||
if (n > max)
|
||||
{
|
||||
debug("StreamProtocolParser::Protocol::compileNumber: %s\n",
|
||||
buffer.expand()());
|
||||
@ -1059,7 +1059,6 @@ compileString(StreamBuffer& buffer, const char*& source,
|
||||
FormatType formatType, Client* client, int quoted)
|
||||
{
|
||||
bool escaped = false;
|
||||
int n;
|
||||
int newline = 0;
|
||||
StreamBuffer formatbuffer;
|
||||
int formatpos = buffer.length();
|
||||
@ -1136,7 +1135,8 @@ compileString(StreamBuffer& buffer, const char*& source,
|
||||
if (escaped) // char after \ in quoted text
|
||||
{
|
||||
escaped = false;
|
||||
unsigned int temp;
|
||||
unsigned int c;
|
||||
int n=1;
|
||||
switch (*source)
|
||||
{
|
||||
case '$': // can't be: readToken would have made a token from this
|
||||
@ -1145,61 +1145,50 @@ compileString(StreamBuffer& buffer, const char*& source,
|
||||
return false;
|
||||
case '?':
|
||||
buffer.append(skip);
|
||||
break;
|
||||
source++;
|
||||
continue;
|
||||
case '_':
|
||||
buffer.append(whitespace);
|
||||
break;
|
||||
source++;
|
||||
continue;
|
||||
case 'a':
|
||||
buffer.append(7);
|
||||
c=7;
|
||||
break;
|
||||
case 'b':
|
||||
buffer.append(8);
|
||||
c=8;
|
||||
break;
|
||||
case 't':
|
||||
buffer.append(9);
|
||||
c=9;
|
||||
break;
|
||||
case 'n':
|
||||
buffer.append('\n');
|
||||
c='\n';
|
||||
break;
|
||||
case 'r':
|
||||
buffer.append('\r');
|
||||
c='\r';
|
||||
break;
|
||||
case 'e':
|
||||
buffer.append(esc).append(esc);
|
||||
c=esc;
|
||||
break;
|
||||
case '0': // octal numbers (max 3 digits after 0)
|
||||
sscanf (source, "%3o%n", &temp, &n);
|
||||
if (temp > 0xFF)
|
||||
case '0': // octal numbers (max 4 digits)
|
||||
sscanf (source, "%4o%n", &c, &n); //cannot fail
|
||||
if (c > 0xFF)
|
||||
{
|
||||
error(line, filename(),
|
||||
"Octal source %#o does not fit in byte: %s\n",
|
||||
temp, source-1);
|
||||
"Octal number %#o does not fit in byte: \"%s\"\n",
|
||||
c, source-1);
|
||||
return false;
|
||||
}
|
||||
if (formatType != NoFormat &&
|
||||
(temp < last_function_code || temp == esc))
|
||||
{
|
||||
buffer.append(esc);
|
||||
}
|
||||
buffer.append(temp);
|
||||
source += n;
|
||||
continue;
|
||||
case 'x': // hex numbers (max 2 digits after 0)
|
||||
if (sscanf (source+1, "%2x%n", &temp, &n) < 1)
|
||||
break;
|
||||
case 'x': // hex numbers (max 2 digits after x)
|
||||
if (sscanf (source+1, "%2x%n", &c, &n) < 1)
|
||||
{
|
||||
error(line, filename(),
|
||||
"Hex digit expected after \\x: %s\n",
|
||||
"Hex digit expected after \\x: \"%s\"\n",
|
||||
source-1);
|
||||
return false;
|
||||
}
|
||||
if (formatType != NoFormat &&
|
||||
(temp < last_function_code || temp == esc))
|
||||
{
|
||||
buffer.append(esc);
|
||||
}
|
||||
buffer.append(temp);
|
||||
source += n+1;
|
||||
continue;
|
||||
n++;
|
||||
break;
|
||||
case '1': // decimal numbers (max 3 digits)
|
||||
case '2':
|
||||
case '3':
|
||||
@ -1209,26 +1198,24 @@ compileString(StreamBuffer& buffer, const char*& source,
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
sscanf (source, "%3u%n", &temp, &n);
|
||||
if (temp > 0xFF)
|
||||
sscanf (source, "%3u%n", &c, &n); //cannot fail
|
||||
if (c > 0xFF)
|
||||
{
|
||||
error(line, filename(),
|
||||
"Decimal source %d does not fit in byte: %s\n",
|
||||
temp, source-1);
|
||||
"Decimal number %d does not fit in byte: \"%s\"\n",
|
||||
c, source-1);
|
||||
return false;
|
||||
}
|
||||
if (formatType != NoFormat &&
|
||||
(temp < last_function_code || temp == esc))
|
||||
{
|
||||
buffer.append(esc);
|
||||
}
|
||||
buffer.append(temp);
|
||||
source += n;
|
||||
continue;
|
||||
break;
|
||||
default: // escaped literals
|
||||
buffer.append(esc).append(*source);
|
||||
c=*source;
|
||||
}
|
||||
source++;
|
||||
source+=n;
|
||||
if (formatType != NoFormat)
|
||||
{
|
||||
buffer.append(esc);
|
||||
}
|
||||
buffer.append(c);
|
||||
continue;
|
||||
}
|
||||
if (quoted) // look for ending quotes and escapes
|
||||
@ -1281,7 +1268,7 @@ compileString(StreamBuffer& buffer, const char*& source,
|
||||
}
|
||||
// try numeric byte value
|
||||
char* p;
|
||||
int temp = strtol(source, &p, 0);
|
||||
int c = strtol(source, &p, 0);
|
||||
if (p != source)
|
||||
{
|
||||
if (*p != 0)
|
||||
@ -1290,18 +1277,17 @@ compileString(StreamBuffer& buffer, const char*& source,
|
||||
"Garbage after numeric source: %s", source);
|
||||
return false;
|
||||
}
|
||||
if (temp > 0xFF || temp < -0x80)
|
||||
if (c > 0xFF || c < -0x80)
|
||||
{
|
||||
error(line, filename(),
|
||||
"Value %s does not fit in byte\n", source);
|
||||
return false;
|
||||
}
|
||||
if (formatType != NoFormat &&
|
||||
(temp < last_function_code || temp == esc))
|
||||
if (formatType != NoFormat)
|
||||
{
|
||||
buffer.append(esc);
|
||||
}
|
||||
buffer.append(temp);
|
||||
buffer.append(c);
|
||||
source = p+1+sizeof(int);
|
||||
continue;
|
||||
}
|
||||
@ -1348,7 +1334,7 @@ compileString(StreamBuffer& buffer, const char*& source,
|
||||
{"del", 0x7f}
|
||||
};
|
||||
size_t i;
|
||||
char c = 0;
|
||||
c=-1;
|
||||
for (i = 0; i < sizeof(codes)/sizeof(*codes); i++)
|
||||
{
|
||||
if (strcmp(source, codes[i].name) == 0)
|
||||
@ -1361,8 +1347,7 @@ compileString(StreamBuffer& buffer, const char*& source,
|
||||
source);
|
||||
return false;
|
||||
}
|
||||
if (formatType != NoFormat &&
|
||||
(temp < last_function_code || temp == esc))
|
||||
if (formatType != NoFormat)
|
||||
{
|
||||
buffer.append(esc);
|
||||
}
|
||||
@ -1371,10 +1356,10 @@ compileString(StreamBuffer& buffer, const char*& source,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (c) continue;
|
||||
if (c >= 0) continue;
|
||||
// source may contain a function name
|
||||
error(line, filename(),
|
||||
"Unexpected word: %s\n", source);
|
||||
"Unexpected word: \"%s\"\n", source);
|
||||
return false;
|
||||
}
|
||||
debug("StreamProtocolParser::Protocol::compileString buffer=%s\n", buffer.expand()());
|
||||
@ -1493,8 +1478,10 @@ compileFormat(StreamBuffer& buffer, const char*& formatstr,
|
||||
buffer.append(&streamFormat, sizeof(streamFormat));
|
||||
buffer.append(infoString);
|
||||
|
||||
debug("StreamProtocolParser::Protocol::compileFormat: format.type=%s, infolen=%d\n",
|
||||
StreamFormatTypeStr[streamFormat.type], streamFormat.infolen);
|
||||
debug("StreamProtocolParser::Protocol::compileFormat: format.type=%s, "
|
||||
"infolen=%d infostring=\"%s\"\n",
|
||||
StreamFormatTypeStr[streamFormat.type],
|
||||
streamFormat.infolen, infoString.expand()());
|
||||
formatstr = source; // move pointer after parsed format
|
||||
return true;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define STR2(x) #x
|
||||
#define STR(x) STR2(x)
|
||||
const char StreamVersion [] =
|
||||
"StreamDevice " STR(STREAM_MAJOR) "." STR(STREAM_MINOR)
|
||||
"StreamDevice " STR(STREAM_MAJOR)
|
||||
"." STR(STREAM_MINOR)
|
||||
"." STR(STREAM_PATCHLEVEL)
|
||||
" built " __DATE__ " " __TIME__;
|
||||
|
||||
|
@ -22,7 +22,8 @@
|
||||
#define devStream_h
|
||||
|
||||
#define STREAM_MAJOR 2
|
||||
#define STREAM_MINOR 4
|
||||
#define STREAM_MINOR 6
|
||||
#define STREAM_PATCHLEVEL 6
|
||||
|
||||
#if defined(__vxworks) || defined(vxWorks)
|
||||
#include <vxWorks.h>
|
||||
@ -40,14 +41,19 @@
|
||||
#define INIT_RUN (!interruptAccept)
|
||||
|
||||
#include <epicsVersion.h>
|
||||
#if (EPICS_VERSION == 3 && EPICS_REVISION == 14)
|
||||
#define EPICS_3_14
|
||||
#ifdef BASE_VERSION
|
||||
#define EPICS_3_13
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && !defined(EPICS_3_14)
|
||||
#if defined(__cplusplus) && defined(EPICS_3_13)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define devStream_epicsExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dbCommon.h>
|
||||
#include <dbScan.h>
|
||||
@ -55,7 +61,12 @@ extern "C" {
|
||||
/* #include <dbFldTypes.h> */
|
||||
#include <dbAccess.h>
|
||||
|
||||
#if defined(__cplusplus) && !defined(EPICS_3_14)
|
||||
#ifdef devStream_epicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && defined(EPICS_3_13)
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -69,23 +80,22 @@ typedef const struct format_s {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllimport)
|
||||
#endif
|
||||
extern FILE* StreamDebugFile;
|
||||
epicsShareExtern FILE* StreamDebugFile;
|
||||
|
||||
extern const char StreamVersion [];
|
||||
|
||||
typedef long (*streamIoFunction) (dbCommon*, format_t*);
|
||||
|
||||
long streamInit(int after);
|
||||
long streamInitRecord(dbCommon *record, struct link *ioLink,
|
||||
epicsShareFunc long streamInit(int after);
|
||||
epicsShareFunc long streamInitRecord(dbCommon *record,
|
||||
const struct link *ioLink,
|
||||
streamIoFunction readData, streamIoFunction writeData);
|
||||
long streamReport(int interest);
|
||||
long streamReadWrite(dbCommon *record);
|
||||
long streamGetIointInfo(int cmd, dbCommon *record, IOSCANPVT *ppvt);
|
||||
long streamPrintf(dbCommon *record, format_t *format, ...);
|
||||
long streamScanfN(dbCommon *record, format_t *format,
|
||||
epicsShareFunc long streamReport(int interest);
|
||||
epicsShareFunc long streamReadWrite(dbCommon *record);
|
||||
epicsShareFunc long streamGetIointInfo(int cmd,
|
||||
dbCommon *record, IOSCANPVT *ppvt);
|
||||
epicsShareFunc long streamPrintf(dbCommon *record, format_t *format, ...);
|
||||
epicsShareFunc long streamScanfN(dbCommon *record, format_t *format,
|
||||
void*, size_t maxStringSize);
|
||||
|
||||
/* backward compatibility stuff */
|
||||
|
@ -1,6 +1,10 @@
|
||||
if (@ARGV[0] == "-3.13") {
|
||||
shift;
|
||||
} else {
|
||||
print "variable(streamDebug, int)\n";
|
||||
print "registrar(streamRegistrar)\n";
|
||||
}
|
||||
print "driver(stream)\n";
|
||||
for (@ARGV) {
|
||||
print "device($_,INST_IO,dev${_}Stream,\"stream\")\n";
|
||||
}
|
||||
print "driver(stream)\n";
|
||||
print "variable(streamDebug, int)\n";
|
||||
print "registrar(streamRegistrar)\n";
|
||||
|
@ -29,18 +29,13 @@ PROD_SRCS_vxWorks = -nil-
|
||||
PROD_LIBS = stream
|
||||
|
||||
ifdef ASYN
|
||||
# Which types of asyn busses do you have?
|
||||
|
||||
# asynDriver up to version 4-16 does not support serial port for Windows!
|
||||
#ifneq ($(OS_CLASS), WIN32)
|
||||
streamApp_DBD += drvAsynSerialPort.dbd
|
||||
#endif
|
||||
|
||||
streamApp_DBD += drvAsynIPPort.dbd
|
||||
#streamApp_DBD += drvGsIP488.dbd
|
||||
#streamApp_DBD += drvNi1014.dbd
|
||||
streamApp_DBD += drvVxi11.dbd
|
||||
# edit asynRegistrars.dbd if necessary
|
||||
streamApp_DBD += asynRegistrars.dbd
|
||||
# add asynRecord.dbd if you like
|
||||
streamApp_DBD += asynRecord.dbd
|
||||
PROD_LIBS += asyn
|
||||
# cygwin needs separate RPC library for asyn
|
||||
PROD_SYS_LIBS_cygwin32 += $(CYGWIN_RPC_LIB)
|
||||
endif
|
||||
|
||||
ifneq ($(words $(CALC) $(SYNAPPS)), 0)
|
||||
@ -56,7 +51,7 @@ endif
|
||||
streamApp_DBD += stream.dbd
|
||||
|
||||
ifdef PCRE
|
||||
LIB_LIBS += pcre
|
||||
PROD_LIBS += pcre
|
||||
else
|
||||
ifneq ($(words $(PCRE_LIB) $(PCRE_INCLUDE)),0)
|
||||
PROD_SYS_LIBS_DEFAULT += pcre
|
||||
@ -73,7 +68,11 @@ CPPFLAGS += -DDEBUGFILE=StreamDebug.log
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
ifeq ($(BASE_3_14), YES)
|
||||
clean:: myclean
|
||||
else
|
||||
clean: myclean
|
||||
endif
|
||||
|
||||
myclean:
|
||||
$(RM) core* StreamDebug.log
|
||||
|
9
streamApp/asynRegistrars.dbd
Normal file
9
streamApp/asynRegistrars.dbd
Normal file
@ -0,0 +1,9 @@
|
||||
registrar(asynRegister)
|
||||
registrar(asynInterposeFlushRegister)
|
||||
registrar(asynInterposeEosRegister)
|
||||
|
||||
# asynDriver up to version 4-16 does not support serial port for Windows!
|
||||
registrar(drvAsynSerialPortRegisterCommands)
|
||||
registrar(drvAsynIPPortRegisterCommands)
|
||||
registrar(drvAsynIPServerPortRegisterCommands)
|
||||
registrar(vxi11RegisterCommands)
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env wish
|
||||
|
||||
wm iconify .
|
||||
|
||||
proc createTerm {sock} {
|
||||
global socket port
|
||||
toplevel .$sock
|
||||
@ -19,16 +17,8 @@ proc createTerm {sock} {
|
||||
wm title .$sock "port $port <-> [fconfigure $sock -peername]"
|
||||
}
|
||||
|
||||
set port [lindex $argv 0]
|
||||
if {$port == ""} { set port 40000 }
|
||||
if [catch {
|
||||
socket -server connect $port
|
||||
} msg ] {
|
||||
return -code error "$msg (port $port)"
|
||||
}
|
||||
|
||||
proc connect {sock addr port} {
|
||||
fconfigure $sock -blocking 0 -buffering none
|
||||
fconfigure $sock -blocking 0 -buffering none -translation binary
|
||||
createTerm $sock
|
||||
fileevent $sock readable "receiveHandler $sock"
|
||||
}
|
||||
@ -50,11 +40,13 @@ proc escape {string} {
|
||||
}
|
||||
|
||||
proc sendReply {sock text} {
|
||||
.$sock.t mark set insert end
|
||||
.$sock.t insert end $text
|
||||
.$sock.t see end
|
||||
puts -nonewline $sock $text
|
||||
# puts "sending \"[escape $text]\"\n"
|
||||
catch {
|
||||
# ignore that socket may already be closed
|
||||
.$sock.t mark set insert end
|
||||
.$sock.t insert end $text
|
||||
.$sock.t see end
|
||||
puts -nonewline $sock $text
|
||||
}
|
||||
}
|
||||
|
||||
proc checkNum {n} {
|
||||
@ -84,6 +76,10 @@ proc receiveHandler {sock} {
|
||||
"echo" {
|
||||
sendReply $sock [string range $a 5 end]
|
||||
}
|
||||
"binary" {
|
||||
set x [checkNum [lindex $l 1]]
|
||||
sendReply $sock [format %c $x]
|
||||
}
|
||||
"longmsg" {
|
||||
set length [checkNum [lindex $l 1]]
|
||||
sendReply $sock "[string range x[string repeat 0123456789abcdefghijklmnopqrstuvwxyz [expr $length / 36 + 1]] 1 $length]\n"
|
||||
@ -95,7 +91,7 @@ proc receiveHandler {sock} {
|
||||
"start" {
|
||||
set wait [checkNum [lindex $l 1]]
|
||||
set ::counter 0
|
||||
after $wait sendAsync $wait [list [lindex $l 2]]
|
||||
after $wait [list sendAsync $wait "[string range $a [string wordend $a 7] end]"]
|
||||
sendReply $sock "Started\n"
|
||||
}
|
||||
"stop" {
|
||||
@ -116,12 +112,16 @@ proc receiveHandler {sock} {
|
||||
"help" {
|
||||
sendReply $sock "help this text\n"
|
||||
sendReply $sock "echo string reply string\n"
|
||||
sendReply $sock "wait msec reply Done after some time\n"
|
||||
sendReply $sock "binary number reply byte with value number\n"
|
||||
sendReply $sock "longmsg length reply string with length characters\n"
|
||||
sendReply $sock "wait msec reply \"Done\" after some time\n"
|
||||
sendReply $sock "start msec start sending messages priodically\n"
|
||||
sendReply $sock "stop stop sending messages\n"
|
||||
sendReply $sock "set key value set a value\n"
|
||||
sendReply $sock "get key reply value\n"
|
||||
sendReply $sock "set key value store a value into variable key\n"
|
||||
sendReply $sock "get key reply previously stored value from key\n"
|
||||
sendReply $sock "disconnect close connection\n"
|
||||
sendReply $sock "exit kill terminal server\n"
|
||||
|
||||
}
|
||||
}
|
||||
} msg] {
|
||||
@ -133,7 +133,7 @@ proc receiveHandler {sock} {
|
||||
proc sendAsync {wait message} {
|
||||
if {$::counter < 0} return
|
||||
foreach term [array names ::socket] {
|
||||
sendReply $::socket($term) "Message number [incr ::counter] $message\n";
|
||||
sendReply $::socket($term) "Message number [incr ::counter]$message";
|
||||
}
|
||||
after $wait sendAsync $wait [list $message]
|
||||
}
|
||||
@ -153,7 +153,6 @@ rename $paste tkTextPaste_org
|
||||
rename $pastesel tkTextPasteSel_org
|
||||
|
||||
proc $insert {w s} {
|
||||
puts [list insert $w $s]
|
||||
global socket
|
||||
if {[string equal $s ""] || [string equal [$w cget -state] "disabled"]} {
|
||||
return
|
||||
@ -191,8 +190,20 @@ for {set ascii 0x61} {$ascii <= 0x7a} {incr ascii} {
|
||||
bind Text <Control-[format %c $ascii]> ""
|
||||
}
|
||||
#remove bindings on symbolic tags
|
||||
foreach tag {Clear Paste Copy Cut } {
|
||||
foreach tag {Clear Paste Copy Cut} {
|
||||
bind Text <<$tag>> ""
|
||||
}
|
||||
|
||||
bind Text <Control-Key> [list $insert %W %A]
|
||||
|
||||
set port [lindex $argv 0]
|
||||
if {$port == ""} { set port 40000 }
|
||||
if [catch {
|
||||
socket -server connect $port
|
||||
} msg ] {
|
||||
return -code error "$msg (port $port)"
|
||||
}
|
||||
|
||||
label .info -text "Accepting connections on port $port"
|
||||
button .exit -text "Exit" -command exit
|
||||
pack .info .exit -expand yes -fill x
|
||||
|
@ -2,17 +2,20 @@ record (stringout, "$(P):cmd")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto command terminal")
|
||||
field (PRIO, "HIGH")
|
||||
field (VAL, "")
|
||||
}
|
||||
record (stringout, "$(P):info")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto info terminal")
|
||||
field (PRIO, "HIGH")
|
||||
}
|
||||
record (stringout, "$(P):request")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto request($(P):reply.VAL) terminal")
|
||||
field (PRIO, "HIGH")
|
||||
}
|
||||
record (stringin, "$(P):reply")
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
terminator = CR LF;
|
||||
readtimeout = 1000;
|
||||
terminator = LF;
|
||||
readtimeout = 10;
|
||||
pollperiod = 10;
|
||||
replytimeout = 1000;
|
||||
command {
|
||||
|
@ -41,7 +41,7 @@ proc receiveHandler {sock} {
|
||||
}
|
||||
|
||||
proc startioc {} {
|
||||
global debug records protocol startup port sock ioc testname env streamversion
|
||||
global debug records protocol startup port sock ioc testname env streamversion asynversion
|
||||
set fd [open test.db w]
|
||||
puts $fd $records
|
||||
close $fd
|
||||
@ -52,7 +52,10 @@ proc startioc {} {
|
||||
|
||||
if [info exists streamversion] {
|
||||
puts $fd "#!/usr/local/bin/iocsh"
|
||||
puts $fd "require stream,$streamversion"
|
||||
if [info exists asynversion] {
|
||||
puts $fd "require asyn,$asynversion"
|
||||
}
|
||||
puts $fd "require stream2,$streamversion"
|
||||
} else {
|
||||
puts $fd "#!../O.$env(EPICS_HOST_ARCH)/streamApp"
|
||||
puts $fd "dbLoadDatabase ../O.Common/streamApp.dbd"
|
||||
@ -202,3 +205,7 @@ if {[lindex $argv 0] == "-sls"} {
|
||||
set streamversion [lindex $argv 1]
|
||||
set argv [lrange $argv 2 end]
|
||||
}
|
||||
if {[lindex $argv 0] == "-asyn"} {
|
||||
set asynversion [lindex $argv 1]
|
||||
set argv [lrange $argv 2 end]
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ source streamtestlib.tcl
|
||||
# Send commands to the ioc shell with ioccmd
|
||||
|
||||
set records {
|
||||
record (ao, "DZ:test1")
|
||||
record (stringout, "DZ:test1")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto test1 device")
|
||||
@ -15,7 +15,225 @@ set records {
|
||||
}
|
||||
|
||||
set protocol {
|
||||
test1 {out 0x55 0x40 0x04 0x00 0x00 'z;' "%<sum>";}
|
||||
Terminator="\n";
|
||||
test1 {
|
||||
out "sum %s %9.1<sum>"; in "sum %=s %9.1<sum>";
|
||||
out "sum8 %s %9.1<sum8>"; in "sum8 %=s %9.1<sum8>";
|
||||
out "sum16 %s %9.1<sum16>"; in "sum16 %=s %9.1<sum16>";
|
||||
out "sum32 %s %9.1<sum32>"; in "sum32 %=s %9.1<sum32>";
|
||||
out "nsum %s %9.1<nsum>"; in "nsum %=s %9.1<nsum>";
|
||||
out "negsum %s %9.1<negsum>"; in "negsum %=s %9.1<negsum>";
|
||||
out "-sum %s %9.1<-sum>"; in "-sum %=s %9.1<-sum>";
|
||||
out "nsum8 %s %9.1<nsum8>"; in "nsum8 %=s %9.1<nsum8>";
|
||||
out "negsum8 %s %9.1<negsum8>"; in "negsum8 %=s %9.1<negsum8>";
|
||||
out "-sum8 %s %9.1<-sum8>"; in "-sum8 %=s %9.1<-sum8>";
|
||||
out "nsum16 %s %9.1<nsum16>"; in "nsum16 %=s %9.1<nsum16>";
|
||||
out "negsum16 %s %9.1<negsum1>"; in "negsum16 %=s %9.1<negsum1>";
|
||||
out "-sum16 %s %9.1<-sum16>"; in "-sum16 %=s %9.1<-sum16>";
|
||||
out "nsum32 %s %9.1<nsum32>"; in "nsum32 %=s %9.1<nsum32>";
|
||||
out "negsum32 %s %9.1<negsum3>"; in "negsum32 %=s %9.1<negsum3>";
|
||||
out "-sum32 %s %9.1<-sum32>"; in "-sum32 %=s %9.1<-sum32>";
|
||||
out "notsum %s %9.1<notsum>"; in "notsum %=s %9.1<notsum>";
|
||||
out "~sum %s %9.1<~sum>"; in "~sum %=s %9.1<~sum>";
|
||||
out "xor %s %9.1<xor>"; in "xor %=s %9.1<xor>";
|
||||
out "xor8 %s %9.1<xor8>"; in "xor8 %=s %9.1<xor8>";
|
||||
out "xor7 %s %9.1<xor7>"; in "xor7 %=s %9.1<xor7>";
|
||||
out "crc8 %s %9.1<crc8>"; in "crc8 %=s %9.1<crc8>";
|
||||
out "ccitt8 %s %9.1<ccitt8>"; in "ccitt8 %=s %9.1<ccitt8>";
|
||||
out "crc16 %s %9.1<crc16>"; in "crc16 %=s %9.1<crc16>";
|
||||
out "crc16r %s %9.1<crc16r>"; in "crc16r %=s %9.1<crc16r>";
|
||||
out "ccitt16 %s %9.1<ccitt16>"; in "ccitt16 %=s %9.1<ccitt16>";
|
||||
out "ccitt16a %s %9.1<ccitt16a>"; in "ccitt16a %=s %9.1<ccitt16a>";
|
||||
out "ccitt16x %s %9.1<ccitt16x>"; in "ccitt16x %=s %9.1<ccitt16x>";
|
||||
out "crc16c %s %9.1<crc16c>"; in "crc16c %=s %9.1<crc16c>";
|
||||
out "xmodem %s %9.1<xmodem>"; in "xmodem %=s %9.1<xmodem>";
|
||||
out "crc32 %s %9.1<crc32>"; in "crc32 %=s %9.1<crc32>";
|
||||
out "crc32r %s %9.1<crc32r>"; in "crc32r %=s %9.1<crc32r>";
|
||||
out "jamcrc %s %9.1<jamcrc>"; in "jamcrc %=s %9.1<jamcrc>";
|
||||
out "adler32 %s %9.1<adler32>"; in "adler32 %=s %9.1<adler32>";
|
||||
out "hexsum8 %s %9.1<hexsum8>"; in "hexsum8 %=s %9.1<hexsum8>";
|
||||
|
||||
out "sum %s %09.1<sum>"; in "sum %=s %09.1<sum>";
|
||||
out "sum8 %s %09.1<sum8>"; in "sum8 %=s %09.1<sum8>";
|
||||
out "sum16 %s %09.1<sum16>"; in "sum16 %=s %09.1<sum16>";
|
||||
out "sum32 %s %09.1<sum32>"; in "sum32 %=s %09.1<sum32>";
|
||||
out "nsum %s %09.1<nsum>"; in "nsum %=s %09.1<nsum>";
|
||||
out "negsum %s %09.1<negsum>"; in "negsum %=s %09.1<negsum>";
|
||||
out "-sum %s %09.1<-sum>"; in "-sum %=s %09.1<-sum>";
|
||||
out "nsum8 %s %09.1<nsum8>"; in "nsum8 %=s %09.1<nsum8>";
|
||||
out "negsum8 %s %09.1<negsum8>"; in "negsum8 %=s %09.1<negsum8>";
|
||||
out "-sum8 %s %09.1<-sum8>"; in "-sum8 %=s %09.1<-sum8>";
|
||||
out "nsum16 %s %09.1<nsum16>"; in "nsum16 %=s %09.1<nsum16>";
|
||||
out "negsum16 %s %09.1<negsum1>"; in "negsum16 %=s %09.1<negsum1>";
|
||||
out "-sum16 %s %09.1<-sum16>"; in "-sum16 %=s %09.1<-sum16>";
|
||||
out "nsum32 %s %09.1<nsum32>"; in "nsum32 %=s %09.1<nsum32>";
|
||||
out "negsum32 %s %09.1<negsum3>"; in "negsum32 %=s %09.1<negsum3>";
|
||||
out "-sum32 %s %09.1<-sum32>"; in "-sum32 %=s %09.1<-sum32>";
|
||||
out "notsum %s %09.1<notsum>"; in "notsum %=s %09.1<notsum>";
|
||||
out "~sum %s %09.1<~sum>"; in "~sum %=s %09.1<~sum>";
|
||||
out "xor %s %09.1<xor>"; in "xor %=s %09.1<xor>";
|
||||
out "xor8 %s %09.1<xor8>"; in "xor8 %=s %09.1<xor8>";
|
||||
out "xor7 %s %09.1<xor7>"; in "xor7 %=s %09.1<xor7>";
|
||||
out "crc8 %s %09.1<crc8>"; in "crc8 %=s %09.1<crc8>";
|
||||
out "ccitt8 %s %09.1<ccitt8>"; in "ccitt8 %=s %09.1<ccitt8>";
|
||||
out "crc16 %s %09.1<crc16>"; in "crc16 %=s %09.1<crc16>";
|
||||
out "crc16r %s %09.1<crc16r>"; in "crc16r %=s %09.1<crc16r>";
|
||||
out "ccitt16 %s %09.1<ccitt16>"; in "ccitt16 %=s %09.1<ccitt16>";
|
||||
out "ccitt16a %s %09.1<ccitt16a>"; in "ccitt16a %=s %09.1<ccitt16a>";
|
||||
out "ccitt16x %s %09.1<ccitt16x>"; in "ccitt16x %=s %09.1<ccitt16x>";
|
||||
out "crc16c %s %09.1<crc16c>"; in "crc16c %=s %09.1<crc16c>";
|
||||
out "xmodem %s %09.1<xmodem>"; in "xmodem %=s %09.1<xmodem>";
|
||||
out "crc32 %s %09.1<crc32>"; in "crc32 %=s %09.1<crc32>";
|
||||
out "crc32r %s %09.1<crc32r>"; in "crc32r %=s %09.1<crc32r>";
|
||||
out "jamcrc %s %09.1<jamcrc>"; in "jamcrc %=s %09.1<jamcrc>";
|
||||
out "adler32 %s %09.1<adler32>"; in "adler32 %=s %09.1<adler32>";
|
||||
out "hexsum8 %s %09.1<hexsum8>"; in "hexsum8 %=s %09.1<hexsum8>";
|
||||
|
||||
out "sum %s %-9.1<sum>"; in "sum %=s %-9.1<sum>";
|
||||
out "sum8 %s %-9.1<sum8>"; in "sum8 %=s %-9.1<sum8>";
|
||||
out "sum16 %s %-9.1<sum16>"; in "sum16 %=s %-9.1<sum16>";
|
||||
out "sum32 %s %-9.1<sum32>"; in "sum32 %=s %-9.1<sum32>";
|
||||
out "nsum %s %-9.1<nsum>"; in "nsum %=s %-9.1<nsum>";
|
||||
out "negsum %s %-9.1<negsum>"; in "negsum %=s %-9.1<negsum>";
|
||||
out "-sum %s %-9.1<-sum>"; in "-sum %=s %-9.1<-sum>";
|
||||
out "nsum8 %s %-9.1<nsum8>"; in "nsum8 %=s %-9.1<nsum8>";
|
||||
out "negsum8 %s %-9.1<negsum8>"; in "negsum8 %=s %-9.1<negsum8>";
|
||||
out "-sum8 %s %-9.1<-sum8>"; in "-sum8 %=s %-9.1<-sum8>";
|
||||
out "nsum16 %s %-9.1<nsum16>"; in "nsum16 %=s %-9.1<nsum16>";
|
||||
out "negsum16 %s %-9.1<negsum1>"; in "negsum16 %=s %-9.1<negsum1>";
|
||||
out "-sum16 %s %-9.1<-sum16>"; in "-sum16 %=s %-9.1<-sum16>";
|
||||
out "nsum32 %s %-9.1<nsum32>"; in "nsum32 %=s %-9.1<nsum32>";
|
||||
out "negsum32 %s %-9.1<negsum3>"; in "negsum32 %=s %-9.1<negsum3>";
|
||||
out "-sum32 %s %-9.1<-sum32>"; in "-sum32 %=s %-9.1<-sum32>";
|
||||
out "notsum %s %-9.1<notsum>"; in "notsum %=s %-9.1<notsum>";
|
||||
out "~sum %s %-9.1<~sum>"; in "~sum %=s %-9.1<~sum>";
|
||||
out "xor %s %-9.1<xor>"; in "xor %=s %-9.1<xor>";
|
||||
out "xor8 %s %-9.1<xor8>"; in "xor8 %=s %-9.1<xor8>";
|
||||
out "xor7 %s %-9.1<xor7>"; in "xor7 %=s %-9.1<xor7>";
|
||||
out "crc8 %s %-9.1<crc8>"; in "crc8 %=s %-9.1<crc8>";
|
||||
out "ccitt8 %s %-9.1<ccitt8>"; in "ccitt8 %=s %-9.1<ccitt8>";
|
||||
out "crc16 %s %-9.1<crc16>"; in "crc16 %=s %-9.1<crc16>";
|
||||
out "crc16r %s %-9.1<crc16r>"; in "crc16r %=s %-9.1<crc16r>";
|
||||
out "ccitt16 %s %-9.1<ccitt16>"; in "ccitt16 %=s %-9.1<ccitt16>";
|
||||
out "ccitt16a %s %-9.1<ccitt16a>"; in "ccitt16a %=s %-9.1<ccitt16a>";
|
||||
out "ccitt16x %s %-9.1<ccitt16x>"; in "ccitt16x %=s %-9.1<ccitt16x>";
|
||||
out "crc16c %s %-9.1<crc16c>"; in "crc16c %=s %-9.1<crc16c>";
|
||||
out "xmodem %s %-9.1<xmodem>"; in "xmodem %=s %-9.1<xmodem>";
|
||||
out "crc32 %s %-9.1<crc32>"; in "crc32 %=s %-9.1<crc32>";
|
||||
out "crc32r %s %-9.1<crc32r>"; in "crc32r %=s %-9.1<crc32r>";
|
||||
out "jamcrc %s %-9.1<jamcrc>"; in "jamcrc %=s %-9.1<jamcrc>";
|
||||
out "adler32 %s %-9.1<adler32>"; in "adler32 %=s %-9.1<adler32>";
|
||||
out "hexsum8 %s %-9.1<hexsum8>"; in "hexsum8 %=s %-9.1<hexsum8>";
|
||||
|
||||
out "sum %s %#9.1<sum>"; in "sum %=s %#9.1<sum>";
|
||||
out "sum8 %s %#9.1<sum8>"; in "sum8 %=s %#9.1<sum8>";
|
||||
out "sum16 %s %#9.1<sum16>"; in "sum16 %=s %#9.1<sum16>";
|
||||
out "sum32 %s %#9.1<sum32>"; in "sum32 %=s %#9.1<sum32>";
|
||||
out "nsum %s %#9.1<nsum>"; in "nsum %=s %#9.1<nsum>";
|
||||
out "negsum %s %#9.1<negsum>"; in "negsum %=s %#9.1<negsum>";
|
||||
out "-sum %s %#9.1<-sum>"; in "-sum %=s %#9.1<-sum>";
|
||||
out "nsum8 %s %#9.1<nsum8>"; in "nsum8 %=s %#9.1<nsum8>";
|
||||
out "negsum8 %s %#9.1<negsum8>"; in "negsum8 %=s %#9.1<negsum8>";
|
||||
out "-sum8 %s %#9.1<-sum8>"; in "-sum8 %=s %#9.1<-sum8>";
|
||||
out "nsum16 %s %#9.1<nsum16>"; in "nsum16 %=s %#9.1<nsum16>";
|
||||
out "negsum16 %s %#9.1<negsum1>"; in "negsum16 %=s %#9.1<negsum1>";
|
||||
out "-sum16 %s %#9.1<-sum16>"; in "-sum16 %=s %#9.1<-sum16>";
|
||||
out "nsum32 %s %#9.1<nsum32>"; in "nsum32 %=s %#9.1<nsum32>";
|
||||
out "negsum32 %s %#9.1<negsum3>"; in "negsum32 %=s %#9.1<negsum3>";
|
||||
out "-sum32 %s %#9.1<-sum32>"; in "-sum32 %=s %#9.1<-sum32>";
|
||||
out "notsum %s %#9.1<notsum>"; in "notsum %=s %#9.1<notsum>";
|
||||
out "~sum %s %#9.1<~sum>"; in "~sum %=s %#9.1<~sum>";
|
||||
out "xor %s %#9.1<xor>"; in "xor %=s %#9.1<xor>";
|
||||
out "xor8 %s %#9.1<xor8>"; in "xor8 %=s %#9.1<xor8>";
|
||||
out "xor7 %s %#9.1<xor7>"; in "xor7 %=s %#9.1<xor7>";
|
||||
out "crc8 %s %#9.1<crc8>"; in "crc8 %=s %#9.1<crc8>";
|
||||
out "ccitt8 %s %#9.1<ccitt8>"; in "ccitt8 %=s %#9.1<ccitt8>";
|
||||
out "crc16 %s %#9.1<crc16>"; in "crc16 %=s %#9.1<crc16>";
|
||||
out "crc16r %s %#9.1<crc16r>"; in "crc16r %=s %#9.1<crc16r>";
|
||||
out "ccitt16 %s %#9.1<ccitt16>"; in "ccitt16 %=s %#9.1<ccitt16>";
|
||||
out "ccitt16a %s %#9.1<ccitt16a>"; in "ccitt16a %=s %#9.1<ccitt16a>";
|
||||
out "ccitt16x %s %#9.1<ccitt16x>"; in "ccitt16x %=s %#9.1<ccitt16x>";
|
||||
out "crc16c %s %#9.1<crc16c>"; in "crc16c %=s %#9.1<crc16c>";
|
||||
out "xmodem %s %#9.1<xmodem>"; in "xmodem %=s %#9.1<xmodem>";
|
||||
out "crc32 %s %#9.1<crc32>"; in "crc32 %=s %#9.1<crc32>";
|
||||
out "crc32r %s %#9.1<crc32r>"; in "crc32r %=s %#9.1<crc32r>";
|
||||
out "jamcrc %s %#9.1<jamcrc>"; in "jamcrc %=s %#9.1<jamcrc>";
|
||||
out "adler32 %s %#9.1<adler32>"; in "adler32 %=s %#9.1<adler32>";
|
||||
out "hexsum8 %s %#9.1<hexsum8>"; in "hexsum8 %=s %#9.1<hexsum8>";
|
||||
|
||||
out "sum %s %#09.1<sum>"; in "sum %=s %#09.1<sum>";
|
||||
out "sum8 %s %#09.1<sum8>"; in "sum8 %=s %#09.1<sum8>";
|
||||
out "sum16 %s %#09.1<sum16>"; in "sum16 %=s %#09.1<sum16>";
|
||||
out "sum32 %s %#09.1<sum32>"; in "sum32 %=s %#09.1<sum32>";
|
||||
out "nsum %s %#09.1<nsum>"; in "nsum %=s %#09.1<nsum>";
|
||||
out "negsum %s %#09.1<negsum>"; in "negsum %=s %#09.1<negsum>";
|
||||
out "-sum %s %#09.1<-sum>"; in "-sum %=s %#09.1<-sum>";
|
||||
out "nsum8 %s %#09.1<nsum8>"; in "nsum8 %=s %#09.1<nsum8>";
|
||||
out "negsum8 %s %#09.1<negsum8>"; in "negsum8 %=s %#09.1<negsum8>";
|
||||
out "-sum8 %s %#09.1<-sum8>"; in "-sum8 %=s %#09.1<-sum8>";
|
||||
out "nsum16 %s %#09.1<nsum16>"; in "nsum16 %=s %#09.1<nsum16>";
|
||||
out "negsum16 %s %#09.1<negsum1>"; in "negsum16 %=s %#09.1<negsum1>";
|
||||
out "-sum16 %s %#09.1<-sum16>"; in "-sum16 %=s %#09.1<-sum16>";
|
||||
out "nsum32 %s %#09.1<nsum32>"; in "nsum32 %=s %#09.1<nsum32>";
|
||||
out "negsum32 %s %#09.1<negsum3>"; in "negsum32 %=s %#09.1<negsum3>";
|
||||
out "-sum32 %s %#09.1<-sum32>"; in "-sum32 %=s %#09.1<-sum32>";
|
||||
out "notsum %s %#09.1<notsum>"; in "notsum %=s %#09.1<notsum>";
|
||||
out "~sum %s %#09.1<~sum>"; in "~sum %=s %#09.1<~sum>";
|
||||
out "xor %s %#09.1<xor>"; in "xor %=s %#09.1<xor>";
|
||||
out "xor8 %s %#09.1<xor8>"; in "xor8 %=s %#09.1<xor8>";
|
||||
out "xor7 %s %#09.1<xor7>"; in "xor7 %=s %#09.1<xor7>";
|
||||
out "crc8 %s %#09.1<crc8>"; in "crc8 %=s %#09.1<crc8>";
|
||||
out "ccitt8 %s %#09.1<ccitt8>"; in "ccitt8 %=s %#09.1<ccitt8>";
|
||||
out "crc16 %s %#09.1<crc16>"; in "crc16 %=s %#09.1<crc16>";
|
||||
out "crc16r %s %#09.1<crc16r>"; in "crc16r %=s %#09.1<crc16r>";
|
||||
out "ccitt16 %s %#09.1<ccitt16>"; in "ccitt16 %=s %#09.1<ccitt16>";
|
||||
out "ccitt16a %s %#09.1<ccitt16a>"; in "ccitt16a %=s %#09.1<ccitt16a>";
|
||||
out "ccitt16x %s %#09.1<ccitt16x>"; in "ccitt16x %=s %#09.1<ccitt16x>";
|
||||
out "crc16c %s %#09.1<crc16c>"; in "crc16c %=s %#09.1<crc16c>";
|
||||
out "xmodem %s %#09.1<xmodem>"; in "xmodem %=s %#09.1<xmodem>";
|
||||
out "crc32 %s %#09.1<crc32>"; in "crc32 %=s %#09.1<crc32>";
|
||||
out "crc32r %s %#09.1<crc32r>"; in "crc32r %=s %#09.1<crc32r>";
|
||||
out "jamcrc %s %#09.1<jamcrc>"; in "jamcrc %=s %#09.1<jamcrc>";
|
||||
out "adler32 %s %#09.1<adler32>"; in "adler32 %=s %#09.1<adler32>";
|
||||
out "hexsum8 %s %#09.1<hexsum8>"; in "hexsum8 %=s %#09.1<hexsum8>";
|
||||
|
||||
out "sum %s %#-9.1<sum>"; in "sum %=s %#-9.1<sum>";
|
||||
out "sum8 %s %#-9.1<sum8>"; in "sum8 %=s %#-9.1<sum8>";
|
||||
out "sum16 %s %#-9.1<sum16>"; in "sum16 %=s %#-9.1<sum16>";
|
||||
out "sum32 %s %#-9.1<sum32>"; in "sum32 %=s %#-9.1<sum32>";
|
||||
out "nsum %s %#-9.1<nsum>"; in "nsum %=s %#-9.1<nsum>";
|
||||
out "negsum %s %#-9.1<negsum>"; in "negsum %=s %#-9.1<negsum>";
|
||||
out "-sum %s %#-9.1<-sum>"; in "-sum %=s %#-9.1<-sum>";
|
||||
out "nsum8 %s %#-9.1<nsum8>"; in "nsum8 %=s %#-9.1<nsum8>";
|
||||
out "negsum8 %s %#-9.1<negsum8>"; in "negsum8 %=s %#-9.1<negsum8>";
|
||||
out "-sum8 %s %#-9.1<-sum8>"; in "-sum8 %=s %#-9.1<-sum8>";
|
||||
out "nsum16 %s %#-9.1<nsum16>"; in "nsum16 %=s %#-9.1<nsum16>";
|
||||
out "negsum16 %s %#-9.1<negsum1>"; in "negsum16 %=s %#-9.1<negsum1>";
|
||||
out "-sum16 %s %#-9.1<-sum16>"; in "-sum16 %=s %#-9.1<-sum16>";
|
||||
out "nsum32 %s %#-9.1<nsum32>"; in "nsum32 %=s %#-9.1<nsum32>";
|
||||
out "negsum32 %s %#-9.1<negsum3>"; in "negsum32 %=s %#-9.1<negsum3>";
|
||||
out "-sum32 %s %#-9.1<-sum32>"; in "-sum32 %=s %#-9.1<-sum32>";
|
||||
out "notsum %s %#-9.1<notsum>"; in "notsum %=s %#-9.1<notsum>";
|
||||
out "~sum %s %#-9.1<~sum>"; in "~sum %=s %#-9.1<~sum>";
|
||||
out "xor %s %#-9.1<xor>"; in "xor %=s %#-9.1<xor>";
|
||||
out "xor8 %s %#-9.1<xor8>"; in "xor8 %=s %#-9.1<xor8>";
|
||||
out "xor7 %s %#-9.1<xor7>"; in "xor7 %=s %#-9.1<xor7>";
|
||||
out "crc8 %s %#-9.1<crc8>"; in "crc8 %=s %#-9.1<crc8>";
|
||||
out "ccitt8 %s %#-9.1<ccitt8>"; in "ccitt8 %=s %#-9.1<ccitt8>";
|
||||
out "crc16 %s %#-9.1<crc16>"; in "crc16 %=s %#-9.1<crc16>";
|
||||
out "crc16r %s %#-9.1<crc16r>"; in "crc16r %=s %#-9.1<crc16r>";
|
||||
out "ccitt16 %s %#-9.1<ccitt16>"; in "ccitt16 %=s %#-9.1<ccitt16>";
|
||||
out "ccitt16a %s %#-9.1<ccitt16a>"; in "ccitt16a %=s %#-9.1<ccitt16a>";
|
||||
out "ccitt16x %s %#-9.1<ccitt16x>"; in "ccitt16x %=s %#-9.1<ccitt16x>";
|
||||
out "crc16c %s %#-9.1<crc16c>"; in "crc16c %=s %#-9.1<crc16c>";
|
||||
out "xmodem %s %#-9.1<xmodem>"; in "xmodem %=s %#-9.1<xmodem>";
|
||||
out "crc32 %s %#-9.1<crc32>"; in "crc32 %=s %#-9.1<crc32>";
|
||||
out "crc32r %s %#-9.1<crc32r>"; in "crc32r %=s %#-9.1<crc32r>";
|
||||
out "jamcrc %s %#-9.1<jamcrc>"; in "jamcrc %=s %#-9.1<jamcrc>";
|
||||
out "adler32 %s %#-9.1<adler32>"; in "adler32 %=s %#-9.1<adler32>";
|
||||
out "hexsum8 %s %#-9.1<hexsum8>"; in "hexsum8 %=s %#-9.1<hexsum8>";
|
||||
out "DONE";
|
||||
}
|
||||
}
|
||||
|
||||
set startup {
|
||||
@ -24,7 +242,432 @@ set startup {
|
||||
set debug 0
|
||||
|
||||
startioc
|
||||
ioccmd {dbpf DZ:test1 "1"}
|
||||
assure "\x55\x40\x04\x00\x00z;\x4e"
|
||||
|
||||
ioccmd {dbpf DZ:test1 "123456789"}
|
||||
assure "sum 123456789 \xDD\n"
|
||||
send "sum 123456789 \xDD\n"
|
||||
assure "sum8 123456789 \xDD\n"
|
||||
send "sum8 123456789 \xDD\n"
|
||||
assure "sum16 123456789 \x01\xDD\n"
|
||||
send "sum16 123456789 \x01\xDD\n"
|
||||
assure "sum32 123456789 \x00\x00\x01\xDD\n"
|
||||
send "sum32 123456789 \x00\x00\x01\xDD\n"
|
||||
assure "nsum 123456789 \x23\n"
|
||||
send "nsum 123456789 \x23\n"
|
||||
assure "negsum 123456789 \x23\n"
|
||||
send "negsum 123456789 \x23\n"
|
||||
assure "-sum 123456789 \x23\n"
|
||||
send "-sum 123456789 \x23\n"
|
||||
assure "nsum8 123456789 \x23\n"
|
||||
send "nsum8 123456789 \x23\n"
|
||||
assure "negsum8 123456789 \x23\n"
|
||||
send "negsum8 123456789 \x23\n"
|
||||
assure "-sum8 123456789 \x23\n"
|
||||
send "-sum8 123456789 \x23\n"
|
||||
assure "nsum16 123456789 \xFE\x23\n"
|
||||
send "nsum16 123456789 \xFE\x23\n"
|
||||
assure "negsum16 123456789 \xFE\x23\n"
|
||||
send "negsum16 123456789 \xFE\x23\n"
|
||||
assure "-sum16 123456789 \xFE\x23\n"
|
||||
send "-sum16 123456789 \xFE\x23\n"
|
||||
assure "nsum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||
send "nsum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||
assure "negsum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||
send "negsum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||
assure "-sum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||
send "-sum32 123456789 \xFF\xFF\xFE\x23\n"
|
||||
assure "notsum 123456789 \x22\n"
|
||||
send "notsum 123456789 \x22\n"
|
||||
assure "~sum 123456789 \x22\n"
|
||||
send "~sum 123456789 \x22\n"
|
||||
assure "xor 123456789 \x31\n"
|
||||
send "xor 123456789 \x31\n"
|
||||
assure "xor8 123456789 \x31\n"
|
||||
send "xor8 123456789 \x31\n"
|
||||
assure "xor7 123456789 \x31\n"
|
||||
send "xor7 123456789 \x31\n"
|
||||
assure "crc8 123456789 \xF4\n"
|
||||
send "crc8 123456789 \xF4\n"
|
||||
assure "ccitt8 123456789 \xA1\n"
|
||||
send "ccitt8 123456789 \xA1\n"
|
||||
assure "crc16 123456789 \xFE\xE8\n"
|
||||
send "crc16 123456789 \xFE\xE8\n"
|
||||
assure "crc16r 123456789 \xBB\x3D\n"
|
||||
send "crc16r 123456789 \xBB\x3D\n"
|
||||
assure "ccitt16 123456789 \x29\xB1\n"
|
||||
send "ccitt16 123456789 \x29\xB1\n"
|
||||
assure "ccitt16a 123456789 \xE5\xCC\n"
|
||||
send "ccitt16a 123456789 \xE5\xCC\n"
|
||||
assure "ccitt16x 123456789 \x31\xC3\n"
|
||||
send "ccitt16x 123456789 \x31\xC3\n"
|
||||
assure "crc16c 123456789 \x31\xC3\n"
|
||||
send "crc16c 123456789 \x31\xC3\n"
|
||||
assure "xmodem 123456789 \x31\xC3\n"
|
||||
send "xmodem 123456789 \x31\xC3\n"
|
||||
assure "crc32 123456789 \xFC\x89\x19\x18\n"
|
||||
send "crc32 123456789 \xFC\x89\x19\x18\n"
|
||||
assure "crc32r 123456789 \xCB\xF4\x39\x26\n"
|
||||
send "crc32r 123456789 \xCB\xF4\x39\x26\n"
|
||||
assure "jamcrc 123456789 \x34\x0B\xC6\xD9\n"
|
||||
send "jamcrc 123456789 \x34\x0B\xC6\xD9\n"
|
||||
assure "adler32 123456789 \x09\x1E\x01\xDE\n"
|
||||
send "adler32 123456789 \x09\x1E\x01\xDE\n"
|
||||
assure "hexsum8 123456789 \x2D\n"
|
||||
send "hexsum8 123456789 \x2D\n"
|
||||
|
||||
assure "sum 123456789 DD\n"
|
||||
send "sum 123456789 DD\n"
|
||||
assure "sum8 123456789 DD\n"
|
||||
send "sum8 123456789 DD\n"
|
||||
assure "sum16 123456789 01DD\n"
|
||||
send "sum16 123456789 01DD\n"
|
||||
assure "sum32 123456789 000001DD\n"
|
||||
send "sum32 123456789 000001DD\n"
|
||||
assure "nsum 123456789 23\n"
|
||||
send "nsum 123456789 23\n"
|
||||
assure "negsum 123456789 23\n"
|
||||
send "negsum 123456789 23\n"
|
||||
assure "-sum 123456789 23\n"
|
||||
send "-sum 123456789 23\n"
|
||||
assure "nsum8 123456789 23\n"
|
||||
send "nsum8 123456789 23\n"
|
||||
assure "negsum8 123456789 23\n"
|
||||
send "negsum8 123456789 23\n"
|
||||
assure "-sum8 123456789 23\n"
|
||||
send "-sum8 123456789 23\n"
|
||||
assure "nsum16 123456789 FE23\n"
|
||||
send "nsum16 123456789 FE23\n"
|
||||
assure "negsum16 123456789 FE23\n"
|
||||
send "negsum16 123456789 FE23\n"
|
||||
assure "-sum16 123456789 FE23\n"
|
||||
send "-sum16 123456789 FE23\n"
|
||||
assure "nsum32 123456789 FFFFFE23\n"
|
||||
send "nsum32 123456789 FFFFFE23\n"
|
||||
assure "negsum32 123456789 FFFFFE23\n"
|
||||
send "negsum32 123456789 FFFFFE23\n"
|
||||
assure "-sum32 123456789 FFFFFE23\n"
|
||||
send "-sum32 123456789 FFFFFE23\n"
|
||||
assure "notsum 123456789 22\n"
|
||||
send "notsum 123456789 22\n"
|
||||
assure "~sum 123456789 22\n"
|
||||
send "~sum 123456789 22\n"
|
||||
assure "xor 123456789 31\n"
|
||||
send "xor 123456789 31\n"
|
||||
assure "xor8 123456789 31\n"
|
||||
send "xor8 123456789 31\n"
|
||||
assure "xor7 123456789 31\n"
|
||||
send "xor7 123456789 31\n"
|
||||
assure "crc8 123456789 F4\n"
|
||||
send "crc8 123456789 F4\n"
|
||||
assure "ccitt8 123456789 A1\n"
|
||||
send "ccitt8 123456789 A1\n"
|
||||
assure "crc16 123456789 FEE8\n"
|
||||
send "crc16 123456789 FEE8\n"
|
||||
assure "crc16r 123456789 BB3D\n"
|
||||
send "crc16r 123456789 BB3D\n"
|
||||
assure "ccitt16 123456789 29B1\n"
|
||||
send "ccitt16 123456789 29B1\n"
|
||||
assure "ccitt16a 123456789 E5CC\n"
|
||||
send "ccitt16a 123456789 E5CC\n"
|
||||
assure "ccitt16x 123456789 31C3\n"
|
||||
send "ccitt16x 123456789 31C3\n"
|
||||
assure "crc16c 123456789 31C3\n"
|
||||
send "crc16c 123456789 31C3\n"
|
||||
assure "xmodem 123456789 31C3\n"
|
||||
send "xmodem 123456789 31C3\n"
|
||||
assure "crc32 123456789 FC891918\n"
|
||||
send "crc32 123456789 FC891918\n"
|
||||
assure "crc32r 123456789 CBF43926\n"
|
||||
send "crc32r 123456789 CBF43926\n"
|
||||
assure "jamcrc 123456789 340BC6D9\n"
|
||||
send "jamcrc 123456789 340BC6D9\n"
|
||||
assure "adler32 123456789 091E01DE\n"
|
||||
send "adler32 123456789 091E01DE\n"
|
||||
assure "hexsum8 123456789 2D\n"
|
||||
send "hexsum8 123456789 2D\n"
|
||||
|
||||
assure "sum 123456789 \x3D\x3D\n"
|
||||
send "sum 123456789 \x3D\x3D\n"
|
||||
assure "sum8 123456789 \x3D\x3D\n"
|
||||
send "sum8 123456789 \x3D\x3D\n"
|
||||
assure "sum16 123456789 \x30\x31\x3D\x3D\n"
|
||||
send "sum16 123456789 \x30\x31\x3D\x3D\n"
|
||||
assure "sum32 123456789 \x30\x30\x30\x30\x30\x31\x3D\x3D\n"
|
||||
send "sum32 123456789 \x30\x30\x30\x30\x30\x31\x3D\x3D\n"
|
||||
assure "nsum 123456789 \x32\x33\n"
|
||||
send "nsum 123456789 \x32\x33\n"
|
||||
assure "negsum 123456789 \x32\x33\n"
|
||||
send "negsum 123456789 \x32\x33\n"
|
||||
assure "-sum 123456789 \x32\x33\n"
|
||||
send "-sum 123456789 \x32\x33\n"
|
||||
assure "nsum8 123456789 \x32\x33\n"
|
||||
send "nsum8 123456789 \x32\x33\n"
|
||||
assure "negsum8 123456789 \x32\x33\n"
|
||||
send "negsum8 123456789 \x32\x33\n"
|
||||
assure "-sum8 123456789 \x32\x33\n"
|
||||
send "-sum8 123456789 \x32\x33\n"
|
||||
assure "nsum16 123456789 \x3F\x3E\x32\x33\n"
|
||||
send "nsum16 123456789 \x3F\x3E\x32\x33\n"
|
||||
assure "negsum16 123456789 \x3F\x3E\x32\x33\n"
|
||||
send "negsum16 123456789 \x3F\x3E\x32\x33\n"
|
||||
assure "-sum16 123456789 \x3F\x3E\x32\x33\n"
|
||||
send "-sum16 123456789 \x3F\x3E\x32\x33\n"
|
||||
assure "nsum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||
send "nsum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||
assure "negsum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||
send "negsum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||
assure "-sum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||
send "-sum32 123456789 \x3F\x3F\x3F\x3F\x3F\x3E\x32\x33\n"
|
||||
assure "notsum 123456789 \x32\x32\n"
|
||||
send "notsum 123456789 \x32\x32\n"
|
||||
assure "~sum 123456789 \x32\x32\n"
|
||||
send "~sum 123456789 \x32\x32\n"
|
||||
assure "xor 123456789 \x33\x31\n"
|
||||
send "xor 123456789 \x33\x31\n"
|
||||
assure "xor8 123456789 \x33\x31\n"
|
||||
send "xor8 123456789 \x33\x31\n"
|
||||
assure "xor7 123456789 \x33\x31\n"
|
||||
send "xor7 123456789 \x33\x31\n"
|
||||
assure "crc8 123456789 \x3F\x34\n"
|
||||
send "crc8 123456789 \x3F\x34\n"
|
||||
assure "ccitt8 123456789 \x3A\x31\n"
|
||||
send "ccitt8 123456789 \x3A\x31\n"
|
||||
assure "crc16 123456789 \x3F\x3E\x3E\x38\n"
|
||||
send "crc16 123456789 \x3F\x3E\x3E\x38\n"
|
||||
assure "crc16r 123456789 \x3B\x3B\x33\x3D\n"
|
||||
send "crc16r 123456789 \x3B\x3B\x33\x3D\n"
|
||||
assure "ccitt16 123456789 \x32\x39\x3B\x31\n"
|
||||
send "ccitt16 123456789 \x32\x39\x3B\x31\n"
|
||||
assure "ccitt16a 123456789 \x3E\x35\x3C\x3C\n"
|
||||
send "ccitt16a 123456789 \x3E\x35\x3C\x3C\n"
|
||||
assure "ccitt16x 123456789 \x33\x31\x3C\x33\n"
|
||||
send "ccitt16x 123456789 \x33\x31\x3C\x33\n"
|
||||
assure "crc16c 123456789 \x33\x31\x3C\x33\n"
|
||||
send "crc16c 123456789 \x33\x31\x3C\x33\n"
|
||||
assure "xmodem 123456789 \x33\x31\x3C\x33\n"
|
||||
send "xmodem 123456789 \x33\x31\x3C\x33\n"
|
||||
assure "crc32 123456789 \x3F\x3C\x38\x39\x31\x39\x31\x38\n"
|
||||
send "crc32 123456789 \x3F\x3C\x38\x39\x31\x39\x31\x38\n"
|
||||
assure "crc32r 123456789 \x3C\x3B\x3F\x34\x33\x39\x32\x36\n"
|
||||
send "crc32r 123456789 \x3C\x3B\x3F\x34\x33\x39\x32\x36\n"
|
||||
assure "jamcrc 123456789 \x33\x34\x30\x3B\x3C\x36\x3D\x39\n"
|
||||
send "jamcrc 123456789 \x33\x34\x30\x3B\x3C\x36\x3D\x39\n"
|
||||
assure "adler32 123456789 \x30\x39\x31\x3E\x30\x31\x3D\x3E\n"
|
||||
send "adler32 123456789 \x30\x39\x31\x3E\x30\x31\x3D\x3E\n"
|
||||
assure "hexsum8 123456789 \x32\x3D\n"
|
||||
send "hexsum8 123456789 \x32\x3D\n"
|
||||
|
||||
assure "sum 123456789 \xDD\n"
|
||||
send "sum 123456789 \xDD\n"
|
||||
assure "sum8 123456789 \xDD\n"
|
||||
send "sum8 123456789 \xDD\n"
|
||||
assure "sum16 123456789 \xDD\x01\n"
|
||||
send "sum16 123456789 \xDD\x01\n"
|
||||
assure "sum32 123456789 \xDD\x01\x00\x00\n"
|
||||
send "sum32 123456789 \xDD\x01\x00\x00\n"
|
||||
assure "nsum 123456789 \x23\n"
|
||||
send "nsum 123456789 \x23\n"
|
||||
assure "negsum 123456789 \x23\n"
|
||||
send "negsum 123456789 \x23\n"
|
||||
assure "-sum 123456789 \x23\n"
|
||||
send "-sum 123456789 \x23\n"
|
||||
assure "nsum8 123456789 \x23\n"
|
||||
send "nsum8 123456789 \x23\n"
|
||||
assure "negsum8 123456789 \x23\n"
|
||||
send "negsum8 123456789 \x23\n"
|
||||
assure "-sum8 123456789 \x23\n"
|
||||
send "-sum8 123456789 \x23\n"
|
||||
assure "nsum16 123456789 \x23\xFE\n"
|
||||
send "nsum16 123456789 \x23\xFE\n"
|
||||
assure "negsum16 123456789 \x23\xFE\n"
|
||||
send "negsum16 123456789 \x23\xFE\n"
|
||||
assure "-sum16 123456789 \x23\xFE\n"
|
||||
send "-sum16 123456789 \x23\xFE\n"
|
||||
assure "nsum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||
send "nsum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||
assure "negsum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||
send "negsum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||
assure "-sum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||
send "-sum32 123456789 \x23\xFE\xFF\xFF\n"
|
||||
assure "notsum 123456789 \x22\n"
|
||||
send "notsum 123456789 \x22\n"
|
||||
assure "~sum 123456789 \x22\n"
|
||||
send "~sum 123456789 \x22\n"
|
||||
assure "xor 123456789 \x31\n"
|
||||
send "xor 123456789 \x31\n"
|
||||
assure "xor8 123456789 \x31\n"
|
||||
send "xor8 123456789 \x31\n"
|
||||
assure "xor7 123456789 \x31\n"
|
||||
send "xor7 123456789 \x31\n"
|
||||
assure "crc8 123456789 \xF4\n"
|
||||
send "crc8 123456789 \xF4\n"
|
||||
assure "ccitt8 123456789 \xA1\n"
|
||||
send "ccitt8 123456789 \xA1\n"
|
||||
assure "crc16 123456789 \xE8\xFE\n"
|
||||
send "crc16 123456789 \xE8\xFE\n"
|
||||
assure "crc16r 123456789 \x3D\xBB\n"
|
||||
send "crc16r 123456789 \x3D\xBB\n"
|
||||
assure "ccitt16 123456789 \xB1\x29\n"
|
||||
send "ccitt16 123456789 \xB1\x29\n"
|
||||
assure "ccitt16a 123456789 \xCC\xE5\n"
|
||||
send "ccitt16a 123456789 \xCC\xE5\n"
|
||||
assure "ccitt16x 123456789 \xC3\x31\n"
|
||||
send "ccitt16x 123456789 \xC3\x31\n"
|
||||
assure "crc16c 123456789 \xC3\x31\n"
|
||||
send "crc16c 123456789 \xC3\x31\n"
|
||||
assure "xmodem 123456789 \xC3\x31\n"
|
||||
send "xmodem 123456789 \xC3\x31\n"
|
||||
assure "crc32 123456789 \x18\x19\x89\xFC\n"
|
||||
send "crc32 123456789 \x18\x19\x89\xFC\n"
|
||||
assure "crc32r 123456789 \x26\x39\xF4\xCB\n"
|
||||
send "crc32r 123456789 \x26\x39\xF4\xCB\n"
|
||||
assure "jamcrc 123456789 \xD9\xC6\x0B\x34\n"
|
||||
send "jamcrc 123456789 \xD9\xC6\x0B\x34\n"
|
||||
assure "adler32 123456789 \xDE\x01\x1E\x09\n"
|
||||
send "adler32 123456789 \xDE\x01\x1E\x09\n"
|
||||
assure "hexsum8 123456789 \x2D\n"
|
||||
send "hexsum8 123456789 \x2D\n"
|
||||
|
||||
assure "sum 123456789 DD\n"
|
||||
send "sum 123456789 DD\n"
|
||||
assure "sum8 123456789 DD\n"
|
||||
send "sum8 123456789 DD\n"
|
||||
assure "sum16 123456789 DD01\n"
|
||||
send "sum16 123456789 DD01\n"
|
||||
assure "sum32 123456789 DD010000\n"
|
||||
send "sum32 123456789 DD010000\n"
|
||||
assure "nsum 123456789 23\n"
|
||||
send "nsum 123456789 23\n"
|
||||
assure "negsum 123456789 23\n"
|
||||
send "negsum 123456789 23\n"
|
||||
assure "-sum 123456789 23\n"
|
||||
send "-sum 123456789 23\n"
|
||||
assure "nsum8 123456789 23\n"
|
||||
send "nsum8 123456789 23\n"
|
||||
assure "negsum8 123456789 23\n"
|
||||
send "negsum8 123456789 23\n"
|
||||
assure "-sum8 123456789 23\n"
|
||||
send "-sum8 123456789 23\n"
|
||||
assure "nsum16 123456789 23FE\n"
|
||||
send "nsum16 123456789 23FE\n"
|
||||
assure "negsum16 123456789 23FE\n"
|
||||
send "negsum16 123456789 23FE\n"
|
||||
assure "-sum16 123456789 23FE\n"
|
||||
send "-sum16 123456789 23FE\n"
|
||||
assure "nsum32 123456789 23FEFFFF\n"
|
||||
send "nsum32 123456789 23FEFFFF\n"
|
||||
assure "negsum32 123456789 23FEFFFF\n"
|
||||
send "negsum32 123456789 23FEFFFF\n"
|
||||
assure "-sum32 123456789 23FEFFFF\n"
|
||||
send "-sum32 123456789 23FEFFFF\n"
|
||||
assure "notsum 123456789 22\n"
|
||||
send "notsum 123456789 22\n"
|
||||
assure "~sum 123456789 22\n"
|
||||
send "~sum 123456789 22\n"
|
||||
assure "xor 123456789 31\n"
|
||||
send "xor 123456789 31\n"
|
||||
assure "xor8 123456789 31\n"
|
||||
send "xor8 123456789 31\n"
|
||||
assure "xor7 123456789 31\n"
|
||||
send "xor7 123456789 31\n"
|
||||
assure "crc8 123456789 F4\n"
|
||||
send "crc8 123456789 F4\n"
|
||||
assure "ccitt8 123456789 A1\n"
|
||||
send "ccitt8 123456789 A1\n"
|
||||
assure "crc16 123456789 E8FE\n"
|
||||
send "crc16 123456789 E8FE\n"
|
||||
assure "crc16r 123456789 3DBB\n"
|
||||
send "crc16r 123456789 3DBB\n"
|
||||
assure "ccitt16 123456789 B129\n"
|
||||
send "ccitt16 123456789 B129\n"
|
||||
assure "ccitt16a 123456789 CCE5\n"
|
||||
send "ccitt16a 123456789 CCE5\n"
|
||||
assure "ccitt16x 123456789 C331\n"
|
||||
send "ccitt16x 123456789 C331\n"
|
||||
assure "crc16c 123456789 C331\n"
|
||||
send "crc16c 123456789 C331\n"
|
||||
assure "xmodem 123456789 C331\n"
|
||||
send "xmodem 123456789 C331\n"
|
||||
assure "crc32 123456789 181989FC\n"
|
||||
send "crc32 123456789 181989FC\n"
|
||||
assure "crc32r 123456789 2639F4CB\n"
|
||||
send "crc32r 123456789 2639F4CB\n"
|
||||
assure "jamcrc 123456789 D9C60B34\n"
|
||||
send "jamcrc 123456789 D9C60B34\n"
|
||||
assure "adler32 123456789 DE011E09\n"
|
||||
send "adler32 123456789 DE011E09\n"
|
||||
assure "hexsum8 123456789 2D\n"
|
||||
send "hexsum8 123456789 2D\n"
|
||||
|
||||
assure "sum 123456789 \x3D\x3D\n"
|
||||
send "sum 123456789 \x3D\x3D\n"
|
||||
assure "sum8 123456789 \x3D\x3D\n"
|
||||
send "sum8 123456789 \x3D\x3D\n"
|
||||
assure "sum16 123456789 \x3D\x3D\x30\x31\n"
|
||||
send "sum16 123456789 \x3D\x3D\x30\x31\n"
|
||||
assure "sum32 123456789 \x3D\x3D\x30\x31\x30\x30\x30\x30\n"
|
||||
send "sum32 123456789 \x3D\x3D\x30\x31\x30\x30\x30\x30\n"
|
||||
assure "nsum 123456789 \x32\x33\n"
|
||||
send "nsum 123456789 \x32\x33\n"
|
||||
assure "negsum 123456789 \x32\x33\n"
|
||||
send "negsum 123456789 \x32\x33\n"
|
||||
assure "-sum 123456789 \x32\x33\n"
|
||||
send "-sum 123456789 \x32\x33\n"
|
||||
assure "nsum8 123456789 \x32\x33\n"
|
||||
send "nsum8 123456789 \x32\x33\n"
|
||||
assure "negsum8 123456789 \x32\x33\n"
|
||||
send "negsum8 123456789 \x32\x33\n"
|
||||
assure "-sum8 123456789 \x32\x33\n"
|
||||
send "-sum8 123456789 \x32\x33\n"
|
||||
assure "nsum16 123456789 \x32\x33\x3F\x3E\n"
|
||||
send "nsum16 123456789 \x32\x33\x3F\x3E\n"
|
||||
assure "negsum16 123456789 \x32\x33\x3F\x3E\n"
|
||||
send "negsum16 123456789 \x32\x33\x3F\x3E\n"
|
||||
assure "-sum16 123456789 \x32\x33\x3F\x3E\n"
|
||||
send "-sum16 123456789 \x32\x33\x3F\x3E\n"
|
||||
assure "nsum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||
send "nsum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||
assure "negsum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||
send "negsum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||
assure "-sum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||
send "-sum32 123456789 \x32\x33\x3F\x3E\x3F\x3F\x3F\x3F\n"
|
||||
assure "notsum 123456789 \x32\x32\n"
|
||||
send "notsum 123456789 \x32\x32\n"
|
||||
assure "~sum 123456789 \x32\x32\n"
|
||||
send "~sum 123456789 \x32\x32\n"
|
||||
assure "xor 123456789 \x33\x31\n"
|
||||
send "xor 123456789 \x33\x31\n"
|
||||
assure "xor8 123456789 \x33\x31\n"
|
||||
send "xor8 123456789 \x33\x31\n"
|
||||
assure "xor7 123456789 \x33\x31\n"
|
||||
send "xor7 123456789 \x33\x31\n"
|
||||
assure "crc8 123456789 \x3F\x34\n"
|
||||
send "crc8 123456789 \x3F\x34\n"
|
||||
assure "ccitt8 123456789 \x3A\x31\n"
|
||||
send "ccitt8 123456789 \x3A\x31\n"
|
||||
assure "crc16 123456789 \x3E\x38\x3F\x3E\n"
|
||||
send "crc16 123456789 \x3E\x38\x3F\x3E\n"
|
||||
assure "crc16r 123456789 \x33\x3D\x3B\x3B\n"
|
||||
send "crc16r 123456789 \x33\x3D\x3B\x3B\n"
|
||||
assure "ccitt16 123456789 \x3B\x31\x32\x39\n"
|
||||
send "ccitt16 123456789 \x3B\x31\x32\x39\n"
|
||||
assure "ccitt16a 123456789 \x3C\x3C\x3E\x35\n"
|
||||
send "ccitt16a 123456789 \x3C\x3C\x3E\x35\n"
|
||||
assure "ccitt16x 123456789 \x3C\x33\x33\x31\n"
|
||||
send "ccitt16x 123456789 \x3C\x33\x33\x31\n"
|
||||
assure "crc16c 123456789 \x3C\x33\x33\x31\n"
|
||||
send "crc16c 123456789 \x3C\x33\x33\x31\n"
|
||||
assure "xmodem 123456789 \x3C\x33\x33\x31\n"
|
||||
send "xmodem 123456789 \x3C\x33\x33\x31\n"
|
||||
assure "crc32 123456789 \x31\x38\x31\x39\x38\x39\x3F\x3C\n"
|
||||
send "crc32 123456789 \x31\x38\x31\x39\x38\x39\x3F\x3C\n"
|
||||
assure "crc32r 123456789 \x32\x36\x33\x39\x3F\x34\x3C\x3B\n"
|
||||
send "crc32r 123456789 \x32\x36\x33\x39\x3F\x34\x3C\x3B\n"
|
||||
assure "jamcrc 123456789 \x3D\x39\x3C\x36\x30\x3B\x33\x34\n"
|
||||
send "jamcrc 123456789 \x3D\x39\x3C\x36\x30\x3B\x33\x34\n"
|
||||
assure "adler32 123456789 \x3D\x3E\x30\x31\x31\x3E\x30\x39\n"
|
||||
send "adler32 123456789 \x3D\x3E\x30\x31\x31\x3E\x30\x39\n"
|
||||
assure "hexsum8 123456789 \x32\x3D\n"
|
||||
send "hexsum8 123456789 \x32\x3D\n"
|
||||
assure "DONE\n"
|
||||
|
||||
finish
|
||||
|
@ -7,6 +7,11 @@ source streamtestlib.tcl
|
||||
# Send commands to the ioc shell with ioccmd
|
||||
|
||||
set records {
|
||||
record (bo, "DZ:percent")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto percent device")
|
||||
}
|
||||
record (ao, "DZ:ao")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
@ -25,25 +30,14 @@ set records {
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto bcd device")
|
||||
}
|
||||
record (stringout, "DZ:chksum")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto chksum device")
|
||||
}
|
||||
}
|
||||
|
||||
set protocol {
|
||||
Terminator = LF;
|
||||
percent {out "\%\x25\37\045" 0x25 37 045;}
|
||||
ao {out "%.2f %.2e %.2E %.2g %.2G %i %d %u %o %04x %#.2f %#.2e %#.2E %#.2g %#.2G %#i %#d %#u %#o %#06x";}
|
||||
lo {out "%d %(VAL)d %06d %x %06X %b %06b %.6b %B.! %06B.!";}
|
||||
bcd {out "%D %6D %.2D %.4D %.6D %.8D %#D %#6D %#.2D %#.4D %#.6D";}
|
||||
chksum {out "%s%<xor>";
|
||||
out "%s%0<sum>";
|
||||
out "%s%0<crc8>";
|
||||
out "%s%0<crc16>";
|
||||
out "%s%0<crc32>";
|
||||
out "%s%0<adler32>";
|
||||
}
|
||||
}
|
||||
|
||||
set startup {
|
||||
@ -58,6 +52,8 @@ startioc
|
||||
# This is normal. E.g. -1 HAS a different number of 1 bits.
|
||||
# Specify the width field in the format if this is a problem.
|
||||
|
||||
ioccmd {dbpf DZ:percent 1}
|
||||
assure "%%%%%%%\n"
|
||||
ioccmd {dbpf DZ:ao 0}
|
||||
assure "0.00 0.00e+00 0.00E+00 0 0 32767 32767 32767 77777 7fff 0.00 0.00e+00 0.00E+00 0.0 0.0 32767 32767 32767 077777 0x7fff\n"
|
||||
ioccmd {dbpf DZ:ao 10}
|
||||
@ -92,11 +88,4 @@ assure "\0\0\0\0\1\2\3\4 \0\0\0\0\1\2\3\4 \4 \3\4 \2\3\4 \1\2\3\4 \4\3\2\1\0\0\0
|
||||
} else {
|
||||
assure "\1\2\3\4 \0\0\1\2\3\4 \4 \3\4 \2\3\4 \1\2\3\4 \4\3\2\1 \4\3\2\1\0\0 \4 \4\3 \4\3\2\n"
|
||||
}
|
||||
ioccmd {dbpf DZ:chksum "123456789"}
|
||||
assure "1234567891\n"
|
||||
assure "123456789DD\n"
|
||||
assure "123456789F4\n"
|
||||
assure "123456789FEE8\n"
|
||||
assure "123456789FC891918\n"
|
||||
assure "123456789091E01DE\n"
|
||||
finish
|
||||
|
33
streamApp/tests/testStrangesum
Executable file
33
streamApp/tests/testStrangesum
Executable file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env tclsh
|
||||
source streamtestlib.tcl
|
||||
|
||||
# Define records, protocol and startup (text goes to files)
|
||||
# The asynPort "device" is connected to a network TCP socket
|
||||
# Talk to the socket with send/receive/assure
|
||||
# Send commands to the ioc shell with ioccmd
|
||||
|
||||
set records {
|
||||
record (stringout, "DZ:test1")
|
||||
{
|
||||
field (DTYP, "stream")
|
||||
field (OUT, "@test.proto test1 device")
|
||||
}
|
||||
}
|
||||
|
||||
set protocol {
|
||||
Terminator="\r\n";
|
||||
test1 {
|
||||
out ":%s%01<-hexsum8>";
|
||||
}
|
||||
}
|
||||
|
||||
set startup {
|
||||
}
|
||||
|
||||
set debug 0
|
||||
|
||||
startioc
|
||||
ioccmd {dbpf DZ:test1 "010304010001"}
|
||||
assure ":010304010001F6\r\n"
|
||||
|
||||
finish
|
Reference in New Issue
Block a user