[usb/usbehci]:

- Implement URB_FUNCTION_SELECT_INTERFACE.
- Add missing IoMarkIrpPending before calling SubmitControlRequest.
- Now use BuildSetupPacketFromURB for creating the CtrlSetup data structure.
- When selecting configuration, make the ConfigurationHandle from the related UsbDevice instead of always the RootHub device.
- Fix typo that caused all pipes to be marked as interrupt type.
- Change CompletePendingURBRequest to only complete one SCE request Irp.

svn path=/trunk/; revision=50303
This commit is contained in:
Michael Martin
2011-01-06 18:29:52 +00:00
parent 748ea2de6c
commit e11ab1740c
+87 -62
View File
@@ -139,20 +139,21 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
}
else
DPRINT("Interrupt Transfer not for hub\n");
DPRINT1("Interrupt Transfer not for hub\n");
break;
}
case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
{
DPRINT1("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
if (Urb->UrbControlGetStatusRequest.Index == 0)
/* If for the hub device */
if ((Urb->UrbControlGetStatusRequest.Index == 0) && (UsbDevice == PdoDeviceExtension->UsbDevices[0]))
{
ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer != NULL);
*(PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer = USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE;
*(PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer = USB_PORT_STATUS_CONNECT /*| USB_PORT_STATUS_ENABLE*/;
}
else
{
DPRINT1("Uknown identifier\n");
DPRINT1("UsbDeviceHandle %x, Index %x not implemented yet\n", UsbDevice, Urb->UrbControlGetStatusRequest.Index);
Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
Status = STATUS_UNSUCCESSFUL;
}
@@ -189,15 +190,14 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer != NULL);
DPRINT("Calling BuildSetUpPacketFromUrb\n");
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
DPRINT("SubmitControlTransfer\n");
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
Urb->UrbControlDescriptorRequest.TransferBuffer,
Urb->UrbControlDescriptorRequest.TransferBufferLength,
Irp);
break;
}
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
@@ -267,24 +267,15 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
if (Urb->UrbControlDescriptorRequest.Index == 0)
DPRINT1("Requesting LANGID's\n");
CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
CtrlSetup.bmRequestType._BM.Reserved = 0;
CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
CtrlSetup.wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
Urb->UrbControlDescriptorRequest.TransferBuffer,
Urb->UrbControlDescriptorRequest.TransferBufferLength,
Irp);
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
break;
}
default:
@@ -301,11 +292,11 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
DPRINT1("Selecting Configuration\n");
DPRINT1("ConfigurationHandle %x\n",Urb->UrbSelectConfiguration.ConfigurationHandle);
if (Urb->UrbSelectConfiguration.ConfigurationDescriptor)
{
Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)&PdoDeviceExtension->UsbDevices[0]->ActiveConfig->ConfigurationDescriptor;
DPRINT("ConfigHandle %x\n", Urb->UrbSelectConfiguration.ConfigurationHandle);
Urb->UrbSelectConfiguration.ConfigurationHandle = &UsbDevice->ActiveConfig->ConfigurationDescriptor;
DPRINT1("ConfigHandle %x\n", Urb->UrbSelectConfiguration.ConfigurationHandle);
ASSERT(FALSE);
InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
DPRINT1("Length %x\n", InterfaceInfo->Length);
@@ -324,7 +315,7 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
InterfaceInfo->Pipes[pCount].MaximumPacketSize = UsbDevice->ActiveInterface->EndPoints[pCount]->EndPointDescriptor.wMaxPacketSize;
InterfaceInfo->Pipes[pCount].EndpointAddress = UsbDevice->ActiveInterface->EndPoints[pCount]->EndPointDescriptor.bEndpointAddress;
InterfaceInfo->Pipes[pCount].Interval = UsbDevice->ActiveInterface->EndPoints[pCount]->EndPointDescriptor.bInterval;
InterfaceInfo->Pipes[pCount].PipeType = UsbdPipeTypeInterrupt;
InterfaceInfo->Pipes[pCount].PipeType = UsbDevice->ActiveInterface->EndPoints[pCount]->EndPointDescriptor.bmAttributes;
InterfaceInfo->Pipes[pCount].PipeHandle = (PVOID)&UsbDevice->ActiveInterface->EndPoints[pCount]->EndPointDescriptor;
if (InterfaceInfo->Pipes[pCount].MaximumTransferSize == 0)
InterfaceInfo->Pipes[pCount].MaximumTransferSize = 4096;
@@ -337,9 +328,39 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
else
{
/* FIXME: Set device to unconfigured state */
DPRINT1("Setting device to unconfigured state not implemented!\n");
}
break;
}
case URB_FUNCTION_SELECT_INTERFACE:
{
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
int i;
DPRINT1("Select Interface!\n");
DPRINT1("Config Handle %x\n", Urb->UrbSelectInterface.ConfigurationHandle);
InterfaceInfo = &Urb->UrbSelectInterface.Interface;
DPRINT1("InterfaceNumber %x\n", InterfaceInfo->InterfaceNumber);
DPRINT1("AlternateSetting %x\n", InterfaceInfo->AlternateSetting);
DPRINT1("NumPipes %x\n", InterfaceInfo->NumberOfPipes);
for (i=0;i<InterfaceInfo->NumberOfPipes;i++)
{
InterfaceInfo->Pipes[i].PipeHandle = (PVOID)&UsbDevice->ActiveInterface->EndPoints[i]->EndPointDescriptor;
}
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
NULL,
0,
Irp);
break;
}
case URB_FUNCTION_CLASS_DEVICE:
{
DPRINT1("URB_FUNCTION_CLASS_DEVICE\n");
@@ -456,7 +477,7 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
{
case USB_REQUEST_GET_STATUS:
{
DPRINT1("USB_REQUEST_GET_STATUS Port %d\n", Urb->UrbControlVendorClassRequest.Index);
DPRINT("USB_REQUEST_GET_STATUS Port %d\n", Urb->UrbControlVendorClassRequest.Index);
ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer != 0);
DPRINT("PortStatus %x\n", PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus);
@@ -467,23 +488,21 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
case USB_REQUEST_CLEAR_FEATURE:
{
DPRINT1("USB_REQUEST_CLEAR_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
Urb->UrbControlVendorClassRequest.Value);
switch (Urb->UrbControlVendorClassRequest.Value)
{
case C_PORT_CONNECTION:
DPRINT1("C_PORT_CONNECTION\n");
DPRINT("C_PORT_CONNECTION\n");
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_CONNECT;
break;
case C_PORT_RESET:
DPRINT1("C_PORT_RESET\n");
DPRINT("C_PORT_RESET\n");
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_RESET;
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus |= USB_PORT_STATUS_ENABLE;
break;
default:
DPRINT1("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
break;
}
CompletePendingURBRequest(PdoDeviceExtension);
break;
}
case USB_REQUEST_SET_FEATURE:
@@ -495,18 +514,10 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
{
case PORT_RESET:
{
//PWORKITEMDATA WorkItemData;
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus |= USB_PORT_STATUS_ENABLE;
DPRINT("Port Reset %d\n", Urb->UrbControlVendorClassRequest.Index-1);
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange |= USB_PORT_STATUS_RESET;
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus &= ~USB_PORT_STATUS_ENABLE;
ResetPort(&FdoDeviceExtension->hcd, Urb->UrbControlVendorClassRequest.Index-1);
//WorkItemData = ExAllocatePool(NonPagedPool, sizeof(WORKITEMDATA));
//WorkItemData->Context = PdoDeviceExtension;
//ExInitializeWorkItem(&WorkItemData->WorkItem, (PWORKER_THREAD_ROUTINE)WorkerThread, (PVOID) WorkItemData)
//ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue);
//IoMarkIrpPending(Irp);
//Status = STATUS_PENDING;
break;
}
case PORT_ENABLE:
@@ -525,7 +536,10 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
break;
}
}
CompletePendingURBRequest(PdoDeviceExtension);
if (!(PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus & 0x8000))
CompletePendingURBRequest(PdoDeviceExtension);
break;
}
case USB_REQUEST_SET_ADDRESS:
@@ -577,6 +591,23 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
}
break;
}
case URB_FUNCTION_CONTROL_TRANSFER:
{
DPRINT1("URB_FUNCTION_CONTROL_TRANSFER\n");
DPRINT1("PipeHandle %x\n", Urb->UrbControlTransfer.PipeHandle);
DPRINT1("TransferFlags %x\n", Urb->UrbControlTransfer.TransferFlags);
DPRINT1("TransferLength %x\n", Urb->UrbControlTransfer.TransferBufferLength);
DPRINT1("TransferBuffer %x\n", Urb->UrbControlTransfer.TransferBuffer);
DPRINT1("TransferMDL %x\n", Urb->UrbControlTransfer.TransferBufferMDL);
DPRINT1("SetupPacket %x\n", Urb->UrbControlTransfer.SetupPacket);
ASSERT(FALSE);
break;
}
case URB_FUNCTION_CLASS_INTERFACE:
{
DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
break;
}
default:
{
DPRINT1("Unhandled URB %x\n", Urb->UrbHeader.Function);
@@ -586,14 +617,6 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Information;
if (Urb->UrbHeader.Status == USBD_STATUS_SUCCESS)
{
/* Fake a successful Control Transfer */
Urb->UrbHeader.Function = 0x08;
Urb->UrbHeader.UsbdFlags = 0;
}
return Status;
}
@@ -606,23 +629,25 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
while (!IsListEmpty(&DeviceExtension->IrpQueue))
if (IsListEmpty(&DeviceExtension->IrpQueue))
{
NextIrp = RemoveHeadList(&DeviceExtension->IrpQueue);
Irp = CONTAINING_RECORD(NextIrp, IRP, Tail.Overlay.ListEntry);
if (!Irp)
{
DPRINT1("No IRP\n");
break;
}
IoSetCancelRoutine(Irp, NULL);
DPRINT1("There should have been one SCE request pending\n");
KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
HandleUrbRequest(DeviceExtension, Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
return;
}
NextIrp = RemoveHeadList(&DeviceExtension->IrpQueue);
Irp = CONTAINING_RECORD(NextIrp, IRP, Tail.Overlay.ListEntry);
if (!Irp)
{
DPRINT1("No Irp\n");
return;
}
IoSetCancelRoutine(Irp, NULL);
KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
HandleUrbRequest(DeviceExtension, Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}