From be5a84c4f20cdfae98624e178e43b1eda559ca6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 11 May 2020 13:38:47 +0200 Subject: [PATCH] Implemented ViGEm::Bus::Targets::EmulationTargetDS4::UsbBulkOrInterruptTransfer --- sys/Ds4Pdo.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/sys/Ds4Pdo.cpp b/sys/Ds4Pdo.cpp index 5dd83f5..baccb6d 100644 --- a/sys/Ds4Pdo.cpp +++ b/sys/Ds4Pdo.cpp @@ -974,10 +974,63 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetStringDescriptorType(PUR NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbBulkOrInterruptTransfer(_URB_BULK_OR_INTERRUPT_TRANSFER* pTransfer, WDFREQUEST Request) { - UNREFERENCED_PARAMETER(pTransfer); - UNREFERENCED_PARAMETER(Request); + NTSTATUS status; + WDFREQUEST notifyRequest; - return NTSTATUS(); + // Data coming FROM us TO higher driver + if (pTransfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN + && pTransfer->PipeHandle == reinterpret_cast(0xFFFF0084)) + { + TraceEvents(TRACE_LEVEL_VERBOSE, + TRACE_USBPDO, + ">> >> >> 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, this->PendingUsbInRequests); + + return (NT_SUCCESS(status)) ? STATUS_PENDING : status; + } + + // Store relevant bytes of buffer in PDO context + RtlCopyBytes(&this->OutputReport, + static_cast(pTransfer->TransferBuffer) + DS4_OUTPUT_BUFFER_OFFSET, + DS4_OUTPUT_BUFFER_LENGTH); + + // Notify user-mode process that new data is available + status = WdfIoQueueRetrieveNextRequest(this->PendingNotificationRequests, ¬ifyRequest); + + if (NT_SUCCESS(status)) + { + PDS4_REQUEST_NOTIFICATION notify = NULL; + + status = WdfRequestRetrieveOutputBuffer( + notifyRequest, + sizeof(DS4_REQUEST_NOTIFICATION), + reinterpret_cast(¬ify), + nullptr + ); + + if (NT_SUCCESS(status)) + { + // Assign values to output buffer + notify->Size = sizeof(DS4_REQUEST_NOTIFICATION); + notify->SerialNo = this->SerialNo; + notify->Report = this->OutputReport; + + WdfRequestCompleteWithInformation(notifyRequest, status, notify->Size); + } + else + { + TraceEvents(TRACE_LEVEL_ERROR, + TRACE_USBPDO, + "WdfRequestRetrieveOutputBuffer failed with status %!STATUS!", + status); + } + } + + return status; } VOID ViGEm::Bus::Targets::EmulationTargetDS4::PendingUsbRequestsTimerFunc(