Jan Breuer
2012-12-26 a4cffa5e99430532bb5bbad3385b910e25025296
Reimplement srq/control callback
7个文件已修改
2个文件已添加
472 ■■■■■ 已修改文件
examples/common/scpi-def.c 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/common/scpi-def.h 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/test-interactive/main.c 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/test-parser/main.c 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/test-tcp-srq/Makefile 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/test-tcp-srq/main.c 337 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/test-tcp/main.c 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
libscpi/inc/scpi/types.h 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
libscpi/src/ieee488.c 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/common/scpi-def.c
@@ -109,6 +109,8 @@
    {.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
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_
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;
}
/*
 * 
 */
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;
}
/*
 * 
 */
examples/test-tcp-srq/Makefile
New file
@@ -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)
examples/test-tcp-srq/main.c
New file
@@ -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);
}
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;
libscpi/inc/scpi/types.h
@@ -52,18 +52,26 @@
    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 {
@@ -187,6 +191,24 @@
        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
}
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
@@ -57,6 +59,12 @@
        return context->registers[name];
    } 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));
    }
}