static void initPeriodic(void) { dbMenu *pmenu = dbFindMenu(pdbbase, "menuScan"); double quantum = epicsThreadSleepQuantum(); int i; if (!pmenu) { errlogPrintf("initPeriodic: menuScan not present\n"); return; } nPeriodic = pmenu->nChoice - SCAN_1ST_PERIODIC; papPeriodic = dbCalloc(nPeriodic, sizeof(periodic_scan_list*)); periodicTaskId = dbCalloc(nPeriodic, sizeof(void *)); for (i = 0; i < nPeriodic; i++) { periodic_scan_list *ppsl = dbCalloc(1, sizeof(periodic_scan_list)); const char *choice = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC]; double number; char *unit; int status = epicsParseDouble(choice, &number, &unit); ppsl->scan_list.lock = epicsMutexMustCreate(); ellInit(&ppsl->scan_list.list); ppsl->name = choice; if (status || number == 0) { errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice); ppsl->period = i; } else if (!*unit || !epicsStrCaseCmp(unit, "second") || !epicsStrCaseCmp(unit, "seconds")) { ppsl->period = number; } else if (!epicsStrCaseCmp(unit, "minute") || !epicsStrCaseCmp(unit, "minutes")) { ppsl->period = number * 60; } else if (!epicsStrCaseCmp(unit, "hour") || !epicsStrCaseCmp(unit, "hours")) { ppsl->period = number * 60 * 60; } else if (!epicsStrCaseCmp(unit, "Hz") || !epicsStrCaseCmp(unit, "Hertz")) { ppsl->period = 1 / number; } else { errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice); ppsl->period = i; } number = ppsl->period / quantum; if ((ppsl->period < 2 * quantum) || (number / floor(number) > 1.1)) { errlogPrintf("initPeriodic: Scan rate '%s' is not achievable.\n", choice); } ppsl->scanCtl = ctlPause; ppsl->loopEvent = epicsEventMustCreate(epicsEventEmpty); papPeriodic[i] = ppsl; } }
/**************************************************************************** * Define private interface asynDrvUser methods ****************************************************************************/ static asynStatus create(void* ppvt,asynUser* pasynUser,const char* drvInfo, const char** pptypeName,size_t* psize) { int i,addr; asynStatus sts; Inst* pinst; Port* pport = (Port*)ppvt; asynPrint(pasynUser,ASYN_TRACE_FLOW,"drvLove::create\n"); sts = pasynManager->getAddr(pasynUser,&addr); if( ISNOTOK(sts) ) return( sts ); for( i = 0; i < cmdCount; ++i ) { if( epicsStrCaseCmp(CmdTable[i].pname,drvInfo) == 0 ) { pinst = callocMustSucceed(sizeof(Inst),sizeof(char),"drvLove::create"); pinst->pport = pport; pinst->pinfo = &pport->instr[addr-1]; pinst->read = CmdTable[i].read; pinst->write = CmdTable[i].write; pinst->pcmd = &CmdTable[i].strings[pinst->pinfo->modidx]; pasynUser->drvUser = (void*)pinst; return( asynSuccess ); } } epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize,"failure to find command %s",drvInfo); return( asynError ); }
/* asynDrvUser routines */ static asynStatus drvUserCreate(void *drvPvt, asynUser *pasynUser, const char *drvInfo, const char **pptypeName, size_t *psize) { FZOOM_ID pfzoom = (FZOOM_ID)drvPvt; int i; char *pstring; for (i=0; i<MAX_FZOOM_COMMANDS; i++) { pstring = fzoomCommands[i].commandString; if (epicsStrCaseCmp(drvInfo, pstring) == 0) { pasynUser->reason = fzoomCommands[i].command; if (pptypeName) *pptypeName = epicsStrDup(pstring); if (psize) *psize = sizeof(fzoomCommands[i].command); asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s::drvUserCreate, port %s command=%s\n", driver, pfzoom->portName, pstring); return(asynSuccess); } } asynPrint(pasynUser, ASYN_TRACE_ERROR, "%s::drvUserCreate, port %s unknown command=%s\n", driver, pfzoom->portName, drvInfo); return(asynError); }
/* asynDrvUser methods */ asynStatus ct_drvUserCreate(void *drvPvt, asynUser *pasynUser, const char *drvInfo, const char **pptypeName, size_t *psize) { int i; char *pstring; const char *functionName = "ct_drvUserCreate"; asynPrint( pasynUser, ASYN_TRACE_FLOW, "%s: attempting to create cmd: %s (CT_MAX_CMD: %d)\n", functionName, drvInfo, CT_MAX_CMD); for (i=0; i < CT_MAX_CMD; i++) { pstring = ct_commands[i].commandString; if (epicsStrCaseCmp( drvInfo, pstring) == 0) { pasynUser->reason = ct_commands[i].command; if (pptypeName) *pptypeName = epicsStrDup(pstring); if (psize) *psize = sizeof( ct_commands[i].command); asynPrint( pasynUser, ASYN_TRACE_FLOW, "%s: command created: %s\n", functionName, pstring); return( asynSuccess ); } } asynPrint( pasynUser, ASYN_TRACE_ERROR, "%s: unknown command: %s\n", functionName, drvInfo); return( asynError ); }
/* * asynOption methods */ static asynStatus setOption(void *ppvt, asynUser *pasynUser, const char *key, const char *val) { interposePvt *pinterposePvt = (interposePvt *)ppvt; asynStatus status; char xBuf[5], rBuf[4]; if (epicsStrCaseCmp(key, "baud") == 0) { int b; epicsUInt32 baud; if(sscanf(val, "%d", &b) != 1) { epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "Bad number"); return asynError; } baud = b; xBuf[0] = CPO_SET_BAUDRATE; xBuf[1] = baud >> 24; xBuf[2] = baud >> 16; xBuf[3] = baud >> 8; xBuf[4] = baud; status = sbComPortOption(pinterposePvt, pasynUser, xBuf, 5, rBuf); if (status == asynSuccess) { pinterposePvt->baud = ((rBuf[0] & 0xFF) << 24) | ((rBuf[1] & 0xFF) << 16) | ((rBuf[2] & 0xFF) << 8) | (rBuf[3] & 0xFF); if (pinterposePvt->baud != baud) { epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "Tried to set %d baud, actually set %d baud.", baud, pinterposePvt->baud); return asynError; } } }
/* asynDrvUser routines */ static asynStatus drvUserCreate(void *drvPvt, asynUser *pasynUser, const char *drvInfo, const char **pptypeName, size_t *psize) { XPSInterposePvt *pPvt = (XPSInterposePvt *) drvPvt; int i; char *pstring; int ncommands = sizeof(XPSCommands)/sizeof(XPSCommands[0]); asynPrint(pasynUser, ASYN_TRACE_FLOW, "XPSInterpose::drvUserCreate, drvInfo=%s, pptypeName=%p, psize=%p, pasynUser=%p\n", drvInfo, pptypeName, psize, pasynUser); for (i=0; i < ncommands; i++) { pstring = XPSCommands[i].commandString; if (epicsStrCaseCmp(drvInfo, pstring) == 0) { break; } } if (i < ncommands) { pasynUser->reason = XPSCommands[i].command; if (pptypeName) { *pptypeName = epicsStrDup(pstring); } if (psize) { *psize = sizeof(XPSCommands[i].command); } asynPrint(pasynUser, ASYN_TRACE_FLOW, "XPSInterpose::drvUserCreate, command=%s\n", pstring); return(asynSuccess); } else { /* This command is not recognized, call the previous driver's routine */ return(pPvt->drvUserPrev->create(pPvt->drvUserPrevPvt, pasynUser, drvInfo, pptypeName, psize)); } }
static long init_ai(aiRecord *prec) { int i; if (prec->inp.type != INST_IO) { recGblRecordError(S_db_badField, (void *)prec, "devAiGeneralTime::init_ai: Illegal INP field"); prec->pact = TRUE; return S_db_badField; } for (i = 0; i < NELEMENTS(ai_channels); i++) { struct ai_channel *pchan = &ai_channels[i]; if (!epicsStrCaseCmp(prec->inp.value.instio.string, pchan->name)) { prec->dpvt = pchan; return 0; } } recGblRecordError(S_db_badField, (void *)prec, "devAiGeneralTime::init_ai: Bad parm"); prec->pact = TRUE; prec->dpvt = NULL; return S_db_badField; }
long epicsShareAPI envGetBoolConfigParam(const ENV_PARAM *pParam, int *pBool) { char text[20]; if(!envGetConfigParam(pParam, sizeof(text), text)) return -1; *pBool = epicsStrCaseCmp(text, "yes")==0; return 0; }
static asynStatus writeCmdOnly(Command* pcommand,asynUser* pasynUser,void* data,ifaceType asynIface) { int eomReason; asynStatus status; char inpBuf[BUFFER_SIZE]; writeRead(pcommand->pport,pasynUser,pcommand->writeCommand,inpBuf,sizeof(inpBuf),&eomReason); status = (epicsStrCaseCmp(inpBuf,"OK")==0 ) ? asynSuccess : asynError; return( status ); }
static asynStatus writeFloatParam(Command* pcommand,asynUser* pasynUser,void* data,ifaceType asynIface) { int eomReason; asynStatus status; char inpBuf[BUFFER_SIZE],outBuf[BUFFER_SIZE]; sprintf(outBuf,pcommand->writeCommand,*(epicsFloat64*)data); writeRead(pcommand->pport,pasynUser,outBuf,inpBuf,sizeof(inpBuf),&eomReason); status = (epicsStrCaseCmp(inpBuf,"OK")==0 ) ? asynSuccess : asynError; return( status ); }
int drvLoveConfig(const char* lovPort,int addr,const char* model) { Port* pport; for( pport = pports; pport; pport = pport->pport ) if( epicsStrCaseCmp(pport->name,lovPort) == 0 ) { if( epicsStrCaseCmp("1600",model) == 0 ) pport->instr[addr-1].modidx = model1600; else if( epicsStrCaseCmp("16A",model) == 0 ) pport->instr[addr-1].modidx = model16A; else { printf("drvLoveConfig::unsupported model \"%s\"",model); return( -1 ); } return( 0 ); } printf("drvLoveConfig::failure to locate port %s\n",lovPort); return( -1 ); }
int callbackParallelThreads(int count, const char *prio) { if (callbackIsInit) { fprintf(stderr, "Callback system already initialized\n"); return -1; } if (count < 0) count = epicsThreadGetCPUs() + count; else if (count == 0) count = callbackParallelThreadsDefault; if (count < 1) count = 1; if (!prio || *prio == 0 || strcmp(prio, "*") == 0) { int i; for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) { callbackQueue[i].threadsConfigured = count; } } else { dbMenu *pdbMenu; int i; if (!pdbbase) { fprintf(stderr, "callbackParallelThreads: pdbbase not set\n"); return -1; } /* Find prio in menuPriority */ pdbMenu = dbFindMenu(pdbbase, "menuPriority"); if (!pdbMenu) { fprintf(stderr, "callbackParallelThreads: No Priority menu\n"); return -1; } for (i = 0; i < pdbMenu->nChoice; i++) { if (epicsStrCaseCmp(prio, pdbMenu->papChoiceValue[i]) == 0) goto found; } fprintf(stderr, "callbackParallelThreads: " "Unknown priority \"%s\"\n", prio); return -1; found: callbackQueue[i].threadsConfigured = count; } return 0; }
/** Finds an attribute by name; the search is case-insensitive. * \param[in] pName The name of the attribute to be found. * \return Returns a pointer to the attribute if found, NULL if not found. */ NDAttribute* NDAttributeList::find(const char *pName) { NDAttribute *pAttribute; NDAttributeListNode *pListNode; //const char *functionName = "NDAttributeList::find"; epicsMutexLock(this->lock); pListNode = (NDAttributeListNode *)ellFirst(&this->list); while (pListNode) { pAttribute = pListNode->pNDAttribute; if (epicsStrCaseCmp(pAttribute->pName, pName) == 0) goto done; pListNode = (NDAttributeListNode *)ellNext(&pListNode->node); } pAttribute = NULL; done: epicsMutexUnlock(this->lock); return(pAttribute); }
/**************************************************************************** * Define private interface asynDrvUser methods ****************************************************************************/ static asynStatus create(void* ppvt,asynUser* pasynUser,const char* drvInfo, const char** pptypeName,size_t* psize) { Port* pport = (Port*)ppvt; int i; for(i = 0; i < commandLen; i++) if( !epicsStrCaseCmp( drvInfo, commandTable[i].tag) ) { pasynUser->reason = i; break; } if( i == commandLen ) { errlogPrintf("%s::create port %s failed to find tag %s\n", driver, pport->myport, drvInfo); pasynUser->reason = 0; return asynError; } return asynSuccess; }
/* asynDrvUser routines */ static asynStatus drvUserCreate(void *drvPvt, asynUser *pasynUser, const char *drvInfo, const char **pptypeName, size_t *psize) { int i; const char *pstring; for (i=0; i<MAX_MCA_COMMANDS; i++) { pstring = mcaCommands[i].commandString; if (epicsStrCaseCmp(drvInfo, pstring) == 0) { pasynUser->reason = mcaCommands[i].command; if (pptypeName) *pptypeName = epicsStrDup(pstring); if (psize) *psize = sizeof(mcaCommands[i].command); asynPrint(pasynUser, ASYN_TRACE_FLOW, "drvMcaAIMAsyn::drvUserCreate, command=%s\n", pstring); return(asynSuccess); } } asynPrint(pasynUser, ASYN_TRACE_ERROR, "drvMcaAIMAsyn::drvUserCreate, unknown command=%s\n", drvInfo); return(asynError); }
static asynStatus readFloat64(void* ppvt,asynUser* pasynUser,epicsFloat64* value) { float readback; int addr,status; const char* pcmd; char inpBuf[BUFFER_SIZE]; Port* pport = (Port*)ppvt; asynPrint(pasynUser,ASYN_TRACE_FLOW,"drvAsynColby::readFloat64 %s: reason - %d\n",pport->myport,pasynUser->reason); if( pasynManager->getAddr(pasynUser,&addr)) return( asynError ); switch( addr ) { case 0: case 1: pcmd = "DEL?"; break; case 4: case 5: pcmd = "STEP?"; break; default: return( asynError ); } epicsMutexMustLock(pport->syncLock); status = writeRead(pport->pasynUser,pcmd,inpBuf,sizeof(inpBuf),pport->iface); epicsMutexUnlock(pport->syncLock); if( status ) return( asynError ); sscanf(inpBuf,"%e",&readback); if( epicsStrCaseCmp(pport->units,"ns")==0 ) *value=(epicsFloat64)readback/1.0E-9; else *value=(epicsFloat64)readback/1.0E-12; asynPrint(pasynUser,ASYN_TRACEIO_FILTER,"drvAsynColby::readFloat64 %s: asyn - 0x%8.8X, addr - %d, value - %f\n",pport->myport,pasynUser,addr,*value); return( asynSuccess ); }
static asynStatus readUInt32(void* ppvt,asynUser* pasynUser,epicsUInt32* value,epicsUInt32 mask) { int addr; Port* pport = (Port*)ppvt; asynPrint(pasynUser,ASYN_TRACE_FLOW,"drvAsynColby::readUInt32 %s:\n",pport->myport); if( pasynManager->getAddr(pasynUser,&addr)) return( asynError ); switch( addr ) { case 2: case 3: *value = 0; return( asynSuccess ); case 6: if( epicsStrCaseCmp(pport->units,"ns")==0 ) *value=0; else *value=1; break; default: return( asynError ); } asynPrint(pasynUser,ASYN_TRACEIO_FILTER,"drvAsynColby::readUInt32 %s: asyn - 0x%8.8X, mask - 0x%8.8X, value - 0x%8.8X\n",pport->myport,pasynUser,(int)mask,(int)*value); return( asynSuccess ); }
static asynStatus setOption(void *drvPvt, asynUser *pasynUser, const char *key, const char *val) { ttyController_t *tty = (ttyController_t *)drvPvt; struct termios termiosPrev; int baudPrev; assert(tty); asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s setOption key %s val %s\n", tty->portName, key, val); /* Make a copy of tty->termios and tty->baud so we can restore them in case of errors */ termiosPrev = tty->termios; baudPrev = tty->baud; if (epicsStrCaseCmp(key, "baud") == 0) { int baud; if(sscanf(val, "%d", &baud) != 1) { epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "Bad number"); return asynError; } #ifndef vxWorks { speed_t baudCode; /* On this system is the baud code the actual baud rate? * If so use it directly, else compare against known baud codes */ #if (defined(B300) && (B300 == 300) && defined(B9600) && (B9600 == 9600)) baudCode = baud; #else switch(baud) { case 50: baudCode = B50 ; break; case 75: baudCode = B75 ; break; case 110: baudCode = B110 ; break; case 134: baudCode = B134 ; break; case 150: baudCode = B150 ; break; case 200: baudCode = B200 ; break; case 300: baudCode = B300 ; break; case 600: baudCode = B600 ; break; case 1200: baudCode = B1200 ; break; case 1800: baudCode = B1800 ; break; case 2400: baudCode = B2400 ; break; case 4800: baudCode = B4800 ; break; case 9600: baudCode = B9600 ; break; case 19200: baudCode = B19200 ; break; #ifdef B28800 case 28800: baudCode = B28800 ; break; #endif case 38400: baudCode = B38400 ; break; #ifdef B57600 case 57600: baudCode = B57600 ; break; #endif #ifdef B115200 case 115200: baudCode = B115200 ; break; #endif #ifdef B230400 case 230400: baudCode = B230400 ; break; #endif #ifdef B460800 case 460800: baudCode = B460800 ; break; #endif #ifdef B500000 case 500000: baudCode = B500000 ; break; #endif #ifdef B576000 case 576000: baudCode = B576000 ; break; #endif #ifdef B921600 case 921600: baudCode = B921600 ; break; #endif #ifdef B1000000 case 1000000: baudCode = B1000000 ; break; #endif #ifdef B1152000 case 1152000: baudCode = B1152000 ; break; #endif #ifdef B1500000 case 1500000: baudCode = B1500000 ; break; #endif #ifdef B2000000 case 2000000: baudCode = B2000000 ; break; #endif #ifdef B2500000 case 2500000: baudCode = B2500000 ; break; #endif #ifdef B3000000 case 3000000: baudCode = B3000000 ; break; #endif #ifdef B3500000 case 3500000: baudCode = B3500000 ; break; #endif #ifdef B4000000 case 4000000: baudCode = B4000000 ; break; #endif default: epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "Unsupported data rate (%d baud)", baud); return asynError; } #endif /* Baudcode is baud */ if(cfsetispeed(&tty->termios,baudCode) < 0 ) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "cfsetispeed returned %s",strerror(errno)); return asynError; } if(cfsetospeed(&tty->termios,baudCode) < 0 ) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "cfsetospeed returned %s",strerror(errno)); return asynError; } } #endif /* vxWorks */ tty->baud = baud; } else if (epicsStrCaseCmp(key, "bits") == 0) { if (epicsStrCaseCmp(val, "5") == 0) { tty->termios.c_cflag = (tty->termios.c_cflag & ~CSIZE) | CS5; } else if (epicsStrCaseCmp(val, "6") == 0) { tty->termios.c_cflag = (tty->termios.c_cflag & ~CSIZE) | CS6; } else if (epicsStrCaseCmp(val, "7") == 0) { tty->termios.c_cflag = (tty->termios.c_cflag & ~CSIZE) | CS7; } else if (epicsStrCaseCmp(val, "8") == 0) { tty->termios.c_cflag = (tty->termios.c_cflag & ~CSIZE) | CS8; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid number of bits."); return asynError; } } else if (epicsStrCaseCmp(key, "parity") == 0) { if (epicsStrCaseCmp(val, "none") == 0) { tty->termios.c_cflag &= ~PARENB; } else if (epicsStrCaseCmp(val, "even") == 0) { tty->termios.c_cflag |= PARENB; tty->termios.c_cflag &= ~PARODD; } else if (epicsStrCaseCmp(val, "odd") == 0) { tty->termios.c_cflag |= PARENB; tty->termios.c_cflag |= PARODD; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid parity."); return asynError; } } else if (epicsStrCaseCmp(key, "stop") == 0) { if (epicsStrCaseCmp(val, "1") == 0) { tty->termios.c_cflag &= ~CSTOPB; } else if (epicsStrCaseCmp(val, "2") == 0) { tty->termios.c_cflag |= CSTOPB; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid number of stop bits."); return asynError; } } else if (epicsStrCaseCmp(key, "clocal") == 0) { if (epicsStrCaseCmp(val, "Y") == 0) { tty->termios.c_cflag |= CLOCAL; } else if (epicsStrCaseCmp(val, "N") == 0) { tty->termios.c_cflag &= ~CLOCAL; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid clocal value."); return asynError; } } else if (epicsStrCaseCmp(key, "crtscts") == 0) { if (epicsStrCaseCmp(val, "Y") == 0) { /* vxWorks uses CLOCAL when it should use CRTSCTS */ #ifdef vxWorks tty->termios.c_cflag &= ~CLOCAL; #else tty->termios.c_cflag |= CRTSCTS; #endif } else if (epicsStrCaseCmp(val, "N") == 0) { #ifdef vxWorks tty->termios.c_cflag |= CLOCAL; #else tty->termios.c_cflag &= ~CRTSCTS; #endif } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid crtscts value."); return asynError; } } else if (epicsStrCaseCmp(key, "ixon") == 0) { if (epicsStrCaseCmp(val, "Y") == 0) { #ifdef vxWorks ioctl(tty->fd, FIOSETOPTIONS, ioctl(tty->fd, FIOGETOPTIONS, 0) | OPT_TANDEM); return asynSuccess; #else tty->termios.c_iflag |= IXON; #endif } else if (epicsStrCaseCmp(val, "N") == 0) { #ifdef vxWorks ioctl(tty->fd, FIOSETOPTIONS, ioctl(tty->fd, FIOGETOPTIONS, 0) & ~OPT_TANDEM); return asynSuccess; #else tty->termios.c_iflag &= ~IXON; #endif } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid ixon value."); return asynError; } } else if (epicsStrCaseCmp(key, "ixany") == 0) { #ifdef vxWorks epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Option ixany not supported on vxWorks"); return asynError; #else if (epicsStrCaseCmp(val, "Y") == 0) { tty->termios.c_iflag |= IXANY; } else if (epicsStrCaseCmp(val, "N") == 0) { tty->termios.c_iflag &= ~IXANY; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid ixany value."); return asynError; } #endif } else if (epicsStrCaseCmp(key, "ixoff") == 0) { #ifdef vxWorks epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Option ixoff not supported on vxWorks"); return asynError; #else if (epicsStrCaseCmp(val, "Y") == 0) { tty->termios.c_iflag |= IXOFF; } else if (epicsStrCaseCmp(val, "N") == 0) { tty->termios.c_iflag &= ~IXOFF; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid ixoff value."); return asynError; } #endif } else if (epicsStrCaseCmp(key, "") != 0) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Unsupported key \"%s\"", key); return asynError; } if (tty->fd >= 0) { if (applyOptions(pasynUser, tty) != asynSuccess) { /* Restore previous values of tty->baud and tty->termios */ tty->baud = baudPrev; tty->termios = termiosPrev; return asynError; } } return asynSuccess; }
/* * asynOption methods */ static asynStatus getOption(void *drvPvt, asynUser *pasynUser, const char *key, char *val, int valSize) { ttyController_t *tty = (ttyController_t *)drvPvt; int l; if (epicsStrCaseCmp(key, "baud") == 0) { l = epicsSnprintf(val, valSize, "%d", tty->baud); } else if (epicsStrCaseCmp(key, "bits") == 0) { switch (tty->termios.c_cflag & CSIZE) { case CS5: l = epicsSnprintf(val, valSize, "5"); break; case CS6: l = epicsSnprintf(val, valSize, "6"); break; case CS7: l = epicsSnprintf(val, valSize, "7"); break; case CS8: l = epicsSnprintf(val, valSize, "8"); break; default: l = epicsSnprintf(val, valSize, "?"); break; } } else if (epicsStrCaseCmp(key, "parity") == 0) { if (tty->termios.c_cflag & PARENB) { if (tty->termios.c_cflag & PARODD) l = epicsSnprintf(val, valSize, "odd"); else l = epicsSnprintf(val, valSize, "even"); } else { l = epicsSnprintf(val, valSize, "none"); } } else if (epicsStrCaseCmp(key, "stop") == 0) { l = epicsSnprintf(val, valSize, "%d", (tty->termios.c_cflag & CSTOPB) ? 2 : 1); } else if (epicsStrCaseCmp(key, "clocal") == 0) { l = epicsSnprintf(val, valSize, "%c", (tty->termios.c_cflag & CLOCAL) ? 'Y' : 'N'); } else if (epicsStrCaseCmp(key, "crtscts") == 0) { char c; /* vxWorks uses CLOCAL when it should use CRTSCTS */ #ifdef vxWorks c = (tty->termios.c_cflag & CLOCAL) ? 'N' : 'Y'; #else c = (tty->termios.c_cflag & CRTSCTS) ? 'Y' : 'N'; #endif l = epicsSnprintf(val, valSize, "%c", c); } else if (epicsStrCaseCmp(key, "ixon") == 0) { #ifdef vxWorks l = epicsSnprintf(val, valSize, "%c", (ioctl(tty->fd, FIOGETOPTIONS, 0) & OPT_TANDEM) ? 'Y' : 'N'); #else l = epicsSnprintf(val, valSize, "%c", (tty->termios.c_iflag & IXON) ? 'Y' : 'N'); #endif } else if (epicsStrCaseCmp(key, "ixany") == 0) { #ifdef vxWorks l = epicsSnprintf(val, valSize, "%c", 'N'); #else l = epicsSnprintf(val, valSize, "%c", (tty->termios.c_iflag & IXANY) ? 'Y' : 'N'); #endif } else if (epicsStrCaseCmp(key, "ixoff") == 0) { #ifdef vxWorks l = epicsSnprintf(val, valSize, "%c", 'N'); #else l = epicsSnprintf(val, valSize, "%c", (tty->termios.c_iflag & IXOFF) ? 'Y' : 'N'); #endif } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Unsupported key \"%s\"", key); return asynError; } if (l >= valSize) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Value buffer for key '%s' is too small.", key); return asynError; } return asynSuccess; }
/* * asynOption methods */ static asynStatus getOption(void *drvPvt, asynUser *pasynUser, const char *key, char *val, int valSize) { ttyController_t *tty = (ttyController_t *)drvPvt; DWORD commConfigSize = sizeof(tty->commConfig); BOOL ret; DWORD error; int l; assert(tty); if (tty->commHandle == INVALID_HANDLE_VALUE) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s disconnected:", tty->serialDeviceName); return asynError; } ret = GetCommConfig(tty->commHandle, &tty->commConfig, &commConfigSize); if (ret == 0) { error = GetLastError(); epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s error calling GetCommConfig %d", tty->serialDeviceName, error); return asynError; } if (epicsStrCaseCmp(key, "baud") == 0) { l = epicsSnprintf(val, valSize, "%d", tty->commConfig.dcb.BaudRate); } else if (epicsStrCaseCmp(key, "bits") == 0) { l = epicsSnprintf(val, valSize, "%d", tty->commConfig.dcb.ByteSize); } else if (epicsStrCaseCmp(key, "parity") == 0) { switch (tty->commConfig.dcb.Parity) { case 0: l = epicsSnprintf(val, valSize, "none"); break; case 1: l = epicsSnprintf(val, valSize, "odd"); break; case 2: l = epicsSnprintf(val, valSize, "even"); break; } } else if (epicsStrCaseCmp(key, "stop") == 0) { l = epicsSnprintf(val, valSize, "%d", (tty->commConfig.dcb.StopBits == 2) ? 2 : 1); } else if (epicsStrCaseCmp(key, "clocal") == 0) { l = epicsSnprintf(val, valSize, "%c", (tty->commConfig.dcb.fOutxDsrFlow == TRUE) ? 'N' : 'Y'); } else if (epicsStrCaseCmp(key, "crtscts") == 0) { l = epicsSnprintf(val, valSize, "%c", (tty->commConfig.dcb.fOutxCtsFlow == TRUE) ? 'Y' : 'N'); } else if (epicsStrCaseCmp(key, "ixon") == 0) { l = epicsSnprintf(val, valSize, "%c", (tty->commConfig.dcb.fOutX == TRUE) ? 'Y' : 'N'); } else if (epicsStrCaseCmp(key, "ixany") == 0) { l = epicsSnprintf(val, valSize, "%c", 'N'); } else if (epicsStrCaseCmp(key, "ixoff") == 0) { l = epicsSnprintf(val, valSize, "%c", (tty->commConfig.dcb.fInX == TRUE) ? 'Y' : 'N'); } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Unsupported key \"%s\"", key); return asynError; } if (l >= valSize) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Value buffer for key '%s' is too small.", key); return asynError; } asynPrint(tty->pasynUser, ASYN_TRACEIO_DRIVER, "%s getOption, key=%s, val=%s\n", tty->serialDeviceName, key, val); return asynSuccess; }
static asynStatus setOption(void *drvPvt, asynUser *pasynUser, const char *key, const char *val) { ttyController_t *tty = (ttyController_t *)drvPvt; DWORD commConfigSize = sizeof(tty->commConfig); BOOL ret; DWORD error; assert(tty); asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s setOption key %s val %s\n", tty->portName, key, val); if (tty->commHandle == INVALID_HANDLE_VALUE) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s disconnected:", tty->serialDeviceName); return asynError; } ret = GetCommConfig(tty->commHandle, &tty->commConfig, &commConfigSize); if (ret == 0) { error = GetLastError(); epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s error calling GetCommConfig %d", tty->serialDeviceName, error); return asynError; } if (epicsStrCaseCmp(key, "baud") == 0) { int baud; if(sscanf(val, "%d", &baud) != 1) { epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "Bad number"); return asynError; } tty->commConfig.dcb.BaudRate = baud; } else if (epicsStrCaseCmp(key, "bits") == 0) { int bits; if(sscanf(val, "%d", &bits) != 1) { epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "Bad number"); return asynError; } tty->commConfig.dcb.ByteSize = bits; } else if (epicsStrCaseCmp(key, "parity") == 0) { if (epicsStrCaseCmp(val, "none") == 0) { tty->commConfig.dcb.Parity = 0; } else if (epicsStrCaseCmp(val, "odd") == 0) { tty->commConfig.dcb.Parity = 1; } else if (epicsStrCaseCmp(val, "even") == 0) { tty->commConfig.dcb.Parity = 2; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid parity."); return asynError; } } else if (epicsStrCaseCmp(key, "stop") == 0) { if (epicsStrCaseCmp(val, "1") == 0) { tty->commConfig.dcb.StopBits = ONESTOPBIT; } else if (epicsStrCaseCmp(val, "2") == 0) { tty->commConfig.dcb.StopBits = TWOSTOPBITS; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid number of stop bits."); return asynError; } } else if (epicsStrCaseCmp(key, "clocal") == 0) { if (epicsStrCaseCmp(val, "Y") == 0) { tty->commConfig.dcb.fOutxDsrFlow = FALSE; tty->commConfig.dcb.fDsrSensitivity = FALSE; tty->commConfig.dcb.fDtrControl = DTR_CONTROL_ENABLE; } else if (epicsStrCaseCmp(val, "N") == 0) { tty->commConfig.dcb.fOutxDsrFlow = TRUE; tty->commConfig.dcb.fDsrSensitivity = TRUE; tty->commConfig.dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid clocal value."); return asynError; } } else if (epicsStrCaseCmp(key, "crtscts") == 0) { if (epicsStrCaseCmp(val, "Y") == 0) { tty->commConfig.dcb.fOutxCtsFlow = TRUE; tty->commConfig.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; } else if (epicsStrCaseCmp(val, "N") == 0) { tty->commConfig.dcb.fOutxCtsFlow = FALSE; tty->commConfig.dcb.fRtsControl = RTS_CONTROL_ENABLE; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid crtscts value."); return asynError; } } else if (epicsStrCaseCmp(key, "ixon") == 0) { if (epicsStrCaseCmp(val, "Y") == 0) { tty->commConfig.dcb.fOutX = TRUE ; } else if (epicsStrCaseCmp(val, "N") == 0) { tty->commConfig.dcb.fOutX = FALSE; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid ixon value."); return asynError; } } else if (epicsStrCaseCmp(key, "ixany") == 0) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Option ixany not supported on Windows"); return asynError; } else if (epicsStrCaseCmp(key, "ixoff") == 0) { if (epicsStrCaseCmp(val, "Y") == 0) { tty->commConfig.dcb.fInX = TRUE; } else if (epicsStrCaseCmp(val, "N") == 0) { tty->commConfig.dcb.fInX = FALSE; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid ixoff value."); return asynError; } } else if (epicsStrCaseCmp(key, "") != 0) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Unsupported key \"%s\"", key); return asynError; } ret = SetCommConfig(tty->commHandle, &tty->commConfig, commConfigSize); if (ret == 0) { error = GetLastError(); epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s error calling SetCommConfig %d", tty->serialDeviceName, error); return asynError; } return asynSuccess; }
static asynStatus setOption(void *drvPvt, asynUser *pasynUser, const char *key, const char *val) { ttyController_t *tty = (ttyController_t *)drvPvt; assert(tty); asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s setOption key %s val %s\n", tty->portName, key, val); if (epicsStrCaseCmp(key, "baud") == 0) { int baud; if(sscanf(val, "%d", &baud) != 1) { epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "Bad number"); return asynError; } #ifndef vxWorks { speed_t baudCode; switch(baud) { case 50: baudCode = B50 ; break; case 75: baudCode = B75 ; break; case 110: baudCode = B110 ; break; case 134: baudCode = B134 ; break; case 150: baudCode = B150 ; break; case 200: baudCode = B200 ; break; case 300: baudCode = B300 ; break; case 600: baudCode = B600 ; break; case 1200: baudCode = B1200 ; break; case 1800: baudCode = B1800 ; break; case 2400: baudCode = B2400 ; break; case 4800: baudCode = B4800 ; break; case 9600: baudCode = B9600 ; break; case 19200: baudCode = B19200 ; break; #ifdef B28800 case 28800: baudCode = B28800 ; break; #endif case 38400: baudCode = B38400 ; break; case 57600: baudCode = B57600 ; break; case 115200: baudCode = B115200 ; break; case 230400: baudCode = B230400 ; break; default: epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "Unsupported data rate (%d baud)", baud); return asynError; } if(cfsetispeed(&tty->termios,baudCode) < 0 ) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "cfsetispeed returned %s\n",strerror(errno)); return asynError; } if(cfsetospeed(&tty->termios,baudCode) < 0 ) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "cfsetospeed returned %s\n",strerror(errno)); return asynError; } } #endif tty->baud = baud; } else if (epicsStrCaseCmp(key, "bits") == 0) { if (epicsStrCaseCmp(val, "5") == 0) { tty->termios.c_cflag = (tty->termios.c_cflag & ~CSIZE) | CS5; } else if (epicsStrCaseCmp(val, "6") == 0) { tty->termios.c_cflag = (tty->termios.c_cflag & ~CSIZE) | CS6; } else if (epicsStrCaseCmp(val, "7") == 0) { tty->termios.c_cflag = (tty->termios.c_cflag & ~CSIZE) | CS7; } else if (epicsStrCaseCmp(val, "8") == 0) { tty->termios.c_cflag = (tty->termios.c_cflag & ~CSIZE) | CS8; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid number of bits."); return asynError; } } else if (epicsStrCaseCmp(key, "parity") == 0) { if (epicsStrCaseCmp(val, "none") == 0) { tty->termios.c_cflag &= ~PARENB; } else if (epicsStrCaseCmp(val, "even") == 0) { tty->termios.c_cflag |= PARENB; tty->termios.c_cflag &= ~PARODD; } else if (epicsStrCaseCmp(val, "odd") == 0) { tty->termios.c_cflag |= PARENB; tty->termios.c_cflag |= PARODD; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid parity."); return asynError; } } else if (epicsStrCaseCmp(key, "stop") == 0) { if (epicsStrCaseCmp(val, "1") == 0) { tty->termios.c_cflag &= ~CSTOPB; } else if (epicsStrCaseCmp(val, "2") == 0) { tty->termios.c_cflag |= CSTOPB; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid number of stop bits."); return asynError; } } else if (epicsStrCaseCmp(key, "clocal") == 0) { if (epicsStrCaseCmp(val, "Y") == 0) { tty->termios.c_cflag |= CLOCAL; } else if (epicsStrCaseCmp(val, "N") == 0) { tty->termios.c_cflag &= ~CLOCAL; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid clocal value."); return asynError; } } else if (epicsStrCaseCmp(key, "crtscts") == 0) { if (epicsStrCaseCmp(val, "Y") == 0) { /* vxWorks uses CLOCAL when it should use CRTSCTS */ #ifdef vxWorks tty->termios.c_cflag &= ~CLOCAL; #else tty->termios.c_cflag |= CRTSCTS; #endif } else if (epicsStrCaseCmp(val, "N") == 0) { #ifdef vxWorks tty->termios.c_cflag |= CLOCAL; #else tty->termios.c_cflag &= ~CRTSCTS; #endif } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid crtscts value."); return asynError; } } else if (epicsStrCaseCmp(key, "ixon") == 0) { if (epicsStrCaseCmp(val, "Y") == 0) { #ifdef vxWorks ioctl(tty->fd, FIOSETOPTIONS, ioctl(tty->fd, FIOGETOPTIONS, 0) | OPT_TANDEM); return asynSuccess; #else tty->termios.c_iflag |= IXON; #endif } else if (epicsStrCaseCmp(val, "N") == 0) { #ifdef vxWorks ioctl(tty->fd, FIOSETOPTIONS, ioctl(tty->fd, FIOGETOPTIONS, 0) & ~OPT_TANDEM); return asynSuccess; #else tty->termios.c_iflag &= ~IXON; #endif } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid ixon value."); return asynError; } } else if (epicsStrCaseCmp(key, "ixany") == 0) { #ifdef vxWorks epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Option ixany not supported on vxWorks"); return asynError; #else if (epicsStrCaseCmp(val, "Y") == 0) { tty->termios.c_iflag |= IXANY; } else if (epicsStrCaseCmp(val, "N") == 0) { tty->termios.c_iflag &= ~IXANY; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid ixany value."); return asynError; } #endif } else if (epicsStrCaseCmp(key, "ixoff") == 0) { #ifdef vxWorks epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Option ixoff not supported on vxWorks"); return asynError; #else if (epicsStrCaseCmp(val, "Y") == 0) { tty->termios.c_iflag |= IXOFF; } else if (epicsStrCaseCmp(val, "N") == 0) { tty->termios.c_iflag &= ~IXOFF; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Invalid ixoff value."); return asynError; } #endif } else if (epicsStrCaseCmp(key, "") != 0) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Unsupported key \"%s\"", key); return asynError; } if (tty->fd >= 0) return applyOptions(pasynUser, tty); return asynSuccess; }
/** Create this driver's NDAttributeList (pAttributeList) by reading an XML file * \param[in] fileName The name of the XML file to read. * * This clears any existing attributes from this drivers' NDAttributeList and then creates a new list * based on the XML file. These attributes can then be associated with an NDArray by calling asynNDArrayDriver::getAttributes() * passing it pNDArray->pAttributeList. * * The following simple example XML file illustrates the way that both PVAttribute and paramAttribute attributes are defined. * <pre> * <?xml version="1.0" standalone="no" ?> * \<Attributes> * \<Attribute name="AcquireTime" type="EPICS_PV" source="13SIM1:cam1:AcquireTime" dbrtype="DBR_NATIVE" description="Camera acquire time"/> * \<Attribute name="CameraManufacturer" type="PARAM" source="MANUFACTURER" datatype="STRING" description="Camera manufacturer"/> * \</Attributes> * </pre> * Each NDAttribute (currently either an PVAttribute or paramAttribute, but other types may be added in the future) * is defined with an XML <b>Attribute</b> tag. For each attribute there are a number of XML attributes * (unfortunately there are 2 meanings of attribute here: the NDAttribute and the XML attribute). * XML attributes have the syntax name="value". The XML attribute names are case-sensitive and must be lower case, i.e. name="xxx", not NAME="xxx". * The XML attribute values are specified by the XML Schema and are always uppercase for <b>datatype</b> and <b>dbrtype</b> attributes. * The XML attribute names are listed here: * * <b>name</b> determines the name of the NDAttribute. It is required, must be unique, is case-insensitive, * and must start with a letter. It can include only letters, numbers and underscore. (No whitespace or other punctuation.) * * <b>type</b> determines the type of the NDAttribute. "EPICS_PV" creates a PVAttribute, while "PARAM" creates a paramAttribute. * The default is EPICS_PV if this XML attribute is absent. * * <b>source</b> determines the source of the NDAttribute. It is required. If type="EPICS_PV" then this is the name of the EPICS PV, which is * case-sensitive. If type="PARAM" then this is the drvInfo string that is used in EPICS database files (e.g. ADBase.template) to identify * this parameter. * * <b>dbrtype</b> determines the data type that will be used to read an EPICS_PV value with channel access. It can be one of the standard EPICS * DBR types (e.g. "DBR_DOUBLE", "DBR_STRING", ...) or it can be the special type "DBR_NATIVE" which means to use the native channel access * data type for this PV. The default is DBR_NATIVE if this XML attribute is absent. Always use uppercase. * * <b>datatype</b> determines the parameter data type for type="PARAM". It must match the actual data type in the driver or plugin * parameter library, and must be "INT", "DOUBLE", or "STRING". The default is "INT" if this XML attribute is absent. Always use uppercase. * * <b>addr</b> determines the asyn addr (address) for type="PARAM". The default is 0 if the XML attribute is absent. * * <b>description</b> determines the description for this attribute. It is not required, and the default is a NULL string. * */ int asynNDArrayDriver::readNDAttributesFile(const char *fileName) { static const char *functionName = "readNDAttributesFile"; const char *pName, *pDBRType, *pSource, *pType, *pDataType, *pAddr, *pDescription=NULL; int dbrType; int addr=0; PVAttribute *pPVAttribute=NULL; paramAttribute *pParamAttribute=NULL; TiXmlDocument doc(fileName); TiXmlElement *Attr, *Attrs; /* Clear any existing attributes */ this->pAttributeList->clear(); if (!fileName || (strlen(fileName) == 0)) return(asynSuccess); if (!doc.LoadFile()) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: cannot open file %s error=%s\n", driverName, functionName, fileName, doc.ErrorDesc()); return(asynError); } Attrs = doc.FirstChildElement( "Attributes" ); if (!Attrs) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: cannot find Attributes element\n", driverName, functionName); return(asynError); } for (Attr = Attrs->FirstChildElement(); Attr; Attr = Attr->NextSiblingElement()) { pName = Attr->Attribute("name"); if (!pName) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: name attribute not found\n", driverName, functionName); return(asynError); } pDescription = Attr->Attribute("description"); pSource = Attr->Attribute("source"); pType = Attr->Attribute("type"); if (!pType) pType = "EPICS_PV"; if (epicsStrCaseCmp(pType, "EPICS_PV") == 0) { pDBRType = Attr->Attribute("dbrtype"); dbrType = DBR_NATIVE; // TODO: do not enforce new uppercase rule yet on value of dbrtype attribute if (pDBRType) { if (!epicsStrCaseCmp(pDBRType, "DBR_CHAR")) dbrType = DBR_CHAR; else if (!epicsStrCaseCmp(pDBRType, "DBR_SHORT")) dbrType = DBR_SHORT; else if (!epicsStrCaseCmp(pDBRType, "DBR_ENUM")) dbrType = DBR_ENUM; else if (!epicsStrCaseCmp(pDBRType, "DBR_INT")) dbrType = DBR_INT; else if (!epicsStrCaseCmp(pDBRType, "DBR_LONG")) dbrType = DBR_LONG; else if (!epicsStrCaseCmp(pDBRType, "DBR_FLOAT")) dbrType = DBR_FLOAT; else if (!epicsStrCaseCmp(pDBRType, "DBR_DOUBLE")) dbrType = DBR_DOUBLE; else if (!epicsStrCaseCmp(pDBRType, "DBR_STRING")) dbrType = DBR_STRING; else if (!epicsStrCaseCmp(pDBRType, "DBR_NATIVE")) dbrType = DBR_NATIVE; else { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: unknown dbrType = %s\n", driverName, functionName, pDBRType); return(asynError); } } asynPrint(pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: Name=%s, PVName=%s, pDBRType=%s, dbrType=%d, pDescription=%s\n", driverName, functionName, pName, pSource, pDBRType, dbrType, pDescription); pPVAttribute = new PVAttribute(pName, pDescription, pSource, dbrType); this->pAttributeList->add(pPVAttribute); } else if (epicsStrCaseCmp(pType, "PARAM") == 0) { // TODO: do not enforce new uppercase rule yet on value of datatype attribute pDataType = Attr->Attribute("datatype"); if (!pDataType) pDataType = "int"; pAddr = Attr->Attribute("addr"); if (pAddr) addr = strtol(pAddr, NULL, 0); else addr = 0; asynPrint(pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: Name=%s, drvInfo=%s, dataType=%s,pDescription=%s\n", driverName, functionName, pName, pSource, pDataType, pDescription); pParamAttribute = new paramAttribute(pName, pDescription, pSource, addr, this, pDataType); this->pAttributeList->add(pParamAttribute); } } return(asynSuccess); }
/* * Configure and register an IP socket from a hostInfo string */ epicsShareFunc int drvAsynIPPortConfigure(const char *portName, const char *hostInfo, unsigned int priority, int noAutoConnect, int userFlags) { ttyController_t *tty; asynInterface *pasynInterface; asynStatus status; char *cp; int nbytes; asynOctet *pasynOctet; int isCom = 0; static int firstTime = 1; /* * Check arguments */ if (portName == NULL) { printf("Port name missing.\n"); return -1; } if (hostInfo == NULL) { printf("TCP host information missing.\n"); return -1; } if (USERFLAG_RESERVED & userFlags) { printf("Reserved userFlags must be 0\n"); return -1; } /* * Perform some one-time-only initializations */ if (firstTime) { firstTime = 0; if (osiSockAttach() == 0) { printf("drvAsynIPPortConfigure: osiSockAttach failed\n"); return -1; } } /* * Create a driver */ nbytes = sizeof(*tty) + sizeof(asynOctet); tty = (ttyController_t *)callocMustSucceed(1, nbytes, "drvAsynIPPortConfigure()"); pasynOctet = (asynOctet *)(tty+1); tty->fd = INVALID_SOCKET; tty->flags = 0; tty->userFlags = userFlags; tty->IPDeviceName = epicsStrDup(hostInfo); tty->portName = epicsStrDup(portName); /* * Parse configuration parameters */ if (strncmp(tty->IPDeviceName, "unix://", 7) == 0) { # if defined(HAS_AF_UNIX) const char *cp = tty->IPDeviceName + 7; size_t l = strlen(cp); if ((l == 0) || (l >= sizeof(tty->farAddr.ua.sun_path)-1)) { printf("Path name \"%s\" invalid.\n", cp); ttyCleanup(tty); return -1; } tty->farAddr.ua.sun_family = AF_UNIX; strcpy(tty->farAddr.ua.sun_path, cp); tty->farAddrSize = sizeof(tty->farAddr.ua) - sizeof(tty->farAddr.ua.sun_path) + l + 1; tty->socketType = SOCK_STREAM; # else printf("AF_UNIX not available on this platform.\n"); ttyCleanup(tty); return -1; # endif } else { int port; int localPort = -1; char protocol[6]; char *secondColon, *blank; protocol[0] = '\0'; if ((cp = strchr(tty->IPDeviceName, ':')) == NULL) { printf("drvAsynIPPortConfigure: \"%s\" is not of the form \"<host>:<port>[:localPort] [protocol]\"\n", tty->IPDeviceName); ttyCleanup(tty); return -1; } *cp = '\0'; tty->IPHostName = epicsStrDup(tty->IPDeviceName); *cp = ':'; if (sscanf(cp, ":%d", &port) < 1) { printf("drvAsynIPPortConfigure: \"%s\" is not of the form \"<host>:<port>[:localPort] [protocol]\"\n", tty->IPDeviceName); ttyCleanup(tty); return -1; } if ((secondColon = strchr(cp+1, ':')) != NULL) { if (sscanf(secondColon, ":%d", &localPort) < 1) { printf("drvAsynIPPortConfigure: \"%s\" is not of the form \"<host>:<port>[:localPort] [protocol]\"\n", tty->IPDeviceName); ttyCleanup(tty); return -1; } tty->localAddr.ia.sin_family = AF_INET; tty->localAddr.ia.sin_port = htons(localPort); tty->localAddrSize = sizeof(tty->localAddr.ia); } if ((blank = strchr(cp, ' ')) != NULL) { sscanf(blank+1, "%5s", protocol); } tty->farAddr.oa.ia.sin_family = AF_INET; tty->farAddr.oa.ia.sin_port = htons(port); tty->farAddrSize = sizeof(tty->farAddr.oa.ia); tty->flags |= FLAG_NEED_LOOKUP; if ((protocol[0] == '\0') || (epicsStrCaseCmp(protocol, "tcp") == 0)) { tty->socketType = SOCK_STREAM; } else if (epicsStrCaseCmp(protocol, "com") == 0) { isCom = 1; tty->socketType = SOCK_STREAM; } else if (epicsStrCaseCmp(protocol, "http") == 0) { tty->socketType = SOCK_STREAM; tty->flags |= FLAG_CONNECT_PER_TRANSACTION; } else if (epicsStrCaseCmp(protocol, "udp") == 0) { tty->socketType = SOCK_DGRAM; } else if (epicsStrCaseCmp(protocol, "udp*") == 0) { tty->socketType = SOCK_DGRAM; tty->flags |= FLAG_BROADCAST; } else { printf("drvAsynIPPortConfigure: Unknown protocol \"%s\".\n", protocol); ttyCleanup(tty); return -1; } } /* * Link with higher level routines */ pasynInterface = (asynInterface *)callocMustSucceed(2, sizeof *pasynInterface, "drvAsynIPPortConfigure"); tty->common.interfaceType = asynCommonType; tty->common.pinterface = (void *)&drvAsynIPPortAsynCommon; tty->common.drvPvt = tty; if (pasynManager->registerPort(tty->portName, ASYN_CANBLOCK, !noAutoConnect, priority, 0) != asynSuccess) { printf("drvAsynIPPortConfigure: Can't register myself.\n"); ttyCleanup(tty); return -1; } status = pasynManager->registerInterface(tty->portName,&tty->common); if(status != asynSuccess) { printf("drvAsynIPPortConfigure: Can't register common.\n"); ttyCleanup(tty); return -1; } pasynOctet->read = readIt; pasynOctet->write = writeIt; pasynOctet->flush = flushIt; tty->octet.interfaceType = asynOctetType; tty->octet.pinterface = pasynOctet; tty->octet.drvPvt = tty; status = pasynOctetBase->initialize(tty->portName,&tty->octet, 0, 0, 1); if(status != asynSuccess) { printf("drvAsynIPPortConfigure: pasynOctetBase->initialize failed.\n"); ttyCleanup(tty); return -1; } if (isCom && (asynInterposeCOM(tty->portName) != 0)) { printf("drvAsynIPPortConfigure: asynInterposeCOM failed.\n"); ttyCleanup(tty); return -1; } if (!(tty->userFlags & USERFLAG_NO_PROCESS_EOS)) asynInterposeEosConfig(tty->portName, -1, 1, 1); tty->pasynUser = pasynManager->createAsynUser(0,0); status = pasynManager->connectDevice(tty->pasynUser,tty->portName,-1); if(status != asynSuccess) { printf("connectDevice failed %s\n",tty->pasynUser->errorMessage); ttyCleanup(tty); return -1; } /* * Register for socket cleanup */ epicsAtExit(cleanup, tty); return 0; }