Reworked AsyncQueue sendCommand processing

Squashed commit of the following:

commit 42fb7d3cde591d40060cc740ccbc47f1ae7a5a50
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Tue Aug 26 13:31:11 2014 +1000

    Get the MODBUS_AP working

commit da785c1434a04c4186d4174eb2dfbaefc850c8e7
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Mon Aug 25 18:01:50 2014 +1000

    Bring Modbus protocol closer to Huber, Knauer and Omron

commit ef06ed7b6911cb49b35c19fe73e55f7c57cfd049
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Mon Aug 25 18:01:18 2014 +1000

    Make Huber, Knauer and Omron protocols more aligned (diffable)

commit 3ef1bb06b3f865502ad7dffc4bf5dba4814d9334
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Fri Aug 22 17:47:50 2014 +1000

    Get the Huber and Knauer protocols to be more alike

commit 2c9932e83f6735e894278648afdcadece654d43b
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Fri Aug 22 17:12:31 2014 +1000

    Clean up the Knauer dual-mode protocol and refactor

commit 333300b19b0e61916e261300ac6ae2b6bab5df09
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Thu Aug 21 15:38:39 2014 +1000

    Get the Knauer dual-mode protocol working(-ish)

commit b1f9d82f1b9eb8a1ff54694adc3482984b0d3d72
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Thu Aug 21 15:37:44 2014 +1000

    Make private functions static (and not duplicated)

commit 0b077414eef9e4351956a2b971d7751cced0d3cd
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Thu Aug 21 12:46:10 2014 +1000

    Knauer moving toward dual protocol

commit 13199bea38a1595ce06923e83474b738b10db94d
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Thu Aug 21 12:42:48 2014 +1000

    Restructure default sendCommand processing in asyncqueue

commit 99a8ea3174ca0636503b0ce0cdb6016790315558
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Thu Aug 21 09:48:50 2014 +1000

    Add a Modbus Protocol handler derived from sct_tcpmodbus

commit 3adf49fb7c8402c8260a0bb20729d551ac88537b
Author: Douglas Clowes <dcl@ansto.gov.au>
Date:   Thu Aug 21 09:43:54 2014 +1000

    Leave the free of private data to the asyncqueue mechanism
This commit is contained in:
Douglas Clowes
2014-08-26 14:30:19 +10:00
parent ee40adceb2
commit a43461b200
11 changed files with 897 additions and 379 deletions

View File

@ -394,7 +394,16 @@ static int StartCommand(pAsyncQueue self)
} }
myCmd->tran->txn_status = ATX_ACTIVE; myCmd->tran->txn_status = ATX_ACTIVE;
iRet = self->protocol->sendCommand(self->protocol, myCmd->tran); if (self->protocol->sendCommand) {
iRet = self->protocol->sendCommand(self->protocol, myCmd->tran);
} else {
pAsyncTxn txn = myCmd->tran;
iRet = AsyncUnitWrite(txn->unit, txn->out_buf, txn->out_len);
if (iRet < 0)
iRet = 0;
else
iRet = 1;
}
/* /*
* Handle case of no response expected * Handle case of no response expected
*/ */

View File

