#include "drv_common.h"
#if (defined(ALLOC_PRAGMA) && defined(PAGING_ENABLED))
#pragma alloc_text(PAGE, Request_Feature)
#pragma alloc_text(PAGE, Request_Vendor)
#pragma alloc_text(PAGE, Request_Status)
#pragma alloc_text(PAGE, Request_Descriptor)
#endif
NTSTATUS Request_Feature(__in PDEVICE_CONTEXT deviceContext,
__in WDF_USB_BMREQUEST_RECIPIENT recipient,
__in USHORT featureIndex,
__in USHORT feature,
__in BOOLEAN setFeature,
__in INT timeout)
{
NTSTATUS status = STATUS_SUCCESS;
WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
WDF_REQUEST_SEND_OPTIONS syncReqOptions;
PAGED_CODE();
if (timeout > LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT || !timeout)
{
timeout = LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT;
}
USBMSG("[%s] recipient=%04d featureIndex=%04d feature=%04d timeout=%d\n",
setFeature ? "Set" : "Clear", recipient, featureIndex, feature, timeout);
WDF_USB_CONTROL_SETUP_PACKET_INIT_FEATURE(&controlSetupPacket, recipient, feature, featureIndex, setFeature);
WDF_REQUEST_SEND_OPTIONS_INIT(&syncReqOptions, 0);
WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&syncReqOptions, WDF_REL_TIMEOUT_IN_MS(timeout));
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
deviceContext->WdfUsbTargetDevice,
WDF_NO_HANDLE,
&syncReqOptions,
&controlSetupPacket,
NULL,
NULL);
if (!NT_SUCCESS(status))
{
USBERR("failed status=%Xh\n", status);
}
return status;
}
NTSTATUS Request_Vendor(__in PDEVICE_CONTEXT deviceContext,
__in PWDF_MEMORY_DESCRIPTOR memoryDescriptor,
__in WDF_USB_BMREQUEST_DIRECTION direction,
__in WDF_USB_BMREQUEST_RECIPIENT recipient,
__in BYTE request,
__in USHORT value,
__in USHORT index,
__in INT timeout,
__out PULONG transferred)
{
NTSTATUS status = STATUS_SUCCESS;
WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
WDF_REQUEST_SEND_OPTIONS syncReqOptions;
PAGED_CODE();
if (timeout > LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT || !timeout)
{
timeout = LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT;
}
USBMSG("direction=%u recipient=%04d request=%04d value=%04d index=%04d timeout=%d\n",
direction, recipient, request, value, index, timeout);
WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(
&controlSetupPacket,
direction,
recipient,
request,
value,
index);
WDF_REQUEST_SEND_OPTIONS_INIT(&syncReqOptions, 0);
WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&syncReqOptions, WDF_REL_TIMEOUT_IN_MS(timeout));
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
deviceContext->WdfUsbTargetDevice,
WDF_NO_HANDLE,
&syncReqOptions,
&controlSetupPacket,
memoryDescriptor,
transferred);
if (!NT_SUCCESS(status))
{
USBERR("failed status=%Xh\n", status);
}
return status;
}
NTSTATUS Request_Status(__in PDEVICE_CONTEXT deviceContext,
__in PWDF_MEMORY_DESCRIPTOR memoryDescriptor,
__in WDF_USB_BMREQUEST_RECIPIENT recipient,
__in USHORT index,
__in INT timeout,
__out PULONG transferred)
{
NTSTATUS status = STATUS_SUCCESS;
WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
WDF_REQUEST_SEND_OPTIONS syncReqOptions;
PAGED_CODE();
if (timeout > LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT || !timeout)
{
timeout = LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT;
}
USBMSG("recipient=%04d index=%04d timeout=%d\n", recipient, index, timeout);
WDF_USB_CONTROL_SETUP_PACKET_INIT_GET_STATUS(&controlSetupPacket, recipient, index);
WDF_REQUEST_SEND_OPTIONS_INIT(&syncReqOptions, 0);
WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&syncReqOptions, WDF_REL_TIMEOUT_IN_MS(timeout));
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
deviceContext->WdfUsbTargetDevice,
WDF_NO_HANDLE,
&syncReqOptions,
&controlSetupPacket,
memoryDescriptor,
transferred);
if (!NT_SUCCESS(status))
{
USBERR("failed status=%Xh\n", status);
}
return status;
}
NTSTATUS Request_Descriptor(__in PDEVICE_CONTEXT deviceContext,
__in PWDF_MEMORY_DESCRIPTOR memoryDescriptor,
__in BOOLEAN setDescriptor,
__in WDF_USB_BMREQUEST_RECIPIENT recipient,
__in UCHAR descriptorType,
__in UCHAR descriptorIndex,
__in USHORT langID,
__out PULONG descriptorLength,
__in INT timeout)
{
NTSTATUS status = STATUS_SUCCESS;
WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
WDF_REQUEST_SEND_OPTIONS syncReqOptions;
PAGED_CODE();
if (timeout > LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT || !timeout)
{
timeout = LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT;
}
USBMSG("[%s] recipient=%04d type=%04d index=%04d langID=%04d timeout=%d\n",
setDescriptor ? "Set" : "Get", recipient, descriptorType, descriptorIndex, langID, timeout);
WDF_USB_CONTROL_SETUP_PACKET_INIT(
&controlSetupPacket,
BmRequestDeviceToHost,
recipient,
setDescriptor ? USB_REQUEST_SET_DESCRIPTOR : USB_REQUEST_GET_DESCRIPTOR,
(USHORT)((descriptorType << 8) | descriptorIndex),
(USHORT)langID);
WDF_REQUEST_SEND_OPTIONS_INIT(&syncReqOptions, 0);
WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&syncReqOptions, WDF_REL_TIMEOUT_IN_MS(timeout));
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
deviceContext->WdfUsbTargetDevice,
WDF_NO_HANDLE,
&syncReqOptions,
&controlSetupPacket,
memoryDescriptor,
descriptorLength);
if (!NT_SUCCESS(status))
{
USBERR("failed status=%Xh\n", status);
}
return status;
}
VOID Request_PreIoInitialize(__in WDFDEVICE Device,
__in WDFREQUEST Request)
{
NTSTATUS status = STATUS_SUCCESS;
WDF_REQUEST_PARAMETERS params;
PREQUEST_CONTEXT requestContext = NULL;
libusb_request* libusbRequest;
size_t libusbRequestSize;
WDF_REQUEST_PARAMETERS_INIT(¶ms);
WdfRequestGetParameters(Request, ¶ms);
if (params.Type != WdfRequestTypeDeviceControl) goto Done;
requestContext = GetRequestContext(Request);
if (!requestContext)
{
status = STATUS_INVALID_DEVICE_REQUEST;
USBERR("NULL request context status=%08Xh\n", status);
goto Done;
}
status = WdfRequestRetrieveInputBuffer(Request, sizeof(libusb_request), (PVOID*)&libusbRequest, &libusbRequestSize);
if(!NT_SUCCESS(status))
{
USBERR("WdfRequestRetrieveInputBuffer failed. status=%08Xh\n", status);
goto Done;
}
requestContext->InputBuffer = libusbRequest;
requestContext->InputBufferLength = (ULONG)libusbRequestSize;
RtlCopyMemory(&requestContext->IoControlRequest, libusbRequest, sizeof(requestContext->IoControlRequest));
switch(params.Parameters.DeviceIoControl.IoControlCode)
{
case LIBUSBK_IOCTL_ISOEX_READ:
case LIBUSBK_IOCTL_ISOEX_WRITE:
status = WdfRequestProbeAndLockUserBufferForWrite(Request, libusbRequest->IsoEx.IsoContext, libusbRequest->IsoEx.IsoContextSize, &requestContext->IsoEx.ContextMemory);
if(!NT_SUCCESS(status))
{
USBERR("WdfRequestProbeAndLockUserBufferForWrite failed. status=%08Xh\n", status);
goto Done;
}
break;
}
Done:
if(NT_SUCCESS(status))
{
status = WdfDeviceEnqueueRequest(Device, Request);
if(NT_SUCCESS(status)) return;
USBERR("WdfDeviceEnqueueRequest failed. status=%08Xh\n", status);
}
WdfRequestComplete(Request, status);
return;
}