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

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)