# HG changeset patch # User Michael Spacefalcon # Date 1385192413 0 # Node ID 7f727aaf5cd49294784815f408d02720bd343d04 # Parent 2f214bd03119924bc5ae228f9bf7953251bc43ce rvinterf: beginning of server implementation diff -r 2f214bd03119 -r 7f727aaf5cd4 .hgignore --- a/.hgignore Fri Nov 22 20:16:00 2013 +0000 +++ b/.hgignore Sat Nov 23 07:40:13 2013 +0000 @@ -15,6 +15,7 @@ ^loadtools/fc-loadtool ^loadtools/fc-xram +^rvinterf/lowlevel/rvinterf$ ^rvinterf/lowlevel/rvtdump$ ^rvinterf/old/etmsend$ ^rvinterf/old/rvtdump$ diff -r 2f214bd03119 -r 7f727aaf5cd4 rvinterf/localsock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/localsock.h Sat Nov 23 07:40:13 2013 +0000 @@ -0,0 +1,73 @@ +/* + * This header defines and describes (through comments) the local UNIX domain + * socket interface implemented between rvinterf and its clients like fc-tmsh. + * + * The UNIX domain sockets used for this ad hoc interface are of the + * SOCK_STREAM kind, but the true nature of the communication is message-based. + * We use the same trick that is used for DNS over TCP: every message in each + * direction is preceded by a 2-byte length. This length and all other + * multibyte numbers are sent in the native byte order of the machine on which + * the rvinterf suite is running. The limit on the size of these messages + * (for sizing buffers etc) is: + */ + +#define LOCALSOCK_MAX_MSG 1024 + +/* + * Each message in the client->rvinterf direction (can be seen as command) + * begins (after the length) with an opcode byte as follows: + */ + +#define CLI2RVI_WANT_RVTRACE 0x00 +#define CLI2RVI_WANT_MUXPROTO 0x01 +#define CLI2RVI_PKT_TO_TARGET 0x02 +#define CLI2RVI_RAWBYTES_TO_TARGET 0x03 + +/* + * The first two commands (CLI2RVI_WANT_RVTRACE and CLI2RVI_WANT_MUXPROTO) + * are the means by which client programs inform rvinterf that they are + * interested in receiving copies of certain packets coming from the target. + * + * The CLI2RVI_WANT_RVTRACE opcode needs to be followed by a USEID mask value + * and a USEID match value, both in the native byte order of the machine + * running rvinterf, for a total message length of 9 bytes. For every RV + * trace message received from the target, rvinterf will iterate through all + * active clients to see who is interested: if the received USEID ANDed with + * the mask equals the match value, the message will be forwarded to that + * client. + * + * The CLI2RVI_WANT_MUXPROTO opcode needs to be followed by one byte + * identifying the RVTMUX protocol of interest, i.e., the first byte of the + * packets exchanged between the host and the target, e.g., 0x12 for L1 traces + * as defined in pktmux.h, for a total message length of 2 bytes. + * + * The last two commands (CLI2RVI_PKT_TO_TARGET and CLI2RVI_RAWBYTES_TO_TARGET) + * cause data payload to be sent to the target serial port. Payload following + * CLI2RVI_PKT_TO_TARGET (must not exceed MAX_PKT_TO_TARGET) is sent with the + * proper packet encapsulation per TI; bytes following + * CLI2RVI_RAWBYTES_TO_TARGET are sent raw. + */ + +/* + * Each message in the rvinterf->client direction begins (after the length) + * with a message type byte as follows: + */ + +#define RVI2CLI_PKT_FROM_TARGET 0x00 +#define RVI2CLI_LOCAL_CMD_RESP 0x01 + +/* + * Messages beginning with RVI2CLI_PKT_FROM_TARGET are packets received + * from the target GSM device; the byte following this type code is the + * first byte of the packet from the target, e.g., 0x11 for RV traces or + * 0x12 for L1 traces. Rvinterf will only start sending these messages + * to a client after that client has expressed interest in receiving + * target->host packets of a particular type. + * + * Messages beginning with RVI2CLI_LOCAL_CMD_RESP are generated locally + * by rvinterf itself as responses to commands, currently as responses to + * CLI2RVI_WANT_{RVTRACE,MUXPROTO}. The byte following the + * RVT2CLI_LOCAL_CMD_RESP type code is ASCII '+' or ASCII '-', indicating + * success or error, respectively. Any remaining bytes form a message + * for the user. + */ diff -r 2f214bd03119 -r 7f727aaf5cd4 rvinterf/lowlevel/Makefile --- a/rvinterf/lowlevel/Makefile Fri Nov 22 20:16:00 2013 +0000 +++ b/rvinterf/lowlevel/Makefile Sat Nov 23 07:40:13 2013 +0000 @@ -1,15 +1,21 @@ CC= gcc CFLAGS= -O2 -PROGS= rvtdump +PROGS= rvtdump rvinterf INSTBIN=/usr/local/bin RVTDUMP_OBJS= format.o format_g23.o openport.o output.o packetrx.o rvtdump.o +RVINTERF_OBJS= format.o format_g23.o logsent.o openport.o output.o packetrx.o \ + packettx.o rvifmain.o + all: ${PROGS} rvtdump: ${RVTDUMP_OBJS} ${CC} ${CFLAGS} -o $@ ${RVTDUMP_OBJS} +rvinterf: ${RVINTERF_OBJS} + ${CC} ${CFLAGS} -o $@ ${RVINTERF_OBJS} + install: ${PROGS} mkdir -p ${INSTBIN} install -c ${PROGS} ${INSTBIN} diff -r 2f214bd03119 -r 7f727aaf5cd4 rvinterf/lowlevel/client.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/lowlevel/client.h Sat Nov 23 07:40:13 2013 +0000 @@ -0,0 +1,23 @@ +/* + * The structure defined in this header file is malloced in rvinterf + * for every client program connection. + */ + +#define MAX_RVT_INTEREST 4 + +typedef unsigned u32; + +struct client { + struct client *next; + struct client **backptr; + int fd; + int rx_state; + u_char rx_buf[LOCALSOCK_MAX_MSG]; + int rx_msglen; + u_char *rx_ptr; + int rx_left; + int int_rvt_count; + u32 int_rvt_mask[MAX_RVT_INTEREST]; + u32 int_rvt_match[MAX_RVT_INTEREST]; + char int_proto[8]; +}; diff -r 2f214bd03119 -r 7f727aaf5cd4 rvinterf/lowlevel/rvifmain.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/lowlevel/rvifmain.c Sat Nov 23 07:40:13 2013 +0000 @@ -0,0 +1,117 @@ +/* + * This module contains the main() function for rvinterf + */ + +#include +#include +#include +#include +#include +#include +#include "../pktmux.h" + +extern int target_fd; +extern char *baudrate_name; + +extern u_char rxpkt[]; +extern size_t rxpkt_len; + +char *logfname; +FILE *logF; +time_t logtime; +int background; + +main(argc, argv) + char **argv; +{ + extern char *optarg; + extern int optind; + int c; + fd_set fds; + + while ((c = getopt(argc, argv, "bB:d:l:")) != EOF) + switch (c) { + case 'b': + background++; + continue; + case 'B': + baudrate_name = optarg; + continue; + case 'd': + target_fd = atoi(optarg); + continue; + case 'l': + logfname = optarg; + continue; + case '?': + default: +usage: fprintf(stderr, + "usage: %s [options] ttyport\n", argv[0]); + exit(1); + } + if (target_fd <= 0) { + if (argc - optind != 1) + goto usage; + open_target_serial(argv[optind]); + } + + set_serial_nonblock(0); + setlinebuf(stdout); + if (logfname) { + logF = fopen(logfname, "w"); + if (!logF) { + perror(logfname); + exit(1); + } + fprintf(logF, "*** Log of rvinterf session ***\n"); + setlinebuf(logF); + } + if (background) { + c = fork(); + if (c < 0) { + perror("fork"); + exit(1); + } + if (c) { + printf("rvinterf forked into background (pid %d)\n", c); + exit(0); + } + } + for (;;) { + FD_ZERO(&fds); + FD_SET(target_fd, &fds); + c = select(target_fd+1, &fds, 0, 0, 0); + time(&logtime); + if (c < 0) { + if (errno == EINTR) + continue; + perror("select"); + exit(1); + } + if (FD_ISSET(target_fd, &fds)) + process_serial_rx(); + } +} + +handle_rx_packet() +{ + switch (rxpkt[0]) { + case RVT_RV_HEADER: + if (rxpkt_len < 6) + goto unknown; + print_rv_trace(); + return; + case RVT_L1_HEADER: + print_l1_trace(); + return; + case RVT_L23_HEADER: + print_g23_trace(); + return; + case RVT_TM_HEADER: + print_etm_output_raw(); + return; + default: + unknown: + print_unknown_packet(); + } +}