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