o: ActiveSupport::Cache::Entry :@compressedF:@value"Ϻ"ɺ
| mlab_xvcd.cpp | ||
|---|---|---|
| 14 | 14 |
// 1.03 2012_12 Release version ready to publish |
| 15 | 15 |
// 1.04 2013_04 Socket Bind Error with explanation (multiple instance of XVC Server) |
| 16 | 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 | 18 |
// |
| 18 | 19 |
// |
| 19 | 20 |
// Purpose: |
| ... | ... | |
| 59 | 60 |
// Ask Google about Xilinx Virtual Cable. |
| 60 | 61 |
// |
| 61 | 62 |
// |
| 62 |
// Compilation: |
|
| 63 |
// Compilation for Windows:
|
|
| 63 | 64 |
// |
| 64 | 65 |
// MS Visual C++ 2010 Express (free, registration required) |
| 65 | 66 |
// Create new empty project for Win32 Console Application and name project mlab_xvcd (to build mlab_xvcd.exe) |
| 66 | 67 |
// Header Files / Add / Existing Items - all .h files |
| 67 |
// Resource Files / Add / Existing Items - all .lib files |
|
| 68 | 68 |
// Source Files / Add / Existing Items - all .cpp files |
| 69 |
// Library Files / Add / Existing Items - all .lib .h files from lib_win32 directory |
|
| 69 | 70 |
// Select Release version (no debug info) |
| 70 | 71 |
// Set static linkage Project Properties / Configuration Release / Configuration Properties |
| 71 | 72 |
// / Code Generation / Runtime Library = Multithreaded (/MT) |
| 72 | 73 |
// |
| 74 |
// Compilation for Linux: |
|
| 73 | 75 |
// |
| 76 |
// On Ubuntu 12.04LTS just run the .sh file |
|
| 77 |
// |
|
| 74 | 78 |
// Problems: |
| 75 | 79 |
// |
| 76 | 80 |
// Programming of SPI FLASH configuration memory connected to FPGA does not work. No idea why. |
| ... | ... | |
| 91 | 95 |
#define WIN32_LEAN_AND_MEAN |
| 92 | 96 |
|
| 93 | 97 |
#include "mlab_xvcd.h" // Program Configuration |
| 94 |
#include <windows.h> // Windows Console Application |
|
| 95 |
#include <winsock2.h> // Windows WinSock2 |
|
| 96 |
#include <ws2tcpip.h> // Windows WinSock2 |
|
| 97 | 98 |
#include <stdlib.h> // Standard Library (exit, atoi, ...) |
| 98 | 99 |
#include <stdio.h> // Standard IO (printf, ...) |
| 99 | 100 |
#include <signal.h> // CTRL+C handling |
| 100 | 101 |
|
| 102 |
#ifdef WIN32 |
|
| 103 |
|
|
| 104 |
#include <windows.h> // Windows Console Application |
|
| 105 |
#include <winsock2.h> // Windows WinSock2 |
|
| 106 |
#include <ws2tcpip.h> // Windows WinSock2 |
|
| 107 |
|
|
| 101 | 108 |
// Link with library |
| 102 | 109 |
#pragma comment (lib, "Ws2_32.lib") |
| 110 |
//#pragma comment (lib, "../lib_win32/ftd2xx.lib") // Add this file to Resources |
|
| 103 | 111 |
|
| 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 |
|
|
| 104 | 124 |
#define XVC_RX_BUFLEN (XVC_JTAG_LEN/8*2+20) // Length of receive buffer in bytes (command+length+TMSbuffer+TDIbuffer) |
| 105 | 125 |
#define XVC_TX_BUFLEN (XVC_JTAG_LEN/8) // Length of transmit buffer in bytes (TDObuffer) |
| 106 | 126 |
|
| 127 |
#ifdef WIN32 |
|
| 107 | 128 |
|
| 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 |
|
|
| 108 | 154 |
// JTAG state machine |
| 109 | 155 |
// ------------------ |
| 110 | 156 |
|
| ... | ... | |
| 168 | 214 |
|
| 169 | 215 |
// Read Command |
| 170 | 216 |
char command[16]; |
| 171 |
int commandLen = 0; |
|
| 217 |
unsigned int commandLen = 0;
|
|
| 172 | 218 |
|
| 173 | 219 |
// Read String terminated by ':' |
| 174 | 220 |
do |
| ... | ... | |
| 220 | 266 |
char buffer[2048]; |
| 221 | 267 |
|
| 222 | 268 |
// Read Data (data string for TMS and TDI) |
| 223 |
int nr_bytes = (len + 7) / 8; |
|
| 269 |
unsigned int nr_bytes = (len + 7) / 8;
|
|
| 224 | 270 |
if (nr_bytes * 2 > sizeof(buffer)) |
| 225 | 271 |
{
|
| 226 | 272 |
fprintf(stderr, "Buffer Size Exceeded\n"); |
| 227 | 273 |
return -2; |
| 228 | 274 |
} |
| 229 | 275 |
|
| 230 |
int iReceivedBytes=0; |
|
| 276 |
unsigned int iReceivedBytes=0;
|
|
| 231 | 277 |
while (iReceivedBytes<nr_bytes * 2) |
| 232 | 278 |
{
|
| 233 | 279 |
iResult = recv(ClientSocket, buffer+iReceivedBytes, nr_bytes * 2 - iReceivedBytes, 0); |
| ... | ... | |
| 302 | 348 |
|
| 303 | 349 |
|
| 304 | 350 |
// Stop Handler - switch JTAG port off and stop program |
| 305 |
void stopHandler(int sig)
|
|
| 351 |
void stopHandler(int) |
|
| 306 | 352 |
{
|
| 307 | 353 |
jtagClosePort(); |
| 308 | 354 |
exit(1); |
| ... | ... | |
| 326 | 372 |
} |
| 327 | 373 |
|
| 328 | 374 |
|
| 329 |
int __cdecl main(int argc, char *argv[])
|
|
| 375 |
int main(int argc, char *argv[]) |
|
| 330 | 376 |
{
|
| 331 | 377 |
// Variables |
| 332 | 378 |
bool verbose = true; |
| ... | ... | |
| 388 | 434 |
{
|
| 389 | 435 |
// Empty String - find device by number and number is empty |
| 390 | 436 |
findDeviceBy = 0; |
| 391 |
findDeviceByStr = ""; |
|
| 437 |
findDeviceByStr = (char *)"";
|
|
| 392 | 438 |
} |
| 393 | 439 |
|
| 394 | 440 |
// Find, Init and Open FTDI USB Chip |
| ... | ... | |
| 402 | 448 |
signal(SIGINT, &stopHandler); |
| 403 | 449 |
|
| 404 | 450 |
printf("Starting Network Server\n");
|
| 405 |
WSADATA wsaData; |
|
| 406 | 451 |
int iResult; |
| 407 | 452 |
|
| 408 | 453 |
SOCKET ListenSocket = INVALID_SOCKET; |
| 409 | 454 |
SOCKET ClientSocket = INVALID_SOCKET; |
| 410 | 455 |
|
| 456 |
#ifdef WIN32 |
|
| 411 | 457 |
// Initialize Winsock |
| 458 |
WSADATA wsaData; |
|
| 412 | 459 |
iResult = WSAStartup(MAKEWORD(2,2), &wsaData); |
| 413 | 460 |
if (iResult != 0) |
| 414 | 461 |
{
|
| ... | ... | |
| 416 | 463 |
jtagClosePort(); |
| 417 | 464 |
return -2; |
| 418 | 465 |
} |
| 466 |
#endif |
|
| 419 | 467 |
|
| 420 | 468 |
// Display HostName and Address |
| 421 | 469 |
char sMyName[255]; |
| ... | ... | |
| 436 | 484 |
|
| 437 | 485 |
// Create Protocol Structure |
| 438 | 486 |
struct addrinfo hints; |
| 439 |
ZeroMemory(&hints, sizeof(hints));
|
|
| 487 |
memset(&hints, 0, sizeof(hints));
|
|
| 440 | 488 |
hints.ai_family = AF_INET; // IP6 |
| 441 | 489 |
hints.ai_socktype = SOCK_STREAM; // Reliable two-way connection |
| 442 | 490 |
hints.ai_protocol = IPPROTO_TCP; // Protocol TCP |
| ... | ... | |
| 457 | 505 |
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); |
| 458 | 506 |
if (ListenSocket == INVALID_SOCKET) |
| 459 | 507 |
{
|
| 460 |
fprintf(stderr, "socket failed with error: %ld\n", WSAGetLastError());
|
|
| 508 |
fprintf(stderr, "socket failed with error: %d\n", WSAGetLastError()); |
|
| 461 | 509 |
freeaddrinfo(result); |
| 462 | 510 |
WSACleanup(); |
| 463 | 511 |
jtagClosePort(); |
| ... | ... | |
| 470 | 518 |
{
|
| 471 | 519 |
int LastError=WSAGetLastError(); |
| 472 | 520 |
fprintf(stderr, "Bind failed with error: %d\n", LastError); |
| 473 |
if (LastError==WSAEADDRINUSE) fprintf(stderr, "Trying to start second instance of XVC Server?\n"); |
|
| 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"); |
|
| 474 | 527 |
freeaddrinfo(result); |
| 475 | 528 |
closesocket(ListenSocket); |
| 476 | 529 |
WSACleanup(); |
| ... | ... | |
| 508 | 561 |
|
| 509 | 562 |
// Set ListenSocket to non-blocking mode |
| 510 | 563 |
// We need during waiting for Accept to detect FTDI disconnect |
| 564 |
|
|
| 565 |
#ifdef WIN32 |
|
| 511 | 566 |
u_long iMode = 1; |
| 512 | 567 |
iResult = ioctlsocket(ListenSocket, FIONBIO, &iMode); |
| 513 | 568 |
if (iResult != NO_ERROR) |
| ... | ... | |
| 517 | 572 |
jtagClosePort(); |
| 518 | 573 |
return -2; |
| 519 | 574 |
} |
| 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 |
|
| 520 | 584 |
|
| 521 | 585 |
// Accept a client SOCKET (wait for Accept) |
| 522 | 586 |
sockaddr ClientSocetAddr; |
| 523 |
int ClientSocetAddrLen = sizeof(sockaddr);
|
|
| 587 |
socklen_t ClientSocetAddrLen = sizeof(sockaddr);
|
|
| 524 | 588 |
do |
| 525 | 589 |
{
|
| 526 | 590 |
// Try Accept (non-blocking) |
| ... | ... | |
| 528 | 592 |
if (ClientSocket == INVALID_SOCKET) |
| 529 | 593 |
{
|
| 530 | 594 |
// Accept Error |
| 595 |
#ifdef WIN32 |
|
| 531 | 596 |
if (WSAGetLastError() != WSAEWOULDBLOCK) |
| 597 |
#else |
|
| 598 |
if (WSAGetLastError() != EAGAIN && WSAGetLastError() != EWOULDBLOCK) |
|
| 599 |
#endif |
|
| 532 | 600 |
{
|
| 533 | 601 |
fprintf(stderr, "accept failed with error: %d\n", WSAGetLastError()); |
| 534 | 602 |
closesocket(ListenSocket); |
| ... | ... | |
| 541 | 609 |
// Check FTDI |
| 542 | 610 |
if (!CheckCable()) |
| 543 | 611 |
{
|
| 544 |
fprintf(stderr, "XVC Cable unexpectadly disconnected\n");
|
|
| 612 |
fprintf(stderr, "XVC Cable unexpectedly disconnected\n");
|
|
| 545 | 613 |
closesocket(ListenSocket); |
| 546 | 614 |
WSACleanup(); |
| 547 | 615 |
jtagClosePort(); |
| 548 | 616 |
return -2; |
| 549 | 617 |
} |
| 550 | 618 |
// Sleep some time (do not eat CPU time for nothong) |
| 551 |
//nanosleep();
|
|
| 619 |
#ifdef WIN32
|
|
| 552 | 620 |
Sleep(100); //ms |
| 621 |
#else |
|
| 622 |
usleep(100000); //us |
|
| 623 |
#endif |
|
| 553 | 624 |
} |
| 554 | 625 |
} |
| 555 | 626 |
} |
| 556 | 627 |
while (ClientSocket == INVALID_SOCKET); |
| 557 | 628 |
|
| 558 | 629 |
// Set (Accepted) Socket to blocking mode |
| 630 |
|
|
| 631 |
#ifdef WIN32 |
|
| 559 | 632 |
iMode = 0; |
| 560 | 633 |
iResult = ioctlsocket(ClientSocket, FIONBIO, &iMode); |
| 561 | 634 |
if (iResult != NO_ERROR) |
| ... | ... | |
| 565 | 638 |
jtagClosePort(); |
| 566 | 639 |
return -2; |
| 567 | 640 |
} |
| 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 |
|
| 568 | 650 |
|
| 569 | 651 |
// Print Accepted + Address |
| 570 | 652 |
printf(" Accepted ");
|
| ... | ... | |
| 584 | 666 |
if (iResult>=0) |
| 585 | 667 |
{
|
| 586 | 668 |
printf(".");
|
| 669 |
fflush(stdout); |
|
| 587 | 670 |
Cnt++; |
| 588 | 671 |
if (Cnt>40) |
| 589 | 672 |
{
|
| ... | ... | |
| 605 | 688 |
if (iResult==-2) |
| 606 | 689 |
{
|
| 607 | 690 |
fprintf(stderr, " Disconnect\n"); |
| 691 |
#ifdef WIN32 |
|
| 608 | 692 |
iResult = shutdown(ClientSocket, SD_SEND); |
| 693 |
#else |
|
| 694 |
iResult = shutdown(ClientSocket, SHUT_WR); |
|
| 695 |
#endif |
|
| 609 | 696 |
if (iResult == SOCKET_ERROR) |
| 610 | 697 |
{
|
| 611 | 698 |
fprintf(stderr, "shutdown failed with error: %d\n", WSAGetLastError()); |