f7b88303ba570dd853c4be45fb5eca6dcfc7e7d4
[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 #endif
27 #include "helper/system.h"
28 #include "helper/replacements.h"
29 #include <jtag/interface.h>
30 #include "bitbang.h"
31
32 /* arbitrary limit on host name length: */
33 #define REMOTE_BITBANG_HOST_MAX 255
34
35 static char *remote_bitbang_host;
36 static char *remote_bitbang_port;
37
38 static int remote_bitbang_fd;
39
40 /* Circular buffer. When start == end, the buffer is empty. */
41 static char remote_bitbang_buf[64];
42 static unsigned remote_bitbang_start;
43 static unsigned remote_bitbang_end;
44
45 static int remote_bitbang_buf_full(void)
46 {
47 return remote_bitbang_end ==
48 ((remote_bitbang_start + sizeof(remote_bitbang_buf) - 1) %
49 sizeof(remote_bitbang_buf));
50 }
51
52 /* Read any incoming data, placing it into the buffer. */
53 static int remote_bitbang_fill_buf(void)
54 {
55 socket_nonblock(remote_bitbang_fd);
56 while (!remote_bitbang_buf_full()) {
57 unsigned contiguous_available_space;
58 if (remote_bitbang_end >= remote_bitbang_start) {
59 contiguous_available_space = sizeof(remote_bitbang_buf) -
60 remote_bitbang_end;
61 if (remote_bitbang_start == 0)
62 contiguous_available_space -= 1;
63 } else {
64 contiguous_available_space = remote_bitbang_start -
65 remote_bitbang_end - 1;
66 }
67 ssize_t count = read_socket(remote_bitbang_fd,
68 remote_bitbang_buf + remote_bitbang_end,
69 contiguous_available_space);
70 if (count > 0) {
71 remote_bitbang_end += count;
72 if (remote_bitbang_end == sizeof(remote_bitbang_buf))
73 remote_bitbang_end = 0;
74 } else if (count == 0) {
75 return ERROR_OK;
76 } else if (count < 0) {
77 #ifdef _WIN32
78 if (WSAGetLastError() == WSAEWOULDBLOCK) {
79 #else
80 if (errno == EAGAIN) {
81 #endif
82 return ERROR_OK;
83 } else {
84 log_socket_error("remote_bitbang_fill_buf");
85 return ERROR_FAIL;
86 }
87 }
88 }
89
90 return ERROR_OK;
91 }
92
93 static int remote_bitbang_putc(int c)
94 {
95 char buf = c;
96 ssize_t count = write_socket(remote_bitbang_fd, &buf, sizeof(buf));
97 if (count < 0) {
98 log_socket_error("remote_bitbang_putc");
99 return ERROR_FAIL;
100 }
101 return ERROR_OK;
102 }
103
104 static int remote_bitbang_quit(void)
105 {
106 if (remote_bitbang_putc('Q') == ERROR_FAIL)
107 return ERROR_FAIL;
108
109 if (close_socket(remote_bitbang_fd) != 0) {
110 log_socket_error("close_socket");
111 return ERROR_FAIL;
112 }
113
114 free(remote_bitbang_host);
115 free(remote_bitbang_port);
116
117 LOG_INFO("remote_bitbang interface quit");
118 return ERROR_OK;
119 }
120
121 static bb_value_t char_to_int(int c)
122 {
123 switch (c) {
124 case '0':
125 return BB_LOW;
126 case '1':
127 return BB_HIGH;
128 default:
129 remote_bitbang_quit();
130 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c, c);
131 return BB_ERROR;
132 }
133 }
134
135 /* Get the next read response. */
136 static bb_value_t remote_bitbang_rread(void)
137 {
138 /* Enable blocking access. */
139 socket_block(remote_bitbang_fd);
140 char c;
141 ssize_t count = read_socket(remote_bitbang_fd, &c, 1);
142 if (count == 1) {
143 return char_to_int(c);
144 } else {
145 remote_bitbang_quit();
146 LOG_ERROR("read_socket: count=%d", (int) count);
147 log_socket_error("read_socket");
148 return BB_ERROR;
149 }
150 }
151
152 static int remote_bitbang_sample(void)
153 {
154 if (remote_bitbang_fill_buf() != ERROR_OK)
155 return ERROR_FAIL;
156 assert(!remote_bitbang_buf_full());
157 return remote_bitbang_putc('R');
158 }
159
160 static bb_value_t remote_bitbang_read_sample(void)
161 {
162 if (remote_bitbang_start != remote_bitbang_end) {
163 int c = remote_bitbang_buf[remote_bitbang_start];
164 remote_bitbang_start =
165 (remote_bitbang_start + 1) % sizeof(remote_bitbang_buf);
166 return char_to_int(c);
167 }
168 return remote_bitbang_rread();
169 }
170
171 static int remote_bitbang_write(int tck, int tms, int tdi)
172 {
173 char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
174 return remote_bitbang_putc(c);
175 }
176
177 static int remote_bitbang_reset(int trst, int srst)
178 {
179 char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0));
180 return remote_bitbang_putc(c);
181 }
182
183 static int remote_bitbang_blink(int on)
184 {
185 char c = on ? 'B' : 'b';
186 return remote_bitbang_putc(c);
187 }
188
189 static struct bitbang_interface remote_bitbang_bitbang = {
190 .buf_size = sizeof(remote_bitbang_buf) - 1,
191 .sample = &remote_bitbang_sample,
192 .read_sample = &remote_bitbang_read_sample,
193 .write = &remote_bitbang_write,
194 .blink = &remote_bitbang_blink,
195 };
196
197 static int remote_bitbang_init_tcp(void)
198 {
199 struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
200 struct addrinfo *result, *rp;
201 int fd = 0;
202
203 LOG_INFO("Connecting to %s:%s",
204 remote_bitbang_host ? remote_bitbang_host : "localhost",
205 remote_bitbang_port);
206
207 /* Obtain address(es) matching host/port */
208 int s = getaddrinfo(remote_bitbang_host, remote_bitbang_port, &hints, &result);
209 if (s != 0) {
210 LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s));
211 return ERROR_FAIL;
212 }
213
214 /* getaddrinfo() returns a list of address structures.
215 Try each address until we successfully connect(2).
216 If socket(2) (or connect(2)) fails, we (close the socket
217 and) try the next address. */
218
219 for (rp = result; rp != NULL ; rp = rp->ai_next) {
220 fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
221 if (fd == -1)
222 continue;
223
224 if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
225 break; /* Success */
226
227 close(fd);
228 }
229
230 freeaddrinfo(result); /* No longer needed */
231
232 if (rp == NULL) { /* No address succeeded */
233 log_socket_error("Failed to connect");
234 return ERROR_FAIL;
235 }
236
237 return fd;
238 }
239
240 static int remote_bitbang_init_unix(void)
241 {
242 if (remote_bitbang_host == NULL) {
243 LOG_ERROR("host/socket not specified");
244 return ERROR_FAIL;
245 }
246
247 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
248 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
249 if (fd < 0) {
250 log_socket_error("socket");
251 return ERROR_FAIL;
252 }
253
254 struct sockaddr_un addr;
255 addr.sun_family = AF_UNIX;
256 strncpy(addr.sun_path, remote_bitbang_host, sizeof(addr.sun_path));
257 addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
258
259 if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
260 log_socket_error("connect");
261 return ERROR_FAIL;
262 }
263
264 return fd;
265 }
266
267 static int remote_bitbang_init(void)
268 {
269 bitbang_interface = &remote_bitbang_bitbang;
270
271 remote_bitbang_start = 0;
272 remote_bitbang_end = 0;
273
274 LOG_INFO("Initializing remote_bitbang driver");
275 if (remote_bitbang_port == NULL)
276 remote_bitbang_fd = remote_bitbang_init_unix();
277 else
278 remote_bitbang_fd = remote_bitbang_init_tcp();
279
280 if (remote_bitbang_fd < 0)
281 return remote_bitbang_fd;
282
283 LOG_INFO("remote_bitbang driver initialized");
284 return ERROR_OK;
285 }
286
287 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command)
288 {
289 if (CMD_ARGC == 1) {
290 uint16_t port;
291 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
292 free(remote_bitbang_port);
293 remote_bitbang_port = port == 0 ? NULL : strdup(CMD_ARGV[0]);
294 return ERROR_OK;
295 }
296 return ERROR_COMMAND_SYNTAX_ERROR;
297 }
298
299 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
300 {
301 if (CMD_ARGC == 1) {
302 free(remote_bitbang_host);
303 remote_bitbang_host = strdup(CMD_ARGV[0]);
304 return ERROR_OK;
305 }
306 return ERROR_COMMAND_SYNTAX_ERROR;
307 }
308
309 static const struct command_registration remote_bitbang_command_handlers[] = {
310 {
311 .name = "remote_bitbang_port",
312 .handler = remote_bitbang_handle_remote_bitbang_port_command,
313 .mode = COMMAND_CONFIG,
314 .help = "Set the port to use to connect to the remote jtag.\n"
315 " if 0 or unset, use unix sockets to connect to the remote jtag.",
316 .usage = "port_number",
317 },
318 {
319 .name = "remote_bitbang_host",
320 .handler = remote_bitbang_handle_remote_bitbang_host_command,
321 .mode = COMMAND_CONFIG,
322 .help = "Set the host to use to connect to the remote jtag.\n"
323 " if port is 0 or unset, this is the name of the unix socket to use.",
324 .usage = "host_name",
325 },
326 COMMAND_REGISTRATION_DONE,
327 };
328
329 static struct jtag_interface remote_bitbang_interface = {
330 .execute_queue = &bitbang_execute_queue,
331 };
332
333 struct adapter_driver remote_bitbang_adapter_driver = {
334 .name = "remote_bitbang",
335 .transports = jtag_only,
336 .commands = remote_bitbang_command_handlers,
337
338 .init = &remote_bitbang_init,
339 .quit = &remote_bitbang_quit,
340 .reset = &remote_bitbang_reset,
341
342 .jtag_ops = &remote_bitbang_interface,
343 };

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)