diff --git a/.gitignore b/.gitignore index fe8b35c..f804316 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ mono_crash.* [Rr]eleases/ x64/ x86/ +[Ww][Ii][Nn]32/ [Aa][Rr][Mm]/ [Aa][Rr][Mm]64/ bld/ @@ -61,6 +62,9 @@ project.lock.json project.fragment.lock.json artifacts/ +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + # StyleCop StyleCopReport.xml @@ -350,4 +354,7 @@ healthchecksdb MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder -.ionide/ \ No newline at end of file +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/client b/client index d466227..4657364 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit d466227688a9d2fbd437f4b9712c596a6547ec2b +Subproject commit 465736429b8fe2b9d236b01ef0404f9bceb31106 diff --git a/sys/Queue.c b/sys/Queue.c index a006934..729443c 100644 --- a/sys/Queue.c +++ b/sys/Queue.c @@ -50,8 +50,6 @@ VOID Bus_EvtIoDeviceControl( PXUSB_REQUEST_NOTIFICATION xusbNotify = NULL; PDS4_SUBMIT_REPORT ds4Submit = NULL; PDS4_REQUEST_NOTIFICATION ds4Notify = NULL; - PXGIP_SUBMIT_REPORT xgipSubmit = NULL; - PXGIP_SUBMIT_INTERRUPT xgipInterrupt = NULL; PVIGEM_CHECK_VERSION pCheckVersion = NULL; PXUSB_GET_USER_INDEX pXusbGetUserIndex = NULL; @@ -278,64 +276,6 @@ VOID Bus_EvtIoDeviceControl( break; #pragma endregion -#pragma region IOCTL_XGIP_SUBMIT_REPORT - case IOCTL_XGIP_SUBMIT_REPORT: - - TraceEvents(TRACE_LEVEL_VERBOSE, - TRACE_QUEUE, - "IOCTL_XGIP_SUBMIT_REPORT"); - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(XGIP_SUBMIT_REPORT), (PVOID)&xgipSubmit, &length); - - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); - break; - } - - if ((sizeof(XGIP_SUBMIT_REPORT) == xgipSubmit->Size) && (length == InputBufferLength)) - { - // This request only supports a single PDO at a time - if (xgipSubmit->SerialNo == 0) - { - status = STATUS_INVALID_PARAMETER; - break; - } - - status = Bus_XgipSubmitReport(Device, xgipSubmit->SerialNo, xgipSubmit, FALSE); - } - - break; -#pragma endregion - -#pragma region IOCTL_XGIP_SUBMIT_INTERRUPT - case IOCTL_XGIP_SUBMIT_INTERRUPT: - - KdPrint((DRIVERNAME "IOCTL_XGIP_SUBMIT_INTERRUPT\n")); - - status = WdfRequestRetrieveInputBuffer(Request, sizeof(XGIP_SUBMIT_INTERRUPT), (PVOID)&xgipInterrupt, &length); - - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); - break; - } - - if ((sizeof(XGIP_SUBMIT_INTERRUPT) == xgipInterrupt->Size) && (length == InputBufferLength)) - { - // This request only supports a single PDO at a time - if (xgipInterrupt->SerialNo == 0) - { - status = STATUS_INVALID_PARAMETER; - break; - } - - status = Bus_XgipSubmitInterrupt(Device, xgipSubmit->SerialNo, xgipInterrupt, FALSE); - } - - break; -#pragma endregion - #pragma region IOCTL_XUSB_GET_USER_INDEX case IOCTL_XUSB_GET_USER_INDEX: diff --git a/sys/ViGEmBus.vcxproj b/sys/ViGEmBus.vcxproj index 013607d..130a349 100644 --- a/sys/ViGEmBus.vcxproj +++ b/sys/ViGEmBus.vcxproj @@ -191,7 +191,6 @@ - @@ -206,7 +205,6 @@ - diff --git a/sys/ViGEmBus.vcxproj.filters b/sys/ViGEmBus.vcxproj.filters index c9b3ac8..5084fb0 100644 --- a/sys/ViGEmBus.vcxproj.filters +++ b/sys/ViGEmBus.vcxproj.filters @@ -48,9 +48,6 @@ Header Files - - Header Files - Header Files @@ -63,6 +60,9 @@ Header Files + + Header Files + @@ -74,9 +74,6 @@ Source Files - - Source Files - Source Files @@ -96,4 +93,9 @@ Source Files + + + Resource Files + + \ No newline at end of file diff --git a/sys/Xgip.h b/sys/Xgip.h deleted file mode 100644 index 3f12906..0000000 --- a/sys/Xgip.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -* Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver -* -* MIT License -* -* Copyright (c) 2016-2019 Nefarius Software Solutions e.U. and Contributors -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - - -// -// For children emulating XGIP devices, the following dummy interfaces -// have to be exposed by the PDO or else the child devices won't start -// - -// Below these interfaces are from wdmguid.h being used as dummies -// {70211B0E-0AFB-47DB-AFC1-410BF842497A} PNP_LOCATION_INTERFACE -// {B38290E5-3CD0-4F9D-9937-F5FE2B44D47A} D3COLD_SUPPORT_INTERFACE -// {2AEB0243-6A6E-486B-82FC-D815F6B97006} REENUMERATE_SELF_INTERFACE_STANDARD - -// {DC7A8E51-49B3-4A3A-9E81-625205E7D729} Seems to be GUID_POWER_THREAD_INTERFACE -// Source: https://github.com/microsoft/Windows-Driver-Frameworks/blob/master/src/framework/shared/irphandlers/pnp/fxpkgpnp.cpp#L63 -DEFINE_GUID(GUID_DEVINTERFACE_XGIP_GUID_POWER_THREAD_INTERFACE_DUMMY, - 0xDC7A8E51, 0x49B3, 0x4A3A, 0x9E, 0x81, 0x62, 0x52, 0x05, 0xE7, 0xD7, 0x29); - -// {DEEE98EA-C0A1-42C3-9738-A04606C84E93} -DEFINE_GUID(GUID_DEVINTERFACE_XGIP_UNKNOWN_4, - 0xDEEE98EA, 0xC0A1, 0x42C3, 0x97, 0x38, 0xA0, 0x46, 0x06, 0xC8, 0x4E, 0x93); - - -#pragma once - -#define XGIP_DESCRIPTOR_SIZE 0x0040 -#define XGIP_CONFIGURATION_SIZE 0x88 -#define XGIP_REPORT_SIZE 0x12 -#define XGIP_SYS_INIT_PACKETS 0x0F -#define XGIP_SYS_INIT_PERIOD 0x32 - -typedef struct _XGIP_DEVICE_DATA -{ - UCHAR Report[XGIP_REPORT_SIZE]; - - // - // Queue for incoming interrupt transfer - // - WDFQUEUE PendingUsbInRequests; - - // - // Queue for inverted calls - // - WDFQUEUE PendingNotificationRequests; - - WDFCOLLECTION XboxgipSysInitCollection; - - BOOLEAN XboxgipSysInitReady; - - WDFTIMER XboxgipSysInitTimer; -} XGIP_DEVICE_DATA, *PXGIP_DEVICE_DATA; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XGIP_DEVICE_DATA, XgipGetData) - - -NTSTATUS -Bus_XgipSubmitInterrupt( - WDFDEVICE Device, - ULONG SerialNo, - PXGIP_SUBMIT_INTERRUPT Report, - _In_ BOOLEAN FromInterface -); - -// -// XGIP-specific functions -// -NTSTATUS Xgip_PreparePdo( - PWDFDEVICE_INIT DeviceInit, - PUNICODE_STRING DeviceId, - PUNICODE_STRING DeviceDescription -); -NTSTATUS Xgip_PrepareHardware(WDFDEVICE Device); -NTSTATUS Xgip_AssignPdoContext(WDFDEVICE Device); -VOID Xgip_GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length); -VOID Xgip_GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor, PPDO_DEVICE_DATA pCommon); -VOID Xgip_SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo); - diff --git a/sys/busenum.c b/sys/busenum.c index 923138b..e9dadf8 100644 --- a/sys/busenum.c +++ b/sys/busenum.c @@ -140,17 +140,8 @@ NTSTATUS Bus_PlugInDevice( description.ProductId = 0x05C4; break; - case XboxOneWired: - - description.VendorId = 0x0E6F; - description.ProductId = 0x0139; - -#if !DBG - // TODO: implement and remove! + default: return STATUS_NOT_SUPPORTED; -#endif - - break; } } else @@ -548,20 +539,6 @@ NTSTATUS Bus_Ds4SubmitReport(WDFDEVICE Device, ULONG SerialNo, PDS4_SUBMIT_REPOR return Bus_SubmitReport(Device, SerialNo, Report, FromInterface); } -NTSTATUS Bus_XgipSubmitReport(WDFDEVICE Device, ULONG SerialNo, PXGIP_SUBMIT_REPORT Report, BOOLEAN FromInterface) -{ - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSENUM, "%!FUNC! Entry"); - - return Bus_SubmitReport(Device, SerialNo, Report, FromInterface); -} - -NTSTATUS Bus_XgipSubmitInterrupt(WDFDEVICE Device, ULONG SerialNo, PXGIP_SUBMIT_INTERRUPT Report, BOOLEAN FromInterface) -{ - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSENUM, "%!FUNC! Entry"); - - return Bus_SubmitReport(Device, SerialNo, Report, FromInterface); -} - WDFDEVICE Bus_GetPdo(IN WDFDEVICE Device, IN ULONG SerialNo) { WDFCHILDLIST list; @@ -639,12 +616,6 @@ NTSTATUS Bus_SubmitReport(WDFDEVICE Device, ULONG SerialNo, PVOID Report, BOOLEA changed = TRUE; - break; - case XboxOneWired: - - // TODO: necessary? - changed = TRUE; - break; default: @@ -679,60 +650,6 @@ NTSTATUS Bus_SubmitReport(WDFDEVICE Device, ULONG SerialNo, PVOID Report, BOOLEA status = WdfIoQueueRetrieveNextRequest(pdoData->PendingUsbInRequests, &usbRequest); - break; - case XboxOneWired: - - // Request is control data - if (((PXGIP_SUBMIT_INTERRUPT)Report)->Size == sizeof(XGIP_SUBMIT_INTERRUPT)) - { - PXGIP_DEVICE_DATA xgip = XgipGetData(hChild); - PXGIP_SUBMIT_INTERRUPT interrupt = (PXGIP_SUBMIT_INTERRUPT)Report; - WDFMEMORY memory; - WDF_OBJECT_ATTRIBUTES memAttribs; - WDF_OBJECT_ATTRIBUTES_INIT(&memAttribs); - - memAttribs.ParentObject = hChild; - - // Allocate kernel memory - status = WdfMemoryCreate(&memAttribs, NonPagedPool, VIGEM_POOL_TAG, - interrupt->InterruptLength, &memory, NULL); - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfMemoryCreate failed with status 0x%X\n", status)); - goto endSubmitReport; - } - - // Copy interrupt buffer to memory object - status = WdfMemoryCopyFromBuffer(memory, 0, interrupt->Interrupt, interrupt->InterruptLength); - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfMemoryCopyFromBuffer failed with status 0x%X\n", status)); - goto endSubmitReport; - } - - // Add memory object to collection - status = WdfCollectionAdd(xgip->XboxgipSysInitCollection, memory); - if (!NT_SUCCESS(status)) - { - KdPrint((DRIVERNAME "WdfCollectionAdd failed with status 0x%X\n", status)); - goto endSubmitReport; - } - - // Check if all packets have been received - xgip->XboxgipSysInitReady = - WdfCollectionGetCount(xgip->XboxgipSysInitCollection) == XGIP_SYS_INIT_PACKETS; - - // If all packets are cached, start initialization timer - if (xgip->XboxgipSysInitReady) - { - WdfTimerStart(xgip->XboxgipSysInitTimer, XGIP_SYS_INIT_PERIOD); - } - - goto endSubmitReport; - } - - status = WdfIoQueueRetrieveNextRequest(XgipGetData(hChild)->PendingUsbInRequests, &usbRequest); - break; default: @@ -788,25 +705,6 @@ NTSTATUS Bus_SubmitReport(WDFDEVICE Device, ULONG SerialNo, PVOID Report, BOOLEA if (Buffer) RtlCopyBytes(Buffer, Ds4GetData(hChild)->Report, DS4_REPORT_SIZE); - break; - case XboxOneWired: - - // Request is input report - if (((PXGIP_SUBMIT_REPORT)Report)->Size == sizeof(XGIP_SUBMIT_REPORT)) - { - urb->UrbBulkOrInterruptTransfer.TransferBufferLength = XGIP_REPORT_SIZE; - - // Increase event counter on every call (can roll-over) - XgipGetData(hChild)->Report[2]++; - - /* Copy report to cache and transfer buffer - * Skip first four bytes as they are not part of the report */ - RtlCopyBytes(XgipGetData(hChild)->Report + 4, &((PXGIP_SUBMIT_REPORT)Report)->Report, sizeof(XGIP_REPORT)); - RtlCopyBytes(Buffer, XgipGetData(hChild)->Report, XGIP_REPORT_SIZE); - - break; - } - break; default: status = STATUS_INVALID_PARAMETER; diff --git a/sys/busenum.h b/sys/busenum.h index 4fe86fe..af1cdbe 100644 --- a/sys/busenum.h +++ b/sys/busenum.h @@ -44,7 +44,6 @@ #include "UsbPdo.h" #include "Xusb.h" #include "Ds4.h" -#include "Xgip.h" #pragma region Macros @@ -106,8 +105,6 @@ EVT_WDF_DEVICE_PREPARE_HARDWARE Pdo_EvtDevicePrepareHardware; EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL Pdo_EvtIoInternalDeviceControl; -EVT_WDF_TIMER Xgip_SysInitTimerFunc; - EVT_WDF_OBJECT_CONTEXT_CLEANUP Bus_EvtDriverContextCleanup; EVT_WDF_TIMER Bus_PlugInRequestCleanUpEvtTimerFunc; @@ -146,14 +143,6 @@ Bus_QueueNotification( WDFREQUEST Request ); -NTSTATUS -Bus_XgipSubmitReport( - WDFDEVICE Device, - ULONG SerialNo, - PXGIP_SUBMIT_REPORT Report, - _In_ BOOLEAN FromInterface -); - NTSTATUS Bus_SubmitReport( WDFDEVICE Device, diff --git a/sys/buspdo.c b/sys/buspdo.c index 7226ed9..05cb933 100644 --- a/sys/buspdo.c +++ b/sys/buspdo.c @@ -189,18 +189,6 @@ NTSTATUS Bus_CreatePdo( break; - // - // A Xbox One device was requested - // - case XboxOneWired: - - status = Xgip_PreparePdo(DeviceInit, &deviceId, &deviceDescription); - - if (!NT_SUCCESS(status)) - goto endCreatePdo; - - break; - default: status = STATUS_INVALID_PARAMETER; @@ -334,23 +322,6 @@ NTSTATUS Bus_CreatePdo( break; } - case XboxOneWired: - { - PXGIP_DEVICE_DATA xgipData = NULL; - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, XGIP_DEVICE_DATA); - - status = WdfObjectAllocateContext(hChild, &pdoAttributes, (PVOID)&xgipData); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, - TRACE_BUSPDO, - "WdfObjectAllocateContext failed with status %!STATUS!", - status); - goto endCreatePdo; - } - - break; - } default: break; } @@ -406,13 +377,6 @@ NTSTATUS Bus_CreatePdo( status = Ds4_AssignPdoContext(hChild, Description); break; - - case XboxOneWired: - - status = Xgip_AssignPdoContext(hChild); - - break; - default: break; } @@ -563,12 +527,6 @@ NTSTATUS Pdo_EvtDevicePrepareHardware( break; - case XboxOneWired: - - status = Xgip_PrepareHardware(Device); - - break; - default: break; } diff --git a/sys/usbpdo.c b/sys/usbpdo.c index 7904a1c..a7cb329 100644 --- a/sys/usbpdo.c +++ b/sys/usbpdo.c @@ -145,12 +145,6 @@ NTSTATUS UsbPdo_GetDeviceDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommon) break; - case XboxOneWired: - - Xgip_GetDeviceDescriptorType(pDescriptor, pCommon); - - break; - default: return STATUS_UNSUCCESSFUL; } @@ -181,11 +175,6 @@ NTSTATUS UsbPdo_GetConfigurationDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommo Ds4_GetConfigurationDescriptorType(Buffer, length); - break; - case XboxOneWired: - - Xgip_GetConfigurationDescriptorType(Buffer, length); - break; default: return STATUS_UNSUCCESSFUL; @@ -212,14 +201,6 @@ NTSTATUS UsbPdo_GetConfigurationDescriptorType(PURB urb, PPDO_DEVICE_DATA pCommo Ds4_GetConfigurationDescriptorType(Buffer, DS4_DESCRIPTOR_SIZE); } - break; - case XboxOneWired: - - if (length >= XGIP_DESCRIPTOR_SIZE) - { - Xgip_GetConfigurationDescriptorType(Buffer, XGIP_DESCRIPTOR_SIZE); - } - break; default: return STATUS_UNSUCCESSFUL; @@ -382,20 +363,6 @@ NTSTATUS UsbPdo_SelectConfiguration(PURB urb, PPDO_DEVICE_DATA pCommon) break; - case XboxOneWired: - - if (urb->UrbHeader.Length < XGIP_CONFIGURATION_SIZE) - { - TraceEvents(TRACE_LEVEL_WARNING, - TRACE_USBPDO, - ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Invalid ConfigurationDescriptor"); - return STATUS_INVALID_PARAMETER; - } - - Xgip_SelectConfiguration(pInfo); - - break; - default: return STATUS_UNSUCCESSFUL; } @@ -800,31 +767,6 @@ NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST R break; } - case XboxOneWired: - { - PXGIP_DEVICE_DATA xgipData = XgipGetData(Device); - - // Data coming FROM us TO higher driver - if (pTransfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN) - { - KdPrint((DRIVERNAME ">> >> >> 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, xgipData->PendingUsbInRequests); - - return (NT_SUCCESS(status)) ? STATUS_PENDING : status; - } - - // Data coming FROM the higher driver TO us - KdPrint((DRIVERNAME ">> >> >> URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: Handle %p, Flags %X, Length %d", - pTransfer->PipeHandle, - pTransfer->TransferFlags, - pTransfer->TransferBufferLength)); - - break; - } default: break; } diff --git a/sys/xgip.c b/sys/xgip.c deleted file mode 100644 index cc288dc..0000000 --- a/sys/xgip.c +++ /dev/null @@ -1,409 +0,0 @@ -/* -* Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver -* -* MIT License -* -* Copyright (c) 2016-2019 Nefarius Software Solutions e.U. and Contributors -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - - -#include "busenum.h" -#include -#include "xgip.tmh" - -NTSTATUS Xgip_PreparePdo(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId, PUNICODE_STRING DeviceDescription) -{ - NTSTATUS status; - UNICODE_STRING buffer; - - // prepare device description - status = RtlUnicodeStringInit(DeviceDescription, L"Virtual Xbox One Controller"); - if (!NT_SUCCESS(status)) - return status; - - // Set hardware IDs - RtlUnicodeStringInit(&buffer, L"USB\\VID_0E6F&PID_0139&REV_0650"); - - status = WdfPdoInitAddHardwareID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - RtlUnicodeStringCopy(DeviceId, &buffer); - - RtlUnicodeStringInit(&buffer, L"USB\\VID_0E6F&PID_0139"); - - status = WdfPdoInitAddHardwareID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - // Set compatible IDs - RtlUnicodeStringInit(&buffer, L"USB\\MS_COMP_XGIP10"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - RtlUnicodeStringInit(&buffer, L"USB\\Class_FF&SubClass_47&Prot_D0"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - RtlUnicodeStringInit(&buffer, L"USB\\Class_FF&SubClass_47"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - RtlUnicodeStringInit(&buffer, L"USB\\Class_FF"); - - status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer); - if (!NT_SUCCESS(status)) - return status; - - return STATUS_SUCCESS; -} - -NTSTATUS Xgip_PrepareHardware(WDFDEVICE Device) -{ - NTSTATUS status; - WDF_QUERY_INTERFACE_CONFIG ifaceCfg; - - // Expose USB_BUS_INTERFACE_USBDI_GUID - USB_BUS_INTERFACE_USBDI_V1 xgipInterface; - - xgipInterface.Size = sizeof(USB_BUS_INTERFACE_USBDI_V1); - xgipInterface.Version = USB_BUSIF_USBDI_VERSION_1; - xgipInterface.BusContext = (PVOID)Device; - - xgipInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; - xgipInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; - - xgipInterface.SubmitIsoOutUrb = UsbPdo_SubmitIsoOutUrb; - xgipInterface.GetUSBDIVersion = UsbPdo_GetUSBDIVersion; - xgipInterface.QueryBusTime = UsbPdo_QueryBusTime; - xgipInterface.QueryBusInformation = UsbPdo_QueryBusInformation; - xgipInterface.IsDeviceHighSpeed = UsbPdo_IsDeviceHighSpeed; - - WDF_QUERY_INTERFACE_CONFIG_INIT(&ifaceCfg, (PINTERFACE)&xgipInterface, &USB_BUS_INTERFACE_USBDI_GUID, NULL); - - status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_XGIP, "WdfDeviceAddQueryInterface failed with status %!STATUS!", status); - return status; - } - - // Default button states - UCHAR DefaultReport[XGIP_REPORT_SIZE] = - { - 0x20, 0x00, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xa3, 0xfd, 0xed, 0x05, 0x5b, 0x03, - 0x6f, 0x02 - }; - - RtlCopyBytes(XgipGetData(Device)->Report, DefaultReport, XGIP_REPORT_SIZE); - - return STATUS_SUCCESS; -} - -NTSTATUS Xgip_AssignPdoContext(WDFDEVICE Device) -{ - NTSTATUS status; - - PXGIP_DEVICE_DATA xgip = XgipGetData(Device); - - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XGIP, "Initializing XGIP context..."); - - RtlZeroMemory(xgip, sizeof(XGIP_DEVICE_DATA)); - - // Set fixed report id - xgip->Report[0] = 0x20; - xgip->Report[3] = 0x0E; - - // I/O Queue for pending IRPs - WDF_IO_QUEUE_CONFIG pendingUsbQueueConfig, notificationsQueueConfig; - - // Create and assign queue for incoming interrupt transfer - WDF_IO_QUEUE_CONFIG_INIT(&pendingUsbQueueConfig, WdfIoQueueDispatchManual); - - status = WdfIoQueueCreate(Device, &pendingUsbQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &xgip->PendingUsbInRequests); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_XGIP, "WdfIoQueueCreate failed with status %!STATUS!", status); - return status; - } - - // Create and assign queue for user-land notification requests - WDF_IO_QUEUE_CONFIG_INIT(¬ificationsQueueConfig, WdfIoQueueDispatchManual); - - status = WdfIoQueueCreate(Device, ¬ificationsQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &xgip->PendingNotificationRequests); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_XGIP, "WdfIoQueueCreate failed with status %!STATUS!", status); - return status; - } - - WDF_OBJECT_ATTRIBUTES collectionAttribs; - WDF_OBJECT_ATTRIBUTES_INIT(&collectionAttribs); - - collectionAttribs.ParentObject = Device; - - status = WdfCollectionCreate(&collectionAttribs, &xgip->XboxgipSysInitCollection); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_XGIP, "WdfCollectionCreate failed with status %!STATUS!", status); - return status; - } - - // Initialize periodic timer - WDF_TIMER_CONFIG timerConfig; - WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, Xgip_SysInitTimerFunc, XGIP_SYS_INIT_PERIOD); - - // Timer object attributes - WDF_OBJECT_ATTRIBUTES timerAttribs; - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttribs); - - // PDO is parent - timerAttribs.ParentObject = Device; - - // Create timer - status = WdfTimerCreate(&timerConfig, &timerAttribs, &xgip->XboxgipSysInitTimer); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_XGIP, "WdfTimerCreate failed with status %!STATUS!", status); - return status; - } - - return STATUS_SUCCESS; -} - -VOID Xgip_GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) -{ - UCHAR XgipDescriptorData[XGIP_DESCRIPTOR_SIZE] = - { - 0x09, // bLength - 0x02, // bDescriptorType (Configuration) - 0x40, 0x00, // wTotalLength 64 - 0x02, // bNumInterfaces 2 - 0x01, // bConfigurationValue - 0x00, // iConfiguration (String Index) - 0xC0, // bmAttributes - 0xFA, // bMaxPower 500mA - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x00, // bInterfaceNumber 0 - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints 2 - 0xFF, // bInterfaceClass - 0x47, // bInterfaceSubClass - 0xD0, // bInterfaceProtocol - 0x00, // iInterface (String Index) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x81, // bEndpointAddress (IN/D2H) - 0x03, // bmAttributes (Interrupt) - 0x40, 0x00, // wMaxPacketSize 64 - 0x04, // bInterval 4 (unit depends on device speed) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x01, // bEndpointAddress (OUT/H2D) - 0x03, // bmAttributes (Interrupt) - 0x40, 0x00, // wMaxPacketSize 64 - 0x04, // bInterval 4 (unit depends on device speed) - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x01, // bInterfaceNumber 1 - 0x00, // bAlternateSetting - 0x00, // bNumEndpoints 0 - 0xFF, // bInterfaceClass - 0x47, // bInterfaceSubClass - 0xD0, // bInterfaceProtocol - 0x00, // iInterface (String Index) - - 0x09, // bLength - 0x04, // bDescriptorType (Interface) - 0x01, // bInterfaceNumber 1 - 0x01, // bAlternateSetting - 0x02, // bNumEndpoints 2 - 0xFF, // bInterfaceClass - 0x47, // bInterfaceSubClass - 0xD0, // bInterfaceProtocol - 0x00, // iInterface (String Index) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x02, // bEndpointAddress (OUT/H2D) - 0x01, // bmAttributes (Isochronous, No Sync, Data EP) - 0xE0, 0x00, // wMaxPacketSize 224 - 0x01, // bInterval 1 (unit depends on device speed) - - 0x07, // bLength - 0x05, // bDescriptorType (Endpoint) - 0x83, // bEndpointAddress (IN/D2H) - 0x01, // bmAttributes (Isochronous, No Sync, Data EP) - 0x80, 0x00, // wMaxPacketSize 128 - 0x01, // bInterval 1 (unit depends on device speed) - - // 64 bytes - - // best guess: USB Standard Descriptor - }; - - RtlCopyBytes(Buffer, XgipDescriptorData, Length); -} - -VOID Xgip_GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor, PPDO_DEVICE_DATA pCommon) -{ - pDescriptor->bLength = 0x12; - pDescriptor->bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE; - pDescriptor->bcdUSB = 0x0200; // USB v2.0 - pDescriptor->bDeviceClass = 0xFF; - pDescriptor->bDeviceSubClass = 0x47; - pDescriptor->bDeviceProtocol = 0xD0; - pDescriptor->bMaxPacketSize0 = 0x40; - pDescriptor->idVendor = pCommon->VendorId; - pDescriptor->idProduct = pCommon->ProductId; - pDescriptor->bcdDevice = 0x0650; - pDescriptor->iManufacturer = 0x01; - pDescriptor->iProduct = 0x02; - pDescriptor->iSerialNumber = 0x03; - pDescriptor->bNumConfigurations = 0x01; -} - -VOID Xgip_SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo) -{ - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_XGIP, ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d", - (int)pInfo->Length, - (int)pInfo->InterfaceNumber, - (int)pInfo->AlternateSetting, - pInfo->NumberOfPipes); - - pInfo->Class = 0xFF; - pInfo->SubClass = 0x47; - pInfo->Protocol = 0xD0; - - pInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; - - pInfo->Pipes[0].MaximumTransferSize = 0x00400000; - pInfo->Pipes[0].MaximumPacketSize = 0x40; - pInfo->Pipes[0].EndpointAddress = 0x81; - pInfo->Pipes[0].Interval = 0x04; - pInfo->Pipes[0].PipeType = UsbdPipeTypeInterrupt; - pInfo->Pipes[0].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0081; - pInfo->Pipes[0].PipeFlags = 0x00; - - pInfo->Pipes[1].MaximumTransferSize = 0x00400000; - pInfo->Pipes[1].MaximumPacketSize = 0x40; - pInfo->Pipes[1].EndpointAddress = 0x01; - pInfo->Pipes[1].Interval = 0x04; - pInfo->Pipes[1].PipeType = UsbdPipeTypeInterrupt; - pInfo->Pipes[1].PipeHandle = (USBD_PIPE_HANDLE)0xFFFF0001; - pInfo->Pipes[1].PipeFlags = 0x00; - - pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_XGIP, ">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d", - (int)pInfo->Length, - (int)pInfo->InterfaceNumber, - (int)pInfo->AlternateSetting, - pInfo->NumberOfPipes); - - pInfo->Class = 0xFF; - pInfo->SubClass = 0x47; - pInfo->Protocol = 0xD0; - - pInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000; -} - -VOID Xgip_SysInitTimerFunc( - _In_ WDFTIMER Timer -) -{ - NTSTATUS status; - WDFDEVICE hChild; - PXGIP_DEVICE_DATA xgip; - WDFREQUEST usbRequest; - PIRP pendingIrp; - PIO_STACK_LOCATION irpStack; - WDFMEMORY mem; - - hChild = WdfTimerGetParentObject(Timer); - xgip = XgipGetData(hChild); - - if (xgip == NULL) return; - - // Is TRUE when collection is filled up - if (xgip->XboxgipSysInitReady) - { - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XGIP, "XBOXGIP ready, completing requests..."); - - // Get pending IN request - status = WdfIoQueueRetrieveNextRequest(xgip->PendingUsbInRequests, &usbRequest); - - if (NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XGIP, "Request found"); - - // Get top memory object - mem = (WDFMEMORY)WdfCollectionGetFirstItem(xgip->XboxgipSysInitCollection); - - // Get pending IRP - pendingIrp = WdfRequestWdmGetIrp(usbRequest); - irpStack = IoGetCurrentIrpStackLocation(pendingIrp); - - // Get USB request block - PURB urb = (PURB)irpStack->Parameters.Others.Argument1; - - // Get buffer size and content - size_t size; - PUCHAR Buffer = WdfMemoryGetBuffer(mem, &size); - - // Assign buffer size and content to URB - urb->UrbBulkOrInterruptTransfer.TransferBufferLength = (ULONG)size; - RtlCopyBytes(urb->UrbBulkOrInterruptTransfer.TransferBuffer, Buffer, size); - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_XGIP, "[%X] Buffer length: %d", - ((PUCHAR)urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0], - urb->UrbBulkOrInterruptTransfer.TransferBufferLength); - - // Complete pending request - WdfRequestComplete(usbRequest, status); - - // Free memory from collection - WdfCollectionRemoveItem(xgip->XboxgipSysInitCollection, 0); - WdfObjectDelete(mem); - } - - // Stop timer when collection is purged - if (WdfCollectionGetCount(xgip->XboxgipSysInitCollection) == 0) - { - TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XGIP, "Collection finished"); - - WdfTimerStop(xgip->XboxgipSysInitTimer, FALSE); - } - } -} -