mirror of
https://github.com/nefarius/ViGEmBus.git
synced 2025-08-10 00:52:17 +00:00
Implemented vigem_target_x360_get_user_index in library and driver
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,3 +22,4 @@
|
||||
/sys/RCb21300
|
||||
/sys/RCa21300
|
||||
*.user
|
||||
/.vs/config
|
||||
|
||||
@@ -42,7 +42,8 @@ typedef enum _VIGEM_PDO_STAGE
|
||||
{
|
||||
ViGEmPdoCreate,
|
||||
ViGEmPdoPrepareHardware,
|
||||
ViGEmPdoInternalIoControl
|
||||
ViGEmPdoInternalIoControl,
|
||||
ViGEmPdoInitFinished
|
||||
|
||||
} VIGEM_PDO_STAGE, *PVIGEM_PDO_STAGE;
|
||||
|
||||
|
||||
@@ -265,6 +265,39 @@ VOID FORCEINLINE XUSB_SUBMIT_REPORT_INIT(
|
||||
Report->SerialNo = SerialNo;
|
||||
}
|
||||
|
||||
typedef struct _XUSB_GET_USER_INDEX
|
||||
{
|
||||
//
|
||||
// sizeof(struct _XUSB_GET_USER_INDEX)
|
||||
//
|
||||
ULONG Size;
|
||||
|
||||
//
|
||||
// Serial number of target device.
|
||||
//
|
||||
ULONG SerialNo;
|
||||
|
||||
//
|
||||
// User index of target device.
|
||||
//
|
||||
OUT ULONG UserIndex;
|
||||
|
||||
} XUSB_GET_USER_INDEX, *PXUSB_GET_USER_INDEX;
|
||||
|
||||
//
|
||||
// Initializes XUSB_GET_USER_INDEX structure.
|
||||
//
|
||||
VOID FORCEINLINE XUSB_GET_USER_INDEX_INIT(
|
||||
_Out_ PXUSB_GET_USER_INDEX GetRequest,
|
||||
_In_ ULONG SerialNo
|
||||
)
|
||||
{
|
||||
RtlZeroMemory(GetRequest, sizeof(XUSB_GET_USER_INDEX));
|
||||
|
||||
GetRequest->Size = sizeof(XUSB_GET_USER_INDEX);
|
||||
GetRequest->SerialNo = SerialNo;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region DualShock 4 section
|
||||
|
||||
@@ -451,7 +451,7 @@ VIGEM_API VIGEM_TARGET_TYPE vigem_target_get_type(PVIGEM_TARGET target);
|
||||
VIGEM_API BOOL vigem_target_is_attached(PVIGEM_TARGET target);
|
||||
|
||||
/**
|
||||
* \fn VIGEM_API ULONG vigem_target_x360_get_user_index(PVIGEM_CLIENT vigem, PVIGEM_TARGET target);
|
||||
* \fn VIGEM_API VIGEM_ERROR vigem_target_x360_get_user_index(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PULONG index);
|
||||
*
|
||||
* \brief Returns the user index of the emulated Xenon device. This value correspondents to the
|
||||
* (zero-based) index number representing the player number via LED present on a
|
||||
@@ -462,10 +462,11 @@ VIGEM_API BOOL vigem_target_is_attached(PVIGEM_TARGET target);
|
||||
*
|
||||
* \param vigem The driver connection object.
|
||||
* \param target The target device object.
|
||||
* \param index The (zero-based) user index of the Xenon device.
|
||||
*
|
||||
* \return The user index of the Xenon device.
|
||||
* \return A VIGEM_ERROR.
|
||||
*/
|
||||
VIGEM_API ULONG vigem_target_x360_get_user_index(PVIGEM_CLIENT vigem, PVIGEM_TARGET target);
|
||||
VIGEM_API VIGEM_ERROR vigem_target_x360_get_user_index(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PULONG index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -635,7 +635,48 @@ BOOL vigem_target_is_attached(PVIGEM_TARGET target)
|
||||
return (target->State == VIGEM_TARGET_CONNECTED);
|
||||
}
|
||||
|
||||
ULONG vigem_target_x360_get_user_index(PVIGEM_CLIENT vigem, PVIGEM_TARGET target)
|
||||
VIGEM_ERROR vigem_target_x360_get_user_index(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PULONG index)
|
||||
{
|
||||
return VIGEM_API ULONG();
|
||||
if (vigem->hBusDevice == nullptr)
|
||||
{
|
||||
return VIGEM_ERROR_BUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (target->SerialNo == 0 || target->Type != Xbox360Wired)
|
||||
{
|
||||
return VIGEM_ERROR_INVALID_TARGET;
|
||||
}
|
||||
|
||||
DWORD transfered = 0;
|
||||
OVERLAPPED lOverlapped = { 0 };
|
||||
lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
|
||||
XUSB_GET_USER_INDEX gui;
|
||||
XUSB_GET_USER_INDEX_INIT(&gui, target->SerialNo);
|
||||
|
||||
DeviceIoControl(
|
||||
vigem->hBusDevice,
|
||||
IOCTL_XUSB_GET_USER_INDEX,
|
||||
&gui,
|
||||
gui.Size,
|
||||
&gui,
|
||||
gui.Size,
|
||||
&transfered,
|
||||
&lOverlapped
|
||||
);
|
||||
|
||||
if (GetOverlappedResult(vigem->hBusDevice, &lOverlapped, &transfered, TRUE) == 0)
|
||||
{
|
||||
if (GetLastError() == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
CloseHandle(lOverlapped.hEvent);
|
||||
return VIGEM_ERROR_INVALID_TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(lOverlapped.hEvent);
|
||||
|
||||
*index = gui.UserIndex;
|
||||
|
||||
return VIGEM_ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -411,7 +411,7 @@ Bus_PdoStageResult(
|
||||
//
|
||||
// If any stage fails or is last stage, get associated request and complete it
|
||||
//
|
||||
if (!NT_SUCCESS(Status) || Stage == ViGEmPdoInternalIoControl)
|
||||
if (!NT_SUCCESS(Status) || Stage == ViGEmPdoInitFinished)
|
||||
{
|
||||
WdfSpinLockAcquire(pFdoData->PendingPluginRequestsLock);
|
||||
|
||||
|
||||
40
sys/Queue.c
40
sys/Queue.c
@@ -50,6 +50,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
PXGIP_SUBMIT_REPORT xgipSubmit = NULL;
|
||||
PXGIP_SUBMIT_INTERRUPT xgipInterrupt = NULL;
|
||||
PVIGEM_CHECK_VERSION pCheckVersion = NULL;
|
||||
PXUSB_GET_USER_INDEX pXusbGetUserIndex = NULL;
|
||||
|
||||
Device = WdfIoQueueGetDevice(Queue);
|
||||
|
||||
@@ -277,6 +278,45 @@ VOID Bus_EvtIoDeviceControl(
|
||||
break;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IOCTL_XUSB_GET_USER_INDEX
|
||||
case IOCTL_XUSB_GET_USER_INDEX:
|
||||
|
||||
KdPrint((DRIVERNAME "IOCTL_XUSB_GET_USER_INDEX"));
|
||||
|
||||
// Don't accept the request if the output buffer can't hold the results
|
||||
if (OutputBufferLength < sizeof(XUSB_GET_USER_INDEX))
|
||||
{
|
||||
KdPrint((DRIVERNAME "IOCTL_XUSB_GET_USER_INDEX: output buffer too small: %ul\n", OutputBufferLength));
|
||||
break;
|
||||
}
|
||||
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
sizeof(XUSB_GET_USER_INDEX),
|
||||
(PVOID)&pXusbGetUserIndex,
|
||||
&length);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
KdPrint((DRIVERNAME "WdfRequestRetrieveInputBuffer failed 0x%x\n", status));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((sizeof(XUSB_GET_USER_INDEX) == pXusbGetUserIndex->Size) && (length == InputBufferLength))
|
||||
{
|
||||
// This request only supports a single PDO at a time
|
||||
if (pXusbGetUserIndex->SerialNo == 0)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
status = Xusb_GetUserIndex(Device, pXusbGetUserIndex);
|
||||
}
|
||||
|
||||
break;
|
||||
#pragma endregion
|
||||
|
||||
default:
|
||||
KdPrint((DRIVERNAME "UNKNOWN IOCTL CODE 0x%x\n", IoControlCode));
|
||||
break; // default status is STATUS_INVALID_PARAMETER
|
||||
|
||||
@@ -124,3 +124,4 @@ NTSTATUS Xusb_AssignPdoContext(WDFDEVICE Device, PPDO_IDENTIFICATION_DESCRIPTION
|
||||
VOID Xusb_GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length);
|
||||
VOID Xusb_GetDeviceDescriptorType(PUSB_DEVICE_DESCRIPTOR pDescriptor, PPDO_DEVICE_DATA pCommon);
|
||||
VOID Xusb_SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo);
|
||||
NTSTATUS Xusb_GetUserIndex(WDFDEVICE Device, PXUSB_GET_USER_INDEX Request);
|
||||
|
||||
16
sys/buspdo.c
16
sys/buspdo.c
@@ -700,6 +700,22 @@ VOID Pdo_EvtIoInternalDeviceControl(
|
||||
// success to the parent bus.
|
||||
//
|
||||
BUS_PDO_REPORT_STAGE_RESULT(pdoData->BusInterface, ViGEmPdoInternalIoControl, pdoData->SerialNo, status);
|
||||
|
||||
//
|
||||
// The DS4 is basically ready to operate at this stage
|
||||
//
|
||||
if (pdoData->TargetType == DualShock4Wired)
|
||||
{
|
||||
//
|
||||
// Report back to FDO that we are ready to operate
|
||||
//
|
||||
BUS_PDO_REPORT_STAGE_RESULT(
|
||||
pdoData->BusInterface,
|
||||
ViGEmPdoInitFinished,
|
||||
pdoData->SerialNo,
|
||||
STATUS_SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
10
sys/usbpdo.c
10
sys/usbpdo.c
@@ -604,6 +604,16 @@ NTSTATUS UsbPdo_BulkOrInterruptTransfer(PURB urb, WDFDEVICE Device, WDFREQUEST R
|
||||
if (Buffer[2] == 0x05) xusb->LedNumber = 3;
|
||||
|
||||
KdPrint((DRIVERNAME "-- LED Number: %d\n", xusb->LedNumber));
|
||||
|
||||
//
|
||||
// Report back to FDO that we are ready to operate
|
||||
//
|
||||
BUS_PDO_REPORT_STAGE_RESULT(
|
||||
pdoData->BusInterface,
|
||||
ViGEmPdoInitFinished,
|
||||
pdoData->SerialNo,
|
||||
STATUS_SUCCESS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
38
sys/xusb.c
38
sys/xusb.c
@@ -504,3 +504,41 @@ VOID Xusb_SelectConfiguration(PUSBD_INTERFACE_INFORMATION pInfo)
|
||||
pInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)0xFFFF0000;
|
||||
}
|
||||
|
||||
NTSTATUS Xusb_GetUserIndex(WDFDEVICE Device, PXUSB_GET_USER_INDEX Request)
|
||||
{
|
||||
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
||||
WDFDEVICE hChild;
|
||||
PPDO_DEVICE_DATA pdoData;
|
||||
PXUSB_DEVICE_DATA xusbData;
|
||||
|
||||
|
||||
KdPrint((DRIVERNAME "Entered Bus_QueueNotification\n"));
|
||||
|
||||
hChild = Bus_GetPdo(Device, Request->SerialNo);
|
||||
|
||||
// Validate child
|
||||
if (hChild == NULL)
|
||||
{
|
||||
KdPrint((DRIVERNAME "Bus_QueueNotification: PDO with serial %d not found\n", Request->SerialNo));
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
|
||||
// Check common context
|
||||
pdoData = PdoGetData(hChild);
|
||||
if (pdoData == NULL)
|
||||
{
|
||||
KdPrint((DRIVERNAME "Bus_QueueNotification: PDO context not found\n"));
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Check if caller owns this PDO
|
||||
if (!IS_OWNER(pdoData))
|
||||
{
|
||||
KdPrint((DRIVERNAME "Bus_QueueNotification: PID mismatch: %d != %d\n", pdoData->OwnerProcessId, CURRENT_PROCESS_ID()));
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
Request->UserIndex = (ULONG)XusbGetData(hChild)->LedNumber;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user