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 } |