90 lines
2.2 KiB
C
90 lines
2.2 KiB
C
/**
|
|
* This is a protocol implementation for the new SICS asynchronous I/O
|
|
* infrastructure and the Juelich chopper system as used at MARS.
|
|
*
|
|
* The Juelich chopper control program likes checksums to come with
|
|
* messages and uses $ as both send and reply terminators.
|
|
*
|
|
* copyright: see file COPYRIGHT
|
|
*
|
|
* Mark Koennecke, June 2008
|
|
*/
|
|
#include <errno.h>
|
|
#include <ascon.h>
|
|
#include <ascon.i>
|
|
#include <dynstring.h>
|
|
|
|
static int calculateJulCheckSum(char *realCommand)
|
|
{
|
|
int i, checkSum = 0;
|
|
|
|
for (i = 1; i < strlen(realCommand); i++) {
|
|
checkSum += (int) realCommand[i];
|
|
}
|
|
return checkSum;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int JulchoHandler(Ascon * a)
|
|
{
|
|
char *data = NULL;
|
|
int checkSum, ret;
|
|
char checkBuffer[30], chr;
|
|
|
|
switch (a->state) {
|
|
case AsconWriteStart:
|
|
data = GetCharArray(a->wrBuffer);
|
|
checkSum = calculateJulCheckSum(data);
|
|
snprintf(checkBuffer, 30, "{%d}$", checkSum);
|
|
DynStringConcat(a->wrBuffer, checkBuffer);
|
|
a->state = AsconWriting;
|
|
a->wrPos = 0;
|
|
break;
|
|
case AsconReading:
|
|
ret = AsconReadChar(a->fd, &chr);
|
|
if (ret < 0) {
|
|
/* EINTR means we must retry */
|
|
if (errno != EINTR && errno != EAGAIN) {
|
|
AsconError(a, "AsconReadChar failed:", errno);
|
|
}
|
|
return 1;
|
|
} else if (ret > 0) {
|
|
a->start = DoubleTime();
|
|
if (chr == '$') {
|
|
DynStringConcatChar(a->rdBuffer, '\0');
|
|
a->state = AsconReadDone;
|
|
break;
|
|
} else {
|
|
if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
|
|
AsconError(a, "DynStringConcatChar failed:", ENOMEM);
|
|
break;
|
|
}
|
|
}
|
|
} else if (ret == 0) {
|
|
if (a->timeout > 0) {
|
|
if (DoubleTime() - a->start > a->timeout) {
|
|
AsconError(a, "read timeout", 0);
|
|
a->state = AsconTimeout;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
break;
|
|
default:
|
|
return AsconStdHandler(a);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
void AddJulChoProtocoll()
|
|
{
|
|
AsconProtocol *prot = NULL;
|
|
|
|
prot = calloc(sizeof(AsconProtocol), 1);
|
|
prot->name = strdup("julcho");
|
|
prot->init = AsconStdInit;
|
|
prot->handler = JulchoHandler;
|
|
AsconInsertProtocol(prot);
|
|
}
|