diff options
-rw-r--r-- | libvxi11client/client.c | 10 | ||||
-rw-r--r-- | libvxi11client/libvxi11client.c | 95 | ||||
-rw-r--r-- | libvxi11client/libvxi11client.h | 5 |
3 files changed, 60 insertions, 50 deletions
diff --git a/libvxi11client/client.c b/libvxi11client/client.c index b851347..f712f29 100644 --- a/libvxi11client/client.c +++ b/libvxi11client/client.c @@ -27,7 +27,7 @@ static char* geterrorstring(int errorcode) { } } -static void interruptcallback(void) { +static void interruptcallback(char* handle) { printf("Interrupt fired\n"); } @@ -40,6 +40,8 @@ int main(int argc, char *argv[]) { exit(1); } + vxi11_start_interrupt_server(interruptcallback); + Context ctx; int err = 0; @@ -144,7 +146,7 @@ int main(int argc, char *argv[]) { printf("Created interrupt channel\n"); // enable interrupts - if ((err = vxi11_enable_srq(&ctx, true, "handle", interruptcallback)) > 0) + if ((err = vxi11_enable_srq(&ctx, true, "handle")) > 0) printf("Enabled interrupts\n"); else printf("Error enabling interrupts; %s\n", geterrorstring(err)); @@ -152,7 +154,7 @@ int main(int argc, char *argv[]) { sleep(10); // disable interrupts - if ((err = vxi11_enable_srq(&ctx, false, NULL, NULL)) > 0) + if ((err = vxi11_enable_srq(&ctx, false, NULL)) > 0) printf("Disabled interrupts\n"); else printf("Error disabling interrupts; %s\n", geterrorstring(err)); @@ -176,6 +178,8 @@ int main(int argc, char *argv[]) { // close if ((err = vxi11_close(&ctx) > 0)) printf("Closed\n"); + + vxi11_stop_interrupt_server(); } else { printf("Error opening device; %s\n", geterrorstring(err)); 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; diff --git a/libvxi11client/libvxi11client.h b/libvxi11client/libvxi11client.h index 0546ac4..27da46c 100644 --- a/libvxi11client/libvxi11client.h +++ b/libvxi11client/libvxi11client.h @@ -20,6 +20,7 @@ typedef struct { CLIENT* clnt; CLIENT* abortclnt; Device_Link devicelink; + bool interruptchannelopen; bool interruptsenabled; } Context; @@ -36,6 +37,8 @@ int vxi11_remote(Context* context, bool waitforlock); int vxi11_readstatusbyte(Context* context, bool waitforlock); int vxi11_create_intr_chan(Context* context); int vxi11_destroy_intr_chan(Context* context); -int vxi11_enable_srq(Context* context, bool enable, char* handle, void (*callback)(void)); +int vxi11_enable_srq(Context* context, bool enable, char* handle); +int vxi11_start_interrupt_server(void (*callback)(char* handle)); +int vxi11_stop_interrupt_server(); int vxi11_docmd(Context* context, unsigned long cmd, bool waitforlock); int vxi11_close(Context* context); |