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 }