FreeCalypso > hg > freecalypso-tools
changeset 346:99471c57155a
fcup-rvtat program written, compiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 04 Feb 2018 16:45:05 +0000 |
parents | cc207d81c05f |
children | dd5bab5156bf |
files | .hgignore rvinterf/rvtat/Makefile rvinterf/rvtat/connect.c rvinterf/rvtat/interf.c rvinterf/rvtat/launchrvif.c rvinterf/rvtat/main.c |
diffstat | 6 files changed, 409 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Sun Feb 04 16:05:11 2018 +0000 +++ b/.hgignore Sun Feb 04 16:45:05 2018 +0000 @@ -46,6 +46,7 @@ ^rvinterf/lowlevel/rvinterf$ ^rvinterf/lowlevel/rvtdump$ ^rvinterf/lowlevel/tfc139$ +^rvinterf/rvtat/fcup-rvtat$ ^rvinterf/tmsh/fc-tmsh$ ^target-utils/.*/crt0\.S$
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/rvtat/Makefile Sun Feb 04 16:45:05 2018 +0000 @@ -0,0 +1,17 @@ +CC= gcc +CFLAGS= -O2 -I../include +PROG= fcup-rvtat +OBJS= connect.o interf.o launchrvif.o main.o +INSTBIN=/opt/freecalypso/bin + +all: ${PROG} + +${PROG}: ${OBJS} + ${CC} ${CFLAGS} -o $@ ${OBJS} + +install: ${PROG} + mkdir -p ${INSTBIN} + install -c ${PROG} ${INSTBIN} + +clean: + rm -f *.o *.out *errs ${PROG}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/rvtat/connect.c Sun Feb 04 16:45:05 2018 +0000 @@ -0,0 +1,56 @@ +/* + * Connecting to an already running rvinterf process + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <unistd.h> +#include "pktmux.h" +#include "localsock.h" +#include "exitcodes.h" + +char *socket_pathname = "/tmp/rvinterf_socket"; +int sock; + +connect_local_socket() +{ + /* local socket binding voodoo copied from osmocon */ + struct sockaddr_un local; + unsigned int namelen; + int rc; + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + perror("socket(AF_UNIX, SOCK_STREAM, 0)"); + exit(ERROR_UNIX); + } + + local.sun_family = AF_UNIX; + strncpy(local.sun_path, socket_pathname, sizeof(local.sun_path)); + local.sun_path[sizeof(local.sun_path) - 1] = '\0'; + + /* we use the same magic that X11 uses in Xtranssock.c for + * calculating the proper length of the sockaddr */ +#if defined(BSD44SOCKETS) || defined(__UNIXWARE__) + local.sun_len = strlen(local.sun_path); +#endif +#if defined(BSD44SOCKETS) || defined(SUN_LEN) + namelen = SUN_LEN(&local); +#else + namelen = strlen(local.sun_path) + + offsetof(struct sockaddr_un, sun_path) + 1; +#endif + + rc = connect(sock, (struct sockaddr *) &local, namelen); + if (rc != 0) { + perror(socket_pathname); + exit(ERROR_RVINTERF); + } + + return(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/rvtat/interf.c Sun Feb 04 16:45:05 2018 +0000 @@ -0,0 +1,129 @@ +/* + * In this module we implement our synchronous interface to the target + * via rvinterf. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include "limits.h" +#include "localsock.h" +#include "pktmux.h" +#include "exitcodes.h" + +extern int sock; + +int rx_enable_state; +u_char rvi_msg[LOCALSOCK_MAX_MSG]; +int rvi_msg_len; + +static void +collect_bytes_from_rvi(buf, nbytes) + u_char *buf; +{ + int cc; + + while (nbytes) { + cc = read(sock, buf, nbytes); + if (cc <= 0) { + perror("read from rvinterf socket"); + exit(ERROR_RVINTERF); + } + buf += cc; + nbytes -= cc; + } +} + +collect_rvi_msg() +{ + u_char lenbuf[2]; + + collect_bytes_from_rvi(lenbuf, 2); + rvi_msg_len = lenbuf[0] << 8 | lenbuf[1]; + if (rvi_msg_len < 1 || rvi_msg_len > LOCALSOCK_MAX_MSG) { + fprintf(stderr, "Invalid length from rvinterf: %02X%02X\n", + lenbuf[0], lenbuf[1]); + exit(ERROR_RVINTERF); + } + collect_bytes_from_rvi(rvi_msg, rvi_msg_len); + return(0); +} + +send_rvimisc_command(cmdpkt, cmdlen) + u_char *cmdpkt; +{ + u_char lenbuf[2]; + + lenbuf[0] = 0; + lenbuf[1] = cmdlen; + write(sock, lenbuf, 2); + write(sock, cmdpkt, cmdlen); +} + +rx_control(enable) +{ + u_char cmdpkt[2]; + int cmdlen; + + /* are we already in the desired state? */ + if (rx_enable_state == enable) + return(0); + /* no, do the work */ + if (enable) { + cmdpkt[0] = CLI2RVI_WANT_MUXPROTO; + cmdpkt[1] = RVT_AT_HEADER; + cmdlen = 2; + } else { + cmdpkt[0] = CLI2RVI_RESET_PACKET_RX; + cmdlen = 1; + } + send_rvimisc_command(cmdpkt, cmdlen); + collect_rvi_msg(); + if (rvi_msg[0] != RVI2CLI_LOCAL_CMD_RESP || rvi_msg_len < 2) { + fprintf(stderr, + "error: unexpected response to rvinterf local command\n"); + exit(ERROR_RVINTERF); + } + if (rvi_msg[1] != '+') { + fprintf(stderr, "Error from rvinterf: %.*s\n", rvi_msg_len - 1, + rvi_msg + 1); + exit(ERROR_RVINTERF); + } + rx_enable_state = enable; + return(0); +} + +send_pkt_to_target(pkt, pktlen) + u_char *pkt; +{ + u_char hdrbuf[3]; + int len1; + + len1 = pktlen + 1; + hdrbuf[0] = len1 >> 8; + hdrbuf[1] = len1 & 0xFF; + hdrbuf[2] = CLI2RVI_PKT_TO_TARGET; + write(sock, hdrbuf, 3); + write(sock, pkt, pktlen); +} + +collect_pkt_from_target() +{ + collect_rvi_msg(); + if (rvi_msg[0] != RVI2CLI_PKT_FROM_TARGET) { + fprintf(stderr, + "error: unexpected response type from rvinterf\n"); + exit(ERROR_RVINTERF); + } + if (rvi_msg_len < 2) { + fprintf(stderr, "error: packet from target is null\n"); + exit(ERROR_RVINTERF); + } + if (rvi_msg[1] != RVT_AT_HEADER) { + fprintf(stderr, + "error: packet from target is not on ATI channel\n"); + exit(ERROR_RVINTERF); + } + return(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/rvtat/launchrvif.c Sun Feb 04 16:45:05 2018 +0000 @@ -0,0 +1,63 @@ +/* + * This module implements the optional "behind the scenes" invokation + * of rvinterf from fc-fsio etc. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include "exitcodes.h" + +static char rvinterf_pathname[] = "/opt/freecalypso/bin/rvinterf"; + +extern int sock; + +char *rvinterf_ttyport, *rvinterf_Bopt, *rvinterf_lopt, *rvinterf_wopt; + +launch_rvinterf() +{ + int sp[2], rc; + char *rvif_argv[11], Sarg[16], **ap; + + rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sp); + if (rc < 0) { + perror("socketpair"); + exit(ERROR_UNIX); + } + sock = sp[0]; + sprintf(Sarg, "-S%d", sp[1]); + ap = rvif_argv; + *ap++ = "rvinterf"; + *ap++ = Sarg; + *ap++ = "-n"; + if (rvinterf_Bopt) { + *ap++ = "-B"; + *ap++ = rvinterf_Bopt; + } + if (rvinterf_lopt) { + *ap++ = "-l"; + *ap++ = rvinterf_lopt; + } + if (rvinterf_wopt) { + *ap++ = "-w"; + *ap++ = rvinterf_wopt; + } + *ap++ = rvinterf_ttyport; + *ap = 0; + rc = vfork(); + if (rc < 0) { + perror("vfork for launching rvinterf"); + exit(ERROR_UNIX); + } + if (!rc) { + /* we are in the child - do the exec */ + close(sp[0]); + execv(rvinterf_pathname, rvif_argv); + perror(rvinterf_pathname); + _exit(1); + } + close(sp[1]); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/rvtat/main.c Sun Feb 04 16:45:05 2018 +0000 @@ -0,0 +1,143 @@ +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> +#include "pktmux.h" +#include "limits.h" +#include "localtypes.h" +#include "exitcodes.h" + +extern char *socket_pathname; +extern char *rvinterf_ttyport, *rvinterf_Bopt, *rvinterf_lopt, *rvinterf_wopt; + +extern u_char rvi_msg[]; +extern int rvi_msg_len; + +char command[256], message[256]; +int cmd_with_msg; + +read_command_input(buf) + char *buf; +{ + char *nl; + + if (!fgets(buf, 256, stdin)) + return(0); + nl = index(buf, '\n'); + if (!nl) { + printf("Ecommand or message is too long\n"); + exit(1); + } + *nl = '\0'; + return(1); +} + +send_to_target(str) + char *str; +{ + unsigned len; + u_char sendpkt[MAX_PKT_TO_TARGET+1]; + + len = strlen(str); + /* fill out the packet */ + sendpkt[0] = RVT_AT_HEADER; + strcpy(sendpkt + 1, str); + /* send it! */ + send_pkt_to_target(sendpkt, len + 1); + return(0); +} + +execute_command() +{ + send_to_target(command); + if (cmd_with_msg) { + collect_pkt_from_target(); + if (rvi_msg_len != 4 || rvi_msg[2] != '>' || rvi_msg[3] != ' '){ + printf("F%.*s\n", rvi_msg_len - 2, rvi_msg + 2); + return; + } + send_to_target(message); + } + for (;;) { + collect_pkt_from_target(); + if (rvi_msg_len == 4 && !strncmp(rvi_msg + 2, "OK", 2) || + rvi_msg_len == 7 && !strncmp(rvi_msg + 2, "ERROR", 5) || + rvi_msg_len == 6 && !strncmp(rvi_msg + 2, "BUSY", 4) || + rvi_msg_len == 12 && + !strncmp(rvi_msg + 2, "NO CARRIER", 10) || + rvi_msg_len >= 12 && + !strncmp(rvi_msg + 2, "+CME ERROR", 10) || + rvi_msg_len >= 12 && + !strncmp(rvi_msg + 2, "+CMS ERROR", 10)) { + printf("F%.*s\n", rvi_msg_len - 2, rvi_msg + 2); + return; + } + printf("I%.*s\n", rvi_msg_len - 2, rvi_msg + 2); + } +} + +main(argc, argv) + char **argv; +{ + extern int optind; + extern char *optarg; + int c, sopt = 0; + + while ((c = getopt(argc, argv, "B:l:p:s:w:")) != EOF) + switch (c) { + case 'B': + rvinterf_Bopt = optarg; + continue; + case 'l': + rvinterf_lopt = optarg; + continue; + case 'p': + rvinterf_ttyport = optarg; + continue; + case 's': + socket_pathname = optarg; + sopt++; + continue; + case 'w': + rvinterf_wopt = optarg; + continue; + case '?': + default: + /* error msg already printed */ + exit(ERROR_USAGE); + } + if (rvinterf_ttyport) { + if (sopt) { + fprintf(stderr, + "%s error: -p and -s options are mutually exclusive\n", + argv[0]); + exit(ERROR_USAGE); + } + launch_rvinterf(); + } else { + if (rvinterf_Bopt || rvinterf_lopt || rvinterf_wopt) { + fprintf(stderr, +"%s error: -B, -l and -w options are meaningful only when launching rvinterf\n", + argv[0]); + exit(ERROR_USAGE); + } + connect_local_socket(); + } + + while (read_command_input(command)) { + if (!strcasecmp(command, "c+m")) { + cmd_with_msg = 1; + if (!read_command_input(command)) + break; + if (!read_command_input(message)) + break; + } else + cmd_with_msg = 0; + rx_control(1); + execute_command(); + fflush(stdout); + } + exit(0); +}