FreeCalypso > hg > fc-sim-tools
comparison calypso/tpinterf.c @ 4:deeeef558279
fcsim-calypso-be put together
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Sun, 14 Mar 2021 05:07:34 +0000 |
| parents | |
| children | b25d4dfe5798 |
comparison
equal
deleted
inserted
replaced
| 3:45ea06eaa9fd | 4:deeeef558279 |
|---|---|
| 1 /* | |
| 2 * This code is based on loadtools/tpinterf.c from FC host tools, | |
| 3 * modified for our different application of interfacing between | |
| 4 * simagent below and fc-simtool above. | |
| 5 */ | |
| 6 | |
| 7 #include <sys/types.h> | |
| 8 #include <sys/time.h> | |
| 9 #include <sys/errno.h> | |
| 10 #include <stdio.h> | |
| 11 #include <string.h> | |
| 12 #include <strings.h> | |
| 13 #include <stdlib.h> | |
| 14 #include <unistd.h> | |
| 15 | |
| 16 extern int errno; | |
| 17 | |
| 18 extern int target_fd; | |
| 19 | |
| 20 /* definition matches target-utils/libcommon/cmdentry.c */ | |
| 21 #define MAXCMD 527 | |
| 22 | |
| 23 /* | |
| 24 * static buffer between tpinterf_make_cmd and tpinterf_send_cmd | |
| 25 * | |
| 26 * We store the command with an ending \r\n so we can use it for | |
| 27 * matching the received echo as well, hence the sizing of the | |
| 28 * buffer. | |
| 29 */ | |
| 30 static char cmdbuf[MAXCMD+2]; | |
| 31 static int cmdlen; | |
| 32 | |
| 33 static int | |
| 34 arg_chars_valid(arg) | |
| 35 char *arg; | |
| 36 { | |
| 37 char *cp; | |
| 38 | |
| 39 for (cp = arg; *cp; cp++) | |
| 40 if (*cp < ' ' || *cp > '~') | |
| 41 return(0); | |
| 42 return(1); | |
| 43 } | |
| 44 | |
| 45 /* | |
| 46 * This function takes a command for the target in argv form and | |
| 47 * converts it to a space-separated continuous string which can be | |
| 48 * passed as tty "keyboard" input to the target, enforcing length | |
| 49 * and character validity limits in the process. The output is | |
| 50 * stored in an internal static buffer for subsequent | |
| 51 * tpinterf_send_cmd(). | |
| 52 * | |
| 53 * Return value: 0 if everything OK, or -1 if some constraint is | |
| 54 * violated. | |
| 55 */ | |
| 56 tpinterf_make_cmd(argv) | |
| 57 char **argv; | |
| 58 { | |
| 59 int arglen; | |
| 60 char **ap, *dp; | |
| 61 | |
| 62 dp = cmdbuf; | |
| 63 cmdlen = 0; | |
| 64 for (ap = argv; *ap; ap++) { | |
| 65 arglen = strlen(*ap); | |
| 66 if (ap != argv) | |
| 67 arglen++; /* separating space */ | |
| 68 if (arglen > MAXCMD - cmdlen) | |
| 69 return(-1); | |
| 70 if (!arg_chars_valid(*ap)) | |
| 71 return(-1); | |
| 72 if (ap != argv) | |
| 73 *dp++ = ' '; | |
| 74 strcpy(dp, *ap); | |
| 75 dp += strlen(*ap); | |
| 76 cmdlen += arglen; | |
| 77 } | |
| 78 *dp++ = '\r'; | |
| 79 *dp = '\n'; | |
| 80 return(0); | |
| 81 } | |
| 82 | |
| 83 /* | |
| 84 * This function sends the previously-constructed command to the target, | |
| 85 * and collects the expected echo. | |
| 86 * | |
| 87 * Return value: 0 if successful, -1 on errors (timeout or wrong response) | |
| 88 */ | |
| 89 tpinterf_send_cmd() | |
| 90 { | |
| 91 char echobuf[MAXCMD+2]; | |
| 92 fd_set fds; | |
| 93 struct timeval tv; | |
| 94 int rcvd, cc; | |
| 95 | |
| 96 write(target_fd, cmdbuf, cmdlen + 1); | |
| 97 for (rcvd = 0; rcvd < cmdlen + 2; ) { | |
| 98 FD_ZERO(&fds); | |
| 99 FD_SET(target_fd, &fds); | |
| 100 tv.tv_sec = 1; | |
| 101 tv.tv_usec = 0; | |
| 102 cc = select(target_fd+1, &fds, NULL, NULL, &tv); | |
| 103 if (cc < 0) { | |
| 104 if (errno == EINTR) | |
| 105 continue; | |
| 106 printf("back end error: failed select\n"); | |
| 107 return(-1); | |
| 108 } | |
| 109 if (cc < 1) { | |
| 110 printf( | |
| 111 "back end error: timeout waiting for command echo\n"); | |
| 112 return(-1); | |
| 113 } | |
| 114 cc = read(target_fd, echobuf + rcvd, cmdlen + 2 - rcvd); | |
| 115 if (cc <= 0) { | |
| 116 printf( | |
| 117 "back end error: failed read after successful select\n"); | |
| 118 return(-1); | |
| 119 } | |
| 120 rcvd += cc; | |
| 121 } | |
| 122 if (bcmp(echobuf, cmdbuf, cmdlen + 2)) { | |
| 123 printf("back end error: command echo mismatch\n"); | |
| 124 return(-1); | |
| 125 } else | |
| 126 return(0); | |
| 127 } | |
| 128 | |
| 129 /* | |
| 130 * This functions reads the serial output from the target until a | |
| 131 * '=' prompt is received. All intermediate output is passed to | |
| 132 * stdout, with some hacks specific to this SIM interface back end. | |
| 133 */ | |
| 134 tpinterf_pass_output(timeout) | |
| 135 { | |
| 136 char buf[1024], *cp; | |
| 137 fd_set fds; | |
| 138 struct timeval tv; | |
| 139 int cc, newline = 1, termflag = 0; | |
| 140 unsigned goodchar; | |
| 141 | |
| 142 for (goodchar = 0; ; ) { | |
| 143 FD_ZERO(&fds); | |
| 144 FD_SET(target_fd, &fds); | |
| 145 tv.tv_sec = timeout; | |
| 146 tv.tv_usec = 0; | |
| 147 cc = select(target_fd+1, &fds, NULL, NULL, &tv); | |
| 148 if (cc < 0) { | |
| 149 if (errno == EINTR) | |
| 150 continue; | |
| 151 printf("back end error: failed select\n"); | |
| 152 return(-1); | |
| 153 } | |
| 154 if (cc < 1) { | |
| 155 printf( | |
| 156 "back end error: timeout waiting for simagent response\n"); | |
| 157 return(-1); | |
| 158 } | |
| 159 cc = read(target_fd, buf + goodchar, sizeof(buf) - goodchar); | |
| 160 if (cc <= 0) { | |
| 161 printf( | |
| 162 "back end error: failed read after successful select\n"); | |
| 163 return(-1); | |
| 164 } | |
| 165 for (cp = buf + goodchar; cc; cp++) { | |
| 166 cc--; | |
| 167 if (*cp == '=' && newline && !cc) | |
| 168 break; | |
| 169 if (*cp == '\n') { | |
| 170 newline = 1; | |
| 171 termflag = 1; | |
| 172 continue; | |
| 173 } | |
| 174 newline = 0; | |
| 175 if (*cp == '\r') | |
| 176 termflag = 1; | |
| 177 if (!termflag) | |
| 178 goodchar++; | |
| 179 if (goodchar >= 516) | |
| 180 termflag = 1; | |
| 181 } | |
| 182 } | |
| 183 if (!goodchar) { | |
| 184 printf("back end error: empty output from simagent\n"); | |
| 185 return(-1); | |
| 186 } | |
| 187 buf[goodchar] = '\0'; | |
| 188 puts(buf); | |
| 189 return(0); | |
| 190 } |
