-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Base asynInterpose implementation #145
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <cantProceed.h> | ||
#include <epicsAssert.h> | ||
#include <epicsExport.h> | ||
#include <epicsStdio.h> | ||
#include <epicsString.h> | ||
#include <iocsh.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
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}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This |
||
|
||
#ifdef __cplusplus | ||
} | ||
#endif /* __cplusplus */ | ||
|
||
#endif /* asynInterposeTemplate_H */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with including this declaration in the widely-used asyn.dbd file is that from now on every EPICS IOC that includes this DBD file will run the
asynInterposeTemplateRegister()
routine during its initialization and thus must include a full copy of your template interpose layer code. Please at least move theregistrar()
line to a separate DBD file so it isn't pulled in unnecessarily by IOCs that don't want it.