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 ***************************************************************************/
27 #include "helper/system.h"
28 #include "helper/replacements.h"
29 #include <jtag/interface.h>
32 /* arbitrary limit on host name length: */
33 #define REMOTE_BITBANG_HOST_MAX 255
35 static char *remote_bitbang_host
;
36 static char *remote_bitbang_port
;
38 static int remote_bitbang_fd
;
39 static uint8_t remote_bitbang_send_buf
[512];
40 static unsigned int remote_bitbang_send_buf_used
;
42 /* Circular buffer. When start == end, the buffer is empty. */
43 static char remote_bitbang_recv_buf
[64];
44 static unsigned int remote_bitbang_recv_buf_start
;
45 static unsigned int remote_bitbang_recv_buf_end
;
47 static bool remote_bitbang_buf_full(void)
49 return remote_bitbang_recv_buf_end
==
50 ((remote_bitbang_recv_buf_start
+ sizeof(remote_bitbang_recv_buf
) - 1) %
51 sizeof(remote_bitbang_recv_buf
));
54 /* Read any incoming data, placing it into the buffer. */
55 static int remote_bitbang_fill_buf(void)
57 socket_nonblock(remote_bitbang_fd
);
58 while (!remote_bitbang_buf_full()) {
59 unsigned int contiguous_available_space
;
60 if (remote_bitbang_recv_buf_end
>= remote_bitbang_recv_buf_start
) {
61 contiguous_available_space
= sizeof(remote_bitbang_recv_buf
) -
62 remote_bitbang_recv_buf_end
;
63 if (remote_bitbang_recv_buf_start
== 0)
64 contiguous_available_space
-= 1;
66 contiguous_available_space
= remote_bitbang_recv_buf_start
-
67 remote_bitbang_recv_buf_end
- 1;
69 ssize_t count
= read_socket(remote_bitbang_fd
,
70 remote_bitbang_recv_buf
+ remote_bitbang_recv_buf_end
,
71 contiguous_available_space
);
73 remote_bitbang_recv_buf_end
+= count
;
74 if (remote_bitbang_recv_buf_end
== sizeof(remote_bitbang_recv_buf
))
75 remote_bitbang_recv_buf_end
= 0;
76 } else if (count
== 0) {
78 } else if (count
< 0) {
80 if (WSAGetLastError() == WSAEWOULDBLOCK
) {
82 if (errno
== EAGAIN
) {
86 log_socket_error("remote_bitbang_fill_buf");
95 static int remote_bitbang_flush(void)
97 if (remote_bitbang_send_buf_used
<= 0)
100 unsigned int offset
= 0;
101 while (offset
< remote_bitbang_send_buf_used
) {
102 ssize_t written
= write_socket(remote_bitbang_fd
, remote_bitbang_send_buf
+ offset
,
103 remote_bitbang_send_buf_used
- offset
);
105 log_socket_error("remote_bitbang_putc");
106 remote_bitbang_send_buf_used
= 0;
111 remote_bitbang_send_buf_used
= 0;
120 static int remote_bitbang_queue(int c
, flush_bool_t flush
)
122 remote_bitbang_send_buf
[remote_bitbang_send_buf_used
++] = c
;
123 if (flush
== FLUSH_SEND_BUF
||
124 remote_bitbang_send_buf_used
>= ARRAY_SIZE(remote_bitbang_send_buf
))
125 return remote_bitbang_flush();
129 static int remote_bitbang_quit(void)
131 if (remote_bitbang_queue('Q', FLUSH_SEND_BUF
) == ERROR_FAIL
)
134 if (close_socket(remote_bitbang_fd
) != 0) {
135 log_socket_error("close_socket");
139 free(remote_bitbang_host
);
140 free(remote_bitbang_port
);
142 LOG_INFO("remote_bitbang interface quit");
146 static bb_value_t
char_to_int(int c
)
154 remote_bitbang_quit();
155 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c
, c
);
160 /* Get the next read response. */
161 static bb_value_t
remote_bitbang_rread(void)
163 if (remote_bitbang_flush() != ERROR_OK
)
166 /* Enable blocking access. */
167 socket_block(remote_bitbang_fd
);
169 ssize_t count
= read_socket(remote_bitbang_fd
, &c
, 1);
171 return char_to_int(c
);
173 remote_bitbang_quit();
174 LOG_ERROR("read_socket: count=%d", (int) count
);
175 log_socket_error("read_socket");
180 static int remote_bitbang_sample(void)
182 if (remote_bitbang_fill_buf() != ERROR_OK
)
184 assert(!remote_bitbang_buf_full());
185 return remote_bitbang_queue('R', NO_FLUSH
);
188 static bb_value_t
remote_bitbang_read_sample(void)
190 if (remote_bitbang_recv_buf_start
== remote_bitbang_recv_buf_end
) {
191 if (remote_bitbang_fill_buf() != ERROR_OK
)
194 if (remote_bitbang_recv_buf_start
!= remote_bitbang_recv_buf_end
) {
195 int c
= remote_bitbang_recv_buf
[remote_bitbang_recv_buf_start
];
196 remote_bitbang_recv_buf_start
=
197 (remote_bitbang_recv_buf_start
+ 1) % sizeof(remote_bitbang_recv_buf
);
198 return char_to_int(c
);
200 return remote_bitbang_rread();
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 freeaddrinfo(result
); /* No longer needed */
266 if (!rp
) { /* No address succeeded */
267 log_socket_error("Failed to connect");
274 static int remote_bitbang_init_unix(void)
276 if (!remote_bitbang_host
) {
277 LOG_ERROR("host/socket not specified");
281 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host
);
282 int fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
284 log_socket_error("socket");
288 struct sockaddr_un addr
;
289 addr
.sun_family
= AF_UNIX
;
290 strncpy(addr
.sun_path
, remote_bitbang_host
, sizeof(addr
.sun_path
));
291 addr
.sun_path
[sizeof(addr
.sun_path
)-1] = '\0';
293 if (connect(fd
, (struct sockaddr
*)&addr
, sizeof(struct sockaddr_un
)) < 0) {
294 log_socket_error("connect");
301 static int remote_bitbang_init(void)
303 bitbang_interface
= &remote_bitbang_bitbang
;
305 remote_bitbang_recv_buf_start
= 0;
306 remote_bitbang_recv_buf_end
= 0;
308 LOG_INFO("Initializing remote_bitbang driver");
309 if (!remote_bitbang_port
)
310 remote_bitbang_fd
= remote_bitbang_init_unix();
312 remote_bitbang_fd
= remote_bitbang_init_tcp();
314 if (remote_bitbang_fd
< 0)
315 return remote_bitbang_fd
;
317 LOG_INFO("remote_bitbang driver initialized");
321 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command
)
325 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
326 free(remote_bitbang_port
);
327 remote_bitbang_port
= port
== 0 ? NULL
: strdup(CMD_ARGV
[0]);
330 return ERROR_COMMAND_SYNTAX_ERROR
;
333 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command
)
336 free(remote_bitbang_host
);
337 remote_bitbang_host
= strdup(CMD_ARGV
[0]);
340 return ERROR_COMMAND_SYNTAX_ERROR
;
343 static const struct command_registration remote_bitbang_command_handlers
[] = {
345 .name
= "remote_bitbang_port",
346 .handler
= remote_bitbang_handle_remote_bitbang_port_command
,
347 .mode
= COMMAND_CONFIG
,
348 .help
= "Set the port to use to connect to the remote jtag.\n"
349 " if 0 or unset, use unix sockets to connect to the remote jtag.",
350 .usage
= "port_number",
353 .name
= "remote_bitbang_host",
354 .handler
= remote_bitbang_handle_remote_bitbang_host_command
,
355 .mode
= COMMAND_CONFIG
,
356 .help
= "Set the host to use to connect to the remote jtag.\n"
357 " if port is 0 or unset, this is the name of the unix socket to use.",
358 .usage
= "host_name",
360 COMMAND_REGISTRATION_DONE
,
363 static int remote_bitbang_execute_queue(void)
365 /* safety: the send buffer must be empty, no leftover characters from
366 * previous transactions */
367 assert(remote_bitbang_send_buf_used
== 0);
369 /* process the JTAG command queue */
370 int ret
= bitbang_execute_queue();
374 /* flush not-yet-sent characters, if any */
375 return remote_bitbang_flush();
378 static struct jtag_interface remote_bitbang_interface
= {
379 .execute_queue
= &remote_bitbang_execute_queue
,
382 struct adapter_driver remote_bitbang_adapter_driver
= {
383 .name
= "remote_bitbang",
384 .transports
= jtag_only
,
385 .commands
= remote_bitbang_command_handlers
,
387 .init
= &remote_bitbang_init
,
388 .quit
= &remote_bitbang_quit
,
389 .reset
= &remote_bitbang_reset
,
391 .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)