1 #include <arpa/inet.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7
8 #ifndef AF_INET
9 #include <sys/socket.h>
10 #endif
11 #ifndef INADDR_ANY
12 #include <netinet/in.h>
13 #endif
14
15 #include <algorithm>
16 #include <cassert>
17 #include <cstdio>
18
19 #include "remote_bitbang.h"
20
21 #if 1
22 # define D(x) x
23 #else
24 # define D(x)
25 #endif
26
27 /////////// remote_bitbang_t
28
remote_bitbang_t(uint16_t port,jtag_dtm_t * tap)29 remote_bitbang_t::remote_bitbang_t(uint16_t port, jtag_dtm_t *tap) :
30 tap(tap),
31 socket_fd(0),
32 client_fd(0),
33 recv_start(0),
34 recv_end(0)
35 {
36 socket_fd = socket(AF_INET, SOCK_STREAM, 0);
37 if (socket_fd == -1) {
38 fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n",
39 strerror(errno), errno);
40 abort();
41 }
42
43 fcntl(socket_fd, F_SETFL, O_NONBLOCK);
44 int reuseaddr = 1;
45 if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
46 sizeof(int)) == -1) {
47 fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n",
48 strerror(errno), errno);
49 abort();
50 }
51
52 struct sockaddr_in addr;
53 memset(&addr, 0, sizeof(addr));
54 addr.sin_family = AF_INET;
55 addr.sin_addr.s_addr = INADDR_ANY;
56 addr.sin_port = htons(port);
57
58 if (bind(socket_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
59 fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n",
60 strerror(errno), errno);
61 abort();
62 }
63
64 if (listen(socket_fd, 1) == -1) {
65 fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n",
66 strerror(errno), errno);
67 abort();
68 }
69
70 socklen_t addrlen = sizeof(addr);
71 if (getsockname(socket_fd, (struct sockaddr *) &addr, &addrlen) == -1) {
72 fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n",
73 strerror(errno), errno);
74 abort();
75 }
76
77 printf("Listening for remote bitbang connection on port %d.\n",
78 ntohs(addr.sin_port));
79 fflush(stdout);
80 }
81
accept()82 void remote_bitbang_t::accept()
83 {
84 client_fd = ::accept(socket_fd, NULL, NULL);
85 if (client_fd == -1) {
86 if (errno == EAGAIN) {
87 // No client waiting to connect right now.
88 } else {
89 fprintf(stderr, "failed to accept on socket: %s (%d)\n", strerror(errno),
90 errno);
91 abort();
92 }
93 } else {
94 fcntl(client_fd, F_SETFL, O_NONBLOCK);
95 }
96 }
97
tick()98 void remote_bitbang_t::tick()
99 {
100 if (client_fd > 0) {
101 execute_commands();
102 } else {
103 this->accept();
104 }
105 }
106
execute_commands()107 void remote_bitbang_t::execute_commands()
108 {
109 static char send_buf[buf_size];
110 unsigned total_processed = 0;
111 bool quit = false;
112 bool in_rti = tap->state() == RUN_TEST_IDLE;
113 bool entered_rti = false;
114 while (1) {
115 if (recv_start < recv_end) {
116 unsigned send_offset = 0;
117 while (recv_start < recv_end) {
118 uint8_t command = recv_buf[recv_start];
119
120 switch (command) {
121 case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break;
122 case 'b': /* fprintf(stderr, "_______\n"); */ break;
123 case 'r': tap->reset(); break;
124 case '0': tap->set_pins(0, 0, 0); break;
125 case '1': tap->set_pins(0, 0, 1); break;
126 case '2': tap->set_pins(0, 1, 0); break;
127 case '3': tap->set_pins(0, 1, 1); break;
128 case '4': tap->set_pins(1, 0, 0); break;
129 case '5': tap->set_pins(1, 0, 1); break;
130 case '6': tap->set_pins(1, 1, 0); break;
131 case '7': tap->set_pins(1, 1, 1); break;
132 case 'R': send_buf[send_offset++] = tap->tdo() ? '1' : '0'; break;
133 case 'Q': quit = true; break;
134 default:
135 fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
136 command);
137 }
138 recv_start++;
139 total_processed++;
140 if (!in_rti && tap->state() == RUN_TEST_IDLE) {
141 entered_rti = true;
142 break;
143 }
144 in_rti = false;
145 }
146 unsigned sent = 0;
147 while (sent < send_offset) {
148 ssize_t bytes = write(client_fd, send_buf + sent, send_offset);
149 if (bytes == -1) {
150 fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno);
151 abort();
152 }
153 sent += bytes;
154 }
155 }
156
157 if (total_processed > buf_size || quit || entered_rti) {
158 // Don't go forever, because that could starve the main simulation.
159 break;
160 }
161
162 recv_start = 0;
163 recv_end = read(client_fd, recv_buf, buf_size);
164
165 if (recv_end == -1) {
166 if (errno == EAGAIN) {
167 break;
168 } else {
169 fprintf(stderr, "remote_bitbang failed to read on socket: %s (%d)\n",
170 strerror(errno), errno);
171 abort();
172 }
173 }
174
175 if (quit) {
176 fprintf(stderr, "Remote Bitbang received 'Q'\n");
177 }
178
179 if (recv_end == 0 || quit) {
180 // The remote disconnected.
181 fprintf(stderr, "Received nothing. Quitting.\n");
182 close(client_fd);
183 client_fd = 0;
184 break;
185 }
186 }
187 }
188