jtag_interface: .speed can be NULL when not needed
[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, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #ifndef _WIN32
26 #include <sys/un.h>
27 #include <netdb.h>
28 #endif
29 #include <jtag/interface.h>
30 #include "bitbang.h"
31
32 #ifndef UNIX_PATH_LEN
33 #define UNIX_PATH_LEN 108
34 #endif
35
36 /* arbitrary limit on host name length: */
37 #define REMOTE_BITBANG_HOST_MAX 255
38
39 #define REMOTE_BITBANG_RAISE_ERROR(expr ...) \
40 do { \
41 LOG_ERROR(expr); \
42 LOG_ERROR("Terminating openocd."); \
43 exit(-1); \
44 } while (0)
45
46 static char remote_bitbang_host[REMOTE_BITBANG_HOST_MAX] = "openocd";
47 static uint16_t remote_bitbang_port;
48
49 FILE *remote_bitbang_in;
50 FILE *remote_bitbang_out;
51
52 static void remote_bitbang_putc(int c)
53 {
54 if (EOF == fputc(c, remote_bitbang_out))
55 REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno));
56 }
57
58 static int remote_bitbang_quit(void)
59 {
60 if (EOF == fputc('Q', remote_bitbang_out)) {
61 LOG_ERROR("fputs: %s", strerror(errno));
62 return ERROR_FAIL;
63 }
64
65 if (EOF == fflush(remote_bitbang_out)) {
66 LOG_ERROR("fflush: %s", strerror(errno));
67 return ERROR_FAIL;
68 }
69
70 /* We only need to close one of the FILE*s, because they both use the same */
71 /* underlying file descriptor. */
72 if (EOF == fclose(remote_bitbang_out)) {
73 LOG_ERROR("fclose: %s", strerror(errno));
74 return ERROR_FAIL;
75 }
76
77 LOG_INFO("remote_bitbang interface quit");
78 return ERROR_OK;
79 }
80
81 /* Get the next read response. */
82 static int remote_bitbang_rread(void)
83 {
84 if (EOF == fflush(remote_bitbang_out)) {
85 remote_bitbang_quit();
86 REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno));
87 }
88
89 int c = fgetc(remote_bitbang_in);
90 switch (c) {
91 case '0':
92 return 0;
93 case '1':
94 return 1;
95 default:
96 remote_bitbang_quit();
97 REMOTE_BITBANG_RAISE_ERROR(
98 "remote_bitbang: invalid read response: %c(%i)", c, c);
99 }
100 }
101
102 static int remote_bitbang_read(void)
103 {
104 remote_bitbang_putc('R');
105 return remote_bitbang_rread();
106 }
107
108 static void remote_bitbang_write(int tck, int tms, int tdi)
109 {
110 char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
111 remote_bitbang_putc(c);
112 }
113
114 static void remote_bitbang_reset(int trst, int srst)
115 {
116 char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0));
117 remote_bitbang_putc(c);
118 }
119
120 static void remote_bitbang_blink(int on)
121 {
122 char c = on ? 'B' : 'b';
123 remote_bitbang_putc(c);
124 }
125
126 static struct bitbang_interface remote_bitbang_bitbang = {
127 .read = &remote_bitbang_read,
128 .write = &remote_bitbang_write,
129 .reset = &remote_bitbang_reset,
130 .blink = &remote_bitbang_blink,
131 };
132
133 static int remote_bitbang_init_tcp(void)
134 {
135 LOG_INFO("Connecting to %s:%i", remote_bitbang_host, remote_bitbang_port);
136 int fd = socket(PF_INET, SOCK_STREAM, 0);
137 if (fd < 0) {
138 LOG_ERROR("socket: %s", strerror(errno));
139 return ERROR_FAIL;
140 }
141
142 struct hostent *hent = gethostbyname(remote_bitbang_host);
143 if (hent == NULL) {
144 char *errorstr = "???";
145 switch (h_errno) {
146 case HOST_NOT_FOUND:
147 errorstr = "host not found";
148 break;
149 case NO_ADDRESS:
150 errorstr = "no address";
151 break;
152 case NO_RECOVERY:
153 errorstr = "no recovery";
154 break;
155 case TRY_AGAIN:
156 errorstr = "try again";
157 break;
158 }
159 LOG_ERROR("gethostbyname: %s", errorstr);
160 return ERROR_FAIL;
161 }
162
163 struct sockaddr_in addr;
164 addr.sin_family = AF_INET;
165 addr.sin_port = htons(remote_bitbang_port);
166 addr.sin_addr = *(struct in_addr *)hent->h_addr;
167 if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
168 LOG_ERROR("connect: %s", strerror(errno));
169 return ERROR_FAIL;
170 }
171
172 remote_bitbang_in = fdopen(fd, "r");
173 if (remote_bitbang_in == NULL) {
174 LOG_ERROR("fdopen: failed to open read stream");
175 return ERROR_FAIL;
176 }
177
178 remote_bitbang_out = fdopen(fd, "w");
179 if (remote_bitbang_out == NULL) {
180 LOG_ERROR("fdopen: failed to open write stream");
181 return ERROR_FAIL;
182 }
183
184 LOG_INFO("remote_bitbang driver initialized");
185 return ERROR_OK;
186 }
187
188 static int remote_bitbang_init_unix(void)
189 {
190 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
191 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
192 if (fd < 0) {
193 LOG_ERROR("socket: %s", strerror(errno));
194 return ERROR_FAIL;
195 }
196
197 struct sockaddr_un addr;
198 addr.sun_family = AF_UNIX;
199 strncpy(addr.sun_path, remote_bitbang_host, UNIX_PATH_LEN);
200 addr.sun_path[UNIX_PATH_LEN-1] = '\0';
201
202 if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
203 LOG_ERROR("connect: %s", strerror(errno));
204 return ERROR_FAIL;
205 }
206
207 remote_bitbang_in = fdopen(fd, "r");
208 if (remote_bitbang_in == NULL) {
209 LOG_ERROR("fdopen: failed to open read stream");
210 return ERROR_FAIL;
211 }
212
213 remote_bitbang_out = fdopen(fd, "w");
214 if (remote_bitbang_out == NULL) {
215 LOG_ERROR("fdopen: failed to open write stream");
216 return ERROR_FAIL;
217 }
218
219 LOG_INFO("remote_bitbang driver initialized");
220 return ERROR_OK;
221 }
222
223 static int remote_bitbang_init(void)
224 {
225 bitbang_interface = &remote_bitbang_bitbang;
226
227 LOG_INFO("Initializing remote_bitbang driver");
228 if (remote_bitbang_port == 0)
229 return remote_bitbang_init_unix();
230 return remote_bitbang_init_tcp();
231 }
232
233 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command)
234 {
235 if (CMD_ARGC == 1) {
236 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], remote_bitbang_port);
237 return ERROR_OK;
238 }
239 return ERROR_COMMAND_SYNTAX_ERROR;
240 }
241
242 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
243 {
244 if (CMD_ARGC == 1) {
245 strncpy(remote_bitbang_host, CMD_ARGV[0], REMOTE_BITBANG_HOST_MAX);
246 remote_bitbang_host[REMOTE_BITBANG_HOST_MAX-1] = '\0';
247 return ERROR_OK;
248 }
249 return ERROR_COMMAND_SYNTAX_ERROR;
250 }
251
252 static const struct command_registration remote_bitbang_command_handlers[] = {
253 {
254 .name = "remote_bitbang_port",
255 .handler = remote_bitbang_handle_remote_bitbang_port_command,
256 .mode = COMMAND_CONFIG,
257 .help = "Set the port to use to connect to the remote jtag.\n"
258 " if 0, use unix sockets to connect to the remote jtag.",
259 .usage = "port_number",
260 },
261 {
262 .name = "remote_bitbang_host",
263 .handler = remote_bitbang_handle_remote_bitbang_host_command,
264 .mode = COMMAND_CONFIG,
265 .help = "Set the host to use to connect to the remote jtag.\n"
266 " if port is 0, this is the name of the unix socket to use.",
267 .usage = "host_name",
268 },
269 COMMAND_REGISTRATION_DONE,
270 };
271
272 struct jtag_interface remote_bitbang_interface = {
273 .name = "remote_bitbang",
274 .execute_queue = &bitbang_execute_queue,
275 .commands = remote_bitbang_command_handlers,
276 .init = &remote_bitbang_init,
277 .quit = &remote_bitbang_quit,
278 };

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)