bitbang: jtag-only drivers: switch to new reset API
[openocd.git] / src / jtag / drivers / remote_bitbang.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Richard Uhler *
3 * ruhler@mit.edu *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #ifndef _WIN32
24 #include <sys/un.h>
25 #include <netdb.h>
26 #endif
27 #include <jtag/interface.h>
28 #include "bitbang.h"
29
30 /* arbitrary limit on host name length: */
31 #define REMOTE_BITBANG_HOST_MAX 255
32
33 static char *remote_bitbang_host;
34 static char *remote_bitbang_port;
35
36 static FILE *remote_bitbang_file;
37 static int remote_bitbang_fd;
38
39 /* Circular buffer. When start == end, the buffer is empty. */
40 static char remote_bitbang_buf[64];
41 static unsigned remote_bitbang_start;
42 static unsigned remote_bitbang_end;
43
44 static int remote_bitbang_buf_full(void)
45 {
46 return remote_bitbang_end ==
47 ((remote_bitbang_start + sizeof(remote_bitbang_buf) - 1) %
48 sizeof(remote_bitbang_buf));
49 }
50
51 /* Read any incoming data, placing it into the buffer. */
52 static int remote_bitbang_fill_buf(void)
53 {
54 socket_nonblock(remote_bitbang_fd);
55 while (!remote_bitbang_buf_full()) {
56 unsigned contiguous_available_space;
57 if (remote_bitbang_end >= remote_bitbang_start) {
58 contiguous_available_space = sizeof(remote_bitbang_buf) -
59 remote_bitbang_end;
60 if (remote_bitbang_start == 0)
61 contiguous_available_space -= 1;
62 } else {
63 contiguous_available_space = remote_bitbang_start -
64 remote_bitbang_end - 1;
65 }
66 ssize_t count = read(remote_bitbang_fd,
67 remote_bitbang_buf + remote_bitbang_end,
68 contiguous_available_space);
69 if (count > 0) {
70 remote_bitbang_end += count;
71 if (remote_bitbang_end == sizeof(remote_bitbang_buf))
72 remote_bitbang_end = 0;
73 } else if (count == 0) {
74 return ERROR_OK;
75 } else if (count < 0) {
76 if (errno == EAGAIN) {
77 return ERROR_OK;
78 } else {
79 LOG_ERROR("remote_bitbang_fill_buf: %s (%d)",
80 strerror(errno), errno);
81 return ERROR_FAIL;
82 }
83 }
84 }
85
86 return ERROR_OK;
87 }
88
89 static int remote_bitbang_putc(int c)
90 {
91 if (EOF == fputc(c, remote_bitbang_file)) {
92 LOG_ERROR("remote_bitbang_putc: %s", strerror(errno));
93 return ERROR_FAIL;
94 }
95 return ERROR_OK;
96 }
97
98 static int remote_bitbang_quit(void)
99 {
100 if (EOF == fputc('Q', remote_bitbang_file)) {
101 LOG_ERROR("fputs: %s", strerror(errno));
102 return ERROR_FAIL;
103 }
104
105 if (EOF == fflush(remote_bitbang_file)) {
106 LOG_ERROR("fflush: %s", strerror(errno));
107 return ERROR_FAIL;
108 }
109
110 /* We only need to close one of the FILE*s, because they both use the same */
111 /* underlying file descriptor. */
112 if (EOF == fclose(remote_bitbang_file)) {
113 LOG_ERROR("fclose: %s", strerror(errno));
114 return ERROR_FAIL;
115 }
116
117 free(remote_bitbang_host);
118 free(remote_bitbang_port);
119
120 LOG_INFO("remote_bitbang interface quit");
121 return ERROR_OK;
122 }
123
124 static bb_value_t char_to_int(int c)
125 {
126 switch (c) {
127 case '0':
128 return BB_LOW;
129 case '1':
130 return BB_HIGH;
131 default:
132 remote_bitbang_quit();
133 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c, c);
134 return BB_ERROR;
135 }
136 }
137
138 /* Get the next read response. */
139 static bb_value_t remote_bitbang_rread(void)
140 {
141 if (EOF == fflush(remote_bitbang_file)) {
142 remote_bitbang_quit();
143 LOG_ERROR("fflush: %s", strerror(errno));
144 return BB_ERROR;
145 }
146
147 /* Enable blocking access. */
148 socket_block(remote_bitbang_fd);
149 char c;
150 ssize_t count = read(remote_bitbang_fd, &c, 1);
151 if (count == 1) {
152 return char_to_int(c);
153 } else {
154 remote_bitbang_quit();
155 LOG_ERROR("read: count=%d, error=%s", (int) count, strerror(errno));
156 return BB_ERROR;
157 }
158 }
159
160 static int remote_bitbang_sample(void)
161 {
162 if (remote_bitbang_fill_buf() != ERROR_OK)
163 return ERROR_FAIL;
164 assert(!remote_bitbang_buf_full());
165 return remote_bitbang_putc('R');
166 }
167
168 static bb_value_t remote_bitbang_read_sample(void)
169 {
170 if (remote_bitbang_start != remote_bitbang_end) {
171 int c = remote_bitbang_buf[remote_bitbang_start];
172 remote_bitbang_start =
173 (remote_bitbang_start + 1) % sizeof(remote_bitbang_buf);
174 return char_to_int(c);
175 }
176 return remote_bitbang_rread();
177 }
178
179 static int remote_bitbang_write(int tck, int tms, int tdi)
180 {
181 char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
182 return remote_bitbang_putc(c);
183 }
184
185 static int remote_bitbang_reset(int trst, int srst)
186 {
187 char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0));
188 return remote_bitbang_putc(c);
189 }
190
191 static int remote_bitbang_blink(int on)
192 {
193 char c = on ? 'B' : 'b';
194 return remote_bitbang_putc(c);
195 }
196
197 static struct bitbang_interface remote_bitbang_bitbang = {
198 .buf_size = sizeof(remote_bitbang_buf) - 1,
199 .sample = &remote_bitbang_sample,
200 .read_sample = &remote_bitbang_read_sample,
201 .write = &remote_bitbang_write,
202 .blink = &remote_bitbang_blink,
203 };
204
205 static int remote_bitbang_init_tcp(void)
206 {
207 struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
208 struct addrinfo *result, *rp;
209 int fd = 0;
210
211 LOG_INFO("Connecting to %s:%s",
212 remote_bitbang_host ? remote_bitbang_host : "localhost",
213 remote_bitbang_port);
214
215 /* Obtain address(es) matching host/port */
216 int s = getaddrinfo(remote_bitbang_host, remote_bitbang_port, &hints, &result);
217 if (s != 0) {
218 LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s));
219 return ERROR_FAIL;
220 }
221
222 /* getaddrinfo() returns a list of address structures.
223 Try each address until we successfully connect(2).
224 If socket(2) (or connect(2)) fails, we (close the socket
225 and) try the next address. */
226
227 for (rp = result; rp != NULL ; rp = rp->ai_next) {
228 fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
229 if (fd == -1)
230 continue;
231
232 if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
233 break; /* Success */
234
235 close(fd);
236 }
237
238 freeaddrinfo(result); /* No longer needed */
239
240 if (rp == NULL) { /* No address succeeded */
241 LOG_ERROR("Failed to connect: %s", strerror(errno));
242 return ERROR_FAIL;
243 }
244
245 return fd;
246 }
247
248 static int remote_bitbang_init_unix(void)
249 {
250 if (remote_bitbang_host == NULL) {
251 LOG_ERROR("host/socket not specified");
252 return ERROR_FAIL;
253 }
254
255 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
256 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
257 if (fd < 0) {
258 LOG_ERROR("socket: %s", strerror(errno));
259 return ERROR_FAIL;
260 }
261
262 struct sockaddr_un addr;
263 addr.sun_family = AF_UNIX;
264 strncpy(addr.sun_path, remote_bitbang_host, sizeof(addr.sun_path));
265 addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
266
267 if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
268 LOG_ERROR("connect: %s", strerror(errno));
269 return ERROR_FAIL;
270 }
271
272 return fd;
273 }
274
275 static int remote_bitbang_init(void)
276 {
277 bitbang_interface = &remote_bitbang_bitbang;
278
279 remote_bitbang_start = 0;
280 remote_bitbang_end = 0;
281
282 LOG_INFO("Initializing remote_bitbang driver");
283 if (remote_bitbang_port == NULL)
284 remote_bitbang_fd = remote_bitbang_init_unix();
285 else
286 remote_bitbang_fd = remote_bitbang_init_tcp();
287
288 if (remote_bitbang_fd < 0)
289 return remote_bitbang_fd;
290
291 remote_bitbang_file = fdopen(remote_bitbang_fd, "w+");
292 if (remote_bitbang_file == NULL) {
293 LOG_ERROR("fdopen: failed to open write stream");
294 close(remote_bitbang_fd);
295 return ERROR_FAIL;
296 }
297
298 LOG_INFO("remote_bitbang driver initialized");
299 return ERROR_OK;
300 }
301
302 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command)
303 {
304 if (CMD_ARGC == 1) {
305 uint16_t port;
306 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
307 free(remote_bitbang_port);
308 remote_bitbang_port = port == 0 ? NULL : strdup(CMD_ARGV[0]);
309 return ERROR_OK;
310 }
311 return ERROR_COMMAND_SYNTAX_ERROR;
312 }
313
314 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
315 {
316 if (CMD_ARGC == 1) {
317 free(remote_bitbang_host);
318 remote_bitbang_host = strdup(CMD_ARGV[0]);
319 return ERROR_OK;
320 }
321 return ERROR_COMMAND_SYNTAX_ERROR;
322 }
323
324 static const struct command_registration remote_bitbang_command_handlers[] = {
325 {
326 .name = "remote_bitbang_port",
327 .handler = remote_bitbang_handle_remote_bitbang_port_command,
328 .mode = COMMAND_CONFIG,
329 .help = "Set the port to use to connect to the remote jtag.\n"
330 " if 0 or unset, use unix sockets to connect to the remote jtag.",
331 .usage = "port_number",
332 },
333 {
334 .name = "remote_bitbang_host",
335 .handler = remote_bitbang_handle_remote_bitbang_host_command,
336 .mode = COMMAND_CONFIG,
337 .help = "Set the host to use to connect to the remote jtag.\n"
338 " if port is 0 or unset, this is the name of the unix socket to use.",
339 .usage = "host_name",
340 },
341 COMMAND_REGISTRATION_DONE,
342 };
343
344 struct jtag_interface remote_bitbang_interface = {
345 .name = "remote_bitbang",
346 .execute_queue = &bitbang_execute_queue,
347 .transports = jtag_only,
348 .commands = remote_bitbang_command_handlers,
349 .init = &remote_bitbang_init,
350 .quit = &remote_bitbang_quit,
351 .reset = &remote_bitbang_reset,
352 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)