예제 #1
0
static void event_handler (evargs args)
{
  pv* ppv = args.usr;

  ppv->status = args.status;
  if (args.status == ECA_NORMAL)
    {
      ppv->dbrType = args.type;
      ppv->value   = calloc(1, dbr_size_n(args.type, args.count));
      memcpy(ppv->value, args.dbr, dbr_size_n(args.type, args.count));
      ppv->nElems = args.count;
      nRead++;
    }
}
예제 #2
0
void event_handler (evargs args)
{
    pv* pv = args.usr;

    pv->status = args.status;
    if (args.status == ECA_NORMAL)
    {
        pv->dbrType = args.type;
        memcpy(pv->value, args.dbr, dbr_size_n(args.type, args.count));

        print_time_val_sts(pv, pv->reqElems);
        fflush(stdout);
    }
}
예제 #3
0
// extra effort taken here to not hold the lock when calling the callback
void dbContextReadNotifyCache::callReadNotify (
    epicsGuard < epicsMutex > & guard, struct dbChannel * dbch,
	unsigned type, unsigned long count, cacReadNotify & notify )
{
    guard.assertIdenticalMutex ( _mutex );

    if ( type > INT_MAX ) {
        notify.exception ( guard, ECA_BADTYPE,
            "type code out of range (high side)",
            type, count );
        return;
    }

    if ( dbChannelElements(dbch) < 0 ) {
        notify.exception ( guard, ECA_BADCOUNT,
            "database has negetive element count",
            type, count);
        return;
    }

    if ( count > static_cast < unsigned long > ( dbChannelElements(dbch) ) ) {
        notify.exception ( guard, ECA_BADCOUNT,
            "element count out of range (high side)",
            type, count);
        return;
    }

    unsigned long size = dbr_size_n ( type, count );
    privateAutoDestroyPtr ptr ( _allocator, size );
    int status;
    {
        epicsGuardRelease < epicsMutex > unguard ( guard );
        status = dbChannel_get ( dbch, static_cast <int> ( type ),
                    ptr.get (), static_cast <long> ( count ), 0 );
    }
    if ( status ) {
        notify.exception ( guard, ECA_GETFAIL,
            "db_get_field() completed unsuccessfuly",
            type, count );
    }
    else {
        notify.completion (
            guard, type, count, ptr.get () );
    }
}
void syncGroupReadNotify::completion (
    epicsGuard < epicsMutex > & guard, unsigned type,
    arrayElementCount count, const void * pData )
{
    if ( this->magic != CASG_MAGIC ) {
        this->sg.printFormated (
            "cac: sync group io_complete(): bad sync grp op magic number?\n" );
        return;
    }

    if ( this->pValue ) {
        size_t size = dbr_size_n ( type, count );
        memcpy ( this->pValue, pData, size );
    }
    this->sg.completionNotify ( guard, *this );
    this->idIsValid = false;
    this->ioComplete = true;
}
예제 #5
0
void connection_handler ( struct connection_handler_args args )
{
    pv *ppv = ( pv * ) ca_puser ( args.chid );
    if ( args.op == CA_OP_CONN_UP ) {
        int dbrType;
                                /* Set up pv structure */
                                /* ------------------- */

                                /* Get natural type and array count */
        ppv->nElems  = ca_element_count(ppv->chid);
        ppv->dbfType = ca_field_type(ppv->chid);

                                /* Set up value structures */
        dbrType = dbf_type_to_DBR_TIME(ppv->dbfType); /* Use native type */
        if (dbr_type_is_ENUM(dbrType))                  /* Enums honour -n option */
        {
            if (enumAsNr) dbrType = DBR_TIME_INT;
            else          dbrType = DBR_TIME_STRING;
        }
        
        else if (floatAsString &&
                 (dbr_type_is_FLOAT(dbrType) || dbr_type_is_DOUBLE(dbrType)))
        {
            dbrType = DBR_TIME_STRING;
        }
                                /* Adjust array count */
        if (reqElems == 0 || ppv->nElems < reqElems){
            ppv->reqElems = ppv->nElems; /* Use full number of points */
        } else {
            ppv->reqElems = reqElems; /* Limit to specified number */
        }

                                /* Remember dbrType */
        ppv->dbrType  = dbrType;

        ppv->onceConnected = 1;
        nConn++;
                                /* Issue CA request */
                                /* ---------------- */
        /* install monitor once with first connect */
        if ( ! ppv->value ) {
                                    /* Allocate value structure */
            ppv->value = calloc(1, dbr_size_n(dbrType, ppv->reqElems));           
            if ( ppv->value ) {
                ppv->status = ca_create_subscription(dbrType,
                                                ppv->reqElems,
                                                ppv->chid,
                                                eventMask,
                                                event_handler,
                                                (void*)ppv,
                                                NULL);
                if ( ppv->status != ECA_NORMAL ) {
                    free ( ppv->value );
                }
            }
        }
    }
    else if ( args.op == CA_OP_CONN_DOWN ) {
        nConn--;
        ppv->status = ECA_DISCONN;
        print_time_val_sts(ppv, ppv->reqElems);
    }
}
예제 #6
0
void comQueSend::insertRequestWithPayLoad (
    ca_uint16_t request, unsigned dataType, arrayElementCount nElem, 
    ca_uint32_t cid, ca_uint32_t requestDependent, 
    const void * pPayload, bool v49Ok ) 
{
    if ( INVALID_DB_REQ ( dataType ) ) {
        throw cacChannel::badType ();
    }
    if ( dataType >= comQueSendCopyDispatchSize ) {
        throw cacChannel::badType();
    }
    ca_uint32_t size = 0u;
    ca_uint32_t payloadSize = 0u;
    if ( nElem == 1 ) {
        if ( dataType == DBR_STRING  ) {
            const char * pStr = static_cast < const char * >  ( pPayload );
            size = strlen ( pStr ) + 1u;
            if ( size > MAX_STRING_SIZE ) {
                throw cacChannel::outOfBounds();
            }
            payloadSize = CA_MESSAGE_ALIGN ( size );
            this->insertRequestHeader ( request, payloadSize, 
                static_cast <ca_uint16_t> ( dataType ), 
                nElem, cid, requestDependent, v49Ok );
            this->pushString ( pStr, size );  
        }
        else {
            size = dbr_size[dataType];
            payloadSize = CA_MESSAGE_ALIGN ( size );
            this->insertRequestHeader ( request, payloadSize, 
                static_cast <ca_uint16_t> ( dataType ), 
                nElem, cid, requestDependent, v49Ok );
            ( this->*dbrCopyScalar [dataType] ) ( pPayload );
        }
    }
    else {
        arrayElementCount maxBytes;
        if ( v49Ok ) {
            maxBytes = 0xffffffff;
        }
        else {
            maxBytes = MAX_TCP - sizeof ( caHdr ); 
        }
        arrayElementCount maxElem = 
            ( maxBytes - sizeof (dbr_double_t) - dbr_size[dataType] ) / 
                dbr_value_size[dataType];
        if ( nElem >= maxElem ) {
            throw cacChannel::outOfBounds();
        }
        // the above checks verify that the total size
        // is lest that 0xffffffff
        size = static_cast < ca_uint32_t > 
            ( dbr_size_n ( dataType, nElem ) ); // X aCC 392
        payloadSize = CA_MESSAGE_ALIGN ( size );
        this->insertRequestHeader ( request, payloadSize, 
            static_cast <ca_uint16_t> ( dataType ), 
            static_cast < ca_uint32_t > ( nElem ), 
            cid, requestDependent, v49Ok );
        ( this->*dbrCopyVector [dataType] ) ( pPayload, nElem );
    }
    // set pad bytes to nill
    unsigned padSize = payloadSize - size;
    if ( padSize ) {
        this->pushString ( cacNillBytes, payloadSize - size );
    }
}
예제 #7
0
int cagetFuZE(char *pvName, char *pvValue) {

  RequestT request = get;
  OutputT format = plain;
  chtype dbrType = -1;
  unsigned long reqElems = 0;
  int n, result;
  pv* pvs;
  int i;
  unsigned long nElems;
  

  result = ca_context_create(ca_disable_preemptive_callback);

  pvs = calloc(1, sizeof(pv));

  pvs[0].name = pvName;
  
  connect_pvs(pvs, 1);
  
  for (n = 0; n < 1; n++) {
    
    /* Set up pvs structure */
    /* -------------------- */

    /* Get natural type and array count */
    nElems         = ca_element_count(pvs[n].chid);
    pvs[n].dbfType = ca_field_type(pvs[n].chid);
    pvs[n].dbrType = dbrType;

    /* Set up value structures */
    if (format != specifiedDbr)
      {
	pvs[n].dbrType = dbf_type_to_DBR_TIME(pvs[n].dbfType); /* Use native type */
	if (dbr_type_is_ENUM(pvs[n].dbrType))                  /* Enums honour -n option */
	  {
	    if (enumAsNr) pvs[n].dbrType = DBR_TIME_INT;
	    else          pvs[n].dbrType = DBR_TIME_STRING;
	  }
	else if (floatAsString &&
		 (dbr_type_is_FLOAT(pvs[n].dbrType) || dbr_type_is_DOUBLE(pvs[n].dbrType)))
	  {
	    pvs[n].dbrType = DBR_TIME_STRING;
	  }
      }

    /* Issue CA request */
    /* ---------------- */

    if (ca_state(pvs[n].chid) == cs_conn)
      {
  	nConn++;
  	pvs[n].onceConnected = 1;
  	if (request == callback)
  	  {
  	    /* Event handler will allocate value and set nElems */
  	    pvs[n].reqElems = reqElems > nElems ? nElems : reqElems;
  	    result = ca_array_get_callback(pvs[n].dbrType,
  					   pvs[n].reqElems,
  					   pvs[n].chid,
  					   event_handler,
  					   (void*)&pvs[n]);
  	  } else {
  	  /* We allocate value structure and set nElems */
	  pvs[n].nElems = reqElems && reqElems < nElems ? reqElems : nElems;
  	  pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].nElems));
	  if (!pvs[n].value) {
  	    fprintf(stderr,"Memory allocation failed\n");
  	    return -1;
  	  }
  	  result = ca_array_get(pvs[n].dbrType,
  				pvs[n].nElems,
  				pvs[n].chid,
  				pvs[n].value);
  	}
  	pvs[n].status = result;
      } else {
      pvs[n].status = ECA_DISCONN;
    }
  }

  if (!nConn) return -1;              /* No connection? We're done. */

  /* Wait for completion */
  /* ------------------- */

  result = ca_pend_io(caTimeout);
  if (result == ECA_TIMEOUT) {
    fprintf(stderr, "Read operation timed out: some PV data was not read.\n");
    return -1;
  }

  if (request == callback)    /* Also wait for callbacks */
    {
      if (caTimeout != 0)
        {
	  double slice = caTimeout / PEND_EVENT_SLICES;
	  for (n = 0; n < PEND_EVENT_SLICES; n++)
            {
	      ca_pend_event(slice);
	      if (nRead >= nConn) break;
            }
	  if (nRead < nConn) {
	    fprintf(stderr, "Read operation timed out: some PV data was not read.\n");
	    return -1;
	  }
	} else {
	/* For 0 timeout keep waiting until all are done */
	    while (nRead < nConn) {
	      ca_pend_event(1.0);
	    }
      }
    }


  // Does this kill the connection??
  ca_context_destroy();
  
  sprintf(pvValue, "%s\n", val2str(pvs[0].value, pvs[0].dbrType, 0));

  return 1;

}
예제 #8
0
파일: channel.c 프로젝트: Cpppro/acquaman
static void
getChanInfo( struct event_handler_args arg)
{
	Channel *chan;
	// Commented out to avoid comparison warning (David Chevrier, Aug 25 2011)
	//int bytecount;
	unsigned int bytecount;
	InfoBuf_t InfoBuf;

	chan = arg.usr;
	if( chan == NULL)
		return;
	/* make sure we can accept any new data, even if it's in a format
	 * we don't know
	 */
	bytecount = dbr_size_n(arg.type, arg.count);
	if( bytecount > sizeof InfoBuf)
		return;
	memcpy( (void*)&InfoBuf, arg.dbr, bytecount );
	switch( ca_field_type(chan->chan_id) )
	{
	/* DBF_INT: note: this is identical to DBF_SHORT */
	case DBF_SHORT:
		chan->cg.lopr = InfoBuf.ca_short.lower_disp_limit;
		chan->cg.hopr = InfoBuf.ca_short.upper_disp_limit;
		strncpy(chan->cg.units, InfoBuf.ca_short.units, MAX_UNITS_SIZE);
		break;
	case DBF_FLOAT:
		chan->cg.lopr = InfoBuf.ca_float.lower_disp_limit;
		chan->cg.hopr = InfoBuf.ca_float.upper_disp_limit;
		strncpy(chan->cg.units, InfoBuf.ca_float.units, MAX_UNITS_SIZE);
		chan->cg.prec = InfoBuf.ca_float.precision;
		break;
	case DBF_ENUM:
	    {
		int i;

		chan->cg.lopr = 0;
		chan->cg.hopr = InfoBuf.ca_enum.no_str - 1;
		for(i=0; i < MAX_ENUM_STATES; i++)
		{
			if( chan->cg.states[i] == NULL)
				continue;
			free( chan->cg.states[i]);
			chan->cg.states[i] = NULL;
		}
		for(i=0; i <= chan->cg.hopr; i++)
		{
			chan->cg.states[i] = strdup(InfoBuf.ca_enum.strs[i] );
		}
	    }
	    break;
	case DBF_CHAR:
		chan->cg.lopr = InfoBuf.ca_char.lower_disp_limit;
		chan->cg.hopr = InfoBuf.ca_char.upper_disp_limit;
		strncpy(chan->cg.units, InfoBuf.ca_char.units, MAX_UNITS_SIZE);
		break;
	case DBF_LONG:
		chan->cg.lopr = InfoBuf.ca_long.lower_disp_limit;
		chan->cg.hopr = InfoBuf.ca_long.upper_disp_limit;
		strncpy(chan->cg.units, InfoBuf.ca_long.units, MAX_UNITS_SIZE);
		break;
	case DBF_DOUBLE:
		chan->cg.lopr = InfoBuf.ca_double.lower_disp_limit;
		chan->cg.hopr = InfoBuf.ca_double.upper_disp_limit;
		strncpy(chan->cg.units, InfoBuf.ca_double.units, MAX_UNITS_SIZE);
		chan->cg.prec = InfoBuf.ca_double.precision;
		DEBUGP printf("read precision %d units %s\n", chan->cg.prec, chan->cg.units);
		break;
	default:
	    break;
	}
}
예제 #9
0
int caget (pv *pvs, int nPvs, OutputT format,
           chtype dbrType, unsigned long reqElems)
{
    unsigned int i;
    int n, result;

    for (n = 0; n < nPvs; n++) {

                                /* Set up pvs structure */
                                /* -------------------- */

                                /* Get natural type and array count */
        pvs[n].nElems  = ca_element_count(pvs[n].chid);
        pvs[n].dbfType = ca_field_type(pvs[n].chid);
        pvs[n].dbrType = dbrType;

                                /* Set up value structures */
        pvs[n].dbrType = dbf_type_to_DBR_TIME(pvs[n].dbfType); /* Use native type */
        if (dbr_type_is_ENUM(pvs[n].dbrType))             /* Enums honour -n option */
        {
            if (enumAsNr) pvs[n].dbrType = DBR_TIME_INT;
            else          pvs[n].dbrType = DBR_TIME_STRING;
        }

        if (reqElems == 0 || pvs[n].nElems < reqElems)    /* Adjust array count */
            pvs[n].reqElems = pvs[n].nElems;
        else
            pvs[n].reqElems = reqElems;

                                /* Issue CA request */
                                /* ---------------- */

        if (ca_state(pvs[n].chid) == cs_conn)
        {
            nConn++;
            pvs[n].onceConnected = 1;
                                   /* Allocate value structure */
            pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].reqElems));
            if(!pvs[n].value){
                fprintf(stderr,"Allocation failed\n");
                exit(1);
            }
            result = ca_array_get(pvs[n].dbrType,
                                  pvs[n].reqElems,
                                  pvs[n].chid,
                                  pvs[n].value);
            pvs[n].status = result;
        } else {
            pvs[n].status = ECA_DISCONN;
        }
    }
    if (!nConn) return 1;              /* No connection? We're done. */

                                /* Wait for completion */
                                /* ------------------- */

    result = ca_pend_io(caTimeout);
    if (result == ECA_TIMEOUT)
        fprintf(stderr, "Read operation timed out: PV data was not read.\n");

                                /* Print the data */
                                /* -------------- */

    for (n = 0; n < nPvs; n++) {

        switch (format) {
        case plain:             /* Emulate old caput behaviour */
            if (pvs[n].reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name);
            else                                               printf("%s", pvs[n].name);
            printf("%c", fieldSeparator);
        case terse:
            if (pvs[n].status == ECA_DISCONN)
                printf("*** not connected\n");
            else if (pvs[n].status == ECA_NORDACCESS)
                printf("*** no read access\n");
            else if (pvs[n].status != ECA_NORMAL)
                printf("*** CA error %s\n", ca_message(pvs[n].status));
            else if (pvs[n].value == 0)
                printf("*** no data available (timeout)\n");
            else
            {
                if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) {
                    dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType);
                    int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s));
                    char *d = calloc(dlen+1, sizeof(char));
                    if(!d){
                        fprintf(stderr,"Allocation failed\n");
                        exit(1);
                    }
                    epicsStrnEscapedFromRaw(d, dlen+1, (char*)s, strlen((char*)s));
                    printf("%s", d);
                    free(d);
                } else {
                    if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].reqElems, fieldSeparator);
                    for (i=0; i<pvs[n].reqElems; ++i) {
                        if (i) printf ("%c", fieldSeparator);
                        printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i));
                    }
                }
                printf("\n");
            }
            break;
        case all:
            print_time_val_sts(&pvs[n], reqElems);
            break;
        default :
            break;
        }
    }
    return 0;
}
예제 #10
0
static void medmUpdateChannelCb(struct event_handler_args args) {
    Channel *pCh = (Channel *)ca_puser(args.chid);
    Boolean statusChanged = False;
    Boolean severityChanged = False;
    Boolean zeroAndNoneZeroTransition = False;
    Record *pr;
    double value;
    int nBytes;
    int allocBytes;

#if DEBUG_CHANNEL_CB || DEBUG_LARGE_ARRAY
    const char *pvname=ca_name(args.chid);
    print("medmUpdateChannelCb: %s\n",pvname);
    if(args.status != ECA_NORMAL) {
	char buf[80];
	envGetConfigParam(&EPICS_CA_MAX_ARRAY_BYTES,80,buf);
	buf[79]='\0';
	print("EPICS_CA_MAX_ARRAY_BYTES: %s\n",buf);
    }
#endif

  /* Increment the event counter */
    caTask.caEventCount++;

  /* Check for valid values */
  /* Same as for updateGraphicalInfoCb */
  /* Don't need to check for read access, checking ECA_NORMAL is enough */
    if(globalDisplayListTraversalMode != DL_EXECUTE) return;
    if(args.status != ECA_NORMAL) {
	medmPostMsg(0,"medmUpdateChannelCb: Bad status [%d] for %s: %s\n",
	  args.status,
	  ca_name(args.chid)?ca_name(args.chid):"Name Unknown",
	  ca_message(args.status));
	return;
    }
    if(!args.dbr) {
	medmPostMsg(0,"medmUpdateChannelCb: Invalid data for [%s]\n",
	  ca_name(args.chid)?ca_name(args.chid):"Name Unknown");
	return;
    }
    if(!pCh || !pCh->chid || !pCh->pr) {
	medmPostMsg(0,"medmUpdateChannelCb: "
	  "Invalid channel information for [%s]\n",
	  ca_name(args.chid)?ca_name(args.chid):"Name Unknown");
	return;
    }
    if(pCh->chid != args.chid) {
	medmPostMsg(0,"medmUpdateChannelCb: chid from args [%x] "
	  "does not match chid from channel [%x]\n"
	  "  [%s]\n",
	  args.chid,
	  pCh->chid,
	  ca_name(args.chid)?ca_name(args.chid):"Name Unknown");
	return;
    }
    pr = pCh->pr;

  /* Allocate space for the data */
    nBytes = dbr_size_n(args.type, args.count);
    if(!pCh->data) {
        /* Allocate maximum space for the variable array data */
        if(pr->currentCount == -2) {
            allocBytes=dbr_size_n(args.type, pr->elementCount);
        } else {
            allocBytes=nBytes;
        }
      /* No previous data, allocate */
	pCh->data = (dataBuf *)malloc(allocBytes);
	pCh->size = allocBytes;
	if(!pCh->data) {
	    medmPostMsg(1,"medmUpdateChannelCb: Memory allocation error [%s]\n",
	      ca_name(args.chid)?ca_name(args.chid):"Name Unknown");
	    return;
	}
    } else if(pCh->size < nBytes) {
      /* Previous data exists but is too small
       * Free it and allocate it again */
	free((char *)pCh->data);
	pCh->data = (dataBuf *)malloc(nBytes);
	pCh->size = nBytes;
	if(pCh->data == NULL) {
	    medmPostMsg(1,"medmUpdateChannelCb: Memory reallocation error"
	      " [%s]\n",
	      ca_name(args.chid)?ca_name(args.chid):"Name Unknown");
	    return;
	}
    }
    pr->currentCount=args.count;

#ifdef __USING_TIME_STAMP__
  /* Copy the returned time stamp to the Record */
    pr->time = ((dataBuf *)args.dbr)->s.stamp;
#endif


  /* Set the array pointer in the Record to point to the value member of the
   *   appropriate struct stored in the Channel
   * (The returned data is not stored there yet) */
    switch (ca_field_type(args.chid)) {
    case DBF_STRING:
	pr->array = (XtPointer)pCh->data->s.value;
	break;
    case DBF_ENUM:
	pr->array = (XtPointer)&(pCh->data->e.value);
	break;
    case DBF_CHAR:
	pr->array = (XtPointer)&(pCh->data->c.value);
	break;
    case DBF_INT:
	pr->array = (XtPointer)&(pCh->data->i.value);
	break;
    case DBF_LONG:
	pr->array = (XtPointer)&(pCh->data->l.value);
	break;
    case DBF_FLOAT:
	pr->array = (XtPointer)&(pCh->data->f.value);
	break;
    case DBF_DOUBLE:
	pr->array = (XtPointer)&(pCh->data->d.value);
	break;
    default:
	break;
    }

  /* For strings and arrays copy the returned data to the Channel
   * (The space is allocated but the data is not stored otherwise) */
    if(ca_field_type(args.chid) == DBF_STRING ||
      ca_element_count(args.chid) > 1) {
	memcpy((void *)pCh->data, args.dbr, nBytes);
    }

  /* Copy the value from the returned data to the Record */
    switch (ca_field_type(args.chid)) {
    case DBF_STRING:
	value = 0.0;
	break;
    case DBF_ENUM:
	value = (double)((dataBuf *)(args.dbr))->e.value;
	break;
    case DBF_CHAR:
	value = (double)((dataBuf *)(args.dbr))->c.value;
	break;
    case DBF_INT:
	value = (double)((dataBuf *)(args.dbr))->i.value;
	break;
    case DBF_LONG:
	value = (double)((dataBuf *)(args.dbr))->l.value;
	break;
    case DBF_FLOAT:
	value = (double)((dataBuf *)(args.dbr))->f.value;
	break;
    case DBF_DOUBLE:
	value = ((dataBuf *)(args.dbr))->d.value;
#if DEBUG_SLIDER
	if(value > 150.0 || value < -150.0) {
	    print("medmUpdateChannelCb: %g\n",value);
	}
#endif
	break;
    default:
	value = 0.0;
	break;
    }

  /* Mark zero to nonzero transition */
    if(((value == 0.0) && (pr->value != 0.0)) ||
      ((value != 0.0) && (pr->value == 0.0)))
      zeroAndNoneZeroTransition = True;

  /* Mark status changed */
    if(pr->status != ((dataBuf *)(args.dbr))->d.status) {
	pr->status = ((dataBuf *)(args.dbr))->d.status;
	statusChanged = True;
    }

  /* Mark severity changed */
    if(pr->severity != ((dataBuf *)(args.dbr))->d.severity) {
	pr->severity = ((dataBuf *)(args.dbr))->d.severity;
	severityChanged = True;
    }

  /* Set the new value into the record */
    pr->value = value;

#if DEBUG_ERASE
    print("medmUpdateChannelCb: [%x]%s %g\n",
      pr, pr->name, pr->value);
#endif

  /* Call the update value callback if there is a monitored change */
    if(pCh->pr->updateValueCb) {
	if(pr->monitorValueChanged) {
	    pr->updateValueCb((XtPointer)pr);
	} else if(pr->monitorStatusChanged && statusChanged) {
	    pr->updateValueCb((XtPointer)pr);
	} else if(pr->monitorSeverityChanged && severityChanged) {
	    pr->updateValueCb((XtPointer)pr);
	} else if(pr->monitorZeroAndNoneZeroTransition &&
	  zeroAndNoneZeroTransition) {
	    pr->updateValueCb((XtPointer)pr);
	}
    }
}
예제 #11
0
static void medmUpdateGraphicalInfoCb(struct event_handler_args args) {
    int nBytes;
    int i;
    Channel *pCh = (Channel *)ca_puser(args.chid);
    Record *pr;

  /* Increment the event counter */
    caTask.caEventCount++;

  /* Check for valid values */
  /* Same as for updateChannelCb */
  /* Don't need to check for read access, checking ECA_NORMAL is enough */
    if(globalDisplayListTraversalMode != DL_EXECUTE) return;
    if(args.status != ECA_NORMAL) return;
    if(!args.dbr) {
	medmPostMsg(0,"medmUpdateGraphicalInfoCb: Invalid data [%s]\n",
	  ca_name(args.chid)?ca_name(args.chid):"Name Unknown");
	return;
    }
    if(!pCh || !pCh->chid || !pCh->pr) {
	medmPostMsg(0,"medmUpdateGraphicalInfoCb: Invalid channel information [%s]\n",
	  ca_name(args.chid)?ca_name(args.chid):"Name Unknown");
	return;
    }
    if(pCh->chid != args.chid) {
	medmPostMsg(0,"medmUpdateGraphicalInfoCb: chid from args [%x] "
	  "does not match chid from channel [%x]\n"
	  "  [%s]\n",
	  args.chid,
	  pCh->chid,
	  ca_name(args.chid)?ca_name(args.chid):"Name Unknown");
	return;
    }
    pr = pCh->pr;

  /* Copy the information to the Channel struct */
    nBytes = dbr_size_n(args.type, args.count);
    memcpy((void *)&(pCh->info),args.dbr,nBytes);

  /* Handle hopr, lopr, and precision */
    switch (ca_field_type(args.chid)) {
    case DBF_STRING:
	pr->value = 0.0;
	pr->hopr = 0.0;
	pr->lopr = 0.0;
	pr->precision = 0;
	break;
    case DBF_ENUM:
	pr->value = (double) pCh->info.e.value;
	pr->hopr = (double) pCh->info.e.no_str - 1.0;
	pr->lopr = 0.0;
	pr->precision = 0;
	for (i = 0; i < pCh->info.e.no_str; i++) {
	    pr->stateStrings[i] = pCh->info.e.strs[i];
	}
	break;
    case DBF_CHAR:
	pr->value = (double) pCh->info.c.value;
	pr->hopr = (double) pCh->info.c.upper_disp_limit;
	pr->lopr = (double) pCh->info.c.lower_disp_limit;
	pr->precision = 0;
	break;
    case DBF_INT:
	pr->value = (double) pCh->info.i.value;
	pr->hopr = (double) pCh->info.i.upper_disp_limit;
	pr->lopr = (double) pCh->info.i.lower_disp_limit;
	pr->precision = 0;
	break;
    case DBF_LONG:
	pr->value = (double) pCh->info.l.value;
	pr->hopr = (double) pCh->info.l.upper_disp_limit;
	pr->lopr = (double) pCh->info.l.lower_disp_limit;
	pr->precision = 0;
	break;
    case DBF_FLOAT:
	pr->value = (double) pCh->info.f.value;
	pr->hopr = (double) pCh->info.f.upper_disp_limit;
	pr->lopr = (double) pCh->info.f.lower_disp_limit;
	pr->precision = pCh->info.f.precision;
	break;
    case DBF_DOUBLE:
	pr->value = (double) pCh->info.d.value;
	pr->hopr = (double) pCh->info.d.upper_disp_limit;
	pr->lopr = (double) pCh->info.d.lower_disp_limit;
	pr->precision = pCh->info.f.precision;
	break;
    default:
	medmPostMsg(0,"medmUpdateGraphicalInfoCb: Unknown data type\n");
	return;
    }

  /* Adjust the precision */
    if(pr->precision < 0) {
	medmPostMsg(0,"medmUpdateGraphicalInfoCb: "
	  "pv = \"%s\" precision = %d\n",
	  ca_name(pCh->chid), pr->precision);
	pr->precision = 0;
    } else if(pr->precision > 17) {
	medmPostMsg(1,"medmUpdateGraphicalInfoCb: "
	  "pv = \"%s\" precision = %d\n",
	  ca_name(pCh->chid), pr->precision);
	pr->precision = 17;
    }

  /* Call the record's graphical info callback or its update value callback */
    if(pr->updateGraphicalInfoCb) {
	pr->updateGraphicalInfoCb((XtPointer)pr);
    } else if(pr->updateValueCb) {
	pr->updateValueCb((XtPointer)pr);
    }
}