From 1f7bcff6dc2e2226eff5c411e91afe753ff79669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 11 May 2020 12:37:40 +0200 Subject: [PATCH] Ported UsbSelectInterface --- sys/Ds4Pdo.cpp | 7 ++ sys/Ds4Pdo.hpp | 1 + sys/EmulationTargetPDO.hpp | 2 + sys/XusbPdo.cpp | 222 +++++++++++++++++++++++++------------ sys/XusbPdo.hpp | 1 + 5 files changed, 165 insertions(+), 68 deletions(-) diff --git a/sys/Ds4Pdo.cpp b/sys/Ds4Pdo.cpp index aeb400a..735a3c9 100644 --- a/sys/Ds4Pdo.cpp +++ b/sys/Ds4Pdo.cpp @@ -871,6 +871,13 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetDescriptorFromInterface( return status; } +NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbSelectInterface(PURB Urb) +{ + UNREFERENCED_PARAMETER(Urb); + + return STATUS_NOT_IMPLEMENTED; +} + VOID ViGEm::Bus::Targets::EmulationTargetDS4::PendingUsbRequestsTimerFunc( _In_ WDFTIMER Timer ) diff --git a/sys/Ds4Pdo.hpp b/sys/Ds4Pdo.hpp index efb2c6e..5cae258 100644 --- a/sys/Ds4Pdo.hpp +++ b/sys/Ds4Pdo.hpp @@ -41,6 +41,7 @@ namespace ViGEm::Bus::Targets void AbortPipe() override; NTSTATUS UsbClassInterface(PURB Urb) override; NTSTATUS UsbGetDescriptorFromInterface(PURB Urb) override; + NTSTATUS UsbSelectInterface(PURB Urb) override; private: static PCWSTR _deviceDescription; diff --git a/sys/EmulationTargetPDO.hpp b/sys/EmulationTargetPDO.hpp index 4c6f064..ff26707 100644 --- a/sys/EmulationTargetPDO.hpp +++ b/sys/EmulationTargetPDO.hpp @@ -64,6 +64,8 @@ namespace ViGEm::Bus::Core virtual NTSTATUS UsbGetDescriptorFromInterface(PURB Urb) = 0; + virtual NTSTATUS UsbSelectInterface(PURB Urb) = 0; + protected: static const ULONG _maxHardwareIdLength = 0xFF; diff --git a/sys/XusbPdo.cpp b/sys/XusbPdo.cpp index 7b2b1f8..a524c6a 100644 --- a/sys/XusbPdo.cpp +++ b/sys/XusbPdo.cpp @@ -16,7 +16,7 @@ ViGEm::Bus::Targets::EmulationTargetXUSB::EmulationTargetXUSB() : EmulationTarge } NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareDevice(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId, - PUNICODE_STRING DeviceDescription) + PUNICODE_STRING DeviceDescription) { NTSTATUS status; DECLARE_UNICODE_STRING_SIZE(buffer, _maxHardwareIdLength); @@ -26,9 +26,9 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareDevice(PWDFDEVICE_INIT if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "RtlUnicodeStringInit failed with status %!STATUS!", - status); + TRACE_XUSB, + "RtlUnicodeStringInit failed with status %!STATUS!", + status); return status; } @@ -41,9 +41,9 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareDevice(PWDFDEVICE_INIT if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfPdoInitAddHardwareID failed with status %!STATUS!", - status); + TRACE_XUSB, + "WdfPdoInitAddHardwareID failed with status %!STATUS!", + status); return status; } @@ -55,9 +55,9 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareDevice(PWDFDEVICE_INIT if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfPdoInitAddCompatibleID #1 failed with status %!STATUS!", - status); + TRACE_XUSB, + "WdfPdoInitAddCompatibleID #1 failed with status %!STATUS!", + status); return status; } @@ -67,9 +67,9 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareDevice(PWDFDEVICE_INIT if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfPdoInitAddCompatibleID #2 failed with status %!STATUS!", - status); + TRACE_XUSB, + "WdfPdoInitAddCompatibleID #2 failed with status %!STATUS!", + status); return status; } @@ -79,9 +79,9 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareDevice(PWDFDEVICE_INIT if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfPdoInitAddCompatibleID #3 failed with status %!STATUS!", - status); + TRACE_XUSB, + "WdfPdoInitAddCompatibleID #3 failed with status %!STATUS!", + status); return status; } @@ -91,9 +91,9 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareDevice(PWDFDEVICE_INIT if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfPdoInitAddCompatibleID #4 failed with status %!STATUS!", - status); + TRACE_XUSB, + "WdfPdoInitAddCompatibleID #4 failed with status %!STATUS!", + status); return status; } @@ -130,10 +130,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware() if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "Couldn't register PNP_LOCATION dummy interface %!GUID! (WdfDeviceAddQueryInterface failed with status %!STATUS!)", - &GUID_PNP_LOCATION_INTERFACE, - status); + TRACE_XUSB, + "Couldn't register PNP_LOCATION dummy interface %!GUID! (WdfDeviceAddQueryInterface failed with status %!STATUS!)", + &GUID_PNP_LOCATION_INTERFACE, + status); return status; } @@ -151,10 +151,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware() if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "Couldn't register D3COLD_SUPPORT dummy interface %!GUID! (WdfDeviceAddQueryInterface failed with status %!STATUS!)", - &GUID_D3COLD_SUPPORT_INTERFACE, - status); + TRACE_XUSB, + "Couldn't register D3COLD_SUPPORT dummy interface %!GUID! (WdfDeviceAddQueryInterface failed with status %!STATUS!)", + &GUID_D3COLD_SUPPORT_INTERFACE, + status); return status; } @@ -172,10 +172,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware() if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "Couldn't register REENUM_SELF_STD dummy interface %!GUID! (WdfDeviceAddQueryInterface failed with status %!STATUS!)", - &GUID_REENUMERATE_SELF_INTERFACE_STANDARD, - status); + TRACE_XUSB, + "Couldn't register REENUM_SELF_STD dummy interface %!GUID! (WdfDeviceAddQueryInterface failed with status %!STATUS!)", + &GUID_REENUMERATE_SELF_INTERFACE_STANDARD, + status); return status; } @@ -209,9 +209,9 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareHardware() if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfDeviceAddQueryInterface failed with status %!STATUS!", - status); + TRACE_XUSB, + "WdfDeviceAddQueryInterface failed with status %!STATUS!", + status); return status; } @@ -229,10 +229,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::InitContext() TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XUSB, "Initializing XUSB context..."); RtlZeroMemory(this->Rumble, ARRAYSIZE(this->Rumble)); - + // Is later overwritten by actual XInput slot this->LedNumber = -1; - + RtlZeroMemory(&this->Packet, sizeof(XUSB_INTERRUPT_IN_PACKET)); // Packet size (20 bytes = 0x14) this->Packet.Size = 0x14; @@ -240,7 +240,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::InitContext() this->ReportedCapabilities = FALSE; this->InterruptInitStage = 0; - + // Allocate blob storage NTSTATUS status = WdfMemoryCreate( &attributes, @@ -253,33 +253,33 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::InitContext() if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfMemoryCreate failed with status %!STATUS!", - status); + TRACE_XUSB, + "WdfMemoryCreate failed with status %!STATUS!", + status); return status; } // Fill blob storage COPY_BYTE_ARRAY(blobBuffer, P99_PROTECT({ - // 0 - 0x01, 0x03, 0x0E, - // 1 - 0x02, 0x03, 0x00, - // 2 - 0x03, 0x03, 0x03, - // 3 - 0x08, 0x03, 0x00, - // 4 - 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xf2, - 0xb3, 0xf8, 0x49, 0xf3, 0xb0, 0xfc, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - // 5 - 0x01, 0x03, 0x03, - // 6 - 0x05, 0x03, 0x00, - // 7 - 0x31, 0x3F, 0xCF, 0xDC - })); + // 0 + 0x01, 0x03, 0x0E, + // 1 + 0x02, 0x03, 0x00, + // 2 + 0x03, 0x03, 0x03, + // 3 + 0x08, 0x03, 0x00, + // 4 + 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xf2, + 0xb3, 0xf8, 0x49, 0xf3, 0xb0, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + // 5 + 0x01, 0x03, 0x03, + // 6 + 0x05, 0x03, 0x00, + // 7 + 0x31, 0x3F, 0xCF, 0xDC + })); // I/O Queue for pending IRPs WDF_IO_QUEUE_CONFIG holdingInQueueConfig; @@ -289,16 +289,16 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::InitContext() status = WdfIoQueueCreate( this->PdoDevice, - &holdingInQueueConfig, - WDF_NO_OBJECT_ATTRIBUTES, + &holdingInQueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, &this->HoldingUsbInRequests ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, - TRACE_XUSB, - "WdfIoQueueCreate (HoldingUsbInRequests) failed with status %!STATUS!", - status); + TRACE_XUSB, + "WdfIoQueueCreate (HoldingUsbInRequests) failed with status %!STATUS!", + status); return status; } @@ -474,9 +474,9 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SelectConfiguration(PURB Urb) ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Invalid ConfigurationDescriptor"); return STATUS_INVALID_PARAMETER; } - + PUSBD_INTERFACE_INFORMATION pInfo = &Urb->UrbSelectConfiguration.Interface; - + TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XUSB, ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d", @@ -605,13 +605,99 @@ void ViGEm::Bus::Targets::EmulationTargetXUSB::AbortPipe() NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbClassInterface(PURB Urb) { UNREFERENCED_PARAMETER(Urb); - + return STATUS_NOT_IMPLEMENTED; } NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbGetDescriptorFromInterface(PURB Urb) { UNREFERENCED_PARAMETER(Urb); - + return STATUS_NOT_IMPLEMENTED; } + +NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbSelectInterface(PURB Urb) +{ + 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); + + 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 = (USBD_PIPE_TYPE)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 = (USBD_PIPE_TYPE)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 = (USBD_PIPE_TYPE)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 = (USBD_PIPE_TYPE)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 = (USBD_PIPE_TYPE)0x03; + pInfo[0].Pipes[0].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0084; + pInfo[0].Pipes[0].PipeFlags = 0x00; + + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +} diff --git a/sys/XusbPdo.hpp b/sys/XusbPdo.hpp index 73c056e..80b14f0 100644 --- a/sys/XusbPdo.hpp +++ b/sys/XusbPdo.hpp @@ -40,6 +40,7 @@ namespace ViGEm::Bus::Targets NTSTATUS UsbClassInterface(PURB Urb) override; NTSTATUS UsbGetDescriptorFromInterface(PURB Urb) override; + NTSTATUS UsbSelectInterface(PURB Urb) override; private: static PCWSTR _deviceDescription;