From a8f9dbca19702adcc1420aad70855d057fd51122 Mon Sep 17 00:00:00 2001
From: daniel <danieruru@gmail.com>
Date: Thu, 17 Jan 2013 06:39:36 +0900
Subject: Everything for multiple instruments on the C side

---
 libvxi11client/libvxi11client.c | 95 +++++++++++++++++++++--------------------
 1 file changed, 49 insertions(+), 46 deletions(-)

(limited to 'libvxi11client/libvxi11client.c')

diff --git a/libvxi11client/libvxi11client.c b/libvxi11client/libvxi11client.c
index 614f6a6..8936545 100644
--- a/libvxi11client/libvxi11client.c
+++ b/libvxi11client/libvxi11client.c
@@ -26,17 +26,9 @@
 #define	VXI11_DEFAULT_TIMEOUT	1000
 
 static GThread* interruptthread;
-static bool interruptchannelopen = false;
-static void (*interruptcallback)(void) = NULL;
-
-static void killinterruptthreadandwait() {
-#ifdef DEBUG
-	printf("Waiting for interrupt thread to die\n");
-#endif
-	interruptchannelopen = false;
-	g_thread_join(interruptthread);
-	interruptthread = NULL;
-}
+static void (*interruptcallback)(char*) = NULL;
+static bool interruptserverstarted = false;
+static unsigned int interruptserverport = -1;
 
 void *
 device_intr_srq_1_svc(Device_SrqParms *argp, struct svc_req *rqstp) {
@@ -45,7 +37,7 @@ device_intr_srq_1_svc(Device_SrqParms *argp, struct svc_req *rqstp) {
 #endif
 
 	if (interruptcallback != NULL) {
-		interruptcallback();
+		interruptcallback(argp->handle.handle_val);
 	}
 
 	static char * result;
@@ -146,6 +138,9 @@ int vxi11_open(Context* context, char* address, char* device) {
 				// failed!
 				return 0;
 
+			context->interruptchannelopen = false;
+			context->interruptsenabled = false;
+
 			return 1;
 		}
 		else if (linkresp == NULL)
@@ -379,7 +374,7 @@ static gpointer interruptthreadfunc(gpointer data) {
 	struct pollfd *my_pollfd = NULL;
 	int last_max_pollfd = 0;
 
-	while (interruptchannelopen) {
+	while (interruptserverstarted) {
 		int max_pollfd = svc_max_pollfd;
 		if (max_pollfd == 0 && svc_pollfd == NULL)
 			break;
@@ -421,44 +416,57 @@ static gpointer interruptthreadfunc(gpointer data) {
 	return NULL;
 }
 
-/**
- * create an interrupt channel from the connected device
- */
-int vxi11_create_intr_chan(Context* context) {
-	if (interruptchannelopen)
-		return 0;
-	else if (context->clnt == NULL)
-		return 0;
-	else if (interruptthread != NULL)
-		return 0;
-
-	interruptchannelopen = true;
-	unsigned int port = -1;
+int vxi11_start_interrupt_server(void (*callback)(char* handle)) {
+	interruptcallback = callback;
+	interruptserverstarted = true;
 	g_thread_init(NULL);
-	interruptthread = g_thread_create(interruptthreadfunc, &port, true, NULL);
+	interruptthread = g_thread_create(interruptthreadfunc, &interruptserverport, true, NULL);
 	if (interruptthread == NULL)
 		return 0;
 
-	while (port == -1) { // spin
+	while (interruptserverport == -1) { // spin
 		usleep(200);
 	};
+	return 1;
+}
+
+int vxi11_stop_interrupt_server() {
+#ifdef DEBUG
+	printf("Waiting for interrupt thread to die\n");
+#endif
+	interruptserverstarted = false;
+	g_thread_join(interruptthread);
+	interruptthread = NULL;
+	return 1;
+}
+
+/**
+ * create an interrupt channel from the connected device
+ */
+int vxi11_create_intr_chan(Context* context) {
+	if (context->clnt == NULL || context->interruptchannelopen)
+		return 0;
+	else if (interruptthread == NULL) {
+#ifdef DEBUG
+		printf("interrupt thread isn't running\n");
+#endif
+		return 0;
+	}
 
 	struct sockaddr_in myaddress;
 	get_myaddress(&myaddress);
 
-	Device_RemoteFunc remotefunc = { .hostAddr = myaddress.sin_addr.s_addr, .hostPort = port, .progNum = DEVICE_INTR,
-			.progVers = DEVICE_INTR_VERSION, .progFamily = DEVICE_TCP };
+	Device_RemoteFunc remotefunc = { .hostAddr = myaddress.sin_addr.s_addr, .hostPort = interruptserverport, .progNum =
+			DEVICE_INTR, .progVers = DEVICE_INTR_VERSION, .progFamily = DEVICE_TCP };
 	Device_Error* error = create_intr_chan_1(&remotefunc, context->clnt);
-	if (error != NULL && error->error == 0)
+	if (error != NULL && error->error == 0) {
+		context->interruptchannelopen = true;
 		return 1;
-	else if (error == NULL) {
-		killinterruptthreadandwait();
-		return 0;
 	}
-	else {
-		killinterruptthreadandwait();
+	else if (error == NULL)
+		return 0;
+	else
 		return -(error->error);
-	}
 }
 
 /**
@@ -466,16 +474,14 @@ int vxi11_create_intr_chan(Context* context) {
  */
 
 int vxi11_destroy_intr_chan(Context* context) {
-	if (!interruptchannelopen)
-		return 0;
-	else if (context->clnt == NULL)
+	if (context->clnt == NULL || !(context->interruptchannelopen))
 		return 0;
 	else if (interruptthread == NULL)
 		return 0;
 
 	Device_Error* error = destroy_intr_chan_1(NULL, context->clnt);
 	if (error != NULL && error->error == 0) {
-		killinterruptthreadandwait();
+		context->interruptchannelopen = false;
 		return 1;
 	}
 	else if (error == NULL)
@@ -488,10 +494,8 @@ int vxi11_destroy_intr_chan(Context* context) {
  * enable interrupts
  */
 
-int vxi11_enable_srq(Context* context, bool enable, char* handle, void (*callback)(void)) {
-	if (!interruptchannelopen)
-		return 0;
-	else if (context->clnt == NULL)
+int vxi11_enable_srq(Context* context, bool enable, char* handle) {
+	if (context->clnt == NULL || !(context->interruptchannelopen))
 		return 0;
 	else if (interruptthread == NULL)
 		return 0;
@@ -502,7 +506,6 @@ int vxi11_enable_srq(Context* context, bool enable, char* handle, void (*callbac
 			params.handle.handle_val = handle;
 			params.handle.handle_len = strlen(handle) + 1;
 		}
-		interruptcallback = callback;
 	}
 	else {
 		params.handle.handle_val = NULL;
-- 
cgit