Rev 2942 Rev 3090
1 // MLAB Xilinx Virtual Cable Network Server 1 // MLAB Xilinx Virtual Cable Network Server
2 // ---------------------------------------- 2 // ----------------------------------------
3 // 3 //
4 // (c) miho 2012, 2013 http://www.mlab.cz/PermaLink/XVC_SOFTWARE 4 // (c) miho 2012, 2013 http://www.mlab.cz/PermaLink/XVC_SOFTWARE
5 // 5 //
6 // This program if free. 6 // This program if free.
7 // 7 //
8 // 8 //
9 // History: 9 // History:
10 // 10 //
11 // 1.00 2012_09 Proof of concept (no configuration, not for public release) 11 // 1.00 2012_09 Proof of concept (no configuration, not for public release)
12 // 1.01 2012_09 Added parameter for device selection 12 // 1.01 2012_09 Added parameter for device selection
13 // 1.02 2012_12 Error handling and debugged 13 // 1.02 2012_12 Error handling and debugged
14 // 1.03 2012_12 Release version ready to publish 14 // 1.03 2012_12 Release version ready to publish
15 // 1.04 2013_04 Socket Bind Error with explanation (multiple instance of XVC Server) 15 // 1.04 2013_04 Socket Bind Error with explanation (multiple instance of XVC Server)
16 // 1.05 2013_04 Test FTDI cable during wait for Accept (to stop the server immediately when cable is disconnected) 16 // 1.05 2013_04 Test FTDI cable during wait for Accept (to stop the server immediately when cable is disconnected)
17 // 1.06 2013_04 Added support for Linux (thanks to Martin Poviser) 17 // 1.06 2013_04 Added support for Linux (thanks to Martin Poviser)
18 // 1.07 2013_04 Rewritten Host Address function for Linux (function gethostbyname returns 127.0.1.1 on Debian systems) 18 // 1.07 2013_04 Rewritten Host Address function for Linux (function gethostbyname returns 127.0.1.1 on Debian systems)
19 // Solved compatibility problems on Linux (FT_SetLatncyTimer requires delay, udev problem with ftdi_sio driver) 19 // Solved compatibility problems on Linux (FT_SetLatncyTimer requires delay, udev problem with ftdi_sio driver)
-   20 // 1.08 2013_06 Added linux x86_64 variant
20 // 21 //
21 // 22 //
22 // Purpose: 23 // Purpose:
23 // 24 //
24 // XILINX development software (ISE, WebPack) supports several types of JTAG programming 25 // XILINX development software (ISE, WebPack) supports several types of JTAG programming
25 // cables. Among them there is one particularly interesting. It is Xilinx Virtual Cable 26 // cables. Among them there is one particularly interesting. It is Xilinx Virtual Cable
26 // which uses (documented) XVC network protocol to send JTAG commands across TCP/IP network. 27 // which uses (documented) XVC network protocol to send JTAG commands across TCP/IP network.
27 // So it is possible to realize own hardware/software and have it directly supported by 28 // So it is possible to realize own hardware/software and have it directly supported by
28 // XILINX development software (both IMPACT and ChipScope). 29 // XILINX development software (both IMPACT and ChipScope).
29 // 30 //
30 // This program listens TCP data send by XILINX ISE IMAPACT (or ChipScope) and sends it 31 // This program listens TCP data send by XILINX ISE IMAPACT (or ChipScope) and sends it
31 // to the JTAG device (typically FPGA) connected to FTDI USB Chip. You can use ordinary 32 // to the JTAG device (typically FPGA) connected to FTDI USB Chip. You can use ordinary
32 // USB/RS232 translator based on FT232R chip or you can use our own module from 33 // USB/RS232 translator based on FT232R chip or you can use our own module from
33 // http://www.mlab.cz/PermaLink/XVC_FT220X 34 // http://www.mlab.cz/PermaLink/XVC_FT220X
34 // 35 //
35 // Target device JTAG port is connected to pins on FTDI USB chip. Program writes to standard 36 // Target device JTAG port is connected to pins on FTDI USB chip. Program writes to standard
36 // output Which pins are used. Program writes what to set in ISE to enable XVC plugin. 37 // output Which pins are used. Program writes what to set in ISE to enable XVC plugin.
37 // 38 //
38 // 39 //
39 // Environment: 40 // Environment:
40 // 41 //
41 // This is Win32 Console Application and run in WinXP / Win7 / Win8 both 32 and 64 bit. 42 // This is Win32 Console Application and run in WinXP / Win7 / Win8 both 32 and 64 bit.
42 // 43 //
43 // Program needs to listen to the network so it is necessary to allow doing so. In Windows 44 // Program needs to listen to the network so it is necessary to allow doing so. In Windows
44 // firewall configuration enable networking for the exe file. 45 // firewall configuration enable networking for the exe file.
45 // WinXP: run as Administrator c:\WINDOWS\System32\firewall.cpl and add the exe file 46 // WinXP: run as Administrator c:\WINDOWS\System32\firewall.cpl and add the exe file
46 // Win7: the system asks directly to do so 47 // Win7: the system asks directly to do so
47 // 48 //
48 // 49 //
49 // Technology: 50 // Technology:
50 // 51 //
51 // The program uses Windows WINSOCK2 library for network communication 52 // The program uses Windows WINSOCK2 library for network communication
52 // and FTDI ftd2xx library for communication with FTDI USB chip. 53 // and FTDI ftd2xx library for communication with FTDI USB chip.
53 // It can be staticly linked to minimize dependencies on libraries. 54 // It can be staticly linked to minimize dependencies on libraries.
54 // Program requires FTDI drivers installed. 55 // Program requires FTDI drivers installed.
55 // Because of the usage of standard libraries you don't need to solve how to sign drivers. 56 // Because of the usage of standard libraries you don't need to solve how to sign drivers.
56 // 57 //
57 // The program was debug with FT232R and FT220X device. 58 // The program was debug with FT232R and FT220X device.
58 // It should work with any similar FTDI USB chip. 59 // It should work with any similar FTDI USB chip.
59 // 60 //
60 // XVC protocol is documented (you have to ask XILINX support to gain access). 61 // XVC protocol is documented (you have to ask XILINX support to gain access).
61 // The program is inspired by the work http://debugmo.de/2012/02/xvcd-the-xilinx-virtual-cable-daemon/ 62 // The program is inspired by the work http://debugmo.de/2012/02/xvcd-the-xilinx-virtual-cable-daemon/
62 // Ask Google about Xilinx Virtual Cable. 63 // Ask Google about Xilinx Virtual Cable.
63 // 64 //
64 // 65 //
65 // Compilation for Windows: 66 // Compilation for Windows:
66 // 67 //
67 // MS Visual C++ 2010 Express (free, registration required) 68 // MS Visual C++ 2010 Express (free, registration required)
68 // Create new empty project for Win32 Console Application and name project mlab_xvcd (to build mlab_xvcd.exe) 69 // Create new empty project for Win32 Console Application and name project mlab_xvcd (to build mlab_xvcd.exe)
69 // Header Files / Add / Existing Items - all .h files 70 // Header Files / Add / Existing Items - all .h files
70 // Source Files / Add / Existing Items - all .cpp files 71 // Source Files / Add / Existing Items - all .cpp files
71 // Library Files / Add / Existing Items - all .lib .h files from lib_win32 directory 72 // Library Files / Add / Existing Items - all .lib .h files from lib_win32 directory
72 // Select Release version (no debug info) 73 // Select Release version (no debug info)
73 // Set static linkage Project Properties / Configuration Release / Configuration Properties 74 // Set static linkage Project Properties / Configuration Release / Configuration Properties
74 // / Code Generation / Runtime Library = Multithreaded (/MT) 75 // / Code Generation / Runtime Library = Multithreaded (/MT)
75 // 76 //
76 // Compilation for Linux: 77 // Compilation for Linux:
77 // 78 //
78 // On Ubuntu 12.04LTS just run the .sh file 79 // On Ubuntu 12.04LTS just run the .sh file
79 // 80 //
80 // Problems: 81 // Problems:
81 // 82 //
82 // Programming of SPI FLASH configuration memory connected to FPGA does not work. No idea why. 83 // Programming of SPI FLASH configuration memory connected to FPGA does not work. No idea why.
83 // It does not work for internal FLASH of Spartan XC3SxxAN either. 84 // It does not work for internal FLASH of Spartan XC3SxxAN either.
84 // 85 //
85 // 86 //
86 // Possible improvements: 87 // Possible improvements:
87 // 88 //
88 // External definition of JTAG pins. 89 // External definition of JTAG pins.
89 // Enable Socket Number (to be able to run multiple XVC Servers), now it is constant XVC_TCP_PORT (should be only a default) 90 // Enable Socket Number (to be able to run multiple XVC Servers), now it is constant XVC_TCP_PORT (should be only a default)
90   91  
91   92  
92 // Library Definitions 93 // Library Definitions
93 // ------------------- 94 // -------------------
94   95  
95 #undef UNICODE 96 #undef UNICODE
96 #define WIN32_LEAN_AND_MEAN 97 #define WIN32_LEAN_AND_MEAN
97   98  
98 #include "mlab_xvcd.h" // Program Configuration 99 #include "mlab_xvcd.h" // Program Configuration
99 #include <stdlib.h> // Standard Library (exit, atoi, ...) 100 #include <stdlib.h> // Standard Library (exit, atoi, ...)
100 #include <stdio.h> // Standard IO (printf, ...) 101 #include <stdio.h> // Standard IO (printf, ...)
101 #include <signal.h> // CTRL+C handling 102 #include <signal.h> // CTRL+C handling
102   103  
103 #ifdef WIN32 104 #ifdef WIN32
104   105  
105 #include <windows.h> // Windows Console Application 106 #include <windows.h> // Windows Console Application
106 #include <winsock2.h> // Windows WinSock2 107 #include <winsock2.h> // Windows WinSock2
107 #include <ws2tcpip.h> // Windows WinSock2 108 #include <ws2tcpip.h> // Windows WinSock2
108   109  
109 // Link with library 110 // Link with library
110 #pragma comment (lib, "Ws2_32.lib") 111 #pragma comment (lib, "Ws2_32.lib")
111 //#pragma comment (lib, "../lib_win32/ftd2xx.lib") // Add this file to Resources 112 //#pragma comment (lib, "../lib_win32/ftd2xx.lib") // Add this file to Resources
112   113  
113 #else // not WIN32 114 #else // not WIN32
114   115  
115 #include "lib_linux_i386/WinTypes.h" 116 #include "lib_linux/WinTypes.h"
116 #include <sys/types.h> 117 #include <sys/types.h>
117 #include <sys/socket.h> 118 #include <sys/socket.h>
118 #include <fcntl.h> 119 #include <fcntl.h>
119 #include <errno.h> 120 #include <errno.h>
120 #include <unistd.h> 121 #include <unistd.h>
121 #include <netdb.h> 122 #include <netdb.h>
122 #include <net/if.h> 123 #include <net/if.h>
123 #include <sys/ioctl.h> 124 #include <sys/ioctl.h>
124 #include <arpa/inet.h> 125 #include <arpa/inet.h>
125   126  
126 #endif 127 #endif
127   128  
128 #define XVC_RX_BUFLEN (XVC_JTAG_LEN/8*2+20) // Length of receive buffer in bytes (command+length+TMSbuffer+TDIbuffer) 129 #define XVC_RX_BUFLEN (XVC_JTAG_LEN/8*2+20) // Length of receive buffer in bytes (command+length+TMSbuffer+TDIbuffer)
129 #define XVC_TX_BUFLEN (XVC_JTAG_LEN/8) // Length of transmit buffer in bytes (TDObuffer) 130 #define XVC_TX_BUFLEN (XVC_JTAG_LEN/8) // Length of transmit buffer in bytes (TDObuffer)
130   131  
131 #ifdef WIN32 132 #ifdef WIN32
132   133  
133 typedef int socklen_t; 134 typedef int socklen_t;
134   135  
135 #else //not WIN32 136 #else //not WIN32
136   137  
137 typedef int SOCKET; 138 typedef int SOCKET;
138   139  
139 #define SOCKET_ERROR -1 140 #define SOCKET_ERROR -1
140 #define INVALID_SOCKET -1 141 #define INVALID_SOCKET -1
141   142  
142 void closesocket(int socket) 143 void closesocket(int socket)
143 { 144 {
144 close(socket); 145 close(socket);
145 } 146 }
146   147  
147 void WSACleanup() 148 void WSACleanup()
148 { 149 {
149 } 150 }
150   151  
151 int WSAGetLastError() 152 int WSAGetLastError()
152 { 153 {
153 return errno; 154 return errno;
154 } 155 }
155   156  
156 #endif 157 #endif
157   158  
158 // JTAG state machine 159 // JTAG state machine
159 // ------------------ 160 // ------------------
160   161  
161 // JTAG States 162 // JTAG States
162 enum 163 enum
163 { 164 {
164 test_logic_reset, run_test_idle, // Starts from 0 165 test_logic_reset, run_test_idle, // Starts from 0
165   166  
166 select_dr_scan, capture_dr, shift_dr, 167 select_dr_scan, capture_dr, shift_dr,
167 exit1_dr, pause_dr, exit2_dr, update_dr, 168 exit1_dr, pause_dr, exit2_dr, update_dr,
168   169  
169 select_ir_scan, capture_ir, shift_ir, 170 select_ir_scan, capture_ir, shift_ir,
170 exit1_ir, pause_ir, exit2_ir, update_ir, 171 exit1_ir, pause_ir, exit2_ir, update_ir,
171   172  
172 num_states 173 num_states
173 }; 174 };
174   175  
175   176  
176 // JTAG State Machine transfer Function 177 // JTAG State Machine transfer Function
177 static int jtagStep(int state, int tms) 178 static int jtagStep(int state, int tms)
178 { 179 {
179 static const int next_state[num_states][2] = 180 static const int next_state[num_states][2] =
180 { 181 {
181 /* JTAG State -->> New State */ 182 /* JTAG State -->> New State */
182 /* -------------------------------------------------------------*/ 183 /* -------------------------------------------------------------*/
183 /* | TMS=0 | TMS=1 */ 184 /* | TMS=0 | TMS=1 */
184 /* -------------------------------------------------------------*/ 185 /* -------------------------------------------------------------*/
185 /* [test_logic_reset] -> */ { run_test_idle, test_logic_reset }, 186 /* [test_logic_reset] -> */ { run_test_idle, test_logic_reset },
186 /* [run_test_idle] -> */ { run_test_idle, select_dr_scan }, 187 /* [run_test_idle] -> */ { run_test_idle, select_dr_scan },
187 /* [select_dr_scan] -> */ { capture_dr, select_ir_scan }, 188 /* [select_dr_scan] -> */ { capture_dr, select_ir_scan },
188 /* [capture_dr] -> */ { shift_dr, exit1_dr }, 189 /* [capture_dr] -> */ { shift_dr, exit1_dr },
189 /* [shift_dr] -> */ { shift_dr, exit1_dr }, 190 /* [shift_dr] -> */ { shift_dr, exit1_dr },
190 /* [exit1_dr] -> */ { pause_dr, update_dr }, 191 /* [exit1_dr] -> */ { pause_dr, update_dr },
191 /* [pause_dr] -> */ { pause_dr, exit2_dr }, 192 /* [pause_dr] -> */ { pause_dr, exit2_dr },
192 /* [exit2_dr] -> */ { shift_dr, update_dr }, 193 /* [exit2_dr] -> */ { shift_dr, update_dr },
193 /* [update_dr] -> */ { run_test_idle, select_dr_scan }, 194 /* [update_dr] -> */ { run_test_idle, select_dr_scan },
194 /* [select_ir_scan] -> */ { capture_ir, test_logic_reset }, 195 /* [select_ir_scan] -> */ { capture_ir, test_logic_reset },
195 /* [capture_ir] -> */ { shift_ir, exit1_ir }, 196 /* [capture_ir] -> */ { shift_ir, exit1_ir },
196 /* [shift_ir] -> */ { shift_ir, exit1_ir }, 197 /* [shift_ir] -> */ { shift_ir, exit1_ir },
197 /* [exit1_ir] -> */ { pause_ir, update_ir }, 198 /* [exit1_ir] -> */ { pause_ir, update_ir },
198 /* [pause_ir] -> */ { pause_ir, exit2_ir }, 199 /* [pause_ir] -> */ { pause_ir, exit2_ir },
199 /* [exit2_ir] -> */ { shift_ir, update_ir }, 200 /* [exit2_ir] -> */ { shift_ir, update_ir },
200 /* [update_ir] -> */ { run_test_idle, select_dr_scan } 201 /* [update_ir] -> */ { run_test_idle, select_dr_scan }
201 }; 202 };
202   203  
203 return next_state[state][tms]; 204 return next_state[state][tms];
204 } 205 }
205   206  
206   207  
207 int handleData(SOCKET ClientSocket) 208 int handleData(SOCKET ClientSocket)
208 { 209 {
209   210  
210 bool seen_tlr = false; 211 bool seen_tlr = false;
211 bool jtagError = false; 212 bool jtagError = false;
212   213  
213 static int jtag_state; 214 static int jtag_state;
214   215  
215 do 216 do
216 { 217 {
217 int iResult; 218 int iResult;
218   219  
219 // Read Command 220 // Read Command
220 char command[16]; 221 char command[16];
221 unsigned int commandLen = 0; 222 unsigned int commandLen = 0;
222   223  
223 // Read String terminated by ':' 224 // Read String terminated by ':'
224 do 225 do
225 { 226 {
226 iResult = recv(ClientSocket, command+commandLen, 1, 0); 227 iResult = recv(ClientSocket, command+commandLen, 1, 0);
227 if (iResult==0) 228 if (iResult==0)
228 { 229 {
229 printf("\n Connection Closed\n\n"); 230 printf("\n Connection Closed\n\n");
230 return -1; 231 return -1;
231 } 232 }
232 else if (iResult==1) 233 else if (iResult==1)
233 { 234 {
234 commandLen++; 235 commandLen++;
235 } 236 }
236 else 237 else
237 { 238 {
238 fprintf(stderr, "Error Reading Command\n"); 239 fprintf(stderr, "Error Reading Command\n");
239 return -2; 240 return -2;
240 } 241 }
241 } 242 }
242 while (command[commandLen-1]!=':' && commandLen<sizeof(command)-1 ); 243 while (command[commandLen-1]!=':' && commandLen<sizeof(command)-1 );
243 command[commandLen] = char(0); 244 command[commandLen] = char(0);
244   245  
245 if (0==strncmp(command, "shift:", sizeof(command))) 246 if (0==strncmp(command, "shift:", sizeof(command)))
246 { 247 {
247 248
248 } 249 }
249 else 250 else
250 { 251 {
251 fprintf(stderr, "Invalid Command '%s'\n", command); 252 fprintf(stderr, "Invalid Command '%s'\n", command);
252 return -2; 253 return -2;
253 } 254 }
254   255  
255 // Read Length (in bits, 32bit integer) 256 // Read Length (in bits, 32bit integer)
256 int len; 257 int len;
257   258  
258 iResult = recv(ClientSocket, (char *)&len, 4, 0); // pøepsat pøenositelnì 259 iResult = recv(ClientSocket, (char *)&len, 4, 0); // pøepsat pøenositelnì
259 if (iResult==0) 260 if (iResult==0)
260 { 261 {
261 printf("\n Connection Closed\n\n"); 262 printf("\n Connection Closed\n\n");
262 return -1; 263 return -1;
263 } 264 }
264 if (iResult != 4) 265 if (iResult != 4)
265 { 266 {
266 fprintf(stderr, "Reading Length Failed\n"); 267 fprintf(stderr, "Reading Length Failed\n");
267 return -2; 268 return -2;
268 } 269 }
269   270  
270 char buffer[2048]; 271 char buffer[2048];
271   272  
272 // Read Data (data string for TMS and TDI) 273 // Read Data (data string for TMS and TDI)
273 unsigned int nr_bytes = (len + 7) / 8; 274 unsigned int nr_bytes = (len + 7) / 8;
274 if (nr_bytes * 2 > sizeof(buffer)) 275 if (nr_bytes * 2 > sizeof(buffer))
275 { 276 {
276 fprintf(stderr, "Buffer Size Exceeded\n"); 277 fprintf(stderr, "Buffer Size Exceeded\n");
277 return -2; 278 return -2;
278 } 279 }
279   280  
280 unsigned int iReceivedBytes=0; 281 unsigned int iReceivedBytes=0;
281 while (iReceivedBytes<nr_bytes * 2) 282 while (iReceivedBytes<nr_bytes * 2)
282 { 283 {
283 iResult = recv(ClientSocket, buffer+iReceivedBytes, nr_bytes * 2 - iReceivedBytes, 0); 284 iResult = recv(ClientSocket, buffer+iReceivedBytes, nr_bytes * 2 - iReceivedBytes, 0);
284 if (iResult==0) 285 if (iResult==0)
285 { 286 {
286 printf("\n Connection Closed\n\n"); 287 printf("\n Connection Closed\n\n");
287 return -1; 288 return -1;
288 } 289 }
289 if (iResult<=0) 290 if (iResult<=0)
290 { 291 {
291 fprintf(stderr, "Reading Data Failed %d %d\n", iResult, nr_bytes * 2); 292 fprintf(stderr, "Reading Data Failed %d %d\n", iResult, nr_bytes * 2);
292 return -2; 293 return -2;
293 } 294 }
294 iReceivedBytes += iResult; 295 iReceivedBytes += iResult;
295 } 296 }
296   297  
297 char result[1024]; 298 char result[1024];
298 memset(result, 0, nr_bytes); 299 memset(result, 0, nr_bytes);
299   300  
300 // Deal with JTAG 301 // Deal with JTAG
301   302  
302 // Only allow exiting if the state is rti and the IR 303 // Only allow exiting if the state is rti and the IR
303 // has the default value (IDCODE) by going through test_logic_reset. 304 // has the default value (IDCODE) by going through test_logic_reset.
304 // As soon as going through capture_dr or capture_ir no exit is 305 // As soon as going through capture_dr or capture_ir no exit is
305 // allowed as this will change DR/IR. 306 // allowed as this will change DR/IR.
306 seen_tlr = (seen_tlr || jtag_state == test_logic_reset) && (jtag_state != capture_dr) && (jtag_state != capture_ir); 307 seen_tlr = (seen_tlr || jtag_state == test_logic_reset) && (jtag_state != capture_dr) && (jtag_state != capture_ir);
307 308
308 // Due to a weird bug(??) xilinx impacts goes through another "capture_ir"/"capture_dr" cycle after 309 // Due to a weird bug(??) xilinx impacts goes through another "capture_ir"/"capture_dr" cycle after
309 // reading IR/DR which unfortunately sets IR to the read-out IR value. 310 // reading IR/DR which unfortunately sets IR to the read-out IR value.
310 // Just ignore these transactions. 311 // Just ignore these transactions.
311 if ((jtag_state == exit1_ir && len == 5 && buffer[0] == 0x17) || (jtag_state == exit1_dr && len == 4 && buffer[0] == 0x0b)) 312 if ((jtag_state == exit1_ir && len == 5 && buffer[0] == 0x17) || (jtag_state == exit1_dr && len == 4 && buffer[0] == 0x0b))
312 { 313 {
313 // printf("Ignoring Bogus jtag State movement at jtag_state %d\n", jtag_state); 314 // printf("Ignoring Bogus jtag State movement at jtag_state %d\n", jtag_state);
314 } 315 }
315 else 316 else
316 { 317 {
317 for (int i = 0; i < len; ++i) 318 for (int i = 0; i < len; ++i)
318 { 319 {
319 // 320 //
320 // Do the actual cycle. 321 // Do the actual cycle.
321 // 322 //
322 int tms = !!(buffer[i/8] & (1<<(i&7))); 323 int tms = !!(buffer[i/8] & (1<<(i&7)));
323 // 324 //
324 // Track the state. 325 // Track the state.
325 // 326 //
326 jtag_state = jtagStep(jtag_state, tms); 327 jtag_state = jtagStep(jtag_state, tms);
327 } 328 }
328 if (jtagScan((unsigned char *) buffer, (unsigned char *) buffer + nr_bytes, (unsigned char *) result, len) < 0) 329 if (jtagScan((unsigned char *) buffer, (unsigned char *) buffer + nr_bytes, (unsigned char *) result, len) < 0)
329 { 330 {
330 //fprintf(stderr, "jtagScan failed\n"); 331 //fprintf(stderr, "jtagScan failed\n");
331 // Can't stop now, have to sent (any) answer not to hung the IMPACT 332 // Can't stop now, have to sent (any) answer not to hung the IMPACT
332 jtagError = true; 333 jtagError = true;
333 } 334 }
334 } 335 }
335   336  
336 // Send the Ansver 337 // Send the Ansver
337 iResult = send(ClientSocket, result, nr_bytes, 0 ); 338 iResult = send(ClientSocket, result, nr_bytes, 0 );
338 if (iResult == SOCKET_ERROR) 339 if (iResult == SOCKET_ERROR)
339 { 340 {
340 printf("Send Failed with Error: %d\n", WSAGetLastError()); 341 printf("Send Failed with Error: %d\n", WSAGetLastError());
341 closesocket(ClientSocket); 342 closesocket(ClientSocket);
342 WSACleanup(); 343 WSACleanup();
343 return -2; 344 return -2;
344 } 345 }
345 // printf("Bytes Sent: %d\n", iSendResult); 346 // printf("Bytes Sent: %d\n", iSendResult);
346 // printf("jtag state %d\n", jtag_state); 347 // printf("jtag state %d\n", jtag_state);
347 } 348 }
348 while (!(seen_tlr && jtag_state == run_test_idle)); 349 while (!(seen_tlr && jtag_state == run_test_idle));
349   350  
350 return jtagError ? -2 : 0; 351 return jtagError ? -2 : 0;
351 } 352 }
352   353  
353   354  
354 // Stop Handler - switch JTAG port off and stop program 355 // Stop Handler - switch JTAG port off and stop program
355 void stopHandler(int) 356 void stopHandler(int)
356 { 357 {
357 jtagClosePort(); 358 jtagClosePort();
358 exit(1); 359 exit(1);
359 } 360 }
360   361  
361   362  
362 // Print help and stop program with error 363 // Print help and stop program with error
363 void Help(char *progName) 364 void Help(char *progName)
364 { 365 {
365 fprintf(stderr, "Bad Parameters\n"); 366 fprintf(stderr, "Bad Parameters\n");
366 fprintf(stderr, "\n"); 367 fprintf(stderr, "\n");
367 fprintf(stderr, "Usage: %s [arg]\n", progName); 368 fprintf(stderr, "Usage: %s [arg]\n", progName);
368 fprintf(stderr, "\n"); 369 fprintf(stderr, "\n");
369 fprintf(stderr, " Where [arg] is one of: \n"); 370 fprintf(stderr, " Where [arg] is one of: \n");
370 fprintf(stderr, " -d Description Fing FTDI device by Description\n"); 371 fprintf(stderr, " -d Description Fing FTDI device by Description\n");
371 fprintf(stderr, " -l Location Fing FTDI device by Loaction\n"); 372 fprintf(stderr, " -l Location Fing FTDI device by Loaction\n");
372 fprintf(stderr, " -s Serial_number Fing FTDI device by it's SN\n"); 373 fprintf(stderr, " -s Serial_number Fing FTDI device by it's SN\n");
373 fprintf(stderr, " -n Number Use N-th FTDI device\n"); 374 fprintf(stderr, " -n Number Use N-th FTDI device\n");
374 fprintf(stderr, " The first FTDI device is used if no argument\n"); 375 fprintf(stderr, " The first FTDI device is used if no argument\n");
375 exit(2); 376 exit(2);
376 } 377 }
377   378  
378   379  
379 int main(int argc, char *argv[]) 380 int main(int argc, char *argv[])
380 { 381 {
381 // Variables 382 // Variables
382 bool verbose = true; 383 bool verbose = true;
383   384  
384 // Program Info 385 // Program Info
385 printf("\n"); 386 printf("\n");
386 printf("Xilinx Virtual Cable Network Server\n"); 387 printf("Xilinx Virtual Cable Network Server\n");
387 printf("===================================\n"); 388 printf("===================================\n");
388 printf("(c) miho " YEAR " v " VERSION "\n\n"); 389 printf("(c) miho " YEAR " v " VERSION "\n\n");
389   390  
390 // Get program name 391 // Get program name
391 char *cp; 392 char *cp;
392 char *progName; 393 char *progName;
393 cp = argv[0]; 394 cp = argv[0];
394 progName=cp; 395 progName=cp;
395 while (cp[0]!='\0') 396 while (cp[0]!='\0')
396 { 397 {
397 if (cp[0]=='/' || cp[0]=='\\') 398 if (cp[0]=='/' || cp[0]=='\\')
398 progName=cp+1; 399 progName=cp+1;
399 cp++; 400 cp++;
400 } 401 }
401   402  
402 // Process command line params 403 // Process command line params
403 char *findDeviceByStr = 0; // String parameter 404 char *findDeviceByStr = 0; // String parameter
404 int findDeviceBy = 0; // What does the string means 405 int findDeviceBy = 0; // What does the string means
405   406  
406 if (argc>1) 407 if (argc>1)
407 { 408 {
408 if (argc==3) 409 if (argc==3)
409 { 410 {
410 findDeviceByStr = argv[2]; 411 findDeviceByStr = argv[2];
411 if (strcmp(argv[1], "-d")==0) 412 if (strcmp(argv[1], "-d")==0)
412 { 413 {
413 findDeviceBy = OPEN_BY_DESCRIPTION; 414 findDeviceBy = OPEN_BY_DESCRIPTION;
414 } 415 }
415 else if (strcmp(argv[1], "-l")==0) 416 else if (strcmp(argv[1], "-l")==0)
416 { 417 {
417 findDeviceBy = OPEN_BY_LOCATION; 418 findDeviceBy = OPEN_BY_LOCATION;
418 } 419 }
419 else if (strcmp(argv[1], "-s")==0) 420 else if (strcmp(argv[1], "-s")==0)
420 { 421 {
421 findDeviceBy = OPEN_BY_SERIAL_NUMBER; 422 findDeviceBy = OPEN_BY_SERIAL_NUMBER;
422 } 423 }
423 else if (strcmp(argv[1], "-n")==0) 424 else if (strcmp(argv[1], "-n")==0)
424 { 425 {
425 findDeviceBy = 0; 426 findDeviceBy = 0;
426 } 427 }
427 else 428 else
428 { 429 {
429 Help(progName); 430 Help(progName);
430 } 431 }
431 } 432 }
432 else 433 else
433 { 434 {
434 Help(progName); 435 Help(progName);
435 } 436 }
436 } 437 }
437 else 438 else
438 { 439 {
439 // Empty String - find device by number and number is empty 440 // Empty String - find device by number and number is empty
440 findDeviceBy = 0; 441 findDeviceBy = 0;
441 findDeviceByStr = (char *)""; 442 findDeviceByStr = (char *)"";
442 } 443 }
443   444  
444 // Find, Init and Open FTDI USB Chip 445 // Find, Init and Open FTDI USB Chip
445 if (jtagOpenPort(findDeviceBy, findDeviceByStr)<0) { 446 if (jtagOpenPort(findDeviceBy, findDeviceByStr)<0) {
446 // No Device Found 447 // No Device Found
447 fprintf(stderr, "ERROR: No Device Found\n"); 448 fprintf(stderr, "ERROR: No Device Found\n");
448 return -1; 449 return -1;
449 } 450 }
450   451  
451 // Signal Handler (for CRTL+C) 452 // Signal Handler (for CRTL+C)
452 signal(SIGINT, &stopHandler); 453 signal(SIGINT, &stopHandler);
453   454  
454 printf("Starting Network Server\n"); 455 printf("Starting Network Server\n");
455 int iResult; 456 int iResult;
456   457  
457 SOCKET ListenSocket = INVALID_SOCKET; 458 SOCKET ListenSocket = INVALID_SOCKET;
458 SOCKET ClientSocket = INVALID_SOCKET; 459 SOCKET ClientSocket = INVALID_SOCKET;
459   460  
460 #ifdef WIN32 461 #ifdef WIN32
461 // Initialize Winsock 462 // Initialize Winsock
462 WSADATA wsaData; 463 WSADATA wsaData;
463 iResult = WSAStartup(MAKEWORD(2,2), &wsaData); 464 iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
464 if (iResult != 0) 465 if (iResult != 0)
465 { 466 {
466 fprintf(stderr, "WSAStartup failed with error: %d\n", iResult); 467 fprintf(stderr, "WSAStartup failed with error: %d\n", iResult);
467 jtagClosePort(); 468 jtagClosePort();
468 return -2; 469 return -2;
469 } 470 }
470 #endif 471 #endif
471   472  
472 // Display HostName 473 // Display HostName
473 char sMyName[255]; 474 char sMyName[255];
474 gethostname(sMyName, sizeof(sMyName)); 475 gethostname(sMyName, sizeof(sMyName));
475 printf(" Host Name %s\n", sMyName); 476 printf(" Host Name %s\n", sMyName);
476   477  
477 // Display Address 478 // Display Address
478 #ifdef WIN32 479 #ifdef WIN32
479 hostent * pHostInfo; 480 hostent * pHostInfo;
480 pHostInfo = gethostbyname(sMyName); 481 pHostInfo = gethostbyname(sMyName);
481 printf(" Network Name %s\n", pHostInfo->h_name); 482 printf(" Network Name %s\n", pHostInfo->h_name);
482 if (pHostInfo->h_length>0 && pHostInfo->h_length<=16) 483 if (pHostInfo->h_length>0 && pHostInfo->h_length<=16)
483 { 484 {
484 printf(" Host Address "); 485 printf(" Host Address ");
485 for (int i=0; i<pHostInfo->h_length-1; i++) 486 for (int i=0; i<pHostInfo->h_length-1; i++)
486 { 487 {
487 printf("%d.", (unsigned char)pHostInfo->h_addr_list[0][i]); 488 printf("%d.", (unsigned char)pHostInfo->h_addr_list[0][i]);
488 } 489 }
489 printf("%d\n", (unsigned char)pHostInfo->h_addr_list[0][pHostInfo->h_length-1]); 490 printf("%d\n", (unsigned char)pHostInfo->h_addr_list[0][pHostInfo->h_length-1]);
490 } 491 }
491 #else 492 #else
492 int TempSocket; 493 int TempSocket;
493 struct ifreq ifreqs[20]; 494 struct ifreq ifreqs[20];
494 struct ifconf ic; 495 struct ifconf ic;
495   496  
496 ic.ifc_len = sizeof ifreqs; 497 ic.ifc_len = sizeof ifreqs;
497 ic.ifc_req = ifreqs; 498 ic.ifc_req = ifreqs;
498   499  
499 TempSocket = socket(AF_INET, SOCK_DGRAM, 0); 500 TempSocket = socket(AF_INET, SOCK_DGRAM, 0);
500 if (TempSocket < 0) { 501 if (TempSocket < 0) {
501 perror("socket"); 502 perror("socket");
502 return -2; 503 return -2;
503 } 504 }
504   505  
505 if (ioctl(TempSocket, SIOCGIFCONF, &ic) < 0) { 506 if (ioctl(TempSocket, SIOCGIFCONF, &ic) < 0) {
506 perror("SIOCGIFCONF"); 507 perror("SIOCGIFCONF");
507 return -2; 508 return -2;
508 } 509 }
509   510  
510 for (int i = 0; i < ic.ifc_len/sizeof(struct ifreq); ++i) 511 for (int i = 0; i < ic.ifc_len/sizeof(struct ifreq); ++i)
511 { 512 {
512 if (ifreqs[i].ifr_name[0]!='l')// remove lo 513 if (ifreqs[i].ifr_name[0]!='l')// remove lo
513 printf(" Host Address %s: %s\n", 514 printf(" Host Address %s: %s\n",
514 ifreqs[i].ifr_name, 515 ifreqs[i].ifr_name,
515 inet_ntoa(((struct sockaddr_in*)&ifreqs[i].ifr_addr)->sin_addr)); 516 inet_ntoa(((struct sockaddr_in*)&ifreqs[i].ifr_addr)->sin_addr));
516 } 517 }
517 #endif 518 #endif
518   519  
519 // Create Protocol Structure 520 // Create Protocol Structure
520 struct addrinfo hints; 521 struct addrinfo hints;
521 memset(&hints, 0, sizeof(hints)); 522 memset(&hints, 0, sizeof(hints));
522 hints.ai_family = AF_INET; // IP6 523 hints.ai_family = AF_INET; // IP6
523 hints.ai_socktype = SOCK_STREAM; // Reliable two-way connection 524 hints.ai_socktype = SOCK_STREAM; // Reliable two-way connection
524 hints.ai_protocol = IPPROTO_TCP; // Protocol TCP 525 hints.ai_protocol = IPPROTO_TCP; // Protocol TCP
525 hints.ai_flags = AI_PASSIVE; 526 hints.ai_flags = AI_PASSIVE;
526   527  
527 // Resolve the server address and port (allocate structure "result") 528 // Resolve the server address and port (allocate structure "result")
528 struct addrinfo *result = NULL; 529 struct addrinfo *result = NULL;
529 iResult = getaddrinfo(NULL, XVC_TCP_PORT, &hints, &result); 530 iResult = getaddrinfo(NULL, XVC_TCP_PORT, &hints, &result);
530 if ( iResult != 0 ) 531 if ( iResult != 0 )
531 { 532 {
532 fprintf(stderr, "getaddrinfo failed with error: %d\n", iResult); 533 fprintf(stderr, "getaddrinfo failed with error: %d\n", iResult);
533 WSACleanup(); 534 WSACleanup();
534 jtagClosePort(); 535 jtagClosePort();
535 return -2; 536 return -2;
536 } 537 }
537   538  
538 // Create a SOCKET 539 // Create a SOCKET
539 ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); 540 ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
540 if (ListenSocket == INVALID_SOCKET) 541 if (ListenSocket == INVALID_SOCKET)
541 { 542 {
542 fprintf(stderr, "socket failed with error: %d\n", WSAGetLastError()); 543 fprintf(stderr, "socket failed with error: %d\n", WSAGetLastError());
543 freeaddrinfo(result); 544 freeaddrinfo(result);
544 WSACleanup(); 545 WSACleanup();
545 jtagClosePort(); 546 jtagClosePort();
546 return -2; 547 return -2;
547 } 548 }
548   549  
549 // Bind the SOCKED (assign the address) 550 // Bind the SOCKED (assign the address)
550 iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); 551 iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
551 if (iResult == SOCKET_ERROR) 552 if (iResult == SOCKET_ERROR)
552 { 553 {
553 int LastError=WSAGetLastError(); 554 int LastError=WSAGetLastError();
554 fprintf(stderr, "Bind failed with error: %d\n", LastError); 555 fprintf(stderr, "Bind failed with error: %d\n", LastError);
555 #ifdef WIN32 556 #ifdef WIN32
556 if (LastError==WSAEADDRINUSE) 557 if (LastError==WSAEADDRINUSE)
557 #else 558 #else
558 if (LastError==EADDRINUSE) 559 if (LastError==EADDRINUSE)
559 #endif 560 #endif
560 fprintf(stderr, "Trying to start second instance of XVC Server?\n"); 561 fprintf(stderr, "Trying to start second instance of XVC Server?\n");
561 freeaddrinfo(result); 562 freeaddrinfo(result);
562 closesocket(ListenSocket); 563 closesocket(ListenSocket);
563 WSACleanup(); 564 WSACleanup();
564 jtagClosePort(); 565 jtagClosePort();
565 return -2; 566 return -2;
566 } 567 }
567   568  
568 if (verbose) 569 if (verbose)
569 { 570 {
570 printf(" Bound Socket %s\n", XVC_TCP_PORT); 571 printf(" Bound Socket %s\n", XVC_TCP_PORT);
571 } 572 }
572   573  
573 // Help for user 574 // Help for user
574 printf(" Set in IMPACT xilinx_xvc host=%s:%s disableversioncheck=true\n", sMyName, XVC_TCP_PORT); 575 printf(" Set in IMPACT xilinx_xvc host=%s:%s disableversioncheck=true\n", sMyName, XVC_TCP_PORT);
575   576  
576 freeaddrinfo(result); 577 freeaddrinfo(result);
577   578  
578 // Listen SOCKET 579 // Listen SOCKET
579 iResult = listen(ListenSocket, SOMAXCONN); 580 iResult = listen(ListenSocket, SOMAXCONN);
580 if (iResult == SOCKET_ERROR) 581 if (iResult == SOCKET_ERROR)
581 { 582 {
582 fprintf(stderr, "listen failed with error: %d\n", WSAGetLastError()); 583 fprintf(stderr, "listen failed with error: %d\n", WSAGetLastError());
583 closesocket(ListenSocket); 584 closesocket(ListenSocket);
584 WSACleanup(); 585 WSACleanup();
585 jtagClosePort(); 586 jtagClosePort();
586 return -2; 587 return -2;
587 } 588 }
588   589  
589 printf("\n"); 590 printf("\n");
590   591  
591 do 592 do
592 { 593 {
593 printf(" Listen\n"); 594 printf(" Listen\n");
594 jtagSetLED(true); 595 jtagSetLED(true);
595   596  
596 // Set ListenSocket to non-blocking mode 597 // Set ListenSocket to non-blocking mode
597 // We need during waiting for Accept to detect FTDI disconnect 598 // We need during waiting for Accept to detect FTDI disconnect
598   599  
599 #ifdef WIN32 600 #ifdef WIN32
600 u_long iMode = 1; 601 u_long iMode = 1;
601 iResult = ioctlsocket(ListenSocket, FIONBIO, &iMode); 602 iResult = ioctlsocket(ListenSocket, FIONBIO, &iMode);
602 if (iResult != NO_ERROR) 603 if (iResult != NO_ERROR)
603 { 604 {
604 fprintf(stderr, "ioctlsocket failed with error: %ld\n", iResult); 605 fprintf(stderr, "ioctlsocket failed with error: %ld\n", iResult);
605 WSACleanup(); 606 WSACleanup();
606 jtagClosePort(); 607 jtagClosePort();
607 return -2; 608 return -2;
608 } 609 }
609 #else 610 #else
610 iResult = fcntl(ListenSocket, F_GETFL, 0); 611 iResult = fcntl(ListenSocket, F_GETFL, 0);
611 if (iResult < 0 || fcntl(ListenSocket, F_SETFL, iResult | O_NONBLOCK) < 0) 612 if (iResult < 0 || fcntl(ListenSocket, F_SETFL, iResult | O_NONBLOCK) < 0)
612 { 613 {
613 fprintf(stderr, "fcntl failed with error: %d\n", errno); 614 fprintf(stderr, "fcntl failed with error: %d\n", errno);
614 jtagClosePort(); 615 jtagClosePort();
615 return -2; 616 return -2;
616 } 617 }
617 #endif 618 #endif
618   619  
619 // Accept a client SOCKET (wait for Accept) 620 // Accept a client SOCKET (wait for Accept)
620 sockaddr ClientSocetAddr; 621 sockaddr ClientSocetAddr;
621 socklen_t ClientSocetAddrLen = sizeof(sockaddr); 622 socklen_t ClientSocetAddrLen = sizeof(sockaddr);
622 do 623 do
623 { 624 {
624 // Try Accept (non-blocking) 625 // Try Accept (non-blocking)
625 ClientSocket = accept(ListenSocket, &ClientSocetAddr, &ClientSocetAddrLen); 626 ClientSocket = accept(ListenSocket, &ClientSocetAddr, &ClientSocetAddrLen);
626 if (ClientSocket == INVALID_SOCKET) 627 if (ClientSocket == INVALID_SOCKET)
627 { 628 {
628 // Accept Error 629 // Accept Error
629 #ifdef WIN32 630 #ifdef WIN32
630 if (WSAGetLastError() != WSAEWOULDBLOCK) 631 if (WSAGetLastError() != WSAEWOULDBLOCK)
631 #else 632 #else
632 if (WSAGetLastError() != EAGAIN && WSAGetLastError() != EWOULDBLOCK) 633 if (WSAGetLastError() != EAGAIN && WSAGetLastError() != EWOULDBLOCK)
633 #endif 634 #endif
634 { 635 {
635 fprintf(stderr, "accept failed with error: %d\n", WSAGetLastError()); 636 fprintf(stderr, "accept failed with error: %d\n", WSAGetLastError());
636 closesocket(ListenSocket); 637 closesocket(ListenSocket);
637 WSACleanup(); 638 WSACleanup();
638 jtagClosePort(); 639 jtagClosePort();
639 return -2; 640 return -2;
640 } 641 }
641 // Not yet Accepted 642 // Not yet Accepted
642 { 643 {
643 // Check FTDI 644 // Check FTDI
644 if (!CheckCable()) 645 if (!CheckCable())
645 { 646 {
646 fprintf(stderr, "XVC Cable unexpectedly disconnected\n"); 647 fprintf(stderr, "XVC Cable unexpectedly disconnected\n");
647 closesocket(ListenSocket); 648 closesocket(ListenSocket);
648 WSACleanup(); 649 WSACleanup();
649 jtagClosePort(); 650 jtagClosePort();
650 return -2; 651 return -2;
651 } 652 }
652 // Sleep some time (do not eat CPU time for nothong) 653 // Sleep some time (do not eat CPU time for nothong)
653 #ifdef WIN32 654 #ifdef WIN32
654 Sleep(100); //ms 655 Sleep(100); //ms
655 #else 656 #else
656 usleep(100000); //us 657 usleep(100000); //us
657 #endif 658 #endif
658 } 659 }
659 } 660 }
660 } 661 }
661 while (ClientSocket == INVALID_SOCKET); 662 while (ClientSocket == INVALID_SOCKET);
662   663  
663 // Set (Accepted) Socket to blocking mode 664 // Set (Accepted) Socket to blocking mode
664   665  
665 #ifdef WIN32 666 #ifdef WIN32
666 iMode = 0; 667 iMode = 0;
667 iResult = ioctlsocket(ClientSocket, FIONBIO, &iMode); 668 iResult = ioctlsocket(ClientSocket, FIONBIO, &iMode);
668 if (iResult != NO_ERROR) 669 if (iResult != NO_ERROR)
669 { 670 {
670 fprintf(stderr, "ioctlsocket failed with error: %ld\n", iResult); 671 fprintf(stderr, "ioctlsocket failed with error: %ld\n", iResult);
671 WSACleanup(); 672 WSACleanup();
672 jtagClosePort(); 673 jtagClosePort();
673 return -2; 674 return -2;
674 } 675 }
675 #else 676 #else
676 iResult = fcntl(ListenSocket, F_GETFL, 0); 677 iResult = fcntl(ListenSocket, F_GETFL, 0);
677 if (iResult < 0 || fcntl(ListenSocket, F_SETFL, iResult & ~O_NONBLOCK) < 0) 678 if (iResult < 0 || fcntl(ListenSocket, F_SETFL, iResult & ~O_NONBLOCK) < 0)
678 { 679 {
679 fprintf(stderr, "fcntl failed with error: %d\n", errno); 680 fprintf(stderr, "fcntl failed with error: %d\n", errno);
680 jtagClosePort(); 681 jtagClosePort();
681 return -2; 682 return -2;
682 } 683 }
683 #endif 684 #endif
684   685  
685 // Print Accepted + Address 686 // Print Accepted + Address
686 printf(" Accepted "); 687 printf(" Accepted ");
687 jtagSetLED(false); 688 jtagSetLED(false);
688 for (int i=2; i<2+4-1; i++) 689 for (int i=2; i<2+4-1; i++)
689 { 690 {
690 printf("%d.", (unsigned char)ClientSocetAddr.sa_data[i]); 691 printf("%d.", (unsigned char)ClientSocetAddr.sa_data[i]);
691 } 692 }
692 printf("%d:%d\n", (unsigned char)ClientSocetAddr.sa_data[2+4-1], (unsigned char)ClientSocetAddr.sa_data[0]*256+(unsigned char)ClientSocetAddr.sa_data[1]); 693 printf("%d:%d\n", (unsigned char)ClientSocetAddr.sa_data[2+4-1], (unsigned char)ClientSocetAddr.sa_data[0]*256+(unsigned char)ClientSocetAddr.sa_data[1]);
693   694  
694 // Process Data until the peer shuts down the connection 695 // Process Data until the peer shuts down the connection
695 int Cnt = 0; 696 int Cnt = 0;
696 printf(" Handle Data "); 697 printf(" Handle Data ");
697 do 698 do
698 { 699 {
699 iResult = handleData(ClientSocket); 700 iResult = handleData(ClientSocket);
700 if (iResult>=0) 701 if (iResult>=0)
701 { 702 {
702 printf("."); 703 printf(".");
703 fflush(stdout); 704 fflush(stdout);
704 Cnt++; 705 Cnt++;
705 if (Cnt>40) 706 if (Cnt>40)
706 { 707 {
707 Cnt = 0; 708 Cnt = 0;
708 printf("\n "); 709 printf("\n ");
709 } 710 }
710 } 711 }
711 } 712 }
712 while (iResult >= 0); 713 while (iResult >= 0);
713   714  
714 // Connection Closed by peer 715 // Connection Closed by peer
715 if (iResult==-1) 716 if (iResult==-1)
716 { 717 {
717 // JTAG port 718 // JTAG port
718 jtagSetIdle(); 719 jtagSetIdle();
719 } 720 }
720   721  
721 // Error - shutdown the connection 722 // Error - shutdown the connection
722 if (iResult==-2) 723 if (iResult==-2)
723 { 724 {
724 fprintf(stderr, " Disconnect\n"); 725 fprintf(stderr, " Disconnect\n");
725 #ifdef WIN32 726 #ifdef WIN32
726 iResult = shutdown(ClientSocket, SD_SEND); 727 iResult = shutdown(ClientSocket, SD_SEND);
727 #else 728 #else
728 iResult = shutdown(ClientSocket, SHUT_WR); 729 iResult = shutdown(ClientSocket, SHUT_WR);
729 #endif 730 #endif
730 if (iResult == SOCKET_ERROR) 731 if (iResult == SOCKET_ERROR)
731 { 732 {
732 fprintf(stderr, "shutdown failed with error: %d\n", WSAGetLastError()); 733 fprintf(stderr, "shutdown failed with error: %d\n", WSAGetLastError());
733 } 734 }
734 iResult=-2; // Error 735 iResult=-2; // Error
735 } 736 }
736   737  
737 // cleanup 738 // cleanup
738 closesocket(ClientSocket); 739 closesocket(ClientSocket);
739   740  
740 } 741 }
741 // If not Error Listen Again 742 // If not Error Listen Again
742 while (iResult!=-2); 743 while (iResult!=-2);
743   744  
744 // cleanup 745 // cleanup
745 closesocket(ListenSocket); 746 closesocket(ListenSocket);
746 WSACleanup(); 747 WSACleanup();
747 jtagClosePort(); 748 jtagClosePort();
748   749  
749 return 1; 750 return 1;
750 } 751 }