Fixed issue #44

This commit is contained in:
Benjamin Höglinger
2018-01-14 20:50:52 +01:00
parent 48505b0617
commit 348cb8ed01
4 changed files with 115 additions and 7 deletions

11
Xusb.h
View File

@@ -52,6 +52,7 @@ DEFINE_GUID(GUID_DEVINTERFACE_XUSB_UNKNOWN_2,
#define XUSB_RUMBLE_SIZE 0x08
#define XUSB_LEDSET_SIZE 0x03
#define XUSB_LEDNUM_SIZE 0x01
#define XUSB_INIT_STAGE_SIZE 0x03
#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))
@@ -91,6 +92,16 @@ typedef struct _XUSB_DEVICE_DATA
//
WDFQUEUE HoldingUsbInRequests;
//
// Required for XInputGetCapabilities to work
//
BOOLEAN ReportedCapabilities;
//
// Required for XInputGetCapabilities to work
//
ULONG InterruptInitStage;
} XUSB_DEVICE_DATA, *PXUSB_DEVICE_DATA;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XUSB_DEVICE_DATA, XusbGetData)

View File

@@ -71,6 +71,13 @@ SOFTWARE.
//
#define HID_GET_REPORT_TYPE(_req_) ((_req_->Value >> 8) & 0xFF)
//
// Some insane macro-magic =3
//
#define P99_PROTECT(...) __VA_ARGS__
#define COPY_BYTE_ARRAY(_dst_, _bytes_) do {BYTE b[] = _bytes_; \
RtlCopyMemory(_dst_, b, RTL_NUMBER_OF_V1(b)); } while (0)
#pragma endregion

View File

@@ -530,8 +530,35 @@ VOID Pdo_EvtIoInternalDeviceControl(
KdPrint((DRIVERNAME ">> >> URB_FUNCTION_CONTROL_TRANSFER\n"));
// Control transfer can safely be ignored
status = STATUS_SUCCESS;
switch (urb->UrbControlTransfer.SetupPacket[6])
{
case 0x04:
//
// Xenon magic
//
COPY_BYTE_ARRAY(urb->UrbControlTransfer.TransferBuffer, P99_PROTECT({
0x31, 0x3F, 0xCF, 0xDC
}));
status = STATUS_SUCCESS;
break;
case 0x14:
//
// This is some weird USB 1.0 condition and _must fail_
//
urb->UrbControlTransfer.Hdr.Status = USBD_STATUS_STALL_PID;
status = STATUS_UNSUCCESSFUL;
break;
case 0x08:
//
// This is some weird USB 1.0 condition and _must fail_
//
urb->UrbControlTransfer.Hdr.Status = USBD_STATUS_STALL_PID;
status = STATUS_UNSUCCESSFUL;
break;
default:
status = STATUS_SUCCESS;
break;
}
break;

View File

@@ -504,16 +504,79 @@ NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST R
if (XUSB_IS_DATA_PIPE(pTransfer))
{
/* 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, pdoData->PendingUsbInRequests);
//
// Send "boot sequence" first, then the actual inputs
//
switch (xusb->InterruptInitStage)
{
case 0:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x01, 0x03, 0x0E
}));
return STATUS_SUCCESS;
case 1:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x02, 0x03, 0x00
}));
return STATUS_SUCCESS;
case 2:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x03, 0x03, 0x03
}));
return STATUS_SUCCESS;
case 3:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x08, 0x03, 0x00
}));
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
}));
return STATUS_SUCCESS;
case 5:
xusb->InterruptInitStage++;
pTransfer->TransferBufferLength = XUSB_INIT_STAGE_SIZE;
COPY_BYTE_ARRAY(pTransfer->TransferBuffer, P99_PROTECT({
0x01, 0x03, 0x03
}));
return STATUS_SUCCESS;
default:
/* 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, pdoData->PendingUsbInRequests);
return (NT_SUCCESS(status)) ? STATUS_PENDING : status;
return (NT_SUCCESS(status)) ? STATUS_PENDING : status;
}
}
if (XUSB_IS_CONTROL_PIPE(pTransfer))
{
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
}));
xusb->ReportedCapabilities = TRUE;
return STATUS_SUCCESS;
}
status = WdfRequestForwardToIoQueue(Request, xusb->HoldingUsbInRequests);
return (NT_SUCCESS(status)) ? STATUS_PENDING : status;