@ -20,17 +20,6 @@
enum replystates {START, HEADER, CHKHEADEREND, MSG}; enum replystates {START, HEADER, CHKHEADEREND, MSG};
static pAsyncProtocol OPAL_Protocol = NULL; static pAsyncProtocol OPAL_Protocol = NULL;
static int OPAL_Tx(pAsyncProtocol p, pAsyncTxn txn) {
if (txn == NULL) {
return 0;
}
txn->txn_status = ATX_ACTIVE;
if (AsyncUnitWrite(txn->unit, txn->out_buf, txn->out_len) < 0) {
return 0;
}
return 1;
}
/* The header and message are followed by the character sequences given below, /* The header and message are followed by the character sequences given below,
* HEADER cr lf cr lf <msg len> cr lf * HEADER cr lf cr lf <msg len> cr lf
* MESSAGE cr lf 0x30 cr lf cr lf * MESSAGE cr lf 0x30 cr lf cr lf
@ -137,7 +126,7 @@ static int OPAL_PrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int
void OpalStatusInitProtocol(SicsInterp *pSics) { void OpalStatusInitProtocol(SicsInterp *pSics) {
if (OPAL_Protocol == NULL) { if (OPAL_Protocol == NULL) {
OPAL_Protocol = AsyncProtocolCreate(pSics, "OPALSTAT", NULL, NULL); OPAL_Protocol = AsyncProtocolCreate(pSics, "OPALSTAT", NULL, NULL);
OPAL_Protocol->sendCommand = OPAL_Tx; OPAL_Protocol->sendCommand = NULL;
OPAL_Protocol->handleInput = OPAL_Rx; OPAL_Protocol->handleInput = OPAL_Rx;
OPAL_Protocol->killPrivate = NULL; OPAL_Protocol->killPrivate = NULL;
OPAL_Protocol->handleEvent = OPAL_Ev; OPAL_Protocol->handleEvent = OPAL_Ev;

View File

@ -183,18 +183,6 @@ static void CAM_Notify(void* context, int event) {
return; return;
} }
static int CAM_Tx(pAsyncProtocol p, pAsyncTxn txn) {
if (txn == NULL) {
return 0;
}
txn->txn_status = ATX_ACTIVE;
if (AsyncUnitWrite(txn->unit, txn->out_buf, txn->out_len) < 0) {
return 0;
}
return 1;
}
int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch); int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch);
static int CAM_Rx(pAsyncProtocol p, pAsyncTxn txn, int ch) { static int CAM_Rx(pAsyncProtocol p, pAsyncTxn txn, int ch) {
int ret = 1; int ret = 1;
@ -221,7 +209,7 @@ static int CAM_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) {
void CameraInitProtocol(SicsInterp *pSics) { void CameraInitProtocol(SicsInterp *pSics) {
if (CAM_Protocol == NULL) { if (CAM_Protocol == NULL) {
CAM_Protocol = AsyncProtocolCreate(pSics, "CAMERA", NULL, NULL); CAM_Protocol = AsyncProtocolCreate(pSics, "CAMERA", NULL, NULL);
CAM_Protocol->sendCommand = CAM_Tx; CAM_Protocol->sendCommand = NULL;
CAM_Protocol->handleInput = CAM_Rx; CAM_Protocol->handleInput = CAM_Rx;
CAM_Protocol->prepareTxn = NULL; CAM_Protocol->prepareTxn = NULL;
CAM_Protocol->killPrivate = NULL; CAM_Protocol->killPrivate = NULL;

View File

@ -1,80 +1,163 @@
#include "huber_asyncprotocol.h" #include "huber_asyncprotocol.h"
#include "asyncprotocol.h" #include "asyncprotocol.h"
#include "asyncqueue.h" #include "asyncqueue.h"
#include "ascon.i"
#include "dynstring.h"
#include <errno.h>
#define PROTOCOL_CONTINUE 0
#define PROTOCOL_COMPLETE 1
#define PROTOCOL_ERROR (-1)
/* Sample Messages
structure:
7B - LEFT BRACE
xx - text
0D 0A - CR LF
*/
#define PROTOCOL_NAME "HUBER_AP"
#define PROTOCOL_INIT HUBERInitProtocol
#define LBRACE '{' #define LBRACE '{'
#define CR '\r' #define CR '\r'
#define LF '\n' #define LF '\n'
/* /*
* Protocol transmit function * Protocol Private data block
* Called by AsyncQueue to transmit a line
*/ */
static int HUBER_Tx(pAsyncProtocol p, pAsyncTxn pTxn) { typedef struct proto_private_t {
int iRet = 1; int state; /**< protocol state machine */
int len; /**< length from the protocol */
pDynString wrBuffer; /**< transmitted message */
pDynString rxBuffer; /**< received message */
} ProtoPrivate;
if (pTxn) { static ProtoPrivate *makeProtoPrivate()
pTxn->txn_status = ATX_ACTIVE; {
iRet = AsyncUnitWrite(pTxn->unit, pTxn->out_buf, pTxn->out_len); ProtoPrivate *priv = calloc(sizeof(ProtoPrivate), 1);
/* TODO handle errors */ priv->wrBuffer = CreateDynString(100, 100);
if (iRet < 0) { /* TODO: EOF */ priv->rxBuffer = CreateDynString(100, 100);
/* return priv;
iRet = AsyncUnitReconnect(pTxn->unit); }
if (iRet == 0)
*/ static ProtoPrivate *Proto_KillPrivate(ProtoPrivate *priv)
return 0; {
if (priv) {
if (priv->rxBuffer) {
DeleteDynString(priv->rxBuffer);
priv->rxBuffer = NULL;
} }
free(priv);
} }
return 1; return NULL;
}
/*
* Protocol Specific Support Functions
*/
/*
* Protocol Prepare Output
*/
static int Proto_Prepare(ProtoPrivate *priv, pDynString wrBuffer)
{
DynStringInsert(wrBuffer, "{", 0);
DynStringConcatChar(wrBuffer, CR);
DynStringConcatChar(wrBuffer, LF);
return PROTOCOL_COMPLETE;
} }
/* /*
* Protocol receive character - characater by character * Protocol receive character - characater by character
*/ */
static int HUBER_Rx(pAsyncProtocol p, pAsyncTxn pTxn, int rxchar) { static int Proto_RxChar(ProtoPrivate *priv, int rxchar)
int iRet = 1; {
enum RX_STATE {
switch (pTxn->txn_state) { RX_START=0,
case 0: /* first character */ RX_TEXT=1,
RX_LAST=2, /* LF */
RX_STOP=99
};
rxchar &= 0xFF;
switch (priv->state) {
case RX_START:
if (rxchar != LBRACE) { if (rxchar != LBRACE) {
/* TODO: error */ priv->state = RX_STOP;
pTxn->txn_state = 99; return PROTOCOL_ERROR;
pTxn->txn_status = ATX_COMPLETE;
break;
} }
/* normal data */ priv->state = RX_TEXT;
pTxn->txn_state = 1; return PROTOCOL_CONTINUE;
/* note fallthrough */ case RX_TEXT:
case 1: /* receiving reply */ if (rxchar == CR) {
if (pTxn->inp_idx < pTxn->inp_len) priv->state = RX_LAST;
pTxn->inp_buf[pTxn->inp_idx++] = rxchar; return PROTOCOL_CONTINUE;
if (rxchar == CR)
pTxn->txn_state = 2;
break;
case 2: /* receiving LF */
if (pTxn->inp_idx < pTxn->inp_len)
pTxn->inp_buf[pTxn->inp_idx++] = rxchar;
if (rxchar != LF) {
/* TODO: error */
} }
pTxn->txn_state = 99; DynStringConcatChar(priv->rxBuffer, rxchar);
pTxn->inp_idx -= 3; return PROTOCOL_CONTINUE;
memmove(pTxn->inp_buf, pTxn->inp_buf + 1, pTxn->inp_idx); case RX_LAST:
break; if (rxchar == LF) {
priv->state = RX_STOP;
return PROTOCOL_COMPLETE;
} else {
priv->state = RX_STOP;
return PROTOCOL_ERROR;
}
default:
return PROTOCOL_ERROR;
} }
if (pTxn->txn_state == 99) { return PROTOCOL_ERROR;
iRet = 0; }
/*
* AsyncProtocol handling
* ======================
*/
static void Async_KillPrivate(pAsyncTxn pTxn)
{
Proto_KillPrivate((ProtoPrivate *) pTxn->proto_private);
pTxn->proto_private = NULL;
}
/*
* AsyncProtocol Receive Character
*/
static int Async_Rx(pAsyncProtocol p, pAsyncTxn pTxn, int rxchar) {
int iRet, str_len;
ProtoPrivate *priv = (ProtoPrivate *) pTxn->proto_private;
iRet = Proto_RxChar(priv, rxchar);
/*
* Keep inp_buf and inp_idx up-to-date after each character
*/
str_len = GetDynStringLength(priv->rxBuffer);
if (str_len > pTxn->inp_idx && pTxn->inp_idx < pTxn->inp_len) {
int xfr_len;
char *tgt = &pTxn->inp_buf[pTxn->inp_idx];
char *loc = &GetCharArray(priv->rxBuffer)[pTxn->inp_idx];
if (str_len > pTxn->inp_len)
xfr_len = pTxn->inp_len - pTxn->inp_idx;
else
xfr_len = str_len - pTxn->inp_idx;
memcpy(tgt, loc, xfr_len);
pTxn->inp_idx += xfr_len;
} }
if (iRet == 0) { /* end of command */
return AQU_POP_CMD; if (iRet == PROTOCOL_CONTINUE) {
return 1; /* Keep Going */
} }
return iRet;
if (iRet == PROTOCOL_ERROR) {
return -1; /* Error condition */
}
/* Message Complete */
return AQU_POP_CMD;
} }
/* /*
* AsyncProtocol Event callback * AsyncProtocol Event callback
*/ */
static int HUBER_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) { static int Async_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) {
if (event == AQU_TIMEOUT) { if (event == AQU_TIMEOUT) {
/* handle command timeout */ /* handle command timeout */
pTxn->txn_status = ATX_TIMEOUT; pTxn->txn_status = ATX_TIMEOUT;
@ -83,34 +166,168 @@ static int HUBER_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) {
return AQU_POP_CMD; return AQU_POP_CMD;
} }
static int HUBER_PrepareTxn(pAsyncProtocol p, pAsyncTxn pTxn, const char* cmd, int cmd_len, int rsp_len) { /*
int i, bcc; * AsyncProtocol Prepare Transaction
pTxn->out_buf = (char*) malloc(cmd_len + 3); */
if (pTxn->out_buf == NULL) { static int Async_PrepareTxn(pAsyncProtocol p, pAsyncTxn pTxn, const char* cmd, int cmd_len, int rsp_len) {
SICSLogWrite("ERROR: Out of memory in HUBER_PrepareTxn", eError); ProtoPrivate *priv;
priv = makeProtoPrivate();
if (priv == NULL) {
SICSLogWrite("ERROR: Out of memory in Async_PrepareTxn", eError);
return 0; return 0;
} }
memcpy(pTxn->out_buf + 1, cmd, cmd_len); priv->state = 0;
pTxn->out_buf[0] = LBRACE; priv->len = 0;
pTxn->out_buf[cmd_len + 1] = CR; DynStringConcatBytes(priv->wrBuffer, cmd, cmd_len);
pTxn->out_buf[cmd_len + 2] = LF; Proto_Prepare(priv, priv->wrBuffer);
pTxn->out_len = cmd_len + 3; pTxn->out_len = GetDynStringLength(priv->wrBuffer);
pTxn->out_buf = (char*) malloc(pTxn->out_len);
if (pTxn->out_buf == NULL) {
SICSLogPrintf(eError, "ERROR: Out of memory in %s:%s", __FILE__, __FUNCTION__);
Proto_KillPrivate(priv);
return 0;
}
pTxn->proto_private = priv;
pTxn->kill_private = Async_KillPrivate;
memcpy(pTxn->out_buf, GetCharArray(priv->wrBuffer), pTxn->out_len);
return 1; return 1;
} }
static pAsyncProtocol HUBER_Protocol = NULL; /*
* Ascon Protocol handling
* =======================
*/
static void Ascon_KillPrivate(void *priv)
{
Proto_KillPrivate((ProtoPrivate *) priv);
}
/*
* Ascon Protocol WriteStart
*/
static int Ascon_Prepare(Ascon *a) {
ProtoPrivate *priv = (ProtoPrivate *) a->private;
Proto_Prepare(priv, a->wrBuffer);
a->wrPos = 0;
a->state = AsconWriting;
return 1;
}
/*
* Ascon Protocol Read Poll
*/
static int Ascon_Rx(Ascon *a) {
int ret, status;
char chr = '\0';
ProtoPrivate *priv = (ProtoPrivate *) a->private;
ret = AsconReadChar(a->fd, &chr);
while (ret > 0) {
a->start = DoubleTime();
status = Proto_RxChar(priv, chr);
if (GetDynStringLength(priv->rxBuffer) > GetDynStringLength(a->rdBuffer)) {
int len_rd = GetDynStringLength(a->rdBuffer);
int len_rx = GetDynStringLength(priv->rxBuffer);
char *loc = &GetCharArray(priv->rxBuffer)[len_rd];
DynStringConcatBytes(a->rdBuffer, loc, len_rx - len_rd);
}
if (status > 0) { /* Complete */
a->state = AsconReadDone;
return 1;
}
else if (status < 0) { /* Error */
AsconError(a, "Protocol Input Error:", status);
/*TODO This hack stops ascon.c:AsconTask() from needlessly closing the connection. Remove this when it's no longer needed */
a->lastReconnect = DoubleTime();
return 1;
}
ret = AsconReadChar(a->fd, &chr);
}
if (ret < 0) {
AsconError(a, "AsconReadChar failed:", errno);
return 1;
}
if (a->state != AsconReadDone) {
if (a->timeout > 0) {
if (DoubleTime() - a->start > a->timeout) {
AsconError(a, "read timeout", 0);
a->state = AsconTimeout;
}
}
}
return 1;
}
/*
* Ascon Protocol Poll Loop
*/
static int AsconProtHandler(Ascon *a) {
ProtoPrivate *priv = (ProtoPrivate *) a->private;
int ret;
switch(a->state){
case AsconWriteStart:
ret = Ascon_Prepare(a);
return ret;
case AsconReadStart:
DynStringClear(priv->rxBuffer);
a->start = DoubleTime();
priv->state = 0;
priv->len = 0;
ret = AsconStdHandler(a);
return ret;
case AsconReading:
ret = Ascon_Rx(a);
return ret;
default:
ret = AsconStdHandler(a);
return ret;
}
return 1;
}
/*
* Ascon Protocol Connection Init
*/
static int AsconInit(Ascon *a, SConnection *con, int argc, char *argv[])
{
int iRet;
ProtoPrivate *priv;
iRet = AsconStdInit(a, con, argc, argv);
priv = makeProtoPrivate();
a->private = priv;
a->killPrivate = Ascon_KillPrivate;
return iRet;
}
static AsyncProtocol *My_Async_Protocol = NULL;
static AsconProtocol *My_Ascon_Protocol = NULL;
/* /*
* Protocol Initialisation * Protocol Initialisation
*/ */
void HUBERInitProtocol(SicsInterp *pSics) { void PROTOCOL_INIT(SicsInterp *pSics) {
if (HUBER_Protocol == NULL) { if (My_Async_Protocol == NULL) {
HUBER_Protocol = AsyncProtocolCreate(pSics, "HUBER_AP", NULL, NULL); AsyncProtocol *prot;
HUBER_Protocol->sendCommand = HUBER_Tx; prot = AsyncProtocolCreate(pSics, PROTOCOL_NAME, NULL, NULL);
HUBER_Protocol->handleInput = HUBER_Rx; prot->sendCommand = NULL;
HUBER_Protocol->handleEvent = HUBER_Ev; prot->handleInput = Async_Rx;
HUBER_Protocol->prepareTxn = HUBER_PrepareTxn; prot->handleEvent = Async_Ev;
HUBER_Protocol->killPrivate = NULL; prot->prepareTxn = Async_PrepareTxn;
My_Async_Protocol = prot;
}
if (My_Ascon_Protocol == NULL) {
AsconProtocol *prot;
prot = calloc(sizeof(AsconProtocol), 1);
prot->name = strdup(PROTOCOL_NAME);
prot->init = AsconInit;
prot->handler = AsconProtHandler;
AsconInsertProtocol(prot);
My_Ascon_Protocol = prot;
} }
} }

View File

@ -1,105 +1,175 @@
#include "knauer_asyncprotocol.h" #include "knauer_asyncprotocol.h"
#include "asyncprotocol.h" #include "asyncprotocol.h"
#include "asyncqueue.h" #include "asyncqueue.h"
#include "ascon.i"
#include "dynstring.h"
#include <errno.h>
#define SYN1 0x55 #define PROTOCOL_CONTINUE 0
#define SYN2 0xAA #define PROTOCOL_COMPLETE 1
#define CR '\r' #define PROTOCOL_ERROR (-1)
#define LF '\n'
/* Sample Messages /* Sample Messages
55 aa 00 08 52 45 4d 4f 54 45 3a 30 55 aa 00 08 52 45 4d 4f 54 45 3a 30
55 aa 00 16 45 52 52 4f 52 3a 34 38 2c 4e 6f 74 20 73 75 70 70 6f 72 74 65 64 55 aa 00 16 45 52 52 4f 52 3a 34 38 2c 4e 6f 74 20 73 75 70 70 6f 72 74 65 64
55 aa 00 18 45 52 52 4f 52 3a 31 36 2c 49 6e 76 61 6c 69 64 20 63 6f 6d 6d 61 6e 64 55 aa 00 18 45 52 52 4f 52 3a 31 36 2c 49 6e 76 61 6c 69 64 20 63 6f 6d 6d 61 6e 64
structure:
55 aa - sync bytes
00 xx - length of following bytes
yy .. zz - count(00 xx) message bytes with no terminator
*/ */
typedef struct knauer_private_t Private, *pPrivate; #define PROTOCOL_NAME "KNAUER_AP"
struct knauer_private_t { #define PROTOCOL_INIT KNAUERInitProtocol
int len; #define SYN1 0x55
}; #define SYN2 0xAA
#define CR '\r'
#define LF '\n'
/* /*
* Protocol transmit function * Protocol Private data block
* Called by AsyncQueue to transmit a line
*/ */
static int KNAUER_Tx(pAsyncProtocol p, pAsyncTxn pTxn) { typedef struct proto_private_t {
int iRet = 1; int state; /**< protocol state machine */
int len; /**< length from the protocol */
pDynString wrBuffer; /**< transmitted message */
pDynString rxBuffer; /**< received message */
} ProtoPrivate;
if (pTxn) { static ProtoPrivate *makeProtoPrivate()
pTxn->txn_status = ATX_ACTIVE; {
iRet = AsyncUnitWrite(pTxn->unit, pTxn->out_buf, pTxn->out_len); ProtoPrivate *priv = calloc(sizeof(ProtoPrivate), 1);
/* TODO handle errors */ priv->wrBuffer = CreateDynString(100, 100);
if (iRet < 0) { /* TODO: EOF */ priv->rxBuffer = CreateDynString(100, 100);
/* return priv;
iRet = AsyncUnitReconnect(pTxn->unit); }
if (iRet == 0)
*/ static ProtoPrivate *Proto_KillPrivate(ProtoPrivate *priv)
return 0; {
if (priv) {
if (priv->rxBuffer) {
DeleteDynString(priv->rxBuffer);
priv->rxBuffer = NULL;
} }
free(priv);
} }
return 1; return NULL;
}
/*
* Protocol Specific Support Functions
*/
/*
* Protocol Prepare Output
*/
static int Proto_Prepare(ProtoPrivate *priv, pDynString wrBuffer)
{
DynStringConcatChar(wrBuffer, CR);
return PROTOCOL_COMPLETE;
} }
/* /*
* Protocol receive character - characater by character * Protocol receive character - characater by character
*/ */
static int KNAUER_Rx(pAsyncProtocol p, pAsyncTxn pTxn, int rxchar) { static int Proto_RxChar(ProtoPrivate *priv, int rxchar)
int iRet = 1; {
pPrivate myPriv = (pPrivate) pTxn->proto_private; enum RX_STATE {
RX_START=0,
RX_TEXT=1,
RX_SYN2=2,
RX_LEN1=3,
RX_LEN2=4,
RX_STOP=99
};
rxchar &= 0xFF; rxchar &= 0xFF;
switch (pTxn->txn_state) { switch (priv->state) {
case 0: /* first SYN byte */ case RX_START:
if (rxchar != SYN1) { if (rxchar != SYN1) {
/* TODO: error */ priv->state = RX_STOP;
pTxn->txn_state = 99; return PROTOCOL_ERROR;
pTxn->txn_status = ATX_COMPLETE;
break;
} }
pTxn->txn_state = 1; priv->state = RX_SYN2;
break; return PROTOCOL_CONTINUE;
case 1: /* second SYN byte */ case RX_SYN2:
if (rxchar != SYN2) { if (rxchar != SYN2) {
/* TODO: error */ priv->state = RX_STOP;
pTxn->txn_state = 99; return PROTOCOL_ERROR;
pTxn->txn_status = ATX_COMPLETE;
break;
} }
pTxn->txn_state = 2; priv->state = RX_LEN1;
break; return PROTOCOL_CONTINUE;
case 2: /* MS length byte */ case RX_LEN1:
myPriv->len = 256 * rxchar; priv->len = 256 * rxchar;
pTxn->txn_state = 3; priv->state = RX_LEN2;
break; return PROTOCOL_CONTINUE;
case 3: /* LS length byte */ case RX_LEN2:
myPriv->len += rxchar; priv->len += rxchar;
pTxn->txn_state = 4; priv->state = RX_TEXT;
break; return PROTOCOL_CONTINUE;
case 4: /* receiving text */ case RX_TEXT:
if (pTxn->inp_idx < pTxn->inp_len) DynStringConcatChar(priv->rxBuffer, rxchar);
pTxn->inp_buf[pTxn->inp_idx++] = rxchar; if (GetDynStringLength(priv->rxBuffer) >= priv->len) {
if (pTxn->inp_idx >= myPriv->len) { priv->state = RX_STOP;
pTxn->txn_state = 99; return PROTOCOL_COMPLETE;
pTxn->txn_status = ATX_COMPLETE; } else {
return PROTOCOL_CONTINUE;
} }
break;
default:
return PROTOCOL_ERROR;
} }
if (pTxn->txn_state == 99) { return PROTOCOL_ERROR;
iRet = 0; }
/*
* AsyncProtocol handling
* ======================
*/
static void Async_KillPrivate(pAsyncTxn pTxn)
{
Proto_KillPrivate((ProtoPrivate *) pTxn->proto_private);
pTxn->proto_private = NULL;
}
/*
* AsyncProtocol Receive Character
*/
static int Async_Rx(pAsyncProtocol p, pAsyncTxn pTxn, int rxchar) {
int iRet, str_len;
ProtoPrivate *priv = (ProtoPrivate *) pTxn->proto_private;
iRet = Proto_RxChar(priv, rxchar);
/*
* Keep inp_buf and inp_idx up-to-date after each character
*/
str_len = GetDynStringLength(priv->rxBuffer);
if (str_len > pTxn->inp_idx && pTxn->inp_idx < pTxn->inp_len) {
int xfr_len;
char *tgt = &pTxn->inp_buf[pTxn->inp_idx];
char *loc = &GetCharArray(priv->rxBuffer)[pTxn->inp_idx];
if (str_len > pTxn->inp_len)
xfr_len = pTxn->inp_len - pTxn->inp_idx;
else
xfr_len = str_len - pTxn->inp_idx;
memcpy(tgt, loc, xfr_len);
pTxn->inp_idx += xfr_len;
} }
if (iRet == 0) { /* end of command */
free(pTxn->proto_private); if (iRet == PROTOCOL_CONTINUE) {
pTxn->proto_private = NULL; return 1; /* Keep Going */
return AQU_POP_CMD;
} }
return iRet;
if (iRet == PROTOCOL_ERROR) {
return -1; /* Error condition */
}
/* Message Complete */
return AQU_POP_CMD;
} }
/* /*
* AsyncProtocol Event callback * AsyncProtocol Event callback
*/ */
static int KNAUER_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) { static int Async_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) {
free(pTxn->proto_private);
pTxn->proto_private = NULL;
if (event == AQU_TIMEOUT) { if (event == AQU_TIMEOUT) {
/* handle command timeout */ /* handle command timeout */
pTxn->txn_status = ATX_TIMEOUT; pTxn->txn_status = ATX_TIMEOUT;
@ -108,41 +178,168 @@ static int KNAUER_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) {
return AQU_POP_CMD; return AQU_POP_CMD;
} }
static int KNAUER_PrepareTxn(pAsyncProtocol p, pAsyncTxn pTxn, const char* cmd, int cmd_len, int rsp_len) { /*
pPrivate myPriv = (pPrivate) malloc(sizeof(Private)); * AsyncProtocol Prepare Transaction
if (myPriv == NULL) { */
SICSLogWrite("ERROR: Out of memory in KNAUER_PrepareTxn", eError); static int Async_PrepareTxn(pAsyncProtocol p, pAsyncTxn pTxn, const char* cmd, int cmd_len, int rsp_len) {
ProtoPrivate *priv;
priv = makeProtoPrivate();
if (priv == NULL) {
SICSLogWrite("ERROR: Out of memory in Async_PrepareTxn", eError);
return 0; return 0;
} }
myPriv->len = 0; priv->state = 0;
pTxn->out_buf = (char*) malloc(cmd_len + 1); priv->len = 0;
DynStringConcatBytes(priv->wrBuffer, cmd, cmd_len);
Proto_Prepare(priv, priv->wrBuffer);
pTxn->out_len = GetDynStringLength(priv->wrBuffer);
pTxn->out_buf = (char*) malloc(pTxn->out_len);
if (pTxn->out_buf == NULL) { if (pTxn->out_buf == NULL) {
SICSLogWrite("ERROR: Out of memory in KNAUER_PrepareTxn", eError); SICSLogPrintf(eError, "ERROR: Out of memory in %s:%s", __FILE__, __FUNCTION__);
free(myPriv); Proto_KillPrivate(priv);
return 0; return 0;
} }
pTxn->proto_private = myPriv; pTxn->proto_private = priv;
memcpy(pTxn->out_buf, cmd, cmd_len); pTxn->kill_private = Async_KillPrivate;
pTxn->out_buf[cmd_len] = CR; memcpy(pTxn->out_buf, GetCharArray(priv->wrBuffer), pTxn->out_len);
pTxn->out_len = cmd_len + 1;
return 1; return 1;
} }
static pAsyncProtocol KNAUER_Protocol = NULL; /*
* Ascon Protocol handling
* =======================
*/
static void Ascon_KillPrivate(void *priv)
{
Proto_KillPrivate((ProtoPrivate *) priv);
}
/*
* Ascon Protocol WriteStart
*/
static int Ascon_Prepare(Ascon *a) {
ProtoPrivate *priv = (ProtoPrivate *) a->private;
Proto_Prepare(priv, a->wrBuffer);
a->wrPos = 0;
a->state = AsconWriting;
return 1;
}
/*
* Ascon Protocol Read Poll
*/
static int Ascon_Rx(Ascon *a) {
int ret, status;
char chr = '\0';
ProtoPrivate *priv = (ProtoPrivate *) a->private;
ret = AsconReadChar(a->fd, &chr);
while (ret > 0) {
a->start = DoubleTime();
status = Proto_RxChar(priv, chr);
if (GetDynStringLength(priv->rxBuffer) > GetDynStringLength(a->rdBuffer)) {
int len_rd = GetDynStringLength(a->rdBuffer);
int len_rx = GetDynStringLength(priv->rxBuffer);
char *loc = &GetCharArray(priv->rxBuffer)[len_rd];
DynStringConcatBytes(a->rdBuffer, loc, len_rx - len_rd);
}
if (status > 0) { /* Complete */
a->state = AsconReadDone;
return 1;
}
else if (status < 0) { /* Error */
AsconError(a, "Protocol Input Error:", status);
/*TODO This hack stops ascon.c:AsconTask() from needlessly closing the connection. Remove this when it's no longer needed */
a->lastReconnect = DoubleTime();
return 1;
}
ret = AsconReadChar(a->fd, &chr);
}
if (ret < 0) {
AsconError(a, "AsconReadChar failed:", errno);
return 1;
}
if (a->state != AsconReadDone) {
if (a->timeout > 0) {
if (DoubleTime() - a->start > a->timeout) {
AsconError(a, "read timeout", 0);
a->state = AsconTimeout;
}
}
}
return 1;
}
/*
* Ascon Protocol Poll Loop
*/
static int AsconProtHandler(Ascon *a) {
ProtoPrivate *priv = (ProtoPrivate *) a->private;
int ret;
switch(a->state){
case AsconWriteStart:
ret = Ascon_Prepare(a);
return ret;
case AsconReadStart:
DynStringClear(priv->rxBuffer);
a->start = DoubleTime();
priv->state = 0;
priv->len = 0;
ret = AsconStdHandler(a);
return ret;
case AsconReading:
ret = Ascon_Rx(a);
return ret;
default:
ret = AsconStdHandler(a);
return ret;
}
return 1;
}
/*
* Ascon Protocol Connection Init
*/
static int AsconInit(Ascon *a, SConnection *con, int argc, char *argv[])
{
int iRet;
ProtoPrivate *priv;
iRet = AsconStdInit(a, con, argc, argv);
priv = makeProtoPrivate();
a->private = priv;
a->killPrivate = Ascon_KillPrivate;
return iRet;
}
static AsyncProtocol *My_Async_Protocol = NULL;
static AsconProtocol *My_Ascon_Protocol = NULL;
/* /*
* Protocol Initialisation * Protocol Initialisation
*/ */
void KNAUERInitProtocol(SicsInterp *pSics) { void PROTOCOL_INIT(SicsInterp *pSics) {
if (KNAUER_Protocol == NULL) { if (My_Async_Protocol == NULL) {
KNAUER_Protocol = AsyncProtocolCreate(pSics, "KNAUER_AP", NULL, NULL); AsyncProtocol *prot;
KNAUER_Protocol->sendCommand = KNAUER_Tx; prot = AsyncProtocolCreate(pSics, PROTOCOL_NAME, NULL, NULL);
KNAUER_Protocol->handleInput = KNAUER_Rx; prot->sendCommand = NULL;
KNAUER_Protocol->handleEvent = KNAUER_Ev; prot->handleInput = Async_Rx;
KNAUER_Protocol->prepareTxn = KNAUER_PrepareTxn; prot->handleEvent = Async_Ev;
KNAUER_Protocol->killPrivate = NULL; prot->prepareTxn = Async_PrepareTxn;
My_Async_Protocol = prot;
}
if (My_Ascon_Protocol == NULL) {
AsconProtocol *prot;
prot = calloc(sizeof(AsconProtocol), 1);
prot->name = strdup(PROTOCOL_NAME);
prot->init = AsconInit;
prot->handler = AsconProtHandler;
AsconInsertProtocol(prot);
My_Ascon_Protocol = prot;
} }
} }

View File

@ -1,105 +1,186 @@
#include "omron_asyncprotocol.h" #include "omron_asyncprotocol.h"
#include "asyncprotocol.h" #include "asyncprotocol.h"
#include "asyncqueue.h" #include "asyncqueue.h"
#include "ascon.i"
#include "dynstring.h"
#include <errno.h>
#define PROTOCOL_CONTINUE 0
#define PROTOCOL_COMPLETE 1
#define PROTOCOL_ERROR (-1)
/* Sample Messages
* structure:
* STX
* data
* ETX
* BCC
*/
#define PROTOCOL_NAME "OMRON_AP"
#define PROTOCOL_INIT OMRONInitProtocol
#define STX 2 #define STX 2
#define ETX 3 #define ETX 3
static int calc_bcc(const char* text) /*
* Protocol Private data block
*/
typedef struct proto_private_t {
int state; /**< protocol state machine */
int len; /**< length from the protocol */
pDynString wrBuffer; /**< transmitted message */
pDynString rxBuffer; /**< received message */
} ProtoPrivate;
static ProtoPrivate *makeProtoPrivate()
{ {
int bcc = 0; ProtoPrivate *priv = calloc(sizeof(ProtoPrivate), 1);
int i = 0; priv->wrBuffer = CreateDynString(100, 100);
int c; priv->rxBuffer = CreateDynString(100, 100);
while (i < 1024) { return priv;
c = text[i] & 0xFF; }
if (c == STX) {
bcc = 0; static ProtoPrivate *Proto_KillPrivate(ProtoPrivate *priv)
} else { {
bcc ^= c; if (priv) {
if (priv->rxBuffer) {
DeleteDynString(priv->rxBuffer);
priv->rxBuffer = NULL;
} }
SICSLogPrintf(eLog, "BCC %02d: char %02X, bcc = %02X", i, c, bcc); free(priv);
if (c == ETX)
break;
++text;
} }
return NULL;
}
/*
* Protocol Specific Support Functions
*/
static int calc_bcc(const char* text, int len)
{
int idx = 0;
int bcc = 0;
int c = 0;
for (idx = 0; idx < len; ++idx) {
c = text[idx] & 0xFF;
bcc ^= c;
}
bcc ^= ETX;
return bcc; return bcc;
} }
/* /*
* Protocol transmit function * Protocol Prepare Output
* Called by AsyncQueue to transmit a line
*/ */
static int OMRON_Tx(pAsyncProtocol p, pAsyncTxn pTxn) { static int Proto_Prepare(ProtoPrivate *priv, pDynString wrBuffer)
int iRet = 1; {
int bcc;
if (pTxn) { char stx[2] = {STX, '\0'};
pTxn->txn_status = ATX_ACTIVE; bcc = calc_bcc(GetCharArray(wrBuffer), GetDynStringLength(wrBuffer));
iRet = AsyncUnitWrite(pTxn->unit, pTxn->out_buf, pTxn->out_len); DynStringInsert(wrBuffer, stx, 0);
/* TODO handle errors */ DynStringConcatChar(wrBuffer, ETX);
if (iRet < 0) { /* TODO: EOF */ DynStringConcatChar(wrBuffer, bcc);
/* return PROTOCOL_COMPLETE;
iRet = AsyncUnitReconnect(pTxn->unit);
if (iRet == 0)
*/
return 0;
}
}
return 1;
} }
/* /*
* Protocol receive character - characater by character * Protocol receive character - characater by character
*/ */
static int OMRON_Rx(pAsyncProtocol p, pAsyncTxn pTxn, int rxchar) { static int Proto_RxChar(ProtoPrivate *priv, int rxchar)
int iRet = 1; {
enum RX_STATE {
switch (pTxn->txn_state) { RX_START=0,
case 0: /* first character */ RX_TEXT=1,
if (rxchar != STX) { /* STX */ RX_LAST=2, /* BCC */
/* TODO: error */ RX_STOP=99
pTxn->txn_state = 99; };
pTxn->txn_status = ATX_COMPLETE; int bcc;
break; rxchar &= 0xFF;
switch (priv->state) {
case RX_START:
if (rxchar != STX) {
priv->state = RX_STOP;
return PROTOCOL_ERROR;
} }
/* normal data */ priv->state = RX_TEXT;
pTxn->txn_state = 1; return PROTOCOL_CONTINUE;
/* note fallthrough */ case RX_TEXT:
case 1: /* receiving reply */ if (rxchar == ETX) {
if (pTxn->inp_idx < pTxn->inp_len) priv->state = RX_LAST;
pTxn->inp_buf[pTxn->inp_idx++] = rxchar; return PROTOCOL_CONTINUE;
if (rxchar == ETX) }
pTxn->txn_state = 2; DynStringConcatChar(priv->rxBuffer, rxchar);
break; return PROTOCOL_CONTINUE;
case 2: /* receiving bcc */ case RX_LAST:
if (pTxn->inp_idx < pTxn->inp_len) bcc = calc_bcc(GetCharArray(priv->rxBuffer), GetDynStringLength(priv->rxBuffer));
pTxn->inp_buf[pTxn->inp_idx++] = rxchar; if (bcc == rxchar) {
if (calc_bcc(pTxn->inp_buf) != rxchar) { priv->state = RX_STOP;
/* TODO: fail bcc */ return PROTOCOL_COMPLETE;
int bcc = calc_bcc(pTxn->inp_buf); } else {
SICSLogPrintf(eError, SICSLogPrintf(eError,
"Omron BCC mismatch, expected %02X but received %02X on message:", "Omron BCC mismatch, expected %02X but received %02X on message:",
bcc, rxchar); bcc, rxchar);
SICSLogWriteHex(pTxn->inp_buf, pTxn->inp_idx, eError); SICSLogWriteHex(GetCharArray(priv->rxBuffer), GetDynStringLength(priv->rxBuffer), eError);
priv->state = RX_STOP;
return PROTOCOL_ERROR;
} }
pTxn->txn_state = 99;
pTxn->inp_idx -= 3; default:
memmove(pTxn->inp_buf, pTxn->inp_buf + 1, pTxn->inp_idx); return PROTOCOL_ERROR;
break;
} }
if (pTxn->txn_state == 99) { return PROTOCOL_ERROR;
iRet = 0; }
/*
* AsyncProtocol handling
* ======================
*/
static void Async_KillPrivate(pAsyncTxn pTxn)
{
Proto_KillPrivate((ProtoPrivate *) pTxn->proto_private);
pTxn->proto_private = NULL;
}
/*
* AsyncProtocol Receive Character
*/
static int Async_Rx(pAsyncProtocol p, pAsyncTxn pTxn, int rxchar) {
int iRet, str_len;
ProtoPrivate *priv = (ProtoPrivate *) pTxn->proto_private;
iRet = Proto_RxChar(priv, rxchar);
/*
* Keep inp_buf and inp_idx up-to-date after each character
*/
str_len = GetDynStringLength(priv->rxBuffer);
if (str_len > pTxn->inp_idx && pTxn->inp_idx < pTxn->inp_len) {
int xfr_len;
char *tgt = &pTxn->inp_buf[pTxn->inp_idx];
char *loc = &GetCharArray(priv->rxBuffer)[pTxn->inp_idx];
if (str_len > pTxn->inp_len)
xfr_len = pTxn->inp_len - pTxn->inp_idx;
else
xfr_len = str_len - pTxn->inp_idx;
memcpy(tgt, loc, xfr_len);
pTxn->inp_idx += xfr_len;
} }
if (iRet == 0) { /* end of command */
return AQU_POP_CMD; if (iRet == PROTOCOL_CONTINUE) {
return 1; /* Keep Going */
} }
return iRet;
if (iRet == PROTOCOL_ERROR) {
return -1; /* Error condition */
}
/* Message Complete */
return AQU_POP_CMD;
} }
/* /*
* AsyncProtocol Event callback * AsyncProtocol Event callback
*/ */
static int OMRON_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) { static int Async_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) {
if (event == AQU_TIMEOUT) { if (event == AQU_TIMEOUT) {
/* handle command timeout */ /* handle command timeout */
pTxn->txn_status = ATX_TIMEOUT; pTxn->txn_status = ATX_TIMEOUT;
@ -108,34 +189,168 @@ static int OMRON_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) {
return AQU_POP_CMD; return AQU_POP_CMD;
} }
static int OMRON_PrepareTxn(pAsyncProtocol p, pAsyncTxn pTxn, const char* cmd, int cmd_len, int rsp_len) { /*
int i, bcc; * AsyncProtocol Prepare Transaction
pTxn->out_buf = (char*) malloc(cmd_len + 3); */
if (pTxn->out_buf == NULL) { static int Async_PrepareTxn(pAsyncProtocol p, pAsyncTxn pTxn, const char* cmd, int cmd_len, int rsp_len) {
SICSLogWrite("ERROR: Out of memory in OMRON_PrepareTxn", eError); ProtoPrivate *priv;
priv = makeProtoPrivate();
if (priv == NULL) {
SICSLogWrite("ERROR: Out of memory in Async_PrepareTxn", eError);
return 0; return 0;
} }
memcpy(pTxn->out_buf + 1, cmd, cmd_len); priv->state = 0;
pTxn->out_buf[0] = STX; priv->len = 0;
pTxn->out_buf[cmd_len + 1] = ETX; DynStringConcatBytes(priv->wrBuffer, cmd, cmd_len);
pTxn->out_buf[cmd_len + 2] = calc_bcc(pTxn->out_buf); Proto_Prepare(priv, priv->wrBuffer);
pTxn->out_len = cmd_len + 3; pTxn->out_len = GetDynStringLength(priv->wrBuffer);
pTxn->out_buf = (char*) malloc(pTxn->out_len);
if (pTxn->out_buf == NULL) {
SICSLogPrintf(eError, "ERROR: Out of memory in %s:%s", __FILE__, __FUNCTION__);
Proto_KillPrivate(priv);
return 0;
}
pTxn->proto_private = priv;
pTxn->kill_private = Async_KillPrivate;
memcpy(pTxn->out_buf, GetCharArray(priv->wrBuffer), pTxn->out_len);
return 1; return 1;
} }
static pAsyncProtocol OMRON_Protocol = NULL; /*
* Ascon Protocol handling
* =======================
*/
static void Ascon_KillPrivate(void *priv)
{
Proto_KillPrivate((ProtoPrivate *) priv);
}
/*
* Ascon Protocol WriteStart
*/
static int Ascon_Prepare(Ascon *a) {
ProtoPrivate *priv = (ProtoPrivate *) a->private;
Proto_Prepare(priv, a->wrBuffer);
a->wrPos = 0;
a->state = AsconWriting;
return 1;
}
/*
* Ascon Protocol Read Poll
*/
static int Ascon_Rx(Ascon *a) {
int ret, status;
char chr = '\0';
ProtoPrivate *priv = (ProtoPrivate *) a->private;
ret = AsconReadChar(a->fd, &chr);
while (ret > 0) {
a->start = DoubleTime();
status = Proto_RxChar(priv, chr);
if (GetDynStringLength(priv->rxBuffer) > GetDynStringLength(a->rdBuffer)) {
int len_rd = GetDynStringLength(a->rdBuffer);
int len_rx = GetDynStringLength(priv->rxBuffer);
char *loc = &GetCharArray(priv->rxBuffer)[len_rd];
DynStringConcatBytes(a->rdBuffer, loc, len_rx - len_rd);
}
if (status > 0) { /* Complete */
a->state = AsconReadDone;
return 1;
}
else if (status < 0) { /* Error */
AsconError(a, "Protocol Input Error:", status);
/*TODO This hack stops ascon.c:AsconTask() from needlessly closing the connection. Remove this when it's no longer needed */
a->lastReconnect = DoubleTime();
return 1;
}
ret = AsconReadChar(a->fd, &chr);
}
if (ret < 0) {
AsconError(a, "AsconReadChar failed:", errno);
return 1;
}
if (a->state != AsconReadDone) {
if (a->timeout > 0) {
if (DoubleTime() - a->start > a->timeout) {
AsconError(a, "read timeout", 0);
a->state = AsconTimeout;
}
}
}
return 1;
}
/*
* Ascon Protocol Poll Loop
*/
static int AsconProtHandler(Ascon *a) {
ProtoPrivate *priv = (ProtoPrivate *) a->private;
int ret;
switch(a->state){
case AsconWriteStart:
ret = Ascon_Prepare(a);
return ret;
case AsconReadStart:
DynStringClear(priv->rxBuffer);
a->start = DoubleTime();
priv->state = 0;
priv->len = 0;
ret = AsconStdHandler(a);
return ret;
case AsconReading:
ret = Ascon_Rx(a);
return ret;
default:
ret = AsconStdHandler(a);
return ret;
}
return 1;
}
/*
* Ascon Protocol Connection Init
*/
static int AsconInit(Ascon *a, SConnection *con, int argc, char *argv[])
{
int iRet;
ProtoPrivate *priv;
iRet = AsconStdInit(a, con, argc, argv);
priv = makeProtoPrivate();
a->private = priv;
a->killPrivate = Ascon_KillPrivate;
return iRet;
}
static AsyncProtocol *My_Async_Protocol = NULL;
static AsconProtocol *My_Ascon_Protocol = NULL;
/* /*
* Protocol Initialisation * Protocol Initialisation
*/ */
void OMRONInitProtocol(SicsInterp *pSics) { void PROTOCOL_INIT(SicsInterp *pSics) {
if (OMRON_Protocol == NULL) { if (My_Async_Protocol == NULL) {
OMRON_Protocol = AsyncProtocolCreate(pSics, "OMRON_AP", NULL, NULL); AsyncProtocol *prot;
OMRON_Protocol->sendCommand = OMRON_Tx; prot = AsyncProtocolCreate(pSics, PROTOCOL_NAME, NULL, NULL);
OMRON_Protocol->handleInput = OMRON_Rx; prot->sendCommand = NULL;
OMRON_Protocol->handleEvent = OMRON_Ev; prot->handleInput = Async_Rx;
OMRON_Protocol->prepareTxn = OMRON_PrepareTxn; prot->handleEvent = Async_Ev;
OMRON_Protocol->killPrivate = NULL; prot->prepareTxn = Async_PrepareTxn;
My_Async_Protocol = prot;
}
if (My_Ascon_Protocol == NULL) {
AsconProtocol *prot;
prot = calloc(sizeof(AsconProtocol), 1);
prot->name = strdup(PROTOCOL_NAME);
prot->init = AsconInit;
prot->handler = AsconProtHandler;
AsconInsertProtocol(prot);
My_Ascon_Protocol = prot;
} }
} }

View File

@ -786,33 +786,6 @@ static void LS340Notify(void* context, int event)
static pAsyncProtocol LS340_Protocol = NULL; static pAsyncProtocol LS340_Protocol = NULL;
static int LS340_Tx(pAsyncProtocol p, pAsyncTxn ctx)
{
int iRet = 1;
pAsyncTxn myCmd = (pAsyncTxn) ctx;
if (myCmd) {
if (strchr(myCmd->out_buf, '?')) {
myCmd->txn_status = ATX_ACTIVE;
} else {
myCmd->txn_status = ATX_COMPLETE;
}
iRet = AsyncUnitWrite(myCmd->unit, myCmd->out_buf, myCmd->out_len);
/* TODO handle errors */
if (iRet < 0) { /* TODO: EOF */
/*
iRet = AsyncUnitReconnect(myCmd->unit);
if (iRet == 0)
*/
return 0;
}
}
return 1;
}
static int LS340_Rx(pAsyncProtocol p, pAsyncTxn ctx, int rxchar) { static int LS340_Rx(pAsyncProtocol p, pAsyncTxn ctx, int rxchar) {
int iRet = 1; int iRet = 1;
pAsyncTxn myCmd = (pAsyncTxn) ctx; pAsyncTxn myCmd = (pAsyncTxn) ctx;
@ -856,17 +829,22 @@ static int LS340_PrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, in
if (txn->out_buf[txn->out_len-1] != '\r') { if (txn->out_buf[txn->out_len-1] != '\r') {
txn->out_buf[txn->out_len++] = '\r'; txn->out_buf[txn->out_len++] = '\r';
// txn->out_buf[txn->out_len++] = '\r';
} }
// txn->out_buf[txn->out_len++] = '\0'; /*
* If this message does not contain a Question Mark (?)
* Then it does not request a reply
*/
if (!strchr(cmd, '?'))
txn->inp_len = 0;
return 1; return 1;
} }
void LS340InitProtocol(SicsInterp *pSics) { void LS340InitProtocol(SicsInterp *pSics) {
if (LS340_Protocol == NULL) { if (LS340_Protocol == NULL) {
LS340_Protocol = AsyncProtocolCreate(pSics, "ls340", NULL, NULL); LS340_Protocol = AsyncProtocolCreate(pSics, "ls340", NULL, NULL);
LS340_Protocol->sendCommand = LS340_Tx; LS340_Protocol->sendCommand = NULL;
LS340_Protocol->handleInput = LS340_Rx; LS340_Protocol->handleInput = LS340_Rx;
LS340_Protocol->handleEvent = LS340_Ev; LS340_Protocol->handleEvent = LS340_Ev;
LS340_Protocol->prepareTxn = LS340_PrepareTxn; LS340_Protocol->prepareTxn = LS340_PrepareTxn;

View File

@ -97,23 +97,6 @@ mxml_node_t *tree;
static int LSS_GetState(void *pData, char *param, LSS_STATUS *retState); static int LSS_GetState(void *pData, char *param, LSS_STATUS *retState);
static int LSS_Tx(pAsyncProtocol p, pAsyncTxn myCmd)
{
int iRet = 1;
if (myCmd) {
myCmd->txn_status = ATX_ACTIVE;
iRet = AsyncUnitWrite(myCmd->unit, myCmd->out_buf, myCmd->out_len);
/* TODO handle errors */
if (iRet < 0) { /* TODO: EOF */
iRet = AsyncUnitReconnect(myCmd->unit);
if (iRet == 0)
return 0;
}
}
return 1;
}
static int LSS_Rx(pAsyncProtocol p, pAsyncTxn myCmd, int rxchar) static int LSS_Rx(pAsyncProtocol p, pAsyncTxn myCmd, int rxchar)
{ {
int iRet = 1; int iRet = 1;
@ -512,7 +495,7 @@ static void LSS_Kill(void* pData)
void LSSInitProtocol(SicsInterp *pSics) { void LSSInitProtocol(SicsInterp *pSics) {
if (LSS_Protocol == NULL) { if (LSS_Protocol == NULL) {
LSS_Protocol = AsyncProtocolCreate(pSics, "LSS", NULL, NULL); LSS_Protocol = AsyncProtocolCreate(pSics, "LSS", NULL, NULL);
LSS_Protocol->sendCommand = LSS_Tx; LSS_Protocol->sendCommand = NULL;
LSS_Protocol->handleInput = LSS_Rx; LSS_Protocol->handleInput = LSS_Rx;
LSS_Protocol->handleEvent = LSS_Ev; LSS_Protocol->handleEvent = LSS_Ev;
LSS_Protocol->prepareTxn = NULL; LSS_Protocol->prepareTxn = NULL;

View File

@ -933,25 +933,6 @@ static int motCreep(pDMC2280Driv self, double target) {
return target_steps; return target_steps;
} }
static int DMC_Tx(pAsyncProtocol p, pAsyncTxn ctx) {
int iRet = 1;
pAsyncTxn myCmd = (pAsyncTxn) ctx;
if (myCmd) {
myCmd->txn_status = ATX_ACTIVE;
iRet = AsyncUnitWrite(myCmd->unit, myCmd->out_buf, myCmd->out_len);
/* TODO handle errors */
if (iRet < 0) { /* TODO: EOF */
/*
iRet = AsyncUnitReconnect(myCmd->unit);
if (iRet == 0)
*/
return 0;
}
}
return 1;
}
static int DMC_Rx(pAsyncProtocol p, pAsyncTxn ctx, int rxchar) { static int DMC_Rx(pAsyncProtocol p, pAsyncTxn ctx, int rxchar) {
int iRet = 1; int iRet = 1;
pAsyncTxn myCmd = (pAsyncTxn) ctx; pAsyncTxn myCmd = (pAsyncTxn) ctx;
@ -6367,7 +6348,7 @@ int DMC2280Action(SConnection *pCon, SicsInterp *pSics, void *pData,
void DMC2280InitProtocol(SicsInterp *pSics) { void DMC2280InitProtocol(SicsInterp *pSics) {
if (DMC2280_Protocol == NULL) { if (DMC2280_Protocol == NULL) {
DMC2280_Protocol = AsyncProtocolCreate(pSics, "DMC2280", NULL, NULL); DMC2280_Protocol = AsyncProtocolCreate(pSics, "DMC2280", NULL, NULL);
DMC2280_Protocol->sendCommand = DMC_Tx; DMC2280_Protocol->sendCommand = NULL;
DMC2280_Protocol->handleInput = DMC_Rx; DMC2280_Protocol->handleInput = DMC_Rx;
DMC2280_Protocol->handleEvent = DMC_Ev; DMC2280_Protocol->handleEvent = DMC_Ev;
DMC2280_Protocol->prepareTxn = NULL; DMC2280_Protocol->prepareTxn = NULL;

View File

@ -778,28 +778,6 @@ static void ORHVPSKillPrivate(void *pData) {
} }
} }
/*
* Protocol transmit function
* Called by AsyncQueue to transmit a line
*/
static int ORHVPS_Tx(pAsyncProtocol p, pAsyncTxn myCmd) {
int iRet = 1;
if (myCmd) {
myCmd->txn_status = ATX_ACTIVE;
iRet = AsyncUnitWrite(myCmd->unit, myCmd->out_buf, myCmd->out_len);
/* TODO handle errors */
if (iRet < 0) { /* TODO: EOF */
/*
iRet = AsyncUnitReconnect(myCmd->unit);
if (iRet == 0)
*/
return 0;
}
}
return 1;
}
/* /*
* Protocol receive character - characater by character * Protocol receive character - characater by character
*/ */
@ -907,7 +885,7 @@ static pAsyncProtocol ORHVPS_Protocol = NULL;
void ORHVPSInitProtocol(SicsInterp *pSics) { void ORHVPSInitProtocol(SicsInterp *pSics) {
if (ORHVPS_Protocol == NULL) { if (ORHVPS_Protocol == NULL) {
ORHVPS_Protocol = AsyncProtocolCreate(pSics, "ORHVPS", NULL, NULL); ORHVPS_Protocol = AsyncProtocolCreate(pSics, "ORHVPS", NULL, NULL);
ORHVPS_Protocol->sendCommand = ORHVPS_Tx; ORHVPS_Protocol->sendCommand = NULL;
ORHVPS_Protocol->handleInput = ORHVPS_Rx; ORHVPS_Protocol->handleInput = ORHVPS_Rx;
ORHVPS_Protocol->handleEvent = ORHVPS_Ev; ORHVPS_Protocol->handleEvent = ORHVPS_Ev;
ORHVPS_Protocol->prepareTxn = ORHVPS_PrepareTxn; ORHVPS_Protocol->prepareTxn = ORHVPS_PrepareTxn;

View File

@ -77,23 +77,6 @@ struct __SafetyPLCController {
static int PLC_GetState(void *pData, char *param, PLC_STATUS *retState); static int PLC_GetState(void *pData, char *param, PLC_STATUS *retState);
static int PLC_Tx(pAsyncProtocol p, pAsyncTxn myCmd)
{
int iRet = 1;
if (myCmd) {
myCmd->txn_status = ATX_ACTIVE;
iRet = AsyncUnitWrite(myCmd->unit, myCmd->out_buf, myCmd->out_len);
/* TODO handle errors */
if (iRet < 0) { /* TODO: EOF */
iRet = AsyncUnitReconnect(myCmd->unit);
if (iRet == 0)
return 0;
}
}
return 1;
}
static int PLC_Rx(pAsyncProtocol p, pAsyncTxn myCmd, int rxchar) static int PLC_Rx(pAsyncProtocol p, pAsyncTxn myCmd, int rxchar)
{ {
int iRet = 1; int iRet = 1;
@ -477,7 +460,7 @@ static void PLC_Kill(void* pData)
void SafetyPLCInitProtocol(SicsInterp *pSics) { void SafetyPLCInitProtocol(SicsInterp *pSics) {
if (PLC_Protocol == NULL) { if (PLC_Protocol == NULL) {
PLC_Protocol = AsyncProtocolCreate(pSics, "SafetyPLC", NULL, NULL); PLC_Protocol = AsyncProtocolCreate(pSics, "SafetyPLC", NULL, NULL);
PLC_Protocol->sendCommand = PLC_Tx; PLC_Protocol->sendCommand = NULL;
PLC_Protocol->handleInput = PLC_Rx; PLC_Protocol->handleInput = PLC_Rx;
PLC_Protocol->handleEvent = PLC_Ev; PLC_Protocol->handleEvent = PLC_Ev;
PLC_Protocol->prepareTxn = NULL; PLC_Protocol->prepareTxn = NULL;