1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2011 by Richard Uhler *
6 ***************************************************************************/
15 #include <netinet/tcp.h>
17 #include "helper/system.h"
18 #include "helper/replacements.h"
19 #include <jtag/interface.h>
22 /* arbitrary limit on host name length: */
23 #define REMOTE_BITBANG_HOST_MAX 255
25 static char *remote_bitbang_host
;
26 static char *remote_bitbang_port
;
28 static int remote_bitbang_fd
;
29 static uint8_t remote_bitbang_send_buf
[512];
30 static unsigned int remote_bitbang_send_buf_used
;
32 /* Circular buffer. When start == end, the buffer is empty. */
33 static char remote_bitbang_recv_buf
[256];
34 static unsigned int remote_bitbang_recv_buf_start
;
35 static unsigned int remote_bitbang_recv_buf_end
;
37 static bool remote_bitbang_recv_buf_full(void)
39 return remote_bitbang_recv_buf_end
==
40 ((remote_bitbang_recv_buf_start
+ sizeof(remote_bitbang_recv_buf
) - 1) %
41 sizeof(remote_bitbang_recv_buf
));
44 static bool remote_bitbang_recv_buf_empty(void)
46 return remote_bitbang_recv_buf_start
== remote_bitbang_recv_buf_end
;
49 static unsigned int remote_bitbang_recv_buf_contiguous_available_space(void)
51 if (remote_bitbang_recv_buf_end
>= remote_bitbang_recv_buf_start
) {
52 unsigned int space
= sizeof(remote_bitbang_recv_buf
) -
53 remote_bitbang_recv_buf_end
;
54 if (remote_bitbang_recv_buf_start
== 0)
58 return remote_bitbang_recv_buf_start
-
59 remote_bitbang_recv_buf_end
- 1;
63 static int remote_bitbang_flush(void)
65 if (remote_bitbang_send_buf_used
<= 0)
68 unsigned int offset
= 0;
69 while (offset
< remote_bitbang_send_buf_used
) {
70 ssize_t written
= write_socket(remote_bitbang_fd
, remote_bitbang_send_buf
+ offset
,
71 remote_bitbang_send_buf_used
- offset
);
73 log_socket_error("remote_bitbang_putc");
74 remote_bitbang_send_buf_used
= 0;
79 remote_bitbang_send_buf_used
= 0;
88 /* Read any incoming data, placing it into the buffer. */
89 static int remote_bitbang_fill_buf(enum block_bool block
)
91 if (remote_bitbang_recv_buf_empty()) {
92 /* If the buffer is empty, reset it to 0 so we get more
93 * contiguous space. */
94 remote_bitbang_recv_buf_start
= 0;
95 remote_bitbang_recv_buf_end
= 0;
99 if (remote_bitbang_flush() != ERROR_OK
)
101 socket_block(remote_bitbang_fd
);
105 while (!remote_bitbang_recv_buf_full()) {
106 unsigned int contiguous_available_space
=
107 remote_bitbang_recv_buf_contiguous_available_space();
108 ssize_t count
= read_socket(remote_bitbang_fd
,
109 remote_bitbang_recv_buf
+ remote_bitbang_recv_buf_end
,
110 contiguous_available_space
);
111 if (first
&& block
== BLOCK
)
112 socket_nonblock(remote_bitbang_fd
);
115 remote_bitbang_recv_buf_end
+= count
;
116 if (remote_bitbang_recv_buf_end
== sizeof(remote_bitbang_recv_buf
))
117 remote_bitbang_recv_buf_end
= 0;
118 } else if (count
== 0) {
120 } else if (count
< 0) {
122 if (WSAGetLastError() == WSAEWOULDBLOCK
) {
124 if (errno
== EAGAIN
) {
128 log_socket_error("remote_bitbang_fill_buf");
142 static int remote_bitbang_queue(int c
, flush_bool_t flush
)
144 remote_bitbang_send_buf
[remote_bitbang_send_buf_used
++] = c
;
145 if (flush
== FLUSH_SEND_BUF
||
146 remote_bitbang_send_buf_used
>= ARRAY_SIZE(remote_bitbang_send_buf
))
147 return remote_bitbang_flush();
151 static int remote_bitbang_quit(void)
153 if (remote_bitbang_queue('Q', FLUSH_SEND_BUF
) == ERROR_FAIL
)
156 if (close_socket(remote_bitbang_fd
) != 0) {
157 log_socket_error("close_socket");
161 free(remote_bitbang_host
);
162 free(remote_bitbang_port
);
164 LOG_INFO("remote_bitbang interface quit");
168 static bb_value_t
char_to_int(int c
)
176 remote_bitbang_quit();
177 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c
, c
);
182 static int remote_bitbang_sample(void)
184 if (remote_bitbang_fill_buf(NO_BLOCK
) != ERROR_OK
)
186 assert(!remote_bitbang_recv_buf_full());
187 return remote_bitbang_queue('R', NO_FLUSH
);
190 static bb_value_t
remote_bitbang_read_sample(void)
192 if (remote_bitbang_recv_buf_empty()) {
193 if (remote_bitbang_fill_buf(BLOCK
) != ERROR_OK
)
196 assert(!remote_bitbang_recv_buf_empty());
197 int c
= remote_bitbang_recv_buf
[remote_bitbang_recv_buf_start
];
198 remote_bitbang_recv_buf_start
=
199 (remote_bitbang_recv_buf_start
+ 1) % sizeof(remote_bitbang_recv_buf
);
200 return char_to_int(c
);
203 static int remote_bitbang_write(int tck
, int tms
, int tdi
)
205 char c
= '0' + ((tck
? 0x4 : 0x0) | (tms
? 0x2 : 0x0) | (tdi
? 0x1 : 0x0));
206 return remote_bitbang_queue(c
, NO_FLUSH
);
209 static int remote_bitbang_reset(int trst
, int srst
)
211 char c
= 'r' + ((trst
? 0x2 : 0x0) | (srst
? 0x1 : 0x0));
212 /* Always flush the send buffer on reset, because the reset call need not be
213 * followed by jtag_execute_queue(). */
214 return remote_bitbang_queue(c
, FLUSH_SEND_BUF
);
217 static int remote_bitbang_blink(int on
)
219 char c
= on
? 'B' : 'b';
220 return remote_bitbang_queue(c
, FLUSH_SEND_BUF
);
223 static struct bitbang_interface remote_bitbang_bitbang
= {
224 .buf_size
= sizeof(remote_bitbang_recv_buf
) - 1,
225 .sample
= &remote_bitbang_sample
,
226 .read_sample
= &remote_bitbang_read_sample
,
227 .write
= &remote_bitbang_write
,
228 .blink
= &remote_bitbang_blink
,
231 static int remote_bitbang_init_tcp(void)
233 struct addrinfo hints
= { .ai_family
= AF_UNSPEC
, .ai_socktype
= SOCK_STREAM
};
234 struct addrinfo
*result
, *rp
;
237 LOG_INFO("Connecting to %s:%s",
238 remote_bitbang_host
? remote_bitbang_host
: "localhost",
239 remote_bitbang_port
);
241 /* Obtain address(es) matching host/port */
242 int s
= getaddrinfo(remote_bitbang_host
, remote_bitbang_port
, &hints
, &result
);
244 LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s
));
248 /* getaddrinfo() returns a list of address structures.
249 Try each address until we successfully connect(2).
250 If socket(2) (or connect(2)) fails, we (close the socket
251 and) try the next address. */
253 for (rp
= result
; rp
; rp
= rp
->ai_next
) {
254 fd
= socket(rp
->ai_family
, rp
->ai_socktype
, rp
->ai_protocol
);
258 if (connect(fd
, rp
->ai_addr
, rp
->ai_addrlen
) != -1)
264 /* We work hard to collapse the writes into the minimum number, so when
265 * we write something we want to get it to the other end of the
266 * connection as fast as possible. */
268 /* On Windows optval has to be a const char *. */
269 setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, (const char *)&one
, sizeof(one
));
271 freeaddrinfo(result
); /* No longer needed */
273 if (!rp
) { /* No address succeeded */
274 log_socket_error("Failed to connect");
281 static int remote_bitbang_init_unix(void)
283 if (!remote_bitbang_host
) {
284 LOG_ERROR("host/socket not specified");
288 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host
);
289 int fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
291 log_socket_error("socket");
295 struct sockaddr_un addr
;
296 addr
.sun_family
= AF_UNIX
;
297 strncpy(addr
.sun_path
, remote_bitbang_host
, sizeof(addr
.sun_path
));
298 addr
.sun_path
[sizeof(addr
.sun_path
)-1] = '\0';
300 if (connect(fd
, (struct sockaddr
*)&addr
, sizeof(struct sockaddr_un
)) < 0) {
301 log_socket_error("connect");
308 static int remote_bitbang_init(void)
310 bitbang_interface
= &remote_bitbang_bitbang
;
312 remote_bitbang_recv_buf_start
= 0;
313 remote_bitbang_recv_buf_end
= 0;
315 LOG_INFO("Initializing remote_bitbang driver");
316 if (!remote_bitbang_port
)
317 remote_bitbang_fd
= remote_bitbang_init_unix();
319 remote_bitbang_fd
= remote_bitbang_init_tcp();
321 if (remote_bitbang_fd
< 0)
322 return remote_bitbang_fd
;
324 socket_nonblock(remote_bitbang_fd
);
326 LOG_INFO("remote_bitbang driver initialized");
330 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command
)
334 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
335 free(remote_bitbang_port
);
336 remote_bitbang_port
= port
== 0 ? NULL
: strdup(CMD_ARGV
[0]);
339 return ERROR_COMMAND_SYNTAX_ERROR
;
342 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command
)
345 free(remote_bitbang_host
);
346 remote_bitbang_host
= strdup(CMD_ARGV
[0]);
349 return ERROR_COMMAND_SYNTAX_ERROR
;
352 static const struct command_registration remote_bitbang_subcommand_handlers
[] = {
355 .handler
= remote_bitbang_handle_remote_bitbang_port_command
,
356 .mode
= COMMAND_CONFIG
,
357 .help
= "Set the port to use to connect to the remote jtag.\n"
358 " if 0 or unset, use unix sockets to connect to the remote jtag.",
359 .usage
= "port_number",
363 .handler
= remote_bitbang_handle_remote_bitbang_host_command
,
364 .mode
= COMMAND_CONFIG
,
365 .help
= "Set the host to use to connect to the remote jtag.\n"
366 " if port is 0 or unset, this is the name of the unix socket to use.",
367 .usage
= "host_name",
369 COMMAND_REGISTRATION_DONE
,
372 static const struct command_registration remote_bitbang_command_handlers
[] = {
374 .name
= "remote_bitbang",
376 .help
= "perform remote_bitbang management",
377 .chain
= remote_bitbang_subcommand_handlers
,
380 COMMAND_REGISTRATION_DONE
383 static int remote_bitbang_execute_queue(void)
385 /* safety: the send buffer must be empty, no leftover characters from
386 * previous transactions */
387 assert(remote_bitbang_send_buf_used
== 0);
389 /* process the JTAG command queue */
390 int ret
= bitbang_execute_queue();
394 /* flush not-yet-sent characters, if any */
395 return remote_bitbang_flush();
398 static struct jtag_interface remote_bitbang_interface
= {
399 .execute_queue
= &remote_bitbang_execute_queue
,
402 struct adapter_driver remote_bitbang_adapter_driver
= {
403 .name
= "remote_bitbang",
404 .transports
= jtag_only
,
405 .commands
= remote_bitbang_command_handlers
,
407 .init
= &remote_bitbang_init
,
408 .quit
= &remote_bitbang_quit
,
409 .reset
= &remote_bitbang_reset
,
411 .jtag_ops
= &remote_bitbang_interface
,
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)