438 lines
11 KiB
C++
438 lines
11 KiB
C++
// Cdev collection access from tcl
|
|
// Johannes van Zeijts
|
|
// March 97, first version
|
|
|
|
/*
|
|
cdevcollection $devices
|
|
cdevcollection $devices $attr
|
|
|
|
$c set attrib $value
|
|
|
|
$c get devices
|
|
$c get attrib
|
|
$c get
|
|
$c get vector $v // store in blt::vector $v
|
|
|
|
$c $message // send to cdev and return results
|
|
|
|
*/
|
|
|
|
#include <tcl.h>
|
|
#include "blt.h"
|
|
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <iostream.h>
|
|
#include <math.h>
|
|
//#include <dl.h>
|
|
|
|
// cdev includes
|
|
#include <cdevSystem.h>
|
|
#include <cdevRequestObject.h>
|
|
#include <cdevDevice.h>
|
|
#include <cdevGroup.h>
|
|
#include <cdevData.h>
|
|
|
|
static int VALUE_TAG_ID =- 1;
|
|
#define VALUE_TAG ((VALUE_TAG_ID<0 && cdevData::tagC2I("value", &VALUE_TAG_ID)!= CDEV_SUCCESS)?-1:VALUE_TAG_ID)
|
|
static int STATUS_TAG_ID =- 1;
|
|
#define STATUS_TAG ((STATUS_TAG_ID<0 && cdevData::tagC2I("status", &STATUS_TAG_ID)!= CDEV_SUCCESS)?-1:STATUS_TAG_ID)
|
|
static int SEVERITY_TAG_ID =- 1;
|
|
#define SEVERITY_TAG ((SEVERITY_TAG_ID<0 && cdevData::tagC2I("severity", &SEVERITY_TAG_ID)!= CDEV_SUCCESS)?-1:SEVERITY_TAG_ID)
|
|
|
|
typedef cdevRequestObject *cdevRequestObjectPtr;
|
|
|
|
// class DeviceEntry {
|
|
// public:
|
|
// DeviceEntry(char*);
|
|
// ~DeviceEntry();
|
|
//
|
|
// cdevRequestObject *request;
|
|
// cdevData result;
|
|
// int status;
|
|
// };
|
|
|
|
|
|
class TclCdevCollection {
|
|
public:
|
|
TclCdevCollection(int, char**);
|
|
~TclCdevCollection();
|
|
|
|
char *getAttrib();
|
|
void setAttrib(char*);
|
|
|
|
void getDevices(Tcl_Interp *);
|
|
void getStatus(Tcl_Interp *);
|
|
void getResult(Tcl_Interp *);
|
|
void getCallback(Tcl_Interp *);
|
|
int getLength() { return ndevices;}
|
|
void getVector(double*);
|
|
|
|
static void deleteCollection(ClientData);
|
|
|
|
int send();
|
|
int sendCallback(Tcl_Interp*, char*);
|
|
int checkCallback();
|
|
|
|
static void callbackFunction(int, void *, cdevRequestObject&, cdevData &);
|
|
static void TimerHandler(ClientData);
|
|
|
|
private:
|
|
cdevRequestObjectPtr *requests;
|
|
cdevData *results;
|
|
char **devices;
|
|
int ndevices;
|
|
char *attrib;
|
|
int *status, *callbacks;
|
|
};
|
|
|
|
TclCdevCollection::TclCdevCollection(int n, char** s) : ndevices(0), devices(NULL), attrib(NULL) {
|
|
if (n < 0) return;
|
|
|
|
ndevices = n;
|
|
devices = new char*[ndevices];
|
|
for (int i = 0; i<ndevices; i++) {
|
|
devices[i] = new char[strlen(s[i])+1];
|
|
strcpy(devices[i],s[i]);
|
|
}
|
|
requests = new cdevRequestObjectPtr[ndevices];
|
|
results = new cdevData[ndevices];
|
|
status = new int[ndevices];
|
|
callbacks = new int[ndevices];
|
|
}
|
|
|
|
TclCdevCollection::~TclCdevCollection() {
|
|
for (int i = 0; i<ndevices; i++) {
|
|
delete devices[i];
|
|
}
|
|
delete [] devices;
|
|
delete [] results;
|
|
delete callbacks;
|
|
delete status;
|
|
delete attrib;
|
|
delete requests;
|
|
}
|
|
|
|
class callbackInfo1 {
|
|
public:
|
|
callbackInfo1(TclCdevCollection*, int);
|
|
TclCdevCollection* ptr;
|
|
int index;
|
|
};
|
|
|
|
class callbackInfo2 {
|
|
public:
|
|
callbackInfo2(Tcl_Interp*, TclCdevCollection*, char*);
|
|
TclCdevCollection* ptr;
|
|
Tcl_Interp* interp;
|
|
char *s;
|
|
};
|
|
|
|
callbackInfo1::callbackInfo1(TclCdevCollection* c, int i) : ptr(c), index(i) {
|
|
}
|
|
|
|
callbackInfo2::callbackInfo2(Tcl_Interp* intp, TclCdevCollection* c, char* v) : interp(intp), ptr(c) {
|
|
s = new char[strlen(v)+1];
|
|
strcpy(s,v);
|
|
}
|
|
|
|
void TclCdevCollection::callbackFunction(int stat, void *userarg, cdevRequestObject&, cdevData &result) {
|
|
callbackInfo1 *info = (callbackInfo1 *) userarg;
|
|
TclCdevCollection *c = info->ptr;
|
|
c->status[info->index] = stat;
|
|
c->results[info->index] = result;
|
|
c->callbacks[info->index] = 1;
|
|
}
|
|
|
|
int TclCdevCollection::checkCallback() {
|
|
int stat = 0;
|
|
for (int i = 0; i < ndevices; i++) {
|
|
if (callbacks[i] == 0) return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void TclCdevCollection::TimerHandler(ClientData dummy) {
|
|
cdevSystem::defaultSystem().poll();
|
|
callbackInfo2 *info = (callbackInfo2 *) dummy;
|
|
if (info->ptr->checkCallback()) {
|
|
// set something
|
|
Tcl_SetVar2(info->interp, "Control", info->s, "1", TCL_GLOBAL_ONLY);
|
|
delete info;
|
|
} else { /// try again later
|
|
Tcl_CreateTimerHandler(50, TclCdevCollection::TimerHandler, dummy);
|
|
}
|
|
}
|
|
|
|
void TclCdevCollection::setAttrib(char* a) {
|
|
char message[256];
|
|
delete attrib;
|
|
attrib = new char[strlen(a)+1];
|
|
strcpy(attrib, a);
|
|
strcpy(message,"get ");
|
|
strcat(message, attrib);
|
|
for(int i = 0; i < ndevices; i++) {
|
|
requests[i] = cdevRequestObject::attachPtr(devices[i], message);
|
|
}
|
|
}
|
|
|
|
char* TclCdevCollection::getAttrib() {
|
|
return attrib;
|
|
}
|
|
|
|
void TclCdevCollection::getDevices(Tcl_Interp *interp) {
|
|
int i;
|
|
for (i = 0; i < ndevices; i++) {
|
|
Tcl_AppendElement(interp, devices[i]);
|
|
}
|
|
}
|
|
|
|
void TclCdevCollection::getStatus(Tcl_Interp *interp) {
|
|
int i;
|
|
char res[256];
|
|
for (i = 0; i < ndevices; i++) {
|
|
sprintf(res, "%d", status[i]);
|
|
Tcl_AppendElement(interp, res);
|
|
}
|
|
}
|
|
|
|
void TclCdevCollection::getCallback(Tcl_Interp *interp) {
|
|
int i;
|
|
char res[256];
|
|
for (i = 0; i < ndevices; i++) {
|
|
sprintf(res, "%d", callbacks[i]);
|
|
Tcl_AppendElement(interp, res);
|
|
}
|
|
}
|
|
|
|
void TclCdevCollection::getResult(Tcl_Interp *interp) {
|
|
int i;
|
|
char res[300];
|
|
for (i = 0; i < ndevices; i++) {
|
|
results[i].get(VALUE_TAG, res, 255);
|
|
Tcl_AppendElement(interp, res);
|
|
}
|
|
}
|
|
|
|
void TclCdevCollection::getVector(double *res) {
|
|
for (int i = 0; i < ndevices; i++) {
|
|
results[i].get(VALUE_TAG, &res[i]);
|
|
}
|
|
}
|
|
|
|
int TclCdevCollection::send() {
|
|
int stat = CDEV_SUCCESS;
|
|
int i;
|
|
for (i = 0; i < ndevices; i++) {
|
|
results[i].remove();
|
|
status[i] = requests[i]->send(NULL, results[i]);
|
|
if ((status[i] != CDEV_SUCCESS) && (stat == CDEV_SUCCESS)) {
|
|
stat = CDEV_ERROR;
|
|
}
|
|
}
|
|
return stat;
|
|
}
|
|
|
|
int TclCdevCollection::sendCallback(Tcl_Interp* interp, char* v) {
|
|
int stat = CDEV_SUCCESS;
|
|
for (int i = 0; i < ndevices; i++) {
|
|
results[i].remove();
|
|
callbacks[i] = 0;
|
|
callbackInfo1* info1 = new callbackInfo1(this, i);
|
|
cdevCallback* cb = new cdevCallback(TclCdevCollection::callbackFunction, (void *) info1);
|
|
status[i] = requests[i]->sendCallback(NULL, *cb);
|
|
if ((status[i] != CDEV_SUCCESS) && (stat == CDEV_SUCCESS)) {
|
|
stat = CDEV_ERROR;
|
|
}
|
|
}
|
|
callbackInfo2 *info2 = new callbackInfo2(interp, this, v);
|
|
Tcl_SetVar2(interp, "Control", v, "0", TCL_GLOBAL_ONLY);
|
|
Tcl_CreateTimerHandler(50, TclCdevCollection::TimerHandler, (ClientData) info2);
|
|
return stat;
|
|
}
|
|
|
|
void TclCdevCollection::deleteCollection(ClientData clientData) {
|
|
TclCdevCollection *collectionPtr;
|
|
collectionPtr = (TclCdevCollection *) clientData;
|
|
delete collectionPtr;
|
|
}
|
|
|
|
int CollectionCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){
|
|
TclCdevCollection *collectionPtr;
|
|
collectionPtr = (TclCdevCollection *) clientData;
|
|
|
|
if (strcmp(argv[1], "get") == 0) {
|
|
if (argc == 2) { // send it out to cdev // get
|
|
if (collectionPtr->getAttrib() == NULL) {
|
|
interp->result = "did not set attrib";
|
|
return TCL_ERROR;
|
|
}
|
|
if (collectionPtr->send() == CDEV_SUCCESS) {
|
|
collectionPtr->getResult(interp);
|
|
return TCL_OK;
|
|
}
|
|
interp->result = "encountered cdev error";
|
|
return TCL_ERROR;
|
|
}
|
|
if (strcmp(argv[2], "attrib") == 0) { // get attrib
|
|
Tcl_SetResult(interp, collectionPtr->getAttrib(), TCL_STATIC);
|
|
return TCL_OK;
|
|
}
|
|
if (strcmp(argv[2], "devices") == 0) { // get devices
|
|
collectionPtr->getDevices(interp);
|
|
return TCL_OK;
|
|
}
|
|
if (strcmp(argv[2], "status") == 0) { // get status
|
|
collectionPtr->getStatus(interp);
|
|
return TCL_OK;
|
|
}
|
|
if (strcmp(argv[2], "callback") == 0) { // get status
|
|
collectionPtr->getCallback(interp);
|
|
return TCL_OK;
|
|
}
|
|
if (strcmp(argv[2], "vector") == 0) { // get vector
|
|
if (argc != 4) return TCL_ERROR;
|
|
Blt_Vector vecInfo;
|
|
|
|
if (!Blt_VectorExists(interp, argv[3])) {
|
|
interp->result = "vector does not exist";
|
|
return TCL_ERROR;
|
|
}
|
|
if (collectionPtr->send() != CDEV_SUCCESS) {
|
|
interp->result = "encountered cdev error";
|
|
return TCL_ERROR;
|
|
}
|
|
if (vecInfo.arraySize < collectionPtr->getLength()) { // resize if necc.
|
|
if (Blt_ResizeVector(interp, argv[3], collectionPtr->getLength()) != TCL_OK) return TCL_ERROR;
|
|
}
|
|
|
|
if (Blt_GetVector(interp, argv[3], &vecInfo) != TCL_OK) return TCL_ERROR;
|
|
|
|
vecInfo.numValues = collectionPtr->getLength();
|
|
vecInfo.valueArr = (double *) malloc(sizeof(double) * collectionPtr->getLength());
|
|
|
|
collectionPtr->getVector(vecInfo.valueArr);
|
|
if (Blt_ResetVector(interp, argv[3], &vecInfo, TCL_DYNAMIC) != TCL_OK) {
|
|
return TCL_ERROR;
|
|
}
|
|
return TCL_OK;
|
|
}
|
|
}
|
|
|
|
if (strcmp(argv[1], "set") == 0) {
|
|
if (argc != 4) return TCL_ERROR;
|
|
if (strcmp(argv[2], "attrib") == 0) { // set attrib $value
|
|
collectionPtr->setAttrib(argv[3]);
|
|
return TCL_OK;
|
|
}
|
|
}
|
|
|
|
if (strcmp(argv[1], "sendcallback") == 0) {
|
|
if (strcmp(argv[2], "vector") == 0) { // sendcallback vector $v
|
|
if (argc != 4) return TCL_ERROR;
|
|
Blt_Vector vecInfo;
|
|
|
|
if (!Blt_VectorExists(interp, argv[3])) {
|
|
interp->result = "vector does not exist";
|
|
return TCL_ERROR;
|
|
}
|
|
if (collectionPtr->sendCallback(interp, argv[3]) != CDEV_SUCCESS) {
|
|
interp->result = "encountered cdev error";
|
|
return TCL_ERROR;
|
|
}
|
|
return TCL_OK;
|
|
}
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if (strcmp(argv[1], "checkcallback") == 0) {
|
|
if (collectionPtr->checkCallback()) {
|
|
interp->result = "1";
|
|
} else {
|
|
interp->result = "0";
|
|
}
|
|
return TCL_OK;
|
|
}
|
|
|
|
if (strcmp(argv[1], "getcallback") == 0) {
|
|
if (strcmp(argv[2], "vector") == 0) { // getcallback vector $v
|
|
if (argc != 4) return TCL_ERROR;
|
|
Blt_Vector vecInfo;
|
|
|
|
if (!Blt_VectorExists(interp, argv[3])) {
|
|
interp->result = "vector does not exist";
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if (!collectionPtr->checkCallback()) {
|
|
interp->result = "callbacks not ready";
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if (vecInfo.arraySize < collectionPtr->getLength()) { // resize if necc.
|
|
if (Blt_ResizeVector(interp, argv[3], collectionPtr->getLength()) != TCL_OK) return TCL_ERROR;
|
|
}
|
|
|
|
if (Blt_GetVector(interp, argv[3], &vecInfo) != TCL_OK) return TCL_ERROR;
|
|
|
|
vecInfo.numValues = collectionPtr->getLength();
|
|
vecInfo.valueArr = (double *) malloc(sizeof(double) * collectionPtr->getLength());
|
|
|
|
collectionPtr->getVector(vecInfo.valueArr);
|
|
if (Blt_ResetVector(interp, argv[3], &vecInfo, TCL_DYNAMIC) != TCL_OK) {
|
|
return TCL_ERROR;
|
|
}
|
|
return TCL_OK;
|
|
}
|
|
}
|
|
|
|
interp->result = "unknown command";
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
int MakeCollectionCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){
|
|
TclCdevCollection *collectionPtr;
|
|
static int id = 0;
|
|
int c1;
|
|
char** s1;
|
|
|
|
if (argc < 2 || argc >3) {
|
|
interp->result = "wrong # args";
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if(Tcl_SplitList(interp, argv[1], &c1, &s1) != TCL_OK) {
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
collectionPtr = new TclCdevCollection(c1,s1);
|
|
free ((char*) s1);
|
|
|
|
sprintf(interp->result, "col%d", id);
|
|
id++;
|
|
|
|
Tcl_CreateCommand(interp, interp->result, CollectionCmd, (ClientData) collectionPtr, TclCdevCollection::deleteCollection);
|
|
|
|
if (argc == 3) {
|
|
collectionPtr->setAttrib(argv[2]);
|
|
}
|
|
|
|
return TCL_OK;
|
|
}
|
|
|
|
|
|
extern "C" int Cdevcollection_Init(Tcl_Interp *interp) {
|
|
|
|
Tcl_PkgRequire(interp, "BLT", "2.4", 0);
|
|
Tcl_PkgRequire(interp, "Cdev", "", 0);
|
|
|
|
if(Tcl_PkgProvide(interp, "Cdevcollection", "1.0") != TCL_OK) {
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
Tcl_CreateCommand(interp, "cdevcollection", MakeCollectionCmd, (ClientData *) NULL, (Tcl_CmdDeleteProc *) NULL);
|
|
return TCL_OK;
|
|
}
|
|
|
|
|