diff --git a/sys/Ds4Pdo.cpp b/sys/Ds4Pdo.cpp index 4c93eaa..c949f82 100644 --- a/sys/Ds4Pdo.cpp +++ b/sys/Ds4Pdo.cpp @@ -12,6 +12,7 @@ PCWSTR ViGEm::Bus::Targets::EmulationTargetDS4::_deviceDescription = L"Virtual D ViGEm::Bus::Targets::EmulationTargetDS4::EmulationTargetDS4() : EmulationTargetPDO(0x054C, 0x05C4) { TargetType = DualShock4Wired; + UsbConfigurationDescriptionSize = DS4_DESCRIPTOR_SIZE; } NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PrepareDevice(PWDFDEVICE_INIT DeviceInit, diff --git a/sys/EmulationTargetPDO.cpp b/sys/EmulationTargetPDO.cpp index 407c01b..c222a0c 100644 --- a/sys/EmulationTargetPDO.cpp +++ b/sys/EmulationTargetPDO.cpp @@ -162,8 +162,8 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::CreateDevice(WDFDEVICE Device, PW #pragma region Expose USB Interface status = WdfDeviceCreateDeviceInterface( - Device, - const_cast(&GUID_DEVINTERFACE_USB_DEVICE), + Device, + const_cast(&GUID_DEVINTERFACE_USB_DEVICE), NULL ); if (!NT_SUCCESS(status)) @@ -219,9 +219,9 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::CreateDevice(WDFDEVICE Device, PW WDF_IO_QUEUE_CONFIG_INIT(¬ificationsQueueConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate( - Device, - ¬ificationsQueueConfig, - WDF_NO_OBJECT_ATTRIBUTES, + Device, + ¬ificationsQueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, &this->PendingNotificationRequests ); if (!NT_SUCCESS(status)) @@ -242,9 +242,9 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::CreateDevice(WDFDEVICE Device, PW defaultPdoQueueConfig.EvtIoInternalDeviceControl = EvtIoInternalDeviceControl; status = WdfIoQueueCreate( - this->PdoDevice, - &defaultPdoQueueConfig, - WDF_NO_OBJECT_ATTRIBUTES, + this->PdoDevice, + &defaultPdoQueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, &defaultPdoQueue ); if (!NT_SUCCESS(status)) @@ -295,7 +295,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::CreateDevice(WDFDEVICE Device, PW } while (FALSE); TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status); - + return status; } @@ -377,8 +377,33 @@ void ViGEm::Bus::Core::EmulationTargetPDO::UsbAbortPipe() WdfIoQueuePurge(this->PendingNotificationRequests, NULL, NULL); } +NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::UsbGetConfigurationDescriptorType(PURB Urb) +{ + const PUCHAR Buffer = (PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer; + + // First request just gets required buffer size back + if (Urb->UrbControlDescriptorRequest.TransferBufferLength == sizeof(USB_CONFIGURATION_DESCRIPTOR)) + { + const ULONG length = sizeof(USB_CONFIGURATION_DESCRIPTOR); + + this->GetConfigurationDescriptorType(Buffer, length); + return STATUS_SUCCESS; + } + + const ULONG length = Urb->UrbControlDescriptorRequest.TransferBufferLength; + + // Second request can store the whole descriptor + if (length >= UsbConfigurationDescriptionSize) + { + this->GetConfigurationDescriptorType(Buffer, UsbConfigurationDescriptionSize); + return STATUS_SUCCESS; + } + + return STATUS_UNSUCCESSFUL; +} + NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::UsbSelectConfiguration(PURB Urb) -{ +{ TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_USBPDO, ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: TotalLength %d", @@ -408,7 +433,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EvtDevicePrepareHardware( { UNREFERENCED_PARAMETER(ResourcesRaw); UNREFERENCED_PARAMETER(ResourcesTranslated); - + const auto ctx = EmulationTargetPdoGetContext(Device); return ctx->Target->PrepareHardware(); diff --git a/sys/EmulationTargetPDO.hpp b/sys/EmulationTargetPDO.hpp index f13a620..dbc4ef6 100644 --- a/sys/EmulationTargetPDO.hpp +++ b/sys/EmulationTargetPDO.hpp @@ -38,7 +38,7 @@ namespace ViGEm::Bus::Core virtual NTSTATUS InitContext() = 0; - virtual VOID GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) = 0; + virtual VOID GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor) = 0; @@ -58,6 +58,8 @@ namespace ViGEm::Bus::Core NTSTATUS UsbSelectConfiguration(PURB Urb); void UsbAbortPipe(); + + NTSTATUS UsbGetConfigurationDescriptorType(PURB Urb); protected: static const ULONG _maxHardwareIdLength = 0xFF; @@ -90,6 +92,8 @@ namespace ViGEm::Bus::Core static const int MAX_INSTANCE_ID_LEN = 80; + virtual VOID GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) = 0; + virtual NTSTATUS SelectConfiguration(PURB Urb) = 0; virtual void AbortPipe() = 0; @@ -138,6 +142,11 @@ namespace ViGEm::Bus::Core // Signals the bus that PDO is ready to receive data // KEVENT PdoBootNotificationEvent; + + // + // Configuration descriptor size + // + ULONG UsbConfigurationDescriptionSize; }; typedef struct _PDO_IDENTIFICATION_DESCRIPTION diff --git a/sys/XusbPdo.cpp b/sys/XusbPdo.cpp index 0c826bc..b43e65c 100644 --- a/sys/XusbPdo.cpp +++ b/sys/XusbPdo.cpp @@ -12,6 +12,7 @@ PCWSTR ViGEm::Bus::Targets::EmulationTargetXUSB::_deviceDescription = L"Virtual ViGEm::Bus::Targets::EmulationTargetXUSB::EmulationTargetXUSB() : EmulationTargetPDO(0x045E, 0x028E) { TargetType = Xbox360Wired; + UsbConfigurationDescriptionSize = XUSB_DESCRIPTOR_SIZE; } NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PrepareDevice(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId,