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 <jtag/interface.h>
30 /* arbitrary limit on host name length: */
31 #define REMOTE_BITBANG_HOST_MAX 255
33 static char *remote_bitbang_host
;
34 static char *remote_bitbang_port
;
36 static FILE *remote_bitbang_file
;
37 static int remote_bitbang_fd
;
39 /* Circular buffer. When start == end, the buffer is empty. */
40 static char remote_bitbang_buf
[64];
41 static unsigned remote_bitbang_start
;
42 static unsigned remote_bitbang_end
;
44 static int remote_bitbang_buf_full(void)
46 return remote_bitbang_end
==
47 ((remote_bitbang_start
+ sizeof(remote_bitbang_buf
) - 1) %
48 sizeof(remote_bitbang_buf
));
51 /* Read any incoming data, placing it into the buffer. */
52 static int remote_bitbang_fill_buf(void)
54 socket_nonblock(remote_bitbang_fd
);
55 while (!remote_bitbang_buf_full()) {
56 unsigned contiguous_available_space
;
57 if (remote_bitbang_end
>= remote_bitbang_start
) {
58 contiguous_available_space
= sizeof(remote_bitbang_buf
) -
60 if (remote_bitbang_start
== 0)
61 contiguous_available_space
-= 1;
63 contiguous_available_space
= remote_bitbang_start
-
64 remote_bitbang_end
- 1;
66 ssize_t count
= read(remote_bitbang_fd
,
67 remote_bitbang_buf
+ remote_bitbang_end
,
68 contiguous_available_space
);
70 remote_bitbang_end
+= count
;
71 if (remote_bitbang_end
== sizeof(remote_bitbang_buf
))
72 remote_bitbang_end
= 0;
73 } else if (count
== 0) {
75 } else if (count
< 0) {
76 if (errno
== EAGAIN
) {
79 LOG_ERROR("remote_bitbang_fill_buf: %s (%d)",
80 strerror(errno
), errno
);
89 static int remote_bitbang_putc(int c
)
91 if (EOF
== fputc(c
, remote_bitbang_file
)) {
92 LOG_ERROR("remote_bitbang_putc: %s", strerror(errno
));
98 static int remote_bitbang_quit(void)
100 if (EOF
== fputc('Q', remote_bitbang_file
)) {
101 LOG_ERROR("fputs: %s", strerror(errno
));
105 if (EOF
== fflush(remote_bitbang_file
)) {
106 LOG_ERROR("fflush: %s", strerror(errno
));
110 /* We only need to close one of the FILE*s, because they both use the same */
111 /* underlying file descriptor. */
112 if (EOF
== fclose(remote_bitbang_file
)) {
113 LOG_ERROR("fclose: %s", strerror(errno
));
117 free(remote_bitbang_host
);
118 free(remote_bitbang_port
);
120 LOG_INFO("remote_bitbang interface quit");
124 static bb_value_t
char_to_int(int c
)
132 remote_bitbang_quit();
133 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c
, c
);
138 /* Get the next read response. */
139 static bb_value_t
remote_bitbang_rread(void)
141 if (EOF
== fflush(remote_bitbang_file
)) {
142 remote_bitbang_quit();
143 LOG_ERROR("fflush: %s", strerror(errno
));
147 /* Enable blocking access. */
148 socket_block(remote_bitbang_fd
);
150 ssize_t count
= read(remote_bitbang_fd
, &c
, 1);
152 return char_to_int(c
);
154 remote_bitbang_quit();
155 LOG_ERROR("read: count=%d, error=%s", (int) count
, strerror(errno
));
160 static int remote_bitbang_sample(void)
162 if (remote_bitbang_fill_buf() != ERROR_OK
)
164 assert(!remote_bitbang_buf_full());
165 return remote_bitbang_putc('R');
168 static bb_value_t
remote_bitbang_read_sample(void)
170 if (remote_bitbang_start
!= remote_bitbang_end
) {
171 int c
= remote_bitbang_buf
[remote_bitbang_start
];
172 remote_bitbang_start
=
173 (remote_bitbang_start
+ 1) % sizeof(remote_bitbang_buf
);
174 return char_to_int(c
);
176 return remote_bitbang_rread();
179 static int remote_bitbang_write(int tck
, int tms
, int tdi
)
181 char c
= '0' + ((tck
? 0x4 : 0x0) | (tms
? 0x2 : 0x0) | (tdi
? 0x1 : 0x0));
182 return remote_bitbang_putc(c
);
185 static int remote_bitbang_reset(int trst
, int srst
)
187 char c
= 'r' + ((trst
? 0x2 : 0x0) | (srst
? 0x1 : 0x0));
188 return remote_bitbang_putc(c
);
191 static int remote_bitbang_blink(int on
)
193 char c
= on
? 'B' : 'b';
194 return remote_bitbang_putc(c
);
197 static struct bitbang_interface remote_bitbang_bitbang
= {
198 .buf_size
= sizeof(remote_bitbang_buf
) - 1,
199 .sample
= &remote_bitbang_sample
,
200 .read_sample
= &remote_bitbang_read_sample
,
201 .write
= &remote_bitbang_write
,
202 .reset
= &remote_bitbang_reset
,
203 .blink
= &remote_bitbang_blink
,
206 static int remote_bitbang_init_tcp(void)
208 struct addrinfo hints
= { .ai_family
= AF_UNSPEC
, .ai_socktype
= SOCK_STREAM
};
209 struct addrinfo
*result
, *rp
;
212 LOG_INFO("Connecting to %s:%s",
213 remote_bitbang_host
? remote_bitbang_host
: "localhost",
214 remote_bitbang_port
);
216 /* Obtain address(es) matching host/port */
217 int s
= getaddrinfo(remote_bitbang_host
, remote_bitbang_port
, &hints
, &result
);
219 LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s
));
223 /* getaddrinfo() returns a list of address structures.
224 Try each address until we successfully connect(2).
225 If socket(2) (or connect(2)) fails, we (close the socket
226 and) try the next address. */
228 for (rp
= result
; rp
!= NULL
; rp
= rp
->ai_next
) {
229 fd
= socket(rp
->ai_family
, rp
->ai_socktype
, rp
->ai_protocol
);
233 if (connect(fd
, rp
->ai_addr
, rp
->ai_addrlen
) != -1)
239 freeaddrinfo(result
); /* No longer needed */
241 if (rp
== NULL
) { /* No address succeeded */
242 LOG_ERROR("Failed to connect: %s", strerror(errno
));
249 static int remote_bitbang_init_unix(void)
251 if (remote_bitbang_host
== NULL
) {
252 LOG_ERROR("host/socket not specified");
256 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host
);
257 int fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
259 LOG_ERROR("socket: %s", strerror(errno
));
263 struct sockaddr_un addr
;
264 addr
.sun_family
= AF_UNIX
;
265 strncpy(addr
.sun_path
, remote_bitbang_host
, sizeof(addr
.sun_path
));
266 addr
.sun_path
[sizeof(addr
.sun_path
)-1] = '\0';
268 if (connect(fd
, (struct sockaddr
*)&addr
, sizeof(struct sockaddr_un
)) < 0) {
269 LOG_ERROR("connect: %s", strerror(errno
));
276 static int remote_bitbang_init(void)
278 bitbang_interface
= &remote_bitbang_bitbang
;
280 remote_bitbang_start
= 0;
281 remote_bitbang_end
= 0;
283 LOG_INFO("Initializing remote_bitbang driver");
284 if (remote_bitbang_port
== NULL
)
285 remote_bitbang_fd
= remote_bitbang_init_unix();
287 remote_bitbang_fd
= remote_bitbang_init_tcp();
289 if (remote_bitbang_fd
< 0)
290 return remote_bitbang_fd
;
292 remote_bitbang_file
= fdopen(remote_bitbang_fd
, "w+");
293 if (remote_bitbang_file
== NULL
) {
294 LOG_ERROR("fdopen: failed to open write stream");
295 close(remote_bitbang_fd
);
299 LOG_INFO("remote_bitbang driver initialized");
303 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command
)
307 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
308 free(remote_bitbang_port
);
309 remote_bitbang_port
= port
== 0 ? NULL
: strdup(CMD_ARGV
[0]);
312 return ERROR_COMMAND_SYNTAX_ERROR
;
315 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command
)
318 free(remote_bitbang_host
);
319 remote_bitbang_host
= strdup(CMD_ARGV
[0]);
322 return ERROR_COMMAND_SYNTAX_ERROR
;
325 static const struct command_registration remote_bitbang_command_handlers
[] = {
327 .name
= "remote_bitbang_port",
328 .handler
= remote_bitbang_handle_remote_bitbang_port_command
,
329 .mode
= COMMAND_CONFIG
,
330 .help
= "Set the port to use to connect to the remote jtag.\n"
331 " if 0 or unset, use unix sockets to connect to the remote jtag.",
332 .usage
= "port_number",
335 .name
= "remote_bitbang_host",
336 .handler
= remote_bitbang_handle_remote_bitbang_host_command
,
337 .mode
= COMMAND_CONFIG
,
338 .help
= "Set the host to use to connect to the remote jtag.\n"
339 " if port is 0 or unset, this is the name of the unix socket to use.",
340 .usage
= "host_name",
342 COMMAND_REGISTRATION_DONE
,
345 struct jtag_interface remote_bitbang_interface
= {
346 .name
= "remote_bitbang",
347 .execute_queue
= &bitbang_execute_queue
,
348 .transports
= jtag_only
,
349 .commands
= remote_bitbang_command_handlers
,
350 .init
= &remote_bitbang_init
,
351 .quit
= &remote_bitbang_quit
,
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)