Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6931273fef | ||
|
|
8d52177933 | ||
|
|
b64fa8bd87 | ||
|
|
34ce2ab6ac | ||
|
|
43ef20b90c | ||
|
|
818bc0d475 | ||
|
|
ca2f9aff52 | ||
|
|
64a93df872 | ||
|
|
ecc03e9ad9 | ||
|
|
db1b46e5f9 | ||
|
|
d87295397e | ||
|
|
7277c336f7 | ||
|
|
30ad5b1149 | ||
|
|
c6bcd1a10b | ||
|
|
f3cf369071 | ||
|
|
adffe02a2d | ||
|
|
e635080cef | ||
|
|
be85da6a3a | ||
|
|
c16006f34d | ||
|
|
72491d8829 | ||
|
|
cb78c5adb8 | ||
|
|
1a2cd5953d | ||
|
|
5da79a5f56 | ||
|
|
9f2d9587f0 | ||
|
|
74e405969a |
45
COPYRIGHT_UniversityOfChicago
Normal file
45
COPYRIGHT_UniversityOfChicago
Normal file
@@ -0,0 +1,45 @@
|
||||
/*****************************************************************
|
||||
COPYRIGHT NOTIFICATION
|
||||
*****************************************************************
|
||||
|
||||
THE FOLLOWING IS A NOTICE OF COPYRIGHT, AVAILABILITY OF THE CODE,
|
||||
AND DISCLAIMER WHICH MUST BE INCLUDED IN THE PROLOGUE OF THE CODE
|
||||
AND IN ALL SOURCE LISTINGS OF THE CODE.
|
||||
|
||||
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
|
||||
|
||||
Argonne National Laboratory (ANL), with facilities in the States of
|
||||
Illinois and Idaho, is owned by the United States Government, and
|
||||
operated by the University of Chicago under provision of a contract
|
||||
with the Department of Energy.
|
||||
|
||||
Portions of this material resulted from work developed under a U.S.
|
||||
Government contract and are subject to the following license: For
|
||||
a period of five years from March 30, 1993, the Government is
|
||||
granted for itself and others acting on its behalf a paid-up,
|
||||
nonexclusive, irrevocable worldwide license in this computer
|
||||
software to reproduce, prepare derivative works, and perform
|
||||
publicly and display publicly. With the approval of DOE, this
|
||||
period may be renewed for two additional five year periods.
|
||||
Following the expiration of this period or periods, the Government
|
||||
is granted for itself and others acting on its behalf, a paid-up,
|
||||
nonexclusive, irrevocable worldwide license in this computer
|
||||
software to reproduce, prepare derivative works, distribute copies
|
||||
to the public, perform publicly and display publicly, and to permit
|
||||
others to do so.
|
||||
|
||||
*****************************************************************
|
||||
DISCLAIMER
|
||||
*****************************************************************
|
||||
|
||||
NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR
|
||||
THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES OR OFFICERS,
|
||||
MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL
|
||||
LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
|
||||
USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS
|
||||
DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY
|
||||
OWNED RIGHTS.
|
||||
|
||||
*****************************************************************
|
||||
LICENSING INQUIRIES MAY BE DIRECTED TO THE INDUSTRIAL TECHNOLOGY
|
||||
DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).
|
||||
10
MakeRelease
10
MakeRelease
@@ -10,6 +10,10 @@
|
||||
# [-b] - For fully built release
|
||||
#
|
||||
# $Log$
|
||||
# Revision 1.1 1995/08/17 20:14:56 jba
|
||||
# Added base/tools scripts functionality to base/Makefile, removed scripts
|
||||
# Moved base/tools/MakeRelease to base dir.
|
||||
#
|
||||
# Revision 1.14 1994/12/19 18:42:08 tang
|
||||
# Make the args length compatible for HP and SUN.
|
||||
#
|
||||
@@ -100,6 +104,12 @@ ls base/README* | xargs tar cvf ${RELS}.Tar
|
||||
|
||||
ls base/Makefile* > /tmp/make_release.out.$$;
|
||||
|
||||
if [ -d startup ];
|
||||
then
|
||||
find startup -name CVS -prune -o ! -type d -print \
|
||||
>> /tmp/make_release.out.$$;
|
||||
fi
|
||||
|
||||
find config base/include base/man base/tools -name CVS -prune -o \
|
||||
! -type d -print >> /tmp/make_release.out.$$;
|
||||
|
||||
|
||||
10
SkeletonCOPYRIGHT_UniversityOfChicago
Normal file
10
SkeletonCOPYRIGHT_UniversityOfChicago
Normal file
@@ -0,0 +1,10 @@
|
||||
/*****************************************************************
|
||||
COPYRIGHT NOTIFICATION
|
||||
*****************************************************************
|
||||
|
||||
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
|
||||
|
||||
This software was developed under a United States Government license
|
||||
described on the COPYRIGHT_UniversityOfChicago file included as part
|
||||
of this distribution.
|
||||
**********************************************************************/
|
||||
@@ -1,3 +1,4 @@
|
||||
/* $Id$ */
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* L O S A L A M O S */
|
||||
@@ -98,6 +99,13 @@
|
||||
/************************************************************************/
|
||||
/*
|
||||
* $Log$
|
||||
* Revision 1.76 1995/08/23 00:34:06 jhill
|
||||
* fixed vxWorks specific SPARC data alignment problem
|
||||
*
|
||||
* Revision 1.75 1995/08/22 00:15:19 jhill
|
||||
* Use 1.0/USEC_PER_SEC and not 1.0e-6
|
||||
* Check for S_db_Pending when calling dbPutNotify()
|
||||
*
|
||||
* Revision 1.74 1995/08/22 00:12:07 jhill
|
||||
* *** empty log message ***
|
||||
*
|
||||
@@ -968,13 +976,14 @@ int epicsShareAPI ca_search_and_connect
|
||||
* also allocate enough for the channel name & paddr
|
||||
* block
|
||||
*/
|
||||
size = sizeof(*chix) + strcnt + sizeof(struct db_addr);
|
||||
size = sizeof(*chix) + strcnt + sizeof(struct db_addr)
|
||||
+CA_MESSAGE_ALIGN(1);
|
||||
*chixptr = chix = (chid) calloc(1,size);
|
||||
if (!chix){
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
chix->id.paddr = (struct db_addr *)
|
||||
(strcnt + (char *) (chix + 1));
|
||||
CA_MESSAGE_ALIGN(strcnt+(char *)(chix+1));
|
||||
*chix->id.paddr = tmp_paddr;
|
||||
chix->puser = puser;
|
||||
chix->pConnFunc = conn_func;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#ifndef __IOCMSG__
|
||||
/* $Id$ */
|
||||
/*
|
||||
* History
|
||||
* .01 01xx90 joh removed status field in favor of a independent m_cmmd-
|
||||
@@ -23,6 +24,7 @@
|
||||
* .09 050594 joh New command added for CA V4.3 - repeater fanout register
|
||||
*
|
||||
* .10 050594 joh New command added for CA V4.3 - wakeup the server
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
#define __IOCMSG__
|
||||
@@ -113,15 +115,15 @@ typedef ca_uint32_t caResId;
|
||||
#define DONTREPLY 5
|
||||
|
||||
/* size of object in bytes rounded up to nearest oct word */
|
||||
#define OCT_ROUND(A) ((((unsigned long)A)+7)>>3)
|
||||
#define OCT_ROUND(A) ((((unsigned long)(A))+7)>>3)
|
||||
#define OCT_SIZEOF(A) (OCT_ROUND(sizeof(A)))
|
||||
|
||||
/* size of object in bytes rounded up to nearest long word */
|
||||
#define QUAD_ROUND(A) (((unsigned long)A)+3)>>2)
|
||||
#define QUAD_ROUND(A) (((unsigned long)(A))+3)>>2)
|
||||
#define QUAD_SIZEOF(A) (QUAD_ROUND(sizeof(A)))
|
||||
|
||||
/* size of object in bytes rounded up to nearest short word */
|
||||
#define BI_ROUND(A) ((((unsigned long)A)+1)>>1)
|
||||
#define BI_ROUND(A) ((((unsigned long)(A))+1)>>1)
|
||||
#define BI_SIZEOF(A) (BI_ROUND(sizeof(A)))
|
||||
|
||||
/*
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
#include <dbFldTypes.h>
|
||||
#include <dbRecDes.h>
|
||||
#include <dbRecType.h>
|
||||
#include <dbEvent.h>
|
||||
#include <db_field_log.h>
|
||||
#include <errMdef.h>
|
||||
#include <recSup.h>
|
||||
|
||||
@@ -622,14 +622,16 @@ int db_post_single_event(struct event_block *pevent)
|
||||
*
|
||||
*/
|
||||
int db_post_events(
|
||||
struct dbCommon *precord,
|
||||
union native_value *pvalue,
|
||||
unsigned int select
|
||||
void *prec,
|
||||
void *pval,
|
||||
unsigned int select
|
||||
)
|
||||
{
|
||||
struct event_block *event;
|
||||
struct event_que *ev_que;
|
||||
unsigned int putix;
|
||||
struct dbCommon *precord = (struct dbCommon *)prec;
|
||||
union native_value *pvalue = (union native_value *)pval;
|
||||
struct event_block *event;
|
||||
struct event_que *ev_que;
|
||||
unsigned int putix;
|
||||
|
||||
if (precord->mlis.count == 0) return OK; /* no monitors set */
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
#include <dbFldTypes.h>
|
||||
#include <dbRecDes.h>
|
||||
#include <dbRecType.h>
|
||||
#include <dbEvent.h>
|
||||
#include <db_field_log.h>
|
||||
#include <errMdef.h>
|
||||
#include <recSup.h>
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <ellLib.h>
|
||||
#include <vxLib.h>
|
||||
#include <tickLib.h>
|
||||
#include <sysLib.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <dbAccess.h>
|
||||
|
||||
@@ -439,7 +439,6 @@ DBBASE *pdbbase;
|
||||
ELLLIST *preclist;
|
||||
int recType;
|
||||
if (!pdbbase || !ppvd || !precType) return;
|
||||
dbPvdFreeMem(pdbbase);
|
||||
/* loop thru the recLocs - removing lists then recLoc only */
|
||||
for (recType = 0; recType < precType->number; recType++) {
|
||||
if (!(precLoc = GET_PRECLOC(precHeader, recType))) continue;
|
||||
@@ -461,6 +460,7 @@ DBBASE *pdbbase;
|
||||
free((void *) precLoc);
|
||||
}
|
||||
/* free the rest of the memory allocations */
|
||||
dbPvdFreeMem(pdbbase);
|
||||
if (pdbbase->pchoiceCvt)
|
||||
free((void *) pdbbase->pchoiceCvt);
|
||||
if (pdbbase->pchoiceDev)
|
||||
@@ -4316,7 +4316,8 @@ RECNODE *precnode;
|
||||
ppvdlist=ppvd[hashInd];
|
||||
ppvdNode = (PVDENTRY *) ellFirst(ppvdlist);
|
||||
while(ppvdNode) {
|
||||
if(strcmp(name,(char *)ppvdNode->precnode->precord) == 0) {
|
||||
if(ppvdNode->precnode && ppvdNode->precnode->precord
|
||||
&& strcmp(name,(char *)ppvdNode->precnode->precord) == 0) {
|
||||
ellDelete(ppvdlist, (ELLNODE*)ppvdNode);
|
||||
free((void *)ppvdNode);
|
||||
return;
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <timexLib.h>
|
||||
|
||||
#include <ellLib.h>
|
||||
#include <fast_lock.h>
|
||||
@@ -112,6 +113,7 @@
|
||||
#include <special.h>
|
||||
#include <dbRecDes.h>
|
||||
#include <dbStaticLib.h>
|
||||
#include <dbEvent.h>
|
||||
#include <ellLib.h>
|
||||
#include <callback.h>
|
||||
|
||||
@@ -170,18 +172,6 @@ long dba(char*pname)
|
||||
if(status) return(1); else return(0);
|
||||
}
|
||||
|
||||
/*Following definition is from dbEvent.c*/
|
||||
struct event_block{
|
||||
ELLNODE node;
|
||||
struct dbAddr *paddr;
|
||||
void (*user_sub)();
|
||||
void *user_arg;
|
||||
struct event_que *ev_que;
|
||||
unsigned char select;
|
||||
char valque;
|
||||
unsigned short npend; /* n times this event is on the que */
|
||||
};
|
||||
|
||||
long dbel(char*pname)
|
||||
{
|
||||
struct dbAddr addr;
|
||||
@@ -200,7 +190,7 @@ long dbel(char*pname)
|
||||
return(0);
|
||||
}
|
||||
while(peb) {
|
||||
pfldDes = peb->paddr->pfldDes;
|
||||
pfldDes = ((struct dbAddr *)peb->paddr)->pfldDes;
|
||||
printf("%4.4s",&pfldDes->fldname[0]);
|
||||
if(peb->select&&DBE_VALUE) printf(" VALUE");
|
||||
if(peb->select&&DBE_LOG) printf(" LOG");
|
||||
@@ -1756,7 +1746,8 @@ char *record_name;
|
||||
* Time the record
|
||||
*/
|
||||
dbScanLock(precord);
|
||||
timexN(timing_routine, precord);
|
||||
timexN((FUNCPTR)timing_routine, (int)precord,
|
||||
0,0,0,0,0,0,0);
|
||||
dbScanUnlock(precord);
|
||||
|
||||
return(0);
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
|
||||
/*
|
||||
* $Log$
|
||||
* Revision 1.14 1995/08/30 15:38:39 jbk
|
||||
* *** empty log message ***
|
||||
*
|
||||
* Revision 1.13 1995/08/18 13:19:31 mrk
|
||||
* Made changes for ansi c
|
||||
*
|
||||
* Revision 1.12 1995/08/17 20:35:09 jbk
|
||||
* fixed all the -pendantic errors (pain)
|
||||
*
|
||||
@@ -99,7 +105,8 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).
|
||||
*/
|
||||
|
||||
#define MAKE_DEBUG TSdriverDebug
|
||||
#define TS_DRIVER
|
||||
#define TS_DRIVER 1
|
||||
#define TS_ALLOW_FORCE 1
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <vme.h>
|
||||
@@ -213,6 +220,9 @@ TSinfo TSdata = { TS_master_dead, TS_async_slave, TS_async_none,
|
||||
|
||||
extern char* sysBootLine;
|
||||
|
||||
int TSdirectTimeVar = 0; /* aother way to indicate direct time */
|
||||
int TSgoodTimeStamps = 0; /* a way to force use of accurate time stamps */
|
||||
|
||||
static WDOG_ID wd;
|
||||
static long correction_factor = 0;
|
||||
static long correction_count = 0;
|
||||
@@ -383,8 +393,13 @@ long TSgetTimeStamp(int event_number,struct timespec* sp)
|
||||
switch(event_number)
|
||||
{
|
||||
case 0:
|
||||
*sp = TSdata.event_table[0]; /* one tick watch dog maintains */
|
||||
break;
|
||||
#ifdef TS_ALLOW_FORCE
|
||||
if(TSgoodTimeStamps==0)
|
||||
#endif
|
||||
{
|
||||
*sp = TSdata.event_table[0]; /* one tick watch dog maintains */
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
{
|
||||
struct timespec ts;
|
||||
@@ -494,6 +509,8 @@ long TSinit(void)
|
||||
TSregisterErrorHandler = TSregisterErrorHandlerError;
|
||||
TSforceSync = TSforceSoftSync;
|
||||
TSgetTime = TSgetCurrentTime;
|
||||
TSdriverInit = TSdriverInitError;
|
||||
TSdirectTime = TSdirectTimeError;
|
||||
TSdata.sync_event=ER_EVENT_RESET_TICK;
|
||||
}
|
||||
|
||||
@@ -518,7 +535,7 @@ long TSinit(void)
|
||||
else
|
||||
TSdata.has_event_system = 1;
|
||||
|
||||
if(TSdirectTime()>0) TSdata.has_direct_time=1;
|
||||
if(TSdirectTime()>0 || TSdirectTimeVar>0) TSdata.has_direct_time=1;
|
||||
|
||||
/* allocate the event table */
|
||||
TSdata.event_table=(struct timespec*)malloc(
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <dbBase.h>
|
||||
#include <dbRecType.h>
|
||||
#include <dbRecDes.h>
|
||||
#include <dbEvent.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbScan.h>
|
||||
#include <devSup.h>
|
||||
|
||||
986
src/dbtools/BSlib.c
Normal file
986
src/dbtools/BSlib.c
Normal file
@@ -0,0 +1,986 @@
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "BSlib.h"
|
||||
|
||||
#ifdef linux
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
#include <vxWorks.h>
|
||||
#include <in.h>
|
||||
#include <ioctl.h>
|
||||
#include <inetLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <ioLib.h>
|
||||
#include <sockLib.h>
|
||||
#include <selectLib.h>
|
||||
#else
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/time.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOLARIS
|
||||
#define BSD_COMP
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
|
||||
|
||||
static long BSgetBroadcastAddr(int soc, struct sockaddr* sin);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* server mode functions */
|
||||
|
||||
#ifndef vxWorks /* server mode functions */
|
||||
static char* filename=(char*)NULL;
|
||||
|
||||
/* ----------------------------- */
|
||||
/* signal catcher for the server */
|
||||
/* ----------------------------- */
|
||||
static void catch_sig(int sig)
|
||||
{
|
||||
fprintf(stderr,"\nbdt server exiting\n");
|
||||
unlink(filename);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* -------------------------------- */
|
||||
/* child reaper for the server mode */
|
||||
/* -------------------------------- */
|
||||
static void get_child(int sig)
|
||||
{
|
||||
#ifdef SOLARIS
|
||||
while(waitpid(-1,(int*)NULL,WNOHANG)>0);
|
||||
#else
|
||||
while(wait3((int *)NULL,WNOHANG,(struct rusage *)NULL)>0);
|
||||
#endif
|
||||
|
||||
#if defined linux || defined SOLARIS
|
||||
signal(SIGCHLD,get_child); /* for reaping children */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ------------------------------- */
|
||||
/* Clear the signals for a process */
|
||||
/* ------------------------------- */
|
||||
int BSserverClearSignals()
|
||||
{
|
||||
signal(SIGCHLD,SIG_DFL);
|
||||
signal(SIGHUP,SIG_DFL);
|
||||
signal(SIGINT,SIG_DFL);
|
||||
signal(SIGTERM,SIG_DFL);
|
||||
signal(SIGQUIT,SIG_DFL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
/* Make a unix process into a generic background process */
|
||||
/* ----------------------------------------------------- */
|
||||
int BSmakeServer(char** argv)
|
||||
{
|
||||
FILE* fd;
|
||||
|
||||
if(filename) return -1;
|
||||
|
||||
/* set up signal handling for the server */
|
||||
signal(SIGCHLD,get_child); /* for reaping children */
|
||||
signal(SIGHUP,catch_sig);
|
||||
signal(SIGINT,catch_sig);
|
||||
signal(SIGTERM,catch_sig);
|
||||
signal(SIGQUIT,catch_sig);
|
||||
|
||||
/* disconnect from parent */
|
||||
switch(fork())
|
||||
{
|
||||
case -1: /* error */
|
||||
perror("Cannot fork");
|
||||
return -1;
|
||||
case 0: /* child */
|
||||
#if defined linux || defined SOLARIS
|
||||
setpgrp();
|
||||
#else
|
||||
setpgrp(0,0);
|
||||
#endif
|
||||
setsid();
|
||||
break;
|
||||
default: /* parent goes away */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* save process ID */
|
||||
filename=(char*)malloc(strlen(argv[0])+10);
|
||||
sprintf(filename,"%s.%d",argv[0],getpid());
|
||||
fd=fopen(filename,"w");
|
||||
fprintf(fd,"%d",getpid());
|
||||
fprintf(stderr,"\npv server pid: %d\n",getpid());
|
||||
fclose(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* server mode functions */
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/* open a bulk data socket to a server given the server IP address */
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
BS* BSipOpen(char* address, int Port)
|
||||
{
|
||||
struct hostent* pHostent;
|
||||
unsigned long addr;
|
||||
BSDATA info;
|
||||
struct sockaddr_in* tsin;
|
||||
|
||||
tsin=(struct sockaddr_in*)&(info.sin);
|
||||
|
||||
#ifndef vxWorks
|
||||
/* Deal with the name -vs- IP number issue. */
|
||||
if (isdigit(address[0]))
|
||||
{
|
||||
#endif
|
||||
addr=inet_addr(address);
|
||||
#ifndef vxWorks
|
||||
}
|
||||
else
|
||||
{
|
||||
if((pHostent=gethostbyname(address))==NULL) return NULL;
|
||||
memcpy((char*)&addr,pHostent->h_addr,sizeof(addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
tsin->sin_port=htons(Port);
|
||||
tsin->sin_family=AF_INET;
|
||||
memcpy((char*)&(tsin->sin_addr),(char*)&addr,sizeof(addr));
|
||||
|
||||
return BSipOpenData(&info);
|
||||
}
|
||||
|
||||
BS* BSipOpenData(BSDATA* info)
|
||||
{
|
||||
struct sockaddr_in tsin;
|
||||
int osoc;
|
||||
BS* bdt;
|
||||
|
||||
tsin.sin_port=0;
|
||||
tsin.sin_family=AF_INET;
|
||||
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
|
||||
if((osoc=socket(AF_INET,SOCK_STREAM,BS_TCP))<0)
|
||||
{
|
||||
perror("BSipOpen: create socket failed");
|
||||
return (BS*)NULL;
|
||||
}
|
||||
|
||||
if((bind(osoc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
|
||||
{
|
||||
perror("BSipOpen: local address bind failed");
|
||||
return (BS*)NULL;
|
||||
}
|
||||
|
||||
if(connect(osoc,(struct sockaddr*)&(info->sin),sizeof(info->sin))<0)
|
||||
{
|
||||
perror("BSipOpen: connect failed");
|
||||
close(osoc);
|
||||
return (BS*)NULL;
|
||||
}
|
||||
|
||||
bdt=(BS*)malloc(sizeof(BS));
|
||||
bdt->soc=osoc;
|
||||
bdt->remaining_send=0;
|
||||
bdt->remaining_recv=0;
|
||||
bdt->state=BSidle;
|
||||
|
||||
#ifndef vxWorks
|
||||
{
|
||||
int j;
|
||||
j = fcntl(bdt->soc, F_GETFL, 0);
|
||||
fcntl(bdt->soc, F_SETFL, j|O_NDELAY);
|
||||
}
|
||||
#endif
|
||||
/* now connected to the bulk data socket on the IOC */
|
||||
return bdt;
|
||||
}
|
||||
|
||||
/* -------------------------------------- */
|
||||
/* write size bytes from buffer to socket */
|
||||
/* -------------------------------------- */
|
||||
int BSwrite(int soc,void* buffer,int size)
|
||||
{
|
||||
int rc;
|
||||
int total;
|
||||
unsigned char* data;
|
||||
fd_set fds;
|
||||
struct timeval to;
|
||||
|
||||
data=(unsigned char*)buffer;
|
||||
total=size;
|
||||
|
||||
to.tv_sec = 5;
|
||||
to.tv_usec = 0;
|
||||
|
||||
do
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc, &fds);
|
||||
if(select(FD_SETSIZE,NULL,&fds,NULL,&to) != 1)
|
||||
{
|
||||
printf("BSwrite: timeout waiting to write data\n");
|
||||
return -1;
|
||||
}
|
||||
/* send block of data */
|
||||
if((rc=send(soc,(char*)&data[size-total],total,0))<0)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
rc = 0;
|
||||
else
|
||||
perror("BSwrite: Send to remote failed");
|
||||
}
|
||||
else
|
||||
total-=rc;
|
||||
}
|
||||
while(rc>0 && total>0);
|
||||
|
||||
return (rc<=0)?-1:0;
|
||||
}
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* send a message header down a BS socket */
|
||||
/* --------------------------------------- */
|
||||
int BSsendHeader(BS* bdt,unsigned short verb,int size)
|
||||
{
|
||||
BSmsgHead buf;
|
||||
|
||||
if(bdt->state!=BSidle)
|
||||
{
|
||||
fprintf(stderr,"BSsendHeader: Interface not idle\n");
|
||||
bdt->state=BSbad;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf.verb=htons(verb);
|
||||
buf.size=htonl((unsigned long)size);
|
||||
|
||||
if(BSwrite(bdt->soc,&buf.verb, sizeof(buf.verb))<0)
|
||||
{
|
||||
fprintf(stderr,"BSsendHeader: write to remote failed");
|
||||
return -1;
|
||||
}
|
||||
if(BSwrite(bdt->soc,&buf.size, sizeof(buf.size))<0)
|
||||
{
|
||||
fprintf(stderr,"BSsendHeader: write to remote failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* don't wait for response if data must go out */
|
||||
if(size)
|
||||
{
|
||||
bdt->remaining_send=size;
|
||||
bdt->state=BSsData;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------- */
|
||||
/* send a message data chunk down a BS socket */
|
||||
/* ------------------------------------------- */
|
||||
int BSsendData(BS* bdt,void* buffer,int size)
|
||||
{
|
||||
int len;
|
||||
int remaining;
|
||||
int rc;
|
||||
|
||||
if(bdt->state!=BSsData)
|
||||
{
|
||||
fprintf(stderr,"BSsendData: Interface not in send data mode\n");
|
||||
bdt->state=BSbad;
|
||||
return -1;
|
||||
}
|
||||
|
||||
remaining=bdt->remaining_send-size;
|
||||
|
||||
if(remaining<0)
|
||||
{
|
||||
fprintf(stderr,"WARNING -- BSsendData: To much data to send\n");
|
||||
len=bdt->remaining_send;
|
||||
}
|
||||
else
|
||||
len=size;
|
||||
|
||||
if (BSwrite(bdt->soc, buffer, len) < 0)
|
||||
return -1;
|
||||
|
||||
bdt->remaining_send-=len;
|
||||
|
||||
if(bdt->remaining_send<0)
|
||||
{
|
||||
fprintf(stderr,"BSsendData: To much data Sent\n");
|
||||
bdt->remaining_send=0;
|
||||
}
|
||||
|
||||
if(bdt->remaining_send==0)
|
||||
bdt->state=BSidle;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int BSflushOutput(BS* bdt)
|
||||
{
|
||||
#ifdef vxWorks
|
||||
ioctl(bdt->soc, FIOWFLUSH, 0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------- */
|
||||
/* Read exactly size bytes from remote */
|
||||
/* ------------------------------------- */
|
||||
int BSread(int soc,void* buffer,int size)
|
||||
{
|
||||
int rc,total;
|
||||
unsigned char* data;
|
||||
fd_set fds;
|
||||
struct timeval to;
|
||||
|
||||
to.tv_sec = 5;
|
||||
to.tv_usec = 0;
|
||||
|
||||
data=(unsigned char*)buffer;
|
||||
total=size;
|
||||
|
||||
do
|
||||
{
|
||||
#if 1
|
||||
/* wait for data chunk */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc, &fds);
|
||||
if (select(soc+1, &fds, NULL, NULL, &to) != 1)
|
||||
{
|
||||
printf("BSread: timeout waiting for data\n");
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
if((rc=recv(soc,(char*)&data[size-total],total,0))<0)
|
||||
{
|
||||
if(errno==EINTR)
|
||||
{
|
||||
printf("BSread: EINTR");
|
||||
rc=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("BSread: Receive data chunk failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
total-=rc;
|
||||
}
|
||||
while(rc>0 && total>0);
|
||||
|
||||
return (rc<=0)?-1:0;
|
||||
}
|
||||
|
||||
/* ------------------------------------- */
|
||||
/* wait for a message header from remote */
|
||||
/* ------------------------------------- */
|
||||
int BSreceiveHeader(BS* bdt,int* verb,int* size)
|
||||
{
|
||||
BSmsgHead buf;
|
||||
|
||||
/* can only receive header when in the idle state */
|
||||
if (bdt->state == BSeof)
|
||||
return -1;
|
||||
|
||||
if(bdt->state != BSidle)
|
||||
{
|
||||
fprintf(stderr,"BSreceiveHeader: Interface not idle\n");
|
||||
bdt->state=BSbad;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(BSread(bdt->soc,&buf.verb,sizeof(buf.verb))<0)
|
||||
{
|
||||
fprintf(stderr,"BSreceiveHeader: Read failed\n");
|
||||
return -1;
|
||||
}
|
||||
if(BSread(bdt->soc,&buf.size,sizeof(buf.size))<0)
|
||||
{
|
||||
fprintf(stderr,"BSreceiveHeader: Read failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* copy message data to user */
|
||||
*verb=ntohs(buf.verb);
|
||||
*size=ntohl(buf.size);
|
||||
|
||||
if(*size)
|
||||
bdt->state=BSrData;
|
||||
|
||||
bdt->remaining_recv=*size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Wait for a chunk of data from remote.
|
||||
User can continually call this with a maximum size until it return 0.
|
||||
------------------------------------------------------------------------ */
|
||||
int BSreceiveData(BS* bdt,void* buffer,int size)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* can only receive data when in the receive data state */
|
||||
switch(bdt->state)
|
||||
{
|
||||
case BSrData: break;
|
||||
case BSidle: return 0;
|
||||
default:
|
||||
fprintf(stderr,"BSreceiveData: bad receive state\n");
|
||||
bdt->state=BSbad;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bdt->remaining_recv < size)
|
||||
size = bdt->remaining_recv;
|
||||
|
||||
if(BSread(bdt->soc,buffer,size)<0)
|
||||
{
|
||||
fprintf(stderr,"BSreceiveData: Read failed\n");
|
||||
bdt->state = BSeof;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bdt->remaining_recv-=size;
|
||||
|
||||
if(bdt->remaining_recv<0)
|
||||
{
|
||||
fprintf(stderr,"BSreceiveData: To much data received\n");
|
||||
bdt->remaining_recv=0;
|
||||
}
|
||||
|
||||
if(bdt->remaining_recv==0)
|
||||
bdt->state=BSidle;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* -------------------- */
|
||||
/* close the connection */
|
||||
/* -------------------- */
|
||||
int BSclose(BS* bdt)
|
||||
{
|
||||
int verb,size,done;
|
||||
|
||||
/* send a close message out */
|
||||
if(BSsendHeader(bdt,BS_Close,0)<0)
|
||||
{
|
||||
fprintf(stderr,"BSclose: Cannot send close message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
done=0;
|
||||
|
||||
do
|
||||
{
|
||||
/* check response */
|
||||
if(BSreceiveHeader(bdt,&verb,&size)<0)
|
||||
{
|
||||
fprintf(stderr,"BSclose: Close message response error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(verb)
|
||||
{
|
||||
case BS_Ok:
|
||||
done=1;
|
||||
break;
|
||||
case BS_Error:
|
||||
fprintf(stderr,"BSclose: Close rejected\n");
|
||||
return -1;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
while(done==0);
|
||||
|
||||
BSfreeBS(bdt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* make a listener socket for UDP - simple */
|
||||
/* --------------------------------------- */
|
||||
int BSopenListenerUDP(int Port)
|
||||
{
|
||||
int nsoc;
|
||||
struct sockaddr_in tsin;
|
||||
|
||||
tsin.sin_port=htons(Port);
|
||||
tsin.sin_family=AF_INET;
|
||||
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
|
||||
if((nsoc=socket(AF_INET,SOCK_DGRAM,BS_UDP))<0)
|
||||
{
|
||||
perror("BSopenListenerUDP: open socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((bind(nsoc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
|
||||
{
|
||||
perror("BSopenListenerUDP: local bind failed");
|
||||
close(nsoc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return nsoc;
|
||||
}
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* make a listener socket for TCP - simple */
|
||||
/* --------------------------------------- */
|
||||
int BSopenListenerTCP(int Port)
|
||||
{
|
||||
int nsoc;
|
||||
struct sockaddr_in tsin;
|
||||
|
||||
memset ((void *)&tsin, 0, sizeof(struct sockaddr_in));
|
||||
tsin.sin_port=htons(Port);
|
||||
tsin.sin_family=htons(AF_INET);
|
||||
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
|
||||
if((nsoc=socket(AF_INET,SOCK_STREAM,BS_TCP))<0)
|
||||
{
|
||||
perror("BSopenListenerTCP: open socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((bind(nsoc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
|
||||
{
|
||||
perror("BSopenListenerTCP: local bind failed");
|
||||
close(nsoc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
listen(nsoc,5);
|
||||
return nsoc;
|
||||
}
|
||||
|
||||
/* ------------------------------- */
|
||||
/* make BS from a socket - simple */
|
||||
/* ------------------------------- */
|
||||
BS* BSmakeBS(int soc)
|
||||
{
|
||||
BS* bdt;
|
||||
bdt=(BS*)malloc(sizeof(BS));
|
||||
bdt->soc=soc;
|
||||
bdt->remaining_send=0;
|
||||
bdt->remaining_recv=0;
|
||||
bdt->state=BSidle;
|
||||
return bdt;
|
||||
}
|
||||
|
||||
/* --------------------------- */
|
||||
/* free a BS and close socket */
|
||||
/* --------------------------- */
|
||||
int BSfreeBS(BS* bdt)
|
||||
{
|
||||
close(bdt->soc);
|
||||
free(bdt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
Next three function adjust the fields of the BSDATA structure.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
int BSgetAddressPort(BSDATA* info, char* ip_addr, int* dest_port)
|
||||
{
|
||||
char* name;
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)&(info->sin);
|
||||
|
||||
*dest_port=sin->sin_port;
|
||||
name=inet_ntoa(sin->sin_addr);
|
||||
strcpy(ip_addr,name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BSsetAddressPort(BSDATA* info, char* ip_addr, int dest_port)
|
||||
{
|
||||
BSsetPort(info, dest_port);
|
||||
return BSsetAddress(info, ip_addr);
|
||||
}
|
||||
|
||||
int BSsetPort(BSDATA* info, int dest_port)
|
||||
{
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)&(info->sin);
|
||||
sin->sin_family=AF_INET;
|
||||
sin->sin_port=htons(dest_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BSsetAddress(BSDATA* info, char* ip_addr)
|
||||
{
|
||||
struct hostent *pHostent;
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)&(info->sin);
|
||||
unsigned long addr;
|
||||
|
||||
#ifndef vxWorks
|
||||
/* Deal with the name -vs- IP number issue. */
|
||||
if (isdigit(ip_addr[0]))
|
||||
{
|
||||
#endif
|
||||
if((addr=inet_addr(ip_addr))==-1) return -1;
|
||||
#ifndef vxWorks
|
||||
}
|
||||
else
|
||||
{
|
||||
if((pHostent=gethostbyname(ip_addr))==NULL) return -1;
|
||||
memcpy((char*)&addr,pHostent->h_addr,sizeof(addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
sin->sin_family=AF_INET;
|
||||
memcpy((char*)&(sin->sin_addr),(char*)&addr,sizeof(addr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/*
|
||||
All this function does is send a broadcast message and return the
|
||||
addressing info to the caller of a responder to the broadcast.
|
||||
|
||||
arguments:
|
||||
soc - broadcast socket to use for sending data
|
||||
trys - number of times to send if no response
|
||||
o_info - outgoing BSDATA, address/port info
|
||||
i_info - incoming BSDATA, address/port where response came from
|
||||
omsg/osize - outgoing message and size
|
||||
imsg/isize - incoming message and buffer size
|
||||
|
||||
Returns the number of bytes read.
|
||||
*/
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
int BSbroadcastTrans(int soc,int trys,BSDATA* o_info,BSDATA* i_info,
|
||||
void* omsg,int osize,void* imsg,int isize)
|
||||
{
|
||||
int i;
|
||||
int rc=0;
|
||||
|
||||
for(i=0;rc==0 && i<trys;i++)
|
||||
{
|
||||
/* send out the message */
|
||||
rc=BSwriteUDP(soc,o_info,omsg,osize);
|
||||
if(rc<0) return rc;
|
||||
|
||||
/* wait for a response */
|
||||
rc=BSreadUDP(soc,i_info,1,imsg,isize);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int BSbroadcast(int soc,BSDATA* o_info, void* omsg,int osize)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* send out the message */
|
||||
rc=BSwriteUDP(soc,o_info,omsg,osize);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/*
|
||||
This function waits for a message and sends out an ACK when it gets one.
|
||||
addressing info to the caller of a responder to the broadcast.
|
||||
|
||||
Lots of arguments:
|
||||
|
||||
soc - The socket to send the message down.
|
||||
info - The socket information telling where the data read came from
|
||||
(returned to the user).
|
||||
tout - Timeout for read in seconds. 0=no wait, -1=wait forever.
|
||||
buf - Buffer to populate with read data.
|
||||
size - Size of the buf.
|
||||
|
||||
returns the length the read message, 0 is timeout, -1 is error
|
||||
*/
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int BSreadUDP(int soc,BSDATA* info,BS_ULONG tout,void* buf,int size)
|
||||
{
|
||||
int mlen,rc;
|
||||
fd_set fds;
|
||||
struct timeval to;
|
||||
int error=0;
|
||||
|
||||
do
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc, &fds);
|
||||
|
||||
if(tout==-1)
|
||||
rc=select(FD_SETSIZE,&fds,NULL,NULL,NULL);
|
||||
else
|
||||
{
|
||||
to.tv_sec=tout;
|
||||
to.tv_usec=0;
|
||||
rc=select(FD_SETSIZE,&fds,NULL,NULL,&to);
|
||||
}
|
||||
|
||||
switch(rc)
|
||||
{
|
||||
case -1: /* bad */
|
||||
switch(errno)
|
||||
{
|
||||
case EINTR: break;
|
||||
default: error=-1; break;
|
||||
}
|
||||
break;
|
||||
case 0: /* timeout */
|
||||
break;
|
||||
default: /* data ready */
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(rc<0 && error==0);
|
||||
|
||||
error=0;
|
||||
|
||||
if(rc>0)
|
||||
{
|
||||
error=0;
|
||||
do
|
||||
{
|
||||
info->len=sizeof(info->sin);
|
||||
mlen=recvfrom(soc,(char*)buf,size,0, &info->sin,&info->len);
|
||||
|
||||
if(mlen<0)
|
||||
{
|
||||
switch(errno)
|
||||
{
|
||||
case EINTR: break;
|
||||
default: error=-1; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(mlen<0 && error==0);
|
||||
|
||||
if(mlen<0)
|
||||
rc=-1;
|
||||
else
|
||||
rc=mlen;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
Write a chuck of data to a UDP socket at an internet address
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BSwriteDataUDP(int soc,int dest_port,char* ip_addr,void* buf,int size)
|
||||
{
|
||||
BSDATA data;
|
||||
|
||||
BSsetAddress(&data,ip_addr);
|
||||
BSsetPort(&data,dest_port);
|
||||
|
||||
return BSwriteUDP(soc,&data,buf,size);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
Write a chunk of data to a UDP socket using BSDATA.
|
||||
Arguments:
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BSwriteUDP(int soc,BSDATA* info,void* obuf,int osize)
|
||||
{
|
||||
int mlen;
|
||||
|
||||
mlen=sendto(soc,(char*)obuf,osize,0,&info->sin,sizeof(info->sin));
|
||||
|
||||
return mlen;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
Write/Read a chuck of data to a UDP socket using BSDATA.
|
||||
Arguments:
|
||||
soc - socket to send message down and read from
|
||||
info - address/port to send message to
|
||||
obuf/osize - outgoing message and size of it.
|
||||
ibuf/isize - incoming message and size of the buffer.
|
||||
|
||||
Returns the number of bytes read, -1 for error.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BStransUDP(int soc,BSDATA* info,void* obuf,int osize,void* ibuf,int isize)
|
||||
{
|
||||
int done,i,mlen,flen;
|
||||
struct sockaddr fromsin;
|
||||
fd_set fds;
|
||||
struct timeval tout;
|
||||
|
||||
done=0;
|
||||
mlen=0;
|
||||
|
||||
for(i=0;i<BS_RETRY_COUNT && done==0;i++)
|
||||
{
|
||||
mlen=sendto(soc,(char*)obuf,osize,0,&(info->sin),sizeof(info->sin));
|
||||
if(mlen<0)
|
||||
{
|
||||
printf("send failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tout.tv_sec=0;
|
||||
tout.tv_usec=200000;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc,&fds);
|
||||
|
||||
switch(select(FD_SETSIZE,&fds,(fd_set*)0,(fd_set*)0,&tout))
|
||||
{
|
||||
case 0: /* timeout */ break;
|
||||
case -1: /* error */
|
||||
printf("select failed\n");
|
||||
return -1;
|
||||
default: /* data ready */
|
||||
flen=sizeof(fromsin);
|
||||
mlen=recvfrom(soc,(char*)ibuf,isize,0,&fromsin,&flen);
|
||||
if(mlen<0) return -1;
|
||||
done=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i>=BS_RETRY_COUNT) return 0;
|
||||
|
||||
return mlen;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
Open a broadcast socket and set port to a default.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BSipBroadcastOpen(BSDATA* info, int default_dest_port)
|
||||
{
|
||||
struct sockaddr_in* sin;
|
||||
int soc;
|
||||
|
||||
sin=(struct sockaddr_in*)&(info->sin);
|
||||
|
||||
if( (soc=BSgetBroadcastSocket(0,sin)) <0) return -1;
|
||||
|
||||
sin->sin_port=htons(default_dest_port);
|
||||
|
||||
return soc;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
BSgetBroadcastSocket() - return a broadcast socket for a port, return
|
||||
a sockaddr also.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BSgetBroadcastSocket(int port, struct sockaddr_in* sin)
|
||||
{
|
||||
int on=1;
|
||||
int soc;
|
||||
BS bs;
|
||||
|
||||
sin->sin_port=htons(port);
|
||||
sin->sin_family=AF_INET;
|
||||
sin->sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
|
||||
if( (soc=socket(AF_INET,SOCK_DGRAM,BS_UDP)) < 0 )
|
||||
{
|
||||
perror("socket create failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
setsockopt(soc,SOL_SOCKET,SO_BROADCAST,(char*)&on,sizeof(on));
|
||||
|
||||
if( bind(soc,(struct sockaddr*)sin,sizeof(struct sockaddr_in)) < 0 )
|
||||
{
|
||||
perror("socket bind failed");
|
||||
close(soc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( BSgetBroadcastAddr(soc,(struct sockaddr*)sin) < 0 )
|
||||
return -1;
|
||||
|
||||
return soc;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
BSgetBroadcastAddr() - Determine the broadcast address, this is
|
||||
directly from the Sun Network Programmer's guide.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static long BSgetBroadcastAddr(int soc, struct sockaddr* sin)
|
||||
{
|
||||
struct ifconf ifc;
|
||||
struct ifreq* ifr;
|
||||
struct ifreq* save;
|
||||
char buf[BUFSIZ];
|
||||
int tot,i;
|
||||
|
||||
ifc.ifc_len = sizeof(buf);
|
||||
ifc.ifc_buf = buf;
|
||||
if(ioctl(soc,SIOCGIFCONF,(int)&ifc) < 0)
|
||||
{ perror("ioctl SIOCGIFCONF failed"); return -1; }
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
tot = ifc.ifc_len/sizeof(struct ifreq);
|
||||
save=(struct ifreq*)NULL;
|
||||
i=0;
|
||||
|
||||
do
|
||||
{
|
||||
if(ifr[i].ifr_addr.sa_family==AF_INET)
|
||||
{
|
||||
if(ioctl(soc,SIOCGIFFLAGS,(int)&ifr[i])<0)
|
||||
{ perror("ioctl SIOCGIFFLAGS failed"); return -1; }
|
||||
|
||||
if( (ifr[i].ifr_flags&IFF_UP) &&
|
||||
!(ifr[i].ifr_flags&IFF_LOOPBACK) &&
|
||||
(ifr[i].ifr_flags&IFF_BROADCAST))
|
||||
{ save=&ifr[i]; }
|
||||
}
|
||||
} while( !save && ++i<tot );
|
||||
|
||||
if(save)
|
||||
{
|
||||
if(ioctl(soc,SIOCGIFBRDADDR,(int)save)<0)
|
||||
{ perror("ioctl SIOCGIFBRDADDR failed"); return -1; }
|
||||
|
||||
memcpy((char*)sin,(char*)&save->ifr_broadaddr,
|
||||
sizeof(save->ifr_broadaddr));
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
188
src/dbtools/BSlib.h
Normal file
188
src/dbtools/BSlib.h
Normal file
@@ -0,0 +1,188 @@
|
||||
#ifndef ___BS_H
|
||||
#define ___BS_H
|
||||
|
||||
/*
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
/*
|
||||
Author: Jim Kowalkowski
|
||||
Date: 9/1/95
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/* got from protocols(5) (cheated) or /etc/protocols */
|
||||
#define BS_UDP 17
|
||||
#define BS_TCP 6
|
||||
|
||||
/* server ports - in the user reserved area - above 50000 */
|
||||
#define BS_UDP_PORT 50296
|
||||
#define BS_TCP_PORT 50297
|
||||
|
||||
/* message types */
|
||||
#define BS_Ok 0
|
||||
#define BS_Error 1
|
||||
#define BS_Close 2
|
||||
#define BS_Ping 3
|
||||
#define BS_Done 4
|
||||
|
||||
#define BS_LAST_VERB 4
|
||||
#define BS_RETRY_COUNT 3
|
||||
|
||||
/* protocol states */
|
||||
typedef enum { BSidle,BSunbound,BSsData,BSrData,BSbad,BSeof } BSstate;
|
||||
|
||||
struct bs
|
||||
{
|
||||
int soc;
|
||||
int remaining_send;
|
||||
int remaining_recv;
|
||||
BSstate state;
|
||||
};
|
||||
typedef struct bs BS;
|
||||
|
||||
struct bs_udp_data
|
||||
{
|
||||
struct sockaddr sin;
|
||||
int len;
|
||||
};
|
||||
typedef struct bs_udp_data BSDATA;
|
||||
|
||||
struct BSmsgHead
|
||||
{
|
||||
unsigned short verb;
|
||||
unsigned long size;
|
||||
};
|
||||
typedef struct BSmsgHead BSmsgHead;
|
||||
|
||||
typedef unsigned long BS_ULONG;
|
||||
|
||||
#define BSgetSocket(BS) (BS->soc)
|
||||
#define BSgetResidualWrite(BS) (BS->remaining_send)
|
||||
#define BSgetResidualRead(BS) (BS->remaining_recv)
|
||||
#define BSgetProtoState(BS) (BS->state)
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Server functions:
|
||||
|
||||
BSopenListenerTCP:
|
||||
Open a socket locally bound to the bulk data transfer TCP server port.
|
||||
Set the socket up as a listener. Return the open socket.
|
||||
|
||||
BSopenListenerUDP:
|
||||
Open a socket locally bound to the bulk data transfer UDP server port.
|
||||
Return the open socket.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
int BSopenListenerTCP(int Port);
|
||||
int BSopenListenerUDP(int Port);
|
||||
int BSopenTCP(BSDATA*);
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Utilities functions:
|
||||
|
||||
BSmakeServer:
|
||||
Available under unix only. Put process in the background, disassociate
|
||||
process from controlling terminal and parent process, and prepare
|
||||
signals for reaping children spawned by the process.
|
||||
|
||||
BSserverClearSignals:
|
||||
Clear the signal handlers for a process, set them to default.
|
||||
|
||||
BSmakeBS:
|
||||
Allocate and initialize a BS from a socket.
|
||||
|
||||
BSfreeBS:
|
||||
Close the open socket and free the memory for the BS.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#ifndef vxWorks
|
||||
int BSmakeServer(char** argv);
|
||||
int BSserverClearSignals();
|
||||
#endif
|
||||
|
||||
BS* BSmakeBS(int socket); /* make a BS from a socket */
|
||||
int BSfreeBS(BS* bdt); /* free a BS */
|
||||
|
||||
int BSgetBroadcastSocket(int port, struct sockaddr_in* sin);
|
||||
int BSipBroadcastOpen(BSDATA* info, int default_dest_port);
|
||||
int BSgetAddressPort(BSDATA* info,char* ip_addr, int* dest_port);
|
||||
int BSsetAddressPort(BSDATA* info,char* ip_addr, int dest_port);
|
||||
int BSsetAddress(BSDATA* info,char* ip_addr);
|
||||
int BSsetPort(BSDATA* info,int dest_port);
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
UDP functions:
|
||||
------------------------------------------------------------------------ */
|
||||
int BStransUDP(int soc,BSDATA* info,void* obuf,int osize,void* ibuf,int isize);
|
||||
int BSwriteUDP(int soc,BSDATA* info,void* obuf,int osize);
|
||||
int BSwriteDataUDP(int soc,int dest_port, char* ip_addr,void* obuf,int osize);
|
||||
int BSreadUDP(int soc,BSDATA* info,BS_ULONG tout,void* buf,int size);
|
||||
int BSbroadcast(int soc,BSDATA* info,void* buf,int size);
|
||||
int BSbroadcastTrans(int soc,int trys,BSDATA* o_info,BSDATA* i_info,
|
||||
void* obuf,int osize,void* ibuf,int isize);
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Client functions:
|
||||
|
||||
BSipOpen:
|
||||
Open a connection to an bulk data transfer given the IP address of the
|
||||
machine where the server exists. The returned BS is returned unbound,
|
||||
a connect must be issued before data transactions can take place.
|
||||
|
||||
BSclose:
|
||||
Completely close a connection to a server and free the BS.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
BS* BSipOpen(char* address, int port);
|
||||
BS* BSipOpenData(BSDATA* info);
|
||||
int BSclose(BS* bdt);
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Client and Server shared functions:
|
||||
|
||||
BSsendHeader:
|
||||
Send a message header out to a connect BS with command and message body
|
||||
size information.
|
||||
|
||||
BSsendData:
|
||||
Send a portion or all the message body out a connected BS. A header
|
||||
must have previously been sent with length information. The interface
|
||||
will only allow the amount of data specified in the header to be sent.
|
||||
|
||||
BSwrite:
|
||||
This call will block until all the data specified in the size parameter
|
||||
are sent down the socket.
|
||||
|
||||
BSread:
|
||||
This call will block until all the data specified in the size parameter
|
||||
is read from the socket.
|
||||
|
||||
BSreceiveHeader:
|
||||
Wait until a message header appears at the BS, return the action and
|
||||
remaining message body size.
|
||||
|
||||
BSreceiveData:
|
||||
Wait for a chunk or the entire body of a message to appear at the BS.
|
||||
Put the data into the buffer for a maximum size. Return the amount of
|
||||
data actually received, or zero if there is no data remaining for the
|
||||
current message.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
int BSsendHeader(BS* bdt, unsigned short verb, int size);
|
||||
int BSsendData(BS* bdt, void* buffer, int size);
|
||||
int BSreceiveHeader(BS* bdt, int* verb, int* size);
|
||||
int BSreceiveData(BS* bdt, void* buffer, int size);
|
||||
int BSread(int socket, void* buffer, int size);
|
||||
int BSwrite(int socket, void* buffer, int size);
|
||||
int BSflushOutput(BS* bdt);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,29 +2,45 @@ EPICS = ../../../..
|
||||
include Target.include
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
# USR_CFLAGS = -v
|
||||
|
||||
LEX = $(ELEX)
|
||||
YACC = $(EYACC)
|
||||
YACCOPT = -l
|
||||
LEXOPT = -L
|
||||
|
||||
SRCS.c = ../dbVarSub.c dbLoadTemplate_lex.c dbLoadTemplate.c \
|
||||
dbLoadRecords_lex.c dbLoadRecords.c
|
||||
dbLoadRecords_lex.c dbLoadRecords.c \
|
||||
../BSlib.c ../PVSserver.c ../rdbapplist.c ../rdbls.o
|
||||
|
||||
OBJS = dbVarSub.o dbLoadTemplate.o dbLoadRecords.o
|
||||
VAR_OBJS = dbVarSub.o dbLoadTemplate.o dbLoadRecords.o
|
||||
OBJS = $(VAR_OBJS) BSlib.o PVSserver.o rdbapplist.o rdbls.o
|
||||
|
||||
PROD = subtool dbLoadTemplate
|
||||
PROD = subtool dbLoadTemplate rdbls rdbapplist
|
||||
TARGETS = PVSserver
|
||||
|
||||
include $(EPICS)/config/RULES.Unix
|
||||
|
||||
dbLoadTemplate.o: dbLoadTemplate_lex.c
|
||||
dbLoadRecords.o: dbLoadRecords_lex.c
|
||||
|
||||
subtool: dbLoadTemplate.c dbLoadTemplate_lex.c dbVarSub.o
|
||||
$(RM) $@
|
||||
$(LINK.c) $(CFLAGS) -DSUB_TOOL -o subtool dbLoadTemplate.c dbVarSub.o -s
|
||||
PVSserver: PVSserver.o BSlib.o
|
||||
$(LINK.c) $(ARCH_DEP_LDLIBS) $(LDFLAGS) -o $@ $^
|
||||
|
||||
dbLoadTemplate: $(OBJS)
|
||||
$(LINK.c) -o $@ $(OBJS) $(LDLIBS) -lDb
|
||||
rdbls: rdbls.o BSlib.o
|
||||
$(LINK.c) $(ARCH_DEP_LDLIBS) $(LDFLAGS) -o $@ $^
|
||||
|
||||
rdbapplist: rdbapplist.o BSlib.o
|
||||
$(LINK.c) $(ARCH_DEP_LDLIBS) $(LDFLAGS) -o $@ $^
|
||||
|
||||
subtool.o: dbLoadTemplate.c dbLoadTemplate_lex.c
|
||||
$(COMPILE.c) $(CFLAGS) -DSUB_TOOL -o $@ $<
|
||||
|
||||
subtool: subtool.o dbVarSub.o
|
||||
$(LINK.c) $(CFLAGS) -DSUB_TOOL -o $@ $^ -s
|
||||
|
||||
dbLoadTemplate: $(VAR_OBJS)
|
||||
$(LINK.c) -o $@ $^ $(LDLIBS) -lDb
|
||||
|
||||
clean::
|
||||
@$(RM) dbLoadTemplate_lex.c dbLoadTemplate.c dbLoadRecords_lex.c \
|
||||
|
||||
@@ -8,8 +8,9 @@ YACCOPT = -l
|
||||
LEXOPT = -L
|
||||
|
||||
SRCS.c = ../dbVarSub.c dbLoadTemplate_lex.c dbLoadTemplate.c \
|
||||
dbLoadRecords_lex.c dbLoadRecords.c
|
||||
LIBOBJS = dbVarSub.o dbLoadTemplate.o dbLoadRecords.o
|
||||
dbLoadRecords_lex.c dbLoadRecords.c ../BSlib.c ../PVSvx.c
|
||||
|
||||
LIBOBJS = dbVarSub.o dbLoadTemplate.o dbLoadRecords.o BSlib.o PVSvx.o
|
||||
|
||||
LIBNAME = dbSubs
|
||||
|
||||
|
||||
31
src/dbtools/PVS.h
Normal file
31
src/dbtools/PVS.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __PVS_H
|
||||
#define __PVS_H
|
||||
|
||||
#include "BSlib.h"
|
||||
|
||||
#define PVS_RETRY_COUNT 4
|
||||
#define PVS_TRANSFER_SIZE 1024
|
||||
#define PVS_UDP 17
|
||||
#define PVS_TCP 6
|
||||
#define PVS_UDP_PORT 50298
|
||||
#define PVS_TCP_PORT 50299
|
||||
#define PVS_UDP_CPORT 50300
|
||||
|
||||
#define PVS_Data (BS_LAST_VERB+1)
|
||||
#define PVS_Alive (BS_LAST_VERB+2)
|
||||
#define PVS_RecList (BS_LAST_VERB+3)
|
||||
#define PVS_AppList (BS_LAST_VERB+4)
|
||||
#define PVS_RecDump (BS_LAST_VERB+5)
|
||||
|
||||
#define PVS_LAST_VERB PVS_RecDump
|
||||
|
||||
struct pvs_info_packet
|
||||
{
|
||||
unsigned short cmd;
|
||||
char text[90];
|
||||
};
|
||||
typedef struct pvs_info_packet PVS_INFO_PACKET;
|
||||
|
||||
#define PVS_SET_CMD(pvs_info,command) (pvs_info)->cmd=htons(command)
|
||||
|
||||
#endif
|
||||
263
src/dbtools/PVSserver.c
Normal file
263
src/dbtools/PVSserver.c
Normal file
@@ -0,0 +1,263 @@
|
||||
|
||||
/* only runable on work station now */
|
||||
|
||||
#include "PVS.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct PVSnode
|
||||
{
|
||||
BSDATA info;
|
||||
int alive;
|
||||
struct PVSnode* next;
|
||||
};
|
||||
typedef struct PVSnode PVSNODE;
|
||||
|
||||
static PVSNODE* ioc_list = (PVSNODE*)NULL;
|
||||
|
||||
static int read_pvs(BSDATA* info,int serv,char* sname);
|
||||
|
||||
#ifndef PVS_SERVER_PROG
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
BSDATA info;
|
||||
int serv;
|
||||
int rc;
|
||||
|
||||
if(argc<4)
|
||||
{
|
||||
fprintf(stderr,"usage: %s IOC-name server-number [server-name]\n",
|
||||
argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
serv=atoi(argv[2]);
|
||||
BSsetAddress(&info,argv[1]);
|
||||
|
||||
if(serv>PVS_LAST_VERB)
|
||||
rc=read_pvs(&info,serv,argv[3]);
|
||||
else
|
||||
rc=read_pvs(&info,serv,(char*)NULL);
|
||||
|
||||
if(rc<0) fprintf(stderr,"read of data failed horribly\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
int soc,mlen;
|
||||
unsigned short buf,in_buf,ping;
|
||||
BSDATA info;
|
||||
PVSNODE* node;
|
||||
|
||||
if(BSmakeServer(argv)<0)
|
||||
{
|
||||
fprintf(stderr,"Cannot make into a server\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((soc=BSopenListenerUDP(PVS_UDP_PORT))<0)
|
||||
{
|
||||
fprintf(stderr,"Open of UDP listener socket failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf=htons(BS_Ok); /* always sends this out */
|
||||
ping=htons(BS_Ping); /* always sends this out */
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* wait forever until a message comes in */
|
||||
|
||||
mlen=BSreadUDP(soc,&info,7,&in_buf,sizeof(in_buf));
|
||||
|
||||
/* check for errors */
|
||||
switch(mlen)
|
||||
{
|
||||
case 0: /* timeout */
|
||||
printf("Why did a timeout occur?\n");
|
||||
/* send out a ping to each of the IOCs in the ioc_list */
|
||||
for(node=ioc_list;node;node=node->next)
|
||||
{
|
||||
mlen=BStransUDP(soc,&(node->info),&ping,sizeof(ping),
|
||||
&in_buf,sizeof(in_buf));
|
||||
|
||||
/* check for errors */
|
||||
switch(mlen)
|
||||
{
|
||||
case 0: /* timeout */
|
||||
printf("IOC dead\n");
|
||||
node->alive=0;
|
||||
break;
|
||||
case -1: /* error */
|
||||
printf("Communications failed\n");
|
||||
break;
|
||||
default: /* ok */
|
||||
if(node->alive==0)
|
||||
{
|
||||
switch(fork())
|
||||
{
|
||||
case -1: /* error */
|
||||
perror("fork failure");
|
||||
break;
|
||||
case 0: /* child */
|
||||
close(soc);
|
||||
BSserverClearSignals();
|
||||
sleep(1);
|
||||
if(read_pvs(&(node->info))==0)
|
||||
node->alive=1;
|
||||
default: /* parent */
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case -1: /* error */
|
||||
fprintf(stderr,"Communications failure\n");
|
||||
break;
|
||||
default: /* ok */
|
||||
if(BSwriteUDP(soc,&info,&buf,sizeof(buf))<0)
|
||||
fprintf(stderr,"respone send failed\n");
|
||||
else
|
||||
{
|
||||
node=(PVSNODE*)malloc(sizeof(PVSNODE));
|
||||
node->alive=1;
|
||||
node->info=info;
|
||||
BSsetPort(&(node->info),PVS_UDP_CPORT);
|
||||
node->next=ioc_list;
|
||||
ioc_list=node;
|
||||
|
||||
switch(fork())
|
||||
{
|
||||
case -1: /* error */
|
||||
perror("fork failure");
|
||||
break;
|
||||
case 0: /* child */
|
||||
close(soc);
|
||||
BSserverClearSignals();
|
||||
sleep(1);
|
||||
return read_pvs(&info,PVS_RecList,NULL);
|
||||
default: /* parent */
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(soc);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int read_pvs(BSDATA* info,int serv,char* sname)
|
||||
{
|
||||
BS* bs;
|
||||
int verb,size,done,len,i,port,rsize;
|
||||
char* buffer;
|
||||
char ip_from[40];
|
||||
FILE* fd;
|
||||
|
||||
BSgetAddressPort(info,ip_from,&port);
|
||||
|
||||
/* printf("IOC %s starting\n",ip_from); */
|
||||
|
||||
/* verify ioc not already added */
|
||||
if(access(ip_from,F_OK)==0)
|
||||
{
|
||||
/* delete the existing file for this IOC */
|
||||
unlink(ip_from);
|
||||
}
|
||||
|
||||
done=0;
|
||||
BSsetPort(info,PVS_TCP_PORT);
|
||||
|
||||
if((bs=BSipOpenData(info))==NULL)
|
||||
{
|
||||
fprintf(stderr,"Open of socket to IOC failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(serv>PVS_LAST_VERB)
|
||||
rsize=strlen(sname)+1;
|
||||
else
|
||||
rsize=0;
|
||||
|
||||
if(BSsendHeader(bs,serv,rsize)<0)
|
||||
{
|
||||
fprintf(stderr,"Command send failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(rsize>0)
|
||||
{
|
||||
if(BSsendData(bs,sname,rsize)<0)
|
||||
{
|
||||
fprintf(stderr,"send of command name failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PVS_SERVER_PROG
|
||||
if((fd=fopen(ip_from,"w"))==(FILE*)NULL)
|
||||
{
|
||||
fprintf(stderr,"Open of name file failed\n");
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
fd=stdout;
|
||||
#endif
|
||||
|
||||
buffer=(char*)malloc(PVS_TRANSFER_SIZE+2);
|
||||
|
||||
while(done==0)
|
||||
{
|
||||
if(BSreceiveHeader(bs,&verb,&size)<0)
|
||||
{
|
||||
fprintf(stderr,"Receive header failed\n");
|
||||
done=-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(verb)
|
||||
{
|
||||
case PVS_Data: /* read a block of names */
|
||||
if((len=BSreceiveData(bs,buffer,size))<0)
|
||||
{
|
||||
fprintf(stderr,"Receive data failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
if(buffer[i]==' ') buffer[i]='\n';
|
||||
}
|
||||
buffer[len]='\n';
|
||||
buffer[len+1]='\0';
|
||||
|
||||
fputs(buffer,fd);
|
||||
}
|
||||
break;
|
||||
case BS_Done: /* transfers complete */
|
||||
BSclose(bs);
|
||||
done=-1;
|
||||
break;
|
||||
default:
|
||||
if(size>0) done=-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PVS_SERVER_PROG
|
||||
fclose(fd);
|
||||
#endif
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
361
src/dbtools/PVSvx.c
Normal file
361
src/dbtools/PVSvx.c
Normal file
@@ -0,0 +1,361 @@
|
||||
|
||||
/* This file not really set up to run under Unix yet, just under vxWorks. */
|
||||
|
||||
#include "PVS.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef vxWorks
|
||||
#include <vxWorks.h>
|
||||
#include <iv.h>
|
||||
#include <taskLib.h>
|
||||
#include <sysSymTbl.h>
|
||||
#include <sysLib.h>
|
||||
#include <symLib.h>
|
||||
#include <dbStaticLib.h>
|
||||
|
||||
extern struct dbBase *pdbBase;
|
||||
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
static void PVSserver(int want_annouce,char* name);
|
||||
static int PVSannouce(int want_annouce,char* name);
|
||||
static void handle_requests(BS* bs);
|
||||
static void handle_reclist(BS* bs);
|
||||
static void handle_applist(BS* bs);
|
||||
static void handle_recdump(BS* bs);
|
||||
static void handle_spylist(BS* bs);
|
||||
static void handle_tasklist(BS* bs);
|
||||
void PVS_test_server(BS* bs);
|
||||
|
||||
static char* names = (char*)NULL;
|
||||
static char* buffer = (char*)NULL;
|
||||
|
||||
#ifdef vxWorks
|
||||
int PVSstart(int want_annouce, char* name)
|
||||
#else
|
||||
int main(int argc,char** argv)
|
||||
#endif
|
||||
{
|
||||
#ifndef vxWorks
|
||||
char* name;
|
||||
int want_annouce;
|
||||
#endif
|
||||
|
||||
#ifndef vxWorks
|
||||
if(argc<3)
|
||||
{
|
||||
fprintf(stderr,"bad args\n");
|
||||
fprintf(stderr," usage: %s a_flag host_name\n",
|
||||
argv[0]);
|
||||
fprintf(stderr," where\n");
|
||||
fprintf(stderr," a_flag=0(want),1(don't want) to annouce boot\n");
|
||||
fprintf(stderr," host_name=PV master host (if one exists)\n");
|
||||
return -1;
|
||||
}
|
||||
name=argv[2];
|
||||
if(sscanf(argv[1],"%d",&want_annouce)<1)
|
||||
{
|
||||
fprintf(stderr,"bad a_flag\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
taskSpawn("PVS",150,VX_FP_TASK|VX_STDIO,5000,
|
||||
(FUNCPTR)PVSserver,want_annouce,(int)name,0,0,0,0,0,0,0,0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int PVSannouce(int want_annouce,char* name)
|
||||
{
|
||||
int soc,mlen;
|
||||
PVS_INFO_PACKET buf,in_buf;
|
||||
BSDATA info,in_info;
|
||||
|
||||
if(want_annouce==0 && name)
|
||||
{
|
||||
if((soc=BSopenListenerUDP(0))<0)
|
||||
{
|
||||
printf("Open of UDP socket failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(BSsetAddressPort(&info,name,PVS_UDP_PORT)<0)
|
||||
{
|
||||
printf("Set send port failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PVS_SET_CMD(&buf,PVS_Alive);
|
||||
mlen=BStransUDP(soc,&info,&buf,sizeof(buf),&in_buf,sizeof(in_buf));
|
||||
|
||||
/* check for errors */
|
||||
switch(mlen)
|
||||
{
|
||||
case 0: /* timeout */
|
||||
printf("No server running on host\n");
|
||||
break;
|
||||
case -1: /* error */
|
||||
printf("Communications failed\n");
|
||||
break;
|
||||
default: /* ok */
|
||||
break;
|
||||
}
|
||||
|
||||
close(soc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void PVSserver(int want_annouce,char* name)
|
||||
{
|
||||
fd_set fds,rfds;
|
||||
int tsoc,usoc,nsoc,len,s;
|
||||
struct sockaddr stemp;
|
||||
int stemp_len;
|
||||
PVS_INFO_PACKET buf;
|
||||
BSDATA info;
|
||||
BS* bs;
|
||||
|
||||
bs=(BS*)NULL;
|
||||
buffer=(char*)malloc(100); /* just make the buffer */
|
||||
names=(char*)malloc(PVS_TRANSFER_SIZE);
|
||||
|
||||
if((tsoc=BSopenListenerTCP(PVS_TCP_PORT))<0)
|
||||
{
|
||||
printf("PVSserver: Open of TCP listener socket failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if((usoc=BSopenListenerUDP(PVS_UDP_CPORT))<0)
|
||||
{
|
||||
printf("PVSserver: Open of UDP listener socket failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(tsoc,&fds);
|
||||
FD_SET(usoc,&fds);
|
||||
|
||||
PVSannouce(want_annouce,name);
|
||||
|
||||
while(1)
|
||||
{
|
||||
rfds=fds;
|
||||
if(select(FD_SETSIZE,&rfds,(fd_set*)NULL,(fd_set*)NULL,
|
||||
(struct timeval*)NULL)<0)
|
||||
{
|
||||
printf("PVSserver: Select failure\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(FD_ISSET(tsoc,&rfds))
|
||||
{
|
||||
/* handle the request here - single threaded server */
|
||||
|
||||
stemp_len=sizeof(stemp);
|
||||
if((nsoc=accept(tsoc,&stemp,&stemp_len))<0)
|
||||
printf("PVSserver: Bad accept\n");
|
||||
else
|
||||
{
|
||||
bs=BSmakeBS(nsoc);
|
||||
handle_requests(bs);
|
||||
BSfreeBS(bs);
|
||||
}
|
||||
}
|
||||
if(FD_ISSET(usoc,&rfds))
|
||||
{
|
||||
/* only pings will come in here for now */
|
||||
len=BSreadUDP(usoc,&info,0,&buf,sizeof(buf));
|
||||
if(len<=0)
|
||||
printf("PVSserver: UDP listener read failure\n");
|
||||
else
|
||||
{
|
||||
if(BSwriteUDP(usoc,&info,&buf,sizeof(buf))<0)
|
||||
printf("PVSserver: UDP listener ping write failure\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_reclist(BS* bs)
|
||||
{
|
||||
DBENTRY db;
|
||||
long rc;
|
||||
char* n;
|
||||
unsigned long names_len;
|
||||
int s;
|
||||
|
||||
dbInitEntry(pdbBase,&db);
|
||||
names_len=0;
|
||||
|
||||
for(rc=dbFirstRecdes(&db);rc==0;rc=dbNextRecdes(&db))
|
||||
{
|
||||
for(rc=dbFirstRecord(&db);rc==0;rc=dbNextRecord(&db))
|
||||
{
|
||||
/* collect the names util we excede the max */
|
||||
n=dbGetRecordName(&db);
|
||||
s=strlen(n);
|
||||
if((names_len+s)>PVS_TRANSFER_SIZE)
|
||||
{
|
||||
names[names_len++]='\0';
|
||||
if(BSsendHeader(bs,PVS_Data,names_len)<0)
|
||||
printf("PVSserver: data cmd failed\n");
|
||||
else
|
||||
{
|
||||
if(BSsendData(bs,names,names_len)<0)
|
||||
printf("PVSserver: data send failed\n");
|
||||
}
|
||||
names_len=0;
|
||||
}
|
||||
memcpy(&names[names_len],n,s);
|
||||
names_len+=s;
|
||||
names[names_len++]=' ';
|
||||
}
|
||||
}
|
||||
if(names_len>0)
|
||||
{
|
||||
names[names_len++]='\0';
|
||||
if(BSsendHeader(bs,PVS_Data,names_len)<0)
|
||||
printf("PVSserver: data cmd failed\n");
|
||||
else
|
||||
{
|
||||
if(BSsendData(bs,names,names_len)<0)
|
||||
printf("PVSserver: data send failed\n");
|
||||
}
|
||||
}
|
||||
BSsendHeader(bs,BS_Done,0);
|
||||
}
|
||||
|
||||
static void handle_requests(BS* bs)
|
||||
{
|
||||
int verb,size,notdone,len;
|
||||
void (*func)(BS*);
|
||||
SYM_TYPE stype;
|
||||
|
||||
notdone=1;
|
||||
while(notdone)
|
||||
{
|
||||
/* at this point I should be getting a command */
|
||||
if(BSreceiveHeader(bs,&verb,&size)<0)
|
||||
{
|
||||
printf("PVSserver: receive header failed\n");
|
||||
notdone=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(verb)
|
||||
{
|
||||
case PVS_RecList: handle_reclist(bs); break;
|
||||
case PVS_AppList: handle_applist(bs); break;
|
||||
case PVS_RecDump: handle_recdump(bs); break;
|
||||
case BS_Close:
|
||||
BSsendHeader(bs,BS_Ok,0);
|
||||
notdone=0;
|
||||
break;
|
||||
case PVS_Data: break;
|
||||
case PVS_Alive: break;
|
||||
case BS_Ok: break;
|
||||
case BS_Error: break;
|
||||
case BS_Ping: break;
|
||||
case BS_Done: break;
|
||||
default:
|
||||
/* custom service */
|
||||
if(size>0)
|
||||
{
|
||||
/* this should be the name of the service */
|
||||
/* look up the symbol name in buffer and call as
|
||||
subroutine, passing it the BS */
|
||||
|
||||
len=BSreceiveData(bs,&buffer[1],size);
|
||||
switch(len)
|
||||
{
|
||||
case 0: /* timeout */ notdone=0; break;
|
||||
case -1: /* error */ notdone=0; break;
|
||||
default:
|
||||
buffer[0]='_';
|
||||
|
||||
if(strncmp(buffer,"_PVS",4)==0)
|
||||
{
|
||||
if(symFindByName(sysSymTbl,buffer,
|
||||
(char**)&func,&stype)==ERROR)
|
||||
func=(void (*)(BS*))NULL;
|
||||
|
||||
if(func)
|
||||
func(bs);
|
||||
else
|
||||
BSsendHeader(bs,BS_Done,0);
|
||||
}
|
||||
else
|
||||
BSsendHeader(bs,BS_Done,0);
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("PVSserver: unknown command received\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
struct dbnode
|
||||
{
|
||||
char* name;
|
||||
struct dbnode* next;
|
||||
};
|
||||
typedef struct dbnode DBNODE;
|
||||
|
||||
extern DBNODE* DbApplList;
|
||||
|
||||
void handle_applist(BS* bs)
|
||||
{
|
||||
DBNODE* n;
|
||||
int size,len;
|
||||
|
||||
len=0;
|
||||
for(n=DbApplList;n;n=n->next)
|
||||
{
|
||||
len=strlen(n->name)+1;
|
||||
|
||||
if(BSsendHeader(bs,PVS_Data,len)<0)
|
||||
printf("PVSserver: data cmd failed\n");
|
||||
else
|
||||
{
|
||||
if(BSsendData(bs,n->name,len)<0)
|
||||
printf("PVSserver: data send failed\n");
|
||||
}
|
||||
}
|
||||
BSsendHeader(bs,BS_Done,0);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
void handle_recdump(BS* bs)
|
||||
{
|
||||
printf("RecDump server invoked\n");
|
||||
BSsendHeader(bs,BS_Done,0);
|
||||
}
|
||||
|
||||
void PVS_test_server(BS* bs)
|
||||
{
|
||||
printf("PVS_test_server invoked\n");
|
||||
BSsendHeader(bs,BS_Done,0);
|
||||
}
|
||||
|
||||
void handle_spylist(BS* bs)
|
||||
{
|
||||
printf("PVS spy list server invoked\n");
|
||||
}
|
||||
|
||||
void handle_tasklist(BS* bs)
|
||||
{
|
||||
printf("PVS task list server invoked\n");
|
||||
}
|
||||
@@ -49,6 +49,17 @@ static char subst_buffer[VAR_MAX_SUB_SIZE];
|
||||
static int subst_used;
|
||||
static int line_num;
|
||||
|
||||
struct db_app_node
|
||||
{
|
||||
char* name;
|
||||
struct db_app_node* next;
|
||||
};
|
||||
typedef struct db_app_node DB_APP_NODE;
|
||||
|
||||
DB_APP_NODE* DbApplList=(DB_APP_NODE*)NULL;
|
||||
static DB_APP_NODE* DbCurrentListHead=(DB_APP_NODE*)NULL;
|
||||
static DB_APP_NODE* DbCurrentListTail=(DB_APP_NODE*)NULL;
|
||||
|
||||
static int yyerror();
|
||||
static void sub_pvname(char*,char*);
|
||||
|
||||
@@ -65,8 +76,9 @@ extern struct dbBase *pdbBase;
|
||||
%token <Str> WORD VALUE
|
||||
%token <Str> FIELD
|
||||
%left O_BRACE C_BRACE O_PAREN C_PAREN
|
||||
%left DATABASE CONTAINER RECORD
|
||||
%left NOWHERE
|
||||
%left DATABASE RECORD
|
||||
%left NOWHERE
|
||||
%token APPL
|
||||
|
||||
%union
|
||||
{
|
||||
@@ -105,18 +117,39 @@ n_body: O_BRACE records C_BRACE
|
||||
;
|
||||
|
||||
db_components: /* null */
|
||||
| db_components container
|
||||
| db_components applic
|
||||
| db_components record
|
||||
;
|
||||
|
||||
container: CONTAINER c_head c_body
|
||||
;
|
||||
applic: APPL O_PAREN VALUE C_PAREN
|
||||
{
|
||||
DB_APP_NODE* an=(DB_APP_NODE*)malloc(sizeof(DB_APP_NODE*));
|
||||
|
||||
c_head: O_PAREN WORD C_PAREN
|
||||
{ free($2); }
|
||||
;
|
||||
if(subst_used)
|
||||
{
|
||||
strcpy(subst_buffer,$<Str>3);
|
||||
if(dbDoSubst(subst_buffer,sizeof(subst_buffer),NULL)!=0)
|
||||
fprintf(stderr,"dbDoSubst failed\n");
|
||||
#ifdef vxWorks
|
||||
an->name=strdup(subst_buffer);
|
||||
free($3);
|
||||
#else
|
||||
printf("\napplication(\"%s\")\n",subst_buffer);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef vxWorks
|
||||
an->name=$<Str>3;
|
||||
#else
|
||||
printf("\napplication(\"%s\")\n",$<Str>3);
|
||||
#endif
|
||||
}
|
||||
if(DbCurrentListHead==(DB_APP_NODE*)NULL) DbCurrentListTail=an;
|
||||
|
||||
c_body: O_BRACE db_components C_BRACE
|
||||
an->next=DbCurrentListHead;
|
||||
DbCurrentListHead=an;
|
||||
}
|
||||
;
|
||||
|
||||
records: /* null */
|
||||
@@ -190,13 +223,24 @@ field: FIELD O_PAREN WORD COMMA VALUE C_PAREN
|
||||
static int yyerror(str)
|
||||
char *str;
|
||||
{ fprintf(stderr,"db file parse, Error line %d : %s\n",line_num, yytext); }
|
||||
|
||||
#ifdef vxWorks
|
||||
static char* strdup(char* x)
|
||||
{
|
||||
char* c;
|
||||
c=(char*)malloc(strlen(x)+1);
|
||||
strcpy(c,x);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int is_not_inited = 1;
|
||||
|
||||
int dbLoadRecords(char* pfilename, char* pattern, char* container)
|
||||
int dbLoadRecords(char* pfilename, char* pattern)
|
||||
{
|
||||
FILE* fp;
|
||||
long status;
|
||||
DB_APP_NODE* an;
|
||||
|
||||
#ifdef vxWorks
|
||||
if(pdbBase==NULL)
|
||||
@@ -243,6 +287,21 @@ int dbLoadRecords(char* pfilename, char* pattern, char* container)
|
||||
if(subst_used) dbFreeSubst();
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if(DbCurrentListHead==(DB_APP_NODE*)NULL)
|
||||
{
|
||||
/* set up a default list to put on the master application list */
|
||||
DbCurrentListHead=(DB_APP_NODE*)malloc(sizeof(DB_APP_NODE));
|
||||
DbCurrentListTail=DbCurrentListHead;
|
||||
DbCurrentListHead->name=strdup(pfilename);
|
||||
DbCurrentListHead->next=(DB_APP_NODE*)NULL;
|
||||
}
|
||||
|
||||
DbCurrentListTail->next=DbApplList;
|
||||
DbApplList=DbCurrentListHead;
|
||||
DbCurrentListHead=(DB_APP_NODE*)NULL;
|
||||
DbCurrentListTail=(DB_APP_NODE*)NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -276,3 +335,14 @@ static void sub_pvname(char* type, char* name)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef vxWorks
|
||||
int dbAppList()
|
||||
{
|
||||
DB_APP_NODE* an;
|
||||
|
||||
for(an=DbApplList;an;an=an->next)
|
||||
printf("%s\n",an->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,9 +12,9 @@ value [a-zA-Z0-9_\,\^~\./\*#\[\]%: ;!|\'\-&\(\)@\?\+<>=\$\{\}]
|
||||
"field" { return(FIELD); }
|
||||
"grecord" { return(RECORD); }
|
||||
"record" { return(RECORD); }
|
||||
"container" { return(CONTAINER); }
|
||||
"database" { return(DATABASE); }
|
||||
"nowhere" { return(NOWHERE); }
|
||||
"application" { return(APPL); }
|
||||
|
||||
\"{value}*\" { yylval.Str=(char *)malloc(strlen(yytext)+1); strcpy(yylval.Str,yytext+1); yylval.Str[strlen(yylval.Str)-1] = '\0'; return(VALUE); }
|
||||
|
||||
|
||||
@@ -276,9 +276,11 @@ sub_pat: WORD EQUALS WORD
|
||||
|
||||
#include "dbLoadTemplate_lex.c"
|
||||
|
||||
static int yyerror(str)
|
||||
char *str;
|
||||
{ fprintf(stderr,"templ file parse, Error line %d : %s\n",line_num, yytext); }
|
||||
static int yyerror(char* str)
|
||||
{
|
||||
fprintf(stderr,"Substitution file parse error\n");
|
||||
fprintf(stderr,"line %d:%s\n",line_num,yytext);
|
||||
}
|
||||
|
||||
static int is_not_inited = 1;
|
||||
|
||||
|
||||
116
src/dbtools/rdbapplist.c
Normal file
116
src/dbtools/rdbapplist.c
Normal file
@@ -0,0 +1,116 @@
|
||||
|
||||
/* only runable on work station now */
|
||||
|
||||
#include "PVS.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int read_pvs(BSDATA* info,int serv,char* sname);
|
||||
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
BSDATA info;
|
||||
int rc;
|
||||
|
||||
if(argc<2)
|
||||
{
|
||||
fprintf(stderr,"usage: %s IOC-ip-address\n",argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(BSsetAddress(&info,argv[1])<0)
|
||||
{
|
||||
fprintf(stderr,"Cannot determine address for %s\n",argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc=read_pvs(&info,PVS_AppList,(char*)NULL);
|
||||
|
||||
if(rc<0) fprintf(stderr,"read of data failed horribly\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_pvs(BSDATA* info,int serv,char* sname)
|
||||
{
|
||||
BS* bs;
|
||||
int verb,size,done,len,i,port,rsize;
|
||||
char* buffer;
|
||||
char ip_from[40];
|
||||
FILE* fd;
|
||||
|
||||
BSgetAddressPort(info,ip_from,&port);
|
||||
|
||||
/* verify ioc not already added */
|
||||
if(access(ip_from,F_OK)==0)
|
||||
{
|
||||
/* delete the existing file for this IOC */
|
||||
unlink(ip_from);
|
||||
}
|
||||
|
||||
done=0;
|
||||
BSsetPort(info,PVS_TCP_PORT);
|
||||
|
||||
if((bs=BSipOpenData(info))==NULL)
|
||||
{
|
||||
fprintf(stderr,"Open of socket to IOC failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(serv>PVS_LAST_VERB)
|
||||
rsize=strlen(sname)+1;
|
||||
else
|
||||
rsize=0;
|
||||
|
||||
if(BSsendHeader(bs,serv,rsize)<0)
|
||||
{
|
||||
fprintf(stderr,"Command send failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(rsize>0)
|
||||
{
|
||||
if(BSsendData(bs,sname,rsize)<0)
|
||||
{
|
||||
fprintf(stderr,"send of command name failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fd=stdout;
|
||||
buffer=(char*)malloc(PVS_TRANSFER_SIZE+2);
|
||||
|
||||
while(done==0)
|
||||
{
|
||||
if(BSreceiveHeader(bs,&verb,&size)<0)
|
||||
{
|
||||
fprintf(stderr,"Receive header failed\n");
|
||||
done=-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(verb)
|
||||
{
|
||||
case PVS_Data: /* read a block of names */
|
||||
if((len=BSreceiveData(bs,buffer,size))<0)
|
||||
fprintf(stderr,"Receive data failed\n");
|
||||
else
|
||||
fputs(buffer,fd);
|
||||
fputc('\n',fd);
|
||||
break;
|
||||
case BS_Done: /* transfers complete */
|
||||
BSclose(bs);
|
||||
done=-1;
|
||||
break;
|
||||
default:
|
||||
if(size>0) done=-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
128
src/dbtools/rdbls.c
Normal file
128
src/dbtools/rdbls.c
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
/* only runable on work station now */
|
||||
|
||||
#include "PVS.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int read_pvs(BSDATA* info,int serv,char* sname);
|
||||
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
BSDATA info;
|
||||
int rc;
|
||||
|
||||
if(argc<2)
|
||||
{
|
||||
fprintf(stderr,"usage: %s IOC-ip-address\n",argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(BSsetAddress(&info,argv[1])<0)
|
||||
{
|
||||
fprintf(stderr,"Cannot determine address for %s\n",argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc=read_pvs(&info,PVS_RecList,(char*)NULL);
|
||||
|
||||
if(rc<0) fprintf(stderr,"read of data failed horribly\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_pvs(BSDATA* info,int serv,char* sname)
|
||||
{
|
||||
BS* bs;
|
||||
int verb,size,done,len,i,port,rsize;
|
||||
char* buffer;
|
||||
char ip_from[40];
|
||||
FILE* fd;
|
||||
|
||||
BSgetAddressPort(info,ip_from,&port);
|
||||
|
||||
/* printf("IOC %s starting\n",ip_from); */
|
||||
|
||||
/* verify ioc not already added */
|
||||
if(access(ip_from,F_OK)==0)
|
||||
{
|
||||
/* delete the existing file for this IOC */
|
||||
unlink(ip_from);
|
||||
}
|
||||
|
||||
done=0;
|
||||
BSsetPort(info,PVS_TCP_PORT);
|
||||
|
||||
if((bs=BSipOpenData(info))==NULL)
|
||||
{
|
||||
fprintf(stderr,"Open of socket to IOC failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(serv>PVS_LAST_VERB)
|
||||
rsize=strlen(sname)+1;
|
||||
else
|
||||
rsize=0;
|
||||
|
||||
if(BSsendHeader(bs,serv,rsize)<0)
|
||||
{
|
||||
fprintf(stderr,"Command send failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(rsize>0)
|
||||
{
|
||||
if(BSsendData(bs,sname,rsize)<0)
|
||||
{
|
||||
fprintf(stderr,"send of command name failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fd=stdout;
|
||||
buffer=(char*)malloc(PVS_TRANSFER_SIZE+2);
|
||||
|
||||
while(done==0)
|
||||
{
|
||||
if(BSreceiveHeader(bs,&verb,&size)<0)
|
||||
{
|
||||
fprintf(stderr,"Receive header failed\n");
|
||||
done=-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(verb)
|
||||
{
|
||||
case PVS_Data: /* read a block of names */
|
||||
if((len=BSreceiveData(bs,buffer,size))<0)
|
||||
{
|
||||
fprintf(stderr,"Receive data failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
if(buffer[i]==' ') buffer[i]='\n';
|
||||
}
|
||||
buffer[len]='\n';
|
||||
buffer[len+1]='\0';
|
||||
|
||||
fputs(buffer,fd);
|
||||
}
|
||||
break;
|
||||
case BS_Done: /* transfers complete */
|
||||
BSclose(bs);
|
||||
done=-1;
|
||||
break;
|
||||
default:
|
||||
if(size>0) done=-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,9 @@
|
||||
* for the DMA buffer that is appropriate.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.1 1995/03/30 19:35:14 jba
|
||||
* Seperated drv files into ansi and old dirs. Added combine dir.
|
||||
*
|
||||
* Revision 1.22 1995/01/06 17:03:43 winans
|
||||
* Added some ifdef'd out test code to see if the end of the sequence program
|
||||
* could be updated to NOT cause an extra sample from port zero to be taken
|
||||
@@ -181,7 +184,7 @@ static char *SccsId = "$Id$";
|
||||
#define ADVANCE_HOLD 0xC0
|
||||
#define RESTART 0x00
|
||||
|
||||
/* analogic 2502 memory structure */
|
||||
/* Analogic 2502 memory structure */
|
||||
struct dvx_2502
|
||||
{
|
||||
unsigned short dev_id; /* device id code (CFF5) */
|
||||
@@ -205,7 +208,7 @@ struct dvx_inbuf
|
||||
short *data; /* data buffer */
|
||||
};
|
||||
|
||||
/* analogic 2502 control structure */
|
||||
/* Analogic 2502 control structure */
|
||||
struct dvx_rec
|
||||
{
|
||||
struct dvx_2502 *pdvx2502; /* pointer to device registers */
|
||||
@@ -224,6 +227,8 @@ struct dvx_rec
|
||||
|
||||
int RearmMode; /* zero if auto-rearm, else manual */
|
||||
|
||||
unsigned short ScanRate; /* User settable scan rate */
|
||||
|
||||
IOSCANPVT *pioscanpvt;
|
||||
};
|
||||
|
||||
@@ -304,19 +309,19 @@ struct {
|
||||
static struct dvx_rec dvx[MAX_DVX_CARDS] = {
|
||||
{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}
|
||||
,{0, 0, 0, 0, 0, 0, 0, 0},
|
||||
0 , NULL
|
||||
0 , DVX_DRATE, NULL
|
||||
},
|
||||
{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}
|
||||
,{0, 0, 0, 0, 0, 0, 0, 0},
|
||||
0, NULL
|
||||
0, DVX_DRATE, NULL
|
||||
},
|
||||
{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}
|
||||
,{0, 0, 0, 0, 0, 0, 0, 0},
|
||||
0, NULL
|
||||
0, DVX_DRATE, NULL
|
||||
},
|
||||
{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}
|
||||
,{0, 0, 0, 0, 0, 0, 0, 0},
|
||||
0, NULL
|
||||
0, DVX_DRATE, NULL
|
||||
}
|
||||
};
|
||||
|
||||
@@ -425,6 +430,16 @@ dvx_int(struct dvx_rec *dvxptr)
|
||||
cptr->csr = dvxptr->csr_shadow;
|
||||
}
|
||||
|
||||
int dvx_SetScanRate(int Card, unsigned int Rate)
|
||||
{
|
||||
/* make sure hardware exists */
|
||||
if ((Card >= ai_num_cards[DVX2502]) || (Card < 0))
|
||||
return(-1);
|
||||
|
||||
dvx[Card].ScanRate = Rate & 0x0000FFFF;
|
||||
dvx[Card].pdvx2502->samp_rate = dvx[Card].ScanRate;
|
||||
return(0);
|
||||
}
|
||||
int dvx_RearmModeSet(int card, int mode)
|
||||
{
|
||||
/* make sure hardware exists */
|
||||
@@ -672,7 +687,11 @@ LOCAL long dvx_driver_init(void)
|
||||
/*
|
||||
* set scan rate and enable external start
|
||||
*/
|
||||
#if 0
|
||||
pDvxA16->samp_rate = DVX_DRATE; /* scan rate of 184 KHz */
|
||||
#else
|
||||
pDvxA16->samp_rate = dvx[i].ScanRate; /* Set scan rate */
|
||||
#endif
|
||||
dvx[i].csr_shadow |= CSR_M_ESTART; /* enable ext start (shadow csr) */
|
||||
pDvxA16->csr = dvx[i].csr_shadow; /* enable external start */
|
||||
dvx[i].mode = RUN_MODE; /* ready to aquire data */
|
||||
@@ -904,12 +923,17 @@ int sramld(int card)
|
||||
#endif
|
||||
|
||||
/* set scan rate and run it once */
|
||||
#if 0
|
||||
dvx[card].pdvx2502->samp_rate = DVX_DRATE;
|
||||
#else
|
||||
dvx[card].pdvx2502->samp_rate = dvx[card].ScanRate; /* Set scan rate */
|
||||
#endif
|
||||
dvx[card].pdvx2502->csr = dvx[card].csr_shadow | CSR_M_START;
|
||||
taskDelay(sysClkRateGet()); /* let scan run */
|
||||
dvx[card].pdvx2502->csr = dvx[card].csr_shadow; /* restore csr */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dvx_driver
|
||||
*
|
||||
|
||||
@@ -45,6 +45,8 @@ SRCS.c += ../recSubArray.c
|
||||
SRCS.c += ../recTimer.c
|
||||
SRCS.c += ../recWait.c
|
||||
SRCS.c += ../recWaitCa.c
|
||||
SRCS.c += ../recDynLink.c
|
||||
SRCS.c += ../recDynLinkTest.c
|
||||
SRCS.c += ../recWaveform.c
|
||||
|
||||
# LIBOBJS += recAai.o
|
||||
@@ -88,6 +90,8 @@ LIBOBJS += recSubArray.o
|
||||
LIBOBJS += recTimer.o
|
||||
LIBOBJS += recWait.o
|
||||
LIBOBJS += recWaitCa.o
|
||||
LIBOBJS += recDynLink.o
|
||||
LIBOBJS += recDynLinkTest.o
|
||||
LIBOBJS += recWaveform.o
|
||||
|
||||
LIBNAME = recSup
|
||||
|
||||
542
src/rec/recDynLink.c
Normal file
542
src/rec/recDynLink.c
Normal file
@@ -0,0 +1,542 @@
|
||||
/*recDynLink.c*/
|
||||
/*****************************************************************
|
||||
COPYRIGHT NOTIFICATION
|
||||
*****************************************************************
|
||||
|
||||
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
|
||||
|
||||
This software was developed under a United States Government license
|
||||
described on the COPYRIGHT_UniversityOfChicago file included as part
|
||||
of this distribution.
|
||||
**********************************************************************/
|
||||
#include <vxWorks.h>
|
||||
#include <taskLib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <rngLib.h>
|
||||
#include <vxLib.h>
|
||||
#include <semLib.h>
|
||||
#include <sysLib.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <taskwd.h>
|
||||
#include <fast_lock.h>
|
||||
#include <db_access.h>
|
||||
#include <cadef.h>
|
||||
#include <caerr.h>
|
||||
#include <caeventmask.h>
|
||||
#include <calink.h>
|
||||
#include <tsDefs.h>
|
||||
#include <task_params.h>
|
||||
#include <recDynLink.h>
|
||||
|
||||
|
||||
/*Definitions to map between old and new database access*/
|
||||
/*because we are using CA must include db_access.h*/
|
||||
/* new field types */
|
||||
#define newDBF_STRING 0
|
||||
#define newDBF_CHAR 1
|
||||
#define newDBF_UCHAR 2
|
||||
#define newDBF_SHORT 3
|
||||
#define newDBF_USHORT 4
|
||||
#define newDBF_LONG 5
|
||||
#define newDBF_ULONG 6
|
||||
#define newDBF_FLOAT 7
|
||||
#define newDBF_DOUBLE 8
|
||||
#define newDBF_ENUM 9
|
||||
|
||||
/* new data request buffer types */
|
||||
#define newDBR_STRING newDBF_STRING
|
||||
#define newDBR_CHAR newDBF_CHAR
|
||||
#define newDBR_UCHAR newDBF_UCHAR
|
||||
#define newDBR_SHORT newDBF_SHORT
|
||||
#define newDBR_USHORT newDBF_USHORT
|
||||
#define newDBR_LONG newDBF_LONG
|
||||
#define newDBR_ULONG newDBF_ULONG
|
||||
#define newDBR_FLOAT newDBF_FLOAT
|
||||
#define newDBR_DOUBLE newDBF_DOUBLE
|
||||
#define newDBR_ENUM newDBF_ENUM
|
||||
#define VALID_newDB_REQ(x) ((x >= 0) && (x <= newDBR_ENUM))
|
||||
static short mapOldToNew[DBF_DOUBLE+1] = {
|
||||
newDBR_STRING,newDBR_SHORT,newDBR_FLOAT,newDBR_ENUM,
|
||||
newDBR_CHAR,newDBR_LONG,newDBR_DOUBLE};
|
||||
static short mapNewToOld[newDBR_ENUM+1] = {
|
||||
DBF_STRING,DBF_CHAR,DBF_CHAR,DBF_SHORT,DBF_SHORT,
|
||||
DBF_LONG,DBF_LONG,DBF_FLOAT,DBF_DOUBLE,DBF_ENUM};
|
||||
|
||||
extern int interruptAccept;
|
||||
|
||||
int recDynLinkQsize = 256;
|
||||
|
||||
LOCAL int inpTaskId=0;
|
||||
LOCAL int outTaskId=0;
|
||||
LOCAL RING_ID inpRingQ;;
|
||||
LOCAL RING_ID outRingQ;;
|
||||
LOCAL SEM_ID wakeUpSem;
|
||||
|
||||
typedef enum{cmdSearch,cmdClear,cmdPut} cmdType;
|
||||
typedef enum{ioInput,ioOutput}ioType;
|
||||
typedef enum{stateStarting,stateSearching,stateGetting,stateConnected}stateType;
|
||||
|
||||
typedef struct dynLinkPvt{
|
||||
FAST_LOCK lock;
|
||||
char *pvname;
|
||||
chid chid;
|
||||
evid evid;
|
||||
recDynCallback searchCallback;
|
||||
recDynCallback monitorCallback;
|
||||
TS_STAMP timestamp;
|
||||
short status;
|
||||
short severity;
|
||||
void *pbuffer;
|
||||
size_t nRequest;
|
||||
short dbrType;
|
||||
double graphicLow,graphHigh;
|
||||
double controlLow,controlHigh;
|
||||
char units[MAX_UNITS_SIZE];
|
||||
short precision;
|
||||
ioType io;
|
||||
stateType state;
|
||||
short scalar;
|
||||
} dynLinkPvt;
|
||||
|
||||
/*For cmdClear data is chid. For all other commands precDynLink*/
|
||||
typedef struct {
|
||||
union {
|
||||
recDynLink *precDynLink;
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
}data;
|
||||
cmdType cmd;
|
||||
}ringBufCmd;
|
||||
|
||||
LOCAL void recDynLinkStartInput(void);
|
||||
LOCAL void recDynLinkStartOutput(void);
|
||||
LOCAL void connectCallback(struct connection_handler_args cha);
|
||||
LOCAL void getCallback(struct event_handler_args eha);
|
||||
LOCAL void monitorCallback(struct event_handler_args eha);
|
||||
LOCAL void recDynLinkInp(void);
|
||||
LOCAL void recDynLinkOut(void);
|
||||
|
||||
long recDynLinkAddInput(recDynLink *precDynLink,char *pvname,
|
||||
short dbrType,int options,
|
||||
recDynCallback searchCallback,recDynCallback monitorCallback)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
struct db_addr dbaddr;
|
||||
ringBufCmd cmd;
|
||||
|
||||
|
||||
if(options&rdlDBONLY && db_name_to_addr(pvname,&dbaddr))return(-1);
|
||||
if(!inpTaskId) recDynLinkStartInput();
|
||||
if(precDynLink->pdynLinkPvt) recDynLinkClear(precDynLink);
|
||||
pdynLinkPvt = (dynLinkPvt *)calloc(1,sizeof(dynLinkPvt));
|
||||
if(!pdynLinkPvt) {
|
||||
printf("recDynLinkAddInput can't allocate storage");
|
||||
taskSuspend(0);
|
||||
}
|
||||
FASTLOCKINIT(&pdynLinkPvt->lock);
|
||||
precDynLink->pdynLinkPvt = pdynLinkPvt;
|
||||
pdynLinkPvt->pvname = pvname;
|
||||
pdynLinkPvt->dbrType = dbrType;
|
||||
pdynLinkPvt->searchCallback = searchCallback;
|
||||
pdynLinkPvt->monitorCallback = monitorCallback;
|
||||
pdynLinkPvt->io = ioInput;
|
||||
pdynLinkPvt->scalar = (options&rdlSCALAR) ? TRUE : FALSE;
|
||||
pdynLinkPvt->state = stateStarting;
|
||||
cmd.data.precDynLink = precDynLink;
|
||||
cmd.cmd = cmdSearch;
|
||||
if(rngBufPut(inpRingQ,(void *)&cmd,sizeof(cmd)) != sizeof(cmd))
|
||||
errMessage(0,"recDynLinkAddInput: rngBufPut error");
|
||||
return(0);
|
||||
}
|
||||
|
||||
long recDynLinkAddOutput(recDynLink *precDynLink,char *pvname,
|
||||
short dbrType,int options,
|
||||
recDynCallback searchCallback)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
struct db_addr dbaddr;
|
||||
ringBufCmd cmd;
|
||||
|
||||
|
||||
if(options&rdlDBONLY && db_name_to_addr(pvname,&dbaddr))return(-1);
|
||||
if(!outTaskId) recDynLinkStartOutput();
|
||||
if(precDynLink->pdynLinkPvt) recDynLinkClear(precDynLink);
|
||||
pdynLinkPvt = (dynLinkPvt *)calloc(1,sizeof(dynLinkPvt));
|
||||
if(!pdynLinkPvt) {
|
||||
printf("recDynLinkAddOutput can't allocate storage");
|
||||
taskSuspend(0);
|
||||
}
|
||||
FASTLOCKINIT(&pdynLinkPvt->lock);
|
||||
precDynLink->pdynLinkPvt = pdynLinkPvt;
|
||||
pdynLinkPvt->pvname = pvname;
|
||||
pdynLinkPvt->dbrType = dbrType;
|
||||
pdynLinkPvt->searchCallback = searchCallback;
|
||||
pdynLinkPvt->io = ioOutput;
|
||||
pdynLinkPvt->scalar = (options&rdlSCALAR) ? TRUE : FALSE;
|
||||
pdynLinkPvt->state = stateStarting;
|
||||
cmd.data.precDynLink = precDynLink;
|
||||
cmd.cmd = cmdSearch;
|
||||
if(rngBufPut(outRingQ,(void *)&cmd,sizeof(cmd)) != sizeof(cmd))
|
||||
errMessage(0,"recDynLinkAddInput: rngBufPut error");
|
||||
semGive(wakeUpSem);
|
||||
return(0);
|
||||
}
|
||||
|
||||
long recDynLinkClear(recDynLink *precDynLink)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
ringBufCmd cmd;
|
||||
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
if(!pdynLinkPvt) {
|
||||
printf("recDynLinkClear. recDynLinkSearch was never called\n");
|
||||
taskSuspend(0);
|
||||
}
|
||||
if(pdynLinkPvt->chid) ca_puser(pdynLinkPvt->chid) = NULL;
|
||||
cmd.data.pdynLinkPvt = pdynLinkPvt;
|
||||
cmd.cmd = cmdClear;
|
||||
if(pdynLinkPvt->io==ioInput) {
|
||||
if(rngBufPut(inpRingQ,(void *)&cmd,sizeof(cmd)) != sizeof(cmd))
|
||||
errMessage(0,"recDynLinkClear: rngBufPut error");
|
||||
} else {
|
||||
if(rngBufPut(outRingQ,(void *)&cmd,sizeof(cmd)) != sizeof(cmd))
|
||||
errMessage(0,"recDynLinkClear: rngBufPut error");
|
||||
}
|
||||
precDynLink->pdynLinkPvt = NULL;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long recDynLinkConnectionStatus(recDynLink *precDynLink)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
long status;
|
||||
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
status = (ca_state(pdynLinkPvt->chid)==cs_conn) ? 0 : -1;
|
||||
return(status);
|
||||
}
|
||||
|
||||
long recDynLinkGetNelem(recDynLink *precDynLink,size_t *nelem)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
if(ca_state(pdynLinkPvt->chid)!=cs_conn) return(-1);
|
||||
*nelem = ca_element_count(pdynLinkPvt->chid);
|
||||
return(0);
|
||||
}
|
||||
|
||||
long recDynLinkGetControlLimits(recDynLink *precDynLink,
|
||||
double *low,double *high)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
if(pdynLinkPvt->state!=stateConnected) return(-1);
|
||||
if(low) *low = pdynLinkPvt->controlLow;
|
||||
if(high) *high = pdynLinkPvt->controlHigh;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long recDynLinkGetGraphicLimits(recDynLink *precDynLink,
|
||||
double *low,double *high)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
if(pdynLinkPvt->state!=stateConnected) return(-1);
|
||||
if(low) *low = pdynLinkPvt->graphicLow;
|
||||
if(high) *high = pdynLinkPvt->graphHigh;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long recDynLinkGetPrecision(recDynLink *precDynLink,int *prec)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
if(pdynLinkPvt->state!=stateConnected) return(-1);
|
||||
if(prec) *prec = pdynLinkPvt->precision;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long recDynLinkGetUnits(recDynLink *precDynLink,char *units,int maxlen)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
int maxToCopy;
|
||||
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
if(pdynLinkPvt->state!=stateConnected) return(-1);
|
||||
maxToCopy = MAX_UNITS_SIZE;
|
||||
if(maxlen<maxToCopy) maxToCopy = maxlen;
|
||||
strncpy(units,pdynLinkPvt->units,maxToCopy);
|
||||
if(maxToCopy<maxlen) units[maxToCopy] = '\0';
|
||||
return(0);
|
||||
}
|
||||
|
||||
long recDynLinkGet(recDynLink *precDynLink,void *pbuffer,size_t *nRequest,
|
||||
TS_STAMP *timestamp,short *status,short *severity)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
long caStatus;
|
||||
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
caStatus = (ca_state(pdynLinkPvt->chid)==cs_conn) ? 0 : -1;
|
||||
if(caStatus) goto all_done;
|
||||
if(*nRequest > pdynLinkPvt->nRequest) {
|
||||
*nRequest = pdynLinkPvt->nRequest;
|
||||
}
|
||||
FASTLOCK(&pdynLinkPvt->lock);
|
||||
memcpy(pbuffer,pdynLinkPvt->pbuffer,
|
||||
(*nRequest * dbr_size[mapNewToOld[pdynLinkPvt->dbrType]]));
|
||||
if(timestamp) *timestamp = pdynLinkPvt->timestamp; /*array copy*/
|
||||
if(status) *status = pdynLinkPvt->status;
|
||||
if(severity) *severity = pdynLinkPvt->severity;
|
||||
FASTUNLOCK(&pdynLinkPvt->lock);
|
||||
all_done:
|
||||
return(caStatus);
|
||||
}
|
||||
|
||||
long recDynLinkPut(recDynLink *precDynLink,void *pbuffer,size_t nRequest)
|
||||
{
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
long status;
|
||||
ringBufCmd cmd;
|
||||
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
if(pdynLinkPvt->io!=ioOutput || pdynLinkPvt->state!=stateConnected) {
|
||||
status = -1;
|
||||
} else {
|
||||
status = (ca_state(pdynLinkPvt->chid)==cs_conn) ? 0 : -1;
|
||||
}
|
||||
if(status) goto all_done;
|
||||
if(pdynLinkPvt->scalar) nRequest = 1;
|
||||
if(nRequest>ca_element_count(pdynLinkPvt->chid))
|
||||
nRequest = ca_element_count(pdynLinkPvt->chid);
|
||||
pdynLinkPvt->nRequest = nRequest;
|
||||
memcpy(pdynLinkPvt->pbuffer,pbuffer,
|
||||
(nRequest * dbr_size[mapNewToOld[pdynLinkPvt->dbrType]]));
|
||||
cmd.data.precDynLink = precDynLink;
|
||||
cmd.cmd = cmdPut;
|
||||
if(rngBufPut(outRingQ,(void *)&cmd,sizeof(cmd)) != sizeof(cmd))
|
||||
errMessage(0,"recDynLinkPut: rngBufPut error");
|
||||
semGive(wakeUpSem);
|
||||
all_done:
|
||||
return(status);
|
||||
}
|
||||
|
||||
LOCAL void recDynLinkStartInput(void)
|
||||
{
|
||||
if((inpRingQ = rngCreate(sizeof(ringBufCmd) * recDynLinkQsize)) == NULL) {
|
||||
errMessage(0,"recDynLinkStart failed");
|
||||
exit(1);
|
||||
}
|
||||
inpTaskId = taskSpawn("recDynINP",CA_CLIENT_PRI-1,VX_FP_TASK,
|
||||
CA_CLIENT_STACK,(FUNCPTR)recDynLinkInp,0,0,0,0,0,0,0,0,0,0);
|
||||
if(inpTaskId==ERROR) {
|
||||
errMessage(0,"recDynLinkStartInput: taskSpawn Failure\n");
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL void recDynLinkStartOutput(void)
|
||||
{
|
||||
if((wakeUpSem=semBCreate(SEM_Q_FIFO,SEM_EMPTY))==NULL)
|
||||
errMessage(0,"semBcreate failed in recDynLinkStart");
|
||||
if((outRingQ = rngCreate(sizeof(ringBufCmd) * recDynLinkQsize)) == NULL) {
|
||||
errMessage(0,"recDynLinkStartOutput failed");
|
||||
exit(1);
|
||||
}
|
||||
outTaskId = taskSpawn("recDynOUT",CA_CLIENT_PRI-1,VX_FP_TASK,
|
||||
CA_CLIENT_STACK,(FUNCPTR)recDynLinkOut,0,0,0,0,0,0,0,0,0,0);
|
||||
if(outTaskId==ERROR) {
|
||||
errMessage(0,"recDynLinkStart: taskSpawn Failure\n");
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL void connectCallback(struct connection_handler_args cha)
|
||||
{
|
||||
chid chid = cha.chid;
|
||||
recDynLink *precDynLink;
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
|
||||
precDynLink = (recDynLink *)ca_puser(cha.chid);
|
||||
if(!precDynLink) return;
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
if(ca_state(chid)==cs_conn) {
|
||||
pdynLinkPvt->state = stateGetting;
|
||||
SEVCHK(ca_get_callback(DBR_CTRL_DOUBLE,chid,getCallback,precDynLink),
|
||||
"ca_get_callback");
|
||||
} else {
|
||||
if(pdynLinkPvt->searchCallback)
|
||||
(pdynLinkPvt->searchCallback)(precDynLink);
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL void getCallback(struct event_handler_args eha)
|
||||
{
|
||||
struct dbr_ctrl_double *pdata = (struct dbr_ctrl_double *)eha.dbr;
|
||||
recDynLink *precDynLink;
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
size_t nRequest;
|
||||
|
||||
precDynLink = (recDynLink *)ca_puser(eha.chid);
|
||||
if(!precDynLink) return;
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
pdynLinkPvt -> graphicLow = pdata->lower_disp_limit;
|
||||
pdynLinkPvt -> graphHigh = pdata->upper_disp_limit;
|
||||
pdynLinkPvt -> controlLow = pdata->lower_ctrl_limit;
|
||||
pdynLinkPvt -> controlHigh = pdata->upper_ctrl_limit;
|
||||
pdynLinkPvt -> precision = pdata->precision;
|
||||
strncpy(pdynLinkPvt->units,pdata->units,MAX_UNITS_SIZE);
|
||||
if(pdynLinkPvt->scalar) {
|
||||
pdynLinkPvt->nRequest = 1;
|
||||
} else {
|
||||
pdynLinkPvt->nRequest = ca_element_count(pdynLinkPvt->chid);
|
||||
}
|
||||
nRequest = pdynLinkPvt->nRequest;
|
||||
pdynLinkPvt->pbuffer = calloc(nRequest,
|
||||
dbr_size[mapNewToOld[pdynLinkPvt->dbrType]]);
|
||||
if(pdynLinkPvt->io==ioInput) {
|
||||
SEVCHK(ca_add_array_event(
|
||||
dbf_type_to_DBR_TIME(mapNewToOld[pdynLinkPvt->dbrType]),
|
||||
pdynLinkPvt->nRequest,
|
||||
pdynLinkPvt->chid,monitorCallback,precDynLink,
|
||||
0.0,0.0,0.0,
|
||||
&pdynLinkPvt->evid),"ca_add_array_event");
|
||||
}
|
||||
pdynLinkPvt->state = stateConnected;
|
||||
if(pdynLinkPvt->searchCallback) (pdynLinkPvt->searchCallback)(precDynLink);
|
||||
}
|
||||
|
||||
LOCAL void monitorCallback(struct event_handler_args eha)
|
||||
{
|
||||
recDynLink *precDynLink;
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
long count = eha.count;
|
||||
void *pbuffer = eha.dbr;
|
||||
struct dbr_time_string *pdbr_time_string;
|
||||
void *pdata;
|
||||
short timeType;
|
||||
|
||||
precDynLink = (recDynLink *)ca_puser(eha.chid);
|
||||
if(!precDynLink) return;
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
if(pdynLinkPvt->pbuffer) {
|
||||
FASTLOCK(&pdynLinkPvt->lock);
|
||||
if(count>=pdynLinkPvt->nRequest)
|
||||
count = pdynLinkPvt->nRequest;
|
||||
pdbr_time_string = (struct dbr_time_string *)pbuffer;
|
||||
timeType = dbf_type_to_DBR_TIME(mapNewToOld[pdynLinkPvt->dbrType]);
|
||||
pdata = (void *)((char *)pbuffer + dbr_value_offset[timeType]);
|
||||
pdynLinkPvt->timestamp = pdbr_time_string->stamp; /*array copy*/
|
||||
pdynLinkPvt->status = pdbr_time_string->status;
|
||||
pdynLinkPvt->severity = pdbr_time_string->severity;
|
||||
memcpy(pdynLinkPvt->pbuffer,pdata,
|
||||
(count * dbr_size[mapNewToOld[pdynLinkPvt->dbrType]]));
|
||||
FASTUNLOCK(&pdynLinkPvt->lock);
|
||||
}
|
||||
if(pdynLinkPvt->monitorCallback)
|
||||
(*pdynLinkPvt->monitorCallback)(precDynLink);
|
||||
}
|
||||
|
||||
LOCAL void recDynLinkInp(void)
|
||||
{
|
||||
int status;
|
||||
recDynLink *precDynLink;
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
int caStatus;
|
||||
ringBufCmd cmd;
|
||||
|
||||
taskwdInsert(taskIdSelf(),NULL,NULL);
|
||||
SEVCHK(ca_task_initialize(),"ca_task_initialize");
|
||||
while(TRUE) {
|
||||
while (rngNBytes(inpRingQ)>=sizeof(cmd) && interruptAccept){
|
||||
if(rngBufGet(inpRingQ,(void *)&cmd,sizeof(cmd))
|
||||
!=sizeof(cmd)) {
|
||||
errMessage(0,"recDynLinkTask: rngBufGet error");
|
||||
continue;
|
||||
}
|
||||
if(cmd.cmd==cmdClear) {
|
||||
pdynLinkPvt = cmd.data.pdynLinkPvt;
|
||||
if(pdynLinkPvt->chid)
|
||||
SEVCHK(ca_clear_channel(pdynLinkPvt->chid),
|
||||
"ca_clear_channel");
|
||||
free(pdynLinkPvt->pbuffer);
|
||||
free((void *)pdynLinkPvt);
|
||||
continue;
|
||||
}
|
||||
precDynLink = cmd.data.precDynLink;
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
switch(cmd.cmd) {
|
||||
case(cmdSearch) :
|
||||
SEVCHK(ca_search_and_connect(pdynLinkPvt->pvname,
|
||||
&pdynLinkPvt->chid, connectCallback,precDynLink),
|
||||
"ca_search_and_connect");
|
||||
break;
|
||||
default:
|
||||
epicsPrintf("Logic error statement in recDynLinkTask\n");
|
||||
}
|
||||
}
|
||||
status = ca_pend_event(.1);
|
||||
if(status!=ECA_NORMAL && status!=ECA_TIMEOUT)
|
||||
SEVCHK(status,"ca_pend_event");
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL void recDynLinkOut(void)
|
||||
{
|
||||
int status;
|
||||
recDynLink *precDynLink;
|
||||
dynLinkPvt *pdynLinkPvt;
|
||||
ringBufCmd cmd;
|
||||
int caStatus;
|
||||
|
||||
taskwdInsert(taskIdSelf(),NULL,NULL);
|
||||
SEVCHK(ca_task_initialize(),"ca_task_initialize");
|
||||
while(TRUE) {
|
||||
semTake(wakeUpSem,sysClkRateGet());
|
||||
while (rngNBytes(outRingQ)>=sizeof(cmd) && interruptAccept){
|
||||
if(rngBufGet(outRingQ,(void *)&cmd,sizeof(cmd))
|
||||
!=sizeof(cmd)) {
|
||||
errMessage(0,"recDynLinkTask: rngBufGet error");
|
||||
continue;
|
||||
}
|
||||
if(cmd.cmd==cmdClear) {
|
||||
pdynLinkPvt = cmd.data.pdynLinkPvt;
|
||||
if(pdynLinkPvt->chid)
|
||||
SEVCHK(ca_clear_channel(pdynLinkPvt->chid),
|
||||
"ca_clear_channel");
|
||||
free(pdynLinkPvt->pbuffer);
|
||||
free((void *)pdynLinkPvt);
|
||||
continue;
|
||||
}
|
||||
precDynLink = cmd.data.precDynLink;
|
||||
pdynLinkPvt = precDynLink->pdynLinkPvt;
|
||||
switch(cmd.cmd) {
|
||||
case(cmdSearch) :
|
||||
SEVCHK(ca_search_and_connect(pdynLinkPvt->pvname,
|
||||
&pdynLinkPvt->chid, connectCallback,precDynLink),
|
||||
"ca_search_and_connect");
|
||||
break;
|
||||
case(cmdPut) :
|
||||
caStatus = ca_array_put(
|
||||
mapNewToOld[pdynLinkPvt->dbrType],
|
||||
pdynLinkPvt->nRequest,pdynLinkPvt->chid,
|
||||
pdynLinkPvt->pbuffer);
|
||||
if(caStatus!=ECA_NORMAL) {
|
||||
epicsPrintf("recDynLinkTask pv=%s CA Error %s\n",
|
||||
pdynLinkPvt->pvname,ca_message(caStatus));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
epicsPrintf("Logic error statement in recDynLinkTask\n");
|
||||
}
|
||||
}
|
||||
status = ca_pend_event(.00001);
|
||||
if(status!=ECA_NORMAL && status!=ECA_TIMEOUT)
|
||||
SEVCHK(status,"ca_pend_event");
|
||||
}
|
||||
}
|
||||
51
src/rec/recDynLink.h
Normal file
51
src/rec/recDynLink.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*recDynLink.c*/
|
||||
/*****************************************************************
|
||||
COPYRIGHT NOTIFICATION
|
||||
*****************************************************************
|
||||
|
||||
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
|
||||
|
||||
This software was developed under a United States Government license
|
||||
described on the COPYRIGHT_UniversityOfChicago file included as part
|
||||
of this distribution.
|
||||
*******************************************************************/
|
||||
#ifndef INCrecDynLinkh
|
||||
#define INCrecDynLinkh
|
||||
|
||||
#include <tsDefs.h>
|
||||
typedef struct recDynLink{
|
||||
void *puserPvt;
|
||||
void *pdynLinkPvt;
|
||||
} recDynLink;
|
||||
typedef void (*recDynCallback)(recDynLink *);
|
||||
|
||||
#define rdlDBONLY 0x1
|
||||
#define rdlSCALAR 0x2
|
||||
|
||||
long recDynLinkAddInput(recDynLink *precDynLink,char *pvname,
|
||||
short dbrType,int options,
|
||||
recDynCallback searchCallback,recDynCallback monitorCallback);
|
||||
long recDynLinkAddOutput(recDynLink *precDynLink,char *pvname,
|
||||
short dbrType,int options,
|
||||
recDynCallback searchCallback);
|
||||
long recDynLinkClear(recDynLink *precDynLink);
|
||||
/*The following routine returns (0,-1) for (connected,not connected)*/
|
||||
long recDynLinkConnectionStatus(recDynLink *precDynLink);
|
||||
/*thye following routine returns (0,-1) if (connected,not connected)*/
|
||||
long recDynLinkGetNelem(recDynLink *precDynLink,size_t *nelem);
|
||||
/*The following 4 routines return (0,-1) if data (is, is not) yet available*/
|
||||
/*searchCallback is not called until this info is available*/
|
||||
long recDynLinkGetControlLimits(recDynLink *precDynLink,
|
||||
double *low,double *high);
|
||||
long recDynLinkGetGraphicLimits(recDynLink *precDynLink,
|
||||
double *low,double *high);
|
||||
long recDynLinkGetPrecision(recDynLink *precDynLink,int *prec);
|
||||
long recDynLinkGetUnits(recDynLink *precDynLink,char *units,int maxlen);
|
||||
|
||||
/*get only valid mfor rdlINPUT. put only valid for rdlOUTPUT*/
|
||||
long recDynLinkGet(recDynLink *precDynLink,
|
||||
void *pbuffer, size_t *nRequest,
|
||||
TS_STAMP *timestamp,short *status,short *severity);
|
||||
long recDynLinkPut(recDynLink *precDynLink,void *pbuffer,size_t nRequest);
|
||||
|
||||
#endif /*INCrecDynLinkh*/
|
||||
191
src/rec/recDynLinkTest.c
Normal file
191
src/rec/recDynLinkTest.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/*recDynLinkTest.c */
|
||||
/*****************************************************************
|
||||
COPYRIGHT NOTIFICATION
|
||||
*****************************************************************
|
||||
|
||||
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
|
||||
|
||||
This software was developed under a United States Government license
|
||||
described on the COPYRIGHT_UniversityOfChicago file included as part
|
||||
of this distribution.
|
||||
***********************************************************************/
|
||||
#include <vxWorks.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <tsDefs.h>
|
||||
#include <recDynLink.h>
|
||||
#include <dbAccess.h>
|
||||
|
||||
/*The remainder of this source module is test code */
|
||||
typedef struct userPvt {
|
||||
char *pvname;
|
||||
double *pbuffer;
|
||||
size_t nRequest;
|
||||
}userPvt;
|
||||
|
||||
LOCAL void mymonitorCallback(recDynLink *precDynLink)
|
||||
{
|
||||
userPvt *puserPvt;
|
||||
long status;
|
||||
size_t nRequest;
|
||||
TS_STAMP timestamp;
|
||||
short AlarmStatus,AlarmSeverity;
|
||||
int i;
|
||||
char timeStr[40];
|
||||
|
||||
puserPvt = (userPvt *)precDynLink->puserPvt;
|
||||
printf("mymonitorCallback: %s\n",puserPvt->pvname);
|
||||
if(recDynLinkConnectionStatus(precDynLink)!=0) {
|
||||
printf(" not connected\n");
|
||||
return;
|
||||
}
|
||||
nRequest = puserPvt->nRequest;
|
||||
status = recDynLinkGet(precDynLink,puserPvt->pbuffer,&nRequest,
|
||||
×tamp,&AlarmStatus,&AlarmSeverity);
|
||||
if(status) {
|
||||
printf("recDynLinkGet returned illegal status\n");
|
||||
return;
|
||||
}
|
||||
tsStampToText(×tamp,TS_TEXT_MMDDYY,timeStr);
|
||||
printf("date %s status %hd severity %hd ",
|
||||
timeStr,AlarmStatus,AlarmSeverity);
|
||||
for(i=0; i<puserPvt->nRequest; i++) {
|
||||
printf(" %f",puserPvt->pbuffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
LOCAL void mysearchCallback(recDynLink *precDynLink)
|
||||
{
|
||||
userPvt *puserPvt;
|
||||
size_t nelem;
|
||||
double controlLow,controlHigh;
|
||||
double graphicLow,graphicHigh;
|
||||
int prec;
|
||||
char units[20];
|
||||
long status;
|
||||
|
||||
puserPvt = (userPvt *)precDynLink->puserPvt;
|
||||
printf("mysearchCallback: %s ",puserPvt->pvname);
|
||||
if(recDynLinkConnectionStatus(precDynLink)==0) {
|
||||
printf("connected\n");
|
||||
status = recDynLinkGetNelem(precDynLink,&nelem);
|
||||
if(status) {
|
||||
printf("recDynLinkGetNelem failed\n");
|
||||
}else{
|
||||
printf("nelem = %u\n",nelem);
|
||||
}
|
||||
status=recDynLinkGetControlLimits(precDynLink,&controlLow,&controlHigh);
|
||||
if(status) {
|
||||
printf("recDynLinkGetControlLimits failed\n");
|
||||
}else{
|
||||
printf("controlLow %f controlHigh %f\n",controlLow,controlHigh);
|
||||
}
|
||||
status=recDynLinkGetGraphicLimits(precDynLink,&graphicLow,&graphicHigh);
|
||||
if(status) {
|
||||
printf("recDynLinkGetGraphicLimits failed\n");
|
||||
}else{
|
||||
printf("graphicLow %f graphicHigh %f\n",graphicLow,graphicHigh);
|
||||
}
|
||||
status = recDynLinkGetPrecision(precDynLink,&prec);
|
||||
if(status) {
|
||||
printf("recDynLinkGetPrecision failed\n");
|
||||
}else{
|
||||
printf("prec = %d\n",prec);
|
||||
}
|
||||
status = recDynLinkGetUnits(precDynLink,units,20);
|
||||
if(status) {
|
||||
printf("recDynLinkGetUnits failed\n");
|
||||
}else{
|
||||
printf("units = %s\n",units);
|
||||
}
|
||||
} else {
|
||||
printf(" not connected\n");
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL recDynLink getDynlink = {NULL,NULL};
|
||||
LOCAL recDynLink putDynlink = {NULL,NULL};
|
||||
|
||||
int recDynTestInput(char *pvname,int nRequest)
|
||||
{
|
||||
userPvt *puserPvt= getDynlink.puserPvt;
|
||||
long status;
|
||||
int options=0;
|
||||
|
||||
if(puserPvt) {
|
||||
recDynLinkClear(&getDynlink);
|
||||
free(puserPvt->pbuffer);
|
||||
free(getDynlink.puserPvt);
|
||||
getDynlink.puserPvt = NULL;
|
||||
}
|
||||
getDynlink.puserPvt = puserPvt = (userPvt *)calloc(1,sizeof(userPvt));
|
||||
puserPvt->pbuffer = calloc(nRequest,sizeof(double));
|
||||
puserPvt->nRequest = nRequest;
|
||||
puserPvt->pvname = pvname;
|
||||
if(nRequest==1) options=rdlSCALAR;;
|
||||
status = recDynLinkAddInput(&getDynlink,pvname,
|
||||
DBR_DOUBLE,options,
|
||||
mysearchCallback,mymonitorCallback);
|
||||
if(status) return(status);
|
||||
return(status);
|
||||
}
|
||||
|
||||
int recDynTestNewOutput(char *pvname,int nRequest)
|
||||
{
|
||||
userPvt *puserPvt= putDynlink.puserPvt;
|
||||
long status;
|
||||
int options=0;
|
||||
|
||||
if(puserPvt) {
|
||||
recDynLinkClear(&putDynlink);
|
||||
free(puserPvt->pbuffer);
|
||||
free(putDynlink.puserPvt);
|
||||
putDynlink.puserPvt = NULL;
|
||||
}
|
||||
putDynlink.puserPvt = puserPvt = (userPvt *)calloc(1,sizeof(userPvt));
|
||||
puserPvt->pbuffer = calloc(nRequest,sizeof(double));
|
||||
puserPvt->nRequest = nRequest;
|
||||
puserPvt->pvname = pvname;
|
||||
if(nRequest==1) options=rdlSCALAR;;
|
||||
status = recDynLinkAddOutput(&putDynlink,pvname,
|
||||
DBR_DOUBLE,options,mysearchCallback);
|
||||
return(status);
|
||||
}
|
||||
|
||||
int recDynTestOutput(int startValue)
|
||||
{
|
||||
userPvt *puserPvt= putDynlink.puserPvt;
|
||||
long status;
|
||||
int i;
|
||||
|
||||
for(i=0; i<puserPvt->nRequest; i++) puserPvt->pbuffer[i] = startValue + i;
|
||||
status = recDynLinkPut(&putDynlink,puserPvt->pbuffer,puserPvt->nRequest);
|
||||
return(status);
|
||||
}
|
||||
|
||||
int recDynTestClearInput(void)
|
||||
{
|
||||
userPvt *puserPvt= getDynlink.puserPvt;
|
||||
|
||||
recDynLinkClear(&getDynlink);
|
||||
free(puserPvt->pbuffer);
|
||||
free(getDynlink.puserPvt);
|
||||
getDynlink.puserPvt = NULL;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int recDynTestClearOutput(void)
|
||||
{
|
||||
userPvt *puserPvt= putDynlink.puserPvt;
|
||||
|
||||
recDynLinkClear(&putDynlink);
|
||||
free(puserPvt->pbuffer);
|
||||
free(putDynlink.puserPvt);
|
||||
putDynlink.puserPvt = NULL;
|
||||
return(0);
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
|
||||
/*
|
||||
* $Log$
|
||||
* Revision 1.14 1995/08/30 15:38:39 jbk
|
||||
* *** empty log message ***
|
||||
*
|
||||
* Revision 1.13 1995/08/18 13:19:31 mrk
|
||||
* Made changes for ansi c
|
||||
*
|
||||
* Revision 1.12 1995/08/17 20:35:09 jbk
|
||||
* fixed all the -pendantic errors (pain)
|
||||
*
|
||||
@@ -99,7 +105,8 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).
|
||||
*/
|
||||
|
||||
#define MAKE_DEBUG TSdriverDebug
|
||||
#define TS_DRIVER
|
||||
#define TS_DRIVER 1
|
||||
#define TS_ALLOW_FORCE 1
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <vme.h>
|
||||
@@ -213,6 +220,9 @@ TSinfo TSdata = { TS_master_dead, TS_async_slave, TS_async_none,
|
||||
|
||||
extern char* sysBootLine;
|
||||
|
||||
int TSdirectTimeVar = 0; /* aother way to indicate direct time */
|
||||
int TSgoodTimeStamps = 0; /* a way to force use of accurate time stamps */
|
||||
|
||||
static WDOG_ID wd;
|
||||
static long correction_factor = 0;
|
||||
static long correction_count = 0;
|
||||
@@ -383,8 +393,13 @@ long TSgetTimeStamp(int event_number,struct timespec* sp)
|
||||
switch(event_number)
|
||||
{
|
||||
case 0:
|
||||
*sp = TSdata.event_table[0]; /* one tick watch dog maintains */
|
||||
break;
|
||||
#ifdef TS_ALLOW_FORCE
|
||||
if(TSgoodTimeStamps==0)
|
||||
#endif
|
||||
{
|
||||
*sp = TSdata.event_table[0]; /* one tick watch dog maintains */
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
{
|
||||
struct timespec ts;
|
||||
@@ -494,6 +509,8 @@ long TSinit(void)
|
||||
TSregisterErrorHandler = TSregisterErrorHandlerError;
|
||||
TSforceSync = TSforceSoftSync;
|
||||
TSgetTime = TSgetCurrentTime;
|
||||
TSdriverInit = TSdriverInitError;
|
||||
TSdirectTime = TSdirectTimeError;
|
||||
TSdata.sync_event=ER_EVENT_RESET_TICK;
|
||||
}
|
||||
|
||||
@@ -518,7 +535,7 @@ long TSinit(void)
|
||||
else
|
||||
TSdata.has_event_system = 1;
|
||||
|
||||
if(TSdirectTime()>0) TSdata.has_direct_time=1;
|
||||
if(TSdirectTime()>0 || TSdirectTimeVar>0) TSdata.has_direct_time=1;
|
||||
|
||||
/* allocate the event table */
|
||||
TSdata.event_table=(struct timespec*)malloc(
|
||||
|
||||
Reference in New Issue
Block a user