]> git.sur5r.net Git - openocd/blob - src/jtag/drivers/remote_bitbang.c
remote_bitbang: fix native windows build
[openocd] / 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_speed(int speed)
134 {
135         return ERROR_OK;
136 }
137
138 static int remote_bitbang_init_tcp(void)
139 {
140         LOG_INFO("Connecting to %s:%i", remote_bitbang_host, remote_bitbang_port);
141         int fd = socket(PF_INET, SOCK_STREAM, 0);
142         if (fd < 0) {
143                 LOG_ERROR("socket: %s", strerror(errno));
144                 return ERROR_FAIL;
145         }
146
147         struct hostent *hent = gethostbyname(remote_bitbang_host);
148         if (hent == NULL) {
149                 char *errorstr = "???";
150                 switch (h_errno) {
151                         case HOST_NOT_FOUND:
152                                 errorstr = "host not found";
153                                 break;
154                         case NO_ADDRESS:
155                                 errorstr = "no address";
156                                 break;
157                         case NO_RECOVERY:
158                                 errorstr = "no recovery";
159                                 break;
160                         case TRY_AGAIN:
161                                 errorstr = "try again";
162                                 break;
163                 }
164                 LOG_ERROR("gethostbyname: %s", errorstr);
165                 return ERROR_FAIL;
166         }
167
168         struct sockaddr_in addr;
169         addr.sin_family = AF_INET;
170         addr.sin_port = htons(remote_bitbang_port);
171         addr.sin_addr = *(struct in_addr *)hent->h_addr;
172         if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
173                 LOG_ERROR("connect: %s", strerror(errno));
174                 return ERROR_FAIL;
175         }
176
177         remote_bitbang_in = fdopen(fd, "r");
178         if (remote_bitbang_in == NULL) {
179                 LOG_ERROR("fdopen: failed to open read stream");
180                 return ERROR_FAIL;
181         }
182
183         remote_bitbang_out = fdopen(fd, "w");
184         if (remote_bitbang_out == NULL) {
185                 LOG_ERROR("fdopen: failed to open write stream");
186                 return ERROR_FAIL;
187         }
188
189         LOG_INFO("remote_bitbang driver initialized");
190         return ERROR_OK;
191 }
192
193 static int remote_bitbang_init_unix(void)
194 {
195         LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
196         int fd = socket(PF_UNIX, SOCK_STREAM, 0);
197         if (fd < 0) {
198                 LOG_ERROR("socket: %s", strerror(errno));
199                 return ERROR_FAIL;
200         }
201
202         struct sockaddr_un addr;
203         addr.sun_family = AF_UNIX;
204         strncpy(addr.sun_path, remote_bitbang_host, UNIX_PATH_LEN);
205         addr.sun_path[UNIX_PATH_LEN-1] = '\0';
206
207         if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
208                 LOG_ERROR("connect: %s", strerror(errno));
209                 return ERROR_FAIL;
210         }
211
212         remote_bitbang_in = fdopen(fd, "r");
213         if (remote_bitbang_in == NULL) {
214                 LOG_ERROR("fdopen: failed to open read stream");
215                 return ERROR_FAIL;
216         }
217
218         remote_bitbang_out = fdopen(fd, "w");
219         if (remote_bitbang_out == NULL) {
220                 LOG_ERROR("fdopen: failed to open write stream");
221                 return ERROR_FAIL;
222         }
223
224         LOG_INFO("remote_bitbang driver initialized");
225         return ERROR_OK;
226 }
227
228 static int remote_bitbang_init(void)
229 {
230         bitbang_interface = &remote_bitbang_bitbang;
231
232         LOG_INFO("Initializing remote_bitbang driver");
233         if (remote_bitbang_port == 0)
234                 return remote_bitbang_init_unix();
235         return remote_bitbang_init_tcp();
236 }
237
238 static int remote_bitbang_khz(int khz, int *jtag_speed)
239 {
240         *jtag_speed = 0;
241         return ERROR_OK;
242 }
243
244 static int remote_bitbang_speed_div(int speed, int *khz)
245 {
246         /* I don't think this really matters any. */
247         *khz = 1;
248         return ERROR_OK;
249 }
250
251 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command)
252 {
253         if (CMD_ARGC == 1) {
254                 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], remote_bitbang_port);
255                 return ERROR_OK;
256         }
257         return ERROR_COMMAND_SYNTAX_ERROR;
258 }
259
260 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
261 {
262         if (CMD_ARGC == 1) {
263                 strncpy(remote_bitbang_host, CMD_ARGV[0], REMOTE_BITBANG_HOST_MAX);
264                 remote_bitbang_host[REMOTE_BITBANG_HOST_MAX-1] = '\0';
265                 return ERROR_OK;
266         }
267         return ERROR_COMMAND_SYNTAX_ERROR;
268 }
269
270 static const struct command_registration remote_bitbang_command_handlers[] = {
271         {
272                 .name = "remote_bitbang_port",
273                 .handler = remote_bitbang_handle_remote_bitbang_port_command,
274                 .mode = COMMAND_CONFIG,
275                 .help = "Set the port to use to connect to the remote jtag.\n"
276                         "  if 0, use unix sockets to connect to the remote jtag.",
277                 .usage = "port_number",
278         },
279         {
280                 .name = "remote_bitbang_host",
281                 .handler = remote_bitbang_handle_remote_bitbang_host_command,
282                 .mode = COMMAND_CONFIG,
283                 .help = "Set the host to use to connect to the remote jtag.\n"
284                         "  if port is 0, this is the name of the unix socket to use.",
285                 .usage = "host_name",
286         },
287         COMMAND_REGISTRATION_DONE,
288 };
289
290 struct jtag_interface remote_bitbang_interface = {
291         .name = "remote_bitbang",
292         .execute_queue = &bitbang_execute_queue,
293         .speed = &remote_bitbang_speed,
294         .commands = remote_bitbang_command_handlers,
295         .init = &remote_bitbang_init,
296         .quit = &remote_bitbang_quit,
297         .khz = &remote_bitbang_khz,
298         .speed_div = &remote_bitbang_speed_div,
299 };