diff --git a/asyn/Makefile b/asyn/Makefile index 889eff333..7f565c8bb 100644 --- a/asyn/Makefile +++ b/asyn/Makefile @@ -102,6 +102,7 @@ DBD += asyn.dbd INC += asynShellCommands.h INC += asynInterposeCom.h INC += asynInterposeEos.h +INC += asynInterposeTemplate.h INC += asynInterposeFlush.h ifneq ($(EPICS_LIBCOM_ONLY),YES) asyn_SRCS += asynShellCommands.c @@ -111,6 +112,7 @@ asyn_SRCS += asynInterposeEos.c asyn_SRCS += asynInterposeFlush.c asyn_SRCS += asynInterposeDelay.c asyn_SRCS += asynInterposeEcho.c +asyn_SRCS += asynInterposeTemplate.c SRC_DIRS += $(ASYN)/asynPortDriver/exceptions INC += ParamListInvalidIndex.h diff --git a/asyn/miscellaneous/asyn.dbd b/asyn/miscellaneous/asyn.dbd index ca23a6723..3678a73b1 100644 --- a/asyn/miscellaneous/asyn.dbd +++ b/asyn/miscellaneous/asyn.dbd @@ -3,6 +3,7 @@ registrar(asynInterposeFlushRegister) registrar(asynInterposeEosRegister) registrar(asynInterposeDelayRegister) registrar(asynInterposeEchoRegister) +registrar(asynInterposeTemplateRegister) # # The following ties this to EPICS records. diff --git a/asyn/miscellaneous/asynInterposeTemplate.c b/asyn/miscellaneous/asynInterposeTemplate.c new file mode 100644 index 000000000..422fca746 --- /dev/null +++ b/asyn/miscellaneous/asynInterposeTemplate.c @@ -0,0 +1,152 @@ +/*asynInterposeTemplate.c*/ + +/* + * Example of an asynInterpose implementation + * The template implementation does *nothing*, + * simply forwards requests to the lower port. + * + * Use this as as a base example to build your asynInterpose. + * + * Author: davide.marcato@lnl.infn.it + */ + +#include "asynInterposeTemplate.h" + +ASYN_API +int asynInterposeTemplateConfig(const char *portName) { + interposePvt *pvt; + asynInterface *plowerLevelInterface; + asynStatus status; + asynUser *pasynUser; + int addr = 0; + + // Populate private data + pvt = callocMustSucceed(1, sizeof(interposePvt), "asynInterposeTemplate"); + pvt->portName = epicsStrDup(portName); + pvt->templateInterface.interfaceType = asynOctetType; + pvt->templateInterface.pinterface = &octet; + pvt->templateInterface.drvPvt = pvt; + pasynUser = pasynManager->createAsynUser(0, 0); + pvt->pasynUser = pasynUser; + pvt->pasynUser->userPvt = pvt; + + // Connect + status = pasynManager->connectDevice(pasynUser, portName, addr); + if (status != asynSuccess) { + printf("%s connectDevice failed\n", portName); + pasynManager->freeAsynUser(pasynUser); + free(pvt); + return -1; + } + + // Add callback + status = pasynManager->exceptionCallbackAdd(pasynUser, ExceptionHandler); + if (status != asynSuccess) { + printf("%s exceptionCallbackAdd failed\n", portName); + pasynManager->freeAsynUser(pasynUser); + free(pvt); + return -1; + } + + // Interpose port + status = pasynManager->interposeInterface(portName, addr, &pvt->templateInterface, + &plowerLevelInterface); + if (status != asynSuccess) { + printf("%s interposeInterface failed\n", portName); + pasynManager->exceptionCallbackRemove(pasynUser); + pasynManager->freeAsynUser(pasynUser); + free(pvt); + return -1; + } + pvt->poctet = (asynOctet *)plowerLevelInterface->pinterface; + pvt->octetPvt = plowerLevelInterface->drvPvt; + + return (0); +} + +// Catch all exceptions +static void ExceptionHandler(asynUser *pasynUser, asynException exception) { + // On connections/disconnections + // Occurs every streamdevice transaction + if (exception == asynExceptionConnect) { + // Default = do nothing + } +} + +/** + * asynOctet methods + */ + +static asynStatus writeIt(void *ppvt, asynUser *pasynUser, const char *data, size_t numchars, + size_t *nbytesTransfered) { + interposePvt *pvt = (interposePvt *)ppvt; + + // Write on underlying port + return pvt->poctet->write(pvt->octetPvt, pasynUser, data, numchars, nbytesTransfered); +} + +static asynStatus readIt(void *ppvt, asynUser *pasynUser, char *data, size_t maxchars, + size_t *nbytesTransfered, int *eomReason) { + interposePvt *pvt = (interposePvt *)ppvt; + + // Read from underlying port + return pvt->poctet->read(pvt->octetPvt, pasynUser, data, maxchars, nbytesTransfered, eomReason); +} + +static asynStatus flushIt(void *ppvt, asynUser *pasynUser) { + interposePvt *pvt = (interposePvt *)ppvt; + return pvt->poctet->flush(pvt->octetPvt, pasynUser); +} + +static asynStatus registerInterruptUser(void *ppvt, asynUser *pasynUser, + interruptCallbackOctet callback, void *userPvt, + void **registrarPvt) { + interposePvt *pvt = (interposePvt *)ppvt; + return pvt->poctet->registerInterruptUser(pvt->octetPvt, pasynUser, callback, userPvt, + registrarPvt); +} + +static asynStatus cancelInterruptUser(void *ppvt, asynUser *pasynUser, void *registrarPvt) { + interposePvt *pvt = (interposePvt *)ppvt; + return pvt->poctet->cancelInterruptUser(pvt->octetPvt, pasynUser, registrarPvt); +} + +static asynStatus setInputEos(void *ppvt, asynUser *pasynUser, const char *eos, int eoslen) { + interposePvt *pvt = (interposePvt *)ppvt; + return pvt->poctet->setInputEos(pvt->octetPvt, pasynUser, eos, eoslen); +} + +static asynStatus getInputEos(void *ppvt, asynUser *pasynUser, char *eos, int eossize, + int *eoslen) { + interposePvt *pvt = (interposePvt *)ppvt; + return pvt->poctet->getInputEos(pvt->octetPvt, pasynUser, eos, eossize, eoslen); +} + +static asynStatus setOutputEos(void *ppvt, asynUser *pasynUser, const char *eos, int eoslen) { + interposePvt *pvt = (interposePvt *)ppvt; + return pvt->poctet->setOutputEos(pvt->octetPvt, pasynUser, eos, eoslen); +} + +static asynStatus getOutputEos(void *ppvt, asynUser *pasynUser, char *eos, int eossize, + int *eoslen) { + interposePvt *pvt = (interposePvt *)ppvt; + return pvt->poctet->getOutputEos(pvt->octetPvt, pasynUser, eos, eossize, eoslen); +} + +/* register asynInterposeTemplateConfig*/ +static const iocshArg asynInterposeTemplateConfigArg0 = {"portName", iocshArgString}; +static const iocshArg *asynInterposeTemplateConfigArgs[] = {&asynInterposeTemplateConfigArg0}; +static const iocshFuncDef asynInterposeTemplateConfigFuncDef = {"asynInterposeTemplateConfig", 1, + asynInterposeTemplateConfigArgs}; +static void asynInterposeTemplateConfigCallFunc(const iocshArgBuf *args) { + asynInterposeTemplateConfig(args[0].sval); +} + +static void asynInterposeTemplateRegister(void) { + static int firstTime = 1; + if (firstTime) { + firstTime = 0; + iocshRegister(&asynInterposeTemplateConfigFuncDef, asynInterposeTemplateConfigCallFunc); + } +} +epicsExportRegistrar(asynInterposeTemplateRegister); diff --git a/asyn/miscellaneous/asynInterposeTemplate.h b/asyn/miscellaneous/asynInterposeTemplate.h new file mode 100644 index 000000000..272655d1f --- /dev/null +++ b/asyn/miscellaneous/asynInterposeTemplate.h @@ -0,0 +1,71 @@ +/*asynInterposeTemplate.h*/ + +/* + * Example of an asynInterpose implementation + * The template implementation does *nothing*, + * simply forwards requests to the lower port. + * + * Use this as as a base example to build your asynInterpose. + * + * Author: davide.marcato@lnl.infn.it + */ + +#ifndef asynInterposeTemplate_H +#define asynInterposeTemplate_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "asynDriver.h" +#include "asynOctet.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +// Interpose private data +typedef struct interposePvt { + char *portName; + asynInterface templateInterface; /* This asynOctet interface */ + asynOctet *poctet; /* The methods we're overriding */ + void *octetPvt; /* Private data of next lower interface */ + asynUser *pasynUser; /* For connect/disconnect reporting */ +} interposePvt; + +ASYN_API +int asynInterposeTemplateConfig(const char *portName); + +/* Connect/disconnect handling */ +static void ExceptionHandler(asynUser *pasynUser, asynException exception); + +/* asynOctet methods */ +static asynStatus writeIt(void *ppvt, asynUser *pasynUser, const char *data, size_t numchars, + size_t *nbytesTransfered); +static asynStatus readIt(void *ppvt, asynUser *pasynUser, char *data, size_t maxchars, + size_t *nbytesTransfered, int *eomReason); +static asynStatus flushIt(void *ppvt, asynUser *pasynUser); +static asynStatus registerInterruptUser(void *ppvt, asynUser *pasynUser, + interruptCallbackOctet callback, void *userPvt, + void **registrarPvt); +static asynStatus cancelInterruptUser(void *ppvt, asynUser *pasynUser, void *registrarPvt); +static asynStatus setInputEos(void *ppvt, asynUser *pasynUser, const char *eos, int eoslen); +static asynStatus getInputEos(void *ppvt, asynUser *pasynUser, char *eos, int eossize, int *eoslen); +static asynStatus setOutputEos(void *ppvt, asynUser *pasynUser, const char *eos, int eoslen); +static asynStatus getOutputEos(void *ppvt, asynUser *pasynUser, char *eos, int eossize, + int *eoslen); +static asynOctet octet = { + writeIt, readIt, flushIt, registerInterruptUser, cancelInterruptUser, + setInputEos, getInputEos, setOutputEos, getOutputEos}; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* asynInterposeTemplate_H */