1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2011 by Richard Uhler *
7 * Copyright (C) 2021 by Manuel Wick <manuel@matronix.de> *
8 ***************************************************************************/
17 #include <netinet/tcp.h>
19 #include "helper/system.h"
20 #include "helper/replacements.h"
21 #include <jtag/interface.h>
24 /* arbitrary limit on host name length: */
25 #define REMOTE_BITBANG_HOST_MAX 255
27 static char *remote_bitbang_host
;
28 static char *remote_bitbang_port
;
30 static int remote_bitbang_fd
;
31 static uint8_t remote_bitbang_send_buf
[512];
32 static unsigned int remote_bitbang_send_buf_used
;
34 static bool use_remote_sleep
;
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
;
41 static bool remote_bitbang_recv_buf_full(void)
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
));
48 static bool remote_bitbang_recv_buf_empty(void)
50 return remote_bitbang_recv_buf_start
== remote_bitbang_recv_buf_end
;
53 static unsigned int remote_bitbang_recv_buf_contiguous_available_space(void)
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)
62 return remote_bitbang_recv_buf_start
-
63 remote_bitbang_recv_buf_end
- 1;
67 static int remote_bitbang_flush(void)
69 if (remote_bitbang_send_buf_used
<= 0)
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
);
77 log_socket_error("remote_bitbang_putc");
78 remote_bitbang_send_buf_used
= 0;
83 remote_bitbang_send_buf_used
= 0;
92 /* Read any incoming data, placing it into the buffer. */
93 static int remote_bitbang_fill_buf(enum block_bool block
)
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;
102 if (block
== BLOCK
) {
103 if (remote_bitbang_flush() != ERROR_OK
)
105 socket_block(remote_bitbang_fd
);
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
);
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) {
124 } else if (count
< 0) {
126 if (WSAGetLastError() == WSAEWOULDBLOCK
) {
128 if (errno
== EAGAIN
) {
132 log_socket_error("remote_bitbang_fill_buf");
146 static int remote_bitbang_queue(int c
, flush_bool_t flush
)
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();
155 static int remote_bitbang_quit(void)
157 if (remote_bitbang_queue('Q', FLUSH_SEND_BUF
) == ERROR_FAIL
)
160 if (close_socket(remote_bitbang_fd
) != 0) {
161 log_socket_error("close_socket");
165 free(remote_bitbang_host
);
166 free(remote_bitbang_port
);
168 LOG_INFO("remote_bitbang interface quit");
172 static bb_value_t
char_to_int(int c
)
180 remote_bitbang_quit();
181 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c
, c
);
186 static int remote_bitbang_sample(void)
188 if (remote_bitbang_fill_buf(NO_BLOCK
) != ERROR_OK
)
190 assert(!remote_bitbang_recv_buf_full());
191 return remote_bitbang_queue('R', NO_FLUSH
);
194 static bb_value_t
remote_bitbang_read_sample(void)
196 if (remote_bitbang_recv_buf_empty()) {
197 if (remote_bitbang_fill_buf(BLOCK
) != ERROR_OK
)
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
);
207 static int remote_bitbang_write(int tck
, int tms
, int tdi
)
209 char c
= '0' + ((tck
? 0x4 : 0x0) | (tms
? 0x2 : 0x0) | (tdi
? 0x1 : 0x0));
210 return remote_bitbang_queue(c
, NO_FLUSH
);
213 static int remote_bitbang_reset(int trst
, int srst
)
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
);
221 static int remote_bitbang_sleep(unsigned int microseconds
)
223 if (!use_remote_sleep
) {
224 jtag_sleep(microseconds
);
229 unsigned int ms
= microseconds
/ 1000;
230 unsigned int us
= microseconds
% 1000;
232 for (unsigned int i
= 0; i
< ms
; i
++) {
233 tmp
= remote_bitbang_queue('D', NO_FLUSH
);
238 for (unsigned int i
= 0; i
< us
; i
++) {
239 tmp
= remote_bitbang_queue('d', NO_FLUSH
);
244 return remote_bitbang_flush();
247 static int remote_bitbang_blink(int on
)
249 char c
= on
? 'B' : 'b';
250 return remote_bitbang_queue(c
, FLUSH_SEND_BUF
);
253 static void remote_bitbang_swdio_drive(bool is_output
)
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");
260 static int remote_bitbang_swdio_read(void)
262 if (remote_bitbang_queue('c', FLUSH_SEND_BUF
) != ERROR_FAIL
)
263 return remote_bitbang_read_sample();
268 static int remote_bitbang_swd_write(int swclk
, int swdio
)
270 char c
= 'd' + ((swclk
? 0x2 : 0x0) | (swdio
? 0x1 : 0x0));
271 return remote_bitbang_queue(c
, NO_FLUSH
);
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
,
286 static int remote_bitbang_init_tcp(void)
288 struct addrinfo hints
= { .ai_family
= AF_UNSPEC
, .ai_socktype
= SOCK_STREAM
};
289 struct addrinfo
*result
, *rp
;
292 LOG_INFO("Connecting to %s:%s",
293 remote_bitbang_host
? remote_bitbang_host
: "localhost",
294 remote_bitbang_port
);
296 /* Obtain address(es) matching host/port */
297 int s
= getaddrinfo(remote_bitbang_host
, remote_bitbang_port
, &hints
, &result
);
299 LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s
));
303 /* getaddrinfo() returns a list of address structures.
304 Try each address until we successfully connect(2).
305 If socket(2) (or connect(2)) fails, we (close the socket
306 and) try the next address. */
308 for (rp
= result
; rp
; rp
= rp
->ai_next
) {
309 fd
= socket(rp
->ai_family
, rp
->ai_socktype
, rp
->ai_protocol
);
313 if (connect(fd
, rp
->ai_addr
, rp
->ai_addrlen
) != -1)
319 /* We work hard to collapse the writes into the minimum number, so when
320 * we write something we want to get it to the other end of the
321 * connection as fast as possible. */
323 /* On Windows optval has to be a const char *. */
324 setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, (const char *)&one
, sizeof(one
));
326 freeaddrinfo(result
); /* No longer needed */
328 if (!rp
) { /* No address succeeded */
329 log_socket_error("Failed to connect");
336 static int remote_bitbang_init_unix(void)
338 if (!remote_bitbang_host
) {
339 LOG_ERROR("host/socket not specified");
343 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host
);
344 int fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
346 log_socket_error("socket");
350 struct sockaddr_un addr
;
351 addr
.sun_family
= AF_UNIX
;
352 strncpy(addr
.sun_path
, remote_bitbang_host
, sizeof(addr
.sun_path
));
353 addr
.sun_path
[sizeof(addr
.sun_path
)-1] = '\0';
355 if (connect(fd
, (struct sockaddr
*)&addr
, sizeof(struct sockaddr_un
)) < 0) {
356 log_socket_error("connect");
363 static int remote_bitbang_init(void)
365 bitbang_interface
= &remote_bitbang_bitbang
;
367 remote_bitbang_recv_buf_start
= 0;
368 remote_bitbang_recv_buf_end
= 0;
370 LOG_INFO("Initializing remote_bitbang driver");
371 if (!remote_bitbang_port
)
372 remote_bitbang_fd
= remote_bitbang_init_unix();
374 remote_bitbang_fd
= remote_bitbang_init_tcp();
376 if (remote_bitbang_fd
< 0)
377 return remote_bitbang_fd
;
379 socket_nonblock(remote_bitbang_fd
);
381 LOG_INFO("remote_bitbang driver initialized");
385 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command
)
389 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
390 free(remote_bitbang_port
);
391 remote_bitbang_port
= port
== 0 ? NULL
: strdup(CMD_ARGV
[0]);
394 return ERROR_COMMAND_SYNTAX_ERROR
;
397 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command
)
400 free(remote_bitbang_host
);
401 remote_bitbang_host
= strdup(CMD_ARGV
[0]);
404 return ERROR_COMMAND_SYNTAX_ERROR
;
407 static const char * const remote_bitbang_transports
[] = { "jtag", "swd", NULL
};
409 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_use_remote_sleep_command
)
412 return ERROR_COMMAND_SYNTAX_ERROR
;
414 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], use_remote_sleep
);
419 static const struct command_registration remote_bitbang_subcommand_handlers
[] = {
422 .handler
= remote_bitbang_handle_remote_bitbang_port_command
,
423 .mode
= COMMAND_CONFIG
,
424 .help
= "Set the port to use to connect to the remote jtag.\n"
425 " if 0 or unset, use unix sockets to connect to the remote jtag.",
426 .usage
= "port_number",
430 .handler
= remote_bitbang_handle_remote_bitbang_host_command
,
431 .mode
= COMMAND_CONFIG
,
432 .help
= "Set the host to use to connect to the remote jtag.\n"
433 " if port is 0 or unset, this is the name of the unix socket to use.",
434 .usage
= "host_name",
437 .name
= "use_remote_sleep",
438 .handler
= remote_bitbang_handle_remote_bitbang_use_remote_sleep_command
,
439 .mode
= COMMAND_CONFIG
,
440 .help
= "Rather than executing sleep locally, include delays in the "
441 "instruction stream for the remote host.",
444 COMMAND_REGISTRATION_DONE
447 static const struct command_registration remote_bitbang_command_handlers
[] = {
449 .name
= "remote_bitbang",
451 .help
= "perform remote_bitbang management",
452 .chain
= remote_bitbang_subcommand_handlers
,
455 COMMAND_REGISTRATION_DONE
458 static int remote_bitbang_execute_queue(void)
460 /* safety: the send buffer must be empty, no leftover characters from
461 * previous transactions */
462 assert(remote_bitbang_send_buf_used
== 0);
464 /* process the JTAG command queue */
465 int ret
= bitbang_execute_queue();
469 /* flush not-yet-sent characters, if any */
470 return remote_bitbang_flush();
473 static struct jtag_interface remote_bitbang_interface
= {
474 .execute_queue
= &remote_bitbang_execute_queue
,
477 struct adapter_driver remote_bitbang_adapter_driver
= {
478 .name
= "remote_bitbang",
479 .transports
= remote_bitbang_transports
,
480 .commands
= remote_bitbang_command_handlers
,
482 .init
= &remote_bitbang_init
,
483 .quit
= &remote_bitbang_quit
,
484 .reset
= &remote_bitbang_reset
,
486 .jtag_ops
= &remote_bitbang_interface
,
487 .swd_ops
= &bitbang_swd
,
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)