int channel_get(Channel *chan) { DEBUGP printf("channel_get %s %s\n", chan->chan_name, chan->valid?"valid":"invalid"); if(! chan->valid) return -1; ca_array_get(chan->chan_type, chan->maxelement, chan->chan_id, chan->dataval); ca_flush_io( ); return 0; }
int channel_put_ackt(Channel *chan, int acknowledge) { short s_acknowledge = acknowledge; int status; if(! chan->valid) return -1; status = ca_array_put( DBR_PUT_ACKT, 1, chan->chan_id, &s_acknowledge); SEVCHK(status, "channel_put : ca_array_put ACKT failed"); ca_flush_io(); return 0; }
int channel_put_acks(Channel *chan, int severity) { short s_severity = severity; int status; if(! chan->valid) return -1; status = ca_array_put( DBR_PUT_ACKS, 1, chan->chan_id, &s_severity); SEVCHK(status, "channel_put : ca_array_put ACKS failed"); ca_flush_io(); return 0; }
void medmSendString(Record *pr, char *data) { int status; Channel *pCh = &((caTask.pages[pr->caId/CA_PAGE_SIZE]) [pr->caId % CA_PAGE_SIZE]); status = ca_put(DBR_STRING,pCh->chid,data); if(status != ECA_NORMAL) { medmPostMsg(1,"medmSendString: ca_put failed: %s\n", ca_message(status)); } ca_flush_io(); }
void medmSendCharacterArray(Record *pr, char *data, unsigned long size) { int status; Channel *pCh = &((caTask.pages[pr->caId/CA_PAGE_SIZE]) [pr->caId % CA_PAGE_SIZE]); status = ca_array_put(DBR_CHAR,size,pCh->chid,data); if(status != ECA_NORMAL) { medmPostMsg(1,"medmSendCharacterArray: ca_put failed: %s\n", ca_message(status)); } ca_flush_io(); }
int channel_put(Channel *chan, int count) { int status; DEBUGP printf("channel_put %s %d %s\n", chan->chan_name, count, chan->valid?"valid":"invalid"); if(! chan->valid) return -1; if( count > chan->maxelement) count = chan->maxelement; status = ca_array_put(chan->chan_type, count, chan->chan_id, chan->dataval); SEVCHK(status, "channel_put : ca_array_put failed"); ca_flush_io(); return 0; }
int channel_put_callback( Channel *chan, int count, CHANNEL_USERFUNC func, void *arg) { int status; DEBUGP printf("channel_put_callback %s %d %s\n", chan->chan_name, count, chan->valid?"valid":"invalid"); if( !chan->valid) return -1; if( count > chan->maxelement) count = chan->maxelement; chan->outstanding = 1; status = ca_array_put_callback( chan->chan_type, count, chan->chan_id, chan->dataval, func, arg); SEVCHK(status, "channel_put_callback : ca_array_put_callback failed"); ca_flush_io(); return 0; }
void medmSendDouble(Record *pr, double data) { int status; Channel *pCh = &((caTask.pages[pr->caId/CA_PAGE_SIZE]) [pr->caId % CA_PAGE_SIZE]); status = ca_put(DBR_DOUBLE,pCh->chid,&data); #if DEBUG_SLIDER if(data > 150.0 || data < -150.0) { print("medmSendDouble: %g\n",data); } #endif if(status != ECA_NORMAL) { medmPostMsg(1,"medmSendDouble: ca_put failed: %s\n", ca_message(status)); } ca_flush_io(); }
/* * create a channel entry, and lookup all details */ Channel * build_PV(char * name) { Channel *chan; int st; chan = (Channel *) calloc( 1, sizeof *chan); if( !chan) return 0; chan->chan_name = strdup(name); chan->initData = 1; chan->createData = 1; chan->monitor = 1; chan->outstanding = 1; st = ca_search_and_connect(name, &(chan->chan_id), connect_callback, chan); DEBUGP printf("ca_search_and_connect = %d\n", st); ca_flush_io(); return chan; }
Channel * init_PV(char *name, chtype chan_type, void *dataptr, int size) { Channel *chan; int st; DEBUGP printf("init_PV(%s, ...)\n", name); chan = (Channel *) calloc( 1, sizeof (Channel)); if( !chan) return 0; DEBUGP printf("Channel Allocated %p\n", chan); chan->chan_name = strdup(name); chan->chan_type = chan_type; chan->dataval = dataptr; chan->maxelement = size; chan->outstanding = 1; st = ca_search_and_connect(name, &(chan->chan_id), connect_callback, chan); DEBUGP printf("ca_search_and_connect = %d\n", st); ca_flush_io(); return chan; }
/* * callback from connection handler: change the state of the channel valid * flag depending on the connection being up or down. * ASSUMPTIONS: chan_id is valid. */ static void connect_callback(struct connection_handler_args args) { Connector *conp; Channel *chan = ca_puser( args.chid); int status; DEBUGP printf("connect callback %p\n", chan); switch( args.op) { case CA_OP_CONN_UP: if( chan->initData == 1) { chan->maxelement = ca_element_count(chan->chan_id); chan->chan_type = ca_field_type(chan->chan_id); chan->initData = 0; } /* * note that a dropped and recreated connection can cause a free and alloc. This * is not always redundant, as software may have restarted with different sizes * for the field! */ if( chan->createData == 1 ) { if( chan->dataval) free( chan->dataval); chan->dataval = calloc(dbr_size[chan->chan_type], chan->maxelement+1); } chan->readAccess = ca_read_access( chan->chan_id); chan->writeAccess = ca_write_access( chan->chan_id); status = ca_array_get_callback( dbf_type_to_DBR_CTRL(ca_field_type(chan->chan_id)), 1, chan->chan_id, getChanInfo, (void*)chan); SEVCHK(status, "connect_callback : ca_get_DBR_CTRL_event failed"); status = ca_replace_access_rights_event( chan->chan_id, getAccessRights); SEVCHK(status, "connect_callback : ca_replace_access_rights_event failed"); chan->valid = 1; chan->outstanding = 0; if( chan->monitor) { chan->status = 100; /* MAGIC: an absurd status */ status = ca_add_array_event(dbf_type_to_DBR_STS(chan->chan_type), chan->maxelement, chan->chan_id, monitorCallback, chan, (double) 0.0, (double) 0.0, (double) 0.0, &(chan->eventId)); SEVCHK(status, "connect_callback : ca_add_event failed"); status = ca_flush_io(); SEVCHK(status, "connect_callback : ca_flush_io failed"); } break; case CA_OP_CONN_DOWN: if( chan->valid && chan->eventId) ca_clear_event(chan->eventId); chan->valid = 0; chan->status = 99; /* * update the access rights and severity for all the connectors */ for(conp=chan->first_connector; conp ; conp=conp->next) { if(conp->newAccess) (*conp->newAccess)(conp); if( conp->newState) (*conp->newState)(conp); } break; default: break; } return; }
int main(int argc,char **argv) { char *pval; double sleepSecs = 0.0; int clearEvery = 0; int indValue = 1; int indNumberCallback = 1; while((argc>1) && (argv[1][0] == '-')) { int i; char option; int narg; option = toupper((argv[1])[1]); pval = argv[2]; argc -= 1; narg = 1; if(option=='S') { sscanf(pval,"%lf",&sleepSecs); argc -= 1; ++narg; } else if(option=='C') { sscanf(pval,"%d",&clearEvery); argc -= 1; ++narg; } else if(option=='V') { verbose = 1; } else { usageExit(); } for(i=1; i<argc; i++) argv[i] = argv[i + narg]; } if(argc != 4) usageExit(); pvname = argv[1]; pvalue1 = argv[2]; pvalue2 = argv[3]; pevent = epicsEventCreate(epicsEventEmpty); SEVCHK(ca_context_create(ca_enable_preemptive_callback), "ca_task_initialize"); while(1) { SEVCHK(ca_search(pvname,&mychid),"ca_search_and_connect"); if(ca_pend_io(3.0)!=ECA_NORMAL) { epicsThreadSleep(5.0); continue; } while(1) { epicsEventWaitStatus status; if(indValue==0) { indValue = 1; pvalue = pvalue2; } else { indValue = 0; pvalue=pvalue1; } if(++indNumberCallback >= MAXnumberCallback) indNumberCallback=0; numberCallback[indNumberCallback] = ++expectedCallback; status = ca_array_put_callback(DBR_STRING,1,mychid, pvalue,putCallback,&numberCallback[indNumberCallback]); if(status!=ECA_NORMAL) { printf("ca_array_put_callback %s\n",ca_message(status)); epicsThreadSleep(2.0); continue; } if((clearEvery>0) && ((expectedCallback % clearEvery)==0)) { ca_flush_io(); epicsThreadSleep(sleepSecs); SEVCHK(ca_clear_channel(mychid),"ca_clear_channel"); ca_flush_io(); expectedCallback = 0; epicsThreadSleep(sleepSecs); if(verbose) { printTime(); printf("Issued ca_clear_channel expectedCallback %d\n", expectedCallback); } break; } ca_flush_io(); if(verbose) { printTime(); printf("Issued ca_put_callback expectedCallback %d\n", expectedCallback); } while(1) { status = epicsEventWaitWithTimeout(pevent,10.0); if(status==epicsEventWaitTimeout) { if(verbose) { printTime(); printf("timeout after 10 seconds\n"); } continue; } break; } if(status!=epicsEventWaitOK) { int i; printTime(); printf("eventWait status %d\n",status); for(i=0; i<MAXnumberCallback; i++) numberCallback[i]=0; } epicsThreadSleep(sleepSecs); } } ca_task_exit(); return(0); }
static void dbCaTask(void *arg) { taskwdInsert(0, NULL, NULL); SEVCHK(ca_context_create(ca_enable_preemptive_callback), "dbCaTask calling ca_context_create"); dbCaClientContext = ca_current_context (); SEVCHK(ca_add_exception_event(exceptionCallback,NULL), "ca_add_exception_event"); epicsEventSignal(startStopEvent); /* channel access event loop */ while (TRUE){ do { epicsEventMustWait(workListEvent); } while (dbCaCtl == ctlPause); while (TRUE) { /* process all requests in workList*/ caLink *pca; short link_action; int status; epicsMutexMustLock(workListLock); if (!(pca = (caLink *)ellGet(&workList))){ /* Take off list head */ epicsMutexUnlock(workListLock); if (dbCaCtl == ctlExit) goto shutdown; break; /* workList is empty */ } link_action = pca->link_action; pca->link_action = 0; if (link_action & CA_CLEAR_CHANNEL) --removesOutstanding; epicsMutexUnlock(workListLock); /* Give back immediately */ if (link_action & CA_CLEAR_CHANNEL) { /* This must be first */ dbCaLinkFree(pca); /* No alarm is raised. Since link is changing so what? */ continue; /* No other link_action makes sense */ } if (link_action & CA_CONNECT) { status = ca_create_channel( pca->pvname,connectionCallback,(void *)pca, CA_PRIORITY_DB_LINKS, &(pca->chid)); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_create_channel %s\n", ca_message(status)); printLinks(pca); continue; } dbca_chan_count++; status = ca_replace_access_rights_event(pca->chid, accessRightsCallback); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask replace_access_rights_event %s\n", ca_message(status)); printLinks(pca); } continue; /*Other options must wait until connect*/ } if (ca_state(pca->chid) != cs_conn) continue; if (link_action & CA_WRITE_NATIVE) { assert(pca->pputNative); if (pca->putType == CA_PUT) { status = ca_array_put( pca->dbrType, pca->nelements, pca->chid, pca->pputNative); } else if (pca->putType==CA_PUT_CALLBACK) { status = ca_array_put_callback( pca->dbrType, pca->nelements, pca->chid, pca->pputNative, putCallback, pca); } else { status = ECA_PUTFAIL; } if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_array_put %s\n", ca_message(status)); printLinks(pca); } epicsMutexMustLock(pca->lock); if (status == ECA_NORMAL) pca->newOutNative = FALSE; epicsMutexUnlock(pca->lock); } if (link_action & CA_WRITE_STRING) { assert(pca->pputString); if (pca->putType == CA_PUT) { status = ca_array_put( DBR_STRING, 1, pca->chid, pca->pputString); } else if (pca->putType==CA_PUT_CALLBACK) { status = ca_array_put_callback( DBR_STRING, 1, pca->chid, pca->pputString, putCallback, pca); } else { status = ECA_PUTFAIL; } if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_array_put %s\n", ca_message(status)); printLinks(pca); } epicsMutexMustLock(pca->lock); if (status == ECA_NORMAL) pca->newOutString = FALSE; epicsMutexUnlock(pca->lock); } /*CA_GET_ATTRIBUTES before CA_MONITOR so that attributes available * before the first monitor callback */ if (link_action & CA_GET_ATTRIBUTES) { status = ca_get_callback(DBR_CTRL_DOUBLE, pca->chid, getAttribEventCallback, pca); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_get_callback %s\n", ca_message(status)); printLinks(pca); } } if (link_action & CA_MONITOR_NATIVE) { size_t element_size; element_size = dbr_value_size[ca_field_type(pca->chid)]; epicsMutexMustLock(pca->lock); pca->pgetNative = dbCalloc(pca->nelements, element_size); epicsMutexUnlock(pca->lock); status = ca_add_array_event( ca_field_type(pca->chid)+DBR_TIME_STRING, ca_element_count(pca->chid), pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_add_array_event %s\n", ca_message(status)); printLinks(pca); } } if (link_action & CA_MONITOR_STRING) { epicsMutexMustLock(pca->lock); pca->pgetString = dbCalloc(1, MAX_STRING_SIZE); epicsMutexUnlock(pca->lock); status = ca_add_array_event(DBR_TIME_STRING, 1, pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_add_array_event %s\n", ca_message(status)); printLinks(pca); } } } SEVCHK(ca_flush_io(), "dbCaTask"); } shutdown: taskwdRemove(0); if (dbca_chan_count == 0) ca_context_destroy(); else fprintf(stderr, "dbCa: chan_count = %d at shutdown\n", dbca_chan_count); epicsEventSignal(startStopEvent); }