From a4cffa5e99430532bb5bbad3385b910e25025296 Mon Sep 17 00:00:00 2001 From: Jan Breuer <jan.breuer@jaybee.cz> Date: 周三, 26 12月 2012 23:32:34 +0800 Subject: [PATCH] Reimplement srq/control callback --- examples/common/scpi-def.h | 5 examples/test-tcp-srq/Makefile | 20 ++ libscpi/inc/scpi/types.h | 46 ++++- libscpi/src/ieee488.c | 12 + examples/test-parser/main.c | 17 + examples/test-tcp/main.c | 16 + examples/test-interactive/main.c | 16 + examples/test-tcp-srq/main.c | 337 ++++++++++++++++++++++++++++++++++++++++++ examples/common/scpi-def.c | 5 9 files changed, 448 insertions(+), 26 deletions(-) diff --git a/examples/common/scpi-def.c b/examples/common/scpi-def.c index 0b9bfbd..1908484 100644 --- a/examples/common/scpi-def.c +++ b/examples/common/scpi-def.c @@ -108,6 +108,8 @@ {.pattern = "MEASure:FRESistance?", .callback = SCPI_StubQ,}, {.pattern = "MEASure:FREQuency?", .callback = SCPI_StubQ,}, {.pattern = "MEASure:PERiod?", .callback = SCPI_StubQ,}, + + {.pattern = "SYSTem:COMMunication:TCPIP:CONTROL?", .callback = SCPI_SystemCommTcpipControlQ,}, SCPI_CMD_LIST_END }; @@ -117,7 +119,8 @@ .error = SCPI_Error, .reset = SCPI_Reset, .test = SCPI_Test, - .srq = SCPI_Srq, + .control = SCPI_Control, + .flush = SCPI_Flush, }; #define SCPI_INPUT_BUFFER_LENGTH 256 diff --git a/examples/common/scpi-def.h b/examples/common/scpi-def.h index 646a653..905aaa4 100644 --- a/examples/common/scpi-def.h +++ b/examples/common/scpi-def.h @@ -7,12 +7,13 @@ size_t SCPI_Write(scpi_t * context, const char * data, size_t len); int SCPI_Error(scpi_t * context, int_fast16_t err); -scpi_result_t SCPI_Srq(scpi_t * context); +scpi_result_t SCPI_Control(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val); scpi_result_t SCPI_Reset(scpi_t * context); scpi_result_t SCPI_Test(scpi_t * context); +scpi_result_t SCPI_Flush(scpi_t * context); - +scpi_result_t SCPI_SystemCommTcpipControlQ(scpi_t * context); #endif // __SCPI_DEF_H_ diff --git a/examples/test-interactive/main.c b/examples/test-interactive/main.c index 6fd1d71..b149558 100644 --- a/examples/test-interactive/main.c +++ b/examples/test-interactive/main.c @@ -45,6 +45,10 @@ return fwrite(data, 1, len, stdout); } +scpi_result_t SCPI_Flush(scpi_t * context) { + return SCPI_RES_OK; +} + int SCPI_Error(scpi_t * context, int_fast16_t err) { (void) context; @@ -52,9 +56,12 @@ return 0; } -scpi_result_t SCPI_Srq(scpi_t * context) { - scpi_reg_val_t stb = SCPI_RegGet(context, SCPI_REG_STB); - fprintf(stderr, "**SRQ: 0x%X (%d)\r\n", stb, stb); +scpi_result_t SCPI_Control(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val) { + if (SCPI_CTRL_SRQ == ctrl) { + fprintf(stderr, "**SRQ: 0x%X (%d)\r\n", val, val); + } else { + fprintf(stderr, "**CTRL %02x: 0x%X (%d)\r\n", ctrl, val, val); + } return SCPI_RES_OK; } @@ -68,6 +75,9 @@ return SCPI_RES_OK; } +scpi_result_t SCPI_SystemCommTcpipControlQ(scpi_t * context) { + return SCPI_RES_ERR; +} /* * */ diff --git a/examples/test-parser/main.c b/examples/test-parser/main.c index d5e3553..0ab2b2a 100644 --- a/examples/test-parser/main.c +++ b/examples/test-parser/main.c @@ -45,6 +45,10 @@ return fwrite(data, 1, len, stdout); } +scpi_result_t SCPI_Flush(scpi_t * context) { + return SCPI_RES_OK; +} + int SCPI_Error(scpi_t * context, int_fast16_t err) { (void) context; @@ -52,9 +56,12 @@ return 0; } -scpi_result_t SCPI_Srq(scpi_t * context) { - scpi_reg_val_t stb = SCPI_RegGet(context, SCPI_REG_STB); - fprintf(stderr, "**SRQ: 0x%X (%d)\r\n", stb, stb); +scpi_result_t SCPI_Control(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val) { + if (SCPI_CTRL_SRQ == ctrl) { + fprintf(stderr, "**SRQ: 0x%X (%d)\r\n", val, val); + } else { + fprintf(stderr, "**CTRL %02x: 0x%X (%d)\r\n", ctrl, val, val); + } return SCPI_RES_OK; } @@ -68,6 +75,10 @@ return SCPI_RES_OK; } +scpi_result_t SCPI_SystemCommTcpipControlQ(scpi_t * context) { + return SCPI_RES_ERR; +} + /* * */ diff --git a/examples/test-tcp-srq/Makefile b/examples/test-tcp-srq/Makefile new file mode 100644 index 0000000..1d225a9 --- /dev/null +++ b/examples/test-tcp-srq/Makefile @@ -0,0 +1,20 @@ + +PROG = test + +SRCS = main.c ../common/scpi-def.c +CFLAGS += -Wextra -I ../../libscpi/inc/ +LDFLAGS += ../../libscpi/dist/libscpi.a + + +all: $(PROG) + +OBJS = $(SRCS:.c=.o) + +.c.o: + $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $< + +$(PROG): $(OBJS) + $(CC) -o $@ $(OBJS) $(LDFLAGS) + +clean: + $(RM) $(PROG) $(OBJS) diff --git a/examples/test-tcp-srq/main.c b/examples/test-tcp-srq/main.c new file mode 100644 index 0000000..0837e95 --- /dev/null +++ b/examples/test-tcp-srq/main.c @@ -0,0 +1,337 @@ +/*- + * Copyright (c) 2012-2013 Jan Breuer, + * + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file main.c + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief TCP/IP SCPI Server + * + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <netinet/in.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <arpa/inet.h> + +#include "scpi/scpi.h" +#include "../common/scpi-def.h" + +#define CONTROL_PORT 5026 + + + +typedef struct { + int io; + int io_listen; + int control_io; + int control_io_listen; + FILE * fio; + fd_set fds; +} user_data_t; + +size_t SCPI_Write(scpi_t * context, const char * data, size_t len) { + if (context->user_context != NULL) { + user_data_t * u = (user_data_t *)(context->user_context); + if (u->fio) { + return fwrite(data, 1, len, u->fio); + } + } + return 0; +} + +scpi_result_t SCPI_Flush(scpi_t * context) { + if (context->user_context != NULL) { + user_data_t * u = (user_data_t *)(context->user_context); + if (u->fio) { + return fflush(u->fio) == 0 ? SCPI_RES_OK : SCPI_RES_ERR; + } + } + return SCPI_RES_OK; +} + +int SCPI_Error(scpi_t * context, int_fast16_t err) { + (void) context; + // BEEP + fprintf(stderr, "**ERROR: %d, \"%s\"\r\n", (int32_t) err, SCPI_ErrorTranslate(err)); + return 0; +} + + +scpi_result_t SCPI_Control(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val) { + char b[16]; + + if (SCPI_CTRL_SRQ == ctrl) { + fprintf(stderr, "**SRQ: 0x%X (%d)\r\n", val, val); + } else { + fprintf(stderr, "**CTRL %02x: 0x%X (%d)\r\n", ctrl, val, val); + } + + if (context->user_context != NULL) { + user_data_t * u = (user_data_t *)(context->user_context); + if (u->control_io >= 0) { + snprintf(b, sizeof(b), "SRQ%d\r\n", val); + return write(u->control_io, b, strlen(b)) > 0 ? SCPI_RES_OK : SCPI_RES_ERR; + } + } + return SCPI_RES_OK; +} + +scpi_result_t SCPI_Test(scpi_t * context) { + fprintf(stderr, "**Test\r\n"); + return SCPI_RES_OK; +} + +scpi_result_t SCPI_Reset(scpi_t * context) { + fprintf(stderr, "**Reset\r\n"); + return SCPI_RES_OK; +} + +scpi_result_t SCPI_SystemCommTcpipControlQ(scpi_t * context) { + SCPI_ResultInt(context, CONTROL_PORT); + return SCPI_RES_OK; +} + +static int createServer(int port) { + int fd; + int rc; + int on = 1; + struct sockaddr_in servaddr; + + /* Configure TCP Server */ + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr=htonl(INADDR_ANY); + servaddr.sin_port=htons(port); + + /* Create socket */ + fd = socket(AF_INET,SOCK_STREAM, 0); + if (fd < 0) + { + perror("socket() failed"); + exit(-1); + } + + /* Set address reuse enable */ + rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); + if (rc < 0) + { + perror("setsockopt() failed"); + close(fd); + exit(-1); + } + + /* Set non blocking */ + rc = ioctl(fd, FIONBIO, (char *)&on); + if (rc < 0) + { + perror("ioctl() failed"); + close(fd); + exit(-1); + } + + /* Bind to socket */ + rc = bind(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)); + if (rc < 0) + { + perror("bind() failed"); + close(fd); + exit(-1); + } + + /* Listen on socket */ + listen(fd, 1); + if (rc < 0) + { + perror("listen() failed"); + close(fd); + exit(-1); + } + + return fd; +} + +static int waitServer(user_data_t * user_data) { + struct timeval timeout; + int rc; + + FD_ZERO(&user_data->fds); + + if (user_data->io >= 0) { + FD_SET(user_data->io, &user_data->fds); + } + + if (user_data->io_listen >= 0) { + FD_SET(user_data->io_listen, &user_data->fds); + } + + if (user_data->control_io >= 0) { + FD_SET(user_data->control_io, &user_data->fds); + } + + if (user_data->control_io_listen >= 0) { + FD_SET(user_data->control_io_listen, &user_data->fds); + } + + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + rc = select(FD_SETSIZE, &user_data->fds, NULL, NULL, &timeout); + + return rc; +} + + +static int processIoListen(user_data_t * user_data) { + struct sockaddr_in cliaddr; + socklen_t clilen; + clilen = sizeof(cliaddr); + + user_data->io = accept(user_data->io_listen, (struct sockaddr *)&cliaddr, &clilen); + user_data->fio = fdopen(user_data->io, "r+"); + + printf("Connection established %s\r\n", inet_ntoa(cliaddr.sin_addr)); +} + +static int processSrqIoListen(user_data_t * user_data) { + struct sockaddr_in cliaddr; + socklen_t clilen; + clilen = sizeof(cliaddr); + + user_data->control_io = accept(user_data->control_io_listen, (struct sockaddr *)&cliaddr, &clilen); + printf("Control Connection established %s\r\n", inet_ntoa(cliaddr.sin_addr)); +} + +static void closeIo(user_data_t * user_data) { + fclose(user_data->fio); + user_data->fio = NULL; + user_data->io = -1; +} + +static void closeSrqIo(user_data_t * user_data) { + close(user_data->control_io); + user_data->control_io = -1; +} + +static int processIo(user_data_t * user_data) { + int rc; + char smbuffer[10]; + rc = recv(user_data->io, smbuffer, sizeof(smbuffer), 0); + if (rc < 0) { + if (errno != EWOULDBLOCK) { + closeIo(user_data); + perror(" recv() failed"); + } + } else if (rc == 0) { + closeIo(user_data); + printf("Connection closed\r\n"); + } else { + SCPI_Input(&scpi_context, smbuffer, rc); + } +} + +static int processSrqIo(user_data_t * user_data) { + int rc; + char smbuffer[10]; + rc = recv(user_data->control_io, smbuffer, sizeof(smbuffer), 0); + if (rc < 0) { + if (errno != EWOULDBLOCK) { + closeSrqIo(user_data); + perror(" recv() failed"); + } + } else if (rc == 0) { + closeSrqIo(user_data); + printf("Control Connection closed\r\n"); + } else { + // nothing to do + } +} + +/* + * + */ +int main(int argc, char** argv) { + (void) argc; + (void) argv; + int rc; + + user_data_t user_data = { + .io_listen = -1, + .io = -1, + .control_io_listen = -1, + .control_io = -1, + .fio = NULL, + }; + + // user_context will be pointer to socket + scpi_context.user_context = &user_data; + + SCPI_Init(&scpi_context); + + user_data.io_listen = createServer(5025); + user_data.control_io_listen = createServer(CONTROL_PORT); + + while(1) { + rc = waitServer(&user_data); + + if (rc < 0) { // failed + perror("select failed"); + exit(-1); + } + + if (rc == 0) { // timeout + SCPI_Input(&scpi_context, NULL, 0); + } + + if ((user_data.io_listen >= 0) && FD_ISSET(user_data.io_listen, &user_data.fds)) { + processIoListen(&user_data); + } + + if ((user_data.control_io_listen >= 0) && FD_ISSET(user_data.control_io_listen, &user_data.fds)) { + processSrqIoListen(&user_data); + } + + if ((user_data.io >= 0) && FD_ISSET(user_data.io, &user_data.fds)) { + processIo(&user_data); + } + + if ((user_data.control_io >= 0) && FD_ISSET(user_data.control_io, &user_data.fds)) { + processSrqIo(&user_data); + } + + } + + return (EXIT_SUCCESS); +} + diff --git a/examples/test-tcp/main.c b/examples/test-tcp/main.c index 55dc792..2336165 100644 --- a/examples/test-tcp/main.c +++ b/examples/test-tcp/main.c @@ -56,6 +56,10 @@ return 0; } +scpi_result_t SCPI_Flush(scpi_t * context) { + return SCPI_RES_OK; +} + int SCPI_Error(scpi_t * context, int_fast16_t err) { (void) context; // BEEP @@ -63,9 +67,12 @@ return 0; } -scpi_result_t SCPI_Srq(scpi_t * context) { - scpi_reg_val_t stb = SCPI_RegGet(context, SCPI_REG_STB); - fprintf(stderr, "**SRQ: 0x%X (%d)\r\n", stb, stb); +scpi_result_t SCPI_Control(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val) { + if (SCPI_CTRL_SRQ == ctrl) { + fprintf(stderr, "**SRQ: 0x%X (%d)\r\n", val, val); + } else { + fprintf(stderr, "**CTRL %02x: 0x%X (%d)\r\n", ctrl, val, val); + } return SCPI_RES_OK; } @@ -79,6 +86,9 @@ return SCPI_RES_OK; } +scpi_result_t SCPI_SystemCommTcpipControlQ(scpi_t * context) { + return SCPI_RES_ERR; +} static int createServer(int port) { int fd; diff --git a/libscpi/inc/scpi/types.h b/libscpi/inc/scpi/types.h index 2fb743f..12af335 100644 --- a/libscpi/inc/scpi/types.h +++ b/libscpi/inc/scpi/types.h @@ -52,19 +52,27 @@ typedef bool bool_t; //typedef enum { FALSE = 0, TRUE } bool_t; - /* scpi interface */ - typedef struct _scpi_t scpi_t; - typedef struct _scpi_interface_t scpi_interface_t; - typedef struct _scpi_buffer_t scpi_buffer_t; - typedef size_t(*scpi_write_t)(scpi_t * context, const char * data, size_t len); - typedef int (*scpi_error_callback_t)(scpi_t * context, int_fast16_t error); + /* IEEE 488.2 registers */ + typedef enum _scpi_reg_name_t scpi_reg_name_t; + typedef enum _scpi_ctrl_name_t scpi_ctrl_name_t; + typedef uint16_t scpi_reg_val_t; /* scpi commands */ typedef enum _scpi_result_t scpi_result_t; typedef struct _scpi_param_list_t scpi_param_list_t; typedef struct _scpi_command_t scpi_command_t; + + /* scpi interface */ + typedef struct _scpi_t scpi_t; + typedef struct _scpi_interface_t scpi_interface_t; + typedef struct _scpi_buffer_t scpi_buffer_t; + typedef size_t(*scpi_write_t)(scpi_t * context, const char * data, size_t len); + typedef scpi_result_t(*scpi_write_control_t)(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val); + typedef int (*scpi_error_callback_t)(scpi_t * context, int_fast16_t error); + typedef scpi_result_t(*scpi_command_callback_t)(scpi_t *); + /* scpi error queue */ typedef void * scpi_error_queue_t; @@ -74,10 +82,6 @@ typedef enum _scpi_special_number_t scpi_special_number_t; typedef struct _scpi_special_number_def_t scpi_special_number_def_t; typedef struct _scpi_number_t scpi_number_t; - - /* IEEE 488.2 registers */ - typedef enum _scpi_reg_name_t scpi_reg_name_t; - typedef uint16_t scpi_reg_val_t; struct _scpi_param_list_t { const scpi_command_t * cmd; @@ -102,10 +106,10 @@ struct _scpi_interface_t { scpi_error_callback_t error; scpi_write_t write; + scpi_write_control_t control; scpi_command_callback_t flush; scpi_command_callback_t reset; scpi_command_callback_t test; - scpi_command_callback_t srq; }; struct _scpi_t { @@ -186,7 +190,25 @@ /* last definition - number of registers */ SCPI_REG_COUNT, }; - + + enum _scpi_ctrl_name_t { + SCPI_CTRL_SRQ = 1, // service request + SCPI_CTRL_GTL, // Go to local + SCPI_CTRL_SDC, // Selected device clear + SCPI_CTRL_PPC, // Parallel poll configure + SCPI_CTRL_GET, // Group execute trigger + SCPI_CTRL_TCT, // Take control + SCPI_CTRL_LLO, // Device clear + SCPI_CTRL_DCL, // Local lockout + SCPI_CTRL_PPU, // Parallel poll unconfigure + SCPI_CTRL_SPE, // Serial poll enable + SCPI_CTRL_SPD, // Serial poll disable + SCPI_CTRL_MLA, // My local address + SCPI_CTRL_UNL, // Unlisten + SCPI_CTRL_MTA, // My talk address + SCPI_CTRL_UNT, // Untalk + SCPI_CTRL_MSA, // My secondary address + }; #ifdef __cplusplus } diff --git a/libscpi/src/ieee488.c b/libscpi/src/ieee488.c index e493a93..513ed90 100644 --- a/libscpi/src/ieee488.c +++ b/libscpi/src/ieee488.c @@ -39,6 +39,8 @@ #include "scpi/error.h" #include "scpi/constants.h" +#include <stdio.h> + /** * Update register value * @param name - register name @@ -58,6 +60,12 @@ } else { return 0; } +} + +static size_t writeControl(scpi_t * context, int ctrl, scpi_reg_val_t val) { + if (context && context->interface && context->interface->control) { + context->interface->control(context, ctrl, val); + } } /** @@ -131,8 +139,8 @@ // set updated register value context->registers[name] = val; - if (srq && context->interface && context->interface->srq) { - context->interface->srq(context); + if (srq) { + writeControl(context, SCPI_CTRL_SRQ, SCPI_RegGet(context, SCPI_REG_STB)); } } -- Gitblit v1.9.1