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