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

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)