1 /***************************************************************************
2 * Copyright (C) 2011 by Richard Uhler *
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. *
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. *
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 ***************************************************************************/
26 #include <netinet/tcp.h>
28 #include "helper/system.h"
29 #include "helper/replacements.h"
30 #include <jtag/interface.h>
33 /* arbitrary limit on host name length: */
34 #define REMOTE_BITBANG_HOST_MAX 255
36 static char *remote_bitbang_host
;
37 static char *remote_bitbang_port
;
39 static int remote_bitbang_fd
;
40 static uint8_t remote_bitbang_send_buf
[512];
41 static unsigned int remote_bitbang_send_buf_used
;
43 /* Circular buffer. When start == end, the buffer is empty. */
44 static char remote_bitbang_recv_buf
[256];
45 static unsigned int remote_bitbang_recv_buf_start
;
46 static unsigned int remote_bitbang_recv_buf_end
;
48 static bool remote_bitbang_recv_buf_full(void)
50 return remote_bitbang_recv_buf_end
==
51 ((remote_bitbang_recv_buf_start
+ sizeof(remote_bitbang_recv_buf
) - 1) %
52 sizeof(remote_bitbang_recv_buf
));
55 static bool remote_bitbang_recv_buf_empty(void)
57 return remote_bitbang_recv_buf_start
== remote_bitbang_recv_buf_end
;
60 static unsigned int remote_bitbang_recv_buf_contiguous_available_space(void)
62 if (remote_bitbang_recv_buf_end
>= remote_bitbang_recv_buf_start
) {
63 unsigned int space
= sizeof(remote_bitbang_recv_buf
) -
64 remote_bitbang_recv_buf_end
;
65 if (remote_bitbang_recv_buf_start
== 0)
69 return remote_bitbang_recv_buf_start
-
70 remote_bitbang_recv_buf_end
- 1;
74 static int remote_bitbang_flush(void)
76 if (remote_bitbang_send_buf_used
<= 0)
79 unsigned int offset
= 0;
80 while (offset
< remote_bitbang_send_buf_used
) {
81 ssize_t written
= write_socket(remote_bitbang_fd
, remote_bitbang_send_buf
+ offset
,
82 remote_bitbang_send_buf_used
- offset
);
84 log_socket_error("remote_bitbang_putc");
85 remote_bitbang_send_buf_used
= 0;
90 remote_bitbang_send_buf_used
= 0;
99 /* Read any incoming data, placing it into the buffer. */
100 static int remote_bitbang_fill_buf(enum block_bool block
)
102 if (remote_bitbang_recv_buf_empty()) {
103 /* If the buffer is empty, reset it to 0 so we get more
104 * contiguous space. */
105 remote_bitbang_recv_buf_start
= 0;
106 remote_bitbang_recv_buf_end
= 0;
109 if (block
== BLOCK
) {
110 if (remote_bitbang_flush() != ERROR_OK
)
112 socket_block(remote_bitbang_fd
);
116 while (!remote_bitbang_recv_buf_full()) {
117 unsigned int contiguous_available_space
=
118 remote_bitbang_recv_buf_contiguous_available_space();
119 ssize_t count
= read_socket(remote_bitbang_fd
,
120 remote_bitbang_recv_buf
+ remote_bitbang_recv_buf_end
,
121 contiguous_available_space
);
122 if (first
&& block
== BLOCK
)
123 socket_nonblock(remote_bitbang_fd
);
126 remote_bitbang_recv_buf_end
+= count
;
127 if (remote_bitbang_recv_buf_end
== sizeof(remote_bitbang_recv_buf
))
128 remote_bitbang_recv_buf_end
= 0;
129 } else if (count
== 0) {
131 } else if (count
< 0) {
133 if (WSAGetLastError() == WSAEWOULDBLOCK
) {
135 if (errno
== EAGAIN
) {
139 log_socket_error("remote_bitbang_fill_buf");
153 static int remote_bitbang_queue(int c
, flush_bool_t flush
)
155 remote_bitbang_send_buf
[remote_bitbang_send_buf_used
++] = c
;
156 if (flush
== FLUSH_SEND_BUF
||
157 remote_bitbang_send_buf_used
>= ARRAY_SIZE(remote_bitbang_send_buf
))
158 return remote_bitbang_flush();
162 static int remote_bitbang_quit(void)
164 if (remote_bitbang_queue('Q', FLUSH_SEND_BUF
) == ERROR_FAIL
)
167 if (close_socket(remote_bitbang_fd
) != 0) {
168 log_socket_error("close_socket");
172 free(remote_bitbang_host
);
173 free(remote_bitbang_port
);
175 LOG_INFO("remote_bitbang interface quit");
179 static bb_value_t
char_to_int(int c
)
187 remote_bitbang_quit();
188 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c
, c
);
193 static int remote_bitbang_sample(void)
195 if (remote_bitbang_fill_buf(NO_BLOCK
) != ERROR_OK
)
197 assert(!remote_bitbang_recv_buf_full());
198 return remote_bitbang_queue('R', NO_FLUSH
);
201 static bb_value_t
remote_bitbang_read_sample(void)
203 if (remote_bitbang_recv_buf_empty()) {
204 if (remote_bitbang_fill_buf(BLOCK
) != ERROR_OK
)
207 assert(!remote_bitbang_recv_buf_empty());
208 int c
= remote_bitbang_recv_buf
[remote_bitbang_recv_buf_start
];
209 remote_bitbang_recv_buf_start
=
210 (remote_bitbang_recv_buf_start
+ 1) % sizeof(remote_bitbang_recv_buf
);
211 return char_to_int(c
);
214 static int remote_bitbang_write(int tck
, int tms
, int tdi
)
216 char c
= '0' + ((tck
? 0x4 : 0x0) | (tms
? 0x2 : 0x0) | (tdi
? 0x1 : 0x0));
217 return remote_bitbang_queue(c
, NO_FLUSH
);
220 static int remote_bitbang_reset(int trst
, int srst
)
222 char c
= 'r' + ((trst
? 0x2 : 0x0) | (srst
? 0x1 : 0x0));
223 /* Always flush the send buffer on reset, because the reset call need not be
224 * followed by jtag_execute_queue(). */
225 return remote_bitbang_queue(c
, FLUSH_SEND_BUF
);
228 static int remote_bitbang_blink(int on
)
230 char c
= on
? 'B' : 'b';
231 return remote_bitbang_queue(c
, FLUSH_SEND_BUF
);
234 static struct bitbang_interface remote_bitbang_bitbang
= {
235 .buf_size
= sizeof(remote_bitbang_recv_buf
) - 1,
236 .sample
= &remote_bitbang_sample
,
237 .read_sample
= &remote_bitbang_read_sample
,
238 .write
= &remote_bitbang_write
,
239 .blink
= &remote_bitbang_blink
,
242 static int remote_bitbang_init_tcp(void)
244 struct addrinfo hints
= { .ai_family
= AF_UNSPEC
, .ai_socktype
= SOCK_STREAM
};
245 struct addrinfo
*result
, *rp
;
248 LOG_INFO("Connecting to %s:%s",
249 remote_bitbang_host
? remote_bitbang_host
: "localhost",
250 remote_bitbang_port
);
252 /* Obtain address(es) matching host/port */
253 int s
= getaddrinfo(remote_bitbang_host
, remote_bitbang_port
, &hints
, &result
);
255 LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s
));
259 /* getaddrinfo() returns a list of address structures.
260 Try each address until we successfully connect(2).
261 If socket(2) (or connect(2)) fails, we (close the socket
262 and) try the next address. */
264 for (rp
= result
; rp
; rp
= rp
->ai_next
) {
265 fd
= socket(rp
->ai_family
, rp
->ai_socktype
, rp
->ai_protocol
);
269 if (connect(fd
, rp
->ai_addr
, rp
->ai_addrlen
) != -1)
275 /* We work hard to collapse the writes into the minimum number, so when
276 * we write something we want to get it to the other end of the
277 * connection as fast as possible. */
279 /* On Windows optval has to be a const char *. */
280 setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, (const char *)&one
, sizeof(one
));
282 freeaddrinfo(result
); /* No longer needed */
284 if (!rp
) { /* No address succeeded */
285 log_socket_error("Failed to connect");
292 static int remote_bitbang_init_unix(void)
294 if (!remote_bitbang_host
) {
295 LOG_ERROR("host/socket not specified");
299 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host
);
300 int fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
302 log_socket_error("socket");
306 struct sockaddr_un addr
;
307 addr
.sun_family
= AF_UNIX
;
308 strncpy(addr
.sun_path
, remote_bitbang_host
, sizeof(addr
.sun_path
));
309 addr
.sun_path
[sizeof(addr
.sun_path
)-1] = '\0';
311 if (connect(fd
, (struct sockaddr
*)&addr
, sizeof(struct sockaddr_un
)) < 0) {
312 log_socket_error("connect");
319 static int remote_bitbang_init(void)
321 bitbang_interface
= &remote_bitbang_bitbang
;
323 remote_bitbang_recv_buf_start
= 0;
324 remote_bitbang_recv_buf_end
= 0;
326 LOG_INFO("Initializing remote_bitbang driver");
327 if (!remote_bitbang_port
)
328 remote_bitbang_fd
= remote_bitbang_init_unix();
330 remote_bitbang_fd
= remote_bitbang_init_tcp();
332 if (remote_bitbang_fd
< 0)
333 return remote_bitbang_fd
;
335 socket_nonblock(remote_bitbang_fd
);
337 LOG_INFO("remote_bitbang driver initialized");
341 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command
)
345 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
346 free(remote_bitbang_port
);
347 remote_bitbang_port
= port
== 0 ? NULL
: strdup(CMD_ARGV
[0]);
350 return ERROR_COMMAND_SYNTAX_ERROR
;
353 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command
)
356 free(remote_bitbang_host
);
357 remote_bitbang_host
= strdup(CMD_ARGV
[0]);
360 return ERROR_COMMAND_SYNTAX_ERROR
;
363 static const struct command_registration remote_bitbang_subcommand_handlers
[] = {
366 .handler
= remote_bitbang_handle_remote_bitbang_port_command
,
367 .mode
= COMMAND_CONFIG
,
368 .help
= "Set the port to use to connect to the remote jtag.\n"
369 " if 0 or unset, use unix sockets to connect to the remote jtag.",
370 .usage
= "port_number",
374 .handler
= remote_bitbang_handle_remote_bitbang_host_command
,
375 .mode
= COMMAND_CONFIG
,
376 .help
= "Set the host to use to connect to the remote jtag.\n"
377 " if port is 0 or unset, this is the name of the unix socket to use.",
378 .usage
= "host_name",
380 COMMAND_REGISTRATION_DONE
,
383 static const struct command_registration remote_bitbang_command_handlers
[] = {
385 .name
= "remote_bitbang",
387 .help
= "perform remote_bitbang management",
388 .chain
= remote_bitbang_subcommand_handlers
,
391 COMMAND_REGISTRATION_DONE
394 static int remote_bitbang_execute_queue(void)
396 /* safety: the send buffer must be empty, no leftover characters from
397 * previous transactions */
398 assert(remote_bitbang_send_buf_used
== 0);
400 /* process the JTAG command queue */
401 int ret
= bitbang_execute_queue();
405 /* flush not-yet-sent characters, if any */
406 return remote_bitbang_flush();
409 static struct jtag_interface remote_bitbang_interface
= {
410 .execute_queue
= &remote_bitbang_execute_queue
,
413 struct adapter_driver remote_bitbang_adapter_driver
= {
414 .name
= "remote_bitbang",
415 .transports
= jtag_only
,
416 .commands
= remote_bitbang_command_handlers
,
418 .init
= &remote_bitbang_init
,
419 .quit
= &remote_bitbang_quit
,
420 .reset
= &remote_bitbang_reset
,
422 .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)