reactos/drivers/usb/usbehci/irp.c
Timo Kreuzer 9ea495ba33 Create a branch for header work.
svn path=/branches/header-work/; revision=45691
2010-02-26 22:57:55 +00:00

433 lines
20 KiB
C

/*
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/usbehci/irp.c
* PURPOSE: IRP Handling.
* PROGRAMMERS:
* Michael Martin
*/
#include "usbehci.h"
VOID
RequestURBCancel (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
KIRQL OldIrql = Irp->CancelIrql;
IoReleaseCancelSpinLock(DISPATCH_LEVEL);
KeAcquireSpinLockAtDpcLevel(&PdoDeviceExtension->IrpQueueLock);
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&PdoDeviceExtension->IrpQueueLock, OldIrql);
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
VOID
QueueURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp)
{
KIRQL OldIrql;
KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &OldIrql);
if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
{
KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, OldIrql);
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
else
{
InsertTailList(&DeviceExtension->IrpQueue, &Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, OldIrql);
}
}
VOID
CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
{
PLIST_ENTRY NextIrp = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ULONG_PTR Information = 0;
PIO_STACK_LOCATION Stack;
PUSB_DEVICE UsbDevice = NULL;
KIRQL oldIrql;
PIRP Irp = NULL;
URB *Urb;
KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
while(!IsListEmpty(&DeviceExtension->IrpQueue))
{
NextIrp = RemoveHeadList(&DeviceExtension->IrpQueue);
Irp = CONTAINING_RECORD(NextIrp, IRP, Tail.Overlay.ListEntry);
if (!Irp)
break;
Stack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(Stack);
Urb = (PURB) Stack->Parameters.Others.Argument1;
ASSERT(Urb);
Information = 0;
Status = STATUS_SUCCESS;
DPRINT1("TransferBuffer %x\n", Urb->UrbControlDescriptorRequest.TransferBuffer);
DPRINT1("TransferBufferLength %x\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
DPRINT1("UsbdDeviceHandle = %x\n", Urb->UrbHeader.UsbdDeviceHandle);
UsbDevice = Urb->UrbHeader.UsbdDeviceHandle;
/* UsbdDeviceHandle of 0 is root hub */
if (UsbDevice == NULL)
UsbDevice = DeviceExtension->UsbDevices[0];
switch (Urb->UrbHeader.Function)
{
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
{
/* Are we suppose to only return on this request when a device is connected
or is it the RootHubInitNotification Callback */
DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:\n");
DPRINT1("--->TransferBufferLength %x\n",Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
DPRINT1("--->TransferBuffer %x\n",Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
DPRINT1("--->PipeHandle %x\n",Urb->UrbBulkOrInterruptTransfer.PipeHandle);
DPRINT1("--->TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags);
/* FIXME */
RtlZeroMemory(Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1;
/* Turn off Irp handling as nothing is handled beyond this */
DeviceExtension->HaltUrbHandling = TRUE;
break;
}
case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
{
DPRINT1("Get Status from Device\n");
break;
}
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
{
Urb->UrbHeader.Function = 0x08;
Urb->UrbHeader.UsbdFlags = 0;
Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
switch(Urb->UrbControlDescriptorRequest.DescriptorType)
{
case USB_DEVICE_DESCRIPTOR_TYPE:
{
DPRINT1("USB DEVICE DESC\n");
if (Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR))
{
Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
}
RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
&UsbDevice->DeviceDescriptor,
Urb->UrbControlDescriptorRequest.TransferBufferLength);
Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
break;
}
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
{
DPRINT1("USB CONFIG DESC\n");
ULONG FullDescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR) +
sizeof(USB_INTERFACE_DESCRIPTOR) +
sizeof(USB_ENDPOINT_DESCRIPTOR);
if (Urb->UrbControlDescriptorRequest.TransferBufferLength >= FullDescriptorLength)
{
Urb->UrbControlDescriptorRequest.TransferBufferLength = FullDescriptorLength;
}
RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
&UsbDevice->ConfigurationDescriptor,
Urb->UrbControlDescriptorRequest.TransferBufferLength);
Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
break;
}
case USB_STRING_DESCRIPTOR_TYPE:
{
DPRINT1("Usb String Descriptor not implemented\n");
break;
}
default:
{
DPRINT1("Descriptor Type %x not supported!\n", Urb->UrbControlDescriptorRequest.DescriptorType);
}
}
break;
}
case URB_FUNCTION_SELECT_CONFIGURATION:
{
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
LONG iCount, pCount;
DPRINT("Selecting Configuration\n");
DPRINT("Length %x\n", Urb->UrbHeader.Length);
DPRINT("Urb->UrbSelectConfiguration.ConfigurationHandle %x\n",Urb->UrbSelectConfiguration.ConfigurationHandle);
if (Urb->UrbSelectConfiguration.ConfigurationDescriptor)
{
DPRINT("ConfigurationDescriptor = %p\n", Urb->UrbSelectConfiguration.ConfigurationDescriptor);
DPRINT(" bLength = %d\n", Urb->UrbSelectConfiguration.ConfigurationDescriptor->bLength);
DPRINT(" bDescriptorType = %d\n", Urb->UrbSelectConfiguration.ConfigurationDescriptor->bDescriptorType);
DPRINT(" wTotalLength = %d\n", Urb->UrbSelectConfiguration.ConfigurationDescriptor->wTotalLength);
DPRINT(" bNumInterfaces = %d\n", Urb->UrbSelectConfiguration.ConfigurationDescriptor->bNumInterfaces);
DPRINT(" bConfigurationValue = %d\n", Urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue);
DPRINT(" iConfiguration = %d\n", Urb->UrbSelectConfiguration.ConfigurationDescriptor->iConfiguration);
DPRINT(" bmAttributes = %04x\n", Urb->UrbSelectConfiguration.ConfigurationDescriptor->bmAttributes);
DPRINT(" MaxPower = %d\n", Urb->UrbSelectConfiguration.ConfigurationDescriptor->MaxPower);
Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)&DeviceExtension->UsbDevices[0]->ConfigurationDescriptor;
DPRINT("ConfigHandle %x\n", Urb->UrbSelectConfiguration.ConfigurationHandle);
InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
for (iCount = 0; iCount < Urb->UrbSelectConfiguration.ConfigurationDescriptor->bNumInterfaces; iCount++)
{
DPRINT("InterfaceInformation[%d]\n", iCount);
DPRINT(" Length = %d\n", InterfaceInfo->Length);
DPRINT(" InterfaceNumber = %d\n", InterfaceInfo->InterfaceNumber);
DPRINT(" AlternateSetting = %d\n", InterfaceInfo->AlternateSetting);
DPRINT(" Class = %02x\n", (ULONG)InterfaceInfo->Class);
DPRINT(" SubClass = %02x\n", (ULONG)InterfaceInfo->SubClass);
DPRINT(" Protocol = %02x\n", (ULONG)InterfaceInfo->Protocol);
DPRINT(" Reserved = %02x\n", (ULONG)InterfaceInfo->Reserved);
DPRINT(" InterfaceHandle = %p\n", InterfaceInfo->InterfaceHandle);
DPRINT(" NumberOfPipes = %d\n", InterfaceInfo->NumberOfPipes);
InterfaceInfo->InterfaceHandle = (PVOID)&UsbDevice->InterfaceDescriptor;
InterfaceInfo->Class = UsbDevice->InterfaceDescriptor.bInterfaceClass;
InterfaceInfo->SubClass = UsbDevice->InterfaceDescriptor.bInterfaceSubClass;
InterfaceInfo->Protocol = UsbDevice->InterfaceDescriptor.bInterfaceProtocol;
InterfaceInfo->Reserved = 0;
for (pCount = 0; pCount < InterfaceInfo->NumberOfPipes; pCount++)
{
DPRINT("Pipe[%d]\n", pCount);
DPRINT(" MaximumPacketSize = %d\n", InterfaceInfo->Pipes[pCount].MaximumPacketSize);
DPRINT(" EndpointAddress = %d\n", InterfaceInfo->Pipes[pCount].EndpointAddress);
DPRINT(" Interval = %d\n", InterfaceInfo->Pipes[pCount].Interval);
DPRINT(" PipeType = %d\n", InterfaceInfo->Pipes[pCount].PipeType);
DPRINT(" PipeHandle = %x\n", InterfaceInfo->Pipes[pCount].PipeHandle);
DPRINT(" MaximumTransferSize = %d\n", InterfaceInfo->Pipes[pCount].MaximumTransferSize);
DPRINT(" PipeFlags = %08x\n", InterfaceInfo->Pipes[pCount].PipeFlags);
InterfaceInfo->Pipes[pCount].MaximumPacketSize = UsbDevice->EndPointDescriptor.wMaxPacketSize;
InterfaceInfo->Pipes[pCount].EndpointAddress = UsbDevice->EndPointDescriptor.bEndpointAddress;
InterfaceInfo->Pipes[pCount].Interval = UsbDevice->EndPointDescriptor.bInterval;
InterfaceInfo->Pipes[pCount].PipeType = UsbdPipeTypeInterrupt;
InterfaceInfo->Pipes[pCount].PipeHandle = (PVOID)&UsbDevice->EndPointDescriptor;
if (InterfaceInfo->Pipes[pCount].MaximumTransferSize == 0)
InterfaceInfo->Pipes[pCount].MaximumTransferSize = 4096;
/* InterfaceInfo->Pipes[j].PipeFlags = 0; */
}
InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length);
}
Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
Urb->UrbHeader.UsbdFlags = 0;
Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
}
else
{
/* FIXME: Set device to unconfigured state */
}
break;
}
case URB_FUNCTION_CLASS_DEVICE:
{
switch (Urb->UrbControlVendorClassRequest.Request)
{
case USB_REQUEST_GET_DESCRIPTOR:
{
DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
DPRINT1("Urb->UrbControlVendorClassRequest.Value %x\n", Urb->UrbControlVendorClassRequest.Value);
switch (Urb->UrbControlVendorClassRequest.Value >> 8)
{
case USB_DEVICE_CLASS_AUDIO:
{
DPRINT1("USB_DEVICE_CLASS_AUDIO\n");
break;
}
case USB_DEVICE_CLASS_COMMUNICATIONS:
{
DPRINT1("USB_DEVICE_CLASS_COMMUNICATIONS\n");
break;
}
case USB_DEVICE_CLASS_HUMAN_INTERFACE:
{
DPRINT1("USB_DEVICE_CLASS_HUMAN_INTERFACE\n");
break;
}
case USB_DEVICE_CLASS_MONITOR:
{
DPRINT1("USB_DEVICE_CLASS_MONITOR\n");
break;
}
case USB_DEVICE_CLASS_PHYSICAL_INTERFACE:
{
DPRINT1("USB_DEVICE_CLASS_PHYSICAL_INTERFACE\n");
break;
}
case USB_DEVICE_CLASS_POWER:
{
DPRINT1("USB_DEVICE_CLASS_POWER\n");
break;
}
case USB_DEVICE_CLASS_PRINTER:
{
DPRINT1("USB_DEVICE_CLASS_PRINTER\n");
break;
}
case USB_DEVICE_CLASS_STORAGE:
{
DPRINT1("USB_DEVICE_CLASS_STORAGE\n");
break;
}
case USB_DEVICE_CLASS_RESERVED:
case USB_DEVICE_CLASS_HUB:
{
PUSB_HUB_DESCRIPTOR UsbHubDescr = Urb->UrbControlVendorClassRequest.TransferBuffer;
/* FIXME: Handle more than root hub? */
if(Urb->UrbControlVendorClassRequest.TransferBufferLength >= sizeof(USB_HUB_DESCRIPTOR))
{
Urb->UrbControlVendorClassRequest.TransferBufferLength = sizeof(USB_HUB_DESCRIPTOR);
}
else
{
/* FIXME: Handle this correctly */
UsbHubDescr->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
UsbHubDescr->bDescriptorType = 0x29;
return;
}
DPRINT1("USB_DEVICE_CLASS_HUB request\n");
UsbHubDescr->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
UsbHubDescr->bDescriptorType = 0x29;
UsbHubDescr->bNumberOfPorts = 0x08;
UsbHubDescr->wHubCharacteristics = 0x0012;
UsbHubDescr->bPowerOnToPowerGood = 0x01;
UsbHubDescr->bHubControlCurrent = 0x00;
UsbHubDescr->bRemoveAndPowerMask[0] = 0x00;
UsbHubDescr->bRemoveAndPowerMask[1] = 0x00;
UsbHubDescr->bRemoveAndPowerMask[2] = 0xff;
break;
}
default:
{
DPRINT1("Unknown UrbControlVendorClassRequest Value\n");
}
}
Urb->UrbHeader.Function = 0x08;
Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
Urb->UrbHeader.UsbdFlags = 0;
break;
}
default:
{
DPRINT1("Unhandled URB request for class device\n");
Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
}
}
break;
}
case URB_FUNCTION_CLASS_OTHER:
{
switch (Urb->UrbControlVendorClassRequest.Request)
{
case USB_REQUEST_GET_STATUS:
{
DPRINT1("USB_REQUEST_GET_STATUS\n");
break;
}
case USB_REQUEST_CLEAR_FEATURE:
{
DPRINT1("USB_REQUEST_CLEAR_FEATURE\n");
break;
}
case USB_REQUEST_SET_FEATURE:
{
DPRINT1("USB_REQUEST_SET_FEATURE value %x\n", Urb->UrbControlVendorClassRequest.Value);
switch(Urb->UrbControlVendorClassRequest.Value)
{
/* FIXME: Needs research */
case 0x01:
{
}
}
break;
}
case USB_REQUEST_SET_ADDRESS:
{
DPRINT1("USB_REQUEST_SET_ADDRESS\n");
break;
}
case USB_REQUEST_GET_DESCRIPTOR:
{
DPRINT1("USB_REQUEST_GET_DESCRIPTOR\n");
break;
}
case USB_REQUEST_SET_DESCRIPTOR:
{
DPRINT1("USB_REQUEST_SET_DESCRIPTOR\n");
break;
}
case USB_REQUEST_GET_CONFIGURATION:
{
DPRINT1("USB_REQUEST_GET_CONFIGURATION\n");
break;
}
case USB_REQUEST_SET_CONFIGURATION:
{
DPRINT1("USB_REQUEST_SET_CONFIGURATION\n");
break;
}
case USB_REQUEST_GET_INTERFACE:
{
DPRINT1("USB_REQUEST_GET_INTERFACE\n");
break;
}
case USB_REQUEST_SET_INTERFACE:
{
DPRINT1("USB_REQUEST_SET_INTERFACE\n");
break;
}
case USB_REQUEST_SYNC_FRAME:
{
DPRINT1("USB_REQUEST_SYNC_FRAME\n");
break;
}
}
break;
}
default:
{
DPRINT1("Unhandled URB %x\n", Urb->UrbHeader.Function);
Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
}
}
KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Information;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
}
KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
}