Пример #1
0
bool VISAInstrument::Initialize()
{
    char desc[256];
    char error_desc[512];
    //check visa system status
    if(!VISASystemManager::Status()){
        fErrorCode="Can't Initialize VISA system";
        fStatus=VI_STATE_UNKNOWN;
        return false;
    }
    //find exactly the unique specified instr,no findlist
    int length=fRsrcName.size()+1;
    char *rsrcname=new char[length];
    fRsrcName.copy(rsrcname,length-1);
    rsrcname[length-1]='\0';
    fStatus = viFindRsrc(fDefaultRM,rsrcname,VI_NULL,VI_NULL,desc);
    delete[] rsrcname;
    if(fStatus < VI_SUCCESS){
        viStatusDesc(fViSession,fStatus,error_desc);
        fErrorCode=error_desc;
        return false;
    }
    //viopen,default timeout 2s,default access mode
    fStatus = viOpen(fDefaultRM,desc,fAccessMode,fOpenTimeout,&fViSession);
    if(fStatus < VI_SUCCESS){
        viStatusDesc(fViSession,fStatus,error_desc);
        fErrorCode=error_desc;
        return false;
    }
    //register this instrument
    if(!VISASystemManager::GetInstance()->Register(this)){
        fStatus=VI_STATE_UNKNOWN;
        fErrorCode="Error! DeviceName Duplication.Please Choose Another DeviceName";
        Close();
        return false;
    }
    fRsrcDesc=desc;

    return true;
}
Пример #2
0
int vxi11_send(VXI11_CLINK * clink, const char *cmd, size_t len)
{
#ifdef WIN32
	ViStatus status;
	char buf[256];
	unsigned char *send_cmd;
#else
	Device_WriteParms write_parms;
	char *send_cmd;
#endif
	size_t bytes_left = len;
	ssize_t write_count;

#ifdef WIN32
	send_cmd = (unsigned char *)malloc(len);
	if (!send_cmd) {
		return 1;
	}
	memcpy(send_cmd, cmd, len);

	while (bytes_left > 0) {
		status =
		    viWrite(clink->session, send_cmd + (len - bytes_left),
			    bytes_left, &write_count);
		if (status == VI_SUCCESS) {
			bytes_left -= write_count;
		} else {
			free(send_cmd);
			viStatusDesc(clink->session, status, buf);
			printf("%s\n", buf);
			return status;
		}
	}
#else
	send_cmd = (char *)malloc(len);
	if (!send_cmd) {
		return 1;
	}
	memcpy(send_cmd, cmd, len);

	write_parms.lid = clink->link->lid;
	write_parms.io_timeout = VXI11_DEFAULT_TIMEOUT;
	write_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT;

/* We can only write (link->maxRecvSize) bytes at a time, so we sit in a loop,
 * writing a chunk at a time, until we're done. */

	do {
		Device_WriteResp write_resp;
		memset(&write_resp, 0, sizeof(write_resp));

		if (bytes_left <= clink->link->maxRecvSize) {
			write_parms.flags = 8;
			write_parms.data.data_len = bytes_left;
		} else {
			write_parms.flags = 0;
			/* We need to check that maxRecvSize is a sane value (ie >0). Believe it
			 * or not, on some versions of Agilent Infiniium scope firmware the scope
			 * returned "0", which breaks Rule B.6.3 of the VXI-11 protocol. Nevertheless
			 * we need to catch this, otherwise the program just hangs. */
			if (clink->link->maxRecvSize > 0) {
				write_parms.data.data_len =
				    clink->link->maxRecvSize;
			} else {
				write_parms.data.data_len = 4096;	/* pretty much anything should be able to cope with 4kB */
			}
		}
		write_parms.data.data_val = send_cmd + (len - bytes_left);

		if (device_write_1(&write_parms, &write_resp, clink->client) !=
		    RPC_SUCCESS) {
			free(send_cmd);
			return -VXI11_NULL_WRITE_RESP;	/* The instrument did not acknowledge the write, just completely
							   dropped it. There was no vxi11 comms error as such, the 
							   instrument is just being rude. Usually occurs when the instrument
							   is busy. If we don't check this first, then the following 
							   line causes a seg fault */
		}
		if (write_resp.error != 0) {
			printf("vxi11_user: write error: %d\n",
			       (int)write_resp.error);
			free(send_cmd);
			return -(write_resp.error);
		}
		bytes_left -= write_resp.size;
	} while (bytes_left > 0);
#endif
	free(send_cmd);

	return 0;
}
Пример #3
0
// ================================================================================================
// FUNCTION  : mexVISA
// ------------------------------------------------------------------------------------------------
// Purpose   : Implement basic VISA functions for a MATLAB toolbox
// Parameters: passed from MATLAB mexFunction
// Returns   : {0=success, -1=failure}
// ================================================================================================
int mexVISA(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    ViStatus Status;      // returned status from called VISA function
    char *tcmd, cmd[256]; // passed command parameter

    // ----------------------
    // Get the command string
    // ----------------------
    if(nrhs<1) mexErrMsgTxt("A string argument must be given as the first parameter.");
    tcmd = ViMexUtil_GetStringValue(prhs[0],0);
    strncpy(cmd, tcmd, 256); mxFree(tcmd); cmd[255] = 0; // copied and free tcmd as it is not free'd below

    // ******************************************
    // *****                                *****
    // *****   COMMAND LOOKUP-AND-EXECUTE   *****
    // *****                                *****
    // ******************************************

    // --------------
    // viOpen
    // --------------
    if(!strcmp(cmd, "viOpen()"))
    {
        ViSession RMSession, Session = 0;
        ViString  Resource; ViUInt32 Timeout;

        if( (nrhs!=3) && (nrhs!=4) )
            mexErrMsgTxt("Incorrect number of input parameters (needs to be 3 or 4)");
        if( nlhs != 2)
            mexErrMsgTxt("2 output terms were expected\n");

        if(!mexVISA_GetViRM(&RMSession))
        {
            Resource = ViMexUtil_GetStringValue(prhs[1], 0);
            Timeout  = (ViUInt32)ViMexUtil_GetUIntValue(prhs[2]);
            
            if(ResourceChecking)
            {
                if(mexVISA_ResourceIsOpen(Resource, &Session))
                {
                    if(AllowSharedSessions) 
                        Status = VI_SUCCESS;
                    else
                        mexErrMsgTxt(" Resource is already open");
                }
            }
            if(!Session)
            {
                Status = viOpen(RMSession, Resource, VI_NULL, Timeout, &Session);
                if(ResourceChecking && (Status == VI_SUCCESS))
                {
                    if(nrhs == 3)
                        mexVISA_InsertSession(Session, Resource, "no stack trace available\n");
                    else
                    {

                        ViString StackTrace = ViMexUtil_GetStringValue(prhs[3], 0);
                        mexVISA_InsertSession(Session, Resource, StackTrace);
                        mxFree(StackTrace);
                    }
                }
            }
            ViMexUtil_PutIntValue(Status, &plhs[0]);
            ViMexUtil_PutUIntValue((unsigned)Session, &plhs[1]);
            mxFree(Resource);
            return 0;
        }
        else mexErrMsgTxt("mexVISA: Call to viOpenDefaultRM prior to viOpen failed.");
    }
    // ---------------
    // viClose
    // ---------------
    if(!strcmp(cmd, "viClose()"))
    {
        ViSession Session;
        ViMexUtil_CheckParameters(nlhs,nrhs,1,2);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        Status = viClose(Session);
        if(ResourceChecking && (Status == VI_SUCCESS))
            mexVISA_RemoveSession(Session);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        return 0;
    }
    // ---------------
    // viWrite
    // ---------------
    if(!strcmp(cmd, "viWrite()"))
    {
        ViSession Session;
        ViUInt32 Count, Return_Count;
        ViBuf Buffer; char *Message;

        ViMexUtil_CheckParameters(nlhs,nrhs,2,3);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        Buffer  = (ViBuf)ViMexUtil_GetStringValue(prhs[2], ((ViUInt32 *)&Count));
        Message = (char *)mxCalloc(Count+2, sizeof(char));
        if(!Message) mexErrMsgTxt("Memory allocation error.");
        sprintf(Message,"%s",Buffer);
        Status = viWrite(Session, Message, Count-1, &Return_Count);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        ViMexUtil_PutUIntValue(Return_Count, &plhs[1]);
        mxFree(Message); mxFree((char *)Buffer);
        return 0;
    }
    // ---------------
    // viWriteBinary
    // ---------------
    if(!strcmp(cmd, "viWriteBinary()"))
    {
        ViSession Session;
        ViUInt32 Count, Return_Count;
        ViBuf Buffer;

        ViMexUtil_CheckParameters(nlhs,nrhs,2,3);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        Buffer  = (ViBuf)ViMexUtil_GetBinaryArray(prhs[2], ((ViUInt32 *)&Count));
        Status = viWrite(Session, Buffer, Count, &Return_Count);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        ViMexUtil_PutUIntValue(Return_Count, &plhs[1]);
        mxFree((char *)Buffer);
        return 0;
    }
    // ---------------
    // viPrintf
    // ---------------
    if(!strcmp(cmd, "viPrintf()"))
    {
        ViSession Session;
        ViUInt32 Count;
        ViBuf Buffer;

        ViMexUtil_CheckParameters(nlhs,nrhs,1,3);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        Buffer  = (ViBuf)ViMexUtil_GetStringValue(prhs[2], ((ViUInt32 *)&Count));
        Status = viPrintf(Session,"%s",Buffer);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        mxFree((char *)Buffer);
        return 0;
    }
    // --------------
    // viRead
    // --------------
    if(!strcmp(cmd, "viRead()"))
    {
        ViSession Session;
        ViUInt32 Count, Return_Count;
        unsigned char *Buffer;

        ViMexUtil_CheckParameters(nlhs,nrhs,2,3);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        Count   = (ViUInt32)ViMexUtil_GetUIntValue(prhs[2]);
        Buffer  = (unsigned char *)mxCalloc(Count+1,sizeof(char));
        if(!Buffer) mexErrMsgTxt("Memory Allocation Failed.\n");
        Status = viRead(Session, Buffer, Count, &Return_Count);
        if(Return_Count < Count) Buffer[Return_Count-1] = '\0';
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        ViMexUtil_PutString(Buffer, &plhs[1]);
        mxFree(Buffer); // removed 6/4/04 for debug
        return 0;
    }
    // --------------
    // viReadBinary
    // --------------
    if(!strcmp(cmd, "viReadBinary()"))
    {
        ViSession Session;
        ViUInt32 Count, Return_Count;
        unsigned char *Buffer;

        ViMexUtil_CheckParameters(nlhs,nrhs,2,3);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        Count   = (ViUInt32)ViMexUtil_GetUIntValue(prhs[2]);
        Buffer  = (unsigned char *)mxCalloc(Count+1,sizeof(char));
        if(!Buffer) mexErrMsgTxt("Memory Allocation Failed.\n");
        Status = viRead(Session, Buffer, Count, &Return_Count);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        ViMexUtil_PutBinaryArray(Return_Count, Buffer, &plhs[1]);
        mxFree(Buffer);
        return 0;
    }
    // -------
    // viClear
    // -------
    if(!strcmp(cmd, "viClear()"))
    {
        ViSession Session;

        ViMexUtil_CheckParameters(nlhs,nrhs,1,2);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        Status = viClear(Session);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        return 0;
    }
    // ---------
    // viReadSTB
    // ---------
    if(!strcmp(cmd, "viReadSTB()"))
    {
        ViSession Session;
        ViUInt16 Status_Byte;

        ViMexUtil_CheckParameters(nlhs,nrhs,2,2);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        Status = viReadSTB(Session, &Status_Byte);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        ViMexUtil_PutUIntValue((unsigned)Status_Byte, &plhs[1]);
        return 0;
    }
    // ---------------
    // viAssertTrigger
    // ---------------
    if(!strcmp(cmd, "viAssertTrigger()"))
    {
        ViSession Session;
        ViUInt16 Protocol;
        char *ProtocolString;

        ViMexUtil_CheckParameters(nlhs,nrhs,1,3);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        ProtocolString = ViMexUtil_GetStringValue(prhs[2], 0);

             if(!strcmp(ProtocolString, "VI_TRIG_PROT_DEFAULT")) Protocol = VI_TRIG_PROT_DEFAULT;
        else if(!strcmp(ProtocolString, "VI_TRIG_PROT_ON"))      Protocol = VI_TRIG_PROT_ON;
        else if(!strcmp(ProtocolString, "VI_TRIG_PROT_OFF"))     Protocol = VI_TRIG_PROT_OFF;
        else if(!strcmp(ProtocolString, "VI_TRIG_PROT_SYNC"))    Protocol = VI_TRIG_PROT_SYNC;  
        else 
        {
            mxFree(ProtocolString);
            mexErrMsgTxt("Unrecognized protocol definition");
        }
        Status = viAssertTrigger(Session, Protocol);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        mxFree(ProtocolString);
        return 0;
    }
    // ------------
    // viStatusDesc
    // ------------
    if(!strcmp(cmd, "viStatusDesc()"))
    {
        ViSession Session;
        char *Description;

        ViMexUtil_CheckParameters(nlhs,nrhs,2,3);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        Status  = (ViStatus) ViMexUtil_GetIntValue(prhs[2]);
        Description = (char *)mxCalloc(256,sizeof(char));
        Status = viStatusDesc(Session, Status, Description);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        ViMexUtil_PutString(Description, &plhs[1]);
        //mxFree(Description);
        return 0;
    }
    // --------------
    // viGetAttribute
    // --------------
    if(!strcmp(cmd, "viGetAttribute()"))
    {
        ViSession Session;
        ViAttr Attribute; char *AttrString;
        int Type; double dVal; char buffer[256];

        ViMexUtil_CheckParameters(nlhs,nrhs,2,3);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        AttrString = ViMexUtil_GetStringValue(prhs[2], 0);

        if(mexVISA_Get_VI_ATTR(AttrString, &Attribute, &Type)) {
            mxFree(AttrString);
            mexErrMsgTxt("Unrecognized/unsupported VISA Attribute type.");
        }
        Status = viGetAttribute(Session, Attribute, ((void *)buffer));
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);

        if(Status >= 0)
        {
            switch(Type)
            {
                case TYPE_ViString    : break; // handle below
                case TYPE_ViStatus    : dVal = (double)(*((ViStatus    *)buffer)); break;
                case TYPE_ViBoolean   : dVal = (double)(*((ViBoolean   *)buffer)); break;
                case TYPE_ViInt8      : dVal = (double)(*((ViInt8      *)buffer)); break;
                case TYPE_ViInt16     : dVal = (double)(*((ViInt16     *)buffer)); break;
                case TYPE_ViInt32     : dVal = (double)(*((ViInt32     *)buffer)); break;
                case TYPE_ViUInt8     : dVal = (double)(*((ViUInt8     *)buffer)); break;
                case TYPE_ViUInt16    : dVal = (double)(*((ViUInt16    *)buffer)); break;
                case TYPE_ViUInt32    : dVal = (double)(*((ViUInt32    *)buffer)); break;
                case TYPE_ViSession   : dVal = (double)(*((ViSession   *)buffer)); break;
                case TYPE_ViBusAddress: dVal = (double)(*((ViBusAddress*)buffer)); break;
                case TYPE_ViBusSize   : dVal = (double)(*((ViBusSize   *)buffer)); break;
                case TYPE_ViVersion   : dVal = (double)(*((ViVersion   *)buffer)); break;
                case TYPE_ViAccessMode: dVal = (double)(*((ViAccessMode*)buffer)); break;
                case TYPE_ViEventType : dVal = (double)(*((ViEventType *)buffer)); break;
                case TYPE_ViJobId     : dVal = (double)(*((ViJobId     *)buffer)); break;
                default: 
                {
                    mxFree(AttrString);
                    mexErrMsgTxt("Unhandled case in mexVISA.c under viGetAttribute.");
                }
            }
            if(Type == TYPE_ViString) {
                ViMexUtil_PutString(buffer, &plhs[1]);
            }
            else
                ViMexUtil_PutRealValue(dVal, &plhs[1]);
        }
        else ViMexUtil_PutRealValue(-1.0, &plhs[1]);
        mxFree(AttrString);
        return 0;
    }
    // --------------
    // viSetAttribute
    // --------------
    if(!strcmp(cmd, "viSetAttribute()"))
    {
        ViSession Session;
        ViAttr Attribute; char *AttrString; 
        double dVal; int Type;

        ViMexUtil_CheckParameters(nlhs,nrhs,1,4);
        Session = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        AttrString = ViMexUtil_GetStringValue(prhs[2], 0);

        if(mexVISA_Get_VI_ATTR(AttrString, &Attribute, &Type)) {
            mxFree(AttrString);
            mexErrMsgTxt("Unrecognized/unsupported VISA Attribute type.");
        }
        if(Type != TYPE_ViString) {
            dVal = ViMexUtil_GetRealValue(prhs[3]);
        }
        switch(Type)
        {
            case TYPE_ViInt8:
            case TYPE_ViInt16:
            case TYPE_ViInt32:
            {
                ViAttrState attrState = (ViAttrState)((ViInt32)dVal);
                Status = viSetAttribute(Session, Attribute, attrState);
            }  break;
 
            case TYPE_ViStatus:
            case TYPE_ViBoolean:
            case TYPE_ViUInt8:
            case TYPE_ViUInt16:
            case TYPE_ViUInt32:
            case TYPE_ViSession:
            case TYPE_ViBusAddress:
            case TYPE_ViBusSize:
            case TYPE_ViVersion:
            case TYPE_ViAccessMode:
            case TYPE_ViEventType:
            case TYPE_ViJobId:
            {
                ViAttrState attrState = (ViAttrState)((ViUInt32)dVal);
                Status = viSetAttribute(Session, Attribute, attrState);
            }  break;

            case TYPE_ViString:
            {
                mxFree(AttrString);
                mexErrMsgTxt("Setting string attributes is not allowed.");
            }  break;

            default: 
            {
                mxFree(AttrString);
                mexErrMsgTxt("Unhandled case in mexVISA.c under viGetAttribute.");
            }
        }
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        mxFree(AttrString);
        return 0;
    }
    // -------------
    // viEnableEvent
    // -------------
    if(!strcmp(cmd, "viEnableEvent()"))
    {
        ViSession Session;
        ViEventType Event; char *EventString;
        ViUInt16 Mechanism;

        ViMexUtil_CheckParameters(nlhs,nrhs,1,4);
        Session     = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        EventString = ViMexUtil_GetStringValue(prhs[2], 0);
        Mechanism   = (ViUInt16)ViMexUtil_GetIntValue(prhs[3]);

        if(Mechanism != 1) {
            mxFree(EventString);
            mexErrMsgTxt("EventMechanism must be VI_QUEUE = 1");
        }
        if(mexVISA_Get_VI_EVENT(EventString, &Event)) {
            mxFree(EventString);
            mexErrMsgTxt("Unrecognized/unsupported VISA Event type.");
        }
        Status = viEnableEvent(Session, Event, Mechanism, VI_NULL);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        mxFree(EventString);
        return 0;
    }
    // ---------------------
    // viDisableEvent
    // ---------------------
    if(!strcmp(cmd, "viDisableEvent()"))
    {
        ViSession Session;
        ViEventType Event; char *EventString;
        ViUInt16 Mechanism;

        ViMexUtil_CheckParameters(nlhs,nrhs,1,4);
        Session     = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        EventString = ViMexUtil_GetStringValue(prhs[2], 0);
        Mechanism   = (ViUInt16)ViMexUtil_GetIntValue(prhs[3]);

        if(Mechanism != 1) 
        {
            mxFree(EventString);
            mexErrMsgTxt("EventMechanism must be VI_QUEUE = 1");
        }
        if(mexVISA_Get_VI_EVENT(EventString, &Event)) 
        {
            mxFree(EventString);
            mexErrMsgTxt("Unrecognized/unsupported VISA Event type.");
        }
        Status = viDisableEvent(Session, Event, Mechanism);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        mxFree(EventString);
        return 0;
    }
    // ---------------
    // viDiscardEvents
    // ---------------
    if(!strcmp(cmd, "viDiscardEvents()"))
    {
        ViSession Session;
        ViEventType Event; char *EventString;
        ViUInt16 Mechanism;

        ViMexUtil_CheckParameters(nlhs,nrhs,1,4);
        Session     = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        EventString = ViMexUtil_GetStringValue(prhs[2], 0);
        Mechanism   = (ViUInt16)ViMexUtil_GetIntValue(prhs[3]);

        if(Mechanism != 1) 
        {
            mxFree(EventString);
            mexErrMsgTxt("EventMechanism must be VI_QUEUE = 1");
        }
        if(mexVISA_Get_VI_EVENT(EventString, &Event)) 
        {
            mxFree(EventString);
            mexErrMsgTxt("Unrecognized/unsupported VISA Event type.");
        }
        Status = viDiscardEvents(Session, Event, Mechanism);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        mxFree(EventString);
        return 0;
    }
    // -------------
    // viWaitOnEvent
    // -------------
    if(!strcmp(cmd, "viWaitOnEvent()"))
    {
        ViSession Session;
        ViEventType Event, OutEventType; char *EventString;
        ViEvent EventHandle;
        ViUInt32 Timeout;

        ViMexUtil_CheckParameters(nlhs,nrhs,3,4);
        Session     = (ViSession)ViMexUtil_GetUIntValue(prhs[1]);
        EventString = ViMexUtil_GetStringValue(prhs[2], 0);
        Timeout     = (ViUInt32)ViMexUtil_GetUIntValue(prhs[3]);

        if(mexVISA_Get_VI_EVENT(EventString, &Event)) 
        {
            mxFree(EventString);
            mexErrMsgTxt("Unrecognized/unsupported VISA Event type.");
        }
        Status = viWaitOnEvent(Session, Event, Timeout, &OutEventType, &EventHandle);
        ViMexUtil_PutIntValue((int)Status, &plhs[0]);
        ViMexUtil_PutUIntValue((unsigned)OutEventType, &plhs[1]);
        ViMexUtil_PutUIntValue((unsigned)EventHandle, &plhs[2]);
        mxFree(EventString);
        return 0;
    }
    // ******************************************************************
    // -------------------
    // No Command Found...
    // -------------------
    return -1;
}
Пример #4
0
/* Use this function from user land to open a device and create a link. Can be
 * used multiple times for the same device (the library will keep track).*/
