Пример #1
0
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;
    }
}
Пример #2
0
/****************************************************************************
 * 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 );
}
Пример #3
0
/* 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);
}
Пример #4
0
/* 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 );			
}
Пример #5
0
/*
 * 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;
            }
        }
    }
Пример #6
0
/* 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));
    }
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
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 );
}
Пример #10
0
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 );
}
Пример #11
0
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 );
}
Пример #12
0
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;
}
Пример #13
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);
}
Пример #14
0
/****************************************************************************
 * 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;
}
Пример #15
0
/* 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);
}
Пример #16
0
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 );
}
Пример #17
0
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 );
}
Пример #18
0
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;
}
Пример #19
0
/*
 * 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;
}
Пример #22
0
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;
}
Пример #23
0
/** 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);
}
Пример #24
0
/*
 * 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;
}