diff --git a/ViGEmClient.sln b/ViGEmClient.sln index 105bb63..44670ff 100644 --- a/ViGEmClient.sln +++ b/ViGEmClient.sln @@ -35,6 +35,22 @@ Global {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x64.Build.0 = Release_LIB|x64 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x86.ActiveCfg = Release_LIB|Win32 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x86.Build.0 = Release_LIB|Win32 + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug_DLL|x64.ActiveCfg = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug_DLL|x64.Build.0 = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug_DLL|x86.ActiveCfg = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug_DLL|x86.Build.0 = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug_LIB|x64.ActiveCfg = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug_LIB|x64.Build.0 = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug_LIB|x86.ActiveCfg = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug_LIB|x86.Build.0 = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_DLL|x64.ActiveCfg = Release|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_DLL|x64.Build.0 = Release|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_DLL|x86.ActiveCfg = Release|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_DLL|x86.Build.0 = Release|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_LIB|x64.ActiveCfg = Release|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_LIB|x64.Build.0 = Release|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_LIB|x86.ActiveCfg = Release|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_LIB|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/appveyor.yml b/appveyor.yml index e10b69d..ab83fff 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,9 @@ version: 1.16.{build}.0 image: Visual Studio 2017 +before_build: +- cmd: vcpkg integrate install +- cmd: vcpkg install boost-asio:x86-windows-static +- cmd: vcpkg install boost-asio:x64-windows-static build_script: - ps: .\build.ps1 artifacts: diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 3d499e1..1ad6c69 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -38,11 +38,18 @@ SOFTWARE. // #include #include -#include -#include #include #include +// +// Boost +// +#include +#include +#include +#include +#include + // // TODO: this is... not optimal. Improve in the future. // @@ -51,7 +58,15 @@ SOFTWARE. #define VIGEM_INVERTED_CALL_THREAD_COUNT 20 -typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); +typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)( + HANDLE hProcess, + DWORD dwPid, + HANDLE hFile, + MINIDUMP_TYPE DumpType, + CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, + CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam +); LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExceptionInfo); @@ -87,6 +102,10 @@ typedef struct _VIGEM_TARGET_T USHORT ProductId; VIGEM_TARGET_TYPE Type; DWORD_PTR Notification; + + boost::shared_ptr io_svc; + boost::shared_ptr worker; + boost::thread_group worker_threads; } VIGEM_TARGET; @@ -108,6 +127,9 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT( target->State = VIGEM_TARGET_INITIALIZED; target->Type = Type; + target->io_svc.reset(new boost::asio::io_service()); + target->worker.reset(new boost::asio::io_service::work(*target->io_svc)); + return target; } @@ -141,6 +163,68 @@ LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExcep return EXCEPTION_CONTINUE_SEARCH; } +void vigem_internal_x360_notification_worker( + PVIGEM_TARGET target, + PVIGEM_CLIENT client +) +{ + DWORD error = ERROR_SUCCESS; + DWORD transferred = 0; + OVERLAPPED lOverlapped = { 0 }; + lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + boost::asio::io_service::strand strand(*target->io_svc); + + XUSB_REQUEST_NOTIFICATION notify; + XUSB_REQUEST_NOTIFICATION_INIT(¬ify, target->SerialNo); + + do + { + DeviceIoControl(client->hBusDevice, + IOCTL_XUSB_REQUEST_NOTIFICATION, + ¬ify, + notify.Size, + ¬ify, + notify.Size, + &transferred, + &lOverlapped); + + if (GetOverlappedResult(client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) + { + if (target->Notification == NULL) + { + if (lOverlapped.hEvent) + CloseHandle(lOverlapped.hEvent); + return; + } + + const boost::function pfn = PFN_VIGEM_X360_NOTIFICATION(target->Notification); + + strand.post(boost::bind(pfn, + client, + target, + notify.LargeMotor, + notify.SmallMotor, + notify.LedNumber + )); + + target->io_svc->poll(); + } + else + { + error = GetLastError(); + } + } while (error != ERROR_OPERATION_ABORTED && error != ERROR_ACCESS_DENIED); + + if (lOverlapped.hEvent) + CloseHandle(lOverlapped.hEvent); +} + PVIGEM_CLIENT vigem_alloc() { SetUnhandledExceptionFilter(vigem_internal_exception_handler); @@ -319,7 +403,11 @@ PVIGEM_TARGET vigem_target_ds4_alloc(void) void vigem_target_free(PVIGEM_TARGET target) { if (target) + { + target->io_svc->stop(); + free(target); + } } VIGEM_ERROR vigem_target_add(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) @@ -507,62 +595,8 @@ VIGEM_ERROR vigem_target_x360_register_notification( target->Notification = reinterpret_cast(notification); - std::vector threadList; - - for (int i = 0; i < VIGEM_INVERTED_CALL_THREAD_COUNT; i++) - { - threadList.emplace_back(std::thread([]( - PVIGEM_TARGET _Target, - PVIGEM_CLIENT _Client) - { - DWORD error = ERROR_SUCCESS; - DWORD transferred = 0; - OVERLAPPED lOverlapped = { 0 }; - lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); - - XUSB_REQUEST_NOTIFICATION notify; - XUSB_REQUEST_NOTIFICATION_INIT(¬ify, _Target->SerialNo); - - do - { - DeviceIoControl(_Client->hBusDevice, - IOCTL_XUSB_REQUEST_NOTIFICATION, - ¬ify, - notify.Size, - ¬ify, - notify.Size, - &transferred, - &lOverlapped); - - if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) - { - if (_Target->Notification == NULL) - { - if (lOverlapped.hEvent) - CloseHandle(lOverlapped.hEvent); - return; - } - - PFN_VIGEM_X360_NOTIFICATION(_Target->Notification)( - _Client, - _Target, - notify.LargeMotor, - notify.SmallMotor, - notify.LedNumber); - } - else - { - error = GetLastError(); - } - } while (error != ERROR_OPERATION_ABORTED && error != ERROR_ACCESS_DENIED); - - if (lOverlapped.hEvent) - CloseHandle(lOverlapped.hEvent); - - }, target, vigem)); - } - - std::for_each(threadList.begin(), threadList.end(), std::mem_fn(&std::thread::detach)); + for (int i = 1; i <= VIGEM_INVERTED_CALL_THREAD_COUNT; i++) + target->worker_threads.create_thread(boost::bind(&vigem_internal_x360_notification_worker, target, vigem)); return VIGEM_ERROR_NONE; } diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index da880bf..aa03ffc 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -38,6 +38,8 @@ {7DB06674-1F4F-464B-8E1C-172E9587F9DC} Win32Proj ViGEmClient + x86-windows-static + x64-windows-static