diff --git a/.gitignore b/.gitignore
index fe8b35c..f804316 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,7 @@ mono_crash.*
[Rr]eleases/
x64/
x86/
+[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
@@ -61,6 +62,9 @@ project.lock.json
project.fragment.lock.json
artifacts/
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
# StyleCop
StyleCopReport.xml
@@ -350,4 +354,7 @@ healthchecksdb
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
-.ionide/
\ No newline at end of file
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
\ No newline at end of file
diff --git a/client b/client
index d466227..4657364 160000
--- a/client
+++ b/client
@@ -1 +1 @@
-Subproject commit d466227688a9d2fbd437f4b9712c596a6547ec2b
+Subproject commit 465736429b8fe2b9d236b01ef0404f9bceb31106
diff --git a/sys/Queue.c b/sys/Queue.c
index a006934..729443c 100644
--- a/sys/Queue.c
+++ b/sys/Queue.c
@@ -50,8 +50,6 @@ VOID Bus_EvtIoDeviceControl(
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;
@@ -278,64 +276,6 @@ VOID Bus_EvtIoDeviceControl(
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:
diff --git a/sys/ViGEmBus.vcxproj b/sys/ViGEmBus.vcxproj
index 013607d..130a349 100644
--- a/sys/ViGEmBus.vcxproj
+++ b/sys/ViGEmBus.vcxproj
@@ -191,7 +191,6 @@
-
@@ -206,7 +205,6 @@
-
diff --git a/sys/ViGEmBus.vcxproj.filters b/sys/ViGEmBus.vcxproj.filters
index c9b3ac8..5084fb0 100644
--- a/sys/ViGEmBus.vcxproj.filters
+++ b/sys/ViGEmBus.vcxproj.filters
@@ -48,9 +48,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -63,6 +60,9 @@
Header Files
+
+ Header Files
+
@@ -74,9 +74,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -96,4 +93,9 @@
Source Files
+
+
+ Resource Files
+
+
\ No newline at end of file
diff --git a/sys/Xgip.h b/sys/Xgip.h
deleted file mode 100644
index 3f12906..0000000
--- a/sys/Xgip.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-* Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver
-*
-* MIT License
-*
-* Copyright (c) 2016-2019 Nefarius Software Solutions e.U. and Contributors
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* 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
-//
-
-// Below these interfaces are from wdmguid.h being used as dummies
-// {70211B0E-0AFB-47DB-AFC1-410BF842497A} PNP_LOCATION_INTERFACE
-// {B38290E5-3CD0-4F9D-9937-F5FE2B44D47A} D3COLD_SUPPORT_INTERFACE
-// {2AEB0243-6A6E-486B-82FC-D815F6B97006} REENUMERATE_SELF_INTERFACE_STANDARD
-
-// {DC7A8E51-49B3-4A3A-9E81-625205E7D729} Seems to be GUID_POWER_THREAD_INTERFACE
-// Source: https://github.com/microsoft/Windows-Driver-Frameworks/blob/master/src/framework/shared/irphandlers/pnp/fxpkgpnp.cpp#L63
-DEFINE_GUID(GUID_DEVINTERFACE_XGIP_GUID_POWER_THREAD_INTERFACE_DUMMY,
- 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/busenum.c b/sys/busenum.c
index 923138b..e9dadf8 100644
--- a/sys/busenum.c
+++ b/sys/busenum.c
@@ -140,17 +140,8 @@ NTSTATUS Bus_PlugInDevice(
description.ProductId = 0x05C4;
break;
- case XboxOneWired:
-
- description.VendorId = 0x0E6F;
- description.ProductId = 0x0139;
-
-#if !DBG
- // TODO: implement and remove!
+ default:
return STATUS_NOT_SUPPORTED;
-#endif
-
- break;
}
}
else
@@ -548,20 +539,6 @@ NTSTATUS Bus_Ds4SubmitReport(WDFDEVICE Device, ULONG SerialNo, PDS4_SUBMIT_REPOR
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;
@@ -639,12 +616,6 @@ NTSTATUS Bus_SubmitReport(WDFDEVICE Device, ULONG SerialNo, PVOID Report, BOOLEA
changed = TRUE;
- break;
- case XboxOneWired:
-
- // TODO: necessary?
- changed = TRUE;
-
break;
default:
@@ -679,60 +650,6 @@ NTSTATUS Bus_SubmitReport(WDFDEVICE Device, ULONG SerialNo, PVOID Report, BOOLEA
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:
@@ -788,25 +705,6 @@ NTSTATUS Bus_SubmitReport(WDFDEVICE Device, ULONG SerialNo, PVOID Report, BOOLEA
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;
diff --git a/sys/busenum.h b/sys/busenum.h
index 4fe86fe..af1cdbe 100644
--- a/sys/busenum.h
+++ b/sys/busenum.h
@@ -44,7 +44,6 @@
#include "UsbPdo.h"
#include "Xusb.h"
#include "Ds4.h"
-#include "Xgip.h"
#pragma region Macros
@@ -106,8 +105,6 @@ EVT_WDF_DEVICE_PREPARE_HARDWARE Pdo_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;
@@ -146,14 +143,6 @@ Bus_QueueNotification(
WDFREQUEST Request
);
-NTSTATUS
-Bus_XgipSubmitReport(
- WDFDEVICE Device,
- ULONG SerialNo,
- PXGIP_SUBMIT_REPORT Report,
- _In_ BOOLEAN FromInterface
-);
-
NTSTATUS
Bus_SubmitReport(
WDFDEVICE Device,
diff --git a/sys/buspdo.c b/sys/buspdo.c
index 7226ed9..05cb933 100644
--- a/sys/buspdo.c
+++ b/sys/buspdo.c
@@ -189,18 +189,6 @@ NTSTATUS Bus_CreatePdo(
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;
@@ -334,23 +322,6 @@ NTSTATUS Bus_CreatePdo(
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;
}
@@ -406,13 +377,6 @@ NTSTATUS Bus_CreatePdo(
status = Ds4_AssignPdoContext(hChild, Description);
break;
-
- case XboxOneWired:
-
- status = Xgip_AssignPdoContext(hChild);
-
- break;
-
default:
break;
}
@@ -563,12 +527,6 @@ NTSTATUS Pdo_EvtDevicePrepareHardware(
break;
- case XboxOneWired:
-
- status = Xgip_PrepareHardware(Device);
-
- break;
-
default:
break;
}
diff --git a/sys/usbpdo.c b/sys/usbpdo.c
index 7904a1c..a7cb329 100644
--- a/sys/usbpdo.c
+++ b/sys/usbpdo.c
@@ -145,12 +145,6 @@ NTSTATUS UsbPdo_GetDeviceDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommon)
break;
- case XboxOneWired:
-
- Xgip_GetDeviceDescriptorType(pDescriptor, pCommon);
-
- break;
-
default:
return STATUS_UNSUCCESSFUL;
}
@@ -181,11 +175,6 @@ NTSTATUS UsbPdo_GetConfigurationDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommo
Ds4_GetConfigurationDescriptorType(Buffer, length);
- break;
- case XboxOneWired:
-
- Xgip_GetConfigurationDescriptorType(Buffer, length);
-
break;
default:
return STATUS_UNSUCCESSFUL;
@@ -212,14 +201,6 @@ NTSTATUS UsbPdo_GetConfigurationDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommo
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;
@@ -382,20 +363,6 @@ NTSTATUS UsbPdo_SelectConfiguration(PURB urb, PPDO_DEVICE_DATA pCommon)
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;
}
@@ -800,31 +767,6 @@ NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST R
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;
}
diff --git a/sys/xgip.c b/sys/xgip.c
deleted file mode 100644
index cc288dc..0000000
--- a/sys/xgip.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
-* Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver
-*
-* MIT License
-*
-* Copyright (c) 2016-2019 Nefarius Software Solutions e.U. and Contributors
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* 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 "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);
- }
- }
-}
-