From 14011d6794fc364a430eb88ccf291cf07ee9ccce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 25 Aug 2018 21:28:56 +0200 Subject: [PATCH 001/107] Ripped client parts out of bus project --- ViGEmBus.ddf | 21 - ViGEmBus.sln => ViGEmClient.sln | 76 +- include/ViGEmBusDriver.h | 85 -- include/{ => km}/ViGEmBusShared.h | 0 {lib => src}/README.md | 0 {lib => src}/ViGEmClient.cpp | 2 +- {lib => src}/ViGEmClient.rc | 0 {lib => src}/ViGEmClient.vcxproj | 0 {lib => src}/ViGEmClient.vcxproj.filters | 0 {lib => src}/resource.h | 0 sys/ByteArray.c | 191 ---- sys/ByteArray.h | 29 - sys/Context.h | 194 ---- sys/Driver.c | 660 ----------- sys/Ds4.c | 466 -------- sys/Ds4.h | 112 -- sys/Queue.c | 458 -------- sys/Queue.h | 30 - sys/README.md | 17 - sys/UsbPdo.h | 51 - sys/Util.h | 50 - sys/ViGEmBus.inf | 84 -- sys/ViGEmBus.rc | 100 -- sys/ViGEmBus.vcxproj | 326 ------ sys/ViGEmBus.vcxproj.filters | 110 -- sys/Xgip.h | 106 -- sys/Xusb.h | 127 --- sys/busenum.c | 823 -------------- sys/busenum.h | 176 --- sys/buspdo.c | 901 --------------- sys/resource.h | 14 - sys/trace.h | 61 - sys/usbpdo.c | 1298 ---------------------- sys/util.c | 60 - sys/xgip.c | 406 ------- sys/xusb.c | 621 ----------- 36 files changed, 2 insertions(+), 7653 deletions(-) delete mode 100644 ViGEmBus.ddf rename ViGEmBus.sln => ViGEmClient.sln (60%) delete mode 100644 include/ViGEmBusDriver.h rename include/{ => km}/ViGEmBusShared.h (100%) rename {lib => src}/README.md (100%) rename {lib => src}/ViGEmClient.cpp (99%) rename {lib => src}/ViGEmClient.rc (100%) rename {lib => src}/ViGEmClient.vcxproj (100%) rename {lib => src}/ViGEmClient.vcxproj.filters (100%) rename {lib => src}/resource.h (100%) delete mode 100644 sys/ByteArray.c delete mode 100644 sys/ByteArray.h delete mode 100644 sys/Context.h delete mode 100644 sys/Driver.c delete mode 100644 sys/Ds4.c delete mode 100644 sys/Ds4.h delete mode 100644 sys/Queue.c delete mode 100644 sys/Queue.h delete mode 100644 sys/README.md delete mode 100644 sys/UsbPdo.h delete mode 100644 sys/Util.h delete mode 100644 sys/ViGEmBus.inf delete mode 100644 sys/ViGEmBus.rc delete mode 100644 sys/ViGEmBus.vcxproj delete mode 100644 sys/ViGEmBus.vcxproj.filters delete mode 100644 sys/Xgip.h delete mode 100644 sys/Xusb.h delete mode 100644 sys/busenum.c delete mode 100644 sys/busenum.h delete mode 100644 sys/buspdo.c delete mode 100644 sys/resource.h delete mode 100644 sys/trace.h delete mode 100644 sys/usbpdo.c delete mode 100644 sys/util.c delete mode 100644 sys/xgip.c delete mode 100644 sys/xusb.c diff --git a/ViGEmBus.ddf b/ViGEmBus.ddf deleted file mode 100644 index 082412e..0000000 --- a/ViGEmBus.ddf +++ /dev/null @@ -1,21 +0,0 @@ -.OPTION EXPLICIT -.Set CabinetFileCountThreshold=0 -.Set FolderFileCountThreshold=0 -.Set FolderSizeThreshold=0 -.Set MaxCabinetSize=0 -.Set MaxDiskFileCount=0 -.Set MaxDiskSize=0 -.Set CompressionType=MSZIP -.Set Cabinet=on -.Set Compress=on -.Set CabinetNameTemplate=ViGEmBus.cab -.Set DestinationDir=ViGEmBus -.\artifacts\ViGEmBus.inf -.Set DestinationDir=ViGEmBus\x64 -.\artifacts\x64\ViGEmBus.sys -.\artifacts\x64\ViGEmBus.pdb -.\artifacts\x64\WdfCoinstaller01009.dll -.Set DestinationDir=ViGEmBus\x86 -.\artifacts\x86\ViGEmBus.sys -.\artifacts\x86\ViGEmBus.pdb -.\artifacts\x86\WdfCoinstaller01009.dll \ No newline at end of file diff --git a/ViGEmBus.sln b/ViGEmClient.sln similarity index 60% rename from ViGEmBus.sln rename to ViGEmClient.sln index e57c1c8..eaf1d95 100644 --- a/ViGEmBus.sln +++ b/ViGEmClient.sln @@ -3,9 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27130.2024 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ViGEmBus", "sys\ViGEmBus.vcxproj", "{040101B0-EE5C-4EF1-99EE-9F81C795C001}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ViGEmClient", "lib\ViGEmClient.vcxproj", "{7DB06674-1F4F-464B-8E1C-172E9587F9DC}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ViGEmClient", "src\ViGEmClient.vcxproj", "{7DB06674-1F4F-464B-8E1C-172E9587F9DC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{148E5E2E-2613-4EA5-AB8F-D93747E927E3}" EndProject @@ -37,78 +35,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|ARM.ActiveCfg = Debug|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|ARM.Build.0 = Debug|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|ARM.Deploy.0 = Debug|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|ARM64.ActiveCfg = Debug|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|ARM64.Build.0 = Debug|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|ARM64.Deploy.0 = Debug|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|x64.ActiveCfg = Debug|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|x64.Build.0 = Debug|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|x64.Deploy.0 = Debug|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|x86.ActiveCfg = Debug|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|x86.Build.0 = Debug|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (dynamic)|x86.Deploy.0 = Debug|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|ARM.ActiveCfg = Debug|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|ARM.Build.0 = Debug|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|ARM.Deploy.0 = Debug|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|ARM64.ActiveCfg = Debug|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|ARM64.Build.0 = Debug|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|ARM64.Deploy.0 = Debug|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|x64.ActiveCfg = Debug|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|x64.Build.0 = Debug|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|x64.Deploy.0 = Debug|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|x86.ActiveCfg = Debug|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|x86.Build.0 = Debug|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug (static)|x86.Deploy.0 = Debug|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|ARM.ActiveCfg = Debug|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|ARM.Build.0 = Debug|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|ARM.Deploy.0 = Debug|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|ARM64.Build.0 = Debug|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x64.ActiveCfg = Debug|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x64.Build.0 = Debug|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x64.Deploy.0 = Debug|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x86.ActiveCfg = Debug|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x86.Build.0 = Debug|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x86.Deploy.0 = Debug|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|ARM.ActiveCfg = Release|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|ARM.Build.0 = Release|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|ARM.Deploy.0 = Release|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|ARM64.ActiveCfg = Release|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|ARM64.Build.0 = Release|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|ARM64.Deploy.0 = Release|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|x64.ActiveCfg = Release|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|x64.Build.0 = Release|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|x64.Deploy.0 = Release|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|x86.ActiveCfg = Release|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|x86.Build.0 = Release|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (dynamic)|x86.Deploy.0 = Release|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|ARM.ActiveCfg = Release|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|ARM.Build.0 = Release|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|ARM.Deploy.0 = Release|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|ARM64.ActiveCfg = Release|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|ARM64.Build.0 = Release|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|ARM64.Deploy.0 = Release|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|x64.ActiveCfg = Release|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|x64.Build.0 = Release|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|x64.Deploy.0 = Release|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|x86.ActiveCfg = Release|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|x86.Build.0 = Release|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release (static)|x86.Deploy.0 = Release|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|ARM.ActiveCfg = Release|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|ARM.Build.0 = Release|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|ARM.Deploy.0 = Release|ARM - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|ARM64.ActiveCfg = Release|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|ARM64.Build.0 = Release|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|ARM64.Deploy.0 = Release|ARM64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x64.ActiveCfg = Release|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x64.Build.0 = Release|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x64.Deploy.0 = Release|x64 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x86.ActiveCfg = Release|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x86.Build.0 = Release|Win32 - {040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x86.Deploy.0 = Release|Win32 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (dynamic)|ARM.ActiveCfg = Debug (dynamic)|Win32 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (dynamic)|ARM64.ActiveCfg = Debug (dynamic)|Win32 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (dynamic)|x64.ActiveCfg = Debug (dynamic)|x64 diff --git a/include/ViGEmBusDriver.h b/include/ViGEmBusDriver.h deleted file mode 100644 index 938e761..0000000 --- a/include/ViGEmBusDriver.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -// {A77BC4D5-6AF7-4E69-8DC4-6B88A6028CE6} -// ReSharper disable once CppMissingIncludeGuard -DEFINE_GUID(GUID_VIGEM_INTERFACE_PDO, - 0xA77BC4D5, 0x6AF7, 0x4E69, 0x8D, 0xC4, 0x6B, 0x88, 0xA6, 0x02, 0x8C, 0xE6); - -// {A8BA2D1F-894F-464A-B0CE-7A0C8FD65DF1} -DEFINE_GUID(GUID_DEVCLASS_VIGEM_RAWPDO, - 0xA8BA2D1F, 0x894F, 0x464A, 0xB0, 0xCE, 0x7A, 0x0C, 0x8F, 0xD6, 0x5D, 0xF1); - -#pragma once - - -// -// Describes the current stage a PDO completed -// -typedef enum _VIGEM_PDO_STAGE -{ - ViGEmPdoCreate, - ViGEmPdoPrepareHardware, - ViGEmPdoInitFinished - -} VIGEM_PDO_STAGE, *PVIGEM_PDO_STAGE; - -// -// PDO stage result callback definition -// -typedef -VOID -(*PVIGEM_BUS_PDO_STAGE_RESULT)( - _In_ PINTERFACE InterfaceHeader, - _In_ VIGEM_PDO_STAGE Stage, - _In_ ULONG Serial, - _In_ NTSTATUS Status - ); - -typedef struct _VIGEM_BUS_INTERFACE { - // - // Standard interface header, must be present - // - INTERFACE InterfaceHeader; - - // - // PDO stage result callback - // - PVIGEM_BUS_PDO_STAGE_RESULT BusPdoStageResult; - -} VIGEM_BUS_INTERFACE, *PVIGEM_BUS_INTERFACE; - -#define VIGEM_BUS_INTERFACE_VERSION 1 - -VOID FORCEINLINE BUS_PDO_REPORT_STAGE_RESULT( - VIGEM_BUS_INTERFACE Interface, - VIGEM_PDO_STAGE Stage, - ULONG Serial, - NTSTATUS Status -) -{ - (*Interface.BusPdoStageResult)(&Interface.InterfaceHeader, Stage, Serial, Status); -} - diff --git a/include/ViGEmBusShared.h b/include/km/ViGEmBusShared.h similarity index 100% rename from include/ViGEmBusShared.h rename to include/km/ViGEmBusShared.h diff --git a/lib/README.md b/src/README.md similarity index 100% rename from lib/README.md rename to src/README.md diff --git a/lib/ViGEmClient.cpp b/src/ViGEmClient.cpp similarity index 99% rename from lib/ViGEmClient.cpp rename to src/ViGEmClient.cpp index 63af076..b3214bb 100644 --- a/lib/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -29,7 +29,7 @@ SOFTWARE. #include #include -#include "ViGEmBusShared.h" +#include "km/ViGEmBusShared.h" #include "ViGEmClient.h" #include #include diff --git a/lib/ViGEmClient.rc b/src/ViGEmClient.rc similarity index 100% rename from lib/ViGEmClient.rc rename to src/ViGEmClient.rc diff --git a/lib/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj similarity index 100% rename from lib/ViGEmClient.vcxproj rename to src/ViGEmClient.vcxproj diff --git a/lib/ViGEmClient.vcxproj.filters b/src/ViGEmClient.vcxproj.filters similarity index 100% rename from lib/ViGEmClient.vcxproj.filters rename to src/ViGEmClient.vcxproj.filters diff --git a/lib/resource.h b/src/resource.h similarity index 100% rename from lib/resource.h rename to src/resource.h diff --git a/sys/ByteArray.c b/sys/ByteArray.c deleted file mode 100644 index 0a00e7d..0000000 --- a/sys/ByteArray.c +++ /dev/null @@ -1,191 +0,0 @@ -#include "ByteArray.h" -#include "trace.h" -#include "bytearray.tmh" - -// -// Helpers -// - -ULONG_PTR align_to_page_size(ULONG_PTR val) -{ - return (val + (PAGE_SIZE - 1)) & -PAGE_SIZE; -} - - -// -// Forward decalarations -// - -NTSTATUS IncreaseCapacityByteArray(IN PBYTE_ARRAY Array, IN ULONG NumElements); - - -// -// Implementation -// - -NTSTATUS InitByteArray(IN OUT PBYTE_ARRAY Array) -{ - // - // Initialize size and default capacity - Array->Size = 0; - Array->Capacity = INITIAL_ARRAY_CAPACITY; - - // - // Allocate memory - Array->Data = (UCHAR*)ExAllocatePoolWithTag(PagedPool, Array->Capacity, ARRAY_POOL_TAG); - if (Array->Data == NULL) - return STATUS_INSUFFICIENT_RESOURCES; - - return STATUS_SUCCESS; -} - -NTSTATUS AppendElementByteArray(IN PBYTE_ARRAY Array, IN PVOID Element) -{ - // - // Make sure there is room to expand into - if (((Array->Size + 1) * sizeof(UCHAR)) > Array->Capacity) - { - // - // Increase capacity - NTSTATUS status = IncreaseCapacityByteArray(Array, sizeof(UCHAR)); - if (!NT_SUCCESS(status)) - return status; - } - - // - // Append the element and increment the size - RtlCopyMemory(Array->Data + (Array->Size * sizeof(UCHAR)), Element, sizeof(UCHAR)); - - // - // Increment size - Array->Size += 1; - - return STATUS_SUCCESS; -} - -NTSTATUS AppendElementsByteArray(IN PBYTE_ARRAY Array, IN PVOID Elements, IN ULONG NumElements) -{ - // - // Make sure there is room to expand into - if ((Array->Size + NumElements) * sizeof(UCHAR) > Array->Capacity) - { - // - // Increase capacity - NTSTATUS status = IncreaseCapacityByteArray(Array, NumElements); - if (!NT_SUCCESS(status)) - return status; - } - - // - // Append the elements and increase the size - RtlCopyMemory(Array->Data + (Array->Size * sizeof(UCHAR)), Elements, NumElements * sizeof(UCHAR)); - - // - // Increase size - Array->Size += NumElements; - - return STATUS_SUCCESS; -} - -NTSTATUS IncreaseCapacityByteArray(IN PBYTE_ARRAY Array, IN ULONG NumElements) -{ - UCHAR* NewData = NULL; - - // - // Align new size to the immediate next page boundary - Array->Capacity = align_to_page_size((Array->Size + NumElements) * sizeof(UCHAR)); - - // - // Allocate new data with new capacity - NewData = (UCHAR*)ExAllocatePoolWithTag(PagedPool, Array->Capacity, ARRAY_POOL_TAG); - if (NewData == NULL) - return STATUS_INSUFFICIENT_RESOURCES; - - // - // Copy old data over - RtlCopyMemory(NewData, Array->Data, Array->Size * sizeof(UCHAR)); - - // - // Free old data - ExFreePoolWithTag(Array->Data, ARRAY_POOL_TAG); - - // - // Set data pointer to new allocation - Array->Data = NewData; - - return STATUS_SUCCESS; -} - -NTSTATUS GetElementByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, OUT PVOID Element) -{ - // - // Check array bounds - if (Index >= Array->Size || (LONG)Index < 0) - return STATUS_ARRAY_BOUNDS_EXCEEDED; - - // - // Copy data over - RtlCopyMemory(Element, Array->Data + (Index * sizeof(UCHAR)), sizeof(UCHAR)); - - return STATUS_SUCCESS; -} - -NTSTATUS GetElementsByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, OUT PVOID Elements, IN ULONG NumElements) -{ - // - // Check array bounds - if (Index >= Array->Size || (LONG)Index < 0) - return STATUS_ARRAY_BOUNDS_EXCEEDED; - - // - // Copy data over - RtlCopyMemory(Elements, Array->Data + (Index * sizeof(UCHAR)), NumElements * sizeof(UCHAR)); - - return STATUS_SUCCESS; -} - -NTSTATUS SetElementByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, IN PVOID Element) -{ - // - // Check array bounds - if (Index >= Array->Size || (LONG)Index < 0) - return STATUS_ARRAY_BOUNDS_EXCEEDED; - - // - // Copy data over - RtlCopyMemory(Array->Data + (Index * sizeof(UCHAR)), Element, sizeof(UCHAR)); - - return STATUS_SUCCESS; -} - -NTSTATUS SetElementsByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, IN PVOID Elements, IN ULONG NumElements) -{ - // - // Check array bounds - if (Index >= Array->Size || (LONG)Index < 0) - return STATUS_ARRAY_BOUNDS_EXCEEDED; - - // - // Copy data over - RtlCopyMemory(Array->Data + (Index * sizeof(UCHAR)), Elements, NumElements * sizeof(UCHAR)); - - return STATUS_SUCCESS; -} - -NTSTATUS FreeByteArray(IN PBYTE_ARRAY Array) -{ - if (Array->Data == NULL) - return STATUS_MEMORY_NOT_ALLOCATED; - - // - // Free data - ExFreePoolWithTag(Array->Data, ARRAY_POOL_TAG); - - // - // Null out everything - Array->Data = NULL; - Array->Size = 0; - Array->Capacity = 0; - - return STATUS_SUCCESS; -} diff --git a/sys/ByteArray.h b/sys/ByteArray.h deleted file mode 100644 index 8ae3661..0000000 --- a/sys/ByteArray.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -#define INITIAL_ARRAY_CAPACITY PAGE_SIZE -#define ARRAY_POOL_TAG 'arrA' - -typedef struct _BYTE_ARRAY -{ - UCHAR* Data; //> array of data we're storing - ULONG_PTR Size; //> slots used so far - ULONG_PTR Capacity; //> total available memory -} BYTE_ARRAY, *PBYTE_ARRAY; - -NTSTATUS InitByteArray(IN OUT PBYTE_ARRAY Array); - -NTSTATUS AppendElementByteArray(IN PBYTE_ARRAY Array, IN PVOID Element); - -NTSTATUS AppendElementsByteArray(IN PBYTE_ARRAY Array, IN PVOID Elements, IN ULONG NumElements); - -NTSTATUS GetElementByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, OUT PVOID Element); - -NTSTATUS GetElementsByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, OUT PVOID Elements, IN ULONG NumElements); - -NTSTATUS SetElementByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, IN PVOID Element); - -NTSTATUS SetElementsByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, IN PVOID Elements, IN ULONG NumElements); - -NTSTATUS FreeByteArray(IN PBYTE_ARRAY Array); \ No newline at end of file diff --git a/sys/Context.h b/sys/Context.h deleted file mode 100644 index 94da20c..0000000 --- a/sys/Context.h +++ /dev/null @@ -1,194 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -#pragma once - -// -// Used to identify children in the device list of the bus. -// -typedef struct _PDO_IDENTIFICATION_DESCRIPTION -{ - WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Header; // should contain this header - - // - // Unique serial number of the device on the bus - // - ULONG SerialNo; - - // - // PID of the process creating this PDO - // - DWORD OwnerProcessId; - - // - // Device type this PDO is emulating - // - VIGEM_TARGET_TYPE TargetType; - - // - // If set, the vendor ID the emulated device is reporting - // - USHORT VendorId; - - // - // If set, the product ID the emulated device is reporting - // - USHORT ProductId; - - // - // Is the current device owner another driver? - // - BOOLEAN OwnerIsDriver; - - // - // SessionId associated with file handle. Used to map file handles to emulated gamepad devices - // - LONG SessionId; - -} PDO_IDENTIFICATION_DESCRIPTION, *PPDO_IDENTIFICATION_DESCRIPTION; - -// -// The PDO device-extension (context). -// -typedef struct _PDO_DEVICE_DATA -{ - // - // Unique serial number of the device on the bus - // - ULONG SerialNo; - - // - // PID of the process creating this PDO - // - DWORD OwnerProcessId; - - // - // Device type this PDO is emulating - // - VIGEM_TARGET_TYPE TargetType; - - // - // If set, the vendor ID the emulated device is reporting - // - USHORT VendorId; - - // - // If set, the product ID the emulated device is reporting - // - USHORT ProductId; - - // - // Interface for PDO to FDO communication - // - VIGEM_BUS_INTERFACE BusInterface; - - // - // Queue for incoming data interrupt transfer - // - WDFQUEUE PendingUsbInRequests; - - // - // Queue for inverted calls - // - WDFQUEUE PendingNotificationRequests; - -} PDO_DEVICE_DATA, *PPDO_DEVICE_DATA; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PDO_DEVICE_DATA, PdoGetData) - -// -// FDO (bus device) context data -// -typedef struct _FDO_DEVICE_DATA -{ - // - // Counter of interface references - // - LONG InterfaceReferenceCounter; - - // - // Next SessionId to assign to a file handle - // - LONG NextSessionId; - - // - // Collection holding pending plugin requests - // - WDFCOLLECTION PendingPluginRequests; - - // - // Sync lock for pending request collection - // - WDFSPINLOCK PendingPluginRequestsLock; - - // - // Periodic timer sweeping up orphaned requests - // - WDFTIMER PendingPluginRequestsCleanupTimer; - -} FDO_DEVICE_DATA, *PFDO_DEVICE_DATA; - -#define FDO_FIRST_SESSION_ID 100 - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_DEVICE_DATA, FdoGetData) - -// -// Context data associated with file objects created by user mode applications -// -typedef struct _FDO_FILE_DATA -{ - // - // SessionId associated with file handle. Used to map file handles to emulated gamepad devices - // - LONG SessionId; - -} FDO_FILE_DATA, *PFDO_FILE_DATA; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_FILE_DATA, FileObjectGetData) - -// -// Context data for plugin requests -// -typedef struct _FDO_PLUGIN_REQUEST_DATA -{ - // - // Unique serial number of the device on the bus - // - ULONG Serial; - - // - // High resolution timestamp taken when this request got moved to pending state - // - LARGE_INTEGER Timestamp; - - // - // Performance counter system frequency taken upon fetching timestamp - // - LARGE_INTEGER Frequency; - -} FDO_PLUGIN_REQUEST_DATA, *PFDO_PLUGIN_REQUEST_DATA; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_PLUGIN_REQUEST_DATA, PluginRequestGetData) - diff --git a/sys/Driver.c b/sys/Driver.c deleted file mode 100644 index fdfdd6b..0000000 --- a/sys/Driver.c +++ /dev/null @@ -1,660 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 "busenum.h" -#include -#include "driver.tmh" - -#ifdef ALLOC_PRAGMA -#pragma alloc_text (INIT, DriverEntry) -#pragma alloc_text (PAGE, Bus_EvtDeviceAdd) -#pragma alloc_text (PAGE, Bus_DeviceFileCreate) -#pragma alloc_text (PAGE, Bus_FileClose) -#pragma alloc_text (PAGE, Bus_EvtDriverContextCleanup) -#pragma alloc_text (PAGE, Bus_PdoStageResult) -#endif - - -// -// Driver entry routine. -// -NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) -{ - WDF_DRIVER_CONFIG config; - NTSTATUS status; - WDFDRIVER driver; - WDF_OBJECT_ATTRIBUTES attributes; - - KdPrint((DRIVERNAME "Virtual Gamepad Emulation Bus Driver [built: %s %s]\n", __DATE__, __TIME__)); - - // - // Initialize WPP Tracing - // - WPP_INIT_TRACING(DriverObject, RegistryPath); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DRIVER, - "Loading Virtual Gamepad Emulation Bus Driver [built: %s %s]", - __DATE__, __TIME__); - - // - // Register cleanup callback - // - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.EvtCleanupCallback = Bus_EvtDriverContextCleanup; - - WDF_DRIVER_CONFIG_INIT(&config, Bus_EvtDeviceAdd); - - status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, &driver); - - if (!NT_SUCCESS(status)) - { - WPP_CLEANUP(DriverObject); - KdPrint((DRIVERNAME "WdfDriverCreate failed with status 0x%x\n", status)); - } - - return status; -} - -// -// Bus-device creation routine. -// -NTSTATUS Bus_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) -{ - WDF_CHILD_LIST_CONFIG config; - NTSTATUS status; - WDFDEVICE device; - WDF_IO_QUEUE_CONFIG queueConfig; - PNP_BUS_INFORMATION busInfo; - WDFQUEUE queue; - WDF_FILEOBJECT_CONFIG foConfig; - WDF_OBJECT_ATTRIBUTES fdoAttributes; - WDF_OBJECT_ATTRIBUTES fileHandleAttributes; - WDF_OBJECT_ATTRIBUTES collectionAttributes; - WDF_OBJECT_ATTRIBUTES timerAttributes; - PFDO_DEVICE_DATA pFDOData; - VIGEM_BUS_INTERFACE busInterface; - PINTERFACE interfaceHeader; - WDF_TIMER_CONFIG reqTimerCfg; - - UNREFERENCED_PARAMETER(Driver); - - PAGED_CODE(); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); - - WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); - // More than one process may talk to the bus at the same time - WdfDeviceInitSetExclusive(DeviceInit, FALSE); - // Bus is power policy owner over all PDOs - WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, TRUE); - -#pragma region Prepare child list - - WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(PDO_IDENTIFICATION_DESCRIPTION), Bus_EvtDeviceListCreatePdo); - - config.EvtChildListIdentificationDescriptionCompare = Bus_EvtChildListIdentificationDescriptionCompare; - - WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES); - -#pragma endregion - -#pragma region Assign File Object Configuration - - WDF_FILEOBJECT_CONFIG_INIT(&foConfig, Bus_DeviceFileCreate, Bus_FileClose, NULL); - - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fileHandleAttributes, FDO_FILE_DATA); - - WdfDeviceInitSetFileObjectConfig(DeviceInit, &foConfig, &fileHandleAttributes); - -#pragma endregion - -#pragma region Create FDO - - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DEVICE_DATA); - - status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device); - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "WdfDeviceCreate failed with status %!STATUS!", - status); - return status; - } - - pFDOData = FdoGetData(device); - if (pFDOData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "FdoGetData failed"); - return STATUS_UNSUCCESSFUL; - } - - pFDOData->InterfaceReferenceCounter = 0; - pFDOData->NextSessionId = FDO_FIRST_SESSION_ID; - -#pragma endregion - -#pragma region Create pending requests collection & lock - - WDF_OBJECT_ATTRIBUTES_INIT(&collectionAttributes); - collectionAttributes.ParentObject = device; - - status = WdfCollectionCreate(&collectionAttributes, &pFDOData->PendingPluginRequests); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "WdfCollectionCreate failed with status %!STATUS!", - status); - return STATUS_UNSUCCESSFUL; - } - - WDF_OBJECT_ATTRIBUTES_INIT(&collectionAttributes); - collectionAttributes.ParentObject = device; - - status = WdfSpinLockCreate(&collectionAttributes, &pFDOData->PendingPluginRequestsLock); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "WdfSpinLockCreate failed with status %!STATUS!", - status); - return STATUS_UNSUCCESSFUL; - } - -#pragma endregion - -#pragma region Create timer for sweeping up orphaned requests - - WDF_TIMER_CONFIG_INIT_PERIODIC( - &reqTimerCfg, - Bus_PlugInRequestCleanUpEvtTimerFunc, - ORC_TIMER_START_DELAY - ); - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); - timerAttributes.ParentObject = device; - - status = WdfTimerCreate(&reqTimerCfg, &timerAttributes, &pFDOData->PendingPluginRequestsCleanupTimer); - if (!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "WdfTimerCreate failed with status %!STATUS!", - status); - return status; - } - -#pragma endregion - -#pragma region Add query interface - - // - // Set up the common interface header - // - interfaceHeader = &busInterface.InterfaceHeader; - - interfaceHeader->Size = sizeof(VIGEM_BUS_INTERFACE); - interfaceHeader->Version = VIGEM_BUS_INTERFACE_VERSION; - interfaceHeader->Context = (PVOID)device; - - // - // We don't pay any particular attention to the reference - // counting of this interface, but we MUST specify routines for - // it. Luckily the framework provides dummy routines - // - interfaceHeader->InterfaceReference = WdfDeviceInterfaceReferenceNoOp; - interfaceHeader->InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; - - busInterface.BusPdoStageResult = Bus_PdoStageResult; - - WDF_QUERY_INTERFACE_CONFIG queryInterfaceConfig; - - WDF_QUERY_INTERFACE_CONFIG_INIT(&queryInterfaceConfig, - interfaceHeader, - &GUID_VIGEM_INTERFACE_PDO, - WDF_NO_EVENT_CALLBACK); - - status = WdfDeviceAddQueryInterface(device, - &queryInterfaceConfig); - - if (!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "WdfDeviceAddQueryInterface failed with status %!STATUS!", - status); - return(status); - } - -#pragma endregion - -#pragma region Create default I/O queue for FDO - - WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); - - queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl; - queueConfig.EvtIoInternalDeviceControl = Bus_EvtIoInternalDeviceControl; - queueConfig.EvtIoDefault = Bus_EvtIoDefault; - - __analysis_assume(queueConfig.EvtIoStop != 0); - status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); - __analysis_assume(queueConfig.EvtIoStop == 0); - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "WdfIoQueueCreate failed with status %!STATUS!", - status); - return status; - } - -#pragma endregion - -#pragma region Expose FDO interface - - status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BUSENUM_VIGEM, NULL); - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "WdfDeviceCreateDeviceInterface failed with status %!STATUS!", - status); - return status; - } - -#pragma endregion - -#pragma region Set bus information - - busInfo.BusTypeGuid = GUID_BUS_TYPE_USB; - busInfo.LegacyBusType = PNPBus; - busInfo.BusNumber = 0; - - WdfDeviceSetBusInformationForChildren(device, &busInfo); - -#pragma endregion - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status); - - return status; -} - -// Gets called when the user-land process (or kernel driver) exits or closes the handle, -// and all IO has completed. -// -_Use_decl_annotations_ -VOID -Bus_DeviceFileCreate( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ WDFFILEOBJECT FileObject -) -{ - NTSTATUS status = STATUS_INVALID_PARAMETER; - PFDO_FILE_DATA pFileData = NULL; - PFDO_DEVICE_DATA pFDOData = NULL; - LONG refCount = 0; - LONG sessionId = 0; - - UNREFERENCED_PARAMETER(Request); - - PAGED_CODE(); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); - - pFileData = FileObjectGetData(FileObject); - - if (pFileData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "FileObjectGetData failed to return file object from WDFFILEOBJECT 0x%p", - FileObject); - } - else - { - pFDOData = FdoGetData(Device); - if (pFDOData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "FdoGetData failed"); - status = STATUS_NO_SUCH_DEVICE; - } - else - { - refCount = InterlockedIncrement(&pFDOData->InterfaceReferenceCounter); - sessionId = InterlockedIncrement(&pFDOData->NextSessionId); - - pFileData->SessionId = sessionId; - status = STATUS_SUCCESS; - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DRIVER, - "File/session id = %d, device ref. count = %d", - (int)sessionId, (int)refCount); - } - } - - WdfRequestComplete(Request, status); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status); -} - -// -// Gets called when the user-land process (or kernel driver) exits or closes the handle. -// -_Use_decl_annotations_ -VOID -Bus_FileClose( - WDFFILEOBJECT FileObject -) -{ - WDFDEVICE device; - WDFDEVICE hChild; - NTSTATUS status; - WDFCHILDLIST list; - WDF_CHILD_LIST_ITERATOR iterator; - WDF_CHILD_RETRIEVE_INFO childInfo; - PDO_IDENTIFICATION_DESCRIPTION description; - PFDO_FILE_DATA pFileData = NULL; - PFDO_DEVICE_DATA pFDOData = NULL; - LONG refCount = 0; - - PAGED_CODE(); - - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); - - // Check common context - pFileData = FileObjectGetData(FileObject); - if (pFileData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "FileObjectGetData failed to return file object from WDFFILEOBJECT 0x%p", - FileObject); - return; - } - - device = WdfFileObjectGetDevice(FileObject); - - pFDOData = FdoGetData(device); - if (pFDOData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "FdoGetData failed"); - status = STATUS_NO_SUCH_DEVICE; - } - else - { - refCount = InterlockedDecrement(&pFDOData->InterfaceReferenceCounter); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DRIVER, - "Device ref. count = %d", - (int)refCount); - } - - list = WdfFdoGetDefaultChildList(device); - - WDF_CHILD_LIST_ITERATOR_INIT(&iterator, WdfRetrievePresentChildren); - - WdfChildListBeginIteration(list, &iterator); - - for (;;) - { - WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &description.Header); - WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description)); - - status = WdfChildListRetrieveNextDevice(list, &iterator, &hChild, &childInfo); - if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES) - { - break; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_DRIVER, - "PDO properties: status = %!STATUS!, pdoPID = %d, curPID = %d, pdoSID = %d, curSID = %d, internal = %d", - (int)childInfo.Status, - (int)description.OwnerProcessId, - (int)CURRENT_PROCESS_ID(), - (int)description.SessionId, - (int)pFileData->SessionId, - (int)description.OwnerIsDriver - ); - - // Only unplug devices with matching session id - if (childInfo.Status == WdfChildListRetrieveDeviceSuccess - && description.SessionId == pFileData->SessionId - && !description.OwnerIsDriver) - { - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DRIVER, - "Unplugging device with serial %d", - description.SerialNo); - - // "Unplug" child - status = WdfChildListUpdateChildDescriptionAsMissing(list, &description.Header); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DRIVER, - "WdfChildListUpdateChildDescriptionAsMissing failed with status %!STATUS!", - status); - } - } - } - - WdfChildListEndIteration(list, &iterator); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status); -} - -VOID -Bus_EvtDriverContextCleanup( - _In_ WDFOBJECT DriverObject -) -/*++ -Routine Description: - - Free all the resources allocated in DriverEntry. - -Arguments: - - DriverObject - handle to a WDF Driver object. - -Return Value: - - VOID. - ---*/ -{ - UNREFERENCED_PARAMETER(DriverObject); - - PAGED_CODE(); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); - - // - // Stop WPP Tracing - // - WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject)); - -} - -// -// Called by PDO when a boot-up stage has been completed -// -_Use_decl_annotations_ -VOID -Bus_PdoStageResult( - _In_ PINTERFACE InterfaceHeader, - _In_ VIGEM_PDO_STAGE Stage, - _In_ ULONG Serial, - _In_ NTSTATUS Status -) -{ - ULONG i; - PFDO_DEVICE_DATA pFdoData; - WDFREQUEST curRequest; - ULONG curSerial; - ULONG items; - - UNREFERENCED_PARAMETER(InterfaceHeader); - - PAGED_CODE(); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DRIVER, - "%!FUNC! Entry (stage = %d, serial = %d, status = %!STATUS!)", - Stage, Serial, Status); - - pFdoData = FdoGetData(InterfaceHeader->Context); - - // - // If any stage fails or is last stage, get associated request and complete it - // - if (!NT_SUCCESS(Status) || Stage == ViGEmPdoInitFinished) - { - WdfSpinLockAcquire(pFdoData->PendingPluginRequestsLock); - - items = WdfCollectionGetCount(pFdoData->PendingPluginRequests); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DRIVER, - "Items count: %d", - items); - - for (i = 0; i < items; i++) - { - curRequest = WdfCollectionGetItem(pFdoData->PendingPluginRequests, i); - curSerial = PluginRequestGetData(curRequest)->Serial; - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DRIVER, - "Serial: %d, curSerial: %d", - Serial, curSerial); - - if (Serial == curSerial) - { - WdfRequestComplete(curRequest, Status); - - WdfCollectionRemove(pFdoData->PendingPluginRequests, curRequest); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DRIVER, - "Removed item with serial: %d", - curSerial); - - break; - } - } - WdfSpinLockRelease(pFdoData->PendingPluginRequestsLock); - } - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit"); -} - -_Use_decl_annotations_ -VOID -Bus_PlugInRequestCleanUpEvtTimerFunc( - WDFTIMER Timer -) -{ - ULONG i; - PFDO_DEVICE_DATA pFdoData; - WDFREQUEST curRequest; - ULONG items; - WDFDEVICE device; - PFDO_PLUGIN_REQUEST_DATA pPluginData; - LONGLONG freq; - LARGE_INTEGER pcNow; - LONGLONG ellapsed; - - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); - - device = WdfTimerGetParentObject(Timer); - pFdoData = FdoGetData(device); - - WdfSpinLockAcquire(pFdoData->PendingPluginRequestsLock); - - items = WdfCollectionGetCount(pFdoData->PendingPluginRequests); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DRIVER, - "Items count: %d", - items); - - // - // Collection is empty; no need to keep timer running - // - if (items == 0) - { - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_DRIVER, - "Collection is empty, stopping periodic timer"); - WdfTimerStop(Timer, FALSE); - } - - for (i = 0; i < items; i++) - { - curRequest = WdfCollectionGetItem(pFdoData->PendingPluginRequests, i); - pPluginData = PluginRequestGetData(curRequest); - - freq = pPluginData->Frequency.QuadPart / ORC_PC_FREQUENCY_DIVIDER; - pcNow = KeQueryPerformanceCounter(NULL); - ellapsed = (pcNow.QuadPart - pPluginData->Timestamp.QuadPart) / freq; - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_DRIVER, - "PDO (serial = %d) plugin request age: %llu ms", - pPluginData->Serial, ellapsed); - - if (ellapsed >= ORC_REQUEST_MAX_AGE) - { - WdfRequestComplete(curRequest, STATUS_SUCCESS); - - WdfCollectionRemove(pFdoData->PendingPluginRequests, curRequest); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DRIVER, - "Removed item with serial: %d", - pPluginData->Serial); - - break; - } - } - WdfSpinLockRelease(pFdoData->PendingPluginRequestsLock); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit"); -} - diff --git a/sys/Ds4.c b/sys/Ds4.c deleted file mode 100644 index 627375e..0000000 --- a/sys/Ds4.c +++ /dev/null @@ -1,466 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 "busenum.h" -#include -#include "ds4.tmh" - -NTSTATUS Ds4_PreparePdo(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId, PUNICODE_STRING DeviceDescription) -{ - NTSTATUS status; - UNICODE_STRING buffer; - - // prepare device description - status = RtlUnicodeStringInit(DeviceDescription, L"Virtual DualShock 4 Controller"); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "RtlUnicodeStringInit failed with status %!STATUS!", - status); - return status; - } - - // Set hardware IDs - RtlUnicodeStringInit(&buffer, L"USB\\VID_054C&PID_05C4&REV_0100"); - - status = WdfPdoInitAddHardwareID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfPdoInitAddHardwareID failed with status %!STATUS!", - status); - return status; - } - - RtlUnicodeStringCopy(DeviceId, &buffer); - - RtlUnicodeStringInit(&buffer, L"USB\\VID_054C&PID_05C4"); - - status = WdfPdoInitAddHardwareID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfPdoInitAddHardwareID failed with status %!STATUS!", - status); - return status; - } - - // Set compatible IDs - RtlUnicodeStringInit(&buffer, L"USB\\Class_03&SubClass_00&Prot_00"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfPdoInitAddCompatibleID (#01) failed with status %!STATUS!", - status); - return status; - } - - RtlUnicodeStringInit(&buffer, L"USB\\Class_03&SubClass_00"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfPdoInitAddCompatibleID (#02) failed with status %!STATUS!", - status); - return status; - } - - RtlUnicodeStringInit(&buffer, L"USB\\Class_03"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfPdoInitAddCompatibleID (#03) failed with status %!STATUS!", - status); - return status; - } - - return STATUS_SUCCESS; -} - -NTSTATUS Ds4_PrepareHardware(WDFDEVICE Device) -{ - NTSTATUS status; - WDF_QUERY_INTERFACE_CONFIG ifaceCfg; - INTERFACE devinterfaceHid; - - devinterfaceHid.Size = sizeof(INTERFACE); - devinterfaceHid.Version = 1; - devinterfaceHid.Context = (PVOID)Device; - - devinterfaceHid.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; - devinterfaceHid.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; - - // Expose GUID_DEVINTERFACE_HID so HIDUSB can initialize - WDF_QUERY_INTERFACE_CONFIG_INIT(&ifaceCfg, (PINTERFACE)&devinterfaceHid, &GUID_DEVINTERFACE_HID, NULL); - - status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfDeviceAddQueryInterface failed with status %!STATUS!", - status); - return status; - } - - PDS4_DEVICE_DATA ds4Data = Ds4GetData(Device); - - // Set default HID input report (everything zero`d) - UCHAR DefaultHidReport[DS4_REPORT_SIZE] = - { - 0x01, 0x82, 0x7F, 0x7E, 0x80, 0x08, 0x00, 0x58, - 0x00, 0x00, 0xFD, 0x63, 0x06, 0x03, 0x00, 0xFE, - 0xFF, 0xFC, 0xFF, 0x79, 0xFD, 0x1B, 0x14, 0xD1, - 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 - }; - - // Initialize HID reports to defaults - RtlCopyBytes(ds4Data->Report, DefaultHidReport, DS4_REPORT_SIZE); - RtlZeroMemory(&ds4Data->OutputReport, sizeof(DS4_OUTPUT_REPORT)); - - // Start pending IRP queue flush timer - WdfTimerStart(ds4Data->PendingUsbInRequestsTimer, DS4_QUEUE_FLUSH_PERIOD); - - return STATUS_SUCCESS; -} - -NTSTATUS Ds4_AssignPdoContext(WDFDEVICE Device, PPDO_IDENTIFICATION_DESCRIPTION Description) -{ - NTSTATUS status; - PDS4_DEVICE_DATA ds4 = Ds4GetData(Device); - - // Initialize periodic timer - WDF_TIMER_CONFIG timerConfig; - WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, Ds4_PendingUsbRequestsTimerFunc, DS4_QUEUE_FLUSH_PERIOD); - - // Timer object attributes - WDF_OBJECT_ATTRIBUTES timerAttribs; - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttribs); - - // PDO is parent - timerAttribs.ParentObject = Device; - - // Create timer - status = WdfTimerCreate(&timerConfig, &timerAttribs, &ds4->PendingUsbInRequestsTimer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfTimerCreate failed with status %!STATUS!", - status); - return status; - } - - // Load/generate MAC address - - // TODO: tidy up this region - - WDFKEY keyParams, keyTargets, keyDS, keySerial; - UNICODE_STRING keyName, valueName; - - status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(), STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &keyParams); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfDriverOpenParametersRegistryKey failed with status %!STATUS!", - status); - return status; - } - - RtlUnicodeStringInit(&keyName, L"Targets"); - - status = WdfRegistryCreateKey( - keyParams, - &keyName, - KEY_ALL_ACCESS, - REG_OPTION_NON_VOLATILE, - NULL, - WDF_NO_OBJECT_ATTRIBUTES, - &keyTargets - ); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfRegistryCreateKey failed with status %!STATUS!", - status); - return status; - } - - RtlUnicodeStringInit(&keyName, L"DualShock"); - - status = WdfRegistryCreateKey( - keyTargets, - &keyName, - KEY_ALL_ACCESS, - REG_OPTION_NON_VOLATILE, - NULL, - WDF_NO_OBJECT_ATTRIBUTES, - &keyDS - ); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfRegistryCreateKey failed with status %!STATUS!", - status); - return status; - } - - DECLARE_UNICODE_STRING_SIZE(serialPath, 4); - RtlUnicodeStringPrintf(&serialPath, L"%04d", Description->SerialNo); - - status = WdfRegistryCreateKey( - keyDS, - &serialPath, - KEY_ALL_ACCESS, - REG_OPTION_NON_VOLATILE, - NULL, - WDF_NO_OBJECT_ATTRIBUTES, - &keySerial - ); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfRegistryCreateKey failed with status %!STATUS!", - status); - return status; - } - - RtlUnicodeStringInit(&valueName, L"TargetMacAddress"); - - status = WdfRegistryQueryValue(keySerial, &valueName, sizeof(MAC_ADDRESS), &ds4->TargetMacAddress, NULL, NULL); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_DS4, - "MAC-Address: %02X:%02X:%02X:%02X:%02X:%02X\n", - ds4->TargetMacAddress.Vendor0, - ds4->TargetMacAddress.Vendor1, - ds4->TargetMacAddress.Vendor2, - ds4->TargetMacAddress.Nic0, - ds4->TargetMacAddress.Nic1, - ds4->TargetMacAddress.Nic2); - - if (status == STATUS_OBJECT_NAME_NOT_FOUND) - { - GenerateRandomMacAddress(&ds4->TargetMacAddress); - - status = WdfRegistryAssignValue(keySerial, &valueName, REG_BINARY, sizeof(MAC_ADDRESS), (PVOID)&ds4->TargetMacAddress); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfRegistryAssignValue failed with status %!STATUS!", - status); - return status; - } - } - else if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_DS4, - "WdfRegistryQueryValue failed with status %!STATUS!", - status); - return status; - } - - WdfRegistryClose(keySerial); - WdfRegistryClose(keyDS); - WdfRegistryClose(keyTargets); - WdfRegistryClose(keyParams); - - return STATUS_SUCCESS; -} - -VOID Ds4_GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) -{ - UCHAR Ds4DescriptorData[DS4_DESCRIPTOR_SIZE] = - { - 0x09, // bLength - 0x02, // bDescriptorType (Configuration) - 0x29, 0x00, // wTotalLength 41 - 0x01, // bNumInterfaces 1 - 0x01, // bConfigurationValue - 0x00, // iConfiguration (String Index) - 0xC0, // bmAttributes Self Powered - 0xFA, // bMaxPower 500mA - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x00, // bInterfaceNumber 0 - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints 2 - 0x03, // bInterfaceClass - 0x00, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0x00, // iInterface (String Index) - - 0x09, // bLength - 0x21, // bDescriptorType (HID) - 0x11, 0x01, // bcdHID 1.11 - 0x00, // bCountryCode - 0x01, // bNumDescriptors - 0x22, // bDescriptorType[0] (HID) - 0xD3, 0x01, // wDescriptorLength[0] 467 - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x84, // bEndpointAddress (IN/D2H) - 0x03, // bmAttributes (Interrupt) - 0x40, 0x00, // wMaxPacketSize 64 - 0x05, // bInterval 5 (unit depends on device speed) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x03, // bEndpointAddress (OUT/H2D) - 0x03, // bmAttributes (Interrupt) - 0x40, 0x00, // wMaxPacketSize 64 - 0x05, // bInterval 5 (unit depends on device speed) - - // 41 bytes - - // best guess: USB Standard Descriptor - }; - - RtlCopyBytes(Buffer, Ds4DescriptorData, Length); -} - -VOID Ds4_GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor, PPDO_DEVICE_DATA pCommon) -{ - pDescriptor->bLength = 0x12; - pDescriptor->bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE; - pDescriptor->bcdUSB = 0x0200; // USB v2.0 - pDescriptor->bDeviceClass = 0x00; // per Interface - pDescriptor->bDeviceSubClass = 0x00; - pDescriptor->bDeviceProtocol = 0x00; - pDescriptor->bMaxPacketSize0 = 0x40; - pDescriptor->idVendor = pCommon->VendorId; - pDescriptor->idProduct = pCommon->ProductId; - pDescriptor->bcdDevice = 0x0100; - pDescriptor->iManufacturer = 0x01; - pDescriptor->iProduct = 0x02; - pDescriptor->iSerialNumber = 0x00; - pDescriptor->bNumConfigurations = 0x01; -} - -VOID Ds4_SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo) -{ - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_DS4, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d", - (int)pInfo->Length, - (int)pInfo->InterfaceNumber, - (int)pInfo->AlternateSetting, - pInfo->NumberOfPipes); - - pInfo->Class = 0x03; // HID - pInfo->SubClass = 0x00; - pInfo->Protocol = 0x00; - - pInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; - - pInfo->Pipes[0].MaximumTransferSize = 0x00400000; - pInfo->Pipes[0].MaximumPacketSize = 0x40; - pInfo->Pipes[0].EndpointAddress = 0x84; - pInfo->Pipes[0].Interval = 0x05; - pInfo->Pipes[0].PipeType = 0x03; - pInfo->Pipes[0].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0084; - pInfo->Pipes[0].PipeFlags = 0x00; - - pInfo->Pipes[1].MaximumTransferSize = 0x00400000; - pInfo->Pipes[1].MaximumPacketSize = 0x40; - pInfo->Pipes[1].EndpointAddress = 0x03; - pInfo->Pipes[1].Interval = 0x05; - pInfo->Pipes[1].PipeType = 0x03; - pInfo->Pipes[1].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0003; - pInfo->Pipes[1].PipeFlags = 0x00; -} - -// -// Completes pending I/O requests if feeder is too slow. -// -VOID Ds4_PendingUsbRequestsTimerFunc( - _In_ WDFTIMER Timer -) -{ - NTSTATUS status; - WDFREQUEST usbRequest; - WDFDEVICE hChild; - PDS4_DEVICE_DATA ds4Data; - PIRP pendingIrp; - PIO_STACK_LOCATION irpStack; - PPDO_DEVICE_DATA pdoData; - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DS4, "%!FUNC! Entry"); - - hChild = WdfTimerGetParentObject(Timer); - pdoData = PdoGetData(hChild); - ds4Data = Ds4GetData(hChild); - - // Get pending USB request - status = WdfIoQueueRetrieveNextRequest(pdoData->PendingUsbInRequests, &usbRequest); - - if (NT_SUCCESS(status)) - { - // Get pending IRP - pendingIrp = WdfRequestWdmGetIrp(usbRequest); - irpStack = IoGetCurrentIrpStackLocation(pendingIrp); - - // Get USB request block - PURB urb = (PURB)irpStack->Parameters.Others.Argument1; - - // Get transfer buffer - PUCHAR Buffer = (PUCHAR)urb->UrbBulkOrInterruptTransfer.TransferBuffer; - // Set buffer length to report size - urb->UrbBulkOrInterruptTransfer.TransferBufferLength = DS4_REPORT_SIZE; - - // Copy cached report to transfer buffer - if (Buffer) - RtlCopyBytes(Buffer, ds4Data->Report, DS4_REPORT_SIZE); - - // Complete pending request - WdfRequestComplete(usbRequest, status); - } - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DS4, "%!FUNC! Exit with status %!STATUS!", status); -} - diff --git a/sys/Ds4.h b/sys/Ds4.h deleted file mode 100644 index b590282..0000000 --- a/sys/Ds4.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -#pragma once - -#define HID_GET_FEATURE_REPORT_SIZE_0 0x31 -#define HID_GET_FEATURE_REPORT_SIZE_1 0x25 -#define HID_GET_FEATURE_REPORT_MAC_ADDRESSES_SIZE 0x10 - -#define HID_SET_FEATURE_REPORT_SIZE_0 0x17 -#define HID_SET_FEATURE_REPORT_SIZE_1 0x11 - -#define HID_REPORT_ID_0 0xA3 -#define HID_REPORT_ID_1 0x02 -#define HID_REPORT_MAC_ADDRESSES_ID 0x12 -#define HID_REPORT_ID_3 0x13 -#define HID_REPORT_ID_4 0x14 - -#define DS4_DESCRIPTOR_SIZE 0x0029 -#if defined(_X86_) -#define DS4_CONFIGURATION_SIZE 0x0050 -#else -#define DS4_CONFIGURATION_SIZE 0x0070 -#endif -#define DS4_HID_REPORT_DESCRIPTOR_SIZE 0x01D3 - -#define DS4_MANUFACTURER_NAME_LENGTH 0x38 -#define DS4_PRODUCT_NAME_LENGTH 0x28 -#define DS4_OUTPUT_BUFFER_OFFSET 0x04 -#define DS4_OUTPUT_BUFFER_LENGTH 0x05 - -#define DS4_REPORT_SIZE 0x40 -#define DS4_QUEUE_FLUSH_PERIOD 0x05 - - -// -// DS4-specific device context data. -// -typedef struct _DS4_DEVICE_DATA -{ - // - // HID Input Report buffer - // - UCHAR Report[DS4_REPORT_SIZE]; - - // - // Output report cache - // - DS4_OUTPUT_REPORT OutputReport; - - // - // Timer for dispatching interrupt transfer - // - WDFTIMER PendingUsbInRequestsTimer; - - // - // Auto-generated MAC address of the target device - // - MAC_ADDRESS TargetMacAddress; - - // - // Default MAC address of the host (not used) - // - MAC_ADDRESS HostMacAddress; - -} DS4_DEVICE_DATA, *PDS4_DEVICE_DATA; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DS4_DEVICE_DATA, Ds4GetData) - - -EVT_WDF_TIMER Ds4_PendingUsbRequestsTimerFunc; - -NTSTATUS -Bus_Ds4SubmitReport( - WDFDEVICE Device, - ULONG SerialNo, - PDS4_SUBMIT_REPORT Report, - _In_ BOOLEAN FromInterface -); - -// -// DS4-specific functions -// -NTSTATUS Ds4_PreparePdo(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId, PUNICODE_STRING DeviceDescription); -NTSTATUS Ds4_PrepareHardware(WDFDEVICE Device); -NTSTATUS Ds4_AssignPdoContext(WDFDEVICE Device, PPDO_IDENTIFICATION_DESCRIPTION Description); -VOID Ds4_GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length); -VOID Ds4_GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor, PPDO_DEVICE_DATA pCommon); -VOID Ds4_SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo); - diff --git a/sys/Queue.c b/sys/Queue.c deleted file mode 100644 index 6ceafd8..0000000 --- a/sys/Queue.c +++ /dev/null @@ -1,458 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 "busenum.h" -#include "queue.tmh" - -#ifdef ALLOC_PRAGMA -#pragma alloc_text (PAGE, Bus_EvtIoDefault) -#endif - -// -// Responds to I/O control requests sent to the FDO. -// -VOID Bus_EvtIoDeviceControl( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t OutputBufferLength, - IN size_t InputBufferLength, - IN ULONG IoControlCode -) -{ - NTSTATUS status = STATUS_INVALID_PARAMETER; - WDFDEVICE Device; - size_t length = 0; - PXUSB_SUBMIT_REPORT xusbSubmit = NULL; - PXUSB_REQUEST_NOTIFICATION xusbNotify = NULL; - PDS4_SUBMIT_REPORT ds4Submit = NULL; - PDS4_REQUEST_NOTIFICATION ds4Notify = NULL; - PXGIP_SUBMIT_REPORT xgipSubmit = NULL; - PXGIP_SUBMIT_INTERRUPT xgipInterrupt = NULL; - PVIGEM_CHECK_VERSION pCheckVersion = NULL; - PXUSB_GET_USER_INDEX pXusbGetUserIndex = NULL; - - Device = WdfIoQueueGetDevice(Queue); - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_QUEUE, "%!FUNC! Entry (device: 0x%p)", Device); - - switch (IoControlCode) - { -#pragma region IOCTL_VIGEM_CHECK_VERSION - case IOCTL_VIGEM_CHECK_VERSION: - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_QUEUE, - "IOCTL_VIGEM_CHECK_VERSION"); - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(VIGEM_CHECK_VERSION), (PVOID)&pCheckVersion, &length); - - if (!NT_SUCCESS(status) || length != sizeof(VIGEM_CHECK_VERSION)) - { - status = STATUS_INVALID_PARAMETER; - break; - } - - status = (pCheckVersion->Version == VIGEM_COMMON_VERSION) ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED; - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_QUEUE, - "Requested version: 0x%04X, compiled version: 0x%04X", - pCheckVersion->Version, VIGEM_COMMON_VERSION); - - break; -#pragma endregion - -#pragma region IOCTL_VIGEM_PLUGIN_TARGET - case IOCTL_VIGEM_PLUGIN_TARGET: - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_QUEUE, - "IOCTL_VIGEM_PLUGIN_TARGET"); - - status = Bus_PlugInDevice(Device, Request, FALSE, &length); - - break; -#pragma endregion - -#pragma region IOCTL_VIGEM_UNPLUG_TARGET - case IOCTL_VIGEM_UNPLUG_TARGET: - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_QUEUE, - "IOCTL_VIGEM_UNPLUG_TARGET"); - - status = Bus_UnPlugDevice(Device, Request, FALSE, &length); - - break; -#pragma endregion - -#pragma region IOCTL_XUSB_SUBMIT_REPORT - case IOCTL_XUSB_SUBMIT_REPORT: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_QUEUE, - "IOCTL_XUSB_SUBMIT_REPORT"); - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(XUSB_SUBMIT_REPORT), (PVOID)&xusbSubmit, &length); - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_QUEUE, - "WdfRequestRetrieveInputBuffer failed with status %!STATUS!", - status); - break; - } - - if ((sizeof(XUSB_SUBMIT_REPORT) == xusbSubmit->Size) && (length == InputBufferLength)) - { - // This request only supports a single PDO at a time - if (xusbSubmit->SerialNo == 0) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_QUEUE, - "Invalid serial 0 submitted"); - - status = STATUS_INVALID_PARAMETER; - break; - } - - status = Bus_XusbSubmitReport(Device, xusbSubmit->SerialNo, xusbSubmit, FALSE); - } - - break; -#pragma endregion - -#pragma region IOCTL_XUSB_REQUEST_NOTIFICATION - case IOCTL_XUSB_REQUEST_NOTIFICATION: - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_QUEUE, - "IOCTL_XUSB_REQUEST_NOTIFICATION"); - - // Don't accept the request if the output buffer can't hold the results - if (OutputBufferLength < sizeof(XUSB_REQUEST_NOTIFICATION)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_QUEUE, - "Output buffer %d too small, require at least %d", - (int)OutputBufferLength, (int)sizeof(XUSB_REQUEST_NOTIFICATION)); - break; - } - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(XUSB_REQUEST_NOTIFICATION), (PVOID)&xusbNotify, &length); - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_QUEUE, - "WdfRequestRetrieveInputBuffer failed with status %!STATUS!", - status); - break; - } - - if ((sizeof(XUSB_REQUEST_NOTIFICATION) == xusbNotify->Size) && (length == InputBufferLength)) - { - // This request only supports a single PDO at a time - if (xusbNotify->SerialNo == 0) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_QUEUE, - "Invalid serial 0 submitted"); - - status = STATUS_INVALID_PARAMETER; - break; - } - - status = Bus_QueueNotification(Device, xusbNotify->SerialNo, Request); - } - - break; -#pragma endregion - -#pragma region IOCTL_DS4_SUBMIT_REPORT - case IOCTL_DS4_SUBMIT_REPORT: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_QUEUE, - "IOCTL_DS4_SUBMIT_REPORT"); - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(DS4_SUBMIT_REPORT), (PVOID)&ds4Submit, &length); - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_QUEUE, - "WdfRequestRetrieveInputBuffer failed with status %!STATUS!", - status); - break; - } - - if ((sizeof(DS4_SUBMIT_REPORT) == ds4Submit->Size) && (length == InputBufferLength)) - { - // This request only supports a single PDO at a time - if (ds4Submit->SerialNo == 0) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_QUEUE, - "Invalid serial 0 submitted"); - - status = STATUS_INVALID_PARAMETER; - break; - } - - status = Bus_Ds4SubmitReport(Device, ds4Submit->SerialNo, ds4Submit, FALSE); - } - - break; -#pragma endregion - -#pragma region IOCTL_DS4_REQUEST_NOTIFICATION - case IOCTL_DS4_REQUEST_NOTIFICATION: - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_QUEUE, - "IOCTL_DS4_REQUEST_NOTIFICATION"); - - // Don't accept the request if the output buffer can't hold the results - if (OutputBufferLength < sizeof(DS4_REQUEST_NOTIFICATION)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_QUEUE, - "Output buffer %d too small, require at least %d", - (int)OutputBufferLength, (int)sizeof(DS4_REQUEST_NOTIFICATION)); - break; - } - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(DS4_REQUEST_NOTIFICATION), (PVOID)&ds4Notify, &length); - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_QUEUE, - "WdfRequestRetrieveInputBuffer failed with status %!STATUS!", - status); - break; - } - - if ((sizeof(DS4_REQUEST_NOTIFICATION) == ds4Notify->Size) && (length == InputBufferLength)) - { - // This request only supports a single PDO at a time - if (ds4Notify->SerialNo == 0) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_QUEUE, - "Invalid serial 0 submitted"); - - status = STATUS_INVALID_PARAMETER; - break; - } - - status = Bus_QueueNotification(Device, ds4Notify->SerialNo, Request); - } - - break; -#pragma endregion - -#pragma region IOCTL_XGIP_SUBMIT_REPORT - case IOCTL_XGIP_SUBMIT_REPORT: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_QUEUE, - "IOCTL_XGIP_SUBMIT_REPORT"); - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(XGIP_SUBMIT_REPORT), (PVOID)&xgipSubmit, &length); - - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); - break; - } - - if ((sizeof(XGIP_SUBMIT_REPORT) == xgipSubmit->Size) && (length == InputBufferLength)) - { - // This request only supports a single PDO at a time - if (xgipSubmit->SerialNo == 0) - { - status = STATUS_INVALID_PARAMETER; - break; - } - - status = Bus_XgipSubmitReport(Device, xgipSubmit->SerialNo, xgipSubmit, FALSE); - } - - break; -#pragma endregion - -#pragma region IOCTL_XGIP_SUBMIT_INTERRUPT - case IOCTL_XGIP_SUBMIT_INTERRUPT: - - KdPrint((DRIVERNAME "IOCTL_XGIP_SUBMIT_INTERRUPT\n")); - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(XGIP_SUBMIT_INTERRUPT), (PVOID)&xgipInterrupt, &length); - - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); - break; - } - - if ((sizeof(XGIP_SUBMIT_INTERRUPT) == xgipInterrupt->Size) && (length == InputBufferLength)) - { - // This request only supports a single PDO at a time - if (xgipInterrupt->SerialNo == 0) - { - status = STATUS_INVALID_PARAMETER; - break; - } - - status = Bus_XgipSubmitInterrupt(Device, xgipSubmit->SerialNo, xgipInterrupt, FALSE); - } - - break; -#pragma endregion - -#pragma region IOCTL_XUSB_GET_USER_INDEX - case IOCTL_XUSB_GET_USER_INDEX: - - KdPrint((DRIVERNAME "IOCTL_XUSB_GET_USER_INDEX")); - - // Don't accept the request if the output buffer can't hold the results - if (OutputBufferLength < sizeof(XUSB_GET_USER_INDEX)) - { - KdPrint((DRIVERNAME "IOCTL_XUSB_GET_USER_INDEX: output buffer too small: %ul\n", OutputBufferLength)); - break; - } - - status = WdfRequestRetrieveInputBuffer( - Request, - sizeof(XUSB_GET_USER_INDEX), - (PVOID)&pXusbGetUserIndex, - &length); - - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); - break; - } - - if ((sizeof(XUSB_GET_USER_INDEX) == pXusbGetUserIndex->Size) && (length == InputBufferLength)) - { - // This request only supports a single PDO at a time - if (pXusbGetUserIndex->SerialNo == 0) - { - status = STATUS_INVALID_PARAMETER; - break; - } - - status = Xusb_GetUserIndex(Device, pXusbGetUserIndex); - } - - break; -#pragma endregion - - default: - - TraceEvents(TRACE_LEVEL_WARNING, - TRACE_QUEUE, - "Unknown I/O control code 0x%X", IoControlCode); - - break; // default status is STATUS_INVALID_PARAMETER - } - - if (status != STATUS_PENDING) - { - WdfRequestCompleteWithInformation(Request, status, length); - } - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_QUEUE, "%!FUNC! Exit with status %!STATUS!", status); -} - -// -// Gets called upon driver-to-driver communication. -// -// TODO: incomplete and unused currently -// -VOID Bus_EvtIoInternalDeviceControl( - _In_ WDFQUEUE Queue, - _In_ WDFREQUEST Request, - _In_ size_t OutputBufferLength, - _In_ size_t InputBufferLength, - _In_ ULONG IoControlCode -) -{ - NTSTATUS status = STATUS_INVALID_PARAMETER; - WDFDEVICE Device; - size_t length = 0; - - UNREFERENCED_PARAMETER(OutputBufferLength); - UNREFERENCED_PARAMETER(InputBufferLength); - - Device = WdfIoQueueGetDevice(Queue); - - KdPrint((DRIVERNAME "Bus_EvtIoInternalDeviceControl: 0x%p\n", Device)); - - switch (IoControlCode) - { - case IOCTL_VIGEM_PLUGIN_TARGET: - - KdPrint((DRIVERNAME "IOCTL_VIGEM_PLUGIN_TARGET\n")); - - status = Bus_PlugInDevice(Device, Request, TRUE, &length); - - break; - - case IOCTL_VIGEM_UNPLUG_TARGET: - - KdPrint((DRIVERNAME "IOCTL_VIGEM_UNPLUG_TARGET\n")); - - status = Bus_UnPlugDevice(Device, Request, TRUE, &length); - - break; - } - - if (status != STATUS_PENDING) - { - WdfRequestCompleteWithInformation(Request, status, length); - } -} - -// -// Catches unsupported requests. -// -VOID Bus_EvtIoDefault( - _In_ WDFQUEUE Queue, - _In_ WDFREQUEST Request -) -{ - UNREFERENCED_PARAMETER(Queue); - UNREFERENCED_PARAMETER(Request); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "%!FUNC! Entry"); - - WdfRequestComplete(Request, STATUS_INVALID_DEVICE_REQUEST); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "%!FUNC! Exit"); -} \ No newline at end of file diff --git a/sys/Queue.h b/sys/Queue.h deleted file mode 100644 index d2956f8..0000000 --- a/sys/Queue.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -#pragma once - -EVT_WDF_IO_QUEUE_IO_DEFAULT Bus_EvtIoDefault; -EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL Bus_EvtIoDeviceControl; -EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL Bus_EvtIoInternalDeviceControl; diff --git a/sys/README.md b/sys/README.md deleted file mode 100644 index 03e6a90..0000000 --- a/sys/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# ViGEm Bus Driver - -Currently supports emulation of the following USB gamepads: -- [Microsoft Xbox 360 Controller](https://en.wikipedia.org/wiki/Xbox_360_controller) -- [Sony DualShock 4 Controller](https://en.wikipedia.org/wiki/DualShock#DualShock_4) -- [Microsoft Xbox One Controller](https://en.wikipedia.org/wiki/Xbox_One_Controller) - - Experimental; not ready for stable release yet - -## Necessary preparations for Windows 7 -Before installing the bus driver on Windows 7 (x86 or x64) the following 3rd party software has to be installed: - * [Xbox 360 Accessories Software 1.2](https://www.microsoft.com/accessories/en-us/products/gaming/xbox-360-controller-for-windows/52a-00004#techspecs-connect) (contains the missing device drivers) - * [Microsoft Security Advisory 3033929 Update](https://technet.microsoft.com/en-us/library/security/3033929) has to be installed to support the drivers signature. Download links: - * [Security Update for Windows 7 (KB3033929)](https://www.microsoft.com/en-us/download/details.aspx?id=46078) - * [Security Update for Windows 7 for x64-based Systems (KB3033929)](https://www.microsoft.com/en-us/download/details.aspx?id=46148) - -## Installation -[Follow the installation instructions](https://github.com/nefarius/ViGEm/wiki/Driver-Installation). diff --git a/sys/UsbPdo.h b/sys/UsbPdo.h deleted file mode 100644 index 42305cc..0000000 --- a/sys/UsbPdo.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -#pragma once - -BOOLEAN USB_BUSIFFN UsbPdo_IsDeviceHighSpeed(IN PVOID BusContext); -NTSTATUS USB_BUSIFFN UsbPdo_QueryBusInformation( - IN PVOID BusContext, - IN ULONG Level, - IN OUT PVOID BusInformationBuffer, - IN OUT PULONG BusInformationBufferLength, - OUT PULONG BusInformationActualLength -); -NTSTATUS USB_BUSIFFN UsbPdo_SubmitIsoOutUrb(IN PVOID BusContext, IN PURB Urb); -NTSTATUS USB_BUSIFFN UsbPdo_QueryBusTime(IN PVOID BusContext, IN OUT PULONG CurrentUsbFrame); -VOID USB_BUSIFFN UsbPdo_GetUSBDIVersion( - IN PVOID BusContext, - IN OUT PUSBD_VERSION_INFORMATION VersionInformation, - IN OUT PULONG HcdCapabilities -); -NTSTATUS UsbPdo_GetDeviceDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommon); -NTSTATUS UsbPdo_GetConfigurationDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommon); -NTSTATUS UsbPdo_GetStringDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommon); -NTSTATUS UsbPdo_SelectConfiguration(PURB urb, PPDO_DEVICE_DATA pCommon); -NTSTATUS UsbPdo_SelectInterface(PURB urb, PPDO_DEVICE_DATA pCommon); -NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST Request); -NTSTATUS UsbPdo_AbortPipe(WDFDEVICE Device); -NTSTATUS UsbPdo_ClassInterface(PURB urb, WDFDEVICE Device, PPDO_DEVICE_DATA pCommon); -NTSTATUS UsbPdo_GetDescriptorFromInterface(PURB urb, PPDO_DEVICE_DATA pCommon); diff --git a/sys/Util.h b/sys/Util.h deleted file mode 100644 index f91464c..0000000 --- a/sys/Util.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -#pragma once - -// -// Returns the current caller process id. -// -#define CURRENT_PROCESS_ID() ((DWORD)((DWORD_PTR)PsGetCurrentProcessId() & 0xFFFFFFFF)) - -#define IS_OWNER(_pdo_) (_pdo_->OwnerProcessId == CURRENT_PROCESS_ID()) - -// -// Represents a MAC address. -// -typedef struct _MAC_ADDRESS -{ - UCHAR Vendor0; - UCHAR Vendor1; - UCHAR Vendor2; - UCHAR Nic0; - UCHAR Nic1; - UCHAR Nic2; -} MAC_ADDRESS, *PMAC_ADDRESS; - - -VOID ReverseByteArray(PUCHAR Array, INT Length); -VOID GenerateRandomMacAddress(PMAC_ADDRESS Address); diff --git a/sys/ViGEmBus.inf b/sys/ViGEmBus.inf deleted file mode 100644 index 4168a4b..0000000 --- a/sys/ViGEmBus.inf +++ /dev/null @@ -1,84 +0,0 @@ -; -; ViGEmBus.inf -; - -[Version] -Signature="$WINDOWS NT$" -Class=System -ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318} -Provider=%ManufacturerName% -CatalogFile=ViGEmBus.cat -DriverVer= ; - -[DestinationDirs] -DefaultDestDir = 12 -ViGEmBus_Device_CoInstaller_CopyFiles = 11 - -; ================= Class section ===================== - -[SourceDisksNames.amd64] -1 = %DiskName%,,,"\x64" - -[SourceDisksNames.x86] -1 = %DiskName%,,,"\x86" - -[SourceDisksFiles] -ViGEmBus.sys = 1,, -WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1 - -;***************************************** -; Install Section -;***************************************** - -[Manufacturer] -%ManufacturerName%=Standard,NTamd64,NTx86 - -[Standard.NTamd64] -%ViGEmBus.DeviceDesc%=ViGEmBus_Device, Root\ViGEmBus - -[Standard.NTx86] -%ViGEmBus.DeviceDesc%=ViGEmBus_Device, Root\ViGEmBus - -[ViGEmBus_Device.NT] -CopyFiles=Drivers_Dir - -[Drivers_Dir] -ViGEmBus.sys - -;-------------- Service installation -[ViGEmBus_Device.NT.Services] -AddService = ViGEmBus,%SPSVCINST_ASSOCSERVICE%, ViGEmBus_Service_Inst - -; -------------- ViGEmBus driver install sections -[ViGEmBus_Service_Inst] -DisplayName = %ViGEmBus.SVCDESC% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 1 ; SERVICE_ERROR_NORMAL -ServiceBinary = %12%\ViGEmBus.sys - -; -;--- ViGEmBus_Device Coinstaller installation ------ -; - -[ViGEmBus_Device.NT.CoInstallers] -AddReg=ViGEmBus_Device_CoInstaller_AddReg -CopyFiles=ViGEmBus_Device_CoInstaller_CopyFiles - -[ViGEmBus_Device_CoInstaller_AddReg] -HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" - -[ViGEmBus_Device_CoInstaller_CopyFiles] -WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll - -[ViGEmBus_Device.NT.Wdf] -KmdfService = ViGEmBus, ViGEmBus_wdfsect -[ViGEmBus_wdfsect] -KmdfLibraryVersion = $KMDFVERSION$ - -[Strings] -SPSVCINST_ASSOCSERVICE= 0x00000002 -ManufacturerName="Benjamin Höglinger-Stelzer" -DiskName = "ViGEmBus Installation Disk" -ViGEmBus.DeviceDesc = "Virtual Gamepad Emulation Bus" -ViGEmBus.SVCDESC = "Virtual Gamepad Emulation Service" diff --git a/sys/ViGEmBus.rc b/sys/ViGEmBus.rc deleted file mode 100644 index 77cb42b..0000000 --- a/sys/ViGEmBus.rc +++ /dev/null @@ -1,100 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// German (Austria) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEA) -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,14,3,0 - PRODUCTVERSION 1,14,3,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0xe9L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000904b0" - BEGIN - VALUE "CompanyName", "Benjamin Höglinger-Stelzer" - VALUE "FileDescription", "Virtual Gamepad Emulation Bus Driver" -VALUE "FileVersion", "1.14.3.0" - VALUE "InternalName", "Virtual Gamepad Emulation Bus Driver" - VALUE "LegalCopyright", "Copyright (C) Benjamin Höglinger-Stelzer 2016" - VALUE "OriginalFilename", "vigembus.sys" - VALUE "ProductName", "Virtual Gamepad Emulation Bus Driver" -VALUE "ProductVersion", "1.14.3.0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x9, 1200 - END -END - -#endif // German (Austria) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/sys/ViGEmBus.vcxproj b/sys/ViGEmBus.vcxproj deleted file mode 100644 index bb36a47..0000000 --- a/sys/ViGEmBus.vcxproj +++ /dev/null @@ -1,326 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - Debug - ARM - - - Release - ARM - - - Debug - ARM64 - - - Release - ARM64 - - - - {040101B0-EE5C-4EF1-99EE-9F81C795C001} - {1bc93793-694f-48fe-9372-81e2b05556fd} - v4.5 - 12.0 - Debug - Win32 - ViGEmBus - $(LatestTargetPlatformVersion) - * - $(APPVEYOR_BUILD_VERSION) - - - - Windows7 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Desktop - 1 - 9 - 1 - - - Windows7 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Desktop - 1 - 9 - 1 - Off - - - Windows7 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Desktop - 1 - 9 - 1 - - - Windows7 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Desktop - 1 - 9 - 1 - Off - - - Windows7 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Desktop - 1 - 9 - 1 - - - Windows7 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Desktop - 1 - 9 - 1 - - - Windows7 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Desktop - 1 - 9 - 1 - - - Windows7 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Desktop - 1 - 9 - 1 - - - - - - - - - - - DbgengKernelDebugger - $(SolutionDir)Include;$(IncludePath) - true - false - - - DbgengKernelDebugger - $(SolutionDir)Include;$(IncludePath) - true - $(SolutionDir)bin\$(DDKPlatform)\ - false - - - DbgengKernelDebugger - $(SolutionDir)Include;$(IncludePath) - true - false - - - DbgengKernelDebugger - $(SolutionDir)Include;$(IncludePath) - true - $(SolutionDir)bin\$(DDKPlatform)\ - false - - - DbgengKernelDebugger - $(SolutionDir)Include;$(IncludePath) - true - - - DbgengKernelDebugger - $(SolutionDir)Include;$(IncludePath) - true - - - DbgengKernelDebugger - $(SolutionDir)Include;$(IncludePath) - true - - - DbgengKernelDebugger - $(SolutionDir)Include;$(IncludePath) - true - - - - $(AppVeyorBuildVersion) - - - $(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies) - - - - - $(AppVeyorBuildVersion) - - - $(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies) - - - - - $(AppVeyorBuildVersion) - - - $(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies) - - - true - true - trace.h - - - - - $(AppVeyorBuildVersion) - - - $(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies) - - - Speed - - - true - true - true - trace.h - - - - - $(AppVeyorBuildVersion) - - - $(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies) - - - - - $(AppVeyorBuildVersion) - - - $(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies) - - - - - $(AppVeyorBuildVersion) - - - $(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies) - - - true - true - trace.h - - - - - $(AppVeyorBuildVersion) - - - $(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies) - - - Speed - - - true - true - true - trace.h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sys/ViGEmBus.vcxproj.filters b/sys/ViGEmBus.vcxproj.filters deleted file mode 100644 index cb0c79e..0000000 --- a/sys/ViGEmBus.vcxproj.filters +++ /dev/null @@ -1,110 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {8E41214B-6785-4CFE-B992-037D68949A14} - inf;inv;inx;mof;mc; - - - {bbf85b1d-5a75-4302-af4e-46627fcf0d78} - - - - - Driver Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files\Common - - - Header Files\Common - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/sys/Xgip.h b/sys/Xgip.h deleted file mode 100644 index 1c3d7fd..0000000 --- a/sys/Xgip.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -// -// For children emulating XGIP devices, the following dummy interfaces -// have to be exposed by the PDO or else the child devices won't start -// - -// {70211B0E-0AFB-47DB-AFC1-410BF842497A} -// ReSharper disable once CppMissingIncludeGuard -DEFINE_GUID(GUID_DEVINTERFACE_XGIP_UNKNOWN_0, - 0x70211B0E, 0x0AFB, 0x47DB, 0xAF, 0xC1, 0x41, 0x0B, 0xF8, 0x42, 0x49, 0x7A); - -// {B38290E5-3CD0-4F9D-9937-F5FE2B44D47A} -DEFINE_GUID(GUID_DEVINTERFACE_XGIP_UNKNOWN_1, - 0xB38290E5, 0x3CD0, 0x4F9D, 0x99, 0x37, 0xF5, 0xFE, 0x2B, 0x44, 0xD4, 0x7A); - -// {2AEB0243-6A6E-486B-82FC-D815F6B97006} -DEFINE_GUID(GUID_DEVINTERFACE_XGIP_UNKNOWN_2, - 0x2AEB0243, 0x6A6E, 0x486B, 0x82, 0xFC, 0xD8, 0x15, 0xF6, 0xB9, 0x70, 0x06); - -// {DC7A8E51-49B3-4A3A-9E81-625205E7D729} -DEFINE_GUID(GUID_DEVINTERFACE_XGIP_UNKNOWN_3, - 0xDC7A8E51, 0x49B3, 0x4A3A, 0x9E, 0x81, 0x62, 0x52, 0x05, 0xE7, 0xD7, 0x29); - -// {DEEE98EA-C0A1-42C3-9738-A04606C84E93} -DEFINE_GUID(GUID_DEVINTERFACE_XGIP_UNKNOWN_4, - 0xDEEE98EA, 0xC0A1, 0x42C3, 0x97, 0x38, 0xA0, 0x46, 0x06, 0xC8, 0x4E, 0x93); - - -#pragma once - -#define XGIP_DESCRIPTOR_SIZE 0x0040 -#define XGIP_CONFIGURATION_SIZE 0x88 -#define XGIP_REPORT_SIZE 0x12 -#define XGIP_SYS_INIT_PACKETS 0x0F -#define XGIP_SYS_INIT_PERIOD 0x32 - -typedef struct _XGIP_DEVICE_DATA -{ - UCHAR Report[XGIP_REPORT_SIZE]; - - // - // Queue for incoming interrupt transfer - // - WDFQUEUE PendingUsbInRequests; - - // - // Queue for inverted calls - // - WDFQUEUE PendingNotificationRequests; - - WDFCOLLECTION XboxgipSysInitCollection; - - BOOLEAN XboxgipSysInitReady; - - WDFTIMER XboxgipSysInitTimer; -} XGIP_DEVICE_DATA, *PXGIP_DEVICE_DATA; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XGIP_DEVICE_DATA, XgipGetData) - - -NTSTATUS -Bus_XgipSubmitInterrupt( - WDFDEVICE Device, - ULONG SerialNo, - PXGIP_SUBMIT_INTERRUPT Report, - _In_ BOOLEAN FromInterface -); - -// -// XGIP-specific functions -// -NTSTATUS Xgip_PreparePdo( - PWDFDEVICE_INIT DeviceInit, - PUNICODE_STRING DeviceId, - PUNICODE_STRING DeviceDescription -); -NTSTATUS Xgip_PrepareHardware(WDFDEVICE Device); -NTSTATUS Xgip_AssignPdoContext(WDFDEVICE Device); -VOID Xgip_GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length); -VOID Xgip_GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor, PPDO_DEVICE_DATA pCommon); -VOID Xgip_SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo); - diff --git a/sys/Xusb.h b/sys/Xusb.h deleted file mode 100644 index f785fe4..0000000 --- a/sys/Xusb.h +++ /dev/null @@ -1,127 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -// -// For children emulating XUSB devices, the following dummy interfaces -// have to be exposed by the PDO or else the child devices won't start -// - -// {70211B0E-0AFB-47DB-AFC1-410BF842497A} -// ReSharper disable once CppMissingIncludeGuard -DEFINE_GUID(GUID_DEVINTERFACE_XUSB_UNKNOWN_0, - 0x70211B0E, 0x0AFB, 0x47DB, 0xAF, 0xC1, 0x41, 0x0B, 0xF8, 0x42, 0x49, 0x7A); - -// {B38290E5-3CD0-4F9D-9937-F5FE2B44D47A} -DEFINE_GUID(GUID_DEVINTERFACE_XUSB_UNKNOWN_1, - 0xB38290E5, 0x3CD0, 0x4F9D, 0x99, 0x37, 0xF5, 0xFE, 0x2B, 0x44, 0xD4, 0x7A); - -// {2AEB0243-6A6E-486B-82FC-D815F6B97006} -DEFINE_GUID(GUID_DEVINTERFACE_XUSB_UNKNOWN_2, - 0x2AEB0243, 0x6A6E, 0x486B, 0x82, 0xFC, 0xD8, 0x15, 0xF6, 0xB9, 0x70, 0x06); - -#pragma once - -#if defined(_X86_) -#define XUSB_CONFIGURATION_SIZE 0x00E4 -#else -#define XUSB_CONFIGURATION_SIZE 0x0130 -#endif -#define XUSB_DESCRIPTOR_SIZE 0x0099 -#define XUSB_RUMBLE_SIZE 0x08 -#define XUSB_LEDSET_SIZE 0x03 -#define XUSB_LEDNUM_SIZE 0x01 -#define XUSB_INIT_STAGE_SIZE 0x03 - -#define XUSB_IS_DATA_PIPE(_x_) ((BOOLEAN)(_x_->PipeHandle == (USBD_PIPE_HANDLE)0xFFFF0081)) -#define XUSB_IS_CONTROL_PIPE(_x_) ((BOOLEAN)(_x_->PipeHandle == (USBD_PIPE_HANDLE)0xFFFF0083)) - -typedef struct _XUSB_INTERRUPT_IN_PACKET -{ - UCHAR Id; - - UCHAR Size; - - XUSB_REPORT Report; - -} XUSB_INTERRUPT_IN_PACKET, *PXUSB_INTERRUPT_IN_PACKET; - -// -// XUSB-specific device context data. -// -typedef struct _XUSB_DEVICE_DATA -{ - // - // Rumble buffer - // - UCHAR Rumble[XUSB_RUMBLE_SIZE]; - - // - // LED number (represents XInput slot index) - // - CHAR LedNumber; - - // - // Report packet - // - XUSB_INTERRUPT_IN_PACKET Packet; - - // - // Queue for incoming control interrupt transfer - // - WDFQUEUE HoldingUsbInRequests; - - // - // Required for XInputGetCapabilities to work - // - BOOLEAN ReportedCapabilities; - - // - // Required for XInputGetCapabilities to work - // - ULONG InterruptInitStage; - -} XUSB_DEVICE_DATA, *PXUSB_DEVICE_DATA; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XUSB_DEVICE_DATA, XusbGetData) - - -NTSTATUS -Bus_XusbSubmitReport( - WDFDEVICE Device, - ULONG SerialNo, - PXUSB_SUBMIT_REPORT Report, - _In_ BOOLEAN FromInterface -); - -// -// XUSB-specific functions -// -NTSTATUS Xusb_PreparePdo(PWDFDEVICE_INIT DeviceInit, USHORT VendorId, USHORT ProductId, PUNICODE_STRING DeviceId, PUNICODE_STRING DeviceDescription); -NTSTATUS Xusb_PrepareHardware(WDFDEVICE Device); -NTSTATUS Xusb_AssignPdoContext(WDFDEVICE Device); -VOID Xusb_GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length); -VOID Xusb_GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor, PPDO_DEVICE_DATA pCommon); -VOID Xusb_SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo); -NTSTATUS Xusb_GetUserIndex(WDFDEVICE Device, PXUSB_GET_USER_INDEX Request); diff --git a/sys/busenum.c b/sys/busenum.c deleted file mode 100644 index 1f7df12..0000000 --- a/sys/busenum.c +++ /dev/null @@ -1,823 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 "busenum.h" -#include -#include -#include "busenum.tmh" - -#ifdef ALLOC_PRAGMA -#pragma alloc_text (PAGE, Bus_PlugInDevice) -#pragma alloc_text (PAGE, Bus_UnPlugDevice) -#endif - - - -// -// Simulates a device plug-in event. -// -NTSTATUS Bus_PlugInDevice( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ BOOLEAN IsInternal, - _Out_ size_t* Transferred) -{ - PDO_IDENTIFICATION_DESCRIPTION description; - NTSTATUS status; - PVIGEM_PLUGIN_TARGET plugIn; - WDFFILEOBJECT fileObject; - PFDO_FILE_DATA pFileData; - size_t length = 0; - WDF_OBJECT_ATTRIBUTES requestAttribs; - PFDO_PLUGIN_REQUEST_DATA pReqData; - PFDO_DEVICE_DATA pFdoData; - - PAGED_CODE(); - - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSENUM, "%!FUNC! Entry"); - - pFdoData = FdoGetData(Device); - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(VIGEM_PLUGIN_TARGET), (PVOID)&plugIn, &length); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "WdfRequestRetrieveInputBuffer failed with status %!STATUS!", status); - return status; - } - - if ((sizeof(VIGEM_PLUGIN_TARGET) != plugIn->Size) || (length != plugIn->Size)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "sizeof(VIGEM_PLUGIN_TARGET) buffer size mismatch [%d != %d]", - sizeof(VIGEM_PLUGIN_TARGET), plugIn->Size); - return STATUS_INVALID_PARAMETER; - } - - if (plugIn->SerialNo == 0) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "Serial no. 0 not allowed"); - return STATUS_INVALID_PARAMETER; - } - - *Transferred = length; - - fileObject = WdfRequestGetFileObject(Request); - if (fileObject == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "WdfRequestGetFileObject failed to fetch WDFFILEOBJECT from request 0x%p", - Request); - return STATUS_INVALID_PARAMETER; - } - - pFileData = FileObjectGetData(fileObject); - if (pFileData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "FileObjectGetData failed to get context data for 0x%p", - fileObject); - return STATUS_INVALID_PARAMETER; - } - - // - // Initialize the description with the information about the newly - // plugged in device. - // - WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description)); - - description.SerialNo = plugIn->SerialNo; - description.TargetType = plugIn->TargetType; - description.OwnerProcessId = CURRENT_PROCESS_ID(); - description.SessionId = pFileData->SessionId; - description.OwnerIsDriver = IsInternal; - - // Set default IDs if supplied values are invalid - if (plugIn->VendorId == 0 || plugIn->ProductId == 0) - { - switch (plugIn->TargetType) - { - case Xbox360Wired: - - description.VendorId = 0x045E; - description.ProductId = 0x028E; - - break; - case DualShock4Wired: - - description.VendorId = 0x054C; - description.ProductId = 0x05C4; - - break; - case XboxOneWired: - - description.VendorId = 0x0E6F; - description.ProductId = 0x0139; - -#if !DBG - // TODO: implement and remove! - return STATUS_NOT_SUPPORTED; -#endif - - break; - } - } - else - { - description.VendorId = plugIn->VendorId; - description.ProductId = plugIn->ProductId; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "New PDO properties: serial = %d, type = %d, pid = %d, session = %d, internal = %d, vid = 0x%04X, pid = 0x%04X", - description.SerialNo, - description.TargetType, - description.OwnerProcessId, - description.SessionId, - description.OwnerIsDriver, - description.VendorId, - description.ProductId - ); - - WdfSpinLockAcquire(pFdoData->PendingPluginRequestsLock); - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "Current pending requests count: %d", - WdfCollectionGetCount(pFdoData->PendingPluginRequests)); - - status = WdfChildListAddOrUpdateChildDescriptionAsPresent(WdfFdoGetDefaultChildList(Device), &description.Header, NULL); - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status %!STATUS!", - status); - - goto pluginEnd; - } - - // - // The requested serial number is already in use - // - if (status == STATUS_OBJECT_NAME_EXISTS) - { - status = STATUS_INVALID_PARAMETER; - - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "The described PDO already exists (%!STATUS!)", - status); - - goto pluginEnd; - } - - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&requestAttribs, FDO_PLUGIN_REQUEST_DATA); - - // - // Allocate context data to request - // - status = WdfObjectAllocateContext(Request, &requestAttribs, (PVOID)&pReqData); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "WdfObjectAllocateContext failed with status %!STATUS!", - status); - - goto pluginEnd; - } - - // - // Glue current serial to request - // - pReqData->Serial = plugIn->SerialNo; - - // - // Timestamp the request to track its age - // - pReqData->Timestamp = KeQueryPerformanceCounter(&pReqData->Frequency); - - // - // Keep track of pending request in collection - // - status = WdfCollectionAdd(pFdoData->PendingPluginRequests, Request); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "WdfCollectionAdd failed with status %!STATUS!", - status); - - goto pluginEnd; - } - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_BUSENUM, - "Added item with serial: %d", - plugIn->SerialNo); - - // - // At least one request present in the collection; start clean-up timer - // - WdfTimerStart( - pFdoData->PendingPluginRequestsCleanupTimer, - WDF_REL_TIMEOUT_IN_MS(ORC_TIMER_PERIODIC_DUE_TIME) - ); - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_DRIVER, - "Started periodic timer"); - - status = NT_SUCCESS(status) ? STATUS_PENDING : status; - -pluginEnd: - - WdfSpinLockRelease(pFdoData->PendingPluginRequestsLock); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSENUM, "%!FUNC! Exit with status %!STATUS!", status); - - return status; -} - -// -// Simulates a device unplug event. -// -NTSTATUS Bus_UnPlugDevice( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ BOOLEAN IsInternal, - _Out_ size_t* Transferred) -{ - NTSTATUS status; - WDFDEVICE hChild; - WDFCHILDLIST list; - WDF_CHILD_LIST_ITERATOR iterator; - WDF_CHILD_RETRIEVE_INFO childInfo; - PDO_IDENTIFICATION_DESCRIPTION description; - BOOLEAN unplugAll; - PVIGEM_UNPLUG_TARGET unPlug; - WDFFILEOBJECT fileObject; - PFDO_FILE_DATA pFileData = NULL; - size_t length = 0; - - PAGED_CODE(); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSENUM, "%!FUNC! Entry"); - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(VIGEM_UNPLUG_TARGET), (PVOID)&unPlug, &length); - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "WdfRequestRetrieveInputBuffer failed with status %!STATUS!", - status); - return status; - } - - if ((sizeof(VIGEM_UNPLUG_TARGET) != unPlug->Size) || (length != unPlug->Size)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "sizeof(VIGEM_UNPLUG_TARGET) buffer size mismatch [%d != %d]", - sizeof(VIGEM_UNPLUG_TARGET), unPlug->Size); - return STATUS_INVALID_PARAMETER; - } - - *Transferred = length; - unplugAll = (unPlug->SerialNo == 0); - - if (!IsInternal) - { - fileObject = WdfRequestGetFileObject(Request); - if (fileObject == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "WdfRequestGetFileObject failed to fetch WDFFILEOBJECT from request 0x%p", - Request); - return STATUS_INVALID_PARAMETER; - } - - pFileData = FileObjectGetData(fileObject); - if (pFileData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "FileObjectGetData failed to get context data for 0x%p", - fileObject); - return STATUS_INVALID_PARAMETER; - } - } - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "Starting child list traversal"); - - list = WdfFdoGetDefaultChildList(Device); - - WDF_CHILD_LIST_ITERATOR_INIT(&iterator, WdfRetrievePresentChildren); - - WdfChildListBeginIteration(list, &iterator); - - for (;;) - { - WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &description.Header); - WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description)); - - status = WdfChildListRetrieveNextDevice(list, &iterator, &hChild, &childInfo); - - // Error or no more children, end loop - if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES) - { - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "WdfChildListRetrieveNextDevice returned with status %!STATUS!", - status); - break; - } - - // If unable to retrieve device - if (childInfo.Status != WdfChildListRetrieveDeviceSuccess) - { - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "childInfo.Status = %d", - childInfo.Status); - continue; - } - - // Child isn't the one we looked for, skip - if (!unplugAll && description.SerialNo != unPlug->SerialNo) - { - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "Seeking serial mismatch: %d != %d", - description.SerialNo, - unPlug->SerialNo); - continue; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "description.SessionId = %d, pFileData->SessionId = %d", - description.SessionId, - pFileData->SessionId); - - // Only unplug owned children - if (IsInternal || description.SessionId == pFileData->SessionId) - { - // Unplug child - status = WdfChildListUpdateChildDescriptionAsMissing(list, &description.Header); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "WdfChildListUpdateChildDescriptionAsMissing failed with status %!STATUS!", - status); - } - } - } - - WdfChildListEndIteration(list, &iterator); - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "Finished child list traversal"); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSENUM, "%!FUNC! Exit with status %!STATUS!", STATUS_SUCCESS); - - return STATUS_SUCCESS; -} - -// -// Sends a report update to an XUSB PDO. -// -NTSTATUS Bus_XusbSubmitReport(WDFDEVICE Device, ULONG SerialNo, PXUSB_SUBMIT_REPORT Report, BOOLEAN FromInterface) -{ - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSENUM, "%!FUNC! Entry"); - - return Bus_SubmitReport(Device, SerialNo, Report, FromInterface); -} - -// -// Queues an inverted call to receive XUSB-specific updates. -// -NTSTATUS Bus_QueueNotification(WDFDEVICE Device, ULONG SerialNo, WDFREQUEST Request) -{ - NTSTATUS status = STATUS_INVALID_PARAMETER; - WDFDEVICE hChild; - PPDO_DEVICE_DATA pdoData; - PXUSB_DEVICE_DATA xusbData; - PDS4_DEVICE_DATA ds4Data; - - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSENUM, "%!FUNC! Entry"); - - hChild = Bus_GetPdo(Device, SerialNo); - - // Validate child - if (hChild == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "Bus_GetPdo: PDO with serial %d not found", - SerialNo); - return STATUS_NO_SUCH_DEVICE; - } - - // Check common context - pdoData = PdoGetData(hChild); - if (pdoData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "PdoGetData failed"); - return STATUS_INVALID_PARAMETER; - } - - // Check if caller owns this PDO - if (!IS_OWNER(pdoData)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "PDO & Request ownership mismatch: %d != %d", - pdoData->OwnerProcessId, - CURRENT_PROCESS_ID()); - return STATUS_ACCESS_DENIED; - } - - // Queue the request for later completion by the PDO and return STATUS_PENDING - switch (pdoData->TargetType) - { - case Xbox360Wired: - - xusbData = XusbGetData(hChild); - - if (xusbData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "XusbGetData failed"); - break; - } - - status = WdfRequestForwardToIoQueue(Request, pdoData->PendingNotificationRequests); - - break; - case DualShock4Wired: - - ds4Data = Ds4GetData(hChild); - - if (ds4Data == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "Ds4GetData failed"); - break; - } - - status = WdfRequestForwardToIoQueue(Request, pdoData->PendingNotificationRequests); - - break; - default: - status = STATUS_NOT_SUPPORTED; - TraceEvents(TRACE_LEVEL_WARNING, - TRACE_BUSENUM, - "Unknown target type: %d (%!STATUS!)", - pdoData->TargetType, - status); - break; - } - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "WdfRequestForwardToIoQueue failed with status %!STATUS!", - status); - } - - status = (NT_SUCCESS(status)) ? STATUS_PENDING : status; - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSENUM, "%!FUNC! Exit with status %!STATUS!", status); - - return status; -} - -// -// Sends a report update to a DS4 PDO. -// -NTSTATUS Bus_Ds4SubmitReport(WDFDEVICE Device, ULONG SerialNo, PDS4_SUBMIT_REPORT Report, BOOLEAN FromInterface) -{ - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSENUM, "%!FUNC! Entry"); - - return Bus_SubmitReport(Device, SerialNo, Report, FromInterface); -} - -NTSTATUS Bus_XgipSubmitReport(WDFDEVICE Device, ULONG SerialNo, PXGIP_SUBMIT_REPORT Report, BOOLEAN FromInterface) -{ - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSENUM, "%!FUNC! Entry"); - - return Bus_SubmitReport(Device, SerialNo, Report, FromInterface); -} - -NTSTATUS Bus_XgipSubmitInterrupt(WDFDEVICE Device, ULONG SerialNo, PXGIP_SUBMIT_INTERRUPT Report, BOOLEAN FromInterface) -{ - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSENUM, "%!FUNC! Entry"); - - return Bus_SubmitReport(Device, SerialNo, Report, FromInterface); -} - -WDFDEVICE Bus_GetPdo(IN WDFDEVICE Device, IN ULONG SerialNo) -{ - WDFCHILDLIST list; - WDF_CHILD_RETRIEVE_INFO info; - - list = WdfFdoGetDefaultChildList(Device); - - PDO_IDENTIFICATION_DESCRIPTION description; - - WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description)); - - description.SerialNo = SerialNo; - - WDF_CHILD_RETRIEVE_INFO_INIT(&info, &description.Header); - - return WdfChildListRetrievePdo(list, &info); -} - -NTSTATUS Bus_SubmitReport(WDFDEVICE Device, ULONG SerialNo, PVOID Report, BOOLEAN FromInterface) -{ - NTSTATUS status = STATUS_SUCCESS; - WDFDEVICE hChild; - PPDO_DEVICE_DATA pdoData; - WDFREQUEST usbRequest; - PIRP pendingIrp; - BOOLEAN changed; - - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSENUM, "%!FUNC! Entry"); - - hChild = Bus_GetPdo(Device, SerialNo); - - // Validate child - if (hChild == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "Bus_GetPdo: PDO with serial %d not found", - SerialNo); - return STATUS_NO_SUCH_DEVICE; - } - - // Check common context - pdoData = PdoGetData(hChild); - if (pdoData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "PdoGetData failed"); - return STATUS_INVALID_PARAMETER; - } - - // Check if caller owns this PDO - if (!FromInterface && !IS_OWNER(pdoData)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSENUM, - "PDO & Request ownership mismatch: %d != %d", - pdoData->OwnerProcessId, - CURRENT_PROCESS_ID()); - return STATUS_ACCESS_DENIED; - } - - // Check if input is different from previous value - switch (pdoData->TargetType) - { - case Xbox360Wired: - - changed = (RtlCompareMemory(&XusbGetData(hChild)->Packet.Report, - &((PXUSB_SUBMIT_REPORT)Report)->Report, - sizeof(XUSB_REPORT)) != sizeof(XUSB_REPORT)); - - break; - case DualShock4Wired: - - changed = TRUE; - - break; - case XboxOneWired: - - // TODO: necessary? - changed = TRUE; - - break; - default: - - changed = FALSE; - - break; - } - - // Don't waste pending IRP if input hasn't changed - if (!changed) - { - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "Input report hasn't changed since last update, aborting with %!STATUS!", - status); - return status; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "Received new report, processing"); - - // Get pending USB request - switch (pdoData->TargetType) - { - case Xbox360Wired: - - status = WdfIoQueueRetrieveNextRequest(pdoData->PendingUsbInRequests, &usbRequest); - - break; - case DualShock4Wired: - - status = WdfIoQueueRetrieveNextRequest(pdoData->PendingUsbInRequests, &usbRequest); - - break; - case XboxOneWired: - - // Request is control data - if (((PXGIP_SUBMIT_INTERRUPT)Report)->Size == sizeof(XGIP_SUBMIT_INTERRUPT)) - { - PXGIP_DEVICE_DATA xgip = XgipGetData(hChild); - PXGIP_SUBMIT_INTERRUPT interrupt = (PXGIP_SUBMIT_INTERRUPT)Report; - WDFMEMORY memory; - WDF_OBJECT_ATTRIBUTES memAttribs; - WDF_OBJECT_ATTRIBUTES_INIT(&memAttribs); - - memAttribs.ParentObject = hChild; - - // Allocate kernel memory - status = WdfMemoryCreate(&memAttribs, NonPagedPool, VIGEM_POOL_TAG, - interrupt->InterruptLength, &memory, NULL); - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfMemoryCreate failed with status 0x%X\n", status)); - goto endSubmitReport; - } - - // Copy interrupt buffer to memory object - status = WdfMemoryCopyFromBuffer(memory, 0, interrupt->Interrupt, interrupt->InterruptLength); - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfMemoryCopyFromBuffer failed with status 0x%X\n", status)); - goto endSubmitReport; - } - - // Add memory object to collection - status = WdfCollectionAdd(xgip->XboxgipSysInitCollection, memory); - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfCollectionAdd failed with status 0x%X\n", status)); - goto endSubmitReport; - } - - // Check if all packets have been received - xgip->XboxgipSysInitReady = - WdfCollectionGetCount(xgip->XboxgipSysInitCollection) == XGIP_SYS_INIT_PACKETS; - - // If all packets are cached, start initialization timer - if (xgip->XboxgipSysInitReady) - { - WdfTimerStart(xgip->XboxgipSysInitTimer, XGIP_SYS_INIT_PERIOD); - } - - goto endSubmitReport; - } - - status = WdfIoQueueRetrieveNextRequest(XgipGetData(hChild)->PendingUsbInRequests, &usbRequest); - - break; - default: - - status = STATUS_NOT_SUPPORTED; - - TraceEvents(TRACE_LEVEL_WARNING, - TRACE_BUSENUM, - "Unknown target type: %d (%!STATUS!)", - pdoData->TargetType, - status); - - goto endSubmitReport; - } - - if (status == STATUS_PENDING) - goto endSubmitReport; - else if (!NT_SUCCESS(status)) - goto endSubmitReport; - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSENUM, - "Processing pending IRP"); - - // Get pending IRP - pendingIrp = WdfRequestWdmGetIrp(usbRequest); - - // Get USB request block - PURB urb = (PURB)URB_FROM_IRP(pendingIrp); - - // Get transfer buffer - PUCHAR Buffer = (PUCHAR)urb->UrbBulkOrInterruptTransfer.TransferBuffer; - - switch (pdoData->TargetType) - { - case Xbox360Wired: - - urb->UrbBulkOrInterruptTransfer.TransferBufferLength = sizeof(XUSB_INTERRUPT_IN_PACKET); - - // Copy submitted report to cache - RtlCopyBytes(&XusbGetData(hChild)->Packet.Report, &((PXUSB_SUBMIT_REPORT)Report)->Report, sizeof(XUSB_REPORT)); - // Copy cached report to URB transfer buffer - RtlCopyBytes(Buffer, &XusbGetData(hChild)->Packet, sizeof(XUSB_INTERRUPT_IN_PACKET)); - - break; - case DualShock4Wired: - - urb->UrbBulkOrInterruptTransfer.TransferBufferLength = DS4_REPORT_SIZE; - - /* Copy report to cache and transfer buffer - * Skip first byte as it contains the never changing report id */ - RtlCopyBytes(Ds4GetData(hChild)->Report + 1, &((PDS4_SUBMIT_REPORT)Report)->Report, sizeof(DS4_REPORT)); - - if (Buffer) - RtlCopyBytes(Buffer, Ds4GetData(hChild)->Report, DS4_REPORT_SIZE); - - break; - case XboxOneWired: - - // Request is input report - if (((PXGIP_SUBMIT_REPORT)Report)->Size == sizeof(XGIP_SUBMIT_REPORT)) - { - urb->UrbBulkOrInterruptTransfer.TransferBufferLength = XGIP_REPORT_SIZE; - - // Increase event counter on every call (can roll-over) - XgipGetData(hChild)->Report[2]++; - - /* Copy report to cache and transfer buffer - * Skip first four bytes as they are not part of the report */ - RtlCopyBytes(XgipGetData(hChild)->Report + 4, &((PXGIP_SUBMIT_REPORT)Report)->Report, sizeof(XGIP_REPORT)); - RtlCopyBytes(Buffer, XgipGetData(hChild)->Report, XGIP_REPORT_SIZE); - - break; - } - - break; - default: - status = STATUS_INVALID_PARAMETER; - break; - } - - // Complete pending request - WdfRequestComplete(usbRequest, status); - -endSubmitReport: - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSENUM, "%!FUNC! Exit with status %!STATUS!", status); - - return status; -} - diff --git a/sys/busenum.h b/sys/busenum.h deleted file mode 100644 index b115d9c..0000000 --- a/sys/busenum.h +++ /dev/null @@ -1,176 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -#pragma once - -#include "trace.h" -#include -#include -#define NTSTRSAFE_LIB -#include -#include -#include -#include "ViGEmBusDriver.h" -#include "ViGEmBusShared.h" -#include "Queue.h" -#include -#include -#include "Context.h" -#include "Util.h" -#include "UsbPdo.h" -#include "Xusb.h" -#include "Ds4.h" -#include "Xgip.h" - - -#pragma region Macros - -#define MAX_INSTANCE_ID_LEN 80 -#define HID_LANGUAGE_ID_LENGTH 0x04 - -#define HID_REQUEST_GET_REPORT 0x01 -#define HID_REQUEST_SET_REPORT 0x09 -#define HID_REPORT_TYPE_FEATURE 0x03 - -#define VIGEM_POOL_TAG 0x45476956 // "EGiV" -#define DRIVERNAME "ViGEm: " -#define MAX_HARDWARE_ID_LENGTH 0xFF - -#define ORC_PC_FREQUENCY_DIVIDER 1000 -#define ORC_TIMER_START_DELAY 500 // ms -#define ORC_TIMER_PERIODIC_DUE_TIME 500 // ms -#define ORC_REQUEST_MAX_AGE 500 // ms - -#pragma endregion - -#pragma region Helpers - -// -// Extracts the HID Report ID from the supplied class request. -// -#define HID_GET_REPORT_ID(_req_) ((_req_->Value) & 0xFF) - -// -// Extracts the HID Report type from the supplied class request. -// -#define HID_GET_REPORT_TYPE(_req_) ((_req_->Value >> 8) & 0xFF) - -// -// Some insane macro-magic =3 -// -#define P99_PROTECT(...) __VA_ARGS__ -#define COPY_BYTE_ARRAY(_dst_, _bytes_) do {BYTE b[] = _bytes_; \ - RtlCopyMemory(_dst_, b, RTL_NUMBER_OF_V1(b)); } while (0) - -#pragma endregion - - -#pragma region WDF callback prototypes - -DRIVER_INITIALIZE DriverEntry; - -EVT_WDF_DRIVER_DEVICE_ADD Bus_EvtDeviceAdd; -EVT_WDF_DEVICE_FILE_CREATE Bus_DeviceFileCreate; -EVT_WDF_FILE_CLOSE Bus_FileClose; - -EVT_WDF_CHILD_LIST_CREATE_DEVICE Bus_EvtDeviceListCreatePdo; - -EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE Bus_EvtChildListIdentificationDescriptionCompare; - -EVT_WDF_DEVICE_PREPARE_HARDWARE Bus_EvtDevicePrepareHardware; - -EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL Pdo_EvtIoInternalDeviceControl; - -EVT_WDF_TIMER Xgip_SysInitTimerFunc; - -EVT_WDF_OBJECT_CONTEXT_CLEANUP Bus_EvtDriverContextCleanup; - -EVT_WDF_TIMER Bus_PlugInRequestCleanUpEvtTimerFunc; - -#pragma endregion - -#pragma region Bus enumeration-specific functions - -NTSTATUS -Bus_PlugInDevice( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ BOOLEAN IsInternal, - _Out_ size_t* Transferred -); - -NTSTATUS -Bus_UnPlugDevice( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ BOOLEAN IsInternal, - _Out_ size_t* Transferred -); - -NTSTATUS -Bus_CreatePdo( - _In_ WDFDEVICE Device, - _In_ PWDFDEVICE_INIT ChildInit, - _In_ PPDO_IDENTIFICATION_DESCRIPTION Description -); - -NTSTATUS -Bus_QueueNotification( - WDFDEVICE Device, - ULONG SerialNo, - WDFREQUEST Request -); - -NTSTATUS -Bus_XgipSubmitReport( - WDFDEVICE Device, - ULONG SerialNo, - PXGIP_SUBMIT_REPORT Report, - _In_ BOOLEAN FromInterface -); - -NTSTATUS -Bus_SubmitReport( - WDFDEVICE Device, - ULONG SerialNo, - PVOID Report, - _In_ BOOLEAN FromInterface -); - -WDFDEVICE -Bus_GetPdo( - IN WDFDEVICE Device, - IN ULONG SerialNo); - -VOID -Bus_PdoStageResult( - _In_ PINTERFACE InterfaceHeader, - _In_ VIGEM_PDO_STAGE Stage, - _In_ ULONG Serial, - _In_ NTSTATUS Status -); - -#pragma endregion - diff --git a/sys/buspdo.c b/sys/buspdo.c deleted file mode 100644 index 5e66306..0000000 --- a/sys/buspdo.c +++ /dev/null @@ -1,901 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 "busenum.h" -#include -#include -#include "buspdo.tmh" - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, Bus_CreatePdo) -#pragma alloc_text(PAGE, Bus_EvtDeviceListCreatePdo) -#pragma alloc_text(PAGE, Bus_EvtDevicePrepareHardware) -#endif - -NTSTATUS Bus_EvtDeviceListCreatePdo( - WDFCHILDLIST DeviceList, - PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, - PWDFDEVICE_INIT ChildInit) -{ - PPDO_IDENTIFICATION_DESCRIPTION pDesc; - - PAGED_CODE(); - - pDesc = CONTAINING_RECORD(IdentificationDescription, PDO_IDENTIFICATION_DESCRIPTION, Header); - - return Bus_CreatePdo(WdfChildListGetDevice(DeviceList), ChildInit, pDesc); -} - -// -// Compares two children on the bus based on their serial numbers. -// -BOOLEAN Bus_EvtChildListIdentificationDescriptionCompare( - WDFCHILDLIST DeviceList, - PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER FirstIdentificationDescription, - PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER SecondIdentificationDescription) -{ - PPDO_IDENTIFICATION_DESCRIPTION lhs, rhs; - - UNREFERENCED_PARAMETER(DeviceList); - - lhs = CONTAINING_RECORD(FirstIdentificationDescription, - PDO_IDENTIFICATION_DESCRIPTION, - Header); - rhs = CONTAINING_RECORD(SecondIdentificationDescription, - PDO_IDENTIFICATION_DESCRIPTION, - Header); - - return (lhs->SerialNo == rhs->SerialNo) ? TRUE : FALSE; -} - -// -// Creates and initializes a PDO (child). -// -NTSTATUS Bus_CreatePdo( - _In_ WDFDEVICE Device, - _In_ PWDFDEVICE_INIT DeviceInit, - _In_ PPDO_IDENTIFICATION_DESCRIPTION Description) -{ - NTSTATUS status; - PPDO_DEVICE_DATA pdoData; - WDFDEVICE hChild = NULL; - WDF_DEVICE_PNP_CAPABILITIES pnpCaps; - WDF_DEVICE_POWER_CAPABILITIES powerCaps; - WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; - WDF_OBJECT_ATTRIBUTES pdoAttributes; - WDF_IO_QUEUE_CONFIG defaultPdoQueueConfig; - WDFQUEUE defaultPdoQueue; - UNICODE_STRING deviceDescription; - VIGEM_BUS_INTERFACE busInterface; - WDF_OBJECT_ATTRIBUTES attributes; - WDF_IO_QUEUE_CONFIG usbInQueueConfig; - WDF_IO_QUEUE_CONFIG notificationsQueueConfig; - - DECLARE_CONST_UNICODE_STRING(deviceLocation, L"Virtual Gamepad Emulation Bus"); - DECLARE_UNICODE_STRING_SIZE(buffer, MAX_INSTANCE_ID_LEN); - // reserve space for device id - DECLARE_UNICODE_STRING_SIZE(deviceId, MAX_INSTANCE_ID_LEN); - - - PAGED_CODE(); - - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); - - // - // Get the FDO interface ASAP to report progress to bus - // - status = WdfFdoQueryForInterface(Device, - &GUID_VIGEM_INTERFACE_PDO, - (PINTERFACE)&busInterface, - sizeof(VIGEM_BUS_INTERFACE), - VIGEM_BUS_INTERFACE_VERSION, - NULL); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfFdoQueryForInterface failed with status %!STATUS!", - status); - return status; - } - - // set device type - WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); - // Bus is power policy owner - WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE); - -#pragma region Enter RAW device mode - - status = WdfPdoInitAssignRawDevice(DeviceInit, &GUID_DEVCLASS_VIGEM_RAWPDO); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfPdoInitAssignRawDevice failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - WdfDeviceInitSetCharacteristics(DeviceInit, FILE_AUTOGENERATED_DEVICE_NAME, TRUE); - - status = WdfDeviceInitAssignSDDLString(DeviceInit, &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfDeviceInitAssignSDDLString failed with status %!STATUS!", - status); - goto endCreatePdo; - } - -#pragma endregion - -#pragma region Prepare PDO - - // set parameters matching desired target device - switch (Description->TargetType) - { - // - // A Xbox 360 device was requested - // - case Xbox360Wired: - - status = Xusb_PreparePdo( - DeviceInit, - Description->VendorId, - Description->ProductId, - &deviceId, - &deviceDescription); - - if (!NT_SUCCESS(status)) - goto endCreatePdo; - - break; - - // - // A Sony DualShock 4 device was requested - // - case DualShock4Wired: - - status = Ds4_PreparePdo(DeviceInit, &deviceId, &deviceDescription); - - if (!NT_SUCCESS(status)) - goto endCreatePdo; - - break; - - // - // A Xbox One device was requested - // - case XboxOneWired: - - status = Xgip_PreparePdo(DeviceInit, &deviceId, &deviceDescription); - - if (!NT_SUCCESS(status)) - goto endCreatePdo; - - break; - - default: - - status = STATUS_INVALID_PARAMETER; - - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "Unknown target type: %d (%!STATUS!)", - Description->TargetType, - status); - - goto endCreatePdo; - } - - // set device id - status = WdfPdoInitAssignDeviceID(DeviceInit, &deviceId); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfPdoInitAssignDeviceID failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - // prepare instance id - status = RtlUnicodeStringPrintf(&buffer, L"%02d", Description->SerialNo); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "RtlUnicodeStringPrintf failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - // set instance id - status = WdfPdoInitAssignInstanceID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfPdoInitAssignInstanceID failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - // set device description (for English operating systems) - status = WdfPdoInitAddDeviceText(DeviceInit, &deviceDescription, &deviceLocation, 0x409); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfPdoInitAddDeviceText failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - // default locale is English - // TODO: add more locales - WdfPdoInitSetDefaultLocale(DeviceInit, 0x409); - -#pragma endregion - -#pragma region PNP/Power event callbacks - - WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); - - pnpPowerCallbacks.EvtDevicePrepareHardware = Bus_EvtDevicePrepareHardware; - - WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); - -#pragma endregion - - // NOTE: not utilized at the moment - WdfPdoInitAllowForwardingRequestToParent(DeviceInit); - -#pragma region Create PDO - - // Add common device data context - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, PDO_DEVICE_DATA); - - status = WdfDeviceCreate(&DeviceInit, &pdoAttributes, &hChild); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfDeviceCreate failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - "Created PDO 0x%p", - hChild); - - switch (Description->TargetType) - { - // Add XUSB-specific device data context - case Xbox360Wired: - { - PXUSB_DEVICE_DATA xusbData = NULL; - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, XUSB_DEVICE_DATA); - - status = WdfObjectAllocateContext(hChild, &pdoAttributes, (PVOID)&xusbData); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfObjectAllocateContext failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - break; - } - case DualShock4Wired: - { - PDS4_DEVICE_DATA ds4Data = NULL; - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, DS4_DEVICE_DATA); - - status = WdfObjectAllocateContext(hChild, &pdoAttributes, (PVOID)&ds4Data); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfObjectAllocateContext failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - break; - } - case XboxOneWired: - { - PXGIP_DEVICE_DATA xgipData = NULL; - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, XGIP_DEVICE_DATA); - - status = WdfObjectAllocateContext(hChild, &pdoAttributes, (PVOID)&xgipData); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfObjectAllocateContext failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - break; - } - default: - break; - } - -#pragma endregion - -#pragma region Expose USB Interface - - status = WdfDeviceCreateDeviceInterface(Device, (LPGUID)&GUID_DEVINTERFACE_USB_DEVICE, NULL); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfDeviceCreateDeviceInterface failed with status %!STATUS!", - status); - goto endCreatePdo; - } - -#pragma endregion - -#pragma region Set PDO contexts - - pdoData = PdoGetData(hChild); - - pdoData->BusInterface = busInterface; - - pdoData->SerialNo = Description->SerialNo; - pdoData->TargetType = Description->TargetType; - pdoData->OwnerProcessId = Description->OwnerProcessId; - pdoData->VendorId = Description->VendorId; - pdoData->ProductId = Description->ProductId; - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - "PDO Context properties: serial = %d, type = %d, pid = %d, vid = 0x%04X, pid = 0x%04X", - pdoData->SerialNo, - pdoData->TargetType, - pdoData->OwnerProcessId, - pdoData->VendorId, - pdoData->ProductId); - - // Initialize additional contexts (if available) - switch (Description->TargetType) - { - case Xbox360Wired: - - status = Xusb_AssignPdoContext(hChild); - - break; - - case DualShock4Wired: - - status = Ds4_AssignPdoContext(hChild, Description); - - break; - - case XboxOneWired: - - status = Xgip_AssignPdoContext(hChild); - - break; - - default: - break; - } - - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "Couldn't initialize additional contexts: %!STATUS!", - status); - - goto endCreatePdo; - } - -#pragma endregion - -#pragma region Create Queues & Locks - - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = hChild; - - // Create and assign queue for incoming interrupt transfer - WDF_IO_QUEUE_CONFIG_INIT(&usbInQueueConfig, WdfIoQueueDispatchManual); - - status = WdfIoQueueCreate(Device, &usbInQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pdoData->PendingUsbInRequests); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfIoQueueCreate (PendingUsbInRequests) failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - // Create and assign queue for user-land notification requests - WDF_IO_QUEUE_CONFIG_INIT(¬ificationsQueueConfig, WdfIoQueueDispatchManual); - - status = WdfIoQueueCreate(Device, ¬ificationsQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pdoData->PendingNotificationRequests); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfIoQueueCreate (PendingNotificationRequests) failed with status %!STATUS!", - status); - goto endCreatePdo; - } - -#pragma endregion - -#pragma region Default I/O queue setup - - WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&defaultPdoQueueConfig, WdfIoQueueDispatchParallel); - - defaultPdoQueueConfig.EvtIoInternalDeviceControl = Pdo_EvtIoInternalDeviceControl; - - status = WdfIoQueueCreate(hChild, &defaultPdoQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &defaultPdoQueue); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfIoQueueCreate (Default) failed with status %!STATUS!", - status); - goto endCreatePdo; - } - -#pragma endregion - -#pragma region PNP capabilities - - WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); - - pnpCaps.Removable = WdfTrue; - pnpCaps.EjectSupported = WdfTrue; - pnpCaps.SurpriseRemovalOK = WdfTrue; - - pnpCaps.Address = Description->SerialNo; - pnpCaps.UINumber = Description->SerialNo; - - WdfDeviceSetPnpCapabilities(hChild, &pnpCaps); - -#pragma endregion - -#pragma region Power capabilities - - WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps); - - powerCaps.DeviceD1 = WdfTrue; - powerCaps.WakeFromD1 = WdfTrue; - powerCaps.DeviceWake = PowerDeviceD1; - - powerCaps.DeviceState[PowerSystemWorking] = PowerDeviceD0; - powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD1; - powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD3; - powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD3; - powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3; - powerCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3; - - WdfDeviceSetPowerCapabilities(hChild, &powerCaps); - -#pragma endregion - - endCreatePdo: - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_BUSPDO, - "BUS_PDO_REPORT_STAGE_RESULT Stage: ViGEmPdoCreate [serial: %d, status: %!STATUS!]", - Description->SerialNo, status); - - BUS_PDO_REPORT_STAGE_RESULT(busInterface, ViGEmPdoCreate, Description->SerialNo, status); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status); - - return status; -} - -// -// Exposes necessary interfaces on PDO power-up. -// -NTSTATUS Bus_EvtDevicePrepareHardware( - _In_ WDFDEVICE Device, - _In_ WDFCMRESLIST ResourcesRaw, - _In_ WDFCMRESLIST ResourcesTranslated -) -{ - PPDO_DEVICE_DATA pdoData; - NTSTATUS status = STATUS_UNSUCCESSFUL; - - PAGED_CODE(); - - UNREFERENCED_PARAMETER(ResourcesRaw); - UNREFERENCED_PARAMETER(ResourcesTranslated); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSENUM, "%!FUNC! Entry"); - - pdoData = PdoGetData(Device); - - switch (pdoData->TargetType) - { - // Expose XUSB interfaces - case Xbox360Wired: - - status = Xusb_PrepareHardware(Device); - - break; - - case DualShock4Wired: - - status = Ds4_PrepareHardware(Device); - - break; - - case XboxOneWired: - - status = Xgip_PrepareHardware(Device); - - break; - - default: - break; - } - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_BUSPDO, - "BUS_PDO_REPORT_STAGE_RESULT Stage: ViGEmPdoCreate [serial: %d, status: %!STATUS!]", - pdoData->SerialNo, status); - - BUS_PDO_REPORT_STAGE_RESULT(pdoData->BusInterface, ViGEmPdoPrepareHardware, pdoData->SerialNo, status); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status); - - return status; -} - -// -// Responds to IRP_MJ_INTERNAL_DEVICE_CONTROL requests sent to PDO. -// -VOID Pdo_EvtIoInternalDeviceControl( - _In_ WDFQUEUE Queue, - _In_ WDFREQUEST Request, - _In_ size_t OutputBufferLength, - _In_ size_t InputBufferLength, - _In_ ULONG IoControlCode -) -{ - // Regular buffers not used in USB communication - UNREFERENCED_PARAMETER(OutputBufferLength); - UNREFERENCED_PARAMETER(InputBufferLength); - - NTSTATUS status = STATUS_INVALID_PARAMETER; - WDFDEVICE hDevice; - PIRP irp; - PURB urb; - PPDO_DEVICE_DATA pdoData; - PIO_STACK_LOCATION irpStack; - - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSPDO, "%!FUNC! Entry"); - - hDevice = WdfIoQueueGetDevice(Queue); - pdoData = PdoGetData(hDevice); - // No help from the framework available from here on - irp = WdfRequestWdmGetIrp(Request); - irpStack = IoGetCurrentIrpStackLocation(irp); - - switch (IoControlCode) - { - case IOCTL_INTERNAL_USB_SUBMIT_URB: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> IOCTL_INTERNAL_USB_SUBMIT_URB"); - - urb = (PURB)URB_FROM_IRP(irp); - - switch (urb->UrbHeader.Function) - { - case URB_FUNCTION_CONTROL_TRANSFER: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> URB_FUNCTION_CONTROL_TRANSFER"); - - switch (urb->UrbControlTransfer.SetupPacket[6]) - { - case 0x04: - // - // Xenon magic - // - COPY_BYTE_ARRAY(urb->UrbControlTransfer.TransferBuffer, P99_PROTECT({ - 0x31, 0x3F, 0xCF, 0xDC - })); - status = STATUS_SUCCESS; - break; - case 0x14: - // - // This is some weird USB 1.0 condition and _must fail_ - // - urb->UrbControlTransfer.Hdr.Status = USBD_STATUS_STALL_PID; - status = STATUS_UNSUCCESSFUL; - break; - case 0x08: - // - // This is some weird USB 1.0 condition and _must fail_ - // - urb->UrbControlTransfer.Hdr.Status = USBD_STATUS_STALL_PID; - status = STATUS_UNSUCCESSFUL; - break; - default: - status = STATUS_SUCCESS; - break; - } - - break; - - case URB_FUNCTION_CONTROL_TRANSFER_EX: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> URB_FUNCTION_CONTROL_TRANSFER_EX"); - - status = STATUS_UNSUCCESSFUL; - - break; - - case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER"); - - status = UsbPdo_BulkOrInterruptTransfer(urb, hDevice, Request); - - break; - - case URB_FUNCTION_SELECT_CONFIGURATION: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> URB_FUNCTION_SELECT_CONFIGURATION"); - - status = UsbPdo_SelectConfiguration(urb, pdoData); - - break; - - case URB_FUNCTION_SELECT_INTERFACE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> URB_FUNCTION_SELECT_INTERFACE"); - - status = UsbPdo_SelectInterface(urb, pdoData); - - break; - - case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE"); - - switch (urb->UrbControlDescriptorRequest.DescriptorType) - { - case USB_DEVICE_DESCRIPTOR_TYPE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> >> USB_DEVICE_DESCRIPTOR_TYPE"); - - status = UsbPdo_GetDeviceDescriptorType(urb, pdoData); - - break; - - case USB_CONFIGURATION_DESCRIPTOR_TYPE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> >> USB_CONFIGURATION_DESCRIPTOR_TYPE"); - - status = UsbPdo_GetConfigurationDescriptorType(urb, pdoData); - - break; - - case USB_STRING_DESCRIPTOR_TYPE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> >> USB_STRING_DESCRIPTOR_TYPE"); - - status = UsbPdo_GetStringDescriptorType(urb, pdoData); - - break; - case USB_INTERFACE_DESCRIPTOR_TYPE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> >> USB_INTERFACE_DESCRIPTOR_TYPE"); - - break; - - case USB_ENDPOINT_DESCRIPTOR_TYPE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> >> USB_ENDPOINT_DESCRIPTOR_TYPE"); - - break; - - default: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> >> Unknown descriptor type"); - - break; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - "<< <<"); - - break; - - case URB_FUNCTION_GET_STATUS_FROM_DEVICE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> URB_FUNCTION_GET_STATUS_FROM_DEVICE"); - - // Defaults always succeed - status = STATUS_SUCCESS; - - break; - - case URB_FUNCTION_ABORT_PIPE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> URB_FUNCTION_ABORT_PIPE"); - - status = UsbPdo_AbortPipe(hDevice); - - break; - - case URB_FUNCTION_CLASS_INTERFACE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> URB_FUNCTION_CLASS_INTERFACE"); - - status = UsbPdo_ClassInterface(urb, hDevice, pdoData); - - break; - - case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE"); - - status = UsbPdo_GetDescriptorFromInterface(urb, pdoData); - - // - // The DS4 is basically ready to operate at this stage - // - if (pdoData->TargetType == DualShock4Wired) - { - // - // Report back to FDO that we are ready to operate - // - BUS_PDO_REPORT_STAGE_RESULT( - pdoData->BusInterface, - ViGEmPdoInitFinished, - pdoData->SerialNo, - STATUS_SUCCESS - ); - } - - break; - - default: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> >> Unknown function: 0x%X", - urb->UrbHeader.Function); - - break; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - "<<"); - - break; - - case IOCTL_INTERNAL_USB_GET_PORT_STATUS: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> IOCTL_INTERNAL_USB_GET_PORT_STATUS"); - - // We report the (virtual) port as always active - *(unsigned long *)irpStack->Parameters.Others.Argument1 = USBD_PORT_ENABLED | USBD_PORT_CONNECTED; - - status = STATUS_SUCCESS; - - break; - - case IOCTL_INTERNAL_USB_RESET_PORT: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> IOCTL_INTERNAL_USB_RESET_PORT"); - - // Sure, why not ;) - status = STATUS_SUCCESS; - - break; - - case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION"); - - // TODO: implement - // This happens if the I/O latency is too high so HIDUSB aborts communication. - status = STATUS_SUCCESS; - - break; - - default: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_BUSPDO, - ">> Unknown I/O control code 0x%X", - IoControlCode); - - break; - } - - if (status != STATUS_PENDING) - { - WdfRequestComplete(Request, status); - } - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status); -} - diff --git a/sys/resource.h b/sys/resource.h deleted file mode 100644 index 97b180c..0000000 --- a/sys/resource.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by ViGEmBus.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/sys/trace.h b/sys/trace.h deleted file mode 100644 index d67e89f..0000000 --- a/sys/trace.h +++ /dev/null @@ -1,61 +0,0 @@ -/*++ - -Module Name: - - Trace.h - -Abstract: - - Header file for the debug tracing related function defintions and macros. - -Environment: - - Kernel mode - ---*/ - -// -// Define the tracing flags. -// -// Tracing GUID - c5ce18fe-27bd-4049-b0b4-8a47cab1dcd9 -// - -#define WPP_CONTROL_GUIDS \ - WPP_DEFINE_CONTROL_GUID( \ - ViGEmBusTraceGuid, (c5ce18fe,27bd,4049,b0b4,8a47cab1dcd9), \ - \ - WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \ - WPP_DEFINE_BIT(TRACE_BUSENUM) \ - WPP_DEFINE_BIT(TRACE_BUSPDO) \ - WPP_DEFINE_BIT(TRACE_BYTEARRAY) \ - WPP_DEFINE_BIT(TRACE_DRIVER) \ - WPP_DEFINE_BIT(TRACE_DS4) \ - WPP_DEFINE_BIT(TRACE_QUEUE) \ - WPP_DEFINE_BIT(TRACE_USBPDO) \ - WPP_DEFINE_BIT(TRACE_UTIL) \ - WPP_DEFINE_BIT(TRACE_XGIP) \ - WPP_DEFINE_BIT(TRACE_XUSB) \ - ) - -#define WPP_FLAG_LEVEL_LOGGER(flag, level) \ - WPP_LEVEL_LOGGER(flag) - -#define WPP_FLAG_LEVEL_ENABLED(flag, level) \ - (WPP_LEVEL_ENABLED(flag) && \ - WPP_CONTROL(WPP_BIT_ ## flag).Level >= level) - -#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \ - WPP_LEVEL_LOGGER(flags) - -#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \ - (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) - -// -// This comment block is scanned by the trace preprocessor to define our -// Trace function. -// -// begin_wpp config -// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); -// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...); -// end_wpp -// diff --git a/sys/usbpdo.c b/sys/usbpdo.c deleted file mode 100644 index f43b073..0000000 --- a/sys/usbpdo.c +++ /dev/null @@ -1,1298 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 "busenum.h" -#include "usbpdo.tmh" - - -// -// Dummy function to satisfy USB interface -// -BOOLEAN USB_BUSIFFN UsbPdo_IsDeviceHighSpeed(IN PVOID BusContext) -{ - UNREFERENCED_PARAMETER(BusContext); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_USBPDO, - "IsDeviceHighSpeed: TRUE"); - - return TRUE; -} - -// -// Dummy function to satisfy USB interface -// -NTSTATUS USB_BUSIFFN UsbPdo_QueryBusInformation( - IN PVOID BusContext, - IN ULONG Level, - IN OUT PVOID BusInformationBuffer, - IN OUT PULONG BusInformationBufferLength, - OUT PULONG BusInformationActualLength -) -{ - UNREFERENCED_PARAMETER(BusContext); - UNREFERENCED_PARAMETER(Level); - UNREFERENCED_PARAMETER(BusInformationBuffer); - UNREFERENCED_PARAMETER(BusInformationBufferLength); - UNREFERENCED_PARAMETER(BusInformationActualLength); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_USBPDO, - "QueryBusInformation: %!STATUS!", STATUS_UNSUCCESSFUL); - - return STATUS_UNSUCCESSFUL; -} - -// -// Dummy function to satisfy USB interface -// -NTSTATUS USB_BUSIFFN UsbPdo_SubmitIsoOutUrb(IN PVOID BusContext, IN PURB Urb) -{ - UNREFERENCED_PARAMETER(BusContext); - UNREFERENCED_PARAMETER(Urb); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_USBPDO, - "SubmitIsoOutUrb: %!STATUS!", STATUS_UNSUCCESSFUL); - - return STATUS_UNSUCCESSFUL; -} - -// -// Dummy function to satisfy USB interface -// -NTSTATUS USB_BUSIFFN UsbPdo_QueryBusTime(IN PVOID BusContext, IN OUT PULONG CurrentUsbFrame) -{ - UNREFERENCED_PARAMETER(BusContext); - UNREFERENCED_PARAMETER(CurrentUsbFrame); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_USBPDO, - "QueryBusTime: %!STATUS!", STATUS_UNSUCCESSFUL); - - return STATUS_UNSUCCESSFUL; -} - -// -// Dummy function to satisfy USB interface -// -VOID USB_BUSIFFN UsbPdo_GetUSBDIVersion( - IN PVOID BusContext, - IN OUT PUSBD_VERSION_INFORMATION VersionInformation, - IN OUT PULONG HcdCapabilities -) -{ - UNREFERENCED_PARAMETER(BusContext); - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_USBPDO, - "GetUSBDIVersion: 0x500, 0x200"); - - if (VersionInformation != NULL) - { - VersionInformation->USBDI_Version = 0x500; /* Usbport */ - VersionInformation->Supported_USB_Version = 0x200; /* USB 2.0 */ - } - - if (HcdCapabilities != NULL) - { - *HcdCapabilities = 0; - } -} - -// -// Set device descriptor to identify the current USB device. -// -NTSTATUS UsbPdo_GetDeviceDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommon) -{ - PUSB_DEVICE_DESCRIPTOR pDescriptor = (PUSB_DEVICE_DESCRIPTOR)urb->UrbControlDescriptorRequest.TransferBuffer; - - switch (pCommon->TargetType) - { - case Xbox360Wired: - - Xusb_GetDeviceDescriptorType(pDescriptor, pCommon); - - break; - - case DualShock4Wired: - - Ds4_GetDeviceDescriptorType(pDescriptor, pCommon); - - break; - - case XboxOneWired: - - Xgip_GetDeviceDescriptorType(pDescriptor, pCommon); - - break; - - default: - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -// -// Set configuration descriptor, expose interfaces and endpoints. -// -NTSTATUS UsbPdo_GetConfigurationDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommon) -{ - PUCHAR Buffer = (PUCHAR)urb->UrbControlDescriptorRequest.TransferBuffer; - - // First request just gets required buffer size back - if (urb->UrbControlDescriptorRequest.TransferBufferLength == sizeof(USB_CONFIGURATION_DESCRIPTOR)) - { - ULONG length = sizeof(USB_CONFIGURATION_DESCRIPTOR); - - switch (pCommon->TargetType) - { - case Xbox360Wired: - - Xusb_GetConfigurationDescriptorType(Buffer, length); - - break; - case DualShock4Wired: - - Ds4_GetConfigurationDescriptorType(Buffer, length); - - break; - case XboxOneWired: - - Xgip_GetConfigurationDescriptorType(Buffer, length); - - break; - default: - return STATUS_UNSUCCESSFUL; - } - } - - ULONG length = urb->UrbControlDescriptorRequest.TransferBufferLength; - - // Second request can store the whole descriptor - switch (pCommon->TargetType) - { - case Xbox360Wired: - - if (length >= XUSB_DESCRIPTOR_SIZE) - { - Xusb_GetConfigurationDescriptorType(Buffer, XUSB_DESCRIPTOR_SIZE); - } - - break; - case DualShock4Wired: - - if (length >= DS4_DESCRIPTOR_SIZE) - { - Ds4_GetConfigurationDescriptorType(Buffer, DS4_DESCRIPTOR_SIZE); - } - - break; - case XboxOneWired: - - if (length >= XGIP_DESCRIPTOR_SIZE) - { - Xgip_GetConfigurationDescriptorType(Buffer, XGIP_DESCRIPTOR_SIZE); - } - - break; - default: - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -// -// Set device string descriptors (currently only used in DS4 emulation). -// -NTSTATUS UsbPdo_GetStringDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommon) -{ - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - "Index = %d", - urb->UrbControlDescriptorRequest.Index); - - switch (pCommon->TargetType) - { - case DualShock4Wired: - { - switch (urb->UrbControlDescriptorRequest.Index) - { - case 0: - { - // "American English" - UCHAR LangId[HID_LANGUAGE_ID_LENGTH] = - { - 0x04, 0x03, 0x09, 0x04 - }; - - urb->UrbControlDescriptorRequest.TransferBufferLength = HID_LANGUAGE_ID_LENGTH; - RtlCopyBytes(urb->UrbControlDescriptorRequest.TransferBuffer, LangId, HID_LANGUAGE_ID_LENGTH); - - break; - } - case 1: - { - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - "LanguageId = 0x%X", - urb->UrbControlDescriptorRequest.LanguageId); - - if (urb->UrbControlDescriptorRequest.TransferBufferLength < DS4_MANUFACTURER_NAME_LENGTH) - { - PUSB_STRING_DESCRIPTOR pDesc = (PUSB_STRING_DESCRIPTOR)urb->UrbControlDescriptorRequest.TransferBuffer; - pDesc->bLength = DS4_MANUFACTURER_NAME_LENGTH; - break; - } - - // "Sony Computer Entertainment" - UCHAR ManufacturerString[DS4_MANUFACTURER_NAME_LENGTH] = - { - 0x38, 0x03, 0x53, 0x00, 0x6F, 0x00, 0x6E, 0x00, - 0x79, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x6D, 0x00, 0x70, 0x00, 0x75, 0x00, 0x74, 0x00, - 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x45, 0x00, - 0x6E, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, - 0x74, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6E, 0x00, - 0x6D, 0x00, 0x65, 0x00, 0x6E, 0x00, 0x74, 0x00 - }; - - urb->UrbControlDescriptorRequest.TransferBufferLength = DS4_MANUFACTURER_NAME_LENGTH; - RtlCopyBytes(urb->UrbControlDescriptorRequest.TransferBuffer, ManufacturerString, DS4_MANUFACTURER_NAME_LENGTH); - - break; - } - case 2: - { - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - "LanguageId = 0x%X", - urb->UrbControlDescriptorRequest.LanguageId); - - if (urb->UrbControlDescriptorRequest.TransferBufferLength < DS4_PRODUCT_NAME_LENGTH) - { - PUSB_STRING_DESCRIPTOR pDesc = (PUSB_STRING_DESCRIPTOR)urb->UrbControlDescriptorRequest.TransferBuffer; - pDesc->bLength = DS4_PRODUCT_NAME_LENGTH; - break; - } - - // "Wireless Controller" - UCHAR ProductString[DS4_PRODUCT_NAME_LENGTH] = - { - 0x28, 0x03, 0x57, 0x00, 0x69, 0x00, 0x72, 0x00, - 0x65, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x73, 0x00, - 0x73, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x6E, 0x00, 0x74, 0x00, 0x72, 0x00, 0x6F, 0x00, - 0x6C, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x72, 0x00 - }; - - urb->UrbControlDescriptorRequest.TransferBufferLength = DS4_PRODUCT_NAME_LENGTH; - RtlCopyBytes(urb->UrbControlDescriptorRequest.TransferBuffer, ProductString, DS4_PRODUCT_NAME_LENGTH); - - break; - } - default: - break; - } - - break; - } - default: - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -// -// Fakes a successfully selected configuration. -// -NTSTATUS UsbPdo_SelectConfiguration(PURB urb, PPDO_DEVICE_DATA pCommon) -{ - PUSBD_INTERFACE_INFORMATION pInfo; - - pInfo = &urb->UrbSelectConfiguration.Interface; - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: TotalLength %d", - urb->UrbHeader.Length); - - if (urb->UrbHeader.Length == sizeof(struct _URB_SELECT_CONFIGURATION)) - { - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: NULL ConfigurationDescriptor"); - return STATUS_SUCCESS; - } - - switch (pCommon->TargetType) - { - case Xbox360Wired: - - if (urb->UrbHeader.Length < XUSB_CONFIGURATION_SIZE) - { - TraceEvents(TRACE_LEVEL_WARNING, - TRACE_USBPDO, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Invalid ConfigurationDescriptor"); - return STATUS_INVALID_PARAMETER; - } - - Xusb_SelectConfiguration(pInfo); - - break; - - case DualShock4Wired: - - if (urb->UrbHeader.Length < DS4_CONFIGURATION_SIZE) - { - TraceEvents(TRACE_LEVEL_WARNING, - TRACE_USBPDO, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Invalid ConfigurationDescriptor"); - return STATUS_INVALID_PARAMETER; - } - - Ds4_SelectConfiguration(pInfo); - - break; - - case XboxOneWired: - - if (urb->UrbHeader.Length < XGIP_CONFIGURATION_SIZE) - { - TraceEvents(TRACE_LEVEL_WARNING, - TRACE_USBPDO, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Invalid ConfigurationDescriptor"); - return STATUS_INVALID_PARAMETER; - } - - Xgip_SelectConfiguration(pInfo); - - break; - - default: - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -// -// Fakes a successfully selected interface. -// -NTSTATUS UsbPdo_SelectInterface(PURB urb, PPDO_DEVICE_DATA pCommon) -{ - PUSBD_INTERFACE_INFORMATION pInfo = &urb->UrbSelectInterface.Interface; - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> URB_FUNCTION_SELECT_INTERFACE: Length %d, Interface %d, Alternate %d, Pipes %d", - (int)pInfo->Length, - (int)pInfo->InterfaceNumber, - (int)pInfo->AlternateSetting, - pInfo->NumberOfPipes); - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> URB_FUNCTION_SELECT_INTERFACE: Class %d, SubClass %d, Protocol %d", - (int)pInfo->Class, - (int)pInfo->SubClass, - (int)pInfo->Protocol); - - switch (pCommon->TargetType) - { - case Xbox360Wired: - { - if (pInfo->InterfaceNumber == 1) - { - pInfo[0].Class = 0xFF; - pInfo[0].SubClass = 0x5D; - pInfo[0].Protocol = 0x03; - pInfo[0].NumberOfPipes = 0x04; - - pInfo[0].InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; - - pInfo[0].Pipes[0].MaximumTransferSize = 0x00400000; - pInfo[0].Pipes[0].MaximumPacketSize = 0x20; - pInfo[0].Pipes[0].EndpointAddress = 0x82; - pInfo[0].Pipes[0].Interval = 0x04; - pInfo[0].Pipes[0].PipeType = 0x03; - pInfo[0].Pipes[0].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0082; - pInfo[0].Pipes[0].PipeFlags = 0x00; - - pInfo[0].Pipes[1].MaximumTransferSize = 0x00400000; - pInfo[0].Pipes[1].MaximumPacketSize = 0x20; - pInfo[0].Pipes[1].EndpointAddress = 0x02; - pInfo[0].Pipes[1].Interval = 0x08; - pInfo[0].Pipes[1].PipeType = 0x03; - pInfo[0].Pipes[1].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0002; - pInfo[0].Pipes[1].PipeFlags = 0x00; - - pInfo[0].Pipes[2].MaximumTransferSize = 0x00400000; - pInfo[0].Pipes[2].MaximumPacketSize = 0x20; - pInfo[0].Pipes[2].EndpointAddress = 0x83; - pInfo[0].Pipes[2].Interval = 0x08; - pInfo[0].Pipes[2].PipeType = 0x03; - pInfo[0].Pipes[2].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0083; - pInfo[0].Pipes[2].PipeFlags = 0x00; - - pInfo[0].Pipes[3].MaximumTransferSize = 0x00400000; - pInfo[0].Pipes[3].MaximumPacketSize = 0x20; - pInfo[0].Pipes[3].EndpointAddress = 0x03; - pInfo[0].Pipes[3].Interval = 0x08; - pInfo[0].Pipes[3].PipeType = 0x03; - pInfo[0].Pipes[3].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0003; - pInfo[0].Pipes[3].PipeFlags = 0x00; - - return STATUS_SUCCESS; - } - - if (pInfo->InterfaceNumber == 2) - { - pInfo[0].Class = 0xFF; - pInfo[0].SubClass = 0x5D; - pInfo[0].Protocol = 0x02; - pInfo[0].NumberOfPipes = 0x01; - - pInfo[0].InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; - - pInfo[0].Pipes[0].MaximumTransferSize = 0x00400000; - pInfo[0].Pipes[0].MaximumPacketSize = 0x20; - pInfo[0].Pipes[0].EndpointAddress = 0x84; - pInfo[0].Pipes[0].Interval = 0x04; - pInfo[0].Pipes[0].PipeType = 0x03; - pInfo[0].Pipes[0].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0084; - pInfo[0].Pipes[0].PipeFlags = 0x00; - - return STATUS_SUCCESS; - } - } - case DualShock4Wired: - { - TraceEvents(TRACE_LEVEL_WARNING, - TRACE_USBPDO, - "Not implemented"); - - break; - } - default: - break; - } - - return STATUS_INVALID_PARAMETER; -} - -// -// Dispatch interrupt transfers. -// -NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST Request) -{ - struct _URB_BULK_OR_INTERRUPT_TRANSFER* pTransfer = &urb->UrbBulkOrInterruptTransfer; - NTSTATUS status; - PPDO_DEVICE_DATA pdoData; - WDFREQUEST notifyRequest; - - pdoData = PdoGetData(Device); - - if (pdoData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_USBPDO, - ">> >> >> PdoGetData failed"); - return STATUS_INVALID_PARAMETER; - } - - switch (pdoData->TargetType) - { - case Xbox360Wired: - { - PXUSB_DEVICE_DATA xusb = XusbGetData(Device); - - // Check context - if (xusb == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_USBPDO, - "No XUSB context found on device %p", - Device); - - return STATUS_UNSUCCESSFUL; - } - - // Data coming FROM us TO higher driver - if (pTransfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN) - { - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> Incoming request, queuing..."); - - if (XUSB_IS_DATA_PIPE(pTransfer)) - { - // - // Send "boot sequence" first, then the actual inputs - // - switch (xusb->InterruptInitStage) - { - case 0: - xusb->InterruptInitStage++; - pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE; - COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({ - 0x01, 0x03, 0x0E - })); - return STATUS_SUCCESS; - case 1: - xusb->InterruptInitStage++; - pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE; - COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({ - 0x02, 0x03, 0x00 - })); - return STATUS_SUCCESS; - case 2: - xusb->InterruptInitStage++; - pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE; - COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({ - 0x03, 0x03, 0x03 - })); - return STATUS_SUCCESS; - case 3: - xusb->InterruptInitStage++; - pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE; - COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({ - 0x08, 0x03, 0x00 - })); - return STATUS_SUCCESS; - case 4: - xusb->InterruptInitStage++; - pTransfer->TransferBufferLength = sizeof(XUSB_INTERRUPT_IN_PACKET); - COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({ - 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xf2, - 0xb3, 0xf8, 0x49, 0xf3, 0xb0, 0xfc, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 - })); - return STATUS_SUCCESS; - case 5: - xusb->InterruptInitStage++; - pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE; - COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({ - 0x01, 0x03, 0x03 - })); - return STATUS_SUCCESS; - default: - /* This request is sent periodically and relies on data the "feeder" - * has to supply, so we queue this request and return with STATUS_PENDING. - * The request gets completed as soon as the "feeder" sent an update. */ - status = WdfRequestForwardToIoQueue(Request, pdoData->PendingUsbInRequests); - - return (NT_SUCCESS(status)) ? STATUS_PENDING : status; - } - } - - if (XUSB_IS_CONTROL_PIPE(pTransfer)) - { - if (!xusb->ReportedCapabilities && pTransfer->TransferBufferLength >= XUSB_INIT_STAGE_SIZE) - { - pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE; - COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({ - 0x05, 0x03, 0x00 - })); - - xusb->ReportedCapabilities = TRUE; - - return STATUS_SUCCESS; - } - - status = WdfRequestForwardToIoQueue(Request, xusb->HoldingUsbInRequests); - - return (NT_SUCCESS(status)) ? STATUS_PENDING : status; - } - } - - // Data coming FROM the higher driver TO us - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: Handle %p, Flags %X, Length %d", - pTransfer->PipeHandle, - pTransfer->TransferFlags, - pTransfer->TransferBufferLength); - - if (pTransfer->TransferBufferLength == XUSB_LEDSET_SIZE) // Led - { - PUCHAR Buffer = pTransfer->TransferBuffer; - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - "-- LED Buffer: %02X %02X %02X", - Buffer[0], Buffer[1], Buffer[2]); - - // extract LED byte to get controller slot - if (Buffer[0] == 0x01 && Buffer[1] == 0x03 && Buffer[2] >= 0x02) - { - if (Buffer[2] == 0x02) xusb->LedNumber = 0; - if (Buffer[2] == 0x03) xusb->LedNumber = 1; - if (Buffer[2] == 0x04) xusb->LedNumber = 2; - if (Buffer[2] == 0x05) xusb->LedNumber = 3; - - TraceEvents(TRACE_LEVEL_INFORMATION, - TRACE_USBPDO, - "-- LED Number: %d", - xusb->LedNumber); - // - // Report back to FDO that we are ready to operate - // - BUS_PDO_REPORT_STAGE_RESULT( - pdoData->BusInterface, - ViGEmPdoInitFinished, - pdoData->SerialNo, - STATUS_SUCCESS - ); - } - } - - // Extract rumble (vibration) information - if (pTransfer->TransferBufferLength == XUSB_RUMBLE_SIZE) - { - PUCHAR Buffer = pTransfer->TransferBuffer; - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - "-- Rumble Buffer: %02X %02X %02X %02X %02X %02X %02X %02X", - Buffer[0], - Buffer[1], - Buffer[2], - Buffer[3], - Buffer[4], - Buffer[5], - Buffer[6], - Buffer[7]); - - RtlCopyBytes(xusb->Rumble, Buffer, pTransfer->TransferBufferLength); - } - - // Notify user-mode process that new data is available - status = WdfIoQueueRetrieveNextRequest(pdoData->PendingNotificationRequests, ¬ifyRequest); - - if (NT_SUCCESS(status)) - { - PXUSB_REQUEST_NOTIFICATION notify = NULL; - - status = WdfRequestRetrieveOutputBuffer(notifyRequest, sizeof(XUSB_REQUEST_NOTIFICATION), (PVOID)¬ify, NULL); - - if (NT_SUCCESS(status)) - { - // Assign values to output buffer - notify->Size = sizeof(XUSB_REQUEST_NOTIFICATION); - notify->SerialNo = pdoData->SerialNo; - notify->LedNumber = xusb->LedNumber; - notify->LargeMotor = xusb->Rumble[3]; - notify->SmallMotor = xusb->Rumble[4]; - - WdfRequestCompleteWithInformation(notifyRequest, status, notify->Size); - } - else - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_USBPDO, - "WdfRequestRetrieveOutputBuffer failed with status %!STATUS!", - status); - } - } - - break; - } - case DualShock4Wired: - { - PDS4_DEVICE_DATA ds4Data = Ds4GetData(Device); - - // Data coming FROM us TO higher driver - if (pTransfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN - && pTransfer->PipeHandle == (USBD_PIPE_HANDLE)0xFFFF0084) - { - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> Incoming request, queuing..."); - - /* This request is sent periodically and relies on data the "feeder" - has to supply, so we queue this request and return with STATUS_PENDING. - The request gets completed as soon as the "feeder" sent an update. */ - status = WdfRequestForwardToIoQueue(Request, pdoData->PendingUsbInRequests); - - return (NT_SUCCESS(status)) ? STATUS_PENDING : status; - } - - // Store relevant bytes of buffer in PDO context - RtlCopyBytes(&ds4Data->OutputReport, - (PUCHAR)pTransfer->TransferBuffer + DS4_OUTPUT_BUFFER_OFFSET, - DS4_OUTPUT_BUFFER_LENGTH); - - // Notify user-mode process that new data is available - status = WdfIoQueueRetrieveNextRequest(pdoData->PendingNotificationRequests, ¬ifyRequest); - - if (NT_SUCCESS(status)) - { - PDS4_REQUEST_NOTIFICATION notify = NULL; - - status = WdfRequestRetrieveOutputBuffer(notifyRequest, sizeof(DS4_REQUEST_NOTIFICATION), (PVOID)¬ify, NULL); - - if (NT_SUCCESS(status)) - { - // Assign values to output buffer - notify->Size = sizeof(DS4_REQUEST_NOTIFICATION); - notify->SerialNo = pdoData->SerialNo; - notify->Report = ds4Data->OutputReport; - - WdfRequestCompleteWithInformation(notifyRequest, status, notify->Size); - } - else - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_USBPDO, - "WdfRequestRetrieveOutputBuffer failed with status %!STATUS!", - status); - } - } - - break; - } - case XboxOneWired: - { - PXGIP_DEVICE_DATA xgipData = XgipGetData(Device); - - // Data coming FROM us TO higher driver - if (pTransfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN) - { - KdPrint((DRIVERNAME ">> >> >> Incoming request, queuing...")); - - /* This request is sent periodically and relies on data the "feeder" - has to supply, so we queue this request and return with STATUS_PENDING. - The request gets completed as soon as the "feeder" sent an update. */ - status = WdfRequestForwardToIoQueue(Request, xgipData->PendingUsbInRequests); - - return (NT_SUCCESS(status)) ? STATUS_PENDING : status; - } - - // Data coming FROM the higher driver TO us - KdPrint((DRIVERNAME ">> >> >> URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: Handle %p, Flags %X, Length %d", - pTransfer->PipeHandle, - pTransfer->TransferFlags, - pTransfer->TransferBufferLength)); - - break; - } - default: - break; - } - - return STATUS_SUCCESS; -} - -// -// Clean-up actions on shutdown. -// -NTSTATUS UsbPdo_AbortPipe(WDFDEVICE Device) -{ - PPDO_DEVICE_DATA pdoData = PdoGetData(Device); - - switch (pdoData->TargetType) - { - case DualShock4Wired: - { - PDS4_DEVICE_DATA ds4 = Ds4GetData(Device); - - // Check context - if (ds4 == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_USBPDO, - "No DS4 context found on device %p", Device); - - return STATUS_UNSUCCESSFUL; - } - - // Higher driver shutting down, emptying PDOs queues - WdfTimerStop(ds4->PendingUsbInRequestsTimer, TRUE); - - break; - } - default: - break; - } - - // Higher driver shutting down, emptying PDOs queues - WdfIoQueuePurge(pdoData->PendingUsbInRequests, NULL, NULL); - WdfIoQueuePurge(pdoData->PendingNotificationRequests, NULL, NULL); - - return STATUS_SUCCESS; -} - -// -// Processes URBs containing HID-related requests. -// -NTSTATUS UsbPdo_ClassInterface(PURB urb, WDFDEVICE Device, PPDO_DEVICE_DATA pCommon) -{ - struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST* pRequest = &urb->UrbControlVendorClassRequest; - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> URB_FUNCTION_CLASS_INTERFACE"); - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> TransferFlags = 0x%X, Request = 0x%X, Value = 0x%X, Index = 0x%X, BufLen = %d", - pRequest->TransferFlags, - pRequest->Request, - pRequest->Value, - pRequest->Index, - pRequest->TransferBufferLength); - - switch (pCommon->TargetType) - { - case DualShock4Wired: - { - PDS4_DEVICE_DATA ds4 = Ds4GetData(Device); - - switch (pRequest->Request) - { - case HID_REQUEST_GET_REPORT: - { - UCHAR reportId = HID_GET_REPORT_ID(pRequest); - UCHAR reportType = HID_GET_REPORT_TYPE(pRequest); - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> >> GET_REPORT(%d): %d", - reportType, reportId); - - switch (reportType) - { - case HID_REPORT_TYPE_FEATURE: - { - switch (reportId) - { - case HID_REPORT_ID_0: - { - // Source: http://eleccelerator.com/wiki/index.php?title=DualShock_4#Class_Requests - UCHAR Response[HID_GET_FEATURE_REPORT_SIZE_0] = - { - 0xA3, 0x41, 0x75, 0x67, 0x20, 0x20, 0x33, 0x20, - 0x32, 0x30, 0x31, 0x33, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x37, 0x3A, 0x30, 0x31, 0x3A, 0x31, - 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x31, 0x03, 0x00, 0x00, - 0x00, 0x49, 0x00, 0x05, 0x00, 0x00, 0x80, 0x03, - 0x00 - }; - - pRequest->TransferBufferLength = HID_GET_FEATURE_REPORT_SIZE_0; - RtlCopyBytes(pRequest->TransferBuffer, Response, HID_GET_FEATURE_REPORT_SIZE_0); - - break; - } - case HID_REPORT_ID_1: - { - // Source: http://eleccelerator.com/wiki/index.php?title=DualShock_4#Class_Requests - UCHAR Response[HID_GET_FEATURE_REPORT_SIZE_1] = - { - 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, - 0x22, 0x7B, 0xDD, 0xB2, 0x22, 0x47, 0xDD, 0xBD, - 0x22, 0x43, 0xDD, 0x1C, 0x02, 0x1C, 0x02, 0x7F, - 0x1E, 0x2E, 0xDF, 0x60, 0x1F, 0x4C, 0xE0, 0x3A, - 0x1D, 0xC6, 0xDE, 0x08, 0x00 - }; - - pRequest->TransferBufferLength = HID_GET_FEATURE_REPORT_SIZE_1; - RtlCopyBytes(pRequest->TransferBuffer, Response, HID_GET_FEATURE_REPORT_SIZE_1); - - break; - } - case HID_REPORT_MAC_ADDRESSES_ID: - { - // Source: http://eleccelerator.com/wiki/index.php?title=DualShock_4#Class_Requests - UCHAR Response[HID_GET_FEATURE_REPORT_MAC_ADDRESSES_SIZE] = - { - 0x12, 0x8B, 0x09, 0x07, 0x6D, 0x66, 0x1C, 0x08, - 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - // Insert (auto-generated) target MAC address into response - RtlCopyBytes(Response + 1, &ds4->TargetMacAddress, sizeof(MAC_ADDRESS)); - // Adjust byte order - ReverseByteArray(Response + 1, sizeof(MAC_ADDRESS)); - - // Insert (auto-generated) host MAC address into response - RtlCopyBytes(Response + 10, &ds4->HostMacAddress, sizeof(MAC_ADDRESS)); - // Adjust byte order - ReverseByteArray(Response + 10, sizeof(MAC_ADDRESS)); - - pRequest->TransferBufferLength = HID_GET_FEATURE_REPORT_MAC_ADDRESSES_SIZE; - RtlCopyBytes(pRequest->TransferBuffer, Response, HID_GET_FEATURE_REPORT_MAC_ADDRESSES_SIZE); - - break; - } - default: - break; - } - break; - } - default: - break; - } - - break; - } - case HID_REQUEST_SET_REPORT: - { - UCHAR reportId = HID_GET_REPORT_ID(pRequest); - UCHAR reportType = HID_GET_REPORT_TYPE(pRequest); - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> >> SET_REPORT(%d): %d", - reportType, reportId); - - switch (reportType) - { - case HID_REPORT_TYPE_FEATURE: - { - switch (reportId) - { - case HID_REPORT_ID_3: - { - // Source: http://eleccelerator.com/wiki/index.php?title=DualShock_4#Class_Requests - UCHAR Response[HID_SET_FEATURE_REPORT_SIZE_0] = - { - 0x13, 0xAC, 0x9E, 0x17, 0x94, 0x05, 0xB0, 0x56, - 0xE8, 0x81, 0x38, 0x08, 0x06, 0x51, 0x41, 0xC0, - 0x7F, 0x12, 0xAA, 0xD9, 0x66, 0x3C, 0xCE - }; - - pRequest->TransferBufferLength = HID_SET_FEATURE_REPORT_SIZE_0; - RtlCopyBytes(pRequest->TransferBuffer, Response, HID_SET_FEATURE_REPORT_SIZE_0); - - break; - } - case HID_REPORT_ID_4: - { - // Source: http://eleccelerator.com/wiki/index.php?title=DualShock_4#Class_Requests - UCHAR Response[HID_SET_FEATURE_REPORT_SIZE_1] = - { - 0x14, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - }; - - pRequest->TransferBufferLength = HID_SET_FEATURE_REPORT_SIZE_1; - RtlCopyBytes(pRequest->TransferBuffer, Response, HID_SET_FEATURE_REPORT_SIZE_1); - - break; - } - default: - break; - } - break; - } - default: - break; - } - - break; - } - default: - break; - } - - break; - } - } - - return STATUS_SUCCESS; -} - -// -// Returns interface HID report descriptor. -// -NTSTATUS UsbPdo_GetDescriptorFromInterface(PURB urb, PPDO_DEVICE_DATA pCommon) -{ - NTSTATUS status = STATUS_INVALID_PARAMETER; - UCHAR Ds4HidReportDescriptor[DS4_HID_REPORT_DESCRIPTOR_SIZE] = - { - 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) - 0x09, 0x05, // Usage (Game Pad) - 0xA1, 0x01, // Collection (Application) - 0x85, 0x01, // Report ID (1) - 0x09, 0x30, // Usage (X) - 0x09, 0x31, // Usage (Y) - 0x09, 0x32, // Usage (Z) - 0x09, 0x35, // Usage (Rz) - 0x15, 0x00, // Logical Minimum (0) - 0x26, 0xFF, 0x00, // Logical Maximum (255) - 0x75, 0x08, // Report Size (8) - 0x95, 0x04, // Report Count (4) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - 0x09, 0x39, // Usage (Hat switch) - 0x15, 0x00, // Logical Minimum (0) - 0x25, 0x07, // Logical Maximum (7) - 0x35, 0x00, // Physical Minimum (0) - 0x46, 0x3B, 0x01, // Physical Maximum (315) - 0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter) - 0x75, 0x04, // Report Size (4) - 0x95, 0x01, // Report Count (1) - 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State) - 0x65, 0x00, // Unit (None) - 0x05, 0x09, // Usage Page (Button) - 0x19, 0x01, // Usage Minimum (0x01) - 0x29, 0x0E, // Usage Maximum (0x0E) - 0x15, 0x00, // Logical Minimum (0) - 0x25, 0x01, // Logical Maximum (1) - 0x75, 0x01, // Report Size (1) - 0x95, 0x0E, // Report Count (14) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) - 0x09, 0x20, // Usage (0x20) - 0x75, 0x06, // Report Size (6) - 0x95, 0x01, // Report Count (1) - 0x15, 0x00, // Logical Minimum (0) - 0x25, 0x7F, // Logical Maximum (127) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) - 0x09, 0x33, // Usage (Rx) - 0x09, 0x34, // Usage (Ry) - 0x15, 0x00, // Logical Minimum (0) - 0x26, 0xFF, 0x00, // Logical Maximum (255) - 0x75, 0x08, // Report Size (8) - 0x95, 0x02, // Report Count (2) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) - 0x09, 0x21, // Usage (0x21) - 0x95, 0x36, // Report Count (54) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - 0x85, 0x05, // Report ID (5) - 0x09, 0x22, // Usage (0x22) - 0x95, 0x1F, // Report Count (31) - 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x04, // Report ID (4) - 0x09, 0x23, // Usage (0x23) - 0x95, 0x24, // Report Count (36) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x02, // Report ID (2) - 0x09, 0x24, // Usage (0x24) - 0x95, 0x24, // Report Count (36) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x08, // Report ID (8) - 0x09, 0x25, // Usage (0x25) - 0x95, 0x03, // Report Count (3) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x10, // Report ID (16) - 0x09, 0x26, // Usage (0x26) - 0x95, 0x04, // Report Count (4) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x11, // Report ID (17) - 0x09, 0x27, // Usage (0x27) - 0x95, 0x02, // Report Count (2) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x12, // Report ID (18) - 0x06, 0x02, 0xFF, // Usage Page (Vendor Defined 0xFF02) - 0x09, 0x21, // Usage (0x21) - 0x95, 0x0F, // Report Count (15) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x13, // Report ID (19) - 0x09, 0x22, // Usage (0x22) - 0x95, 0x16, // Report Count (22) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x14, // Report ID (20) - 0x06, 0x05, 0xFF, // Usage Page (Vendor Defined 0xFF05) - 0x09, 0x20, // Usage (0x20) - 0x95, 0x10, // Report Count (16) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x15, // Report ID (21) - 0x09, 0x21, // Usage (0x21) - 0x95, 0x2C, // Report Count (44) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x06, 0x80, 0xFF, // Usage Page (Vendor Defined 0xFF80) - 0x85, 0x80, // Report ID (128) - 0x09, 0x20, // Usage (0x20) - 0x95, 0x06, // Report Count (6) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x81, // Report ID (129) - 0x09, 0x21, // Usage (0x21) - 0x95, 0x06, // Report Count (6) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x82, // Report ID (130) - 0x09, 0x22, // Usage (0x22) - 0x95, 0x05, // Report Count (5) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x83, // Report ID (131) - 0x09, 0x23, // Usage (0x23) - 0x95, 0x01, // Report Count (1) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x84, // Report ID (132) - 0x09, 0x24, // Usage (0x24) - 0x95, 0x04, // Report Count (4) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x85, // Report ID (133) - 0x09, 0x25, // Usage (0x25) - 0x95, 0x06, // Report Count (6) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x86, // Report ID (134) - 0x09, 0x26, // Usage (0x26) - 0x95, 0x06, // Report Count (6) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x87, // Report ID (135) - 0x09, 0x27, // Usage (0x27) - 0x95, 0x23, // Report Count (35) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x88, // Report ID (136) - 0x09, 0x28, // Usage (0x28) - 0x95, 0x22, // Report Count (34) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x89, // Report ID (137) - 0x09, 0x29, // Usage (0x29) - 0x95, 0x02, // Report Count (2) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x90, // Report ID (144) - 0x09, 0x30, // Usage (0x30) - 0x95, 0x05, // Report Count (5) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x91, // Report ID (145) - 0x09, 0x31, // Usage (0x31) - 0x95, 0x03, // Report Count (3) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x92, // Report ID (146) - 0x09, 0x32, // Usage (0x32) - 0x95, 0x03, // Report Count (3) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0x93, // Report ID (147) - 0x09, 0x33, // Usage (0x33) - 0x95, 0x0C, // Report Count (12) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xA0, // Report ID (160) - 0x09, 0x40, // Usage (0x40) - 0x95, 0x06, // Report Count (6) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xA1, // Report ID (161) - 0x09, 0x41, // Usage (0x41) - 0x95, 0x01, // Report Count (1) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xA2, // Report ID (162) - 0x09, 0x42, // Usage (0x42) - 0x95, 0x01, // Report Count (1) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xA3, // Report ID (163) - 0x09, 0x43, // Usage (0x43) - 0x95, 0x30, // Report Count (48) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xA4, // Report ID (164) - 0x09, 0x44, // Usage (0x44) - 0x95, 0x0D, // Report Count (13) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xA5, // Report ID (165) - 0x09, 0x45, // Usage (0x45) - 0x95, 0x15, // Report Count (21) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xA6, // Report ID (166) - 0x09, 0x46, // Usage (0x46) - 0x95, 0x15, // Report Count (21) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xF0, // Report ID (240) - 0x09, 0x47, // Usage (0x47) - 0x95, 0x3F, // Report Count (63) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xF1, // Report ID (241) - 0x09, 0x48, // Usage (0x48) - 0x95, 0x3F, // Report Count (63) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xF2, // Report ID (242) - 0x09, 0x49, // Usage (0x49) - 0x95, 0x0F, // Report Count (15) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xA7, // Report ID (167) - 0x09, 0x4A, // Usage (0x4A) - 0x95, 0x01, // Report Count (1) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xA8, // Report ID (168) - 0x09, 0x4B, // Usage (0x4B) - 0x95, 0x01, // Report Count (1) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xA9, // Report ID (169) - 0x09, 0x4C, // Usage (0x4C) - 0x95, 0x08, // Report Count (8) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xAA, // Report ID (170) - 0x09, 0x4E, // Usage (0x4E) - 0x95, 0x01, // Report Count (1) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xAB, // Report ID (171) - 0x09, 0x4F, // Usage (0x4F) - 0x95, 0x39, // Report Count (57) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xAC, // Report ID (172) - 0x09, 0x50, // Usage (0x50) - 0x95, 0x39, // Report Count (57) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xAD, // Report ID (173) - 0x09, 0x51, // Usage (0x51) - 0x95, 0x0B, // Report Count (11) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xAE, // Report ID (174) - 0x09, 0x52, // Usage (0x52) - 0x95, 0x01, // Report Count (1) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xAF, // Report ID (175) - 0x09, 0x53, // Usage (0x53) - 0x95, 0x02, // Report Count (2) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0x85, 0xB0, // Report ID (176) - 0x09, 0x54, // Usage (0x54) - 0x95, 0x3F, // Report Count (63) - 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) - 0xC0, // End Collection - }; - - struct _URB_CONTROL_DESCRIPTOR_REQUEST* pRequest = &urb->UrbControlDescriptorRequest; - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_USBPDO, - ">> >> >> _URB_CONTROL_DESCRIPTOR_REQUEST: Buffer Length %d", - pRequest->TransferBufferLength); - - switch (pCommon->TargetType) - { - case DualShock4Wired: - { - if (pRequest->TransferBufferLength >= DS4_HID_REPORT_DESCRIPTOR_SIZE) - { - RtlCopyMemory(pRequest->TransferBuffer, Ds4HidReportDescriptor, DS4_HID_REPORT_DESCRIPTOR_SIZE); - status = STATUS_SUCCESS; - } - - break; - } - default: - break; - } - - return status; -} - diff --git a/sys/util.c b/sys/util.c deleted file mode 100644 index 3ebc372..0000000 --- a/sys/util.c +++ /dev/null @@ -1,60 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 -#include "busenum.h" -#include "util.tmh" - - -VOID ReverseByteArray(PUCHAR Array, INT Length) -{ - PUCHAR s = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, sizeof(UCHAR) * Length, VIGEM_POOL_TAG); - INT c, d; - - if (s == NULL) - return; - - for (c = Length - 1, d = 0; c >= 0; c--, d++) - *(s + d) = *(Array + c); - - for (c = 0; c < Length; c++) - *(Array + c) = *(s + c); - - ExFreePoolWithTag(s, VIGEM_POOL_TAG); -} - -VOID GenerateRandomMacAddress(PMAC_ADDRESS Address) -{ - // Vendor "C0:13:37" - Address->Vendor0 = 0xC0; - Address->Vendor1 = 0x13; - Address->Vendor2 = 0x37; - - ULONG seed = KeQueryPerformanceCounter(NULL).LowPart; - - Address->Nic0 = RtlRandomEx(&seed) % 0xFF; - Address->Nic1 = RtlRandomEx(&seed) % 0xFF; - Address->Nic2 = RtlRandomEx(&seed) % 0xFF; -} diff --git a/sys/xgip.c b/sys/xgip.c deleted file mode 100644 index 387d26a..0000000 --- a/sys/xgip.c +++ /dev/null @@ -1,406 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 "busenum.h" -#include "xgip.tmh" - -NTSTATUS Xgip_PreparePdo(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId, PUNICODE_STRING DeviceDescription) -{ - NTSTATUS status; - UNICODE_STRING buffer; - - // prepare device description - status = RtlUnicodeStringInit(DeviceDescription, L"Virtual Xbox One Controller"); - if (!NT_SUCCESS(status)) - return status; - - // Set hardware IDs - RtlUnicodeStringInit(&buffer, L"USB\\VID_0E6F&PID_0139&REV_0650"); - - status = WdfPdoInitAddHardwareID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - RtlUnicodeStringCopy(DeviceId, &buffer); - - RtlUnicodeStringInit(&buffer, L"USB\\VID_0E6F&PID_0139"); - - status = WdfPdoInitAddHardwareID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - // Set compatible IDs - RtlUnicodeStringInit(&buffer, L"USB\\MS_COMP_XGIP10"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - RtlUnicodeStringInit(&buffer, L"USB\\Class_FF&SubClass_47&Prot_D0"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - RtlUnicodeStringInit(&buffer, L"USB\\Class_FF&SubClass_47"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - RtlUnicodeStringInit(&buffer, L"USB\\Class_FF"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - return STATUS_SUCCESS; -} - -NTSTATUS Xgip_PrepareHardware(WDFDEVICE Device) -{ - NTSTATUS status; - WDF_QUERY_INTERFACE_CONFIG ifaceCfg; - - // Expose USB_BUS_INTERFACE_USBDI_GUID - USB_BUS_INTERFACE_USBDI_V1 xgipInterface; - - xgipInterface.Size = sizeof(USB_BUS_INTERFACE_USBDI_V1); - xgipInterface.Version = USB_BUSIF_USBDI_VERSION_1; - xgipInterface.BusContext = (PVOID)Device; - - xgipInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; - xgipInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; - - xgipInterface.SubmitIsoOutUrb = UsbPdo_SubmitIsoOutUrb; - xgipInterface.GetUSBDIVersion = UsbPdo_GetUSBDIVersion; - xgipInterface.QueryBusTime = UsbPdo_QueryBusTime; - xgipInterface.QueryBusInformation = UsbPdo_QueryBusInformation; - xgipInterface.IsDeviceHighSpeed = UsbPdo_IsDeviceHighSpeed; - - WDF_QUERY_INTERFACE_CONFIG_INIT(&ifaceCfg, (PINTERFACE)&xgipInterface, &USB_BUS_INTERFACE_USBDI_GUID, NULL); - - status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_XGIP, "WdfDeviceAddQueryInterface failed with status %!STATUS!", status); - return status; - } - - // Default button states - UCHAR DefaultReport[XGIP_REPORT_SIZE] = - { - 0x20, 0x00, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xa3, 0xfd, 0xed, 0x05, 0x5b, 0x03, - 0x6f, 0x02 - }; - - RtlCopyBytes(XgipGetData(Device)->Report, DefaultReport, XGIP_REPORT_SIZE); - - return STATUS_SUCCESS; -} - -NTSTATUS Xgip_AssignPdoContext(WDFDEVICE Device) -{ - NTSTATUS status; - - PXGIP_DEVICE_DATA xgip = XgipGetData(Device); - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XGIP, "Initializing XGIP context..."); - - RtlZeroMemory(xgip, sizeof(XGIP_DEVICE_DATA)); - - // Set fixed report id - xgip->Report[0] = 0x20; - xgip->Report[3] = 0x0E; - - // I/O Queue for pending IRPs - WDF_IO_QUEUE_CONFIG pendingUsbQueueConfig, notificationsQueueConfig; - - // Create and assign queue for incoming interrupt transfer - WDF_IO_QUEUE_CONFIG_INIT(&pendingUsbQueueConfig, WdfIoQueueDispatchManual); - - status = WdfIoQueueCreate(Device, &pendingUsbQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &xgip->PendingUsbInRequests); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_XGIP, "WdfIoQueueCreate failed with status %!STATUS!", status); - return status; - } - - // Create and assign queue for user-land notification requests - WDF_IO_QUEUE_CONFIG_INIT(¬ificationsQueueConfig, WdfIoQueueDispatchManual); - - status = WdfIoQueueCreate(Device, ¬ificationsQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &xgip->PendingNotificationRequests); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_XGIP, "WdfIoQueueCreate failed with status %!STATUS!", status); - return status; - } - - WDF_OBJECT_ATTRIBUTES collectionAttribs; - WDF_OBJECT_ATTRIBUTES_INIT(&collectionAttribs); - - collectionAttribs.ParentObject = Device; - - status = WdfCollectionCreate(&collectionAttribs, &xgip->XboxgipSysInitCollection); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_XGIP, "WdfCollectionCreate failed with status %!STATUS!", status); - return status; - } - - // Initialize periodic timer - WDF_TIMER_CONFIG timerConfig; - WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, Xgip_SysInitTimerFunc, XGIP_SYS_INIT_PERIOD); - - // Timer object attributes - WDF_OBJECT_ATTRIBUTES timerAttribs; - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttribs); - - // PDO is parent - timerAttribs.ParentObject = Device; - - // Create timer - status = WdfTimerCreate(&timerConfig, &timerAttribs, &xgip->XboxgipSysInitTimer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_XGIP, "WdfTimerCreate failed with status %!STATUS!", status); - return status; - } - - return STATUS_SUCCESS; -} - -VOID Xgip_GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) -{ - UCHAR XgipDescriptorData[XGIP_DESCRIPTOR_SIZE] = - { - 0x09, // bLength - 0x02, // bDescriptorType (Configuration) - 0x40, 0x00, // wTotalLength 64 - 0x02, // bNumInterfaces 2 - 0x01, // bConfigurationValue - 0x00, // iConfiguration (String Index) - 0xC0, // bmAttributes - 0xFA, // bMaxPower 500mA - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x00, // bInterfaceNumber 0 - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints 2 - 0xFF, // bInterfaceClass - 0x47, // bInterfaceSubClass - 0xD0, // bInterfaceProtocol - 0x00, // iInterface (String Index) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x81, // bEndpointAddress (IN/D2H) - 0x03, // bmAttributes (Interrupt) - 0x40, 0x00, // wMaxPacketSize 64 - 0x04, // bInterval 4 (unit depends on device speed) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x01, // bEndpointAddress (OUT/H2D) - 0x03, // bmAttributes (Interrupt) - 0x40, 0x00, // wMaxPacketSize 64 - 0x04, // bInterval 4 (unit depends on device speed) - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x01, // bInterfaceNumber 1 - 0x00, // bAlternateSetting - 0x00, // bNumEndpoints 0 - 0xFF, // bInterfaceClass - 0x47, // bInterfaceSubClass - 0xD0, // bInterfaceProtocol - 0x00, // iInterface (String Index) - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x01, // bInterfaceNumber 1 - 0x01, // bAlternateSetting - 0x02, // bNumEndpoints 2 - 0xFF, // bInterfaceClass - 0x47, // bInterfaceSubClass - 0xD0, // bInterfaceProtocol - 0x00, // iInterface (String Index) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x02, // bEndpointAddress (OUT/H2D) - 0x01, // bmAttributes (Isochronous, No Sync, Data EP) - 0xE0, 0x00, // wMaxPacketSize 224 - 0x01, // bInterval 1 (unit depends on device speed) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x83, // bEndpointAddress (IN/D2H) - 0x01, // bmAttributes (Isochronous, No Sync, Data EP) - 0x80, 0x00, // wMaxPacketSize 128 - 0x01, // bInterval 1 (unit depends on device speed) - - // 64 bytes - - // best guess: USB Standard Descriptor - }; - - RtlCopyBytes(Buffer, XgipDescriptorData, Length); -} - -VOID Xgip_GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor, PPDO_DEVICE_DATA pCommon) -{ - pDescriptor->bLength = 0x12; - pDescriptor->bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE; - pDescriptor->bcdUSB = 0x0200; // USB v2.0 - pDescriptor->bDeviceClass = 0xFF; - pDescriptor->bDeviceSubClass = 0x47; - pDescriptor->bDeviceProtocol = 0xD0; - pDescriptor->bMaxPacketSize0 = 0x40; - pDescriptor->idVendor = pCommon->VendorId; - pDescriptor->idProduct = pCommon->ProductId; - pDescriptor->bcdDevice = 0x0650; - pDescriptor->iManufacturer = 0x01; - pDescriptor->iProduct = 0x02; - pDescriptor->iSerialNumber = 0x03; - pDescriptor->bNumConfigurations = 0x01; -} - -VOID Xgip_SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo) -{ - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_XGIP, ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d", - (int)pInfo->Length, - (int)pInfo->InterfaceNumber, - (int)pInfo->AlternateSetting, - pInfo->NumberOfPipes); - - pInfo->Class = 0xFF; - pInfo->SubClass = 0x47; - pInfo->Protocol = 0xD0; - - pInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; - - pInfo->Pipes[0].MaximumTransferSize = 0x00400000; - pInfo->Pipes[0].MaximumPacketSize = 0x40; - pInfo->Pipes[0].EndpointAddress = 0x81; - pInfo->Pipes[0].Interval = 0x04; - pInfo->Pipes[0].PipeType = UsbdPipeTypeInterrupt; - pInfo->Pipes[0].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0081; - pInfo->Pipes[0].PipeFlags = 0x00; - - pInfo->Pipes[1].MaximumTransferSize = 0x00400000; - pInfo->Pipes[1].MaximumPacketSize = 0x40; - pInfo->Pipes[1].EndpointAddress = 0x01; - pInfo->Pipes[1].Interval = 0x04; - pInfo->Pipes[1].PipeType = UsbdPipeTypeInterrupt; - pInfo->Pipes[1].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0001; - pInfo->Pipes[1].PipeFlags = 0x00; - - pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_XGIP, ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d", - (int)pInfo->Length, - (int)pInfo->InterfaceNumber, - (int)pInfo->AlternateSetting, - pInfo->NumberOfPipes); - - pInfo->Class = 0xFF; - pInfo->SubClass = 0x47; - pInfo->Protocol = 0xD0; - - pInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; -} - -VOID Xgip_SysInitTimerFunc( - _In_ WDFTIMER Timer -) -{ - NTSTATUS status; - WDFDEVICE hChild; - PXGIP_DEVICE_DATA xgip; - WDFREQUEST usbRequest; - PIRP pendingIrp; - PIO_STACK_LOCATION irpStack; - WDFMEMORY mem; - - hChild = WdfTimerGetParentObject(Timer); - xgip = XgipGetData(hChild); - - if (xgip == NULL) return; - - // Is TRUE when collection is filled up - if (xgip->XboxgipSysInitReady) - { - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XGIP, "XBOXGIP ready, completing requests..."); - - // Get pending IN request - status = WdfIoQueueRetrieveNextRequest(xgip->PendingUsbInRequests, &usbRequest); - - if (NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XGIP, "Request found"); - - // Get top memory object - mem = (WDFMEMORY)WdfCollectionGetFirstItem(xgip->XboxgipSysInitCollection); - - // Get pending IRP - pendingIrp = WdfRequestWdmGetIrp(usbRequest); - irpStack = IoGetCurrentIrpStackLocation(pendingIrp); - - // Get USB request block - PURB urb = (PURB)irpStack->Parameters.Others.Argument1; - - // Get buffer size and content - size_t size; - PUCHAR Buffer = WdfMemoryGetBuffer(mem, &size); - - // Assign buffer size and content to URB - urb->UrbBulkOrInterruptTransfer.TransferBufferLength = (ULONG)size; - RtlCopyBytes(urb->UrbBulkOrInterruptTransfer.TransferBuffer, Buffer, size); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_XGIP, "[%X] Buffer length: %d", - ((PUCHAR)urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0], - urb->UrbBulkOrInterruptTransfer.TransferBufferLength); - - // Complete pending request - WdfRequestComplete(usbRequest, status); - - // Free memory from collection - WdfCollectionRemoveItem(xgip->XboxgipSysInitCollection, 0); - WdfObjectDelete(mem); - } - - // Stop timer when collection is purged - if (WdfCollectionGetCount(xgip->XboxgipSysInitCollection) == 0) - { - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XGIP, "Collection finished"); - - WdfTimerStop(xgip->XboxgipSysInitTimer, FALSE); - } - } -} - diff --git a/sys/xusb.c b/sys/xusb.c deleted file mode 100644 index 540ffd7..0000000 --- a/sys/xusb.c +++ /dev/null @@ -1,621 +0,0 @@ -/* -MIT License - -Copyright (c) 2016 Benjamin "Nefarius" Höglinger - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 "busenum.h" -#include "xusb.tmh" - -NTSTATUS Xusb_PreparePdo( - PWDFDEVICE_INIT DeviceInit, - USHORT VendorId, - USHORT ProductId, - PUNICODE_STRING DeviceId, - PUNICODE_STRING DeviceDescription) -{ - NTSTATUS status; - DECLARE_UNICODE_STRING_SIZE(buffer, MAX_HARDWARE_ID_LENGTH); - - // prepare device description - status = RtlUnicodeStringInit(DeviceDescription, L"Virtual Xbox 360 Controller"); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "RtlUnicodeStringInit failed with status %!STATUS!", - status); - return status; - } - - // Set hardware ID - RtlUnicodeStringPrintf(&buffer, L"USB\\VID_%04X&PID_%04X", VendorId, ProductId); - - RtlUnicodeStringCopy(DeviceId, &buffer); - - status = WdfPdoInitAddHardwareID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfPdoInitAddHardwareID failed with status %!STATUS!", - status); - return status; - } - - - // Set compatible IDs - RtlUnicodeStringInit(&buffer, L"USB\\MS_COMP_XUSB10"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfPdoInitAddCompatibleID #1 failed with status %!STATUS!", - status); - return status; - } - - RtlUnicodeStringInit(&buffer, L"USB\\Class_FF&SubClass_5D&Prot_01"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfPdoInitAddCompatibleID #2 failed with status %!STATUS!", - status); - return status; - } - - RtlUnicodeStringInit(&buffer, L"USB\\Class_FF&SubClass_5D"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfPdoInitAddCompatibleID #3 failed with status %!STATUS!", - status); - return status; - } - - RtlUnicodeStringInit(&buffer, L"USB\\Class_FF"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfPdoInitAddCompatibleID #4 failed with status %!STATUS!", - status); - return status; - } - - return STATUS_SUCCESS; -} - -NTSTATUS Xusb_PrepareHardware(WDFDEVICE Device) -{ - NTSTATUS status; - WDF_QUERY_INTERFACE_CONFIG ifaceCfg; - - INTERFACE dummyIface; - - dummyIface.Size = sizeof(INTERFACE); - dummyIface.Version = 1; - dummyIface.Context = (PVOID)Device; - - dummyIface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; - dummyIface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; - - /* XUSB.sys will query for the following three (unknown) interfaces - * BUT WONT USE IT so we just expose them to satisfy initialization. */ - - // Dummy 0 - - WDF_QUERY_INTERFACE_CONFIG_INIT(&ifaceCfg, (PINTERFACE)&dummyIface, &GUID_DEVINTERFACE_XUSB_UNKNOWN_0, NULL); - - status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "Couldn't register unknown interface GUID: %08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X " \ - "(WdfDeviceAddQueryInterface failed with status %!STATUS!)", - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data1, - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data2, - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data3, - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data4[0], - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data4[1], - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data4[2], - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data4[3], - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data4[4], - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data4[5], - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data4[6], - GUID_DEVINTERFACE_XUSB_UNKNOWN_0.Data4[7], - status); - - return status; - } - - // Dummy 1 - - WDF_QUERY_INTERFACE_CONFIG_INIT(&ifaceCfg, (PINTERFACE)&dummyIface, &GUID_DEVINTERFACE_XUSB_UNKNOWN_1, NULL); - - status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "Couldn't register unknown interface GUID: %08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X " \ - "(WdfDeviceAddQueryInterface failed with status %!STATUS!)", - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data1, - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data2, - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data3, - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data4[0], - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data4[1], - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data4[2], - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data4[3], - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data4[4], - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data4[5], - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data4[6], - GUID_DEVINTERFACE_XUSB_UNKNOWN_1.Data4[7], - status); - - return status; - } - - // Dummy 2 - - WDF_QUERY_INTERFACE_CONFIG_INIT(&ifaceCfg, (PINTERFACE)&dummyIface, &GUID_DEVINTERFACE_XUSB_UNKNOWN_2, NULL); - - status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "Couldn't register unknown interface GUID: %08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X " \ - "(WdfDeviceAddQueryInterface failed with status %!STATUS!)", - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data1, - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data2, - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data3, - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data4[0], - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data4[1], - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data4[2], - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data4[3], - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data4[4], - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data4[5], - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data4[6], - GUID_DEVINTERFACE_XUSB_UNKNOWN_2.Data4[7], - status); - - return status; - } - - // Expose USB_BUS_INTERFACE_USBDI_GUID - - // This interface actually IS used - USB_BUS_INTERFACE_USBDI_V1 xusbInterface; - - xusbInterface.Size = sizeof(USB_BUS_INTERFACE_USBDI_V1); - xusbInterface.Version = USB_BUSIF_USBDI_VERSION_1; - xusbInterface.BusContext = (PVOID)Device; - - xusbInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; - xusbInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; - - xusbInterface.SubmitIsoOutUrb = UsbPdo_SubmitIsoOutUrb; - xusbInterface.GetUSBDIVersion = UsbPdo_GetUSBDIVersion; - xusbInterface.QueryBusTime = UsbPdo_QueryBusTime; - xusbInterface.QueryBusInformation = UsbPdo_QueryBusInformation; - xusbInterface.IsDeviceHighSpeed = UsbPdo_IsDeviceHighSpeed; - - WDF_QUERY_INTERFACE_CONFIG_INIT(&ifaceCfg, (PINTERFACE)&xusbInterface, &USB_BUS_INTERFACE_USBDI_GUID, NULL); - - status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfDeviceAddQueryInterface failed with status %!STATUS!", - status); - return status; - } - - return STATUS_SUCCESS; -} - -NTSTATUS Xusb_AssignPdoContext(WDFDEVICE Device) -{ - NTSTATUS status; - WDF_OBJECT_ATTRIBUTES attributes; - - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = Device; - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XUSB, "Initializing XUSB context..."); - - PXUSB_DEVICE_DATA xusb = XusbGetData(Device); - - RtlZeroMemory(xusb, sizeof(XUSB_DEVICE_DATA)); - - // Is later overwritten by actual XInput slot - xusb->LedNumber = -1; - // Packet size (20 bytes = 0x14) - xusb->Packet.Size = 0x14; - - // I/O Queue for pending IRPs - WDF_IO_QUEUE_CONFIG holdingInQueueConfig; - - // Create and assign queue for unhandled interrupt requests - WDF_IO_QUEUE_CONFIG_INIT(&holdingInQueueConfig, WdfIoQueueDispatchManual); - - status = WdfIoQueueCreate(Device, &holdingInQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &xusb->HoldingUsbInRequests); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfIoQueueCreate (HoldingUsbInRequests) failed with status %!STATUS!", - status); - return status; - } - - return STATUS_SUCCESS; -} - -VOID Xusb_GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) -{ - UCHAR XusbDescriptorData[XUSB_DESCRIPTOR_SIZE] = - { - 0x09, // bLength - 0x02, // bDescriptorType (Configuration) - 0x99, 0x00, // wTotalLength 153 - 0x04, // bNumInterfaces 4 - 0x01, // bConfigurationValue - 0x00, // iConfiguration (String Index) - 0xA0, // bmAttributes Remote Wakeup - 0xFA, // bMaxPower 500mA - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x00, // bInterfaceNumber 0 - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints 2 - 0xFF, // bInterfaceClass - 0x5D, // bInterfaceSubClass - 0x01, // bInterfaceProtocol - 0x00, // iInterface (String Index) - - 0x11, // bLength - 0x21, // bDescriptorType (HID) - 0x00, 0x01, // bcdHID 1.00 - 0x01, // bCountryCode - 0x25, // bNumDescriptors - 0x81, // bDescriptorType[0] (Unknown 0x81) - 0x14, 0x00, // wDescriptorLength[0] 20 - 0x00, // bDescriptorType[1] (Unknown 0x00) - 0x00, 0x00, // wDescriptorLength[1] 0 - 0x13, // bDescriptorType[2] (Unknown 0x13) - 0x01, 0x08, // wDescriptorLength[2] 2049 - 0x00, // bDescriptorType[3] (Unknown 0x00) - 0x00, - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x81, // bEndpointAddress (IN/D2H) - 0x03, // bmAttributes (Interrupt) - 0x20, 0x00, // wMaxPacketSize 32 - 0x04, // bInterval 4 (unit depends on device speed) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x01, // bEndpointAddress (OUT/H2D) - 0x03, // bmAttributes (Interrupt) - 0x20, 0x00, // wMaxPacketSize 32 - 0x08, // bInterval 8 (unit depends on device speed) - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x01, // bInterfaceNumber 1 - 0x00, // bAlternateSetting - 0x04, // bNumEndpoints 4 - 0xFF, // bInterfaceClass - 0x5D, // bInterfaceSubClass - 0x03, // bInterfaceProtocol - 0x00, // iInterface (String Index) - - 0x1B, // bLength - 0x21, // bDescriptorType (HID) - 0x00, 0x01, // bcdHID 1.00 - 0x01, // bCountryCode - 0x01, // bNumDescriptors - 0x82, // bDescriptorType[0] (Unknown 0x82) - 0x40, 0x01, // wDescriptorLength[0] 320 - 0x02, 0x20, 0x16, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x82, // bEndpointAddress (IN/D2H) - 0x03, // bmAttributes (Interrupt) - 0x20, 0x00, // wMaxPacketSize 32 - 0x02, // bInterval 2 (unit depends on device speed) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x02, // bEndpointAddress (OUT/H2D) - 0x03, // bmAttributes (Interrupt) - 0x20, 0x00, // wMaxPacketSize 32 - 0x04, // bInterval 4 (unit depends on device speed) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x83, // bEndpointAddress (IN/D2H) - 0x03, // bmAttributes (Interrupt) - 0x20, 0x00, // wMaxPacketSize 32 - 0x40, // bInterval 64 (unit depends on device speed) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x03, // bEndpointAddress (OUT/H2D) - 0x03, // bmAttributes (Interrupt) - 0x20, 0x00, // wMaxPacketSize 32 - 0x10, // bInterval 16 (unit depends on device speed) - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x02, // bInterfaceNumber 2 - 0x00, // bAlternateSetting - 0x01, // bNumEndpoints 1 - 0xFF, // bInterfaceClass - 0x5D, // bInterfaceSubClass - 0x02, // bInterfaceProtocol - 0x00, // iInterface (String Index) - - 0x09, // bLength - 0x21, // bDescriptorType (HID) - 0x00, 0x01, // bcdHID 1.00 - 0x01, // bCountryCode - 0x22, // bNumDescriptors - 0x84, // bDescriptorType[0] (Unknown 0x84) - 0x07, 0x00, // wDescriptorLength[0] 7 - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x84, // bEndpointAddress (IN/D2H) - 0x03, // bmAttributes (Interrupt) - 0x20, 0x00, // wMaxPacketSize 32 - 0x10, // bInterval 16 (unit depends on device speed) - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x03, // bInterfaceNumber 3 - 0x00, // bAlternateSetting - 0x00, // bNumEndpoints 0 - 0xFF, // bInterfaceClass - 0xFD, // bInterfaceSubClass - 0x13, // bInterfaceProtocol - 0x04, // iInterface (String Index) - - 0x06, // bLength - 0x41, // bDescriptorType (Unknown) - 0x00, 0x01, 0x01, 0x03, - // 153 bytes - - // best guess: USB Standard Descriptor - }; - - RtlCopyBytes(Buffer, XusbDescriptorData, Length); -} - -VOID Xusb_GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor, PPDO_DEVICE_DATA pCommon) -{ - pDescriptor->bLength = 0x12; - pDescriptor->bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE; - pDescriptor->bcdUSB = 0x0200; // USB v2.0 - pDescriptor->bDeviceClass = 0xFF; - pDescriptor->bDeviceSubClass = 0xFF; - pDescriptor->bDeviceProtocol = 0xFF; - pDescriptor->bMaxPacketSize0 = 0x08; - pDescriptor->idVendor = pCommon->VendorId; - pDescriptor->idProduct = pCommon->ProductId; - pDescriptor->bcdDevice = 0x0114; - pDescriptor->iManufacturer = 0x01; - pDescriptor->iProduct = 0x02; - pDescriptor->iSerialNumber = 0x03; - pDescriptor->bNumConfigurations = 0x01; -} - -VOID Xusb_SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo) -{ - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_XUSB, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d", - (int)pInfo->Length, - (int)pInfo->InterfaceNumber, - (int)pInfo->AlternateSetting, - pInfo->NumberOfPipes); - - pInfo->Class = 0xFF; - pInfo->SubClass = 0x5D; - pInfo->Protocol = 0x01; - - pInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; - - pInfo->Pipes[0].MaximumTransferSize = 0x00400000; - pInfo->Pipes[0].MaximumPacketSize = 0x20; - pInfo->Pipes[0].EndpointAddress = 0x81; - pInfo->Pipes[0].Interval = 0x04; - pInfo->Pipes[0].PipeType = 0x03; - pInfo->Pipes[0].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0081; - pInfo->Pipes[0].PipeFlags = 0x00; - - pInfo->Pipes[1].MaximumTransferSize = 0x00400000; - pInfo->Pipes[1].MaximumPacketSize = 0x20; - pInfo->Pipes[1].EndpointAddress = 0x01; - pInfo->Pipes[1].Interval = 0x08; - pInfo->Pipes[1].PipeType = 0x03; - pInfo->Pipes[1].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0001; - pInfo->Pipes[1].PipeFlags = 0x00; - - pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length); - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_XUSB, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d", - (int)pInfo->Length, - (int)pInfo->InterfaceNumber, - (int)pInfo->AlternateSetting, - pInfo->NumberOfPipes); - - pInfo->Class = 0xFF; - pInfo->SubClass = 0x5D; - pInfo->Protocol = 0x03; - - pInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; - - pInfo->Pipes[0].MaximumTransferSize = 0x00400000; - pInfo->Pipes[0].MaximumPacketSize = 0x20; - pInfo->Pipes[0].EndpointAddress = 0x82; - pInfo->Pipes[0].Interval = 0x04; - pInfo->Pipes[0].PipeType = 0x03; - pInfo->Pipes[0].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0082; - pInfo->Pipes[0].PipeFlags = 0x00; - - pInfo->Pipes[1].MaximumTransferSize = 0x00400000; - pInfo->Pipes[1].MaximumPacketSize = 0x20; - pInfo->Pipes[1].EndpointAddress = 0x02; - pInfo->Pipes[1].Interval = 0x08; - pInfo->Pipes[1].PipeType = 0x03; - pInfo->Pipes[1].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0002; - pInfo->Pipes[1].PipeFlags = 0x00; - - pInfo->Pipes[2].MaximumTransferSize = 0x00400000; - pInfo->Pipes[2].MaximumPacketSize = 0x20; - pInfo->Pipes[2].EndpointAddress = 0x83; - pInfo->Pipes[2].Interval = 0x08; - pInfo->Pipes[2].PipeType = 0x03; - pInfo->Pipes[2].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0083; - pInfo->Pipes[2].PipeFlags = 0x00; - - pInfo->Pipes[3].MaximumTransferSize = 0x00400000; - pInfo->Pipes[3].MaximumPacketSize = 0x20; - pInfo->Pipes[3].EndpointAddress = 0x03; - pInfo->Pipes[3].Interval = 0x08; - pInfo->Pipes[3].PipeType = 0x03; - pInfo->Pipes[3].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0003; - pInfo->Pipes[3].PipeFlags = 0x00; - - pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length); - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_XUSB, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d", - (int)pInfo->Length, - (int)pInfo->InterfaceNumber, - (int)pInfo->AlternateSetting, - pInfo->NumberOfPipes); - - pInfo->Class = 0xFF; - pInfo->SubClass = 0x5D; - pInfo->Protocol = 0x02; - - pInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; - - pInfo->Pipes[0].MaximumTransferSize = 0x00400000; - pInfo->Pipes[0].MaximumPacketSize = 0x20; - pInfo->Pipes[0].EndpointAddress = 0x84; - pInfo->Pipes[0].Interval = 0x04; - pInfo->Pipes[0].PipeType = 0x03; - pInfo->Pipes[0].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0084; - pInfo->Pipes[0].PipeFlags = 0x00; - - pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length); - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_XUSB, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d", - (int)pInfo->Length, - (int)pInfo->InterfaceNumber, - (int)pInfo->AlternateSetting, - pInfo->NumberOfPipes); - - pInfo->Class = 0xFF; - pInfo->SubClass = 0xFD; - pInfo->Protocol = 0x13; - - pInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; -} - -NTSTATUS Xusb_GetUserIndex(WDFDEVICE Device, PXUSB_GET_USER_INDEX Request) -{ - NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; - WDFDEVICE hChild; - PPDO_DEVICE_DATA pdoData; - CHAR userIndex; - - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_XUSB, "%!FUNC! Entry"); - - hChild = Bus_GetPdo(Device, Request->SerialNo); - - // Validate child - if (hChild == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "Bus_GetPdo for serial %d failed", Request->SerialNo); - return STATUS_NO_SUCH_DEVICE; - } - - // Check common context - pdoData = PdoGetData(hChild); - if (pdoData == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "PdoGetData failed"); - return STATUS_INVALID_PARAMETER; - } - - // Check if caller owns this PDO - if (!IS_OWNER(pdoData)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "PID mismatch: %d != %d", - pdoData->OwnerProcessId, - CURRENT_PROCESS_ID()); - return STATUS_ACCESS_DENIED; - } - - userIndex = XusbGetData(hChild)->LedNumber; - - if (userIndex >= 0) - { - Request->UserIndex = (ULONG)userIndex; - status = STATUS_SUCCESS; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XUSB, "%!FUNC! Exit with status %!STATUS!", status); - - return status; -} From 65e2779a1b3bddea38f12657ff3d9c31769259ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 25 Aug 2018 22:30:28 +0200 Subject: [PATCH 002/107] Fixed build script --- .nuke | 2 +- build/.build.csproj.dotsettings | 23 ------------- build/Build.cs | 58 +++------------------------------ 3 files changed, 5 insertions(+), 78 deletions(-) delete mode 100644 build/.build.csproj.dotsettings diff --git a/.nuke b/.nuke index 4d60562..a9c2c79 100644 --- a/.nuke +++ b/.nuke @@ -1 +1 @@ -ViGEmBus.sln \ No newline at end of file +ViGEmClient.sln \ No newline at end of file diff --git a/build/.build.csproj.dotsettings b/build/.build.csproj.dotsettings deleted file mode 100644 index ea35790..0000000 --- a/build/.build.csproj.dotsettings +++ /dev/null @@ -1,23 +0,0 @@ - - False - Implicit - Implicit - ExpressionBody - 0 - NEXT_LINE - True - NEVER - False - WRAP_IF_LONG - True - False - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - True - True - True - True - True - True - True - True diff --git a/build/Build.cs b/build/Build.cs index e3801fd..6dd1cf9 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Linq; using Nuke.Common; using Nuke.Common.Git; @@ -17,11 +16,13 @@ class Build : NukeBuild [Solution] readonly Solution Solution; [GitRepository] readonly GitRepository GitRepository; + AbsolutePath SourceDirectory => RootDirectory / "src"; AbsolutePath ArtifactsDirectory => RootDirectory / "artifacts"; Target Clean => _ => _ .Executes(() => { + DeleteDirectories(GlobDirectories(SourceDirectory, "**/bin", "**/obj")); EnsureCleanDirectory(ArtifactsDirectory); }); @@ -31,13 +32,7 @@ class Build : NukeBuild { MSBuild(s => s .SetTargetPath(SolutionFile) - .SetTargets("Restore") - .SetTargetPlatform(MSBuildTargetPlatform.x64)); - - MSBuild(s => s - .SetTargetPath(SolutionFile) - .SetTargets("Restore") - .SetTargetPlatform(MSBuildTargetPlatform.x86)); + .SetTargets("Restore")); }); Target Compile => _ => _ @@ -49,52 +44,7 @@ class Build : NukeBuild .SetTargets("Rebuild") .SetConfiguration(Configuration) .SetMaxCpuCount(Environment.ProcessorCount) - .SetNodeReuse(IsLocalBuild) - .SetTargetPlatform(MSBuildTargetPlatform.x64)); - - MSBuild(s => s - .SetTargetPath(SolutionFile) - .SetTargets("Rebuild") - .SetConfiguration(Configuration) - .SetMaxCpuCount(Environment.ProcessorCount) - .SetNodeReuse(IsLocalBuild) - .SetTargetPlatform(MSBuildTargetPlatform.x86)); - - #region Ugly hack, fix me! - EnsureExistingDirectory(Path.Combine(ArtifactsDirectory, @"x64")); - EnsureExistingDirectory(Path.Combine(ArtifactsDirectory, @"x86")); - - File.Copy( - Path.Combine(WorkingDirectory, @"bin\x64\ViGEmBus.inf"), - Path.Combine(ArtifactsDirectory, @"ViGEmBus.inf") - ); - - File.Copy( - Path.Combine(WorkingDirectory, @"bin\x64\ViGEmBus.pdb"), - Path.Combine(ArtifactsDirectory, @"x64\ViGEmBus.pdb") - ); - File.Copy( - Path.Combine(WorkingDirectory, @"bin\x64\ViGEmBus\ViGEmBus.sys"), - Path.Combine(ArtifactsDirectory, @"x64\ViGEmBus.sys") - ); - File.Copy( - Path.Combine(WorkingDirectory, @"bin\x64\ViGEmBus\WdfCoinstaller01009.dll"), - Path.Combine(ArtifactsDirectory, @"x64\WdfCoinstaller01009.dll") - ); - - File.Copy( - Path.Combine(WorkingDirectory, @"bin\x86\ViGEmBus.pdb"), - Path.Combine(ArtifactsDirectory, @"x86\ViGEmBus.pdb") - ); - File.Copy( - Path.Combine(WorkingDirectory, @"bin\x86\ViGEmBus\ViGEmBus.sys"), - Path.Combine(ArtifactsDirectory, @"x86\ViGEmBus.sys") - ); - File.Copy( - Path.Combine(WorkingDirectory, @"bin\x86\ViGEmBus\WdfCoinstaller01009.dll"), - Path.Combine(ArtifactsDirectory, @"x86\WdfCoinstaller01009.dll") - ); - #endregion + .SetNodeReuse(IsLocalBuild)); }); private Target Pack => _ => _ From dbe15963982d4462aca3d00a56a575f770df12ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 25 Aug 2018 22:30:37 +0200 Subject: [PATCH 003/107] Fixed solution settings --- .gitignore | 5 ++ ViGEmClient.sln | 154 +++++++++++++----------------------------------- 2 files changed, 46 insertions(+), 113 deletions(-) diff --git a/.gitignore b/.gitignore index 2fb2a52..077a52e 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,8 @@ /artifacts /.vs/ViGEmBus/DesignTimeBuild /build/obj +/.vs/ViGEmClient +/src/Release (static) +/src/x64/Debug (static) +/src/x64/Release (dynamic) +/src/x64/Release (static) diff --git a/ViGEmClient.sln b/ViGEmClient.sln index eaf1d95..f46c223 100644 --- a/ViGEmClient.sln +++ b/ViGEmClient.sln @@ -5,124 +5,52 @@ VisualStudioVersion = 15.0.27130.2024 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ViGEmClient", "src\ViGEmClient.vcxproj", "{7DB06674-1F4F-464B-8E1C-172E9587F9DC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{148E5E2E-2613-4EA5-AB8F-D93747E927E3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{A11CD588-F74A-41B5-9E5B-E60937052009}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug (dynamic)|ARM = Debug (dynamic)|ARM - Debug (dynamic)|ARM64 = Debug (dynamic)|ARM64 - Debug (dynamic)|x64 = Debug (dynamic)|x64 - Debug (dynamic)|x86 = Debug (dynamic)|x86 - Debug (static)|ARM = Debug (static)|ARM - Debug (static)|ARM64 = Debug (static)|ARM64 - Debug (static)|x64 = Debug (static)|x64 - Debug (static)|x86 = Debug (static)|x86 - Debug|ARM = Debug|ARM - Debug|ARM64 = Debug|ARM64 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release (dynamic)|ARM = Release (dynamic)|ARM - Release (dynamic)|ARM64 = Release (dynamic)|ARM64 - Release (dynamic)|x64 = Release (dynamic)|x64 - Release (dynamic)|x86 = Release (dynamic)|x86 - Release (static)|ARM = Release (static)|ARM - Release (static)|ARM64 = Release (static)|ARM64 - Release (static)|x64 = Release (static)|x64 - Release (static)|x86 = Release (static)|x86 - Release|ARM = Release|ARM - Release|ARM64 = Release|ARM64 - Release|x64 = Release|x64 - Release|x86 = Release|x86 + Debug_DLL|x64 = Debug_DLL|x64 + Debug_DLL|x86 = Debug_DLL|x86 + Debug_LIB|x64 = Debug_LIB|x64 + Debug_LIB|x86 = Debug_LIB|x86 + Release_DLL|x64 = Release_DLL|x64 + Release_DLL|x86 = Release_DLL|x86 + Release_LIB|x64 = Release_LIB|x64 + Release_LIB|x86 = Release_LIB|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (dynamic)|ARM.ActiveCfg = Debug (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (dynamic)|ARM64.ActiveCfg = Debug (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (dynamic)|x64.ActiveCfg = Debug (dynamic)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (dynamic)|x64.Build.0 = Debug (dynamic)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (dynamic)|x86.ActiveCfg = Debug (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (dynamic)|x86.Build.0 = Debug (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (static)|ARM.ActiveCfg = Debug (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (static)|ARM64.ActiveCfg = Debug (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (static)|x64.ActiveCfg = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (static)|x64.Build.0 = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (static)|x86.ActiveCfg = Debug (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug (static)|x86.Build.0 = Debug (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|ARM.ActiveCfg = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|ARM.Build.0 = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|ARM64.ActiveCfg = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|ARM64.Build.0 = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x64.ActiveCfg = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x64.Build.0 = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x86.ActiveCfg = Debug (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x86.Build.0 = Debug (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (dynamic)|ARM.ActiveCfg = Release (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (dynamic)|ARM64.ActiveCfg = Release (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (dynamic)|x64.ActiveCfg = Release (dynamic)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (dynamic)|x64.Build.0 = Release (dynamic)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (dynamic)|x86.ActiveCfg = Release (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (dynamic)|x86.Build.0 = Release (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (static)|ARM.ActiveCfg = Release (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (static)|ARM64.ActiveCfg = Release (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (static)|x64.Build.0 = Release (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (static)|x86.ActiveCfg = Release (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release (static)|x86.Build.0 = Release (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|ARM.ActiveCfg = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|ARM.Build.0 = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|ARM64.ActiveCfg = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|ARM64.Build.0 = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x64.ActiveCfg = Release (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x64.Build.0 = Release (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x86.ActiveCfg = Release (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x86.Build.0 = Release (static)|Win32 - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (dynamic)|ARM.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (dynamic)|ARM.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (dynamic)|ARM64.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (dynamic)|ARM64.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (dynamic)|x64.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (dynamic)|x64.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (dynamic)|x86.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (dynamic)|x86.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (static)|ARM.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (static)|ARM.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (static)|ARM64.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (static)|ARM64.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (static)|x64.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (static)|x64.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (static)|x86.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug (static)|x86.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug|ARM.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug|ARM.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug|ARM64.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug|x64.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug|x64.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug|x86.ActiveCfg = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Debug|x86.Build.0 = Debug|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (dynamic)|ARM.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (dynamic)|ARM.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (dynamic)|ARM64.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (dynamic)|ARM64.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (dynamic)|x64.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (dynamic)|x64.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (dynamic)|x86.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (dynamic)|x86.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (static)|ARM.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (static)|ARM.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (static)|ARM64.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (static)|ARM64.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (static)|x64.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (static)|x64.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (static)|x86.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release (static)|x86.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release|ARM.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release|ARM.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release|ARM64.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release|ARM64.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release|x64.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release|x64.Build.0 = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release|x86.ActiveCfg = Release|Any CPU - {148E5E2E-2613-4EA5-AB8F-D93747E927E3}.Release|x86.Build.0 = Release|Any CPU + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x64.ActiveCfg = Debug (dynamic)|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x64.Build.0 = Debug (dynamic)|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x86.ActiveCfg = Debug (dynamic)|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x86.Build.0 = Debug (dynamic)|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x64.ActiveCfg = Debug (static)|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x64.Build.0 = Debug (static)|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x86.ActiveCfg = Debug (static)|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x86.Build.0 = Debug (static)|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x64.ActiveCfg = Release (dynamic)|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x64.Build.0 = Release (dynamic)|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x86.ActiveCfg = Release (dynamic)|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x86.Build.0 = Release (dynamic)|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x64.ActiveCfg = Release (static)|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x64.Build.0 = Release (static)|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x86.ActiveCfg = Release (static)|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x86.Build.0 = Release (static)|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 From c22d46fb1dd31119cac83029831f048eeb54a54f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 25 Aug 2018 22:31:16 +0200 Subject: [PATCH 004/107] Fixed appveyor.yml --- appveyor.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 7d45ec5..c10822d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,18 +2,6 @@ version: 1.16.{build}.0 image: Visual Studio 2017 build_script: - ps: .\build.ps1 -configuration release -after_build: -- ps: | - Invoke-WebRequest "https://downloads.vigem.org/other/pavel-a/ddverpatch/verpatch-1.0.15.1-x86-codeplex.zip" -OutFile verpatch-1.0.15.1-x86-codeplex.zip - Expand-Archive verpatch-1.0.15.1-x86-codeplex.zip -DestinationPath . - .\verpatch.exe .\artifacts\x64\ViGEmBus.sys "$env:APPVEYOR_BUILD_VERSION" - .\verpatch.exe .\artifacts\x64\ViGEmBus.sys /pv "$env:APPVEYOR_BUILD_VERSION" - .\verpatch.exe .\artifacts\x86\ViGEmBus.sys "$env:APPVEYOR_BUILD_VERSION" - .\verpatch.exe .\artifacts\x86\ViGEmBus.sys /pv "$env:APPVEYOR_BUILD_VERSION" - makecab.exe /f ViGEmBus.ddf -artifacts: -- path: disk1\ViGEmBus.cab - name: ViGEmBus_unsigned_x86_amd64 deploy: - provider: Environment name: BUILDBOT From 8601e6a29920808c684243456444c6470b867528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 25 Aug 2018 22:35:30 +0200 Subject: [PATCH 005/107] Corrected build configuration name --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index c10822d..02f1487 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ version: 1.16.{build}.0 image: Visual Studio 2017 build_script: -- ps: .\build.ps1 -configuration release +- ps: .\build.ps1 -configuration Release_DLL deploy: - provider: Environment name: BUILDBOT From bd6c370bdc7b29a1a6ffefa770a7bb0bb28f65b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 25 Aug 2018 22:45:41 +0200 Subject: [PATCH 006/107] Fixed README.md --- README.md | 65 +++---------------------------------------------------- 1 file changed, 3 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 047c5eb..a6c97c3 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,9 @@ # ViGEm Bus Driver -Windows kernel-mode driver emulating well-known USB game controllers. +Developer SDK for communication with `ViGEmBus`. -[![Build status](https://ci.appveyor.com/api/projects/status/rv74ufluwib52dq2?svg=true -)](https://ci.appveyor.com/project/nefarius/indicium-supra) [![Discord](https://img.shields.io/discord/346756263763378176.svg)](https://discord.gg/QTJpBX5) [![Website](https://img.shields.io/website-up-down-green-red/https/vigem.org.svg?label=ViGEm.org)](https://vigem.org/) [![PayPal Donate](https://img.shields.io/badge/paypal-donate-blue.svg)]() [![Support on Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)]() [![GitHub followers](https://img.shields.io/github/followers/nefarius.svg?style=social&label=Follow)](https://github.com/nefarius) [![Twitter Follow](https://img.shields.io/twitter/follow/nefariusmaximus.svg?style=social&label=Follow)](https://twitter.com/nefariusmaximus) +[![Build status](https://ci.appveyor.com/api/projects/status/k806d3m2egjr0j56?svg=true)](https://ci.appveyor.com/project/nefarius/vigemclient) [![Discord](https://img.shields.io/discord/346756263763378176.svg)](https://discord.gg/QTJpBX5) [![Website](https://img.shields.io/website-up-down-green-red/https/vigem.org.svg?label=ViGEm.org)](https://vigem.org/) [![PayPal Donate](https://img.shields.io/badge/paypal-donate-blue.svg)]() [![Support on Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)]() [![GitHub followers](https://img.shields.io/github/followers/nefarius.svg?style=social&label=Follow)](https://github.com/nefarius) [![Twitter Follow](https://img.shields.io/twitter/follow/nefariusmaximus.svg?style=social&label=Follow)](https://twitter.com/nefariusmaximus) ## About -**Disclaimer:** this project is for software developers. To make it do something useful you'll also need a [feeder application](). -The `ViGEmBus` driver and `ViGEmClient` libraries represent the core of the Virtual Gamepad Emulation Framework (or `ViGEm` , for short). `ViGEm` aims for a 100% accurate [emulation]() of well-known gaming peripherals as pure software-based devices at kernel level. As it mimics "the real thing" games and other processes require no additional modification whatsoever to detect `ViGEm`-based devices (no Proxy-DLLs or API-Hooking) and simply work out of the box. While the (now obsolete) [Scarlett.Crush Productions Virtual Bus Driver]() is the spiritual father of this project, `ViGEm` has been designed and written from the ground up utilizing Microsoft's [Kernel-Mode Driver Framework](https://en.wikipedia.org/wiki/Kernel-Mode_Driver_Framework). - -### Emulated devices -Currently supports emulation of the following USB Gamepads: -- [Microsoft Xbox 360 Controller](https://en.wikipedia.org/wiki/Xbox_360_controller) -- [Sony DualShock 4 Controller](https://en.wikipedia.org/wiki/DualShock#DualShock_4) - -## Use cases -A few examples of the most common use cases for `ViGEm` are: - * You have an unsupported input device you'd like to use within games without modifying said game. - * You want the freedom to use a different controller of your choice in [PS4 Remote Play](). - * You encountered a game not compatible with [x360ce](). - * You want to extend the reach of your input device (like send traffic to a different machine over a network). - * You want to test/benchmark your game and need a replay mechanism for your user inputs. - * You want to work around player slot assignment order issues in `XInput`. - -## Supported Systems -The driver is built for Windows 7/8/8.1/10 (x86 and amd64). - -## How to build - -### Prerequisites - - Visual Studio **2017** ([Community Edition](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) is just fine) - - [WDK for Windows 10, version 1803](https://developer.microsoft.com/en-us/windows/hardware/windows-driver-kit) - - You can either build directly within Visual Studio or in PowerShell by running the build script: - - ``` - .\build.ps1 -configuration release - ``` - - Do bear in mind that you'll need to sign the driver to use it without [test mode](). - -## Installation -To grab the latest signed binaries for use or redistribution [follow the installation instructions](). - -### Necessary preparations for Windows 7 -Before installing the bus driver on Windows 7 (x86 or x64) the following 3rd party software has to be installed: - * [Xbox 360 Accessories Software 1.2](https://www.microsoft.com/accessories/en-us/products/gaming/xbox-360-controller-for-windows/52a-00004#techspecs-connect) (contains the missing device drivers) - * [Microsoft Security Advisory 3033929 Update](https://technet.microsoft.com/en-us/library/security/3033929) has to be installed to support the drivers signature. Download links: - * [Security Update for Windows 7 (KB3033929)](https://www.microsoft.com/en-us/download/details.aspx?id=46078) - * [Security Update for Windows 7 for x64-based Systems (KB3033929)](https://www.microsoft.com/en-us/download/details.aspx?id=46148) - -## Sponsors - - [3dRudder](https://www.3drudder.com/) - - [Wohlfeil.IT e.U.](https://wohlfeil.it/) - - [Parsec](https://parsecgaming.com/) - - [Rainway, Inc](https://rainway.io/) - -## Known users of ViGEm - - [3dRudder](https://www.3drudder.com/) - - [Parsec](https://parsecgaming.com/) - - [GloSC](https://github.com/Alia5/GloSC) - - [UCR](https://github.com/Snoothy/UCR) - - [InputMapper](https://inputmapper.com/) - - [Oculus VR, LLC.](https://www.oculus.com/) - - [Rainway, Inc](https://rainway.io/) - - [WiimoteHook](https://forum.cemu.info/showthread.php/140-WiimoteHook-Nintendo-Wii-Remote-with-Motion-Rumble-and-Nunchuk-support) +TBD \ No newline at end of file From 8129b70df71211497baef8b44b0f5e95a5f0e2e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 25 Aug 2018 22:46:49 +0200 Subject: [PATCH 007/107] Corrected title in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a6c97c3..2deb2b0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ViGEm Bus Driver +# ViGEm Client Native SDK Developer SDK for communication with `ViGEmBus`. From 4eec42f32defb55830c03e8e7a8bdd3078c494a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 25 Aug 2018 23:02:38 +0200 Subject: [PATCH 008/107] Fixed include path when referenced as submodule --- src/ViGEmClient.vcxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index 3c9995f..e883acc 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -129,28 +129,28 @@ - $(SolutionDir)Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); From 47e28ccd3aa440d859339b5542d7be5df690e4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 25 Aug 2018 23:08:46 +0200 Subject: [PATCH 009/107] Fixed output directory on dynamic build --- src/ViGEmClient.vcxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index e883acc..54035fd 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -133,24 +133,28 @@ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)bin\$(Platform)\ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)bin\$(Platform)\ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)bin\$(Platform)\ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)bin\$(Platform)\ From f9e92ca2fd301a84a0bf192876517ef938db854e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 26 Aug 2018 14:04:29 +0200 Subject: [PATCH 010/107] Added error code VIGEM_ERROR_BUS_INVALID_HANDLE Added some more NULL-pointer checks Minor refactoring --- include/ViGEmClient.h | 3 +- src/ViGEmClient.cpp | 235 ++++++++++++++++++++++++++++++------------ 2 files changed, 171 insertions(+), 67 deletions(-) diff --git a/include/ViGEmClient.h b/include/ViGEmClient.h index 51bd7e0..e7fc502 100644 --- a/include/ViGEmClient.h +++ b/include/ViGEmClient.h @@ -61,7 +61,8 @@ extern "C" { VIGEM_ERROR_BUS_ACCESS_FAILED = 0xE0000009, VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED = 0xE0000010, VIGEM_ERROR_CALLBACK_NOT_FOUND = 0xE0000011, - VIGEM_ERROR_BUS_ALREADY_CONNECTED = 0xE0000012 + VIGEM_ERROR_BUS_ALREADY_CONNECTED = 0xE0000012, + VIGEM_ERROR_BUS_INVALID_HANDLE = 0xE0000013 } VIGEM_ERROR; /** diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index b3214bb..24f84d4 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -25,14 +25,14 @@ SOFTWARE. #define WIN32_LEAN_AND_MEAN #include -#include +#include #include #include #include "km/ViGEmBusShared.h" #include "ViGEmClient.h" #include -#include +#include #include #define VIGEM_TARGETS_MAX USHRT_MAX @@ -92,7 +92,10 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT( PVIGEM_CLIENT vigem_alloc() { - auto driver = static_cast(malloc(sizeof(VIGEM_CLIENT))); + const auto driver = static_cast(malloc(sizeof(VIGEM_CLIENT))); + + if (!driver) + return nullptr; RtlZeroMemory(driver, sizeof(VIGEM_CLIENT)); driver->hBusDevice = INVALID_HANDLE_VALUE; @@ -108,6 +111,9 @@ void vigem_free(PVIGEM_CLIENT vigem) VIGEM_ERROR vigem_connect(PVIGEM_CLIENT vigem) { + if (!vigem) + return VIGEM_ERROR_BUS_INVALID_HANDLE; + SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { 0 }; deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); DWORD memberIndex = 0; @@ -120,20 +126,38 @@ VIGEM_ERROR vigem_connect(PVIGEM_CLIENT vigem) return VIGEM_ERROR_BUS_ALREADY_CONNECTED; } - auto deviceInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_BUSENUM_VIGEM, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + const auto deviceInfoSet = SetupDiGetClassDevs( + &GUID_DEVINTERFACE_BUSENUM_VIGEM, + nullptr, + nullptr, + DIGCF_PRESENT | DIGCF_DEVICEINTERFACE + ); // enumerate device instances - while (SetupDiEnumDeviceInterfaces(deviceInfoSet, nullptr, &GUID_DEVINTERFACE_BUSENUM_VIGEM, memberIndex++, &deviceInterfaceData)) + while (SetupDiEnumDeviceInterfaces( + deviceInfoSet, + nullptr, + &GUID_DEVINTERFACE_BUSENUM_VIGEM, + memberIndex++, + &deviceInterfaceData + )) { // get required target buffer size SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, nullptr, 0, &requiredSize, nullptr); // allocate target buffer - auto detailDataBuffer = static_cast(malloc(requiredSize)); + const auto detailDataBuffer = static_cast(malloc(requiredSize)); detailDataBuffer->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // get detail buffer - if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, detailDataBuffer, requiredSize, &requiredSize, nullptr)) + if (!SetupDiGetDeviceInterfaceDetail( + deviceInfoSet, + &deviceInterfaceData, + detailDataBuffer, + requiredSize, + &requiredSize, + nullptr + )) { SetupDiDestroyDeviceInfoList(deviceInfoSet); free(detailDataBuffer); @@ -142,13 +166,15 @@ VIGEM_ERROR vigem_connect(PVIGEM_CLIENT vigem) } // bus found, open it - vigem->hBusDevice = CreateFile(detailDataBuffer->DevicePath, + vigem->hBusDevice = CreateFile( + detailDataBuffer->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED, - nullptr); + nullptr + ); // check bus open result if (vigem->hBusDevice == INVALID_HANDLE_VALUE) @@ -166,7 +192,16 @@ VIGEM_ERROR vigem_connect(PVIGEM_CLIENT vigem) VIGEM_CHECK_VERSION_INIT(&version, VIGEM_COMMON_VERSION); // send compiled library version to driver to check compatibility - DeviceIoControl(vigem->hBusDevice, IOCTL_VIGEM_CHECK_VERSION, &version, version.Size, nullptr, 0, &transfered, &lOverlapped); + DeviceIoControl( + vigem->hBusDevice, + IOCTL_VIGEM_CHECK_VERSION, + &version, + version.Size, + nullptr, + 0, + &transfered, + &lOverlapped + ); // wait for result if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) != 0) @@ -190,6 +225,9 @@ VIGEM_ERROR vigem_connect(PVIGEM_CLIENT vigem) void vigem_disconnect(PVIGEM_CLIENT vigem) { + if (!vigem) + return; + if (vigem->hBusDevice != INVALID_HANDLE_VALUE) { CloseHandle(vigem->hBusDevice); @@ -201,7 +239,10 @@ void vigem_disconnect(PVIGEM_CLIENT vigem) PVIGEM_TARGET vigem_target_x360_alloc(void) { - auto target = VIGEM_TARGET_ALLOC_INIT(Xbox360Wired); + const auto target = VIGEM_TARGET_ALLOC_INIT(Xbox360Wired); + + if (!target) + return nullptr; target->VendorId = 0x045E; target->ProductId = 0x028E; @@ -211,7 +252,10 @@ PVIGEM_TARGET vigem_target_x360_alloc(void) PVIGEM_TARGET vigem_target_ds4_alloc(void) { - auto target = VIGEM_TARGET_ALLOC_INIT(DualShock4Wired); + const auto target = VIGEM_TARGET_ALLOC_INIT(DualShock4Wired); + + if (!target) + return nullptr; target->VendorId = 0x054C; target->ProductId = 0x05C4; @@ -227,20 +271,20 @@ void vigem_target_free(PVIGEM_TARGET target) VIGEM_ERROR vigem_target_add(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) { + if (!vigem) + return VIGEM_ERROR_BUS_INVALID_HANDLE; + + if (!target) + return VIGEM_ERROR_INVALID_TARGET; + if (vigem->hBusDevice == nullptr) - { return VIGEM_ERROR_BUS_NOT_FOUND; - } if (target->State == VIGEM_TARGET_NEW) - { return VIGEM_ERROR_TARGET_UNINITIALIZED; - } if (target->State == VIGEM_TARGET_CONNECTED) - { return VIGEM_ERROR_ALREADY_CONNECTED; - } DWORD transfered = 0; VIGEM_PLUGIN_TARGET plugin; @@ -254,7 +298,16 @@ VIGEM_ERROR vigem_target_add(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) plugin.VendorId = target->VendorId; plugin.ProductId = target->ProductId; - DeviceIoControl(vigem->hBusDevice, IOCTL_VIGEM_PLUGIN_TARGET, &plugin, plugin.Size, nullptr, 0, &transfered, &lOverlapped); + DeviceIoControl( + vigem->hBusDevice, + IOCTL_VIGEM_PLUGIN_TARGET, + &plugin, + plugin.Size, + nullptr, + 0, + &transfered, + &lOverlapped + ); if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) != 0) { @@ -272,20 +325,20 @@ VIGEM_ERROR vigem_target_add(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) VIGEM_ERROR vigem_target_add_async(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PFN_VIGEM_TARGET_ADD_RESULT result) { + if (!vigem) + return VIGEM_ERROR_BUS_INVALID_HANDLE; + + if (!target) + return VIGEM_ERROR_INVALID_TARGET; + if (vigem->hBusDevice == nullptr) - { return VIGEM_ERROR_BUS_NOT_FOUND; - } if (target->State == VIGEM_TARGET_NEW) - { return VIGEM_ERROR_TARGET_UNINITIALIZED; - } if (target->State == VIGEM_TARGET_CONNECTED) - { return VIGEM_ERROR_ALREADY_CONNECTED; - } std::thread _async{ []( PVIGEM_TARGET _Target, @@ -332,20 +385,20 @@ VIGEM_ERROR vigem_target_add_async(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PF VIGEM_ERROR vigem_target_remove(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) { + if (!vigem) + return VIGEM_ERROR_BUS_INVALID_HANDLE; + + if (!target) + return VIGEM_ERROR_INVALID_TARGET; + if (vigem->hBusDevice == nullptr) - { return VIGEM_ERROR_BUS_NOT_FOUND; - } if (target->State == VIGEM_TARGET_NEW) - { return VIGEM_ERROR_TARGET_UNINITIALIZED; - } if (target->State != VIGEM_TARGET_CONNECTED) - { return VIGEM_ERROR_TARGET_NOT_PLUGGED_IN; - } DWORD transfered = 0; VIGEM_UNPLUG_TARGET unplug; @@ -354,16 +407,22 @@ VIGEM_ERROR vigem_target_remove(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) VIGEM_UNPLUG_TARGET_INIT(&unplug, target->SerialNo); - DeviceIoControl(vigem->hBusDevice, IOCTL_VIGEM_UNPLUG_TARGET, &unplug, unplug.Size, nullptr, 0, &transfered, &lOverlapped); + DeviceIoControl( + vigem->hBusDevice, + IOCTL_VIGEM_UNPLUG_TARGET, + &unplug, + unplug.Size, + nullptr, + 0, + &transfered, + &lOverlapped + ); if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) != 0) { target->State = VIGEM_TARGET_DISCONNECTED; CloseHandle(lOverlapped.hEvent); - //g_xusbCallbacks.erase(Target->SerialNo); - //g_ds4Callbacks.erase(Target->SerialNo); - return VIGEM_ERROR_NONE; } @@ -372,22 +431,26 @@ VIGEM_ERROR vigem_target_remove(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) return VIGEM_ERROR_REMOVAL_FAILED; } -VIGEM_ERROR vigem_target_x360_register_notification(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PFN_VIGEM_X360_NOTIFICATION notification) +VIGEM_ERROR vigem_target_x360_register_notification( + PVIGEM_CLIENT vigem, + PVIGEM_TARGET target, + PFN_VIGEM_X360_NOTIFICATION notification +) { + if (!vigem) + return VIGEM_ERROR_BUS_INVALID_HANDLE; + + if (!target) + return VIGEM_ERROR_INVALID_TARGET; + if (vigem->hBusDevice == nullptr) - { return VIGEM_ERROR_BUS_NOT_FOUND; - } if (target->SerialNo == 0 || notification == nullptr) - { return VIGEM_ERROR_INVALID_TARGET; - } if (target->Notification == reinterpret_cast(notification)) - { return VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED; - } target->Notification = reinterpret_cast(notification); @@ -444,22 +507,26 @@ VIGEM_ERROR vigem_target_x360_register_notification(PVIGEM_CLIENT vigem, PVIGEM_ return VIGEM_ERROR_NONE; } -VIGEM_ERROR vigem_target_ds4_register_notification(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PFN_VIGEM_DS4_NOTIFICATION notification) +VIGEM_ERROR vigem_target_ds4_register_notification( + PVIGEM_CLIENT vigem, + PVIGEM_TARGET target, + PFN_VIGEM_DS4_NOTIFICATION notification +) { + if (!vigem) + return VIGEM_ERROR_BUS_INVALID_HANDLE; + + if (!target) + return VIGEM_ERROR_INVALID_TARGET; + if (vigem->hBusDevice == nullptr) - { return VIGEM_ERROR_BUS_NOT_FOUND; - } if (target->SerialNo == 0 || notification == nullptr) - { return VIGEM_ERROR_INVALID_TARGET; - } if (target->Notification == reinterpret_cast(notification)) - { return VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED; - } target->Notification = reinterpret_cast(notification); @@ -546,17 +613,23 @@ USHORT vigem_target_get_pid(PVIGEM_TARGET target) return target->ProductId; } -VIGEM_ERROR vigem_target_x360_update(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, XUSB_REPORT report) +VIGEM_ERROR vigem_target_x360_update( + PVIGEM_CLIENT vigem, + PVIGEM_TARGET target, + XUSB_REPORT report +) { + if (!vigem) + return VIGEM_ERROR_BUS_INVALID_HANDLE; + + if (!target) + return VIGEM_ERROR_INVALID_TARGET; + if (vigem->hBusDevice == nullptr) - { return VIGEM_ERROR_BUS_NOT_FOUND; - } if (target->SerialNo == 0) - { return VIGEM_ERROR_INVALID_TARGET; - } DWORD transfered = 0; OVERLAPPED lOverlapped = { 0 }; @@ -567,7 +640,16 @@ VIGEM_ERROR vigem_target_x360_update(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, xsr.Report = report; - DeviceIoControl(vigem->hBusDevice, IOCTL_XUSB_SUBMIT_REPORT, &xsr, xsr.Size, nullptr, 0, &transfered, &lOverlapped); + DeviceIoControl( + vigem->hBusDevice, + IOCTL_XUSB_SUBMIT_REPORT, + &xsr, + xsr.Size, + nullptr, + 0, + &transfered, + &lOverlapped + ); if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) == 0) { @@ -583,17 +665,23 @@ VIGEM_ERROR vigem_target_x360_update(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, return VIGEM_ERROR_NONE; } -VIGEM_ERROR vigem_target_ds4_update(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, DS4_REPORT report) +VIGEM_ERROR vigem_target_ds4_update( + PVIGEM_CLIENT vigem, + PVIGEM_TARGET target, + DS4_REPORT report +) { + if (!vigem) + return VIGEM_ERROR_BUS_INVALID_HANDLE; + + if (!target) + return VIGEM_ERROR_INVALID_TARGET; + if (vigem->hBusDevice == nullptr) - { return VIGEM_ERROR_BUS_NOT_FOUND; - } if (target->SerialNo == 0) - { return VIGEM_ERROR_INVALID_TARGET; - } DWORD transfered = 0; OVERLAPPED lOverlapped = { 0 }; @@ -604,7 +692,16 @@ VIGEM_ERROR vigem_target_ds4_update(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, D dsr.Report = report; - DeviceIoControl(vigem->hBusDevice, IOCTL_DS4_SUBMIT_REPORT, &dsr, dsr.Size, nullptr, 0, &transfered, &lOverlapped); + DeviceIoControl( + vigem->hBusDevice, + IOCTL_DS4_SUBMIT_REPORT, + &dsr, + dsr.Size, + nullptr, + 0, + &transfered, + &lOverlapped + ); if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) == 0) { @@ -635,17 +732,23 @@ BOOL vigem_target_is_attached(PVIGEM_TARGET target) return (target->State == VIGEM_TARGET_CONNECTED); } -VIGEM_ERROR vigem_target_x360_get_user_index(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PULONG index) +VIGEM_ERROR vigem_target_x360_get_user_index( + PVIGEM_CLIENT vigem, + PVIGEM_TARGET target, + PULONG index +) { + if (!vigem) + return VIGEM_ERROR_BUS_INVALID_HANDLE; + + if (!target) + return VIGEM_ERROR_INVALID_TARGET; + if (vigem->hBusDevice == nullptr) - { return VIGEM_ERROR_BUS_NOT_FOUND; - } if (target->SerialNo == 0 || target->Type != Xbox360Wired) - { return VIGEM_ERROR_INVALID_TARGET; - } DWORD transfered = 0; OVERLAPPED lOverlapped = { 0 }; From 8bd4ee866975df599b41ecba24df7e76e3c788e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 26 Aug 2018 14:20:48 +0200 Subject: [PATCH 011/107] Added error code VIGEM_ERROR_XUSB_USERINDEX_OUT_OF_RANGE --- .gitignore | 1 + include/ViGEmClient.h | 3 +- src/ViGEmClient.cpp | 119 +++++++++++++++++++++++------------------- 3 files changed, 67 insertions(+), 56 deletions(-) diff --git a/.gitignore b/.gitignore index 077a52e..1539f3d 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ /src/x64/Debug (static) /src/x64/Release (dynamic) /src/x64/Release (static) +*.TMP diff --git a/include/ViGEmClient.h b/include/ViGEmClient.h index e7fc502..a0f9647 100644 --- a/include/ViGEmClient.h +++ b/include/ViGEmClient.h @@ -62,7 +62,8 @@ extern "C" { VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED = 0xE0000010, VIGEM_ERROR_CALLBACK_NOT_FOUND = 0xE0000011, VIGEM_ERROR_BUS_ALREADY_CONNECTED = 0xE0000012, - VIGEM_ERROR_BUS_INVALID_HANDLE = 0xE0000013 + VIGEM_ERROR_BUS_INVALID_HANDLE = 0xE0000013, + VIGEM_ERROR_XUSB_USERINDEX_OUT_OF_RANGE = 0xE0000014 } VIGEM_ERROR; /** diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 24f84d4..24fed98 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -127,18 +127,18 @@ VIGEM_ERROR vigem_connect(PVIGEM_CLIENT vigem) } const auto deviceInfoSet = SetupDiGetClassDevs( - &GUID_DEVINTERFACE_BUSENUM_VIGEM, - nullptr, - nullptr, + &GUID_DEVINTERFACE_BUSENUM_VIGEM, + nullptr, + nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE ); // enumerate device instances while (SetupDiEnumDeviceInterfaces( - deviceInfoSet, - nullptr, - &GUID_DEVINTERFACE_BUSENUM_VIGEM, - memberIndex++, + deviceInfoSet, + nullptr, + &GUID_DEVINTERFACE_BUSENUM_VIGEM, + memberIndex++, &deviceInterfaceData )) { @@ -151,11 +151,11 @@ VIGEM_ERROR vigem_connect(PVIGEM_CLIENT vigem) // get detail buffer if (!SetupDiGetDeviceInterfaceDetail( - deviceInfoSet, - &deviceInterfaceData, - detailDataBuffer, - requiredSize, - &requiredSize, + deviceInfoSet, + &deviceInterfaceData, + detailDataBuffer, + requiredSize, + &requiredSize, nullptr )) { @@ -193,13 +193,13 @@ VIGEM_ERROR vigem_connect(PVIGEM_CLIENT vigem) // send compiled library version to driver to check compatibility DeviceIoControl( - vigem->hBusDevice, - IOCTL_VIGEM_CHECK_VERSION, - &version, - version.Size, - nullptr, - 0, - &transfered, + vigem->hBusDevice, + IOCTL_VIGEM_CHECK_VERSION, + &version, + version.Size, + nullptr, + 0, + &transfered, &lOverlapped ); @@ -299,13 +299,13 @@ VIGEM_ERROR vigem_target_add(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) plugin.ProductId = target->ProductId; DeviceIoControl( - vigem->hBusDevice, - IOCTL_VIGEM_PLUGIN_TARGET, + vigem->hBusDevice, + IOCTL_VIGEM_PLUGIN_TARGET, &plugin, - plugin.Size, - nullptr, - 0, - &transfered, + plugin.Size, + nullptr, + 0, + &transfered, &lOverlapped ); @@ -408,13 +408,13 @@ VIGEM_ERROR vigem_target_remove(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) VIGEM_UNPLUG_TARGET_INIT(&unplug, target->SerialNo); DeviceIoControl( - vigem->hBusDevice, - IOCTL_VIGEM_UNPLUG_TARGET, - &unplug, + vigem->hBusDevice, + IOCTL_VIGEM_UNPLUG_TARGET, + &unplug, unplug.Size, - nullptr, - 0, - &transfered, + nullptr, + 0, + &transfered, &lOverlapped ); @@ -432,8 +432,8 @@ VIGEM_ERROR vigem_target_remove(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) } VIGEM_ERROR vigem_target_x360_register_notification( - PVIGEM_CLIENT vigem, - PVIGEM_TARGET target, + PVIGEM_CLIENT vigem, + PVIGEM_TARGET target, PFN_VIGEM_X360_NOTIFICATION notification ) { @@ -508,8 +508,8 @@ VIGEM_ERROR vigem_target_x360_register_notification( } VIGEM_ERROR vigem_target_ds4_register_notification( - PVIGEM_CLIENT vigem, - PVIGEM_TARGET target, + PVIGEM_CLIENT vigem, + PVIGEM_TARGET target, PFN_VIGEM_DS4_NOTIFICATION notification ) { @@ -614,8 +614,8 @@ USHORT vigem_target_get_pid(PVIGEM_TARGET target) } VIGEM_ERROR vigem_target_x360_update( - PVIGEM_CLIENT vigem, - PVIGEM_TARGET target, + PVIGEM_CLIENT vigem, + PVIGEM_TARGET target, XUSB_REPORT report ) { @@ -641,13 +641,13 @@ VIGEM_ERROR vigem_target_x360_update( xsr.Report = report; DeviceIoControl( - vigem->hBusDevice, - IOCTL_XUSB_SUBMIT_REPORT, - &xsr, - xsr.Size, - nullptr, - 0, - &transfered, + vigem->hBusDevice, + IOCTL_XUSB_SUBMIT_REPORT, + &xsr, + xsr.Size, + nullptr, + 0, + &transfered, &lOverlapped ); @@ -666,8 +666,8 @@ VIGEM_ERROR vigem_target_x360_update( } VIGEM_ERROR vigem_target_ds4_update( - PVIGEM_CLIENT vigem, - PVIGEM_TARGET target, + PVIGEM_CLIENT vigem, + PVIGEM_TARGET target, DS4_REPORT report ) { @@ -693,13 +693,13 @@ VIGEM_ERROR vigem_target_ds4_update( dsr.Report = report; DeviceIoControl( - vigem->hBusDevice, + vigem->hBusDevice, IOCTL_DS4_SUBMIT_REPORT, - &dsr, - dsr.Size, - nullptr, - 0, - &transfered, + &dsr, + dsr.Size, + nullptr, + 0, + &transfered, &lOverlapped ); @@ -733,8 +733,8 @@ BOOL vigem_target_is_attached(PVIGEM_TARGET target) } VIGEM_ERROR vigem_target_x360_get_user_index( - PVIGEM_CLIENT vigem, - PVIGEM_TARGET target, + PVIGEM_CLIENT vigem, + PVIGEM_TARGET target, PULONG index ) { @@ -770,11 +770,20 @@ VIGEM_ERROR vigem_target_x360_get_user_index( if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) == 0) { - if (GetLastError() == ERROR_ACCESS_DENIED) + const auto error = GetLastError(); + + if (error == ERROR_ACCESS_DENIED) { CloseHandle(lOverlapped.hEvent); return VIGEM_ERROR_INVALID_TARGET; } + + // TODO: handle userindex out-of-range situation here + //if (error == ???) + //{ + // CloseHandle(lOverlapped.hEvent); + // return VIGEM_ERROR_XUSB_USERINDEX_OUT_OF_RANGE; + //} } CloseHandle(lOverlapped.hEvent); From c0f72dedcffafa891e069cb54ae9b15b6b2021f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 26 Aug 2018 15:58:53 +0200 Subject: [PATCH 012/107] Corrected resource language to English --- src/ViGEmClient.rc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ViGEmClient.rc b/src/ViGEmClient.rc index 7ae36a9..352d7ba 100644 --- a/src/ViGEmClient.rc +++ b/src/ViGEmClient.rc @@ -17,6 +17,7 @@ #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEA) LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN +#pragma code_page(1252) #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -64,21 +65,21 @@ VS_VERSION_INFO VERSIONINFO BEGIN BLOCK "StringFileInfo" BEGIN - BLOCK "0c0704b0" + BLOCK "000904b0" BEGIN VALUE "CompanyName", "Benjamin Höglinger-Stelzer" VALUE "FileDescription", "Virtual Gamepad Emulation User-Mode Library" -VALUE "FileVersion", "1.14.3.0" + VALUE "FileVersion", "1.14.3.0" VALUE "InternalName", "Virtual Gamepad Emulation User-Mode Library" VALUE "LegalCopyright", "Copyright (C) Benjamin Höglinger-Stelzer 2017" VALUE "OriginalFilename", "ViGEmCli.lib" VALUE "ProductName", "Virtual Gamepad Emulation User-Mode Library" -VALUE "ProductVersion", "1.14.3.0" + VALUE "ProductVersion", "1.14.3.0" END END BLOCK "VarFileInfo" BEGIN - VALUE "Translation", 0xc07, 1200 + VALUE "Translation", 0x9, 1200 END END From 7e6ccb7815f2e4189f9c3f2e2d4645ac85e6e173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 2 Sep 2018 16:32:43 +0200 Subject: [PATCH 013/107] Refactored build configuration names Updated .gitignore --- .gitignore | 5 +++ ViGEmClient.sln | 32 +++++++------- src/ViGEmClient.vcxproj | 96 ++++++++++++++++++++--------------------- 3 files changed, 69 insertions(+), 64 deletions(-) diff --git a/.gitignore b/.gitignore index 1539f3d..19ebddc 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,8 @@ /src/x64/Release (dynamic) /src/x64/Release (static) *.TMP +/src/Debug_LIB +/src/x64/Debug_LIB +/x64/Debug_LIB +/Debug_LIB +*.aps diff --git a/ViGEmClient.sln b/ViGEmClient.sln index f46c223..44670ff 100644 --- a/ViGEmClient.sln +++ b/ViGEmClient.sln @@ -19,22 +19,22 @@ Global Release_LIB|x86 = Release_LIB|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x64.ActiveCfg = Debug (dynamic)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x64.Build.0 = Debug (dynamic)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x86.ActiveCfg = Debug (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x86.Build.0 = Debug (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x64.ActiveCfg = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x64.Build.0 = Debug (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x86.ActiveCfg = Debug (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x86.Build.0 = Debug (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x64.ActiveCfg = Release (dynamic)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x64.Build.0 = Release (dynamic)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x86.ActiveCfg = Release (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x86.Build.0 = Release (dynamic)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x64.ActiveCfg = Release (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x64.Build.0 = Release (static)|x64 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x86.ActiveCfg = Release (static)|Win32 - {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x86.Build.0 = Release (static)|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x64.ActiveCfg = Debug_DLL|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x64.Build.0 = Debug_DLL|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x86.ActiveCfg = Debug_DLL|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x86.Build.0 = Debug_DLL|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x64.ActiveCfg = Debug_LIB|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x64.Build.0 = Debug_LIB|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x86.ActiveCfg = Debug_LIB|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x86.Build.0 = Debug_LIB|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x64.ActiveCfg = Release_DLL|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x64.Build.0 = Release_DLL|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x86.ActiveCfg = Release_DLL|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x86.Build.0 = Release_DLL|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x64.ActiveCfg = Release_LIB|x64 + {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 diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index 54035fd..543fb2b 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -1,36 +1,36 @@  - - Debug (dynamic) + + Debug_DLL Win32 - - Debug (dynamic) + + Debug_DLL x64 - - Debug (static) + + Debug_LIB Win32 - - Release (dynamic) + + Release_DLL Win32 - - Release (dynamic) + + Release_DLL x64 - - Release (static) + + Release_LIB Win32 - - Debug (static) + + Debug_LIB x64 - - Release (static) + + Release_LIB x64 @@ -46,52 +46,52 @@ $(WindowsTargetPlatformVersion) - + StaticLibrary true v141 Unicode - + DynamicLibrary true v141 Unicode - + StaticLibrary false v141 true Unicode - + DynamicLibrary false v141 true Unicode - + StaticLibrary true v141 Unicode - + DynamicLibrary true v141 Unicode - + StaticLibrary false v141 true Unicode - + DynamicLibrary false v141 @@ -103,60 +103,60 @@ - + - + - + - + - + - + - + - + - + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); $(SolutionDir)bin\$(Platform)\ - + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); $(SolutionDir)bin\$(Platform)\ - + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); $(SolutionDir)bin\$(Platform)\ - + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - + $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); $(SolutionDir)bin\$(Platform)\ - + @@ -169,7 +169,7 @@ Windows - + @@ -183,7 +183,7 @@ setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - + @@ -196,7 +196,7 @@ Windows - + @@ -210,7 +210,7 @@ setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - + Level3 @@ -227,7 +227,7 @@ true - + Level3 @@ -245,7 +245,7 @@ setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - + Level3 @@ -262,7 +262,7 @@ true - + Level3 From af43119d7faaac5f9d8fef84f266ce84cab7f7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 2 Sep 2018 16:37:09 +0200 Subject: [PATCH 014/107] Corrected runtime library settings --- .gitignore | 4 ++++ src/ViGEmClient.vcxproj | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 19ebddc..0b18a8b 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,7 @@ /x64/Debug_LIB /Debug_LIB *.aps +/Release_LIB +/src/Release_LIB +/src/x64/Release_LIB +/x64/Release_LIB diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index 543fb2b..e087262 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -164,6 +164,7 @@ Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true + MultiThreadedDebug Windows @@ -191,6 +192,7 @@ Disabled _DEBUG;_LIB;%(PreprocessorDefinitions) true + MultiThreadedDebug Windows @@ -220,6 +222,7 @@ true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true + MultiThreaded Windows @@ -255,6 +258,7 @@ true NDEBUG;_LIB;%(PreprocessorDefinitions) true + MultiThreaded Windows From c3f459704c08a1bff4eaf7ac20f7fe0617159e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 2 Sep 2018 20:12:24 +0200 Subject: [PATCH 015/107] Added build instructions --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2deb2b0..fd54a2b 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,17 @@ Developer SDK for communication with `ViGEmBus`. ## About -TBD \ No newline at end of file +TBD + +## How to build + +### Prerequisites + +- Visual Studio **2017** ([Community Edition](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) is just fine) +- [.NET Core SDK 2.1](https://www.microsoft.com/net/download/dotnet-core/2.1) (or greater, required for building only) + +You can either build directly within Visual Studio or in PowerShell by running the build script: + +```PowerShell +.\build.ps1 -configuration release +``` From 3579f08f0110803d8368061d33c1b39e86ff6e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 12:44:28 +0200 Subject: [PATCH 016/107] Updated nuke to 0.8.0 Excluded build project from solution --- ViGEmClient.sln | 8 -------- build/_build.csproj | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/ViGEmClient.sln b/ViGEmClient.sln index 44670ff..8e022b6 100644 --- a/ViGEmClient.sln +++ b/ViGEmClient.sln @@ -36,21 +36,13 @@ Global {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/build/_build.csproj b/build/_build.csproj index 3ce5270..68dd6c9 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -10,7 +10,7 @@ - + From 69df51911c09ef4d6262948b69aa12580e434892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 13:47:29 +0200 Subject: [PATCH 017/107] Fixed warning LNK4068: /MACHINE not specified; defaulting to X64 --- .gitignore | 10 ++++------ build/Build.cs | 11 ++++++++++- src/ViGEmClient.vcxproj | 12 ++++++++---- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 0b18a8b..76e53a4 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ /.vs/ViGEmBus/v15 /build/bin/Release /build/obj/Release -/lib/x64 +/lib /packages /sys/x64/Release /x64/Release @@ -19,9 +19,8 @@ /build/bin/Debug /build/obj/Debug /bin -/sys/x64/Debug -/x64/Debug -/x64/Debug (static) +/sys/x64 +/x64 *.user /.vs/config /sys/RCa21300 @@ -43,5 +42,4 @@ *.aps /Release_LIB /src/Release_LIB -/src/x64/Release_LIB -/x64/Release_LIB +/src/x64 diff --git a/build/Build.cs b/build/Build.cs index 6dd1cf9..0986df4 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -44,7 +44,16 @@ class Build : NukeBuild .SetTargets("Rebuild") .SetConfiguration(Configuration) .SetMaxCpuCount(Environment.ProcessorCount) - .SetNodeReuse(IsLocalBuild)); + .SetNodeReuse(IsLocalBuild) + .SetTargetPlatform(MSBuildTargetPlatform.x64)); + + MSBuild(s => s + .SetTargetPath(SolutionFile) + .SetTargets("Rebuild") + .SetConfiguration(Configuration) + .SetMaxCpuCount(Environment.ProcessorCount) + .SetNodeReuse(IsLocalBuild) + .SetTargetPlatform(MSBuildTargetPlatform.x86)); }); private Target Pack => _ => _ diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index e087262..bd1aa62 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -130,31 +130,35 @@ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)lib\debug\$(PlatformShortName)\ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)bin\$(Platform)\ + $(SolutionDir)bin\debug\$(PlatformShortName)\ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)lib\release\$(PlatformShortName)\ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)bin\$(Platform)\ + $(SolutionDir)bin\release\$(PlatformShortName)\ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)lib\debug\$(PlatformShortName)\ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)bin\$(Platform)\ + $(SolutionDir)bin\debug\$(PlatformShortName)\ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)lib\release\$(PlatformShortName)\ $(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - $(SolutionDir)bin\$(Platform)\ + $(SolutionDir)bin\release\$(PlatformShortName)\ From 9e91a124d179bf26a878a952153042ac871da243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 13:51:31 +0200 Subject: [PATCH 018/107] Forgot to save :) --- src/ViGEmClient.vcxproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index bd1aa62..517d690 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -173,6 +173,9 @@ Windows + + MachineX86 + @@ -233,6 +236,9 @@ true true + + MachineX86 + From c739f8ef9043a35ab1ebbd3a60ee0bdf45828144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 14:21:04 +0200 Subject: [PATCH 019/107] Refactored include directory structure to comply with cmake/vcpkg --- include/{ViGEmClient.h => ViGEm/Client.h} | 2 +- include/{ViGEmCommon.h => ViGEm/Common.h} | 0 include/{ViGEmUtil.h => ViGEm/Util.h} | 0 .../ViGEmBusShared.h => ViGEm/km/BusShared.h} | 2 +- src/ViGEmClient.cpp | 4 ++-- src/ViGEmClient.vcxproj | 8 ++++---- src/ViGEmClient.vcxproj.filters | 17 ++++++++++------- 7 files changed, 18 insertions(+), 15 deletions(-) rename include/{ViGEmClient.h => ViGEm/Client.h} (99%) rename include/{ViGEmCommon.h => ViGEm/Common.h} (100%) rename include/{ViGEmUtil.h => ViGEm/Util.h} (100%) rename include/{km/ViGEmBusShared.h => ViGEm/km/BusShared.h} (99%) diff --git a/include/ViGEmClient.h b/include/ViGEm/Client.h similarity index 99% rename from include/ViGEmClient.h rename to include/ViGEm/Client.h index a0f9647..c490c95 100644 --- a/include/ViGEmClient.h +++ b/include/ViGEm/Client.h @@ -30,7 +30,7 @@ SOFTWARE. extern "C" { #endif -#include "ViGEmCommon.h" +#include "ViGEm/Common.h" #ifdef VIGEM_DYNAMIC #ifdef VIGEM_EXPORTS diff --git a/include/ViGEmCommon.h b/include/ViGEm/Common.h similarity index 100% rename from include/ViGEmCommon.h rename to include/ViGEm/Common.h diff --git a/include/ViGEmUtil.h b/include/ViGEm/Util.h similarity index 100% rename from include/ViGEmUtil.h rename to include/ViGEm/Util.h diff --git a/include/km/ViGEmBusShared.h b/include/ViGEm/km/BusShared.h similarity index 99% rename from include/km/ViGEmBusShared.h rename to include/ViGEm/km/BusShared.h index 941da48..7fb9663 100644 --- a/include/km/ViGEmBusShared.h +++ b/include/ViGEm/km/BusShared.h @@ -30,7 +30,7 @@ DEFINE_GUID(GUID_DEVINTERFACE_BUSENUM_VIGEM, #pragma once -#include "ViGEmCommon.h" +#include "ViGEm/Common.h" // // Common version for user-mode library and driver compatibility diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 24fed98..28373a4 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -29,8 +29,8 @@ SOFTWARE. #include #include -#include "km/ViGEmBusShared.h" -#include "ViGEmClient.h" +#include "ViGEm/km/BusShared.h" +#include "ViGEm/Client.h" #include #include #include diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index 517d690..5b16b05 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -295,10 +295,10 @@ - - - - + + + + diff --git a/src/ViGEmClient.vcxproj.filters b/src/ViGEmClient.vcxproj.filters index b783fc4..e4d4823 100644 --- a/src/ViGEmClient.vcxproj.filters +++ b/src/ViGEmClient.vcxproj.filters @@ -13,22 +13,25 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {3355fb06-3745-4161-8c61-b8bca15ff8fa} + Header Files - + Header Files - - Header Files + + Header Files\ViGEm - - Header Files + + Header Files\ViGEm - - Header Files + + Header Files\ViGEm From a7018a373c007245e87aa5a025f24b037797b411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 16:05:28 +0200 Subject: [PATCH 020/107] Added vcpkg ports file --- vcpkg/ports/vigemclient/CONTROL | 3 +++ vcpkg/ports/vigemclient/portfile.cmake | 34 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 vcpkg/ports/vigemclient/CONTROL create mode 100644 vcpkg/ports/vigemclient/portfile.cmake diff --git a/vcpkg/ports/vigemclient/CONTROL b/vcpkg/ports/vigemclient/CONTROL new file mode 100644 index 0000000..acd552d --- /dev/null +++ b/vcpkg/ports/vigemclient/CONTROL @@ -0,0 +1,3 @@ +Source: vigemclient +Version: 1.16.13.0 +Description: ViGEm Client SDK for feeder development diff --git a/vcpkg/ports/vigemclient/portfile.cmake b/vcpkg/ports/vigemclient/portfile.cmake new file mode 100644 index 0000000..df3690f --- /dev/null +++ b/vcpkg/ports/vigemclient/portfile.cmake @@ -0,0 +1,34 @@ +include(vcpkg_common_functions) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO ViGEm/ViGEmClient + REF v1.16.18.0 + SHA512 7628b91197a9db42c7e6641ef4ac6aeb1854d199312b0a6ac3fbfe281354495e8f597865000b90c12ad36575aaf7a3da34da04a6efa8bb64bb9d47878640ac2c + HEAD_REF master +) + +if (VCPKG_LIBRARY_LINKAGE STREQUAL dynamic) + vcpkg_install_msbuild( + SOURCE_PATH ${SOURCE_PATH} + PROJECT_SUBPATH "src/ViGEmClient.vcxproj" + INCLUDES_SUBPATH "include" + PLATFORM ${VCPKG_TARGET_ARCHITECTURE} + RELEASE_CONFIGURATION Release_DLL + DEBUG_CONFIGURATION Debug_DLL + USE_VCPKG_INTEGRATION + ALLOW_ROOT_INCLUDES) +elseif (VCPKG_LIBRARY_LINKAGE STREQUAL static) + vcpkg_install_msbuild( + SOURCE_PATH ${SOURCE_PATH} + PROJECT_SUBPATH "src/ViGEmClient.vcxproj" + INCLUDES_SUBPATH "include" + PLATFORM ${VCPKG_TARGET_ARCHITECTURE} + RELEASE_CONFIGURATION Release_LIB + DEBUG_CONFIGURATION Debug_LIB + USE_VCPKG_INTEGRATION + ALLOW_ROOT_INCLUDES) +endif() + +# Handle copyright +file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/vigemclient RENAME copyright) From 5522b8ae32cdfa246e86a0e96702ce45ce8010fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 20:48:47 +0200 Subject: [PATCH 021/107] Updated appveyor.yml to use vcpkg --- appveyor.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 02f1487..47bf999 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,12 @@ version: 1.16.{build}.0 image: Visual Studio 2017 +install: +- ps: Copy-Item "$env:APPVEYOR_BUILD_FOLDER\\vcpkg\\ports\\vigemclient" "c:\\tools\\vcpkg\\ports" build_script: -- ps: .\build.ps1 -configuration Release_DLL +- cmd: "vcpkg build vigemclient:x64-windows" +- cmd: "vcpkg build vigemclient:x64-windows-static" +- cmd: "vcpkg build vigemclient:x86-windows" +- cmd: "vcpkg build vigemclient:x86-windows-static" deploy: - provider: Environment name: BUILDBOT From b7eff7e771674a80a784106c499ff1c06f0dac62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 21:03:52 +0200 Subject: [PATCH 022/107] Test --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 47bf999..f941a33 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,6 +3,7 @@ image: Visual Studio 2017 install: - ps: Copy-Item "$env:APPVEYOR_BUILD_FOLDER\\vcpkg\\ports\\vigemclient" "c:\\tools\\vcpkg\\ports" build_script: +- ps: Write-Host "$env:APPVEYOR_BUILD_FOLDER\\vcpkg\\ports\\vigemclient" - cmd: "vcpkg build vigemclient:x64-windows" - cmd: "vcpkg build vigemclient:x64-windows-static" - cmd: "vcpkg build vigemclient:x86-windows" From f704b3eb9f90346b867c3dd446b61c9834471ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 21:11:50 +0200 Subject: [PATCH 023/107] Boop --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f941a33..9371d23 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,9 @@ version: 1.16.{build}.0 image: Visual Studio 2017 install: -- ps: Copy-Item "$env:APPVEYOR_BUILD_FOLDER\\vcpkg\\ports\\vigemclient" "c:\\tools\\vcpkg\\ports" +- ps: Copy-Item "$env:APPVEYOR_BUILD_FOLDER\vcpkg\ports\vigemclient" "c:\tools\vcpkg\ports" build_script: -- ps: Write-Host "$env:APPVEYOR_BUILD_FOLDER\\vcpkg\\ports\\vigemclient" +- ps: ls "c:\tools\vcpkg\ports" - cmd: "vcpkg build vigemclient:x64-windows" - cmd: "vcpkg build vigemclient:x64-windows-static" - cmd: "vcpkg build vigemclient:x86-windows" From 0684093224876527d3314c5dad0725df6f644aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 21:21:03 +0200 Subject: [PATCH 024/107] Derp --- appveyor.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 9371d23..5959ae2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,11 +3,10 @@ image: Visual Studio 2017 install: - ps: Copy-Item "$env:APPVEYOR_BUILD_FOLDER\vcpkg\ports\vigemclient" "c:\tools\vcpkg\ports" build_script: -- ps: ls "c:\tools\vcpkg\ports" -- cmd: "vcpkg build vigemclient:x64-windows" -- cmd: "vcpkg build vigemclient:x64-windows-static" -- cmd: "vcpkg build vigemclient:x86-windows" -- cmd: "vcpkg build vigemclient:x86-windows-static" +- ps: "vcpkg build vigemclient:x64-windows" +- ps: "vcpkg build vigemclient:x64-windows-static" +- ps: "vcpkg build vigemclient:x86-windows" +- ps: "vcpkg build vigemclient:x86-windows-static" deploy: - provider: Environment name: BUILDBOT From aa8684ed433c6aabc3d22ba0bce772d4ee5c978f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 21:24:33 +0200 Subject: [PATCH 025/107] Work pls --- appveyor.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 5959ae2..cf1a0d3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,11 +2,13 @@ version: 1.16.{build}.0 image: Visual Studio 2017 install: - ps: Copy-Item "$env:APPVEYOR_BUILD_FOLDER\vcpkg\ports\vigemclient" "c:\tools\vcpkg\ports" +- cmd: vcpkg update +- cmd: vcpkg upgrade build_script: -- ps: "vcpkg build vigemclient:x64-windows" -- ps: "vcpkg build vigemclient:x64-windows-static" -- ps: "vcpkg build vigemclient:x86-windows" -- ps: "vcpkg build vigemclient:x86-windows-static" +- cmd: "vcpkg build vigemclient:x64-windows" +- cmd: "vcpkg build vigemclient:x64-windows-static" +- cmd: "vcpkg build vigemclient:x86-windows" +- cmd: "vcpkg build vigemclient:x86-windows-static" deploy: - provider: Environment name: BUILDBOT From d371928137b6d30046433a2e8c8107f74f2afc0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 22 Sep 2018 21:36:43 +0200 Subject: [PATCH 026/107] Revert "Updated appveyor.yml to use vcpkg" This reverts commit 5522b8ae32cdfa246e86a0e96702ce45ce8010fd. # Conflicts: # appveyor.yml --- appveyor.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index cf1a0d3..02f1487 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,14 +1,7 @@ version: 1.16.{build}.0 image: Visual Studio 2017 -install: -- ps: Copy-Item "$env:APPVEYOR_BUILD_FOLDER\vcpkg\ports\vigemclient" "c:\tools\vcpkg\ports" -- cmd: vcpkg update -- cmd: vcpkg upgrade build_script: -- cmd: "vcpkg build vigemclient:x64-windows" -- cmd: "vcpkg build vigemclient:x64-windows-static" -- cmd: "vcpkg build vigemclient:x86-windows" -- cmd: "vcpkg build vigemclient:x86-windows-static" +- ps: .\build.ps1 -configuration Release_DLL deploy: - provider: Environment name: BUILDBOT From 894ccee273efed72c2735a798fb0c94719eaf9a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Sep 2018 12:42:11 +0200 Subject: [PATCH 027/107] Fixed header include instruction --- vcpkg/ports/vigemclient/portfile.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vcpkg/ports/vigemclient/portfile.cmake b/vcpkg/ports/vigemclient/portfile.cmake index df3690f..ee9f4cc 100644 --- a/vcpkg/ports/vigemclient/portfile.cmake +++ b/vcpkg/ports/vigemclient/portfile.cmake @@ -17,7 +17,7 @@ if (VCPKG_LIBRARY_LINKAGE STREQUAL dynamic) RELEASE_CONFIGURATION Release_DLL DEBUG_CONFIGURATION Debug_DLL USE_VCPKG_INTEGRATION - ALLOW_ROOT_INCLUDES) + REMOVE_ROOT_INCLUDES) elseif (VCPKG_LIBRARY_LINKAGE STREQUAL static) vcpkg_install_msbuild( SOURCE_PATH ${SOURCE_PATH} @@ -27,7 +27,7 @@ elseif (VCPKG_LIBRARY_LINKAGE STREQUAL static) RELEASE_CONFIGURATION Release_LIB DEBUG_CONFIGURATION Debug_LIB USE_VCPKG_INTEGRATION - ALLOW_ROOT_INCLUDES) + REMOVE_ROOT_INCLUDES) endif() # Handle copyright From a49b1ac1139cdb6a5a52e1e42b83add91c608fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Sep 2018 12:51:42 +0200 Subject: [PATCH 028/107] Updated vcpkg build instructions & version --- vcpkg/ports/vigemclient/CONTROL | 2 +- vcpkg/ports/vigemclient/portfile.cmake | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vcpkg/ports/vigemclient/CONTROL b/vcpkg/ports/vigemclient/CONTROL index acd552d..60ec21a 100644 --- a/vcpkg/ports/vigemclient/CONTROL +++ b/vcpkg/ports/vigemclient/CONTROL @@ -1,3 +1,3 @@ Source: vigemclient -Version: 1.16.13.0 +Version: 1.16.28.0 Description: ViGEm Client SDK for feeder development diff --git a/vcpkg/ports/vigemclient/portfile.cmake b/vcpkg/ports/vigemclient/portfile.cmake index ee9f4cc..da46963 100644 --- a/vcpkg/ports/vigemclient/portfile.cmake +++ b/vcpkg/ports/vigemclient/portfile.cmake @@ -3,8 +3,8 @@ include(vcpkg_common_functions) vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO ViGEm/ViGEmClient - REF v1.16.18.0 - SHA512 7628b91197a9db42c7e6641ef4ac6aeb1854d199312b0a6ac3fbfe281354495e8f597865000b90c12ad36575aaf7a3da34da04a6efa8bb64bb9d47878640ac2c + REF v1.16.28.0 + SHA512 39a321d90655895135f56b9e611ba6230e98afe296ad59f1afe99671c4a4b9ac02feb57814207e7586f0eae04ce8fd875f715a1f3bb63750dd2f742fedb6af81 HEAD_REF master ) From bc722fec5f4307d69e655975ab23a9f3fbf8769f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Sep 2018 14:58:25 +0200 Subject: [PATCH 029/107] Finished implementation of "vigem_target_x360_get_user_index" --- include/ViGEm/km/BusShared.h | 9 +++++++-- src/ViGEmClient.cpp | 13 +++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/include/ViGEm/km/BusShared.h b/include/ViGEm/km/BusShared.h index 7fb9663..2e401ba 100644 --- a/include/ViGEm/km/BusShared.h +++ b/include/ViGEm/km/BusShared.h @@ -23,8 +23,13 @@ SOFTWARE. */ +// +// GUID identifying the bus device. Used by client library to detect and communicate. +// +// IMPORTANT: make sure to change this value if you fork it or introduce +// breaking changes! +// // {96E42B22-F5E9-42F8-B043-ED0F932F014F} -// ReSharper disable once CppMissingIncludeGuard DEFINE_GUID(GUID_DEVINTERFACE_BUSENUM_VIGEM, 0x96E42B22, 0xF5E9, 0x42F8, 0xB0, 0x43, 0xED, 0x0F, 0x93, 0x2F, 0x01, 0x4F); @@ -41,7 +46,7 @@ DEFINE_GUID(GUID_DEVINTERFACE_BUSENUM_VIGEM, // access is permitted and success reported. If they mismatch, an // error is reported and the user-mode library skips this instance. // -#define VIGEM_COMMON_VERSION 0x0001 +#define VIGEM_COMMON_VERSION 0x0002 #define FILE_DEVICE_BUSENUM FILE_DEVICE_BUS_EXTENDER #define BUSENUM_IOCTL(_index_) CTL_CODE(FILE_DEVICE_BUSENUM, _index_, METHOD_BUFFERED, FILE_READ_DATA) diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 28373a4..0e069ff 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -35,6 +35,8 @@ SOFTWARE. #include #include +#include + #define VIGEM_TARGETS_MAX USHRT_MAX // @@ -778,12 +780,11 @@ VIGEM_ERROR vigem_target_x360_get_user_index( return VIGEM_ERROR_INVALID_TARGET; } - // TODO: handle userindex out-of-range situation here - //if (error == ???) - //{ - // CloseHandle(lOverlapped.hEvent); - // return VIGEM_ERROR_XUSB_USERINDEX_OUT_OF_RANGE; - //} + if (error == ERROR_INVALID_DEVICE_OBJECT_PARAMETER) + { + CloseHandle(lOverlapped.hEvent); + return VIGEM_ERROR_XUSB_USERINDEX_OUT_OF_RANGE; + } } CloseHandle(lOverlapped.hEvent); From 5090cba91468005a4cd2f977f0eb9dc6482125e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Sep 2018 15:02:35 +0200 Subject: [PATCH 030/107] Fixed missing include file path --- src/ViGEmClient.vcxproj | 2 +- src/ViGEmClient.vcxproj.filters | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index 5b16b05..d0d158c 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -295,10 +295,10 @@ - + diff --git a/src/ViGEmClient.vcxproj.filters b/src/ViGEmClient.vcxproj.filters index e4d4823..58fac3a 100644 --- a/src/ViGEmClient.vcxproj.filters +++ b/src/ViGEmClient.vcxproj.filters @@ -16,14 +16,14 @@ {3355fb06-3745-4161-8c61-b8bca15ff8fa} + + {e0df94ae-e213-4f04-981d-02d6d321df28} + Header Files - - Header Files - Header Files\ViGEm @@ -33,6 +33,9 @@ Header Files\ViGEm + + Header Files\ViGEm\km + From e8bbbe6e82f8f99757b32796d0da8147187eb58a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Sep 2018 18:36:26 +0200 Subject: [PATCH 031/107] Decreased version again to test compatibility --- .gitignore | 2 ++ include/ViGEm/km/BusShared.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 76e53a4..17d10b3 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ /Release_LIB /src/Release_LIB /src/x64 +/src/Debug_DLL +/src/Release_DLL diff --git a/include/ViGEm/km/BusShared.h b/include/ViGEm/km/BusShared.h index 2e401ba..c4b5d55 100644 --- a/include/ViGEm/km/BusShared.h +++ b/include/ViGEm/km/BusShared.h @@ -46,7 +46,7 @@ DEFINE_GUID(GUID_DEVINTERFACE_BUSENUM_VIGEM, // access is permitted and success reported. If they mismatch, an // error is reported and the user-mode library skips this instance. // -#define VIGEM_COMMON_VERSION 0x0002 +#define VIGEM_COMMON_VERSION 0x0001 #define FILE_DEVICE_BUSENUM FILE_DEVICE_BUS_EXTENDER #define BUSENUM_IOCTL(_index_) CTL_CODE(FILE_DEVICE_BUSENUM, _index_, METHOD_BUFFERED, FILE_READ_DATA) From 2427959f0861112c7211285b377cf640af71cca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger?= Date: Wed, 26 Sep 2018 16:30:47 +0200 Subject: [PATCH 032/107] Update README.md --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index fd54a2b..9dd1798 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,15 @@ You can either build directly within Visual Studio or in PowerShell by running t ```PowerShell .\build.ps1 -configuration release ``` + +## Contribute + +### Bugs & Features + +Found a bug and want it fixed? Open a detailed issue on the [GitHub issue tracker](../../issues)! + +Have an idea for a new feature? [Check out the project board](https://projects.vigem.org/public/board/27281599595f5fbe5f915884fb9ca2de92726e74173f1ac434300b2d40af), maybe it's already on there! If not, let's have a chat about your request on [Discord](https://discord.vigem.org) or the [community forums](https://forums.vigem.org). + +### Questions & Support + +Please respect that the GitHub issue tracker isn't a helpdesk. We offer a [Discord server](https://discord.vigem.org) and [forums](https://forums.vigem.org), where you're welcome to check out and engage in discussions! From 5aa4fabedaa20db897b46c0ca3007106525d1be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Thu, 27 Sep 2018 16:58:52 +0200 Subject: [PATCH 033/107] Fixed version resource language and other properties --- src/ViGEmClient.rc | 88 ++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/src/ViGEmClient.rc b/src/ViGEmClient.rc index 352d7ba..3a38bba 100644 --- a/src/ViGEmClient.rc +++ b/src/ViGEmClient.rc @@ -12,6 +12,55 @@ ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// English resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x7L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000904b0" + BEGIN + VALUE "CompanyName", "Benjamin Höglinger-Stelzer" + VALUE "FileDescription", "Virtual Gamepad Emulation User-Mode Library" + VALUE "FileVersion", "1.0.0.0" + VALUE "InternalName", "Virtual Gamepad Emulation User-Mode Library" + VALUE "LegalCopyright", "Copyright (C) Benjamin Höglinger-Stelzer 2017-2018" + VALUE "OriginalFilename", "ViGEmClient.lib" + VALUE "ProductName", "Virtual Gamepad Emulation User-Mode Library" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x9, 1200 + END +END + +#endif // English resources +///////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////////// // German (Austria) resources @@ -44,45 +93,6 @@ END #endif // APSTUDIO_INVOKED - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,14,3,0 - PRODUCTVERSION 1,14,3,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x7L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000904b0" - BEGIN - VALUE "CompanyName", "Benjamin Höglinger-Stelzer" - VALUE "FileDescription", "Virtual Gamepad Emulation User-Mode Library" - VALUE "FileVersion", "1.14.3.0" - VALUE "InternalName", "Virtual Gamepad Emulation User-Mode Library" - VALUE "LegalCopyright", "Copyright (C) Benjamin Höglinger-Stelzer 2017" - VALUE "OriginalFilename", "ViGEmCli.lib" - VALUE "ProductName", "Virtual Gamepad Emulation User-Mode Library" - VALUE "ProductVersion", "1.14.3.0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x9, 1200 - END -END - #endif // German (Austria) resources ///////////////////////////////////////////////////////////////////////////// From bca4337b069f1505a0d627380b0dacdcb7e82461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 29 Sep 2018 21:43:02 +0200 Subject: [PATCH 034/107] Updated nuke to 0.9.1 --- build/_build.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/_build.csproj b/build/_build.csproj index 68dd6c9..6212d6b 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -10,7 +10,7 @@ - + From cb3d90f2fc5779e1be9c63a50f1f2591ec48601b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 29 Sep 2018 22:48:18 +0200 Subject: [PATCH 035/107] Implemented version stamping in build script --- appveyor.yml | 1 + build/Build.cs | 88 ++++++++++++++++++++----- build/_build.csproj | 7 ++ build/default.json | 10 +++ src/ViGEmClient.rc | 110 -------------------------------- src/ViGEmClient.vcxproj | 4 -- src/ViGEmClient.vcxproj.filters | 12 +--- src/resource.h | 14 ---- 8 files changed, 92 insertions(+), 154 deletions(-) create mode 100644 build/default.json delete mode 100644 src/ViGEmClient.rc delete mode 100644 src/resource.h diff --git a/appveyor.yml b/appveyor.yml index 02f1487..2067927 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,7 @@ version: 1.16.{build}.0 image: Visual Studio 2017 build_script: +- ps: .\build.ps1 -configuration Release_LIB - ps: .\build.ps1 -configuration Release_DLL deploy: - provider: Environment diff --git a/build/Build.cs b/build/Build.cs index 0986df4..60d601f 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -1,46 +1,49 @@ using System; -using System.Linq; +using System.IO; +using JsonConfig; using Nuke.Common; +using Nuke.Common.BuildServers; using Nuke.Common.Git; using Nuke.Common.ProjectModel; +using Nuke.Common.Tools.GitVersion; using Nuke.Common.Tools.MSBuild; -using static Nuke.Common.EnvironmentInfo; +using Vestris.ResourceLib; using static Nuke.Common.IO.FileSystemTasks; using static Nuke.Common.IO.PathConstruction; using static Nuke.Common.Tools.MSBuild.MSBuildTasks; -class Build : NukeBuild +internal class Build : NukeBuild { - public static int Main () => Execute(x => x.Compile); + [GitRepository] private readonly GitRepository GitRepository; + [GitVersion] private readonly GitVersion GitVersion; - [Solution] readonly Solution Solution; - [GitRepository] readonly GitRepository GitRepository; + [Solution("ViGEmClient.sln")] private readonly Solution Solution; - AbsolutePath SourceDirectory => RootDirectory / "src"; - AbsolutePath ArtifactsDirectory => RootDirectory / "artifacts"; + private AbsolutePath SourceDirectory => RootDirectory / "src"; + private AbsolutePath ArtifactsDirectory => RootDirectory / "artifacts"; - Target Clean => _ => _ + private Target Clean => _ => _ .Executes(() => { DeleteDirectories(GlobDirectories(SourceDirectory, "**/bin", "**/obj")); EnsureCleanDirectory(ArtifactsDirectory); }); - Target Restore => _ => _ + private Target Restore => _ => _ .DependsOn(Clean) .Executes(() => { MSBuild(s => s - .SetTargetPath(SolutionFile) + .SetTargetPath(Solution) .SetTargets("Restore")); }); - Target Compile => _ => _ + private Target Compile => _ => _ .DependsOn(Restore) .Executes(() => { MSBuild(s => s - .SetTargetPath(SolutionFile) + .SetTargetPath(Solution) .SetTargets("Rebuild") .SetConfiguration(Configuration) .SetMaxCpuCount(Environment.ProcessorCount) @@ -48,12 +51,26 @@ class Build : NukeBuild .SetTargetPlatform(MSBuildTargetPlatform.x64)); MSBuild(s => s - .SetTargetPath(SolutionFile) + .SetTargetPath(Solution) .SetTargets("Rebuild") .SetConfiguration(Configuration) .SetMaxCpuCount(Environment.ProcessorCount) .SetNodeReuse(IsLocalBuild) .SetTargetPlatform(MSBuildTargetPlatform.x86)); + + if (Configuration.Equals("release_dll", StringComparison.InvariantCultureIgnoreCase)) + { + var version = + new Version(IsLocalBuild ? GitVersion.GetNormalizedFileVersion() : AppVeyor.Instance.BuildVersion); + + StampVersion( + Path.Combine(RootDirectory, @"bin\release\x64\ViGEmClient.dll"), + version); + + StampVersion( + Path.Combine(RootDirectory, @"bin\release\x86\ViGEmClient.dll"), + version); + } }); private Target Pack => _ => _ @@ -61,10 +78,49 @@ class Build : NukeBuild .Executes(() => { MSBuild(s => s - .SetTargetPath(SolutionFile) + .SetTargetPath(Solution) .SetTargets("Restore", "Pack") .SetPackageOutputPath(ArtifactsDirectory) .SetConfiguration(Configuration) .EnableIncludeSymbols()); }); -} + + public static int Main() + { + return Execute(x => x.Compile); + } + + private static void StampVersion(string path, Version version) + { + var versionResource = new VersionResource + { + FileVersion = version.ToString(), + ProductVersion = version.ToString() + }; + + var stringFileInfo = new StringFileInfo(); + versionResource[stringFileInfo.Key] = stringFileInfo; + var stringFileInfoStrings = new StringTable + { + LanguageID = 1033, + CodePage = 1200 + }; + stringFileInfo.Strings.Add(stringFileInfoStrings.Key, stringFileInfoStrings); + stringFileInfoStrings["CompanyName"] = Config.Global.Version.CompanyName; + stringFileInfoStrings["FileDescription"] = Config.Global.Version.FileDescription; + stringFileInfoStrings["FileVersion"] = version.ToString(); + stringFileInfoStrings["InternalName"] = Config.Global.Version.InternalName; + stringFileInfoStrings["LegalCopyright"] = Config.Global.Version.LegalCopyright; + stringFileInfoStrings["OriginalFilename"] = Config.Global.Version.OriginalFilename; + stringFileInfoStrings["ProductName"] = Config.Global.Version.ProductName; + stringFileInfoStrings["ProductVersion"] = version.ToString(); + + var varFileInfo = new VarFileInfo(); + versionResource[varFileInfo.Key] = varFileInfo; + var varFileInfoTranslation = new VarTable("Translation"); + varFileInfo.Vars.Add(varFileInfoTranslation.Key, varFileInfoTranslation); + varFileInfoTranslation[ResourceUtil.USENGLISHLANGID] = 1300; + + versionResource.SaveTo(path); + } +} \ No newline at end of file diff --git a/build/_build.csproj b/build/_build.csproj index 6212d6b..75bc310 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -10,14 +10,21 @@ + + + + + + Never + diff --git a/build/default.json b/build/default.json new file mode 100644 index 0000000..f98e7c9 --- /dev/null +++ b/build/default.json @@ -0,0 +1,10 @@ +{ + "Version": { + "CompanyName": "Benjamin Höglinger-Stelzer", + "FileDescription": "Virtual Gamepad Emulation Framework User-Mode Library", + "InternalName": "ViGEmClient", + "LegalCopyright": "Copyright (C) 2017-2018 Benjamin Hoeglinger-Stelzer All Rights Reserved", + "OriginalFilename": "ViGEmClient", + "ProductName": "Virtual Gamepad Emulation Framework User-Mode Library" + } +} \ No newline at end of file diff --git a/src/ViGEmClient.rc b/src/ViGEmClient.rc deleted file mode 100644 index 3a38bba..0000000 --- a/src/ViGEmClient.rc +++ /dev/null @@ -1,110 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL -#pragma code_page(1252) - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,0 - PRODUCTVERSION 1,0,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x7L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000904b0" - BEGIN - VALUE "CompanyName", "Benjamin Höglinger-Stelzer" - VALUE "FileDescription", "Virtual Gamepad Emulation User-Mode Library" - VALUE "FileVersion", "1.0.0.0" - VALUE "InternalName", "Virtual Gamepad Emulation User-Mode Library" - VALUE "LegalCopyright", "Copyright (C) Benjamin Höglinger-Stelzer 2017-2018" - VALUE "OriginalFilename", "ViGEmClient.lib" - VALUE "ProductName", "Virtual Gamepad Emulation User-Mode Library" - VALUE "ProductVersion", "1.0.0.0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x9, 1200 - END -END - -#endif // English resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// German (Austria) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEA) -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // German (Austria) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index d0d158c..7732345 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -299,14 +299,10 @@ - - - - diff --git a/src/ViGEmClient.vcxproj.filters b/src/ViGEmClient.vcxproj.filters index 58fac3a..d8eb3a3 100644 --- a/src/ViGEmClient.vcxproj.filters +++ b/src/ViGEmClient.vcxproj.filters @@ -21,9 +21,6 @@ - - Header Files - Header Files\ViGEm @@ -33,8 +30,8 @@ Header Files\ViGEm - - Header Files\ViGEm\km + + Header Files @@ -42,9 +39,4 @@ Source Files - - - Resource Files - - \ No newline at end of file diff --git a/src/resource.h b/src/resource.h deleted file mode 100644 index ab53b9b..0000000 --- a/src/resource.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by ViGEmClient.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif From 000af269d193016d7d695e14ebac79b2660c0a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 30 Sep 2018 20:17:16 +0200 Subject: [PATCH 036/107] Converted umlaut --- build/default.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/default.json b/build/default.json index f98e7c9..5af32c1 100644 --- a/build/default.json +++ b/build/default.json @@ -1,6 +1,6 @@ { "Version": { - "CompanyName": "Benjamin Höglinger-Stelzer", + "CompanyName": "Benjamin Hoeglinger-Stelzer", "FileDescription": "Virtual Gamepad Emulation Framework User-Mode Library", "InternalName": "ViGEmClient", "LegalCopyright": "Copyright (C) 2017-2018 Benjamin Hoeglinger-Stelzer All Rights Reserved", From f24c6b978c79b502eb4b0b590f47c637a7c0f6fe Mon Sep 17 00:00:00 2001 From: Joe Kaushal Date: Fri, 7 Dec 2018 19:33:50 +0000 Subject: [PATCH 037/107] Update Util.h for cmake/vcpkg include directory structure --- include/ViGEm/Util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ViGEm/Util.h b/include/ViGEm/Util.h index 3233f15..4d41aee 100644 --- a/include/ViGEm/Util.h +++ b/include/ViGEm/Util.h @@ -1,6 +1,6 @@ #pragma once -#include "ViGEmCommon.h" +#include "ViGEm/Common.h" #include VOID FORCEINLINE XUSB_TO_DS4_REPORT( From 9975c375c5e7f36d83d7ac1e44d9ea15f09b48cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Wed, 26 Dec 2018 22:11:47 +0100 Subject: [PATCH 038/107] Fixed DLL not being compiled with static runtime --- src/ViGEmClient.vcxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index 7732345..da880bf 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -185,6 +185,7 @@ Disabled VIGEM_DYNAMIC;VIGEM_EXPORTS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true + MultiThreadedDebug Windows @@ -213,6 +214,7 @@ Disabled VIGEM_DYNAMIC;VIGEM_EXPORTS;_DEBUG;_LIB;%(PreprocessorDefinitions) true + MultiThreadedDebug Windows @@ -250,6 +252,7 @@ true VIGEM_DYNAMIC;VIGEM_EXPORTS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true + MultiThreaded Windows @@ -286,6 +289,7 @@ true VIGEM_DYNAMIC;VIGEM_EXPORTS;NDEBUG;_LIB;%(PreprocessorDefinitions) true + MultiThreaded Windows From ca0a5789f3b99658f2004ac9bc1724dde94b51f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Wed, 26 Dec 2018 22:55:01 +0100 Subject: [PATCH 039/107] Build settings fixes --- ViGEmClient.sln | 8 ++++++++ appveyor.yml | 3 +-- build/Build.cs | 23 ++++++++++------------- build/_build.csproj | 4 ++-- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/ViGEmClient.sln b/ViGEmClient.sln index 8e022b6..44670ff 100644 --- a/ViGEmClient.sln +++ b/ViGEmClient.sln @@ -36,13 +36,21 @@ Global {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 2067927..5db981d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,7 @@ version: 1.16.{build}.0 image: Visual Studio 2017 build_script: -- ps: .\build.ps1 -configuration Release_LIB -- ps: .\build.ps1 -configuration Release_DLL +- ps: .\build.ps1 deploy: - provider: Environment name: BUILDBOT diff --git a/build/Build.cs b/build/Build.cs index 60d601f..c38d86e 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -12,22 +12,19 @@ using static Nuke.Common.IO.FileSystemTasks; using static Nuke.Common.IO.PathConstruction; using static Nuke.Common.Tools.MSBuild.MSBuildTasks; -internal class Build : NukeBuild +class Build : NukeBuild { + [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] + private readonly string Configuration = IsLocalBuild ? "Debug" : "Release"; + [GitRepository] private readonly GitRepository GitRepository; [GitVersion] private readonly GitVersion GitVersion; [Solution("ViGEmClient.sln")] private readonly Solution Solution; - - private AbsolutePath SourceDirectory => RootDirectory / "src"; private AbsolutePath ArtifactsDirectory => RootDirectory / "artifacts"; private Target Clean => _ => _ - .Executes(() => - { - DeleteDirectories(GlobDirectories(SourceDirectory, "**/bin", "**/obj")); - EnsureCleanDirectory(ArtifactsDirectory); - }); + .Executes(() => { EnsureCleanDirectory(ArtifactsDirectory); }); private Target Restore => _ => _ .DependsOn(Clean) @@ -45,7 +42,7 @@ internal class Build : NukeBuild MSBuild(s => s .SetTargetPath(Solution) .SetTargets("Rebuild") - .SetConfiguration(Configuration) + .SetConfiguration($"{Configuration}_DLL") .SetMaxCpuCount(Environment.ProcessorCount) .SetNodeReuse(IsLocalBuild) .SetTargetPlatform(MSBuildTargetPlatform.x64)); @@ -53,22 +50,22 @@ internal class Build : NukeBuild MSBuild(s => s .SetTargetPath(Solution) .SetTargets("Rebuild") - .SetConfiguration(Configuration) + .SetConfiguration($"{Configuration}_DLL") .SetMaxCpuCount(Environment.ProcessorCount) .SetNodeReuse(IsLocalBuild) .SetTargetPlatform(MSBuildTargetPlatform.x86)); - if (Configuration.Equals("release_dll", StringComparison.InvariantCultureIgnoreCase)) + if (Configuration.Equals($"{Configuration}_dll", StringComparison.InvariantCultureIgnoreCase)) { var version = new Version(IsLocalBuild ? GitVersion.GetNormalizedFileVersion() : AppVeyor.Instance.BuildVersion); StampVersion( - Path.Combine(RootDirectory, @"bin\release\x64\ViGEmClient.dll"), + Path.Combine(RootDirectory, $@"bin\{Configuration}\x64\ViGEmClient.dll"), version); StampVersion( - Path.Combine(RootDirectory, @"bin\release\x86\ViGEmClient.dll"), + Path.Combine(RootDirectory, $@"bin\{Configuration}\x86\ViGEmClient.dll"), version); } }); diff --git a/build/_build.csproj b/build/_build.csproj index 75bc310..f285fb8 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -11,8 +11,8 @@ - - + + From 19c1a48c79d4ab128e376279bdd96e245b5c9eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Wed, 26 Dec 2018 22:58:15 +0100 Subject: [PATCH 040/107] Added artifact filter --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 5db981d..e10b69d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,6 +2,8 @@ version: 1.16.{build}.0 image: Visual Studio 2017 build_script: - ps: .\build.ps1 +artifacts: +- path: 'bin**\*.dll' deploy: - provider: Environment name: BUILDBOT From f7a1c245c72a9048f37e5066c6ad4605bf65c052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Thu, 27 Dec 2018 16:47:25 +0100 Subject: [PATCH 041/107] Fixed CLI Debug build complaining about locked DLL --- ViGEmClient.sln | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/ViGEmClient.sln b/ViGEmClient.sln index 44670ff..105bb63 100644 --- a/ViGEmClient.sln +++ b/ViGEmClient.sln @@ -35,22 +35,6 @@ 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 From d315abe8674e37bfe245ffd01273d8707f922847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Wed, 27 Mar 2019 14:48:06 +0100 Subject: [PATCH 042/107] Fixed crash on 32-bit builds caused by calling convention mismatch --- include/ViGEm/Client.h | 4 ++-- src/ViGEmClient.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/ViGEm/Client.h b/include/ViGEm/Client.h index c490c95..48aaa45 100644 --- a/include/ViGEm/Client.h +++ b/include/ViGEm/Client.h @@ -94,7 +94,7 @@ extern "C" { typedef _Function_class_(EVT_VIGEM_TARGET_ADD_RESULT) - VOID + VOID CALLBACK EVT_VIGEM_TARGET_ADD_RESULT( PVIGEM_CLIENT Client, PVIGEM_TARGET Target, @@ -105,7 +105,7 @@ extern "C" { typedef _Function_class_(EVT_VIGEM_X360_NOTIFICATION) - VOID + VOID CALLBACK EVT_VIGEM_X360_NOTIFICATION( PVIGEM_CLIENT Client, PVIGEM_TARGET Target, diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 0e069ff..6366437 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -487,7 +487,7 @@ VIGEM_ERROR vigem_target_x360_register_notification( return; } - reinterpret_cast(_Target->Notification)( + PFN_VIGEM_X360_NOTIFICATION(_Target->Notification)( _Client, _Target, notify.LargeMotor, @@ -563,7 +563,7 @@ VIGEM_ERROR vigem_target_ds4_register_notification( return; } - reinterpret_cast(_Target->Notification)( + PFN_VIGEM_DS4_NOTIFICATION(_Target->Notification)( _Client, _Target, notify.Report.LargeMotor, From a24657a475414c689d0b4bd0580075cd40e88568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 30 Mar 2019 19:17:10 +0100 Subject: [PATCH 043/107] Addressed issue https://github.com/ViGEm/ViGEmBus/issues/13 Typo fixes Added malloc return value check --- src/ViGEmClient.cpp | 196 +++++++++++++++++++++++++------------------- 1 file changed, 111 insertions(+), 85 deletions(-) diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 6366437..60396e1 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -25,18 +25,26 @@ SOFTWARE. #define WIN32_LEAN_AND_MEAN #include -#include #include #include #include "ViGEm/km/BusShared.h" #include "ViGEm/Client.h" #include + +// +// STL +// +#include #include #include - #include +#include +#include +// +// TODO: this is... not optimal. Improve in the future. +// #define VIGEM_TARGETS_MAX USHRT_MAX // @@ -82,6 +90,10 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT( ) { auto target = static_cast(malloc(sizeof(VIGEM_TARGET))); + + if (!target) + return nullptr; + RtlZeroMemory(target, sizeof(VIGEM_TARGET)); target->Size = sizeof(VIGEM_TARGET); @@ -186,7 +198,7 @@ VIGEM_ERROR vigem_connect(PVIGEM_CLIENT vigem) continue; } - DWORD transfered = 0; + DWORD transferred = 0; OVERLAPPED lOverlapped = { 0 }; lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); @@ -201,12 +213,12 @@ VIGEM_ERROR vigem_connect(PVIGEM_CLIENT vigem) version.Size, nullptr, 0, - &transfered, + &transferred, &lOverlapped ); // wait for result - if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) != 0) + if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) { error = VIGEM_ERROR_NONE; free(detailDataBuffer); @@ -456,55 +468,62 @@ VIGEM_ERROR vigem_target_x360_register_notification( target->Notification = reinterpret_cast(notification); - std::thread _async{ []( - PVIGEM_TARGET _Target, - PVIGEM_CLIENT _Client) + std::vector threadList; + + for (int i = 0; i < 5; i++) { - DWORD error = ERROR_SUCCESS; - DWORD transfered = 0; - OVERLAPPED lOverlapped = { 0 }; - lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); - - XUSB_REQUEST_NOTIFICATION notify; - XUSB_REQUEST_NOTIFICATION_INIT(¬ify, _Target->SerialNo); - - do + threadList.emplace_back(std::thread([]( + PVIGEM_TARGET _Target, + PVIGEM_CLIENT _Client) { - DeviceIoControl(_Client->hBusDevice, - IOCTL_XUSB_REQUEST_NOTIFICATION, - ¬ify, - notify.Size, - ¬ify, - notify.Size, - &transfered, - &lOverlapped); + DWORD error = ERROR_SUCCESS; + DWORD transferred = 0; + OVERLAPPED lOverlapped = { 0 }; + lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); - if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transfered, TRUE) != 0) + XUSB_REQUEST_NOTIFICATION notify; + XUSB_REQUEST_NOTIFICATION_INIT(¬ify, _Target->SerialNo); + + do { - if (_Target->Notification == NULL) + DeviceIoControl(_Client->hBusDevice, + IOCTL_XUSB_REQUEST_NOTIFICATION, + ¬ify, + notify.Size, + ¬ify, + notify.Size, + &transferred, + &lOverlapped); + + if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) { - CloseHandle(lOverlapped.hEvent); - return; + 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); - 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); - CloseHandle(lOverlapped.hEvent); + }, target, vigem)); + } - }, target, vigem }; - - _async.detach(); + std::for_each(threadList.begin(), threadList.end(), std::mem_fn(&std::thread::detach)); return VIGEM_ERROR_NONE; } @@ -532,55 +551,62 @@ VIGEM_ERROR vigem_target_ds4_register_notification( target->Notification = reinterpret_cast(notification); - std::thread _async{ []( - PVIGEM_TARGET _Target, - PVIGEM_CLIENT _Client) + std::vector threadList; + + for (int i = 0; i < 5; i++) { - DWORD error = ERROR_SUCCESS; - DWORD transfered = 0; - OVERLAPPED lOverlapped = { 0 }; - lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); - - DS4_REQUEST_NOTIFICATION notify; - DS4_REQUEST_NOTIFICATION_INIT(¬ify, _Target->SerialNo); - - do + threadList.emplace_back(std::thread([]( + PVIGEM_TARGET _Target, + PVIGEM_CLIENT _Client) { - DeviceIoControl(_Client->hBusDevice, - IOCTL_DS4_REQUEST_NOTIFICATION, - ¬ify, - notify.Size, - ¬ify, - notify.Size, - &transfered, - &lOverlapped); + DWORD error = ERROR_SUCCESS; + DWORD transferred = 0; + OVERLAPPED lOverlapped = { 0 }; + lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); - if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transfered, TRUE) != 0) + DS4_REQUEST_NOTIFICATION notify; + DS4_REQUEST_NOTIFICATION_INIT(¬ify, _Target->SerialNo); + + do { - if (_Target->Notification == NULL) + DeviceIoControl(_Client->hBusDevice, + IOCTL_DS4_REQUEST_NOTIFICATION, + ¬ify, + notify.Size, + ¬ify, + notify.Size, + &transferred, + &lOverlapped); + + if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) { - CloseHandle(lOverlapped.hEvent); - return; + if (_Target->Notification == NULL) + { + if (lOverlapped.hEvent) + CloseHandle(lOverlapped.hEvent); + return; + } + + PFN_VIGEM_DS4_NOTIFICATION(_Target->Notification)( + _Client, + _Target, + notify.Report.LargeMotor, + notify.Report.SmallMotor, + notify.Report.LightbarColor); } + else + { + error = GetLastError(); + } + } while (error != ERROR_OPERATION_ABORTED && error != ERROR_ACCESS_DENIED); - PFN_VIGEM_DS4_NOTIFICATION(_Target->Notification)( - _Client, - _Target, - notify.Report.LargeMotor, - notify.Report.SmallMotor, - notify.Report.LightbarColor); - } - else - { - error = GetLastError(); - } - } while (error != ERROR_OPERATION_ABORTED && error != ERROR_ACCESS_DENIED); + if (lOverlapped.hEvent) + CloseHandle(lOverlapped.hEvent); - CloseHandle(lOverlapped.hEvent); + }, target, vigem)); + } - }, target, vigem }; - - _async.detach(); + std::for_each(threadList.begin(), threadList.end(), std::mem_fn(&std::thread::detach)); return VIGEM_ERROR_NONE; } From 5bf631e8f132c66e13b8a00610b35cc1f057529d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Wed, 10 Apr 2019 21:04:40 +0200 Subject: [PATCH 044/107] Added crash handler --- src/ViGEmClient.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 6366437..d7d168b 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -28,6 +28,7 @@ SOFTWARE. #include #include #include +#include #include "ViGEm/km/BusShared.h" #include "ViGEm/Client.h" @@ -39,6 +40,11 @@ SOFTWARE. #define VIGEM_TARGETS_MAX USHRT_MAX + +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); + // // Represents a driver connection object. // @@ -92,8 +98,39 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT( } +LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExceptionInfo) +{ + const auto mhLib = LoadLibrary(L"dbghelp.dll"); + const auto pDump = reinterpret_cast(GetProcAddress(mhLib, "MiniDumpWriteDump")); + + const auto hFile = CreateFile( + L"ViGEmClient.dmp", + GENERIC_WRITE, + FILE_SHARE_WRITE, + nullptr, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + nullptr + ); + + if (hFile != INVALID_HANDLE_VALUE) + { + _MINIDUMP_EXCEPTION_INFORMATION ExInfo; + ExInfo.ThreadId = GetCurrentThreadId(); + ExInfo.ExceptionPointers = apExceptionInfo; + ExInfo.ClientPointers = FALSE; + + pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, nullptr, nullptr); + CloseHandle(hFile); + } + + return EXCEPTION_CONTINUE_SEARCH; +} + PVIGEM_CLIENT vigem_alloc() { + SetUnhandledExceptionFilter(vigem_internal_exception_handler); + const auto driver = static_cast(malloc(sizeof(VIGEM_CLIENT))); if (!driver) From 842c5ddd9d15e298adf008b08576185cd5e87109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Wed, 10 Apr 2019 21:33:49 +0200 Subject: [PATCH 045/107] More threads! --- src/ViGEmClient.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index abc1905..3d499e1 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -48,6 +48,8 @@ SOFTWARE. // #define VIGEM_TARGETS_MAX USHRT_MAX +#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); @@ -507,7 +509,7 @@ VIGEM_ERROR vigem_target_x360_register_notification( std::vector threadList; - for (int i = 0; i < 5; i++) + for (int i = 0; i < VIGEM_INVERTED_CALL_THREAD_COUNT; i++) { threadList.emplace_back(std::thread([]( PVIGEM_TARGET _Target, @@ -590,7 +592,7 @@ VIGEM_ERROR vigem_target_ds4_register_notification( std::vector threadList; - for (int i = 0; i < 5; i++) + for (int i = 0; i < VIGEM_INVERTED_CALL_THREAD_COUNT; i++) { threadList.emplace_back(std::thread([]( PVIGEM_TARGET _Target, From ca5a0c8c0d19d3077730b0aff8a9c69934b35de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 16 Apr 2019 16:05:46 +0200 Subject: [PATCH 046/107] Redesigned X360 notification callback handling to use Boost ASIO and strands --- ViGEmClient.sln | 16 +++++ appveyor.yml | 4 ++ src/ViGEmClient.cpp | 152 ++++++++++++++++++++++++---------------- src/ViGEmClient.vcxproj | 2 + 4 files changed, 115 insertions(+), 59 deletions(-) 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 From 005a152323e3d4bd6f349a43bee348b074d05126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 16 Apr 2019 16:12:41 +0200 Subject: [PATCH 047/107] Added build cache --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index ab83fff..0b5b6a2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,6 +8,8 @@ build_script: - ps: .\build.ps1 artifacts: - path: 'bin**\*.dll' +cache: +- c:\tools\vcpkg\installed\ deploy: - provider: Environment name: BUILDBOT From 7d8a5248f01c2b77a7d99f939b312262a5727239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 16 Apr 2019 18:10:50 +0200 Subject: [PATCH 048/107] Added tester console application Typo fixes Fixed a bug where bus handle wasn't checked correctly --- ViGEmClient.sln | 51 +++++++++ app/Tester/Tester.cpp | 47 ++++++++ app/Tester/Tester.vcxproj | 176 ++++++++++++++++++++++++++++++ app/Tester/Tester.vcxproj.filters | 22 ++++ src/ViGEmClient.cpp | 49 +++++---- 5 files changed, 325 insertions(+), 20 deletions(-) create mode 100644 app/Tester/Tester.cpp create mode 100644 app/Tester/Tester.vcxproj create mode 100644 app/Tester/Tester.vcxproj.filters diff --git a/ViGEmClient.sln b/ViGEmClient.sln index 44670ff..acd5cb8 100644 --- a/ViGEmClient.sln +++ b/ViGEmClient.sln @@ -7,16 +7,24 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ViGEmClient", "src\ViGEmCli EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{A11CD588-F74A-41B5-9E5B-E60937052009}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "App", "App", "{8169FFB3-60F9-4A0C-B172-8E26B982B45F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tester", "app\Tester\Tester.vcxproj", "{2F4ED0AB-0B51-4506-91AA-1984C5D44B85}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_DLL|x64 = Debug_DLL|x64 Debug_DLL|x86 = Debug_DLL|x86 Debug_LIB|x64 = Debug_LIB|x64 Debug_LIB|x86 = Debug_LIB|x86 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release_DLL|x64 = Release_DLL|x64 Release_DLL|x86 = Release_DLL|x86 Release_LIB|x64 = Release_LIB|x64 Release_LIB|x86 = Release_LIB|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x64.ActiveCfg = Debug_DLL|x64 @@ -27,6 +35,10 @@ Global {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x64.Build.0 = Debug_LIB|x64 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x86.ActiveCfg = Debug_LIB|Win32 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x86.Build.0 = Debug_LIB|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x64.ActiveCfg = Debug_LIB|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x64.Build.0 = Debug_LIB|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x86.ActiveCfg = Debug_LIB|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x86.Build.0 = Debug_LIB|Win32 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x64.ActiveCfg = Release_DLL|x64 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x64.Build.0 = Release_DLL|x64 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x86.ActiveCfg = Release_DLL|Win32 @@ -35,6 +47,10 @@ 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 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x64.ActiveCfg = Release_LIB|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x64.Build.0 = Release_LIB|x64 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x86.ActiveCfg = Release_LIB|Win32 + {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|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 @@ -43,6 +59,10 @@ Global {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}.Debug|x64.ActiveCfg = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug|x64.Build.0 = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug|x86.ActiveCfg = Debug|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug|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 @@ -51,10 +71,41 @@ Global {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 + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release|x64.ActiveCfg = Release|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release|x64.Build.0 = Release|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release|x86.ActiveCfg = Release|Any CPU + {A11CD588-F74A-41B5-9E5B-E60937052009}.Release|x86.Build.0 = Release|Any CPU + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x64.ActiveCfg = Debug|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x64.Build.0 = Debug|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x86.ActiveCfg = Debug|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x86.Build.0 = Debug|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_LIB|x64.ActiveCfg = Debug|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_LIB|x64.Build.0 = Debug|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_LIB|x86.ActiveCfg = Debug|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_LIB|x86.Build.0 = Debug|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug|x64.ActiveCfg = Debug|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug|x64.Build.0 = Debug|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug|x86.ActiveCfg = Debug|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug|x86.Build.0 = Debug|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_DLL|x64.ActiveCfg = Release|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_DLL|x64.Build.0 = Release|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_DLL|x86.ActiveCfg = Release|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_DLL|x86.Build.0 = Release|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_LIB|x64.ActiveCfg = Release|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_LIB|x64.Build.0 = Release|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_LIB|x86.ActiveCfg = Release|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_LIB|x86.Build.0 = Release|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release|x64.ActiveCfg = Release|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release|x64.Build.0 = Release|x64 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release|x86.ActiveCfg = Release|Win32 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85} = {8169FFB3-60F9-4A0C-B172-8E26B982B45F} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D5CD61FD-80BB-4E0E-840C-BAF66ABB1CF0} EndGlobalSection diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp new file mode 100644 index 0000000..f47ab34 --- /dev/null +++ b/app/Tester/Tester.cpp @@ -0,0 +1,47 @@ +// Tester.cpp : This file contains the 'main' function. Program execution begins and ends there. +// + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include + +VOID CALLBACK notification( + PVIGEM_CLIENT Client, + PVIGEM_TARGET Target, + UCHAR LargeMotor, + UCHAR SmallMotor, + UCHAR LedNumber +) +{ + std::cout << LargeMotor << " " << SmallMotor << std::endl; +} + +int main() +{ + const auto client = vigem_alloc(); + + const auto x360 = vigem_target_x360_alloc(); + + auto ret = vigem_target_add(client, x360); + + ret = vigem_target_x360_register_notification(client, x360, ¬ification); + + getchar(); + + vigem_target_remove(client, x360); + vigem_target_free(x360); + vigem_free(client); +} + +// Run program: Ctrl + F5 or Debug > Start Without Debugging menu +// Debug program: F5 or Debug > Start Debugging menu + +// Tips for Getting Started: +// 1. Use the Solution Explorer window to add/manage files +// 2. Use the Team Explorer window to connect to source control +// 3. Use the Output window to see build output and other messages +// 4. Use the Error List window to view errors +// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project +// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file diff --git a/app/Tester/Tester.vcxproj b/app/Tester/Tester.vcxproj new file mode 100644 index 0000000..045ec6d --- /dev/null +++ b/app/Tester/Tester.vcxproj @@ -0,0 +1,176 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {2F4ED0AB-0B51-4506-91AA-1984C5D44B85} + Win32Proj + Tester + 10.0.17763.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + false + $(SolutionDir)include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + true + $(SolutionDir)include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + true + $(SolutionDir)include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + false + $(SolutionDir)include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + + + + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + true + true + setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + true + true + setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + {7db06674-1f4f-464b-8e1c-172e9587f9dc} + + + + + + \ No newline at end of file diff --git a/app/Tester/Tester.vcxproj.filters b/app/Tester/Tester.vcxproj.filters new file mode 100644 index 0000000..87da40a --- /dev/null +++ b/app/Tester/Tester.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 1ad6c69..fc9149c 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -418,7 +418,7 @@ VIGEM_ERROR vigem_target_add(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) if (!target) return VIGEM_ERROR_INVALID_TARGET; - if (vigem->hBusDevice == nullptr) + if (vigem->hBusDevice == INVALID_HANDLE_VALUE) return VIGEM_ERROR_BUS_NOT_FOUND; if (target->State == VIGEM_TARGET_NEW) @@ -472,7 +472,7 @@ VIGEM_ERROR vigem_target_add_async(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PF if (!target) return VIGEM_ERROR_INVALID_TARGET; - if (vigem->hBusDevice == nullptr) + if (vigem->hBusDevice == INVALID_HANDLE_VALUE) return VIGEM_ERROR_BUS_NOT_FOUND; if (target->State == VIGEM_TARGET_NEW) @@ -486,7 +486,7 @@ VIGEM_ERROR vigem_target_add_async(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PF PVIGEM_CLIENT _Client, PFN_VIGEM_TARGET_ADD_RESULT _Result) { - DWORD transfered = 0; + DWORD transferred = 0; VIGEM_PLUGIN_TARGET plugin; OVERLAPPED lOverlapped = { 0 }; lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); @@ -498,9 +498,18 @@ VIGEM_ERROR vigem_target_add_async(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PF plugin.VendorId = _Target->VendorId; plugin.ProductId = _Target->ProductId; - DeviceIoControl(_Client->hBusDevice, IOCTL_VIGEM_PLUGIN_TARGET, &plugin, plugin.Size, nullptr, 0, &transfered, &lOverlapped); + DeviceIoControl( + _Client->hBusDevice, + IOCTL_VIGEM_PLUGIN_TARGET, + &plugin, + plugin.Size, + nullptr, + 0, + &transferred, + &lOverlapped + ); - if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transfered, TRUE) != 0) + if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) { _Target->State = VIGEM_TARGET_CONNECTED; CloseHandle(lOverlapped.hEvent); @@ -532,7 +541,7 @@ VIGEM_ERROR vigem_target_remove(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) if (!target) return VIGEM_ERROR_INVALID_TARGET; - if (vigem->hBusDevice == nullptr) + if (vigem->hBusDevice == INVALID_HANDLE_VALUE) return VIGEM_ERROR_BUS_NOT_FOUND; if (target->State == VIGEM_TARGET_NEW) @@ -584,7 +593,7 @@ VIGEM_ERROR vigem_target_x360_register_notification( if (!target) return VIGEM_ERROR_INVALID_TARGET; - if (vigem->hBusDevice == nullptr) + if (vigem->hBusDevice == INVALID_HANDLE_VALUE) return VIGEM_ERROR_BUS_NOT_FOUND; if (target->SerialNo == 0 || notification == nullptr) @@ -613,7 +622,7 @@ VIGEM_ERROR vigem_target_ds4_register_notification( if (!target) return VIGEM_ERROR_INVALID_TARGET; - if (vigem->hBusDevice == nullptr) + if (vigem->hBusDevice == INVALID_HANDLE_VALUE) return VIGEM_ERROR_BUS_NOT_FOUND; if (target->SerialNo == 0 || notification == nullptr) @@ -726,13 +735,13 @@ VIGEM_ERROR vigem_target_x360_update( if (!target) return VIGEM_ERROR_INVALID_TARGET; - if (vigem->hBusDevice == nullptr) + if (vigem->hBusDevice == INVALID_HANDLE_VALUE) return VIGEM_ERROR_BUS_NOT_FOUND; if (target->SerialNo == 0) return VIGEM_ERROR_INVALID_TARGET; - DWORD transfered = 0; + DWORD transferred = 0; OVERLAPPED lOverlapped = { 0 }; lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); @@ -748,11 +757,11 @@ VIGEM_ERROR vigem_target_x360_update( xsr.Size, nullptr, 0, - &transfered, + &transferred, &lOverlapped ); - if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) == 0) + if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transferred, TRUE) == 0) { if (GetLastError() == ERROR_ACCESS_DENIED) { @@ -778,13 +787,13 @@ VIGEM_ERROR vigem_target_ds4_update( if (!target) return VIGEM_ERROR_INVALID_TARGET; - if (vigem->hBusDevice == nullptr) + if (vigem->hBusDevice == INVALID_HANDLE_VALUE) return VIGEM_ERROR_BUS_NOT_FOUND; if (target->SerialNo == 0) return VIGEM_ERROR_INVALID_TARGET; - DWORD transfered = 0; + DWORD transferred = 0; OVERLAPPED lOverlapped = { 0 }; lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); @@ -800,11 +809,11 @@ VIGEM_ERROR vigem_target_ds4_update( dsr.Size, nullptr, 0, - &transfered, + &transferred, &lOverlapped ); - if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) == 0) + if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transferred, TRUE) == 0) { if (GetLastError() == ERROR_ACCESS_DENIED) { @@ -845,13 +854,13 @@ VIGEM_ERROR vigem_target_x360_get_user_index( if (!target) return VIGEM_ERROR_INVALID_TARGET; - if (vigem->hBusDevice == nullptr) + if (vigem->hBusDevice == INVALID_HANDLE_VALUE) return VIGEM_ERROR_BUS_NOT_FOUND; if (target->SerialNo == 0 || target->Type != Xbox360Wired) return VIGEM_ERROR_INVALID_TARGET; - DWORD transfered = 0; + DWORD transferred = 0; OVERLAPPED lOverlapped = { 0 }; lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); @@ -865,11 +874,11 @@ VIGEM_ERROR vigem_target_x360_get_user_index( gui.Size, &gui, gui.Size, - &transfered, + &transferred, &lOverlapped ); - if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) == 0) + if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transferred, TRUE) == 0) { const auto error = GetLastError(); From c2d99b1f39b070e3ce3753cb2dad84f705ce74a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 16 Apr 2019 18:11:39 +0200 Subject: [PATCH 049/107] Another typo fix --- .gitignore | 2 ++ src/ViGEmClient.cpp | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 17d10b3..3a5565e 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,5 @@ /src/x64 /src/Debug_DLL /src/Release_DLL +/app/Tester/Debug +/Debug diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index fc9149c..4c0f882 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -427,7 +427,7 @@ VIGEM_ERROR vigem_target_add(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) if (target->State == VIGEM_TARGET_CONNECTED) return VIGEM_ERROR_ALREADY_CONNECTED; - DWORD transfered = 0; + DWORD transferred = 0; VIGEM_PLUGIN_TARGET plugin; OVERLAPPED lOverlapped = { 0 }; lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); @@ -446,11 +446,11 @@ VIGEM_ERROR vigem_target_add(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) plugin.Size, nullptr, 0, - &transfered, + &transferred, &lOverlapped ); - if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) != 0) + if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) { target->State = VIGEM_TARGET_CONNECTED; CloseHandle(lOverlapped.hEvent); From 3acc340aa5d92a14ab574fdadd447ad20ee90fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 16 Apr 2019 20:05:37 +0200 Subject: [PATCH 050/107] OMG --- app/Tester/Tester.cpp | 28 +++++++++-- src/ViGEmClient.cpp | 107 +++++++++++++++++++++++++----------------- 2 files changed, 89 insertions(+), 46 deletions(-) diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp index f47ab34..f4e1b2e 100644 --- a/app/Tester/Tester.cpp +++ b/app/Tester/Tester.cpp @@ -5,7 +5,12 @@ #include #include +#include #include +#include "../../../vcpkg/installed/x86-windows-static/include/boost/thread/thread_only.hpp" +#include "../../../vcpkg/installed/x86-windows-static/include/boost/thread/once.hpp" + +static std::mutex m; VOID CALLBACK notification( PVIGEM_CLIENT Client, @@ -15,20 +20,37 @@ VOID CALLBACK notification( UCHAR LedNumber ) { - std::cout << LargeMotor << " " << SmallMotor << std::endl; + m.lock(); + + //std::cout.width(3); + //std::cout << (int)LargeMotor << " "; + //std::cout.width(3); + //std::cout << (int)SmallMotor << std::endl; + + m.unlock(); } int main() { const auto client = vigem_alloc(); + auto ret = vigem_connect(client); + const auto x360 = vigem_target_x360_alloc(); - auto ret = vigem_target_add(client, x360); + ret = vigem_target_add(client, x360); ret = vigem_target_x360_register_notification(client, x360, ¬ification); - getchar(); + XUSB_REPORT report; + XUSB_REPORT_INIT(&report); + + while(true) + { + ret = vigem_target_x360_update(client, x360, report); + report.bLeftTrigger++; + boost::detail::win32::sleep(10); + } vigem_target_remove(client, x360); vigem_target_free(x360); diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 4c0f882..e1a9ece 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -50,6 +50,11 @@ SOFTWARE. #include #include +#include +#include +#include +#include + // // TODO: this is... not optimal. Improve in the future. // @@ -59,14 +64,14 @@ SOFTWARE. typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)( - HANDLE hProcess, - DWORD dwPid, - HANDLE hFile, - MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + 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); @@ -102,10 +107,11 @@ 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; + boost::shared_ptr worker_threads; + boost::shared_ptr enqueue_lock; } VIGEM_TARGET; @@ -121,7 +127,7 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT( if (!target) return nullptr; - RtlZeroMemory(target, sizeof(VIGEM_TARGET)); + memset(target, 0, sizeof(VIGEM_TARGET)); target->Size = sizeof(VIGEM_TARGET); target->State = VIGEM_TARGET_INITIALIZED; @@ -129,6 +135,8 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT( target->io_svc.reset(new boost::asio::io_service()); target->worker.reset(new boost::asio::io_service::work(*target->io_svc)); + target->worker_threads.reset(new boost::thread_group()); + target->enqueue_lock.reset(new boost::mutex()); return target; } @@ -136,31 +144,31 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT( LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExceptionInfo) { - const auto mhLib = LoadLibrary(L"dbghelp.dll"); - const auto pDump = reinterpret_cast(GetProcAddress(mhLib, "MiniDumpWriteDump")); + const auto mhLib = LoadLibrary(L"dbghelp.dll"); + const auto pDump = reinterpret_cast(GetProcAddress(mhLib, "MiniDumpWriteDump")); - const auto hFile = CreateFile( - L"ViGEmClient.dmp", - GENERIC_WRITE, - FILE_SHARE_WRITE, - nullptr, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - nullptr - ); + const auto hFile = CreateFile( + L"ViGEmClient.dmp", + GENERIC_WRITE, + FILE_SHARE_WRITE, + nullptr, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + nullptr + ); - if (hFile != INVALID_HANDLE_VALUE) - { - _MINIDUMP_EXCEPTION_INFORMATION ExInfo; - ExInfo.ThreadId = GetCurrentThreadId(); - ExInfo.ExceptionPointers = apExceptionInfo; - ExInfo.ClientPointers = FALSE; + if (hFile != INVALID_HANDLE_VALUE) + { + _MINIDUMP_EXCEPTION_INFORMATION ExInfo; + ExInfo.ThreadId = GetCurrentThreadId(); + ExInfo.ExceptionPointers = apExceptionInfo; + ExInfo.ClientPointers = FALSE; - pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, nullptr, nullptr); - CloseHandle(hFile); - } + pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, nullptr, nullptr); + CloseHandle(hFile); + } - return EXCEPTION_CONTINUE_SEARCH; + return EXCEPTION_CONTINUE_SEARCH; } void vigem_internal_x360_notification_worker( @@ -177,6 +185,8 @@ void vigem_internal_x360_notification_worker( XUSB_REQUEST_NOTIFICATION notify; XUSB_REQUEST_NOTIFICATION_INIT(¬ify, target->SerialNo); + static std::mutex m; + do { DeviceIoControl(client->hBusDevice, @@ -190,6 +200,15 @@ void vigem_internal_x360_notification_worker( if (GetOverlappedResult(client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) { + m.lock(); + auto timestamp = std::chrono::high_resolution_clock::now(); + std::cout << std::chrono::duration_cast(timestamp.time_since_epoch()).count() << " "; + std::cout.width(3); + std::cout << (int)notify.LargeMotor << " "; + std::cout.width(3); + std::cout << (int)notify.SmallMotor << std::endl; + m.unlock(); + if (target->Notification == NULL) { if (lOverlapped.hEvent) @@ -197,10 +216,11 @@ void vigem_internal_x360_notification_worker( return; } + target->enqueue_lock->lock(); const boost::function pfn = PFN_VIGEM_X360_NOTIFICATION(target->Notification); @@ -212,6 +232,7 @@ void vigem_internal_x360_notification_worker( notify.SmallMotor, notify.LedNumber )); + target->enqueue_lock->unlock(); target->io_svc->poll(); } @@ -227,7 +248,7 @@ void vigem_internal_x360_notification_worker( PVIGEM_CLIENT vigem_alloc() { - SetUnhandledExceptionFilter(vigem_internal_exception_handler); + SetUnhandledExceptionFilter(vigem_internal_exception_handler); const auto driver = static_cast(malloc(sizeof(VIGEM_CLIENT))); @@ -499,13 +520,13 @@ VIGEM_ERROR vigem_target_add_async(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PF plugin.ProductId = _Target->ProductId; DeviceIoControl( - _Client->hBusDevice, - IOCTL_VIGEM_PLUGIN_TARGET, - &plugin, - plugin.Size, - nullptr, - 0, - &transferred, + _Client->hBusDevice, + IOCTL_VIGEM_PLUGIN_TARGET, + &plugin, + plugin.Size, + nullptr, + 0, + &transferred, &lOverlapped ); @@ -605,7 +626,7 @@ VIGEM_ERROR vigem_target_x360_register_notification( target->Notification = reinterpret_cast(notification); 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)); + target->worker_threads->create_thread(boost::bind(&vigem_internal_x360_notification_worker, target, vigem)); return VIGEM_ERROR_NONE; } From 9071d6c3afd0533a4c9793e8b498dacf85545576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 21 Apr 2019 16:57:05 +0200 Subject: [PATCH 051/107] Created class XusbNotificationRequest --- src/ViGEmClient.vcxproj | 4 +++- src/ViGEmClient.vcxproj.filters | 6 ++++++ src/XusbNotificationRequest.cpp | 28 ++++++++++++++++++++++++++++ src/XusbNotificationRequest.h | 18 ++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/XusbNotificationRequest.cpp create mode 100644 src/XusbNotificationRequest.h diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index aa03ffc..c06afea 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -38,7 +38,7 @@ {7DB06674-1F4F-464B-8E1C-172E9587F9DC} Win32Proj ViGEmClient - x86-windows-static + x86-windows-static x64-windows-static @@ -305,9 +305,11 @@ + + diff --git a/src/ViGEmClient.vcxproj.filters b/src/ViGEmClient.vcxproj.filters index d8eb3a3..5f0b4b3 100644 --- a/src/ViGEmClient.vcxproj.filters +++ b/src/ViGEmClient.vcxproj.filters @@ -33,10 +33,16 @@ Header Files + + Header Files + Source Files + + Source Files + \ No newline at end of file diff --git a/src/XusbNotificationRequest.cpp b/src/XusbNotificationRequest.cpp new file mode 100644 index 0000000..3fbd4e7 --- /dev/null +++ b/src/XusbNotificationRequest.cpp @@ -0,0 +1,28 @@ +#include "XusbNotificationRequest.h" + + +XusbNotificationRequest::XusbNotificationRequest( + HANDLE bus, + ULONG serial, + HANDLE wait +) : parent_bus(bus), + payload(), transferred(0), + overlapped() +{ + overlapped.hEvent = wait; + XUSB_REQUEST_NOTIFICATION_INIT(&payload, serial); +} + +void XusbNotificationRequest::requestAsync() +{ + DeviceIoControl( + parent_bus, + IOCTL_XUSB_REQUEST_NOTIFICATION, + &payload, + payload.Size, + &payload, + payload.Size, + &transferred, + &overlapped + ); +} diff --git a/src/XusbNotificationRequest.h b/src/XusbNotificationRequest.h new file mode 100644 index 0000000..d12df3c --- /dev/null +++ b/src/XusbNotificationRequest.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include "ViGEm/km/BusShared.h" + +class XusbNotificationRequest +{ +private: + HANDLE parent_bus; + XUSB_REQUEST_NOTIFICATION payload; + DWORD transferred; + OVERLAPPED overlapped; + +public: + XusbNotificationRequest(HANDLE bus, ULONG serial, HANDLE wait); + + void requestAsync(); +}; From 3f1286cbc971e2abef10c0dd7da718e08d0e71a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 22 Apr 2019 12:13:45 +0200 Subject: [PATCH 052/107] No comment --- src/Internal.h | 48 ++++++++++++++++++++ src/NotificationRequestPool.cpp | 79 +++++++++++++++++++++++++++++++++ src/NotificationRequestPool.h | 34 ++++++++++++++ src/ViGEmClient.cpp | 68 +++++++++++----------------- src/ViGEmClient.vcxproj | 3 ++ src/ViGEmClient.vcxproj.filters | 9 ++++ src/XusbNotificationRequest.cpp | 27 ++++++++--- src/XusbNotificationRequest.h | 8 ++-- 8 files changed, 227 insertions(+), 49 deletions(-) create mode 100644 src/Internal.h create mode 100644 src/NotificationRequestPool.cpp create mode 100644 src/NotificationRequestPool.h diff --git a/src/Internal.h b/src/Internal.h new file mode 100644 index 0000000..3c3076a --- /dev/null +++ b/src/Internal.h @@ -0,0 +1,48 @@ +#pragma once +#include "XusbNotificationRequest.h" +#include "NotificationRequestPool.h" + +// +// Represents a driver connection object. +// +typedef struct _VIGEM_CLIENT_T +{ + HANDLE hBusDevice; + +} VIGEM_CLIENT; + +// +// Represents the (connection) state of a target device object. +// +typedef enum _VIGEM_TARGET_STATE +{ + VIGEM_TARGET_NEW, + VIGEM_TARGET_INITIALIZED, + VIGEM_TARGET_CONNECTED, + VIGEM_TARGET_DISCONNECTED +} VIGEM_TARGET_STATE, *PVIGEM_TARGET_STATE; + +// +// Represents a virtual gamepad object. +// +typedef struct _VIGEM_TARGET_T +{ + ULONG Size; + ULONG SerialNo; + VIGEM_TARGET_STATE State; + USHORT VendorId; + USHORT ProductId; + VIGEM_TARGET_TYPE Type; + DWORD_PTR Notification; + + boost::shared_ptr io_svc; + boost::shared_ptr worker; + boost::shared_ptr worker_threads; + boost::shared_ptr enqueue_lock; + + std::shared_ptr pool; + + HANDLE WaitHandles[VIGEM_INVERTED_CALL_THREAD_COUNT]; + std::vector notify_req; + +} VIGEM_TARGET; diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp new file mode 100644 index 0000000..d9eda03 --- /dev/null +++ b/src/NotificationRequestPool.cpp @@ -0,0 +1,79 @@ +#include "NotificationRequestPool.h" + +NotificationRequestPool::NotificationRequestPool( + HANDLE bus, + const ULONG serial, + PFN_VIGEM_X360_NOTIFICATION callback) : + callback_(callback), + stop_(false) +{ + for (auto& wait_handle : wait_handles_) + { + wait_handle = CreateEvent(nullptr, FALSE, FALSE, nullptr); + XusbNotificationRequest req(bus, serial, wait_handle); + requests_.push_back(std::ref(req)); + } + + io_svc_.reset(new boost::asio::io_service()); + worker_.reset(new boost::asio::io_service::work(*io_svc_)); + worker_threads_.reset(new boost::thread_group()); + + thread_ = std::make_shared(boost::ref(*this)); + + for (auto& request : requests_) + request.get().request_async(); +} + +NotificationRequestPool::~NotificationRequestPool() +{ + for (auto& wait_handle : wait_handles_) + CloseHandle(wait_handle); + + thread_->join(); +} + +void NotificationRequestPool::operator()() +{ + boost::asio::io_service::strand strand(*io_svc_); + + while (true) + { + const auto ret = WaitForMultipleObjects( + requests_.size(), + wait_handles_, + FALSE, + INFINITE + ); + + const auto index = ret - WAIT_OBJECT_0; + auto& req = requests_[index].get(); + + //const boost::function pfn = callback_; + + //strand.post(boost::bind(pfn, + // client, + // target, + // notify.LargeMotor, + // notify.SmallMotor, + // notify.LedNumber + //)); + + req.request_async(); + + boost::mutex::scoped_lock lock(m_); + if (stop_) + break; + } +} + +void NotificationRequestPool::terminate() +{ + boost::mutex::scoped_lock lock(m_); + stop_ = true; +} diff --git a/src/NotificationRequestPool.h b/src/NotificationRequestPool.h new file mode 100644 index 0000000..238692d --- /dev/null +++ b/src/NotificationRequestPool.h @@ -0,0 +1,34 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include "XusbNotificationRequest.h" +#include "ViGEm/Client.h" + +#define VIGEM_INVERTED_CALL_THREAD_COUNT 20 + + +class NotificationRequestPool +{ + HANDLE wait_handles_[VIGEM_INVERTED_CALL_THREAD_COUNT]{}; + PFN_VIGEM_X360_NOTIFICATION callback_; + std::vector> requests_; + std::shared_ptr thread_; + boost::mutex m_; + boost::condition_variable cv_; + bool stop_; + + boost::shared_ptr io_svc_; + boost::shared_ptr worker_; + boost::shared_ptr worker_threads_; + +public: + NotificationRequestPool(HANDLE bus, ULONG serial, PFN_VIGEM_X360_NOTIFICATION callback); + ~NotificationRequestPool(); + + void operator()(); + void terminate(); +}; diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index e1a9ece..017af7f 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -55,12 +55,15 @@ SOFTWARE. #include #include +#include "Internal.h" + +#include "NotificationRequestPool.h" + // // TODO: this is... not optimal. Improve in the future. // #define VIGEM_TARGETS_MAX USHRT_MAX -#define VIGEM_INVERTED_CALL_THREAD_COUNT 20 typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)( @@ -75,45 +78,7 @@ typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)( LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExceptionInfo); -// -// Represents a driver connection object. -// -typedef struct _VIGEM_CLIENT_T -{ - HANDLE hBusDevice; -} VIGEM_CLIENT; - -// -// Represents the (connection) state of a target device object. -// -typedef enum _VIGEM_TARGET_STATE -{ - VIGEM_TARGET_NEW, - VIGEM_TARGET_INITIALIZED, - VIGEM_TARGET_CONNECTED, - VIGEM_TARGET_DISCONNECTED -} VIGEM_TARGET_STATE, *PVIGEM_TARGET_STATE; - -// -// Represents a virtual gamepad object. -// -typedef struct _VIGEM_TARGET_T -{ - ULONG Size; - ULONG SerialNo; - VIGEM_TARGET_STATE State; - USHORT VendorId; - USHORT ProductId; - VIGEM_TARGET_TYPE Type; - DWORD_PTR Notification; - - boost::shared_ptr io_svc; - boost::shared_ptr worker; - boost::shared_ptr worker_threads; - boost::shared_ptr enqueue_lock; - -} VIGEM_TARGET; // // Initializes a virtual gamepad object. @@ -138,6 +103,9 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT( target->worker_threads.reset(new boost::thread_group()); target->enqueue_lock.reset(new boost::mutex()); + for (auto& WaitHandle : target->WaitHandles) + WaitHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr); + return target; } @@ -625,8 +593,26 @@ VIGEM_ERROR vigem_target_x360_register_notification( target->Notification = reinterpret_cast(notification); - 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)); + //for (auto i = 0; i < /* VIGEM_INVERTED_CALL_THREAD_COUNT */ 1; i++) + //{ + // auto req = new XusbNotificationRequest( + // vigem->hBusDevice, + // target->SerialNo, + // target->WaitHandles[i] + // ); + // target->notify_req.emplace_back(req); + // //target->worker_threads->create_thread(*req); + //} + + target->pool = std::make_shared( + vigem->hBusDevice, + target->SerialNo, + PFN_VIGEM_X360_NOTIFICATION(target->Notification) + ); + + + //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 c06afea..5683040 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -305,9 +305,12 @@ + + + diff --git a/src/ViGEmClient.vcxproj.filters b/src/ViGEmClient.vcxproj.filters index 5f0b4b3..ed9f98d 100644 --- a/src/ViGEmClient.vcxproj.filters +++ b/src/ViGEmClient.vcxproj.filters @@ -36,6 +36,12 @@ Header Files + + Header Files + + + Header Files + @@ -44,5 +50,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/src/XusbNotificationRequest.cpp b/src/XusbNotificationRequest.cpp index 3fbd4e7..9944bcd 100644 --- a/src/XusbNotificationRequest.cpp +++ b/src/XusbNotificationRequest.cpp @@ -4,25 +4,42 @@ XusbNotificationRequest::XusbNotificationRequest( HANDLE bus, ULONG serial, - HANDLE wait + HANDLE notification ) : parent_bus(bus), payload(), transferred(0), overlapped() { - overlapped.hEvent = wait; + overlapped.hEvent = notification; XUSB_REQUEST_NOTIFICATION_INIT(&payload, serial); } -void XusbNotificationRequest::requestAsync() +bool XusbNotificationRequest::request_async() { - DeviceIoControl( + const auto ret = DeviceIoControl( parent_bus, IOCTL_XUSB_REQUEST_NOTIFICATION, &payload, payload.Size, &payload, payload.Size, - &transferred, + nullptr, &overlapped ); + + return (!ret && GetLastError() == ERROR_IO_PENDING); +} + +UCHAR XusbNotificationRequest::get_led_number() const +{ + return payload.LedNumber; +} + +UCHAR XusbNotificationRequest::get_large_motor() const +{ + return payload.LargeMotor; +} + +UCHAR XusbNotificationRequest::get_small_motor() const +{ + return payload.SmallMotor; } diff --git a/src/XusbNotificationRequest.h b/src/XusbNotificationRequest.h index d12df3c..0aa3f8f 100644 --- a/src/XusbNotificationRequest.h +++ b/src/XusbNotificationRequest.h @@ -5,14 +5,16 @@ class XusbNotificationRequest { -private: HANDLE parent_bus; XUSB_REQUEST_NOTIFICATION payload; DWORD transferred; OVERLAPPED overlapped; public: - XusbNotificationRequest(HANDLE bus, ULONG serial, HANDLE wait); + XusbNotificationRequest(HANDLE bus, ULONG serial, HANDLE notification); + bool request_async(); - void requestAsync(); + UCHAR get_led_number() const; + UCHAR get_large_motor() const; + UCHAR get_small_motor() const; }; From 3408227bb1c72fda7573c8aa5ff06beee1ca2332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 22 Apr 2019 14:03:14 +0200 Subject: [PATCH 053/107] It appears to be working --- app/Tester/Tester.cpp | 12 +++-- src/Internal.h | 10 +--- src/NotificationRequestPool.cpp | 95 +++++++++++++++++++++++---------- src/NotificationRequestPool.h | 17 ++++-- src/ViGEmClient.cpp | 91 +------------------------------ src/XusbNotificationRequest.cpp | 34 ++++++------ src/XusbNotificationRequest.h | 7 ++- 7 files changed, 115 insertions(+), 151 deletions(-) diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp index f4e1b2e..fd53607 100644 --- a/app/Tester/Tester.cpp +++ b/app/Tester/Tester.cpp @@ -22,10 +22,14 @@ VOID CALLBACK notification( { m.lock(); - //std::cout.width(3); - //std::cout << (int)LargeMotor << " "; - //std::cout.width(3); - //std::cout << (int)SmallMotor << std::endl; + static int count = 1; + + std::cout.width(3); + std::cout << count++ << " "; + std::cout.width(3); + std::cout << (int)LargeMotor << " "; + std::cout.width(3); + std::cout << (int)SmallMotor << std::endl; m.unlock(); } diff --git a/src/Internal.h b/src/Internal.h index 3c3076a..07ff4db 100644 --- a/src/Internal.h +++ b/src/Internal.h @@ -22,6 +22,8 @@ typedef enum _VIGEM_TARGET_STATE VIGEM_TARGET_DISCONNECTED } VIGEM_TARGET_STATE, *PVIGEM_TARGET_STATE; +class NotificationRequestPool; + // // Represents a virtual gamepad object. // @@ -35,14 +37,6 @@ typedef struct _VIGEM_TARGET_T VIGEM_TARGET_TYPE Type; DWORD_PTR Notification; - boost::shared_ptr io_svc; - boost::shared_ptr worker; - boost::shared_ptr worker_threads; - boost::shared_ptr enqueue_lock; - std::shared_ptr pool; - HANDLE WaitHandles[VIGEM_INVERTED_CALL_THREAD_COUNT]; - std::vector notify_req; - } VIGEM_TARGET; diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp index d9eda03..7ea1fcc 100644 --- a/src/NotificationRequestPool.cpp +++ b/src/NotificationRequestPool.cpp @@ -1,27 +1,48 @@ #include "NotificationRequestPool.h" +void NotificationRequestPool::strand_dispatch_worker() const +{ + io_svc_->run(); +} + NotificationRequestPool::NotificationRequestPool( - HANDLE bus, - const ULONG serial, - PFN_VIGEM_X360_NOTIFICATION callback) : + PVIGEM_CLIENT client, + PVIGEM_TARGET target, + PFN_VIGEM_X360_NOTIFICATION callback +) : + client_(client), + target_(target), callback_(callback), stop_(false) { + // prepare array of handles and request wrappers for (auto& wait_handle : wait_handles_) { + // create auto-reset event wait_handle = CreateEvent(nullptr, FALSE, FALSE, nullptr); - XusbNotificationRequest req(bus, serial, wait_handle); - requests_.push_back(std::ref(req)); + // create async pending I/O request wrapper + auto req = new XusbNotificationRequest( + client_->hBusDevice, + target_->SerialNo, + wait_handle + ); + requests_.push_back(req); } + // init ASIO io_svc_.reset(new boost::asio::io_service()); worker_.reset(new boost::asio::io_service::work(*io_svc_)); - worker_threads_.reset(new boost::thread_group()); + // launch notification completion thread thread_ = std::make_shared(boost::ref(*this)); + // launch boost I/O service dispatcher thread + worker_thread_ = std::make_shared( + boost::bind(&NotificationRequestPool::strand_dispatch_worker, this)); + + // submit pending I/O to driver for (auto& request : requests_) - request.get().request_async(); + request->request_async(); } NotificationRequestPool::~NotificationRequestPool() @@ -29,46 +50,64 @@ NotificationRequestPool::~NotificationRequestPool() for (auto& wait_handle : wait_handles_) CloseHandle(wait_handle); + io_svc_->stop(); + worker_thread_->join(); + thread_->join(); } void NotificationRequestPool::operator()() { + // used to dispatch notification callback boost::asio::io_service::strand strand(*io_svc_); while (true) { + // wait for the first pending I/O to signal its event const auto ret = WaitForMultipleObjects( requests_.size(), wait_handles_, FALSE, - INFINITE + 25 ); + // timeout has occurred... + if (ret == WAIT_TIMEOUT) + { + // ...check for termination request + boost::mutex::scoped_lock lock(m_); + if (stop_) + // exits function (terminates thread) + break; + + // go for another round + continue; + } + + // index of the request which just got completed const auto index = ret - WAIT_OBJECT_0; - auto& req = requests_[index].get(); + // grab associated request + const auto req = requests_[index]; - //const boost::function pfn = callback_; + // prepare queueing library caller notification callback + const boost::function pfn = callback_; - //strand.post(boost::bind(pfn, - // client, - // target, - // notify.LargeMotor, - // notify.SmallMotor, - // notify.LedNumber - //)); + // submit callback for async yet ordered invocation + strand.post(boost::bind(pfn, + client_, + target_, + req->get_large_motor(), + req->get_small_motor(), + req->get_led_number() + )); - req.request_async(); - - boost::mutex::scoped_lock lock(m_); - if (stop_) - break; + // submit another pending I/O + req->request_async(); } } diff --git a/src/NotificationRequestPool.h b/src/NotificationRequestPool.h index 238692d..9ec91a7 100644 --- a/src/NotificationRequestPool.h +++ b/src/NotificationRequestPool.h @@ -7,6 +7,7 @@ #include #include "XusbNotificationRequest.h" #include "ViGEm/Client.h" +#include "Internal.h" #define VIGEM_INVERTED_CALL_THREAD_COUNT 20 @@ -14,8 +15,12 @@ class NotificationRequestPool { HANDLE wait_handles_[VIGEM_INVERTED_CALL_THREAD_COUNT]{}; + + PVIGEM_CLIENT client_; + PVIGEM_TARGET target_; PFN_VIGEM_X360_NOTIFICATION callback_; - std::vector> requests_; + + std::vector requests_; std::shared_ptr thread_; boost::mutex m_; boost::condition_variable cv_; @@ -23,10 +28,16 @@ class NotificationRequestPool boost::shared_ptr io_svc_; boost::shared_ptr worker_; - boost::shared_ptr worker_threads_; + std::shared_ptr worker_thread_; + + void strand_dispatch_worker() const; public: - NotificationRequestPool(HANDLE bus, ULONG serial, PFN_VIGEM_X360_NOTIFICATION callback); + NotificationRequestPool( + PVIGEM_CLIENT client, + PVIGEM_TARGET target, + PFN_VIGEM_X360_NOTIFICATION callback + ); ~NotificationRequestPool(); void operator()(); diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 017af7f..fbd955a 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -98,14 +98,6 @@ 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)); - target->worker_threads.reset(new boost::thread_group()); - target->enqueue_lock.reset(new boost::mutex()); - - for (auto& WaitHandle : target->WaitHandles) - WaitHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr); - return target; } @@ -139,81 +131,6 @@ 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); - - static std::mutex m; - - do - { - DeviceIoControl(client->hBusDevice, - IOCTL_XUSB_REQUEST_NOTIFICATION, - ¬ify, - notify.Size, - ¬ify, - notify.Size, - &transferred, - &lOverlapped); - - if (GetOverlappedResult(client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) - { - m.lock(); - auto timestamp = std::chrono::high_resolution_clock::now(); - std::cout << std::chrono::duration_cast(timestamp.time_since_epoch()).count() << " "; - std::cout.width(3); - std::cout << (int)notify.LargeMotor << " "; - std::cout.width(3); - std::cout << (int)notify.SmallMotor << std::endl; - m.unlock(); - - if (target->Notification == NULL) - { - if (lOverlapped.hEvent) - CloseHandle(lOverlapped.hEvent); - return; - } - - target->enqueue_lock->lock(); - const boost::function pfn = PFN_VIGEM_X360_NOTIFICATION(target->Notification); - - strand.post(boost::bind(pfn, - client, - target, - notify.LargeMotor, - notify.SmallMotor, - notify.LedNumber - )); - target->enqueue_lock->unlock(); - - 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); @@ -392,11 +309,7 @@ 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) @@ -605,8 +518,8 @@ VIGEM_ERROR vigem_target_x360_register_notification( //} target->pool = std::make_shared( - vigem->hBusDevice, - target->SerialNo, + vigem, + target, PFN_VIGEM_X360_NOTIFICATION(target->Notification) ); diff --git a/src/XusbNotificationRequest.cpp b/src/XusbNotificationRequest.cpp index 9944bcd..6ccc7a6 100644 --- a/src/XusbNotificationRequest.cpp +++ b/src/XusbNotificationRequest.cpp @@ -5,41 +5,45 @@ XusbNotificationRequest::XusbNotificationRequest( HANDLE bus, ULONG serial, HANDLE notification -) : parent_bus(bus), - payload(), transferred(0), - overlapped() +) : parent_bus_(bus), + payload_(), + overlapped_() { - overlapped.hEvent = notification; - XUSB_REQUEST_NOTIFICATION_INIT(&payload, serial); + memset(&overlapped_, 0, sizeof(OVERLAPPED)); + overlapped_.hEvent = notification; + XUSB_REQUEST_NOTIFICATION_INIT(&payload_, serial); } bool XusbNotificationRequest::request_async() { + // queue request in driver const auto ret = DeviceIoControl( - parent_bus, + parent_bus_, IOCTL_XUSB_REQUEST_NOTIFICATION, - &payload, - payload.Size, - &payload, - payload.Size, + &payload_, + payload_.Size, + &payload_, + payload_.Size, nullptr, - &overlapped + &overlapped_ ); - return (!ret && GetLastError() == ERROR_IO_PENDING); + const auto error = GetLastError(); + + return (!ret && error == ERROR_IO_PENDING); } UCHAR XusbNotificationRequest::get_led_number() const { - return payload.LedNumber; + return payload_.LedNumber; } UCHAR XusbNotificationRequest::get_large_motor() const { - return payload.LargeMotor; + return payload_.LargeMotor; } UCHAR XusbNotificationRequest::get_small_motor() const { - return payload.SmallMotor; + return payload_.SmallMotor; } diff --git a/src/XusbNotificationRequest.h b/src/XusbNotificationRequest.h index 0aa3f8f..dd6b2b0 100644 --- a/src/XusbNotificationRequest.h +++ b/src/XusbNotificationRequest.h @@ -5,10 +5,9 @@ class XusbNotificationRequest { - HANDLE parent_bus; - XUSB_REQUEST_NOTIFICATION payload; - DWORD transferred; - OVERLAPPED overlapped; + HANDLE parent_bus_; + XUSB_REQUEST_NOTIFICATION payload_; + OVERLAPPED overlapped_; public: XusbNotificationRequest(HANDLE bus, ULONG serial, HANDLE notification); From ea63179aac18dded4493662673f3444cacb79fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 22 Apr 2019 14:08:28 +0200 Subject: [PATCH 054/107] Removed deprecated code --- src/Internal.h | 8 ++++++-- src/ViGEmClient.cpp | 28 ++-------------------------- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/src/Internal.h b/src/Internal.h index 07ff4db..3659f04 100644 --- a/src/Internal.h +++ b/src/Internal.h @@ -1,6 +1,10 @@ #pragma once -#include "XusbNotificationRequest.h" -#include "NotificationRequestPool.h" + +// +// TODO: this is... not optimal. Improve in the future. +// +#define VIGEM_TARGETS_MAX USHRT_MAX + // // Represents a driver connection object. diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index fbd955a..8e42093 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -47,24 +47,14 @@ SOFTWARE. #include #include #include -#include #include -#include -#include -#include #include #include "Internal.h" #include "NotificationRequestPool.h" -// -// TODO: this is... not optimal. Improve in the future. -// -#define VIGEM_TARGETS_MAX USHRT_MAX - - typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)( HANDLE hProcess, @@ -79,7 +69,6 @@ typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)( LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExceptionInfo); - // // Initializes a virtual gamepad object. // @@ -504,18 +493,9 @@ VIGEM_ERROR vigem_target_x360_register_notification( if (target->Notification == reinterpret_cast(notification)) return VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED; - target->Notification = reinterpret_cast(notification); + // TODO: tidy up this mess - //for (auto i = 0; i < /* VIGEM_INVERTED_CALL_THREAD_COUNT */ 1; i++) - //{ - // auto req = new XusbNotificationRequest( - // vigem->hBusDevice, - // target->SerialNo, - // target->WaitHandles[i] - // ); - // target->notify_req.emplace_back(req); - // //target->worker_threads->create_thread(*req); - //} + target->Notification = reinterpret_cast(notification); target->pool = std::make_shared( vigem, @@ -523,10 +503,6 @@ VIGEM_ERROR vigem_target_x360_register_notification( PFN_VIGEM_X360_NOTIFICATION(target->Notification) ); - - //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; } From ca441cf623cc6d9a3137ce7727878ec1b1dd4203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 22 Apr 2019 14:11:06 +0200 Subject: [PATCH 055/107] Fixed broken tester code --- app/Tester/Tester.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp index fd53607..09c2145 100644 --- a/app/Tester/Tester.cpp +++ b/app/Tester/Tester.cpp @@ -7,8 +7,6 @@ #include #include -#include "../../../vcpkg/installed/x86-windows-static/include/boost/thread/thread_only.hpp" -#include "../../../vcpkg/installed/x86-windows-static/include/boost/thread/once.hpp" static std::mutex m; @@ -53,21 +51,10 @@ int main() { ret = vigem_target_x360_update(client, x360, report); report.bLeftTrigger++; - boost::detail::win32::sleep(10); + Sleep(10); } vigem_target_remove(client, x360); vigem_target_free(x360); vigem_free(client); } - -// Run program: Ctrl + F5 or Debug > Start Without Debugging menu -// Debug program: F5 or Debug > Start Debugging menu - -// Tips for Getting Started: -// 1. Use the Solution Explorer window to add/manage files -// 2. Use the Team Explorer window to connect to source control -// 3. Use the Output window to see build output and other messages -// 4. Use the Error List window to view errors -// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project -// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file From eddb75c0c443d06b416a1500ea7dc0588888de92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 22 Apr 2019 19:14:26 +0200 Subject: [PATCH 056/107] Added comments --- src/NotificationRequestPool.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp index 7ea1fcc..4624fb4 100644 --- a/src/NotificationRequestPool.cpp +++ b/src/NotificationRequestPool.cpp @@ -67,8 +67,8 @@ void NotificationRequestPool::operator()() const auto ret = WaitForMultipleObjects( requests_.size(), wait_handles_, - FALSE, - 25 + FALSE, // first one to be signaled wins + 25 // don't block indefinitely so worker can be canceled ); // timeout has occurred... From e4d313d8b1d75319dac17aa6d92a57a20e3189c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 23 Apr 2019 21:34:36 +0200 Subject: [PATCH 057/107] Sylveonification, almost --- src/NotificationRequestPool.cpp | 7 +++---- src/NotificationRequestPool.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp index 4624fb4..6bcf909 100644 --- a/src/NotificationRequestPool.cpp +++ b/src/NotificationRequestPool.cpp @@ -21,12 +21,11 @@ NotificationRequestPool::NotificationRequestPool( // create auto-reset event wait_handle = CreateEvent(nullptr, FALSE, FALSE, nullptr); // create async pending I/O request wrapper - auto req = new XusbNotificationRequest( + requests_.push_back(std::make_unique( client_->hBusDevice, target_->SerialNo, wait_handle - ); - requests_.push_back(req); + )); } // init ASIO @@ -87,7 +86,7 @@ void NotificationRequestPool::operator()() // index of the request which just got completed const auto index = ret - WAIT_OBJECT_0; // grab associated request - const auto req = requests_[index]; + const auto req = requests_[index].get(); // prepare queueing library caller notification callback const boost::function requests_; + std::vector> requests_; std::shared_ptr thread_; boost::mutex m_; boost::condition_variable cv_; From 61b482a88aef172b02ead18b01ba5e57a9be65f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Thu, 25 Apr 2019 17:02:02 +0200 Subject: [PATCH 058/107] Removed VIGEM_INVERTED_CALL_THREAD_COUNT macro --- src/NotificationRequestPool.h | 5 ++--- src/ViGEmClient.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/NotificationRequestPool.h b/src/NotificationRequestPool.h index 026f30a..c544cb9 100644 --- a/src/NotificationRequestPool.h +++ b/src/NotificationRequestPool.h @@ -9,12 +9,11 @@ #include "ViGEm/Client.h" #include "Internal.h" -#define VIGEM_INVERTED_CALL_THREAD_COUNT 20 - class NotificationRequestPool { - HANDLE wait_handles_[VIGEM_INVERTED_CALL_THREAD_COUNT]{}; + static const int thread_count = 20; + HANDLE wait_handles_[thread_count]{}; PVIGEM_CLIENT client_; PVIGEM_TARGET target_; diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 8e42093..f2a37e5 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -531,7 +531,7 @@ VIGEM_ERROR vigem_target_ds4_register_notification( std::vector threadList; - for (int i = 0; i < VIGEM_INVERTED_CALL_THREAD_COUNT; i++) + for (int i = 0; i < 20 /* TODO: legacy, remove */; i++) { threadList.emplace_back(std::thread([]( PVIGEM_TARGET _Target, From 88a325f520051a9a057c42a8d4fc9f82ff1af9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 28 May 2019 15:34:30 +0200 Subject: [PATCH 059/107] Trying to generalize and tidy up this mess --- src/NotificationRequestPool.cpp | 6 +++--- src/NotificationRequestPool.h | 6 +++--- src/ViGEmClient.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp index 6bcf909..bd79adc 100644 --- a/src/NotificationRequestPool.cpp +++ b/src/NotificationRequestPool.cpp @@ -8,7 +8,7 @@ void NotificationRequestPool::strand_dispatch_worker() const NotificationRequestPool::NotificationRequestPool( PVIGEM_CLIENT client, PVIGEM_TARGET target, - PFN_VIGEM_X360_NOTIFICATION callback + FARPROC callback ) : client_(client), target_(target), @@ -44,7 +44,7 @@ NotificationRequestPool::NotificationRequestPool( request->request_async(); } -NotificationRequestPool::~NotificationRequestPool() +NotificationRequestPool::~NotificationRequestPool() noexcept(false) { for (auto& wait_handle : wait_handles_) CloseHandle(wait_handle); @@ -94,7 +94,7 @@ void NotificationRequestPool::operator()() PVIGEM_TARGET, UCHAR, UCHAR, - UCHAR)> pfn = callback_; + UCHAR)> pfn = PFN_VIGEM_X360_NOTIFICATION(callback_); // submit callback for async yet ordered invocation strand.post(boost::bind(pfn, diff --git a/src/NotificationRequestPool.h b/src/NotificationRequestPool.h index c544cb9..af0d3eb 100644 --- a/src/NotificationRequestPool.h +++ b/src/NotificationRequestPool.h @@ -17,7 +17,7 @@ class NotificationRequestPool PVIGEM_CLIENT client_; PVIGEM_TARGET target_; - PFN_VIGEM_X360_NOTIFICATION callback_; + FARPROC callback_; std::vector> requests_; std::shared_ptr thread_; @@ -35,9 +35,9 @@ public: NotificationRequestPool( PVIGEM_CLIENT client, PVIGEM_TARGET target, - PFN_VIGEM_X360_NOTIFICATION callback + FARPROC callback ); - ~NotificationRequestPool(); + ~NotificationRequestPool() noexcept(false); void operator()(); void terminate(); diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index f2a37e5..60d673e 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -500,7 +500,7 @@ VIGEM_ERROR vigem_target_x360_register_notification( target->pool = std::make_shared( vigem, target, - PFN_VIGEM_X360_NOTIFICATION(target->Notification) + reinterpret_cast(target->Notification) ); return VIGEM_ERROR_NONE; From fb3b55c5d5efe604105c345a454b4caf0d40e4a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 28 May 2019 15:43:45 +0200 Subject: [PATCH 060/107] Added cancel through ESC to tester --- app/Tester/Tester.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp index 09c2145..57dc1f0 100644 --- a/app/Tester/Tester.cpp +++ b/app/Tester/Tester.cpp @@ -47,7 +47,7 @@ int main() XUSB_REPORT report; XUSB_REPORT_INIT(&report); - while(true) + while(!(GetAsyncKeyState(VK_ESCAPE) & 0x8000)) { ret = vigem_target_x360_update(client, x360, report); report.bLeftTrigger++; From 7f4f579e88f959fe5b89d93f02f8bb49be9644ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 28 May 2019 16:41:52 +0200 Subject: [PATCH 061/107] De-cluttered includes --- src/NotificationRequestPool.h | 1 - src/ViGEmClient.cpp | 9 --------- src/ViGEmClient.vcxproj | 16 ++++++++-------- src/XusbNotificationRequest.cpp | 1 + 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/NotificationRequestPool.h b/src/NotificationRequestPool.h index af0d3eb..b3840d3 100644 --- a/src/NotificationRequestPool.h +++ b/src/NotificationRequestPool.h @@ -1,6 +1,5 @@ #pragma once -#define WIN32_LEAN_AND_MEAN #include #include #include diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 60d673e..e4f2c98 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -23,7 +23,6 @@ SOFTWARE. */ -#define WIN32_LEAN_AND_MEAN #include #include #include @@ -41,14 +40,6 @@ SOFTWARE. #include #include -// -// Boost -// -#include -#include -#include -#include - #include #include "Internal.h" diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index 5683040..f5fc0ea 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -168,7 +168,7 @@ Level3 Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreadedDebug @@ -185,7 +185,7 @@ Level3 Disabled - VIGEM_DYNAMIC;VIGEM_EXPORTS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + WIN32_LEAN_AND_MEAN;VIGEM_DYNAMIC;VIGEM_EXPORTS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreadedDebug @@ -200,7 +200,7 @@ Level3 Disabled - _DEBUG;_LIB;%(PreprocessorDefinitions) + WIN32_LEAN_AND_MEAN;_DEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreadedDebug @@ -214,7 +214,7 @@ Level3 Disabled - VIGEM_DYNAMIC;VIGEM_EXPORTS;_DEBUG;_LIB;%(PreprocessorDefinitions) + WIN32_LEAN_AND_MEAN;VIGEM_DYNAMIC;VIGEM_EXPORTS;_DEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreadedDebug @@ -231,7 +231,7 @@ MaxSpeed true true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreaded @@ -252,7 +252,7 @@ MaxSpeed true true - VIGEM_DYNAMIC;VIGEM_EXPORTS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + WIN32_LEAN_AND_MEAN;VIGEM_DYNAMIC;VIGEM_EXPORTS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreaded @@ -271,7 +271,7 @@ MaxSpeed true true - NDEBUG;_LIB;%(PreprocessorDefinitions) + WIN32_LEAN_AND_MEAN;NDEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreaded @@ -289,7 +289,7 @@ MaxSpeed true true - VIGEM_DYNAMIC;VIGEM_EXPORTS;NDEBUG;_LIB;%(PreprocessorDefinitions) + WIN32_LEAN_AND_MEAN;VIGEM_DYNAMIC;VIGEM_EXPORTS;NDEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreaded diff --git a/src/XusbNotificationRequest.cpp b/src/XusbNotificationRequest.cpp index 6ccc7a6..38af045 100644 --- a/src/XusbNotificationRequest.cpp +++ b/src/XusbNotificationRequest.cpp @@ -1,4 +1,5 @@ #include "XusbNotificationRequest.h" +#include XusbNotificationRequest::XusbNotificationRequest( From 6b371f660b311e24ab4c830e07399b3f965dc70d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 28 May 2019 16:44:26 +0200 Subject: [PATCH 062/107] Added license header snippet --- src/Internal.h | 25 +++++++++++++++++++++++++ src/NotificationRequestPool.cpp | 27 ++++++++++++++++++++++++++- src/NotificationRequestPool.h | 27 ++++++++++++++++++++++++++- src/XusbNotificationRequest.cpp | 27 ++++++++++++++++++++++++++- src/XusbNotificationRequest.h | 27 ++++++++++++++++++++++++++- 5 files changed, 129 insertions(+), 4 deletions(-) diff --git a/src/Internal.h b/src/Internal.h index 3659f04..19f9e10 100644 --- a/src/Internal.h +++ b/src/Internal.h @@ -1,3 +1,28 @@ +/* +MIT License + +Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors + +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 +AUTHORS OR COPYRIGHT HOLDERS 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. +*/ + + #pragma once // diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp index bd79adc..f429938 100644 --- a/src/NotificationRequestPool.cpp +++ b/src/NotificationRequestPool.cpp @@ -1,4 +1,29 @@ -#include "NotificationRequestPool.h" +/* +MIT License + +Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors + +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 +AUTHORS OR COPYRIGHT HOLDERS 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 "NotificationRequestPool.h" void NotificationRequestPool::strand_dispatch_worker() const { diff --git a/src/NotificationRequestPool.h b/src/NotificationRequestPool.h index b3840d3..19fd7bf 100644 --- a/src/NotificationRequestPool.h +++ b/src/NotificationRequestPool.h @@ -1,4 +1,29 @@ -#pragma once +/* +MIT License + +Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors + +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 +AUTHORS OR COPYRIGHT HOLDERS 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. +*/ + + +#pragma once #include #include diff --git a/src/XusbNotificationRequest.cpp b/src/XusbNotificationRequest.cpp index 38af045..9929c12 100644 --- a/src/XusbNotificationRequest.cpp +++ b/src/XusbNotificationRequest.cpp @@ -1,4 +1,29 @@ -#include "XusbNotificationRequest.h" +/* +MIT License + +Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors + +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 +AUTHORS OR COPYRIGHT HOLDERS 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 "XusbNotificationRequest.h" #include diff --git a/src/XusbNotificationRequest.h b/src/XusbNotificationRequest.h index dd6b2b0..479d20e 100644 --- a/src/XusbNotificationRequest.h +++ b/src/XusbNotificationRequest.h @@ -1,4 +1,29 @@ -#pragma once +/* +MIT License + +Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors + +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 +AUTHORS OR COPYRIGHT HOLDERS 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. +*/ + + +#pragma once #include #include "ViGEm/km/BusShared.h" From 0875d8ce3835de6e047480c882e5c2175a866c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 28 May 2019 18:01:47 +0200 Subject: [PATCH 063/107] Refactored code to make it more generic --- src/Internal.h | 2 +- src/NotificationRequestPool.cpp | 20 +++---------------- src/ViGEmClient.cpp | 10 ++++------ src/XusbNotificationRequest.cpp | 35 ++++++++++++++++++++++++++++----- src/XusbNotificationRequest.h | 8 ++++++-- 5 files changed, 44 insertions(+), 31 deletions(-) diff --git a/src/Internal.h b/src/Internal.h index 19f9e10..0520691 100644 --- a/src/Internal.h +++ b/src/Internal.h @@ -64,7 +64,7 @@ typedef struct _VIGEM_TARGET_T USHORT VendorId; USHORT ProductId; VIGEM_TARGET_TYPE Type; - DWORD_PTR Notification; + FARPROC Notification; std::shared_ptr pool; diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp index f429938..89c9b08 100644 --- a/src/NotificationRequestPool.cpp +++ b/src/NotificationRequestPool.cpp @@ -47,8 +47,8 @@ NotificationRequestPool::NotificationRequestPool( wait_handle = CreateEvent(nullptr, FALSE, FALSE, nullptr); // create async pending I/O request wrapper requests_.push_back(std::make_unique( - client_->hBusDevice, - target_->SerialNo, + client_, + target_, wait_handle )); } @@ -113,22 +113,8 @@ void NotificationRequestPool::operator()() // grab associated request const auto req = requests_[index].get(); - // prepare queueing library caller notification callback - const boost::function pfn = PFN_VIGEM_X360_NOTIFICATION(callback_); - // submit callback for async yet ordered invocation - strand.post(boost::bind(pfn, - client_, - target_, - req->get_large_motor(), - req->get_small_motor(), - req->get_led_number() - )); + req->post(std::move(strand)); // submit another pending I/O req->request_async(); diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index e4f2c98..d42ef63 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -481,12 +481,10 @@ VIGEM_ERROR vigem_target_x360_register_notification( if (target->SerialNo == 0 || notification == nullptr) return VIGEM_ERROR_INVALID_TARGET; - if (target->Notification == reinterpret_cast(notification)) + if (target->Notification == reinterpret_cast(notification)) return VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED; - // TODO: tidy up this mess - - target->Notification = reinterpret_cast(notification); + target->Notification = reinterpret_cast(notification); target->pool = std::make_shared( vigem, @@ -515,10 +513,10 @@ VIGEM_ERROR vigem_target_ds4_register_notification( if (target->SerialNo == 0 || notification == nullptr) return VIGEM_ERROR_INVALID_TARGET; - if (target->Notification == reinterpret_cast(notification)) + if (target->Notification == reinterpret_cast(notification)) return VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED; - target->Notification = reinterpret_cast(notification); + target->Notification = reinterpret_cast(notification); std::vector threadList; diff --git a/src/XusbNotificationRequest.cpp b/src/XusbNotificationRequest.cpp index 9929c12..a0b75b1 100644 --- a/src/XusbNotificationRequest.cpp +++ b/src/XusbNotificationRequest.cpp @@ -25,26 +25,31 @@ SOFTWARE. #include "XusbNotificationRequest.h" #include +#include +#include "Internal.h" +#include +#include XusbNotificationRequest::XusbNotificationRequest( - HANDLE bus, - ULONG serial, + PVIGEM_CLIENT client, + PVIGEM_TARGET target, HANDLE notification -) : parent_bus_(bus), +) : client_(client), + target_(target), payload_(), overlapped_() { memset(&overlapped_, 0, sizeof(OVERLAPPED)); overlapped_.hEvent = notification; - XUSB_REQUEST_NOTIFICATION_INIT(&payload_, serial); + XUSB_REQUEST_NOTIFICATION_INIT(&payload_, target_->SerialNo); } bool XusbNotificationRequest::request_async() { // queue request in driver const auto ret = DeviceIoControl( - parent_bus_, + client_->hBusDevice, IOCTL_XUSB_REQUEST_NOTIFICATION, &payload_, payload_.Size, @@ -59,6 +64,26 @@ bool XusbNotificationRequest::request_async() return (!ret && error == ERROR_IO_PENDING); } +void XusbNotificationRequest::post(boost::asio::io_service::strand strand) const +{ + // prepare queueing library caller notification callback + const boost::function pfn = PFN_VIGEM_X360_NOTIFICATION(target_->Notification); + + // submit callback for async yet ordered invocation + strand.post(boost::bind(pfn, + client_, + target_, + payload_.LargeMotor, + payload_.SmallMotor, + payload_.LedNumber + )); +} + UCHAR XusbNotificationRequest::get_led_number() const { return payload_.LedNumber; diff --git a/src/XusbNotificationRequest.h b/src/XusbNotificationRequest.h index 479d20e..84ec8c2 100644 --- a/src/XusbNotificationRequest.h +++ b/src/XusbNotificationRequest.h @@ -27,16 +27,20 @@ SOFTWARE. #include #include "ViGEm/km/BusShared.h" +#include +#include "ViGEm/Client.h" class XusbNotificationRequest { - HANDLE parent_bus_; + PVIGEM_CLIENT client_; + PVIGEM_TARGET target_; XUSB_REQUEST_NOTIFICATION payload_; OVERLAPPED overlapped_; public: - XusbNotificationRequest(HANDLE bus, ULONG serial, HANDLE notification); + XusbNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target, HANDLE notification); bool request_async(); + void post(boost::asio::io_service::strand strand) const; UCHAR get_led_number() const; UCHAR get_large_motor() const; From 435fa9750be6ef8b8216a3a6bed67a117537cef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 28 May 2019 18:02:41 +0200 Subject: [PATCH 064/107] Removed legacy functions --- src/XusbNotificationRequest.cpp | 15 --------------- src/XusbNotificationRequest.h | 4 ---- 2 files changed, 19 deletions(-) diff --git a/src/XusbNotificationRequest.cpp b/src/XusbNotificationRequest.cpp index a0b75b1..1a01cc9 100644 --- a/src/XusbNotificationRequest.cpp +++ b/src/XusbNotificationRequest.cpp @@ -83,18 +83,3 @@ void XusbNotificationRequest::post(boost::asio::io_service::strand strand) const payload_.LedNumber )); } - -UCHAR XusbNotificationRequest::get_led_number() const -{ - return payload_.LedNumber; -} - -UCHAR XusbNotificationRequest::get_large_motor() const -{ - return payload_.LargeMotor; -} - -UCHAR XusbNotificationRequest::get_small_motor() const -{ - return payload_.SmallMotor; -} diff --git a/src/XusbNotificationRequest.h b/src/XusbNotificationRequest.h index 84ec8c2..624f9d2 100644 --- a/src/XusbNotificationRequest.h +++ b/src/XusbNotificationRequest.h @@ -41,8 +41,4 @@ public: XusbNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target, HANDLE notification); bool request_async(); void post(boost::asio::io_service::strand strand) const; - - UCHAR get_led_number() const; - UCHAR get_large_motor() const; - UCHAR get_small_motor() const; }; From 267c0cc9d915f92941cad8c0bfbbc65532db94a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 28 May 2019 21:06:15 +0200 Subject: [PATCH 065/107] Removed unused variables --- .gitignore | 1 + src/NotificationRequestPool.cpp | 1 - src/NotificationRequestPool.h | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 3a5565e..3e59bb2 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,4 @@ /src/Release_DLL /app/Tester/Debug /Debug +/app/Tester/x64/Debug diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp index 89c9b08..b7b2eba 100644 --- a/src/NotificationRequestPool.cpp +++ b/src/NotificationRequestPool.cpp @@ -37,7 +37,6 @@ NotificationRequestPool::NotificationRequestPool( ) : client_(client), target_(target), - callback_(callback), stop_(false) { // prepare array of handles and request wrappers diff --git a/src/NotificationRequestPool.h b/src/NotificationRequestPool.h index 19fd7bf..d43b216 100644 --- a/src/NotificationRequestPool.h +++ b/src/NotificationRequestPool.h @@ -41,7 +41,6 @@ class NotificationRequestPool PVIGEM_CLIENT client_; PVIGEM_TARGET target_; - FARPROC callback_; std::vector> requests_; std::shared_ptr thread_; From 6f616adf5c158e23755a98d719aaf0aa9bb897c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 28 May 2019 21:18:33 +0200 Subject: [PATCH 066/107] Fixed x360 notification clean-up --- app/Tester/Tester.cpp | 1 + src/Internal.h | 2 +- src/NotificationRequestPool.cpp | 8 ++++---- src/NotificationRequestPool.h | 3 +-- src/ViGEmClient.cpp | 8 ++++---- src/XusbNotificationRequest.cpp | 2 +- src/XusbNotificationRequest.h | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp index 57dc1f0..dc8f4a9 100644 --- a/app/Tester/Tester.cpp +++ b/app/Tester/Tester.cpp @@ -54,6 +54,7 @@ int main() Sleep(10); } + vigem_target_x360_unregister_notification(x360); vigem_target_remove(client, x360); vigem_target_free(x360); vigem_free(client); diff --git a/src/Internal.h b/src/Internal.h index 0520691..a703fec 100644 --- a/src/Internal.h +++ b/src/Internal.h @@ -66,6 +66,6 @@ typedef struct _VIGEM_TARGET_T VIGEM_TARGET_TYPE Type; FARPROC Notification; - std::shared_ptr pool; + std::unique_ptr NotificationPool; } VIGEM_TARGET; diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp index b7b2eba..2dd9616 100644 --- a/src/NotificationRequestPool.cpp +++ b/src/NotificationRequestPool.cpp @@ -32,8 +32,7 @@ void NotificationRequestPool::strand_dispatch_worker() const NotificationRequestPool::NotificationRequestPool( PVIGEM_CLIENT client, - PVIGEM_TARGET target, - FARPROC callback + PVIGEM_TARGET target ) : client_(client), target_(target), @@ -73,10 +72,11 @@ NotificationRequestPool::~NotificationRequestPool() noexcept(false) for (auto& wait_handle : wait_handles_) CloseHandle(wait_handle); + for (auto& request : requests_) + request.reset(); + io_svc_->stop(); worker_thread_->join(); - - thread_->join(); } void NotificationRequestPool::operator()() diff --git a/src/NotificationRequestPool.h b/src/NotificationRequestPool.h index d43b216..eaca845 100644 --- a/src/NotificationRequestPool.h +++ b/src/NotificationRequestPool.h @@ -57,8 +57,7 @@ class NotificationRequestPool public: NotificationRequestPool( PVIGEM_CLIENT client, - PVIGEM_TARGET target, - FARPROC callback + PVIGEM_TARGET target ); ~NotificationRequestPool() noexcept(false); diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index d42ef63..ebb6192 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -486,10 +486,9 @@ VIGEM_ERROR vigem_target_x360_register_notification( target->Notification = reinterpret_cast(notification); - target->pool = std::make_shared( + target->NotificationPool = std::make_unique( vigem, - target, - reinterpret_cast(target->Notification) + target ); return VIGEM_ERROR_NONE; @@ -580,7 +579,8 @@ VIGEM_ERROR vigem_target_ds4_register_notification( void vigem_target_x360_unregister_notification(PVIGEM_TARGET target) { - target->Notification = NULL; + target->NotificationPool.reset(); + target->Notification = nullptr; } void vigem_target_ds4_unregister_notification(PVIGEM_TARGET target) diff --git a/src/XusbNotificationRequest.cpp b/src/XusbNotificationRequest.cpp index 1a01cc9..d951b44 100644 --- a/src/XusbNotificationRequest.cpp +++ b/src/XusbNotificationRequest.cpp @@ -64,7 +64,7 @@ bool XusbNotificationRequest::request_async() return (!ret && error == ERROR_IO_PENDING); } -void XusbNotificationRequest::post(boost::asio::io_service::strand strand) const +void XusbNotificationRequest::post(boost::asio::io_service::strand strand) { // prepare queueing library caller notification callback const boost::function Date: Tue, 28 May 2019 21:22:39 +0200 Subject: [PATCH 067/107] Updated README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9dd1798..0bb0dd3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Developer SDK for communication with `ViGEmBus`. -[![Build status](https://ci.appveyor.com/api/projects/status/k806d3m2egjr0j56?svg=true)](https://ci.appveyor.com/project/nefarius/vigemclient) [![Discord](https://img.shields.io/discord/346756263763378176.svg)](https://discord.gg/QTJpBX5) [![Website](https://img.shields.io/website-up-down-green-red/https/vigem.org.svg?label=ViGEm.org)](https://vigem.org/) [![PayPal Donate](https://img.shields.io/badge/paypal-donate-blue.svg)]() [![Support on Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)]() [![GitHub followers](https://img.shields.io/github/followers/nefarius.svg?style=social&label=Follow)](https://github.com/nefarius) [![Twitter Follow](https://img.shields.io/twitter/follow/nefariusmaximus.svg?style=social&label=Follow)](https://twitter.com/nefariusmaximus) +[![Build status](https://ci.appveyor.com/api/projects/status/k806d3m2egjr0j56?svg=true)](https://ci.appveyor.com/project/nefarius/vigemclient) [![Discord](https://img.shields.io/discord/346756263763378176.svg)](https://discord.vigem.org) [![Website](https://img.shields.io/website-up-down-green-red/https/vigem.org.svg?label=ViGEm.org)](https://vigem.org/) [![PayPal Donate](https://img.shields.io/badge/paypal-donate-blue.svg)]() [![Support on Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)]() [![GitHub followers](https://img.shields.io/github/followers/nefarius.svg?style=social&label=Follow)](https://github.com/nefarius) [![Twitter Follow](https://img.shields.io/twitter/follow/nefariusmaximus.svg?style=social&label=Follow)](https://twitter.com/nefariusmaximus) ## About @@ -10,15 +10,21 @@ TBD ## How to build +### Dependencies + +- [Boost.Asio](https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio.html) + ### Prerequisites - Visual Studio **2017** ([Community Edition](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) is just fine) - [.NET Core SDK 2.1](https://www.microsoft.com/net/download/dotnet-core/2.1) (or greater, required for building only) +- [Vcpkg Quick Start] + - `.\vcpkg.exe install boost-asio:x86-windows-static boost-asio:x64-windows-static` You can either build directly within Visual Studio or in PowerShell by running the build script: ```PowerShell -.\build.ps1 -configuration release +.\build.ps1 ``` ## Contribute From 5799777c822d332f6ce5b97526f255f23d96cc99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger?= Date: Fri, 26 Jul 2019 00:16:04 +0200 Subject: [PATCH 068/107] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bb0dd3..e9f53e7 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ TBD - Visual Studio **2017** ([Community Edition](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) is just fine) - [.NET Core SDK 2.1](https://www.microsoft.com/net/download/dotnet-core/2.1) (or greater, required for building only) -- [Vcpkg Quick Start] +- [Vcpkg Quick Start](https://github.com/Microsoft/vcpkg#quick-start) - `.\vcpkg.exe install boost-asio:x86-windows-static boost-asio:x64-windows-static` You can either build directly within Visual Studio or in PowerShell by running the build script: From ee90cef6eec289be77b0b01ef730ee8d865252d3 Mon Sep 17 00:00:00 2001 From: ttsuki Date: Fri, 2 Aug 2019 06:27:29 +0900 Subject: [PATCH 069/107] Fixed crash on destructing NotificationRequestPool --- src/NotificationRequestPool.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp index 2dd9616..d911eee 100644 --- a/src/NotificationRequestPool.cpp +++ b/src/NotificationRequestPool.cpp @@ -107,6 +107,13 @@ void NotificationRequestPool::operator()() continue; } + // handles are closed...? + if (ret == WAIT_FAILED) + { + // exits function (terminates thread) + break; + } + // index of the request which just got completed const auto index = ret - WAIT_OBJECT_0; // grab associated request From 02552a5f24f1fe4e31a3fde08643e1fde88f7097 Mon Sep 17 00:00:00 2001 From: mika-n Date: Mon, 19 Aug 2019 04:12:14 +0300 Subject: [PATCH 070/107] Removed NotificationPool and boost references. Created a new notification thread handler logic, which is simpler and more straight forward than use of BOOST:ASIO library. At the same time fixed a thread cleanup bug in unregister_notification functions (sometimes the old code crashed when a notifications was unregistered. There was some multithread cleanup issue). --- .gitignore | 5 + src/Internal.h | 7 +- src/ViGEmClient.cpp | 230 +++++++++++++++++++++++--------- src/ViGEmClient.vcxproj | 4 - src/ViGEmClient.vcxproj.filters | 12 -- 5 files changed, 173 insertions(+), 85 deletions(-) diff --git a/.gitignore b/.gitignore index 3e59bb2..f6b3aac 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,8 @@ /app/Tester/Debug /Debug /app/Tester/x64/Debug +/app/Tester/x64/Release/Tester.tlog +/app/Tester/x64/Release/Tester.log +/app/Tester/x64/Release/Tester.obj +/app/Tester/x64/Release/vc141.pdb +/app/Tester/x64/Release/vcpkg.applocal.log diff --git a/src/Internal.h b/src/Internal.h index a703fec..d8f52ea 100644 --- a/src/Internal.h +++ b/src/Internal.h @@ -51,7 +51,7 @@ typedef enum _VIGEM_TARGET_STATE VIGEM_TARGET_DISCONNECTED } VIGEM_TARGET_STATE, *PVIGEM_TARGET_STATE; -class NotificationRequestPool; + // // Represents a virtual gamepad object. @@ -66,6 +66,7 @@ typedef struct _VIGEM_TARGET_T VIGEM_TARGET_TYPE Type; FARPROC Notification; - std::unique_ptr NotificationPool; - + bool closingNotificationThreads; + HANDLE cancelNotificationThreadEvent; + std::unique_ptr> notificationThreadList; } VIGEM_TARGET; diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index ebb6192..748bb6c 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -44,9 +44,6 @@ SOFTWARE. #include "Internal.h" -#include "NotificationRequestPool.h" - - typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)( HANDLE hProcess, DWORD dwPid, @@ -60,6 +57,74 @@ typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)( LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExceptionInfo); +// +// DeviceIOControl request notification handler classes for X360 and DS4 controller types. +// vigem_target_XXX_register_notification functions use x360 or DS4 derived class instances in a notification thread handlers. +// +class NotificationRequestPayload +{ +public: + LPVOID lpPayloadBuffer; + DWORD payloadBufferSize; + DWORD ioControlCode; + +public: + NotificationRequestPayload(DWORD _bufferSize, DWORD _ioControlCode) + { + lpPayloadBuffer = malloc(_bufferSize); + payloadBufferSize = _bufferSize; + ioControlCode = _ioControlCode; + } + + virtual ~NotificationRequestPayload() + { + free(lpPayloadBuffer); + } + + virtual void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) = 0; +}; + +class NotificationRequestPayloadX360 : public NotificationRequestPayload +{ +public: + NotificationRequestPayloadX360(ULONG _serialNo) : NotificationRequestPayload(sizeof(XUSB_REQUEST_NOTIFICATION), IOCTL_XUSB_REQUEST_NOTIFICATION) + { + // Let base class to allocate required buffer size, but initialize it here with a correct type of initialization function + XUSB_REQUEST_NOTIFICATION_INIT((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer, _serialNo); + } + + void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) override + { + if(target->Notification != nullptr) + PFN_VIGEM_X360_NOTIFICATION(target->Notification)(client, target, + ((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LargeMotor, + ((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->SmallMotor, + ((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LedNumber + ); + } +}; + +class NotificationRequestPayloadDS4 : public NotificationRequestPayload +{ +public: + NotificationRequestPayloadDS4(ULONG _serialNo) : NotificationRequestPayload(sizeof(DS4_REQUEST_NOTIFICATION), IOCTL_DS4_REQUEST_NOTIFICATION) + { + // Let base class to allocate required buffer size, but initialize it here with a correct type of initialization function + DS4_REQUEST_NOTIFICATION_INIT((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer, _serialNo); + } + + void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) override + { + if (target->Notification != nullptr) + PFN_VIGEM_DS4_NOTIFICATION(target->Notification)(client, target, + ((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LargeMotor, + ((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.SmallMotor, + ((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LightbarColor + ); + } +}; + + // // Initializes a virtual gamepad object. // @@ -77,7 +142,7 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT( target->Size = sizeof(VIGEM_TARGET); target->State = VIGEM_TARGET_INITIALIZED; target->Type = Type; - + target->notificationThreadList = nullptr; return target; } @@ -288,8 +353,8 @@ PVIGEM_TARGET vigem_target_ds4_alloc(void) void vigem_target_free(PVIGEM_TARGET target) { - if (target) - free(target); + if (target) + free(target); } VIGEM_ERROR vigem_target_add(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) @@ -463,6 +528,57 @@ VIGEM_ERROR vigem_target_remove(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) return VIGEM_ERROR_REMOVAL_FAILED; } +void vigem_notification_thread_worker( + PVIGEM_CLIENT client, + PVIGEM_TARGET target, + std::unique_ptr pNotificationRequestPayload +) +{ + BOOL devIoResult; + DWORD error; + DWORD transferred = 0; + OVERLAPPED lOverlapped = { 0 }; + HANDLE waitObjects[2]; + waitObjects[0] = target->cancelNotificationThreadEvent; + waitObjects[1] = lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);; + + do + { + devIoResult = DeviceIoControl(client->hBusDevice, + pNotificationRequestPayload->ioControlCode, + pNotificationRequestPayload->lpPayloadBuffer, + pNotificationRequestPayload->payloadBufferSize, + pNotificationRequestPayload->lpPayloadBuffer, + pNotificationRequestPayload->payloadBufferSize, + &transferred, + &lOverlapped); + + if (!devIoResult) + { + if (GetLastError() == ERROR_IO_PENDING) + { + // DeviceIoControl is not yet completed to return all data. Wait for overlapped completion and thread cancellation events + error = WaitForMultipleObjects(2, waitObjects, FALSE, INFINITE); + if (error != (WAIT_OBJECT_0 + 1)) + break; // Cancel event signaled or error while waiting for events (maybe handles were closed?). Quit this thread worker + } + else + // Hmm... DeviceIoControl failed and is not just in async pending state. Quit the notification thread because the virtual controller may be in unknown state + break; + } + + if (GetOverlappedResult(client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) + pNotificationRequestPayload->ProcessNotificationRequest(client, target); + + } while (target->closingNotificationThreads != TRUE && target->Notification != nullptr); + + if (lOverlapped.hEvent) + CloseHandle(lOverlapped.hEvent); + + // Caller created the unique_ptr object, but this thread worker function should delete the object because it is no longer needed (thread specific object) + pNotificationRequestPayload.reset(); +} + VIGEM_ERROR vigem_target_x360_register_notification( PVIGEM_CLIENT vigem, PVIGEM_TARGET target, @@ -486,10 +602,18 @@ VIGEM_ERROR vigem_target_x360_register_notification( target->Notification = reinterpret_cast(notification); - target->NotificationPool = std::make_unique( - vigem, - target - ); + if (target->cancelNotificationThreadEvent == 0) + target->cancelNotificationThreadEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + else + ResetEvent(target->cancelNotificationThreadEvent); + + if(target->notificationThreadList == nullptr) + target->notificationThreadList = std::make_unique>(); + + target->closingNotificationThreads = FALSE; + + for (int i = 0; i < 20; i++) + target->notificationThreadList->emplace_back(std::thread(&vigem_notification_thread_worker, vigem, target, std::make_unique(target->SerialNo))); return VIGEM_ERROR_NONE; } @@ -517,75 +641,49 @@ VIGEM_ERROR vigem_target_ds4_register_notification( target->Notification = reinterpret_cast(notification); - std::vector threadList; + if (target->cancelNotificationThreadEvent == 0) + target->cancelNotificationThreadEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + else + ResetEvent(target->cancelNotificationThreadEvent); - for (int i = 0; i < 20 /* TODO: legacy, remove */; 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); + if (target->notificationThreadList == nullptr) + target->notificationThreadList = std::make_unique>(); - DS4_REQUEST_NOTIFICATION notify; - DS4_REQUEST_NOTIFICATION_INIT(¬ify, _Target->SerialNo); + target->closingNotificationThreads = FALSE; - do - { - DeviceIoControl(_Client->hBusDevice, - IOCTL_DS4_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_DS4_NOTIFICATION(_Target->Notification)( - _Client, - _Target, - notify.Report.LargeMotor, - notify.Report.SmallMotor, - notify.Report.LightbarColor); - } - 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 = 0; i < 20; i++) + target->notificationThreadList->emplace_back(std::thread(&vigem_notification_thread_worker, vigem, target, std::make_unique(target->SerialNo))); return VIGEM_ERROR_NONE; } void vigem_target_x360_unregister_notification(PVIGEM_TARGET target) { - target->NotificationPool.reset(); - target->Notification = nullptr; + target->closingNotificationThreads = TRUE; + + if (target->cancelNotificationThreadEvent != 0) + SetEvent(target->cancelNotificationThreadEvent); + + if (target->notificationThreadList != nullptr) + { + // Wait for completion of all notification threads before cleaning up target object and Notification function pointer (a thread may be in the middle of handling a notification request, so close it cleanly) + std::for_each(target->notificationThreadList->begin(), target->notificationThreadList->end(), std::mem_fn(&std::thread::join)); + target->notificationThreadList.reset(); + target->notificationThreadList = nullptr; + } + + if (target->cancelNotificationThreadEvent != 0) + { + CloseHandle(target->cancelNotificationThreadEvent); + target->cancelNotificationThreadEvent = 0; + } + + target->Notification = nullptr; } void vigem_target_ds4_unregister_notification(PVIGEM_TARGET target) { - target->Notification = NULL; + vigem_target_x360_unregister_notification(target); // The same x360_unregister handler works for DS4_unregister also } void vigem_target_set_vid(PVIGEM_TARGET target, USHORT vid) diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index f5fc0ea..12c905e 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -306,13 +306,9 @@ - - - - diff --git a/src/ViGEmClient.vcxproj.filters b/src/ViGEmClient.vcxproj.filters index ed9f98d..ae5b838 100644 --- a/src/ViGEmClient.vcxproj.filters +++ b/src/ViGEmClient.vcxproj.filters @@ -33,12 +33,6 @@ Header Files - - Header Files - - - Header Files - Header Files @@ -47,11 +41,5 @@ Source Files - - Source Files - - - Source Files - \ No newline at end of file From 0b8756d522f2dee0de9d56e91b66671df3970066 Mon Sep 17 00:00:00 2001 From: mika-n Date: Tue, 27 Aug 2019 15:11:50 +0300 Subject: [PATCH 071/107] Fine tuned notification background thread logic to make sure that received FFB events are passed on to a callback function in correct order (first-in, first-out). Also, the thread uses a ring buffer to pool IO requests and to make sure that at any time there is always at least one pending IO request ready to receive new FFB events from Vigem kernel driver. --- .gitignore | 14 ++++++ src/ViGEmClient.cpp | 112 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 102 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index f6b3aac..312b51e 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,17 @@ /app/Tester/x64/Release/Tester.obj /app/Tester/x64/Release/vc141.pdb /app/Tester/x64/Release/vcpkg.applocal.log +/app/Tester/Release/Tester.tlog/CL.command.1.tlog +/app/Tester/Release/Tester.tlog/CL.read.1.tlog +/app/Tester/Release/Tester.tlog/CL.write.1.tlog +/app/Tester/Release/Tester.tlog/link.command.1.tlog +/app/Tester/Release/Tester.tlog/link.read.1.tlog +/app/Tester/Release/Tester.tlog/link.write.1.tlog +/app/Tester/Release/Tester.tlog/Tester.lastbuildstate +/app/Tester/Release/Tester.tlog/Tester.write.1u.tlog +/app/Tester/Release/Tester.Build.CppClean.log +/app/Tester/Release/Tester.log +/app/Tester/Release/Tester.obj +/app/Tester/Release/vc141.pdb +/app/Tester/Release/vcpkg.applocal.log +/app/Tester/x64/Release/Tester.Build.CppClean.log diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 748bb6c..fa93121 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -528,52 +528,104 @@ VIGEM_ERROR vigem_target_remove(PVIGEM_CLIENT vigem, PVIGEM_TARGET target) return VIGEM_ERROR_REMOVAL_FAILED; } +// Num of items in Notification DeviceIOControl queue (at any time there should be at least one extra call waiting for the new events or there is danger that notification events are lost). +// The size of this queue is based on "scientific" experimentals and estimations (few games seem to sometimes flood the FFB driver interface). +#define NOTIFICATION_OVERLAPPED_QUEUE_SIZE 6 + void vigem_notification_thread_worker( PVIGEM_CLIENT client, PVIGEM_TARGET target, - std::unique_ptr pNotificationRequestPayload + std::unique_ptr >> pNotificationRequestPayload ) { - BOOL devIoResult; + int idx; DWORD error; - DWORD transferred = 0; - OVERLAPPED lOverlapped = { 0 }; + HANDLE waitObjects[2]; + + BOOL devIoResult[NOTIFICATION_OVERLAPPED_QUEUE_SIZE]; + DWORD lastIoError[NOTIFICATION_OVERLAPPED_QUEUE_SIZE]; + DWORD transferred[NOTIFICATION_OVERLAPPED_QUEUE_SIZE]; + OVERLAPPED lOverlapped[NOTIFICATION_OVERLAPPED_QUEUE_SIZE]; + + int currentOverlappedIdx; + int futureOverlappedIdx; + + memset(lOverlapped, 0, sizeof(lOverlapped)); + for(idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++) + lOverlapped[idx].hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + waitObjects[0] = target->cancelNotificationThreadEvent; - waitObjects[1] = lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);; + + currentOverlappedIdx = 0; + futureOverlappedIdx = NOTIFICATION_OVERLAPPED_QUEUE_SIZE - 1; + + // Send out DeviceIOControl calls to wait for incoming feedback notifications. Use N pending requests to make sure that events are not lost even when application would flood FFB events. + // The order of DeviceIoControl calls and GetOverlappedResult requests is important to ensure that feedback callback function is called in correct order (ie. FIFO buffer with FFB events). + // Note! This loop doesn't call DevIo for the last lOverlapped item on purpose. The DO while loop does it as a first step (futureOverlappedIdx=NOTIFICATION_OVERLAPPED_QUEUE_SIZE-1 in the first loop round). + for (idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE-1; idx++) + { + devIoResult[idx] = DeviceIoControl(client->hBusDevice, + (*pNotificationRequestPayload)[idx]->ioControlCode, + (*pNotificationRequestPayload)[idx]->lpPayloadBuffer, + (*pNotificationRequestPayload)[idx]->payloadBufferSize, + (*pNotificationRequestPayload)[idx]->lpPayloadBuffer, + (*pNotificationRequestPayload)[idx]->payloadBufferSize, + &transferred[idx], + &lOverlapped[idx]); + + lastIoError[idx] = GetLastError(); + } do { - devIoResult = DeviceIoControl(client->hBusDevice, - pNotificationRequestPayload->ioControlCode, - pNotificationRequestPayload->lpPayloadBuffer, - pNotificationRequestPayload->payloadBufferSize, - pNotificationRequestPayload->lpPayloadBuffer, - pNotificationRequestPayload->payloadBufferSize, - &transferred, - &lOverlapped); + // Before reading data from "current overlapped request" then send a new DeviceIoControl request to wait for upcoming new FFB events (ring buffer of overlapped objects). + devIoResult[futureOverlappedIdx] = DeviceIoControl(client->hBusDevice, + (*pNotificationRequestPayload)[futureOverlappedIdx]->ioControlCode, + (*pNotificationRequestPayload)[futureOverlappedIdx]->lpPayloadBuffer, + (*pNotificationRequestPayload)[futureOverlappedIdx]->payloadBufferSize, + (*pNotificationRequestPayload)[futureOverlappedIdx]->lpPayloadBuffer, + (*pNotificationRequestPayload)[futureOverlappedIdx]->payloadBufferSize, + &transferred[futureOverlappedIdx], + &lOverlapped[futureOverlappedIdx]); - if (!devIoResult) + lastIoError[futureOverlappedIdx] = GetLastError(); + + // currentOverlappedIdx is an index to the "oldest" DeviceIOControl call, so it will receive the next FFB event in a FFB sequence (in case there are multiple FFB events coming in) + if (!devIoResult[currentOverlappedIdx]) { - if (GetLastError() == ERROR_IO_PENDING) + if (lastIoError[currentOverlappedIdx] == ERROR_IO_PENDING) { // DeviceIoControl is not yet completed to return all data. Wait for overlapped completion and thread cancellation events + waitObjects[1] = lOverlapped[currentOverlappedIdx].hEvent; error = WaitForMultipleObjects(2, waitObjects, FALSE, INFINITE); if (error != (WAIT_OBJECT_0 + 1)) break; // Cancel event signaled or error while waiting for events (maybe handles were closed?). Quit this thread worker + + // At this point overlapped event was signaled by a device driver and data is ready and waiting for in a buffer. The next GetOverlappedResult call should return immediately. } else - // Hmm... DeviceIoControl failed and is not just in async pending state. Quit the notification thread because the virtual controller may be in unknown state + // Hmm... DeviceIoControl failed and is not just in async pending state. Quit the notification thread because the virtual controller may be in unknown state or device handles were closed break; } - if (GetOverlappedResult(client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0) - pNotificationRequestPayload->ProcessNotificationRequest(client, target); + if (GetOverlappedResult(client->hBusDevice, &lOverlapped[currentOverlappedIdx], &transferred[currentOverlappedIdx], TRUE) != 0) + (*pNotificationRequestPayload)[currentOverlappedIdx]->ProcessNotificationRequest(client, target); + if (currentOverlappedIdx >= NOTIFICATION_OVERLAPPED_QUEUE_SIZE-1) + currentOverlappedIdx = 0; + else + currentOverlappedIdx++; + + if (futureOverlappedIdx >= NOTIFICATION_OVERLAPPED_QUEUE_SIZE-1) + futureOverlappedIdx = 0; + else + futureOverlappedIdx++; } while (target->closingNotificationThreads != TRUE && target->Notification != nullptr); - if (lOverlapped.hEvent) - CloseHandle(lOverlapped.hEvent); + for (idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++) + if(lOverlapped[idx].hEvent) + CloseHandle(lOverlapped[idx].hEvent); // Caller created the unique_ptr object, but this thread worker function should delete the object because it is no longer needed (thread specific object) pNotificationRequestPayload.reset(); @@ -612,8 +664,15 @@ VIGEM_ERROR vigem_target_x360_register_notification( target->closingNotificationThreads = FALSE; - for (int i = 0; i < 20; i++) - target->notificationThreadList->emplace_back(std::thread(&vigem_notification_thread_worker, vigem, target, std::make_unique(target->SerialNo))); + std::unique_ptr>> payloadVector = std::make_unique>>(); + payloadVector->reserve(NOTIFICATION_OVERLAPPED_QUEUE_SIZE); + for (int idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++) + payloadVector->push_back(std::make_unique(target->SerialNo)); + + // Nowadays there is only one background thread listening for incoming FFB events, but there used to be more. This code still uses notificationThreadList vector even + // when there is only one item in the vector. If it is someday find out that this logic needs more background threads then it is easy to do because the thread vector is already in place. + //for (int i = 0; i < 1; i++) + target->notificationThreadList->emplace_back(std::thread(&vigem_notification_thread_worker, vigem, target, std::move(payloadVector))); return VIGEM_ERROR_NONE; } @@ -651,8 +710,13 @@ VIGEM_ERROR vigem_target_ds4_register_notification( target->closingNotificationThreads = FALSE; - for (int i = 0; i < 20; i++) - target->notificationThreadList->emplace_back(std::thread(&vigem_notification_thread_worker, vigem, target, std::make_unique(target->SerialNo))); + std::unique_ptr>> payloadVector = std::make_unique>>(); + payloadVector->reserve(NOTIFICATION_OVERLAPPED_QUEUE_SIZE); + for (int idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++) + payloadVector->push_back(std::make_unique(target->SerialNo)); + + //for (int i = 0; i < 1; i++) + target->notificationThreadList->emplace_back(std::thread(&vigem_notification_thread_worker, vigem, target, std::move(payloadVector))); return VIGEM_ERROR_NONE; } From 7420261dc38f5857a6ba0ac8ea436f29b6997840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 10:46:08 -0400 Subject: [PATCH 072/107] Removed obsolete files Removed Vcpkg attributes from project file Removed Vcpkg instructions and cache from appveyor.yml --- appveyor.yml | 6 -- src/NotificationRequestPool.cpp | 134 -------------------------------- src/NotificationRequestPool.h | 66 ---------------- src/ViGEmClient.vcxproj | 2 - src/XusbNotificationRequest.cpp | 85 -------------------- src/XusbNotificationRequest.h | 44 ----------- 6 files changed, 337 deletions(-) delete mode 100644 src/NotificationRequestPool.cpp delete mode 100644 src/NotificationRequestPool.h delete mode 100644 src/XusbNotificationRequest.cpp delete mode 100644 src/XusbNotificationRequest.h diff --git a/appveyor.yml b/appveyor.yml index 0b5b6a2..e10b69d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,15 +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: - path: 'bin**\*.dll' -cache: -- c:\tools\vcpkg\installed\ deploy: - provider: Environment name: BUILDBOT diff --git a/src/NotificationRequestPool.cpp b/src/NotificationRequestPool.cpp deleted file mode 100644 index d911eee..0000000 --- a/src/NotificationRequestPool.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* -MIT License - -Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 "NotificationRequestPool.h" - -void NotificationRequestPool::strand_dispatch_worker() const -{ - io_svc_->run(); -} - -NotificationRequestPool::NotificationRequestPool( - PVIGEM_CLIENT client, - PVIGEM_TARGET target -) : - client_(client), - target_(target), - stop_(false) -{ - // prepare array of handles and request wrappers - for (auto& wait_handle : wait_handles_) - { - // create auto-reset event - wait_handle = CreateEvent(nullptr, FALSE, FALSE, nullptr); - // create async pending I/O request wrapper - requests_.push_back(std::make_unique( - client_, - target_, - wait_handle - )); - } - - // init ASIO - io_svc_.reset(new boost::asio::io_service()); - worker_.reset(new boost::asio::io_service::work(*io_svc_)); - - // launch notification completion thread - thread_ = std::make_shared(boost::ref(*this)); - - // launch boost I/O service dispatcher thread - worker_thread_ = std::make_shared( - boost::bind(&NotificationRequestPool::strand_dispatch_worker, this)); - - // submit pending I/O to driver - for (auto& request : requests_) - request->request_async(); -} - -NotificationRequestPool::~NotificationRequestPool() noexcept(false) -{ - for (auto& wait_handle : wait_handles_) - CloseHandle(wait_handle); - - for (auto& request : requests_) - request.reset(); - - io_svc_->stop(); - worker_thread_->join(); -} - -void NotificationRequestPool::operator()() -{ - // used to dispatch notification callback - boost::asio::io_service::strand strand(*io_svc_); - - while (true) - { - // wait for the first pending I/O to signal its event - const auto ret = WaitForMultipleObjects( - requests_.size(), - wait_handles_, - FALSE, // first one to be signaled wins - 25 // don't block indefinitely so worker can be canceled - ); - - // timeout has occurred... - if (ret == WAIT_TIMEOUT) - { - // ...check for termination request - boost::mutex::scoped_lock lock(m_); - if (stop_) - // exits function (terminates thread) - break; - - // go for another round - continue; - } - - // handles are closed...? - if (ret == WAIT_FAILED) - { - // exits function (terminates thread) - break; - } - - // index of the request which just got completed - const auto index = ret - WAIT_OBJECT_0; - // grab associated request - const auto req = requests_[index].get(); - - // submit callback for async yet ordered invocation - req->post(std::move(strand)); - - // submit another pending I/O - req->request_async(); - } -} - -void NotificationRequestPool::terminate() -{ - boost::mutex::scoped_lock lock(m_); - stop_ = true; -} diff --git a/src/NotificationRequestPool.h b/src/NotificationRequestPool.h deleted file mode 100644 index eaca845..0000000 --- a/src/NotificationRequestPool.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -MIT License - -Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -#pragma once - -#include -#include -#include -#include -#include "XusbNotificationRequest.h" -#include "ViGEm/Client.h" -#include "Internal.h" - - -class NotificationRequestPool -{ - static const int thread_count = 20; - HANDLE wait_handles_[thread_count]{}; - - PVIGEM_CLIENT client_; - PVIGEM_TARGET target_; - - std::vector> requests_; - std::shared_ptr thread_; - boost::mutex m_; - boost::condition_variable cv_; - bool stop_; - - boost::shared_ptr io_svc_; - boost::shared_ptr worker_; - std::shared_ptr worker_thread_; - - void strand_dispatch_worker() const; - -public: - NotificationRequestPool( - PVIGEM_CLIENT client, - PVIGEM_TARGET target - ); - ~NotificationRequestPool() noexcept(false); - - void operator()(); - void terminate(); -}; diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index 12c905e..dddf1ba 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -38,8 +38,6 @@ {7DB06674-1F4F-464B-8E1C-172E9587F9DC} Win32Proj ViGEmClient - x86-windows-static - x64-windows-static diff --git a/src/XusbNotificationRequest.cpp b/src/XusbNotificationRequest.cpp deleted file mode 100644 index d951b44..0000000 --- a/src/XusbNotificationRequest.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -MIT License - -Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors - -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 -AUTHORS OR COPYRIGHT HOLDERS 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 "XusbNotificationRequest.h" -#include -#include -#include "Internal.h" -#include -#include - - -XusbNotificationRequest::XusbNotificationRequest( - PVIGEM_CLIENT client, - PVIGEM_TARGET target, - HANDLE notification -) : client_(client), - target_(target), - payload_(), - overlapped_() -{ - memset(&overlapped_, 0, sizeof(OVERLAPPED)); - overlapped_.hEvent = notification; - XUSB_REQUEST_NOTIFICATION_INIT(&payload_, target_->SerialNo); -} - -bool XusbNotificationRequest::request_async() -{ - // queue request in driver - const auto ret = DeviceIoControl( - client_->hBusDevice, - IOCTL_XUSB_REQUEST_NOTIFICATION, - &payload_, - payload_.Size, - &payload_, - payload_.Size, - nullptr, - &overlapped_ - ); - - const auto error = GetLastError(); - - return (!ret && error == ERROR_IO_PENDING); -} - -void XusbNotificationRequest::post(boost::asio::io_service::strand strand) -{ - // prepare queueing library caller notification callback - const boost::function pfn = PFN_VIGEM_X360_NOTIFICATION(target_->Notification); - - // submit callback for async yet ordered invocation - strand.post(boost::bind(pfn, - client_, - target_, - payload_.LargeMotor, - payload_.SmallMotor, - payload_.LedNumber - )); -} diff --git a/src/XusbNotificationRequest.h b/src/XusbNotificationRequest.h deleted file mode 100644 index 851a2d0..0000000 --- a/src/XusbNotificationRequest.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -MIT License - -Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors - -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 -AUTHORS OR COPYRIGHT HOLDERS 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. -*/ - - -#pragma once - -#include -#include "ViGEm/km/BusShared.h" -#include -#include "ViGEm/Client.h" - -class XusbNotificationRequest -{ - PVIGEM_CLIENT client_; - PVIGEM_TARGET target_; - XUSB_REQUEST_NOTIFICATION payload_; - OVERLAPPED overlapped_; - -public: - XusbNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target, HANDLE notification); - bool request_async(); - void post(boost::asio::io_service::strand strand); -}; From ff2fd11726b4705c652ab72b8edf87b6fc4b2af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 14:06:48 -0400 Subject: [PATCH 073/107] Updated nuke dependencies Removed outdated information from README.md --- README.md | 8 +------- build/_build.csproj | 9 ++++++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e9f53e7..845aca7 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,10 @@ TBD ## How to build -### Dependencies - -- [Boost.Asio](https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio.html) - ### Prerequisites - Visual Studio **2017** ([Community Edition](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) is just fine) -- [.NET Core SDK 2.1](https://www.microsoft.com/net/download/dotnet-core/2.1) (or greater, required for building only) -- [Vcpkg Quick Start](https://github.com/Microsoft/vcpkg#quick-start) - - `.\vcpkg.exe install boost-asio:x86-windows-static boost-asio:x64-windows-static` +- [.NET Core SDK 2.1](https://github.com/dotnet/cli/tree/release/2.1#installers-and-binaries) (or greater, required for building only) You can either build directly within Visual Studio or in PowerShell by running the build script: diff --git a/build/_build.csproj b/build/_build.csproj index f285fb8..8f86e40 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -11,9 +11,12 @@ - - - + + + all + runtime; build; native; contentfiles; analyzers + + From 4bf9e77e71d27ed67c86649a02456066cdb7b9d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 14:12:13 -0400 Subject: [PATCH 074/107] Removed GitVersion.CommandLine package --- build/Build.cs | 2 ++ build/_build.csproj | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/build/Build.cs b/build/Build.cs index c38d86e..589d656 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -60,6 +60,8 @@ class Build : NukeBuild var version = new Version(IsLocalBuild ? GitVersion.GetNormalizedFileVersion() : AppVeyor.Instance.BuildVersion); + Console.WriteLine($"Stamping version {version}"); + StampVersion( Path.Combine(RootDirectory, $@"bin\{Configuration}\x64\ViGEmClient.dll"), version); diff --git a/build/_build.csproj b/build/_build.csproj index 8f86e40..5ac5266 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -12,10 +12,6 @@ - - all - runtime; build; native; contentfiles; analyzers - From b75613cee31b6ced10aaba55b2633214945f6f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 14:14:23 -0400 Subject: [PATCH 075/107] Added GitVersion.CommandLine.DotNetCore --- build/_build.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/_build.csproj b/build/_build.csproj index 5ac5266..526f2f3 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -10,6 +10,10 @@ + + all + runtime; build; native; contentfiles; analyzers + From c134228cf1a6f2b242722f1b1d4f422e31920693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 14:21:29 -0400 Subject: [PATCH 076/107] Hopefully fixed stamping --- build/Build.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/build/Build.cs b/build/Build.cs index 589d656..11b850a 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -55,7 +55,7 @@ class Build : NukeBuild .SetNodeReuse(IsLocalBuild) .SetTargetPlatform(MSBuildTargetPlatform.x86)); - if (Configuration.Equals($"{Configuration}_dll", StringComparison.InvariantCultureIgnoreCase)) + if (Configuration.Contains($"{Configuration}_dll", StringComparison.InvariantCultureIgnoreCase)) { var version = new Version(IsLocalBuild ? GitVersion.GetNormalizedFileVersion() : AppVeyor.Instance.BuildVersion); @@ -122,4 +122,12 @@ class Build : NukeBuild versionResource.SaveTo(path); } +} + +public static class StringExtensions +{ + public static bool Contains(this string source, string toCheck, StringComparison comp) + { + return source?.IndexOf(toCheck, comp) >= 0; + } } \ No newline at end of file From 0fb762dfe3659c520b2270cb4424345a1012688b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 14:24:55 -0400 Subject: [PATCH 077/107] Argh --- build/Build.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/Build.cs b/build/Build.cs index 11b850a..3f6b7f6 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -55,6 +55,8 @@ class Build : NukeBuild .SetNodeReuse(IsLocalBuild) .SetTargetPlatform(MSBuildTargetPlatform.x86)); + Console.WriteLine($"!! {Configuration}"); + if (Configuration.Contains($"{Configuration}_dll", StringComparison.InvariantCultureIgnoreCase)) { var version = From f1086c0b93163ddd5e531910c4a8b779e4046767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 14:27:33 -0400 Subject: [PATCH 078/107] Oops --- build/Build.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/build/Build.cs b/build/Build.cs index 3f6b7f6..8586f90 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -15,7 +15,7 @@ using static Nuke.Common.Tools.MSBuild.MSBuildTasks; class Build : NukeBuild { [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] - private readonly string Configuration = IsLocalBuild ? "Debug" : "Release"; + private readonly string Configuration = IsLocalBuild ? "Debug_DLL" : "Release_DLL"; [GitRepository] private readonly GitRepository GitRepository; [GitVersion] private readonly GitVersion GitVersion; @@ -55,9 +55,7 @@ class Build : NukeBuild .SetNodeReuse(IsLocalBuild) .SetTargetPlatform(MSBuildTargetPlatform.x86)); - Console.WriteLine($"!! {Configuration}"); - - if (Configuration.Contains($"{Configuration}_dll", StringComparison.InvariantCultureIgnoreCase)) + if (Configuration.Equals($"{Configuration}_dll", StringComparison.InvariantCultureIgnoreCase)) { var version = new Version(IsLocalBuild ? GitVersion.GetNormalizedFileVersion() : AppVeyor.Instance.BuildVersion); @@ -125,11 +123,3 @@ class Build : NukeBuild versionResource.SaveTo(path); } } - -public static class StringExtensions -{ - public static bool Contains(this string source, string toCheck, StringComparison comp) - { - return source?.IndexOf(toCheck, comp) >= 0; - } -} \ No newline at end of file From 8331babf527d8e625442320074a7d4db13fc19a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 14:32:04 -0400 Subject: [PATCH 079/107] How did this ever work... --- build/Build.cs | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/build/Build.cs b/build/Build.cs index 8586f90..4a527bc 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -1,5 +1,3 @@ -using System; -using System.IO; using JsonConfig; using Nuke.Common; using Nuke.Common.BuildServers; @@ -7,6 +5,8 @@ using Nuke.Common.Git; using Nuke.Common.ProjectModel; using Nuke.Common.Tools.GitVersion; using Nuke.Common.Tools.MSBuild; +using System; +using System.IO; using Vestris.ResourceLib; using static Nuke.Common.IO.FileSystemTasks; using static Nuke.Common.IO.PathConstruction; @@ -21,7 +21,7 @@ class Build : NukeBuild [GitVersion] private readonly GitVersion GitVersion; [Solution("ViGEmClient.sln")] private readonly Solution Solution; - private AbsolutePath ArtifactsDirectory => RootDirectory / "artifacts"; + private AbsolutePath ArtifactsDirectory => RootDirectory / "bin"; private Target Clean => _ => _ .Executes(() => { EnsureCleanDirectory(ArtifactsDirectory); }); @@ -42,7 +42,7 @@ class Build : NukeBuild MSBuild(s => s .SetTargetPath(Solution) .SetTargets("Rebuild") - .SetConfiguration($"{Configuration}_DLL") + .SetConfiguration(Configuration) .SetMaxCpuCount(Environment.ProcessorCount) .SetNodeReuse(IsLocalBuild) .SetTargetPlatform(MSBuildTargetPlatform.x64)); @@ -50,26 +50,23 @@ class Build : NukeBuild MSBuild(s => s .SetTargetPath(Solution) .SetTargets("Rebuild") - .SetConfiguration($"{Configuration}_DLL") + .SetConfiguration(Configuration) .SetMaxCpuCount(Environment.ProcessorCount) .SetNodeReuse(IsLocalBuild) .SetTargetPlatform(MSBuildTargetPlatform.x86)); - if (Configuration.Equals($"{Configuration}_dll", StringComparison.InvariantCultureIgnoreCase)) - { - var version = - new Version(IsLocalBuild ? GitVersion.GetNormalizedFileVersion() : AppVeyor.Instance.BuildVersion); + var version = + new Version(IsLocalBuild ? GitVersion.GetNormalizedFileVersion() : AppVeyor.Instance.BuildVersion); - Console.WriteLine($"Stamping version {version}"); + Console.WriteLine($"Stamping version {version}"); - StampVersion( - Path.Combine(RootDirectory, $@"bin\{Configuration}\x64\ViGEmClient.dll"), - version); + StampVersion( + Path.Combine(RootDirectory, $@"bin\{Configuration}\x64\ViGEmClient.dll"), + version); - StampVersion( - Path.Combine(RootDirectory, $@"bin\{Configuration}\x86\ViGEmClient.dll"), - version); - } + StampVersion( + Path.Combine(RootDirectory, $@"bin\{Configuration}\x86\ViGEmClient.dll"), + version); }); private Target Pack => _ => _ From da35120a0ff55a3891084239b5873ab0d7ee4c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 14:35:58 -0400 Subject: [PATCH 080/107] How can this be so broken... --- build/Build.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build/Build.cs b/build/Build.cs index 4a527bc..a630381 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -61,11 +61,15 @@ class Build : NukeBuild Console.WriteLine($"Stamping version {version}"); StampVersion( - Path.Combine(RootDirectory, $@"bin\{Configuration}\x64\ViGEmClient.dll"), + Path.Combine( + RootDirectory, + $@"bin\{Configuration.Substring(0, Configuration.Length - 4)}\x64\ViGEmClient.dll"), version); StampVersion( - Path.Combine(RootDirectory, $@"bin\{Configuration}\x86\ViGEmClient.dll"), + Path.Combine( + RootDirectory, + $@"bin\{Configuration.Substring(0, Configuration.Length - 4)}\x86\ViGEmClient.dll"), version); }); From 204b4b1891336ce80bb3523fa40140c8554c5b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 15:10:34 -0400 Subject: [PATCH 081/107] Updated copyright information --- build/default.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/default.json b/build/default.json index 5af32c1..c676756 100644 --- a/build/default.json +++ b/build/default.json @@ -1,9 +1,9 @@ { "Version": { - "CompanyName": "Benjamin Hoeglinger-Stelzer", + "CompanyName": "Nefarius Software Solutions e.U.", "FileDescription": "Virtual Gamepad Emulation Framework User-Mode Library", "InternalName": "ViGEmClient", - "LegalCopyright": "Copyright (C) 2017-2018 Benjamin Hoeglinger-Stelzer All Rights Reserved", + "LegalCopyright": "Copyright (C) 2017-2019 Benjamin Hoeglinger-Stelzer All Rights Reserved", "OriginalFilename": "ViGEmClient", "ProductName": "Virtual Gamepad Emulation Framework User-Mode Library" } From 6e597da2d26fa047d016aeda0101bcdf4da920fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 15:15:05 -0400 Subject: [PATCH 082/107] Added lib files as build artifacts --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index e10b69d..e6b7f08 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,6 +3,7 @@ image: Visual Studio 2017 build_script: - ps: .\build.ps1 artifacts: +- path: 'bin**\*.lib' - path: 'bin**\*.dll' deploy: - provider: Environment From 3ff5759bba25be9655b75fbc03cba8e5e7b2add3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Tue, 27 Aug 2019 15:45:29 -0400 Subject: [PATCH 083/107] Updated README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 845aca7..1b932d9 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ You can either build directly within Visual Studio or in PowerShell by running t Found a bug and want it fixed? Open a detailed issue on the [GitHub issue tracker](../../issues)! -Have an idea for a new feature? [Check out the project board](https://projects.vigem.org/public/board/27281599595f5fbe5f915884fb9ca2de92726e74173f1ac434300b2d40af), maybe it's already on there! If not, let's have a chat about your request on [Discord](https://discord.vigem.org) or the [community forums](https://forums.vigem.org). +Have an idea for a new feature? Let's have a chat about your request on [Discord](https://discord.vigem.org) or the [community forums](https://forums.vigem.org). ### Questions & Support From 121a1b7f49ed16db4caf83bda4f08a981064aa9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Wed, 2 Oct 2019 15:06:42 +0200 Subject: [PATCH 084/107] Checked for null parameter in vigem_target_x360_get_user_index Added error code VIGEM_ERROR_INVALID_PARAMETER --- include/ViGEm/Client.h | 4 +++- src/ViGEmClient.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/ViGEm/Client.h b/include/ViGEm/Client.h index 48aaa45..3a85a60 100644 --- a/include/ViGEm/Client.h +++ b/include/ViGEm/Client.h @@ -63,7 +63,9 @@ extern "C" { VIGEM_ERROR_CALLBACK_NOT_FOUND = 0xE0000011, VIGEM_ERROR_BUS_ALREADY_CONNECTED = 0xE0000012, VIGEM_ERROR_BUS_INVALID_HANDLE = 0xE0000013, - VIGEM_ERROR_XUSB_USERINDEX_OUT_OF_RANGE = 0xE0000014 + VIGEM_ERROR_XUSB_USERINDEX_OUT_OF_RANGE = 0xE0000014, + VIGEM_ERROR_INVALID_PARAMETER = 0xE0000015 + } VIGEM_ERROR; /** diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index fa93121..daf75c7 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -907,6 +907,9 @@ VIGEM_ERROR vigem_target_x360_get_user_index( if (target->SerialNo == 0 || target->Type != Xbox360Wired) return VIGEM_ERROR_INVALID_TARGET; + if (!index) + return VIGEM_ERROR_INVALID_PARAMETER; + DWORD transferred = 0; OVERLAPPED lOverlapped = { 0 }; lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); From 593dc53d8ea9baa0d3006f3da58318bb05dc2a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 11 Nov 2019 20:52:38 +0100 Subject: [PATCH 085/107] Fixed build settings for nuke Added debug symbols to artifacts --- ViGEmClient.sln | 12 ------------ appveyor.yml | 1 + 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/ViGEmClient.sln b/ViGEmClient.sln index acd5cb8..42551db 100644 --- a/ViGEmClient.sln +++ b/ViGEmClient.sln @@ -52,29 +52,17 @@ Global {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x86.ActiveCfg = Release_LIB|Win32 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|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}.Debug|x64.ActiveCfg = Debug|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug|x64.Build.0 = Debug|Any CPU {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug|x86.ActiveCfg = Debug|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug|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 {A11CD588-F74A-41B5-9E5B-E60937052009}.Release|x64.ActiveCfg = Release|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Release|x64.Build.0 = Release|Any CPU {A11CD588-F74A-41B5-9E5B-E60937052009}.Release|x86.ActiveCfg = Release|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Release|x86.Build.0 = Release|Any CPU {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x64.ActiveCfg = Debug|x64 {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x64.Build.0 = Debug|x64 {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x86.ActiveCfg = Debug|Win32 diff --git a/appveyor.yml b/appveyor.yml index e6b7f08..710f231 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,6 +5,7 @@ build_script: artifacts: - path: 'bin**\*.lib' - path: 'bin**\*.dll' +- path: 'bin**\*.pdb' deploy: - provider: Environment name: BUILDBOT From 20d6d7565753438933ed8f08d80801c87afc4a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 11 Nov 2019 21:37:14 +0100 Subject: [PATCH 086/107] Improved crash dump handler --- src/ViGEmClient.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index daf75c7..cc23494 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -162,6 +162,12 @@ LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExcep nullptr ); + const DWORD flags = MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | + MiniDumpWithUnloadedModules | MiniDumpWithProcessThreadData | + MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo | + MiniDumpWithFullAuxiliaryState | MiniDumpIgnoreInaccessibleMemory | + MiniDumpWithTokenInformation; + if (hFile != INVALID_HANDLE_VALUE) { _MINIDUMP_EXCEPTION_INFORMATION ExInfo; @@ -169,7 +175,15 @@ LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExcep ExInfo.ExceptionPointers = apExceptionInfo; ExInfo.ClientPointers = FALSE; - pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, nullptr, nullptr); + pDump( + GetCurrentProcess(), + GetCurrentProcessId(), + hFile, + (MINIDUMP_TYPE)flags, + &ExInfo, + nullptr, + nullptr + ); CloseHandle(hFile); } From 9d2443ed0019483f53df7f882e1637a2b732e18e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Thu, 14 Nov 2019 18:46:02 +0100 Subject: [PATCH 087/107] Attempted to fix issue #5 Added basic DS4 test code to tester application --- app/Tester/Tester.cpp | 30 ++++++++++++++++++++++++++++-- app/Tester/Tester.vcxproj | 10 +++++----- appveyor.yml | 2 +- src/ViGEmClient.cpp | 12 +++++++++++- src/ViGEmClient.vcxproj | 18 +++++++++--------- 5 files changed, 54 insertions(+), 18 deletions(-) diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp index dc8f4a9..0dc3074 100644 --- a/app/Tester/Tester.cpp +++ b/app/Tester/Tester.cpp @@ -38,12 +38,19 @@ int main() auto ret = vigem_connect(client); +#if X360 const auto x360 = vigem_target_x360_alloc(); - ret = vigem_target_add(client, x360); + ret = vigem_target_add(client, x360); - ret = vigem_target_x360_register_notification(client, x360, ¬ification); + ret = vigem_target_x360_register_notification(client, x360, ¬ification); +#endif + + const auto ds4 = vigem_target_ds4_alloc(); + + ret = vigem_target_add(client, ds4); +#if X360 XUSB_REPORT report; XUSB_REPORT_INIT(&report); @@ -54,8 +61,27 @@ int main() Sleep(10); } +#endif + + DS4_REPORT report; + DS4_REPORT_INIT(&report); + + while (!(GetAsyncKeyState(VK_ESCAPE) & 0x8000)) + { + ret = vigem_target_ds4_update(client, ds4, report); + report.bThumbLX++; + report.wButtons |= DS4_BUTTON_CIRCLE; + Sleep(10); + } + +#if X360 vigem_target_x360_unregister_notification(x360); vigem_target_remove(client, x360); vigem_target_free(x360); +#endif + + vigem_target_remove(client, ds4); + vigem_target_free(ds4); + vigem_free(client); } diff --git a/app/Tester/Tester.vcxproj b/app/Tester/Tester.vcxproj index 045ec6d..2dcc7f4 100644 --- a/app/Tester/Tester.vcxproj +++ b/app/Tester/Tester.vcxproj @@ -23,32 +23,32 @@ {2F4ED0AB-0B51-4506-91AA-1984C5D44B85} Win32Proj Tester - 10.0.17763.0 + 10.0 Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/appveyor.yml b/appveyor.yml index 710f231..cb72e00 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ version: 1.16.{build}.0 -image: Visual Studio 2017 +image: Visual Studio 2019 build_script: - ps: .\build.ps1 artifacts: diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index cc23494..8055d82 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -23,11 +23,17 @@ SOFTWARE. */ +// +// WinAPI +// #include #include #include #include +// +// Driver shared +// #include "ViGEm/km/BusShared.h" #include "ViGEm/Client.h" #include @@ -39,11 +45,15 @@ SOFTWARE. #include #include #include - #include +#include +// +// Internal +// #include "Internal.h" + typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)( HANDLE hProcess, DWORD dwPid, diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index dddf1ba..3e6c8c9 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -42,59 +42,59 @@ $([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0')) - $(LatestTargetPlatformVersion) + 10.0 $(WindowsTargetPlatformVersion) StaticLibrary true - v141 + v142 Unicode DynamicLibrary true - v141 + v142 Unicode StaticLibrary false - v141 + v142 true Unicode DynamicLibrary false - v141 + v142 true Unicode StaticLibrary true - v141 + v142 Unicode DynamicLibrary true - v141 + v142 Unicode StaticLibrary false - v141 + v142 true Unicode DynamicLibrary false - v141 + v142 true Unicode From 27516cb05e666124dcb2f086591eed2fc06b70bc Mon Sep 17 00:00:00 2001 From: Jason Hart Date: Thu, 14 Nov 2019 13:18:58 -0500 Subject: [PATCH 088/107] Fix a missed bug that causes errors when using 'Prefer 32-bit' --- include/ViGEm/Client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ViGEm/Client.h b/include/ViGEm/Client.h index 3a85a60..6b31b30 100644 --- a/include/ViGEm/Client.h +++ b/include/ViGEm/Client.h @@ -120,7 +120,7 @@ extern "C" { typedef _Function_class_(EVT_VIGEM_DS4_NOTIFICATION) - VOID + VOID CALLBACK EVT_VIGEM_DS4_NOTIFICATION( PVIGEM_CLIENT Client, PVIGEM_TARGET Target, From 52682b59c458388a74afbc3d7ef23de21983a86f Mon Sep 17 00:00:00 2001 From: Jason Hart Date: Thu, 14 Nov 2019 13:58:13 -0500 Subject: [PATCH 089/107] Update Licensing --- include/ViGEm/Client.h | 2 +- include/ViGEm/Common.h | 2 +- include/ViGEm/km/BusShared.h | 2 +- src/ViGEmClient.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/ViGEm/Client.h b/include/ViGEm/Client.h index 6b31b30..722f3f4 100644 --- a/include/ViGEm/Client.h +++ b/include/ViGEm/Client.h @@ -1,7 +1,7 @@ /* MIT License -Copyright (c) 2017 Benjamin "Nefarius" Höglinger +Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/include/ViGEm/Common.h b/include/ViGEm/Common.h index 990b50e..fde8e30 100644 --- a/include/ViGEm/Common.h +++ b/include/ViGEm/Common.h @@ -1,7 +1,7 @@ /* MIT License -Copyright (c) 2017 Benjamin "Nefarius" Höglinger +Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/include/ViGEm/km/BusShared.h b/include/ViGEm/km/BusShared.h index c4b5d55..9a1a69c 100644 --- a/include/ViGEm/km/BusShared.h +++ b/include/ViGEm/km/BusShared.h @@ -1,7 +1,7 @@ /* MIT License -Copyright (c) 2016 Benjamin "Nefarius" Höglinger +Copyright (c) 2016-2019 Nefarius Software Solutions e.U. and Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 8055d82..e4d0b88 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -1,7 +1,7 @@ /* MIT License -Copyright (c) 2017 Benjamin "Nefarius" Höglinger +Copyright (c) 2017-2019 Nefarius Software Solutions e.U. and Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From b0220256428b94bee9379c306c0b77b61840e963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 1 Feb 2020 20:34:41 +0100 Subject: [PATCH 090/107] Removed nuke Added rc file --- .nuke | 1 - README.md | 9 +-- ViGEmClient.sln | 18 +---- build.ps1 | 65 ---------------- build.sh | 68 ----------------- build/Build.cs | 126 -------------------------------- build/_build.csproj | 44 ----------- build/default.json | 10 --- src/ViGEmClient.rc | 110 ++++++++++++++++++++++++++++ src/ViGEmClient.vcxproj | 4 + src/ViGEmClient.vcxproj.filters | 8 ++ src/resource.h | 14 ++++ 12 files changed, 139 insertions(+), 338 deletions(-) delete mode 100644 .nuke delete mode 100644 build.ps1 delete mode 100644 build.sh delete mode 100644 build/Build.cs delete mode 100644 build/_build.csproj delete mode 100644 build/default.json create mode 100644 src/ViGEmClient.rc create mode 100644 src/resource.h diff --git a/.nuke b/.nuke deleted file mode 100644 index a9c2c79..0000000 --- a/.nuke +++ /dev/null @@ -1 +0,0 @@ -ViGEmClient.sln \ No newline at end of file diff --git a/README.md b/README.md index 1b932d9..a467c6b 100644 --- a/README.md +++ b/README.md @@ -12,14 +12,7 @@ TBD ### Prerequisites -- Visual Studio **2017** ([Community Edition](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) is just fine) -- [.NET Core SDK 2.1](https://github.com/dotnet/cli/tree/release/2.1#installers-and-binaries) (or greater, required for building only) - -You can either build directly within Visual Studio or in PowerShell by running the build script: - -```PowerShell -.\build.ps1 -``` +- Visual Studio **2019** ([Community Edition](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=16) is just fine) ## Contribute diff --git a/ViGEmClient.sln b/ViGEmClient.sln index 42551db..4c2877b 100644 --- a/ViGEmClient.sln +++ b/ViGEmClient.sln @@ -1,12 +1,10 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2024 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29709.97 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ViGEmClient", "src\ViGEmClient.vcxproj", "{7DB06674-1F4F-464B-8E1C-172E9587F9DC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{A11CD588-F74A-41B5-9E5B-E60937052009}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "App", "App", "{8169FFB3-60F9-4A0C-B172-8E26B982B45F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tester", "app\Tester\Tester.vcxproj", "{2F4ED0AB-0B51-4506-91AA-1984C5D44B85}" @@ -51,18 +49,6 @@ Global {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x64.Build.0 = Release_LIB|x64 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x86.ActiveCfg = Release_LIB|Win32 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|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|x86.ActiveCfg = Debug|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug_LIB|x64.ActiveCfg = Debug|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug_LIB|x86.ActiveCfg = Debug|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug|x64.ActiveCfg = Debug|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Debug|x86.ActiveCfg = Debug|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_DLL|x64.ActiveCfg = Release|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_DLL|x86.ActiveCfg = Release|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_LIB|x64.ActiveCfg = Release|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Release_LIB|x86.ActiveCfg = Release|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Release|x64.ActiveCfg = Release|Any CPU - {A11CD588-F74A-41B5-9E5B-E60937052009}.Release|x86.ActiveCfg = Release|Any CPU {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x64.ActiveCfg = Debug|x64 {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x64.Build.0 = Debug|x64 {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x86.ActiveCfg = Debug|Win32 diff --git a/build.ps1 b/build.ps1 deleted file mode 100644 index 728f31b..0000000 --- a/build.ps1 +++ /dev/null @@ -1,65 +0,0 @@ -[CmdletBinding()] -Param( - #[switch]$CustomParam, - [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] - [string[]]$BuildArguments -) - -Write-Output "Windows PowerShell $($Host.Version)" - -Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { $host.SetShouldExit(1) } -$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent - -########################################################################### -# CONFIGURATION -########################################################################### - -$BuildProjectFile = "$PSScriptRoot\build\_build.csproj" -$TempDirectory = "$PSScriptRoot\\.tmp" - -$DotNetGlobalFile = "$PSScriptRoot\\global.json" -$DotNetInstallUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1" -$DotNetReleasesUrl = "https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases.json" - -$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1 -$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 -$env:NUGET_XMLDOC_MODE = "skip" - -########################################################################### -# EXECUTION -########################################################################### - -function ExecSafe([scriptblock] $cmd) { - & $cmd - if ($LASTEXITCODE) { exit $LASTEXITCODE } -} - -# If global.json exists, load expected version -if (Test-Path $DotNetGlobalFile) { - $DotNetVersion = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json).sdk.version -} - -# If dotnet is installed locally, and expected version is not set or installation matches the expected version -if ((Get-Command "dotnet" -ErrorAction SilentlyContinue) -ne $null -and ` - (!(Test-Path variable:DotNetVersion) -or $(& dotnet --version) -eq $DotNetVersion)) { - $env:DOTNET_EXE = (Get-Command "dotnet").Path -} -else { - $DotNetDirectory = "$TempDirectory\dotnet-win" - $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe" - - # If expected version is not set, get latest version - if (!(Test-Path variable:DotNetVersion)) { - $DotNetVersion = $(Invoke-WebRequest -UseBasicParsing $DotNetReleasesUrl | ConvertFrom-Json)[0]."version-sdk" - } - - # Download and execute install script - $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" - md -force $TempDirectory > $null - (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) - ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } -} - -Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)" - -ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile -- $BuildArguments } diff --git a/build.sh b/build.sh deleted file mode 100644 index 7dfb86b..0000000 --- a/build.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env bash - -echo $(bash --version 2>&1 | head -n 1) - -#CUSTOMPARAM=0 -BUILD_ARGUMENTS=() -for i in "$@"; do - case $(echo $1 | awk '{print tolower($0)}') in - # -custom-param) CUSTOMPARAM=1;; - *) BUILD_ARGUMENTS+=("$1") ;; - esac - shift -done - -set -eo pipefail -SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) - -########################################################################### -# CONFIGURATION -########################################################################### - -BUILD_PROJECT_FILE="$SCRIPT_DIR/build/_build.csproj" -TEMP_DIRECTORY="$SCRIPT_DIR//.tmp" - -DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" -DOTNET_INSTALL_URL="https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.sh" -DOTNET_RELEASES_URL="https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases.json" - -export DOTNET_CLI_TELEMETRY_OPTOUT=1 -export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 -export NUGET_XMLDOC_MODE="skip" - -########################################################################### -# EXECUTION -########################################################################### - -function FirstJsonValue { - perl -nle 'print $1 if m{"'$1'": "([^"\-]+)",?}' <<< ${@:2} -} - -# If global.json exists, load expected version -if [ -f "$DOTNET_GLOBAL_FILE" ]; then - DOTNET_VERSION=$(FirstJsonValue "version" $(cat "$DOTNET_GLOBAL_FILE")) -fi - -# If dotnet is installed locally, and expected version is not set or installation matches the expected version -if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version) == "$DOTNET_VERSION") ]]; then - export DOTNET_EXE="$(command -v dotnet)" -else - DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" - export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" - - # If expected version is not set, get latest version - if [ -z ${DOTNET_VERSION+x} ]; then - DOTNET_VERSION=$(FirstJsonValue "version-sdk" $(curl -s "$DOTNET_RELEASES_URL")) - fi - - # Download and execute install script - DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" - mkdir -p "$TEMP_DIRECTORY" - curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" - chmod +x "$DOTNET_INSTALL_FILE" - "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path -fi - -echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)" - -"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]} diff --git a/build/Build.cs b/build/Build.cs deleted file mode 100644 index a630381..0000000 --- a/build/Build.cs +++ /dev/null @@ -1,126 +0,0 @@ -using JsonConfig; -using Nuke.Common; -using Nuke.Common.BuildServers; -using Nuke.Common.Git; -using Nuke.Common.ProjectModel; -using Nuke.Common.Tools.GitVersion; -using Nuke.Common.Tools.MSBuild; -using System; -using System.IO; -using Vestris.ResourceLib; -using static Nuke.Common.IO.FileSystemTasks; -using static Nuke.Common.IO.PathConstruction; -using static Nuke.Common.Tools.MSBuild.MSBuildTasks; - -class Build : NukeBuild -{ - [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] - private readonly string Configuration = IsLocalBuild ? "Debug_DLL" : "Release_DLL"; - - [GitRepository] private readonly GitRepository GitRepository; - [GitVersion] private readonly GitVersion GitVersion; - - [Solution("ViGEmClient.sln")] private readonly Solution Solution; - private AbsolutePath ArtifactsDirectory => RootDirectory / "bin"; - - private Target Clean => _ => _ - .Executes(() => { EnsureCleanDirectory(ArtifactsDirectory); }); - - private Target Restore => _ => _ - .DependsOn(Clean) - .Executes(() => - { - MSBuild(s => s - .SetTargetPath(Solution) - .SetTargets("Restore")); - }); - - private Target Compile => _ => _ - .DependsOn(Restore) - .Executes(() => - { - MSBuild(s => s - .SetTargetPath(Solution) - .SetTargets("Rebuild") - .SetConfiguration(Configuration) - .SetMaxCpuCount(Environment.ProcessorCount) - .SetNodeReuse(IsLocalBuild) - .SetTargetPlatform(MSBuildTargetPlatform.x64)); - - MSBuild(s => s - .SetTargetPath(Solution) - .SetTargets("Rebuild") - .SetConfiguration(Configuration) - .SetMaxCpuCount(Environment.ProcessorCount) - .SetNodeReuse(IsLocalBuild) - .SetTargetPlatform(MSBuildTargetPlatform.x86)); - - var version = - new Version(IsLocalBuild ? GitVersion.GetNormalizedFileVersion() : AppVeyor.Instance.BuildVersion); - - Console.WriteLine($"Stamping version {version}"); - - StampVersion( - Path.Combine( - RootDirectory, - $@"bin\{Configuration.Substring(0, Configuration.Length - 4)}\x64\ViGEmClient.dll"), - version); - - StampVersion( - Path.Combine( - RootDirectory, - $@"bin\{Configuration.Substring(0, Configuration.Length - 4)}\x86\ViGEmClient.dll"), - version); - }); - - private Target Pack => _ => _ - .DependsOn(Compile) - .Executes(() => - { - MSBuild(s => s - .SetTargetPath(Solution) - .SetTargets("Restore", "Pack") - .SetPackageOutputPath(ArtifactsDirectory) - .SetConfiguration(Configuration) - .EnableIncludeSymbols()); - }); - - public static int Main() - { - return Execute(x => x.Compile); - } - - private static void StampVersion(string path, Version version) - { - var versionResource = new VersionResource - { - FileVersion = version.ToString(), - ProductVersion = version.ToString() - }; - - var stringFileInfo = new StringFileInfo(); - versionResource[stringFileInfo.Key] = stringFileInfo; - var stringFileInfoStrings = new StringTable - { - LanguageID = 1033, - CodePage = 1200 - }; - stringFileInfo.Strings.Add(stringFileInfoStrings.Key, stringFileInfoStrings); - stringFileInfoStrings["CompanyName"] = Config.Global.Version.CompanyName; - stringFileInfoStrings["FileDescription"] = Config.Global.Version.FileDescription; - stringFileInfoStrings["FileVersion"] = version.ToString(); - stringFileInfoStrings["InternalName"] = Config.Global.Version.InternalName; - stringFileInfoStrings["LegalCopyright"] = Config.Global.Version.LegalCopyright; - stringFileInfoStrings["OriginalFilename"] = Config.Global.Version.OriginalFilename; - stringFileInfoStrings["ProductName"] = Config.Global.Version.ProductName; - stringFileInfoStrings["ProductVersion"] = version.ToString(); - - var varFileInfo = new VarFileInfo(); - versionResource[varFileInfo.Key] = varFileInfo; - var varFileInfoTranslation = new VarTable("Translation"); - varFileInfo.Vars.Add(varFileInfoTranslation.Key, varFileInfoTranslation); - varFileInfoTranslation[ResourceUtil.USENGLISHLANGID] = 1300; - - versionResource.SaveTo(path); - } -} diff --git a/build/_build.csproj b/build/_build.csproj deleted file mode 100644 index 526f2f3..0000000 --- a/build/_build.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - Exe - netcoreapp2.0 - false - - False - CS0649;CS0169 - - - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - - - - - - - - Never - - - - - - - - - - - - - - - diff --git a/build/default.json b/build/default.json deleted file mode 100644 index c676756..0000000 --- a/build/default.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Version": { - "CompanyName": "Nefarius Software Solutions e.U.", - "FileDescription": "Virtual Gamepad Emulation Framework User-Mode Library", - "InternalName": "ViGEmClient", - "LegalCopyright": "Copyright (C) 2017-2019 Benjamin Hoeglinger-Stelzer All Rights Reserved", - "OriginalFilename": "ViGEmClient", - "ProductName": "Virtual Gamepad Emulation Framework User-Mode Library" - } -} \ No newline at end of file diff --git a/src/ViGEmClient.rc b/src/ViGEmClient.rc new file mode 100644 index 0000000..0c94343 --- /dev/null +++ b/src/ViGEmClient.rc @@ -0,0 +1,110 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (United Kingdom) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "Nefarius Software Solutions e.U." + VALUE "FileDescription", "Virtual Gamepad Emulation Framework User-Mode Library" + VALUE "FileVersion", "1.0.0.1" + VALUE "InternalName", "ViGEmClient.dll" + VALUE "LegalCopyright", "Copyright (C) 2017-2020 Nefarius Software Solutions e.U." + VALUE "OriginalFilename", "ViGEmClient.dll" + VALUE "ProductName", "Virtual Gamepad Emulation Framework User-Mode Library" + VALUE "ProductVersion", "1.0.0.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1200 + END +END + +#endif // English (United Kingdom) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/ViGEmClient.vcxproj b/src/ViGEmClient.vcxproj index 3e6c8c9..88bd185 100644 --- a/src/ViGEmClient.vcxproj +++ b/src/ViGEmClient.vcxproj @@ -304,10 +304,14 @@ + + + + diff --git a/src/ViGEmClient.vcxproj.filters b/src/ViGEmClient.vcxproj.filters index ae5b838..555d0ff 100644 --- a/src/ViGEmClient.vcxproj.filters +++ b/src/ViGEmClient.vcxproj.filters @@ -36,10 +36,18 @@ Header Files + + Header Files + Source Files + + + Resource Files + + \ No newline at end of file diff --git a/src/resource.h b/src/resource.h new file mode 100644 index 0000000..ab53b9b --- /dev/null +++ b/src/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ViGEmClient.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif From 86a781216a976084be8d42295a3df841b024dd49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 1 Feb 2020 20:38:49 +0100 Subject: [PATCH 091/107] Updated appveyor.yml --- appveyor.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index cb72e00..f38e2bd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,18 @@ version: 1.16.{build}.0 image: Visual Studio 2019 -build_script: -- ps: .\build.ps1 +platform: +- x86 +- x64 +configuration: +- Release_DLL +install: +- cmd: git submodule -q update --init +before_build: +- ps: Invoke-WebRequest "https://downloads.vigem.org/other/nefarius/vpatch/vpatch.exe" -OutFile vpatch.exe +- cmd: vpatch.exe --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\src\%APPVEYOR_PROJECT_NAME%.vcxproj" --vcxproj.inf-time-stamp +- cmd: vpatch.exe --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\src\%APPVEYOR_PROJECT_NAME%.rc" --resource.file-version --resource.product-version +build: + project: $(APPVEYOR_BUILD_FOLDER)\$(APPVEYOR_PROJECT_NAME).sln artifacts: - path: 'bin**\*.lib' - path: 'bin**\*.dll' From c47bdc08ac597a6718d3422e7d4b7d3fdf15df7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 1 Feb 2020 20:41:28 +0100 Subject: [PATCH 092/107] Updated README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a467c6b..bae0250 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # ViGEm Client Native SDK -Developer SDK for communication with `ViGEmBus`. +Developer SDK for communication with [`ViGEmBus`](https://github.com/ViGEm/ViGEmBus). [![Build status](https://ci.appveyor.com/api/projects/status/k806d3m2egjr0j56?svg=true)](https://ci.appveyor.com/project/nefarius/vigemclient) [![Discord](https://img.shields.io/discord/346756263763378176.svg)](https://discord.vigem.org) [![Website](https://img.shields.io/website-up-down-green-red/https/vigem.org.svg?label=ViGEm.org)](https://vigem.org/) [![PayPal Donate](https://img.shields.io/badge/paypal-donate-blue.svg)]() [![Support on Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)]() [![GitHub followers](https://img.shields.io/github/followers/nefarius.svg?style=social&label=Follow)](https://github.com/nefarius) [![Twitter Follow](https://img.shields.io/twitter/follow/nefariusmaximus.svg?style=social&label=Follow)](https://twitter.com/nefariusmaximus) ## About -TBD +Soon... ## How to build From c1283da949a96a31d91fd30a2dbc5cc26212b637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sat, 1 Feb 2020 20:44:54 +0100 Subject: [PATCH 093/107] Moved file --- src/ViGEmClient.vcxproj.filters | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ViGEmClient.vcxproj.filters b/src/ViGEmClient.vcxproj.filters index 555d0ff..6b63c24 100644 --- a/src/ViGEmClient.vcxproj.filters +++ b/src/ViGEmClient.vcxproj.filters @@ -30,15 +30,15 @@ Header Files\ViGEm - - Header Files - Header Files Header Files + + Header Files\ViGEm\km + From 971f7acd3dfa5ef03e80d7e510ed88201dd273b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 2 Feb 2020 17:42:28 +0100 Subject: [PATCH 094/107] Minor fix in demo app --- .gitignore | 1 + app/Tester/Tester.cpp | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 312b51e..9b87940 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,4 @@ /app/Tester/Release/vc141.pdb /app/Tester/Release/vcpkg.applocal.log /app/Tester/x64/Release/Tester.Build.CppClean.log +/app/Tester/x64/Release diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp index 0dc3074..70cb574 100644 --- a/app/Tester/Tester.cpp +++ b/app/Tester/Tester.cpp @@ -8,6 +8,9 @@ #include #include +// Comment out for DS4 sample +#define X360 + static std::mutex m; VOID CALLBACK notification( @@ -38,7 +41,7 @@ int main() auto ret = vigem_connect(client); -#if X360 +#ifdef X360 const auto x360 = vigem_target_x360_alloc(); ret = vigem_target_add(client, x360); @@ -50,7 +53,7 @@ int main() ret = vigem_target_add(client, ds4); -#if X360 +#ifdef X360 XUSB_REPORT report; XUSB_REPORT_INIT(&report); @@ -61,7 +64,7 @@ int main() Sleep(10); } -#endif +#else DS4_REPORT report; DS4_REPORT_INIT(&report); @@ -74,7 +77,9 @@ int main() Sleep(10); } -#if X360 + #endif + +#ifdef X360 vigem_target_x360_unregister_notification(x360); vigem_target_remove(client, x360); vigem_target_free(x360); From 371d9be90f7f30d6e49dbd97664c1d71d654e1a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 17 Feb 2020 19:45:59 +0100 Subject: [PATCH 095/107] Removed files ported over to own repository (https://github.com/ViGEm/ViGEmClient.vcpkg) --- vcpkg/ports/vigemclient/CONTROL | 3 --- vcpkg/ports/vigemclient/portfile.cmake | 34 -------------------------- 2 files changed, 37 deletions(-) delete mode 100644 vcpkg/ports/vigemclient/CONTROL delete mode 100644 vcpkg/ports/vigemclient/portfile.cmake diff --git a/vcpkg/ports/vigemclient/CONTROL b/vcpkg/ports/vigemclient/CONTROL deleted file mode 100644 index 60ec21a..0000000 --- a/vcpkg/ports/vigemclient/CONTROL +++ /dev/null @@ -1,3 +0,0 @@ -Source: vigemclient -Version: 1.16.28.0 -Description: ViGEm Client SDK for feeder development diff --git a/vcpkg/ports/vigemclient/portfile.cmake b/vcpkg/ports/vigemclient/portfile.cmake deleted file mode 100644 index da46963..0000000 --- a/vcpkg/ports/vigemclient/portfile.cmake +++ /dev/null @@ -1,34 +0,0 @@ -include(vcpkg_common_functions) - -vcpkg_from_github( - OUT_SOURCE_PATH SOURCE_PATH - REPO ViGEm/ViGEmClient - REF v1.16.28.0 - SHA512 39a321d90655895135f56b9e611ba6230e98afe296ad59f1afe99671c4a4b9ac02feb57814207e7586f0eae04ce8fd875f715a1f3bb63750dd2f742fedb6af81 - HEAD_REF master -) - -if (VCPKG_LIBRARY_LINKAGE STREQUAL dynamic) - vcpkg_install_msbuild( - SOURCE_PATH ${SOURCE_PATH} - PROJECT_SUBPATH "src/ViGEmClient.vcxproj" - INCLUDES_SUBPATH "include" - PLATFORM ${VCPKG_TARGET_ARCHITECTURE} - RELEASE_CONFIGURATION Release_DLL - DEBUG_CONFIGURATION Debug_DLL - USE_VCPKG_INTEGRATION - REMOVE_ROOT_INCLUDES) -elseif (VCPKG_LIBRARY_LINKAGE STREQUAL static) - vcpkg_install_msbuild( - SOURCE_PATH ${SOURCE_PATH} - PROJECT_SUBPATH "src/ViGEmClient.vcxproj" - INCLUDES_SUBPATH "include" - PLATFORM ${VCPKG_TARGET_ARCHITECTURE} - RELEASE_CONFIGURATION Release_LIB - DEBUG_CONFIGURATION Debug_LIB - USE_VCPKG_INTEGRATION - REMOVE_ROOT_INCLUDES) -endif() - -# Handle copyright -file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/vigemclient RENAME copyright) From f09f487a294148e8d9c0476a7bacba7f5473d57e Mon Sep 17 00:00:00 2001 From: JP Flouret Date: Wed, 1 Apr 2020 15:05:03 -0700 Subject: [PATCH 096/107] Add user-data paramater to notification callback --- include/ViGEm/Client.h | 8 ++++++-- src/Internal.h | 1 + src/ViGEmClient.cpp | 13 +++++++++---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/ViGEm/Client.h b/include/ViGEm/Client.h index 722f3f4..3acc105 100644 --- a/include/ViGEm/Client.h +++ b/include/ViGEm/Client.h @@ -111,6 +111,7 @@ extern "C" { EVT_VIGEM_X360_NOTIFICATION( PVIGEM_CLIENT Client, PVIGEM_TARGET Target, + LPVOID UserData, UCHAR LargeMotor, UCHAR SmallMotor, UCHAR LedNumber @@ -124,6 +125,7 @@ extern "C" { EVT_VIGEM_DS4_NOTIFICATION( PVIGEM_CLIENT Client, PVIGEM_TARGET Target, + LPVOID UserData, UCHAR LargeMotor, UCHAR SmallMotor, DS4_LIGHTBAR_COLOR LightbarColor @@ -291,10 +293,11 @@ extern "C" { * \param vigem The driver connection object. * \param target The target device object. * \param notification The notification callback. + * \param userData The user data passed to the notification callback. * * \return A VIGEM_ERROR. */ - VIGEM_API VIGEM_ERROR vigem_target_x360_register_notification(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PFN_VIGEM_X360_NOTIFICATION notification); + VIGEM_API VIGEM_ERROR vigem_target_x360_register_notification(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PFN_VIGEM_X360_NOTIFICATION notification, LPVOID userData); /** * \fn VIGEM_ERROR vigem_target_ds4_register_notification(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PVIGEM_DS4_NOTIFICATION notification); @@ -309,10 +312,11 @@ extern "C" { * \param vigem The driver connection object. * \param target The target device object. * \param notification The notification callback. + * \param userData The user data passed to the notification callback. * * \return A VIGEM_ERROR. */ - VIGEM_API VIGEM_ERROR vigem_target_ds4_register_notification(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PFN_VIGEM_DS4_NOTIFICATION notification); + VIGEM_API VIGEM_ERROR vigem_target_ds4_register_notification(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PFN_VIGEM_DS4_NOTIFICATION notification, LPVOID userData); /** * \fn void vigem_target_x360_unregister_notification(PVIGEM_TARGET target); diff --git a/src/Internal.h b/src/Internal.h index d8f52ea..888a5a7 100644 --- a/src/Internal.h +++ b/src/Internal.h @@ -65,6 +65,7 @@ typedef struct _VIGEM_TARGET_T USHORT ProductId; VIGEM_TARGET_TYPE Type; FARPROC Notification; + LPVOID NotificationUserData; bool closingNotificationThreads; HANDLE cancelNotificationThreadEvent; diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index e4d0b88..7e5e2f7 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -106,7 +106,7 @@ public: void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) override { if(target->Notification != nullptr) - PFN_VIGEM_X360_NOTIFICATION(target->Notification)(client, target, + PFN_VIGEM_X360_NOTIFICATION(target->Notification)(client, target, target->NotificationUserData, ((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LargeMotor, ((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->SmallMotor, ((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LedNumber @@ -126,7 +126,7 @@ public: void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) override { if (target->Notification != nullptr) - PFN_VIGEM_DS4_NOTIFICATION(target->Notification)(client, target, + PFN_VIGEM_DS4_NOTIFICATION(target->Notification)(client, target, target->NotificationUserData, ((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LargeMotor, ((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.SmallMotor, ((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LightbarColor @@ -658,7 +658,8 @@ void vigem_notification_thread_worker( VIGEM_ERROR vigem_target_x360_register_notification( PVIGEM_CLIENT vigem, PVIGEM_TARGET target, - PFN_VIGEM_X360_NOTIFICATION notification + PFN_VIGEM_X360_NOTIFICATION notification, + LPVOID userData ) { if (!vigem) @@ -677,6 +678,7 @@ VIGEM_ERROR vigem_target_x360_register_notification( return VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED; target->Notification = reinterpret_cast(notification); + target->NotificationUserData = userData; if (target->cancelNotificationThreadEvent == 0) target->cancelNotificationThreadEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); @@ -704,7 +706,8 @@ VIGEM_ERROR vigem_target_x360_register_notification( VIGEM_ERROR vigem_target_ds4_register_notification( PVIGEM_CLIENT vigem, PVIGEM_TARGET target, - PFN_VIGEM_DS4_NOTIFICATION notification + PFN_VIGEM_DS4_NOTIFICATION notification, + LPVOID userData ) { if (!vigem) @@ -723,6 +726,7 @@ VIGEM_ERROR vigem_target_ds4_register_notification( return VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED; target->Notification = reinterpret_cast(notification); + target->NotificationUserData = userData; if (target->cancelNotificationThreadEvent == 0) target->cancelNotificationThreadEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); @@ -767,6 +771,7 @@ void vigem_target_x360_unregister_notification(PVIGEM_TARGET target) } target->Notification = nullptr; + target->NotificationUserData = nullptr; } void vigem_target_ds4_unregister_notification(PVIGEM_TARGET target) From 4ad5aa90e1d11c3aeb1e6c9b1a6e34d16d36a879 Mon Sep 17 00:00:00 2001 From: JP Flouret Date: Wed, 1 Apr 2020 15:39:55 -0700 Subject: [PATCH 097/107] Add user-data parameter to Tester app --- app/Tester/Tester.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp index 70cb574..f3c8ece 100644 --- a/app/Tester/Tester.cpp +++ b/app/Tester/Tester.cpp @@ -16,6 +16,7 @@ static std::mutex m; VOID CALLBACK notification( PVIGEM_CLIENT Client, PVIGEM_TARGET Target, + LPVOID UserData, UCHAR LargeMotor, UCHAR SmallMotor, UCHAR LedNumber @@ -46,7 +47,7 @@ int main() ret = vigem_target_add(client, x360); - ret = vigem_target_x360_register_notification(client, x360, ¬ification); + ret = vigem_target_x360_register_notification(client, x360, ¬ification, nullptr); #endif const auto ds4 = vigem_target_ds4_alloc(); From cbb94a3750de1edb0ce81e91a12abc4e85a298d1 Mon Sep 17 00:00:00 2001 From: JP Flouret Date: Thu, 2 Apr 2020 10:26:30 -0700 Subject: [PATCH 098/107] Moved user-data to last parameter of notification --- app/Tester/Tester.cpp | 4 ++-- include/ViGEm/Client.h | 8 ++++---- src/ViGEmClient.cpp | 10 ++++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp index f3c8ece..5dcf350 100644 --- a/app/Tester/Tester.cpp +++ b/app/Tester/Tester.cpp @@ -16,10 +16,10 @@ static std::mutex m; VOID CALLBACK notification( PVIGEM_CLIENT Client, PVIGEM_TARGET Target, - LPVOID UserData, UCHAR LargeMotor, UCHAR SmallMotor, - UCHAR LedNumber + UCHAR LedNumber, + LPVOID UserData ) { m.lock(); diff --git a/include/ViGEm/Client.h b/include/ViGEm/Client.h index 3acc105..3d36283 100644 --- a/include/ViGEm/Client.h +++ b/include/ViGEm/Client.h @@ -111,10 +111,10 @@ extern "C" { EVT_VIGEM_X360_NOTIFICATION( PVIGEM_CLIENT Client, PVIGEM_TARGET Target, - LPVOID UserData, UCHAR LargeMotor, UCHAR SmallMotor, - UCHAR LedNumber + UCHAR LedNumber, + LPVOID UserData ); typedef EVT_VIGEM_X360_NOTIFICATION *PFN_VIGEM_X360_NOTIFICATION; @@ -125,10 +125,10 @@ extern "C" { EVT_VIGEM_DS4_NOTIFICATION( PVIGEM_CLIENT Client, PVIGEM_TARGET Target, - LPVOID UserData, UCHAR LargeMotor, UCHAR SmallMotor, - DS4_LIGHTBAR_COLOR LightbarColor + DS4_LIGHTBAR_COLOR LightbarColor, + LPVOID UserData ); typedef EVT_VIGEM_DS4_NOTIFICATION *PFN_VIGEM_DS4_NOTIFICATION; diff --git a/src/ViGEmClient.cpp b/src/ViGEmClient.cpp index 7e5e2f7..18e8bd8 100644 --- a/src/ViGEmClient.cpp +++ b/src/ViGEmClient.cpp @@ -106,10 +106,11 @@ public: void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) override { if(target->Notification != nullptr) - PFN_VIGEM_X360_NOTIFICATION(target->Notification)(client, target, target->NotificationUserData, + PFN_VIGEM_X360_NOTIFICATION(target->Notification)(client, target, ((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LargeMotor, ((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->SmallMotor, - ((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LedNumber + ((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LedNumber, + target->NotificationUserData ); } }; @@ -126,10 +127,11 @@ public: void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) override { if (target->Notification != nullptr) - PFN_VIGEM_DS4_NOTIFICATION(target->Notification)(client, target, target->NotificationUserData, + PFN_VIGEM_DS4_NOTIFICATION(target->Notification)(client, target, ((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LargeMotor, ((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.SmallMotor, - ((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LightbarColor + ((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LightbarColor, + target->NotificationUserData ); } }; From ce064add9d7806f663fe6376fadd0dac9adb2b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Fri, 8 May 2020 11:15:49 +0200 Subject: [PATCH 099/107] Removed incomplete Microsoft Xbox One Controller (wired) enum member --- include/ViGEm/Common.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/include/ViGEm/Common.h b/include/ViGEm/Common.h index fde8e30..3943293 100644 --- a/include/ViGEm/Common.h +++ b/include/ViGEm/Common.h @@ -33,15 +33,11 @@ typedef enum _VIGEM_TARGET_TYPE // // Microsoft Xbox 360 Controller (wired) // - Xbox360Wired, - // - // Microsoft Xbox One Controller (wired) - // - XboxOneWired, + Xbox360Wired = 0, // // Sony DualShock 4 (wired) // - DualShock4Wired + DualShock4Wired = 2 // NOTE: 1 skipped on purpose to maintain compatibility } VIGEM_TARGET_TYPE, *PVIGEM_TARGET_TYPE; From 465736429b8fe2b9d236b01ef0404f9bceb31106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Fri, 8 May 2020 11:28:59 +0200 Subject: [PATCH 100/107] Removed XGIP bollocks --- include/ViGEm/km/BusShared.h | 98 +----------------------------------- 1 file changed, 2 insertions(+), 96 deletions(-) diff --git a/include/ViGEm/km/BusShared.h b/include/ViGEm/km/BusShared.h index 9a1a69c..bf62d7f 100644 --- a/include/ViGEm/km/BusShared.h +++ b/include/ViGEm/km/BusShared.h @@ -67,8 +67,8 @@ DEFINE_GUID(GUID_DEVINTERFACE_BUSENUM_VIGEM, #define IOCTL_XUSB_SUBMIT_REPORT BUSENUM_W_IOCTL (IOCTL_VIGEM_BASE + 0x201) #define IOCTL_DS4_SUBMIT_REPORT BUSENUM_W_IOCTL (IOCTL_VIGEM_BASE + 0x202) #define IOCTL_DS4_REQUEST_NOTIFICATION BUSENUM_W_IOCTL (IOCTL_VIGEM_BASE + 0x203) -#define IOCTL_XGIP_SUBMIT_REPORT BUSENUM_W_IOCTL (IOCTL_VIGEM_BASE + 0x204) -#define IOCTL_XGIP_SUBMIT_INTERRUPT BUSENUM_W_IOCTL (IOCTL_VIGEM_BASE + 0x205) +//#define IOCTL_XGIP_SUBMIT_REPORT BUSENUM_W_IOCTL (IOCTL_VIGEM_BASE + 0x204) +//#define IOCTL_XGIP_SUBMIT_INTERRUPT BUSENUM_W_IOCTL (IOCTL_VIGEM_BASE + 0x205) #define IOCTL_XUSB_GET_USER_INDEX BUSENUM_RW_IOCTL(IOCTL_VIGEM_BASE + 0x206) @@ -402,97 +402,3 @@ VOID FORCEINLINE DS4_SUBMIT_REPORT_INIT( #pragma endregion -#pragma region XGIP (aka Xbox One device) section - EXPERIMENTAL - -typedef struct _XGIP_REPORT -{ - UCHAR Buttons1; - UCHAR Buttons2; - SHORT LeftTrigger; - SHORT RightTrigger; - SHORT ThumbLX; - SHORT ThumbLY; - SHORT ThumbRX; - SHORT ThumbRY; - -} XGIP_REPORT, *PXGIP_REPORT; - -// -// Xbox One request data -// -typedef struct _XGIP_SUBMIT_REPORT -{ - // - // sizeof(struct _XGIP_SUBMIT_REPORT) - // - ULONG Size; - - // - // Serial number of target device. - // - ULONG SerialNo; - - // - // HID Input report - // - XGIP_REPORT Report; - -} XGIP_SUBMIT_REPORT, *PXGIP_SUBMIT_REPORT; - -// -// Initializes an Xbox One report. -// -VOID FORCEINLINE XGIP_SUBMIT_REPORT_INIT( - _Out_ PXGIP_SUBMIT_REPORT Report, - _In_ ULONG SerialNo -) -{ - RtlZeroMemory(Report, sizeof(XGIP_SUBMIT_REPORT)); - - Report->Size = sizeof(XGIP_SUBMIT_REPORT); - Report->SerialNo = SerialNo; -} - -// -// Xbox One interrupt data -// -typedef struct _XGIP_SUBMIT_INTERRUPT -{ - // - // sizeof(struct _XGIP_SUBMIT_INTERRUPT) - // - ULONG Size; - - // - // Serial number of target device. - // - ULONG SerialNo; - - // - // Interrupt buffer. - // - UCHAR Interrupt[64]; - - // - // Length of interrupt buffer. - // - ULONG InterruptLength; - -} XGIP_SUBMIT_INTERRUPT, *PXGIP_SUBMIT_INTERRUPT; - -// -// Initializes an Xbox One interrupt. -// -VOID FORCEINLINE XGIP_SUBMIT_INTERRUPT_INIT( - _Out_ PXGIP_SUBMIT_INTERRUPT Report, - _In_ ULONG SerialNo -) -{ - RtlZeroMemory(Report, sizeof(XGIP_SUBMIT_INTERRUPT)); - - Report->Size = sizeof(XGIP_SUBMIT_INTERRUPT); - Report->SerialNo = SerialNo; -} - -#pragma endregion - From 1e9e45e0eaa60a2fe4bc2bde33ba32d894e6d979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Aug 2020 14:56:35 +0200 Subject: [PATCH 101/107] Added sum docs --- README.md | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bae0250..e8dc64a 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,21 @@ # ViGEm Client Native SDK -Developer SDK for communication with [`ViGEmBus`](https://github.com/ViGEm/ViGEmBus). +C/C++ developer SDK for communication with [`ViGEmBus`](https://github.com/ViGEm/ViGEmBus). -[![Build status](https://ci.appveyor.com/api/projects/status/k806d3m2egjr0j56?svg=true)](https://ci.appveyor.com/project/nefarius/vigemclient) [![Discord](https://img.shields.io/discord/346756263763378176.svg)](https://discord.vigem.org) [![Website](https://img.shields.io/website-up-down-green-red/https/vigem.org.svg?label=ViGEm.org)](https://vigem.org/) [![PayPal Donate](https://img.shields.io/badge/paypal-donate-blue.svg)]() [![Support on Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)]() [![GitHub followers](https://img.shields.io/github/followers/nefarius.svg?style=social&label=Follow)](https://github.com/nefarius) [![Twitter Follow](https://img.shields.io/twitter/follow/nefariusmaximus.svg?style=social&label=Follow)](https://twitter.com/nefariusmaximus) +[![Build status](https://ci.appveyor.com/api/projects/status/k806d3m2egjr0j56?svg=true)](https://ci.appveyor.com/project/nefarius/vigemclient) [![Discord](https://img.shields.io/discord/346756263763378176.svg)](https://discord.vigem.org) ## About -Soon... +**TL;DR:** use this if you want to create virtual game controllers from your C/C++ application 😊 + +The `ViGEmClient` provides a small library exposing a simple API for creating and "feeding" (periodically updating it with new input data) virtual game controllers through [`ViGEmBus`](https://github.com/ViGEm/ViGEmBus). The library takes care of discovering a compatible instance of the bus driver on the users system and abstracting away the inner workings of the emulation framework. You can use and distribute it with your project as either a static component (recommended) or a dynamic library (DLL). This library is **not** thread-safe, ensure proper synchronization in a multi-threaded environment. ## How to build ### Prerequisites - Visual Studio **2019** ([Community Edition](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=16) is just fine) + - When linking statically, make sure to also link against `setupapi.lib` ## Contribute @@ -25,3 +28,122 @@ Have an idea for a new feature? Let's have a chat about your request on [Discord ### Questions & Support Please respect that the GitHub issue tracker isn't a helpdesk. We offer a [Discord server](https://discord.vigem.org) and [forums](https://forums.vigem.org), where you're welcome to check out and engage in discussions! + +## How to use + +### Integration + +Integrating this library into your project is pretty straight-forward, there are no additional 3rd party dependencies. You can either `git submodule` or `git subtree` this repository directly into your source tree or use the provided [`vcpkg`](https://github.com/microsoft/vcpkg) package manager integration [found here](https://github.com/ViGEm/ViGEmClient.vcpkg) (recommended, can be updates with ease). The library tries to handle driver compatibility internally so static linking is recommended to avoid DLL hell 😊 + +### API usage + +For a general overview of the provided types and functions [take a look at the main include file](./include/ViGEm/Client.h). + +Now, onwards to a practical example 😉 First, include some basic headers: + +```cpp +// +// Windows basic types 'n' fun +// +#define WIN32_LEAN_AND_MEAN +#include + +// +// Optional depending on your use case +// +#include + +// +// The ViGEm API +// +#include + +// +// Link against SetupAPI +// +#pragma comment(lib, "setupapi.lib") +``` + +To initialize the API call `vigem_alloc` which gives you an opaque handle to the underlying driver: + +```cpp +const auto client = vigem_alloc(); + +if (client == nullptr) +{ + std::cerr << L"Uh, not enough memory to do that?!" << std::endl; + return -1; +} +``` + +Establish connection to the driver: + +```cpp +const auto retval = vigem_connect(client); + +if (!VIGEM_SUCCESS(retval)) +{ + std::cerr << L"ViGEm Bus connection failed with error code: 0x" << std::hex << retval << std::endl; + return -1; +} +``` + +👉 Note: this is an "expensive" operation, it's recommended you do this once in your project, not every frame for performance benefits. + +--- + +With this handle we're prepared to spawn (connect) and feed (supply with periodic input updates) one or many emulated controller devices. So let's spawn an Xbox 360 controller: + +```cpp +// +// Allocate handle to identify new pad +// +const auto pad = vigem_target_x360_alloc(); + +// +// Add client to the bus, this equals a plug-in event +// +const auto pir = vigem_target_add(client, pad); + +// +// Error handling +// +if (!VIGEM_SUCCESS(pir)) +{ + std::cerr << L"Target plugin failed with error code: 0x" << std::hex << retval << std::endl; + return -1; +} + +XINPUT_STATE state; + +// +// Grab the input from a physical X36ß pad in this example +// +XInputGetState(0, &state); + +// +// The XINPUT_GAMEPAD structure is identical to the XUSB_REPORT structure +// so we can simply take it "as-is" and cast it. +// +// Call this function on every input state change e.g. in a loop polling +// another joystick or network device or thermometer or... you get the idea. +// +vigem_target_x360_update(client, pad, *reinterpret_cast(&state.Gamepad)); + +// +// We're done with this pad, free resources (this disconnects the virtual device) +// +vigem_target_remove(client, pad); +vigem_target_free(pad); +``` + +--- + +Once ViGEm interaction is no longer required (e.g. the application is about to end) the acquired resources need to be freed properly: + +```cpp +vigem_disconnect(client); +vigem_free(client); +``` + +After that the `client` handle will become invalid and must not be used again. From e293709f94d772f0761d8425d5dc134229cba2fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Aug 2020 15:00:32 +0200 Subject: [PATCH 102/107] Bugfix in sample code --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e8dc64a..5caa10d 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ const auto client = vigem_alloc(); if (client == nullptr) { - std::cerr << L"Uh, not enough memory to do that?!" << std::endl; + std::cerr << "Uh, not enough memory to do that?!" << std::endl; return -1; } ``` @@ -83,7 +83,7 @@ const auto retval = vigem_connect(client); if (!VIGEM_SUCCESS(retval)) { - std::cerr << L"ViGEm Bus connection failed with error code: 0x" << std::hex << retval << std::endl; + std::cerr << "ViGEm Bus connection failed with error code: 0x" << std::hex << retval << std::endl; return -1; } ``` @@ -110,7 +110,7 @@ const auto pir = vigem_target_add(client, pad); // if (!VIGEM_SUCCESS(pir)) { - std::cerr << L"Target plugin failed with error code: 0x" << std::hex << retval << std::endl; + std::cerr << "Target plugin failed with error code: 0x" << std::hex << retval << std::endl; return -1; } From 88585583ff37b949a8f07019eeb170b28917501e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Aug 2020 16:10:45 +0200 Subject: [PATCH 103/107] Added use case of notification callback --- README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/README.md b/README.md index 5caa10d..3623827 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,47 @@ vigem_target_free(pad); --- +Alright, so we got the feeding side of things done, but what about the other direction? After all, the virtual device can receive some state changes as well (for the Xbox 360 device the LED ring can change and rumble/vibration requests can arrive) and this information is of interest for us. This is achieved by registering a notification callback like so: + +```cpp +// +// Define the callback function +// +VOID CALLBACK notification( + PVIGEM_CLIENT Client, + PVIGEM_TARGET Target, + UCHAR LargeMotor, + UCHAR SmallMotor, + UCHAR LedNumber, + LPVOID UserData +) +{ + static int count = 1; + + std::cout.width(3); + std::cout << count++ << " "; + std::cout.width(3); + std::cout << (int)LargeMotor << " "; + std::cout.width(3); + std::cout << (int)SmallMotor << std::endl; +} + +const auto ret = vigem_target_x360_register_notification(client, x360, ¬ification, nullptr); + +// +// Error handling +// +if (!VIGEM_SUCCESS(ret)) +{ + std::cerr << "Registering for notification failed with error code: 0x" << std::hex << retval << std::endl; + return -1; +} +``` + +The function `notification` will now get invoked every time a rumble request was sent to the virtual controller and can get handled accordingly. + +--- + Once ViGEm interaction is no longer required (e.g. the application is about to end) the acquired resources need to be freed properly: ```cpp From f96d8263523c18470d6cb74ecb1907d6dbcd736a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Aug 2020 16:14:39 +0200 Subject: [PATCH 104/107] Typo fixes --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3623827..5b03171 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ VOID CALLBACK notification( std::cout << (int)SmallMotor << std::endl; } -const auto ret = vigem_target_x360_register_notification(client, x360, ¬ification, nullptr); +const auto ret = vigem_target_x360_register_notification(client, pad, ¬ification, nullptr); // // Error handling From 3659ab648c8807194a469d5402b883a59f96ad81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Aug 2020 16:17:50 +0200 Subject: [PATCH 105/107] More fixes --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5b03171..5e44a07 100644 --- a/README.md +++ b/README.md @@ -163,20 +163,24 @@ VOID CALLBACK notification( std::cout.width(3); std::cout << (int)SmallMotor << std::endl; } +``` -const auto ret = vigem_target_x360_register_notification(client, pad, ¬ification, nullptr); +Register it: + +```cpp +const auto retval = vigem_target_x360_register_notification(client, pad, ¬ification, nullptr); // // Error handling // -if (!VIGEM_SUCCESS(ret)) +if (!VIGEM_SUCCESS(retval)) { std::cerr << "Registering for notification failed with error code: 0x" << std::hex << retval << std::endl; return -1; } ``` -The function `notification` will now get invoked every time a rumble request was sent to the virtual controller and can get handled accordingly. +The function `notification` will now get invoked every time a rumble request was sent to the virtual controller and can get handled accordingly. This is a blocking call and the invocation will take place in the order the underlying requests arrived. --- From ac6bab7eb80a481f3121739011f50b9c0aa3f2ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 23 Aug 2020 16:18:51 +0200 Subject: [PATCH 106/107] More fixes --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e44a07..37707d1 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ vigem_target_free(pad); --- -Alright, so we got the feeding side of things done, but what about the other direction? After all, the virtual device can receive some state changes as well (for the Xbox 360 device the LED ring can change and rumble/vibration requests can arrive) and this information is of interest for us. This is achieved by registering a notification callback like so: +Alright, so we got the feeding side of things done, but what about the other direction? After all, the virtual device can receive some state changes as well (for the Xbox 360 device the LED ring can change and rumble/vibration requests can arrive) and this information is of interest for us. This is achieved by defining a notification callback like so: ```cpp // From 18c67764ae7cc9827095eb4e70d75aa52ac8b392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 24 Aug 2020 11:29:02 +0200 Subject: [PATCH 107/107] Removed tester console app --- ViGEmClient.sln | 31 ------ app/Tester/Tester.cpp | 93 ---------------- app/Tester/Tester.vcxproj | 176 ------------------------------ app/Tester/Tester.vcxproj.filters | 22 ---- 4 files changed, 322 deletions(-) delete mode 100644 app/Tester/Tester.cpp delete mode 100644 app/Tester/Tester.vcxproj delete mode 100644 app/Tester/Tester.vcxproj.filters diff --git a/ViGEmClient.sln b/ViGEmClient.sln index 4c2877b..9ff0015 100644 --- a/ViGEmClient.sln +++ b/ViGEmClient.sln @@ -5,10 +5,6 @@ VisualStudioVersion = 16.0.29709.97 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ViGEmClient", "src\ViGEmClient.vcxproj", "{7DB06674-1F4F-464B-8E1C-172E9587F9DC}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "App", "App", "{8169FFB3-60F9-4A0C-B172-8E26B982B45F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tester", "app\Tester\Tester.vcxproj", "{2F4ED0AB-0B51-4506-91AA-1984C5D44B85}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_DLL|x64 = Debug_DLL|x64 @@ -49,37 +45,10 @@ Global {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x64.Build.0 = Release_LIB|x64 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x86.ActiveCfg = Release_LIB|Win32 {7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x86.Build.0 = Release_LIB|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x64.ActiveCfg = Debug|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x64.Build.0 = Debug|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x86.ActiveCfg = Debug|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_DLL|x86.Build.0 = Debug|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_LIB|x64.ActiveCfg = Debug|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_LIB|x64.Build.0 = Debug|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_LIB|x86.ActiveCfg = Debug|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug_LIB|x86.Build.0 = Debug|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug|x64.ActiveCfg = Debug|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug|x64.Build.0 = Debug|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug|x86.ActiveCfg = Debug|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Debug|x86.Build.0 = Debug|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_DLL|x64.ActiveCfg = Release|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_DLL|x64.Build.0 = Release|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_DLL|x86.ActiveCfg = Release|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_DLL|x86.Build.0 = Release|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_LIB|x64.ActiveCfg = Release|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_LIB|x64.Build.0 = Release|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_LIB|x86.ActiveCfg = Release|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release_LIB|x86.Build.0 = Release|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release|x64.ActiveCfg = Release|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release|x64.Build.0 = Release|x64 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release|x86.ActiveCfg = Release|Win32 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85} = {8169FFB3-60F9-4A0C-B172-8E26B982B45F} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D5CD61FD-80BB-4E0E-840C-BAF66ABB1CF0} EndGlobalSection diff --git a/app/Tester/Tester.cpp b/app/Tester/Tester.cpp deleted file mode 100644 index 5dcf350..0000000 --- a/app/Tester/Tester.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// Tester.cpp : This file contains the 'main' function. Program execution begins and ends there. -// - -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include -#include - -// Comment out for DS4 sample -#define X360 - -static std::mutex m; - -VOID CALLBACK notification( - PVIGEM_CLIENT Client, - PVIGEM_TARGET Target, - UCHAR LargeMotor, - UCHAR SmallMotor, - UCHAR LedNumber, - LPVOID UserData -) -{ - m.lock(); - - static int count = 1; - - std::cout.width(3); - std::cout << count++ << " "; - std::cout.width(3); - std::cout << (int)LargeMotor << " "; - std::cout.width(3); - std::cout << (int)SmallMotor << std::endl; - - m.unlock(); -} - -int main() -{ - const auto client = vigem_alloc(); - - auto ret = vigem_connect(client); - -#ifdef X360 - const auto x360 = vigem_target_x360_alloc(); - - ret = vigem_target_add(client, x360); - - ret = vigem_target_x360_register_notification(client, x360, ¬ification, nullptr); -#endif - - const auto ds4 = vigem_target_ds4_alloc(); - - ret = vigem_target_add(client, ds4); - -#ifdef X360 - XUSB_REPORT report; - XUSB_REPORT_INIT(&report); - - while(!(GetAsyncKeyState(VK_ESCAPE) & 0x8000)) - { - ret = vigem_target_x360_update(client, x360, report); - report.bLeftTrigger++; - Sleep(10); - } - -#else - - DS4_REPORT report; - DS4_REPORT_INIT(&report); - - while (!(GetAsyncKeyState(VK_ESCAPE) & 0x8000)) - { - ret = vigem_target_ds4_update(client, ds4, report); - report.bThumbLX++; - report.wButtons |= DS4_BUTTON_CIRCLE; - Sleep(10); - } - - #endif - -#ifdef X360 - vigem_target_x360_unregister_notification(x360); - vigem_target_remove(client, x360); - vigem_target_free(x360); -#endif - - vigem_target_remove(client, ds4); - vigem_target_free(ds4); - - vigem_free(client); -} diff --git a/app/Tester/Tester.vcxproj b/app/Tester/Tester.vcxproj deleted file mode 100644 index 2dcc7f4..0000000 --- a/app/Tester/Tester.vcxproj +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {2F4ED0AB-0B51-4506-91AA-1984C5D44B85} - Win32Proj - Tester - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - false - $(SolutionDir)include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - - - true - $(SolutionDir)include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - - - true - $(SolutionDir)include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - - - false - $(SolutionDir)include;$(VC_IncludePath);$(WindowsSDK_IncludePath); - - - - - - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreaded - - - Console - true - true - true - setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDebug - - - Console - true - setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDebug - - - Console - true - setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreaded - - - Console - true - true - true - setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - - {7db06674-1f4f-464b-8e1c-172e9587f9dc} - - - - - - \ No newline at end of file diff --git a/app/Tester/Tester.vcxproj.filters b/app/Tester/Tester.vcxproj.filters deleted file mode 100644 index 87da40a..0000000 --- a/app/Tester/Tester.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file