diff --git a/sys/EmulationTargetPDO.hpp b/sys/EmulationTargetPDO.hpp index 2f3d065..c630ca2 100644 --- a/sys/EmulationTargetPDO.hpp +++ b/sys/EmulationTargetPDO.hpp @@ -70,6 +70,12 @@ namespace ViGEm::Bus::Core OUT EmulationTargetPDO** Object ); + static bool GetPdoBySerial( + IN WDFDEVICE ParentDevice, + IN ULONG SerialNo, + OUT EmulationTargetPDO** Object + ); + virtual NTSTATUS PdoPrepareDevice(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId, PUNICODE_STRING DeviceDescription) = 0; @@ -124,12 +130,6 @@ namespace ViGEm::Bus::Core static EVT_WDF_DEVICE_CONTEXT_CLEANUP EvtDeviceContextCleanup; - static bool GetPdoBySerial( - IN WDFDEVICE ParentDevice, - IN ULONG SerialNo, - OUT EmulationTargetPDO** Object - ); - HANDLE _WaitDeviceReadyCompletionWorkerThreadHandle{}; protected: diff --git a/sys/Queue.cpp b/sys/Queue.cpp index da1bd42..571c380 100644 --- a/sys/Queue.cpp +++ b/sys/Queue.cpp @@ -68,6 +68,7 @@ VOID Bus_EvtIoDeviceControl( PDS4_SUBMIT_REPORT ds4Submit = nullptr; PDS4_REQUEST_NOTIFICATION ds4Notify = nullptr; PVIGEM_CHECK_VERSION pCheckVersion = nullptr; + PVIGEM_WAIT_DEVICE_READY pWaitDeviceReady = nullptr; PXUSB_GET_USER_INDEX pXusbGetUserIndex = nullptr; EmulationTargetPDO* pdo; @@ -107,6 +108,47 @@ VOID Bus_EvtIoDeviceControl( #pragma endregion +#pragma region IOCTL_VIGEM_WAIT_DEVICE_READY + + case IOCTL_VIGEM_WAIT_DEVICE_READY: + + TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_WAIT_DEVICE_READY"); + + status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(VIGEM_WAIT_DEVICE_READY), + reinterpret_cast(&pWaitDeviceReady), + &length + ); + + if (!NT_SUCCESS(status) || length != sizeof(VIGEM_WAIT_DEVICE_READY)) + { + status = STATUS_INVALID_PARAMETER; + break; + } + + // This request only supports a single PDO at a time + if (pWaitDeviceReady->SerialNo == 0) + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_QUEUE, + "Invalid serial 0 submitted"); + + status = STATUS_INVALID_PARAMETER; + break; + } + + if (!EmulationTargetPDO::GetPdoBySerial(Device, xusbSubmit->SerialNo, &pdo)) + status = STATUS_DEVICE_DOES_NOT_EXIST; + else + status = pdo->EnqueueWaitDeviceReady(Request); + + status = NT_SUCCESS(status) ? STATUS_PENDING : status; + + break; + +#pragma endregion + #pragma region IOCTL_VIGEM_PLUGIN_TARGET case IOCTL_VIGEM_PLUGIN_TARGET: