reactos/drivers/usb/usbport/urb.c

1066 lines
35 KiB
C

/*
* PROJECT: ReactOS USB Port Driver
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: USBPort URB functions
* COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
*/
#include "usbport.h"
#define NDEBUG
#include <debug.h>
#define NDEBUG_USBPORT_URB
#include "usbdebug.h"
NTSTATUS
NTAPI
USBPORT_HandleGetConfiguration(IN PURB Urb)
{
PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
DPRINT_URB("USBPORT_HandleGetConfiguration: Urb - %p\n", Urb);
SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
&Urb->UrbControlGetConfigurationRequest.Reserved1;
SetupPacket->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
SetupPacket->bRequest = USB_REQUEST_GET_CONFIGURATION;
SetupPacket->wValue.W = 0;
SetupPacket->wIndex.W = 0;
SetupPacket->wLength = Urb->UrbControlGetConfigurationRequest.TransferBufferLength;
Urb->UrbControlGetConfigurationRequest.Reserved0 |= USBD_TRANSFER_DIRECTION_IN; // 1;
Urb->UrbControlGetConfigurationRequest.Reserved0 |= USBD_SHORT_TRANSFER_OK; // 2
USBPORT_DumpingSetupPacket(SetupPacket);
USBPORT_QueueTransferUrb(Urb);
return STATUS_PENDING;
}
NTSTATUS
NTAPI
USBPORT_HandleGetCurrentFrame(IN PDEVICE_OBJECT FdoDevice,
IN PIRP Irp,
IN PURB Urb)
{
PUSBPORT_DEVICE_EXTENSION FdoExtension;
PUSBPORT_REGISTRATION_PACKET Packet;
ULONG FrameNumber;
KIRQL OldIrql;
FdoExtension = FdoDevice->DeviceExtension;
Packet = &FdoExtension->MiniPortInterface->Packet;
KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
FrameNumber = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt);
KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
Urb->UrbGetCurrentFrameNumber.FrameNumber = FrameNumber;
DPRINT_URB("USBPORT_HandleGetCurrentFrame: FrameNumber - %p\n",
FrameNumber);
return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
}
NTSTATUS
NTAPI
USBPORT_AbortPipe(IN PDEVICE_OBJECT FdoDevice,
IN PIRP Irp,
IN PURB Urb)
{
PUSBPORT_ENDPOINT Endpoint;
PUSBPORT_PIPE_HANDLE PipeHandle;
PUSBPORT_DEVICE_HANDLE DeviceHandle;
NTSTATUS Status;
DPRINT_URB("USBPORT_AbortPipe: ... \n");
PipeHandle = Urb->UrbPipeRequest.PipeHandle;
DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
if (USBPORT_ValidatePipeHandle(DeviceHandle, PipeHandle))
{
if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE))
{
Endpoint = PipeHandle->Endpoint;
Status = STATUS_PENDING;
Irp->IoStatus.Status = Status;
IoMarkIrpPending(Irp);
USBPORT_AbortEndpoint(FdoDevice, Endpoint, Irp);
return Status;
}
Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
}
else
{
Status = USBPORT_USBDStatusToNtStatus(Urb,
USBD_STATUS_INVALID_PIPE_HANDLE);
}
return Status;
}
NTSTATUS
NTAPI
USBPORT_ResetPipe(IN PDEVICE_OBJECT FdoDevice,
IN PIRP Irp,
IN PURB Urb)
{
PUSBPORT_DEVICE_EXTENSION FdoExtension;
PUSBPORT_REGISTRATION_PACKET Packet;
PUSBPORT_PIPE_HANDLE PipeHandle;
PUSBPORT_ENDPOINT Endpoint;
NTSTATUS Status;
DPRINT_URB("USBPORT_ResetPipe: ... \n");
FdoExtension = FdoDevice->DeviceExtension;
Packet = &FdoExtension->MiniPortInterface->Packet;
PipeHandle = Urb->UrbPipeRequest.PipeHandle;
if (!USBPORT_ValidatePipeHandle((PUSBPORT_DEVICE_HANDLE)Urb->UrbHeader.UsbdDeviceHandle,
PipeHandle))
{
return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_INVALID_PIPE_HANDLE);
}
Endpoint = PipeHandle->Endpoint;
KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
if (IsListEmpty(&Endpoint->TransferList))
{
if (Urb->UrbHeader.UsbdFlags & USBD_FLAG_NOT_ISO_TRANSFER)
{
KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
Packet->SetEndpointDataToggle(FdoExtension->MiniPortExt,
Endpoint + 1,
0);
KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
}
Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
}
else
{
Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_ERROR_BUSY);
}
Endpoint->Flags |= ENDPOINT_FLAG_QUEUENE_EMPTY;
KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
Packet->SetEndpointStatus(FdoExtension->MiniPortExt,
Endpoint + 1,
USBPORT_ENDPOINT_RUN);
KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
return Status;
}
NTSTATUS
NTAPI
USBPORT_ClearStall(IN PDEVICE_OBJECT FdoDevice,
IN PIRP Irp,
IN PURB Urb)
{
PUSBPORT_DEVICE_HANDLE DeviceHandle;
PUSBPORT_PIPE_HANDLE PipeHandle;
USBD_STATUS USBDStatus;
PUSBPORT_ENDPOINT Endpoint;
NTSTATUS Status;
USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
DPRINT_URB("USBPORT_ClearStall: ... \n");
PipeHandle = Urb->UrbPipeRequest.PipeHandle;
DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
if (!USBPORT_ValidatePipeHandle(DeviceHandle, PipeHandle))
{
return USBPORT_USBDStatusToNtStatus(Urb,
USBD_STATUS_INVALID_PIPE_HANDLE);
}
Endpoint = PipeHandle->Endpoint;
RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
SetupPacket.bRequest = USB_REQUEST_CLEAR_FEATURE;
SetupPacket.wValue.W = 0;
SetupPacket.wIndex.W = Endpoint->EndpointProperties.EndpointAddress;
SetupPacket.wLength = 0;
USBPORT_SendSetupPacket(DeviceHandle,
FdoDevice,
&SetupPacket,
NULL,
0,
NULL,
&USBDStatus);
Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
return Status;
}
NTSTATUS
NTAPI
USBPORT_SyncResetPipeAndClearStall(IN PDEVICE_OBJECT FdoDevice,
IN PIRP Irp,
IN PURB Urb)
{
PUSBPORT_DEVICE_HANDLE DeviceHandle;
PUSBPORT_PIPE_HANDLE PipeHandle;
PUSBPORT_ENDPOINT Endpoint;
ULONG EndpointState;
NTSTATUS Status;
DPRINT_URB("USBPORT_SyncResetPipeAndClearStall: ... \n");
ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
ASSERT(Urb->UrbPipeRequest.PipeHandle);
DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
PipeHandle = Urb->UrbPipeRequest.PipeHandle;
if (!USBPORT_ValidatePipeHandle(DeviceHandle, PipeHandle))
{
return USBPORT_USBDStatusToNtStatus(Urb,
USBD_STATUS_INVALID_PIPE_HANDLE);
}
if (PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE)
{
return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
}
Endpoint = PipeHandle->Endpoint;
InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
if (Endpoint->EndpointProperties.TransferType != USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
{
Urb->UrbHeader.UsbdFlags |= USBD_FLAG_NOT_ISO_TRANSFER;
Status = USBPORT_ClearStall(FdoDevice, Irp, Urb);
}
else
{
Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
}
if (NT_SUCCESS(Status))
{
Status = USBPORT_ResetPipe(FdoDevice, Irp, Urb);
if (Endpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
{
while (TRUE)
{
KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
&Endpoint->EndpointOldIrql);
EndpointState = USBPORT_GetEndpointState(Endpoint);
if (EndpointState == USBPORT_ENDPOINT_PAUSED &&
IsListEmpty(&Endpoint->TransferList))
{
USBPORT_SetEndpointState(Endpoint,
USBPORT_ENDPOINT_ACTIVE);
}
KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
Endpoint->EndpointOldIrql);
if (EndpointState == USBPORT_ENDPOINT_ACTIVE)
{
break;
}
USBPORT_Wait(FdoDevice, 1);
}
}
}
InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
return Status;
}
NTSTATUS
NTAPI
USBPORT_HandleSetOrClearFeature(IN PURB Urb)
{
PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
DPRINT_URB("USBPORT_HandleSetOrClearFeature: Urb - %p\n", Urb);
SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
&Urb->UrbControlFeatureRequest.Reserved0;
SetupPacket->wLength = 0;
Urb->UrbControlFeatureRequest.Reserved3 = 0; // TransferBufferLength
SetupPacket->bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
switch (Urb->UrbHeader.Function)
{
case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
SetupPacket->bRequest = USB_REQUEST_SET_FEATURE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
break;
case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE\n");
SetupPacket->bRequest = USB_REQUEST_SET_FEATURE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
break;
case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE\n");
SetupPacket->bRequest = USB_REQUEST_SET_FEATURE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
break;
case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT\n");
SetupPacket->bRequest = USB_REQUEST_CLEAR_FEATURE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
break;
case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT\n");
SetupPacket->bRequest = USB_REQUEST_CLEAR_FEATURE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
break;
case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE\n");
SetupPacket->bRequest = USB_REQUEST_CLEAR_FEATURE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
break;
case URB_FUNCTION_CLEAR_FEATURE_TO_OTHER:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE\n");
SetupPacket->bRequest = USB_REQUEST_CLEAR_FEATURE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_OTHER;
break;
case URB_FUNCTION_SET_FEATURE_TO_OTHER:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE\n");
SetupPacket->bRequest = USB_REQUEST_SET_FEATURE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_OTHER;
break;
}
Urb->UrbControlFeatureRequest.Reserved2 &= ~USBD_TRANSFER_DIRECTION_IN;
Urb->UrbControlFeatureRequest.Reserved2 |= USBD_SHORT_TRANSFER_OK;
USBPORT_DumpingSetupPacket(SetupPacket);
USBPORT_QueueTransferUrb(Urb);
return STATUS_PENDING;
}
NTSTATUS
NTAPI
USBPORT_HandleDataTransfers(IN PURB Urb)
{
PUSBPORT_ENDPOINT Endpoint;
DPRINT_URB("USBPORT_HandleDataTransfers: Urb - %p\n", Urb);
Endpoint = ((PUSBPORT_PIPE_HANDLE)
(Urb->UrbBulkOrInterruptTransfer.PipeHandle))->Endpoint;
if (Endpoint->EndpointProperties.TransferType != USBPORT_TRANSFER_TYPE_CONTROL)
{
if (Endpoint->EndpointProperties.Direction == USBPORT_TRANSFER_DIRECTION_OUT)
{
Urb->UrbBulkOrInterruptTransfer.TransferFlags &= ~USBD_TRANSFER_DIRECTION_IN;
}
else
{
Urb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_TRANSFER_DIRECTION_IN;
}
}
USBPORT_QueueTransferUrb(Urb);
return STATUS_PENDING;
}
NTSTATUS
NTAPI
USBPORT_HandleGetStatus(IN PIRP Irp,
IN PURB Urb)
{
PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
NTSTATUS Status;
SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
&Urb->UrbControlDescriptorRequest.Reserved1;
SetupPacket->bmRequestType.B = 0;
SetupPacket->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
SetupPacket->bRequest = USB_REQUEST_GET_STATUS;
SetupPacket->wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
SetupPacket->wValue.W = 0;
switch (Urb->UrbHeader.Function)
{
case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
DPRINT_URB("USBPORT_HandleGetStatus: URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
break;
case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
DPRINT_URB("USBPORT_HandleGetStatus: URB_FUNCTION_GET_STATUS_FROM_INTERFACE\n");
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
break;
case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
DPRINT_URB("USBPORT_HandleGetStatus: URB_FUNCTION_GET_STATUS_FROM_ENDPOINT\n");
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
break;
case URB_FUNCTION_GET_STATUS_FROM_OTHER:
DPRINT_URB("USBPORT_HandleGetStatus: URB_FUNCTION_GET_STATUS_FROM_OTHER\n");
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_OTHER;
break;
}
if (SetupPacket->wLength == 2)
{
Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
if (SetupPacket->bmRequestType.Dir)
Urb->UrbControlTransfer.TransferFlags |= USBD_TRANSFER_DIRECTION_IN;
else
Urb->UrbControlTransfer.TransferFlags &= ~USBD_TRANSFER_DIRECTION_IN;
//USBPORT_DumpingSetupPacket(SetupPacket);
USBPORT_QueueTransferUrb(Urb);
Status = STATUS_PENDING;
}
else
{
Status = USBPORT_USBDStatusToNtStatus(Urb,
USBD_STATUS_INVALID_PARAMETER);
DPRINT1("USBPORT_HandleGetStatus: Bad wLength\n");
USBPORT_DumpingSetupPacket(SetupPacket);
}
return Status;
}
NTSTATUS
NTAPI
USBPORT_HandleVendorOrClass(IN PIRP Irp,
IN PURB Urb)
{
PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
/*
Specifies a value, from 4 to 31 inclusive,
that becomes part of the request type code in the USB-defined setup packet.
This value is defined by USB for a class request or the vendor for a vendor request.
*/
SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
&Urb->UrbControlDescriptorRequest.Reserved1;
SetupPacket->bmRequestType.Dir = USBD_TRANSFER_DIRECTION_FLAG
(Urb->UrbControlTransfer.TransferFlags);
SetupPacket->wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
switch (Urb->UrbHeader.Function)
{
case URB_FUNCTION_VENDOR_DEVICE:
DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_VENDOR_DEVICE\n");
SetupPacket->bmRequestType.Type = BMREQUEST_VENDOR;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
break;
case URB_FUNCTION_VENDOR_INTERFACE:
DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_VENDOR_INTERFACE\n");
SetupPacket->bmRequestType.Type = BMREQUEST_VENDOR;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
break;
case URB_FUNCTION_VENDOR_ENDPOINT:
DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_VENDOR_ENDPOINT\n");
SetupPacket->bmRequestType.Type = BMREQUEST_VENDOR;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
break;
case URB_FUNCTION_CLASS_DEVICE:
DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_CLASS_DEVICE\n");
SetupPacket->bmRequestType.Type = BMREQUEST_CLASS;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
break;
case URB_FUNCTION_CLASS_INTERFACE:
DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_CLASS_INTERFACE\n");
SetupPacket->bmRequestType.Type = BMREQUEST_CLASS;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
break;
case URB_FUNCTION_CLASS_ENDPOINT:
DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_CLASS_ENDPOINT\n");
SetupPacket->bmRequestType.Type = BMREQUEST_CLASS;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
break;
case URB_FUNCTION_CLASS_OTHER:
DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_CLASS_OTHER\n");
SetupPacket->bmRequestType.Type = BMREQUEST_CLASS;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_OTHER;
break;
case URB_FUNCTION_VENDOR_OTHER:
DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_VENDOR_OTHER\n");
SetupPacket->bmRequestType.Type = BMREQUEST_VENDOR;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_OTHER;
break;
}
USBPORT_DumpingSetupPacket(SetupPacket);
USBPORT_QueueTransferUrb(Urb);
return STATUS_PENDING;
}
NTSTATUS
NTAPI
USBPORT_HandleGetSetDescriptor(IN PIRP Irp,
IN PURB Urb)
{
PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
&Urb->UrbControlDescriptorRequest.Reserved1;
SetupPacket->wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
SetupPacket->bmRequestType.B = 0; // Clear bmRequestType
SetupPacket->bmRequestType.Type = BMREQUEST_STANDARD;
switch (Urb->UrbHeader.Function)
{
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
SetupPacket->bRequest = USB_REQUEST_GET_DESCRIPTOR;
SetupPacket->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
break;
case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE\n");
SetupPacket->bRequest = USB_REQUEST_SET_DESCRIPTOR;
SetupPacket->bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
break;
case URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT\n");
SetupPacket->bRequest = USB_REQUEST_GET_DESCRIPTOR;
SetupPacket->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
break;
case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT\n");
SetupPacket->bRequest = USB_REQUEST_SET_DESCRIPTOR;
SetupPacket->bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
break;
case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE\n");
SetupPacket->bRequest = USB_REQUEST_GET_DESCRIPTOR;
SetupPacket->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
break;
case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE\n");
SetupPacket->bRequest = USB_REQUEST_SET_DESCRIPTOR;
SetupPacket->bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
break;
}
Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
if (SetupPacket->bmRequestType.Dir)
Urb->UrbControlTransfer.TransferFlags |= USBD_TRANSFER_DIRECTION_IN;
else
Urb->UrbControlTransfer.TransferFlags &= ~USBD_TRANSFER_DIRECTION_IN;
USBPORT_DumpingSetupPacket(SetupPacket);
USBPORT_QueueTransferUrb(Urb);
return STATUS_PENDING;
}
NTSTATUS
NTAPI
USBPORT_ValidateTransferParametersURB(IN PURB Urb)
{
struct _URB_CONTROL_TRANSFER *UrbRequest;
PMDL Mdl;
DPRINT_URB("USBPORT_ValidateTransferParametersURB: Urb - %p\n", Urb);
UrbRequest = &Urb->UrbControlTransfer;
if (UrbRequest->TransferBuffer == NULL &&
UrbRequest->TransferBufferMDL == NULL &&
UrbRequest->TransferBufferLength > 0)
{
DPRINT1("USBPORT_ValidateTransferParametersURB: Not valid parameter\n");
USBPORT_DumpingURB(Urb);
return STATUS_INVALID_PARAMETER;
}
if ((UrbRequest->TransferBuffer != NULL) &&
(UrbRequest->TransferBufferMDL != NULL) &&
UrbRequest->TransferBufferLength == 0)
{
DPRINT1("USBPORT_ValidateTransferParametersURB: Not valid parameter\n");
USBPORT_DumpingURB(Urb);
return STATUS_INVALID_PARAMETER;
}
if (UrbRequest->TransferBuffer != NULL &&
UrbRequest->TransferBufferMDL == NULL &&
UrbRequest->TransferBufferLength != 0)
{
DPRINT_URB("USBPORT_ValidateTransferParametersURB: TransferBuffer - %p, TransferBufferLength - %x\n",
UrbRequest->TransferBuffer,
UrbRequest->TransferBufferLength);
Mdl = IoAllocateMdl(UrbRequest->TransferBuffer,
UrbRequest->TransferBufferLength,
FALSE,
FALSE,
NULL);
if (!Mdl)
{
DPRINT1("USBPORT_ValidateTransferParametersURB: Not allocated Mdl\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(Mdl);
UrbRequest->TransferBufferMDL = Mdl;
Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_MDL;
DPRINT_URB("USBPORT_ValidateTransferParametersURB: Mdl - %p\n", Mdl);
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
USBPORT_ValidateURB(IN PDEVICE_OBJECT FdoDevice,
IN PIRP Irp,
IN PURB Urb,
IN BOOLEAN IsControlTransfer,
IN BOOLEAN IsNullTransfer)
{
struct _URB_CONTROL_TRANSFER *UrbRequest;
PUSBPORT_DEVICE_HANDLE DeviceHandle;
NTSTATUS Status;
USBD_STATUS USBDStatus;
UrbRequest = &Urb->UrbControlTransfer;
if (UrbRequest->UrbLink)
{
Status = USBPORT_USBDStatusToNtStatus(Urb,
USBD_STATUS_INVALID_PARAMETER);
DPRINT1("USBPORT_ValidateURB: Not valid parameter\n");
USBPORT_DumpingURB(Urb);
return Status;
}
DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
if (IsControlTransfer)
{
UrbRequest->TransferFlags |= USBD_DEFAULT_PIPE_TRANSFER;
UrbRequest->PipeHandle = &DeviceHandle->PipeHandle;
}
if (UrbRequest->TransferFlags & USBD_DEFAULT_PIPE_TRANSFER)
{
if (UrbRequest->TransferBufferLength > 0x1000)
{
Status = USBPORT_USBDStatusToNtStatus(Urb,
USBD_STATUS_INVALID_PARAMETER);
DPRINT1("USBPORT_ValidateURB: Not valid parameter\n");
USBPORT_DumpingURB(Urb);
return Status;
}
if (Urb->UrbHeader.Function == URB_FUNCTION_CONTROL_TRANSFER)
{
UrbRequest->PipeHandle = &DeviceHandle->PipeHandle;
}
}
if (!USBPORT_ValidatePipeHandle(DeviceHandle, UrbRequest->PipeHandle))
{
Status = USBPORT_USBDStatusToNtStatus(Urb,
USBD_STATUS_INVALID_PIPE_HANDLE);
DPRINT1("USBPORT_ValidateURB: Not valid pipe handle\n");
USBPORT_DumpingURB(Urb);
return Status;
}
UrbRequest->hca.Reserved8[0] = NULL; // Transfer
if (IsNullTransfer)
{
UrbRequest->TransferBuffer = 0;
UrbRequest->TransferBufferMDL = NULL;
UrbRequest->TransferBufferLength = 0;
}
else
{
Status = USBPORT_ValidateTransferParametersURB(Urb);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
USBDStatus = USBPORT_AllocateTransfer(FdoDevice,
Urb,
DeviceHandle,
Irp,
NULL);
Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
if (!NT_SUCCESS(Status))
{
DPRINT1("USBPORT_ValidateURB: Not allocated transfer\n");
}
return Status;
}
NTSTATUS
NTAPI
USBPORT_HandleSubmitURB(IN PDEVICE_OBJECT PdoDevice,
IN PIRP Irp,
IN PURB Urb)
{
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
PDEVICE_OBJECT FdoDevice;
PUSBPORT_DEVICE_EXTENSION FdoExtension;
USHORT Function;
PUSBPORT_DEVICE_HANDLE DeviceHandle;
NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
ASSERT(Urb);
PdoExtension = PdoDevice->DeviceExtension;
FdoDevice = PdoExtension->FdoDevice;
FdoExtension = FdoDevice->DeviceExtension;
Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
Urb->UrbHeader.UsbdFlags = 0;
Function = Urb->UrbHeader.Function;
if (Function > URB_FUNCTION_MAX)
{
Status = USBPORT_USBDStatusToNtStatus(Urb,
USBD_STATUS_INVALID_URB_FUNCTION);
DPRINT1("USBPORT_HandleSubmitURB: Unknown URB function - %x !!!\n",
Function);
return Status;
}
if (FdoExtension->TimerFlags & USBPORT_TMFLAG_RH_SUSPENDED)
{
DPRINT1("USBPORT_HandleSubmitURB: Bad Request\n");
USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_DEVICE_GONE);
Irp->IoStatus.Status = STATUS_PENDING;
IoMarkIrpPending(Irp);
IoCsqInsertIrp(&FdoExtension->BadRequestIoCsq, Irp, NULL);
return STATUS_PENDING;
}
DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
if (!DeviceHandle)
{
DeviceHandle = &PdoExtension->DeviceHandle;
Urb->UrbHeader.UsbdDeviceHandle = DeviceHandle;
}
if (!USBPORT_ValidateDeviceHandle(PdoExtension->FdoDevice,
DeviceHandle))
{
DPRINT1("USBPORT_HandleSubmitURB: Not valid device handle\n");
Irp->IoStatus.Status = STATUS_PENDING;
IoMarkIrpPending(Irp);
IoCsqInsertIrp(&FdoExtension->BadRequestIoCsq, Irp, NULL);
return STATUS_PENDING;
}
InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
DPRINT_URB("USBPORT_HandleSubmitURB: Function - 0x%02X, DeviceHandle - %p\n",
Function,
Urb->UrbHeader.UsbdDeviceHandle);
switch (Function)
{
case URB_FUNCTION_ISOCH_TRANSFER:
DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_ISOCH_TRANSFER UNIMPLEMENTED. FIXME. \n");
break;
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
case URB_FUNCTION_CONTROL_TRANSFER:
Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, FALSE, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
break;
}
Status = USBPORT_HandleDataTransfers(Urb);
break;
case URB_FUNCTION_VENDOR_DEVICE:
case URB_FUNCTION_VENDOR_INTERFACE:
case URB_FUNCTION_VENDOR_ENDPOINT:
case URB_FUNCTION_CLASS_DEVICE:
case URB_FUNCTION_CLASS_INTERFACE:
case URB_FUNCTION_CLASS_ENDPOINT:
case URB_FUNCTION_CLASS_OTHER:
case URB_FUNCTION_VENDOR_OTHER:
Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
break;
}
Status = USBPORT_HandleVendorOrClass(Irp, Urb);
break;
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:
case URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT:
case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:
case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
break;
}
Status = USBPORT_HandleGetSetDescriptor(Irp, Urb);
break;
case URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR:
DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR (0x2A) NOT_SUPPORTED\n");
return USBPORT_USBDStatusToNtStatus(Urb,
USBD_STATUS_INVALID_URB_FUNCTION);
case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
case URB_FUNCTION_GET_STATUS_FROM_OTHER:
Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
break;
}
Status = USBPORT_HandleGetStatus(Irp, Urb);
break;
case URB_FUNCTION_SELECT_CONFIGURATION:
Status = USBPORT_HandleSelectConfiguration(PdoExtension->FdoDevice,
Irp,
Urb);
break;
case URB_FUNCTION_SELECT_INTERFACE:
Status = USBPORT_HandleSelectInterface(PdoExtension->FdoDevice,
Irp,
Urb);
break;
case URB_FUNCTION_GET_CONFIGURATION:
Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
break;
}
Status = USBPORT_HandleGetConfiguration(Urb);
break;
case URB_FUNCTION_GET_INTERFACE:
DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_INTERFACE (0x27) NOT_SUPPORTED\n");
return USBPORT_USBDStatusToNtStatus(Urb,
USBD_STATUS_INVALID_URB_FUNCTION);
case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
Status = USBPORT_SyncResetPipeAndClearStall(PdoExtension->FdoDevice,
Irp,
Urb);
break;
case URB_FUNCTION_SYNC_RESET_PIPE:
Status = USBPORT_ResetPipe(PdoExtension->FdoDevice,
Irp,
Urb);
break;
case URB_FUNCTION_SYNC_CLEAR_STALL:
Status = USBPORT_ClearStall(PdoExtension->FdoDevice,
Irp,
Urb);
break;
case URB_FUNCTION_ABORT_PIPE:
Status = USBPORT_AbortPipe(PdoExtension->FdoDevice,
Irp,
Urb);
break;
case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
case URB_FUNCTION_CLEAR_FEATURE_TO_OTHER:
case URB_FUNCTION_SET_FEATURE_TO_OTHER:
Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
break;
}
Status = USBPORT_HandleSetOrClearFeature(Urb);
break;
case URB_FUNCTION_GET_CURRENT_FRAME_NUMBER:
Status = USBPORT_HandleGetCurrentFrame(PdoExtension->FdoDevice,
Irp,
Urb);
break;
case URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL:
DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL (0x03) NOT_SUPPORTED\n");
return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED);
case URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL:
DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL (0x04) NOT_SUPPORTED\n");
return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED);
case URB_FUNCTION_GET_FRAME_LENGTH:
DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_FRAME_LENGTH (0x05) NOT_SUPPORTED\n");
return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED);
case URB_FUNCTION_SET_FRAME_LENGTH:
DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_SET_FRAME_LENGTH (0x06) NOT_SUPPORTED\n");
return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED);
default:
DPRINT1("USBPORT_HandleSubmitURB: Unknown URB Function - %x\n",
Function);
//URB_FUNCTION_RESERVED_0X0016
//URB_FUNCTION_RESERVE_0X001D
//URB_FUNCTION_RESERVE_0X002B
//URB_FUNCTION_RESERVE_0X002C
//URB_FUNCTION_RESERVE_0X002D
//URB_FUNCTION_RESERVE_0X002E
//URB_FUNCTION_RESERVE_0X002F
break;
}
if (Status == STATUS_PENDING)
{
return Status;
}
if (Urb->UrbHeader.UsbdFlags & USBD_FLAG_ALLOCATED_TRANSFER)
{
PUSBPORT_TRANSFER Transfer;
Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
Urb->UrbControlTransfer.hca.Reserved8[0] = NULL;
Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_TRANSFER;
ExFreePoolWithTag(Transfer, USB_PORT_TAG);
}
InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}