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:
318
multichan.c
318
multichan.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user