static void interruptCallbackOutput(void *drvPvt, asynUser *pasynUser, epicsFloat64 value) { devPvt *pPvt = (devPvt *)drvPvt; dbCommon *pr = pPvt->pr; ringBufferElement *rp; asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynFloat64::interruptCallbackOutput new value=%f\n", pr->name, value); if (!interruptAccept) return; epicsMutexLock(pPvt->ringBufferLock); rp = &pPvt->ringBuffer[pPvt->ringHead]; rp->value = value; rp->time = pasynUser->timestamp; rp->status = pasynUser->auxStatus; rp->alarmStatus = pasynUser->alarmStatus; rp->alarmSeverity = pasynUser->alarmSeverity; pPvt->ringHead = (pPvt->ringHead==pPvt->ringSize) ? 0 : pPvt->ringHead+1; if (pPvt->ringHead == pPvt->ringTail) { pPvt->ringTail = (pPvt->ringTail==pPvt->ringSize) ? 0 : pPvt->ringTail+1; pPvt->ringBufferOverflows++; } else { scanOnce(pr); } epicsMutexUnlock(pPvt->ringBufferLock); }
void scanShutdown(void) { int i; if (scanCtl == ctlExit) return; scanCtl = ctlExit; interruptAccept = FALSE; for (i = 0; i < nPeriodic; i++) { papPeriodic[i]->scanCtl = ctlExit; epicsEventSignal(papPeriodic[i]->loopEvent); epicsEventWait(startStopEvent); } scanOnce((dbCommon *)&exitOnce); epicsEventWait(startStopEvent); deletePeriodic(); ioscanDestroy(); epicsRingPointerDelete(onceQ); epicsEventDestroy(startStopEvent); epicsEventDestroy(onceSem); onceSem = startStopEvent = NULL; free(periodicTaskId); papPeriodic = NULL; periodicTaskId = NULL; }
static void interruptCallbackOutput(void *drvPvt, asynUser *pasynUser, epicsInt32 value) { devInt32Pvt *pPvt = (devInt32Pvt *)drvPvt; dbCommon *pr = pPvt->pr; ringBufferElement *rp; if (pPvt->mask) { value &= pPvt->mask; if (pPvt->bipolar && (value & pPvt->signBit)) value |= ~pPvt->mask; } asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynInt32::interruptCallbackOutput new value=%d\n", pr->name, value); if (!interruptAccept) return; epicsMutexLock(pPvt->ringBufferLock); rp = &pPvt->ringBuffer[pPvt->ringHead]; rp->value = value; rp->time = pasynUser->timestamp; rp->status = pasynUser->auxStatus; pPvt->ringHead = (pPvt->ringHead==pPvt->ringSize) ? 0 : pPvt->ringHead+1; if (pPvt->ringHead == pPvt->ringTail) { pPvt->ringTail = (pPvt->ringTail==pPvt->ringSize) ? 0 : pPvt->ringTail+1; pPvt->ringBufferOverflows++; } else { scanOnce(pr); } epicsMutexUnlock(pPvt->ringBufferLock); }
static void accessRightsCallback(struct access_rights_handler_args arg) { caLink *pca = (caLink *)ca_puser(arg.chid); struct link *plink; struct pv_link *ppv_link; dbCommon *precord; assert(pca); if (ca_state(pca->chid) != cs_conn) return; /* connectionCallback will handle */ epicsMutexMustLock(pca->lock); plink = pca->plink; if (!plink) goto done; pca->hasReadAccess = ca_read_access(arg.chid); pca->hasWriteAccess = ca_write_access(arg.chid); if (pca->hasReadAccess && pca->hasWriteAccess) goto done; ppv_link = &plink->value.pv_link; precord = ppv_link->precord; if (precord && ((ppv_link->pvlMask & pvlOptCP) || ((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0))) scanOnce(precord); done: epicsMutexUnlock(pca->lock); }
static void liSrqHandler(void *userPrivate,asynUser *pasynUser, epicsInt32 statusByte) { longinRecord *pli = (longinRecord *)userPrivate; gpibDpvt *pgpibDpvt = gpibDpvtGet(pli); pli->val = statusByte; pli->udf = FALSE; scanOnce(pgpibDpvt->precord); }
/* We need to know when a save or restore operation has completed, so client software * can wait for the operation to complete before acting on the result. */ void configMenuCallback(int status, void *puserPvt) { aSubRecord *pasub = (aSubRecord *)puserPvt; epicsInt32 *d = (epicsInt32 *)pasub->d; if (configMenuDebug) printf("configMenuCallback:status=%d, puserPvt=%p\n", status, puserPvt); dbScanLock((dbCommon *)pasub); *d = (epicsInt32)status; dbScanUnlock((dbCommon *)pasub); scanOnce((dbCommon *)puserPvt); }
/* Callback for bo, see ao_callback comments */ static void check_bo_callback(void *arg) { boRecord *rec = (boRecord *) arg; struct rset *rset= (struct rset *)(rec->rset); DevicePrivate *pvt = (DevicePrivate *)rec->dpvt; unsigned long rval; eip_bool process = false; /* We are about the check and even set val, & rval -> lock */ dbScanLock((dbCommon *)rec); if (rec->pact) { (*rset->process) ((dbCommon *)rec); dbScanUnlock((dbCommon *)rec); return; } /* Check if record's (R)VAL is current */ if (!check_data((dbCommon *) rec)) { (*rset->process) ((dbCommon *)rec); dbScanUnlock((dbCommon *)rec); return; } if (get_bits((dbCommon *)rec, 1, &rval) && (rec->udf || rec->sevr == INVALID_ALARM || rec->rval != rval)) { if (rec->tpro) printf("'%s': got %lu from driver\n", rec->name, rval); if (!rec->udf && pvt->special & SPCO_FORCE) { if (rec->tpro) printf("'%s': will re-write record's value %u\n", rec->name, (unsigned int)rec->val); } else { /* back-convert rval into val */ rec->rval = rval; rec->val = (rec->rval==0) ? 0 : 1; rec->udf = false; if (rec->tpro) printf("'%s': updated record to tag, val = %u\n", rec->name, (unsigned int)rec->val); } process = true; } dbScanUnlock((dbCommon *)rec); /* Does record need processing and is not periodic? */ if (process && rec->scan < SCAN_1ST_PERIODIC) scanOnce(rec); }
void recGblFwdLink(void *precord) { dbCommon *pdbc = precord; dbScanFwdLink(&pdbc->flnk); /*Handle dbPutFieldNotify record completions*/ if(pdbc->ppn) dbNotifyCompletion(pdbc); if(pdbc->rpro) { /*If anyone requested reprocessing do it*/ pdbc->rpro = FALSE; scanOnce(pdbc); } /*In case putField caused put we are all done */ pdbc->putf = FALSE; }
static void interruptCallbackOutput(void *drvPvt, asynUser *pasynUser, epicsInt32 value) { devInt32Pvt *pPvt = (devInt32Pvt *)drvPvt; dbCommon *pr = pPvt->pr; int count, size = sizeof(epicsInt32); asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynInt32::interruptCallbackOutput new value=%d\n", pr->name, value); epicsMutexLock(pPvt->mutexId); count = epicsRingBytesPut(pPvt->ringBuffer, (char *)&value, size); if (count != size) { pPvt->ringBufferOverflows++; } epicsMutexUnlock(pPvt->mutexId); scanOnce(pr); }
static void testRTT() { wifi_scan_result results[256]; int num_results = scanOnce(WIFI_BAND_ABG, results, countof(results)); if (num_results == 0) { printMsg("RTT aborted because of no scan results\n"); return; } else { printMsg("Retrieved %d scan results\n", num_results); } num_results = removeDuplicateScanResults(results, num_results); /* printMsg("Deduped scan results - %d\n", num_results); for (int i = 0; i < num_results; i++) { printScanResult(results[i]); } */ sortScanResultsByRssi(results, num_results); printMsg("Sorted scan results -\n"); for (int i = 0; i < num_results; i++) { printScanResult(results[i]); } static const int max_ap = 5; wifi_rtt_config params[max_ap]; memset(params, 0, sizeof(params)); printMsg("Configuring RTT for %d APs, num_samples = %d\n", min(num_results, max_ap), rtt_samples); unsigned num_ap = 0; for (int i = 0; i < min(num_results, max_ap); i++, num_ap++) { memcpy(params[i].addr, results[i].bssid, sizeof(mac_addr)); mac_addr &addr = params[i].addr; printMsg("Adding %02x:%02x:%02x:%02x:%02x:%02x (%d) for RTT\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], results[i].channel); params[i].type = RTT_TYPE_1_SIDED; params[i].channel.center_freq = results[i].channel; params[i].channel.width = WIFI_CHAN_WIDTH_20; params[i].peer = WIFI_PEER_INVALID; params[i].continuous = 1; params[i].interval = 1000; params[i].num_samples_per_measurement = rtt_samples; params[i].num_retries_per_measurement = 10; } wifi_rtt_event_handler handler; handler.on_rtt_results = &onRTTResults; int result = wifi_rtt_range_request(rttCmdId, wlan0Handle, num_ap, params, handler); if (result == WIFI_SUCCESS) { printMsg("Waiting for RTT results\n"); while (true) { EventInfo info; memset(&info, 0, sizeof(info)); getEventFromCache(info); if (info.type == EVENT_TYPE_SCAN_RESULTS_AVAILABLE) { retrieveScanResults(); } else if (info.type == EVENT_TYPE_RTT_RESULTS) { break; } } } else { printMsg("Could not set setRTTAPs : %d\n", result); } }
/* Callback for mbbo */ static void check_mbbo_callback(void *arg) { mbboRecord *rec = (mbboRecord *) arg; struct rset *rset= (struct rset *)(rec->rset); DevicePrivate *pvt = (DevicePrivate *)rec->dpvt; unsigned long rval, *state_val; size_t i; eip_bool process = false; /* We are about the check and even set val, & rval -> lock */ dbScanLock((dbCommon *)rec); if (rec->pact) { (*rset->process) ((dbCommon *)rec); dbScanUnlock((dbCommon *)rec); return; } /* Check if record's (R)VAL is current */ if (!check_data ((dbCommon *) rec)) { (*rset->process) ((dbCommon *)rec); dbScanUnlock((dbCommon *)rec); return; } if (get_bits ((dbCommon *)rec, rec->nobt, &rval) && (rec->udf || rec->sevr == INVALID_ALARM || rec->rval != rval)) { if (rec->tpro) printf("'%s': got %lu from driver\n", rec->name, rval); if (!rec->udf && pvt->special & SPCO_FORCE) { if (rec->tpro) printf("'%s': will re-write record's rval 0x%X\n", rec->name, (unsigned int)rec->rval); } else { /* back-convert rval into val */ if (rec->sdef) { rec->val = 65535; /* initalize to unknown state*/ state_val = &rec->zrvl; for (i=0; i<16; ++i) { if (*state_val == rval) { rec->val = i; break; } state_val++; } rec->udf = false; } else { /* the raw value is the desired val */ rec->val = (unsigned short)rval; rec->udf = false; } if (rec->tpro) printf("--> val = %u\n", (unsigned int)rec->val); } process = true; } dbScanUnlock((dbCommon *)rec); /* Does record need processing and is not periodic? */ if (process && rec->scan < SCAN_1ST_PERIODIC) scanOnce (rec); }
/* Callback from driver for every received tag, for ao record: * Check if * * 1) pact set -> this is the "finshed the write" callback * 2) pact not set -> this is the "new value" callback * Tag value is either different from current record value * or there is no current record value: * 2a) disconnected; process record to set WRITE/INVALID * 2b) PLC's value != record's idea of the current value * 2c) record is UDF, so this is the first time we get a value * from the PLC after a reboot * Causing process if necessary to update the record. * That process()/scanOnce() call should NOT cause the record to write * to the PLC because the xxx_write method will notice that * the PLC and record value agree. * It will, however, trigger CA monitors. * * Problem: Alarms are handled before "write_xx" is called. * So we have to set udf in here, * then process() can recognize udf and finally it will * call write_xx. */ static void check_ao_callback(void *arg) { aoRecord *rec = (aoRecord *) arg; struct rset *rset= (struct rset *)(rec->rset); DevicePrivate *pvt = (DevicePrivate *)rec->dpvt; double dbl; CN_DINT dint; eip_bool process = false; /* We are about the check and even set val, & rval -> lock */ dbScanLock((dbCommon *)rec); if (rec->pact) { if (rec->tpro) printf("EIP check_ao_callback('%s'), pact=%d\n", rec->name, rec->pact); (*rset->process) ((dbCommon *)rec); dbScanUnlock((dbCommon *)rec); return; } /* Check if record's (R)VAL is current */ if (!check_data((dbCommon *)rec)) { if (rec->tpro) printf("EIP check_ao_callback('%s'), no data\n", rec->name); (*rset->process) ((dbCommon *)rec); dbScanUnlock((dbCommon *)rec); return; } if (get_CIP_typecode(pvt->tag->data) == T_CIP_REAL) { if (rec->tpro) printf("EIP check_ao_callback('%s') w/ real data\n", rec->name); if (get_CIP_double(pvt->tag->data, pvt->element, &dbl) && (rec->udf || rec->sevr == INVALID_ALARM || rec->val != dbl)) { if (rec->tpro) printf("'%s': got %g from driver\n", rec->name, dbl); if (!rec->udf && pvt->special & SPCO_FORCE) { if (rec->tpro) printf("'%s': will re-write record's value %g\n", rec->name, rec->val); } else { rec->val = rec->pval = dbl; rec->udf = false; if (rec->tpro) printf("'%s': updated record's value %g\n", rec->name, rec->val); } process = true; } } else { if (rec->tpro) printf("EIP check_ao_callback('%s') w/ int. data\n", rec->name); if (get_CIP_DINT(pvt->tag->data, pvt->element, &dint) && (rec->udf || rec->sevr == INVALID_ALARM || rec->rval != dint)) { if (rec->tpro) printf("AO '%s': got %ld from driver\n", rec->name, (long)dint); if (!rec->udf && pvt->special & SPCO_FORCE) { if (rec->tpro) printf("AO '%s': will re-write record's rval 0x%X\n", rec->name, (unsigned int)rec->rval); } else { /* back-convert raw value into val (copied from ao init) */ dbl = (double)dint + (double)rec->roff; if (rec->aslo!=0.0) dbl *= rec->aslo; dbl += rec->aoff; switch (rec->linr) { case menuConvertNO_CONVERSION: rec->val = rec->pval = dbl; rec->udf = false; break; case menuConvertLINEAR: case menuConvertSLOPE: dbl = dbl*rec->eslo + rec->eoff; rec->val = rec->pval = dbl; rec->udf = false; break; default: if (cvtRawToEngBpt(&dbl,rec->linr,rec->init, (void *)&rec->pbrk, &rec->lbrk)!=0) break; /* cannot back-convert */ rec->val = rec->pval = dbl; rec->udf = false; } if (rec->tpro) printf("'%s': updated record's value to %g\n", rec->name, rec->val); } process = true; } } dbScanUnlock((dbCommon *)rec); /* Does record need processing and is not periodic? */ if (process && rec->scan < SCAN_1ST_PERIODIC) scanOnce(rec); }
static void eventCallback(struct event_handler_args arg) { caLink *pca = (caLink *)arg.usr; struct link *plink; size_t size; dbCommon *precord = 0; struct dbr_time_double *pdbr_time_double; dbCaCallback monitor = 0; void *userPvt = 0; assert(pca); epicsMutexMustLock(pca->lock); plink = pca->plink; if (!plink) goto done; monitor = pca->monitor; userPvt = pca->userPvt; precord = plink->value.pv_link.precord; if (arg.status != ECA_NORMAL) { if (precord) { if (arg.status != ECA_NORDACCESS && arg.status != ECA_GETFAIL) errlogPrintf("dbCa: eventCallback record %s error %s\n", precord->name, ca_message(arg.status)); } else { errlogPrintf("dbCa: eventCallback error %s\n", ca_message(arg.status)); } goto done; } assert(arg.dbr); size = arg.count * dbr_value_size[arg.type]; if (arg.type == DBR_TIME_STRING && ca_field_type(pca->chid) == DBR_ENUM) { assert(pca->pgetString); memcpy(pca->pgetString, dbr_value_ptr(arg.dbr, arg.type), size); pca->gotInString = TRUE; } else switch (arg.type){ case DBR_TIME_STRING: case DBR_TIME_SHORT: case DBR_TIME_FLOAT: case DBR_TIME_ENUM: case DBR_TIME_CHAR: case DBR_TIME_LONG: case DBR_TIME_DOUBLE: assert(pca->pgetNative); memcpy(pca->pgetNative, dbr_value_ptr(arg.dbr, arg.type), size); pca->gotInNative = TRUE; break; default: errMessage(-1, "dbCa: eventCallback Logic Error\n"); break; } pdbr_time_double = (struct dbr_time_double *)arg.dbr; pca->sevr = pdbr_time_double->severity; pca->stat = pdbr_time_double->status; memcpy(&pca->timeStamp, &pdbr_time_double->stamp, sizeof(epicsTimeStamp)); if (precord) { struct pv_link *ppv_link = &plink->value.pv_link; if ((ppv_link->pvlMask & pvlOptCP) || ((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0)) scanOnce(precord); } done: epicsMutexUnlock(pca->lock); if (monitor) monitor(userPvt); }
static void connectionCallback(struct connection_handler_args arg) { caLink *pca; short link_action = 0; struct link *plink; pca = ca_puser(arg.chid); assert(pca); epicsMutexMustLock(pca->lock); plink = pca->plink; if (!plink) goto done; pca->isConnected = (ca_state(arg.chid) == cs_conn); if (!pca->isConnected) { struct pv_link *ppv_link = &plink->value.pv_link; dbCommon *precord = ppv_link->precord; pca->nDisconnect++; if (precord && ((ppv_link->pvlMask & pvlOptCP) || ((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0))) scanOnce(precord); goto done; } pca->hasReadAccess = ca_read_access(arg.chid); pca->hasWriteAccess = ca_write_access(arg.chid); if (pca->gotFirstConnection) { if (pca->nelements != ca_element_count(arg.chid) || pca->dbrType != ca_field_type(arg.chid)) { /* BUG: We have no way to clear any old subscription with the * originally chosen data type/size. That will continue * to send us data and will result in an assert() fail. */ /* Let next dbCaGetLink and/or dbCaPutLink determine options */ plink->value.pv_link.pvlMask &= ~(pvlOptInpNative | pvlOptInpString | pvlOptOutNative | pvlOptOutString); pca->gotInNative = 0; pca->gotOutNative = 0; pca->gotInString = 0; pca->gotOutString = 0; free(pca->pgetNative); pca->pgetNative = 0; free(pca->pgetString); pca->pgetString = 0; free(pca->pputNative); pca->pputNative = 0; free(pca->pputString); pca->pputString = 0; } } pca->gotFirstConnection = TRUE; pca->nelements = ca_element_count(arg.chid); pca->dbrType = ca_field_type(arg.chid); if ((plink->value.pv_link.pvlMask & pvlOptInpNative) && !pca->pgetNative) { link_action |= CA_MONITOR_NATIVE; } if ((plink->value.pv_link.pvlMask & pvlOptInpString) && !pca->pgetString) { link_action |= CA_MONITOR_STRING; } if ((plink->value.pv_link.pvlMask & pvlOptOutNative) && pca->gotOutNative) { link_action |= CA_WRITE_NATIVE; } if ((plink->value.pv_link.pvlMask & pvlOptOutString) && pca->gotOutString) { link_action |= CA_WRITE_STRING; } pca->gotAttributes = 0; if (pca->dbrType != DBR_STRING) { link_action |= CA_GET_ATTRIBUTES; } done: if (link_action) addAction(pca, link_action); epicsMutexUnlock(pca->lock); }