4 Commits

Author SHA1 Message Date
Benjamin Höglinger-Stelzer
d64b303323 Merge branch 'master' into feature/core/stack-memory-usage 2018-09-30 20:29:36 +02:00
Benjamin Höglinger-Stelzer
5ef68cac46 Tab/space fix 2018-09-30 20:13:59 +02:00
Benjamin Höglinger-Stelzer
f537206c2d Replaced tabs with spaces 2018-09-30 17:22:14 +02:00
Benjamin Höglinger-Stelzer
d07521b0e1 Introduced context space for XUSB binary blobs to use heap memory instead of stack space 2018-09-30 17:19:03 +02:00
8 changed files with 178 additions and 44 deletions

View File

@@ -22,13 +22,13 @@
#include <ntifs.h>
#define INITIAL_ARRAY_CAPACITY PAGE_SIZE
#define ARRAY_POOL_TAG 'arrA'
#define ARRAY_POOL_TAG 'arrA'
typedef struct _BYTE_ARRAY
{
UCHAR* Data; //> array of data we're storing
ULONG_PTR Size; //> slots used so far
ULONG_PTR Capacity; //> total available memory
UCHAR* Data; //> array of data we're storing
ULONG_PTR Size; //> slots used so far
ULONG_PTR Capacity; //> total available memory
} BYTE_ARRAY, *PBYTE_ARRAY;
NTSTATUS InitByteArray(IN OUT PBYTE_ARRAY Array);

View File

@@ -32,7 +32,7 @@
#define HID_REPORT_ID_3 0x13
#define HID_REPORT_ID_4 0x14
#define DS4_DESCRIPTOR_SIZE 0x0029
#define DS4_DESCRIPTOR_SIZE 0x0029
#if defined(_X86_)
#define DS4_CONFIGURATION_SIZE 0x0050
#else

View File

@@ -46,7 +46,7 @@ DEFINE_GUID(GUID_DEVINTERFACE_XGIP_UNKNOWN_4,
#pragma once
#define XGIP_DESCRIPTOR_SIZE 0x0040
#define XGIP_DESCRIPTOR_SIZE 0x0040
#define XGIP_CONFIGURATION_SIZE 0x88
#define XGIP_REPORT_SIZE 0x12
#define XGIP_SYS_INIT_PACKETS 0x0F

View File

@@ -44,11 +44,12 @@ DEFINE_GUID(GUID_DEVINTERFACE_XUSB_UNKNOWN_2,
#else
#define XUSB_CONFIGURATION_SIZE 0x0130
#endif
#define XUSB_DESCRIPTOR_SIZE 0x0099
#define XUSB_DESCRIPTOR_SIZE 0x0099
#define XUSB_RUMBLE_SIZE 0x08
#define XUSB_LEDSET_SIZE 0x03
#define XUSB_LEDNUM_SIZE 0x01
#define XUSB_INIT_STAGE_SIZE 0x03
#define XUSB_INIT_BLOB_COUNT 0x07
#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))
@@ -98,6 +99,11 @@ typedef struct _XUSB_DEVICE_DATA
//
ULONG InterruptInitStage;
//
// Storage of binary blobs (packets) for PDO initialization
//
PVOID InterruptInitStageBlobs[XUSB_INIT_BLOB_COUNT];
} XUSB_DEVICE_DATA, *PXUSB_DEVICE_DATA;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XUSB_DEVICE_DATA, XusbGetData)
@@ -116,6 +122,7 @@ 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);

View File

@@ -93,7 +93,8 @@ EVT_WDF_CHILD_LIST_CREATE_DEVICE Bus_EvtDeviceListCreatePdo;
EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE Bus_EvtChildListIdentificationDescriptionCompare;
EVT_WDF_DEVICE_PREPARE_HARDWARE Bus_EvtDevicePrepareHardware;
EVT_WDF_DEVICE_PREPARE_HARDWARE Pdo_EvtDevicePrepareHardware;
EVT_WDF_DEVICE_RELEASE_HARDWARE Pdo_EvtDeviceReleaseHardware;
EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL Pdo_EvtIoInternalDeviceControl;

View File

