From 30ae45ec2b3339a4ad9b4be703cecbc093e9e871 Mon Sep 17 00:00:00 2001 From: Malcolm Robb Date: Fri, 25 Apr 2014 14:48:14 +0100 Subject: [PATCH] Windows Version of dump1090 Make the modifications necessary to compile dump1090 for WinXP, Win7 and hopefully Win8. The files can be compiled using M$ Visual Studio/C++ 6.0. Due to various licensing issues, I haven't included the libraries or DLLs. You will need to locate pthreadVC2.lib and rtlsdr.lib to link the file, install the zadig drivers to support the dongle, and locate libusb-1.0.dll, msvcr100.dll, pthreadVC2.dll and rtlsdr.dll. dump1090.exe will not run on any Windows version prior to XP SP2, because msvcr100.dll imports several functions from the Windows kernel that are not available on earlier versions. This means dump1090 won't work on Win2K. The major change to the code relates to file handles. The original code assumes Linux behaviour in that handles are allocated from 0 sequentially upwards. However Windows handles are allocated pseudo randomly, and handle numbers greater than 1024 would break the code. The code has therefore been modified to use a linked list of connection structures, rather than a static array limited to 1024 entries. --- Release/dump1090.bat | 1 + Release/dump1090.exe | Bin 0 -> 110592 bytes Release/view1090.exe | Bin 90112 -> 90112 bytes anet.c | 142 ++-- coaa1090.obj | Bin 18424 -> 18316 bytes dump1090.c | 40 ++ dump1090.dsp | 148 +++++ dump1090.dsw | 41 ++ dump1090.h | 38 +- net_io.c | 142 ++-- ppup1090.c | 55 +- pthreads/pthread.h | 1368 +++++++++++++++++++++++++++++++++++++++ pthreads/sched.h | 183 ++++++ pthreads/semaphore.h | 169 +++++ rtlsdr/rtl-sdr.h | 366 +++++++++++ rtlsdr/rtl-sdr_export.h | 47 ++ view1090.c | 58 +- view1090.dsp | 149 +++++ winstubs.h | 110 ++++ 19 files changed, 2869 insertions(+), 188 deletions(-) create mode 100644 Release/dump1090.bat create mode 100644 Release/dump1090.exe create mode 100644 dump1090.dsp create mode 100644 dump1090.dsw create mode 100644 pthreads/pthread.h create mode 100644 pthreads/sched.h create mode 100644 pthreads/semaphore.h create mode 100644 rtlsdr/rtl-sdr.h create mode 100644 rtlsdr/rtl-sdr_export.h create mode 100644 view1090.dsp create mode 100644 winstubs.h diff --git a/Release/dump1090.bat b/Release/dump1090.bat new file mode 100644 index 0000000..dab0b46 --- /dev/null +++ b/Release/dump1090.bat @@ -0,0 +1 @@ +dump1090.exe --interactive --net --net-ro-size 500 --net-ro-rate 5 \ No newline at end of file diff --git a/Release/dump1090.exe b/Release/dump1090.exe new file mode 100644 index 0000000000000000000000000000000000000000..bb8a2a15654763402ccbcbd7cc9f8bf9105beba9 GIT binary patch literal 110592 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 literal 0 HcmV?d00001 diff --git a/Release/view1090.exe b/Release/view1090.exe index db55062a5d4a1b5149fca442282d646bf7d7a6d2..21a927edf04959ef7ed0241cd4fdcb84c3492731 100644 GIT binary patch delta 23831 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%0ASXgHAKpAg*;`LcP@p&V=@Uk+4oJ9Q2nJo_F+FxO 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 delta 23958 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#ifndef _WIN32 + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#else + #include "winstubs.h" //Put everything Windows specific in here + #include "dump1090.h" +#endif #include "anet.h" @@ -58,7 +63,7 @@ static void anetSetError(char *err, const char *fmt, ...) int anetNonBlock(char *err, int fd) { int flags; - +#ifndef _WIN32 /* Set the socket nonblocking. * Note that fcntl(2) for F_GETFL and F_SETFL can't be * interrupted by a signal. */ @@ -70,13 +75,21 @@ int anetNonBlock(char *err, int fd) anetSetError(err, "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno)); return ANET_ERR; } +#else + flags = 1; + if (ioctlsocket(fd, FIONBIO, &flags)) { + errno = WSAGetLastError(); + anetSetError(err, "ioctlsocket(FIONBIO): %s", strerror(errno)); + return ANET_ERR; + } +#endif return ANET_OK; } int anetTcpNoDelay(char *err, int fd) { int yes = 1; - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(yes)) == -1) { anetSetError(err, "setsockopt TCP_NODELAY: %s", strerror(errno)); return ANET_ERR; @@ -86,7 +99,7 @@ int anetTcpNoDelay(char *err, int fd) int anetSetSendBuffer(char *err, int fd, int buffsize) { - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1) + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&buffsize, sizeof(buffsize)) == -1) { anetSetError(err, "setsockopt SO_SNDBUF: %s", strerror(errno)); return ANET_ERR; @@ -97,7 +110,7 @@ int anetSetSendBuffer(char *err, int fd, int buffsize) int anetTcpKeepAlive(char *err, int fd) { int yes = 1; - if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) { + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&yes, sizeof(yes)) == -1) { anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); return ANET_ERR; } @@ -109,7 +122,7 @@ int anetResolve(char *err, char *host, char *ipbuf) struct sockaddr_in sa; sa.sin_family = AF_INET; - if (inet_aton(host, &sa.sin_addr) == 0) { + if (inet_aton(host, (void*)&sa.sin_addr) == 0) { struct hostent *he; he = gethostbyname(host); @@ -132,7 +145,7 @@ static int anetCreateSocket(char *err, int domain) { /* Make sure connection-intensive things like the redis benckmark * will be able to close/open sockets a zillion of times */ - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) == -1) { anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno)); return ANET_ERR; } @@ -150,8 +163,8 @@ static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) return ANET_ERR; sa.sin_family = AF_INET; - sa.sin_port = htons(port); - if (inet_aton(addr, &sa.sin_addr) == 0) { + sa.sin_port = htons((uint16_t)port); + if (inet_aton(addr, (void*)&sa.sin_addr) == 0) { struct hostent *he; he = gethostbyname(addr); @@ -188,42 +201,6 @@ int anetTcpNonBlockConnect(char *err, char *addr, int port) return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONBLOCK); } -int anetUnixGenericConnect(char *err, char *path, int flags) -{ - int s; - struct sockaddr_un sa; - - if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR) - return ANET_ERR; - - sa.sun_family = AF_LOCAL; - strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); - if (flags & ANET_CONNECT_NONBLOCK) { - if (anetNonBlock(err,s) != ANET_OK) - return ANET_ERR; - } - if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) == -1) { - if (errno == EINPROGRESS && - flags & ANET_CONNECT_NONBLOCK) - return s; - - anetSetError(err, "connect: %s", strerror(errno)); - close(s); - return ANET_ERR; - } - return s; -} - -int anetUnixConnect(char *err, char *path) -{ - return anetUnixGenericConnect(err,path,ANET_CONNECT_NONE); -} - -int anetUnixNonBlockConnect(char *err, char *path) -{ - return anetUnixGenericConnect(err,path,ANET_CONNECT_NONBLOCK); -} - /* Like read(2) but make sure 'count' is read before to return * (unless error or EOF condition is encountered) */ int anetRead(int fd, char *buf, int count) @@ -256,6 +233,9 @@ int anetWrite(int fd, char *buf, int count) static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) { if (bind(s,sa,len) == -1) { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif anetSetError(err, "bind: %s", strerror(errno)); close(s); return ANET_ERR; @@ -265,6 +245,9 @@ static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) { * the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); * which will thus give us a backlog of 512 entries */ if (listen(s, 511) == -1) { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif anetSetError(err, "listen: %s", strerror(errno)); close(s); return ANET_ERR; @@ -282,9 +265,9 @@ int anetTcpServer(char *err, int port, char *bindaddr) memset(&sa,0,sizeof(sa)); sa.sin_family = AF_INET; - sa.sin_port = htons(port); + sa.sin_port = htons((uint16_t)port); sa.sin_addr.s_addr = htonl(INADDR_ANY); - if (bindaddr && inet_aton(bindaddr, &sa.sin_addr) == 0) { + if (bindaddr && inet_aton(bindaddr, (void*)&sa.sin_addr) == 0) { anetSetError(err, "invalid bind address"); close(s); return ANET_ERR; @@ -294,32 +277,21 @@ int anetTcpServer(char *err, int port, char *bindaddr) return s; } -int anetUnixServer(char *err, char *path, mode_t perm) -{ - int s; - struct sockaddr_un sa; - - if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR) - return ANET_ERR; - - memset(&sa,0,sizeof(sa)); - sa.sun_family = AF_LOCAL; - strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); - if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa)) == ANET_ERR) - return ANET_ERR; - if (perm) - chmod(sa.sun_path, perm); - return s; -} - static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) { int fd; while(1) { fd = accept(s,sa,len); if (fd == -1) { - if (errno == EINTR) +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + +#ifndef _WIN32 + } else if (errno == EINTR) { continue; - else { +#endif + } else { anetSetError(err, "accept: %s", strerror(errno)); return ANET_ERR; } @@ -341,16 +313,6 @@ int anetTcpAccept(char *err, int s, char *ip, int *port) { return fd; } -int anetUnixAccept(char *err, int s) { - int fd; - struct sockaddr_un sa; - socklen_t salen = sizeof(sa); - if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == ANET_ERR) - return ANET_ERR; - - return fd; -} - int anetPeerToString(int fd, char *ip, int *port) { struct sockaddr_in sa; socklen_t salen = sizeof(sa); diff --git a/coaa1090.obj b/coaa1090.obj index 845210c2dbf3d7625f9ef8e9787183cae170c7d7..acbae5f80f3b9911b3f997bfd0b9119833d56060 100644 GIT binary patch delta 7537 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 delta 7639 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\n" +" Copyright (C) 2014 by Malcolm Robb \n" +"\n" +" All rights reserved.\n" +"\n" +" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" +" ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" +" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" +" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" +" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" +" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" +" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" +" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" +" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" +" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" +" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" +"\n" +" For further details refer to \n" +"\n" + ); + + // delay for 1 second to give the user a chance to read the copyright + while (llTime >= time(NULL)) {} +} +#endif // //========================================================================= // @@ -586,6 +621,11 @@ int main(int argc, char **argv) { } } +#ifdef _WIN32 + // Try to comply with the Copyright license conditions for binary distribution + if (!Modes.quiet) {showCopyright();} +#endif + #ifndef _WIN32 // Setup for SIGWINCH for handling lines if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);} diff --git a/dump1090.dsp b/dump1090.dsp new file mode 100644 index 0000000..652d18e --- /dev/null +++ b/dump1090.dsp @@ -0,0 +1,148 @@ +# Microsoft Developer Studio Project File - Name="dump1090" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=dump1090 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "dump1090.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "dump1090.mak" CFG="dump1090 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "dump1090 - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "dump1090 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "dump1090 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I ".\pthreads\." /I ".\rtlsdr\." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "dump1090 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".\pthreads\." /I ".\rtlsdr\." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "dump1090 - Win32 Release" +# Name "dump1090 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\anet.c +# End Source File +# Begin Source File + +SOURCE=.\dump1090.c +# End Source File +# Begin Source File + +SOURCE=.\interactive.c +# End Source File +# Begin Source File + +SOURCE=.\mode_ac.c +# End Source File +# Begin Source File + +SOURCE=.\mode_s.c +# End Source File +# Begin Source File + +SOURCE=.\net_io.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\anet.h +# End Source File +# Begin Source File + +SOURCE=.\dump1090.h +# End Source File +# Begin Source File + +SOURCE=.\winstubs.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "Library Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\pthreads\pthreadVC2.lib +# End Source File +# Begin Source File + +SOURCE=.\rtlsdr\rtlsdr.lib +# End Source File +# End Group +# End Target +# End Project diff --git a/dump1090.dsw b/dump1090.dsw new file mode 100644 index 0000000..c29f0f1 --- /dev/null +++ b/dump1090.dsw @@ -0,0 +1,41 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "dump1090"=.\dump1090.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "view1090"=.\view1090.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/dump1090.h b/dump1090.h index 68bc6d9..815d6f4 100644 --- a/dump1090.h +++ b/dump1090.h @@ -37,7 +37,7 @@ // MinorVer changes when additional features are added, but not for bug fixes (range 00-99) // DayDate & Year changes for all changes, including for bug fixes. It represent the release date of the update // -#define MODES_DUMP1090_VERSION "1.08.1003.14" +#define MODES_DUMP1090_VERSION "1.08.2504.14" // ============================= Include files ========================== @@ -62,6 +62,7 @@ #else #include "winstubs.h" //Put everything Windows specific in here #include "rtl-sdr.h" + #include "anet.h" #endif // ============================= #defines =============================== @@ -166,7 +167,6 @@ #define MODES_NET_HEARTBEAT_RATE 900 // Each block is approx 65mS - default is > 1 min #define MODES_NET_SERVICES_NUM 6 -#define MODES_NET_MAX_FD 1024 #define MODES_NET_INPUT_RAW_PORT 30001 #define MODES_NET_OUTPUT_RAW_PORT 30002 #define MODES_NET_OUTPUT_SBS_PORT 30003 @@ -186,10 +186,11 @@ // Structure used to describe a networking client struct client { - int fd; // File descriptor - int service; // TCP port the client is connected to - int buflen; // Amount of data on buffer - char buf[MODES_CLIENT_BUF_SIZE+1]; // Read buffer + struct client* next; // Pointer to next client + int fd; // File descriptor + int service; // TCP port the client is connected to + int buflen; // Amount of data on buffer + char buf[MODES_CLIENT_BUF_SIZE+1]; // Read buffer }; // Structure used to describe an aircraft in iteractive mode @@ -256,20 +257,19 @@ struct { // Internal state // Networking char aneterr[ANET_ERR_LEN]; - struct client *clients[MODES_NET_MAX_FD]; // Our clients - int maxfd; // Greatest fd currently active - int sbsos; // SBS output listening socket - int ros; // Raw output listening socket - int ris; // Raw input listening socket - int bos; // Beast output listening socket - int bis; // Beast input listening socket - int https; // HTTP listening socket - char *rawOut; // Buffer for building raw output data - int rawOutUsed; // How much of the buffer is currently used - char *beastOut; // Buffer for building beast output data - int beastOutUsed; // How much if the buffer is currently used + struct client *clients; // Our clients + int sbsos; // SBS output listening socket + int ros; // Raw output listening socket + int ris; // Raw input listening socket + int bos; // Beast output listening socket + int bis; // Beast input listening socket + int https; // HTTP listening socket + char *rawOut; // Buffer for building raw output data + int rawOutUsed; // How much of the buffer is currently used + char *beastOut; // Buffer for building beast output data + int beastOutUsed; // How much if the buffer is currently used #ifdef _WIN32 - WSADATA wsaData; // Windows socket initialisation + WSADATA wsaData; // Windows socket initialisation #endif // Configuration diff --git a/net_io.c b/net_io.c index 684b961..add5956 100644 --- a/net_io.c +++ b/net_io.c @@ -61,8 +61,18 @@ void modesInitNet(void) { }; int j; - memset(Modes.clients,0,sizeof(Modes.clients)); - Modes.maxfd = -1; + Modes.clients = NULL; + +#ifdef _WIN32 + if ( (!Modes.wsaData.wVersion) + && (!Modes.wsaData.wHighVersion) ) { + // Try to start the windows socket support + if (WSAStartup(MAKEWORD(2,1),&Modes.wsaData) != 0) + { + fprintf(stderr, "WSAStartup returned Error\n"); + } + } +#endif for (j = 0; j < MODES_NET_SERVICES_NUM; j++) { int s = anetTcpServer(Modes.aneterr, services[j].port, NULL); @@ -75,7 +85,9 @@ void modesInitNet(void) { *services[j].socket = s; } +#ifndef _WIN32 signal(SIGPIPE, SIG_IGN); +#endif } // //========================================================================= @@ -83,7 +95,7 @@ void modesInitNet(void) { // This function gets called from time to time when the decoding thread is // awakened by new data arriving. This usually happens a few times every second // -void modesAcceptClients(void) { +struct client * modesAcceptClients(void) { int fd, port; unsigned int j; struct client *c; @@ -100,20 +112,15 @@ void modesAcceptClients(void) { fd = anetTcpAccept(Modes.aneterr, services[j], NULL, &port); if (fd == -1) continue; - if (fd >= MODES_NET_MAX_FD) { - close(fd); - return; // Max number of clients reached - } - anetNonBlock(Modes.aneterr, fd); c = (struct client *) malloc(sizeof(*c)); - c->service = services[j]; - c->fd = fd; - c->buflen = 0; - Modes.clients[fd] = c; + c->service = services[j]; + c->next = Modes.clients; + c->fd = fd; + c->buflen = 0; + Modes.clients = c; anetSetSendBuffer(Modes.aneterr,fd,MODES_NET_SNDBUF_SIZE); - if (Modes.maxfd < fd) Modes.maxfd = fd; if (services[j] == Modes.sbsos) Modes.stat_sbs_connections++; if (services[j] == Modes.ros) Modes.stat_raw_connections++; if (services[j] == Modes.bos) Modes.stat_beast_connections++; @@ -123,43 +130,44 @@ void modesAcceptClients(void) { if (Modes.debug & MODES_DEBUG_NET) printf("Created new client %d\n", fd); } + return Modes.clients; } // //========================================================================= // // On error free the client, collect the structure, adjust maxfd if needed. // -void modesFreeClient(int fd) { - close(fd); - if (Modes.clients[fd]->service == Modes.sbsos) { - if (Modes.stat_sbs_connections) Modes.stat_sbs_connections--; - } - else if (Modes.clients[fd]->service == Modes.ros) { - if (Modes.stat_raw_connections) Modes.stat_raw_connections--; - } - else if (Modes.clients[fd]->service == Modes.bos) { - if (Modes.stat_beast_connections) Modes.stat_beast_connections--; - } - free(Modes.clients[fd]); - Modes.clients[fd] = NULL; +void modesFreeClient(struct client *c) { - if (Modes.debug & MODES_DEBUG_NET) - printf("Closing client %d\n", fd); - - // If this was our maxfd, scan the clients array to find trhe new max. - // Note that we are sure there is no active fd greater than the closed - // fd, so we scan from fd-1 to 0. - if (Modes.maxfd == fd) { - int j; - - Modes.maxfd = -1; - for (j = fd-1; j >= 0; j--) { - if (Modes.clients[j]) { - Modes.maxfd = j; - break; + // Unhook this client from the linked list of clients + struct client *p = Modes.clients; + if (p) { + if (p == c) { + Modes.clients = c->next; + } else { + while ((p) && (p->next != c)) { + p = p->next; + } + if (p) { + p->next = c->next; } } } + + // It's now safe to remove this client + close(c->fd); + if (c->service == Modes.sbsos) { + if (Modes.stat_sbs_connections) Modes.stat_sbs_connections--; + } else if (c->service == Modes.ros) { + if (Modes.stat_raw_connections) Modes.stat_raw_connections--; + } else if (c->service == Modes.bos) { + if (Modes.stat_beast_connections) Modes.stat_beast_connections--; + } + + if (Modes.debug & MODES_DEBUG_NET) + printf("Closing client %d\n", c->fd); + + free(c); } // //========================================================================= @@ -167,17 +175,21 @@ void modesFreeClient(int fd) { // Send the specified message to all clients listening for a given service // void modesSendAllClients(int service, void *msg, int len) { - int j; - struct client *c; + struct client *c = Modes.clients; - for (j = 0; j <= Modes.maxfd; j++) { - c = Modes.clients[j]; - if (c && c->service == service) { - int nwritten = write(j, msg, len); + while (c) { + struct client *next = c->next; + if (c->service == service) { +#ifndef _WIN32 + int nwritten = write(c->fd, msg, len); +#else + int nwritten = send(c->fd, msg, len, 0 ); +#endif if (nwritten != len) { - modesFreeClient(j); + modesFreeClient(c); } } + c = next; } } // @@ -707,7 +719,12 @@ int handleHTTPRequest(struct client *c, char *p) { if (stat(getFile, &sbuf) != -1 && (fd = open(getFile, O_RDONLY)) != -1) { content = (char *) malloc(sbuf.st_size); +#ifndef _WIN32 if (read(fd, content, sbuf.st_size) == -1) { +#else + if (recv(fd, content, sbuf.st_size, 0) == -1) { + errno = WSAGetLastError(); +#endif snprintf(content, sbuf.st_size, "Error reading from file: %s", strerror(errno)); } clen = sbuf.st_size; @@ -755,8 +772,13 @@ int handleHTTPRequest(struct client *c, char *p) { } // Send header and content. +#ifndef _WIN32 if ( (write(c->fd, hdr, hdrlen) != hdrlen) || (write(c->fd, content, clen) != clen) ) { +#else + if ( (send(c->fd, hdr, hdrlen, 0) != hdrlen) + || (send(c->fd, content, clen, 0) != clen) ) { +#endif free(content); return 1; } @@ -797,14 +819,19 @@ void modesReadFromClient(struct client *c, char *sep, left = MODES_CLIENT_BUF_SIZE; // If there is garbage, read more to discard it ASAP } +#ifndef _WIN32 nread = read(c->fd, c->buf+c->buflen, left); +#else + nread = recv(c->fd, c->buf+c->buflen, left, 0); + if (nread < 0) {errno = WSAGetLastError();} +#endif // If we didn't get all the data we asked for, then return once we've processed what we did get. if (nread != left) { bContinue = 0; } if ( (nread < 0) && (errno != EAGAIN)) { // Error, or end of file - modesFreeClient(c->fd); + modesFreeClient(c); } if (nread <= 0) { break; // Serve next client @@ -851,7 +878,7 @@ void modesReadFromClient(struct client *c, char *sep, } // Have a 0x1a followed by 1, 2 or 3 - pass message less 0x1a to handler. if (handler(c, s)) { - modesFreeClient(c->fd); + modesFreeClient(c); return; } fullmsg = 1; @@ -867,7 +894,7 @@ void modesReadFromClient(struct client *c, char *sep, while ((e = strstr(s, sep)) != NULL) { // end of first message if found *e = '\0'; // The handler expects null terminated strings if (handler(c, s)) { // Pass message to handler. - modesFreeClient(c->fd); // Handler returns 1 on error to signal we . + modesFreeClient(c); // Handler returns 1 on error to signal we . return; // should close the client connection } s = e + strlen(sep); // Move to start of next message @@ -890,19 +917,18 @@ void modesReadFromClient(struct client *c, char *sep, // function that depends on the kind of service (raw, http, ...). // void modesReadFromClients(void) { - int j; - struct client *c; - modesAcceptClients(); + struct client *c = modesAcceptClients(); - for (j = 0; j <= Modes.maxfd; j++) { - if ((c = Modes.clients[j]) == NULL) continue; - if (c->service == Modes.ris) + while (c) { + if (c->service == Modes.ris) { modesReadFromClient(c,"\n",decodeHexMessage); - else if (c->service == Modes.bis) + } else if (c->service == Modes.bis) { modesReadFromClient(c,"",decodeBinMessage); - else if (c->service == Modes.https) + } else if (c->service == Modes.https) { modesReadFromClient(c,"\r\n\r\n",handleHTTPRequest); + } + c = c->next; } } // diff --git a/ppup1090.c b/ppup1090.c index 1c36dd5..3a69bbf 100644 --- a/ppup1090.c +++ b/ppup1090.c @@ -130,6 +130,41 @@ void showHelp(void) { "--help Show this help\n" ); } + +#ifdef _WIN32 +void showCopyright(void) { + uint64_t llTime = time(NULL) + 1; + + printf( +"-----------------------------------------------------------------------------\n" +"| ppup1090 RPi Uploader for COAA Planeplotter Ver : "MODES_DUMP1090_VERSION " |\n" +"-----------------------------------------------------------------------------\n" +"\n" +" Copyright (C) 2012 by Salvatore Sanfilippo \n" +" Copyright (C) 2014 by Malcolm Robb \n" +"\n" +" All rights reserved.\n" +"\n" +" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" +" ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" +" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" +" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" +" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" +" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" +" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" +" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" +" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" +" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" +" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" +"\n" +" For further details refer to \n" +"\n" + ); + + // delay for 1 second to give the user a chance to read the copyright + while (llTime >= time(NULL)) {} +} +#endif // //========================================================================= // @@ -162,6 +197,11 @@ int main(int argc, char **argv) { } } +#ifdef _WIN32 + // Try to comply with the Copyright license conditions for binary distribution + if (!Modes.quiet) {showCopyright();} +#endif + // Initialization ppup1090Init(); @@ -181,20 +221,13 @@ int main(int argc, char **argv) { // allocates a handle greater than 1024, then dump1090 won't like it. On my test machine, // the first Windows handle is usually in the 0x54 (84 decimal) region. - if (fd >= MODES_NET_MAX_FD) { // Max number of clients reached - close(fd); - exit(1); - } - c = (struct client *) malloc(sizeof(*c)); + c->next = NULL; c->buflen = 0; c->fd = c->service = Modes.bis = fd; - Modes.clients[fd] = c; - if (Modes.maxfd < fd) { - Modes.maxfd = fd; - } + Modes.clients = c; // Keep going till the user does something that stops us while (!Modes.exit) { @@ -208,7 +241,11 @@ int main(int argc, char **argv) { {close(fd);} closeCOAA (); +#ifndef _WIN32 pthread_exit(0); +#else + return (0); +#endif } // //========================================================================= diff --git a/pthreads/pthread.h b/pthreads/pthread.h new file mode 100644 index 0000000..b4072f7 --- /dev/null +++ b/pthreads/pthread.h @@ -0,0 +1,1368 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,9,1,0 +#define PTW32_VERSION_STRING "2, 9, 1, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#if !defined(RC_INVOKED) + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#if defined(_UWIN) +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_PTW32_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if (defined(__MINGW64__) || defined(__MINGW32__)) && defined(__cplusplus) +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#if defined(PTW32_INCLUDE_WINDOWS_H) +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +typedef unsigned long ULONG_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if defined(HAVE_PTW32_CONFIG_H) +#include "config.h" +#endif /* HAVE_PTW32_CONFIG_H */ + +#if !defined(NEED_FTIME) +#include +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if defined(HAVE_SIGNAL_H) +#include +#endif /* HAVE_SIGNAL_H */ + +#include + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#if !defined(PTW32_CONFIG_H) +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(__MINGW64__) +# define HAVE_STRUCT_TIMESPEC +# define HAVE_MODE_T +# elif defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#if defined(NEED_ERRNO) +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#if !defined(ENOTSUP) +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#if !defined(ETIMEDOUT) +# define ETIMEDOUT 10060 /* Same as WSAETIMEDOUT */ +#endif + +#if !defined(ENOSYS) +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#if !defined(EDEADLK) +# if defined(EDEADLOCK) +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +/* POSIX 2008 - related to robust mutexes */ +#if !defined(EOWNERDEAD) +# define EOWNERDEAD 43 +#endif +#if !defined(ENOTRECOVERABLE) +# define ENOTRECOVERABLE 44 +#endif + +#include + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. + */ +#if !defined(PTW32_INCLUDE_WINDOWS_H) +#if !defined(HANDLE) +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#if !defined(DWORD) +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#if !defined(HAVE_STRUCT_TIMESPEC) +#define HAVE_STRUCT_TIMESPEC +#if !defined(_TIMESPEC_DEFINED) +#define _TIMESPEC_DEFINED +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif /* _TIMESPEC_DEFINED */ +#endif /* HAVE_STRUCT_TIMESPEC */ + +#if !defined(SIG_BLOCK) +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#if !defined(SIG_UNBLOCK) +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#if !defined(SIG_SETMASK) +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#if defined(__cplusplus) +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in , which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200809L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200809L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200809L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200809L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200809L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in , which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (must be at least 256) + * + * SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (must be at least 32767) + * + */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX 128 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 64 + + /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + + /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX 32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX INT_MAX + + +#if defined(__GNUC__) && !defined(__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the library, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the library, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#if !defined(PTW32_STATIC_LIB) +# if defined(PTW32_BUILD) +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_mutexattr_{get,set}robust + */ + PTHREAD_MUTEX_STALLED = 0, /* Default */ + PTHREAD_MUTEX_ROBUST = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *)(size_t) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} + +struct pthread_once_t_ +{ + int done; /* indicates if user function has been executed */ + void * lock; + int reserved1; + int reserved2; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t)(size_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t)(size_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t)(size_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#if defined(__CLEANUP_SEH) + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#if defined(__CLEANUP_C) + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#if defined(__CLEANUP_CXX) + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (const pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(const pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(PTW32_CDECL *start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (PTW32_CDECL *init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + ptw32_cleanup_callback_t routine, + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (PTW32_CDECL *destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setrobust( + pthread_mutexattr_t *attr, + int robust); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getrobust( + const pthread_mutexattr_t * attr, + int * robust); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_consistent (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); +PTW32_DLLPORT unsigned __int64 PTW32_CDECL pthread_getunique_np(pthread_t thread); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); +/* + * Returns the win32 thread ID for POSIX thread. + */ +PTW32_DLLPORT DWORD PTW32_CDECL pthread_getw32threadid_np (pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#if !defined(_UWIN) +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# if !defined(errno) +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#if defined(__cplusplus) + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#if !defined(PTW32_BUILD) + +#if defined(__CLEANUP_SEH) + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#if defined(__CLEANUP_CXX) + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#if defined(_MSC_VER) + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#if !defined(PtW32NoCatchWarn) + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #if defined(PtW32CatchAll)") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#if defined(__cplusplus) +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#if defined(PTW32__HANDLE_DEF) +# undef HANDLE +#endif +#if defined(PTW32__DWORD_DEF) +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/pthreads/sched.h b/pthreads/sched.h new file mode 100644 index 0000000..f36a97a --- /dev/null +++ b/pthreads/sched.h @@ -0,0 +1,183 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(_SCHED_H) +#define _SCHED_H + +#undef PTW32_SCHED_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_SCHED_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_SCHED_LEVEL +#define PTW32_SCHED_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_SCHED_LEVEL +#define PTW32_SCHED_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_SCHED_LEVEL_MAX 3 + +#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_SCHED_LEVEL) +#define PTW32_SCHED_LEVEL PTW32_SCHED_LEVEL_MAX +/* Include everything */ +#endif + + +#if defined(__GNUC__) && !defined(__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the library, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the library, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#if !defined(PTW32_STATIC_LIB) +# if defined(PTW32_BUILD) +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#if !defined(PTW32_CONFIG_H) +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(__MINGW64__) +# define HAVE_STRUCT_TIMESPEC +# define HAVE_MODE_T +# elif defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX +#if defined(NEED_ERRNO) +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */ + +#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN) +# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX +/* For pid_t */ +# include +/* Required by Unix 98 */ +# include +# else + typedef int pid_t; +# endif +#else + typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#if defined(__cplusplus) +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#if defined(__cplusplus) +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_SCHED_LEVEL +#undef PTW32_SCHED_LEVEL_MAX + +#endif /* !_SCHED_H */ + diff --git a/pthreads/semaphore.h b/pthreads/semaphore.h new file mode 100644 index 0000000..c6e9407 --- /dev/null +++ b/pthreads/semaphore.h @@ -0,0 +1,169 @@ +/* + * Module: semaphore.h + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined( SEMAPHORE_H ) +#define SEMAPHORE_H + +#undef PTW32_SEMAPHORE_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_SEMAPHORE_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_SEMAPHORE_LEVEL +#define PTW32_SEMAPHORE_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_SEMAPHORE_LEVEL +#define PTW32_SEMAPHORE_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_SEMAPHORE_LEVEL_MAX 3 + +#if !defined(PTW32_SEMAPHORE_LEVEL) +#define PTW32_SEMAPHORE_LEVEL PTW32_SEMAPHORE_LEVEL_MAX +/* Include everything */ +#endif + +#if defined(__GNUC__) && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the library, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the library, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#if !defined(PTW32_STATIC_LIB) +# if defined(PTW32_BUILD) +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#if !defined(PTW32_CONFIG_H) +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(__MINGW64__) +# define HAVE_STRUCT_TIMESPEC +# define HAVE_MODE_T +# elif defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX +#if defined(NEED_ERRNO) +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX */ + +#define _POSIX_SEMAPHORES + +#if defined(__cplusplus) +extern "C" +{ +#endif /* __cplusplus */ + +#if !defined(HAVE_MODE_T) +typedef unsigned int mode_t; +#endif + + +typedef struct sem_t_ * sem_t; + +PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, + int pshared, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, + const struct timespec * abstime); + +PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, + int count); + +PTW32_DLLPORT int __cdecl sem_open (const char * name, + int oflag, + mode_t mode, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_unlink (const char * name); + +PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, + int * sval); + +#if defined(__cplusplus) +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_SEMAPHORE_LEVEL +#undef PTW32_SEMAPHORE_LEVEL_MAX + +#endif /* !SEMAPHORE_H */ diff --git a/rtlsdr/rtl-sdr.h b/rtlsdr/rtl-sdr.h new file mode 100644 index 0000000..bb028fe --- /dev/null +++ b/rtlsdr/rtl-sdr.h @@ -0,0 +1,366 @@ +/* + * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver + * Copyright (C) 2012 by Steve Markgraf + * Copyright (C) 2012 by Dimitri Stolnikov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __RTL_SDR_H +#define __RTL_SDR_H + +#ifdef __cplusplus +extern "C" { +#endif + +//#include +#include "rtl-sdr_export.h" + +typedef struct rtlsdr_dev rtlsdr_dev_t; + +RTLSDR_API uint32_t rtlsdr_get_device_count(void); + +RTLSDR_API const char* rtlsdr_get_device_name(uint32_t index); + +/*! + * Get USB device strings. + * + * NOTE: The string arguments must provide space for up to 256 bytes. + * + * \param index the device index + * \param manufact manufacturer name, may be NULL + * \param product product name, may be NULL + * \param serial serial number, may be NULL + * \return 0 on success + */ +RTLSDR_API int rtlsdr_get_device_usb_strings(uint32_t index, + char *manufact, + char *product, + char *serial); + +/*! + * Get device index by USB serial string descriptor. + * + * \param serial serial string of the device + * \return device index of first device where the name matched + * \return -1 if name is NULL + * \return -2 if no devices were found at all + * \return -3 if devices were found, but none with matching name + */ +RTLSDR_API int rtlsdr_get_index_by_serial(const char *serial); + +RTLSDR_API int rtlsdr_open(rtlsdr_dev_t **dev, uint32_t index); + +RTLSDR_API int rtlsdr_close(rtlsdr_dev_t *dev); + +/* configuration functions */ + +/*! + * Set crystal oscillator frequencies used for the RTL2832 and the tuner IC. + * + * Usually both ICs use the same clock. Changing the clock may make sense if + * you are applying an external clock to the tuner or to compensate the + * frequency (and samplerate) error caused by the original (cheap) crystal. + * + * NOTE: Call this function only if you fully understand the implications. + * + * \param dev the device handle given by rtlsdr_open() + * \param rtl_freq frequency value used to clock the RTL2832 in Hz + * \param tuner_freq frequency value used to clock the tuner IC in Hz + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_xtal_freq(rtlsdr_dev_t *dev, uint32_t rtl_freq, + uint32_t tuner_freq); + +/*! + * Get crystal oscillator frequencies used for the RTL2832 and the tuner IC. + * + * Usually both ICs use the same clock. + * + * \param dev the device handle given by rtlsdr_open() + * \param rtl_freq frequency value used to clock the RTL2832 in Hz + * \param tuner_freq frequency value used to clock the tuner IC in Hz + * \return 0 on success + */ +RTLSDR_API int rtlsdr_get_xtal_freq(rtlsdr_dev_t *dev, uint32_t *rtl_freq, + uint32_t *tuner_freq); + +/*! + * Get USB device strings. + * + * NOTE: The string arguments must provide space for up to 256 bytes. + * + * \param dev the device handle given by rtlsdr_open() + * \param manufact manufacturer name, may be NULL + * \param product product name, may be NULL + * \param serial serial number, may be NULL + * \return 0 on success + */ +RTLSDR_API int rtlsdr_get_usb_strings(rtlsdr_dev_t *dev, char *manufact, + char *product, char *serial); + +/*! + * Write the device EEPROM + * + * \param dev the device handle given by rtlsdr_open() + * \param data buffer of data to be written + * \param offset address where the data should be written + * \param len length of the data + * \return 0 on success + * \return -1 if device handle is invalid + * \return -2 if EEPROM size is exceeded + * \return -3 if no EEPROM was found + */ + +RTLSDR_API int rtlsdr_write_eeprom(rtlsdr_dev_t *dev, uint8_t *data, + uint8_t offset, uint16_t len); + +/*! + * Read the device EEPROM + * + * \param dev the device handle given by rtlsdr_open() + * \param data buffer where the data should be written + * \param offset address where the data should be read from + * \param len length of the data + * \return 0 on success + * \return -1 if device handle is invalid + * \return -2 if EEPROM size is exceeded + * \return -3 if no EEPROM was found + */ + +RTLSDR_API int rtlsdr_read_eeprom(rtlsdr_dev_t *dev, uint8_t *data, + uint8_t offset, uint16_t len); + +RTLSDR_API int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq); + +/*! + * Get actual frequency the device is tuned to. + * + * \param dev the device handle given by rtlsdr_open() + * \return 0 on error, frequency in Hz otherwise + */ +RTLSDR_API uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev); + +/*! + * Set the frequency correction value for the device. + * + * \param dev the device handle given by rtlsdr_open() + * \param ppm correction value in parts per million (ppm) + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_freq_correction(rtlsdr_dev_t *dev, int ppm); + +/*! + * Get actual frequency correction value of the device. + * + * \param dev the device handle given by rtlsdr_open() + * \return correction value in parts per million (ppm) + */ +RTLSDR_API int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev); + +enum rtlsdr_tuner { + RTLSDR_TUNER_UNKNOWN = 0, + RTLSDR_TUNER_E4000, + RTLSDR_TUNER_FC0012, + RTLSDR_TUNER_FC0013, + RTLSDR_TUNER_FC2580, + RTLSDR_TUNER_R820T +}; + +/*! + * Get the tuner type. + * + * \param dev the device handle given by rtlsdr_open() + * \return RTLSDR_TUNER_UNKNOWN on error, tuner type otherwise + */ +RTLSDR_API enum rtlsdr_tuner rtlsdr_get_tuner_type(rtlsdr_dev_t *dev); + +/*! + * Get a list of gains supported by the tuner. + * + * NOTE: The gains argument must be preallocated by the caller. If NULL is + * being given instead, the number of available gain values will be returned. + * + * \param dev the device handle given by rtlsdr_open() + * \param gains array of gain values. In tenths of a dB, 115 means 11.5 dB. + * \return <= 0 on error, number of available (returned) gain values otherwise + */ +RTLSDR_API int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains); + +/*! + * Set the gain for the device. + * Manual gain mode must be enabled for this to work. + * + * Valid gain values (in tenths of a dB) for the E4000 tuner: + * -10, 15, 40, 65, 90, 115, 140, 165, 190, + * 215, 240, 290, 340, 420, 430, 450, 470, 490 + * + * Valid gain values may be queried with \ref rtlsdr_get_tuner_gains function. + * + * \param dev the device handle given by rtlsdr_open() + * \param gain in tenths of a dB, 115 means 11.5 dB. + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain); + +/*! + * Get actual gain the device is configured to. + * + * \param dev the device handle given by rtlsdr_open() + * \return 0 on error, gain in tenths of a dB, 115 means 11.5 dB. + */ +RTLSDR_API int rtlsdr_get_tuner_gain(rtlsdr_dev_t *dev); + +/*! + * Set the intermediate frequency gain for the device. + * + * \param dev the device handle given by rtlsdr_open() + * \param stage intermediate frequency gain stage number (1 to 6 for E4000) + * \param gain in tenths of a dB, -30 means -3.0 dB. + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_tuner_if_gain(rtlsdr_dev_t *dev, int stage, int gain); + +/*! + * Set the gain mode (automatic/manual) for the device. + * Manual gain mode must be enabled for the gain setter function to work. + * + * \param dev the device handle given by rtlsdr_open() + * \param manual gain mode, 1 means manual gain mode shall be enabled. + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int manual); + +/* this will select the baseband filters according to the requested sample rate */ +RTLSDR_API int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t rate); + +/*! + * Get actual sample rate the device is configured to. + * + * \param dev the device handle given by rtlsdr_open() + * \return 0 on error, sample rate in Hz otherwise + */ +RTLSDR_API uint32_t rtlsdr_get_sample_rate(rtlsdr_dev_t *dev); + +/*! + * Enable test mode that returns an 8 bit counter instead of the samples. + * The counter is generated inside the RTL2832. + * + * \param dev the device handle given by rtlsdr_open() + * \param test mode, 1 means enabled, 0 disabled + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_testmode(rtlsdr_dev_t *dev, int on); + +/*! + * Enable or disable the internal digital AGC of the RTL2832. + * + * \param dev the device handle given by rtlsdr_open() + * \param digital AGC mode, 1 means enabled, 0 disabled + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_agc_mode(rtlsdr_dev_t *dev, int on); + +/*! + * Enable or disable the direct sampling mode. When enabled, the IF mode + * of the RTL2832 is activated, and rtlsdr_set_center_freq() will control + * the IF-frequency of the DDC, which can be used to tune from 0 to 28.8 MHz + * (xtal frequency of the RTL2832). + * + * \param dev the device handle given by rtlsdr_open() + * \param on 0 means disabled, 1 I-ADC input enabled, 2 Q-ADC input enabled + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on); + +/*! + * Get state of the direct sampling mode + * + * \param dev the device handle given by rtlsdr_open() + * \return -1 on error, 0 means disabled, 1 I-ADC input enabled + * 2 Q-ADC input enabled + */ +RTLSDR_API int rtlsdr_get_direct_sampling(rtlsdr_dev_t *dev); + +/*! + * Enable or disable offset tuning for zero-IF tuners, which allows to avoid + * problems caused by the DC offset of the ADCs and 1/f noise. + * + * \param dev the device handle given by rtlsdr_open() + * \param on 0 means disabled, 1 enabled + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on); + +/*! + * Get state of the offset tuning mode + * + * \param dev the device handle given by rtlsdr_open() + * \return -1 on error, 0 means disabled, 1 enabled + */ +RTLSDR_API int rtlsdr_get_offset_tuning(rtlsdr_dev_t *dev); + +/* streaming functions */ + +RTLSDR_API int rtlsdr_reset_buffer(rtlsdr_dev_t *dev); + +RTLSDR_API int rtlsdr_read_sync(rtlsdr_dev_t *dev, void *buf, int len, int *n_read); + +typedef void(*rtlsdr_read_async_cb_t)(unsigned char *buf, uint32_t len, void *ctx); + +/*! + * Read samples from the device asynchronously. This function will block until + * it is being canceled using rtlsdr_cancel_async() + * + * NOTE: This function is deprecated and is subject for removal. + * + * \param dev the device handle given by rtlsdr_open() + * \param cb callback function to return received samples + * \param ctx user specific context to pass via the callback function + * \return 0 on success + */ +RTLSDR_API int rtlsdr_wait_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx); + +/*! + * Read samples from the device asynchronously. This function will block until + * it is being canceled using rtlsdr_cancel_async() + * + * \param dev the device handle given by rtlsdr_open() + * \param cb callback function to return received samples + * \param ctx user specific context to pass via the callback function + * \param buf_num optional buffer count, buf_num * buf_len = overall buffer size + * set to 0 for default buffer count (32) + * \param buf_len optional buffer length, must be multiple of 512, + * set to 0 for default buffer length (16 * 32 * 512) + * \return 0 on success + */ +RTLSDR_API int rtlsdr_read_async(rtlsdr_dev_t *dev, + rtlsdr_read_async_cb_t cb, + void *ctx, + uint32_t buf_num, + uint32_t buf_len); + +/*! + * Cancel all pending asynchronous operations on the device. + * + * \param dev the device handle given by rtlsdr_open() + * \return 0 on success + */ +RTLSDR_API int rtlsdr_cancel_async(rtlsdr_dev_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* __RTL_SDR_H */ diff --git a/rtlsdr/rtl-sdr_export.h b/rtlsdr/rtl-sdr_export.h new file mode 100644 index 0000000..69e178d --- /dev/null +++ b/rtlsdr/rtl-sdr_export.h @@ -0,0 +1,47 @@ +/* + * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver + * Copyright (C) 2012 by Hoernchen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef RTLSDR_EXPORT_H +#define RTLSDR_EXPORT_H + +#if defined __GNUC__ +# if __GNUC__ >= 4 +# define __SDR_EXPORT __attribute__((visibility("default"))) +# define __SDR_IMPORT __attribute__((visibility("default"))) +# else +# define __SDR_EXPORT +# define __SDR_IMPORT +# endif +#elif _MSC_VER +# define __SDR_EXPORT __declspec(dllexport) +# define __SDR_IMPORT __declspec(dllimport) +#else +# define __SDR_EXPORT +# define __SDR_IMPORT +#endif + +#ifndef rtlsdr_STATIC +# ifdef rtlsdr_EXPORTS +# define RTLSDR_API __SDR_EXPORT +# else +# define RTLSDR_API __SDR_IMPORT +# endif +#else +#define RTLSDR_API +#endif +#endif /* RTLSDR_EXPORT_H */ diff --git a/view1090.c b/view1090.c index ae9ee89..4830bca 100644 --- a/view1090.c +++ b/view1090.c @@ -1,6 +1,6 @@ // view1090, a Mode S messages viewer for dump1090 devices. // -// Copyright (C) 2013 by Malcolm Robb +// Copyright (C) 2014 by Malcolm Robb // // All rights reserved. // @@ -140,6 +140,41 @@ void showHelp(void) { "--help Show this help\n" ); } + +#ifdef _WIN32 +void showCopyright(void) { + uint64_t llTime = time(NULL) + 1; + + printf( +"-----------------------------------------------------------------------------\n" +"| view1090 ModeS Viewer Ver : " MODES_DUMP1090_VERSION " |\n" +"-----------------------------------------------------------------------------\n" +"\n" +" Copyright (C) 2012 by Salvatore Sanfilippo \n" +" Copyright (C) 2014 by Malcolm Robb \n" +"\n" +" All rights reserved.\n" +"\n" +" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" +" ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" +" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" +" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" +" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" +" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" +" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" +" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" +" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" +" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" +" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" +"\n" +" For further details refer to \n" +"\n" + ); + + // delay for 1 second to give the user a chance to read the copyright + while (llTime >= time(NULL)) {} +} +#endif // //========================================================================= // @@ -195,6 +230,11 @@ int main(int argc, char **argv) { } } +#ifdef _WIN32 + // Try to comply with the Copyright license conditions for binary distribution + if (!Modes.quiet) {showCopyright();} +#endif + #ifndef _WIN32 // Setup for SIGWINCH for handling lines if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);} @@ -219,21 +259,13 @@ int main(int argc, char **argv) { // allocates a handle greater than 1024, then dump1090 won't like it. On my test machine, // the first Windows handle is usually in the 0x54 (84 decimal) region. - if (fd >= MODES_NET_MAX_FD) { // Max number of clients reached - fprintf(stderr, "Max number of clients exceeded : fd = 0x%X\n", fd); - close(fd); - exit(1); - } - c = (struct client *) malloc(sizeof(*c)); + c->next = NULL; c->buflen = 0; c->fd = c->service = Modes.bis = fd; - Modes.clients[fd] = c; - if (Modes.maxfd < fd) { - Modes.maxfd = fd; - } + Modes.clients = c; // Keep going till the user does something that stops us while (!Modes.exit) { @@ -246,9 +278,11 @@ int main(int argc, char **argv) { if (fd != ANET_ERR) {close(fd);} +#ifndef _WIN32 pthread_exit(0); - +#else return (0); +#endif } // //========================================================================= diff --git a/view1090.dsp b/view1090.dsp new file mode 100644 index 0000000..de97af8 --- /dev/null +++ b/view1090.dsp @@ -0,0 +1,149 @@ +# Microsoft Developer Studio Project File - Name="view1090" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=view1090 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "view1090.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "view1090.mak" CFG="view1090 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "view1090 - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "view1090 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "view1090 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I ".\pthreads\." /I ".\rtlsdr\." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "view1090 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".\pthreads\." /I ".\rtlsdr\." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "view1090 - Win32 Release" +# Name "view1090 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\anet.c +# End Source File +# Begin Source File + +SOURCE=.\interactive.c +# End Source File +# Begin Source File + +SOURCE=.\mode_ac.c +# End Source File +# Begin Source File + +SOURCE=.\mode_s.c +# End Source File +# Begin Source File + +SOURCE=.\net_io.c +# End Source File +# Begin Source File + +SOURCE=.\view1090.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\dump1090.h +# End Source File +# Begin Source File + +SOURCE=.\view1090.h +# End Source File +# Begin Source File + +SOURCE=.\winstubs.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "Library Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\pthreads\pthreadVC2.lib +# End Source File +# Begin Source File + +SOURCE=.\rtlsdr\rtlsdr.lib +# End Source File +# End Group +# End Target +# End Project diff --git a/winstubs.h b/winstubs.h new file mode 100644 index 0000000..f416668 --- /dev/null +++ b/winstubs.h @@ -0,0 +1,110 @@ +// dump1090, a Mode S messages decoder for RTLSDR devices. +// +// Copyright (C) 2014 by Malcolm Robb +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// This file provides basic Windows implementation of Linux specific functions +// used in the dump1090 project. This allows dump1090 to be compiled and debugged +// using Microsoft Visual C++ 6.0 +// +// Note that not all functions actually provide equivalent functionality to their +// Linux equivalents. They are simply stubs to allow the project to compile. +// +#ifndef __WINSTUBS_H +#define __WINSTUBS_H + +#include +#include +#include + +typedef UCHAR uint8_t; +typedef USHORT uint16_t; +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; +typedef UINT32 mode_t; +typedef long ssize_t; +typedef int socklen_t; + +#include +#include +#include +#include +#include +#include +#include + +#define M_PI 3.14159265358979323846 +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//Functions not included in the MSVC maths library. This will do for our use. +_inline double round(double d) {return floor(d + 0.5);} +_inline double trunc(double d) {return (d>0) ? floor(d):ceil(d) ;} + +//usleep works in microseconds, and isn't supported in Windows. This will do for our use. +_inline void usleep(UINT32 ulSleep) {Sleep(ulSleep/1000);} +_inline uint64_t strtoll(const char *p, void *e, UINT32 base) {return _atoi64(p);} +_inline int inet_aton(const char * cp, DWORD * ulAddr) { *ulAddr = inet_addr(cp); return 0;} +#define snprintf _snprintf +#define vsnprintf _vsnprintf + +_inline void cls() { + HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + COORD coord = {0, 0}; + DWORD count; + + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(hStdOut, &csbi); + + FillConsoleOutputCharacter(hStdOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, coord, &count); + + SetConsoleCursorPosition(hStdOut, coord); +} + +_inline int gettimeofday(struct timeval *tv, struct timezone *tz) { + SYSTEMTIME stSystemTime; + GetLocalTime(&stSystemTime); + + tv->tv_sec = stSystemTime.wSecond + (60 * (stSystemTime.wMinute + (60 * stSystemTime.wHour))); + tv->tv_usec = stSystemTime.wMilliseconds * 1000; + + return 0; + } + +#define STDIN_FILENO 0 +#define EINPROGRESS WSAEINPROGRESS +#define EWOULDBLOCK WSAEWOULDBLOCK + +#ifdef __cplusplus +} +#endif + +#endif // __WINSTUBS_H