diff --git a/sys/Context.h b/sys/Context.h index c8ba6e2..7174f16 100644 --- a/sys/Context.h +++ b/sys/Context.h @@ -27,7 +27,6 @@ #pragma once -EXTERN_C_START // // Used to identify children in the device list of the bus. @@ -196,4 +195,3 @@ typedef struct _FDO_PLUGIN_REQUEST_DATA WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_PLUGIN_REQUEST_DATA, PluginRequestGetData) -EXTERN_C_END diff --git a/sys/Ds4Pdo.cpp b/sys/Ds4Pdo.cpp index df50ddb..a270253 100644 --- a/sys/Ds4Pdo.cpp +++ b/sys/Ds4Pdo.cpp @@ -5,12 +5,14 @@ #include #include +#include "Ds4.h" PCWSTR ViGEm::Bus::Targets::EmulationTargetDS4::_deviceDescription = L"Virtual DualShock 4 Controller"; ViGEm::Bus::Targets::EmulationTargetDS4::EmulationTargetDS4() : EmulationTargetPDO(0x054C, 0x05C4) { + TargetType = DualShock4Wired; } NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PrepareDevice(PWDFDEVICE_INIT DeviceInit, @@ -97,14 +99,14 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PrepareDevice(PWDFDEVICE_INIT return STATUS_SUCCESS; } -NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PrepareHardware(WDFDEVICE Device) +NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PrepareHardware() { WDF_QUERY_INTERFACE_CONFIG ifaceCfg; INTERFACE devinterfaceHid; devinterfaceHid.Size = sizeof(INTERFACE); devinterfaceHid.Version = 1; - devinterfaceHid.Context = (PVOID)Device; + devinterfaceHid.Context = static_cast(this->PdoDevice); devinterfaceHid.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; devinterfaceHid.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; @@ -117,7 +119,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PrepareHardware(WDFDEVICE Devi NULL ); - NTSTATUS status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); + NTSTATUS status = WdfDeviceAddQueryInterface(this->PdoDevice, &ifaceCfg); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, @@ -150,7 +152,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PrepareHardware(WDFDEVICE Devi return STATUS_SUCCESS; } -NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::InitContext(WDFDEVICE Device) +NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::InitContext() { NTSTATUS status; @@ -167,7 +169,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::InitContext(WDFDEVICE Device) WDF_OBJECT_ATTRIBUTES_INIT(&timerAttribs); // PDO is parent - timerAttribs.ParentObject = Device; + timerAttribs.ParentObject = this->PdoDevice; // Create timer status = WdfTimerCreate( @@ -433,5 +435,38 @@ VOID ViGEm::Bus::Targets::EmulationTargetDS4::PendingUsbRequestsTimerFunc( _In_ WDFTIMER Timer ) { - UNREFERENCED_PARAMETER(Timer); + auto ctx = reinterpret_cast(Core::EmulationTargetPdoGetContext(WdfTimerGetParentObject(Timer))); + + WDFREQUEST usbRequest; + PIRP pendingIrp; + PIO_STACK_LOCATION irpStack; + + TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DS4, "%!FUNC! Entry"); + + // Get pending USB request + NTSTATUS status = WdfIoQueueRetrieveNextRequest(ctx->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, ctx->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/Ds4Pdo.hpp b/sys/Ds4Pdo.hpp index f54ac0f..69f85be 100644 --- a/sys/Ds4Pdo.hpp +++ b/sys/Ds4Pdo.hpp @@ -18,9 +18,9 @@ namespace ViGEm::Bus::Targets PUNICODE_STRING DeviceId, PUNICODE_STRING DeviceDescription) override; - NTSTATUS PrepareHardware(WDFDEVICE Device) override; + NTSTATUS PrepareHardware() override; - NTSTATUS InitContext(WDFDEVICE Device) override; + NTSTATUS InitContext() override; VOID GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) override; @@ -87,14 +87,4 @@ namespace ViGEm::Bus::Targets static EVT_WDF_TIMER PendingUsbRequestsTimerFunc; }; - - // - // DS4-specific device context data. - // - typedef struct _DS4_PDO_CONTEXT - { - EmulationTargetDS4* Context; - } DS4_PDO_CONTEXT, *PDS4_PDO_CONTEXT; - - WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DS4_PDO_CONTEXT, Ds4PdoGetContext) } diff --git a/sys/EmulationTargetPDO.cpp b/sys/EmulationTargetPDO.cpp index c6ee249..f1eccc7 100644 --- a/sys/EmulationTargetPDO.cpp +++ b/sys/EmulationTargetPDO.cpp @@ -1,7 +1,305 @@ #include "EmulationTargetPDO.hpp" #include "CRTCPP.hpp" +#include "trace.h" +#include "EmulationTargetPDO.tmh" +#define NTSTRSAFE_LIB +#include +#include +PCWSTR ViGEm::Bus::Core::EmulationTargetPDO::_deviceLocation = L"Virtual Gamepad Emulation Bus"; + +NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::CreateDevice(WDFDEVICE Device, PWDFDEVICE_INIT DeviceInit, PPDO_IDENTIFICATION_DESCRIPTION Description) +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + 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; + 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); + + UNREFERENCED_PARAMETER(Description); + UNREFERENCED_PARAMETER(Device); + + PAGED_CODE(); + + // set device type + WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); + // Bus is power policy owner + WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE); + + do + { +#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); + break; + } + + 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); + break; + } + +#pragma endregion + +#pragma region Prepare PDO + + status = this->PrepareDevice(DeviceInit, &deviceId, &deviceDescription); + + if (!NT_SUCCESS(status)) + break; + + // set device id + status = WdfPdoInitAssignDeviceID(DeviceInit, &deviceId); + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_BUSPDO, + "WdfPdoInitAssignDeviceID failed with status %!STATUS!", + status); + break; + } + + // prepare instance id + status = RtlUnicodeStringPrintf(&buffer, L"%02d", this->SerialNo); + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_BUSPDO, + "RtlUnicodeStringPrintf failed with status %!STATUS!", + status); + break; + } + + // set instance id + status = WdfPdoInitAssignInstanceID(DeviceInit, &buffer); + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_BUSPDO, + "WdfPdoInitAssignInstanceID failed with status %!STATUS!", + status); + break; + } + + // 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); + break; + } + + // default locale is English + // TODO: add more locales + WdfPdoInitSetDefaultLocale(DeviceInit, 0x409); + +#pragma region PNP/Power event callbacks + + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + + pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware; + + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + +#pragma endregion + + // NOTE: not utilized at the moment + WdfPdoInitAllowForwardingRequestToParent(DeviceInit); + +#pragma endregion + +#pragma region Create PDO + + // Add common device data context + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, EMULATION_TARGET_PDO_CONTEXT); + + status = WdfDeviceCreate(&DeviceInit, &pdoAttributes, &this->PdoDevice); + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_BUSPDO, + "WdfDeviceCreate failed with status %!STATUS!", + status); + break; + } + + TraceEvents(TRACE_LEVEL_VERBOSE, + TRACE_BUSPDO, + "Created PDO 0x%p", + this->PdoDevice); + +#pragma endregion + +#pragma region Expose USB Interface + + status = WdfDeviceCreateDeviceInterface( + Device, + const_cast(&GUID_DEVINTERFACE_USB_DEVICE), + NULL + ); + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_BUSPDO, + "WdfDeviceCreateDeviceInterface failed with status %!STATUS!", + status); + break; + } + +#pragma endregion + +#pragma region Set PDO contexts + + status = this->InitContext(); + + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_BUSPDO, + "Couldn't initialize additional contexts: %!STATUS!", + status); + break; + } + +#pragma endregion + +#pragma region Create Queues & Locks + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = this->PdoDevice; + + // Create and assign queue for incoming interrupt transfer + WDF_IO_QUEUE_CONFIG_INIT(&usbInQueueConfig, WdfIoQueueDispatchManual); + + status = WdfIoQueueCreate( + this->PdoDevice, + &usbInQueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &this->PendingUsbInRequests + ); + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_BUSPDO, + "WdfIoQueueCreate (PendingUsbInRequests) failed with status %!STATUS!", + status); + break; + } + + // Create and assign queue for user-land notification requests + WDF_IO_QUEUE_CONFIG_INIT(¬ificationsQueueConfig, WdfIoQueueDispatchManual); + + status = WdfIoQueueCreate( + Device, + ¬ificationsQueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &this->PendingNotificationRequests + ); + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_BUSPDO, + "WdfIoQueueCreate (PendingNotificationRequests) failed with status %!STATUS!", + status); + break; + } + +#pragma endregion + +#pragma region Default I/O queue setup + + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&defaultPdoQueueConfig, WdfIoQueueDispatchParallel); + + defaultPdoQueueConfig.EvtIoInternalDeviceControl = EvtIoInternalDeviceControl; + + status = WdfIoQueueCreate( + this->PdoDevice, + &defaultPdoQueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &defaultPdoQueue + ); + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_BUSPDO, + "WdfIoQueueCreate (Default) failed with status %!STATUS!", + status); + break; + } + +#pragma endregion + +#pragma region PNP capabilities + + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + + pnpCaps.Removable = WdfTrue; + pnpCaps.EjectSupported = WdfTrue; + pnpCaps.SurpriseRemovalOK = WdfTrue; + + pnpCaps.Address = this->SerialNo; + pnpCaps.UINumber = this->SerialNo; + + WdfDeviceSetPnpCapabilities(this->PdoDevice, &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(this->PdoDevice, &powerCaps); + +#pragma endregion + + } while (FALSE); + + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status); + + return status; +} + +#pragma region USB Interface Functions + BOOLEAN USB_BUSIFFN ViGEm::Bus::Core::EmulationTargetPDO::UsbIsDeviceHighSpeed(IN PVOID BusContext) { UNREFERENCED_PARAMETER(BusContext); @@ -10,9 +308,9 @@ BOOLEAN USB_BUSIFFN ViGEm::Bus::Core::EmulationTargetPDO::UsbIsDeviceHighSpeed(I } NTSTATUS USB_BUSIFFN ViGEm::Bus::Core::EmulationTargetPDO::UsbQueryBusInformation(IN PVOID BusContext, IN ULONG Level, - IN OUT PVOID BusInformationBuffer, - IN OUT PULONG BusInformationBufferLength, - OUT PULONG BusInformationActualLength) + IN OUT PVOID BusInformationBuffer, + IN OUT PULONG BusInformationBufferLength, + OUT PULONG BusInformationActualLength) { UNREFERENCED_PARAMETER(BusContext); UNREFERENCED_PARAMETER(Level); @@ -40,8 +338,8 @@ NTSTATUS USB_BUSIFFN ViGEm::Bus::Core::EmulationTargetPDO::UsbQueryBusTime(IN PV } VOID USB_BUSIFFN ViGEm::Bus::Core::EmulationTargetPDO::UsbGetUSBDIVersion(IN PVOID BusContext, - IN OUT PUSBD_VERSION_INFORMATION VersionInformation, - IN OUT PULONG HcdCapabilities) + IN OUT PUSBD_VERSION_INFORMATION VersionInformation, + IN OUT PULONG HcdCapabilities) { UNREFERENCED_PARAMETER(BusContext); @@ -57,6 +355,38 @@ VOID USB_BUSIFFN ViGEm::Bus::Core::EmulationTargetPDO::UsbGetUSBDIVersion(IN PVO } } -ViGEm::Bus::Core::EmulationTargetPDO::EmulationTargetPDO(USHORT VID, USHORT PID): VendorId(VID), ProductId(PID) +#pragma endregion + +ViGEm::Bus::Core::EmulationTargetPDO::EmulationTargetPDO(USHORT VID, USHORT PID) : VendorId(VID), ProductId(PID) { } + +NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourcesRaw, + _In_ WDFCMRESLIST ResourcesTranslated +) +{ + UNREFERENCED_PARAMETER(ResourcesRaw); + UNREFERENCED_PARAMETER(ResourcesTranslated); + + const auto ctx = EmulationTargetPdoGetContext(Device); + + return ctx->Target->PrepareHardware(); +} + +VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl( + _In_ WDFQUEUE Queue, + _In_ WDFREQUEST Request, + _In_ size_t OutputBufferLength, + _In_ size_t InputBufferLength, + _In_ ULONG IoControlCode +) +{ + UNREFERENCED_PARAMETER(Queue); + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(InputBufferLength); + UNREFERENCED_PARAMETER(IoControlCode); + + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} diff --git a/sys/EmulationTargetPDO.hpp b/sys/EmulationTargetPDO.hpp index 5413835..8c4d2c7 100644 --- a/sys/EmulationTargetPDO.hpp +++ b/sys/EmulationTargetPDO.hpp @@ -18,6 +18,12 @@ namespace ViGEm::Bus::Core { + // {A8BA2D1F-894F-464A-B0CE-7A0C8FD65DF1} + DEFINE_GUID(GUID_DEVCLASS_VIGEM_RAWPDO, + 0xA8BA2D1F, 0x894F, 0x464A, 0xB0, 0xCE, 0x7A, 0x0C, 0x8F, 0xD6, 0x5D, 0xF1); + + typedef struct _PDO_IDENTIFICATION_DESCRIPTION* PPDO_IDENTIFICATION_DESCRIPTION; + class EmulationTargetPDO { public: @@ -25,21 +31,27 @@ namespace ViGEm::Bus::Core virtual ~EmulationTargetPDO() = default; - virtual NTSTATUS PrepareDevice(PWDFDEVICE_INIT DeviceInit, + virtual NTSTATUS PrepareDevice(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId, PUNICODE_STRING DeviceDescription) = 0; - virtual NTSTATUS PrepareHardware(WDFDEVICE Device) = 0; + virtual NTSTATUS PrepareHardware() = 0; - virtual NTSTATUS InitContext(WDFDEVICE Device) = 0; + virtual NTSTATUS InitContext() = 0; virtual VOID GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) = 0; virtual VOID GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor) = 0; virtual VOID SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo) = 0; + + NTSTATUS CreateDevice(_In_ WDFDEVICE Device, + _In_ PWDFDEVICE_INIT DeviceInit, + _In_ PPDO_IDENTIFICATION_DESCRIPTION Description); protected: static const ULONG _maxHardwareIdLength = 0xFF; + static PCWSTR _deviceLocation; + static BOOLEAN USB_BUSIFFN UsbIsDeviceHighSpeed(IN PVOID BusContext); static NTSTATUS USB_BUSIFFN UsbQueryBusInformation( @@ -60,44 +72,69 @@ namespace ViGEm::Bus::Core IN OUT PULONG HcdCapabilities ); - // - // Unique serial number of the device on the bus - // - ULONG SerialNo{}; + static EVT_WDF_DEVICE_PREPARE_HARDWARE EvtDevicePrepareHardware; - // - // PID of the process creating this PDO - // - DWORD OwnerProcessId{}; + static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL EvtIoInternalDeviceControl; - // - // Device type this PDO is emulating - // - VIGEM_TARGET_TYPE TargetType; + static const int MAX_INSTANCE_ID_LEN = 80; - // - // If set, the vendor ID the emulated device is reporting - // - USHORT VendorId{}; + // + // Unique serial number of the device on the bus + // + ULONG SerialNo{}; - // - // If set, the product ID the emulated device is reporting - // - USHORT ProductId{}; + // + // PID of the process creating this PDO + // + DWORD OwnerProcessId{}; - // - // Queue for incoming data interrupt transfer - // - WDFQUEUE PendingUsbInRequests{}; + // + // Device type this PDO is emulating + // + VIGEM_TARGET_TYPE TargetType; - // - // Queue for inverted calls - // - WDFQUEUE PendingNotificationRequests{}; + // + // If set, the vendor ID the emulated device is reporting + // + USHORT VendorId{}; + + // + // If set, the product ID the emulated device is reporting + // + USHORT ProductId{}; + + // + // Queue for incoming data interrupt transfer + // + WDFQUEUE PendingUsbInRequests{}; + + // + // Queue for inverted calls + // + WDFQUEUE PendingNotificationRequests{}; + + // + // This child objects' device object + // + WDFDEVICE PdoDevice; + + // + // Signals the bus that PDO is ready to receive data + // + KEVENT PdoBootNotificationEvent; }; typedef struct _PDO_IDENTIFICATION_DESCRIPTION { - EmulationTargetPDO* Context; + WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Header; + + EmulationTargetPDO* Target; } PDO_IDENTIFICATION_DESCRIPTION, *PPDO_IDENTIFICATION_DESCRIPTION; + + typedef struct _EMULATION_TARGET_PDO_CONTEXT + { + EmulationTargetPDO* Target; + } EMULATION_TARGET_PDO_CONTEXT, *PEMULATION_TARGET_PDO_CONTEXT; + + WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(EMULATION_TARGET_PDO_CONTEXT, EmulationTargetPdoGetContext) } diff --git a/sys/XusbPdo.cpp b/sys/XusbPdo.cpp index c492915..af2d221 100644 --- a/sys/XusbPdo.cpp +++ b/sys/XusbPdo.cpp @@ -11,6 +11,7 @@ PCWSTR ViGEm::Bus::Targets::EmulationTargetXUSB::_deviceDescription = L"Virtual ViGEm::Bus::Targets::EmulationTargetXUSB::EmulationTargetXUSB() : EmulationTargetPDO(0x045E, 0x028E) { + TargetType = Xbox360Wired; } NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareDevice(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId, @@ -98,7 +99,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareDevice(PWDFDEVICE_INIT return STATUS_SUCCESS; } -NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware(WDFDEVICE Device) +NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware() { WDF_QUERY_INTERFACE_CONFIG ifaceCfg; @@ -106,7 +107,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware(WDFDEVICE Dev dummyIface.Size = sizeof(INTERFACE); dummyIface.Version = 1; - dummyIface.Context = static_cast(Device); + dummyIface.Context = static_cast(this->PdoDevice); dummyIface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; dummyIface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; @@ -124,7 +125,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware(WDFDEVICE Dev nullptr ); - NTSTATUS status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); + NTSTATUS status = WdfDeviceAddQueryInterface(this->PdoDevice, &ifaceCfg); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, @@ -145,7 +146,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware(WDFDEVICE Dev nullptr ); - status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); + status = WdfDeviceAddQueryInterface(this->PdoDevice, &ifaceCfg); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, @@ -166,7 +167,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware(WDFDEVICE Dev nullptr ); - status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); + status = WdfDeviceAddQueryInterface(this->PdoDevice, &ifaceCfg); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, @@ -185,7 +186,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware(WDFDEVICE Dev xusbInterface.Size = sizeof(USB_BUS_INTERFACE_USBDI_V1); xusbInterface.Version = USB_BUSIF_USBDI_VERSION_1; - xusbInterface.BusContext = static_cast(Device); + xusbInterface.BusContext = static_cast(this->PdoDevice); xusbInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; xusbInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; @@ -203,7 +204,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware(WDFDEVICE Dev nullptr ); - status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); + status = WdfDeviceAddQueryInterface(this->PdoDevice, &ifaceCfg); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, @@ -216,13 +217,13 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware(WDFDEVICE Dev return STATUS_SUCCESS; } -NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::InitContext(WDFDEVICE Device) +NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::InitContext() { WDF_OBJECT_ATTRIBUTES attributes; PUCHAR blobBuffer; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = Device; + attributes.ParentObject = this->PdoDevice; TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XUSB, "Initializing XUSB context..."); @@ -286,7 +287,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::InitContext(WDFDEVICE Device) WDF_IO_QUEUE_CONFIG_INIT(&holdingInQueueConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate( - Device, + this->PdoDevice, &holdingInQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &this->HoldingUsbInRequests diff --git a/sys/XusbPdo.hpp b/sys/XusbPdo.hpp index 08c2d5f..3606e81 100644 --- a/sys/XusbPdo.hpp +++ b/sys/XusbPdo.hpp @@ -26,9 +26,9 @@ namespace ViGEm::Bus::Targets NTSTATUS PrepareDevice(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId, PUNICODE_STRING DeviceDescription) override; - NTSTATUS PrepareHardware(WDFDEVICE Device) override; + NTSTATUS PrepareHardware() override; - NTSTATUS InitContext(WDFDEVICE Device) override; + NTSTATUS InitContext() override; VOID GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) override; @@ -95,14 +95,4 @@ namespace ViGEm::Bus::Targets // WDFMEMORY InterruptBlobStorage; }; - - // - // XUSB-specific device context data. - // - typedef struct _XUSB_PDO_CONTEXT - { - EmulationTargetXUSB* Context; - } XUSB_PDO_CONTEXT, *PXUSB_PDO_CONTEXT; - - WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XUSB_PDO_CONTEXT, XusbPdoGetContext) }