documentation update
This commit is contained in:
@ -19,7 +19,7 @@
|
|||||||
href="http://www.aps.anl.gov/epics/modules/soft/asyn/">
|
href="http://www.aps.anl.gov/epics/modules/soft/asyn/">
|
||||||
<em>asynDriver</em></a>.
|
<em>asynDriver</em></a>.
|
||||||
You should first try to implement your bus driver compatible to
|
You should first try to implement your bus driver compatible to
|
||||||
<em>asynDriver</em>.
|
<em>asynOctet</em>.
|
||||||
Then it can be used by <em>StreamDevice</em> automatically.
|
Then it can be used by <em>StreamDevice</em> automatically.
|
||||||
Only if that does not work, write your own bus interface.
|
Only if that does not work, write your own bus interface.
|
||||||
</p>
|
</p>
|
||||||
@ -68,17 +68,13 @@ class MyInterface : StreamBusInterface
|
|||||||
// StreamBusInterface virtual methods
|
// StreamBusInterface virtual methods
|
||||||
bool <a href="#lock">lockRequest</a>(unsigned long lockTimeout_ms);
|
bool <a href="#lock">lockRequest</a>(unsigned long lockTimeout_ms);
|
||||||
bool <a href="#lock">unlock</a>();
|
bool <a href="#lock">unlock</a>();
|
||||||
bool <a href="#write">writeRequest</a>(const void* output, size_t size,
|
bool <a href="#write">writeRequest</a>(const void* output, size_t size, unsigned long writeTimeout_ms);
|
||||||
unsigned long writeTimeout_ms);
|
bool <a href="#read">readRequest</a>(unsigned long replyTimeout_ms, unsigned long readTimeout_ms, long expectedLength, bool async);
|
||||||
bool <a href="#read">readRequest</a>(unsigned long replyTimeout_ms,
|
|
||||||
unsigned long readTimeout_ms,
|
|
||||||
long expectedLength, bool async);
|
|
||||||
bool <a href="#read">supportsAsyncRead</a>();
|
bool <a href="#read">supportsAsyncRead</a>();
|
||||||
bool <a href="#event">supportsEvent</a>();
|
bool <a href="#event">supportsEvent</a>();
|
||||||
bool <a href="#event">acceptEvent</a>(unsigned long mask,
|
bool <a href="#event">acceptEvent</a>(unsigned long mask, unsigned long timeout_ms);
|
||||||
unsigned long replytimeout_ms);
|
bool <a href="#connect">connectRequest</a>(unsigned long timeout_ms);
|
||||||
bool <a href="#connect">connectRequest</a>(unsigned long connecttimeout_ms);
|
bool <a href="#connect">disconnectRequest</a>();
|
||||||
bool <a href="#connect">disconnect</a>();
|
|
||||||
void <a href="#lock">finish</a>();
|
void <a href="#lock">finish</a>();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -132,13 +128,13 @@ bool <a href="#event">supportsEvent</a>();
|
|||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool <a href="#event">acceptEvent</a>(unsigned long mask,
|
bool <a href="#event">acceptEvent</a>(unsigned long mask,
|
||||||
unsigned long replytimeout_ms);
|
unsigned long timeout_ms);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool <a href="#connect">connectRequest</a>(unsigned long connecttimeout_ms);
|
bool <a href="#connect">connectRequest</a>(unsigned long timeout_ms);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool <a href="#connect">disconnect</a>();
|
bool <a href="#connect">disconnectRequest</a>();
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void <a href="#lock">finish</a>();
|
void <a href="#lock">finish</a>();
|
||||||
@ -157,24 +153,24 @@ callback methods which must be called in response to the above request
|
|||||||
methods (most probably from another thread):
|
methods (most probably from another thread):
|
||||||
</p>
|
</p>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void <a href="#lock">lockCallback</a>(StreamIoStatus status);
|
void <a href="#lock">lockCallback</a>(StreamIoStatus status = StreamIoSuccess);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void <a href="#write">writeCallback</a>(StreamIoStatus status);
|
void <a href="#write">writeCallback</a>(StreamIoStatus status = StreamIoSuccess);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
long <a href="#read">readCallback</a>(StreamIoStatus status,
|
ssize_t <a href="#read">readCallback</a>(StreamIoStatus status,
|
||||||
const void* input = NULL,
|
const void* buffer = NULL,
|
||||||
long size = 0);
|
size_t size = 0);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void <a href="#event">eventCallback</a>(StreamIoStatus status);
|
void <a href="#event">eventCallback</a>(StreamIoStatus status = StreamIoSuccess);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void <a href="#connect">connectCallback</a>(StreamIoStatus status);
|
void <a href="#connect">connectCallback</a>(StreamIoStatus status = StreamIoSuccess);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void <a href="#connect">disconnectCallback</a>(StreamIoStatus status);
|
void <a href="#connect">disconnectCallback</a>(StreamIoStatus status = StreamIoSuccess);
|
||||||
</code></div>
|
</code></div>
|
||||||
|
|
||||||
<h3>Other provided methods, attibutes, and types</h3>
|
<h3>Other provided methods, attibutes, and types</h3>
|
||||||
@ -197,6 +193,9 @@ const char* <a href="#read">getInTerminator</a>(size_t& length);
|
|||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
enum StreamIoStatus {StreamIoSuccess, StreamIoTimeout, StreamIoNoReply, StreamIoEnd, StreamIoFault};
|
enum StreamIoStatus {StreamIoSuccess, StreamIoTimeout, StreamIoNoReply, StreamIoEnd, StreamIoFault};
|
||||||
</code></div>
|
</code></div>
|
||||||
|
<div class="indent"><code>
|
||||||
|
const char* ::toStr(StreamIoStatus);
|
||||||
|
</code></div>
|
||||||
|
|
||||||
<a name="theory"></a>
|
<a name="theory"></a>
|
||||||
<h2>Theory of Operation</h2>
|
<h2>Theory of Operation</h2>
|
||||||
@ -276,34 +275,47 @@ correct.
|
|||||||
<a name="connect"></a>
|
<a name="connect"></a>
|
||||||
<h3>Connecting and disconnecting</h3>
|
<h3>Connecting and disconnecting</h3>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool connectRequest(unsigned long connecttimeout_ms);
|
bool connectRequest(unsigned long timeout_ms);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool disconnect();
|
bool disconnectRequest();
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void connectCallback(IoStatus status);
|
void connectCallback(IoStatus status = StreamIoSuccess);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void disconnectCallback(IoStatus status);
|
void disconnectCallback(IoStatus status = StreamIoSuccess);
|
||||||
</code></div>
|
</code></div>
|
||||||
<p>
|
<p>
|
||||||
Connection should be handled automatically.
|
Whenever possible connection should be handled automatically.
|
||||||
If the device is disconnected, each attempt to access the
|
The interface should call <code>connectCallback()</code> when
|
||||||
device should try to (re-)connect.
|
the device has connected and <code>disconnectCallback()</code> when
|
||||||
|
the device has disconnected.
|
||||||
|
These callbacks can be called asynchronously at any time.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If the device is disconnected, an attempt to access the
|
||||||
|
device should try to reconnect.
|
||||||
Normally, the interface should not try to disconnect unless
|
Normally, the interface should not try to disconnect unless
|
||||||
the device does so.
|
the device does so automatically.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
However, sometimes the client wants to connect or
|
However, sometimes the client wants to connect or
|
||||||
disconnect explicitely.
|
disconnect explicitly.
|
||||||
To connect, the client calls <code>connectRequest()</code>.
|
To connect, the client calls <code>connectRequest()</code>.
|
||||||
This function should return <code>true</code> immediately
|
This function should set up things to reconnect but should not block
|
||||||
or <code>false</code> if the request cannot be accepted or connection
|
waiting.
|
||||||
|
Instead it should immediately return <code>true</code> if
|
||||||
|
it expects that connection can be established soon, or
|
||||||
|
<code>false</code> if the request cannot be accepted or connection
|
||||||
handling is not supported.
|
handling is not supported.
|
||||||
The interface should call <code>connectCallback(StreamIoSuccess)</code>
|
The interface should call <code>connectCallback()</code>
|
||||||
once the bus could be connected.
|
once the bus could be connected.
|
||||||
If the bus cannot be connected within <code>connecttimeout_ms</code>
|
If the device can connect immediately without waiting, it may also call
|
||||||
|
<code>connectCallback()</code> directly from <code>connectRequest()</code>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If the bus cannot be connected within <code>timeout_ms</code>
|
||||||
milliseconds, the bus interface should call
|
milliseconds, the bus interface should call
|
||||||
<code>connectCallback(StreamIoTimeout)</code>.
|
<code>connectCallback(StreamIoTimeout)</code>.
|
||||||
</p>
|
</p>
|
||||||
@ -313,11 +325,11 @@ something wrong with the I/O hardware,
|
|||||||
<code>connectCallback(StreamIoFault)</code> may be called.
|
<code>connectCallback(StreamIoFault)</code> may be called.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
To disconnect, the client calls <code>disconnectRequest()</code>;
|
To disconnect explicitly, the client calls <code>disconnectRequest()</code>;
|
||||||
This function should return <code>true</code> immediately or
|
This function should return <code>true</code> immediately or
|
||||||
<code>false</code> if the request cannot be accepted or connection
|
<code>false</code> if the request cannot be accepted or connection
|
||||||
handling is not supported.
|
handling is not supported.
|
||||||
The interface should call <code>connectCallback(StreamIoSuccess)</code>
|
The interface should call <code>connectCallback()</code>
|
||||||
once the bus is disconnected. There is no timeout for this operation.
|
once the bus is disconnected. There is no timeout for this operation.
|
||||||
If disconnecting is impossible, the interface should call
|
If disconnecting is impossible, the interface should call
|
||||||
<code>connectCallback(StreamIoFault)</code>.
|
<code>connectCallback(StreamIoFault)</code>.
|
||||||
@ -326,10 +338,10 @@ If disconnecting is impossible, the interface should call
|
|||||||
<a name="lock"></a>
|
<a name="lock"></a>
|
||||||
<h3>Bus locking</h3>
|
<h3>Bus locking</h3>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool lockRequest(unsigned long lockTimeout_ms);
|
bool lockRequest(unsigned long timeout_ms);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void lockCallback(IoStatus status);
|
void lockCallback(IoStatus status = StreamIoSuccess);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool unlock();
|
bool unlock();
|
||||||
@ -348,7 +360,7 @@ or <code>false</code> if the request cannot be accepted.
|
|||||||
If the device is already locked, the bus interface should add itself to
|
If the device is already locked, the bus interface should add itself to
|
||||||
a queue, sorted by <code>priority()</code>.
|
a queue, sorted by <code>priority()</code>.
|
||||||
As soon as the device is available, the bus interface should call
|
As soon as the device is available, the bus interface should call
|
||||||
<code>lockCallback(StreamIoSuccess)</code>.
|
<code>lockCallback()</code>.
|
||||||
If the bus cannot be locked within <code>lockTimeout_ms</code>
|
If the bus cannot be locked within <code>lockTimeout_ms</code>
|
||||||
milliseconds, the bus interface should call
|
milliseconds, the bus interface should call
|
||||||
<code>lockCallback(StreamIoTimeout)</code>.
|
<code>lockCallback(StreamIoTimeout)</code>.
|
||||||
@ -369,7 +381,7 @@ locked the device.
|
|||||||
When the protocol ends and the device is locked, the client calls
|
When the protocol ends and the device is locked, the client calls
|
||||||
<code>unlock()</code>.
|
<code>unlock()</code>.
|
||||||
If other bus interfaces are in the lock queue, the next one should
|
If other bus interfaces are in the lock queue, the next one should
|
||||||
call <code>lockCallback(StreamIoSuccess)</code> now.
|
call <code>lockCallback()</code> now.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The client calls <code>finish()</code> when the protocol ends.
|
The client calls <code>finish()</code> when the protocol ends.
|
||||||
@ -385,7 +397,7 @@ bool writeRequest(const void* output,
|
|||||||
size_t size, unsigned long writeTimeout_ms);
|
size_t size, unsigned long writeTimeout_ms);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void writeCallback(IoStatus status);
|
void writeCallback(IoStatus status = StreamIoSuccess);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
const char* getOutTerminator(size_t& length);
|
const char* getOutTerminator(size_t& length);
|
||||||
@ -404,7 +416,7 @@ The function should arrange transmission of <code>size</code> bytes of
|
|||||||
or <code>false</code> if the request cannot be accepted.
|
or <code>false</code> if the request cannot be accepted.
|
||||||
It must not block until output has completed.
|
It must not block until output has completed.
|
||||||
After all output has been successfully transmitted, but not earlier, the
|
After all output has been successfully transmitted, but not earlier, the
|
||||||
interface should call <code>writeCallback(StreamIoSuccess)</code>.
|
interface should call <code>writeCallback()</code>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If output blocks for <code>writeTimeout_ms</code> milliseconds,
|
If output blocks for <code>writeTimeout_ms</code> milliseconds,
|
||||||
@ -417,14 +429,15 @@ something wrong with the I/O hardware,
|
|||||||
<code>writeCallback(StreamIoFault)</code> may be called.
|
<code>writeCallback(StreamIoFault)</code> may be called.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The interface must transmit excactly the <code>size</code> bytes
|
The interface must send excactly the <code>size</code> bytes
|
||||||
from <code>output</code>.
|
from <code>output</code>, not less.
|
||||||
It must not change anything and it should not assume that
|
It should not change anything unless the bus needs some special
|
||||||
any bytes have a special meaning.
|
formatting (e.g. added header, escaped bytes) and it should not
|
||||||
|
assume that any bytes have a special meaning.
|
||||||
In particular, a null byte does not terminate <code>output</code>.
|
In particular, a null byte does not terminate <code>output</code>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
A call to <code>getOutTerminator</code> tells the interface which
|
A call to <code>getOutTerminator()</code> tells the interface which
|
||||||
terminator has already been added to the output.
|
terminator has already been added to the output.
|
||||||
If <code>NULL</code> was returned, the client is not aware of a
|
If <code>NULL</code> was returned, the client is not aware of a
|
||||||
terminator (no outTerminator was defined in the protocol).
|
terminator (no outTerminator was defined in the protocol).
|
||||||
@ -450,9 +463,9 @@ bool readRequest(unsigned long replyTimeout_ms,
|
|||||||
long expectedLength, bool async);
|
long expectedLength, bool async);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
long readCallback(IoStatus status,
|
ssize_t readCallback(IoStatus status,
|
||||||
const void* input = NULL,
|
const void* buffer = NULL,
|
||||||
long size = 0);
|
size_t size = 0);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
const char* getInTerminator(size_t& length);
|
const char* getInTerminator(size_t& length);
|
||||||
@ -487,11 +500,11 @@ The client copies its contents. It does not modify or free it.
|
|||||||
It is not necessary to wait until all data has been received.
|
It is not necessary to wait until all data has been received.
|
||||||
The bus interface can call <code>n=readCallback()</code> after
|
The bus interface can call <code>n=readCallback()</code> after
|
||||||
any amount of input has been received.
|
any amount of input has been received.
|
||||||
If the client needs more input, <code>readCallback()</code>
|
If the client expects more input, <code>readCallback()</code>
|
||||||
returns a non-zero value.
|
returns a non-zero value.
|
||||||
A positive <code>n</code> means, the client needs another
|
A positive <code>n</code> means, the client expects another
|
||||||
<code>n</code> bytes of input.
|
<code>n</code> bytes of input.
|
||||||
A negative <code>n</code> means, the client needs an unspecified
|
A negative <code>n</code> means, the client expects an unspecified
|
||||||
amount of additional input.
|
amount of additional input.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@ -559,46 +572,43 @@ something wrong with the I/O hardware,
|
|||||||
<code>readCallback(StreamIoFault)</code> may be called.
|
<code>readCallback(StreamIoFault)</code> may be called.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If the <code>async</code> flag is <code>true</code>, the client
|
Sometimes a client wishes to get any input received at any time, even
|
||||||
wants to read input asyncronously without any timeout.
|
when requested by another client.
|
||||||
That means, the bus interface should call <code>readCallback()</code>
|
If a client wishes to receive such asynchronous input, it first calls
|
||||||
even if the input was requested by another client.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If a client wishes to receive asynchonous input, it first calls
|
|
||||||
<code>supportsAsyncRead()</code>.
|
<code>supportsAsyncRead()</code>.
|
||||||
The default implementation of this method always returns
|
The default implementation of this method always returns
|
||||||
<code>false</code>.
|
<code>false</code>.
|
||||||
A bus interface may overwrite this method to return <code>true</code>
|
If a bus interface supports asynchronous input, it should overwrite
|
||||||
and eventually prepare for asynchonous input.
|
this method to set up everything needed to receive asynchronous input
|
||||||
|
and then return <code>true</code>.
|
||||||
The client is then allowed to call <code>readRequest()</code> with
|
The client is then allowed to call <code>readRequest()</code> with
|
||||||
the <code>async==true</code>.
|
the <code>async==true</code>.
|
||||||
This means that the client is interested in any input.
|
This means that the client is now interested in asynchronous input.
|
||||||
It should receive a <code>readCallback()</code> of all input which came
|
It should receive a <code>readCallback()</code> of all input which came
|
||||||
in response to a synchonous (<code>async==false</code>) request from
|
in response to any synchonous (<code>async==false</code>) request from
|
||||||
another client (which of course should receive the input, too).
|
another client (which should receive the input, too).
|
||||||
The interface should also receive asynchonous input when no
|
The interface should also receive asynchronous input when no
|
||||||
synchonous client is active at the moment.
|
synchonous client is active at the moment.
|
||||||
Many asynchonous <code>readRequest()</code> calls from different clients
|
Many asynchronous <code>readRequest()</code> calls from different clients
|
||||||
may be active at the same time.
|
may be active at the same time.
|
||||||
All of them should receive the same input.
|
All of them should receive the same input.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
For asynchonous requests, <code>replyTimeout_ms</code> has a different
|
For asynchronous requests, <code>replyTimeout_ms</code> has a different
|
||||||
meaning: If the bus interface has to poll the bus for input, it may take
|
meaning: If the bus interface has to poll the bus for input, it may take
|
||||||
<code>replyTimeout_ms</code> as a hint for the poll period.
|
<code>replyTimeout_ms</code> as a hint for the poll period.
|
||||||
If many asynchonous requests are active at the same time, it should poll
|
If many asynchronous requests are active at the same time, it should poll
|
||||||
with the shortest period of all clients.
|
with the shortest period of all clients.
|
||||||
An asynchonous request does not time out.
|
An asynchronous request does not time out.
|
||||||
It stays active until the next input arrives.
|
It stays active until the next input arrives.
|
||||||
The client may reissue the asynchronous <code>readRequest()</code>
|
The client may reissue the asynchronous <code>readRequest()</code>
|
||||||
from within the <code>readCallback()</code> if it wants to continue
|
from within the <code>readCallback()</code> if it wants to continue
|
||||||
receiving asynchonous input.
|
receiving asynchronous input.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If the client calls <code>finish()</code> at any time, the bus
|
If the client calls <code>finish()</code> at any time, the bus
|
||||||
interface should cancel all outstanding requests, including
|
interface should cancel all outstanding requests, including
|
||||||
asynchonous read requests.
|
asynchronous read requests.
|
||||||
</p>
|
</p>
|
||||||
<a name="event"></a>
|
<a name="event"></a>
|
||||||
<h3>Handling events</h3>
|
<h3>Handling events</h3>
|
||||||
@ -606,10 +616,10 @@ asynchonous read requests.
|
|||||||
bool supportsEvent();
|
bool supportsEvent();
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
bool acceptEvent(unsigned long mask, unsigned long replytimeout_ms);
|
bool acceptEvent(unsigned long mask, unsigned long timeout_ms);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
void eventCallback(StreamIoStatus status);
|
void eventCallback(StreamIoStatus status = StreamIoSuccess);
|
||||||
</code></div>
|
</code></div>
|
||||||
<p>
|
<p>
|
||||||
An event is a sort of input from a device which is not part of
|
An event is a sort of input from a device which is not part of
|
||||||
@ -627,9 +637,9 @@ If <code>true</code> is returned, the client is allowed to call
|
|||||||
If <code>mask</code> is illegal, <code>acceptEvent()</code> should
|
If <code>mask</code> is illegal, <code>acceptEvent()</code> should
|
||||||
return <code>false</code>.
|
return <code>false</code>.
|
||||||
The call to <code>acceptEvent()</code> must not block.
|
The call to <code>acceptEvent()</code> must not block.
|
||||||
It should arrange to call <code>eventCallback(StreamIoSuccess)</code>
|
It should arrange to call <code>eventCallback()</code>
|
||||||
when the event matching <code>mask</code> arrives within
|
when the event matching <code>mask</code> arrives within
|
||||||
<code>replytimeout_ms</code> milliseconds.
|
<code>timeout_ms</code> milliseconds.
|
||||||
If no such event arrives within this time, the bus interface
|
If no such event arrives within this time, the bus interface
|
||||||
should call <code>eventCallback(StreamIoTimeout)</code>.
|
should call <code>eventCallback(StreamIoTimeout)</code>.
|
||||||
</p>
|
</p>
|
||||||
|
@ -44,7 +44,7 @@ class MyConverter : public StreamFormatConverter
|
|||||||
{
|
{
|
||||||
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||||
bool printLong(const StreamFormat&, StreamBuffer&, long);
|
bool printLong(const StreamFormat&, StreamBuffer&, long);
|
||||||
int scanLong(const StreamFormat&, const char*, long&);
|
ssize_t scanLong(const StreamFormat&, const char*, long&);
|
||||||
};
|
};
|
||||||
|
|
||||||
RegisterConverter(MyConverter,"Q");
|
RegisterConverter(MyConverter,"Q");
|
||||||
@ -73,17 +73,17 @@ Provide multiple classes, that's more efficient.
|
|||||||
<a name="parsing"></a>
|
<a name="parsing"></a>
|
||||||
<h3>Parsing</h3>
|
<h3>Parsing</h3>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
int parse (const StreamFormat& fmt, StreamBuffer& info,
|
int parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||||
const char*& source, bool scanFormat);
|
const char*& source, bool scanFormat);
|
||||||
</code></div>
|
</code></div>
|
||||||
<div class="indent"><code>
|
<div class="indent"><code>
|
||||||
struct StreamFormat {
|
struct StreamFormat {
|
||||||
char conv;
|
char conv;
|
||||||
StreamFormatType type;
|
StreamFormatType type;
|
||||||
unsigned char flags;
|
unsigned short flags;
|
||||||
short prec;
|
long prec;
|
||||||
unsigned short width;
|
unsigned long width;
|
||||||
unsigned short infolen;
|
unsigned long infolen;
|
||||||
const char* info;
|
const char* info;
|
||||||
};
|
};
|
||||||
</code></div>
|
</code></div>
|
||||||
@ -124,12 +124,12 @@ flags set:
|
|||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
It is not necessary that these flags have exactly the same meaning in your
|
It is not necessary that these flags have exactly the same meaning in your
|
||||||
formats, but a similar and intuitive meaning helpful for the user.
|
formats, but a similar and intuitive meaning is helpful for the user.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
There are two additional flags, <code>default_flag</code> indicating a
|
There are two additional flags, <code>default_flag</code> indicating a
|
||||||
<code>?</code> and <code>compare_flag</code> indicating a <code>=</code>
|
<code>?</code> and <code>compare_flag</code> indicating a <code>=</code>
|
||||||
int the format, that are handled internally by <em>StreamDevice</em> and
|
in the format, that are handled internally by <em>StreamDevice</em> and
|
||||||
are not of interest to the converter class.
|
are not of interest to the converter class.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@ -163,13 +163,13 @@ This will probably be necessary if you have parsed additional characters
|
|||||||
from the format string as in the above example<br>
|
from the format string as in the above example<br>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Return <code>long_format</code>, <em>double_format</em>,
|
Return <code>unsigned_format</code>, <code>signed_format</code>,
|
||||||
<em>string_format</em>, or <code>enum_format</code> depending on the
|
<code>double_format</code>, <code>string_format</code>, or
|
||||||
|
<code>enum_format</code> depending on the
|
||||||
datatype associated with the conversion character.
|
datatype associated with the conversion character.
|
||||||
It is not necessary to return the same value for print and for scan
|
It is not necessary to return the same value for print and for scan
|
||||||
formats.
|
formats.
|
||||||
You can even return different values depending on the format string,
|
You can even return different values depending on the format string.
|
||||||
but I can't imagine why anyone should do that.
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If the format is not a real data conversion but does other things with
|
If the format is not a real data conversion but does other things with
|
||||||
@ -178,7 +178,8 @@ return <code>pseudo_format</code>.
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Return <code>false</code> if there is any parse error or if print or scan
|
Return <code>false</code> if there is any parse error or if print or scan
|
||||||
is requested but not supported by this conversion.
|
is requested but not supported by this conversion or flags are used that
|
||||||
|
are not supported by this conversion.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a name="printing_scanning"></a>
|
<a name="printing_scanning"></a>
|
||||||
@ -191,7 +192,45 @@ That method is called whenever the conversion appears in an output or input,
|
|||||||
respectively.
|
respectively.
|
||||||
You only need to implement the flavour of print and/or scan suitable for
|
You only need to implement the flavour of print and/or scan suitable for
|
||||||
the datatype returned by <code>parse()</code>.
|
the datatype returned by <code>parse()</code>.
|
||||||
|
Both <code>unsigned_format</code> and <code>signed_format</code> will use
|
||||||
|
the <code>Long</code> flavour.
|
||||||
</p>
|
</p>
|
||||||
|
</p>
|
||||||
|
The possible interface methods are:
|
||||||
|
</p>
|
||||||
|
<div class="indent"><code>
|
||||||
|
bool printLong(const StreamFormat& fmt,
|
||||||
|
StreamBuffer& output, long value);
|
||||||
|
</code></div>
|
||||||
|
<div class="indent"><code>
|
||||||
|
bool printDouble(const StreamFormat& fmt,
|
||||||
|
StreamBuffer& output, double value);
|
||||||
|
</code></div>
|
||||||
|
<div class="indent"><code>
|
||||||
|
bool printString(const StreamFormat& fmt,
|
||||||
|
StreamBuffer& output, const char* value);
|
||||||
|
</code></div>
|
||||||
|
<div class="indent"><code>
|
||||||
|
bool printPseudo(const StreamFormat& fmt,
|
||||||
|
StreamBuffer& output);
|
||||||
|
</code></div>
|
||||||
|
<div class="indent"><code>
|
||||||
|
ssize_t scanLong(const StreamFormat& fmt,
|
||||||
|
const char* input, long& value);
|
||||||
|
</code></div>
|
||||||
|
<div class="indent"><code>
|
||||||
|
ssize_t scanDouble(const StreamFormat& fmt,
|
||||||
|
const char* input, double& value);
|
||||||
|
</code></div>
|
||||||
|
<div class="indent"><code>
|
||||||
|
ssize_t scanString(const StreamFormat& fmt,
|
||||||
|
const char* input, char* value, size_t& size);
|
||||||
|
</code></div>
|
||||||
|
<div class="indent"><code>
|
||||||
|
ssize_t scanPseudo(const StreamFormat& fmt,
|
||||||
|
StreamBuffer& inputLine, size_t& cursor);
|
||||||
|
</code></div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Now, <code>fmt.type</code> contains the value returned by <code>parse()</code>.
|
Now, <code>fmt.type</code> contains the value returned by <code>parse()</code>.
|
||||||
With <code>fmt.info()</code> get access to the string you have written to
|
With <code>fmt.info()</code> get access to the string you have written to
|
||||||
@ -203,16 +242,21 @@ The length of the info string can be found in <code>fmt.infolen</code>.
|
|||||||
<p>
|
<p>
|
||||||
In <code>print*()</code>, append the converted value to <code>output</code>.
|
In <code>print*()</code>, append the converted value to <code>output</code>.
|
||||||
Do not modify what is already in output (unless you really know what you're
|
Do not modify what is already in output (unless you really know what you're
|
||||||
doing).
|
doing, e.g. some <code>printPseudo</code> methods).
|
||||||
Return <code>true</code> on success, <code>false</code> on failure.
|
Return <code>true</code> on success, <code>false</code> on failure.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
In <code>scan*()</code>, read the value from input and return the number of
|
In <code>scan*()</code>, read the value from input and return the number of
|
||||||
consumed bytes.
|
consumed bytes or -1 on failure.
|
||||||
In the string version, don't write more bytes than <code>maxlen</code>!
|
|
||||||
If the <code>skip_flag</code> is set, you don't need to write to
|
If the <code>skip_flag</code> is set, you don't need to write to
|
||||||
<code>value</code>, since the value will be discarded anyway.
|
<code>value</code>, since the value will be discarded anyway.
|
||||||
Return <code>-1</code> on failure.
|
In <code>scanString()</code>, don't write more bytes than
|
||||||
|
<code>maxlen</code> to <code>value</code> and set <code>size</code> to the
|
||||||
|
actual string length, which may be different to the number of bytes consumed
|
||||||
|
(e.g. if leading spaces are skipped).
|
||||||
|
In <code>scanPseudo()</code>, <code>cursor</code> is the index of the first
|
||||||
|
byte in <code>inputLine</code> to consider, which may be larger than
|
||||||
|
<code>0</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<h2>What is <em>StreamDevice</em>?</h2>
|
<h2>What is <em>StreamDevice</em>?</h2>
|
||||||
<p>
|
<p>
|
||||||
<em>StreamDevice</em> is a generic
|
<em>StreamDevice</em> is a generic
|
||||||
<a href="http://www.aps.anl.gov/epics" target="ex">EPICS</a>
|
<a href="https://www.aps.anl.gov/epics" target="ex">EPICS</a>
|
||||||
device support for devices with a "byte stream" based
|
device support for devices with a "byte stream" based
|
||||||
communication interface.
|
communication interface.
|
||||||
That means devices that can be controlled by sending and
|
That means devices that can be controlled by sending and
|
||||||
@ -52,7 +52,7 @@ It does not provide loops or branches.
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<em>StreamDevice</em> comes with an interface to<a target="ex"
|
<em>StreamDevice</em> comes with an interface to<a target="ex"
|
||||||
href="http://www.aps.anl.gov/epics/modules/soft/asyn/">
|
href="https://www.aps.anl.gov/epics/modules/soft/asyn/">
|
||||||
<em>asynDriver</em></a>
|
<em>asynDriver</em></a>
|
||||||
but can be extended to
|
but can be extended to
|
||||||
<a href="businterface.html">support other bus drivers</a>.
|
<a href="businterface.html">support other bus drivers</a>.
|
||||||
@ -82,14 +82,26 @@ primitive commands.
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
It is not a block oriented device support.
|
It is not a block oriented device support.
|
||||||
It is not possible to send or receive huge blocks of data that contain
|
It is not intended for huge binary blocks of data that contain
|
||||||
many process variables distributed over many records.
|
many process variables distributed over many records.
|
||||||
|
Consider <a href="https://github.com/paulscherrerinstitute/regdev"
|
||||||
|
target="ex"><em>regDev</em></a>
|
||||||
|
for that.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
It is not a very flexible html, xml, json, etc. parser. Data needs to
|
||||||
|
come in a predictible order to be parsable by <em>StreamDevice</em>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Recommended Readings</h2>
|
<h2>Recommended Readings</h2>
|
||||||
<p>
|
<p>
|
||||||
<a href="http://www.aps.anl.gov/epics/base/R3-14/12-docs/AppDevGuide"
|
IOC Application Developer's Guide:
|
||||||
target="ex">IOC Application Developer's Guide</a>
|
<a href="https://www.aps.anl.gov/epics/base/R3-14/12-docs/AppDevGuide"
|
||||||
|
target="ex">R3.14.12</a>,
|
||||||
|
<a href="https://www.aps.anl.gov/epics/base/R3-16/1-docs/AppDevGuide"
|
||||||
|
target="ex">R3.15.5</a>,
|
||||||
|
<a href="https://www.aps.anl.gov/epics/base/R3-15/5-docs/AppDevGuide"
|
||||||
|
target="ex">R3.16.1</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="https://wiki-ext.aps.anl.gov/epics/index.php/RRM_3-14"
|
<a href="https://wiki-ext.aps.anl.gov/epics/index.php/RRM_3-14"
|
||||||
@ -105,6 +117,28 @@ This marks text you typically type in configuration files etc.
|
|||||||
Longer code segments are often set in a box.
|
Longer code segments are often set in a box.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<h2>Changes in Version 2.8</h2>
|
||||||
|
<ul>
|
||||||
|
<li>Support standard EPICS module build system.
|
||||||
|
<li>Compatible with EPICS base releases up to 7.0.1.
|
||||||
|
<ul>
|
||||||
|
<li>Support for new record types: int64in, int64out, lsi, lso.
|
||||||
|
<li>Support for INT64 and UINT64 in aai, aao, waveform.
|
||||||
|
</ul>
|
||||||
|
<li>Run @init more often (e.g. when device re-connects or paused IOC is resumed).
|
||||||
|
<li>Use "COMM" error code in .STAT when device is disconnected.
|
||||||
|
<li>Allow spaces in protocol parameter list.
|
||||||
|
<li>Errors are new silent by default (var streamError 0) except during init.
|
||||||
|
<li>Support output redirect of all shell functions.
|
||||||
|
<li>Fix building shared libraries on Windows.
|
||||||
|
<li>Fix some C++11 warnings.
|
||||||
|
<li>Fix several signed/unsigned problems.
|
||||||
|
<li>Dropped support for cygnus-2.7.2 gcc (used by some old cygwin).
|
||||||
|
<li>Several bug fixes.
|
||||||
|
<li>Several documentation updates.
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<a href="setup.html">Next: Setup</a>
|
<a href="setup.html">Next: Setup</a>
|
||||||
Dirk Zimoch, 2018
|
Dirk Zimoch, 2018
|
||||||
|
@ -210,6 +210,15 @@ div div div a {list-style-type:circle;}
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a target="_parent" href="formatconverter.html">Format Converter API</a>
|
<a target="_parent" href="formatconverter.html">Format Converter API</a>
|
||||||
|
<div>
|
||||||
|
<a target="_parent" href="formatconverter.html#class">Converter Class</a>
|
||||||
|
<a target="_parent" href="formatconverter.html#theory">Theory of Operation</a>
|
||||||
|
<div>
|
||||||
|
<a target="_parent" href="formatconverter.html#registration">Registration</a>
|
||||||
|
<a target="_parent" href="formatconverter.html#parsing">Parsing</a>
|
||||||
|
<a target="_parent" href="formatconverter.html#printing_scanning">Printing and Scanning</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a target="_parent" href="osinterface.html">Operating System API</a>
|
<a target="_parent" href="osinterface.html">Operating System API</a>
|
||||||
|
Reference in New Issue
Block a user