jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / remote_bitbang.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2011 by Richard Uhler *
5 * ruhler@mit.edu *
6 * *
7 * Copyright (C) 2021 by Manuel Wick <manuel@matronix.de> *
8 ***************************************************************************/
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #ifndef _WIN32
15 #include <sys/un.h>
16 #include <netdb.h>
17 #include <netinet/tcp.h>
18 #endif
19 #include "helper/system.h"
20 #include "helper/replacements.h"
21 #include <jtag/interface.h>
22 #include "bitbang.h"
23
24 /* arbitrary limit on host name length: */
25 #define REMOTE_BITBANG_HOST_MAX 255
26
27 static char *remote_bitbang_host;
28 static char *remote_bitbang_port;
29
30 static int remote_bitbang_fd;
31 static uint8_t remote_bitbang_send_buf[512];
32 static unsigned int remote_bitbang_send_buf_used;
33
34 static bool use_remote_sleep;
35
36 /* Circular buffer. When start == end, the buffer is empty. */
37 static char remote_bitbang_recv_buf[256];
38 static unsigned int remote_bitbang_recv_buf_start;
39 static unsigned int remote_bitbang_recv_buf_end;
40
41 static bool remote_bitbang_recv_buf_full(void)
42 {
43 return remote_bitbang_recv_buf_end ==
44 ((remote_bitbang_recv_buf_start + sizeof(remote_bitbang_recv_buf) - 1) %
45 sizeof(remote_bitbang_recv_buf));
46 }
47
48 static bool remote_bitbang_recv_buf_empty(void)
49 {
50 return remote_bitbang_recv_buf_start == remote_bitbang_recv_buf_end;
51 }
52
53 static unsigned int remote_bitbang_recv_buf_contiguous_available_space(void)
54 {
55 if (remote_bitbang_recv_buf_end >= remote_bitbang_recv_buf_start) {
56 unsigned int space = sizeof(remote_bitbang_recv_buf) -
57 remote_bitbang_recv_buf_end;
58 if (remote_bitbang_recv_buf_start == 0)
59 space -= 1;
60 return space;
61 } else {
62 return remote_bitbang_recv_buf_start -
63 remote_bitbang_recv_buf_end - 1;
64 }
65 }
66
67 static int remote_bitbang_flush(void)
68 {
69 if (remote_bitbang_send_buf_used <= 0)
70 return ERROR_OK;
71
72 unsigned int offset = 0;
73 while (offset < remote_bitbang_send_buf_used) {
74 ssize_t written = write_socket(remote_bitbang_fd, remote_bitbang_send_buf + offset,
75 remote_bitbang_send_buf_used - offset);
76 if (written < 0) {
77 log_socket_error("remote_bitbang_putc");
78 remote_bitbang_send_buf_used = 0;
79 return ERROR_FAIL;
80 }
81 offset += written;
82 }
83 remote_bitbang_send_buf_used = 0;
84 return ERROR_OK;
85 }
86
87 enum block_bool {
88 NO_BLOCK,
89 BLOCK
90 };
91
92 /* Read any incoming data, placing it into the buffer. */
93 static int remote_bitbang_fill_buf(enum block_bool block)
94 {
95 if (remote_bitbang_recv_buf_empty()) {
96 /* If the buffer is empty, reset it to 0 so we get more
97 * contiguous space. */
98 remote_bitbang_recv_buf_start = 0;
99 remote_bitbang_recv_buf_end = 0;
100 }
101
102 if (block == BLOCK) {
103 if (remote_bitbang_flush() != ERROR_OK)
104 return ERROR_FAIL;
105 socket_block(remote_bitbang_fd);
106 }
107
108 bool first = true;
109 while (!remote_bitbang_recv_buf_full()) {
110 unsigned int contiguous_available_space =
111 remote_bitbang_recv_buf_contiguous_available_space();
112 ssize_t count = read_socket(remote_bitbang_fd,
113 remote_bitbang_recv_buf + remote_bitbang_recv_buf_end,
114 contiguous_available_space);
115 if (first && block == BLOCK)
116 socket_nonblock(remote_bitbang_fd);
117 first = false;
118 if (count > 0) {
119 remote_bitbang_recv_buf_end += count;
120 if (remote_bitbang_recv_buf_end == sizeof(remote_bitbang_recv_buf))
121 remote_bitbang_recv_buf_end = 0;
122 } else if (count == 0) {
123 return ERROR_OK;
124 } else if (count < 0) {
125 #ifdef _WIN32
126 if (WSAGetLastError() == WSAEWOULDBLOCK) {
127 #else
128 if (errno == EAGAIN) {
129 #endif
130 return ERROR_OK;
131 } else {
132 log_socket_error("remote_bitbang_fill_buf");
133 return ERROR_FAIL;
134 }
135 }
136 }
137
138 return ERROR_OK;
139 }
140
141 typedef enum {
142 NO_FLUSH,
143 FLUSH_SEND_BUF
144 } flush_bool_t;
145
146 static int remote_bitbang_queue(int c, flush_bool_t flush)
147 {
148 remote_bitbang_send_buf[remote_bitbang_send_buf_used++] = c;
149 if (flush == FLUSH_SEND_BUF ||
150 remote_bitbang_send_buf_used >= ARRAY_SIZE(remote_bitbang_send_buf))
151 return remote_bitbang_flush();
152 return ERROR_OK;
153 }
154
155 static int remote_bitbang_quit(void)
156 {
157 if (remote_bitbang_queue('Q', FLUSH_SEND_BUF) == ERROR_FAIL)
158 return ERROR_FAIL;
159
160 if (close_socket(remote_bitbang_fd) != 0) {
161 log_socket_error("close_socket");
162 return ERROR_FAIL;
163 }
164
165 free(remote_bitbang_host);
166 free(remote_bitbang_port);
167
168 LOG_INFO("remote_bitbang interface quit");
169 return ERROR_OK;
170 }
171
172 static bb_value_t char_to_int(int c)
173 {
174 switch (c) {
175 case '0':
176 return BB_LOW;
177 case '1':
178 return BB_HIGH;
179 default:
180 remote_bitbang_quit();
181 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c, c);
182 return BB_ERROR;
183 }
184 }
185
186 static int remote_bitbang_sample(void)
187 {
188 if (remote_bitbang_fill_buf(NO_BLOCK) != ERROR_OK)
189 return ERROR_FAIL;
190 assert(!remote_bitbang_recv_buf_full());
191 return remote_bitbang_queue('R', NO_FLUSH);
192 }
193
194 static bb_value_t remote_bitbang_read_sample(void)
195 {
196 if (remote_bitbang_recv_buf_empty()) {
197 if (remote_bitbang_fill_buf(BLOCK) != ERROR_OK)
198 return BB_ERROR;
199 }
200 assert(!remote_bitbang_recv_buf_empty());
201 int c = remote_bitbang_recv_buf[remote_bitbang_recv_buf_start];
202 remote_bitbang_recv_buf_start =
203 (remote_bitbang_recv_buf_start + 1) % sizeof(remote_bitbang_recv_buf);
204 return char_to_int(c);
205 }
206
207 static int remote_bitbang_write(int tck, int tms, int tdi)
208 {
209 char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
210 return remote_bitbang_queue(c, NO_FLUSH);
211 }
212
213 static int remote_bitbang_reset(int trst, int srst)
214 {
215 char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0));
216 /* Always flush the send buffer on reset, because the reset call need not be
217 * followed by jtag_execute_queue(). */
218 return remote_bitbang_queue(c, FLUSH_SEND_BUF);
219 }
220
221 static int remote_bitbang_sleep(unsigned int microseconds)
222 {
223 if (!use_remote_sleep) {
224 jtag_sleep(microseconds);
225 return ERROR_OK;
226 }
227
228 int tmp;
229 unsigned int ms = microseconds / 1000;
230 unsigned int us = microseconds % 1000;
231
232 for (unsigned int i = 0; i < ms; i++) {
233 tmp = remote_bitbang_queue('Z', NO_FLUSH);
234 if (tmp != ERROR_OK)
235 return tmp;
236 }
237
238 for (unsigned int i = 0; i < us; i++) {
239 tmp = remote_bitbang_queue('z', NO_FLUSH);
240 if (tmp != ERROR_OK)
241 return tmp;
242 }
243
244 return remote_bitbang_flush();
245 }
246
247 static int remote_bitbang_blink(int on)
248 {
249 char c = on ? 'B' : 'b';
250 return remote_bitbang_queue(c, FLUSH_SEND_BUF);
251 }
252
253 static void remote_bitbang_swdio_drive(bool is_output)
254 {
255 char c = is_output ? 'O' : 'o';
256 if (remote_bitbang_queue(c, FLUSH_SEND_BUF) == ERROR_FAIL)
257 LOG_ERROR("Error setting direction for swdio");
258 }
259
260 static int remote_bitbang_swdio_read(void)
261 {
262 if (remote_bitbang_queue('c', FLUSH_SEND_BUF) != ERROR_FAIL)
263 return remote_bitbang_read_sample();
264 else
265 return BB_ERROR;
266 }
267
268 static int remote_bitbang_swd_write(int swclk, int swdio)
269 {
270 char c = 'd' + ((swclk ? 0x2 : 0x0) | (swdio ? 0x1 : 0x0));
271 return remote_bitbang_queue(c, NO_FLUSH);
272 }
273
274 static struct bitbang_interface remote_bitbang_bitbang = {
275 .buf_size = sizeof(remote_bitbang_recv_buf) - 1,
276 .sample = &remote_bitbang_sample,
277 .read_sample = &remote_bitbang_read_sample,
278 .write = &remote_bitbang_write,
279 .swdio_read = &remote_bitbang_swdio_read,
280 .swdio_drive = &remote_bitbang_swdio_drive,
281 .swd_write = &remote_bitbang_swd_write,
282 .blink = &remote_bitbang_blink,
283 .sleep = &remote_bitbang_sleep,
284 .flush = &remote_bitbang_flush,
285 };
286
287 static int remote_bitbang_init_tcp(void)
288 {
289 struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
290 struct addrinfo *result, *rp;
291 int fd = 0;
292
293 LOG_INFO("Connecting to %s:%s",
294 remote_bitbang_host ? remote_bitbang_host : "localhost",
295 remote_bitbang_port);
296
297 /* Obtain address(es) matching host/port */
298 int s = getaddrinfo(remote_bitbang_host, remote_bitbang_port, &hints, &result);
299 if (s != 0) {
300 LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s));
301 return ERROR_FAIL;
302 }
303
304 /* getaddrinfo() returns a list of address structures.
305 Try each address until we successfully connect(2).
306 If socket(2) (or connect(2)) fails, we (close the socket
307 and) try the next address. */
308
309 for (rp = result; rp ; rp = rp->ai_next) {
310 fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
311 if (fd == -1)
312 continue;
313
314 if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
315 break; /* Success */
316
317 close(fd);
318 }
319
320 /* We work hard to collapse the writes into the minimum number, so when
321 * we write something we want to get it to the other end of the
322 * connection as fast as possible. */
323 int one = 1;
324 /* On Windows optval has to be a const char *. */
325 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&one, sizeof(one));
326
327 freeaddrinfo(result); /* No longer needed */
328
329 if (!rp) { /* No address succeeded */
330 log_socket_error("Failed to connect");
331 return ERROR_FAIL;
332 }
333
334 return fd;
335 }
336
337 static int remote_bitbang_init_unix(void)
338 {
339 if (!remote_bitbang_host) {
340 LOG_ERROR("host/socket not specified");
341 return ERROR_FAIL;
342 }
343
344 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
345 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
346 if (fd < 0) {
347 log_socket_error("socket");
348 return ERROR_FAIL;
349 }
350
351 struct sockaddr_un addr;
352 addr.sun_family = AF_UNIX;
353 strncpy(addr.sun_path, remote_bitbang_host, sizeof(addr.sun_path));
354 addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
355
356 if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
357 log_socket_error("connect");
358 return ERROR_FAIL;
359 }
360
361 return fd;
362 }
363
364 static int remote_bitbang_init(void)
365 {
366 bitbang_interface = &remote_bitbang_bitbang;
367
368 remote_bitbang_recv_buf_start = 0;
369 remote_bitbang_recv_buf_end = 0;
370
371 LOG_INFO("Initializing remote_bitbang driver");
372 if (!remote_bitbang_port)
373 remote_bitbang_fd = remote_bitbang_init_unix();
374 else
375 remote_bitbang_fd = remote_bitbang_init_tcp();
376
377 if (remote_bitbang_fd < 0)
378 return remote_bitbang_fd;
379
380 socket_nonblock(remote_bitbang_fd);
381
382 LOG_INFO("remote_bitbang driver initialized");
383 return ERROR_OK;
384 }
385
386 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command)
387 {
388 if (CMD_ARGC == 1) {
389 uint16_t port;
390 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
391 free(remote_bitbang_port);
392 remote_bitbang_port = port == 0 ? NULL : strdup(CMD_ARGV[0]);
393 return ERROR_OK;
394 }
395 return ERROR_COMMAND_SYNTAX_ERROR;
396 }
397
398 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
399 {
400 if (CMD_ARGC == 1) {
401 free(remote_bitbang_host);
402 remote_bitbang_host = strdup(CMD_ARGV[0]);
403 return ERROR_OK;
404 }
405 return ERROR_COMMAND_SYNTAX_ERROR;
406 }
407
408 static const char * const remote_bitbang_transports[] = { "jtag", "swd", NULL };
409
410 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_use_remote_sleep_command)
411 {
412 if (CMD_ARGC != 1)
413 return ERROR_COMMAND_SYNTAX_ERROR;
414
415 COMMAND_PARSE_ON_OFF(CMD_ARGV[0], use_remote_sleep);
416
417 return ERROR_OK;
418 }
419
420 static const struct command_registration remote_bitbang_subcommand_handlers[] = {
421 {
422 .name = "port",
423 .handler = remote_bitbang_handle_remote_bitbang_port_command,
424 .mode = COMMAND_CONFIG,
425 .help = "Set the port to use to connect to the remote jtag.\n"
426 " if 0 or unset, use unix sockets to connect to the remote jtag.",
427 .usage = "port_number",
428 },
429 {
430 .name = "host",
431 .handler = remote_bitbang_handle_remote_bitbang_host_command,
432 .mode = COMMAND_CONFIG,
433 .help = "Set the host to use to connect to the remote jtag.\n"
434 " if port is 0 or unset, this is the name of the unix socket to use.",
435 .usage = "host_name",
436 },
437 {
438 .name = "use_remote_sleep",
439 .handler = remote_bitbang_handle_remote_bitbang_use_remote_sleep_command,
440 .mode = COMMAND_CONFIG,
441 .help = "Rather than executing sleep locally, include delays in the "
442 "instruction stream for the remote host.",
443 .usage = "(on|off)",
444 },
445 COMMAND_REGISTRATION_DONE
446 };
447
448 static const struct command_registration remote_bitbang_command_handlers[] = {
449 {
450 .name = "remote_bitbang",
451 .mode = COMMAND_ANY,
452 .help = "perform remote_bitbang management",
453 .chain = remote_bitbang_subcommand_handlers,
454 .usage = "",
455 },
456 COMMAND_REGISTRATION_DONE
457 };
458
459 static int remote_bitbang_execute_queue(struct jtag_command *cmd_queue)
460 {
461 /* safety: the send buffer must be empty, no leftover characters from
462 * previous transactions */
463 assert(remote_bitbang_send_buf_used == 0);
464
465 /* process the JTAG command queue */
466 int ret = bitbang_execute_queue(cmd_queue);
467 if (ret != ERROR_OK)
468 return ret;
469
470 /* flush not-yet-sent characters, if any */
471 return remote_bitbang_flush();
472 }
473
474 static struct jtag_interface remote_bitbang_interface = {
475 .execute_queue = &remote_bitbang_execute_queue,
476 };
477
478 struct adapter_driver remote_bitbang_adapter_driver = {
479 .name = "remote_bitbang",
480 .transports = remote_bitbang_transports,
481 .commands = remote_bitbang_command_handlers,
482
483 .init = &remote_bitbang_init,
484 .quit = &remote_bitbang_quit,
485 .reset = &remote_bitbang_reset,
486
487 .jtag_ops = &remote_bitbang_interface,
488 .swd_ops = &bitbang_swd,
489 };

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)