diff --git a/src/ioc/dbStatic/devSup.h b/src/ioc/dbStatic/devSup.h index bd900cae4..aa3aa5c3d 100644 --- a/src/ioc/dbStatic/devSup.h +++ b/src/ioc/dbStatic/devSup.h @@ -21,6 +21,7 @@ /* structures defined elsewhere */ struct dbCommon; struct devSup; +struct ioscan_head; /* aka IOSCANPVT */ #ifdef __cplusplus extern "C" { @@ -38,6 +39,73 @@ typedef struct dset { /* device support entry table */ /*other functions are record dependent*/ } dset; +/** Type safe alternative to 'struct dset' + * + * Recommended usage + @code + long my_drv_init_record(dbCommon *prec); + long my_drv_get_iointr_info(int deattach, dbCommon *prec, IOCSCANPVT* pscan); + long my_longin_read(longinRecord *prec); + typedef struct { + typed_dset common; + long (*read)(longinRecord *prec); + } my_longin_dset; + static const my_longin_dset devLiMyDrvName = {{ + 5, // 4 from typed_dset + 1 more + NULL, + NULL, + &my_drv_init_record, + &my_drv_get_iointr_info + }, + &my_longin_read + }; + epicsExportAddress(dset, devLiMyDrvName); + @endcode + */ +typedef struct typed_dset { + /** Number of function pointers which follow. Must be >=4 */ + long number; + /** Called from dbior() */ + long (*report)(int lvl); + /** Called twice during iocInit(). + * First with phase=0 early, before init_record() and array field alloc. + * Again with phase=1 after init_record() + */ + long (*init)(int phase); + /** Called once per record instance */ + long (*init_record)(struct dbCommon *prec); + /** Called when SCAN="I/O Intr" on startup, or after SCAN is changed. + * + * Caller must assign third arguement (IOCSCANPVT*). eg. + @code + struct mpvt { + IOSCANPVT drvlist; + }; + ... + // init code calls + scanIoInit(&pvt->drvlist); + ... + long my_get_ioint_info(int deattach, struct dbCommon *prec, IOCSCANPVT* pscan) { + if(prec->dpvt) + *pscan = &((mypvt*)prec->dpvt)->drvlist; + @endcode + * + * When a particular record instance can/will only used a single scan list, then + * the 'detach' argument should be ignored. + * + * If this is not the case, then the following should be noted. + * get_ioint_info() called with deattach=0 to fetch the scan list to which this record will be added. + * Again with detach=1 to fetch the scan list from which this record will be removed. + * Calls will be balanced. + * A call with detach=0 will be matched by a call with detach=1. + * + * @note get_ioint_info() will be called during IOC shutdown if the del_record() + * extended callback is provided. (from 3.15.0.1) + */ + long (*get_ioint_info)(int deattach, struct dbCommon *prec, struct ioscan_head** pscan); + /*other functions are record dependent*/ +} typed_dset; + typedef struct dsxt { /* device support extension table */ long (*add_record)(struct dbCommon *precord); long (*del_record)(struct dbCommon *precord);