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; -}