You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

281 lines
7.5 KiB

  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. #ifdef HAVE_CONFIG_H
  19. #include "config.h"
  20. #endif
  21. #ifndef _WIN32
  22. #include <sys/un.h>
  23. #include <netdb.h>
  24. #endif
  25. #include <jtag/interface.h>
  26. #include "bitbang.h"
  27. /* arbitrary limit on host name length: */
  28. #define REMOTE_BITBANG_HOST_MAX 255
  29. #define REMOTE_BITBANG_RAISE_ERROR(expr ...) \
  30. do { \
  31. LOG_ERROR(expr); \
  32. LOG_ERROR("Terminating openocd."); \
  33. exit(-1); \
  34. } while (0)
  35. static char *remote_bitbang_host;
  36. static char *remote_bitbang_port;
  37. FILE *remote_bitbang_in;
  38. FILE *remote_bitbang_out;
  39. static void remote_bitbang_putc(int c)
  40. {
  41. if (EOF == fputc(c, remote_bitbang_out))
  42. REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno));
  43. }
  44. static int remote_bitbang_quit(void)
  45. {
  46. if (EOF == fputc('Q', remote_bitbang_out)) {
  47. LOG_ERROR("fputs: %s", strerror(errno));
  48. return ERROR_FAIL;
  49. }
  50. if (EOF == fflush(remote_bitbang_out)) {
  51. LOG_ERROR("fflush: %s", strerror(errno));
  52. return ERROR_FAIL;
  53. }
  54. /* We only need to close one of the FILE*s, because they both use the same */
  55. /* underlying file descriptor. */
  56. if (EOF == fclose(remote_bitbang_out)) {
  57. LOG_ERROR("fclose: %s", strerror(errno));
  58. return ERROR_FAIL;
  59. }
  60. free(remote_bitbang_host);
  61. free(remote_bitbang_port);
  62. LOG_INFO("remote_bitbang interface quit");
  63. return ERROR_OK;
  64. }
  65. /* Get the next read response. */
  66. static int remote_bitbang_rread(void)
  67. {
  68. if (EOF == fflush(remote_bitbang_out)) {
  69. remote_bitbang_quit();
  70. REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno));
  71. }
  72. int c = fgetc(remote_bitbang_in);
  73. switch (c) {
  74. case '0':
  75. return 0;
  76. case '1':
  77. return 1;
  78. default:
  79. remote_bitbang_quit();
  80. REMOTE_BITBANG_RAISE_ERROR(
  81. "remote_bitbang: invalid read response: %c(%i)", c, c);
  82. }
  83. }
  84. static int remote_bitbang_read(void)
  85. {
  86. remote_bitbang_putc('R');
  87. return remote_bitbang_rread();
  88. }
  89. static void remote_bitbang_write(int tck, int tms, int tdi)
  90. {
  91. char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
  92. remote_bitbang_putc(c);
  93. }
  94. static void remote_bitbang_reset(int trst, int srst)
  95. {
  96. char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0));
  97. remote_bitbang_putc(c);
  98. }
  99. static void remote_bitbang_blink(int on)
  100. {
  101. char c = on ? 'B' : 'b';
  102. remote_bitbang_putc(c);
  103. }
  104. static struct bitbang_interface remote_bitbang_bitbang = {
  105. .read = &remote_bitbang_read,
  106. .write = &remote_bitbang_write,
  107. .reset = &remote_bitbang_reset,
  108. .blink = &remote_bitbang_blink,
  109. };
  110. static int remote_bitbang_init_tcp(void)
  111. {
  112. struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
  113. struct addrinfo *result, *rp;
  114. int fd;
  115. LOG_INFO("Connecting to %s:%s",
  116. remote_bitbang_host ? remote_bitbang_host : "localhost",
  117. remote_bitbang_port);
  118. /* Obtain address(es) matching host/port */
  119. int s = getaddrinfo(remote_bitbang_host, remote_bitbang_port, &hints, &result);
  120. if (s != 0) {
  121. LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s));
  122. return ERROR_FAIL;
  123. }
  124. /* getaddrinfo() returns a list of address structures.
  125. Try each address until we successfully connect(2).
  126. If socket(2) (or connect(2)) fails, we (close the socket
  127. and) try the next address. */
  128. for (rp = result; rp != NULL ; rp = rp->ai_next) {
  129. fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
  130. if (fd == -1)
  131. continue;
  132. if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
  133. break; /* Success */
  134. close(fd);
  135. }
  136. freeaddrinfo(result); /* No longer needed */
  137. if (rp == NULL) { /* No address succeeded */
  138. LOG_ERROR("Failed to connect: %s", strerror(errno));
  139. return ERROR_FAIL;
  140. }
  141. return fd;
  142. }
  143. static int remote_bitbang_init_unix(void)
  144. {
  145. if (remote_bitbang_host == NULL) {
  146. LOG_ERROR("host/socket not specified");
  147. return ERROR_FAIL;
  148. }
  149. LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
  150. int fd = socket(PF_UNIX, SOCK_STREAM, 0);
  151. if (fd < 0) {
  152. LOG_ERROR("socket: %s", strerror(errno));
  153. return ERROR_FAIL;
  154. }
  155. struct sockaddr_un addr;
  156. addr.sun_family = AF_UNIX;
  157. strncpy(addr.sun_path, remote_bitbang_host, sizeof(addr.sun_path));
  158. addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
  159. if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
  160. LOG_ERROR("connect: %s", strerror(errno));
  161. return ERROR_FAIL;
  162. }
  163. return fd;
  164. }
  165. static int remote_bitbang_init(void)
  166. {
  167. int fd;
  168. bitbang_interface = &remote_bitbang_bitbang;
  169. LOG_INFO("Initializing remote_bitbang driver");
  170. if (remote_bitbang_port == NULL)
  171. fd = remote_bitbang_init_unix();
  172. else
  173. fd = remote_bitbang_init_tcp();
  174. if (fd < 0)
  175. return fd;
  176. remote_bitbang_in = fdopen(fd, "r");
  177. if (remote_bitbang_in == NULL) {
  178. LOG_ERROR("fdopen: failed to open read stream");
  179. close(fd);
  180. return ERROR_FAIL;
  181. }
  182. remote_bitbang_out = fdopen(fd, "w");
  183. if (remote_bitbang_out == NULL) {
  184. LOG_ERROR("fdopen: failed to open write stream");
  185. fclose(remote_bitbang_in);
  186. return ERROR_FAIL;
  187. }
  188. LOG_INFO("remote_bitbang driver initialized");
  189. return ERROR_OK;
  190. }
  191. COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command)
  192. {
  193. if (CMD_ARGC == 1) {
  194. uint16_t port;
  195. COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
  196. free(remote_bitbang_port);
  197. remote_bitbang_port = port == 0 ? NULL : strdup(CMD_ARGV[0]);
  198. return ERROR_OK;
  199. }
  200. return ERROR_COMMAND_SYNTAX_ERROR;
  201. }
  202. COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
  203. {
  204. if (CMD_ARGC == 1) {
  205. free(remote_bitbang_host);
  206. remote_bitbang_host = strdup(CMD_ARGV[0]);
  207. return ERROR_OK;
  208. }
  209. return ERROR_COMMAND_SYNTAX_ERROR;
  210. }
  211. static const struct command_registration remote_bitbang_command_handlers[] = {
  212. {
  213. .name = "remote_bitbang_port",
  214. .handler = remote_bitbang_handle_remote_bitbang_port_command,
  215. .mode = COMMAND_CONFIG,
  216. .help = "Set the port to use to connect to the remote jtag.\n"
  217. " if 0 or unset, use unix sockets to connect to the remote jtag.",
  218. .usage = "port_number",
  219. },
  220. {
  221. .name = "remote_bitbang_host",
  222. .handler = remote_bitbang_handle_remote_bitbang_host_command,
  223. .mode = COMMAND_CONFIG,
  224. .help = "Set the host to use to connect to the remote jtag.\n"
  225. " if port is 0 or unset, this is the name of the unix socket to use.",
  226. .usage = "host_name",
  227. },
  228. COMMAND_REGISTRATION_DONE,
  229. };
  230. struct jtag_interface remote_bitbang_interface = {
  231. .name = "remote_bitbang",
  232. .execute_queue = &bitbang_execute_queue,
  233. .commands = remote_bitbang_command_handlers,
  234. .init = &remote_bitbang_init,
  235. .quit = &remote_bitbang_quit,
  236. };