From 768a06613e38194e58d37ab3b1c5bb4a326f0e2b Mon Sep 17 00:00:00 2001 From: ultramn Date: Thu, 16 Mar 2017 17:17:07 -0700 Subject: Almost compiles on Apple (not quite there) --- Makefile | 2 +- redist/json_helpers.c | 2 +- src/survive.c | 4 ++++ src/survive_config.c | 2 +- src/survive_vive.c | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 525f7c5..cac4135 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ all : lib data_recorder test calibrate calibrate_client CC:=gcc CFLAGS:=-Iinclude/libsurvive -I. -fPIC -g -O3 -Iredist -flto -DUSE_DOUBLE -std=gnu99 -rdynamic -LDFLAGS:=-lpthread -lusb-1.0 -lz -lX11 -lm -flto -g +LDFLAGS:=-L/usr/local/lib -lpthread -lusb-1.0 -lz -lX11 -lm -flto -g POSERS:=src/poser_dummy.o src/poser_daveortho.o src/poser_charlesslow.o REDISTS:=redist/json_helpers.o redist/linmath.o redist/jsmn.o diff --git a/redist/json_helpers.c b/redist/json_helpers.c index 7690318..e0b86f4 100644 --- a/redist/json_helpers.c +++ b/redist/json_helpers.c @@ -7,7 +7,7 @@ #include #include "json_helpers.h" #include -#ifndef __FreeBSD__ +#if !defined(__FreeBSD__) && !defined(__APPLE__) #include #endif diff --git a/src/survive.c b/src/survive.c index 81c45c3..9554d9c 100755 --- a/src/survive.c +++ b/src/survive.c @@ -9,6 +9,10 @@ #include "survive_config.h" +#ifdef __APPLE__ +#define z_const const +#endif + #ifdef RUNTIME_SYMNUM #include static int did_runtime_symnum; diff --git a/src/survive_config.c b/src/survive_config.c index 07b9326..5458ef0 100644 --- a/src/survive_config.c +++ b/src/survive_config.c @@ -3,7 +3,7 @@ #include #include "survive_config.h" #include -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__APPLE__) #include #else #include //for alloca diff --git a/src/survive_vive.c b/src/survive_vive.c index 1929b1a..5a76d24 100755 --- a/src/survive_vive.c +++ b/src/survive_vive.c @@ -18,7 +18,7 @@ #include #include #include -#ifndef __FreeBSD__ +#if !defined(__FreeBSD__) && !defined(__APPLE__) #include // for alloca #endif -- cgit v1.2.3 From fcc65b6ad403bc9b59591291c939c8257b8b91d9 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 00:26:47 -0400 Subject: Fix windows build to allow for linktime code genreation. --- .gitignore | 3 +++ include/libsurvive/survive.h | 6 ++++-- winbuild/libsurvive/libsurvive.vcxproj | 20 ++++++++++++-------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index a7db3ac..d692b50 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ windows/calinfo - Copy/WM1_points.csv windows/udev[USB_DEV_LIGHTHOUSE] windows/udev[USB_DEV_LIGHTHOUSE] windows/config.json +*.ipch +winbuild/.vs/libsurvive/v15/.suo +*.tlog diff --git a/include/libsurvive/survive.h b/include/libsurvive/survive.h index e3e167a..28180e4 100644 --- a/include/libsurvive/survive.h +++ b/include/libsurvive/survive.h @@ -136,10 +136,12 @@ void survive_default_angle_process( SurviveObject * so, int sensor_id, int acode ////////////////////// Survive Drivers //////////////////////////// -void RegisterDriver( const char * name, void * data ); +void RegisterDriver(const char * name, void * data); #ifdef _WIN32 -#define REGISTER_LINKTIME( func ) +#define REGISTER_LINKTIME( func ) \ + __pragma(comment(linker,"/export:REGISTER"#func));\ + void REGISTER##func() { RegisterDriver(#func, &func); } #else #define REGISTER_LINKTIME( func ) \ void __attribute__((constructor)) REGISTER##func() { RegisterDriver(#func, &func); } diff --git a/winbuild/libsurvive/libsurvive.vcxproj b/winbuild/libsurvive/libsurvive.vcxproj index dc23907..2a5029c 100644 --- a/winbuild/libsurvive/libsurvive.vcxproj +++ b/winbuild/libsurvive/libsurvive.vcxproj @@ -30,27 +30,27 @@ StaticLibrary true v141 - Unicode + MultiByte StaticLibrary false v141 true - Unicode + MultiByte StaticLibrary true v141 - Unicode + MultiByte StaticLibrary false v141 true - Unicode + MultiByte @@ -77,12 +77,13 @@ Level3 Disabled - USE_DOUBLE;MANUAL_REGISTRATION;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;_DEBUG;_LIB;%(PreprocessorDefinitions) + USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;_DEBUG;_LIB;%(PreprocessorDefinitions) ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) Windows + @@ -90,12 +91,13 @@ Level3 Disabled - USE_DOUBLE;MANUAL_REGISTRATION;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) Windows + @@ -105,7 +107,7 @@ MaxSpeed true true - USE_DOUBLE;MANUAL_REGISTRATION;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) @@ -113,6 +115,7 @@ true true + @@ -122,7 +125,7 @@ MaxSpeed true true - USE_DOUBLE;MANUAL_REGISTRATION;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;NDEBUG;_LIB;%(PreprocessorDefinitions) + USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;NDEBUG;_LIB;%(PreprocessorDefinitions) ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) @@ -130,6 +133,7 @@ true true + -- cgit v1.2.3 From 735e800187ee4df9b18ba51c125ff1ce4e07a7da Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 00:27:06 -0400 Subject: Include changes for link-time code generation. --- winbuild/calibrate/calibrate.vcxproj | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/winbuild/calibrate/calibrate.vcxproj b/winbuild/calibrate/calibrate.vcxproj index 13fce78..7a62c14 100644 --- a/winbuild/calibrate/calibrate.vcxproj +++ b/winbuild/calibrate/calibrate.vcxproj @@ -30,27 +30,27 @@ Application true v141 - Unicode + MultiByte Application false v141 true - Unicode + MultiByte Application true v141 - Unicode + MultiByte Application false v141 true - Unicode + MultiByte @@ -96,7 +96,12 @@ setupapi.lib;dbghelp.lib;%(AdditionalDependencies) + true + UseFastLinkTimeCodeGeneration + + true + @@ -114,7 +119,12 @@ setupapi.lib;dbghelp.lib;%(AdditionalDependencies) + true + UseFastLinkTimeCodeGeneration + + true + @@ -134,7 +144,11 @@ setupapi.lib;dbghelp.lib;%(AdditionalDependencies) + true + + true + @@ -154,7 +168,11 @@ setupapi.lib;dbghelp.lib;%(AdditionalDependencies) + true + + true + -- cgit v1.2.3 From aaba94082eb058d76b39addd3f8e9a894e6af4b2 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 00:31:34 -0400 Subject: cleanup gitignore. --- .gitignore | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index d692b50..d045537 100644 --- a/.gitignore +++ b/.gitignore @@ -2,20 +2,11 @@ lib test windows/calibrate.exe -windows/calinfo/1.json.gz +windows/calinfo/* windows/calibrate.def -windows/calinfo/3.json.gz -windows/calinfo/WM1_points.csv -windows/calinfo/HMD_normals.csv -windows/calinfo/WM0_points.csv -windows/calinfo/WM1_normals.csv -windows/calinfo/HMD_points.csv -windows/calinfo/WM0_normals.csv -windows/calinfo/2.json.gz -windows/calinfo - Copy/WM1_points.csv -windows/udev[USB_DEV_LIGHTHOUSE] windows/udev[USB_DEV_LIGHTHOUSE] windows/config.json +winbuild/x64 *.ipch winbuild/.vs/libsurvive/v15/.suo *.tlog -- cgit v1.2.3 From 153120faa83c6577c99a671d47f211c55169fc26 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 00:32:30 -0400 Subject: Fix definition for the x64 folder for Windows. --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d045537..77c0fc0 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ windows/calinfo/* windows/calibrate.def windows/udev[USB_DEV_LIGHTHOUSE] windows/config.json -winbuild/x64 +winbuild/x64/* *.ipch winbuild/.vs/libsurvive/v15/.suo *.tlog -- cgit v1.2.3 From 0500fc0c5b31baf13b89c4d4c0ff5d68c112a524 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 00:33:37 -0400 Subject: Include more things in the gitignore. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 77c0fc0..83b0111 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ windows/calibrate.def windows/udev[USB_DEV_LIGHTHOUSE] windows/config.json winbuild/x64/* +winbuild/x64/calibrate/* +winbuild/x64/libsurvive/* *.ipch winbuild/.vs/libsurvive/v15/.suo *.tlog -- cgit v1.2.3 From 313b1b31e589dcfb7e6ac14d446c01a14af16ed8 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 00:34:37 -0400 Subject: Finally, the correct gitignore. --- .gitignore | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 83b0111..3ff5664 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,10 @@ windows/calibrate.def windows/udev[USB_DEV_LIGHTHOUSE] windows/config.json winbuild/x64/* -winbuild/x64/calibrate/* -winbuild/x64/libsurvive/* +winbuild/calibrate/x64/* +winbuild/libsurvive/x64/* +winbuild/.vs/* +*.user *.ipch winbuild/.vs/libsurvive/v15/.suo *.tlog -- cgit v1.2.3 From c9be7c057aa9570d0f67109c87b74e3aab640322 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 00:42:05 -0400 Subject: Update, adding rawdrawnull for OSX. --- .gitignore | 2 ++ redist/RawDrawNull.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 redist/RawDrawNull.c diff --git a/.gitignore b/.gitignore index 3ff5664..034a8bc 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ windows/calibrate.def windows/udev[USB_DEV_LIGHTHOUSE] windows/config.json winbuild/x64/* +winbuild/calibrate/calinfo/* +winbuild/calibrate/config.json winbuild/calibrate/x64/* winbuild/libsurvive/x64/* winbuild/.vs/* diff --git a/redist/RawDrawNull.c b/redist/RawDrawNull.c new file mode 100644 index 0000000..34346cc --- /dev/null +++ b/redist/RawDrawNull.c @@ -0,0 +1,74 @@ +//Copyright (c) 2017 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose. + +#include "DrawFunctions.h" + +static int w, h; +void CNFGGetDimensions( short * x, short * y ) +{ + *x = w; + *y = h; +} + +static void InternalLinkScreenAndGo( const char * WindowName ) +{ +} + +void CNFGSetupFullscreen( const char * WindowName, int screen_no ) +{ + CNFGSetup( WindowName, 640, 480 ); +} + + +void CNFGTearDown() +{ +} + +void CNFGSetup( const char * WindowName, int sw, int sh ) +{ + w = sw; + h = sh; +} + +void CNFGHandleInput() +{ +} + + +void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h ) +{ +} + + +#ifndef RASTERIZER + + +uint32_t CNFGColor( uint32_t RGB ) +{ +} + +void CNFGClearFrame() +{ +} + +void CNFGSwapBuffers() +{ +} + +void CNFGTackSegment( short x1, short y1, short x2, short y2 ) +{ +} + +void CNFGTackPixel( short x1, short y1 ) +{ +} + +void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) +{ +} + +void CNFGTackPoly( RDPoint * points, int verts ) +{ +} + +#endif + -- cgit v1.2.3 From 8ea24c306fdf2a141433e396307e92a227416ba5 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 01:08:06 -0400 Subject: Fix Warnings --- redist/WinDriver.c | 2 +- redist/json_helpers.c | 6 +++--- redist/json_helpers.h | 2 +- redist/linmath.c | 16 ++++++++-------- redist/os_generic.c | 1 + redist/symbol_enumerator.c | 10 +++++++--- src/poser_charlesslow.c | 8 ++++---- src/poser_daveortho.c | 2 +- src/survive.c | 4 +++- src/survive_cal.c | 6 +++++- src/survive_config.c | 14 +++++++------- src/survive_config.h | 4 ++-- src/survive_driverman.c | 2 +- src/survive_vive.c | 4 +++- winbuild/libsurvive/libsurvive.vcxproj | 8 ++++---- windows/hid.c | 22 +++++++++++----------- 16 files changed, 62 insertions(+), 49 deletions(-) diff --git a/redist/WinDriver.c b/redist/WinDriver.c index a6dd1e6..3613150 100644 --- a/redist/WinDriver.c +++ b/redist/WinDriver.c @@ -220,7 +220,7 @@ void CNFGHandleInput() case WM_MBUTTONUP: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 3, 0 ); break; case WM_KEYDOWN: case WM_KEYUP: - HandleKey( tolower( msg.wParam ), (msg.message==WM_KEYDOWN) ); + HandleKey( tolower( (int)msg.wParam ), (msg.message==WM_KEYDOWN) ); break; default: DispatchMessage(&msg); diff --git a/redist/json_helpers.c b/redist/json_helpers.c index e0b86f4..1e2f43e 100644 --- a/redist/json_helpers.c +++ b/redist/json_helpers.c @@ -107,7 +107,7 @@ void json_write_str(FILE* f, const char* tag, const char* v) { void (*json_begin_object)(char* tag) = NULL; void (*json_end_object)() = NULL; -void (*json_tag_value)(char* tag, char** values, uint16_t count) = NULL; +void (*json_tag_value)(char* tag, char** values, uint8_t count) = NULL; uint32_t JSON_STRING_LEN; @@ -146,7 +146,7 @@ static uint16_t json_load_array(const char* JSON_STRING, jsmntok_t* tokens, uint values[i] = substr(JSON_STRING, t->start, t->end, JSON_STRING_LEN); } - if (json_tag_value != NULL) json_tag_value(tag, values, i); + if (json_tag_value != NULL) json_tag_value(tag, values, (uint8_t)i); for (i=0;i 0) { - float S = sqrt(tr+1.0) * 2; // S=4*qw - q[0] = 0.25 * S; + FLT S = FLT_SQRT(tr+1.0) * 2.; // S=4*qw + q[0] = 0.25f * S; q[1] = (matrix44[9] - matrix44[6]) / S; q[2] = (matrix44[2] - matrix44[8]) / S; q[3] = (matrix44[4] - matrix44[1]) / S; } else if ((matrix44[0] > matrix44[5])&(matrix44[0] > matrix44[10])) { - float S = sqrt(1.0 + matrix44[0] - matrix44[5] - matrix44[10]) * 2; // S=4*qx + FLT S = FLT_SQRT(1.0 + matrix44[0] - matrix44[5] - matrix44[10]) * 2.; // S=4*qx q[0] = (matrix44[9] - matrix44[6]) / S; - q[1] = 0.25 * S; + q[1] = 0.25f * S; q[2] = (matrix44[1] + matrix44[4]) / S; q[3] = (matrix44[2] + matrix44[8]) / S; } else if (matrix44[5] > matrix44[10]) { - float S = sqrt(1.0 + matrix44[5] - matrix44[0] - matrix44[10]) * 2; // S=4*qy + FLT S = FLT_SQRT(1.0 + matrix44[5] - matrix44[0] - matrix44[10]) * 2.; // S=4*qy q[0] = (matrix44[2] - matrix44[8]) / S; q[1] = (matrix44[1] + matrix44[4]) / S; - q[2] = 0.25 * S; + q[2] = 0.25f * S; q[3] = (matrix44[6] + matrix44[9]) / S; } else { - float S = sqrt(1.0 + matrix44[10] - matrix44[0] - matrix44[5]) * 2; // S=4*qz + FLT S = FLT_SQRT(1.0 + matrix44[10] - matrix44[0] - matrix44[5]) * 2.; // S=4*qz q[0] = (matrix44[4] - matrix44[1]) / S; q[1] = (matrix44[2] + matrix44[8]) / S; q[2] = (matrix44[6] + matrix44[9]) / S; diff --git a/redist/os_generic.c b/redist/os_generic.c index 0993d7a..1ab4863 100644 --- a/redist/os_generic.c +++ b/redist/os_generic.c @@ -55,6 +55,7 @@ void * OGJoinThread( og_thread_t ot ) { WaitForSingleObject( ot, INFINITE ); CloseHandle( ot ); + return 0; } void OGCancelThread( og_thread_t ot ) diff --git a/redist/symbol_enumerator.c b/redist/symbol_enumerator.c index 7d33900..fcb3727 100644 --- a/redist/symbol_enumerator.c +++ b/redist/symbol_enumerator.c @@ -51,9 +51,13 @@ BOOL WINAPI SymEnumSymbols( ); BOOL WINAPI SymInitialize( - HANDLE hProcess, - PCTSTR UserSearchPath, - BOOL fInvadeProcess + HANDLE hProcess, + PCTSTR UserSearchPath, + BOOL fInvadeProcess +); + +BOOL WINAPI SymCleanup( + HANDLE hProcess ); BOOL CALLBACK __cdecl mycb( diff --git a/src/poser_charlesslow.c b/src/poser_charlesslow.c index def8323..080ad6a 100644 --- a/src/poser_charlesslow.c +++ b/src/poser_charlesslow.c @@ -123,9 +123,9 @@ int PoserCharlesSlow( SurviveObject * so, PoserData * pd ) ft = RunOpti(so, fs, lh, 0, LighthousePos, LighthouseQuat); if( cycle == 0 ) { - float sk = ft*10.; + FLT sk = ft*10.; if( sk > 1 ) sk = 1; - uint8_t cell = (1.0 - sk) * 255; + uint8_t cell = (uint8_t)((1.0 - sk) * 255); FLT epsilon = 0.1; if( dz == 0 ) { /* Why is dz special? ? */ @@ -231,7 +231,7 @@ static FLT RunOpti( SurviveObject * hmd, PoserDataFullScene * fs, int lh, int pr if( fs->lengths[p][lh][0] < 0 || fs->lengths[p][lh][1] < 0 ) continue; FLT me_to_dot[3]; sub3d( me_to_dot, LighthousePos, &hmd_points[p*3] ); - float dot = dot3d( &hmd_normals[p*3], me_to_dot ); + FLT dot = dot3d( &hmd_normals[p*3], me_to_dot ); if( dot < -.01 ) { return 1000; } } int iters = 6; @@ -321,7 +321,7 @@ static FLT RunOpti( SurviveObject * hmd, PoserDataFullScene * fs, int lh, int pr } //Step 2: Determine error. - float errorsq = 0.0; + FLT errorsq = 0.0; int count = 0; for( p = 0; p < dpts; p++ ) { diff --git a/src/poser_daveortho.c b/src/poser_daveortho.c index 9f3b55a..e81e154 100644 --- a/src/poser_daveortho.c +++ b/src/poser_daveortho.c @@ -120,7 +120,7 @@ int PoserDaveOrtho( SurviveObject * so, PoserData * pd ) break; } } - + return 0; } diff --git a/src/survive.c b/src/survive.c index 9554d9c..f637bd8 100755 --- a/src/survive.c +++ b/src/survive.c @@ -165,6 +165,7 @@ int survive_add_object( SurviveContext * ctx, SurviveObject * obj ) ctx->objs = realloc( ctx->objs, sizeof( SurviveObject * ) * (oldct+1) ); ctx->objs[oldct] = obj; ctx->objs_ct = oldct+1; + return 0; } void survive_add_driver( SurviveContext * ctx, void * payload, DeviceDriverCb poll, DeviceDriverCb close, DeviceDriverMagicCb magic ) @@ -188,7 +189,8 @@ int survive_send_magic( SurviveContext * ctx, int magic_code, void * data, int d for( i = 0; i < oldct; i++ ) { ctx->drivermagics[i]( ctx, ctx->drivers[i], magic_code, data, datalen ); - } + } + return 0; } void survive_close( SurviveContext * ctx ) diff --git a/src/survive_cal.c b/src/survive_cal.c index 985ab24..0eb9446 100755 --- a/src/survive_cal.c +++ b/src/survive_cal.c @@ -18,6 +18,10 @@ #include "survive_config.h" +#ifdef WINDOWS +int mkdir(const char *); +#endif + #define PTS_BEFORE_COMMON 32 #define NEEDED_COMMON_POINTS 10 #define MIN_SENSORS_VISIBLE_PER_LH_FOR_CAL 4 @@ -455,7 +459,7 @@ static void handle_calibration( struct SurviveCalData *cd ) stddevang += Sdiff2; stddevlen += Ldiff2; - int llm = Sdiff / HISTOGRAMBINANG + (HISTOGRAMSIZE/2.0); + int llm = (int)( Sdiff / HISTOGRAMBINANG + (HISTOGRAMSIZE/2.0) ); if( llm < 0 ) llm = 0; if( llm >= HISTOGRAMSIZE ) llm = HISTOGRAMSIZE-1; diff --git a/src/survive_config.c b/src/survive_config.c index 5458ef0..0810280 100644 --- a/src/survive_config.c +++ b/src/survive_config.c @@ -33,7 +33,7 @@ void destroy_config_entry(config_entry* ce) { if (ce->data!=NULL) { free(ce->data); ce->data=NULL; } } -void init_config_group(config_group *cg, uint16_t count) { +void init_config_group(config_group *cg, uint8_t count) { uint16_t i = 0; cg->used_entries = 0; cg->max_entries = count; @@ -99,7 +99,7 @@ void config_set_lighthouse(config_group* lh_config, BaseStationData* bsd, uint8_ } void sstrcpy(char** dest, const char *src) { - uint32_t len = strlen(src)+1; + uint32_t len = (uint32_t)strlen(src)+1; assert(dest!=NULL); char* ptr = (char*)realloc(*dest, len); //acts like malloc if dest==NULL @@ -143,7 +143,7 @@ FLT config_read_float(config_group *cg, const char *tag, const FLT def) { return config_set_float(cg, tag, def); } -uint16_t config_read_float_array(config_group *cg, const char *tag, const FLT** values, const FLT* def, uint16_t count) { +uint16_t config_read_float_array(config_group *cg, const char *tag, const FLT** values, const FLT* def, uint8_t count) { config_entry *cv = find_config_entry(cg, tag); if (cv != NULL) { @@ -237,7 +237,7 @@ void write_config_group(FILE* f, config_group *cg, char *tag) { for (i=0;i < cg->used_entries;++i) { if (cg->config_entries[i].type == CONFIG_FLOAT) { - json_write_float(f, cg->config_entries[i].tag, cg->config_entries[i].numeric.f); + json_write_float(f, cg->config_entries[i].tag, (float)cg->config_entries[i].numeric.f); } else if (cg->config_entries[i].type == CONFIG_UINT32) { json_write_uint32(f, cg->config_entries[i].tag, cg->config_entries[i].numeric.i); } else if (cg->config_entries[i].type == CONFIG_STRING) { @@ -295,7 +295,7 @@ void pop_config_group() { } -int parse_floats(char* tag, char** values, uint16_t count) { +int parse_floats(char* tag, char** values, uint8_t count) { uint16_t i = 0; FLT *f; f = alloca(sizeof(FLT) * count); @@ -348,12 +348,12 @@ int parse_uint32(char* tag, char** values, uint16_t count) { // if (count>1) // config_set_uint32_array(cg, tag, f, count); // else - config_set_uint32(cg, tag, l[0]); + config_set_uint32(cg, tag, (uint32_t)l[0]); return 1; } -void handle_tag_value(char* tag, char** values, uint16_t count) { +void handle_tag_value(char* tag, char** values, uint8_t count) { print_json_value(tag,values,count); config_group* cg = cg_stack[cg_stack_head]; diff --git a/src/survive_config.h b/src/survive_config.h index c8c7762..83db624 100644 --- a/src/survive_config.h +++ b/src/survive_config.h @@ -35,7 +35,7 @@ typedef struct config_group { //extern config_group global_config_values; //extern config_group lh_config[2]; //lighthouse configs -void init_config_group(config_group *cg, uint16_t count); +void init_config_group(config_group *cg, uint8_t count); void destroy_config_group(config_group* cg); //void config_init(); @@ -52,7 +52,7 @@ const uint32_t config_set_uint32(config_group *cg, const char *tag, const uint32 const char* config_set_str(config_group *cg, const char *tag, const char* value); FLT config_read_float(config_group *cg, const char *tag, const FLT def); -uint16_t config_read_float_array(config_group *cg, const char *tag, const FLT** values, const FLT* def, uint16_t count); +uint16_t config_read_float_array(config_group *cg, const char *tag, const FLT** values, const FLT* def, uint8_t count); uint32_t config_read_uint32(config_group *cg, const char *tag, const uint32_t def); const char* config_read_str(config_group *cg, const char *tag, const char *def); diff --git a/src/survive_driverman.c b/src/survive_driverman.c index d694e64..2afaf65 100644 --- a/src/survive_driverman.c +++ b/src/survive_driverman.c @@ -31,7 +31,7 @@ void * GetDriver( const char * element ) const char * GetDriverNameMatching( const char * prefix, int place ) { int i; - int prefixlen = strlen( prefix ); + int prefixlen = (int)strlen( prefix ); for( i = 0; i < NrDrivers; i++ ) { diff --git a/src/survive_vive.c b/src/survive_vive.c index 5a76d24..cdc319d 100755 --- a/src/survive_vive.c +++ b/src/survive_vive.c @@ -550,7 +550,7 @@ int survive_vive_send_magic(struct SurviveContext * ctx, void * drv, int magic_c if( r != sizeof( vive_magic_power_off2 ) ) return 5; } } - + return 0; } void survive_vive_usb_close( struct SurviveViveData * sv ) @@ -594,6 +594,7 @@ int survive_vive_usb_poll( struct SurviveContext * ctx, void * v ) } return r; #endif + return 0; } @@ -1234,6 +1235,7 @@ int survive_vive_close( SurviveContext * ctx, void * driver ) SurviveViveData * sv = driver; survive_vive_usb_close( sv ); + return 0; } diff --git a/winbuild/libsurvive/libsurvive.vcxproj b/winbuild/libsurvive/libsurvive.vcxproj index 2a5029c..82a4e40 100644 --- a/winbuild/libsurvive/libsurvive.vcxproj +++ b/winbuild/libsurvive/libsurvive.vcxproj @@ -77,7 +77,7 @@ Level3 Disabled - USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;_DEBUG;_LIB;%(PreprocessorDefinitions) + USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WINDOWS;_DEBUG;_LIB;%(PreprocessorDefinitions) ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) @@ -91,7 +91,7 @@ Level3 Disabled - USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WINDOWS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) @@ -107,7 +107,7 @@ MaxSpeed true true - USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WINDOWS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) @@ -125,7 +125,7 @@ MaxSpeed true true - USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;NDEBUG;_LIB;%(PreprocessorDefinitions) + USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WINDOWS;NDEBUG;_LIB;%(PreprocessorDefinitions) ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) diff --git a/windows/hid.c b/windows/hid.c index 8f80071..6c379b5 100644 --- a/windows/hid.c +++ b/windows/hid.c @@ -687,7 +687,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char * length = dev->output_report_length; } - res = WriteFile(dev->device_handle, buf, length, NULL, &ol); + res = WriteFile(dev->device_handle, buf, (DWORD)length, NULL, &ol); if (!res) { if (GetLastError() != ERROR_IO_PENDING) { @@ -730,7 +730,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char dev->read_pending = TRUE; memset(dev->read_buf, 0, dev->input_report_length); ResetEvent(ev); - res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol); + res = ReadFile(dev->device_handle, dev->read_buf, (DWORD)dev->input_report_length, &bytes_read, &dev->ol); if (!res) { if (GetLastError() != ERROR_IO_PENDING) { @@ -784,7 +784,7 @@ end_of_function: return -1; } - return copy_len; + return (int)copy_len; } int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) @@ -800,13 +800,13 @@ int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonbloc int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) { - BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, length); + BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, (ULONG)length); if (!res) { register_error(dev, "HidD_SetFeature"); return -1; } - return length; + return (int)length; } @@ -828,8 +828,8 @@ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned res = DeviceIoControl(dev->device_handle, IOCTL_HID_GET_FEATURE, - data, length, - data, length, + data, (DWORD)length, + data, (DWORD)length, &bytes_returned, &ol); if (!res) { @@ -870,7 +870,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev { BOOL res; - res = HidD_GetManufacturerString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); + res = HidD_GetManufacturerString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); if (!res) { register_error(dev, "HidD_GetManufacturerString"); return -1; @@ -883,7 +883,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wch { BOOL res; - res = HidD_GetProductString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); + res = HidD_GetProductString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); if (!res) { register_error(dev, "HidD_GetProductString"); return -1; @@ -896,7 +896,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *de { BOOL res; - res = HidD_GetSerialNumberString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); + res = HidD_GetSerialNumberString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); if (!res) { register_error(dev, "HidD_GetSerialNumberString"); return -1; @@ -909,7 +909,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int { BOOL res; - res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS)); + res = HidD_GetIndexedString(dev->device_handle, string_index, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); if (!res) { register_error(dev, "HidD_GetIndexedString"); return -1; -- cgit v1.2.3 From 5cc41bddc37f8ed116575dddab34b514a417c883 Mon Sep 17 00:00:00 2001 From: ultramn Date: Thu, 16 Mar 2017 18:17:40 -0700 Subject: Modified Makefile to compile on Mac --- Makefile | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index cac4135..11f18f9 100644 --- a/Makefile +++ b/Makefile @@ -2,11 +2,31 @@ all : lib data_recorder test calibrate calibrate_client CC:=gcc + CFLAGS:=-Iinclude/libsurvive -I. -fPIC -g -O3 -Iredist -flto -DUSE_DOUBLE -std=gnu99 -rdynamic -LDFLAGS:=-L/usr/local/lib -lpthread -lusb-1.0 -lz -lX11 -lm -flto -g +LDFLAGS:=-L/usr/local/lib -lpthread -lusb-1.0 -lz -lm -flto -g + +#---------- +# Platform specific changes to CFLAGS/LDFLAGS +#---------- +UNAME=$(shell uname) + +# Mac OSX +ifeq ($(UNAME), Darwin) +DRAWFUNCTIONS_C=redist/RawDrawNull.c +GRAPHICS_LOFI:=redist/RawDrawNull.o + +# Linux / FreeBSD +else +LDFLAGS:=$(LDFLAGS) -lX11 +DRAWFUNCTIONS_C=redist/XDriver.c redist/DrawFunctions.c +GRAPHICS_LOFI:=redist/DrawFunctions.o redist/XDriver.o + +endif + POSERS:=src/poser_dummy.o src/poser_daveortho.o src/poser_charlesslow.o -REDISTS:=redist/json_helpers.o redist/linmath.o redist/jsmn.o +REDISTS:=redist/json_helpers.o redist/linmath.o redist/jsmn.o redist/os_generic.o LIBSURVIVE_CORE:=src/survive.o src/survive_usb.o src/survive_data.o src/survive_process.o src/ootx_decoder.o src/survive_driverman.o src/survive_vive.o src/survive_config.o src/survive_cal.o LIBSURVIVE_CORE:=$(LIBSURVIVE_CORE) LIBSURVIVE_O:=$(POSERS) $(REDISTS) $(LIBSURVIVE_CORE) @@ -21,7 +41,6 @@ LIBSURVIVE_C:=$(LIBSURVIVE_O:.o=.c) # -DRUNTIME_SYMNUM = Don't assume __attribute__((constructor)) works. Instead comb for anything starting with REGISTER. -GRAPHICS_LOFI:=redist/DrawFunctions.o redist/XDriver.o # unused: redist/crc32.c @@ -38,7 +57,7 @@ calibrate_client : calibrate_client.c ./lib/libsurvive.so redist/os_generic.c $ $(CC) -o $@ $^ $(LDFLAGS) $(CFLAGS) ## Still not working!!! Don't use. -static_calibrate : calibrate.c redist/os_generic.c redist/XDriver.c redist/DrawFunctions.c $(LIBSURVIVE_C) +static_calibrate : calibrate.c redist/os_generic.c $(DRAWFUNCTIONS) $(LIBSURVIVE_C) tcc -o $@ $^ $(CFLAGS) $(LDFLAGS) -DTCC lib: @@ -49,7 +68,7 @@ lib/libsurvive.so : $(LIBSURVIVE_O) calibrate_tcc : $(LIBSURVIVE_C) - tcc -DRUNTIME_SYMNUM $(CFLAGS) -o $@ $^ $(LDFLAGS) calibrate.c redist/XDriver.c redist/os_generic.c redist/DrawFunctions.c redist/symbol_enumerator.c + tcc -DRUNTIME_SYMNUM $(CFLAGS) -o $@ $^ $(LDFLAGS) calibrate.c redist/os_generic.c $(DRAWFUNCTIONS) redist/symbol_enumerator.c clean : rm -rf *.o src/*.o *~ src/*~ test data_recorder lib/libsurvive.so redist/*.o redist/*~ -- cgit v1.2.3 From 47d2e48cdb9d894e011fd02ed18486adefc49c72 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 01:18:05 -0400 Subject: Fix TCC compile. --- include/libsurvive/survive.h | 12 ++---------- redist/json_helpers.c | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/include/libsurvive/survive.h b/include/libsurvive/survive.h index 28180e4..e04586c 100644 --- a/include/libsurvive/survive.h +++ b/include/libsurvive/survive.h @@ -138,7 +138,7 @@ void survive_default_angle_process( SurviveObject * so, int sensor_id, int acode void RegisterDriver(const char * name, void * data); -#ifdef _WIN32 +#ifdef _MSC_VER #define REGISTER_LINKTIME( func ) \ __pragma(comment(linker,"/export:REGISTER"#func));\ void REGISTER##func() { RegisterDriver(#func, &func); } @@ -157,22 +157,14 @@ void survive_add_driver( SurviveContext * ctx, void * payload, DeviceDriverCb po //For lightcap, etc. Don't change this structure at all. Regular vive is dependent on it being exactly as-is. //When you write drivers, you can use this to send survive lightcap data. -#ifdef _WIN32 -#pragma pack(push,1) -#endif typedef struct { uint8_t sensor_id; uint16_t length; uint32_t timestamp; } -#ifdef __linux__ -__attribute__((packed)) -#endif LightcapElement; -#ifdef _WIN32 -#pragma pack(pop) -#endif + //This is the disambiguator function, for taking light timing and figuring out place-in-sweep for a given photodiode. void handle_lightcap( SurviveObject * so, LightcapElement * le ); diff --git a/redist/json_helpers.c b/redist/json_helpers.c index 1e2f43e..115076e 100644 --- a/redist/json_helpers.c +++ b/redist/json_helpers.c @@ -11,7 +11,7 @@ #include #endif -#ifdef _WIN32 +#ifdef _MSC_VER #include // Windows doesn't provide asprintf, so we need to make it. -- cgit v1.2.3 From 1837afbe2aa17af10fa508d71807912b0da6ec50 Mon Sep 17 00:00:00 2001 From: ultramn Date: Thu, 16 Mar 2017 18:22:32 -0700 Subject: Makefile now compiles on Mac --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 11f18f9..03f37d6 100644 --- a/Makefile +++ b/Makefile @@ -13,13 +13,13 @@ UNAME=$(shell uname) # Mac OSX ifeq ($(UNAME), Darwin) -DRAWFUNCTIONS_C=redist/RawDrawNull.c -GRAPHICS_LOFI:=redist/RawDrawNull.o +DRAWFUNCTIONS=redist/DrawFunctions.c redist/RawDrawNull.c +GRAPHICS_LOFI:=redist/DrawFunctions.o redist/RawDrawNull.o # Linux / FreeBSD else LDFLAGS:=$(LDFLAGS) -lX11 -DRAWFUNCTIONS_C=redist/XDriver.c redist/DrawFunctions.c +DRAWFUNCTIONS=redist/DrawFunctions.c redist/XDriver.c GRAPHICS_LOFI:=redist/DrawFunctions.o redist/XDriver.o endif -- cgit v1.2.3 From d84be3e09ce89a291f5b9eb04e6cc1fd34a00541 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 01:33:26 -0400 Subject: Remove winbuild folder. --- .gitignore | 12 +- redist/json_helpers.c | 3 +- src/survive_data.c | 2 +- winbuild/build_tcc.bat | 14 + winbuild/hid.c | 996 +++++++++++++++++ winbuild/hidapi.h | 405 +++++++ winbuild/libsurvive/libsurvive.vcxproj | 12 +- winbuild/libsurvive/libsurvive.vcxproj.filters | 8 +- winbuild/tcc_stubs.c | 59 + windows/build_tcc.bat | 14 - windows/custom_msvcrt.def | 1400 ------------------------ windows/hid.c | 996 ----------------- windows/hidapi.h | 405 ------- windows/tcc_stubs.c | 59 - 14 files changed, 1494 insertions(+), 2891 deletions(-) create mode 100644 winbuild/build_tcc.bat create mode 100644 winbuild/hid.c create mode 100644 winbuild/hidapi.h create mode 100644 winbuild/tcc_stubs.c delete mode 100644 windows/build_tcc.bat delete mode 100644 windows/custom_msvcrt.def delete mode 100644 windows/hid.c delete mode 100644 windows/hidapi.h delete mode 100644 windows/tcc_stubs.c diff --git a/.gitignore b/.gitignore index 034a8bc..4c22fa3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,11 @@ *.o lib test -windows/calibrate.exe -windows/calinfo/* -windows/calibrate.def -windows/udev[USB_DEV_LIGHTHOUSE] -windows/config.json +winbuild/calibrate.exe +winbuild/calinfo/* +winbuild/calibrate.def +winbuild/udev[USB_DEV_LIGHTHOUSE] +winbuild/config.json winbuild/x64/* winbuild/calibrate/calinfo/* winbuild/calibrate/config.json @@ -16,3 +16,5 @@ winbuild/.vs/* *.ipch winbuild/.vs/libsurvive/v15/.suo *.tlog +winbuild/calibrate.exe +winbuild/calibrate.def diff --git a/redist/json_helpers.c b/redist/json_helpers.c index 115076e..eb3600b 100644 --- a/redist/json_helpers.c +++ b/redist/json_helpers.c @@ -164,7 +164,8 @@ void json_load_file(const char* path) { jsmn_parser parser; jsmn_init(&parser); - uint32_t items = jsmn_parse(&parser, JSON_STRING, JSON_STRING_LEN, NULL, 0); + int32_t items = jsmn_parse(&parser, JSON_STRING, JSON_STRING_LEN, NULL, 0); + if (items < 0) return; jsmntok_t* tokens = malloc(items * sizeof(jsmntok_t)); jsmn_init(&parser); diff --git a/src/survive_data.c b/src/survive_data.c index 60849e2..4a2cfb6 100644 --- a/src/survive_data.c +++ b/src/survive_data.c @@ -44,7 +44,7 @@ void handle_lightcap( SurviveObject * so, LightcapElement * le ) { int is_new_pulse = delta > so->pulselength_min_sync /*1500*/ + last_sync_length; - printf("m sync %d %d %d %d\n", le->sensor_id, so->last_sync_time[ssn], le->timestamp, delta); +// printf("m sync %d %d %d %d\n", le->sensor_id, so->last_sync_time[ssn], le->timestamp, delta); so->did_handle_ootx = 0; diff --git a/winbuild/build_tcc.bat b/winbuild/build_tcc.bat new file mode 100644 index 0000000..753ba7c --- /dev/null +++ b/winbuild/build_tcc.bat @@ -0,0 +1,14 @@ +@echo off + +set TCC=C:\tcc\tcc.exe +echo Be sure to have TinyCC installed to %TCC% (or change the TCC parameter.) + +set SR=..\src\ +set RD=..\redist\ +set SOURCES=%SR%ootx_decoder.c %SR%poser_charlesslow.c %SR%poser_daveortho.c %SR%poser_dummy.c %SR%survive.c %SR%survive_cal.c %SR%survive_config.c %SR%survive_data.c %SR%survive_driverman.c %SR%survive_process.c %SR%survive_vive.c +set REDIST=%RD%crc32.c %RD%linmath.c %RD%puff.c %RD%jsmn.c %RD%json_helpers.c %RD%symbol_enumerator.c +set EXEC=..\calibrate.c %RD%WinDriver.c %RD%os_generic.c %RD%DrawFunctions.c +set CFLAGS=-DNOZLIB -DTCC -DWINDOWS -DHIDAPI -DWIN32 -DRUNTIME_SYMNUM -O0 -g -rdynamic -I..\redist -I..\include\libsurvive -I..\src -I. +set LDFLAGS=-lkernel32 -lgdi32 -luser32 -lsetupapi -ldbghelp +@echo on +%TCC% -v %CFLAGS% %SOURCES% %REDIST% %EXEC% %LDFLAGS% tcc_stubs.c hid.c -o calibrate.exe diff --git a/winbuild/hid.c b/winbuild/hid.c new file mode 100644 index 0000000..6c379b5 --- /dev/null +++ b/winbuild/hid.c @@ -0,0 +1,996 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + + +/* Copy of LICENSE-orig.txt (compatible with MIT/x11 license) + + HIDAPI - Multi-Platform library for + communication with HID devices. + + Copyright 2009, Alan Ott, Signal 11 Software. + All Rights Reserved. + + This software may be used by anyone for any reason so + long as the copyright notice in the source files + remains intact. +*/ + +#include + +#ifndef _NTDEF_ +typedef LONG NTSTATUS; +#endif + +#ifdef __MINGW32__ +#include +#include +#endif + +#ifdef __CYGWIN__ +#include +#define _wcsdup wcsdup +#endif + +/* The maximum number of characters that can be passed into the + HidD_Get*String() functions without it failing.*/ +#define MAX_STRING_WCHARS 0xFFF + +/*#define HIDAPI_USE_DDK*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef TCC + typedef struct _SP_DEVINFO_DATA { + DWORD cbSize; + GUID ClassGuid; + DWORD DevInst; + ULONG_PTR Reserved; + } SP_DEVINFO_DATA, *PSP_DEVINFO_DATA; + typedef struct _SP_DEVICE_INTERFACE_DATA { + DWORD cbSize; + GUID InterfaceClassGuid; + DWORD Flags; + ULONG_PTR Reserved; + } SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA; + typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA { + DWORD cbSize; + CHAR DevicePath[ANYSIZE_ARRAY]; + } SP_DEVICE_INTERFACE_DETAIL_DATA_A, *PSP_DEVICE_INTERFACE_DETAIL_DATA_A; + typedef PVOID HDEVINFO; + + HDEVINFO WINAPI SetupDiGetClassDevsA(CONST GUID*,PCSTR,HWND,DWORD); + + #define DIGCF_PRESENT 0x00000002 + #define DIGCF_DEVICEINTERFACE 0x00000010 + #define SPDRP_CLASS 7 + #define SPDRP_DRIVER 9 + #define FILE_DEVICE_KEYBOARD 0x0000000b + #define METHOD_OUT_DIRECT 2 + enum + { FILE_ANY_ACCESS = 0x00000000UL, + FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS, + FILE_READ_ACCESS = 0x00000001UL, + FILE_WRITE_ACCESS = 0x00000002UL + }; + #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m)) + +#else + #include + #include +#endif + #ifdef HIDAPI_USE_DDK + #include + #endif + + /* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */ + #define HID_OUT_CTL_CODE(id) \ + CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include +#include + + +#include "hidapi.h" + +#undef MIN +#define MIN(x,y) ((x) < (y)? (x): (y)) + +#ifdef _MSC_VER + /* Thanks Microsoft, but I know how to use strncpy(). */ + #pragma warning(disable:4996) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HIDAPI_USE_DDK + /* Since we're not building with the DDK, and the HID header + files aren't part of the SDK, we have to define all this + stuff here. In lookup_functions(), the function pointers + defined below are set. */ + typedef struct _HIDD_ATTRIBUTES{ + ULONG Size; + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; + } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; + + typedef USHORT USAGE; + typedef struct _HIDP_CAPS { + USAGE Usage; + USAGE UsagePage; + USHORT InputReportByteLength; + USHORT OutputReportByteLength; + USHORT FeatureReportByteLength; + USHORT Reserved[17]; + USHORT fields_not_used_by_hidapi[10]; + } HIDP_CAPS, *PHIDP_CAPS; + typedef void* PHIDP_PREPARSED_DATA; + #define HIDP_STATUS_SUCCESS 0x110000 + + typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib); + typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); + typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data); + typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps); + typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers); + + static HidD_GetAttributes_ HidD_GetAttributes; + static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; + static HidD_GetManufacturerString_ HidD_GetManufacturerString; + static HidD_GetProductString_ HidD_GetProductString; + static HidD_SetFeature_ HidD_SetFeature; + static HidD_GetFeature_ HidD_GetFeature; + static HidD_GetIndexedString_ HidD_GetIndexedString; + static HidD_GetPreparsedData_ HidD_GetPreparsedData; + static HidD_FreePreparsedData_ HidD_FreePreparsedData; + static HidP_GetCaps_ HidP_GetCaps; + static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers; + + static HMODULE lib_handle = NULL; + static BOOLEAN initialized = FALSE; +#endif /* HIDAPI_USE_DDK */ + +struct hid_device_ { + HANDLE device_handle; + BOOL blocking; + USHORT output_report_length; + size_t input_report_length; + void *last_error_str; + DWORD last_error_num; + BOOL read_pending; + char *read_buf; + OVERLAPPED ol; +}; + +static hid_device *new_hid_device() +{ + hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); + dev->device_handle = INVALID_HANDLE_VALUE; + dev->blocking = TRUE; + dev->output_report_length = 0; + dev->input_report_length = 0; + dev->last_error_str = NULL; + dev->last_error_num = 0; + dev->read_pending = FALSE; + dev->read_buf = NULL; + memset(&dev->ol, 0, sizeof(dev->ol)); + dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + CloseHandle(dev->ol.hEvent); + CloseHandle(dev->device_handle); + LocalFree(dev->last_error_str); + free(dev->read_buf); + free(dev); +} + +static void register_error(hid_device *device, const char *op) +{ + WCHAR *ptr, *msg; + + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPVOID)&msg, 0/*sz*/, + NULL); + + /* Get rid of the CR and LF that FormatMessage() sticks at the + end of the message. Thanks Microsoft! */ + ptr = msg; + while (*ptr) { + if (*ptr == '\r') { + *ptr = 0x0000; + break; + } + ptr++; + } + + /* Store the message off in the Device entry so that + the hid_error() function can pick it up. */ + LocalFree(device->last_error_str); + device->last_error_str = msg; +} + +#ifndef HIDAPI_USE_DDK +static int lookup_functions() +{ + lib_handle = LoadLibraryA("hid.dll"); + if (lib_handle) { +#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1; + RESOLVE(HidD_GetAttributes); + RESOLVE(HidD_GetSerialNumberString); + RESOLVE(HidD_GetManufacturerString); + RESOLVE(HidD_GetProductString); + RESOLVE(HidD_SetFeature); + RESOLVE(HidD_GetFeature); + RESOLVE(HidD_GetIndexedString); + RESOLVE(HidD_GetPreparsedData); + RESOLVE(HidD_FreePreparsedData); + RESOLVE(HidP_GetCaps); + RESOLVE(HidD_SetNumInputBuffers); +#undef RESOLVE + } + else + return -1; + + return 0; +} +#endif + +static HANDLE open_device(const char *path, BOOL enumerate) +{ + HANDLE handle; + DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ); + DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; + + handle = CreateFileA(path, + desired_access, + share_mode, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/ + 0); + + return handle; +} + +int HID_API_EXPORT hid_init(void) +{ +#ifndef HIDAPI_USE_DDK + if (!initialized) { + if (lookup_functions() < 0) { + hid_exit(); + return -1; + } + initialized = TRUE; + } +#endif + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ +#ifndef HIDAPI_USE_DDK + if (lib_handle) + FreeLibrary(lib_handle); + lib_handle = NULL; + initialized = FALSE; +#endif + return 0; +} + +struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + BOOL res; + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + + /* Windows objects for interacting with the driver. */ + GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; + SP_DEVINFO_DATA devinfo_data; + SP_DEVICE_INTERFACE_DATA device_interface_data; + SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; + HDEVINFO device_info_set = INVALID_HANDLE_VALUE; + int device_index = 0; + int i; + + if (hid_init() < 0) + return NULL; + + /* Initialize the Windows objects. */ + memset(&devinfo_data, 0x0, sizeof(devinfo_data)); + devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); + device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + /* Get information for all the devices belonging to the HID class. */ + device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + + /* Iterate over each device in the HID class, looking for the right one. */ + + for (;;) { + HANDLE write_handle = INVALID_HANDLE_VALUE; + DWORD required_size = 0; + HIDD_ATTRIBUTES attrib; + + res = SetupDiEnumDeviceInterfaces(device_info_set, + NULL, + &InterfaceClassGuid, + device_index, + &device_interface_data); + + if (!res) { + /* A return of FALSE from this function means that + there are no more devices. */ + break; + } + + /* Call with 0-sized detail size, and let the function + tell us how long the detail struct needs to be. The + size is put in &required_size. */ + res = SetupDiGetDeviceInterfaceDetailA(device_info_set, + &device_interface_data, + NULL, + 0, + &required_size, + NULL); + + /* Allocate a long enough structure for device_interface_detail_data. */ + device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); + device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + + /* Get the detailed data for this device. The detail data gives us + the device path for this device, which is then passed into + CreateFile() to get a handle to the device. */ + res = SetupDiGetDeviceInterfaceDetailA(device_info_set, + &device_interface_data, + device_interface_detail_data, + required_size, + NULL, + NULL); + + if (!res) { + /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); + Continue to the next device. */ + goto cont; + } + + /* Make sure this device is of Setup Class "HIDClass" and has a + driver bound to it. */ + for (i = 0; ; i++) { + char driver_name[256]; + + /* Populate devinfo_data. This function will return failure + when there are no more interfaces left. */ + res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); + if (!res) + goto cont; + + res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, + SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); + if (!res) + goto cont; + + if (strcmp(driver_name, "HIDClass") == 0) { + /* See if there's a driver bound. */ + res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, + SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); + if (res) + break; + } + } + + //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); + + /* Open a handle to the device */ + write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); + + /* Check validity of write_handle. */ + if (write_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + //register_error(dev, "CreateFile"); + goto cont_close; + } + + + /* Get the Vendor ID and Product ID for this device. */ + attrib.Size = sizeof(HIDD_ATTRIBUTES); + HidD_GetAttributes(write_handle, &attrib); + //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); + + /* Check the VID/PID to see if we should add this + device to the enumeration list. */ + if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && + (product_id == 0x0 || attrib.ProductID == product_id)) { + + #define WSTR_LEN 512 + const char *str; + struct hid_device_info *tmp; + PHIDP_PREPARSED_DATA pp_data = NULL; + HIDP_CAPS caps; + BOOLEAN res; + NTSTATUS nt_res; + wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ + size_t len; + + /* VID/PID match. Create the record. */ + tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Get the Usage Page and Usage for this device. */ + res = HidD_GetPreparsedData(write_handle, &pp_data); + if (res) { + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res == HIDP_STATUS_SUCCESS) { + cur_dev->usage_page = caps.UsagePage; + cur_dev->usage = caps.Usage; + } + + HidD_FreePreparsedData(pp_data); + } + + /* Fill out the record */ + cur_dev->next = NULL; + str = device_interface_detail_data->DevicePath; + if (str) { + len = strlen(str); + cur_dev->path = (char*) calloc(len+1, sizeof(char)); + strncpy(cur_dev->path, str, len+1); + cur_dev->path[len] = '\0'; + } + else + cur_dev->path = NULL; + + /* Serial Number */ + res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->serial_number = _wcsdup(wstr); + } + + /* Manufacturer String */ + res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->manufacturer_string = _wcsdup(wstr); + } + + /* Product String */ + res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->product_string = _wcsdup(wstr); + } + + /* VID/PID */ + cur_dev->vendor_id = attrib.VendorID; + cur_dev->product_id = attrib.ProductID; + + /* Release Number */ + cur_dev->release_number = attrib.VersionNumber; + + /* Interface Number. It can sometimes be parsed out of the path + on Windows if a device has multiple interfaces. See + http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or + search for "Hardware IDs for HID Devices" at MSDN. If it's not + in the path, it's set to -1. */ + cur_dev->interface_number = -1; + if (cur_dev->path) { + char *interface_component = strstr(cur_dev->path, "&mi_"); + if (interface_component) { + char *hex_str = interface_component + 4; + char *endptr = NULL; + cur_dev->interface_number = strtol(hex_str, &endptr, 16); + if (endptr == hex_str) { + /* The parsing failed. Set interface_number to -1. */ + cur_dev->interface_number = -1; + } + } + } + } + +cont_close: + CloseHandle(write_handle); +cont: + /* We no longer need the detail data. It can be freed */ + free(device_interface_detail_data); + + device_index++; + + } + + /* Close the device information handle. */ + SetupDiDestroyDeviceInfoList(device_info_set); + + return root; + +} + +void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) +{ + /* TODO: Merge this with the Linux version. This function is platform-independent. */ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + + +HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + /* TODO: Merge this functions with the Linux version. This function should be platform independent. */ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device *handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) +{ + hid_device *dev; + HIDP_CAPS caps; + PHIDP_PREPARSED_DATA pp_data = NULL; + BOOLEAN res; + NTSTATUS nt_res; + + if (hid_init() < 0) { + return NULL; + } + + dev = new_hid_device(); + + /* Open a handle to the device */ + dev->device_handle = open_device(path, FALSE); + + /* Check validity of write_handle. */ + if (dev->device_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + register_error(dev, "CreateFile"); + goto err; + } + + /* Set the Input Report buffer size to 64 reports. */ + res = HidD_SetNumInputBuffers(dev->device_handle, 64); + if (!res) { + register_error(dev, "HidD_SetNumInputBuffers"); + goto err; + } + + /* Get the Input Report length for the device. */ + res = HidD_GetPreparsedData(dev->device_handle, &pp_data); + if (!res) { + register_error(dev, "HidD_GetPreparsedData"); + goto err; + } + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res != HIDP_STATUS_SUCCESS) { + register_error(dev, "HidP_GetCaps"); + goto err_pp_data; + } + dev->output_report_length = caps.OutputReportByteLength; + dev->input_report_length = caps.InputReportByteLength; + HidD_FreePreparsedData(pp_data); + + dev->read_buf = (char*) malloc(dev->input_report_length); + + return dev; + +err_pp_data: + HidD_FreePreparsedData(pp_data); +err: + free_hid_device(dev); + return NULL; +} + +int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + DWORD bytes_written; + BOOL res; + + OVERLAPPED ol; + unsigned char *buf; + memset(&ol, 0, sizeof(ol)); + + /* Make sure the right number of bytes are passed to WriteFile. Windows + expects the number of bytes which are in the _longest_ report (plus + one for the report number) bytes even if the data is a report + which is shorter than that. Windows gives us this value in + caps.OutputReportByteLength. If a user passes in fewer bytes than this, + create a temporary buffer which is the proper size. */ + if (length >= dev->output_report_length) { + /* The user passed the right number of bytes. Use the buffer as-is. */ + buf = (unsigned char *) data; + } else { + /* Create a temporary buffer and copy the user's data + into it, padding the rest with zeros. */ + buf = (unsigned char *) malloc(dev->output_report_length); + memcpy(buf, data, length); + memset(buf + length, 0, dev->output_report_length - length); + length = dev->output_report_length; + } + + res = WriteFile(dev->device_handle, buf, (DWORD)length, NULL, &ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* WriteFile() failed. Return error. */ + register_error(dev, "WriteFile"); + bytes_written = -1; + goto end_of_function; + } + } + + /* Wait here until the write is done. This makes + hid_write() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/); + if (!res) { + /* The Write operation failed. */ + register_error(dev, "WriteFile"); + bytes_written = -1; + goto end_of_function; + } + +end_of_function: + if (buf != data) + free(buf); + + return bytes_written; +} + + +int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + DWORD bytes_read = 0; + size_t copy_len = 0; + BOOL res; + + /* Copy the handle for convenience. */ + HANDLE ev = dev->ol.hEvent; + + if (!dev->read_pending) { + /* Start an Overlapped I/O read. */ + dev->read_pending = TRUE; + memset(dev->read_buf, 0, dev->input_report_length); + ResetEvent(ev); + res = ReadFile(dev->device_handle, dev->read_buf, (DWORD)dev->input_report_length, &bytes_read, &dev->ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* ReadFile() has failed. + Clean up and return error. */ + CancelIo(dev->device_handle); + dev->read_pending = FALSE; + goto end_of_function; + } + } + } + + if (milliseconds >= 0) { + /* See if there is any data yet. */ + res = WaitForSingleObject(ev, milliseconds); + if (res != WAIT_OBJECT_0) { + /* There was no data this time. Return zero bytes available, + but leave the Overlapped I/O running. */ + return 0; + } + } + + /* Either WaitForSingleObject() told us that ReadFile has completed, or + we are in non-blocking mode. Get the number of bytes read. The actual + data has been copied to the data[] array which was passed to ReadFile(). */ + res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); + + /* Set pending back to false, even if GetOverlappedResult() returned error. */ + dev->read_pending = FALSE; + + if (res && bytes_read > 0) { + if (dev->read_buf[0] == 0x0) { + /* If report numbers aren't being used, but Windows sticks a report + number (0x0) on the beginning of the report anyway. To make this + work like the other platforms, and to make it work more like the + HID spec, we'll skip over this byte. */ + bytes_read--; + copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf+1, copy_len); + } + else { + /* Copy the whole buffer, report number and all. */ + copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf, copy_len); + } + } + +end_of_function: + if (!res) { + register_error(dev, "GetOverlappedResult"); + return -1; + } + + return (int)copy_len; +} + +int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) +{ + dev->blocking = !nonblock; + return 0; /* Success */ +} + +int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, (ULONG)length); + if (!res) { + register_error(dev, "HidD_SetFeature"); + return -1; + } + + return (int)length; +} + + +int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + BOOL res; +#if 0 + res = HidD_GetFeature(dev->device_handle, data, length); + if (!res) { + register_error(dev, "HidD_GetFeature"); + return -1; + } + return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */ +#else + DWORD bytes_returned; + + OVERLAPPED ol; + memset(&ol, 0, sizeof(ol)); + + res = DeviceIoControl(dev->device_handle, + IOCTL_HID_GET_FEATURE, + data, (DWORD)length, + data, (DWORD)length, + &bytes_returned, &ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* DeviceIoControl() failed. Return error. */ + register_error(dev, "Send Feature Report DeviceIoControl"); + return -1; + } + } + + /* Wait here until the write is done. This makes + hid_get_feature_report() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/); + if (!res) { + /* The operation failed. */ + register_error(dev, "Send Feature Report GetOverLappedResult"); + return -1; + } + + /* bytes_returned does not include the first byte which contains the + report ID. The data buffer actually contains one more byte than + bytes_returned. */ + bytes_returned++; + + return bytes_returned; +#endif +} + +void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) +{ + if (!dev) + return; + CancelIo(dev->device_handle); + free_hid_device(dev); +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetManufacturerString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetManufacturerString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetProductString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetProductString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetSerialNumberString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetSerialNumberString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetIndexedString(dev->device_handle, string_index, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetIndexedString"); + return -1; + } + + return 0; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + return (wchar_t*)dev->last_error_str; +} + + +/*#define PICPGM*/ +/*#define S11*/ +#define P32 +#ifdef S11 + unsigned short VendorID = 0xa0a0; + unsigned short ProductID = 0x0001; +#endif + +#ifdef P32 + unsigned short VendorID = 0x04d8; + unsigned short ProductID = 0x3f; +#endif + + +#ifdef PICPGM + unsigned short VendorID = 0x04d8; + unsigned short ProductID = 0x0033; +#endif + + +#if 0 +int __cdecl main(int argc, char* argv[]) +{ + int res; + unsigned char buf[65]; + + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + /* Set up the command buffer. */ + memset(buf,0x00,sizeof(buf)); + buf[0] = 0; + buf[1] = 0x81; + + + /* Open the device. */ + int handle = open(VendorID, ProductID, L"12345"); + if (handle < 0) + printf("unable to open device\n"); + + + /* Toggle LED (cmd 0x80) */ + buf[1] = 0x80; + res = write(handle, buf, 65); + if (res < 0) + printf("Unable to write()\n"); + + /* Request state (cmd 0x81) */ + buf[1] = 0x81; + write(handle, buf, 65); + if (res < 0) + printf("Unable to write() (2)\n"); + + /* Read requested state */ + read(handle, buf, 65); + if (res < 0) + printf("Unable to read()\n"); + + /* Print out the returned buffer. */ + for (int i = 0; i < 4; i++) + printf("buf[%d]: %d\n", i, buf[i]); + + return 0; +} +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/winbuild/hidapi.h b/winbuild/hidapi.h new file mode 100644 index 0000000..43b8e7a --- /dev/null +++ b/winbuild/hidapi.h @@ -0,0 +1,405 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/* Copy of LICENSE-orig.txt (compatible with MIT/x11 license) + + HIDAPI - Multi-Platform library for + communication with HID devices. + + Copyright 2009, Alan Ott, Signal 11 Software. + All Rights Reserved. + + This software may be used by anyone for any reason so + long as the copyright notice in the source files + remains intact. +*/ + + +/** @file + * @defgroup API hidapi API + */ + +#ifndef HIDAPI_H__ +#define HIDAPI_H__ + +#include + +#ifdef _WIN32 + #define HID_API_EXPORT __declspec(dllexport) + #define HID_API_CALL +#else + #define HID_API_EXPORT /**< API export macro */ + #define HID_API_CALL /**< API call macro */ +#endif + +#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ + +#ifdef __cplusplus +extern "C" { +#endif + struct hid_device_; + typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ + + /** hidapi info structure */ + struct hid_device_info { + /** Platform-specific device path */ + char *path; + /** Device Vendor ID */ + unsigned short vendor_id; + /** Device Product ID */ + unsigned short product_id; + /** Serial Number */ + wchar_t *serial_number; + /** Device Release Number in binary-coded decimal, + also known as Device Version Number */ + unsigned short release_number; + /** Manufacturer String */ + wchar_t *manufacturer_string; + /** Product string */ + wchar_t *product_string; + /** Usage Page for this Device/Interface + (Windows/Mac only). */ + unsigned short usage_page; + /** Usage for this Device/Interface + (Windows/Mac only).*/ + unsigned short usage; + /** The USB interface which this logical device + represents. Valid on both Linux implementations + in all cases, and valid on the Windows implementation + only if the device contains more than one interface. */ + int interface_number; + + /** Pointer to the next device */ + struct hid_device_info *next; + }; + + + /** @brief Initialize the HIDAPI library. + + This function initializes the HIDAPI library. Calling it is not + strictly necessary, as it will be called automatically by + hid_enumerate() and any of the hid_open_*() functions if it is + needed. This function should be called at the beginning of + execution however, if there is a chance of HIDAPI handles + being opened by different threads simultaneously. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_init(void); + + /** @brief Finalize the HIDAPI library. + + This function frees all of the static data associated with + HIDAPI. It should be called at the end of execution to avoid + memory leaks. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_exit(void); + + /** @brief Enumerate the HID Devices. + + This function returns a linked list of all the HID devices + attached to the system which match vendor_id and product_id. + If @p vendor_id is set to 0 then any vendor matches. + If @p product_id is set to 0 then any product matches. + If @p vendor_id and @p product_id are both set to 0, then + all HID devices will be returned. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the types of device + to open. + @param product_id The Product ID (PID) of the types of + device to open. + + @returns + This function returns a pointer to a linked list of type + struct #hid_device, containing information about the HID devices + attached to the system, or NULL in the case of failure. Free + this linked list by calling hid_free_enumeration(). + */ + struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); + + /** @brief Free an enumeration Linked List + + This function frees a linked list created by hid_enumerate(). + + @ingroup API + @param devs Pointer to a list of struct_device returned from + hid_enumerate(). + */ + void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); + + /** @brief Open a HID device using a Vendor ID (VID), Product ID + (PID) and optionally a serial number. + + If @p serial_number is NULL, the first device with the + specified VID and PID is opened. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the device to open. + @param product_id The Product ID (PID) of the device to open. + @param serial_number The Serial Number of the device to open + (Optionally NULL). + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); + + /** @brief Open a HID device by its path name. + + The path name be determined by calling hid_enumerate(), or a + platform-specific path name can be used (eg: /dev/hidraw0 on + Linux). + + @ingroup API + @param path The path name of the device to open + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); + + /** @brief Write an Output report to a HID device. + + The first byte of @p data[] must contain the Report ID. For + devices which only support a single report, this must be set + to 0x0. The remaining bytes contain the report data. Since + the Report ID is mandatory, calls to hid_write() will always + contain one more byte than the report contains. For example, + if a hid report is 16 bytes long, 17 bytes must be passed to + hid_write(), the Report ID (or 0x0, for devices with a + single report), followed by the report data (16 bytes). In + this example, the length passed in would be 17. + + hid_write() will send the data on the first OUT endpoint, if + one exists. If it does not, it will send the data through + the Control Endpoint (Endpoint 0). + + @ingroup API + @param device A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send. + + @returns + This function returns the actual number of bytes written and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); + + /** @brief Read an Input report from a HID device with timeout. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + @param milliseconds timeout in milliseconds or -1 for blocking wait. + + @returns + This function returns the actual number of bytes read and + -1 on error. If no packet was available to be read within + the timeout period, this function returns 0. + */ + int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); + + /** @brief Read an Input report from a HID device. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + + @returns + This function returns the actual number of bytes read and + -1 on error. If no packet was available to be read and + the handle is in non-blocking mode, this function returns 0. + */ + int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); + + /** @brief Set the device handle to be non-blocking. + + In non-blocking mode calls to hid_read() will return + immediately with a value of 0 if there is no data to be + read. In blocking mode, hid_read() will wait (block) until + there is data to read before returning. + + Nonblocking can be turned on and off at any time. + + @ingroup API + @param device A device handle returned from hid_open(). + @param nonblock enable or not the nonblocking reads + - 1 to enable nonblocking + - 0 to disable nonblocking. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); + + /** @brief Send a Feature report to the device. + + Feature reports are sent over the Control endpoint as a + Set_Report transfer. The first byte of @p data[] must + contain the Report ID. For devices which only support a + single report, this must be set to 0x0. The remaining bytes + contain the report data. Since the Report ID is mandatory, + calls to hid_send_feature_report() will always contain one + more byte than the report contains. For example, if a hid + report is 16 bytes long, 17 bytes must be passed to + hid_send_feature_report(): the Report ID (or 0x0, for + devices which do not use numbered reports), followed by the + report data (16 bytes). In this example, the length passed + in would be 17. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send, including + the report number. + + @returns + This function returns the actual number of bytes written and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); + + /** @brief Get a feature report from a HID device. + + Set the first byte of @p data[] to the Report ID of the + report to be read. Make sure to allow space for this + extra byte in @p data[]. Upon return, the first byte will + still contain the Report ID, and the report data will + start in data[1]. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into, including + the Report ID. Set the first byte of @p data[] to the + Report ID of the report to be read, or set it to zero + if your device does not use numbered reports. + @param length The number of bytes to read, including an + extra byte for the report ID. The buffer can be longer + than the actual report. + + @returns + This function returns the number of bytes read plus + one for the report ID (which is still in the first + byte), or -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); + + /** @brief Close a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + */ + void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); + + /** @brief Get The Manufacturer String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get The Product String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get The Serial Number String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get a string from a HID device, based on its string index. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string_index The index of the string to get. + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); + + /** @brief Get a string describing the last error which occurred. + + @ingroup API + @param device A device handle returned from hid_open(). + + @returns + This function returns a string containing the last error + which occurred or NULL if none has occurred. + */ + HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/winbuild/libsurvive/libsurvive.vcxproj b/winbuild/libsurvive/libsurvive.vcxproj index 82a4e40..c19beda 100644 --- a/winbuild/libsurvive/libsurvive.vcxproj +++ b/winbuild/libsurvive/libsurvive.vcxproj @@ -78,7 +78,7 @@ Level3 Disabled USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WINDOWS;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) + ..\..\winbuild;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) Windows @@ -92,7 +92,7 @@ Level3 Disabled USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WINDOWS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) + ..\..\winbuild;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) Windows @@ -108,7 +108,7 @@ true true USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WINDOWS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) + ..\..\winbuild;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) Windows @@ -126,7 +126,7 @@ true true USE_DOUBLE;RUNTIME_SYMNUM;RUNTIME_SYMNUMX;NOZLIB;_CRT_SECURE_NO_WARNINGS;HIDAPI;WINDOWS;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\..\windows;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) + ..\..\winbuild;..\..\include\libsurvive;..\..\redist;%(AdditionalIncludeDirectories) Windows @@ -160,7 +160,7 @@ - + @@ -177,7 +177,7 @@ - + diff --git a/winbuild/libsurvive/libsurvive.vcxproj.filters b/winbuild/libsurvive/libsurvive.vcxproj.filters index 370ce14..8cb8a3d 100644 --- a/winbuild/libsurvive/libsurvive.vcxproj.filters +++ b/winbuild/libsurvive/libsurvive.vcxproj.filters @@ -78,10 +78,10 @@ Source Files - + Source Files - + Source Files @@ -125,10 +125,10 @@ Header Files - + Header Files - + Header Files diff --git a/winbuild/tcc_stubs.c b/winbuild/tcc_stubs.c new file mode 100644 index 0000000..7872914 --- /dev/null +++ b/winbuild/tcc_stubs.c @@ -0,0 +1,59 @@ + +#include <_mingw.h> + +#define REMATH(x) double __cdecl x( double f ); float x##f(float v) { return x(v); } + +REMATH( acos ); +REMATH( cos ); +REMATH( sin ); +REMATH( sqrt ); +REMATH( asin ); + +double __cdecl strtod (const char* str, char** endptr); +float strtof( const char* str, char** endptr) +{ + return strtod( str, endptr ); +} + +double __cdecl atan2(double a, double b); +float atan2f(float a, float b) +{ + return atan2( a, b ); +} + +//From http://stackoverflow.com/questions/40159892/using-asprintf-on-windows +int __cdecl vsprintf_s( + char *buffer, + size_t numberOfElements, + const char *format, + va_list argptr +); + +int asprintf(char **strp, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int r = vasprintf(strp, fmt, ap); + va_end(ap); + return r; +} + +int vasprintf(char **strp, const char *fmt, va_list ap) { + // _vscprintf tells you how big the buffer needs to be + int len = _vscprintf(fmt, ap); + if (len == -1) { + return -1; + } + size_t size = (size_t)len + 1; + char *str = (char*)malloc(size); + if (!str) { + return -1; + } + // _vsprintf_s is the "secure" version of vsprintf + int r = vsprintf_s(str, len + 1, fmt, ap); + if (r == -1) { + free(str); + return -1; + } + *strp = str; + return r; +} \ No newline at end of file diff --git a/windows/build_tcc.bat b/windows/build_tcc.bat deleted file mode 100644 index 753ba7c..0000000 --- a/windows/build_tcc.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off - -set TCC=C:\tcc\tcc.exe -echo Be sure to have TinyCC installed to %TCC% (or change the TCC parameter.) - -set SR=..\src\ -set RD=..\redist\ -set SOURCES=%SR%ootx_decoder.c %SR%poser_charlesslow.c %SR%poser_daveortho.c %SR%poser_dummy.c %SR%survive.c %SR%survive_cal.c %SR%survive_config.c %SR%survive_data.c %SR%survive_driverman.c %SR%survive_process.c %SR%survive_vive.c -set REDIST=%RD%crc32.c %RD%linmath.c %RD%puff.c %RD%jsmn.c %RD%json_helpers.c %RD%symbol_enumerator.c -set EXEC=..\calibrate.c %RD%WinDriver.c %RD%os_generic.c %RD%DrawFunctions.c -set CFLAGS=-DNOZLIB -DTCC -DWINDOWS -DHIDAPI -DWIN32 -DRUNTIME_SYMNUM -O0 -g -rdynamic -I..\redist -I..\include\libsurvive -I..\src -I. -set LDFLAGS=-lkernel32 -lgdi32 -luser32 -lsetupapi -ldbghelp -@echo on -%TCC% -v %CFLAGS% %SOURCES% %REDIST% %EXEC% %LDFLAGS% tcc_stubs.c hid.c -o calibrate.exe diff --git a/windows/custom_msvcrt.def b/windows/custom_msvcrt.def deleted file mode 100644 index f40884e..0000000 --- a/windows/custom_msvcrt.def +++ /dev/null @@ -1,1400 +0,0 @@ -LIBRARY msvcrt.dll - -EXPORTS -$I10_OUTPUT -??0__non_rtti_object@@QAE@ABV0@@Z -??0__non_rtti_object@@QAE@PBD@Z -??0bad_cast@@AAE@PBQBD@Z -??0bad_cast@@QAE@ABQBD@Z -??0bad_cast@@QAE@ABV0@@Z -??0bad_cast@@QAE@PBD@Z -??0bad_typeid@@QAE@ABV0@@Z -??0bad_typeid@@QAE@PBD@Z -??0exception@@QAE@ABQBD@Z -??0exception@@QAE@ABQBDH@Z -??0exception@@QAE@ABV0@@Z -??0exception@@QAE@XZ -??1__non_rtti_object@@UAE@XZ -??1bad_cast@@UAE@XZ -??1bad_typeid@@UAE@XZ -??1exception@@UAE@XZ -??1type_info@@UAE@XZ -??2@YAPAXI@Z -??2@YAPAXIHPBDH@Z -??3@YAXPAX@Z -??4__non_rtti_object@@QAEAAV0@ABV0@@Z -??4bad_cast@@QAEAAV0@ABV0@@Z -??4bad_typeid@@QAEAAV0@ABV0@@Z -??4exception@@QAEAAV0@ABV0@@Z -??8type_info@@QBEHABV0@@Z -??9type_info@@QBEHABV0@@Z -??_7__non_rtti_object@@6B@ -??_7bad_cast@@6B@ -??_7bad_typeid@@6B@ -??_7exception@@6B@ -??_E__non_rtti_object@@UAEPAXI@Z -??_Ebad_cast@@UAEPAXI@Z -??_Ebad_typeid@@UAEPAXI@Z -??_Eexception@@UAEPAXI@Z -??_Fbad_cast@@QAEXXZ -??_Fbad_typeid@@QAEXXZ -??_G__non_rtti_object@@UAEPAXI@Z -??_Gbad_cast@@UAEPAXI@Z -??_Gbad_typeid@@UAEPAXI@Z -??_Gexception@@UAEPAXI@Z -??_U@YAPAXI@Z -??_U@YAPAXIHPBDH@Z -??_V@YAXPAX@Z -?_query_new_handler@@YAP6AHI@ZXZ -?_query_new_mode@@YAHXZ -?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z -?_set_new_mode@@YAHH@Z -?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z -?before@type_info@@QBEHABV1@@Z -?name@type_info@@QBEPBDXZ -?raw_name@type_info@@QBEPBDXZ -?set_new_handler@@YAP6AXXZP6AXXZ@Z -?set_terminate@@YAP6AXXZP6AXXZ@Z -?set_unexpected@@YAP6AXXZP6AXXZ@Z -?terminate@@YAXXZ -?unexpected@@YAXXZ -?what@exception@@UBEPBDXZ -_CIacos -_CIasin -_CIatan -_CIatan2 -_CIcos -_CIcosh -_CIexp -_CIfmod -_CIlog -_CIlog10 -_CIpow -_CIsin -_CIsinh -_CIsqrt -_CItan -_CItanh -_CrtCheckMemory -_CrtDbgBreak -_CrtDbgReport -_CrtDbgReportV -_CrtDbgReportW -_CrtDbgReportWV -_CrtDoForAllClientObjects -_CrtDumpMemoryLeaks -_CrtIsMemoryBlock -_CrtIsValidHeapPointer -_CrtIsValidPointer -_CrtMemCheckpoint -_CrtMemDifference -_CrtMemDumpAllObjectsSince -_CrtMemDumpStatistics -_CrtReportBlockType -_CrtSetAllocHook -_CrtSetBreakAlloc -_CrtSetDbgBlockType -_CrtSetDbgFlag -_CrtSetDumpClient -_CrtSetReportFile -_CrtSetReportHook -_CrtSetReportHook2 -_CrtSetReportMode -_CxxThrowException -_EH_prolog -_Getdays -_Getmonths -_Gettnames -_HUGE -_Strftime -_XcptFilter -__CppXcptFilter -__CxxCallUnwindDelDtor -__CxxCallUnwindDtor -__CxxCallUnwindVecDtor -__CxxDetectRethrow -__CxxExceptionFilter -__CxxFrameHandler -__CxxFrameHandler2 -__CxxFrameHandler3 -__CxxLongjmpUnwind -__CxxQueryExceptionSize -__CxxRegisterExceptionObject -__CxxUnregisterExceptionObject -__DestructExceptionObject -__RTCastToVoid -__RTDynamicCast -__RTtypeid -__STRINGTOLD -___lc_codepage_func -___lc_collate_cp_func -___lc_handle_func -___mb_cur_max_func -___setlc_active_func -___unguarded_readlc_active_add_func -__argc -__argv -__badioinfo -__crtCompareStringA -__crtCompareStringW -__crtGetLocaleInfoW -__crtGetStringTypeW -__crtLCMapStringA -__crtLCMapStringW -__daylight -__dllonexit -__doserrno -__dstbias -__fpecode -__getmainargs -__initenv -__iob_func -__isascii -__iscsym -__iscsymf -__lc_codepage -__lc_collate_cp -__lc_handle -__lconv_init -__libm_sse2_acos -__libm_sse2_acosf -__libm_sse2_asin -__libm_sse2_asinf -__libm_sse2_atan -__libm_sse2_atan2 -__libm_sse2_atanf -__libm_sse2_cos -__libm_sse2_cosf -__libm_sse2_exp -__libm_sse2_expf -__libm_sse2_log -__libm_sse2_log10 -__libm_sse2_log10f -__libm_sse2_logf -__libm_sse2_pow -__libm_sse2_powf -__libm_sse2_sin -__libm_sse2_sinf -__libm_sse2_tan -__libm_sse2_tanf -__mb_cur_max -__p___argc -__p___argv -__p___initenv -__p___mb_cur_max -__p___wargv -__p___winitenv -__p__acmdln -__p__amblksiz -__p__commode -__p__daylight -__p__dstbias -__p__environ -__p__fileinfo -__p__fmode -__p__iob -__p__mbcasemap -__p__mbctype -__p__osver -__p__pctype -__p__pgmptr -__p__pwctype -__p__timezone -__p__tzname -__p__wcmdln -__p__wenviron -__p__winmajor -__p__winminor -__p__winver -__p__wpgmptr -__pctype_func -__pioinfo -__pwctype_func -__pxcptinfoptrs -__set_app_type -__setlc_active -__setusermatherr -__strncnt -__threadhandle -__threadid -__toascii -__unDName -__unDNameEx -__uncaught_exception -__unguarded_readlc_active -__wargv -__wcserror -__wcserror_s -__wcsncnt -__wgetmainargs -__winitenv -_abnormal_termination -_abs64 -_access -_access_s -_acmdln -_adj_fdiv_m16i -_adj_fdiv_m32 -_adj_fdiv_m32i -_adj_fdiv_m64 -_adj_fdiv_r -_adj_fdivr_m16i -_adj_fdivr_m32 -_adj_fdivr_m32i -_adj_fdivr_m64 -_adj_fpatan -_adj_fprem -_adj_fprem1 -_adj_fptan -_adjust_fdiv -_aexit_rtn -_aligned_free -_aligned_free_dbg -_aligned_malloc -_aligned_malloc_dbg -_aligned_offset_malloc -_aligned_offset_malloc_dbg -_aligned_offset_realloc -_aligned_offset_realloc_dbg -_aligned_realloc -_aligned_realloc_dbg -_amsg_exit -_assert -_atodbl -_atodbl_l -_atof_l -_atoflt_l -_atoi64 -_atoi64_l -_atoi_l -_atol_l -_atoldbl -_atoldbl_l -_beep -_beginthread -_beginthreadex -_c_exit -_cabs -_callnewh -_calloc_dbg -_cexit -_cgets -_cgets_s -_cgetws -_cgetws_s -_chdir -_chdrive -_chgsign -_chkesp -_chmod -_chsize -_chsize_s -_chvalidator -_chvalidator_l -_clearfp -_close -_commit -_commode -_control87 -_controlfp -_controlfp_s -_copysign -_cprintf -_cprintf_l -_cprintf_p -_cprintf_p_l -_cprintf_s -_cprintf_s_l -_cputs -_cputws -_creat -_crtAssertBusy -_crtBreakAlloc -_crtDbgFlag -_cscanf -_cscanf_l -_cscanf_s -_cscanf_s_l -_ctime32 -_ctime32_s -_ctime64 -_ctime64_s -_ctype -_cwait -_cwprintf -_cwprintf_l -_cwprintf_p -_cwprintf_p_l -_cwprintf_s -_cwprintf_s_l -_cwscanf -_cwscanf_l -_cwscanf_s -_cwscanf_s_l -_daylight -_difftime32 -_difftime64 -_dstbias -_dup -_dup2 -_ecvt -_ecvt_s -_endthread -_endthreadex -_environ -_eof -_errno -_except_handler2 -_except_handler3 -_except_handler4_common -_execl -_execle -_execlp -_execlpe -_execv -_execve -_execvp -_execvpe -_exit -_expand -_expand_dbg -_fcloseall -_fcvt -_fcvt_s -_fdopen -_fgetchar -_fgetwchar -_filbuf -_fileinfo -_filelength -_filelengthi64 -_fileno -_findclose -_findfirst -_findfirst64 -_findfirsti64 -_findnext -_findnext64 -_findnexti64 -_finite -_flsbuf -_flushall -_fmode -_fpclass -_fpieee_flt -_fpreset -_fprintf_l -_fprintf_p -_fprintf_p_l -_fprintf_s_l -_fputchar -_fputwchar -_free_dbg -_freea -_freea_s -_fscanf_l -_fscanf_s_l -_fseeki64 -_fsopen -_fstat -_fstat64 -_fstati64 -_ftime -_ftime32 -_ftime32_s -_ftime64 -_ftime64_s -_ftol -_ftol2 -_ftol2_sse -_ftol2_sse_excpt -_fullpath -_fullpath_dbg -_futime -_futime32 -_futime64 -_fwprintf_l -_fwprintf_p -_fwprintf_p_l -_fwprintf_s_l -_fwscanf_l -_fwscanf_s_l -_gcvt -_gcvt_s -_get_doserrno -_get_environ -_get_errno -_get_fileinfo -_get_fmode -_get_heap_handle -_get_osfhandle -_get_osplatform -_get_osver -_get_output_format -_get_pgmptr -_get_sbh_threshold -_get_wenviron -_get_winmajor -_get_winminor -_get_winver -_get_wpgmptr -_getch -_getche -_getcwd -_getdcwd -_getdiskfree -_getdllprocaddr -_getdrive -_getdrives -_getmaxstdio -_getmbcp -_getpid -_getsystime -_getw -_getwch -_getwche -_getws -_global_unwind2 -_gmtime32 -_gmtime32_s -_gmtime64 -_gmtime64_s -_heapadd -_heapchk -_heapmin -_heapset -_heapused -_heapwalk -_hypot -_i64toa -_i64toa_s -_i64tow -_i64tow_s -_initterm -_initterm_e -_inp -_inpd -_inpw -_invalid_parameter -_iob -_isalnum_l -_isalpha_l -_isatty -_iscntrl_l -_isctype -_isctype_l -_isdigit_l -_isgraph_l -_isleadbyte_l -_islower_l -_ismbbalnum -_ismbbalnum_l -_ismbbalpha -_ismbbalpha_l -_ismbbgraph -_ismbbgraph_l -_ismbbkalnum -_ismbbkalnum_l -_ismbbkana -_ismbbkana_l -_ismbbkprint -_ismbbkprint_l -_ismbbkpunct -_ismbbkpunct_l -_ismbblead -_ismbblead_l -_ismbbprint -_ismbbprint_l -_ismbbpunct -_ismbbpunct_l -_ismbbtrail -_ismbbtrail_l -_ismbcalnum -_ismbcalnum_l -_ismbcalpha -_ismbcalpha_l -_ismbcdigit -_ismbcdigit_l -_ismbcgraph -_ismbcgraph_l -_ismbchira -_ismbchira_l -_ismbckata -_ismbckata_l -_ismbcl0 -_ismbcl0_l -_ismbcl1 -_ismbcl1_l -_ismbcl2 -_ismbcl2_l -_ismbclegal -_ismbclegal_l -_ismbclower -_ismbclower_l -_ismbcprint -_ismbcprint_l -_ismbcpunct -_ismbcpunct_l -_ismbcspace -_ismbcspace_l -_ismbcsymbol -_ismbcsymbol_l -_ismbcupper -_ismbcupper_l -_ismbslead -_ismbslead_l -_ismbstrail -_ismbstrail_l -_isnan -_isprint_l -_isspace_l -_isupper_l -_iswalnum_l -_iswalpha_l -_iswcntrl_l -_iswctype_l -_iswdigit_l -_iswgraph_l -_iswlower_l -_iswprint_l -_iswpunct_l -_iswspace_l -_iswupper_l -_iswxdigit_l -_isxdigit_l -_itoa -_itoa_s -_itow -_itow_s -_j0 -_j1 -_jn -_kbhit -_lfind -_lfind_s -_loaddll -_local_unwind2 -_local_unwind4 -_localtime32 -_localtime32_s -_localtime64 -_localtime64_s -_lock -_locking -_logb -_longjmpex -_lrotl -_lrotr -_lsearch -_lsearch_s -_lseek -_lseeki64 -_ltoa -_ltoa_s -_ltow -_ltow_s -_makepath -_makepath_s -_malloc_dbg -_mbbtombc -_mbbtombc_l -_mbbtype -_mbcasemap -_mbccpy -_mbccpy_l -_mbccpy_s -_mbccpy_s_l -_mbcjistojms -_mbcjistojms_l -_mbcjmstojis -_mbcjmstojis_l -_mbclen -_mbclen_l -_mbctohira -_mbctohira_l -_mbctokata -_mbctokata_l -_mbctolower -_mbctolower_l -_mbctombb -_mbctombb_l -_mbctoupper -_mbctoupper_l -_mbctype -_mblen_l -_mbsbtype -_mbsbtype_l -_mbscat -_mbscat_s -_mbscat_s_l -_mbschr -_mbschr_l -_mbscmp -_mbscmp_l -_mbscoll -_mbscoll_l -_mbscpy -_mbscpy_s -_mbscpy_s_l -_mbscspn -_mbscspn_l -_mbsdec -_mbsdec_l -_mbsdup -_mbsicmp -_mbsicmp_l -_mbsicoll -_mbsicoll_l -_mbsinc -_mbsinc_l -_mbslen -_mbslen_l -_mbslwr -_mbslwr_l -_mbslwr_s -_mbslwr_s_l -_mbsnbcat -_mbsnbcat_l -_mbsnbcat_s -_mbsnbcat_s_l -_mbsnbcmp -_mbsnbcmp_l -_mbsnbcnt -_mbsnbcnt_l -_mbsnbcoll -_mbsnbcoll_l -_mbsnbcpy -_mbsnbcpy_l -_mbsnbcpy_s -_mbsnbcpy_s_l -_mbsnbicmp -_mbsnbicmp_l -_mbsnbicoll -_mbsnbicoll_l -_mbsnbset -_mbsnbset_l -_mbsnbset_s -_mbsnbset_s_l -_mbsncat -_mbsncat_l -_mbsncat_s -_mbsncat_s_l -_mbsnccnt -_mbsnccnt_l -_mbsncmp -_mbsncmp_l -_mbsncoll -_mbsncoll_l -_mbsncpy -_mbsncpy_l -_mbsncpy_s -_mbsncpy_s_l -_mbsnextc -_mbsnextc_l -_mbsnicmp -_mbsnicmp_l -_mbsnicoll -_mbsnicoll_l -_mbsninc -_mbsninc_l -_mbsnlen -_mbsnlen_l -_mbsnset -_mbsnset_l -_mbsnset_s -_mbsnset_s_l -_mbspbrk -_mbspbrk_l -_mbsrchr -_mbsrchr_l -_mbsrev -_mbsrev_l -_mbsset -_mbsset_l -_mbsset_s -_mbsset_s_l -_mbsspn -_mbsspn_l -_mbsspnp -_mbsspnp_l -_mbsstr -_mbsstr_l -_mbstok -_mbstok_l -_mbstok_s -_mbstok_s_l -_mbstowcs_l -_mbstowcs_s_l -_mbstrlen -_mbstrlen_l -_mbstrnlen -_mbstrnlen_l -_mbsupr -_mbsupr_l -_mbsupr_s -_mbsupr_s_l -_mbtowc_l -_memccpy -_memicmp -_memicmp_l -_mkdir -_mkgmtime -_mkgmtime32 -_mkgmtime64 -_mktemp -_mktemp_s -_mktime32 -_mktime64 -_msize -_msize_debug -_nextafter -_onexit -_open -_open_osfhandle -_osplatform -_osver -_outp -_outpd -_outpw -_pclose -_pctype -_pgmptr -_pipe -_popen -_printf_l -_printf_p -_printf_p_l -_printf_s_l -_purecall -_putch -_putenv -_putenv_s -_putw -_putwch -_putws -_pwctype -_read -_realloc_dbg -_resetstkoflw -_rmdir -_rmtmp -_rotl -_rotl64 -_rotr -_rotr64 -_safe_fdiv -_safe_fdivr -_safe_fprem -_safe_fprem1 -_scalb -_scanf_l -_scanf_s_l -_scprintf -_scprintf_l -_scprintf_p_l -_scwprintf -_scwprintf_l -_scwprintf_p_l -_searchenv -_searchenv_s -_seh_longjmp_unwind -_seh_longjmp_unwind4 -_set_SSE2_enable -_set_controlfp -_set_doserrno -_set_errno -_set_error_mode -_set_fileinfo -_set_fmode -_set_output_format -_set_sbh_threshold -_seterrormode -_setjmp -_setjmp3 -_setmaxstdio -_setmbcp -_setmode -_setsystime -_sleep -_snprintf -_snprintf_c -_snprintf_c_l -_snprintf_l -_snprintf_s -_snprintf_s_l -_snscanf -_snscanf_l -_snscanf_s -_snscanf_s_l -_snwprintf -_snwprintf_l -_snwprintf_s -_snwprintf_s_l -_snwscanf -_snwscanf_l -_snwscanf_s -_snwscanf_s_l -_sopen -_sopen_s -_spawnl -_spawnle -_spawnlp -_spawnlpe -_spawnv -_spawnve -_spawnvp -_spawnvpe -_splitpath -_splitpath_s -_sprintf_l -_sprintf_p_l -_sprintf_s_l -_sscanf_l -_sscanf_s_l -_stat -_stat64 -_stati64 -_statusfp -_strcmpi -_strcoll_l -_strdate -_strdate_s -_strdup -_strdup_dbg -_strerror -_strerror_s -_stricmp -_stricmp_l -_stricoll -_stricoll_l -_strlwr -_strlwr_l -_strlwr_s -_strlwr_s_l -_strncoll -_strncoll_l -_strnicmp -_strnicmp_l -_strnicoll -_strnicoll_l -_strnset -_strnset_s -_strrev -_strset -_strset_s -_strtime -_strtime_s -_strtod_l -_strtoi64 -_strtoi64_l -_strtol_l -_strtoui64 -_strtoui64_l -_strtoul_l -_strupr -_strupr_l -_strupr_s -_strupr_s_l -_strxfrm_l -_swab -_swprintf -_swprintf_c -_swprintf_c_l -_swprintf_p_l -_swprintf_s_l -_swscanf_l -_swscanf_s_l -_sys_errlist -_sys_nerr -_tell -_telli64 -_tempnam -_tempnam_dbg -_time32 -_time64 -_timezone -_tolower -_tolower_l -_toupper -_toupper_l -_towlower_l -_towupper_l -_tzname -_tzset -_ui64toa -_ui64toa_s -_ui64tow -_ui64tow_s -_ultoa -_ultoa_s -_ultow -_ultow_s -_umask -_umask_s -_ungetch -_ungetwch -_unlink -_unloaddll -_unlock -_utime -_utime32 -_utime64 -_vcprintf -_vcprintf_l -_vcprintf_p -_vcprintf_p_l -_vcprintf_s -_vcprintf_s_l -_vcwprintf -_vcwprintf_l -_vcwprintf_p -_vcwprintf_p_l -_vcwprintf_s -_vcwprintf_s_l -_vfprintf_l -_vfprintf_p -_vfprintf_p_l -_vfprintf_s_l -_vfwprintf_l -_vfwprintf_p -_vfwprintf_p_l -_vfwprintf_s_l -_vprintf_l -_vprintf_p -_vprintf_p_l -_vprintf_s_l -_vscprintf -_vscprintf_l -_vscprintf_p_l -_vscwprintf -_vscwprintf_l -_vscwprintf_p_l -_vsnprintf -_vsnprintf_c -_vsnprintf_c_l -_vsnprintf_l -_vsnprintf_s -_vsnprintf_s_l -_vsnwprintf -_vsnwprintf_l -_vsnwprintf_s -_vsnwprintf_s_l -_vsprintf_l -_vsprintf_p -_vsprintf_p_l -_vsprintf_s_l -_vswprintf -_vswprintf_c -_vswprintf_c_l -_vswprintf_l -_vswprintf_p_l -_vswprintf_s_l -_vwprintf_l -_vwprintf_p -_vwprintf_p_l -_vwprintf_s_l -_waccess -_waccess_s -_wasctime -_wasctime_s -_wassert -_wchdir -_wchmod -_wcmdln -_wcreat -_wcscoll_l -_wcsdup -_wcsdup_dbg -_wcserror -_wcserror_s -_wcsftime_l -_wcsicmp -_wcsicmp_l -_wcsicoll -_wcsicoll_l -_wcslwr -_wcslwr_l -_wcslwr_s -_wcslwr_s_l -_wcsncoll -_wcsncoll_l -_wcsnicmp -_wcsnicmp_l -_wcsnicoll -_wcsnicoll_l -_wcsnset -_wcsnset_s -_wcsrev -_wcsset -_wcsset_s -_wcstoi64 -_wcstoi64_l -_wcstol_l -_wcstombs_l -_wcstombs_s_l -_wcstoui64 -_wcstoui64_l -_wcstoul_l -_wcsupr -_wcsupr_l -_wcsupr_s -_wcsupr_s_l -_wcsxfrm_l -_wctime -_wctime32 -_wctime32_s -_wctime64 -_wctime64_s -_wctomb_l -_wctomb_s_l -_wctype -_wenviron -_wexecl -_wexecle -_wexeclp -_wexeclpe -_wexecv -_wexecve -_wexecvp -_wexecvpe -_wfdopen -_wfindfirst -_wfindfirst64 -_wfindfirsti64 -_wfindnext -_wfindnext64 -_wfindnexti64 -_wfopen -_wfopen_s -_wfreopen -_wfreopen_s -_wfsopen -_wfullpath -_wfullpath_dbg -_wgetcwd -_wgetdcwd -_wgetenv -_wgetenv_s -_winmajor -_winminor -_winput_s -_winver -_wmakepath -_wmakepath_s -_wmkdir -_wmktemp -_wmktemp_s -_wopen -_woutput_s -_wperror -_wpgmptr -_wpopen -_wprintf_l -_wprintf_p -_wprintf_p_l -_wprintf_s_l -_wputenv -_wputenv_s -_wremove -_wrename -_write -_wrmdir -_wscanf_l -_wscanf_s_l -_wsearchenv -_wsearchenv_s -_wsetlocale -_wsopen -_wsopen_s -_wspawnl -_wspawnle -_wspawnlp -_wspawnlpe -_wspawnv -_wspawnve -_wspawnvp -_wspawnvpe -_wsplitpath -_wsplitpath_s -_wstat -_wstat64 -_wstati64 -_wstrdate -_wstrdate_s -_wstrtime -_wstrtime_s -_wsystem -_wtempnam -_wtempnam_dbg -_wtmpnam -_wtmpnam_s -_wtof -_wtof_l -_wtoi -_wtoi64 -_wtoi64_l -_wtoi_l -_wtol -_wtol_l -_wunlink -_wutime -_wutime32 -_wutime64 -_y0 -_y1 -_yn -abort -abs -acos -asctime -asctime_s -asin -atan -atan2 -atexit -atof -atoi -atol -bsearch -bsearch_s -btowc -calloc -ceil -clearerr -clearerr_s -clock -cos -cosh -ctime -difftime -div -exit -exp -fabs -fclose -feof -ferror -fflush -fgetc -fgetpos -fgets -fgetwc -fgetws -floor -fmod -fopen -fopen_s -fprintf -fprintf_s -fputc -fputs -fputwc -fputws -fread -free -freopen -freopen_s -frexp -fscanf -fscanf_s -fseek -fsetpos -ftell -fwprintf -fwprintf_s -fwrite -fwscanf -fwscanf_s -getc -getchar -getenv -getenv_s -gets -getwc -getwchar -gmtime -is_wctype -isalnum -isalpha -iscntrl -isdigit -isgraph -isleadbyte -islower -isprint -ispunct -isspace -isupper -iswalnum -iswalpha -iswascii -iswcntrl -iswctype -iswdigit -iswgraph -iswlower -iswprint -iswpunct -iswspace -iswupper -iswxdigit -isxdigit -labs -ldexp -ldiv -localeconv -localtime -log -log10 -longjmp -malloc -mblen -mbrlen -mbrtowc -mbsdup_dbg -mbsrtowcs -mbsrtowcs_s -mbstowcs -mbstowcs_s -mbtowc -memchr -memcmp -memcpy -memcpy_s -memmove -memmove_s -memset -mktime -modf -perror -pow -printf -printf_s -putc -putchar -puts -putwc -putwchar -qsort -qsort_s -raise -rand -rand_s -realloc -remove -rename -rewind -scanf -scanf_s -setbuf -setlocale -setvbuf -signal -sin -sinh -sprintf -sprintf_s -sqrt -srand -sscanf -sscanf_s -strcat -strcat_s -strchr -strcmp -strcoll -strcpy -strcpy_s -strcspn -strerror -strerror_s -strftime -strlen -strncat -strncat_s -strncmp -strncpy -strncpy_s -strnlen -strpbrk -strrchr -strspn -strstr -strtod -strtok -strtok_s -strtol -strtoul -strxfrm -swprintf -swprintf_s -swscanf -swscanf_s -system -tan -tanh -time -tmpfile -tmpfile_s -tmpnam -tmpnam_s -tolower -toupper -towlower -towupper -ungetc -ungetwc -utime -vfprintf -vfprintf_s -vfwprintf -vfwprintf_s -vprintf -vprintf_s -vsnprintf -vsprintf -vsprintf_s -vswprintf -vswprintf_s -vwprintf -vwprintf_s -wcrtomb -wcrtomb_s -wcscat -wcscat_s -wcschr -wcscmp -wcscoll -wcscpy -wcscpy_s -wcscspn -wcsftime -wcslen -wcsncat -wcsncat_s -wcsncmp -wcsncpy -wcsncpy_s -wcsnlen -wcspbrk -wcsrchr -wcsrtombs -wcsrtombs_s -wcsspn -wcsstr -wcstod -wcstok -wcstok_s -wcstol -wcstombs -wcstombs_s -wcstoul -wcsxfrm -wctob -wctomb -wctomb_s -wprintf -wprintf_s -wscanf -wscanf_s -vsprintf_s \ No newline at end of file diff --git a/windows/hid.c b/windows/hid.c deleted file mode 100644 index 6c379b5..0000000 --- a/windows/hid.c +++ /dev/null @@ -1,996 +0,0 @@ -/******************************************************* - HIDAPI - Multi-Platform library for - communication with HID devices. - - Alan Ott - Signal 11 Software - - 8/22/2009 - - Copyright 2009, All Rights Reserved. - - At the discretion of the user of this library, - this software may be licensed under the terms of the - GNU General Public License v3, a BSD-Style license, or the - original HIDAPI license as outlined in the LICENSE.txt, - LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt - files located at the root of the source distribution. - These files may also be found in the public source - code repository located at: - http://github.com/signal11/hidapi . -********************************************************/ - - -/* Copy of LICENSE-orig.txt (compatible with MIT/x11 license) - - HIDAPI - Multi-Platform library for - communication with HID devices. - - Copyright 2009, Alan Ott, Signal 11 Software. - All Rights Reserved. - - This software may be used by anyone for any reason so - long as the copyright notice in the source files - remains intact. -*/ - -#include - -#ifndef _NTDEF_ -typedef LONG NTSTATUS; -#endif - -#ifdef __MINGW32__ -#include -#include -#endif - -#ifdef __CYGWIN__ -#include -#define _wcsdup wcsdup -#endif - -/* The maximum number of characters that can be passed into the - HidD_Get*String() functions without it failing.*/ -#define MAX_STRING_WCHARS 0xFFF - -/*#define HIDAPI_USE_DDK*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef TCC - typedef struct _SP_DEVINFO_DATA { - DWORD cbSize; - GUID ClassGuid; - DWORD DevInst; - ULONG_PTR Reserved; - } SP_DEVINFO_DATA, *PSP_DEVINFO_DATA; - typedef struct _SP_DEVICE_INTERFACE_DATA { - DWORD cbSize; - GUID InterfaceClassGuid; - DWORD Flags; - ULONG_PTR Reserved; - } SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA; - typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA { - DWORD cbSize; - CHAR DevicePath[ANYSIZE_ARRAY]; - } SP_DEVICE_INTERFACE_DETAIL_DATA_A, *PSP_DEVICE_INTERFACE_DETAIL_DATA_A; - typedef PVOID HDEVINFO; - - HDEVINFO WINAPI SetupDiGetClassDevsA(CONST GUID*,PCSTR,HWND,DWORD); - - #define DIGCF_PRESENT 0x00000002 - #define DIGCF_DEVICEINTERFACE 0x00000010 - #define SPDRP_CLASS 7 - #define SPDRP_DRIVER 9 - #define FILE_DEVICE_KEYBOARD 0x0000000b - #define METHOD_OUT_DIRECT 2 - enum - { FILE_ANY_ACCESS = 0x00000000UL, - FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS, - FILE_READ_ACCESS = 0x00000001UL, - FILE_WRITE_ACCESS = 0x00000002UL - }; - #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m)) - -#else - #include - #include -#endif - #ifdef HIDAPI_USE_DDK - #include - #endif - - /* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */ - #define HID_OUT_CTL_CODE(id) \ - CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) - #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#include -#include - - -#include "hidapi.h" - -#undef MIN -#define MIN(x,y) ((x) < (y)? (x): (y)) - -#ifdef _MSC_VER - /* Thanks Microsoft, but I know how to use strncpy(). */ - #pragma warning(disable:4996) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef HIDAPI_USE_DDK - /* Since we're not building with the DDK, and the HID header - files aren't part of the SDK, we have to define all this - stuff here. In lookup_functions(), the function pointers - defined below are set. */ - typedef struct _HIDD_ATTRIBUTES{ - ULONG Size; - USHORT VendorID; - USHORT ProductID; - USHORT VersionNumber; - } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; - - typedef USHORT USAGE; - typedef struct _HIDP_CAPS { - USAGE Usage; - USAGE UsagePage; - USHORT InputReportByteLength; - USHORT OutputReportByteLength; - USHORT FeatureReportByteLength; - USHORT Reserved[17]; - USHORT fields_not_used_by_hidapi[10]; - } HIDP_CAPS, *PHIDP_CAPS; - typedef void* PHIDP_PREPARSED_DATA; - #define HIDP_STATUS_SUCCESS 0x110000 - - typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib); - typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); - typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); - typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); - typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data); - typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps); - typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers); - - static HidD_GetAttributes_ HidD_GetAttributes; - static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; - static HidD_GetManufacturerString_ HidD_GetManufacturerString; - static HidD_GetProductString_ HidD_GetProductString; - static HidD_SetFeature_ HidD_SetFeature; - static HidD_GetFeature_ HidD_GetFeature; - static HidD_GetIndexedString_ HidD_GetIndexedString; - static HidD_GetPreparsedData_ HidD_GetPreparsedData; - static HidD_FreePreparsedData_ HidD_FreePreparsedData; - static HidP_GetCaps_ HidP_GetCaps; - static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers; - - static HMODULE lib_handle = NULL; - static BOOLEAN initialized = FALSE; -#endif /* HIDAPI_USE_DDK */ - -struct hid_device_ { - HANDLE device_handle; - BOOL blocking; - USHORT output_report_length; - size_t input_report_length; - void *last_error_str; - DWORD last_error_num; - BOOL read_pending; - char *read_buf; - OVERLAPPED ol; -}; - -static hid_device *new_hid_device() -{ - hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); - dev->device_handle = INVALID_HANDLE_VALUE; - dev->blocking = TRUE; - dev->output_report_length = 0; - dev->input_report_length = 0; - dev->last_error_str = NULL; - dev->last_error_num = 0; - dev->read_pending = FALSE; - dev->read_buf = NULL; - memset(&dev->ol, 0, sizeof(dev->ol)); - dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL); - - return dev; -} - -static void free_hid_device(hid_device *dev) -{ - CloseHandle(dev->ol.hEvent); - CloseHandle(dev->device_handle); - LocalFree(dev->last_error_str); - free(dev->read_buf); - free(dev); -} - -static void register_error(hid_device *device, const char *op) -{ - WCHAR *ptr, *msg; - - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPVOID)&msg, 0/*sz*/, - NULL); - - /* Get rid of the CR and LF that FormatMessage() sticks at the - end of the message. Thanks Microsoft! */ - ptr = msg; - while (*ptr) { - if (*ptr == '\r') { - *ptr = 0x0000; - break; - } - ptr++; - } - - /* Store the message off in the Device entry so that - the hid_error() function can pick it up. */ - LocalFree(device->last_error_str); - device->last_error_str = msg; -} - -#ifndef HIDAPI_USE_DDK -static int lookup_functions() -{ - lib_handle = LoadLibraryA("hid.dll"); - if (lib_handle) { -#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1; - RESOLVE(HidD_GetAttributes); - RESOLVE(HidD_GetSerialNumberString); - RESOLVE(HidD_GetManufacturerString); - RESOLVE(HidD_GetProductString); - RESOLVE(HidD_SetFeature); - RESOLVE(HidD_GetFeature); - RESOLVE(HidD_GetIndexedString); - RESOLVE(HidD_GetPreparsedData); - RESOLVE(HidD_FreePreparsedData); - RESOLVE(HidP_GetCaps); - RESOLVE(HidD_SetNumInputBuffers); -#undef RESOLVE - } - else - return -1; - - return 0; -} -#endif - -static HANDLE open_device(const char *path, BOOL enumerate) -{ - HANDLE handle; - DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ); - DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; - - handle = CreateFileA(path, - desired_access, - share_mode, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/ - 0); - - return handle; -} - -int HID_API_EXPORT hid_init(void) -{ -#ifndef HIDAPI_USE_DDK - if (!initialized) { - if (lookup_functions() < 0) { - hid_exit(); - return -1; - } - initialized = TRUE; - } -#endif - return 0; -} - -int HID_API_EXPORT hid_exit(void) -{ -#ifndef HIDAPI_USE_DDK - if (lib_handle) - FreeLibrary(lib_handle); - lib_handle = NULL; - initialized = FALSE; -#endif - return 0; -} - -struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) -{ - BOOL res; - struct hid_device_info *root = NULL; /* return object */ - struct hid_device_info *cur_dev = NULL; - - /* Windows objects for interacting with the driver. */ - GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; - SP_DEVINFO_DATA devinfo_data; - SP_DEVICE_INTERFACE_DATA device_interface_data; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; - HDEVINFO device_info_set = INVALID_HANDLE_VALUE; - int device_index = 0; - int i; - - if (hid_init() < 0) - return NULL; - - /* Initialize the Windows objects. */ - memset(&devinfo_data, 0x0, sizeof(devinfo_data)); - devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); - device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - - /* Get information for all the devices belonging to the HID class. */ - device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - - /* Iterate over each device in the HID class, looking for the right one. */ - - for (;;) { - HANDLE write_handle = INVALID_HANDLE_VALUE; - DWORD required_size = 0; - HIDD_ATTRIBUTES attrib; - - res = SetupDiEnumDeviceInterfaces(device_info_set, - NULL, - &InterfaceClassGuid, - device_index, - &device_interface_data); - - if (!res) { - /* A return of FALSE from this function means that - there are no more devices. */ - break; - } - - /* Call with 0-sized detail size, and let the function - tell us how long the detail struct needs to be. The - size is put in &required_size. */ - res = SetupDiGetDeviceInterfaceDetailA(device_info_set, - &device_interface_data, - NULL, - 0, - &required_size, - NULL); - - /* Allocate a long enough structure for device_interface_detail_data. */ - device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); - device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - - /* Get the detailed data for this device. The detail data gives us - the device path for this device, which is then passed into - CreateFile() to get a handle to the device. */ - res = SetupDiGetDeviceInterfaceDetailA(device_info_set, - &device_interface_data, - device_interface_detail_data, - required_size, - NULL, - NULL); - - if (!res) { - /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); - Continue to the next device. */ - goto cont; - } - - /* Make sure this device is of Setup Class "HIDClass" and has a - driver bound to it. */ - for (i = 0; ; i++) { - char driver_name[256]; - - /* Populate devinfo_data. This function will return failure - when there are no more interfaces left. */ - res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); - if (!res) - goto cont; - - res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, - SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); - if (!res) - goto cont; - - if (strcmp(driver_name, "HIDClass") == 0) { - /* See if there's a driver bound. */ - res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, - SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); - if (res) - break; - } - } - - //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); - - /* Open a handle to the device */ - write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); - - /* Check validity of write_handle. */ - if (write_handle == INVALID_HANDLE_VALUE) { - /* Unable to open the device. */ - //register_error(dev, "CreateFile"); - goto cont_close; - } - - - /* Get the Vendor ID and Product ID for this device. */ - attrib.Size = sizeof(HIDD_ATTRIBUTES); - HidD_GetAttributes(write_handle, &attrib); - //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); - - /* Check the VID/PID to see if we should add this - device to the enumeration list. */ - if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && - (product_id == 0x0 || attrib.ProductID == product_id)) { - - #define WSTR_LEN 512 - const char *str; - struct hid_device_info *tmp; - PHIDP_PREPARSED_DATA pp_data = NULL; - HIDP_CAPS caps; - BOOLEAN res; - NTSTATUS nt_res; - wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ - size_t len; - - /* VID/PID match. Create the record. */ - tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); - if (cur_dev) { - cur_dev->next = tmp; - } - else { - root = tmp; - } - cur_dev = tmp; - - /* Get the Usage Page and Usage for this device. */ - res = HidD_GetPreparsedData(write_handle, &pp_data); - if (res) { - nt_res = HidP_GetCaps(pp_data, &caps); - if (nt_res == HIDP_STATUS_SUCCESS) { - cur_dev->usage_page = caps.UsagePage; - cur_dev->usage = caps.Usage; - } - - HidD_FreePreparsedData(pp_data); - } - - /* Fill out the record */ - cur_dev->next = NULL; - str = device_interface_detail_data->DevicePath; - if (str) { - len = strlen(str); - cur_dev->path = (char*) calloc(len+1, sizeof(char)); - strncpy(cur_dev->path, str, len+1); - cur_dev->path[len] = '\0'; - } - else - cur_dev->path = NULL; - - /* Serial Number */ - res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); - wstr[WSTR_LEN-1] = 0x0000; - if (res) { - cur_dev->serial_number = _wcsdup(wstr); - } - - /* Manufacturer String */ - res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); - wstr[WSTR_LEN-1] = 0x0000; - if (res) { - cur_dev->manufacturer_string = _wcsdup(wstr); - } - - /* Product String */ - res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); - wstr[WSTR_LEN-1] = 0x0000; - if (res) { - cur_dev->product_string = _wcsdup(wstr); - } - - /* VID/PID */ - cur_dev->vendor_id = attrib.VendorID; - cur_dev->product_id = attrib.ProductID; - - /* Release Number */ - cur_dev->release_number = attrib.VersionNumber; - - /* Interface Number. It can sometimes be parsed out of the path - on Windows if a device has multiple interfaces. See - http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or - search for "Hardware IDs for HID Devices" at MSDN. If it's not - in the path, it's set to -1. */ - cur_dev->interface_number = -1; - if (cur_dev->path) { - char *interface_component = strstr(cur_dev->path, "&mi_"); - if (interface_component) { - char *hex_str = interface_component + 4; - char *endptr = NULL; - cur_dev->interface_number = strtol(hex_str, &endptr, 16); - if (endptr == hex_str) { - /* The parsing failed. Set interface_number to -1. */ - cur_dev->interface_number = -1; - } - } - } - } - -cont_close: - CloseHandle(write_handle); -cont: - /* We no longer need the detail data. It can be freed */ - free(device_interface_detail_data); - - device_index++; - - } - - /* Close the device information handle. */ - SetupDiDestroyDeviceInfoList(device_info_set); - - return root; - -} - -void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) -{ - /* TODO: Merge this with the Linux version. This function is platform-independent. */ - struct hid_device_info *d = devs; - while (d) { - struct hid_device_info *next = d->next; - free(d->path); - free(d->serial_number); - free(d->manufacturer_string); - free(d->product_string); - free(d); - d = next; - } -} - - -HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) -{ - /* TODO: Merge this functions with the Linux version. This function should be platform independent. */ - struct hid_device_info *devs, *cur_dev; - const char *path_to_open = NULL; - hid_device *handle = NULL; - - devs = hid_enumerate(vendor_id, product_id); - cur_dev = devs; - while (cur_dev) { - if (cur_dev->vendor_id == vendor_id && - cur_dev->product_id == product_id) { - if (serial_number) { - if (wcscmp(serial_number, cur_dev->serial_number) == 0) { - path_to_open = cur_dev->path; - break; - } - } - else { - path_to_open = cur_dev->path; - break; - } - } - cur_dev = cur_dev->next; - } - - if (path_to_open) { - /* Open the device */ - handle = hid_open_path(path_to_open); - } - - hid_free_enumeration(devs); - - return handle; -} - -HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) -{ - hid_device *dev; - HIDP_CAPS caps; - PHIDP_PREPARSED_DATA pp_data = NULL; - BOOLEAN res; - NTSTATUS nt_res; - - if (hid_init() < 0) { - return NULL; - } - - dev = new_hid_device(); - - /* Open a handle to the device */ - dev->device_handle = open_device(path, FALSE); - - /* Check validity of write_handle. */ - if (dev->device_handle == INVALID_HANDLE_VALUE) { - /* Unable to open the device. */ - register_error(dev, "CreateFile"); - goto err; - } - - /* Set the Input Report buffer size to 64 reports. */ - res = HidD_SetNumInputBuffers(dev->device_handle, 64); - if (!res) { - register_error(dev, "HidD_SetNumInputBuffers"); - goto err; - } - - /* Get the Input Report length for the device. */ - res = HidD_GetPreparsedData(dev->device_handle, &pp_data); - if (!res) { - register_error(dev, "HidD_GetPreparsedData"); - goto err; - } - nt_res = HidP_GetCaps(pp_data, &caps); - if (nt_res != HIDP_STATUS_SUCCESS) { - register_error(dev, "HidP_GetCaps"); - goto err_pp_data; - } - dev->output_report_length = caps.OutputReportByteLength; - dev->input_report_length = caps.InputReportByteLength; - HidD_FreePreparsedData(pp_data); - - dev->read_buf = (char*) malloc(dev->input_report_length); - - return dev; - -err_pp_data: - HidD_FreePreparsedData(pp_data); -err: - free_hid_device(dev); - return NULL; -} - -int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length) -{ - DWORD bytes_written; - BOOL res; - - OVERLAPPED ol; - unsigned char *buf; - memset(&ol, 0, sizeof(ol)); - - /* Make sure the right number of bytes are passed to WriteFile. Windows - expects the number of bytes which are in the _longest_ report (plus - one for the report number) bytes even if the data is a report - which is shorter than that. Windows gives us this value in - caps.OutputReportByteLength. If a user passes in fewer bytes than this, - create a temporary buffer which is the proper size. */ - if (length >= dev->output_report_length) { - /* The user passed the right number of bytes. Use the buffer as-is. */ - buf = (unsigned char *) data; - } else { - /* Create a temporary buffer and copy the user's data - into it, padding the rest with zeros. */ - buf = (unsigned char *) malloc(dev->output_report_length); - memcpy(buf, data, length); - memset(buf + length, 0, dev->output_report_length - length); - length = dev->output_report_length; - } - - res = WriteFile(dev->device_handle, buf, (DWORD)length, NULL, &ol); - - if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { - /* WriteFile() failed. Return error. */ - register_error(dev, "WriteFile"); - bytes_written = -1; - goto end_of_function; - } - } - - /* Wait here until the write is done. This makes - hid_write() synchronous. */ - res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/); - if (!res) { - /* The Write operation failed. */ - register_error(dev, "WriteFile"); - bytes_written = -1; - goto end_of_function; - } - -end_of_function: - if (buf != data) - free(buf); - - return bytes_written; -} - - -int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) -{ - DWORD bytes_read = 0; - size_t copy_len = 0; - BOOL res; - - /* Copy the handle for convenience. */ - HANDLE ev = dev->ol.hEvent; - - if (!dev->read_pending) { - /* Start an Overlapped I/O read. */ - dev->read_pending = TRUE; - memset(dev->read_buf, 0, dev->input_report_length); - ResetEvent(ev); - res = ReadFile(dev->device_handle, dev->read_buf, (DWORD)dev->input_report_length, &bytes_read, &dev->ol); - - if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { - /* ReadFile() has failed. - Clean up and return error. */ - CancelIo(dev->device_handle); - dev->read_pending = FALSE; - goto end_of_function; - } - } - } - - if (milliseconds >= 0) { - /* See if there is any data yet. */ - res = WaitForSingleObject(ev, milliseconds); - if (res != WAIT_OBJECT_0) { - /* There was no data this time. Return zero bytes available, - but leave the Overlapped I/O running. */ - return 0; - } - } - - /* Either WaitForSingleObject() told us that ReadFile has completed, or - we are in non-blocking mode. Get the number of bytes read. The actual - data has been copied to the data[] array which was passed to ReadFile(). */ - res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); - - /* Set pending back to false, even if GetOverlappedResult() returned error. */ - dev->read_pending = FALSE; - - if (res && bytes_read > 0) { - if (dev->read_buf[0] == 0x0) { - /* If report numbers aren't being used, but Windows sticks a report - number (0x0) on the beginning of the report anyway. To make this - work like the other platforms, and to make it work more like the - HID spec, we'll skip over this byte. */ - bytes_read--; - copy_len = length > bytes_read ? bytes_read : length; - memcpy(data, dev->read_buf+1, copy_len); - } - else { - /* Copy the whole buffer, report number and all. */ - copy_len = length > bytes_read ? bytes_read : length; - memcpy(data, dev->read_buf, copy_len); - } - } - -end_of_function: - if (!res) { - register_error(dev, "GetOverlappedResult"); - return -1; - } - - return (int)copy_len; -} - -int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) -{ - return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); -} - -int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) -{ - dev->blocking = !nonblock; - return 0; /* Success */ -} - -int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) -{ - BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, (ULONG)length); - if (!res) { - register_error(dev, "HidD_SetFeature"); - return -1; - } - - return (int)length; -} - - -int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) -{ - BOOL res; -#if 0 - res = HidD_GetFeature(dev->device_handle, data, length); - if (!res) { - register_error(dev, "HidD_GetFeature"); - return -1; - } - return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */ -#else - DWORD bytes_returned; - - OVERLAPPED ol; - memset(&ol, 0, sizeof(ol)); - - res = DeviceIoControl(dev->device_handle, - IOCTL_HID_GET_FEATURE, - data, (DWORD)length, - data, (DWORD)length, - &bytes_returned, &ol); - - if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { - /* DeviceIoControl() failed. Return error. */ - register_error(dev, "Send Feature Report DeviceIoControl"); - return -1; - } - } - - /* Wait here until the write is done. This makes - hid_get_feature_report() synchronous. */ - res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/); - if (!res) { - /* The operation failed. */ - register_error(dev, "Send Feature Report GetOverLappedResult"); - return -1; - } - - /* bytes_returned does not include the first byte which contains the - report ID. The data buffer actually contains one more byte than - bytes_returned. */ - bytes_returned++; - - return bytes_returned; -#endif -} - -void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) -{ - if (!dev) - return; - CancelIo(dev->device_handle); - free_hid_device(dev); -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetManufacturerString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); - if (!res) { - register_error(dev, "HidD_GetManufacturerString"); - return -1; - } - - return 0; -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetProductString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); - if (!res) { - register_error(dev, "HidD_GetProductString"); - return -1; - } - - return 0; -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetSerialNumberString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); - if (!res) { - register_error(dev, "HidD_GetSerialNumberString"); - return -1; - } - - return 0; -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetIndexedString(dev->device_handle, string_index, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); - if (!res) { - register_error(dev, "HidD_GetIndexedString"); - return -1; - } - - return 0; -} - - -HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) -{ - return (wchar_t*)dev->last_error_str; -} - - -/*#define PICPGM*/ -/*#define S11*/ -#define P32 -#ifdef S11 - unsigned short VendorID = 0xa0a0; - unsigned short ProductID = 0x0001; -#endif - -#ifdef P32 - unsigned short VendorID = 0x04d8; - unsigned short ProductID = 0x3f; -#endif - - -#ifdef PICPGM - unsigned short VendorID = 0x04d8; - unsigned short ProductID = 0x0033; -#endif - - -#if 0 -int __cdecl main(int argc, char* argv[]) -{ - int res; - unsigned char buf[65]; - - UNREFERENCED_PARAMETER(argc); - UNREFERENCED_PARAMETER(argv); - - /* Set up the command buffer. */ - memset(buf,0x00,sizeof(buf)); - buf[0] = 0; - buf[1] = 0x81; - - - /* Open the device. */ - int handle = open(VendorID, ProductID, L"12345"); - if (handle < 0) - printf("unable to open device\n"); - - - /* Toggle LED (cmd 0x80) */ - buf[1] = 0x80; - res = write(handle, buf, 65); - if (res < 0) - printf("Unable to write()\n"); - - /* Request state (cmd 0x81) */ - buf[1] = 0x81; - write(handle, buf, 65); - if (res < 0) - printf("Unable to write() (2)\n"); - - /* Read requested state */ - read(handle, buf, 65); - if (res < 0) - printf("Unable to read()\n"); - - /* Print out the returned buffer. */ - for (int i = 0; i < 4; i++) - printf("buf[%d]: %d\n", i, buf[i]); - - return 0; -} -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif diff --git a/windows/hidapi.h b/windows/hidapi.h deleted file mode 100644 index 43b8e7a..0000000 --- a/windows/hidapi.h +++ /dev/null @@ -1,405 +0,0 @@ -/******************************************************* - HIDAPI - Multi-Platform library for - communication with HID devices. - - Alan Ott - Signal 11 Software - - 8/22/2009 - - Copyright 2009, All Rights Reserved. - - At the discretion of the user of this library, - this software may be licensed under the terms of the - GNU General Public License v3, a BSD-Style license, or the - original HIDAPI license as outlined in the LICENSE.txt, - LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt - files located at the root of the source distribution. - These files may also be found in the public source - code repository located at: - http://github.com/signal11/hidapi . -********************************************************/ - -/* Copy of LICENSE-orig.txt (compatible with MIT/x11 license) - - HIDAPI - Multi-Platform library for - communication with HID devices. - - Copyright 2009, Alan Ott, Signal 11 Software. - All Rights Reserved. - - This software may be used by anyone for any reason so - long as the copyright notice in the source files - remains intact. -*/ - - -/** @file - * @defgroup API hidapi API - */ - -#ifndef HIDAPI_H__ -#define HIDAPI_H__ - -#include - -#ifdef _WIN32 - #define HID_API_EXPORT __declspec(dllexport) - #define HID_API_CALL -#else - #define HID_API_EXPORT /**< API export macro */ - #define HID_API_CALL /**< API call macro */ -#endif - -#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ - -#ifdef __cplusplus -extern "C" { -#endif - struct hid_device_; - typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ - - /** hidapi info structure */ - struct hid_device_info { - /** Platform-specific device path */ - char *path; - /** Device Vendor ID */ - unsigned short vendor_id; - /** Device Product ID */ - unsigned short product_id; - /** Serial Number */ - wchar_t *serial_number; - /** Device Release Number in binary-coded decimal, - also known as Device Version Number */ - unsigned short release_number; - /** Manufacturer String */ - wchar_t *manufacturer_string; - /** Product string */ - wchar_t *product_string; - /** Usage Page for this Device/Interface - (Windows/Mac only). */ - unsigned short usage_page; - /** Usage for this Device/Interface - (Windows/Mac only).*/ - unsigned short usage; - /** The USB interface which this logical device - represents. Valid on both Linux implementations - in all cases, and valid on the Windows implementation - only if the device contains more than one interface. */ - int interface_number; - - /** Pointer to the next device */ - struct hid_device_info *next; - }; - - - /** @brief Initialize the HIDAPI library. - - This function initializes the HIDAPI library. Calling it is not - strictly necessary, as it will be called automatically by - hid_enumerate() and any of the hid_open_*() functions if it is - needed. This function should be called at the beginning of - execution however, if there is a chance of HIDAPI handles - being opened by different threads simultaneously. - - @ingroup API - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_init(void); - - /** @brief Finalize the HIDAPI library. - - This function frees all of the static data associated with - HIDAPI. It should be called at the end of execution to avoid - memory leaks. - - @ingroup API - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_exit(void); - - /** @brief Enumerate the HID Devices. - - This function returns a linked list of all the HID devices - attached to the system which match vendor_id and product_id. - If @p vendor_id is set to 0 then any vendor matches. - If @p product_id is set to 0 then any product matches. - If @p vendor_id and @p product_id are both set to 0, then - all HID devices will be returned. - - @ingroup API - @param vendor_id The Vendor ID (VID) of the types of device - to open. - @param product_id The Product ID (PID) of the types of - device to open. - - @returns - This function returns a pointer to a linked list of type - struct #hid_device, containing information about the HID devices - attached to the system, or NULL in the case of failure. Free - this linked list by calling hid_free_enumeration(). - */ - struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); - - /** @brief Free an enumeration Linked List - - This function frees a linked list created by hid_enumerate(). - - @ingroup API - @param devs Pointer to a list of struct_device returned from - hid_enumerate(). - */ - void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); - - /** @brief Open a HID device using a Vendor ID (VID), Product ID - (PID) and optionally a serial number. - - If @p serial_number is NULL, the first device with the - specified VID and PID is opened. - - @ingroup API - @param vendor_id The Vendor ID (VID) of the device to open. - @param product_id The Product ID (PID) of the device to open. - @param serial_number The Serial Number of the device to open - (Optionally NULL). - - @returns - This function returns a pointer to a #hid_device object on - success or NULL on failure. - */ - HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); - - /** @brief Open a HID device by its path name. - - The path name be determined by calling hid_enumerate(), or a - platform-specific path name can be used (eg: /dev/hidraw0 on - Linux). - - @ingroup API - @param path The path name of the device to open - - @returns - This function returns a pointer to a #hid_device object on - success or NULL on failure. - */ - HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); - - /** @brief Write an Output report to a HID device. - - The first byte of @p data[] must contain the Report ID. For - devices which only support a single report, this must be set - to 0x0. The remaining bytes contain the report data. Since - the Report ID is mandatory, calls to hid_write() will always - contain one more byte than the report contains. For example, - if a hid report is 16 bytes long, 17 bytes must be passed to - hid_write(), the Report ID (or 0x0, for devices with a - single report), followed by the report data (16 bytes). In - this example, the length passed in would be 17. - - hid_write() will send the data on the first OUT endpoint, if - one exists. If it does not, it will send the data through - the Control Endpoint (Endpoint 0). - - @ingroup API - @param device A device handle returned from hid_open(). - @param data The data to send, including the report number as - the first byte. - @param length The length in bytes of the data to send. - - @returns - This function returns the actual number of bytes written and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); - - /** @brief Read an Input report from a HID device with timeout. - - Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will - contain the Report number if the device uses numbered reports. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into. - @param length The number of bytes to read. For devices with - multiple reports, make sure to read an extra byte for - the report number. - @param milliseconds timeout in milliseconds or -1 for blocking wait. - - @returns - This function returns the actual number of bytes read and - -1 on error. If no packet was available to be read within - the timeout period, this function returns 0. - */ - int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); - - /** @brief Read an Input report from a HID device. - - Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will - contain the Report number if the device uses numbered reports. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into. - @param length The number of bytes to read. For devices with - multiple reports, make sure to read an extra byte for - the report number. - - @returns - This function returns the actual number of bytes read and - -1 on error. If no packet was available to be read and - the handle is in non-blocking mode, this function returns 0. - */ - int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); - - /** @brief Set the device handle to be non-blocking. - - In non-blocking mode calls to hid_read() will return - immediately with a value of 0 if there is no data to be - read. In blocking mode, hid_read() will wait (block) until - there is data to read before returning. - - Nonblocking can be turned on and off at any time. - - @ingroup API - @param device A device handle returned from hid_open(). - @param nonblock enable or not the nonblocking reads - - 1 to enable nonblocking - - 0 to disable nonblocking. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); - - /** @brief Send a Feature report to the device. - - Feature reports are sent over the Control endpoint as a - Set_Report transfer. The first byte of @p data[] must - contain the Report ID. For devices which only support a - single report, this must be set to 0x0. The remaining bytes - contain the report data. Since the Report ID is mandatory, - calls to hid_send_feature_report() will always contain one - more byte than the report contains. For example, if a hid - report is 16 bytes long, 17 bytes must be passed to - hid_send_feature_report(): the Report ID (or 0x0, for - devices which do not use numbered reports), followed by the - report data (16 bytes). In this example, the length passed - in would be 17. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data The data to send, including the report number as - the first byte. - @param length The length in bytes of the data to send, including - the report number. - - @returns - This function returns the actual number of bytes written and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); - - /** @brief Get a feature report from a HID device. - - Set the first byte of @p data[] to the Report ID of the - report to be read. Make sure to allow space for this - extra byte in @p data[]. Upon return, the first byte will - still contain the Report ID, and the report data will - start in data[1]. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into, including - the Report ID. Set the first byte of @p data[] to the - Report ID of the report to be read, or set it to zero - if your device does not use numbered reports. - @param length The number of bytes to read, including an - extra byte for the report ID. The buffer can be longer - than the actual report. - - @returns - This function returns the number of bytes read plus - one for the report ID (which is still in the first - byte), or -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); - - /** @brief Close a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - */ - void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); - - /** @brief Get The Manufacturer String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get The Product String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get The Serial Number String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get a string from a HID device, based on its string index. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string_index The index of the string to get. - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); - - /** @brief Get a string describing the last error which occurred. - - @ingroup API - @param device A device handle returned from hid_open(). - - @returns - This function returns a string containing the last error - which occurred or NULL if none has occurred. - */ - HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/windows/tcc_stubs.c b/windows/tcc_stubs.c deleted file mode 100644 index 7872914..0000000 --- a/windows/tcc_stubs.c +++ /dev/null @@ -1,59 +0,0 @@ - -#include <_mingw.h> - -#define REMATH(x) double __cdecl x( double f ); float x##f(float v) { return x(v); } - -REMATH( acos ); -REMATH( cos ); -REMATH( sin ); -REMATH( sqrt ); -REMATH( asin ); - -double __cdecl strtod (const char* str, char** endptr); -float strtof( const char* str, char** endptr) -{ - return strtod( str, endptr ); -} - -double __cdecl atan2(double a, double b); -float atan2f(float a, float b) -{ - return atan2( a, b ); -} - -//From http://stackoverflow.com/questions/40159892/using-asprintf-on-windows -int __cdecl vsprintf_s( - char *buffer, - size_t numberOfElements, - const char *format, - va_list argptr -); - -int asprintf(char **strp, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - int r = vasprintf(strp, fmt, ap); - va_end(ap); - return r; -} - -int vasprintf(char **strp, const char *fmt, va_list ap) { - // _vscprintf tells you how big the buffer needs to be - int len = _vscprintf(fmt, ap); - if (len == -1) { - return -1; - } - size_t size = (size_t)len + 1; - char *str = (char*)malloc(size); - if (!str) { - return -1; - } - // _vsprintf_s is the "secure" version of vsprintf - int r = vsprintf_s(str, len + 1, fmt, ap); - if (r == -1) { - free(str); - return -1; - } - *strp = str; - return r; -} \ No newline at end of file -- cgit v1.2.3 From 26c9beb059c02c7f66a072b34bda04db105bb6dc Mon Sep 17 00:00:00 2001 From: cnlohr Date: Thu, 16 Mar 2017 21:57:44 -0400 Subject: Add HID-OSX --- redist/hid-osx.c | 1111 +++++++++++++++++++++++++++++++++++++++++++++++++++++ redist/hidapi.h | 405 +++++++++++++++++++ winbuild/hidapi.h | 405 ------------------- 3 files changed, 1516 insertions(+), 405 deletions(-) create mode 100644 redist/hid-osx.c create mode 100644 redist/hidapi.h delete mode 100644 winbuild/hidapi.h diff --git a/redist/hid-osx.c b/redist/hid-osx.c new file mode 100644 index 0000000..57a337c --- /dev/null +++ b/redist/hid-osx.c @@ -0,0 +1,1111 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 2010-07-03 + + Copyright 2010, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/* See Apple Technical Note TN2187 for details on IOHidManager. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hidapi.h" + +/* Barrier implementation because Mac OSX doesn't have pthread_barrier. + It also doesn't have clock_gettime(). So much for POSIX and SUSv2. + This implementation came from Brent Priddy and was posted on + StackOverflow. It is used with his permission. */ +typedef int pthread_barrierattr_t; +typedef struct pthread_barrier { + pthread_mutex_t mutex; + pthread_cond_t cond; + int count; + int trip_count; +} pthread_barrier_t; + +static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) +{ + if(count == 0) { + errno = EINVAL; + return -1; + } + + if(pthread_mutex_init(&barrier->mutex, 0) < 0) { + return -1; + } + if(pthread_cond_init(&barrier->cond, 0) < 0) { + pthread_mutex_destroy(&barrier->mutex); + return -1; + } + barrier->trip_count = count; + barrier->count = 0; + + return 0; +} + +static int pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} + +static int pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_mutex_lock(&barrier->mutex); + ++(barrier->count); + if(barrier->count >= barrier->trip_count) + { + barrier->count = 0; + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return 1; + } + else + { + pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + pthread_mutex_unlock(&barrier->mutex); + return 0; + } +} + +static int return_data(hid_device *dev, unsigned char *data, size_t length); + +/* Linked List of input reports received from the device. */ +struct input_report { + uint8_t *data; + size_t len; + struct input_report *next; +}; + +struct hid_device_ { + IOHIDDeviceRef device_handle; + int blocking; + int uses_numbered_reports; + int disconnected; + CFStringRef run_loop_mode; + CFRunLoopRef run_loop; + CFRunLoopSourceRef source; + uint8_t *input_report_buf; + CFIndex max_input_report_len; + struct input_report *input_reports; + + pthread_t thread; + pthread_mutex_t mutex; /* Protects input_reports */ + pthread_cond_t condition; + pthread_barrier_t barrier; /* Ensures correct startup sequence */ + pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */ + int shutdown_thread; +}; + +static hid_device *new_hid_device(void) +{ + hid_device *dev = calloc(1, sizeof(hid_device)); + dev->device_handle = NULL; + dev->blocking = 1; + dev->uses_numbered_reports = 0; + dev->disconnected = 0; + dev->run_loop_mode = NULL; + dev->run_loop = NULL; + dev->source = NULL; + dev->input_report_buf = NULL; + dev->input_reports = NULL; + dev->shutdown_thread = 0; + + /* Thread objects */ + pthread_mutex_init(&dev->mutex, NULL); + pthread_cond_init(&dev->condition, NULL); + pthread_barrier_init(&dev->barrier, NULL, 2); + pthread_barrier_init(&dev->shutdown_barrier, NULL, 2); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + if (!dev) + return; + + /* Delete any input reports still left over. */ + struct input_report *rpt = dev->input_reports; + while (rpt) { + struct input_report *next = rpt->next; + free(rpt->data); + free(rpt); + rpt = next; + } + + /* Free the string and the report buffer. The check for NULL + is necessary here as CFRelease() doesn't handle NULL like + free() and others do. */ + if (dev->run_loop_mode) + CFRelease(dev->run_loop_mode); + if (dev->source) + CFRelease(dev->source); + free(dev->input_report_buf); + + /* Clean up the thread objects */ + pthread_barrier_destroy(&dev->shutdown_barrier); + pthread_barrier_destroy(&dev->barrier); + pthread_cond_destroy(&dev->condition); + pthread_mutex_destroy(&dev->mutex); + + /* Free the structure itself. */ + free(dev); +} + +static IOHIDManagerRef hid_mgr = 0x0; + + +#if 0 +static void register_error(hid_device *device, const char *op) +{ + +} +#endif + + +static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key) +{ + CFTypeRef ref; + int32_t value; + + ref = IOHIDDeviceGetProperty(device, key); + if (ref) { + if (CFGetTypeID(ref) == CFNumberGetTypeID()) { + CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value); + return value; + } + } + return 0; +} + +static unsigned short get_vendor_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDVendorIDKey)); +} + +static unsigned short get_product_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDProductIDKey)); +} + +static int32_t get_max_report_length(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDMaxInputReportSizeKey)); +} + +static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len) +{ + CFStringRef str; + + if (!len) + return 0; + + str = IOHIDDeviceGetProperty(device, prop); + + buf[0] = 0; + + if (str) { + CFIndex str_len = CFStringGetLength(str); + CFRange range; + CFIndex used_buf_len; + CFIndex chars_copied; + + len --; + + range.location = 0; + range.length = ((size_t)str_len > len)? len: (size_t)str_len; + chars_copied = CFStringGetBytes(str, + range, + kCFStringEncodingUTF32LE, + (char)'?', + FALSE, + (UInt8*)buf, + len * sizeof(wchar_t), + &used_buf_len); + + if (chars_copied == len) + buf[len] = 0; /* len is decremented above */ + else + buf[chars_copied] = 0; + + return 0; + } + else + return -1; + +} + +static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len); +} + +static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len); +} + +static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len); +} + + +/* Implementation of wcsdup() for Mac. */ +static wchar_t *dup_wcs(const wchar_t *s) +{ + size_t len = wcslen(s); + wchar_t *ret = malloc((len+1)*sizeof(wchar_t)); + wcscpy(ret, s); + + return ret; +} + +/* hidapi_IOHIDDeviceGetService() + * + * Return the io_service_t corresponding to a given IOHIDDeviceRef, either by: + * - on OS X 10.6 and above, calling IOHIDDeviceGetService() + * - on OS X 10.5, extract it from the IOHIDDevice struct + */ +static io_service_t hidapi_IOHIDDeviceGetService(IOHIDDeviceRef device) +{ + static void *iokit_framework = NULL; + static io_service_t (*dynamic_IOHIDDeviceGetService)(IOHIDDeviceRef device) = NULL; + + /* Use dlopen()/dlsym() to get a pointer to IOHIDDeviceGetService() if it exists. + * If any of these steps fail, dynamic_IOHIDDeviceGetService will be left NULL + * and the fallback method will be used. + */ + if (iokit_framework == NULL) { + iokit_framework = dlopen("/System/Library/IOKit.framework/IOKit", RTLD_LAZY); + + if (iokit_framework != NULL) + dynamic_IOHIDDeviceGetService = dlsym(iokit_framework, "IOHIDDeviceGetService"); + } + + if (dynamic_IOHIDDeviceGetService != NULL) { + /* Running on OS X 10.6 and above: IOHIDDeviceGetService() exists */ + return dynamic_IOHIDDeviceGetService(device); + } + else + { + /* Running on OS X 10.5: IOHIDDeviceGetService() doesn't exist. + * + * Be naughty and pull the service out of the IOHIDDevice. + * IOHIDDevice is an opaque struct not exposed to applications, but its + * layout is stable through all available versions of OS X. + * Tested and working on OS X 10.5.8 i386, x86_64, and ppc. + */ + struct IOHIDDevice_internal { + /* The first field of the IOHIDDevice struct is a + * CFRuntimeBase (which is a private CF struct). + * + * a, b, and c are the 3 fields that make up a CFRuntimeBase. + * See http://opensource.apple.com/source/CF/CF-476.18/CFRuntime.h + * + * The second field of the IOHIDDevice is the io_service_t we're looking for. + */ + uintptr_t a; + uint8_t b[4]; +#if __LP64__ + uint32_t c; +#endif + io_service_t service; + }; + struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *)device; + + return tmp->service; + } +} + +/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */ +static int init_hid_manager(void) +{ + /* Initialize all the HID Manager Objects */ + hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hid_mgr) { + IOHIDManagerSetDeviceMatching(hid_mgr, NULL); + IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + return 0; + } + + return -1; +} + +/* Initialize the IOHIDManager if necessary. This is the public function, and + it is safe to call this function repeatedly. Return 0 for success and -1 + for failure. */ +int HID_API_EXPORT hid_init(void) +{ + if (!hid_mgr) { + return init_hid_manager(); + } + + /* Already initialized. */ + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ + if (hid_mgr) { + /* Close the HID manager. */ + IOHIDManagerClose(hid_mgr, kIOHIDOptionsTypeNone); + CFRelease(hid_mgr); + hid_mgr = NULL; + } + + return 0; +} + +static void process_pending_events(void) { + SInt32 res; + do { + res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE); + } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut); +} + +struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + CFIndex num_devices; + int i; + + /* Set up the HID Manager if it hasn't been done */ + if (hid_init() < 0) + return NULL; + + /* give the IOHIDManager a chance to update itself */ + process_pending_events(); + + /* Get a list of the Devices */ + IOHIDManagerSetDeviceMatching(hid_mgr, NULL); + CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); + + /* Convert the list into a C array so we can iterate easily. */ + num_devices = CFSetGetCount(device_set); + IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + + /* Iterate over each device, making an entry for it. */ + for (i = 0; i < num_devices; i++) { + unsigned short dev_vid; + unsigned short dev_pid; + #define BUF_LEN 256 + wchar_t buf[BUF_LEN]; + + IOHIDDeviceRef dev = device_array[i]; + + if (!dev) { + continue; + } + dev_vid = get_vendor_id(dev); + dev_pid = get_product_id(dev); + + /* Check the VID/PID against the arguments */ + if ((vendor_id == 0x0 || vendor_id == dev_vid) && + (product_id == 0x0 || product_id == dev_pid)) { + struct hid_device_info *tmp; + io_object_t iokit_dev; + kern_return_t res; + io_string_t path; + + /* VID/PID match. Create the record. */ + tmp = malloc(sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Get the Usage Page and Usage for this device. */ + cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey)); + cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey)); + + /* Fill out the record */ + cur_dev->next = NULL; + + /* Fill in the path (IOService plane) */ + iokit_dev = hidapi_IOHIDDeviceGetService(dev); + res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path); + if (res == KERN_SUCCESS) + cur_dev->path = strdup(path); + else + cur_dev->path = strdup(""); + + /* Serial Number */ + get_serial_number(dev, buf, BUF_LEN); + cur_dev->serial_number = dup_wcs(buf); + + /* Manufacturer and Product strings */ + get_manufacturer_string(dev, buf, BUF_LEN); + cur_dev->manufacturer_string = dup_wcs(buf); + get_product_string(dev, buf, BUF_LEN); + cur_dev->product_string = dup_wcs(buf); + + /* VID/PID */ + cur_dev->vendor_id = dev_vid; + cur_dev->product_id = dev_pid; + + /* Release Number */ + cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey)); + + /* Interface Number (Unsupported on Mac)*/ + cur_dev->interface_number = -1; + } + } + + free(device_array); + CFRelease(device_set); + + return root; +} + +void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) +{ + /* This function is identical to the Linux version. Platform independent. */ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + +hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + /* This function is identical to the Linux version. Platform independent. */ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device * handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +static void hid_device_removal_callback(void *context, IOReturn result, + void *sender) +{ + /* Stop the Run Loop for this device. */ + hid_device *d = context; + + d->disconnected = 1; + CFRunLoopStop(d->run_loop); +} + +/* The Run Loop calls this function for each input report received. + This function puts the data into a linked list to be picked up by + hid_read(). */ +static void hid_report_callback(void *context, IOReturn result, void *sender, + IOHIDReportType report_type, uint32_t report_id, + uint8_t *report, CFIndex report_length) +{ + struct input_report *rpt; + hid_device *dev = context; + + /* Make a new Input Report object */ + rpt = calloc(1, sizeof(struct input_report)); + rpt->data = calloc(1, report_length); + memcpy(rpt->data, report, report_length); + rpt->len = report_length; + rpt->next = NULL; + + /* Lock this section */ + pthread_mutex_lock(&dev->mutex); + + /* Attach the new report object to the end of the list. */ + if (dev->input_reports == NULL) { + /* The list is empty. Put it at the root. */ + dev->input_reports = rpt; + } + else { + /* Find the end of the list and attach. */ + struct input_report *cur = dev->input_reports; + int num_queued = 0; + while (cur->next != NULL) { + cur = cur->next; + num_queued++; + } + cur->next = rpt; + + /* Pop one off if we've reached 30 in the queue. This + way we don't grow forever if the user never reads + anything from the device. */ + if (num_queued > 30) { + return_data(dev, NULL, 0); + } + } + + /* Signal a waiting thread that there is data. */ + pthread_cond_signal(&dev->condition); + + /* Unlock */ + pthread_mutex_unlock(&dev->mutex); + +} + +/* This gets called when the read_thread's run loop gets signaled by + hid_close(), and serves to stop the read_thread's run loop. */ +static void perform_signal_callback(void *context) +{ + hid_device *dev = context; + CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/ +} + +static void *read_thread(void *param) +{ + hid_device *dev = param; + SInt32 code; + + /* Move the device's run loop to this thread. */ + IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode); + + /* Create the RunLoopSource which is used to signal the + event loop to stop when hid_close() is called. */ + CFRunLoopSourceContext ctx; + memset(&ctx, 0, sizeof(ctx)); + ctx.version = 0; + ctx.info = dev; + ctx.perform = &perform_signal_callback; + dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx); + CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode); + + /* Store off the Run Loop so it can be stopped from hid_close() + and on device disconnection. */ + dev->run_loop = CFRunLoopGetCurrent(); + + /* Notify the main thread that the read thread is up and running. */ + pthread_barrier_wait(&dev->barrier); + + /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input + reports into the hid_report_callback(). */ + while (!dev->shutdown_thread && !dev->disconnected) { + code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE); + /* Return if the device has been disconnected */ + if (code == kCFRunLoopRunFinished) { + dev->disconnected = 1; + break; + } + + + /* Break if The Run Loop returns Finished or Stopped. */ + if (code != kCFRunLoopRunTimedOut && + code != kCFRunLoopRunHandledSource) { + /* There was some kind of error. Setting + shutdown seems to make sense, but + there may be something else more appropriate */ + dev->shutdown_thread = 1; + break; + } + } + + /* Now that the read thread is stopping, Wake any threads which are + waiting on data (in hid_read_timeout()). Do this under a mutex to + make sure that a thread which is about to go to sleep waiting on + the condition actually will go to sleep before the condition is + signaled. */ + pthread_mutex_lock(&dev->mutex); + pthread_cond_broadcast(&dev->condition); + pthread_mutex_unlock(&dev->mutex); + + /* Wait here until hid_close() is called and makes it past + the call to CFRunLoopWakeUp(). This thread still needs to + be valid when that function is called on the other thread. */ + pthread_barrier_wait(&dev->shutdown_barrier); + + return NULL; +} + +/* hid_open_path() + * + * path must be a valid path to an IOHIDDevice in the IOService plane + * Example: "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd120000/IOUSBInterface@0/IOUSBHIDDriver" + */ +hid_device * HID_API_EXPORT hid_open_path(const char *path) +{ + hid_device *dev = NULL; + io_registry_entry_t entry = MACH_PORT_NULL; + + dev = new_hid_device(); + + /* Set up the HID Manager if it hasn't been done */ + if (hid_init() < 0) + return NULL; + + /* Get the IORegistry entry for the given path */ + entry = IORegistryEntryFromPath(kIOMasterPortDefault, path); + if (entry == MACH_PORT_NULL) { + /* Path wasn't valid (maybe device was removed?) */ + goto return_error; + } + + /* Create an IOHIDDevice for the entry */ + dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry); + if (dev->device_handle == NULL) { + /* Error creating the HID device */ + goto return_error; + } + + /* Open the IOHIDDevice */ + IOReturn ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); + if (ret == kIOReturnSuccess) { + char str[32]; + + /* Create the buffers for receiving data */ + dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle); + dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t)); + + /* Create the Run Loop Mode for this device. + printing the reference seems to work. */ + sprintf(str, "HIDAPI_%p", dev->device_handle); + dev->run_loop_mode = + CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); + + /* Attach the device to a Run Loop */ + IOHIDDeviceRegisterInputReportCallback( + dev->device_handle, dev->input_report_buf, dev->max_input_report_len, + &hid_report_callback, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); + + /* Start the read thread */ + pthread_create(&dev->thread, NULL, read_thread, dev); + + /* Wait here for the read thread to be initialized. */ + pthread_barrier_wait(&dev->barrier); + + IOObjectRelease(entry); + return dev; + } + else { + goto return_error; + } + +return_error: + if (dev->device_handle != NULL) + CFRelease(dev->device_handle); + + if (entry != MACH_PORT_NULL) + IOObjectRelease(entry); + + free_hid_device(dev); + return NULL; +} + +static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length) +{ + const unsigned char *data_to_send; + size_t length_to_send; + IOReturn res; + + /* Return if the device has been disconnected. */ + if (dev->disconnected) + return -1; + + if (data[0] == 0x0) { + /* Not using numbered Reports. + Don't send the report number. */ + data_to_send = data+1; + length_to_send = length-1; + } + else { + /* Using numbered Reports. + Send the Report Number */ + data_to_send = data; + length_to_send = length; + } + + if (!dev->disconnected) { + res = IOHIDDeviceSetReport(dev->device_handle, + type, + data[0], /* Report ID*/ + data_to_send, length_to_send); + + if (res == kIOReturnSuccess) { + return length; + } + else + return -1; + } + + return -1; +} + +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, kIOHIDReportTypeOutput, data, length); +} + +/* Helper function, so that this isn't duplicated in hid_read(). */ +static int return_data(hid_device *dev, unsigned char *data, size_t length) +{ + /* Copy the data out of the linked list item (rpt) into the + return buffer (data), and delete the liked list item. */ + struct input_report *rpt = dev->input_reports; + size_t len = (length < rpt->len)? length: rpt->len; + memcpy(data, rpt->data, len); + dev->input_reports = rpt->next; + free(rpt->data); + free(rpt); + return len; +} + +static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + while (!dev->input_reports) { + int res = pthread_cond_wait(cond, mutex); + if (res != 0) + return res; + + /* A res of 0 means we may have been signaled or it may + be a spurious wakeup. Check to see that there's acutally + data in the queue before returning, and if not, go back + to sleep. See the pthread_cond_timedwait() man page for + details. */ + + if (dev->shutdown_thread || dev->disconnected) + return -1; + } + + return 0; +} + +static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) +{ + while (!dev->input_reports) { + int res = pthread_cond_timedwait(cond, mutex, abstime); + if (res != 0) + return res; + + /* A res of 0 means we may have been signaled or it may + be a spurious wakeup. Check to see that there's acutally + data in the queue before returning, and if not, go back + to sleep. See the pthread_cond_timedwait() man page for + details. */ + + if (dev->shutdown_thread || dev->disconnected) + return -1; + } + + return 0; + +} + +int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + int bytes_read = -1; + + /* Lock the access to the report list. */ + pthread_mutex_lock(&dev->mutex); + + /* There's an input report queued up. Return it. */ + if (dev->input_reports) { + /* Return the first one */ + bytes_read = return_data(dev, data, length); + goto ret; + } + + /* Return if the device has been disconnected. */ + if (dev->disconnected) { + bytes_read = -1; + goto ret; + } + + if (dev->shutdown_thread) { + /* This means the device has been closed (or there + has been an error. An error code of -1 should + be returned. */ + bytes_read = -1; + goto ret; + } + + /* There is no data. Go to sleep and wait for data. */ + + if (milliseconds == -1) { + /* Blocking */ + int res; + res = cond_wait(dev, &dev->condition, &dev->mutex); + if (res == 0) + bytes_read = return_data(dev, data, length); + else { + /* There was an error, or a device disconnection. */ + bytes_read = -1; + } + } + else if (milliseconds > 0) { + /* Non-blocking, but called with timeout. */ + int res; + struct timespec ts; + struct timeval tv; + gettimeofday(&tv, NULL); + TIMEVAL_TO_TIMESPEC(&tv, &ts); + ts.tv_sec += milliseconds / 1000; + ts.tv_nsec += (milliseconds % 1000) * 1000000; + if (ts.tv_nsec >= 1000000000L) { + ts.tv_sec++; + ts.tv_nsec -= 1000000000L; + } + + res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts); + if (res == 0) + bytes_read = return_data(dev, data, length); + else if (res == ETIMEDOUT) + bytes_read = 0; + else + bytes_read = -1; + } + else { + /* Purely non-blocking */ + bytes_read = 0; + } + +ret: + /* Unlock */ + pthread_mutex_unlock(&dev->mutex); + return bytes_read; +} + +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) +{ + /* All Nonblocking operation is handled by the library. */ + dev->blocking = !nonblock; + + return 0; +} + +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, kIOHIDReportTypeFeature, data, length); +} + +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + CFIndex len = length; + IOReturn res; + + /* Return if the device has been unplugged. */ + if (dev->disconnected) + return -1; + + res = IOHIDDeviceGetReport(dev->device_handle, + kIOHIDReportTypeFeature, + data[0], /* Report ID */ + data, &len); + if (res == kIOReturnSuccess) + return len; + else + return -1; +} + + +void HID_API_EXPORT hid_close(hid_device *dev) +{ + if (!dev) + return; + + /* Disconnect the report callback before close. */ + if (!dev->disconnected) { + IOHIDDeviceRegisterInputReportCallback( + dev->device_handle, dev->input_report_buf, dev->max_input_report_len, + NULL, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev); + IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode); + IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode); + } + + /* Cause read_thread() to stop. */ + dev->shutdown_thread = 1; + + /* Wake up the run thread's event loop so that the thread can exit. */ + CFRunLoopSourceSignal(dev->source); + CFRunLoopWakeUp(dev->run_loop); + + /* Notify the read thread that it can shut down now. */ + pthread_barrier_wait(&dev->shutdown_barrier); + + /* Wait for read_thread() to end. */ + pthread_join(dev->thread, NULL); + + /* Close the OS handle to the device, but only if it's not + been unplugged. If it's been unplugged, then calling + IOHIDDeviceClose() will crash. */ + if (!dev->disconnected) { + IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); + } + + /* Clear out the queue of received reports. */ + pthread_mutex_lock(&dev->mutex); + while (dev->input_reports) { + return_data(dev, NULL, 0); + } + pthread_mutex_unlock(&dev->mutex); + CFRelease(dev->device_handle); + + free_hid_device(dev); +} + +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_manufacturer_string(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_product_string(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_serial_number(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + /* TODO: */ + + return 0; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + /* TODO: */ + + return NULL; +} + + + + + + + +#if 0 +static int32_t get_location_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDLocationIDKey)); +} + +static int32_t get_usage(IOHIDDeviceRef device) +{ + int32_t res; + res = get_int_property(device, CFSTR(kIOHIDDeviceUsageKey)); + if (!res) + res = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey)); + return res; +} + +static int32_t get_usage_page(IOHIDDeviceRef device) +{ + int32_t res; + res = get_int_property(device, CFSTR(kIOHIDDeviceUsagePageKey)); + if (!res) + res = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey)); + return res; +} + +static int get_transport(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDTransportKey), buf, len); +} + + +int main(void) +{ + IOHIDManagerRef mgr; + int i; + + mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + IOHIDManagerSetDeviceMatching(mgr, NULL); + IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone); + + CFSetRef device_set = IOHIDManagerCopyDevices(mgr); + + CFIndex num_devices = CFSetGetCount(device_set); + IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + + for (i = 0; i < num_devices; i++) { + IOHIDDeviceRef dev = device_array[i]; + printf("Device: %p\n", dev); + printf(" %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev)); + + wchar_t serial[256], buf[256]; + char cbuf[256]; + get_serial_number(dev, serial, 256); + + + printf(" Serial: %ls\n", serial); + printf(" Loc: %ld\n", get_location_id(dev)); + get_transport(dev, buf, 256); + printf(" Trans: %ls\n", buf); + make_path(dev, cbuf, 256); + printf(" Path: %s\n", cbuf); + + } + + return 0; +} +#endif + diff --git a/redist/hidapi.h b/redist/hidapi.h new file mode 100644 index 0000000..43b8e7a --- /dev/null +++ b/redist/hidapi.h @@ -0,0 +1,405 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/* Copy of LICENSE-orig.txt (compatible with MIT/x11 license) + + HIDAPI - Multi-Platform library for + communication with HID devices. + + Copyright 2009, Alan Ott, Signal 11 Software. + All Rights Reserved. + + This software may be used by anyone for any reason so + long as the copyright notice in the source files + remains intact. +*/ + + +/** @file + * @defgroup API hidapi API + */ + +#ifndef HIDAPI_H__ +#define HIDAPI_H__ + +#include + +#ifdef _WIN32 + #define HID_API_EXPORT __declspec(dllexport) + #define HID_API_CALL +#else + #define HID_API_EXPORT /**< API export macro */ + #define HID_API_CALL /**< API call macro */ +#endif + +#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ + +#ifdef __cplusplus +extern "C" { +#endif + struct hid_device_; + typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ + + /** hidapi info structure */ + struct hid_device_info { + /** Platform-specific device path */ + char *path; + /** Device Vendor ID */ + unsigned short vendor_id; + /** Device Product ID */ + unsigned short product_id; + /** Serial Number */ + wchar_t *serial_number; + /** Device Release Number in binary-coded decimal, + also known as Device Version Number */ + unsigned short release_number; + /** Manufacturer String */ + wchar_t *manufacturer_string; + /** Product string */ + wchar_t *product_string; + /** Usage Page for this Device/Interface + (Windows/Mac only). */ + unsigned short usage_page; + /** Usage for this Device/Interface + (Windows/Mac only).*/ + unsigned short usage; + /** The USB interface which this logical device + represents. Valid on both Linux implementations + in all cases, and valid on the Windows implementation + only if the device contains more than one interface. */ + int interface_number; + + /** Pointer to the next device */ + struct hid_device_info *next; + }; + + + /** @brief Initialize the HIDAPI library. + + This function initializes the HIDAPI library. Calling it is not + strictly necessary, as it will be called automatically by + hid_enumerate() and any of the hid_open_*() functions if it is + needed. This function should be called at the beginning of + execution however, if there is a chance of HIDAPI handles + being opened by different threads simultaneously. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_init(void); + + /** @brief Finalize the HIDAPI library. + + This function frees all of the static data associated with + HIDAPI. It should be called at the end of execution to avoid + memory leaks. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_exit(void); + + /** @brief Enumerate the HID Devices. + + This function returns a linked list of all the HID devices + attached to the system which match vendor_id and product_id. + If @p vendor_id is set to 0 then any vendor matches. + If @p product_id is set to 0 then any product matches. + If @p vendor_id and @p product_id are both set to 0, then + all HID devices will be returned. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the types of device + to open. + @param product_id The Product ID (PID) of the types of + device to open. + + @returns + This function returns a pointer to a linked list of type + struct #hid_device, containing information about the HID devices + attached to the system, or NULL in the case of failure. Free + this linked list by calling hid_free_enumeration(). + */ + struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); + + /** @brief Free an enumeration Linked List + + This function frees a linked list created by hid_enumerate(). + + @ingroup API + @param devs Pointer to a list of struct_device returned from + hid_enumerate(). + */ + void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); + + /** @brief Open a HID device using a Vendor ID (VID), Product ID + (PID) and optionally a serial number. + + If @p serial_number is NULL, the first device with the + specified VID and PID is opened. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the device to open. + @param product_id The Product ID (PID) of the device to open. + @param serial_number The Serial Number of the device to open + (Optionally NULL). + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); + + /** @brief Open a HID device by its path name. + + The path name be determined by calling hid_enumerate(), or a + platform-specific path name can be used (eg: /dev/hidraw0 on + Linux). + + @ingroup API + @param path The path name of the device to open + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); + + /** @brief Write an Output report to a HID device. + + The first byte of @p data[] must contain the Report ID. For + devices which only support a single report, this must be set + to 0x0. The remaining bytes contain the report data. Since + the Report ID is mandatory, calls to hid_write() will always + contain one more byte than the report contains. For example, + if a hid report is 16 bytes long, 17 bytes must be passed to + hid_write(), the Report ID (or 0x0, for devices with a + single report), followed by the report data (16 bytes). In + this example, the length passed in would be 17. + + hid_write() will send the data on the first OUT endpoint, if + one exists. If it does not, it will send the data through + the Control Endpoint (Endpoint 0). + + @ingroup API + @param device A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send. + + @returns + This function returns the actual number of bytes written and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); + + /** @brief Read an Input report from a HID device with timeout. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + @param milliseconds timeout in milliseconds or -1 for blocking wait. + + @returns + This function returns the actual number of bytes read and + -1 on error. If no packet was available to be read within + the timeout period, this function returns 0. + */ + int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); + + /** @brief Read an Input report from a HID device. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + + @returns + This function returns the actual number of bytes read and + -1 on error. If no packet was available to be read and + the handle is in non-blocking mode, this function returns 0. + */ + int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); + + /** @brief Set the device handle to be non-blocking. + + In non-blocking mode calls to hid_read() will return + immediately with a value of 0 if there is no data to be + read. In blocking mode, hid_read() will wait (block) until + there is data to read before returning. + + Nonblocking can be turned on and off at any time. + + @ingroup API + @param device A device handle returned from hid_open(). + @param nonblock enable or not the nonblocking reads + - 1 to enable nonblocking + - 0 to disable nonblocking. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); + + /** @brief Send a Feature report to the device. + + Feature reports are sent over the Control endpoint as a + Set_Report transfer. The first byte of @p data[] must + contain the Report ID. For devices which only support a + single report, this must be set to 0x0. The remaining bytes + contain the report data. Since the Report ID is mandatory, + calls to hid_send_feature_report() will always contain one + more byte than the report contains. For example, if a hid + report is 16 bytes long, 17 bytes must be passed to + hid_send_feature_report(): the Report ID (or 0x0, for + devices which do not use numbered reports), followed by the + report data (16 bytes). In this example, the length passed + in would be 17. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send, including + the report number. + + @returns + This function returns the actual number of bytes written and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); + + /** @brief Get a feature report from a HID device. + + Set the first byte of @p data[] to the Report ID of the + report to be read. Make sure to allow space for this + extra byte in @p data[]. Upon return, the first byte will + still contain the Report ID, and the report data will + start in data[1]. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into, including + the Report ID. Set the first byte of @p data[] to the + Report ID of the report to be read, or set it to zero + if your device does not use numbered reports. + @param length The number of bytes to read, including an + extra byte for the report ID. The buffer can be longer + than the actual report. + + @returns + This function returns the number of bytes read plus + one for the report ID (which is still in the first + byte), or -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); + + /** @brief Close a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + */ + void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); + + /** @brief Get The Manufacturer String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get The Product String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get The Serial Number String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get a string from a HID device, based on its string index. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string_index The index of the string to get. + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); + + /** @brief Get a string describing the last error which occurred. + + @ingroup API + @param device A device handle returned from hid_open(). + + @returns + This function returns a string containing the last error + which occurred or NULL if none has occurred. + */ + HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/winbuild/hidapi.h b/winbuild/hidapi.h deleted file mode 100644 index 43b8e7a..0000000 --- a/winbuild/hidapi.h +++ /dev/null @@ -1,405 +0,0 @@ -/******************************************************* - HIDAPI - Multi-Platform library for - communication with HID devices. - - Alan Ott - Signal 11 Software - - 8/22/2009 - - Copyright 2009, All Rights Reserved. - - At the discretion of the user of this library, - this software may be licensed under the terms of the - GNU General Public License v3, a BSD-Style license, or the - original HIDAPI license as outlined in the LICENSE.txt, - LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt - files located at the root of the source distribution. - These files may also be found in the public source - code repository located at: - http://github.com/signal11/hidapi . -********************************************************/ - -/* Copy of LICENSE-orig.txt (compatible with MIT/x11 license) - - HIDAPI - Multi-Platform library for - communication with HID devices. - - Copyright 2009, Alan Ott, Signal 11 Software. - All Rights Reserved. - - This software may be used by anyone for any reason so - long as the copyright notice in the source files - remains intact. -*/ - - -/** @file - * @defgroup API hidapi API - */ - -#ifndef HIDAPI_H__ -#define HIDAPI_H__ - -#include - -#ifdef _WIN32 - #define HID_API_EXPORT __declspec(dllexport) - #define HID_API_CALL -#else - #define HID_API_EXPORT /**< API export macro */ - #define HID_API_CALL /**< API call macro */ -#endif - -#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ - -#ifdef __cplusplus -extern "C" { -#endif - struct hid_device_; - typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ - - /** hidapi info structure */ - struct hid_device_info { - /** Platform-specific device path */ - char *path; - /** Device Vendor ID */ - unsigned short vendor_id; - /** Device Product ID */ - unsigned short product_id; - /** Serial Number */ - wchar_t *serial_number; - /** Device Release Number in binary-coded decimal, - also known as Device Version Number */ - unsigned short release_number; - /** Manufacturer String */ - wchar_t *manufacturer_string; - /** Product string */ - wchar_t *product_string; - /** Usage Page for this Device/Interface - (Windows/Mac only). */ - unsigned short usage_page; - /** Usage for this Device/Interface - (Windows/Mac only).*/ - unsigned short usage; - /** The USB interface which this logical device - represents. Valid on both Linux implementations - in all cases, and valid on the Windows implementation - only if the device contains more than one interface. */ - int interface_number; - - /** Pointer to the next device */ - struct hid_device_info *next; - }; - - - /** @brief Initialize the HIDAPI library. - - This function initializes the HIDAPI library. Calling it is not - strictly necessary, as it will be called automatically by - hid_enumerate() and any of the hid_open_*() functions if it is - needed. This function should be called at the beginning of - execution however, if there is a chance of HIDAPI handles - being opened by different threads simultaneously. - - @ingroup API - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_init(void); - - /** @brief Finalize the HIDAPI library. - - This function frees all of the static data associated with - HIDAPI. It should be called at the end of execution to avoid - memory leaks. - - @ingroup API - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_exit(void); - - /** @brief Enumerate the HID Devices. - - This function returns a linked list of all the HID devices - attached to the system which match vendor_id and product_id. - If @p vendor_id is set to 0 then any vendor matches. - If @p product_id is set to 0 then any product matches. - If @p vendor_id and @p product_id are both set to 0, then - all HID devices will be returned. - - @ingroup API - @param vendor_id The Vendor ID (VID) of the types of device - to open. - @param product_id The Product ID (PID) of the types of - device to open. - - @returns - This function returns a pointer to a linked list of type - struct #hid_device, containing information about the HID devices - attached to the system, or NULL in the case of failure. Free - this linked list by calling hid_free_enumeration(). - */ - struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); - - /** @brief Free an enumeration Linked List - - This function frees a linked list created by hid_enumerate(). - - @ingroup API - @param devs Pointer to a list of struct_device returned from - hid_enumerate(). - */ - void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); - - /** @brief Open a HID device using a Vendor ID (VID), Product ID - (PID) and optionally a serial number. - - If @p serial_number is NULL, the first device with the - specified VID and PID is opened. - - @ingroup API - @param vendor_id The Vendor ID (VID) of the device to open. - @param product_id The Product ID (PID) of the device to open. - @param serial_number The Serial Number of the device to open - (Optionally NULL). - - @returns - This function returns a pointer to a #hid_device object on - success or NULL on failure. - */ - HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); - - /** @brief Open a HID device by its path name. - - The path name be determined by calling hid_enumerate(), or a - platform-specific path name can be used (eg: /dev/hidraw0 on - Linux). - - @ingroup API - @param path The path name of the device to open - - @returns - This function returns a pointer to a #hid_device object on - success or NULL on failure. - */ - HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); - - /** @brief Write an Output report to a HID device. - - The first byte of @p data[] must contain the Report ID. For - devices which only support a single report, this must be set - to 0x0. The remaining bytes contain the report data. Since - the Report ID is mandatory, calls to hid_write() will always - contain one more byte than the report contains. For example, - if a hid report is 16 bytes long, 17 bytes must be passed to - hid_write(), the Report ID (or 0x0, for devices with a - single report), followed by the report data (16 bytes). In - this example, the length passed in would be 17. - - hid_write() will send the data on the first OUT endpoint, if - one exists. If it does not, it will send the data through - the Control Endpoint (Endpoint 0). - - @ingroup API - @param device A device handle returned from hid_open(). - @param data The data to send, including the report number as - the first byte. - @param length The length in bytes of the data to send. - - @returns - This function returns the actual number of bytes written and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); - - /** @brief Read an Input report from a HID device with timeout. - - Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will - contain the Report number if the device uses numbered reports. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into. - @param length The number of bytes to read. For devices with - multiple reports, make sure to read an extra byte for - the report number. - @param milliseconds timeout in milliseconds or -1 for blocking wait. - - @returns - This function returns the actual number of bytes read and - -1 on error. If no packet was available to be read within - the timeout period, this function returns 0. - */ - int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); - - /** @brief Read an Input report from a HID device. - - Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will - contain the Report number if the device uses numbered reports. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into. - @param length The number of bytes to read. For devices with - multiple reports, make sure to read an extra byte for - the report number. - - @returns - This function returns the actual number of bytes read and - -1 on error. If no packet was available to be read and - the handle is in non-blocking mode, this function returns 0. - */ - int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); - - /** @brief Set the device handle to be non-blocking. - - In non-blocking mode calls to hid_read() will return - immediately with a value of 0 if there is no data to be - read. In blocking mode, hid_read() will wait (block) until - there is data to read before returning. - - Nonblocking can be turned on and off at any time. - - @ingroup API - @param device A device handle returned from hid_open(). - @param nonblock enable or not the nonblocking reads - - 1 to enable nonblocking - - 0 to disable nonblocking. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); - - /** @brief Send a Feature report to the device. - - Feature reports are sent over the Control endpoint as a - Set_Report transfer. The first byte of @p data[] must - contain the Report ID. For devices which only support a - single report, this must be set to 0x0. The remaining bytes - contain the report data. Since the Report ID is mandatory, - calls to hid_send_feature_report() will always contain one - more byte than the report contains. For example, if a hid - report is 16 bytes long, 17 bytes must be passed to - hid_send_feature_report(): the Report ID (or 0x0, for - devices which do not use numbered reports), followed by the - report data (16 bytes). In this example, the length passed - in would be 17. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data The data to send, including the report number as - the first byte. - @param length The length in bytes of the data to send, including - the report number. - - @returns - This function returns the actual number of bytes written and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); - - /** @brief Get a feature report from a HID device. - - Set the first byte of @p data[] to the Report ID of the - report to be read. Make sure to allow space for this - extra byte in @p data[]. Upon return, the first byte will - still contain the Report ID, and the report data will - start in data[1]. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into, including - the Report ID. Set the first byte of @p data[] to the - Report ID of the report to be read, or set it to zero - if your device does not use numbered reports. - @param length The number of bytes to read, including an - extra byte for the report ID. The buffer can be longer - than the actual report. - - @returns - This function returns the number of bytes read plus - one for the report ID (which is still in the first - byte), or -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); - - /** @brief Close a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - */ - void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); - - /** @brief Get The Manufacturer String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get The Product String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get The Serial Number String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get a string from a HID device, based on its string index. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string_index The index of the string to get. - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); - - /** @brief Get a string describing the last error which occurred. - - @ingroup API - @param device A device handle returned from hid_open(). - - @returns - This function returns a string containing the last error - which occurred or NULL if none has occurred. - */ - HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); - -#ifdef __cplusplus -} -#endif - -#endif - -- cgit v1.2.3 From 964e147104c902bd2feda4717dd6c852d7514231 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 02:02:30 -0400 Subject: Move the HID file over to the right place. --- redist/hid-windows.c | 996 +++++++++++++++++++++++++ redist/json_helpers.c | 2 +- winbuild/build_tcc.bat | 2 +- winbuild/hid.c | 996 ------------------------- winbuild/libsurvive/libsurvive.vcxproj | 2 +- winbuild/libsurvive/libsurvive.vcxproj.filters | 2 +- 6 files changed, 1000 insertions(+), 1000 deletions(-) create mode 100644 redist/hid-windows.c delete mode 100644 winbuild/hid.c diff --git a/redist/hid-windows.c b/redist/hid-windows.c new file mode 100644 index 0000000..6c379b5 --- /dev/null +++ b/redist/hid-windows.c @@ -0,0 +1,996 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + + +/* Copy of LICENSE-orig.txt (compatible with MIT/x11 license) + + HIDAPI - Multi-Platform library for + communication with HID devices. + + Copyright 2009, Alan Ott, Signal 11 Software. + All Rights Reserved. + + This software may be used by anyone for any reason so + long as the copyright notice in the source files + remains intact. +*/ + +#include + +#ifndef _NTDEF_ +typedef LONG NTSTATUS; +#endif + +#ifdef __MINGW32__ +#include +#include +#endif + +#ifdef __CYGWIN__ +#include +#define _wcsdup wcsdup +#endif + +/* The maximum number of characters that can be passed into the + HidD_Get*String() functions without it failing.*/ +#define MAX_STRING_WCHARS 0xFFF + +/*#define HIDAPI_USE_DDK*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef TCC + typedef struct _SP_DEVINFO_DATA { + DWORD cbSize; + GUID ClassGuid; + DWORD DevInst; + ULONG_PTR Reserved; + } SP_DEVINFO_DATA, *PSP_DEVINFO_DATA; + typedef struct _SP_DEVICE_INTERFACE_DATA { + DWORD cbSize; + GUID InterfaceClassGuid; + DWORD Flags; + ULONG_PTR Reserved; + } SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA; + typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA { + DWORD cbSize; + CHAR DevicePath[ANYSIZE_ARRAY]; + } SP_DEVICE_INTERFACE_DETAIL_DATA_A, *PSP_DEVICE_INTERFACE_DETAIL_DATA_A; + typedef PVOID HDEVINFO; + + HDEVINFO WINAPI SetupDiGetClassDevsA(CONST GUID*,PCSTR,HWND,DWORD); + + #define DIGCF_PRESENT 0x00000002 + #define DIGCF_DEVICEINTERFACE 0x00000010 + #define SPDRP_CLASS 7 + #define SPDRP_DRIVER 9 + #define FILE_DEVICE_KEYBOARD 0x0000000b + #define METHOD_OUT_DIRECT 2 + enum + { FILE_ANY_ACCESS = 0x00000000UL, + FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS, + FILE_READ_ACCESS = 0x00000001UL, + FILE_WRITE_ACCESS = 0x00000002UL + }; + #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m)) + +#else + #include + #include +#endif + #ifdef HIDAPI_USE_DDK + #include + #endif + + /* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */ + #define HID_OUT_CTL_CODE(id) \ + CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include +#include + + +#include "hidapi.h" + +#undef MIN +#define MIN(x,y) ((x) < (y)? (x): (y)) + +#ifdef _MSC_VER + /* Thanks Microsoft, but I know how to use strncpy(). */ + #pragma warning(disable:4996) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HIDAPI_USE_DDK + /* Since we're not building with the DDK, and the HID header + files aren't part of the SDK, we have to define all this + stuff here. In lookup_functions(), the function pointers + defined below are set. */ + typedef struct _HIDD_ATTRIBUTES{ + ULONG Size; + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; + } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; + + typedef USHORT USAGE; + typedef struct _HIDP_CAPS { + USAGE Usage; + USAGE UsagePage; + USHORT InputReportByteLength; + USHORT OutputReportByteLength; + USHORT FeatureReportByteLength; + USHORT Reserved[17]; + USHORT fields_not_used_by_hidapi[10]; + } HIDP_CAPS, *PHIDP_CAPS; + typedef void* PHIDP_PREPARSED_DATA; + #define HIDP_STATUS_SUCCESS 0x110000 + + typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib); + typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); + typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data); + typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps); + typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers); + + static HidD_GetAttributes_ HidD_GetAttributes; + static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; + static HidD_GetManufacturerString_ HidD_GetManufacturerString; + static HidD_GetProductString_ HidD_GetProductString; + static HidD_SetFeature_ HidD_SetFeature; + static HidD_GetFeature_ HidD_GetFeature; + static HidD_GetIndexedString_ HidD_GetIndexedString; + static HidD_GetPreparsedData_ HidD_GetPreparsedData; + static HidD_FreePreparsedData_ HidD_FreePreparsedData; + static HidP_GetCaps_ HidP_GetCaps; + static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers; + + static HMODULE lib_handle = NULL; + static BOOLEAN initialized = FALSE; +#endif /* HIDAPI_USE_DDK */ + +struct hid_device_ { + HANDLE device_handle; + BOOL blocking; + USHORT output_report_length; + size_t input_report_length; + void *last_error_str; + DWORD last_error_num; + BOOL read_pending; + char *read_buf; + OVERLAPPED ol; +}; + +static hid_device *new_hid_device() +{ + hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); + dev->device_handle = INVALID_HANDLE_VALUE; + dev->blocking = TRUE; + dev->output_report_length = 0; + dev->input_report_length = 0; + dev->last_error_str = NULL; + dev->last_error_num = 0; + dev->read_pending = FALSE; + dev->read_buf = NULL; + memset(&dev->ol, 0, sizeof(dev->ol)); + dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + CloseHandle(dev->ol.hEvent); + CloseHandle(dev->device_handle); + LocalFree(dev->last_error_str); + free(dev->read_buf); + free(dev); +} + +static void register_error(hid_device *device, const char *op) +{ + WCHAR *ptr, *msg; + + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPVOID)&msg, 0/*sz*/, + NULL); + + /* Get rid of the CR and LF that FormatMessage() sticks at the + end of the message. Thanks Microsoft! */ + ptr = msg; + while (*ptr) { + if (*ptr == '\r') { + *ptr = 0x0000; + break; + } + ptr++; + } + + /* Store the message off in the Device entry so that + the hid_error() function can pick it up. */ + LocalFree(device->last_error_str); + device->last_error_str = msg; +} + +#ifndef HIDAPI_USE_DDK +static int lookup_functions() +{ + lib_handle = LoadLibraryA("hid.dll"); + if (lib_handle) { +#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1; + RESOLVE(HidD_GetAttributes); + RESOLVE(HidD_GetSerialNumberString); + RESOLVE(HidD_GetManufacturerString); + RESOLVE(HidD_GetProductString); + RESOLVE(HidD_SetFeature); + RESOLVE(HidD_GetFeature); + RESOLVE(HidD_GetIndexedString); + RESOLVE(HidD_GetPreparsedData); + RESOLVE(HidD_FreePreparsedData); + RESOLVE(HidP_GetCaps); + RESOLVE(HidD_SetNumInputBuffers); +#undef RESOLVE + } + else + return -1; + + return 0; +} +#endif + +static HANDLE open_device(const char *path, BOOL enumerate) +{ + HANDLE handle; + DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ); + DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; + + handle = CreateFileA(path, + desired_access, + share_mode, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/ + 0); + + return handle; +} + +int HID_API_EXPORT hid_init(void) +{ +#ifndef HIDAPI_USE_DDK + if (!initialized) { + if (lookup_functions() < 0) { + hid_exit(); + return -1; + } + initialized = TRUE; + } +#endif + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ +#ifndef HIDAPI_USE_DDK + if (lib_handle) + FreeLibrary(lib_handle); + lib_handle = NULL; + initialized = FALSE; +#endif + return 0; +} + +struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + BOOL res; + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + + /* Windows objects for interacting with the driver. */ + GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; + SP_DEVINFO_DATA devinfo_data; + SP_DEVICE_INTERFACE_DATA device_interface_data; + SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; + HDEVINFO device_info_set = INVALID_HANDLE_VALUE; + int device_index = 0; + int i; + + if (hid_init() < 0) + return NULL; + + /* Initialize the Windows objects. */ + memset(&devinfo_data, 0x0, sizeof(devinfo_data)); + devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); + device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + /* Get information for all the devices belonging to the HID class. */ + device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + + /* Iterate over each device in the HID class, looking for the right one. */ + + for (;;) { + HANDLE write_handle = INVALID_HANDLE_VALUE; + DWORD required_size = 0; + HIDD_ATTRIBUTES attrib; + + res = SetupDiEnumDeviceInterfaces(device_info_set, + NULL, + &InterfaceClassGuid, + device_index, + &device_interface_data); + + if (!res) { + /* A return of FALSE from this function means that + there are no more devices. */ + break; + } + + /* Call with 0-sized detail size, and let the function + tell us how long the detail struct needs to be. The + size is put in &required_size. */ + res = SetupDiGetDeviceInterfaceDetailA(device_info_set, + &device_interface_data, + NULL, + 0, + &required_size, + NULL); + + /* Allocate a long enough structure for device_interface_detail_data. */ + device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); + device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + + /* Get the detailed data for this device. The detail data gives us + the device path for this device, which is then passed into + CreateFile() to get a handle to the device. */ + res = SetupDiGetDeviceInterfaceDetailA(device_info_set, + &device_interface_data, + device_interface_detail_data, + required_size, + NULL, + NULL); + + if (!res) { + /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); + Continue to the next device. */ + goto cont; + } + + /* Make sure this device is of Setup Class "HIDClass" and has a + driver bound to it. */ + for (i = 0; ; i++) { + char driver_name[256]; + + /* Populate devinfo_data. This function will return failure + when there are no more interfaces left. */ + res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); + if (!res) + goto cont; + + res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, + SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); + if (!res) + goto cont; + + if (strcmp(driver_name, "HIDClass") == 0) { + /* See if there's a driver bound. */ + res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, + SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); + if (res) + break; + } + } + + //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); + + /* Open a handle to the device */ + write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); + + /* Check validity of write_handle. */ + if (write_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + //register_error(dev, "CreateFile"); + goto cont_close; + } + + + /* Get the Vendor ID and Product ID for this device. */ + attrib.Size = sizeof(HIDD_ATTRIBUTES); + HidD_GetAttributes(write_handle, &attrib); + //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); + + /* Check the VID/PID to see if we should add this + device to the enumeration list. */ + if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && + (product_id == 0x0 || attrib.ProductID == product_id)) { + + #define WSTR_LEN 512 + const char *str; + struct hid_device_info *tmp; + PHIDP_PREPARSED_DATA pp_data = NULL; + HIDP_CAPS caps; + BOOLEAN res; + NTSTATUS nt_res; + wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ + size_t len; + + /* VID/PID match. Create the record. */ + tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Get the Usage Page and Usage for this device. */ + res = HidD_GetPreparsedData(write_handle, &pp_data); + if (res) { + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res == HIDP_STATUS_SUCCESS) { + cur_dev->usage_page = caps.UsagePage; + cur_dev->usage = caps.Usage; + } + + HidD_FreePreparsedData(pp_data); + } + + /* Fill out the record */ + cur_dev->next = NULL; + str = device_interface_detail_data->DevicePath; + if (str) { + len = strlen(str); + cur_dev->path = (char*) calloc(len+1, sizeof(char)); + strncpy(cur_dev->path, str, len+1); + cur_dev->path[len] = '\0'; + } + else + cur_dev->path = NULL; + + /* Serial Number */ + res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->serial_number = _wcsdup(wstr); + } + + /* Manufacturer String */ + res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->manufacturer_string = _wcsdup(wstr); + } + + /* Product String */ + res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->product_string = _wcsdup(wstr); + } + + /* VID/PID */ + cur_dev->vendor_id = attrib.VendorID; + cur_dev->product_id = attrib.ProductID; + + /* Release Number */ + cur_dev->release_number = attrib.VersionNumber; + + /* Interface Number. It can sometimes be parsed out of the path + on Windows if a device has multiple interfaces. See + http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or + search for "Hardware IDs for HID Devices" at MSDN. If it's not + in the path, it's set to -1. */ + cur_dev->interface_number = -1; + if (cur_dev->path) { + char *interface_component = strstr(cur_dev->path, "&mi_"); + if (interface_component) { + char *hex_str = interface_component + 4; + char *endptr = NULL; + cur_dev->interface_number = strtol(hex_str, &endptr, 16); + if (endptr == hex_str) { + /* The parsing failed. Set interface_number to -1. */ + cur_dev->interface_number = -1; + } + } + } + } + +cont_close: + CloseHandle(write_handle); +cont: + /* We no longer need the detail data. It can be freed */ + free(device_interface_detail_data); + + device_index++; + + } + + /* Close the device information handle. */ + SetupDiDestroyDeviceInfoList(device_info_set); + + return root; + +} + +void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) +{ + /* TODO: Merge this with the Linux version. This function is platform-independent. */ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + + +HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + /* TODO: Merge this functions with the Linux version. This function should be platform independent. */ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device *handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) +{ + hid_device *dev; + HIDP_CAPS caps; + PHIDP_PREPARSED_DATA pp_data = NULL; + BOOLEAN res; + NTSTATUS nt_res; + + if (hid_init() < 0) { + return NULL; + } + + dev = new_hid_device(); + + /* Open a handle to the device */ + dev->device_handle = open_device(path, FALSE); + + /* Check validity of write_handle. */ + if (dev->device_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + register_error(dev, "CreateFile"); + goto err; + } + + /* Set the Input Report buffer size to 64 reports. */ + res = HidD_SetNumInputBuffers(dev->device_handle, 64); + if (!res) { + register_error(dev, "HidD_SetNumInputBuffers"); + goto err; + } + + /* Get the Input Report length for the device. */ + res = HidD_GetPreparsedData(dev->device_handle, &pp_data); + if (!res) { + register_error(dev, "HidD_GetPreparsedData"); + goto err; + } + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res != HIDP_STATUS_SUCCESS) { + register_error(dev, "HidP_GetCaps"); + goto err_pp_data; + } + dev->output_report_length = caps.OutputReportByteLength; + dev->input_report_length = caps.InputReportByteLength; + HidD_FreePreparsedData(pp_data); + + dev->read_buf = (char*) malloc(dev->input_report_length); + + return dev; + +err_pp_data: + HidD_FreePreparsedData(pp_data); +err: + free_hid_device(dev); + return NULL; +} + +int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + DWORD bytes_written; + BOOL res; + + OVERLAPPED ol; + unsigned char *buf; + memset(&ol, 0, sizeof(ol)); + + /* Make sure the right number of bytes are passed to WriteFile. Windows + expects the number of bytes which are in the _longest_ report (plus + one for the report number) bytes even if the data is a report + which is shorter than that. Windows gives us this value in + caps.OutputReportByteLength. If a user passes in fewer bytes than this, + create a temporary buffer which is the proper size. */ + if (length >= dev->output_report_length) { + /* The user passed the right number of bytes. Use the buffer as-is. */ + buf = (unsigned char *) data; + } else { + /* Create a temporary buffer and copy the user's data + into it, padding the rest with zeros. */ + buf = (unsigned char *) malloc(dev->output_report_length); + memcpy(buf, data, length); + memset(buf + length, 0, dev->output_report_length - length); + length = dev->output_report_length; + } + + res = WriteFile(dev->device_handle, buf, (DWORD)length, NULL, &ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* WriteFile() failed. Return error. */ + register_error(dev, "WriteFile"); + bytes_written = -1; + goto end_of_function; + } + } + + /* Wait here until the write is done. This makes + hid_write() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/); + if (!res) { + /* The Write operation failed. */ + register_error(dev, "WriteFile"); + bytes_written = -1; + goto end_of_function; + } + +end_of_function: + if (buf != data) + free(buf); + + return bytes_written; +} + + +int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + DWORD bytes_read = 0; + size_t copy_len = 0; + BOOL res; + + /* Copy the handle for convenience. */ + HANDLE ev = dev->ol.hEvent; + + if (!dev->read_pending) { + /* Start an Overlapped I/O read. */ + dev->read_pending = TRUE; + memset(dev->read_buf, 0, dev->input_report_length); + ResetEvent(ev); + res = ReadFile(dev->device_handle, dev->read_buf, (DWORD)dev->input_report_length, &bytes_read, &dev->ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* ReadFile() has failed. + Clean up and return error. */ + CancelIo(dev->device_handle); + dev->read_pending = FALSE; + goto end_of_function; + } + } + } + + if (milliseconds >= 0) { + /* See if there is any data yet. */ + res = WaitForSingleObject(ev, milliseconds); + if (res != WAIT_OBJECT_0) { + /* There was no data this time. Return zero bytes available, + but leave the Overlapped I/O running. */ + return 0; + } + } + + /* Either WaitForSingleObject() told us that ReadFile has completed, or + we are in non-blocking mode. Get the number of bytes read. The actual + data has been copied to the data[] array which was passed to ReadFile(). */ + res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); + + /* Set pending back to false, even if GetOverlappedResult() returned error. */ + dev->read_pending = FALSE; + + if (res && bytes_read > 0) { + if (dev->read_buf[0] == 0x0) { + /* If report numbers aren't being used, but Windows sticks a report + number (0x0) on the beginning of the report anyway. To make this + work like the other platforms, and to make it work more like the + HID spec, we'll skip over this byte. */ + bytes_read--; + copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf+1, copy_len); + } + else { + /* Copy the whole buffer, report number and all. */ + copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf, copy_len); + } + } + +end_of_function: + if (!res) { + register_error(dev, "GetOverlappedResult"); + return -1; + } + + return (int)copy_len; +} + +int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) +{ + dev->blocking = !nonblock; + return 0; /* Success */ +} + +int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, (ULONG)length); + if (!res) { + register_error(dev, "HidD_SetFeature"); + return -1; + } + + return (int)length; +} + + +int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + BOOL res; +#if 0 + res = HidD_GetFeature(dev->device_handle, data, length); + if (!res) { + register_error(dev, "HidD_GetFeature"); + return -1; + } + return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */ +#else + DWORD bytes_returned; + + OVERLAPPED ol; + memset(&ol, 0, sizeof(ol)); + + res = DeviceIoControl(dev->device_handle, + IOCTL_HID_GET_FEATURE, + data, (DWORD)length, + data, (DWORD)length, + &bytes_returned, &ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* DeviceIoControl() failed. Return error. */ + register_error(dev, "Send Feature Report DeviceIoControl"); + return -1; + } + } + + /* Wait here until the write is done. This makes + hid_get_feature_report() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/); + if (!res) { + /* The operation failed. */ + register_error(dev, "Send Feature Report GetOverLappedResult"); + return -1; + } + + /* bytes_returned does not include the first byte which contains the + report ID. The data buffer actually contains one more byte than + bytes_returned. */ + bytes_returned++; + + return bytes_returned; +#endif +} + +void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) +{ + if (!dev) + return; + CancelIo(dev->device_handle); + free_hid_device(dev); +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetManufacturerString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetManufacturerString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetProductString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetProductString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetSerialNumberString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetSerialNumberString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetIndexedString(dev->device_handle, string_index, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetIndexedString"); + return -1; + } + + return 0; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + return (wchar_t*)dev->last_error_str; +} + + +/*#define PICPGM*/ +/*#define S11*/ +#define P32 +#ifdef S11 + unsigned short VendorID = 0xa0a0; + unsigned short ProductID = 0x0001; +#endif + +#ifdef P32 + unsigned short VendorID = 0x04d8; + unsigned short ProductID = 0x3f; +#endif + + +#ifdef PICPGM + unsigned short VendorID = 0x04d8; + unsigned short ProductID = 0x0033; +#endif + + +#if 0 +int __cdecl main(int argc, char* argv[]) +{ + int res; + unsigned char buf[65]; + + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + /* Set up the command buffer. */ + memset(buf,0x00,sizeof(buf)); + buf[0] = 0; + buf[1] = 0x81; + + + /* Open the device. */ + int handle = open(VendorID, ProductID, L"12345"); + if (handle < 0) + printf("unable to open device\n"); + + + /* Toggle LED (cmd 0x80) */ + buf[1] = 0x80; + res = write(handle, buf, 65); + if (res < 0) + printf("Unable to write()\n"); + + /* Request state (cmd 0x81) */ + buf[1] = 0x81; + write(handle, buf, 65); + if (res < 0) + printf("Unable to write() (2)\n"); + + /* Read requested state */ + read(handle, buf, 65); + if (res < 0) + printf("Unable to read()\n"); + + /* Print out the returned buffer. */ + for (int i = 0; i < 4; i++) + printf("buf[%d]: %d\n", i, buf[i]); + + return 0; +} +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/redist/json_helpers.c b/redist/json_helpers.c index eb3600b..0267932 100644 --- a/redist/json_helpers.c +++ b/redist/json_helpers.c @@ -173,7 +173,7 @@ void json_load_file(const char* path) { int16_t children = -1; - for (i=0; i - -#ifndef _NTDEF_ -typedef LONG NTSTATUS; -#endif - -#ifdef __MINGW32__ -#include -#include -#endif - -#ifdef __CYGWIN__ -#include -#define _wcsdup wcsdup -#endif - -/* The maximum number of characters that can be passed into the - HidD_Get*String() functions without it failing.*/ -#define MAX_STRING_WCHARS 0xFFF - -/*#define HIDAPI_USE_DDK*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef TCC - typedef struct _SP_DEVINFO_DATA { - DWORD cbSize; - GUID ClassGuid; - DWORD DevInst; - ULONG_PTR Reserved; - } SP_DEVINFO_DATA, *PSP_DEVINFO_DATA; - typedef struct _SP_DEVICE_INTERFACE_DATA { - DWORD cbSize; - GUID InterfaceClassGuid; - DWORD Flags; - ULONG_PTR Reserved; - } SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA; - typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA { - DWORD cbSize; - CHAR DevicePath[ANYSIZE_ARRAY]; - } SP_DEVICE_INTERFACE_DETAIL_DATA_A, *PSP_DEVICE_INTERFACE_DETAIL_DATA_A; - typedef PVOID HDEVINFO; - - HDEVINFO WINAPI SetupDiGetClassDevsA(CONST GUID*,PCSTR,HWND,DWORD); - - #define DIGCF_PRESENT 0x00000002 - #define DIGCF_DEVICEINTERFACE 0x00000010 - #define SPDRP_CLASS 7 - #define SPDRP_DRIVER 9 - #define FILE_DEVICE_KEYBOARD 0x0000000b - #define METHOD_OUT_DIRECT 2 - enum - { FILE_ANY_ACCESS = 0x00000000UL, - FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS, - FILE_READ_ACCESS = 0x00000001UL, - FILE_WRITE_ACCESS = 0x00000002UL - }; - #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m)) - -#else - #include - #include -#endif - #ifdef HIDAPI_USE_DDK - #include - #endif - - /* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */ - #define HID_OUT_CTL_CODE(id) \ - CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) - #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#include -#include - - -#include "hidapi.h" - -#undef MIN -#define MIN(x,y) ((x) < (y)? (x): (y)) - -#ifdef _MSC_VER - /* Thanks Microsoft, but I know how to use strncpy(). */ - #pragma warning(disable:4996) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef HIDAPI_USE_DDK - /* Since we're not building with the DDK, and the HID header - files aren't part of the SDK, we have to define all this - stuff here. In lookup_functions(), the function pointers - defined below are set. */ - typedef struct _HIDD_ATTRIBUTES{ - ULONG Size; - USHORT VendorID; - USHORT ProductID; - USHORT VersionNumber; - } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; - - typedef USHORT USAGE; - typedef struct _HIDP_CAPS { - USAGE Usage; - USAGE UsagePage; - USHORT InputReportByteLength; - USHORT OutputReportByteLength; - USHORT FeatureReportByteLength; - USHORT Reserved[17]; - USHORT fields_not_used_by_hidapi[10]; - } HIDP_CAPS, *PHIDP_CAPS; - typedef void* PHIDP_PREPARSED_DATA; - #define HIDP_STATUS_SUCCESS 0x110000 - - typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib); - typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); - typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); - typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); - typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data); - typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps); - typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers); - - static HidD_GetAttributes_ HidD_GetAttributes; - static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; - static HidD_GetManufacturerString_ HidD_GetManufacturerString; - static HidD_GetProductString_ HidD_GetProductString; - static HidD_SetFeature_ HidD_SetFeature; - static HidD_GetFeature_ HidD_GetFeature; - static HidD_GetIndexedString_ HidD_GetIndexedString; - static HidD_GetPreparsedData_ HidD_GetPreparsedData; - static HidD_FreePreparsedData_ HidD_FreePreparsedData; - static HidP_GetCaps_ HidP_GetCaps; - static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers; - - static HMODULE lib_handle = NULL; - static BOOLEAN initialized = FALSE; -#endif /* HIDAPI_USE_DDK */ - -struct hid_device_ { - HANDLE device_handle; - BOOL blocking; - USHORT output_report_length; - size_t input_report_length; - void *last_error_str; - DWORD last_error_num; - BOOL read_pending; - char *read_buf; - OVERLAPPED ol; -}; - -static hid_device *new_hid_device() -{ - hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); - dev->device_handle = INVALID_HANDLE_VALUE; - dev->blocking = TRUE; - dev->output_report_length = 0; - dev->input_report_length = 0; - dev->last_error_str = NULL; - dev->last_error_num = 0; - dev->read_pending = FALSE; - dev->read_buf = NULL; - memset(&dev->ol, 0, sizeof(dev->ol)); - dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL); - - return dev; -} - -static void free_hid_device(hid_device *dev) -{ - CloseHandle(dev->ol.hEvent); - CloseHandle(dev->device_handle); - LocalFree(dev->last_error_str); - free(dev->read_buf); - free(dev); -} - -static void register_error(hid_device *device, const char *op) -{ - WCHAR *ptr, *msg; - - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPVOID)&msg, 0/*sz*/, - NULL); - - /* Get rid of the CR and LF that FormatMessage() sticks at the - end of the message. Thanks Microsoft! */ - ptr = msg; - while (*ptr) { - if (*ptr == '\r') { - *ptr = 0x0000; - break; - } - ptr++; - } - - /* Store the message off in the Device entry so that - the hid_error() function can pick it up. */ - LocalFree(device->last_error_str); - device->last_error_str = msg; -} - -#ifndef HIDAPI_USE_DDK -static int lookup_functions() -{ - lib_handle = LoadLibraryA("hid.dll"); - if (lib_handle) { -#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1; - RESOLVE(HidD_GetAttributes); - RESOLVE(HidD_GetSerialNumberString); - RESOLVE(HidD_GetManufacturerString); - RESOLVE(HidD_GetProductString); - RESOLVE(HidD_SetFeature); - RESOLVE(HidD_GetFeature); - RESOLVE(HidD_GetIndexedString); - RESOLVE(HidD_GetPreparsedData); - RESOLVE(HidD_FreePreparsedData); - RESOLVE(HidP_GetCaps); - RESOLVE(HidD_SetNumInputBuffers); -#undef RESOLVE - } - else - return -1; - - return 0; -} -#endif - -static HANDLE open_device(const char *path, BOOL enumerate) -{ - HANDLE handle; - DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ); - DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; - - handle = CreateFileA(path, - desired_access, - share_mode, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/ - 0); - - return handle; -} - -int HID_API_EXPORT hid_init(void) -{ -#ifndef HIDAPI_USE_DDK - if (!initialized) { - if (lookup_functions() < 0) { - hid_exit(); - return -1; - } - initialized = TRUE; - } -#endif - return 0; -} - -int HID_API_EXPORT hid_exit(void) -{ -#ifndef HIDAPI_USE_DDK - if (lib_handle) - FreeLibrary(lib_handle); - lib_handle = NULL; - initialized = FALSE; -#endif - return 0; -} - -struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) -{ - BOOL res; - struct hid_device_info *root = NULL; /* return object */ - struct hid_device_info *cur_dev = NULL; - - /* Windows objects for interacting with the driver. */ - GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; - SP_DEVINFO_DATA devinfo_data; - SP_DEVICE_INTERFACE_DATA device_interface_data; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; - HDEVINFO device_info_set = INVALID_HANDLE_VALUE; - int device_index = 0; - int i; - - if (hid_init() < 0) - return NULL; - - /* Initialize the Windows objects. */ - memset(&devinfo_data, 0x0, sizeof(devinfo_data)); - devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); - device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - - /* Get information for all the devices belonging to the HID class. */ - device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - - /* Iterate over each device in the HID class, looking for the right one. */ - - for (;;) { - HANDLE write_handle = INVALID_HANDLE_VALUE; - DWORD required_size = 0; - HIDD_ATTRIBUTES attrib; - - res = SetupDiEnumDeviceInterfaces(device_info_set, - NULL, - &InterfaceClassGuid, - device_index, - &device_interface_data); - - if (!res) { - /* A return of FALSE from this function means that - there are no more devices. */ - break; - } - - /* Call with 0-sized detail size, and let the function - tell us how long the detail struct needs to be. The - size is put in &required_size. */ - res = SetupDiGetDeviceInterfaceDetailA(device_info_set, - &device_interface_data, - NULL, - 0, - &required_size, - NULL); - - /* Allocate a long enough structure for device_interface_detail_data. */ - device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); - device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - - /* Get the detailed data for this device. The detail data gives us - the device path for this device, which is then passed into - CreateFile() to get a handle to the device. */ - res = SetupDiGetDeviceInterfaceDetailA(device_info_set, - &device_interface_data, - device_interface_detail_data, - required_size, - NULL, - NULL); - - if (!res) { - /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); - Continue to the next device. */ - goto cont; - } - - /* Make sure this device is of Setup Class "HIDClass" and has a - driver bound to it. */ - for (i = 0; ; i++) { - char driver_name[256]; - - /* Populate devinfo_data. This function will return failure - when there are no more interfaces left. */ - res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); - if (!res) - goto cont; - - res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, - SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); - if (!res) - goto cont; - - if (strcmp(driver_name, "HIDClass") == 0) { - /* See if there's a driver bound. */ - res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, - SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); - if (res) - break; - } - } - - //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); - - /* Open a handle to the device */ - write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); - - /* Check validity of write_handle. */ - if (write_handle == INVALID_HANDLE_VALUE) { - /* Unable to open the device. */ - //register_error(dev, "CreateFile"); - goto cont_close; - } - - - /* Get the Vendor ID and Product ID for this device. */ - attrib.Size = sizeof(HIDD_ATTRIBUTES); - HidD_GetAttributes(write_handle, &attrib); - //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); - - /* Check the VID/PID to see if we should add this - device to the enumeration list. */ - if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && - (product_id == 0x0 || attrib.ProductID == product_id)) { - - #define WSTR_LEN 512 - const char *str; - struct hid_device_info *tmp; - PHIDP_PREPARSED_DATA pp_data = NULL; - HIDP_CAPS caps; - BOOLEAN res; - NTSTATUS nt_res; - wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ - size_t len; - - /* VID/PID match. Create the record. */ - tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); - if (cur_dev) { - cur_dev->next = tmp; - } - else { - root = tmp; - } - cur_dev = tmp; - - /* Get the Usage Page and Usage for this device. */ - res = HidD_GetPreparsedData(write_handle, &pp_data); - if (res) { - nt_res = HidP_GetCaps(pp_data, &caps); - if (nt_res == HIDP_STATUS_SUCCESS) { - cur_dev->usage_page = caps.UsagePage; - cur_dev->usage = caps.Usage; - } - - HidD_FreePreparsedData(pp_data); - } - - /* Fill out the record */ - cur_dev->next = NULL; - str = device_interface_detail_data->DevicePath; - if (str) { - len = strlen(str); - cur_dev->path = (char*) calloc(len+1, sizeof(char)); - strncpy(cur_dev->path, str, len+1); - cur_dev->path[len] = '\0'; - } - else - cur_dev->path = NULL; - - /* Serial Number */ - res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); - wstr[WSTR_LEN-1] = 0x0000; - if (res) { - cur_dev->serial_number = _wcsdup(wstr); - } - - /* Manufacturer String */ - res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); - wstr[WSTR_LEN-1] = 0x0000; - if (res) { - cur_dev->manufacturer_string = _wcsdup(wstr); - } - - /* Product String */ - res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); - wstr[WSTR_LEN-1] = 0x0000; - if (res) { - cur_dev->product_string = _wcsdup(wstr); - } - - /* VID/PID */ - cur_dev->vendor_id = attrib.VendorID; - cur_dev->product_id = attrib.ProductID; - - /* Release Number */ - cur_dev->release_number = attrib.VersionNumber; - - /* Interface Number. It can sometimes be parsed out of the path - on Windows if a device has multiple interfaces. See - http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or - search for "Hardware IDs for HID Devices" at MSDN. If it's not - in the path, it's set to -1. */ - cur_dev->interface_number = -1; - if (cur_dev->path) { - char *interface_component = strstr(cur_dev->path, "&mi_"); - if (interface_component) { - char *hex_str = interface_component + 4; - char *endptr = NULL; - cur_dev->interface_number = strtol(hex_str, &endptr, 16); - if (endptr == hex_str) { - /* The parsing failed. Set interface_number to -1. */ - cur_dev->interface_number = -1; - } - } - } - } - -cont_close: - CloseHandle(write_handle); -cont: - /* We no longer need the detail data. It can be freed */ - free(device_interface_detail_data); - - device_index++; - - } - - /* Close the device information handle. */ - SetupDiDestroyDeviceInfoList(device_info_set); - - return root; - -} - -void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) -{ - /* TODO: Merge this with the Linux version. This function is platform-independent. */ - struct hid_device_info *d = devs; - while (d) { - struct hid_device_info *next = d->next; - free(d->path); - free(d->serial_number); - free(d->manufacturer_string); - free(d->product_string); - free(d); - d = next; - } -} - - -HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) -{ - /* TODO: Merge this functions with the Linux version. This function should be platform independent. */ - struct hid_device_info *devs, *cur_dev; - const char *path_to_open = NULL; - hid_device *handle = NULL; - - devs = hid_enumerate(vendor_id, product_id); - cur_dev = devs; - while (cur_dev) { - if (cur_dev->vendor_id == vendor_id && - cur_dev->product_id == product_id) { - if (serial_number) { - if (wcscmp(serial_number, cur_dev->serial_number) == 0) { - path_to_open = cur_dev->path; - break; - } - } - else { - path_to_open = cur_dev->path; - break; - } - } - cur_dev = cur_dev->next; - } - - if (path_to_open) { - /* Open the device */ - handle = hid_open_path(path_to_open); - } - - hid_free_enumeration(devs); - - return handle; -} - -HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) -{ - hid_device *dev; - HIDP_CAPS caps; - PHIDP_PREPARSED_DATA pp_data = NULL; - BOOLEAN res; - NTSTATUS nt_res; - - if (hid_init() < 0) { - return NULL; - } - - dev = new_hid_device(); - - /* Open a handle to the device */ - dev->device_handle = open_device(path, FALSE); - - /* Check validity of write_handle. */ - if (dev->device_handle == INVALID_HANDLE_VALUE) { - /* Unable to open the device. */ - register_error(dev, "CreateFile"); - goto err; - } - - /* Set the Input Report buffer size to 64 reports. */ - res = HidD_SetNumInputBuffers(dev->device_handle, 64); - if (!res) { - register_error(dev, "HidD_SetNumInputBuffers"); - goto err; - } - - /* Get the Input Report length for the device. */ - res = HidD_GetPreparsedData(dev->device_handle, &pp_data); - if (!res) { - register_error(dev, "HidD_GetPreparsedData"); - goto err; - } - nt_res = HidP_GetCaps(pp_data, &caps); - if (nt_res != HIDP_STATUS_SUCCESS) { - register_error(dev, "HidP_GetCaps"); - goto err_pp_data; - } - dev->output_report_length = caps.OutputReportByteLength; - dev->input_report_length = caps.InputReportByteLength; - HidD_FreePreparsedData(pp_data); - - dev->read_buf = (char*) malloc(dev->input_report_length); - - return dev; - -err_pp_data: - HidD_FreePreparsedData(pp_data); -err: - free_hid_device(dev); - return NULL; -} - -int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length) -{ - DWORD bytes_written; - BOOL res; - - OVERLAPPED ol; - unsigned char *buf; - memset(&ol, 0, sizeof(ol)); - - /* Make sure the right number of bytes are passed to WriteFile. Windows - expects the number of bytes which are in the _longest_ report (plus - one for the report number) bytes even if the data is a report - which is shorter than that. Windows gives us this value in - caps.OutputReportByteLength. If a user passes in fewer bytes than this, - create a temporary buffer which is the proper size. */ - if (length >= dev->output_report_length) { - /* The user passed the right number of bytes. Use the buffer as-is. */ - buf = (unsigned char *) data; - } else { - /* Create a temporary buffer and copy the user's data - into it, padding the rest with zeros. */ - buf = (unsigned char *) malloc(dev->output_report_length); - memcpy(buf, data, length); - memset(buf + length, 0, dev->output_report_length - length); - length = dev->output_report_length; - } - - res = WriteFile(dev->device_handle, buf, (DWORD)length, NULL, &ol); - - if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { - /* WriteFile() failed. Return error. */ - register_error(dev, "WriteFile"); - bytes_written = -1; - goto end_of_function; - } - } - - /* Wait here until the write is done. This makes - hid_write() synchronous. */ - res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/); - if (!res) { - /* The Write operation failed. */ - register_error(dev, "WriteFile"); - bytes_written = -1; - goto end_of_function; - } - -end_of_function: - if (buf != data) - free(buf); - - return bytes_written; -} - - -int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) -{ - DWORD bytes_read = 0; - size_t copy_len = 0; - BOOL res; - - /* Copy the handle for convenience. */ - HANDLE ev = dev->ol.hEvent; - - if (!dev->read_pending) { - /* Start an Overlapped I/O read. */ - dev->read_pending = TRUE; - memset(dev->read_buf, 0, dev->input_report_length); - ResetEvent(ev); - res = ReadFile(dev->device_handle, dev->read_buf, (DWORD)dev->input_report_length, &bytes_read, &dev->ol); - - if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { - /* ReadFile() has failed. - Clean up and return error. */ - CancelIo(dev->device_handle); - dev->read_pending = FALSE; - goto end_of_function; - } - } - } - - if (milliseconds >= 0) { - /* See if there is any data yet. */ - res = WaitForSingleObject(ev, milliseconds); - if (res != WAIT_OBJECT_0) { - /* There was no data this time. Return zero bytes available, - but leave the Overlapped I/O running. */ - return 0; - } - } - - /* Either WaitForSingleObject() told us that ReadFile has completed, or - we are in non-blocking mode. Get the number of bytes read. The actual - data has been copied to the data[] array which was passed to ReadFile(). */ - res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); - - /* Set pending back to false, even if GetOverlappedResult() returned error. */ - dev->read_pending = FALSE; - - if (res && bytes_read > 0) { - if (dev->read_buf[0] == 0x0) { - /* If report numbers aren't being used, but Windows sticks a report - number (0x0) on the beginning of the report anyway. To make this - work like the other platforms, and to make it work more like the - HID spec, we'll skip over this byte. */ - bytes_read--; - copy_len = length > bytes_read ? bytes_read : length; - memcpy(data, dev->read_buf+1, copy_len); - } - else { - /* Copy the whole buffer, report number and all. */ - copy_len = length > bytes_read ? bytes_read : length; - memcpy(data, dev->read_buf, copy_len); - } - } - -end_of_function: - if (!res) { - register_error(dev, "GetOverlappedResult"); - return -1; - } - - return (int)copy_len; -} - -int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) -{ - return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); -} - -int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) -{ - dev->blocking = !nonblock; - return 0; /* Success */ -} - -int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) -{ - BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, (ULONG)length); - if (!res) { - register_error(dev, "HidD_SetFeature"); - return -1; - } - - return (int)length; -} - - -int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) -{ - BOOL res; -#if 0 - res = HidD_GetFeature(dev->device_handle, data, length); - if (!res) { - register_error(dev, "HidD_GetFeature"); - return -1; - } - return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */ -#else - DWORD bytes_returned; - - OVERLAPPED ol; - memset(&ol, 0, sizeof(ol)); - - res = DeviceIoControl(dev->device_handle, - IOCTL_HID_GET_FEATURE, - data, (DWORD)length, - data, (DWORD)length, - &bytes_returned, &ol); - - if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { - /* DeviceIoControl() failed. Return error. */ - register_error(dev, "Send Feature Report DeviceIoControl"); - return -1; - } - } - - /* Wait here until the write is done. This makes - hid_get_feature_report() synchronous. */ - res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/); - if (!res) { - /* The operation failed. */ - register_error(dev, "Send Feature Report GetOverLappedResult"); - return -1; - } - - /* bytes_returned does not include the first byte which contains the - report ID. The data buffer actually contains one more byte than - bytes_returned. */ - bytes_returned++; - - return bytes_returned; -#endif -} - -void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) -{ - if (!dev) - return; - CancelIo(dev->device_handle); - free_hid_device(dev); -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetManufacturerString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); - if (!res) { - register_error(dev, "HidD_GetManufacturerString"); - return -1; - } - - return 0; -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetProductString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); - if (!res) { - register_error(dev, "HidD_GetProductString"); - return -1; - } - - return 0; -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetSerialNumberString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); - if (!res) { - register_error(dev, "HidD_GetSerialNumberString"); - return -1; - } - - return 0; -} - -int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) -{ - BOOL res; - - res = HidD_GetIndexedString(dev->device_handle, string_index, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); - if (!res) { - register_error(dev, "HidD_GetIndexedString"); - return -1; - } - - return 0; -} - - -HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) -{ - return (wchar_t*)dev->last_error_str; -} - - -/*#define PICPGM*/ -/*#define S11*/ -#define P32 -#ifdef S11 - unsigned short VendorID = 0xa0a0; - unsigned short ProductID = 0x0001; -#endif - -#ifdef P32 - unsigned short VendorID = 0x04d8; - unsigned short ProductID = 0x3f; -#endif - - -#ifdef PICPGM - unsigned short VendorID = 0x04d8; - unsigned short ProductID = 0x0033; -#endif - - -#if 0 -int __cdecl main(int argc, char* argv[]) -{ - int res; - unsigned char buf[65]; - - UNREFERENCED_PARAMETER(argc); - UNREFERENCED_PARAMETER(argv); - - /* Set up the command buffer. */ - memset(buf,0x00,sizeof(buf)); - buf[0] = 0; - buf[1] = 0x81; - - - /* Open the device. */ - int handle = open(VendorID, ProductID, L"12345"); - if (handle < 0) - printf("unable to open device\n"); - - - /* Toggle LED (cmd 0x80) */ - buf[1] = 0x80; - res = write(handle, buf, 65); - if (res < 0) - printf("Unable to write()\n"); - - /* Request state (cmd 0x81) */ - buf[1] = 0x81; - write(handle, buf, 65); - if (res < 0) - printf("Unable to write() (2)\n"); - - /* Read requested state */ - read(handle, buf, 65); - if (res < 0) - printf("Unable to read()\n"); - - /* Print out the returned buffer. */ - for (int i = 0; i < 4; i++) - printf("buf[%d]: %d\n", i, buf[i]); - - return 0; -} -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif diff --git a/winbuild/libsurvive/libsurvive.vcxproj b/winbuild/libsurvive/libsurvive.vcxproj index c19beda..996f342 100644 --- a/winbuild/libsurvive/libsurvive.vcxproj +++ b/winbuild/libsurvive/libsurvive.vcxproj @@ -141,6 +141,7 @@ + @@ -160,7 +161,6 @@ - diff --git a/winbuild/libsurvive/libsurvive.vcxproj.filters b/winbuild/libsurvive/libsurvive.vcxproj.filters index 8cb8a3d..8be02f1 100644 --- a/winbuild/libsurvive/libsurvive.vcxproj.filters +++ b/winbuild/libsurvive/libsurvive.vcxproj.filters @@ -81,7 +81,7 @@ Source Files - + Source Files -- cgit v1.2.3 From 8091ccf0f33399140f5f2222b35458bebde9e843 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 02:19:35 -0400 Subject: Add rasterizer tools. --- redist/RawDrawRasterizer.c | 234 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 redist/RawDrawRasterizer.c diff --git a/redist/RawDrawRasterizer.c b/redist/RawDrawRasterizer.c new file mode 100644 index 0000000..ae80503 --- /dev/null +++ b/redist/RawDrawRasterizer.c @@ -0,0 +1,234 @@ +#ifdef RASTERIZER +#include "Rasterizer.h" +#include "DrawFunctions.h" +#include +#include +#include + +static uint32_t * buffer = 0; +static short bufferx; +static short buffery; + +static uint32_t SWAPS( uint32_t r ) +{ + uint32_t ret = (r&0xFF)<<16; + r>>=8; + ret |= (r&0xff)<<8; + r>>=8; + ret |= r; + return ret; +} + +uint32_t CNFGColor( uint32_t RGB ) +{ + CNFGLastColor = SWAPS(RGB); + return CNFGLastColor; +} + +void CNFGTackSegment( short x1, short y1, short x2, short y2 ) +{ + short tx, ty; + float slope, lp; + + short dx = x2 - x1; + short dy = y2 - y1; + + if( !buffer ) return; + + if( dx < 0 ) dx = -dx; + if( dy < 0 ) dy = -dy; + + if( dx > dy ) + { + short minx = (x1 < x2)?x1:x2; + short maxx = (x1 < x2)?x2:x1; + short miny = (x1 < x2)?y1:y2; + short maxy = (x1 < x2)?y2:y1; + float thisy = miny; + slope = (float)(maxy-miny) / (float)(maxx-minx); + + for( tx = minx; tx <= maxx; tx++ ) + { + thisy += slope; + ty = thisy; + if( tx < 0 || ty < 0 || ty >= buffery ) continue; + if( tx >= bufferx ) break; + buffer[ty * bufferx + tx] = CNFGLastColor; + } + } + else + { + short minx = (y1 < y2)?x1:x2; + short maxx = (y1 < y2)?x2:x1; + short miny = (y1 < y2)?y1:y2; + short maxy = (y1 < y2)?y2:y1; + float thisx = minx; + slope = (float)(maxx-minx) / (float)(maxy-miny); + + for( ty = miny; ty <= maxy; ty++ ) + { + thisx += slope; + tx = thisx; + if( ty < 0 || tx < 0 || tx >= bufferx ) continue; + if( ty >= buffery ) break; + buffer[ty * bufferx + tx] = CNFGLastColor; + } + } +} + +void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) +{ + short minx = (x1=x2)?x1:x2; + short maxy = (y1>=y2)?y1:y2; + + short x, y; + + if( minx < 0 ) minx = 0; + if( miny < 0 ) miny = 0; + if( maxx >= bufferx ) maxx = bufferx-1; + if( maxy >= buffery ) maxy = buffery-1; + + for( y = miny; y <= maxy; y++ ) + { + uint32_t * bufferstart = &buffer[y * bufferx + minx]; + for( x = minx; x <= maxx; x++ ) + { + (*bufferstart++) = CNFGLastColor; + } + } +} + +void CNFGTackPoly( RDPoint * points, int verts ) +{ + short minx = 10000, miny = 10000; + short maxx =-10000, maxy =-10000; + short i, x, y; + + //Just in case... + if( verts > 32767 ) return; + + for( i = 0; i < verts; i++ ) + { + RDPoint * p = &points[i]; + if( p->x < minx ) minx = p->x; + if( p->y < miny ) miny = p->y; + if( p->x > maxx ) maxx = p->x; + if( p->y > maxy ) maxy = p->y; + } + + if( miny < 0 ) miny = 0; + if( maxy >= buffery ) maxy = buffery-1; + + for( y = miny; y <= maxy; y++ ) + { + short startfillx = maxx; + short endfillx = minx; + + //Figure out what line segments intersect this line. + for( i = 0; i < verts; i++ ) + { + short pl = i + 1; + if( pl == verts ) pl = 0; + + RDPoint ptop; + RDPoint pbot; + + ptop.x = points[i].x; + ptop.y = points[i].y; + pbot.x = points[pl].x; + pbot.y = points[pl].y; +//printf( "Poly: %d %d\n", pbot.y, ptop.y ); + + if( pbot.y < ptop.y ) + { + RDPoint ptmp; + ptmp.x = pbot.x; + ptmp.y = pbot.y; + pbot.x = ptop.x; + pbot.y = ptop.y; + ptop.x = ptmp.x; + ptop.y = ptmp.y; + } + + //Make sure this line segment is within our range. +//printf( "PT: %d %d %d\n", y, ptop.y, pbot.y ); + if( ptop.y <= y && pbot.y >= y ) + { + short diffy = pbot.y - ptop.y; + uint32_t placey = (uint32_t)(y - ptop.y)<<16; //Scale by 16 so we can do integer math. + short diffx = pbot.x - ptop.x; + short isectx; + + if( diffy == 0 ) + { + if( pbot.x < ptop.x ) + { + if( startfillx > pbot.x ) startfillx = pbot.x; + if( endfillx < ptop.x ) endfillx = ptop.x; + } + else + { + if( startfillx > ptop.x ) startfillx = ptop.x; + if( endfillx < pbot.x ) endfillx = pbot.x; + } + } + else + { + //Inner part is scaled by 65536, outer part must be scaled back. + isectx = (( (placey / diffy) * diffx + 32768 )>>16) + ptop.x; + if( isectx < startfillx ) startfillx = isectx; + if( isectx > endfillx ) endfillx = isectx; + } +//printf( "R: %d %d %d\n", pbot.x, ptop.x, isectx ); + } + } + +//printf( "%d %d %d\n", y, startfillx, endfillx ); + + if( endfillx >= bufferx ) endfillx = bufferx - 1; + if( endfillx >= bufferx ) endfillx = buffery - 1; + if( startfillx < 0 ) startfillx = 0; + if( startfillx < 0 ) startfillx = 0; + + unsigned int * bufferstart = &buffer[y * bufferx + startfillx]; + for( x = startfillx; x <= endfillx; x++ ) + { + (*bufferstart++) = CNFGLastColor; + } + } +//exit(1); +} + + +void CNFGClearFrame() +{ + int i, m; + uint32_t col = 0; + short x, y; + CNFGGetDimensions( &x, &y ); + if( x != bufferx || y != buffery || !buffer ) + { + bufferx = x; + buffery = y; + printf( "MALLOCING: %d\n", x * y ); + buffer = malloc( x * y * 8 ); + } + + m = x * y; + col = CNFGColor( CNFGBGColor ); + for( i = 0; i < m; i++ ) + { +//printf( "Got: %d %p %d\n", m, buffer, i ); + buffer[i] = col; + } +} + +void CNFGSwapBuffers() +{ + CNFGUpdateScreenWithBitmap( buffer, bufferx, buffery ); +} + + +#endif -- cgit v1.2.3 From c295dffc63f6d9107294c485f40eef6d269df832 Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 02:23:28 -0400 Subject: Add needed function to rdr --- redist/RawDrawRasterizer.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/redist/RawDrawRasterizer.c b/redist/RawDrawRasterizer.c index ae80503..4ed77d7 100644 --- a/redist/RawDrawRasterizer.c +++ b/redist/RawDrawRasterizer.c @@ -25,6 +25,11 @@ uint32_t CNFGColor( uint32_t RGB ) return CNFGLastColor; } +void CNFGTackPixel( short x, short y ) +{ + buffer[bufferx*y+x] = CNFGLastColor; +} + void CNFGTackSegment( short x1, short y1, short x2, short y2 ) { short tx, ty; -- cgit v1.2.3 From 2954876a8fb8c21d1947dfa6c77e47008a719b8a Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 02:24:21 -0400 Subject: Fix non-needed header. --- redist/RawDrawRasterizer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/redist/RawDrawRasterizer.c b/redist/RawDrawRasterizer.c index 4ed77d7..af40588 100644 --- a/redist/RawDrawRasterizer.c +++ b/redist/RawDrawRasterizer.c @@ -1,5 +1,4 @@ #ifdef RASTERIZER -#include "Rasterizer.h" #include "DrawFunctions.h" #include #include -- cgit v1.2.3 From 195053d034b2bca63db1f72be14bff9b2c7b1916 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 17 Mar 2017 01:13:42 -0400 Subject: bump rawdraw to newest version. --- Makefile | 8 +- calibrate.c | 2 +- calibrate_client.c | 2 +- data_recorder.c | 2 +- redist/CNFGFunctions.c | 272 ++++++++++++++++++++++++++++++++++++++++ redist/CNFGFunctions.h | 59 +++++++++ redist/CNFGNullDriver.c | 74 +++++++++++ redist/CNFGRasterizer.h | 247 ++++++++++++++++++++++++++++++++++++ redist/CNFGWinDriver.c | 289 ++++++++++++++++++++++++++++++++++++++++++ redist/CNFGXDriver.c | 304 +++++++++++++++++++++++++++++++++++++++++++++ redist/DrawFunctions.c | 277 ----------------------------------------- redist/DrawFunctions.h | 55 -------- redist/RawDrawNull.c | 74 ----------- redist/RawDrawRasterizer.c | 238 ----------------------------------- redist/WinDriver.c | 231 ---------------------------------- redist/XDriver.c | 290 ------------------------------------------ test.c | 2 +- 17 files changed, 1253 insertions(+), 1173 deletions(-) create mode 100644 redist/CNFGFunctions.c create mode 100644 redist/CNFGFunctions.h create mode 100644 redist/CNFGNullDriver.c create mode 100644 redist/CNFGRasterizer.h create mode 100644 redist/CNFGWinDriver.c create mode 100644 redist/CNFGXDriver.c delete mode 100644 redist/DrawFunctions.c delete mode 100644 redist/DrawFunctions.h delete mode 100644 redist/RawDrawNull.c delete mode 100644 redist/RawDrawRasterizer.c delete mode 100644 redist/WinDriver.c delete mode 100644 redist/XDriver.c diff --git a/Makefile b/Makefile index 03f37d6..a642877 100644 --- a/Makefile +++ b/Makefile @@ -13,14 +13,14 @@ UNAME=$(shell uname) # Mac OSX ifeq ($(UNAME), Darwin) -DRAWFUNCTIONS=redist/DrawFunctions.c redist/RawDrawNull.c -GRAPHICS_LOFI:=redist/DrawFunctions.o redist/RawDrawNull.o +DRAWFUNCTIONS=redist/CNFGFunctions.c redist/CNFGNullDriver.c +GRAPHICS_LOFI:=redist/CNFGFunctions.o redist/CNFGNullDriver.o # Linux / FreeBSD else LDFLAGS:=$(LDFLAGS) -lX11 -DRAWFUNCTIONS=redist/DrawFunctions.c redist/XDriver.c -GRAPHICS_LOFI:=redist/DrawFunctions.o redist/XDriver.o +DRAWFUNCTIONS=redist/CNFGFunctions.c redist/CNFGXDriver.c +GRAPHICS_LOFI:=redist/CNFGFunctions.o redist/CNFGXDriver.o endif diff --git a/calibrate.c b/calibrate.c index 9633a77..3d83baf 100644 --- a/calibrate.c +++ b/calibrate.c @@ -7,7 +7,7 @@ #include #include #include "src/survive_cal.h" -#include +#include #include "src/survive_config.h" diff --git a/calibrate_client.c b/calibrate_client.c index f28520b..5e31cfb 100644 --- a/calibrate_client.c +++ b/calibrate_client.c @@ -8,7 +8,7 @@ #include #include #include "src/survive_cal.h" -#include +#include #include "src/survive_config.h" diff --git a/data_recorder.c b/data_recorder.c index 5504d42..630598a 100644 --- a/data_recorder.c +++ b/data_recorder.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include struct SurviveContext * ctx; diff --git a/redist/CNFGFunctions.c b/redist/CNFGFunctions.c new file mode 100644 index 0000000..947456f --- /dev/null +++ b/redist/CNFGFunctions.c @@ -0,0 +1,272 @@ +/* +Copyright (c) 2010, 2011 Charles Lohr + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "CNFGFunctions.h" +#include + +int CNFGPenX, CNFGPenY; +uint32_t CNFGBGColor; +uint32_t CNFGLastColor; +uint32_t CNFGDialogColor; //background for boxes +const unsigned short FontCharMap[256] = { + 65535, 0, 10, 20, 32, 44, 56, 68, 70, 65535, 65535, 80, 92, 65535, 104, 114, + 126, 132, 138, 148, 156, 166, 180, 188, 200, 206, 212, 218, 224, 228, 238, 244, + 65535, 250, 254, 258, 266, 278, 288, 302, 304, 310, 316, 324, 328, 226, 252, 330, + 332, 342, 348, 358, 366, 372, 382, 392, 400, 410, 420, 424, 428, 262, 432, 436, + 446, 460, 470, 486, 496, 508, 516, 522, 536, 542, 548, 556, 568, 572, 580, 586, + 598, 608, 622, 634, 644, 648, 654, 662, 670, 682, 692, 700, 706, 708, 492, 198, + 714, 716, 726, 734, 742, 750, 760, 768, 782, 790, 794, 802, 204, 810, 820, 384, + 828, 836, 844, 850, 860, 864, 872, 880, 890, 894, 902, 908, 916, 920, 928, 934, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 944, 948, 960, 970, 986, 996, 1000, 1016, 1020, 1026, 1034, 1042, 364, 1046, 1056, 1058, + 1066, 1072, 1080, 932, 1092, 1100, 68, 1110, 1114, 1116, 1124, 1132, 1142, 1154, 1170, 1180, + 1192, 1204, 1218, 1234, 1248, 1264, 1276, 1290, 1300, 1310, 1322, 1334, 1342, 1350, 1360, 1370, + 1384, 1396, 1406, 1416, 1428, 1442, 1454, 1458, 1472, 1480, 1488, 1498, 1508, 1520, 1530, 1544, + 1556, 1568, 1582, 1598, 1612, 1628, 1642, 1654, 1666, 1678, 1692, 1706, 1710, 1714, 1720, 1726, + 1738, 1752, 1762, 1772, 1784, 1798, 1810, 1816, 1826, 1836, 1846, 1858, 1870, 1880, 1890, 65535, }; + +const unsigned char FontCharData[1902] = { + 0x00, 0x01, 0x20, 0x21, 0x03, 0x23, 0x23, 0x14, 0x14, 0x83, 0x00, 0x01, 0x20, 0x21, 0x04, 0x24, + 0x24, 0x13, 0x13, 0x84, 0x01, 0x21, 0x21, 0x23, 0x23, 0x14, 0x14, 0x03, 0x03, 0x01, 0x11, 0x92, + 0x11, 0x22, 0x22, 0x23, 0x23, 0x14, 0x14, 0x03, 0x03, 0x02, 0x02, 0x91, 0x01, 0x21, 0x21, 0x23, + 0x23, 0x01, 0x03, 0x21, 0x03, 0x01, 0x12, 0x94, 0x03, 0x23, 0x13, 0x14, 0x23, 0x22, 0x22, 0x11, + 0x11, 0x02, 0x02, 0x83, 0x12, 0x92, 0x12, 0x12, 0x01, 0x21, 0x21, 0x23, 0x23, 0x03, 0x03, 0x81, + 0x03, 0x21, 0x21, 0x22, 0x21, 0x11, 0x03, 0x14, 0x14, 0x23, 0x23, 0x92, 0x01, 0x10, 0x10, 0x21, + 0x21, 0x12, 0x12, 0x01, 0x12, 0x14, 0x03, 0xa3, 0x02, 0x03, 0x03, 0x13, 0x02, 0x12, 0x13, 0x10, + 0x10, 0xa1, 0x01, 0x23, 0x03, 0x21, 0x02, 0x11, 0x11, 0x22, 0x22, 0x13, 0x13, 0x82, 0x00, 0x22, + 0x22, 0x04, 0x04, 0x80, 0x20, 0x02, 0x02, 0x24, 0x24, 0xa0, 0x01, 0x10, 0x10, 0x21, 0x10, 0x14, + 0x14, 0x03, 0x14, 0xa3, 0x00, 0x03, 0x04, 0x04, 0x20, 0x23, 0x24, 0xa4, 0x00, 0x20, 0x00, 0x02, + 0x02, 0x22, 0x10, 0x14, 0x20, 0xa4, 0x01, 0x21, 0x21, 0x23, 0x23, 0x03, 0x03, 0x01, 0x20, 0x10, + 0x10, 0x14, 0x14, 0x84, 0x03, 0x23, 0x23, 0x24, 0x24, 0x04, 0x04, 0x83, 0x01, 0x10, 0x10, 0x21, + 0x10, 0x14, 0x14, 0x03, 0x14, 0x23, 0x04, 0xa4, 0x01, 0x10, 0x21, 0x10, 0x10, 0x94, 0x03, 0x14, + 0x23, 0x14, 0x10, 0x94, 0x02, 0x22, 0x22, 0x11, 0x22, 0x93, 0x02, 0x22, 0x02, 0x11, 0x02, 0x93, + 0x01, 0x02, 0x02, 0xa2, 0x02, 0x22, 0x22, 0x11, 0x11, 0x02, 0x02, 0x13, 0x13, 0xa2, 0x11, 0x22, + 0x22, 0x02, 0x02, 0x91, 0x02, 0x13, 0x13, 0x22, 0x22, 0x82, 0x10, 0x13, 0x14, 0x94, 0x10, 0x01, + 0x20, 0x91, 0x10, 0x14, 0x20, 0x24, 0x01, 0x21, 0x03, 0xa3, 0x21, 0x10, 0x10, 0x01, 0x01, 0x23, + 0x23, 0x14, 0x14, 0x03, 0x10, 0x94, 0x00, 0x01, 0x23, 0x24, 0x04, 0x03, 0x03, 0x21, 0x21, 0xa0, + 0x21, 0x10, 0x10, 0x01, 0x01, 0x12, 0x12, 0x03, 0x03, 0x14, 0x14, 0x23, 0x02, 0xa4, 0x10, 0x91, + 0x10, 0x01, 0x01, 0x03, 0x03, 0x94, 0x10, 0x21, 0x21, 0x23, 0x23, 0x94, 0x01, 0x23, 0x11, 0x13, + 0x21, 0x03, 0x02, 0xa2, 0x02, 0x22, 0x11, 0x93, 0x04, 0x93, 0x03, 0xa1, 0x00, 0x20, 0x20, 0x24, + 0x24, 0x04, 0x04, 0x00, 0x12, 0x92, 0x01, 0x10, 0x10, 0x14, 0x04, 0xa4, 0x01, 0x10, 0x10, 0x21, + 0x21, 0x22, 0x22, 0x04, 0x04, 0xa4, 0x00, 0x20, 0x20, 0x24, 0x24, 0x04, 0x12, 0xa2, 0x00, 0x02, + 0x02, 0x22, 0x20, 0xa4, 0x20, 0x00, 0x00, 0x02, 0x02, 0x22, 0x22, 0x24, 0x24, 0x84, 0x20, 0x02, + 0x02, 0x22, 0x22, 0x24, 0x24, 0x04, 0x04, 0x82, 0x00, 0x20, 0x20, 0x21, 0x21, 0x12, 0x12, 0x94, + 0x00, 0x04, 0x00, 0x20, 0x20, 0x24, 0x04, 0x24, 0x02, 0xa2, 0x00, 0x02, 0x02, 0x22, 0x22, 0x20, + 0x20, 0x00, 0x22, 0x84, 0x11, 0x11, 0x13, 0x93, 0x11, 0x11, 0x13, 0x84, 0x20, 0x02, 0x02, 0xa4, + 0x00, 0x22, 0x22, 0x84, 0x01, 0x10, 0x10, 0x21, 0x21, 0x12, 0x12, 0x13, 0x14, 0x94, 0x21, 0x01, + 0x01, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x12, 0x12, 0x13, 0x13, 0xa3, 0x04, 0x01, 0x01, 0x10, + 0x10, 0x21, 0x21, 0x24, 0x02, 0xa2, 0x00, 0x04, 0x04, 0x14, 0x14, 0x23, 0x23, 0x12, 0x12, 0x02, + 0x12, 0x21, 0x21, 0x10, 0x10, 0x80, 0x23, 0x14, 0x14, 0x03, 0x03, 0x01, 0x01, 0x10, 0x10, 0xa1, + 0x00, 0x10, 0x10, 0x21, 0x21, 0x23, 0x23, 0x14, 0x14, 0x04, 0x04, 0x80, 0x00, 0x04, 0x04, 0x24, + 0x00, 0x20, 0x02, 0x92, 0x00, 0x04, 0x00, 0x20, 0x02, 0x92, 0x21, 0x10, 0x10, 0x01, 0x01, 0x03, + 0x03, 0x14, 0x14, 0x23, 0x23, 0x22, 0x22, 0x92, 0x00, 0x04, 0x20, 0x24, 0x02, 0xa2, 0x00, 0x20, + 0x10, 0x14, 0x04, 0xa4, 0x00, 0x20, 0x20, 0x23, 0x23, 0x14, 0x14, 0x83, 0x00, 0x04, 0x02, 0x12, + 0x12, 0x21, 0x21, 0x20, 0x12, 0x23, 0x23, 0xa4, 0x00, 0x04, 0x04, 0xa4, 0x04, 0x00, 0x00, 0x11, + 0x11, 0x20, 0x20, 0xa4, 0x04, 0x00, 0x00, 0x22, 0x20, 0xa4, 0x01, 0x10, 0x10, 0x21, 0x21, 0x23, + 0x23, 0x14, 0x14, 0x03, 0x03, 0x81, 0x00, 0x04, 0x00, 0x10, 0x10, 0x21, 0x21, 0x12, 0x12, 0x82, + 0x01, 0x10, 0x10, 0x21, 0x21, 0x23, 0x23, 0x14, 0x14, 0x03, 0x03, 0x01, 0x04, 0x93, 0x00, 0x04, + 0x00, 0x10, 0x10, 0x21, 0x21, 0x12, 0x12, 0x02, 0x02, 0xa4, 0x21, 0x10, 0x10, 0x01, 0x01, 0x23, + 0x23, 0x14, 0x14, 0x83, 0x00, 0x20, 0x10, 0x94, 0x00, 0x04, 0x04, 0x24, 0x24, 0xa0, 0x00, 0x03, + 0x03, 0x14, 0x14, 0x23, 0x23, 0xa0, 0x00, 0x04, 0x04, 0x24, 0x14, 0x13, 0x24, 0xa0, 0x00, 0x01, + 0x01, 0x23, 0x23, 0x24, 0x04, 0x03, 0x03, 0x21, 0x21, 0xa0, 0x00, 0x01, 0x01, 0x12, 0x12, 0x14, + 0x12, 0x21, 0x21, 0xa0, 0x00, 0x20, 0x20, 0x02, 0x02, 0x04, 0x04, 0xa4, 0x10, 0x00, 0x00, 0x04, + 0x04, 0x94, 0x01, 0xa3, 0x10, 0x20, 0x20, 0x24, 0x24, 0x94, 0x00, 0x91, 0x02, 0x04, 0x04, 0x24, + 0x24, 0x22, 0x23, 0x12, 0x12, 0x82, 0x00, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x82, 0x24, 0x04, + 0x04, 0x03, 0x03, 0x12, 0x12, 0xa2, 0x20, 0x24, 0x24, 0x04, 0x04, 0x02, 0x02, 0xa2, 0x24, 0x04, + 0x04, 0x02, 0x02, 0x22, 0x22, 0x23, 0x23, 0x93, 0x04, 0x01, 0x02, 0x12, 0x01, 0x10, 0x10, 0xa1, + 0x23, 0x12, 0x12, 0x03, 0x03, 0x14, 0x14, 0x23, 0x23, 0x24, 0x24, 0x15, 0x15, 0x84, 0x00, 0x04, + 0x03, 0x12, 0x12, 0x23, 0x23, 0xa4, 0x11, 0x11, 0x12, 0x94, 0x22, 0x22, 0x23, 0x24, 0x24, 0x15, + 0x15, 0x84, 0x00, 0x04, 0x03, 0x13, 0x13, 0x22, 0x13, 0xa4, 0x02, 0x04, 0x02, 0x13, 0x12, 0x14, + 0x12, 0x23, 0x23, 0xa4, 0x02, 0x04, 0x03, 0x12, 0x12, 0x23, 0x23, 0xa4, 0x02, 0x05, 0x04, 0x24, + 0x24, 0x22, 0x22, 0x82, 0x02, 0x04, 0x04, 0x24, 0x25, 0x22, 0x22, 0x82, 0x02, 0x04, 0x03, 0x12, + 0x12, 0xa2, 0x22, 0x02, 0x02, 0x03, 0x03, 0x23, 0x23, 0x24, 0x24, 0x84, 0x11, 0x14, 0x02, 0xa2, + 0x02, 0x04, 0x04, 0x14, 0x14, 0x23, 0x24, 0xa2, 0x02, 0x03, 0x03, 0x14, 0x14, 0x23, 0x23, 0xa2, + 0x02, 0x03, 0x03, 0x14, 0x14, 0x12, 0x13, 0x24, 0x24, 0xa2, 0x02, 0x24, 0x04, 0xa2, 0x02, 0x03, + 0x03, 0x14, 0x22, 0x23, 0x23, 0x85, 0x02, 0x22, 0x22, 0x04, 0x04, 0xa4, 0x20, 0x10, 0x10, 0x14, + 0x14, 0x24, 0x12, 0x82, 0x10, 0x11, 0x13, 0x94, 0x00, 0x10, 0x10, 0x14, 0x14, 0x04, 0x12, 0xa2, + 0x01, 0x10, 0x10, 0x11, 0x11, 0xa0, 0x03, 0x04, 0x04, 0x24, 0x24, 0x23, 0x23, 0x12, 0x12, 0x83, + 0x10, 0x10, 0x11, 0x94, 0x21, 0x10, 0x10, 0x01, 0x01, 0x02, 0x02, 0x13, 0x13, 0x22, 0x10, 0x93, + 0x11, 0x00, 0x00, 0x04, 0x04, 0x24, 0x24, 0x23, 0x02, 0x92, 0x01, 0x02, 0x11, 0x21, 0x22, 0x23, + 0x03, 0x13, 0x02, 0x11, 0x11, 0x22, 0x22, 0x13, 0x13, 0x82, 0x00, 0x11, 0x11, 0x20, 0x11, 0x14, + 0x02, 0x22, 0x03, 0xa3, 0x10, 0x12, 0x13, 0x95, 0x20, 0x00, 0x00, 0x02, 0x02, 0x11, 0x11, 0x22, + 0x02, 0x13, 0x13, 0x22, 0x22, 0x24, 0x24, 0x84, 0x00, 0x00, 0x20, 0xa0, 0x20, 0x10, 0x10, 0x11, + 0x11, 0xa1, 0x10, 0x21, 0x20, 0x21, 0x21, 0x11, 0x11, 0x90, 0x11, 0x02, 0x02, 0x13, 0x21, 0x12, + 0x12, 0xa3, 0x01, 0x21, 0x21, 0xa2, 0x10, 0x20, 0x20, 0x21, 0x21, 0x11, 0x12, 0x10, 0x11, 0xa2, + 0x00, 0xa0, 0x01, 0x10, 0x10, 0x21, 0x21, 0x12, 0x12, 0x81, 0x02, 0x22, 0x11, 0x13, 0x03, 0xa3, + 0x01, 0x10, 0x10, 0x21, 0x21, 0x03, 0x03, 0xa3, 0x01, 0x10, 0x10, 0x21, 0x21, 0x12, 0x12, 0x02, + 0x12, 0x23, 0x23, 0x83, 0x02, 0x05, 0x04, 0x14, 0x14, 0x23, 0x22, 0xa4, 0x14, 0x10, 0x10, 0x01, + 0x01, 0x12, 0x10, 0x20, 0x20, 0xa4, 0x14, 0x15, 0x15, 0x85, 0x20, 0xa1, 0x10, 0x20, 0x20, 0x21, + 0x21, 0x11, 0x11, 0x90, 0x01, 0x12, 0x12, 0x03, 0x11, 0x22, 0x22, 0x93, 0x00, 0x01, 0x02, 0x20, + 0x12, 0x13, 0x13, 0x23, 0x22, 0xa4, 0x00, 0x01, 0x02, 0x20, 0x12, 0x22, 0x22, 0x13, 0x13, 0x14, + 0x14, 0xa4, 0x00, 0x10, 0x10, 0x11, 0x11, 0x01, 0x11, 0x02, 0x02, 0x20, 0x12, 0x13, 0x13, 0x23, + 0x22, 0xa4, 0x10, 0x10, 0x11, 0x12, 0x12, 0x03, 0x03, 0x14, 0x14, 0xa3, 0x04, 0x02, 0x02, 0x11, + 0x11, 0x22, 0x22, 0x24, 0x03, 0x23, 0x10, 0xa1, 0x04, 0x02, 0x02, 0x11, 0x11, 0x22, 0x22, 0x24, + 0x03, 0x23, 0x01, 0x90, 0x04, 0x02, 0x02, 0x11, 0x11, 0x22, 0x22, 0x24, 0x03, 0x23, 0x01, 0x10, + 0x10, 0xa1, 0x04, 0x02, 0x02, 0x11, 0x11, 0x22, 0x22, 0x24, 0x03, 0x23, 0x01, 0x10, 0x10, 0x11, + 0x11, 0xa0, 0x04, 0x02, 0x02, 0x11, 0x11, 0x22, 0x22, 0x24, 0x03, 0x23, 0x00, 0x00, 0x20, 0xa0, + 0x04, 0x02, 0x02, 0x11, 0x11, 0x22, 0x22, 0x24, 0x03, 0x23, 0x00, 0x20, 0x20, 0x11, 0x11, 0x80, + 0x00, 0x04, 0x02, 0x22, 0x00, 0x11, 0x10, 0x14, 0x10, 0x20, 0x14, 0xa4, 0x23, 0x14, 0x14, 0x03, + 0x03, 0x01, 0x01, 0x10, 0x10, 0x21, 0x14, 0x15, 0x15, 0x85, 0x02, 0x22, 0x02, 0x04, 0x04, 0x24, + 0x03, 0x13, 0x00, 0x91, 0x02, 0x22, 0x02, 0x04, 0x04, 0x24, 0x03, 0x13, 0x11, 0xa0, 0x02, 0x22, + 0x02, 0x04, 0x04, 0x24, 0x03, 0x13, 0x01, 0x10, 0x10, 0xa1, 0x02, 0x22, 0x02, 0x04, 0x04, 0x24, + 0x03, 0x13, 0x00, 0x00, 0x20, 0xa0, 0x02, 0x22, 0x12, 0x14, 0x04, 0x24, 0x00, 0x91, 0x02, 0x22, + 0x12, 0x14, 0x04, 0x24, 0x11, 0xa0, 0x02, 0x22, 0x12, 0x14, 0x04, 0x24, 0x01, 0x10, 0x10, 0xa1, + 0x02, 0x22, 0x12, 0x14, 0x04, 0x24, 0x20, 0x20, 0x00, 0x80, 0x00, 0x10, 0x10, 0x21, 0x21, 0x23, + 0x23, 0x14, 0x14, 0x04, 0x04, 0x00, 0x02, 0x92, 0x04, 0x02, 0x02, 0x24, 0x24, 0x22, 0x01, 0x10, + 0x10, 0x11, 0x11, 0xa0, 0x02, 0x22, 0x22, 0x24, 0x24, 0x04, 0x04, 0x02, 0x00, 0x91, 0x02, 0x22, + 0x22, 0x24, 0x24, 0x04, 0x04, 0x02, 0x11, 0xa0, 0x02, 0x22, 0x22, 0x24, 0x24, 0x04, 0x04, 0x02, + 0x11, 0x20, 0x00, 0x91, 0x02, 0x22, 0x22, 0x24, 0x24, 0x04, 0x04, 0x02, 0x01, 0x10, 0x10, 0x11, + 0x11, 0xa0, 0x01, 0x21, 0x21, 0x24, 0x24, 0x04, 0x04, 0x01, 0x00, 0x00, 0x20, 0xa0, 0x01, 0x23, + 0x03, 0xa1, 0x01, 0x10, 0x10, 0x21, 0x21, 0x23, 0x23, 0x14, 0x14, 0x03, 0x03, 0x01, 0x03, 0xa1, + 0x01, 0x04, 0x04, 0x24, 0x24, 0x21, 0x11, 0xa0, 0x01, 0x04, 0x04, 0x24, 0x24, 0x21, 0x00, 0x91, + 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x01, 0x10, 0x10, 0xa1, 0x01, 0x04, 0x04, 0x24, 0x24, 0x21, + 0x00, 0x00, 0x20, 0xa0, 0x01, 0x02, 0x02, 0x13, 0x13, 0x14, 0x13, 0x22, 0x22, 0x21, 0x11, 0xa0, + 0x00, 0x04, 0x01, 0x11, 0x11, 0x22, 0x22, 0x13, 0x13, 0x83, 0x00, 0x05, 0x00, 0x10, 0x10, 0x21, + 0x21, 0x12, 0x02, 0x22, 0x22, 0x24, 0x24, 0x84, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x23, 0x12, + 0x12, 0x02, 0x00, 0x91, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x23, 0x12, 0x12, 0x02, 0x11, 0xa0, + 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x23, 0x12, 0x12, 0x02, 0x01, 0x10, 0x10, 0xa1, 0x02, 0x04, + 0x04, 0x24, 0x24, 0x22, 0x23, 0x12, 0x12, 0x02, 0x01, 0x10, 0x10, 0x11, 0x11, 0xa0, 0x02, 0x04, + 0x04, 0x24, 0x24, 0x22, 0x23, 0x12, 0x12, 0x02, 0x01, 0x01, 0x21, 0xa1, 0x02, 0x04, 0x04, 0x24, + 0x24, 0x22, 0x23, 0x12, 0x12, 0x02, 0x01, 0x10, 0x10, 0x21, 0x21, 0x81, 0x02, 0x13, 0x02, 0x04, + 0x04, 0x24, 0x12, 0x14, 0x12, 0x22, 0x13, 0x23, 0x22, 0xa3, 0x03, 0x04, 0x04, 0x24, 0x03, 0x12, + 0x12, 0x22, 0x14, 0x15, 0x15, 0x85, 0x24, 0x04, 0x04, 0x02, 0x02, 0x22, 0x22, 0x23, 0x23, 0x13, + 0x00, 0x91, 0x24, 0x04, 0x04, 0x02, 0x02, 0x22, 0x22, 0x23, 0x23, 0x13, 0x11, 0xa0, 0x24, 0x04, + 0x04, 0x02, 0x02, 0x22, 0x22, 0x23, 0x23, 0x13, 0x01, 0x10, 0x10, 0xa1, 0x24, 0x04, 0x04, 0x02, + 0x02, 0x22, 0x22, 0x23, 0x23, 0x13, 0x01, 0x01, 0x21, 0xa1, 0x12, 0x14, 0x00, 0x91, 0x12, 0x14, + 0x11, 0xa0, 0x12, 0x14, 0x01, 0x10, 0x10, 0xa1, 0x12, 0x14, 0x01, 0x01, 0x21, 0xa1, 0x00, 0x22, + 0x11, 0x20, 0x02, 0x22, 0x22, 0x24, 0x24, 0x04, 0x04, 0x82, 0x02, 0x04, 0x03, 0x12, 0x12, 0x23, + 0x23, 0x24, 0x01, 0x10, 0x10, 0x11, 0x11, 0xa0, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x02, + 0x00, 0x91, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x02, 0x11, 0xa0, 0x02, 0x04, 0x04, 0x24, + 0x24, 0x22, 0x22, 0x02, 0x01, 0x10, 0x10, 0xa1, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x02, + 0x01, 0x10, 0x10, 0x11, 0x11, 0xa0, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x02, 0x01, 0x01, + 0x21, 0xa1, 0x11, 0x11, 0x02, 0x22, 0x13, 0x93, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x02, + 0x04, 0xa2, 0x02, 0x04, 0x04, 0x14, 0x14, 0x23, 0x24, 0x22, 0x00, 0x91, 0x02, 0x04, 0x04, 0x14, + 0x14, 0x23, 0x24, 0x22, 0x11, 0xa0, 0x02, 0x04, 0x04, 0x14, 0x14, 0x23, 0x24, 0x22, 0x01, 0x10, + 0x10, 0xa1, 0x02, 0x04, 0x04, 0x14, 0x14, 0x23, 0x24, 0x22, 0x01, 0x01, 0x21, 0xa1, 0x02, 0x03, + 0x03, 0x14, 0x22, 0x23, 0x23, 0x05, 0x11, 0xa0, 0x00, 0x04, 0x02, 0x11, 0x11, 0x22, 0x22, 0x13, + 0x13, 0x82, 0x02, 0x03, 0x03, 0x14, 0x22, 0x23, 0x23, 0x05, 0x01, 0x01, 0x21, 0xa1, }; + + + +void CNFGDrawText( const char * text, int scale ) +{ + const unsigned char * lmap; + float iox = (float)CNFGPenX; + float ioy = (float)CNFGPenY; + + int place = 0; + unsigned short index; + int bQuit = 0; + while( text[place] ) + { + unsigned char c = text[place]; + + switch( c ) + { + case 9: + iox += 12 * scale; + break; + case 10: + iox = (float)CNFGPenX; + ioy += 6 * scale; + break; + default: + index = FontCharMap[c]; + if( index == 65535 ) + { + iox += 3 * scale; + break; + } + + lmap = &FontCharData[index]; + do + { + int x1 = (int)((((*lmap) & 0x70)>>4)*scale + iox); + int y1 = (int)(((*lmap) & 0x0f)*scale + ioy); + int x2 = (int)((((*(lmap+1)) & 0x70)>>4)*scale + iox); + int y2 = (int)(((*(lmap+1)) & 0x0f)*scale + ioy); + lmap++; + CNFGTackSegment( x1, y1, x2, y2 ); + bQuit = *lmap & 0x80; + lmap++; + } while( !bQuit ); + + iox += 3 * scale; + } + place++; + } +} + + +void CNFGDrawBox( int x1, int y1, int x2, int y2 ) +{ + unsigned lc = CNFGLastColor; + CNFGColor( CNFGDialogColor ); + CNFGTackRectangle( x1, y1, x2, y2 ); + CNFGColor( lc ); + CNFGTackSegment( x1, y1, x2, y1 ); + CNFGTackSegment( x2, y1, x2, y2 ); + CNFGTackSegment( x2, y2, x1, y2 ); + CNFGTackSegment( x1, y2, x1, y1 ); +} + +void CNFGGetTextExtents( const char * text, int * w, int * h, int textsize ) +{ + int charsx = 0; + int charsy = 1; + int charsline = 0; + const char * s; + + for( s = text; *s; s++ ) + { + if( *s == '\n' ) + { + charsline = 0; + if( *(s+1) ) + charsy++; + } + else + { + charsline++; + if( charsline > charsx ) + charsx = charsline; + } + } + + *w = charsx * textsize * 3 + textsize; + *h = charsy * textsize * 6; +} + +void CNFGDrawTextbox( int x, int y, const char * text, int textsize ) +{ + int w; + int h; + + CNFGGetTextExtents( text, &w, &h, textsize ); + + CNFGDrawBox( x, y, x + w, y + h ); + CNFGPenX = x + textsize; + CNFGPenY = y + textsize; + CNFGDrawText( text, textsize ); +} diff --git a/redist/CNFGFunctions.h b/redist/CNFGFunctions.h new file mode 100644 index 0000000..9ecb1bd --- /dev/null +++ b/redist/CNFGFunctions.h @@ -0,0 +1,59 @@ +//Copyright (c) 2011 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose. + +#ifndef _DRAWFUCNTIONS_H +#define _DRAWFUCNTIONS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct { + short x, y; +} RDPoint; + +extern int CNFGPenX, CNFGPenY; +extern uint32_t CNFGBGColor; +extern uint32_t CNFGLastColor; +extern uint32_t CNFGDialogColor; //background for boxes + +void CNFGDrawText( const char * text, int scale ); +void CNFGDrawBox( int x1, int y1, int x2, int y2 ); +void CNFGGetTextExtents( const char * text, int * w, int * h, int textsize ); +void CNFGDrawTextbox( int x, int y, const char * text, int textsize ); //ignores pen. + +//To be provided by driver. +uint32_t CNFGColor( uint32_t RGB ); +void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h ); +void CNFGTackPixel( short x1, short y1 ); +void CNFGTackSegment( short x1, short y1, short x2, short y2 ); +void CNFGTackRectangle( short x1, short y1, short x2, short y2 ); +void CNFGTackPoly( RDPoint * points, int verts ); +void CNFGClearFrame(); +void CNFGSwapBuffers(); + +void CNFGGetDimensions( short * x, short * y ); +void CNFGSetup( const char * WindowName, int w, int h ); +void CNFGSetupFullscreen( const char * WindowName, int screen_number ); +void CNFGHandleInput(); + + +//You must provide: +void HandleKey( int keycode, int bDown ); +void HandleButton( int x, int y, int button, int bDown ); +void HandleMotion( int x, int y, int mask ); +void HandleDestroy(); + + +//Internal function for resizing rasterizer for rasterizer-mode. +void CNFGInternalResize( short x, short y ); //don't call this. + + +#ifdef __cplusplus +}; +#endif + + +#endif + diff --git a/redist/CNFGNullDriver.c b/redist/CNFGNullDriver.c new file mode 100644 index 0000000..34346cc --- /dev/null +++ b/redist/CNFGNullDriver.c @@ -0,0 +1,74 @@ +//Copyright (c) 2017 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose. + +#include "DrawFunctions.h" + +static int w, h; +void CNFGGetDimensions( short * x, short * y ) +{ + *x = w; + *y = h; +} + +static void InternalLinkScreenAndGo( const char * WindowName ) +{ +} + +void CNFGSetupFullscreen( const char * WindowName, int screen_no ) +{ + CNFGSetup( WindowName, 640, 480 ); +} + + +void CNFGTearDown() +{ +} + +void CNFGSetup( const char * WindowName, int sw, int sh ) +{ + w = sw; + h = sh; +} + +void CNFGHandleInput() +{ +} + + +void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h ) +{ +} + + +#ifndef RASTERIZER + + +uint32_t CNFGColor( uint32_t RGB ) +{ +} + +void CNFGClearFrame() +{ +} + +void CNFGSwapBuffers() +{ +} + +void CNFGTackSegment( short x1, short y1, short x2, short y2 ) +{ +} + +void CNFGTackPixel( short x1, short y1 ) +{ +} + +void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) +{ +} + +void CNFGTackPoly( RDPoint * points, int verts ) +{ +} + +#endif + diff --git a/redist/CNFGRasterizer.h b/redist/CNFGRasterizer.h new file mode 100644 index 0000000..1b8e2dd --- /dev/null +++ b/redist/CNFGRasterizer.h @@ -0,0 +1,247 @@ +//Don't call this file yourself. It is intended to be included in any drivers which want to support the rasterizer plugin. + +#ifdef RASTERIZER +#include "CNFGFunctions.h" +#include +#include + +static uint32_t * buffer = 0; +static short bufferx; +static short buffery; + + +void CNFGInternalResize( short x, short y ) +{ + bufferx = x; + buffery = y; + if( buffer ) free( buffer ); + buffer = malloc( bufferx * buffery * 4 ); +} + +static uint32_t SWAPS( uint32_t r ) +{ + uint32_t ret = (r&0xFF)<<16; + r>>=8; + ret |= (r&0xff)<<8; + r>>=8; + ret |= r; + return ret; +} + +uint32_t CNFGColor( uint32_t RGB ) +{ + CNFGLastColor = SWAPS(RGB); + return CNFGLastColor; +} + +void CNFGTackSegment( short x1, short y1, short x2, short y2 ) +{ + short tx, ty; + float slope, lp; + + short dx = x2 - x1; + short dy = y2 - y1; + + if( !buffer ) return; + + if( dx < 0 ) dx = -dx; + if( dy < 0 ) dy = -dy; + + if( dx > dy ) + { + short minx = (x1 < x2)?x1:x2; + short maxx = (x1 < x2)?x2:x1; + short miny = (x1 < x2)?y1:y2; + short maxy = (x1 < x2)?y2:y1; + float thisy = miny; + slope = (float)(maxy-miny) / (float)(maxx-minx); + + for( tx = minx; tx <= maxx; tx++ ) + { + ty = thisy; + if( tx < 0 || ty < 0 || ty >= buffery ) continue; + if( tx >= bufferx ) break; + buffer[ty * bufferx + tx] = CNFGLastColor; + thisy += slope; + } + } + else + { + short minx = (y1 < y2)?x1:x2; + short maxx = (y1 < y2)?x2:x1; + short miny = (y1 < y2)?y1:y2; + short maxy = (y1 < y2)?y2:y1; + float thisx = minx; + slope = (float)(maxx-minx) / (float)(maxy-miny); + + for( ty = miny; ty <= maxy; ty++ ) + { + tx = thisx; + if( ty < 0 || tx < 0 || tx >= bufferx ) continue; + if( ty >= buffery ) break; + buffer[ty * bufferx + tx] = CNFGLastColor; + thisx += slope; + } + } +} +void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) +{ + short minx = (x1=x2)?x1:x2; + short maxy = (y1>=y2)?y1:y2; + + short x, y; + + if( minx < 0 ) minx = 0; + if( miny < 0 ) miny = 0; + if( maxx >= bufferx ) maxx = bufferx-1; + if( maxy >= buffery ) maxy = buffery-1; + + for( y = miny; y <= maxy; y++ ) + { + uint32_t * bufferstart = &buffer[y * bufferx + minx]; + for( x = minx; x <= maxx; x++ ) + { + (*bufferstart++) = CNFGLastColor; + } + } +} + +void CNFGTackPoly( RDPoint * points, int verts ) +{ + short minx = 10000, miny = 10000; + short maxx =-10000, maxy =-10000; + short i, x, y; + + //Just in case... + if( verts > 32767 ) return; + + for( i = 0; i < verts; i++ ) + { + RDPoint * p = &points[i]; + if( p->x < minx ) minx = p->x; + if( p->y < miny ) miny = p->y; + if( p->x > maxx ) maxx = p->x; + if( p->y > maxy ) maxy = p->y; + } + + if( miny < 0 ) miny = 0; + if( maxy >= buffery ) maxy = buffery-1; + + for( y = miny; y <= maxy; y++ ) + { + short startfillx = maxx; + short endfillx = minx; + + //Figure out what line segments intersect this line. + for( i = 0; i < verts; i++ ) + { + short pl = i + 1; + if( pl == verts ) pl = 0; + + RDPoint ptop; + RDPoint pbot; + + ptop.x = points[i].x; + ptop.y = points[i].y; + pbot.x = points[pl].x; + pbot.y = points[pl].y; +//printf( "Poly: %d %d\n", pbot.y, ptop.y ); + + if( pbot.y < ptop.y ) + { + RDPoint ptmp; + ptmp.x = pbot.x; + ptmp.y = pbot.y; + pbot.x = ptop.x; + pbot.y = ptop.y; + ptop.x = ptmp.x; + ptop.y = ptmp.y; + } + + //Make sure this line segment is within our range. +//printf( "PT: %d %d %d\n", y, ptop.y, pbot.y ); + if( ptop.y <= y && pbot.y >= y ) + { + short diffy = pbot.y - ptop.y; + uint32_t placey = (uint32_t)(y - ptop.y)<<16; //Scale by 16 so we can do integer math. + short diffx = pbot.x - ptop.x; + short isectx; + + if( diffy == 0 ) + { + if( pbot.x < ptop.x ) + { + if( startfillx > pbot.x ) startfillx = pbot.x; + if( endfillx < ptop.x ) endfillx = ptop.x; + } + else + { + if( startfillx > ptop.x ) startfillx = ptop.x; + if( endfillx < pbot.x ) endfillx = pbot.x; + } + } + else + { + //Inner part is scaled by 65536, outer part must be scaled back. + isectx = (( (placey / diffy) * diffx + 32768 )>>16) + ptop.x; + if( isectx < startfillx ) startfillx = isectx; + if( isectx > endfillx ) endfillx = isectx; + } +//printf( "R: %d %d %d\n", pbot.x, ptop.x, isectx ); + } + } + +//printf( "%d %d %d\n", y, startfillx, endfillx ); + + if( endfillx >= bufferx ) endfillx = bufferx - 1; + if( endfillx >= bufferx ) endfillx = buffery - 1; + if( startfillx < 0 ) startfillx = 0; + if( startfillx < 0 ) startfillx = 0; + + unsigned int * bufferstart = &buffer[y * bufferx + startfillx]; + for( x = startfillx; x <= endfillx; x++ ) + { + (*bufferstart++) = CNFGLastColor; + } + } +//exit(1); +} + + +void CNFGClearFrame() +{ + int i, m; + uint32_t col = 0; + short x, y; + CNFGGetDimensions( &x, &y ); + if( x != bufferx || y != buffery || !buffer ) + { + bufferx = x; + buffery = y; + buffer = malloc( x * y * 8 ); + } + + m = x * y; + col = CNFGColor( CNFGBGColor ); + for( i = 0; i < m; i++ ) + { +//printf( "Got: %d %p %d\n", m, buffer, i ); + buffer[i] = col; + } +} + +void CNFGTackPixel( short x, short y ) +{ + if( x < 0 || y < 0 || x >= bufferx || y >= buffery ) return; + buffer[x+bufferx*y] = CNFGLastColor; +} + +void CNFGSwapBuffers() +{ + CNFGUpdateScreenWithBitmap( (long unsigned int*)buffer, bufferx, buffery ); +} + + +#endif diff --git a/redist/CNFGWinDriver.c b/redist/CNFGWinDriver.c new file mode 100644 index 0000000..a029419 --- /dev/null +++ b/redist/CNFGWinDriver.c @@ -0,0 +1,289 @@ +//Copyright (c) 2011 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose. +//Portion from: http://en.wikibooks.org/wiki/Windows_Programming/Window_Creation + + +#include "CNFGFunctions.h" +#include +#include +#include //for alloca + +static HBITMAP lsBitmap; +static HINSTANCE lhInstance; +static HWND lsHWND; +static HDC lsWindowHDC; +static HDC lsHDC; + + +#ifdef RASTERIZER +#include "CNFGRasterizer.h" + +void InternalHandleResize() +{ + if( lsBitmap ) DeleteObject( lsBitmap ); + + CNFGInternalResize( bufferx, buffery ); + lsBitmap = CreateBitmap( bufferx, buffery, 1, 32, buffer ); + SelectObject( lsHDC, lsBitmap ); +} +#else +static int bufferx, buffery; +static int bufferx, buffery; +static void InternalHandleResize(); +#endif + + +void CNFGGetDimensions( short * x, short * y ) +{ + *x = bufferx; + *y = buffery; +} + + + +void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h ) +{ + RECT r; + + int a = SetBitmapBits(lsBitmap,w*h*4,data); + a = BitBlt(lsWindowHDC, 0, 0, w, h, lsHDC, 0, 0, SRCCOPY); + UpdateWindow( lsHWND ); + + int thisw, thish; + + //Check to see if the window is closed. + if( !IsWindow( lsHWND ) ) + { + exit( 0 ); + } + + GetClientRect( lsHWND, &r ); + thisw = r.right - r.left; + thish = r.bottom - r.top; + if( thisw != bufferx || thish != buffery ) + { + bufferx = thisw; + buffery = thish; + InternalHandleResize(); + } +} + + +void CNFGTearDown() +{ + PostQuitMessage(0); +} + +//This was from the article +LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_DESTROY: + HandleDestroy(); + CNFGTearDown(); + return 0; + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +//This was from the article, too... well, mostly. +void CNFGSetup( const char * name_of_window, int width, int height ) +{ + static LPSTR szClassName = "MyClass"; + RECT client, window; + WNDCLASS wnd; + int w, h, wd, hd; + HINSTANCE hInstance = GetModuleHandle(NULL); + + bufferx = width; + buffery = height; + + wnd.style = CS_HREDRAW | CS_VREDRAW; //we will explain this later + wnd.lpfnWndProc = MyWndProc; + wnd.cbClsExtra = 0; + wnd.cbWndExtra = 0; + wnd.hInstance = hInstance; + wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION); //default icon + wnd.hCursor = LoadCursor(NULL, IDC_ARROW); //default arrow mouse cursor + wnd.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); + wnd.lpszMenuName = NULL; //no menu + wnd.lpszClassName = szClassName; + + if(!RegisterClass(&wnd)) //register the WNDCLASS + { + MessageBox(NULL, "This Program Requires Windows NT", "Error", MB_OK); + } + + lsHWND = CreateWindow(szClassName, + name_of_window, //name_of_window, + WS_OVERLAPPEDWINDOW, //basic window style + CW_USEDEFAULT, + CW_USEDEFAULT, //set starting point to default value + bufferx, + buffery, //set all the dimensions to default value + NULL, //no parent window + NULL, //no menu + hInstance, + NULL); //no parameters to pass + + + lsWindowHDC = GetDC( lsHWND ); + + lsHDC = CreateCompatibleDC( lsWindowHDC ); + lsBitmap = CreateCompatibleBitmap( lsWindowHDC, bufferx, buffery ); + SelectObject( lsHDC, lsBitmap ); + + //lsClearBrush = CreateSolidBrush( CNFGBGColor ); + //lsHBR = CreateSolidBrush( 0xFFFFFF ); + //lsHPEN = CreatePen( PS_SOLID, 0, 0xFFFFFF ); + + ShowWindow(lsHWND, 1); //display the window on the screen + + //Once set up... we have to change the window's borders so we get the client size right. + GetClientRect( lsHWND, &client ); + GetWindowRect( lsHWND, &window ); + w = ( window.right - window.left); + h = ( window.bottom - window.top); + wd = w - client.right; + hd = h - client.bottom; + MoveWindow( lsHWND, window.left, window.top, bufferx + wd, buffery + hd, 1 ); + + InternalHandleResize(); +} + +void CNFGHandleInput() +{ + int ldown = 0; + + MSG msg; + while( PeekMessage( &msg, lsHWND, 0, 0xFFFF, 1 ) ) + { + TranslateMessage(&msg); + + switch( msg.message ) + { + case WM_MOUSEMOVE: + HandleMotion( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, ( (msg.wParam & 0x01)?1:0) | ((msg.wParam & 0x02)?2:0) | ((msg.wParam & 0x10)?4:0) ); + break; + case WM_LBUTTONDOWN: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 1, 1 ); break; + case WM_RBUTTONDOWN: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 2, 1 ); break; + case WM_MBUTTONDOWN: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 3, 1 ); break; + case WM_LBUTTONUP: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 1, 0 ); break; + case WM_RBUTTONUP: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 2, 0 ); break; + case WM_MBUTTONUP: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 3, 0 ); break; + case WM_KEYDOWN: + case WM_KEYUP: + HandleKey( tolower( msg.wParam ), (msg.message==WM_KEYDOWN) ); + break; + default: + DispatchMessage(&msg); + break; + } + } +} + + +#ifndef RASTERIZER + +static HBITMAP lsBackBitmap; +static HDC lsWindowHDC; +static HBRUSH lsHBR; +static HPEN lsHPEN; +static HBRUSH lsClearBrush; + +static void InternalHandleResize() +{ + DeleteObject( lsBackBitmap ); + lsBackBitmap = CreateCompatibleBitmap( lsHDC, bufferx, buffery ); + SelectObject( lsHDC, lsBackBitmap ); +} + +uint32_t CNFGColor( uint32_t RGB ) +{ + CNFGLastColor = RGB; + + DeleteObject( lsHBR ); + lsHBR = CreateSolidBrush( RGB ); + SelectObject( lsHDC, lsHBR ); + + DeleteObject( lsHPEN ); + lsHPEN = CreatePen( PS_SOLID, 0, RGB ); + SelectObject( lsHDC, lsHPEN ); + + return RGB; +} + +void CNFGTackSegment( short x1, short y1, short x2, short y2 ) +{ + POINT pt[2] = { {x1, y1}, {x2, y2} }; + Polyline( lsHDC, pt, 2 ); + SetPixel( lsHDC, x1, y1, CNFGLastColor ); + SetPixel( lsHDC, x2, y2, CNFGLastColor ); +} + +void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) +{ + RECT r; + if( x1 < x2 ) { r.left = x1; r.right = x2; } + else { r.left = x2; r.right = x1; } + if( y1 < y2 ) { r.top = y1; r.bottom = y2; } + else { r.top = y2; r.bottom = y1; } + FillRect( lsHDC, &r, lsHBR ); +} + +void CNFGClearFrame() +{ + RECT r = { 0, 0, bufferx, buffery }; + DeleteObject( lsClearBrush ); + lsClearBrush = CreateSolidBrush( CNFGBGColor ); + SelectObject( lsHDC, lsClearBrush ); + + FillRect( lsHDC, &r, lsClearBrush ); +} + +void CNFGTackPoly( RDPoint * points, int verts ) +{ + int i; + POINT * t = (POINT*)alloca( sizeof( POINT ) * verts ); + for( i = 0; i < verts; i++ ) + { + t[i].x = points[i].x; + t[i].y = points[i].y; + } + Polygon( lsHDC, t, verts ); +} + + +void CNFGTackPixel( short x1, short y1 ) +{ + SetPixel( lsHDC, x1, y1, CNFGLastColor ); +} + +void CNFGSwapBuffers() +{ + int thisw, thish; + + RECT r; + BitBlt( lsWindowHDC, 0, 0, bufferx, buffery, lsHDC, 0, 0, SRCCOPY ); + UpdateWindow( lsHWND ); + //Check to see if the window is closed. + if( !IsWindow( lsHWND ) ) + { + exit( 0 ); + } + + GetClientRect( lsHWND, &r ); + thisw = r.right - r.left; + thish = r.bottom - r.top; + + if( thisw != bufferx || thish != buffery ) + { + bufferx = thisw; + buffery = thish; + InternalHandleResize(); + } +} + +void CNFGInternalResize( short bufferx, short buffery ) { } +#endif + diff --git a/redist/CNFGXDriver.c b/redist/CNFGXDriver.c new file mode 100644 index 0000000..8a8904a --- /dev/null +++ b/redist/CNFGXDriver.c @@ -0,0 +1,304 @@ +//Copyright (c) 2011 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose. +//portions from +//http://www.xmission.com/~georgeps/documentation/tutorials/Xlib_Beginner.html + +//#define HAS_XINERAMA + +#include "CNFGFunctions.h" + +#include +#include +#include +#include +#include +#ifdef HAS_XINERAMA +#include +#include +#endif +#include +#include + +XWindowAttributes CNFGWinAtt; +XClassHint *CNFGClassHint; +Display *CNFGDisplay; +Window CNFGWindow; +Pixmap CNFGPixmap; +GC CNFGGC; +GC CNFGWindowGC; +int FullScreen = 0; + +void CNFGGetDimensions( short * x, short * y ) +{ + static int lastx; + static int lasty; + + *x = CNFGWinAtt.width; + *y = CNFGWinAtt.height; + + if( lastx != *x || lasty != *y ) + { + lastx = *x; + lasty = *y; + CNFGInternalResize( lastx, lasty ); + } +} + +static void InternalLinkScreenAndGo( const char * WindowName ) +{ + XGetWindowAttributes( CNFGDisplay, CNFGWindow, &CNFGWinAtt ); + + XGetClassHint( CNFGDisplay, CNFGWindow, CNFGClassHint ); + if (!CNFGClassHint) { + CNFGClassHint = XAllocClassHint(); + if (CNFGClassHint) { + CNFGClassHint->res_name = "cnping"; + CNFGClassHint->res_class = "cnping"; + XSetClassHint( CNFGDisplay, CNFGWindow, CNFGClassHint ); + } else { + fprintf( stderr, "Failed to allocate XClassHint!\n" ); + } + } else { + fprintf( stderr, "Pre-existing XClassHint\n" ); + } + + XSelectInput (CNFGDisplay, CNFGWindow, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ExposureMask | PointerMotionMask ); + XSetStandardProperties( CNFGDisplay, CNFGWindow, WindowName, WindowName, None, NULL, 0, NULL ); + + CNFGWindowGC = XCreateGC(CNFGDisplay, CNFGWindow, 0, 0); + + CNFGPixmap = XCreatePixmap( CNFGDisplay, CNFGWindow, CNFGWinAtt.width, CNFGWinAtt.height, CNFGWinAtt.depth ); + CNFGGC = XCreateGC(CNFGDisplay, CNFGPixmap, 0, 0); +} + +void CNFGSetupFullscreen( const char * WindowName, int screen_no ) +{ +#ifdef HAS_XINERAMA + XineramaScreenInfo *screeninfo = NULL; + int screens; + int event_basep, error_basep, a, b; + CNFGDisplay = XOpenDisplay(NULL); + int screen = XDefaultScreen(CNFGDisplay); + int xpos, ypos; + + if (!XShapeQueryExtension(CNFGDisplay, &event_basep, &error_basep)) + { + fprintf( stderr, "X-Server does not support shape extension" ); + exit( 1 ); + } + + Visual * visual = DefaultVisual(CNFGDisplay, screen); + CNFGWinAtt.depth = DefaultDepth(CNFGDisplay, screen); + + if (XineramaQueryExtension(CNFGDisplay, &a, &b ) && + (screeninfo = XineramaQueryScreens(CNFGDisplay, &screens)) && + XineramaIsActive(CNFGDisplay) && screen_no >= 0 && + screen_no < screens ) { + + CNFGWinAtt.width = screeninfo[screen_no].width; + CNFGWinAtt.height = screeninfo[screen_no].height; + xpos = screeninfo[screen_no].x_org; + ypos = screeninfo[screen_no].y_org; + } else + { + CNFGWinAtt.width = XDisplayWidth(CNFGDisplay, screen); + CNFGWinAtt.height = XDisplayHeight(CNFGDisplay, screen); + xpos = 0; + ypos = 0; + } + if (screeninfo) + XFree(screeninfo); + + + XSetWindowAttributes setwinattr; + setwinattr.override_redirect = 1; + setwinattr.save_under = 1; + setwinattr.event_mask = StructureNotifyMask | SubstructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonPressMask | PointerMotionMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask |KeyPressMask |KeyReleaseMask | SubstructureNotifyMask | FocusChangeMask; + setwinattr.border_pixel = 0; + + CNFGWindow = XCreateWindow(CNFGDisplay, XRootWindow(CNFGDisplay, screen), + xpos, ypos, CNFGWinAtt.width, CNFGWinAtt.height, + 0, CNFGWinAtt.depth, InputOutput, visual, CWBorderPixel | CWEventMask | CWOverrideRedirect | CWSaveUnder, &setwinattr); + + XMapWindow(CNFGDisplay, CNFGWindow); + XSetInputFocus( CNFGDisplay, CNFGWindow, RevertToParent, CurrentTime ); + XFlush(CNFGDisplay); + FullScreen = 1; +//printf( "%d %d %d %d\n", xpos, ypos, CNFGWinAtt.width, CNFGWinAtt.height ); + InternalLinkScreenAndGo( WindowName ); +/* + setwinattr.override_redirect = 1; + XChangeWindowAttributes( + CNFGDisplay, CNFGWindow, + CWBorderPixel | CWEventMask | CWOverrideRedirect, &setwinattr); +*/ +#else + CNFGSetup( WindowName, 640, 480 ); +#endif +} + + +void CNFGTearDown() +{ + if ( CNFGClassHint ) XFree( CNFGClassHint ); + if ( CNFGGC ) XFreeGC( CNFGDisplay, CNFGGC ); + if ( CNFGWindowGC ) XFreeGC( CNFGDisplay, CNFGWindowGC ); + if ( CNFGDisplay ) XCloseDisplay( CNFGDisplay ); + CNFGDisplay = NULL; + CNFGWindowGC = CNFGGC = NULL; + CNFGClassHint = NULL; +} + +void CNFGSetup( const char * WindowName, int w, int h ) +{ + CNFGDisplay = XOpenDisplay(NULL); + atexit( CNFGTearDown ); + XGetWindowAttributes( CNFGDisplay, RootWindow(CNFGDisplay, 0), &CNFGWinAtt ); + + int depth = CNFGWinAtt.depth; + CNFGWindow = XCreateWindow(CNFGDisplay, RootWindow(CNFGDisplay, 0), 1, 1, w, h, 0, depth, InputOutput, CopyFromParent, 0, 0 ); + XMapWindow(CNFGDisplay, CNFGWindow); + XFlush(CNFGDisplay); + + InternalLinkScreenAndGo( WindowName ); + + Atom WM_DELETE_WINDOW = XInternAtom( CNFGDisplay, "WM_DELETE_WINDOW", False ); + XSetWMProtocols( CNFGDisplay, CNFGWindow, &WM_DELETE_WINDOW, 1 ); + XSelectInput( CNFGDisplay, CNFGWindow, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ExposureMask | PointerMotionMask ); +} + +void CNFGHandleInput() +{ + static int ButtonsDown; + XEvent report; + + int bKeyDirection = 1; + int r; + while( XPending( CNFGDisplay ) ) + { + r=XNextEvent( CNFGDisplay, &report ); + + bKeyDirection = 1; + switch (report.type) + { + case NoExpose: + break; + case Expose: + XGetWindowAttributes( CNFGDisplay, CNFGWindow, &CNFGWinAtt ); + if( CNFGPixmap ) XFreePixmap( CNFGDisplay, CNFGPixmap ); + CNFGPixmap = XCreatePixmap( CNFGDisplay, CNFGWindow, CNFGWinAtt.width, CNFGWinAtt.height, CNFGWinAtt.depth ); + if( CNFGGC ) XFreeGC( CNFGDisplay, CNFGGC ); + CNFGGC = XCreateGC(CNFGDisplay, CNFGPixmap, 0, 0); + break; + case KeyRelease: + bKeyDirection = 0; + case KeyPress: + HandleKey( XLookupKeysym(&report.xkey, 0), bKeyDirection ); + break; + case ButtonRelease: + bKeyDirection = 0; + case ButtonPress: + HandleButton( report.xbutton.x, report.xbutton.y, report.xbutton.button, bKeyDirection ); + ButtonsDown = (ButtonsDown & (~(1<>1 ); + break; + case ClientMessage: + // Only subscribed to WM_DELETE_WINDOW, so just exit + exit( 0 ); + break; + default: + printf( "Event: %d\n", report.type ); + } + } +} + + +void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h ) +{ + static XImage *xi; + static int depth; + static int lw, lh; + static unsigned char * lbuffer; + int r, ls; + + if( !xi ) + { + int screen = DefaultScreen(CNFGDisplay); + Visual * visual = DefaultVisual(CNFGDisplay, screen); + depth = DefaultDepth(CNFGDisplay, screen)/8; +// xi = XCreateImage(CNFGDisplay, DefaultVisual( CNFGDisplay, DefaultScreen(CNFGDisplay) ), depth*8, ZPixmap, 0, (char*)data, w, h, 32, w*4 ); +// lw = w; +// lh = h; + } + + if( lw != w || lh != h ) + { + if( xi ) free( xi ); + xi = XCreateImage(CNFGDisplay, DefaultVisual( CNFGDisplay, DefaultScreen(CNFGDisplay) ), depth*8, ZPixmap, 0, (char*)data, w, h, 32, w*4 ); + lw = w; + lh = h; + } + + ls = lw * lh; + + XPutImage(CNFGDisplay, CNFGWindow, CNFGWindowGC, xi, 0, 0, 0, 0, w, h ); +} + + +#ifndef RASTERIZER + + +uint32_t CNFGColor( uint32_t RGB ) +{ + unsigned char red = RGB & 0xFF; + unsigned char grn = ( RGB >> 8 ) & 0xFF; + unsigned char blu = ( RGB >> 16 ) & 0xFF; + CNFGLastColor = RGB; + unsigned long color = (red<<16)|(grn<<8)|(blu); + XSetForeground(CNFGDisplay, CNFGGC, color); + return color; +} + +void CNFGClearFrame() +{ + XGetWindowAttributes( CNFGDisplay, CNFGWindow, &CNFGWinAtt ); + XSetForeground(CNFGDisplay, CNFGGC, CNFGColor(CNFGBGColor) ); + XFillRectangle(CNFGDisplay, CNFGPixmap, CNFGGC, 0, 0, CNFGWinAtt.width, CNFGWinAtt.height ); +} + +void CNFGSwapBuffers() +{ + XCopyArea(CNFGDisplay, CNFGPixmap, CNFGWindow, CNFGWindowGC, 0,0,CNFGWinAtt.width,CNFGWinAtt.height,0,0); + XFlush(CNFGDisplay); + if( FullScreen ) + XSetInputFocus( CNFGDisplay, CNFGWindow, RevertToParent, CurrentTime ); +} + +void CNFGTackSegment( short x1, short y1, short x2, short y2 ) +{ + XDrawLine( CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1, x2, y2 ); +} + +void CNFGTackPixel( short x1, short y1 ) +{ + XDrawPoint( CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1 ); +} + +void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) +{ + XFillRectangle(CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1, x2-x1, y2-y1 ); +} + +void CNFGTackPoly( RDPoint * points, int verts ) +{ + XFillPolygon(CNFGDisplay, CNFGPixmap, CNFGGC, (XPoint *)points, 3, Convex, CoordModeOrigin ); +} + +void CNFGInternalResize( short x, short y ) { } + +#else +#include "CNFGRasterizer.h" +#endif + diff --git a/redist/DrawFunctions.c b/redist/DrawFunctions.c deleted file mode 100644 index f4f27d2..0000000 --- a/redist/DrawFunctions.c +++ /dev/null @@ -1,277 +0,0 @@ -/* -Copyright (c) 2010, 2011 Charles Lohr - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "DrawFunctions.h" -#include - -int CNFGPenX, CNFGPenY; -uint32_t CNFGBGColor; -uint32_t CNFGLastColor; -uint32_t CNFGDialogColor; //background for boxes - -const unsigned short FontCharMap[256] = { - 65535, 0, 10, 20, 32, 44, 56, 68, 70, 65535, 65535, 80, 92, 65535, 104, 114, - 126, 132, 138, 148, 156, 166, 180, 188, 200, 206, 212, 218, 224, 228, 238, 244, - 65535, 250, 254, 258, 266, 278, 288, 302, 304, 310, 316, 324, 328, 226, 252, 330, - 332, 342, 348, 358, 366, 372, 382, 392, 400, 410, 420, 424, 428, 262, 432, 436, - 446, 460, 470, 486, 496, 508, 516, 522, 536, 542, 548, 556, 568, 572, 580, 586, - 598, 608, 622, 634, 644, 648, 654, 662, 670, 682, 692, 700, 706, 708, 492, 198, - 714, 716, 726, 734, 742, 750, 760, 768, 782, 790, 794, 802, 204, 810, 820, 384, - 828, 836, 844, 850, 860, 864, 872, 880, 890, 894, 902, 908, 916, 920, 928, 934, - 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, - 944, 948, 960, 970, 986, 996, 1000, 1016, 1020, 1026, 1034, 1042, 364, 1046, 1056, 1058, - 1066, 1072, 1080, 932, 1092, 1100, 68, 1110, 1114, 1116, 1124, 1132, 1142, 1154, 1170, 1180, - 1192, 1204, 1218, 1234, 1248, 1264, 1276, 1290, 1300, 1310, 1322, 1334, 1342, 1350, 1360, 1370, - 1384, 1396, 1406, 1416, 1428, 1442, 1454, 1458, 1472, 1480, 1488, 1498, 1508, 1520, 1530, 1544, - 1556, 1568, 1582, 1598, 1612, 1628, 1642, 1654, 1666, 1678, 1692, 1706, 1710, 1714, 1720, 1726, - 1738, 1752, 1762, 1772, 1784, 1798, 1810, 1816, 1826, 1836, 1846, 1858, 1870, 1880, 1890, 65535, }; - -const unsigned char FontCharData[1902] = { - 0x00, 0x01, 0x20, 0x21, 0x03, 0x23, 0x23, 0x14, 0x14, 0x83, 0x00, 0x01, 0x20, 0x21, 0x04, 0x24, - 0x24, 0x13, 0x13, 0x84, 0x01, 0x21, 0x21, 0x23, 0x23, 0x14, 0x14, 0x03, 0x03, 0x01, 0x11, 0x92, - 0x11, 0x22, 0x22, 0x23, 0x23, 0x14, 0x14, 0x03, 0x03, 0x02, 0x02, 0x91, 0x01, 0x21, 0x21, 0x23, - 0x23, 0x01, 0x03, 0x21, 0x03, 0x01, 0x12, 0x94, 0x03, 0x23, 0x13, 0x14, 0x23, 0x22, 0x22, 0x11, - 0x11, 0x02, 0x02, 0x83, 0x12, 0x92, 0x12, 0x12, 0x01, 0x21, 0x21, 0x23, 0x23, 0x03, 0x03, 0x81, - 0x03, 0x21, 0x21, 0x22, 0x21, 0x11, 0x03, 0x14, 0x14, 0x23, 0x23, 0x92, 0x01, 0x10, 0x10, 0x21, - 0x21, 0x12, 0x12, 0x01, 0x12, 0x14, 0x03, 0xa3, 0x02, 0x03, 0x03, 0x13, 0x02, 0x12, 0x13, 0x10, - 0x10, 0xa1, 0x01, 0x23, 0x03, 0x21, 0x02, 0x11, 0x11, 0x22, 0x22, 0x13, 0x13, 0x82, 0x00, 0x22, - 0x22, 0x04, 0x04, 0x80, 0x20, 0x02, 0x02, 0x24, 0x24, 0xa0, 0x01, 0x10, 0x10, 0x21, 0x10, 0x14, - 0x14, 0x03, 0x14, 0xa3, 0x00, 0x03, 0x04, 0x04, 0x20, 0x23, 0x24, 0xa4, 0x00, 0x20, 0x00, 0x02, - 0x02, 0x22, 0x10, 0x14, 0x20, 0xa4, 0x01, 0x21, 0x21, 0x23, 0x23, 0x03, 0x03, 0x01, 0x20, 0x10, - 0x10, 0x14, 0x14, 0x84, 0x03, 0x23, 0x23, 0x24, 0x24, 0x04, 0x04, 0x83, 0x01, 0x10, 0x10, 0x21, - 0x10, 0x14, 0x14, 0x03, 0x14, 0x23, 0x04, 0xa4, 0x01, 0x10, 0x21, 0x10, 0x10, 0x94, 0x03, 0x14, - 0x23, 0x14, 0x10, 0x94, 0x02, 0x22, 0x22, 0x11, 0x22, 0x93, 0x02, 0x22, 0x02, 0x11, 0x02, 0x93, - 0x01, 0x02, 0x02, 0xa2, 0x02, 0x22, 0x22, 0x11, 0x11, 0x02, 0x02, 0x13, 0x13, 0xa2, 0x11, 0x22, - 0x22, 0x02, 0x02, 0x91, 0x02, 0x13, 0x13, 0x22, 0x22, 0x82, 0x10, 0x13, 0x14, 0x94, 0x10, 0x01, - 0x20, 0x91, 0x10, 0x14, 0x20, 0x24, 0x01, 0x21, 0x03, 0xa3, 0x21, 0x10, 0x10, 0x01, 0x01, 0x23, - 0x23, 0x14, 0x14, 0x03, 0x10, 0x94, 0x00, 0x01, 0x23, 0x24, 0x04, 0x03, 0x03, 0x21, 0x21, 0xa0, - 0x21, 0x10, 0x10, 0x01, 0x01, 0x12, 0x12, 0x03, 0x03, 0x14, 0x14, 0x23, 0x02, 0xa4, 0x10, 0x91, - 0x10, 0x01, 0x01, 0x03, 0x03, 0x94, 0x10, 0x21, 0x21, 0x23, 0x23, 0x94, 0x01, 0x23, 0x11, 0x13, - 0x21, 0x03, 0x02, 0xa2, 0x02, 0x22, 0x11, 0x93, 0x31, 0xc0, 0x03, 0xa1, 0x00, 0x20, 0x20, 0x24, - 0x24, 0x04, 0x04, 0x00, 0x12, 0x92, 0x01, 0x10, 0x10, 0x14, 0x04, 0xa4, 0x01, 0x10, 0x10, 0x21, - 0x21, 0x22, 0x22, 0x04, 0x04, 0xa4, 0x00, 0x20, 0x20, 0x24, 0x24, 0x04, 0x12, 0xa2, 0x00, 0x02, - 0x02, 0x22, 0x20, 0xa4, 0x20, 0x00, 0x00, 0x02, 0x02, 0x22, 0x22, 0x24, 0x24, 0x84, 0x20, 0x02, - 0x02, 0x22, 0x22, 0x24, 0x24, 0x04, 0x04, 0x82, 0x00, 0x20, 0x20, 0x21, 0x21, 0x12, 0x12, 0x94, - 0x00, 0x04, 0x00, 0x20, 0x20, 0x24, 0x04, 0x24, 0x02, 0xa2, 0x00, 0x02, 0x02, 0x22, 0x22, 0x20, - 0x20, 0x00, 0x22, 0x84, 0x11, 0x11, 0x13, 0x93, 0x11, 0x11, 0x13, 0x84, 0x20, 0x02, 0x02, 0xa4, - 0x00, 0x22, 0x22, 0x84, 0x01, 0x10, 0x10, 0x21, 0x21, 0x12, 0x12, 0x13, 0x14, 0x94, 0x21, 0x01, - 0x01, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x12, 0x12, 0x13, 0x13, 0xa3, 0x04, 0x01, 0x01, 0x10, - 0x10, 0x21, 0x21, 0x24, 0x02, 0xa2, 0x00, 0x04, 0x04, 0x14, 0x14, 0x23, 0x23, 0x12, 0x12, 0x02, - 0x12, 0x21, 0x21, 0x10, 0x10, 0x80, 0x23, 0x14, 0x14, 0x03, 0x03, 0x01, 0x01, 0x10, 0x10, 0xa1, - 0x00, 0x10, 0x10, 0x21, 0x21, 0x23, 0x23, 0x14, 0x14, 0x04, 0x04, 0x80, 0x00, 0x04, 0x04, 0x24, - 0x00, 0x20, 0x02, 0x92, 0x00, 0x04, 0x00, 0x20, 0x02, 0x92, 0x21, 0x10, 0x10, 0x01, 0x01, 0x03, - 0x03, 0x14, 0x14, 0x23, 0x23, 0x22, 0x22, 0x92, 0x00, 0x04, 0x20, 0x24, 0x02, 0xa2, 0x00, 0x20, - 0x10, 0x14, 0x04, 0xa4, 0x00, 0x20, 0x20, 0x23, 0x23, 0x14, 0x14, 0x83, 0x00, 0x04, 0x02, 0x12, - 0x12, 0x21, 0x21, 0x20, 0x12, 0x23, 0x23, 0xa4, 0x00, 0x04, 0x04, 0xa4, 0x04, 0x00, 0x00, 0x11, - 0x11, 0x20, 0x20, 0xa4, 0x04, 0x00, 0x00, 0x22, 0x20, 0xa4, 0x01, 0x10, 0x10, 0x21, 0x21, 0x23, - 0x23, 0x14, 0x14, 0x03, 0x03, 0x81, 0x00, 0x04, 0x00, 0x10, 0x10, 0x21, 0x21, 0x12, 0x12, 0x82, - 0x01, 0x10, 0x10, 0x21, 0x21, 0x23, 0x23, 0x14, 0x14, 0x03, 0x03, 0x01, 0x04, 0x93, 0x00, 0x04, - 0x00, 0x10, 0x10, 0x21, 0x21, 0x12, 0x12, 0x02, 0x02, 0xa4, 0x21, 0x10, 0x10, 0x01, 0x01, 0x23, - 0x23, 0x14, 0x14, 0x83, 0x00, 0x20, 0x10, 0x94, 0x00, 0x04, 0x04, 0x24, 0x24, 0xa0, 0x00, 0x03, - 0x03, 0x14, 0x14, 0x23, 0x23, 0xa0, 0x00, 0x04, 0x04, 0x24, 0x14, 0x13, 0x24, 0xa0, 0x00, 0x01, - 0x01, 0x23, 0x23, 0x24, 0x04, 0x03, 0x03, 0x21, 0x21, 0xa0, 0x00, 0x01, 0x01, 0x12, 0x12, 0x14, - 0x12, 0x21, 0x21, 0xa0, 0x00, 0x20, 0x20, 0x02, 0x02, 0x04, 0x04, 0xa4, 0x10, 0x00, 0x00, 0x04, - 0x04, 0x94, 0x01, 0xa3, 0x10, 0x20, 0x20, 0x24, 0x24, 0x94, 0x00, 0x91, 0x02, 0x04, 0x04, 0x24, - 0x24, 0x22, 0x23, 0x12, 0x12, 0x82, 0x00, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x82, 0x24, 0x04, - 0x04, 0x03, 0x03, 0x12, 0x12, 0xa2, 0x20, 0x24, 0x24, 0x04, 0x04, 0x02, 0x02, 0xa2, 0x24, 0x04, - 0x04, 0x02, 0x02, 0x22, 0x22, 0x23, 0x23, 0x93, 0x04, 0x01, 0x02, 0x12, 0x01, 0x10, 0x10, 0xa1, - 0x23, 0x12, 0x12, 0x03, 0x03, 0x14, 0x14, 0x23, 0x23, 0x24, 0x24, 0x15, 0x15, 0x84, 0x00, 0x04, - 0x03, 0x12, 0x12, 0x23, 0x23, 0xa4, 0x11, 0x11, 0x12, 0x94, 0x22, 0x22, 0x23, 0x24, 0x24, 0x15, - 0x15, 0x84, 0x00, 0x04, 0x03, 0x13, 0x13, 0x22, 0x13, 0xa4, 0x02, 0x04, 0x02, 0x13, 0x12, 0x14, - 0x12, 0x23, 0x23, 0xa4, 0x02, 0x04, 0x03, 0x12, 0x12, 0x23, 0x23, 0xa4, 0x02, 0x05, 0x04, 0x24, - 0x24, 0x22, 0x22, 0x82, 0x02, 0x04, 0x04, 0x24, 0x25, 0x22, 0x22, 0x82, 0x02, 0x04, 0x03, 0x12, - 0x12, 0xa2, 0x22, 0x02, 0x02, 0x03, 0x03, 0x23, 0x23, 0x24, 0x24, 0x84, 0x11, 0x14, 0x02, 0xa2, - 0x02, 0x04, 0x04, 0x14, 0x14, 0x23, 0x24, 0xa2, 0x02, 0x03, 0x03, 0x14, 0x14, 0x23, 0x23, 0xa2, - 0x02, 0x03, 0x03, 0x14, 0x14, 0x12, 0x13, 0x24, 0x24, 0xa2, 0x02, 0x24, 0x04, 0xa2, 0x02, 0x03, - 0x03, 0x14, 0x22, 0x23, 0x23, 0x85, 0x02, 0x22, 0x22, 0x04, 0x04, 0xa4, 0x20, 0x10, 0x10, 0x14, - 0x14, 0x24, 0x12, 0x82, 0x10, 0x11, 0x13, 0x94, 0x00, 0x10, 0x10, 0x14, 0x14, 0x04, 0x12, 0xa2, - 0x01, 0x10, 0x10, 0x11, 0x11, 0xa0, 0x03, 0x04, 0x04, 0x24, 0x24, 0x23, 0x23, 0x12, 0x12, 0x83, - 0x10, 0x10, 0x11, 0x94, 0x21, 0x10, 0x10, 0x01, 0x01, 0x02, 0x02, 0x13, 0x13, 0x22, 0x10, 0x93, - 0x11, 0x00, 0x00, 0x04, 0x04, 0x24, 0x24, 0x23, 0x02, 0x92, 0x01, 0x02, 0x11, 0x21, 0x22, 0x23, - 0x03, 0x13, 0x02, 0x11, 0x11, 0x22, 0x22, 0x13, 0x13, 0x82, 0x00, 0x11, 0x11, 0x20, 0x11, 0x14, - 0x02, 0x22, 0x03, 0xa3, 0x10, 0x12, 0x13, 0x95, 0x20, 0x00, 0x00, 0x02, 0x02, 0x11, 0x11, 0x22, - 0x02, 0x13, 0x13, 0x22, 0x22, 0x24, 0x24, 0x84, 0x00, 0x00, 0x20, 0xa0, 0x20, 0x10, 0x10, 0x11, - 0x11, 0xa1, 0x10, 0x21, 0x20, 0x21, 0x21, 0x11, 0x11, 0x90, 0x11, 0x02, 0x02, 0x13, 0x21, 0x12, - 0x12, 0xa3, 0x01, 0x21, 0x21, 0xa2, 0x10, 0x20, 0x20, 0x21, 0x21, 0x11, 0x12, 0x10, 0x11, 0xa2, - 0x00, 0xa0, 0x01, 0x10, 0x10, 0x21, 0x21, 0x12, 0x12, 0x81, 0x02, 0x22, 0x11, 0x13, 0x03, 0xa3, - 0x01, 0x10, 0x10, 0x21, 0x21, 0x03, 0x03, 0xa3, 0x01, 0x10, 0x10, 0x21, 0x21, 0x12, 0x12, 0x02, - 0x12, 0x23, 0x23, 0x83, 0x02, 0x05, 0x04, 0x14, 0x14, 0x23, 0x22, 0xa4, 0x14, 0x10, 0x10, 0x01, - 0x01, 0x12, 0x10, 0x20, 0x20, 0xa4, 0x14, 0x15, 0x15, 0x85, 0x20, 0xa1, 0x10, 0x20, 0x20, 0x21, - 0x21, 0x11, 0x11, 0x90, 0x01, 0x12, 0x12, 0x03, 0x11, 0x22, 0x22, 0x93, 0x00, 0x01, 0x02, 0x20, - 0x12, 0x13, 0x13, 0x23, 0x22, 0xa4, 0x00, 0x01, 0x02, 0x20, 0x12, 0x22, 0x22, 0x13, 0x13, 0x14, - 0x14, 0xa4, 0x00, 0x10, 0x10, 0x11, 0x11, 0x01, 0x11, 0x02, 0x02, 0x20, 0x12, 0x13, 0x13, 0x23, - 0x22, 0xa4, 0x10, 0x10, 0x11, 0x12, 0x12, 0x03, 0x03, 0x14, 0x14, 0xa3, 0x04, 0x02, 0x02, 0x11, - 0x11, 0x22, 0x22, 0x24, 0x03, 0x23, 0x10, 0xa1, 0x04, 0x02, 0x02, 0x11, 0x11, 0x22, 0x22, 0x24, - 0x03, 0x23, 0x01, 0x90, 0x04, 0x02, 0x02, 0x11, 0x11, 0x22, 0x22, 0x24, 0x03, 0x23, 0x01, 0x10, - 0x10, 0xa1, 0x04, 0x02, 0x02, 0x11, 0x11, 0x22, 0x22, 0x24, 0x03, 0x23, 0x01, 0x10, 0x10, 0x11, - 0x11, 0xa0, 0x04, 0x02, 0x02, 0x11, 0x11, 0x22, 0x22, 0x24, 0x03, 0x23, 0x00, 0x00, 0x20, 0xa0, - 0x04, 0x02, 0x02, 0x11, 0x11, 0x22, 0x22, 0x24, 0x03, 0x23, 0x00, 0x20, 0x20, 0x11, 0x11, 0x80, - 0x00, 0x04, 0x02, 0x22, 0x00, 0x11, 0x10, 0x14, 0x10, 0x20, 0x14, 0xa4, 0x23, 0x14, 0x14, 0x03, - 0x03, 0x01, 0x01, 0x10, 0x10, 0x21, 0x14, 0x15, 0x15, 0x85, 0x02, 0x22, 0x02, 0x04, 0x04, 0x24, - 0x03, 0x13, 0x00, 0x91, 0x02, 0x22, 0x02, 0x04, 0x04, 0x24, 0x03, 0x13, 0x11, 0xa0, 0x02, 0x22, - 0x02, 0x04, 0x04, 0x24, 0x03, 0x13, 0x01, 0x10, 0x10, 0xa1, 0x02, 0x22, 0x02, 0x04, 0x04, 0x24, - 0x03, 0x13, 0x00, 0x00, 0x20, 0xa0, 0x02, 0x22, 0x12, 0x14, 0x04, 0x24, 0x00, 0x91, 0x02, 0x22, - 0x12, 0x14, 0x04, 0x24, 0x11, 0xa0, 0x02, 0x22, 0x12, 0x14, 0x04, 0x24, 0x01, 0x10, 0x10, 0xa1, - 0x02, 0x22, 0x12, 0x14, 0x04, 0x24, 0x20, 0x20, 0x00, 0x80, 0x00, 0x10, 0x10, 0x21, 0x21, 0x23, - 0x23, 0x14, 0x14, 0x04, 0x04, 0x00, 0x02, 0x92, 0x04, 0x02, 0x02, 0x24, 0x24, 0x22, 0x01, 0x10, - 0x10, 0x11, 0x11, 0xa0, 0x02, 0x22, 0x22, 0x24, 0x24, 0x04, 0x04, 0x02, 0x00, 0x91, 0x02, 0x22, - 0x22, 0x24, 0x24, 0x04, 0x04, 0x02, 0x11, 0xa0, 0x02, 0x22, 0x22, 0x24, 0x24, 0x04, 0x04, 0x02, - 0x11, 0x20, 0x00, 0x91, 0x02, 0x22, 0x22, 0x24, 0x24, 0x04, 0x04, 0x02, 0x01, 0x10, 0x10, 0x11, - 0x11, 0xa0, 0x01, 0x21, 0x21, 0x24, 0x24, 0x04, 0x04, 0x01, 0x00, 0x00, 0x20, 0xa0, 0x01, 0x23, - 0x03, 0xa1, 0x01, 0x10, 0x10, 0x21, 0x21, 0x23, 0x23, 0x14, 0x14, 0x03, 0x03, 0x01, 0x03, 0xa1, - 0x01, 0x04, 0x04, 0x24, 0x24, 0x21, 0x11, 0xa0, 0x01, 0x04, 0x04, 0x24, 0x24, 0x21, 0x00, 0x91, - 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x01, 0x10, 0x10, 0xa1, 0x01, 0x04, 0x04, 0x24, 0x24, 0x21, - 0x00, 0x00, 0x20, 0xa0, 0x01, 0x02, 0x02, 0x13, 0x13, 0x14, 0x13, 0x22, 0x22, 0x21, 0x11, 0xa0, - 0x00, 0x04, 0x01, 0x11, 0x11, 0x22, 0x22, 0x13, 0x13, 0x83, 0x00, 0x05, 0x00, 0x10, 0x10, 0x21, - 0x21, 0x12, 0x02, 0x22, 0x22, 0x24, 0x24, 0x84, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x23, 0x12, - 0x12, 0x02, 0x00, 0x91, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x23, 0x12, 0x12, 0x02, 0x11, 0xa0, - 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x23, 0x12, 0x12, 0x02, 0x01, 0x10, 0x10, 0xa1, 0x02, 0x04, - 0x04, 0x24, 0x24, 0x22, 0x23, 0x12, 0x12, 0x02, 0x01, 0x10, 0x10, 0x11, 0x11, 0xa0, 0x02, 0x04, - 0x04, 0x24, 0x24, 0x22, 0x23, 0x12, 0x12, 0x02, 0x01, 0x01, 0x21, 0xa1, 0x02, 0x04, 0x04, 0x24, - 0x24, 0x22, 0x23, 0x12, 0x12, 0x02, 0x01, 0x10, 0x10, 0x21, 0x21, 0x81, 0x02, 0x13, 0x02, 0x04, - 0x04, 0x24, 0x12, 0x14, 0x12, 0x22, 0x13, 0x23, 0x22, 0xa3, 0x03, 0x04, 0x04, 0x24, 0x03, 0x12, - 0x12, 0x22, 0x14, 0x15, 0x15, 0x85, 0x24, 0x04, 0x04, 0x02, 0x02, 0x22, 0x22, 0x23, 0x23, 0x13, - 0x00, 0x91, 0x24, 0x04, 0x04, 0x02, 0x02, 0x22, 0x22, 0x23, 0x23, 0x13, 0x11, 0xa0, 0x24, 0x04, - 0x04, 0x02, 0x02, 0x22, 0x22, 0x23, 0x23, 0x13, 0x01, 0x10, 0x10, 0xa1, 0x24, 0x04, 0x04, 0x02, - 0x02, 0x22, 0x22, 0x23, 0x23, 0x13, 0x01, 0x01, 0x21, 0xa1, 0x12, 0x14, 0x00, 0x91, 0x12, 0x14, - 0x11, 0xa0, 0x12, 0x14, 0x01, 0x10, 0x10, 0xa1, 0x12, 0x14, 0x01, 0x01, 0x21, 0xa1, 0x00, 0x22, - 0x11, 0x20, 0x02, 0x22, 0x22, 0x24, 0x24, 0x04, 0x04, 0x82, 0x02, 0x04, 0x03, 0x12, 0x12, 0x23, - 0x23, 0x24, 0x01, 0x10, 0x10, 0x11, 0x11, 0xa0, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x02, - 0x00, 0x91, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x02, 0x11, 0xa0, 0x02, 0x04, 0x04, 0x24, - 0x24, 0x22, 0x22, 0x02, 0x01, 0x10, 0x10, 0xa1, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x02, - 0x01, 0x10, 0x10, 0x11, 0x11, 0xa0, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x02, 0x01, 0x01, - 0x21, 0xa1, 0x11, 0x11, 0x02, 0x22, 0x13, 0x93, 0x02, 0x04, 0x04, 0x24, 0x24, 0x22, 0x22, 0x02, - 0x04, 0xa2, 0x02, 0x04, 0x04, 0x14, 0x14, 0x23, 0x24, 0x22, 0x00, 0x91, 0x02, 0x04, 0x04, 0x14, - 0x14, 0x23, 0x24, 0x22, 0x11, 0xa0, 0x02, 0x04, 0x04, 0x14, 0x14, 0x23, 0x24, 0x22, 0x01, 0x10, - 0x10, 0xa1, 0x02, 0x04, 0x04, 0x14, 0x14, 0x23, 0x24, 0x22, 0x01, 0x01, 0x21, 0xa1, 0x02, 0x03, - 0x03, 0x14, 0x22, 0x23, 0x23, 0x05, 0x11, 0xa0, 0x00, 0x04, 0x02, 0x11, 0x11, 0x22, 0x22, 0x13, - 0x13, 0x82, 0x02, 0x03, 0x03, 0x14, 0x22, 0x23, 0x23, 0x05, 0x01, 0x01, 0x21, 0xa1, }; - - - -void CNFGDrawText( const char * text, int scale ) -{ - const unsigned char * lmap; - float iox = (float)CNFGPenX; - float ioy = (float)CNFGPenY; - - int place = 0; - unsigned short index; - int bQuit = 0; - while( text[place] ) - { - unsigned char c = text[place]; - - switch( c ) - { - case 9: - iox += 12 * scale; - break; - case 10: - iox = (float)CNFGPenX; - ioy += 6 * scale; - break; - default: - index = FontCharMap[c]; - if( index == 65535 ) - { - iox += 3 * scale; - break; - } - - lmap = &FontCharData[index]; - do - { - int x1 = (int)((((*lmap) & 0x70)>>4)*scale + iox); - int y1 = (int)(((*lmap) & 0x0f)*scale + ioy); - int x2 = (int)((((*(lmap+1)) & 0x70)>>4)*scale + iox); - int y2 = (int)(((*(lmap+1)) & 0x0f)*scale + ioy); - lmap++; - if(x1 == x2 && y1 == y2){ - CNFGTackPixel( x1, y1 ); - } else { - CNFGTackSegment( x1, y1, x2, y2 ); - } - bQuit = *lmap & 0x80; - lmap++; - } while( !bQuit ); - - iox += 3 * scale; - } - place++; - } -} - - -void CNFGDrawBox( int x1, int y1, int x2, int y2 ) -{ - unsigned lc = CNFGLastColor; - CNFGColor( CNFGDialogColor ); - CNFGTackRectangle( x1, y1, x2, y2 ); - CNFGColor( lc ); - CNFGTackSegment( x1, y1, x2, y1 ); - CNFGTackSegment( x2, y1, x2, y2 ); - CNFGTackSegment( x2, y2, x1, y2 ); - CNFGTackSegment( x1, y2, x1, y1 ); -} - -void CNFGGetTextExtents( const char * text, int * w, int * h, int textsize ) -{ - int charsx = 0; - int charsy = 1; - int charsline = 0; - const char * s; - - for( s = text; *s; s++ ) - { - if( *s == '\n' ) - { - charsline = 0; - if( *(s+1) ) - charsy++; - } - else - { - charsline++; - if( charsline > charsx ) - charsx = charsline; - } - } - - *w = charsx * textsize * 3 + textsize; - *h = charsy * textsize * 6; -} - -void CNFGDrawTextbox( int x, int y, const char * text, int textsize ) -{ - int w; - int h; - - CNFGGetTextExtents( text, &w, &h, textsize ); - - CNFGDrawBox( x, y, x + w, y + h ); - CNFGPenX = x + textsize; - CNFGPenY = y + textsize; - CNFGDrawText( text, textsize ); -} diff --git a/redist/DrawFunctions.h b/redist/DrawFunctions.h deleted file mode 100644 index 542fcf9..0000000 --- a/redist/DrawFunctions.h +++ /dev/null @@ -1,55 +0,0 @@ -//Copyright (c) 2011 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose. - -#ifndef _DRAWFUCNTIONS_H -#define _DRAWFUCNTIONS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef struct { - short x, y; -} RDPoint; - -extern int CNFGPenX, CNFGPenY; -extern uint32_t CNFGBGColor; -extern uint32_t CNFGLastColor; -extern uint32_t CNFGDialogColor; //background for boxes - -void CNFGDrawText( const char * text, int scale ); -void CNFGDrawBox( int x1, int y1, int x2, int y2 ); -void CNFGGetTextExtents( const char * text, int * w, int * h, int textsize ); -void CNFGDrawTextbox( int x, int y, const char * text, int textsize ); //ignores pen. - -//To be provided by driver. -uint32_t CNFGColor( uint32_t RGB ); -void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h ); -void CNFGTackPixel( short x1, short y1 ); -void CNFGTackSegment( short x1, short y1, short x2, short y2 ); -void CNFGTackRectangle( short x1, short y1, short x2, short y2 ); -void CNFGTackPoly( RDPoint * points, int verts ); -void CNFGClearFrame(); -void CNFGSwapBuffers(); - -void CNFGGetDimensions( short * x, short * y ); -void CNFGTearDown(); -void CNFGSetup( const char * WindowName, int w, int h ); -void CNFGSetupFullscreen( const char * WindowName, int screen_number ); -void CNFGHandleInput(); - - -//You must provide: -void HandleKey( int keycode, int bDown ); -void HandleButton( int x, int y, int button, int bDown ); -void HandleMotion( int x, int y, int mask ); - - -#ifdef __cplusplus -}; -#endif - - -#endif - diff --git a/redist/RawDrawNull.c b/redist/RawDrawNull.c deleted file mode 100644 index 34346cc..0000000 --- a/redist/RawDrawNull.c +++ /dev/null @@ -1,74 +0,0 @@ -//Copyright (c) 2017 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose. - -#include "DrawFunctions.h" - -static int w, h; -void CNFGGetDimensions( short * x, short * y ) -{ - *x = w; - *y = h; -} - -static void InternalLinkScreenAndGo( const char * WindowName ) -{ -} - -void CNFGSetupFullscreen( const char * WindowName, int screen_no ) -{ - CNFGSetup( WindowName, 640, 480 ); -} - - -void CNFGTearDown() -{ -} - -void CNFGSetup( const char * WindowName, int sw, int sh ) -{ - w = sw; - h = sh; -} - -void CNFGHandleInput() -{ -} - - -void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h ) -{ -} - - -#ifndef RASTERIZER - - -uint32_t CNFGColor( uint32_t RGB ) -{ -} - -void CNFGClearFrame() -{ -} - -void CNFGSwapBuffers() -{ -} - -void CNFGTackSegment( short x1, short y1, short x2, short y2 ) -{ -} - -void CNFGTackPixel( short x1, short y1 ) -{ -} - -void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) -{ -} - -void CNFGTackPoly( RDPoint * points, int verts ) -{ -} - -#endif - diff --git a/redist/RawDrawRasterizer.c b/redist/RawDrawRasterizer.c deleted file mode 100644 index af40588..0000000 --- a/redist/RawDrawRasterizer.c +++ /dev/null @@ -1,238 +0,0 @@ -#ifdef RASTERIZER -#include "DrawFunctions.h" -#include -#include -#include - -static uint32_t * buffer = 0; -static short bufferx; -static short buffery; - -static uint32_t SWAPS( uint32_t r ) -{ - uint32_t ret = (r&0xFF)<<16; - r>>=8; - ret |= (r&0xff)<<8; - r>>=8; - ret |= r; - return ret; -} - -uint32_t CNFGColor( uint32_t RGB ) -{ - CNFGLastColor = SWAPS(RGB); - return CNFGLastColor; -} - -void CNFGTackPixel( short x, short y ) -{ - buffer[bufferx*y+x] = CNFGLastColor; -} - -void CNFGTackSegment( short x1, short y1, short x2, short y2 ) -{ - short tx, ty; - float slope, lp; - - short dx = x2 - x1; - short dy = y2 - y1; - - if( !buffer ) return; - - if( dx < 0 ) dx = -dx; - if( dy < 0 ) dy = -dy; - - if( dx > dy ) - { - short minx = (x1 < x2)?x1:x2; - short maxx = (x1 < x2)?x2:x1; - short miny = (x1 < x2)?y1:y2; - short maxy = (x1 < x2)?y2:y1; - float thisy = miny; - slope = (float)(maxy-miny) / (float)(maxx-minx); - - for( tx = minx; tx <= maxx; tx++ ) - { - thisy += slope; - ty = thisy; - if( tx < 0 || ty < 0 || ty >= buffery ) continue; - if( tx >= bufferx ) break; - buffer[ty * bufferx + tx] = CNFGLastColor; - } - } - else - { - short minx = (y1 < y2)?x1:x2; - short maxx = (y1 < y2)?x2:x1; - short miny = (y1 < y2)?y1:y2; - short maxy = (y1 < y2)?y2:y1; - float thisx = minx; - slope = (float)(maxx-minx) / (float)(maxy-miny); - - for( ty = miny; ty <= maxy; ty++ ) - { - thisx += slope; - tx = thisx; - if( ty < 0 || tx < 0 || tx >= bufferx ) continue; - if( ty >= buffery ) break; - buffer[ty * bufferx + tx] = CNFGLastColor; - } - } -} - -void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) -{ - short minx = (x1=x2)?x1:x2; - short maxy = (y1>=y2)?y1:y2; - - short x, y; - - if( minx < 0 ) minx = 0; - if( miny < 0 ) miny = 0; - if( maxx >= bufferx ) maxx = bufferx-1; - if( maxy >= buffery ) maxy = buffery-1; - - for( y = miny; y <= maxy; y++ ) - { - uint32_t * bufferstart = &buffer[y * bufferx + minx]; - for( x = minx; x <= maxx; x++ ) - { - (*bufferstart++) = CNFGLastColor; - } - } -} - -void CNFGTackPoly( RDPoint * points, int verts ) -{ - short minx = 10000, miny = 10000; - short maxx =-10000, maxy =-10000; - short i, x, y; - - //Just in case... - if( verts > 32767 ) return; - - for( i = 0; i < verts; i++ ) - { - RDPoint * p = &points[i]; - if( p->x < minx ) minx = p->x; - if( p->y < miny ) miny = p->y; - if( p->x > maxx ) maxx = p->x; - if( p->y > maxy ) maxy = p->y; - } - - if( miny < 0 ) miny = 0; - if( maxy >= buffery ) maxy = buffery-1; - - for( y = miny; y <= maxy; y++ ) - { - short startfillx = maxx; - short endfillx = minx; - - //Figure out what line segments intersect this line. - for( i = 0; i < verts; i++ ) - { - short pl = i + 1; - if( pl == verts ) pl = 0; - - RDPoint ptop; - RDPoint pbot; - - ptop.x = points[i].x; - ptop.y = points[i].y; - pbot.x = points[pl].x; - pbot.y = points[pl].y; -//printf( "Poly: %d %d\n", pbot.y, ptop.y ); - - if( pbot.y < ptop.y ) - { - RDPoint ptmp; - ptmp.x = pbot.x; - ptmp.y = pbot.y; - pbot.x = ptop.x; - pbot.y = ptop.y; - ptop.x = ptmp.x; - ptop.y = ptmp.y; - } - - //Make sure this line segment is within our range. -//printf( "PT: %d %d %d\n", y, ptop.y, pbot.y ); - if( ptop.y <= y && pbot.y >= y ) - { - short diffy = pbot.y - ptop.y; - uint32_t placey = (uint32_t)(y - ptop.y)<<16; //Scale by 16 so we can do integer math. - short diffx = pbot.x - ptop.x; - short isectx; - - if( diffy == 0 ) - { - if( pbot.x < ptop.x ) - { - if( startfillx > pbot.x ) startfillx = pbot.x; - if( endfillx < ptop.x ) endfillx = ptop.x; - } - else - { - if( startfillx > ptop.x ) startfillx = ptop.x; - if( endfillx < pbot.x ) endfillx = pbot.x; - } - } - else - { - //Inner part is scaled by 65536, outer part must be scaled back. - isectx = (( (placey / diffy) * diffx + 32768 )>>16) + ptop.x; - if( isectx < startfillx ) startfillx = isectx; - if( isectx > endfillx ) endfillx = isectx; - } -//printf( "R: %d %d %d\n", pbot.x, ptop.x, isectx ); - } - } - -//printf( "%d %d %d\n", y, startfillx, endfillx ); - - if( endfillx >= bufferx ) endfillx = bufferx - 1; - if( endfillx >= bufferx ) endfillx = buffery - 1; - if( startfillx < 0 ) startfillx = 0; - if( startfillx < 0 ) startfillx = 0; - - unsigned int * bufferstart = &buffer[y * bufferx + startfillx]; - for( x = startfillx; x <= endfillx; x++ ) - { - (*bufferstart++) = CNFGLastColor; - } - } -//exit(1); -} - - -void CNFGClearFrame() -{ - int i, m; - uint32_t col = 0; - short x, y; - CNFGGetDimensions( &x, &y ); - if( x != bufferx || y != buffery || !buffer ) - { - bufferx = x; - buffery = y; - printf( "MALLOCING: %d\n", x * y ); - buffer = malloc( x * y * 8 ); - } - - m = x * y; - col = CNFGColor( CNFGBGColor ); - for( i = 0; i < m; i++ ) - { -//printf( "Got: %d %p %d\n", m, buffer, i ); - buffer[i] = col; - } -} - -void CNFGSwapBuffers() -{ - CNFGUpdateScreenWithBitmap( buffer, bufferx, buffery ); -} - - -#endif diff --git a/redist/WinDriver.c b/redist/WinDriver.c deleted file mode 100644 index 3613150..0000000 --- a/redist/WinDriver.c +++ /dev/null @@ -1,231 +0,0 @@ -//Copyright (c) 2011 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose. -//Portion from: http://en.wikibooks.org/wiki/Windows_Programming/Window_Creation - - -#include "DrawFunctions.h" -#include -#include -#include //for alloca - -static HINSTANCE lhInstance; -static HWND lsHWND; -static HDC lsHDC; -static HBITMAP lsBackBitmap; -static HDC lsWindowHDC; -static HBRUSH lsHBR; -static HPEN lsHPEN; -static HBRUSH lsClearBrush; -static unsigned int lsLastWidth; -static unsigned int lsLastHeight; - -static void InternalHandleResize() -{ - DeleteObject( lsBackBitmap ); - lsBackBitmap = CreateCompatibleBitmap( lsHDC, lsLastWidth, lsLastHeight ); - SelectObject( lsHDC, lsBackBitmap ); - -} - -uint32_t CNFGColor( uint32_t RGB ) -{ - CNFGLastColor = RGB; - - DeleteObject( lsHBR ); - lsHBR = CreateSolidBrush( RGB ); - SelectObject( lsHDC, lsHBR ); - - DeleteObject( lsHPEN ); - lsHPEN = CreatePen( PS_SOLID, 0, RGB ); - SelectObject( lsHDC, lsHPEN ); - - return RGB; -} - -void CNFGTackSegment( short x1, short y1, short x2, short y2 ) -{ - POINT pt[2] = { {x1, y1}, {x2, y2} }; - Polyline( lsHDC, pt, 2 ); - SetPixel( lsHDC, x1, y1, CNFGLastColor ); - SetPixel( lsHDC, x2, y2, CNFGLastColor ); -} - -void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) -{ - RECT r; - if( x1 < x2 ) { r.left = x1; r.right = x2; } - else { r.left = x2; r.right = x1; } - if( y1 < y2 ) { r.top = y1; r.bottom = y2; } - else { r.top = y2; r.bottom = y1; } - FillRect( lsHDC, &r, lsHBR ); -} - -void CNFGClearFrame() -{ - RECT r = { 0, 0, lsLastWidth, lsLastHeight }; - DeleteObject( lsClearBrush ); - lsClearBrush = CreateSolidBrush( CNFGBGColor ); - SelectObject( lsHDC, lsClearBrush ); - - FillRect( lsHDC, &r, lsClearBrush ); -} - -void CNFGSwapBuffers() -{ - int thisw, thish; - RECT r; - BitBlt( lsWindowHDC, 0, 0, lsLastWidth, lsLastHeight, lsHDC, 0, 0, SRCCOPY ); - UpdateWindow( lsHWND ); - - //Check to see if the window is closed. - if( !IsWindow( lsHWND ) ) - { - exit( 0 ); - } - - GetClientRect( lsHWND, &r ); - thisw = r.right - r.left; - thish = r.bottom - r.top; - if( thisw != lsLastWidth || thish != lsLastHeight ) - { - lsLastWidth = thisw; - lsLastHeight = thish; - InternalHandleResize(); - } -} - -void CNFGTackPoly( RDPoint * points, int verts ) -{ - int i; - POINT * t = (POINT*)alloca( sizeof( POINT ) * verts ); - for( i = 0; i < verts; i++ ) - { - t[i].x = points[i].x; - t[i].y = points[i].y; - } - Polygon( lsHDC, t, verts ); -} - - -void CNFGTackPixel( short x1, short y1 ) -{ - SetPixel( lsHDC, x1, y1, CNFGLastColor ); -} - -void CNFGGetDimensions( short * x, short * y ) -{ - *x = lsLastWidth; - *y = lsLastHeight; -} - -//This was from the article -LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch(msg) - { - case WM_DESTROY: - CNFGTearDown(); - return 0; - } - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -void CNFGTearDown() -{ - PostQuitMessage(0); -} - -//This was from the article, too... well, mostly. -void CNFGSetup( const char * name_of_window, int width, int height ) -{ - static LPSTR szClassName = "MyClass"; - RECT client, window; - WNDCLASS wnd; - int w, h, wd, hd; - HINSTANCE hInstance = GetModuleHandle(NULL); - - lsLastWidth = width; - lsLastHeight = height; - - wnd.style = CS_HREDRAW | CS_VREDRAW; //we will explain this later - wnd.lpfnWndProc = MyWndProc; - wnd.cbClsExtra = 0; - wnd.cbWndExtra = 0; - wnd.hInstance = hInstance; - wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION); //default icon - wnd.hCursor = LoadCursor(NULL, IDC_ARROW); //default arrow mouse cursor - wnd.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); - wnd.lpszMenuName = NULL; //no menu - wnd.lpszClassName = szClassName; - - if(!RegisterClass(&wnd)) //register the WNDCLASS - { - MessageBox(NULL, "This Program Requires Windows NT", "Error", MB_OK); - } - - lsHWND = CreateWindow(szClassName, - name_of_window, //name_of_window, - WS_OVERLAPPEDWINDOW, //basic window style - CW_USEDEFAULT, - CW_USEDEFAULT, //set starting point to default value - lsLastWidth, - lsLastHeight, //set all the dimensions to default value - NULL, //no parent window - NULL, //no menu - hInstance, - NULL); //no parameters to pass - - - lsWindowHDC = GetDC( lsHWND ); - lsHDC = CreateCompatibleDC( lsWindowHDC ); - lsBackBitmap = CreateCompatibleBitmap( lsWindowHDC, lsLastWidth, lsLastHeight ); - SelectObject( lsHDC, lsBackBitmap ); - - lsClearBrush = CreateSolidBrush( CNFGBGColor ); - lsHBR = CreateSolidBrush( 0xFFFFFF ); - lsHPEN = CreatePen( PS_SOLID, 0, 0xFFFFFF ); - - ShowWindow(lsHWND, 1); //display the window on the screen - - //Once set up... we have to change the window's borders so we get the client size right. - GetClientRect( lsHWND, &client ); - GetWindowRect( lsHWND, &window ); - w = ( window.right - window.left); - h = ( window.bottom - window.top); - wd = w - client.right; - hd = h - client.bottom; - MoveWindow( lsHWND, window.left, window.top, lsLastWidth + wd, lsLastHeight + hd, 1 ); - - InternalHandleResize(); -} - -void CNFGHandleInput() -{ - int ldown = 0; - - MSG msg; - while( PeekMessage( &msg, lsHWND, 0, 0xFFFF, 1 ) ) - { - TranslateMessage(&msg); - - switch( msg.message ) - { - case WM_MOUSEMOVE: - HandleMotion( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, ( (msg.wParam & 0x01)?1:0) | ((msg.wParam & 0x02)?2:0) | ((msg.wParam & 0x10)?4:0) ); - break; - case WM_LBUTTONDOWN: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 1, 1 ); break; - case WM_RBUTTONDOWN: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 2, 1 ); break; - case WM_MBUTTONDOWN: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 3, 1 ); break; - case WM_LBUTTONUP: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 1, 0 ); break; - case WM_RBUTTONUP: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 2, 0 ); break; - case WM_MBUTTONUP: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 3, 0 ); break; - case WM_KEYDOWN: - case WM_KEYUP: - HandleKey( tolower( (int)msg.wParam ), (msg.message==WM_KEYDOWN) ); - break; - default: - DispatchMessage(&msg); - break; - } - } -} - diff --git a/redist/XDriver.c b/redist/XDriver.c deleted file mode 100644 index 507ca95..0000000 --- a/redist/XDriver.c +++ /dev/null @@ -1,290 +0,0 @@ -//Copyright (c) 2011 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose. -//portions from -//http://www.xmission.com/~georgeps/documentation/tutorials/Xlib_Beginner.html - -//#define HAS_XINERAMA - -#include "DrawFunctions.h" - -#include -#include -#include -#include -#include -#ifdef HAS_XINERAMA -#include -#include -#endif -#include -#include - -XWindowAttributes CNFGWinAtt; -XClassHint *CNFGClassHint; -Display *CNFGDisplay; -Window CNFGWindow; -Pixmap CNFGPixmap; -GC CNFGGC; -GC CNFGWindowGC; -int FullScreen = 0; - -void CNFGGetDimensions( short * x, short * y ) -{ - *x = CNFGWinAtt.width; - *y = CNFGWinAtt.height; -} - -static void InternalLinkScreenAndGo( const char * WindowName ) -{ - XGetWindowAttributes( CNFGDisplay, CNFGWindow, &CNFGWinAtt ); - - XGetClassHint( CNFGDisplay, CNFGWindow, CNFGClassHint ); - if (!CNFGClassHint) { - CNFGClassHint = XAllocClassHint(); - if (CNFGClassHint) { - CNFGClassHint->res_name = "cnping"; - CNFGClassHint->res_class = "cnping"; - XSetClassHint( CNFGDisplay, CNFGWindow, CNFGClassHint ); - } else { - fprintf( stderr, "Failed to allocate XClassHint!\n" ); - } - } else { - fprintf( stderr, "Pre-existing XClassHint\n" ); - } - - XSelectInput (CNFGDisplay, CNFGWindow, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ExposureMask | PointerMotionMask ); - XSetStandardProperties( CNFGDisplay, CNFGWindow, WindowName, WindowName, None, NULL, 0, NULL ); - - CNFGWindowGC = XCreateGC(CNFGDisplay, CNFGWindow, 0, 0); - - CNFGPixmap = XCreatePixmap( CNFGDisplay, CNFGWindow, CNFGWinAtt.width, CNFGWinAtt.height, CNFGWinAtt.depth ); - CNFGGC = XCreateGC(CNFGDisplay, CNFGPixmap, 0, 0); -} - -void CNFGSetupFullscreen( const char * WindowName, int screen_no ) -{ -#ifdef HAS_XINERAMA - XineramaScreenInfo *screeninfo = NULL; - int screens; - int event_basep, error_basep, a, b; - CNFGDisplay = XOpenDisplay(NULL); - int screen = XDefaultScreen(CNFGDisplay); - int xpos, ypos; - - if (!XShapeQueryExtension(CNFGDisplay, &event_basep, &error_basep)) - { - fprintf( stderr, "X-Server does not support shape extension" ); - exit( 1 ); - } - - Visual * visual = DefaultVisual(CNFGDisplay, screen); - CNFGWinAtt.depth = DefaultDepth(CNFGDisplay, screen); - - if (XineramaQueryExtension(CNFGDisplay, &a, &b ) && - (screeninfo = XineramaQueryScreens(CNFGDisplay, &screens)) && - XineramaIsActive(CNFGDisplay) && screen_no >= 0 && - screen_no < screens ) { - - CNFGWinAtt.width = screeninfo[screen_no].width; - CNFGWinAtt.height = screeninfo[screen_no].height; - xpos = screeninfo[screen_no].x_org; - ypos = screeninfo[screen_no].y_org; - } else - { - CNFGWinAtt.width = XDisplayWidth(CNFGDisplay, screen); - CNFGWinAtt.height = XDisplayHeight(CNFGDisplay, screen); - xpos = 0; - ypos = 0; - } - if (screeninfo) - XFree(screeninfo); - - - XSetWindowAttributes setwinattr; - setwinattr.override_redirect = 1; - setwinattr.save_under = 1; - setwinattr.event_mask = StructureNotifyMask | SubstructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonPressMask | PointerMotionMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask |KeyPressMask |KeyReleaseMask | SubstructureNotifyMask | FocusChangeMask; - setwinattr.border_pixel = 0; - - CNFGWindow = XCreateWindow(CNFGDisplay, XRootWindow(CNFGDisplay, screen), - xpos, ypos, CNFGWinAtt.width, CNFGWinAtt.height, - 0, CNFGWinAtt.depth, InputOutput, visual, CWBorderPixel | CWEventMask | CWOverrideRedirect | CWSaveUnder, &setwinattr); - - XMapWindow(CNFGDisplay, CNFGWindow); - XSetInputFocus( CNFGDisplay, CNFGWindow, RevertToParent, CurrentTime ); - XFlush(CNFGDisplay); - FullScreen = 1; -//printf( "%d %d %d %d\n", xpos, ypos, CNFGWinAtt.width, CNFGWinAtt.height ); - InternalLinkScreenAndGo( WindowName ); -/* - setwinattr.override_redirect = 1; - XChangeWindowAttributes( - CNFGDisplay, CNFGWindow, - CWBorderPixel | CWEventMask | CWOverrideRedirect, &setwinattr); -*/ -#else - CNFGSetup( WindowName, 640, 480 ); -#endif -} - - -void CNFGTearDown() -{ - if ( CNFGClassHint ) XFree( CNFGClassHint ); - if ( CNFGGC ) XFreeGC( CNFGDisplay, CNFGGC ); - if ( CNFGWindowGC ) XFreeGC( CNFGDisplay, CNFGWindowGC ); - if ( CNFGDisplay ) XCloseDisplay( CNFGDisplay ); - CNFGDisplay = NULL; - CNFGWindowGC = CNFGGC = NULL; - CNFGClassHint = NULL; -} - -void CNFGSetup( const char * WindowName, int w, int h ) -{ - CNFGDisplay = XOpenDisplay(NULL); - atexit( CNFGTearDown ); - XGetWindowAttributes( CNFGDisplay, RootWindow(CNFGDisplay, 0), &CNFGWinAtt ); - - int depth = CNFGWinAtt.depth; - CNFGWindow = XCreateWindow(CNFGDisplay, RootWindow(CNFGDisplay, 0), 1, 1, w, h, 0, depth, InputOutput, CopyFromParent, 0, 0 ); - XMapWindow(CNFGDisplay, CNFGWindow); - XFlush(CNFGDisplay); - - InternalLinkScreenAndGo( WindowName ); - - Atom WM_DELETE_WINDOW = XInternAtom( CNFGDisplay, "WM_DELETE_WINDOW", False ); - XSetWMProtocols( CNFGDisplay, CNFGWindow, &WM_DELETE_WINDOW, 1 ); - XSelectInput( CNFGDisplay, CNFGWindow, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ExposureMask | PointerMotionMask ); -} - -void CNFGHandleInput() -{ - static int ButtonsDown; - XEvent report; - - int bKeyDirection = 1; - int r; - while( XPending( CNFGDisplay ) ) - { - r=XNextEvent( CNFGDisplay, &report ); - - bKeyDirection = 1; - switch (report.type) - { - case NoExpose: - break; - case Expose: - XGetWindowAttributes( CNFGDisplay, CNFGWindow, &CNFGWinAtt ); - if( CNFGPixmap ) XFreePixmap( CNFGDisplay, CNFGPixmap ); - CNFGPixmap = XCreatePixmap( CNFGDisplay, CNFGWindow, CNFGWinAtt.width, CNFGWinAtt.height, CNFGWinAtt.depth ); - if( CNFGGC ) XFreeGC( CNFGDisplay, CNFGGC ); - CNFGGC = XCreateGC(CNFGDisplay, CNFGPixmap, 0, 0); - break; - case KeyRelease: - bKeyDirection = 0; - case KeyPress: - HandleKey( XLookupKeysym(&report.xkey, 0), bKeyDirection ); - break; - case ButtonRelease: - bKeyDirection = 0; - case ButtonPress: - HandleButton( report.xbutton.x, report.xbutton.y, report.xbutton.button, bKeyDirection ); - ButtonsDown = (ButtonsDown & (~(1<>1 ); - break; - case ClientMessage: - // Only subscribed to WM_DELETE_WINDOW, so just exit - exit( 0 ); - break; - default: - printf( "Event: %d\n", report.type ); - } - } -} - - -void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h ) -{ - static XImage *xi; - static int depth; - static int lw, lh; - static unsigned char * lbuffer; - int r, ls; - - if( !xi ) - { - int screen = DefaultScreen(CNFGDisplay); - Visual * visual = DefaultVisual(CNFGDisplay, screen); - depth = DefaultDepth(CNFGDisplay, screen)/8; -// xi = XCreateImage(CNFGDisplay, DefaultVisual( CNFGDisplay, DefaultScreen(CNFGDisplay) ), depth*8, ZPixmap, 0, (char*)data, w, h, 32, w*4 ); -// lw = w; -// lh = h; - } - - if( lw != w || lh != h ) - { - if( xi ) free( xi ); - xi = XCreateImage(CNFGDisplay, DefaultVisual( CNFGDisplay, DefaultScreen(CNFGDisplay) ), depth*8, ZPixmap, 0, (char*)data, w, h, 32, w*4 ); - lw = w; - lh = h; - } - - ls = lw * lh; - - XPutImage(CNFGDisplay, CNFGWindow, CNFGWindowGC, xi, 0, 0, 0, 0, w, h ); -} - - -#ifndef RASTERIZER - - -uint32_t CNFGColor( uint32_t RGB ) -{ - unsigned char red = RGB & 0xFF; - unsigned char grn = ( RGB >> 8 ) & 0xFF; - unsigned char blu = ( RGB >> 16 ) & 0xFF; - CNFGLastColor = RGB; - unsigned long color = (red<<16)|(grn<<8)|(blu); - XSetForeground(CNFGDisplay, CNFGGC, color); - return color; -} - -void CNFGClearFrame() -{ - XGetWindowAttributes( CNFGDisplay, CNFGWindow, &CNFGWinAtt ); - XSetForeground(CNFGDisplay, CNFGGC, CNFGColor(CNFGBGColor) ); - XFillRectangle(CNFGDisplay, CNFGPixmap, CNFGGC, 0, 0, CNFGWinAtt.width, CNFGWinAtt.height ); -} - -void CNFGSwapBuffers() -{ - XCopyArea(CNFGDisplay, CNFGPixmap, CNFGWindow, CNFGWindowGC, 0,0,CNFGWinAtt.width,CNFGWinAtt.height,0,0); - XFlush(CNFGDisplay); - if( FullScreen ) - XSetInputFocus( CNFGDisplay, CNFGWindow, RevertToParent, CurrentTime ); -} - -void CNFGTackSegment( short x1, short y1, short x2, short y2 ) -{ - XDrawLine( CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1, x2, y2 ); -} - -void CNFGTackPixel( short x1, short y1 ) -{ - XDrawPoint( CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1 ); -} - -void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) -{ - XFillRectangle(CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1, x2-x1, y2-y1 ); -} - -void CNFGTackPoly( RDPoint * points, int verts ) -{ - XFillPolygon(CNFGDisplay, CNFGPixmap, CNFGGC, (XPoint *)points, 3, Convex, CoordModeOrigin ); -} - -#endif - diff --git a/test.c b/test.c index a7da490..7679ad4 100755 --- a/test.c +++ b/test.c @@ -5,7 +5,7 @@ #include #include -#include +#include struct SurviveContext * ctx; -- cgit v1.2.3 From 743e4b60f03db3c8c340b63b8d27eac579e146dd Mon Sep 17 00:00:00 2001 From: CNLohr Date: Fri, 17 Mar 2017 03:10:55 -0400 Subject: Update Windows build to reflect changes in RawDraw. --- calibrate.c | 4 ++++ calibrate_client.c | 3 +++ data_recorder.c | 4 ++++ winbuild/build_tcc.bat | 2 +- winbuild/libsurvive/libsurvive.vcxproj | 6 +++--- winbuild/libsurvive/libsurvive.vcxproj.filters | 18 +++++++++--------- 6 files changed, 24 insertions(+), 13 deletions(-) diff --git a/calibrate.c b/calibrate.c index 3d83baf..726a8cc 100644 --- a/calibrate.c +++ b/calibrate.c @@ -40,6 +40,10 @@ void HandleMotion( int x, int y, int mask ) { } +void HandleDestroy() +{ +} + //int bufferpts[32*2*3][2]; int bufferpts[32*2*3][2]; diff --git a/calibrate_client.c b/calibrate_client.c index 5e31cfb..1a2ee41 100644 --- a/calibrate_client.c +++ b/calibrate_client.c @@ -35,6 +35,9 @@ void HandleButton( int x, int y, int button, int bDown ) void HandleMotion( int x, int y, int mask ) { } +void HandleDestroy() +{ +} int bufferpts[32*2*3]; char buffermts[32*128*3]; diff --git a/data_recorder.c b/data_recorder.c index 630598a..afc17b2 100644 --- a/data_recorder.c +++ b/data_recorder.c @@ -33,6 +33,10 @@ void HandleMotion( int x, int y, int mask ) { } +void HandleDestroy() +{ +} + int bufferpts[32*2*3]; char buffermts[32*128*3]; int buffertimeto[32*3]; diff --git a/winbuild/build_tcc.bat b/winbuild/build_tcc.bat index 46f4beb..5be1361 100644 --- a/winbuild/build_tcc.bat +++ b/winbuild/build_tcc.bat @@ -7,7 +7,7 @@ set SR=..\src\ set RD=..\redist\ set SOURCES=%SR%ootx_decoder.c %SR%poser_charlesslow.c %SR%poser_daveortho.c %SR%poser_dummy.c %SR%survive.c %SR%survive_cal.c %SR%survive_config.c %SR%survive_data.c %SR%survive_driverman.c %SR%survive_process.c %SR%survive_vive.c set REDIST=%RD%crc32.c %RD%linmath.c %RD%puff.c %RD%jsmn.c %RD%json_helpers.c %RD%symbol_enumerator.c -set EXEC=..\calibrate.c %RD%WinDriver.c %RD%os_generic.c %RD%DrawFunctions.c +set EXEC=..\calibrate.c %RD%CNFGWinDriver.c %RD%os_generic.c %RD%CNFGFunctions.c set CFLAGS=-DNOZLIB -DTCC -DWINDOWS -DHIDAPI -DWIN32 -DRUNTIME_SYMNUM -O0 -g -rdynamic -I..\redist -I..\include\libsurvive -I..\src -I. set LDFLAGS=-lkernel32 -lgdi32 -luser32 -lsetupapi -ldbghelp @echo on diff --git a/winbuild/libsurvive/libsurvive.vcxproj b/winbuild/libsurvive/libsurvive.vcxproj index 996f342..643cff5 100644 --- a/winbuild/libsurvive/libsurvive.vcxproj +++ b/winbuild/libsurvive/libsurvive.vcxproj @@ -139,8 +139,9 @@ + + - @@ -148,7 +149,6 @@ - @@ -166,8 +166,8 @@ + - diff --git a/winbuild/libsurvive/libsurvive.vcxproj.filters b/winbuild/libsurvive/libsurvive.vcxproj.filters index 8be02f1..0bb9d1b 100644 --- a/winbuild/libsurvive/libsurvive.vcxproj.filters +++ b/winbuild/libsurvive/libsurvive.vcxproj.filters @@ -60,12 +60,6 @@ Source Files - - Source Files - - - Source Files - Source Files @@ -84,6 +78,12 @@ Source Files + + Source Files + + + Source Files + @@ -110,9 +110,6 @@ Header Files - - Header Files - Header Files @@ -131,5 +128,8 @@ Header Files + + Header Files + \ No newline at end of file -- cgit v1.2.3 From c90a23cc928b7434a1e3aceb36b783761bfc8d7e Mon Sep 17 00:00:00 2001 From: geekmaster Date: Fri, 17 Mar 2017 13:13:12 -0500 Subject: Update README.md Add Intel Integrated Graphics section. --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6e097f8..45ac38f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # libsurvive -**WARNING PROJECT NOT YET IN EXPERIMENTAL PHASE** +**WARNING PROJECT IN EXPERIMENTAL PHASE** Discord: https://discordapp.com/invite/7QbCAGS @@ -40,8 +40,7 @@ I say "high-performance" really this project is based tightly off of OSVR-Vive-L 2. Put it under an open-source instead of a force-source license. (GPL to MIT/X11) 3. Write it in C. 4. Avoid extra layers where convenient. -5. (long shot) Make the vive vivable for use with Intel Integrated Graphics systems. - +5. (long shot) Make the vive vivable for use with Intel Integrated Graphics systems. [It works with HD4000 using DisplayPort. See "Intel Integrated Graphics" section below.] Will ~~I~~ we succeed? Probably not. @@ -50,7 +49,7 @@ Definitely going to try! ## External dependencies -* libUSB +* libUSB (hidapi ???) * pthread * libX11 (where applicable) * zlib (may use puff.c if needed) @@ -71,7 +70,10 @@ It is written in some fairly stout "layers" which are basically just function ca I may or may not read data from the Vive regarding configuration. If I do, it would be added to the survive_usb.c +## Intel Integrated Graphics +The limiting factor for Vive viability on a given computer is the maximum available pixel clock frequency, and frequency limitations of the HDMI port, and HDMI and DisplayPort video cables. DisplayPort can support higher frequencies than HDMI, on Ivy Bridge HD4000 graphics. In fact, the vive works with HD4000 graphics using DisplayPort, with native EDID resolution (2160x1200@90Hz). +To support the Vive on HDMI, you either need a newer version of HDMI, or you need to define a custom resolution that respects pixel clock and video port limits, and is also accepted and displayed by the Vive. So far, we have not had success using custom resolutions on linux or on Windows. Windows imposes additional limitations in the form of restriction of WHQL certified drivers forbidden from using custom display resolutions (only allowing those defined by EDID in the monitor). Intel has released uncertified beta drivers for Haswell and newer processors, which should be able to support custom resolutions for the Vive (untested at this time). - +but HDMI will require non-certified drivers to allow custom resolutions (due to WHQL restrictions). Haswell (Iris) graphics and later can use the new intel beta drivers to allow custom resolutions.] -- cgit v1.2.3