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