/*
 * This is sample code generated by rpcgen.
 * These are only templates and you can use them
 * as a guideline for developing your own functions.
 */

#include "vxi11.h"
#include "stdio.h"
#include "globals.h"
#include <stdbool.h>

#define ERR_SYNTAXERROR 1
#define ERR_DEVICENOTACCESSIBLE 3
#define ERR_INVALIDLINKINDENTIFIER 4
#define ERR_PARAMETERERROR 5
#define ERR_CHANNELNOTESTABLISHED 6
#define ERR_OPERATIONNOTSUPPORTED 8
#define ERR_OUTOFRESOURCES 9
#define ERR_DEVICELOCKEDBYANOTHERLINK 11
#define ERR_NOLOCKHELDBYTHISLINK 12
#define ERR_IOTIMEOUT 15
#define ERR_IOERROR 17
#define ERR_INVALIDADDRESS 21
#define ERR_ABORT 23
#define ERR_CHANNELALREADYESTABLISHED 29

static bool isLocked() {
	return globals.VxiLocks.locked_network_server != NO_SERVER_LOCKED;
}

static bool haveLock(int lid) {
	return globals.VxiLocks.locked_network_server == lid;
}

static bool waitForLock(long timeout) {
	return false;
}

static void lock(int lid) {
	globals.VxiLocks.locked_network_server = lid;
}

static void unlock() {
	globals.VxiLocks.locked_network_server = NO_SERVER_LOCKED;
}

Device_Error *
device_abort_1_svc(Device_Link *argp, struct svc_req *rqstp) {
	printf("device_abort_1_svc()\n");
	static Device_Error result;

	/*
	 * insert server code here
	 */
	result.error = 0;
	return &result;
}

Create_LinkResp *
create_link_1_svc(Create_LinkParms *argp, struct svc_req *rqstp) {
	printf("create_link_1_svc()\n");
	static Create_LinkResp result;
	globals.Remote.vxi_connections++;
	result.error = 0;
	return &result;
}

Device_WriteResp *
device_write_1_svc(Device_WriteParms *argp, struct svc_req *rqstp) {
	static Device_WriteResp result;
	printf("device_write_1_svc()\n");

	if (isLocked(argp->lid) && !haveLock(argp->lid))
		result.error = ERR_DEVICELOCKEDBYANOTHERLINK;
	else {
		printf("%s\n", argp->data.data_val);
		//result.size = argp->data.data_len;
		result.size = 1;
		result.error = 0;
	}
	return &result;
}

Device_ReadResp *
device_read_1_svc(Device_ReadParms *argp, struct svc_req *rqstp) {
	static Device_ReadResp result;
	printf("device_read_1_svc()\n");

	if (isLocked(argp->lid) && !haveLock(argp->lid))
		result.error = ERR_DEVICELOCKEDBYANOTHERLINK;
	else {
		result.data.data_val = "HELLO!";
		result.data.data_len = 7;
		result.error = 0;
		result.reason = 0x4;
	}
	return &result;
}

Device_ReadStbResp *
device_readstb_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) {
	printf("device_readstb_1_svc()\n");
	static Device_ReadStbResp result;
	result.error = 0;
	result.stb = 0;
	return &result;
}

Device_Error *
device_trigger_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) {
	printf("device_trigger_1_svc()\n");
	static Device_Error result;

	result.error = 0;
	return &result;
}

Device_Error *
device_clear_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) {
	printf("device_clear_1_svc()\n");
	static Device_Error result;

	result.error = 0;
	return &result;
}

Device_Error *
device_remote_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) {
	static Device_Error result;
	printf("device_remote_1_svc()\n");

	if (isLocked() && !haveLock(argp->lid))
		result.error = ERR_DEVICELOCKEDBYANOTHERLINK;
	else
		result.error = 0;
	return &result;
}

Device_Error *
device_local_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) {
	static Device_Error result;
	printf("device_local_1_svc()\n");

	if (isLocked() && !haveLock(argp->lid))
		result.error = ERR_DEVICELOCKEDBYANOTHERLINK;
	else
		result.error = 0;
	return &result;
}

Device_Error *
device_lock_1_svc(Device_LockParms *argp, struct svc_req *rqstp) {
	static Device_Error result;
	printf("device_lock_1_svc()\n");

	if (isLocked(argp->lid)) {
		result.error = ERR_DEVICELOCKEDBYANOTHERLINK;
		if (haveLock(argp->lid)) {
			// maybe do something here to warn about a device trying to lock multiple times?
		}
	}
	else {
		lock(argp->lid);
		result.error = 0;
	}
	return &result;
}

Device_Error *
device_unlock_1_svc(Device_Link *argp, struct svc_req *rqstp) {
	static Device_Error result;
	printf("device_unlock_1_svc()\n");

	if (!isLocked(*argp) || !haveLock(*argp))
		result.error = ERR_NOLOCKHELDBYTHISLINK;
	else {
		result.error = 0;
		unlock();
	}
	return &result;
}

Device_Error *
device_enable_srq_1_svc(Device_EnableSrqParms *argp, struct svc_req *rqstp) {
	static Device_Error result;
	printf("device_enable_srq_1_svc()\n");
	return &result;
}

Device_DocmdResp *
device_docmd_1_svc(Device_DocmdParms *argp, struct svc_req *rqstp) {
	printf("device_docmd_1_svc()\n");
	static Device_DocmdResp result;
	result.data_out.data_out_len = 0;
	result.data_out.data_out_val = NULL;
	result.error = ERR_OPERATIONNOTSUPPORTED;
	return &result;
}

Device_Error *
destroy_link_1_svc(Device_Link *argp, struct svc_req *rqstp) {
	printf("destroy_link_1_svc()\n");
	static Device_Error result;
	globals.Remote.vxi_connections--;
	return &result;
}

Device_Error *
create_intr_chan_1_svc(Device_RemoteFunc *argp, struct svc_req *rqstp) {
	printf("create_intr_chan_1_svc()\n");
	static Device_Error result;
	result.error = 0;
	return &result;
}

Device_Error *
destroy_intr_chan_1_svc(void *argp, struct svc_req *rqstp) {
	printf("destroy_intr_chan_1_svc()\n");
	static Device_Error result;
	result.error = 0;
	return &result;
}

void *
device_intr_srq_1_svc(Device_SrqParms *argp, struct svc_req *rqstp) {
	printf("device_intr_srq_1_svc()\n");
	static char * result;
	return (void *) &result;
}