openocd: fix SPDX tag format for files .c
[openocd.git] / src / jtag / drivers / remote_bitbang.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2011 by Richard Uhler *
5 * ruhler@mit.edu *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #ifndef _WIN32
13 #include <sys/un.h>
14 #include <netdb.h>
15 #include <netinet/tcp.h>
16 #endif
17 #include "helper/system.h"
18 #include "helper/replacements.h"
19 #include <jtag/interface.h>
20 #include "bitbang.h"
21
22 /* arbitrary limit on host name length: */
23 #define REMOTE_BITBANG_HOST_MAX 255
24
25 static char *remote_bitbang_host;
26 static char *remote_bitbang_port;
27
28 static int remote_bitbang_fd;
29 static uint8_t remote_bitbang_send_buf[512];
30 static unsigned int remote_bitbang_send_buf_used;
31
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;
36
37 static bool remote_bitbang_recv_buf_full(void)
38 {
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));
42 }
43
44 static bool remote_bitbang_recv_buf_empty(void)
45 {
46 return remote_bitbang_recv_buf_start == remote_bitbang_recv_buf_end;
47 }
48
49 static unsigned int remote_bitbang_recv_buf_contiguous_available_space(void)
50 {
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)
55 space -= 1;
56 return space;
57 } else {
58 return remote_bitbang_recv_buf_start -
59 remote_bitbang_recv_buf_end - 1;
60 }
61 }
62
63 static int remote_bitbang_flush(void)
64 {
65 if (remote_bitbang_send_buf_used <= 0)
66 return ERROR_OK;
67
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);
72 if (written < 0) {
73 log_socket_error("remote_bitbang_putc");
74 remote_bitbang_send_buf_used = 0;
75 return ERROR_FAIL;
76 }
77 offset += written;
78 }
79 remote_bitbang_send_buf_used = 0;
80 return ERROR_OK;
81 }
82
83 enum block_bool {
84 NO_BLOCK,
85 BLOCK
86 };
87
88 /* Read any incoming data, placing it into the buffer. */
89 static int remote_bitbang_fill_buf(enum block_bool block)
90 {
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;
96 }
97
98 if (block == BLOCK) {
99 if (remote_bitbang_flush() != ERROR_OK)
100 return ERROR_FAIL;
101 socket_block(remote_bitbang_fd);
102 }
103
104 bool first = true;
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);
113 first = false;
114 if (count > 0) {
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) {
119 return ERROR_OK;
120 } else if (count < 0) {
121 #ifdef _WIN32
122 if (WSAGetLastError() == WSAEWOULDBLOCK) {
123 #else
124 if (errno == EAGAIN) {
125 #endif
126 return ERROR_OK;
127 } else {
128 log_socket_error("remote_bitbang_fill_buf");
129 return ERROR_FAIL;
130 }
131 }
132 }
133
134 return ERROR_OK;
135 }
136
137 typedef enum {
138 NO_FLUSH,
139 FLUSH_SEND_BUF
140 } flush_bool_t;
141
142 static int remote_bitbang_queue(int c, flush_bool_t flush)
143 {
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();
148 return ERROR_OK;
149 }
150
151 static int remote_bitbang_quit(void)
152 {
153 if (remote_bitbang_queue('Q', FLUSH_SEND_BUF) == ERROR_FAIL)
154 return ERROR_FAIL;
155
156 if (close_socket(remote_bitbang_fd) != 0) {
157 log_socket_error("close_socket");
158 return ERROR_FAIL;
159 }
160
161 free(remote_bitbang_host);
162 free(remote_bitbang_port);
163
164 LOG_INFO("remote_bitbang interface quit");
165 return ERROR_OK;
166 }
167
168 static bb_value_t char_to_int(int c)
169 {
170 switch (c) {
171 case '0':
172 return BB_LOW;
173 case '1':
174 return BB_HIGH;
175 default:
176 remote_bitbang_quit();
177 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c, c);
178 return BB_ERROR;
179 }
180 }
181
182 static int remote_bitbang_sample(void)
183 {
184 if (remote_bitbang_fill_buf(NO_BLOCK) != ERROR_OK)
185 return ERROR_FAIL;
186 assert(!remote_bitbang_recv_buf_full());
187 return remote_bitbang_queue('R', NO_FLUSH);
188 }
189
190 static bb_value_t remote_bitbang_read_sample(void)
191 {
192 if (remote_bitbang_recv_buf_empty()) {
193 if (remote_bitbang_fill_buf(BLOCK) != ERROR_OK)
194 return BB_ERROR;
195 }
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);
201 }
202
203 static int remote_bitbang_write(int tck, int tms, int tdi)
204 {
205 char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
206 return remote_bitbang_queue(c, NO_FLUSH);
207 }
208
209 static int remote_bitbang_reset(int trst, int srst)
210 {
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);
215 }
216
217 static int remote_bitbang_blink(int on)
218 {
219 char c = on ? 'B' : 'b';
220 return remote_bitbang_queue(c, FLUSH_SEND_BUF);
221 }
222
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,
229 };
230
231 static int remote_bitbang_init_tcp(void)
232 {
233 struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
234 struct addrinfo *result, *rp;
235 int fd = 0;
236
237 LOG_INFO("Connecting to %s:%s",
238 remote_bitbang_host ? remote_bitbang_host : "localhost",
239 remote_bitbang_port);
240
241 /* Obtain address(es) matching host/port */
242 int s = getaddrinfo(remote_bitbang_host, remote_bitbang_port, &hints, &result);
243 if (s != 0) {
244 LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s));
245 return ERROR_FAIL;
246 }
247
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. */
252
253 for (rp = result; rp ; rp = rp->ai_next) {
254 fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
255 if (fd == -1)
256 continue;
257
258 if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
259 break; /* Success */
260
261 close(fd);
262 }
263
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. */
267 int one = 1;
268 /* On Windows optval has to be a const char *. */
269 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&one, sizeof(one));
270
271 freeaddrinfo(result); /* No longer needed */
272
273 if (!rp) { /* No address succeeded */
274 log_socket_error("Failed to connect");
275 return ERROR_FAIL;
276 }
277
278 return fd;
279 }
280
281 static int remote_bitbang_init_unix(void)
282 {
283 if (!remote_bitbang_host) {
284 LOG_ERROR("host/socket not specified");
285 return ERROR_FAIL;
286 }
287
288 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
289 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
290 if (fd < 0) {
291 log_socket_error("socket");
292 return ERROR_FAIL;
293 }
294
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';
299
300 if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
301 log_socket_error("connect");
302 return ERROR_FAIL;
303 }
304
305 return fd;
306 }
307
308 static int remote_bitbang_init(void)
309 {
310 bitbang_interface = &remote_bitbang_bitbang;
311
312 remote_bitbang_recv_buf_start = 0;
313 remote_bitbang_recv_buf_end = 0;
314
315 LOG_INFO("Initializing remote_bitbang driver");
316 if (!remote_bitbang_port)
317 remote_bitbang_fd = remote_bitbang_init_unix();
318 else
319 remote_bitbang_fd = remote_bitbang_init_tcp();
320
321 if (remote_bitbang_fd < 0)
322 return remote_bitbang_fd;
323
324 socket_nonblock(remote_bitbang_fd);
325
326 LOG_INFO("remote_bitbang driver initialized");
327 return ERROR_OK;
328 }
329
330 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command)
331 {
332 if (CMD_ARGC == 1) {
333 uint16_t port;
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]);
337 return ERROR_OK;
338 }
339 return ERROR_COMMAND_SYNTAX_ERROR;
340 }
341
342 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
343 {
344 if (CMD_ARGC == 1) {
345 free(remote_bitbang_host);
346 remote_bitbang_host = strdup(CMD_ARGV[0]);
347 return ERROR_OK;
348 }
349 return ERROR_COMMAND_SYNTAX_ERROR;
350 }
351
352 static const struct command_registration remote_bitbang_subcommand_handlers[] = {
353 {
354 .name = "port",
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",
360 },
361 {
362 .name = "host",
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",
368 },
369 COMMAND_REGISTRATION_DONE,
370 };
371
372 static const struct command_registration remote_bitbang_command_handlers[] = {
373 {
374 .name = "remote_bitbang",
375 .mode = COMMAND_ANY,
376 .help = "perform remote_bitbang management",
377 .chain = remote_bitbang_subcommand_handlers,
378 .usage = "",
379 },
380 COMMAND_REGISTRATION_DONE
381 };
382
383 static int remote_bitbang_execute_queue(void)
384 {
385 /* safety: the send buffer must be empty, no leftover characters from
386 * previous transactions */
387 assert(remote_bitbang_send_buf_used == 0);
388
389 /* process the JTAG command queue */
390 int ret = bitbang_execute_queue();
391 if (ret != ERROR_OK)
392 return ret;
393
394 /* flush not-yet-sent characters, if any */
395 return remote_bitbang_flush();
396 }
397
398 static struct jtag_interface remote_bitbang_interface = {
399 .execute_queue = &remote_bitbang_execute_queue,
400 };
401
402 struct adapter_driver remote_bitbang_adapter_driver = {
403 .name = "remote_bitbang",
404 .transports = jtag_only,
405 .commands = remote_bitbang_command_handlers,
406
407 .init = &remote_bitbang_init,
408 .quit = &remote_bitbang_quit,
409 .reset = &remote_bitbang_reset,
410
411 .jtag_ops = &remote_bitbang_interface,
412 };

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)