int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device)
{
#ifdef WIN32
	ViStatus status;
	char buf[256];
#else
	int ret;
	struct _vxi11_client_t *tail, *client = NULL;
#endif
	char default_device[6] = "inst0";
	char *use_device;

	if(device){
		use_device = device;
	}else{
		use_device = default_device;
	}

	*clink = (VXI11_CLINK *) calloc(1, sizeof(VXI11_CLINK));
	if (!(*clink)) {
		return 1;
	}

#ifdef WIN32
	status = viOpenDefaultRM(&clink->rm);
	if (status != VI_SUCCESS) {
		viStatusDesc(NULL, status, buf);
		printf("%s\n", buf);
		free(*clink);
		*clink = NULL;
		return 1;
	}
	viOpen(clink->rm, (char *)address, VI_NULL, VI_NULL, &clink->session);
	if (status != VI_SUCCESS) {
		viStatusDesc(clink->rm, status, buf);
		printf("%s\n", buf);
		free(*clink);
		*clink = NULL;
		return 1;
	}
#else
	/* Have a look to see if we've already initialised an instrument with
	 * this address */
	tail = VXI11_CLIENTS;
	while (tail) {
		if (strcmp(address, tail->address) == 0) {
			client = tail;
			break;
		}
		tail = tail->next;
	}

	/* Couldn't find a match, must be a new address */
	if (!client) {
		/* Create a new client, keep a note of where the client pointer
		 * is, for this address. Because it's a new client, this
		 * must be link number 1. Keep track of how many devices we've
		 * opened so we don't run out of storage space. */
		client = (struct _vxi11_client_t *)calloc(1, sizeof(struct _vxi11_client_t));
		if (!client) {
			free(*clink);
			*clink = NULL;
			return 1;
		}

		(*clink)->client =
		    clnt_create(address, DEVICE_CORE, DEVICE_CORE_VERSION,
				"tcp");

		if ((*clink)->client == NULL) {
			clnt_pcreateerror(address);
			free(client);
			free(*clink);
			*clink = NULL;
			return 1;
		}
		ret = _vxi11_open_link(*clink, address, use_device);
		if (ret != 0) {
			clnt_destroy((*clink)->client);
			free(client);
			free(*clink);
			*clink = NULL;
			return 1;
		}

		strncpy(client->address, address, 20);
		client->client_address = (*clink)->client;
		client->link_count = 1;
		client->next = VXI11_CLIENTS;
		VXI11_CLIENTS = client;
	} else {
		/* Copy the client pointer address. Just establish a new link
		 *  not a new client). Add one to the link count */
		(*clink)->client = client->client_address;
		ret = _vxi11_open_link((*clink), address, use_device);
		client->link_count++;
	}
#endif
	return 0;
}