mirror of
https://github.com/nefarius/ViGEmBus.git
synced 2025-08-10 00:52:17 +00:00
Fixed issue #44
This commit is contained in:
11
Xusb.h
11
Xusb.h
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
31
buspdo.c
31
buspdo.c
@@ -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;
|
||||
|
||||
|
||||
73
usbpdo.c
73
usbpdo.c
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user