mirror of
https://github.com/nefarius/ViGEmBus.git
synced 2025-08-10 00:52:17 +00:00
Compare commits
3 Commits
v1.16.95.0
...
v1.16.102.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca03977296 | ||
|
|
c5a46e884b | ||
|
|
31d65aa40e |
13
sys/Xusb.h
13
sys/Xusb.h
@@ -49,7 +49,15 @@ DEFINE_GUID(GUID_DEVINTERFACE_XUSB_UNKNOWN_2,
|
||||
#define XUSB_LEDSET_SIZE 0x03
|
||||
#define XUSB_LEDNUM_SIZE 0x01
|
||||
#define XUSB_INIT_STAGE_SIZE 0x03
|
||||
#define XUSB_INIT_BLOB_COUNT 0x07
|
||||
#define XUSB_BLOB_STORAGE_SIZE 0x26
|
||||
|
||||
#define XUSB_BLOB_00_OFFSET 0x00
|
||||
#define XUSB_BLOB_01_OFFSET 0x03
|
||||
#define XUSB_BLOB_02_OFFSET 0x06
|
||||
#define XUSB_BLOB_03_OFFSET 0x09
|
||||
#define XUSB_BLOB_04_OFFSET 0x0C
|
||||
#define XUSB_BLOB_05_OFFSET 0x20
|
||||
#define XUSB_BLOB_06_OFFSET 0x23
|
||||
|
||||
#define XUSB_IS_DATA_PIPE(_x_) ((BOOLEAN)(_x_->PipeHandle == (USBD_PIPE_HANDLE)0xFFFF0081))
|
||||
#define XUSB_IS_CONTROL_PIPE(_x_) ((BOOLEAN)(_x_->PipeHandle == (USBD_PIPE_HANDLE)0xFFFF0083))
|
||||
@@ -102,7 +110,7 @@ typedef struct _XUSB_DEVICE_DATA
|
||||
//
|
||||
// Storage of binary blobs (packets) for PDO initialization
|
||||
//
|
||||
PVOID InterruptInitStageBlobs[XUSB_INIT_BLOB_COUNT];
|
||||
WDFMEMORY InterruptBlobStorage;
|
||||
|
||||
} XUSB_DEVICE_DATA, *PXUSB_DEVICE_DATA;
|
||||
|
||||
@@ -122,7 +130,6 @@ Bus_XusbSubmitReport(
|
||||
//
|
||||
NTSTATUS Xusb_PreparePdo(PWDFDEVICE_INIT DeviceInit, USHORT VendorId, USHORT ProductId, PUNICODE_STRING DeviceId, PUNICODE_STRING DeviceDescription);
|
||||
NTSTATUS Xusb_PrepareHardware(WDFDEVICE Device);
|
||||
NTSTATUS Xusb_ReleaseHardware(WDFDEVICE Device);
|
||||
NTSTATUS Xusb_AssignPdoContext(WDFDEVICE Device);
|
||||
VOID Xusb_GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length);
|
||||
VOID Xusb_GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor, PPDO_DEVICE_DATA pCommon);
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#define HID_REPORT_TYPE_FEATURE 0x03
|
||||
|
||||
#define VIGEM_POOL_TAG 0x45476956 // "EGiV"
|
||||
#define XUSB_POOL_TAG 'BSUX'
|
||||
#define DRIVERNAME "ViGEm: "
|
||||
#define MAX_HARDWARE_ID_LENGTH 0xFF
|
||||
|
||||
@@ -94,7 +95,6 @@ EVT_WDF_CHILD_LIST_CREATE_DEVICE Bus_EvtDeviceListCreatePdo;
|
||||
EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE Bus_EvtChildListIdentificationDescriptionCompare;
|
||||
|
||||
EVT_WDF_DEVICE_PREPARE_HARDWARE Pdo_EvtDevicePrepareHardware;
|
||||
EVT_WDF_DEVICE_RELEASE_HARDWARE Pdo_EvtDeviceReleaseHardware;
|
||||
|
||||
EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL Pdo_EvtIoInternalDeviceControl;
|
||||
|
||||
|
||||
45
sys/buspdo.c
45
sys/buspdo.c
@@ -26,7 +26,6 @@
|
||||
#pragma alloc_text(PAGE, Bus_CreatePdo)
|
||||
#pragma alloc_text(PAGE, Bus_EvtDeviceListCreatePdo)
|
||||
#pragma alloc_text(PAGE, Pdo_EvtDevicePrepareHardware)
|
||||
#pragma alloc_text(PAGE, Pdo_EvtDeviceReleaseHardware)
|
||||
#endif
|
||||
|
||||
NTSTATUS Bus_EvtDeviceListCreatePdo(
|
||||
@@ -262,7 +261,6 @@ NTSTATUS Bus_CreatePdo(
|
||||
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
|
||||
|
||||
pnpPowerCallbacks.EvtDevicePrepareHardware = Pdo_EvtDevicePrepareHardware;
|
||||
pnpPowerCallbacks.EvtDeviceReleaseHardware = Pdo_EvtDeviceReleaseHardware;
|
||||
|
||||
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
|
||||
|
||||
@@ -431,7 +429,7 @@ NTSTATUS Bus_CreatePdo(
|
||||
// Create and assign queue for incoming interrupt transfer
|
||||
WDF_IO_QUEUE_CONFIG_INIT(&usbInQueueConfig, WdfIoQueueDispatchManual);
|
||||
|
||||
status = WdfIoQueueCreate(Device, &usbInQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pdoData->PendingUsbInRequests);
|
||||
status = WdfIoQueueCreate(hChild, &usbInQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pdoData->PendingUsbInRequests);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
@@ -444,7 +442,7 @@ NTSTATUS Bus_CreatePdo(
|
||||
// Create and assign queue for user-land notification requests
|
||||
WDF_IO_QUEUE_CONFIG_INIT(¬ificationsQueueConfig, WdfIoQueueDispatchManual);
|
||||
|
||||
status = WdfIoQueueCreate(Device, ¬ificationsQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pdoData->PendingNotificationRequests);
|
||||
status = WdfIoQueueCreate(hChild, ¬ificationsQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pdoData->PendingNotificationRequests);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
@@ -579,45 +577,6 @@ NTSTATUS Pdo_EvtDevicePrepareHardware(
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// PDO power-down.
|
||||
//
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS
|
||||
Pdo_EvtDeviceReleaseHardware(
|
||||
WDFDEVICE Device,
|
||||
WDFCMRESLIST ResourcesTranslated
|
||||
)
|
||||
{
|
||||
PPDO_DEVICE_DATA pdoData;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER(ResourcesTranslated);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSENUM, "%!FUNC! Entry");
|
||||
|
||||
pdoData = PdoGetData(Device);
|
||||
|
||||
switch (pdoData->TargetType)
|
||||
{
|
||||
// Free XUSB resources
|
||||
case Xbox360Wired:
|
||||
|
||||
status = Xusb_ReleaseHardware(Device);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Responds to IRP_MJ_INTERNAL_DEVICE_CONTROL requests sent to PDO.
|
||||
//
|
||||
|
||||
65
sys/usbpdo.c
65
sys/usbpdo.c
@@ -509,6 +509,7 @@ NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST R
|
||||
NTSTATUS status;
|
||||
PPDO_DEVICE_DATA pdoData;
|
||||
WDFREQUEST notifyRequest;
|
||||
PUCHAR blobBuffer;
|
||||
|
||||
pdoData = PdoGetData(Device);
|
||||
|
||||
@@ -544,6 +545,8 @@ NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST R
|
||||
TRACE_USBPDO,
|
||||
">> >> >> Incoming request, queuing...");
|
||||
|
||||
blobBuffer = WdfMemoryGetBuffer(xusb->InterruptBlobStorage, NULL);
|
||||
|
||||
if (XUSB_IS_DATA_PIPE(pTransfer))
|
||||
{
|
||||
//
|
||||
@@ -553,57 +556,57 @@ NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST R
|
||||
{
|
||||
case 0:
|
||||
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
|
||||
xusb->InterruptInitStage++;
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
|
||||
&blobBuffer[XUSB_BLOB_00_OFFSET],
|
||||
XUSB_INIT_STAGE_SIZE
|
||||
);
|
||||
xusb->InterruptInitStage++;
|
||||
);
|
||||
return STATUS_SUCCESS;
|
||||
case 1:
|
||||
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
|
||||
XUSB_INIT_STAGE_SIZE
|
||||
);
|
||||
xusb->InterruptInitStage++;
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
&blobBuffer[XUSB_BLOB_01_OFFSET],
|
||||
XUSB_INIT_STAGE_SIZE
|
||||
);
|
||||
return STATUS_SUCCESS;
|
||||
case 2:
|
||||
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
|
||||
XUSB_INIT_STAGE_SIZE
|
||||
);
|
||||
xusb->InterruptInitStage++;
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
&blobBuffer[XUSB_BLOB_02_OFFSET],
|
||||
XUSB_INIT_STAGE_SIZE
|
||||
);
|
||||
return STATUS_SUCCESS;
|
||||
case 3:
|
||||
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
|
||||
XUSB_INIT_STAGE_SIZE
|
||||
);
|
||||
xusb->InterruptInitStage++;
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
&blobBuffer[XUSB_BLOB_03_OFFSET],
|
||||
XUSB_INIT_STAGE_SIZE
|
||||
);
|
||||
return STATUS_SUCCESS;
|
||||
case 4:
|
||||
pTransfer->TransferBufferLength = sizeof(XUSB_INTERRUPT_IN_PACKET);
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
|
||||
sizeof(XUSB_INTERRUPT_IN_PACKET)
|
||||
);
|
||||
xusb->InterruptInitStage++;
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
&blobBuffer[XUSB_BLOB_04_OFFSET],
|
||||
sizeof(XUSB_INTERRUPT_IN_PACKET)
|
||||
);
|
||||
return STATUS_SUCCESS;
|
||||
case 5:
|
||||
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
|
||||
XUSB_INIT_STAGE_SIZE
|
||||
);
|
||||
xusb->InterruptInitStage++;
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
&blobBuffer[XUSB_BLOB_05_OFFSET],
|
||||
XUSB_INIT_STAGE_SIZE
|
||||
);
|
||||
return STATUS_SUCCESS;
|
||||
default:
|
||||
/* This request is sent periodically and relies on data the "feeder"
|
||||
@@ -620,10 +623,10 @@ NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST R
|
||||
if (!xusb->ReportedCapabilities && pTransfer->TransferBufferLength >= XUSB_INIT_STAGE_SIZE)
|
||||
{
|
||||
RtlCopyMemory(
|
||||
pTransfer->TransferBuffer,
|
||||
xusb->InterruptInitStageBlobs[0x06],
|
||||
pTransfer->TransferBuffer,
|
||||
&blobBuffer[XUSB_BLOB_06_OFFSET],
|
||||
XUSB_INIT_STAGE_SIZE
|
||||
);
|
||||
);
|
||||
|
||||
xusb->ReportedCapabilities = TRUE;
|
||||
|
||||
|
||||
99
sys/xusb.c
99
sys/xusb.c
@@ -240,26 +240,11 @@ NTSTATUS Xusb_PrepareHardware(WDFDEVICE Device)
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS Xusb_ReleaseHardware(WDFDEVICE Device)
|
||||
{
|
||||
ULONG index;
|
||||
|
||||
PXUSB_DEVICE_DATA xusb = XusbGetData(Device);
|
||||
|
||||
for (index = 0; index < XUSB_INIT_BLOB_COUNT; index++)
|
||||
{
|
||||
if (xusb->InterruptInitStageBlobs[index])
|
||||
ExFreePoolWithTag(xusb->InterruptInitStageBlobs[index], VIGEM_POOL_TAG);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS Xusb_AssignPdoContext(WDFDEVICE Device)
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDF_OBJECT_ATTRIBUTES attributes;
|
||||
ULONG index;
|
||||
WDF_OBJECT_ATTRIBUTES attributes;
|
||||
PUCHAR blobBuffer;
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
|
||||
attributes.ParentObject = Device;
|
||||
@@ -275,61 +260,41 @@ NTSTATUS Xusb_AssignPdoContext(WDFDEVICE Device)
|
||||
// Packet size (20 bytes = 0x14)
|
||||
xusb->Packet.Size = 0x14;
|
||||
|
||||
// Prepare blob storage
|
||||
xusb->InterruptInitStageBlobs[0] = ExAllocatePoolWithTag(NonPagedPool, XUSB_INIT_STAGE_SIZE, VIGEM_POOL_TAG);
|
||||
xusb->InterruptInitStageBlobs[1] = ExAllocatePoolWithTag(NonPagedPool, XUSB_INIT_STAGE_SIZE, VIGEM_POOL_TAG);
|
||||
xusb->InterruptInitStageBlobs[2] = ExAllocatePoolWithTag(NonPagedPool, XUSB_INIT_STAGE_SIZE, VIGEM_POOL_TAG);
|
||||
xusb->InterruptInitStageBlobs[3] = ExAllocatePoolWithTag(NonPagedPool, XUSB_INIT_STAGE_SIZE, VIGEM_POOL_TAG);
|
||||
xusb->InterruptInitStageBlobs[4] = ExAllocatePoolWithTag(NonPagedPool, sizeof(XUSB_INTERRUPT_IN_PACKET), VIGEM_POOL_TAG);
|
||||
xusb->InterruptInitStageBlobs[5] = ExAllocatePoolWithTag(NonPagedPool, XUSB_INIT_STAGE_SIZE, VIGEM_POOL_TAG);
|
||||
xusb->InterruptInitStageBlobs[6] = ExAllocatePoolWithTag(NonPagedPool, XUSB_INIT_STAGE_SIZE, VIGEM_POOL_TAG);
|
||||
|
||||
// Validate allocations
|
||||
for (index = 0; index < XUSB_INIT_BLOB_COUNT; index++)
|
||||
// Allocate blob storage
|
||||
status = WdfMemoryCreate(
|
||||
&attributes,
|
||||
NonPagedPoolNx,
|
||||
XUSB_POOL_TAG,
|
||||
XUSB_BLOB_STORAGE_SIZE,
|
||||
&xusb->InterruptBlobStorage,
|
||||
&blobBuffer
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
// If even one allocation failed...
|
||||
if (!xusb->InterruptInitStageBlobs[index])
|
||||
{
|
||||
// ...re-enumerate...
|
||||
for (index = 0; index < XUSB_INIT_BLOB_COUNT; index++)
|
||||
{
|
||||
// ...and free the ones who succeeded...
|
||||
if (xusb->InterruptInitStageBlobs[index])
|
||||
// ...to not leak memory...
|
||||
ExFreePoolWithTag(xusb->InterruptInitStageBlobs[index], VIGEM_POOL_TAG);
|
||||
}
|
||||
|
||||
// ...and abort with error
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_XUSB,
|
||||
"WdfMemoryCreate failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill blobs
|
||||
*
|
||||
* Values obtained by reversing the communication of a physical pad.
|
||||
*/
|
||||
COPY_BYTE_ARRAY(xusb->InterruptInitStageBlobs[0], P99_PROTECT({
|
||||
0x01, 0x03, 0x0E
|
||||
}));
|
||||
COPY_BYTE_ARRAY(xusb->InterruptInitStageBlobs[1], P99_PROTECT({
|
||||
0x02, 0x03, 0x00
|
||||
}));
|
||||
COPY_BYTE_ARRAY(xusb->InterruptInitStageBlobs[2], P99_PROTECT({
|
||||
0x03, 0x03, 0x03
|
||||
}));
|
||||
COPY_BYTE_ARRAY(xusb->InterruptInitStageBlobs[3], P99_PROTECT({
|
||||
0x08, 0x03, 0x00
|
||||
}));
|
||||
COPY_BYTE_ARRAY(xusb->InterruptInitStageBlobs[4], P99_PROTECT({
|
||||
// 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
|
||||
}));
|
||||
COPY_BYTE_ARRAY(xusb->InterruptInitStageBlobs[5], P99_PROTECT({
|
||||
0x01, 0x03, 0x03
|
||||
}));
|
||||
COPY_BYTE_ARRAY(xusb->InterruptInitStageBlobs[6], P99_PROTECT({
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 5
|
||||
0x01, 0x03, 0x03,
|
||||
// 6
|
||||
0x05, 0x03, 0x00
|
||||
}));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user