jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / remote_bitbang.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Richard Uhler *
3 * ruhler@mit.edu *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #ifndef _WIN32
24 #include <sys/un.h>
25 #include <netdb.h>
26 #include <netinet/tcp.h>
27 #endif
28 #include "helper/system.h"
29 #include "helper/replacements.h"
30 #include <jtag/interface.h>
31 #include "bitbang.h"
32
33 /* arbitrary limit on host name length: */
34 #define REMOTE_BITBANG_HOST_MAX 255
35
36 static char *remote_bitbang_host;
37 static char *remote_bitbang_port;
38
39 static int remote_bitbang_fd;
40 static uint8_t remote_bitbang_send_buf[512];
41 static unsigned int remote_bitbang_send_buf_used;
42
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;
47
48 static bool remote_bitbang_recv_buf_full(void)
49 {
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));
53 }
54
55 static bool remote_bitbang_recv_buf_empty(void)
56 {
57 return remote_bitbang_recv_buf_start == remote_bitbang_recv_buf_end;
58 }
59
60 static unsigned int remote_bitbang_recv_buf_contiguous_available_space(void)
61 {
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)
66 space -= 1;
67 return space;
68 } else {
69 return remote_bitbang_recv_buf_start -
70 remote_bitbang_recv_buf_end - 1;
71 }
72 }
73
74 static int remote_bitbang_flush(void)
75 {
76 if (remote_bitbang_send_buf_used <= 0)
77 return ERROR_OK;
78
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);
83 if (written < 0) {
84 log_socket_error("remote_bitbang_putc");
85 remote_bitbang_send_buf_used = 0;
86 return ERROR_FAIL;
87 }
88 offset += written;
89 }
90 remote_bitbang_send_buf_used = 0;
91 return ERROR_OK;
92 }
93
94 enum block_bool {
95 NO_BLOCK,
96 BLOCK
97 };
98
99 /* Read any incoming data, placing it into the buffer. */
100 static int remote_bitbang_fill_buf(enum block_bool block)
101 {
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;
107 }
108
109 if (block == BLOCK) {
110 if (remote_bitbang_flush() != ERROR_OK)
111 return ERROR_FAIL;
112 socket_block(remote_bitbang_fd);
113 }
114
115 bool first = true;
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);
124 first = false;
125 if (count > 0) {
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) {
130 return ERROR_OK;
131 } else if (count < 0) {
132 #ifdef _WIN32
133 if (WSAGetLastError() == WSAEWOULDBLOCK) {
134 #else
135 if (errno == EAGAIN) {
136 #endif
137 return ERROR_OK;
138 } else {
139 log_socket_error("remote_bitbang_fill_buf");
140 return ERROR_FAIL;
141 }
142 }
143 }
144
145 return ERROR_OK;
146 }
147
148 typedef enum {
149 NO_FLUSH,
150 FLUSH_SEND_BUF
151 } flush_bool_t;
152
153 static int remote_bitbang_queue(int c, flush_bool_t flush)
154 {
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();
159 return ERROR_OK;
160 }
161
162 static int remote_bitbang_quit(void)
163 {
164 if (remote_bitbang_queue('Q', FLUSH_SEND_BUF) == ERROR_FAIL)
165 return ERROR_FAIL;
166
167 if (close_socket(remote_bitbang_fd) != 0) {
168 log_socket_error("close_socket");
169 return ERROR_FAIL;
170 }
171
172 free(remote_bitbang_host);
173 free(remote_bitbang_port);
174
175 LOG_INFO("remote_bitbang interface quit");
176 return ERROR_OK;
177 }
178
179 static bb_value_t char_to_int(int c)
180 {
181 switch (c) {
182 case '0':
183 return BB_LOW;
184 case '1':
185 return BB_HIGH;
186 default:
187 remote_bitbang_quit();
188 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c, c);
189 return BB_ERROR;
190 }
191 }
192
193 static int remote_bitbang_sample(void)
194 {
195 if (remote_bitbang_fill_buf(NO_BLOCK) != ERROR_OK)
196 return ERROR_FAIL;
197 assert(!remote_bitbang_recv_buf_full());
198 return remote_bitbang_queue('R', NO_FLUSH);
199 }
200
201 static bb_value_t remote_bitbang_read_sample(void)
202 {
203 if (remote_bitbang_recv_buf_empty()) {
204 if (remote_bitbang_fill_buf(BLOCK) != ERROR_OK)
205 return BB_ERROR;
206 }
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);
212 }
213
214 static int remote_bitbang_write(int tck, int tms, int tdi)
215 {
216 char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
217 return remote_bitbang_queue(c, NO_FLUSH);
218 }
219
220 static int remote_bitbang_reset(int trst, int srst)
221 {
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);
226 }
227
228 static int remote_bitbang_blink(int on)
229 {
230 char c = on ? 'B' : 'b';
231 return remote_bitbang_queue(c, FLUSH_SEND_BUF);
232 }
233
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,
240 };
241
242 static int remote_bitbang_init_tcp(void)
243 {
244 struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
245 struct addrinfo *result, *rp;
246 int fd = 0;
247
248 LOG_INFO("Connecting to %s:%s",
249 remote_bitbang_host ? remote_bitbang_host : "localhost",
250 remote_bitbang_port);
251
252 /* Obtain address(es) matching host/port */
253 int s = getaddrinfo(remote_bitbang_host, remote_bitbang_port, &hints, &result);
254 if (s != 0) {
255 LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s));
256 return ERROR_FAIL;
257 }
258
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. */
263
264 for (rp = result; rp ; rp = rp->ai_next) {
265 fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
266 if (fd == -1)
267 continue;
268
269 if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
270 break; /* Success */
271
272 close(fd);
273 }
274
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. */
278 int one = 1;
279 /* On Windows optval has to be a const char *. */
280 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&one, sizeof(one));
281
282 freeaddrinfo(result); /* No longer needed */
283
284 if (!rp) { /* No address succeeded */
285 log_socket_error("Failed to connect");
286 return ERROR_FAIL;
287 }
288
289 return fd;
290 }
291
292 static int remote_bitbang_init_unix(void)
293 {
294 if (!remote_bitbang_host) {
295 LOG_ERROR("host/socket not specified");
296 return ERROR_FAIL;
297 }
298
299 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
300 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
301 if (fd < 0) {
302 log_socket_error("socket");
303 return ERROR_FAIL;
304 }
305
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';
310
311 if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
312 log_socket_error("connect");
313 return ERROR_FAIL;
314 }
315
316 return fd;
317 }
318
319 static int remote_bitbang_init(void)
320 {
321 bitbang_interface = &remote_bitbang_bitbang;
322
323 remote_bitbang_recv_buf_start = 0;
324 remote_bitbang_recv_buf_end = 0;
325
326 LOG_INFO("Initializing remote_bitbang driver");
327 if (!remote_bitbang_port)
328 remote_bitbang_fd = remote_bitbang_init_unix();
329 else
330 remote_bitbang_fd = remote_bitbang_init_tcp();
331
332 if (remote_bitbang_fd < 0)
333 return remote_bitbang_fd;
334
335 socket_nonblock(remote_bitbang_fd);
336
337 LOG_INFO("remote_bitbang driver initialized");
338 return ERROR_OK;
339 }
340
341 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command)
342 {
343 if (CMD_ARGC == 1) {
344 uint16_t port;
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]);
348 return ERROR_OK;
349 }
350 return ERROR_COMMAND_SYNTAX_ERROR;
351 }
352
353 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
354 {
355 if (CMD_ARGC == 1) {
356 free(remote_bitbang_host);
357 remote_bitbang_host = strdup(CMD_ARGV[0]);
358 return ERROR_OK;
359 }
360 return ERROR_COMMAND_SYNTAX_ERROR;
361 }
362
363 static const struct command_registration remote_bitbang_subcommand_handlers[] = {
364 {
365 .name = "port",
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",
371 },
372 {
373 .name = "host",
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",
379 },
380 COMMAND_REGISTRATION_DONE,
381 };
382
383 static const struct command_registration remote_bitbang_command_handlers[] = {
384 {
385 .name = "remote_bitbang",
386 .mode = COMMAND_ANY,
387 .help = "perform remote_bitbang management",
388 .chain = remote_bitbang_subcommand_handlers,
389 .usage = "",
390 },
391 COMMAND_REGISTRATION_DONE
392 };
393
394 static int remote_bitbang_execute_queue(void)
395 {
396 /* safety: the send buffer must be empty, no leftover characters from
397 * previous transactions */
398 assert(remote_bitbang_send_buf_used == 0);
399
400 /* process the JTAG command queue */
401 int ret = bitbang_execute_queue();
402 if (ret != ERROR_OK)
403 return ret;
404
405 /* flush not-yet-sent characters, if any */
406 return remote_bitbang_flush();
407 }
408
409 static struct jtag_interface remote_bitbang_interface = {
410 .execute_queue = &remote_bitbang_execute_queue,
411 };
412
413 struct adapter_driver remote_bitbang_adapter_driver = {
414 .name = "remote_bitbang",
415 .transports = jtag_only,
416 .commands = remote_bitbang_command_handlers,
417
418 .init = &remote_bitbang_init,
419 .quit = &remote_bitbang_quit,
420 .reset = &remote_bitbang_reset,
421
422 .jtag_ops = &remote_bitbang_interface,
423 };

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)