797 lines
20 KiB
C
797 lines
20 KiB
C
/*--------------------------------------------------------------------------
|
|
S P S
|
|
|
|
Implementation file for the SICS module handling Siemens SPS controllers
|
|
at SinQ.
|
|
|
|
copyright: see copyright.h
|
|
I cannot imagine that somebody wants this. It is highly special for SINQ.
|
|
It handles a protocoll tailor made by Siemens for Sinq. I cannot imagine
|
|
that somebody wants something from Siemens anyway.
|
|
|
|
|
|
Mark Koennnecke, Juli 1998
|
|
|
|
Feature added: bipa command, Mark Koennecke, May 2009
|
|
|
|
Reworked to use rs232controller rather then the older serialport code
|
|
|
|
Mark Koennecke, November 2009
|
|
|
|
---------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <tcl.h>
|
|
#include "sics.h"
|
|
#include "rs232controller.h"
|
|
#include "sics.h"
|
|
#include "lld.h"
|
|
#include "bit.h"
|
|
#include "sps.i"
|
|
#include "sps.h"
|
|
|
|
/*--------------------- some internal defines ----------------------------*/
|
|
#define SPSOFFLINE -10
|
|
#define COMMDEAD -11
|
|
#define COMMRECONNECT -12
|
|
#define COMMTMO -13
|
|
/*-------------------------------------------------------------------------*/
|
|
static float SimRandom(void)
|
|
{
|
|
float fVal;
|
|
|
|
fVal = ((float) rand() / (float) RAND_MAX) * 100.0;
|
|
return fVal;
|
|
}
|
|
|
|
/*--------------------- static functions ---------------------------------*/
|
|
static int init(pSPS self)
|
|
{
|
|
int iRet;
|
|
|
|
assert(self);
|
|
assert(self->pHost);
|
|
prs232 rs232;
|
|
|
|
/* check if in simulation mode */
|
|
if (self->iMode)
|
|
return 1;
|
|
|
|
rs232 = createRS232(self->pHost,self->iPort);
|
|
self->pData = rs232;
|
|
iRet = initRS232(rs232);
|
|
if(iRet != 1){
|
|
self->iLastError = COMMDEAD;
|
|
return 0;
|
|
}
|
|
setRS232SendTerminator(rs232,"\r\n");
|
|
setRS232ReplyTerminator(rs232,"\n");
|
|
setRS232Timeout(rs232,20000);
|
|
/* setRS232Debug(rs232,1); */
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static int SPSCommand(pSPS self, char *pCommand, char *pReply,
|
|
int iReplyLen)
|
|
{
|
|
int iRet, i;
|
|
char pError[132];
|
|
prs232 rs232;
|
|
|
|
assert(self);
|
|
assert(pCommand);
|
|
assert(pReply);
|
|
|
|
rs232 = (prs232)self->pData;
|
|
/*
|
|
try at least three times to get the command through before
|
|
giving up
|
|
*/
|
|
for (i = 0; i < 3; i++) {
|
|
if(availableRS232(rs232)){
|
|
memset(pReply,0, iReplyLen);
|
|
iRet = iReplyLen;
|
|
readRS232(rs232, pReply, &iRet);
|
|
/* printf("Dirt on the SPS cable: %d bytes, text = %s\n", iRet, pReply); */
|
|
}
|
|
iRet = transactRS232(rs232, pCommand,strlen(pCommand), pReply, iReplyLen);
|
|
if (iRet < 0) {
|
|
switch (iRet) {
|
|
case TIMEOUT:
|
|
self->iLastError = COMMTMO;
|
|
continue;
|
|
break;
|
|
default:
|
|
self->iLastError = iRet;
|
|
getRS232Error(iRet,pError,131);
|
|
Log(ERROR,"dev", "SPS-TROUBLE: %s", pError);
|
|
closeRS232(rs232);
|
|
iRet = initRS232(rs232);
|
|
if (iRet == 0) {
|
|
return 0;
|
|
}
|
|
continue;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SPSSetButton(pSPS self, SConnection * pCon, int iByte, int iBit)
|
|
{
|
|
Permission perm;
|
|
char pCommand[30];
|
|
char pBueffel[256];
|
|
int iRet, iTest, i;
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
|
|
/* first check permissions */
|
|
iRet = LLDnodePtr2First(self->lPermissions);
|
|
iTest = 0;
|
|
while (iRet != 0) {
|
|
LLDnodeDataTo(self->lPermissions, &perm);
|
|
if (perm.iByte == iByte) {
|
|
if (perm.iBit == iBit) {
|
|
iTest = SCMatchRights(pCon, perm.iPrivilege);
|
|
break;
|
|
}
|
|
}
|
|
iRet = LLDnodePtr2Next(self->lPermissions);
|
|
}
|
|
if (!iTest) {
|
|
sprintf(pBueffel, "ERROR: you have no permission to flip %d.%d",
|
|
iByte, iBit);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
/* if in sim mode, return true */
|
|
if (self->iMode) {
|
|
return 1;
|
|
}
|
|
|
|
/* format command and send a command to set a bit through the
|
|
drain in order to simulate a button press
|
|
*/
|
|
sprintf(pCommand, "S%3.3d%1.1d", iByte, iBit);
|
|
iRet = SPSCommand(self, pCommand, pBueffel, 255);
|
|
if (!iRet) {
|
|
SCWrite(pCon, pBueffel, eError);
|
|
SCWrite(pCon, "ERROR: Sending flip command failed", eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SPSGetStatus(pSPS self, int iStatus, int *iSet)
|
|
{
|
|
int iRet, i, i2, iVal;
|
|
unsigned char pByte[16];
|
|
char pBueffel[256], pNum[10];
|
|
char *pPtr;
|
|
unsigned char cBit, cMask;
|
|
|
|
assert(self);
|
|
|
|
if ((iStatus < 0) || (iStatus >= 128)) {
|
|
return -1;
|
|
}
|
|
|
|
/* if in simulation mode, return 1 */
|
|
if (self->iMode) {
|
|
*iSet = 1;
|
|
return 1;
|
|
}
|
|
|
|
/* send an R command down to the SPS */
|
|
iRet = SPSCommand(self, "R", pBueffel, 255);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
|
|
/* decode the reply into the Byte array */
|
|
pPtr = strchr(pBueffel, 'R');
|
|
if (pPtr == NULL) {
|
|
return -2;
|
|
}
|
|
pPtr++;
|
|
for (i = 0; i < 16; i++) {
|
|
/* skip the whitespace */
|
|
pPtr++;
|
|
pNum[0] = *pPtr;
|
|
pPtr++;
|
|
pNum[1] = *pPtr;
|
|
pPtr++;
|
|
pNum[2] = *pPtr;
|
|
pPtr++;
|
|
pNum[3] = '\0';
|
|
pByte[i] = atoi(pNum);
|
|
}
|
|
|
|
/* test the bit */
|
|
i = iStatus / 8;
|
|
cBit = pByte[i];
|
|
i2 = iStatus % 8;
|
|
cMask = 1 << i2;
|
|
|
|
/*
|
|
printf("Byte %d, Value %d, Bit %d, Value: %d\n", i,cBit, i2, (cBit & cMask));
|
|
*/
|
|
|
|
if ((cBit & cMask) > 0) {
|
|
*iSet = 1;
|
|
} else {
|
|
*iSet = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static void byteToString(unsigned char byte, char txt[9])
|
|
{
|
|
int i;
|
|
for(i = 0; i < 8; i++){
|
|
if(byte & (1 << i) ){
|
|
txt[i] = '1';
|
|
} else {
|
|
txt[i] = '0';
|
|
}
|
|
}
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int SPSBitPattern(pSPS self, SConnection *pCon)
|
|
{
|
|
int iRet, i;
|
|
char pBueffel[256], *pPtr = NULL, pNum[10], pText[9];
|
|
unsigned char byte;
|
|
pDynString result = NULL;
|
|
|
|
if(self->iMode){
|
|
SCWrite(pCon,"00000 0001000 00001000 00010000", eValue);
|
|
return 1;
|
|
}
|
|
/* send an R command down to the SPS */
|
|
iRet = SPSCommand(self, "R", pBueffel, 255);
|
|
if (!iRet) {
|
|
SCWrite(pCon,"ERROR: communication error in SPSBitPattern",
|
|
eError);
|
|
return 0;
|
|
}
|
|
result = CreateDynString(128,128);
|
|
if(result == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in SPSBitpattern", eError);
|
|
return 0;
|
|
}
|
|
|
|
/* decode the reply into the Byte array */
|
|
pPtr = strchr(pBueffel, 'R');
|
|
if (pPtr == NULL) {
|
|
return -2;
|
|
}
|
|
pPtr++;
|
|
for (i = 0; i < 16; i++) {
|
|
/* skip the whitespace */
|
|
pPtr++;
|
|
pNum[0] = *pPtr;
|
|
pPtr++;
|
|
pNum[1] = *pPtr;
|
|
pPtr++;
|
|
pNum[2] = *pPtr;
|
|
pPtr++;
|
|
pNum[3] = '\0';
|
|
byte = atoi(pNum);
|
|
memset(pText,0,9*sizeof(char));
|
|
byteToString(byte, pText);
|
|
DynStringConcat(result, pText);
|
|
if(((i+1) % 4) == 0){
|
|
DynStringConcatChar(result,'\n');
|
|
} else {
|
|
DynStringConcatChar(result,' ');
|
|
}
|
|
}
|
|
SCWrite(pCon,GetCharArray(result), eValue);
|
|
DeleteDynString(result);
|
|
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------
|
|
This is a special feature for SANS at SINQ. SANS has a collimator and
|
|
the length of the collimator can only be deduced from the SPS status
|
|
message by checking each of nine segments separately. For efficiency
|
|
this is coded into a special function for SANS. This also needs a special
|
|
function for testing bits.
|
|
|
|
Mark Koennecke, April 1999
|
|
*/
|
|
static int TestBit(unsigned char cByte, int iBit)
|
|
{
|
|
unsigned char cMask;
|
|
|
|
assert(iBit >= 0);
|
|
assert(iBit < 8);
|
|
|
|
cMask = 1 << iBit;
|
|
if ((cMask & cByte) > 0) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int SPSGetSANS(pSPS self, float *fLength)
|
|
{
|
|
int iRet, i, i2, iVal;
|
|
unsigned char pByte[16];
|
|
char pBueffel[256], pNum[10];
|
|
char *pPtr;
|
|
unsigned char cBit, cMask;
|
|
float fLang;
|
|
|
|
assert(self);
|
|
|
|
/* if in simulation mode, return a random number */
|
|
if (self->iMode) {
|
|
*fLength = SimRandom();
|
|
return 1;
|
|
}
|
|
|
|
/* send an R command down to the SPS */
|
|
iRet = SPSCommand(self, "R", pBueffel, 255);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
|
|
/* decode the reply into the Byte array */
|
|
pPtr = strchr(pBueffel, 'R');
|
|
if (pPtr == NULL) {
|
|
return -2;
|
|
}
|
|
pPtr++;
|
|
for (i = 0; i < 16; i++) {
|
|
/* skip the whitespace */
|
|
pPtr++;
|
|
pNum[0] = *pPtr;
|
|
pPtr++;
|
|
pNum[1] = *pPtr;
|
|
pPtr++;
|
|
pNum[2] = *pPtr;
|
|
pPtr++;
|
|
pNum[3] = '\0';
|
|
pByte[i] = atoi(pNum);
|
|
}
|
|
|
|
fLang = 189.;
|
|
if (TestBit(pByte[0], 1) > 0) {
|
|
fLang = 18.;
|
|
}
|
|
/* coll 1 15m */
|
|
if (TestBit(pByte[0], 3) > 0) {
|
|
fLang = 15.;
|
|
}
|
|
/* coll 2 11 m */
|
|
if (TestBit(pByte[0], 7) > 0) {
|
|
fLang = 11.;
|
|
}
|
|
/* coll 3 8 m */
|
|
if (TestBit(pByte[1], 3) > 0) {
|
|
fLang -= 3.;
|
|
}
|
|
/* coll 4 6m */
|
|
if (TestBit(pByte[1], 7) > 0) {
|
|
fLang -= 2.;
|
|
}
|
|
/* coll 5 4.5 m */
|
|
if (TestBit(pByte[2], 3) > 0) {
|
|
fLang -= 1.5;
|
|
}
|
|
/* coll 6 3 m */
|
|
if (TestBit(pByte[2], 7) > 0) {
|
|
fLang -= 1.5;
|
|
}
|
|
/* coll 7 */
|
|
if (TestBit(pByte[3], 3) > 0) {
|
|
fLang -= 1.;
|
|
}
|
|
/* coll 8 */
|
|
if (TestBit(pByte[3], 6) > 0) {
|
|
fLang -= 1.;
|
|
}
|
|
if (TestBit(pByte[3], 7) > 0) {
|
|
fLang -= 0.6;
|
|
}
|
|
*fLength = fLang;
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SPSGetADC(pSPS self, int iWhich, int *iValue)
|
|
{
|
|
int iADC[8];
|
|
int i, iRet;
|
|
char *pPtr, pBueffel[256], pNum[10];
|
|
|
|
assert(self);
|
|
|
|
/* check iWhich */
|
|
if ((iWhich < 0) || (iWhich > 7)) {
|
|
return 0;
|
|
}
|
|
|
|
/* give a random number in simulation mode */
|
|
if (self->iMode) {
|
|
*iValue = (int) SimRandom();
|
|
return 1;
|
|
}
|
|
|
|
/* send an A command to the box */
|
|
iRet = SPSCommand(self, "A", pBueffel, 255);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
|
|
/* decode the result */
|
|
pPtr = strchr(pBueffel, 'A');
|
|
if (pPtr == NULL) { /* a silly answer was returned */
|
|
Log(ERROR,"dev","%s:%s", "SPS: Silly answer in SPSGetADC",pBueffel);
|
|
return 0;
|
|
}
|
|
pPtr++;
|
|
for (i = 0; i < 8; i++) {
|
|
pPtr++; /* skip whitespace */
|
|
strncpy(pNum, pPtr, 5); /* strlcpy probably wrong here */
|
|
pNum[5] = '\0';
|
|
pPtr += 5;
|
|
iADC[i] = atoi(pNum);
|
|
}
|
|
|
|
/* now give the value */
|
|
*iValue = iADC[iWhich];
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void SPSAddPermission(pSPS self, int iByte, int iBit, int iRights)
|
|
{
|
|
Permission perm;
|
|
|
|
assert(self);
|
|
|
|
perm.iByte = iByte;
|
|
perm.iBit = iBit;
|
|
perm.iPrivilege = iRights;
|
|
|
|
LLDnodeAppendFrom(self->lPermissions, &perm);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
void RemoveSPS(void *pData)
|
|
{
|
|
pSPS self = NULL;
|
|
prs232 rs232 = NULL;
|
|
|
|
|
|
self = (pSPS) pData;
|
|
|
|
if (!self)
|
|
return;
|
|
|
|
rs232 = (prs232)self->pData;
|
|
if (self->pHost) {
|
|
free(self->pHost);
|
|
}
|
|
|
|
if(rs232 != NULL){
|
|
closeRS232(rs232);
|
|
KillRS232(rs232);
|
|
}
|
|
|
|
if (self->pDes) {
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
LLDdelete(self->lPermissions);
|
|
free(self);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int SPSFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
int iRet, iVal;
|
|
pSPS pNew = NULL;
|
|
char pBueffel[256];
|
|
|
|
assert(pCon);
|
|
assert(pSics);
|
|
|
|
/* we need at least two extra arguments: name and either host or sim */
|
|
if (argc < 3) {
|
|
SCWrite(pCon,
|
|
"ERROR: Insufficient number of arguments for installing SPS",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* allocate a new SPS */
|
|
pNew = (pSPS) malloc(sizeof(SPS));
|
|
if (!pNew) {
|
|
SCWrite(pCon, "ERROR: no memory to allocate SPS", eError);
|
|
return 0;
|
|
}
|
|
memset(pNew, 0, sizeof(SPS));
|
|
pNew->pDes = CreateDescriptor("SPS");
|
|
pNew->lPermissions = LLDcreate(sizeof(Permission));
|
|
if ((!pNew->pDes) || (pNew->lPermissions < 0)) {
|
|
SCWrite(pCon, "ERROR: no memory to allocate SPS", eError);
|
|
return 0;
|
|
}
|
|
pNew->pHost = strdup(argv[2]);
|
|
|
|
/* check if we go for sim */
|
|
strtolower(argv[2]);
|
|
if (strcmp(argv[2], "sim") == 0) {
|
|
pNew->iMode = 1;
|
|
} else { /* we are installing a real one and need tons more arguments */
|
|
|
|
if (argc < 5) {
|
|
SCWrite(pCon,
|
|
"ERROR: Insufficient number of arguments for installing SPS",
|
|
eError);
|
|
RemoveSPS(pNew);
|
|
return 0;
|
|
}
|
|
/* get port number */
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[3], &iVal);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,255,
|
|
"ERROR: expected integer argument for port, got %s",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
RemoveSPS(pNew);
|
|
return 0;
|
|
}
|
|
pNew->iPort = iVal;
|
|
|
|
/* get channel number */
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[4], &iVal);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,255,
|
|
"ERROR: expected integer argument for channel, got %s",
|
|
argv[4]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
RemoveSPS(pNew);
|
|
return 0;
|
|
}
|
|
pNew->iChannel = iVal;
|
|
}
|
|
|
|
/* initialise */
|
|
iRet = init(pNew);
|
|
if (!iRet) {
|
|
SCWrite(pCon, "ERROR: Failure to initialise SPS controller", eError);
|
|
RemoveSPS(pNew);
|
|
return 0;
|
|
}
|
|
|
|
/* install command */
|
|
iRet = AddCommand(pSics, argv[1], SPSAction, RemoveSPS, pNew);
|
|
if (!iRet) {
|
|
snprintf(pBueffel,255, "ERROR: duplicate SPS command %s NOT created",
|
|
argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
RemoveSPS(pNew);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int SPSAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pSPS self = NULL;
|
|
char pBueffel[256];
|
|
int iByte, iBit, iSet;
|
|
int iRet, i;
|
|
float fLang;
|
|
|
|
self = (pSPS) pData;
|
|
assert(self);
|
|
|
|
/* we need at least 3 arguments */
|
|
if (argc < 2) {
|
|
snprintf(pBueffel,255, "ERROR: need at least two arguments to %s", argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
/* do something according to key word */
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "push") == 0) { /* operate a button */
|
|
/* four arguments needed */
|
|
if (argc < 4) {
|
|
snprintf(pBueffel,255, "ERROR: need at least two arguments to %s push",
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
/* convert arguments */
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iByte);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,255,
|
|
"ERROR: expected integer argument for byte, got %s",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[3], &iBit);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,255, "ERROR: expected integer argument for bit, got %s",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
/* try it */
|
|
iRet = SPSSetButton(self, pCon, iByte, iBit);
|
|
if (!iRet) {
|
|
SCWrite(pCon, "ERROR: Pushing button failed", eError);
|
|
return 0;
|
|
} else {
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "status") == 0) { /* status bits */
|
|
/* which bit ? */
|
|
if (argc < 3) {
|
|
snprintf(pBueffel,255, "ERROR: need at least two arguments to %s push",
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iByte);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: expected integer argument for bit, got %s",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = SPSGetStatus(self, iByte, &iSet);
|
|
if (iRet <= 0) {
|
|
snprintf(pBueffel,255, "ERROR: failed to read status bit %d", iByte);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
sprintf(pBueffel, "%s.status.%3.3d = %d", argv[0], iByte, iSet);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "stat2") == 0) { /* status bits */
|
|
if (argc < 4) {
|
|
snprintf(pBueffel,255, "ERROR: need at least two arguments to %s stat2",
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
/* which bit ? */
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iByte);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,255, "ERROR: expected integer argument for bit, got %s",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[3], &iBit);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: expected integer argument for bit, got %s",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
if ((iByte <= 0) || (iBit < 0) || (iBit > 7)) {
|
|
SCWrite(pCon, "ERROR: arguments out of range for stat2", eError);
|
|
return 0;
|
|
}
|
|
iRet = SPSGetStatus(self, ((iByte - 1) * 8 + iBit), &iSet);
|
|
if (iRet <= 0) {
|
|
sprintf(pBueffel, "ERROR: failed to read status bit %d", iByte);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
sprintf(pBueffel, "%s.status.%3.3d.%1.1d = %d", argv[0], iByte, iBit,
|
|
iSet);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "adc") == 0) { /* ADC values */
|
|
/* which ADC ? */
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iByte);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,255, "ERROR: expected integer argument for ADC, got %s",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = SPSGetADC(self, iByte, &iSet);
|
|
if (!iRet) {
|
|
sprintf(pBueffel, "ERROR: failed to read ADC %d", iByte);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
sprintf(pBueffel, "%s.ADC.%1.1d = %d", argv[0], iByte, iSet);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "perm") == 0) {
|
|
/* only managers may set permissions */
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
SCWrite(pCon,
|
|
"ERROR: Security: Only mangagers may configure SPS buttons",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* we need lots of parameters */
|
|
if (argc < 5) {
|
|
snprintf(pBueffel,255, "ERROR: need at least three arguments to %s perm",
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
/* convert arguments */
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iByte);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,255,
|
|
"ERROR: expected integer argument for byte, got %s",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[3], &iBit);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,255, "ERROR: expected integer argument for bit, got %s",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
/* try to convert user code */
|
|
strtolower(argv[4]);
|
|
iSet = 0;
|
|
iSet = decodeSICSPriv(argv[4]);
|
|
if (iSet < 0) {
|
|
sprintf(pBueffel, "ERROR: %s is not valid user code", argv[4]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
/* do it, finally */
|
|
SPSAddPermission(self, iByte, iBit, iSet);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/* -------- sans collimator */
|
|
else if (strcmp(argv[1], "colli") == 0) {
|
|
iRet = SPSGetSANS(self, &fLang);
|
|
if (!iRet) {
|
|
SCWrite(pCon, "ERROR: cannot read SANS collimator", eError);
|
|
return 0;
|
|
} else {
|
|
sprintf(pBueffel, "SANS.collimator = %f", fLang);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
}
|
|
/* -------- bit pattern*/
|
|
else if (strcmp(argv[1], "bipa") == 0) {
|
|
return SPSBitPattern(self,pCon);
|
|
}
|
|
sprintf(pBueffel, "ERROR: %s does not not understand subcommand %s",
|
|
argv[0], argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|