diff --git a/asyncprotocol.h b/asyncprotocol.h index 4bc183ba..259e12cc 100644 --- a/asyncprotocol.h +++ b/asyncprotocol.h @@ -26,6 +26,12 @@ typedef enum { ATX_DISCO = 3 } ATX_STATUS; +#define AQU_TIMEOUT -1 +#define AQU_DISCONNECT -2 +#define AQU_RECONNECT -3 +#define AQU_RETRY_CMD -4 +#define AQU_POP_CMD -5 + struct __async_txn { pAsyncUnit unit; /**< unit that transaction is associated with */ int txn_state; /**< protocol handler transaction parse state */ @@ -38,6 +44,8 @@ struct __async_txn { int inp_len; /**< length of input buffer */ int inp_idx; /**< index of next character (number already received) */ AsyncTxnHandler handleResponse; /**< Txn response handler of command sender */ + void *proto_private; /**< Protocol Private structure */ + void (*kill_private) (struct __async_txn *pTxn); /**< if it needs killing */ void *cntx; /**< opaque context used by command sender */ /* The cntx field may be used by protocol handler from sendCommand * as long as it is restored when response is complete diff --git a/asyncqueue.c b/asyncqueue.c index d551912c..e1c52173 100644 --- a/asyncqueue.c +++ b/asyncqueue.c @@ -167,6 +167,11 @@ static void AQ_Purge(pAsyncQueue self) self->command_head = self->command_tail = NULL; free(myCmd->tran->out_buf); free(myCmd->tran->inp_buf); + if (myCmd->tran->proto_private) + if (myCmd->tran->kill_private) + myCmd->tran->kill_private(myCmd->tran); + else + free(myCmd->tran->proto_private); free(myCmd->tran); free(myCmd); myCmd = self->command_head; @@ -455,6 +460,11 @@ static int PopCommand(pAsyncQueue self) self->command_head = self->command_tail = NULL; free(myCmd->tran->out_buf); free(myCmd->tran->inp_buf); + if (myCmd->tran->proto_private) + if (myCmd->tran->kill_private) + myCmd->tran->kill_private(myCmd->tran); + else + free(myCmd->tran->proto_private); free(myCmd->tran); free(myCmd); return 1; @@ -531,7 +541,7 @@ static int MyCallback(void *context, int mode) for (i = 0; i < nchars; ++i) { iRet = self->protocol->handleInput(self->protocol, myCmd->tran, - reply[i]); + reply[i] & 0xFF); if (iRet == 0 || iRet == AQU_POP_CMD) { /* end of command */ if (self->trace) { struct timeval tv; @@ -666,6 +676,7 @@ pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit, } if (unit->queue->protocol->prepareTxn) { int iRet; + myTxn->inp_len = rsp_len; /* allowing protocol to change it */ iRet = unit->queue->protocol->prepareTxn(unit->queue->protocol, myTxn, command, cmd_len, rsp_len); @@ -673,6 +684,7 @@ pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit, free(myTxn); return NULL; } + rsp_len = myTxn->inp_len; /* allowed protocol to change it */ } else { myTxn->out_buf = (char *) malloc(cmd_len + 5); if (myTxn->out_buf == NULL) { diff --git a/asyncqueue.h b/asyncqueue.h index c2aa5a83..669916c3 100644 --- a/asyncqueue.h +++ b/asyncqueue.h @@ -11,12 +11,6 @@ #include "asyncprotocol.h" -#define AQU_TIMEOUT -1 -#define AQU_DISCONNECT -2 -#define AQU_RECONNECT -3 -#define AQU_RETRY_CMD -4 -#define AQU_POP_CMD -5 - typedef struct __AsyncQueue AsyncQueue, *pAsyncQueue; diff --git a/site_ansto/hardsup/huber_asyncprotocol.c b/site_ansto/hardsup/huber_asyncprotocol.c index 5684673b..62ed18b7 100644 --- a/site_ansto/hardsup/huber_asyncprotocol.c +++ b/site_ansto/hardsup/huber_asyncprotocol.c @@ -1,4 +1,4 @@ -#include "sics.h" +#include "huber_asyncprotocol.h" #include "asyncprotocol.h" #include "asyncqueue.h" @@ -10,16 +10,16 @@ * Protocol transmit function * Called by AsyncQueue to transmit a line */ -static int HUBER_Tx(pAsyncProtocol p, pAsyncTxn myCmd) { +static int HUBER_Tx(pAsyncProtocol p, pAsyncTxn pTxn) { int iRet = 1; - if (myCmd) { - myCmd->txn_status = ATX_ACTIVE; - iRet = AsyncUnitWrite(myCmd->unit, myCmd->out_buf, myCmd->out_len); + if (pTxn) { + pTxn->txn_status = ATX_ACTIVE; + iRet = AsyncUnitWrite(pTxn->unit, pTxn->out_buf, pTxn->out_len); /* TODO handle errors */ if (iRet < 0) { /* TODO: EOF */ /* - iRet = AsyncUnitReconnect(myCmd->unit); + iRet = AsyncUnitReconnect(pTxn->unit); if (iRet == 0) */ return 0; @@ -31,39 +31,38 @@ static int HUBER_Tx(pAsyncProtocol p, pAsyncTxn myCmd) { /* * Protocol receive character - characater by character */ -static int HUBER_Rx(pAsyncProtocol p, pAsyncTxn ctx, int rxchar) { +static int HUBER_Rx(pAsyncProtocol p, pAsyncTxn pTxn, int rxchar) { int iRet = 1; - pAsyncTxn myCmd = (pAsyncTxn) ctx; - switch (myCmd->txn_state) { + switch (pTxn->txn_state) { case 0: /* first character */ if (rxchar != LBRACE) { /* TODO: error */ - myCmd->txn_state = 99; - myCmd->txn_status = ATX_COMPLETE; + pTxn->txn_state = 99; + pTxn->txn_status = ATX_COMPLETE; break; } /* normal data */ - myCmd->txn_state = 1; + pTxn->txn_state = 1; /* note fallthrough */ case 1: /* receiving reply */ - if (myCmd->inp_idx < myCmd->inp_len) - myCmd->inp_buf[myCmd->inp_idx++] = rxchar; + if (pTxn->inp_idx < pTxn->inp_len) + pTxn->inp_buf[pTxn->inp_idx++] = rxchar; if (rxchar == CR) - myCmd->txn_state = 2; + pTxn->txn_state = 2; break; case 2: /* receiving LF */ - if (myCmd->inp_idx < myCmd->inp_len) - myCmd->inp_buf[myCmd->inp_idx++] = rxchar; + if (pTxn->inp_idx < pTxn->inp_len) + pTxn->inp_buf[pTxn->inp_idx++] = rxchar; if (rxchar != LF) { /* TODO: error */ } - myCmd->txn_state = 99; - myCmd->inp_idx -= 3; - memmove(myCmd->inp_buf, myCmd->inp_buf + 1, myCmd->inp_idx); + pTxn->txn_state = 99; + pTxn->inp_idx -= 3; + memmove(pTxn->inp_buf, pTxn->inp_buf + 1, pTxn->inp_idx); break; } - if (myCmd->txn_state == 99) { + if (pTxn->txn_state == 99) { iRet = 0; } if (iRet == 0) { /* end of command */ @@ -84,18 +83,18 @@ static int HUBER_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) { return AQU_POP_CMD; } -static int HUBER_PrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_len, int rsp_len) { +static int HUBER_PrepareTxn(pAsyncProtocol p, pAsyncTxn pTxn, const char* cmd, int cmd_len, int rsp_len) { int i, bcc; - txn->out_buf = (char*) malloc(cmd_len + 3); - if (txn->out_buf == NULL) { + pTxn->out_buf = (char*) malloc(cmd_len + 3); + if (pTxn->out_buf == NULL) { SICSLogWrite("ERROR: Out of memory in HUBER_PrepareTxn", eError); return 0; } - memcpy(txn->out_buf + 1, cmd, cmd_len); - txn->out_buf[0] = LBRACE; - txn->out_buf[cmd_len + 1] = CR; - txn->out_buf[cmd_len + 2] = LF; - txn->out_len = cmd_len + 3; + memcpy(pTxn->out_buf + 1, cmd, cmd_len); + pTxn->out_buf[0] = LBRACE; + pTxn->out_buf[cmd_len + 1] = CR; + pTxn->out_buf[cmd_len + 2] = LF; + pTxn->out_len = cmd_len + 3; return 1; } diff --git a/site_ansto/hardsup/huber_asyncprotocol.h b/site_ansto/hardsup/huber_asyncprotocol.h index 6a3400a5..15e18383 100644 --- a/site_ansto/hardsup/huber_asyncprotocol.h +++ b/site_ansto/hardsup/huber_asyncprotocol.h @@ -1,4 +1,5 @@ #ifndef HUBER_ASYNCPROTOCOL_H #define HUBER_ASYNCPROTOCOL_H +#include "sics.h" void HUBERInitProtocol(SicsInterp *pSics); #endif diff --git a/site_ansto/hardsup/knauer_asyncprotocol.c b/site_ansto/hardsup/knauer_asyncprotocol.c new file mode 100644 index 00000000..aada3c97 --- /dev/null +++ b/site_ansto/hardsup/knauer_asyncprotocol.c @@ -0,0 +1,148 @@ +#include "knauer_asyncprotocol.h" +#include "asyncprotocol.h" +#include "asyncqueue.h" + +#define SYN1 0x55 +#define SYN2 0xAA +#define CR '\r' +#define LF '\n' + +/* Sample Messages + 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 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 +*/ +typedef struct knauer_private_t Private, *pPrivate; +struct knauer_private_t { + int len; +}; + +/* + * Protocol transmit function + * Called by AsyncQueue to transmit a line + */ +static int KNAUER_Tx(pAsyncProtocol p, pAsyncTxn pTxn) { + int iRet = 1; + + if (pTxn) { + pTxn->txn_status = ATX_ACTIVE; + iRet = AsyncUnitWrite(pTxn->unit, pTxn->out_buf, pTxn->out_len); + /* TODO handle errors */ + if (iRet < 0) { /* TODO: EOF */ + /* + iRet = AsyncUnitReconnect(pTxn->unit); + if (iRet == 0) + */ + return 0; + } + } + return 1; +} + +/* + * Protocol receive character - characater by character + */ +static int KNAUER_Rx(pAsyncProtocol p, pAsyncTxn pTxn, int rxchar) { + int iRet = 1; + pPrivate myPriv = (pPrivate) pTxn->proto_private; + + rxchar &= 0xFF; + switch (pTxn->txn_state) { + case 0: /* first SYN byte */ + if (rxchar != SYN1) { + /* TODO: error */ + pTxn->txn_state = 99; + pTxn->txn_status = ATX_COMPLETE; + break; + } + pTxn->txn_state = 1; + break; + case 1: /* second SYN byte */ + if (rxchar != SYN2) { + /* TODO: error */ + pTxn->txn_state = 99; + pTxn->txn_status = ATX_COMPLETE; + break; + } + pTxn->txn_state = 2; + break; + case 2: /* MS length byte */ + myPriv->len = 256 * rxchar; + pTxn->txn_state = 3; + break; + case 3: /* LS length byte */ + myPriv->len += rxchar; + pTxn->txn_state = 4; + break; + case 4: /* receiving text */ + if (pTxn->inp_idx < pTxn->inp_len) + pTxn->inp_buf[pTxn->inp_idx++] = rxchar; + if (pTxn->inp_idx >= myPriv->len) { + pTxn->txn_state = 99; + pTxn->txn_status = ATX_COMPLETE; + } + break; + } + if (pTxn->txn_state == 99) { + iRet = 0; + } + if (iRet == 0) { /* end of command */ + free(pTxn->proto_private); + pTxn->proto_private = NULL; + return AQU_POP_CMD; + } + return iRet; +} + +/* + * AsyncProtocol Event callback + */ +static int KNAUER_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) { + free(pTxn->proto_private); + pTxn->proto_private = NULL; + if (event == AQU_TIMEOUT) { + /* handle command timeout */ + pTxn->txn_status = ATX_TIMEOUT; + 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)); + if (myPriv == NULL) { + SICSLogWrite("ERROR: Out of memory in KNAUER_PrepareTxn", eError); + return 0; + } + myPriv->len = 0; + pTxn->out_buf = (char*) malloc(cmd_len + 1); + if (pTxn->out_buf == NULL) { + SICSLogWrite("ERROR: Out of memory in KNAUER_PrepareTxn", eError); + free(myPriv); + return 0; + } + pTxn->proto_private = myPriv; + memcpy(pTxn->out_buf, cmd, cmd_len); + pTxn->out_buf[cmd_len] = CR; + pTxn->out_len = cmd_len + 1; + + return 1; +} + +static pAsyncProtocol KNAUER_Protocol = NULL; + +/* + * Protocol Initialisation + */ +void KNAUERInitProtocol(SicsInterp *pSics) { + if (KNAUER_Protocol == NULL) { + KNAUER_Protocol = AsyncProtocolCreate(pSics, "KNAUER_AP", NULL, NULL); + KNAUER_Protocol->sendCommand = KNAUER_Tx; + KNAUER_Protocol->handleInput = KNAUER_Rx; + KNAUER_Protocol->handleEvent = KNAUER_Ev; + KNAUER_Protocol->prepareTxn = KNAUER_PrepareTxn; + KNAUER_Protocol->killPrivate = NULL; + } +} + + diff --git a/site_ansto/hardsup/knauer_asyncprotocol.h b/site_ansto/hardsup/knauer_asyncprotocol.h new file mode 100644 index 00000000..eda10893 --- /dev/null +++ b/site_ansto/hardsup/knauer_asyncprotocol.h @@ -0,0 +1,5 @@ +#ifndef KNAUER_ASYNCPROTOCOL_H +#define KNAUER_ASYNCPROTOCOL_H +#include "sics.h" +void KNAUERInitProtocol(SicsInterp *pSics); +#endif diff --git a/site_ansto/hardsup/loader_asyncprotocol.c b/site_ansto/hardsup/loader_asyncprotocol.c new file mode 100644 index 00000000..cb1c7441 --- /dev/null +++ b/site_ansto/hardsup/loader_asyncprotocol.c @@ -0,0 +1,12 @@ +#include "loader_asyncprotocol.h" +#include "huber_asyncprotocol.h" +#include "knauer_asyncprotocol.h" +#include "omron_asyncprotocol.h" +#include "sics.h" + +void LOADERInitProtocol(SicsInterp *pSics) +{ + HUBERInitProtocol(pSics); + KNAUERInitProtocol(pSics); + OMRONInitProtocol(pSics); +} diff --git a/site_ansto/hardsup/loader_asyncprotocol.h b/site_ansto/hardsup/loader_asyncprotocol.h new file mode 100644 index 00000000..a61d5925 --- /dev/null +++ b/site_ansto/hardsup/loader_asyncprotocol.h @@ -0,0 +1,5 @@ +#ifndef LOADER_ASYNCPROTOCOL_H +#define LOADER_ASYNCPROTOCOL_H +#include "sics.h" +void LOADERInitProtocol(SicsInterp *pSics); +#endif diff --git a/site_ansto/hardsup/makefile b/site_ansto/hardsup/makefile index b7196508..dcac1541 100644 --- a/site_ansto/hardsup/makefile +++ b/site_ansto/hardsup/makefile @@ -37,6 +37,8 @@ HOBJ += sct_asyncqueue.o HOBJ += aqp_opalstatus.o HOBJ += omron_asyncprotocol.o HOBJ += huber_asyncprotocol.o +HOBJ += knauer_asyncprotocol.o +HOBJ += loader_asyncprotocol.o libhlib.a: $(HOBJ) rm -f libhlib.a diff --git a/site_ansto/hardsup/omron_asyncprotocol.c b/site_ansto/hardsup/omron_asyncprotocol.c index c8c70be8..2266d07a 100644 --- a/site_ansto/hardsup/omron_asyncprotocol.c +++ b/site_ansto/hardsup/omron_asyncprotocol.c @@ -1,4 +1,4 @@ -#include "sics.h" +#include "omron_asyncprotocol.h" #include "asyncprotocol.h" #include "asyncqueue.h" @@ -30,16 +30,16 @@ static int calc_bcc(const char* text) * Protocol transmit function * Called by AsyncQueue to transmit a line */ -static int OMRON_Tx(pAsyncProtocol p, pAsyncTxn myCmd) { +static int OMRON_Tx(pAsyncProtocol p, pAsyncTxn pTxn) { int iRet = 1; - if (myCmd) { - myCmd->txn_status = ATX_ACTIVE; - iRet = AsyncUnitWrite(myCmd->unit, myCmd->out_buf, myCmd->out_len); + if (pTxn) { + pTxn->txn_status = ATX_ACTIVE; + iRet = AsyncUnitWrite(pTxn->unit, pTxn->out_buf, pTxn->out_len); /* TODO handle errors */ if (iRet < 0) { /* TODO: EOF */ /* - iRet = AsyncUnitReconnect(myCmd->unit); + iRet = AsyncUnitReconnect(pTxn->unit); if (iRet == 0) */ return 0; @@ -51,44 +51,43 @@ static int OMRON_Tx(pAsyncProtocol p, pAsyncTxn myCmd) { /* * Protocol receive character - characater by character */ -static int OMRON_Rx(pAsyncProtocol p, pAsyncTxn ctx, int rxchar) { +static int OMRON_Rx(pAsyncProtocol p, pAsyncTxn pTxn, int rxchar) { int iRet = 1; - pAsyncTxn myCmd = (pAsyncTxn) ctx; - switch (myCmd->txn_state) { + switch (pTxn->txn_state) { case 0: /* first character */ if (rxchar != STX) { /* STX */ /* TODO: error */ - myCmd->txn_state = 99; - myCmd->txn_status = ATX_COMPLETE; + pTxn->txn_state = 99; + pTxn->txn_status = ATX_COMPLETE; break; } /* normal data */ - myCmd->txn_state = 1; + pTxn->txn_state = 1; /* note fallthrough */ case 1: /* receiving reply */ - if (myCmd->inp_idx < myCmd->inp_len) - myCmd->inp_buf[myCmd->inp_idx++] = rxchar; + if (pTxn->inp_idx < pTxn->inp_len) + pTxn->inp_buf[pTxn->inp_idx++] = rxchar; if (rxchar == ETX) - myCmd->txn_state = 2; + pTxn->txn_state = 2; break; case 2: /* receiving bcc */ - if (myCmd->inp_idx < myCmd->inp_len) - myCmd->inp_buf[myCmd->inp_idx++] = rxchar; - if (calc_bcc(myCmd->inp_buf) != rxchar) { + if (pTxn->inp_idx < pTxn->inp_len) + pTxn->inp_buf[pTxn->inp_idx++] = rxchar; + if (calc_bcc(pTxn->inp_buf) != rxchar) { /* TODO: fail bcc */ - int bcc = calc_bcc(myCmd->inp_buf); + int bcc = calc_bcc(pTxn->inp_buf); SICSLogPrintf(eError, "Omron BCC mismatch, expected %02X but received %02X on message:", bcc, rxchar); - SICSLogWriteHex(myCmd->inp_buf, myCmd->inp_idx, eError); + SICSLogWriteHex(pTxn->inp_buf, pTxn->inp_idx, eError); } - myCmd->txn_state = 99; - myCmd->inp_idx -= 3; - memmove(myCmd->inp_buf, myCmd->inp_buf + 1, myCmd->inp_idx); + pTxn->txn_state = 99; + pTxn->inp_idx -= 3; + memmove(pTxn->inp_buf, pTxn->inp_buf + 1, pTxn->inp_idx); break; } - if (myCmd->txn_state == 99) { + if (pTxn->txn_state == 99) { iRet = 0; } if (iRet == 0) { /* end of command */ @@ -109,18 +108,18 @@ static int OMRON_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) { return AQU_POP_CMD; } -static int OMRON_PrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_len, int rsp_len) { +static int OMRON_PrepareTxn(pAsyncProtocol p, pAsyncTxn pTxn, const char* cmd, int cmd_len, int rsp_len) { int i, bcc; - txn->out_buf = (char*) malloc(cmd_len + 3); - if (txn->out_buf == NULL) { + pTxn->out_buf = (char*) malloc(cmd_len + 3); + if (pTxn->out_buf == NULL) { SICSLogWrite("ERROR: Out of memory in OMRON_PrepareTxn", eError); return 0; } - memcpy(txn->out_buf + 1, cmd, cmd_len); - txn->out_buf[0] = STX; - txn->out_buf[cmd_len + 1] = ETX; - txn->out_buf[cmd_len + 2] = calc_bcc(txn->out_buf); - txn->out_len = cmd_len + 3; + memcpy(pTxn->out_buf + 1, cmd, cmd_len); + pTxn->out_buf[0] = STX; + pTxn->out_buf[cmd_len + 1] = ETX; + pTxn->out_buf[cmd_len + 2] = calc_bcc(pTxn->out_buf); + pTxn->out_len = cmd_len + 3; return 1; } diff --git a/site_ansto/hardsup/omron_asyncprotocol.h b/site_ansto/hardsup/omron_asyncprotocol.h index f0a0ab7b..091a82f8 100644 --- a/site_ansto/hardsup/omron_asyncprotocol.h +++ b/site_ansto/hardsup/omron_asyncprotocol.h @@ -1,4 +1,5 @@ #ifndef OMRON_ASYNCPROTOCOL_H #define OMRON_ASYNCPROTOCOL_H +#include "sics.h" void OMRONInitProtocol(SicsInterp *pSics); #endif diff --git a/site_ansto/site_ansto.c b/site_ansto/site_ansto.c index 8d2715bc..f67feef4 100644 --- a/site_ansto/site_ansto.c +++ b/site_ansto/site_ansto.c @@ -383,8 +383,7 @@ static void AddCommands(SicsInterp *pInter) LS340InitProtocol(pInter); CameraInitProtocol(pInter); OpalStatusInitProtocol(pInter); - OMRONInitProtocol(pInter); - HUBERInitProtocol(pInter); + LOADERInitProtocol(pInter); AddCommand(pInter,"InstallProtocolHandler", InstallProtocol,NULL,NULL); AddCommand(pInter,"hostnam",hostNamCmd,NULL,NULL); AddCommand(pInter,"portnum",portNumCmd,NULL,NULL);