Make MultiChan a SICS object (command)

r1504 | dcl | 2007-02-19 12:23:27 +1100 (Mon, 19 Feb 2007) | 2 lines
This commit is contained in:
Douglas Clowes
2007-02-19 12:23:27 +11:00
parent 5ac29e785b
commit b95298e92c
2 changed files with 250 additions and 84 deletions

View File

@@ -38,6 +38,9 @@ struct __MultiChan {
};
struct __MultiChanController {
pObjectDescriptor pDes;
char* pHost;
int iPort;
int unit_count; /* number of units connected */
pMultiChan units; /* head of unit chain */
prs232 controller; /* associated RS232 controller object */
@@ -48,9 +51,9 @@ struct __MultiChanController {
};
static pMultiChanController mcc_array[FD_SETSIZE];
static mcc_index = 0;
static int mcc_index = 0;
static int MC_Notify(pMultiChanController self, int event)
static void MC_Notify(pMultiChanController self, int event)
{
pMultiChan unit;
for (unit = self->units; unit; unit = unit->next)
@@ -85,14 +88,35 @@ static int CommandTimeout(void* cntx, int mode);
static int StartCommand(pMultiChanController self)
{
pMC_Cmd myCmd = self->command_head;
mkChannel* sock = self->controller->pSock;
/*
* Remove any old command timeout timer
*/
if (self->nw_tmr)
NetWatchRemoveTimer(self->nw_tmr);
/*
* Discard any input before sending command
*/
while (NETAvailable(sock, 0)) {
char reply[1];
int iRet;
iRet = NETRead(sock, reply, 1, 0);
if (iRet < 0) { /* TODO: EOF */
iRet = MC_Reconnect(self);
if (iRet == 0)
return 0;
}
}
/*
* Add a new command timeout timer
*/
if (myCmd->unit->timeout > 0)
NetWatchRegisterTimer(&self->nw_tmr, myCmd->unit->timeout * 1000,
NetWatchRegisterTimer(&self->nw_tmr, myCmd->unit->timeout,
CommandTimeout, self);
else
NetWatchRegisterTimer(&self->nw_tmr, 1000000,
NetWatchRegisterTimer(&self->nw_tmr, 1000,
CommandTimeout, self);
return myCmd->tx(myCmd->cntx);
}
@@ -102,6 +126,7 @@ static int CommandTimeout(void* cntx, int mode)
pMultiChanController self = (pMultiChanController) cntx;
self->nw_tmr = 0;
StartCommand(self);
return 1;
}
static int QueCommand(pMultiChanController self, pMC_Cmd cmd)
@@ -116,6 +141,7 @@ static int QueCommand(pMultiChanController self, pMC_Cmd cmd)
self->command_tail->next = cmd;
self->command_tail = cmd;
}
return 1;
}
static int PopCommand(pMultiChanController self)
@@ -135,6 +161,7 @@ static int PopCommand(pMultiChanController self)
else
self->command_head = self->command_tail = NULL;
free(myCmd);
return 1;
}
static int MyCallback(void* context, int mode)
@@ -170,84 +197,11 @@ static int MyCallback(void* context, int mode)
return 1;
}
int MultiChanCreate(const char* name, pMultiChan* handle)
{
int i;
prs232 ctlr = NULL;
pMultiChanController self = NULL;
pMultiChan unit = NULL;
*handle = NULL;
ctlr = (prs232)FindCommandData(pServ->pSics, name, "RS232 Controller");
if(ctlr == NULL || ctlr->pSock == NULL) {
return 0;
}
for (i = 0; i < mcc_index; ++i)
if (mcc_array[i]->controller == ctlr) {
self = mcc_array[i];
break;
}
if (self == NULL) {
self = (pMultiChanController) malloc(sizeof(MultiChanController));
/* TODO check malloc */
if (self == NULL)
return 0;
memset(self, 0, sizeof(MultiChanController));
mcc_array[mcc_index++] = self;
self->controller = ctlr;
NetWatchRegisterCallback(&self->nw_ctx,
self->controller->pSock->sockid,
MyCallback,
self);
}
++self->unit_count;
unit = (pMultiChan) malloc(sizeof(MultiChan));
/* TODO: check malloc failure */
memset(unit, 0, sizeof(MultiChan));
unit->mcc = self;
unit->next = self->units;
self->units = unit;
*handle = unit;
return 1;
}
int MultiChanDestroy(pMultiChan chan)
{
assert(chan);
assert(chan->mcc);
pMultiChanController self = chan->mcc;
pMultiChan* pNxt = &self->units;
while (*pNxt) {
if (*pNxt == chan) {
*pNxt = (*pNxt)->next;
break;
}
pNxt = &(*pNxt)->next;
}
--self->unit_count;
if (self->unit_count <= 0) {
int i;
for (i = 0; i < mcc_index; ++i)
if (mcc_array[i] == self) {
--mcc_index;
if (mcc_index > 0)
mcc_array[i] = mcc_array[mcc_index];
if (self->nw_ctx)
NetWatchRemoveCallback(self->nw_ctx);
if (self->nw_tmr)
NetWatchRemoveTimer(self->nw_tmr);
free(self);
}
}
free(chan);
return 1;
}
int MultiChanReconnect(pMultiChan unit)
{
int iRet;
assert(unit);
assert(unit->mcc);
iRet = MC_Reconnect(unit->mcc);
/* TODO: handle in-progress */
return iRet;
@@ -273,3 +227,209 @@ int MultiChanEnque(pMultiChan unit, void* context, MCC_Transmit tx, MCC_Receive
myCmd->unit = unit;
return QueCommand(unit->mcc, myCmd);
}
int MultiChanWrite(pMultiChan unit, void* buffer, int buflen)
{
int iRet;
mkChannel* sock;
assert(unit);
assert(unit->mcc);
sock = MultiChanGetSocket(unit);
iRet = NETWrite(sock, buffer, buflen);
/* TODO handle errors */
if (iRet < 0) { /* TODO: EOF */
iRet = MC_Reconnect(unit->mcc);
if (iRet == 0)
return 0;
}
return 1;
}
void MultiChanSetNotify(pMultiChan unit, void* context, MCC_Notify notify)
{
assert(unit);
unit->notify_func = notify;
unit->notify_cntx = context;
}
int MultiChanGetTimeout(pMultiChan unit)
{
assert(unit);
return unit->timeout;
}
int MultiChanSetTimeout(pMultiChan unit, int timeout)
{
int old_timeout;
assert(unit);
old_timeout = unit->timeout;
unit->timeout = timeout;
return old_timeout;
}
static int MC_Action(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[])
{
pMultiChanController self = (pMultiChanController) pData;
/* TODO: handle private stuff */
return RS232Action(pCon, pSics, self->controller, argc, argv);
}
static pMultiChanController MC_Create(const char* host, int port)
{
int i;
pMultiChanController self = NULL;
prs232 ctlr = NULL;
/* try to find the MCC with this name */
self = (pMultiChanController)FindCommandData(pServ->pSics, host, "MultiChan");
if (self == NULL) {
ctlr = (prs232)FindCommandData(pServ->pSics, host, "RS232 Controller");
if(ctlr == NULL || ctlr->pSock == NULL) {
return NULL;
}
for (i = 0; i < mcc_index; ++i)
if (mcc_array[i]->controller == ctlr) {
self = mcc_array[i];
break;
}
if (self == NULL) {
self = (pMultiChanController) malloc(sizeof(MultiChanController));
if (self == NULL)
return NULL;
memset(self, 0, sizeof(MultiChanController));
self->controller = ctlr;
self->pDes = CreateDescriptor("MultiChan");
mcc_array[mcc_index++] = self;
}
} else {
for (i = 0; i < mcc_index; ++i)
if (mcc_array[i] == self) {
break;
}
if (i == mcc_index)
mcc_array[mcc_index++] = self;
}
return self;
}
static int MC_Init(pMultiChanController self)
{
/* TODO: Init the controller */
if (self->nw_ctx == NULL)
NetWatchRegisterCallback(&self->nw_ctx,
self->controller->pSock->sockid,
MyCallback,
self);
return 1;
}
static void MC_Kill(pMultiChanController self)
{
int i;
for (i = 0; i < mcc_index; ++i)
if (mcc_array[i] == self) {
--mcc_index;
if (mcc_index > 0)
mcc_array[i] = mcc_array[mcc_index];
if (self->nw_ctx)
NetWatchRemoveCallback(self->nw_ctx);
if (self->nw_tmr)
NetWatchRemoveTimer(self->nw_tmr);
free(self);
return;
}
}
int MultiChanFactory(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[])
{
pMultiChanController pNew = NULL;
int iRet, status;
char pError[256];
if(argc < 4)
{
SCWrite(pCon,"ERROR: insufficient no of arguments to MultiChanFactory",
eError);
return 0;
}
/*
create data structure and open port
*/
pNew = MC_Create(argv[2], atoi(argv[3]));
if(!pNew)
{
SCWrite(pCon,"ERROR: failed to create MultiChan in MultiChanFactory",eError);
return 0;
}
status = MC_Init(pNew);
if(status != 1)
{
sprintf(pError,"ERROR: failed to connect to %s at port %d",
pNew->pHost, pNew->iPort);
SCWrite(pCon,pError,eError);
}
/*
create the command
*/
iRet = AddCommand(pSics, argv[1], MC_Action, MC_Kill, pNew);
if(!iRet)
{
sprintf(pError,"ERROR: duplicate command %s not created", argv[1]);
SCWrite(pCon,pError,eError);
MC_Kill(pNew);
return 0;
}
return 1;
}
int MultiChanCreate(const char* name, pMultiChan* handle)
{
int status;
pMultiChanController self = NULL;
pMultiChan unit = NULL;
*handle = NULL;
self = MC_Create(name, 0);
if (self == NULL)
return 0;
status = MC_Init(self);
unit = (pMultiChan) malloc(sizeof(MultiChan));
/* TODO: check malloc failure */
memset(unit, 0, sizeof(MultiChan));
++self->unit_count;
unit->mcc = self;
unit->next = self->units;
self->units = unit;
*handle = unit;
return 1;
}
int MultiChanDestroy(pMultiChan chan)
{
assert(chan);
assert(chan->mcc);
pMultiChanController self = chan->mcc;
pMultiChan* pNxt = &self->units;
while (*pNxt) {
if (*pNxt == chan) {
*pNxt = (*pNxt)->next;
break;
}
pNxt = &(*pNxt)->next;
}
--self->unit_count;
if (self->unit_count <= 0) {
MC_Kill(self);
}
free(chan);
return 1;
}