@@ -25,7 +25,8 @@
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Bus_CreatePdo)
#pragma alloc_text(PAGE, Bus_EvtDeviceListCreatePdo)
#pragma alloc_text(PAGE, Bus_EvtDevicePrepareHardware)
#pragma alloc_text(PAGE, Pdo_EvtDevicePrepareHardware)
#pragma alloc_text(PAGE, Pdo_EvtDeviceReleaseHardware)
#endif
NTSTATUS Bus_EvtDeviceListCreatePdo(
@@ -260,7 +261,8 @@ NTSTATUS Bus_CreatePdo(
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
pnpPowerCallbacks.EvtDevicePrepareHardware = Bus_EvtDevicePrepareHardware;
pnpPowerCallbacks.EvtDevicePrepareHardware = Pdo_EvtDevicePrepareHardware;
pnpPowerCallbacks.EvtDeviceReleaseHardware = Pdo_EvtDeviceReleaseHardware;
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
@@ -520,9 +522,9 @@ NTSTATUS Bus_CreatePdo(
}
//
// Exposes necessary interfaces on PDO power-up.
// PDO power-up.
//
NTSTATUS Bus_EvtDevicePrepareHardware(
NTSTATUS Pdo_EvtDevicePrepareHardware(
_In_ WDFDEVICE Device,
_In_ WDFCMRESLIST ResourcesRaw,
_In_ WDFCMRESLIST ResourcesTranslated
@@ -577,6 +579,45 @@ NTSTATUS Bus_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.
//

View File

@@ -552,48 +552,58 @@ NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST R
switch (xusb->InterruptInitStage)
{
case 0:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x01, 0x03, 0x0E
}));
RtlCopyMemory(
pTransfer->TransferBuffer,
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
XUSB_INIT_STAGE_SIZE
);
xusb->InterruptInitStage++;
return STATUS_SUCCESS;
case 1:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x02, 0x03, 0x00
}));
RtlCopyMemory(
pTransfer->TransferBuffer,
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
XUSB_INIT_STAGE_SIZE
);
xusb->InterruptInitStage++;
return STATUS_SUCCESS;
case 2:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x03, 0x03, 0x03
}));
RtlCopyMemory(
pTransfer->TransferBuffer,
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
XUSB_INIT_STAGE_SIZE
);
xusb->InterruptInitStage++;
return STATUS_SUCCESS;
case 3:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x08, 0x03, 0x00
}));
RtlCopyMemory(
pTransfer->TransferBuffer,
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
XUSB_INIT_STAGE_SIZE
);
xusb->InterruptInitStage++;
return STATUS_SUCCESS;
case 4:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = sizeof(XUSB_INTERRUPT_IN_PACKET);
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xf2,
0xb3, 0xf8, 0x49, 0xf3, 0xb0, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
}));
RtlCopyMemory(
pTransfer->TransferBuffer,
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
sizeof(XUSB_INTERRUPT_IN_PACKET)
);
xusb->InterruptInitStage++;
return STATUS_SUCCESS;
case 5:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x01, 0x03, 0x03
}));
RtlCopyMemory(
pTransfer->TransferBuffer,
xusb->InterruptInitStageBlobs[xusb->InterruptInitStage],
XUSB_INIT_STAGE_SIZE
);
xusb->InterruptInitStage++;
return STATUS_SUCCESS;
default:
/* This request is sent periodically and relies on data the "feeder"
@@ -609,10 +619,11 @@ NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST R
{
if (!xusb->ReportedCapabilities && pTransfer->TransferBufferLength >= XUSB_INIT_STAGE_SIZE)
{
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x05, 0x03, 0x00
}));
RtlCopyMemory(
pTransfer->TransferBuffer,
xusb->InterruptInitStageBlobs[0x06],
XUSB_INIT_STAGE_SIZE
);
xusb->ReportedCapabilities = TRUE;

View File

@@ -240,10 +240,26 @@ 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;
NTSTATUS status;
WDF_OBJECT_ATTRIBUTES attributes;
ULONG index;
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = Device;
@@ -259,6 +275,64 @@ 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++)
{
// 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;
}
}
/*
* 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({
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({
0x05, 0x03, 0x00
}));
// I/O Queue for pending IRPs
WDF_IO_QUEUE_CONFIG holdingInQueueConfig;