[USBOHCI]

- Implement reseting pipe and clear pipe stall

svn path=/branches/usb-bringup-trunk/; revision=55394
This commit is contained in:
Johannes Anderwald 2012-02-03 14:47:18 +00:00
parent 690f71f605
commit c2d96ce7ff
6 changed files with 341 additions and 0 deletions

View file

@ -229,6 +229,7 @@ typedef struct _OHCI_ENDPOINT_DESCRIPTOR
#define OHCI_ENDPOINT_SKIP 0x00004000
#define OHCI_ENDPOINT_SET_DEVICE_ADDRESS(s) (s)
#define OHCI_ENDPOINT_GET_DEVICE_ADDRESS(s) ((s) & 0xFF)
#define OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(s) (((s) >> 7) & 0xf)
#define OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(s) ((s) << 7)
#define OHCI_ENDPOINT_GET_MAX_PACKET_SIZE(s) (((s) >> 16) & 0x07ff)

View file

@ -70,6 +70,9 @@ public:
NTSTATUS HandleClassEndpoint(IN OUT PIRP Irp, PURB Urb);
NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
NTSTATUS HandleIsochronousTransfer(IN OUT PIRP Irp, PURB Urb);
NTSTATUS HandleClearStall(IN OUT PIRP Irp, PURB Urb);
NTSTATUS HandleSyncResetAndClearStall(IN OUT PIRP Irp, PURB Urb);
NTSTATUS HandleAbortPipe(IN OUT PIRP Irp, PURB Urb);
friend VOID StatusChangeEndpointCallBack(PVOID Context);
@ -1692,6 +1695,187 @@ CHubController::HandleClassEndpoint(
return Status;
}
NTSTATUS
CHubController::HandleSyncResetAndClearStall(
IN OUT PIRP Irp,
IN OUT PURB Urb)
{
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
NTSTATUS Status = STATUS_SUCCESS;
PUSBDEVICE UsbDevice;
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
ULONG Type;
//
// sanity check
//
PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
//
// check if this is a valid usb device handle
//
if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
{
DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
//
// invalid device handle
//
return STATUS_DEVICE_NOT_CONNECTED;
}
//
// get endpoint descriptor
//
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
//
// get type
//
Type = (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS)
{
//
// clear stall
//
Status = HandleClearStall(Irp, Urb);
}
DPRINT1("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status);
//
// FIXME reset data toggle
//
//
// done
//
return Status;
}
NTSTATUS
CHubController::HandleAbortPipe(
IN OUT PIRP Irp,
IN OUT PURB Urb)
{
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
NTSTATUS Status;
PUSBDEVICE UsbDevice;
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
//
// sanity check
//
PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
//
// check if this is a valid usb device handle
//
if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
{
DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
//
// invalid device handle
//
return STATUS_DEVICE_NOT_CONNECTED;
}
//
// get endpoint descriptor
//
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
//
// get device
//
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
//
// issue request
//
Status = UsbDevice->AbortPipe(EndpointDescriptor);
DPRINT1("URB_FUNCTION_ABORT_PIPE Status %x\n", Status);
//
// done
//
return Status;
}
//-----------------------------------------------------------------------------------------
NTSTATUS
CHubController::HandleClearStall(
IN OUT PIRP Irp,
IN OUT PURB Urb)
{
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
NTSTATUS Status;
PUSBDEVICE UsbDevice;
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
//
// sanity check
//
PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
//
// check if this is a valid usb device handle
//
if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
{
DPRINT1("HandleClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
//
// invalid device handle
//
return STATUS_DEVICE_NOT_CONNECTED;
}
//
// get endpoint descriptor
//
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
//
// get device
//
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
DPRINT1("URB_FUNCTION_SYNC_CLEAR_STALL\n");
//
// initialize setup packet
//
CtrlSetup.bmRequestType.B = 0x02;
CtrlSetup.bRequest = USB_REQUEST_CLEAR_FEATURE;
CtrlSetup.wValue.W = USB_FEATURE_ENDPOINT_STALL;
CtrlSetup.wIndex.W = EndpointDescriptor->bEndpointAddress;
CtrlSetup.wLength = 0;
CtrlSetup.wValue.W = 0;
//
// issue request
//
Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 0, 0);
DPRINT1("URB_FUNCTION_CLEAR_STALL Status %x\n", Status);
//
// done
//
return Status;
}
//-----------------------------------------------------------------------------------------
NTSTATUS
CHubController::HandleClassInterface(
@ -1813,6 +1997,16 @@ CHubController::HandleDeviceControl(
switch (Urb->UrbHeader.Function)
{
case URB_FUNCTION_SYNC_RESET_PIPE:
case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
Status = HandleSyncResetAndClearStall(Irp, Urb);
break;
case URB_FUNCTION_ABORT_PIPE:
Status = HandleAbortPipe(Irp, Urb);
break;
case URB_FUNCTION_SYNC_CLEAR_STALL:
Status = HandleClearStall(Irp, Urb);
break;
case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
Status = HandleGetDescriptorFromInterface(Irp, Urb);
break;

View file

@ -556,6 +556,14 @@ DECLARE_INTERFACE_(IUSBQueue, IUnknown)
virtual VOID TransferDescriptorCompletionCallback(ULONG TransferDescriptorLogicalAddress) = 0;
//-----------------------------------------------------------------------------------------
//
// AbortDevicePipe
//
// Description: aborts all pending requsts of an device
virtual NTSTATUS AbortDevicePipe(UCHAR DeviceAddress, IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) = 0;
};
typedef IUSBQueue *PUSBQUEUE;
@ -809,6 +817,16 @@ DECLARE_INTERFACE_(IUSBDevice, IUnknown)
virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle,
IN OUT PUSBD_INTERFACE_INFORMATION Interface) = 0;
//-----------------------------------------------------------------------------------------
//
// AbortPipe
//
// Description: aborts all pending requsts
virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) = 0;
};
typedef IUSBDevice *PUSBDEVICE;

View file

@ -52,6 +52,7 @@ public:
virtual NTSTATUS SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, OUT ULONG BufferLength, OUT PVOID Buffer);
virtual NTSTATUS SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, IN PUSBD_INTERFACE_INFORMATION Interface, OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle);
virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, IN OUT PUSBD_INTERFACE_INFORMATION Interface);
virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor);
// local function
virtual NTSTATUS CommitIrp(PIRP Irp);
@ -1174,6 +1175,22 @@ CUSBDevice::SelectInterface(
return Status;
}
NTSTATUS
CUSBDevice::AbortPipe(
IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor)
{
//
// let it handle usb queue
//
ASSERT(m_Queue);
ASSERT(m_DeviceAddress);
//
// done
//
return m_Queue->AbortDevicePipe(m_DeviceAddress, EndpointDescriptor);
}
//----------------------------------------------------------------------------------------
NTSTATUS
CreateUSBDevice(

View file

@ -40,6 +40,7 @@ public:
virtual NTSTATUS CancelRequests();
virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest);
virtual VOID TransferDescriptorCompletionCallback(ULONG TransferDescriptorLogicalAddress);
virtual NTSTATUS AbortDevicePipe(UCHAR DeviceAddress, IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor);
// local functions
BOOLEAN IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress);
@ -740,6 +741,115 @@ CUSBQueue::FindInterruptEndpointDescriptor(
return m_InterruptEndpoints[Index];
}
NTSTATUS
CUSBQueue::AbortDevicePipe(
IN UCHAR DeviceAddress,
IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor)
{
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor, CurrentDescriptor, PreviousDescriptor, TempDescriptor;
ULONG Type;
POHCI_GENERAL_TD TransferDescriptor;
//
// get type
//
Type = (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
//
// check type
//
if (Type == USB_ENDPOINT_TYPE_BULK)
{
//
// get head descriptor
//
HeadDescriptor = m_BulkHeadEndpointDescriptor;
}
else if (Type == USB_ENDPOINT_TYPE_CONTROL)
{
//
// get head descriptor
//
HeadDescriptor = m_ControlHeadEndpointDescriptor;
}
else if (Type == USB_ENDPOINT_TYPE_INTERRUPT)
{
//
// get head descriptor
//
HeadDescriptor = FindInterruptEndpointDescriptor(EndpointDescriptor->bInterval);
ASSERT(HeadDescriptor);
}
else if (Type == USB_ENDPOINT_TYPE_ISOCHRONOUS)
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
//
// FIXME should disable list processing
//
//
// now remove all endpoints
//
ASSERT(HeadDescriptor);
CurrentDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)HeadDescriptor->NextDescriptor;
PreviousDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)HeadDescriptor;
while(CurrentDescriptor)
{
if ((CurrentDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HEAD_MASK) == CurrentDescriptor->TailPhysicalDescriptor || (CurrentDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HALTED))
{
//
// cleanup endpoint
//
TempDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentDescriptor->NextDescriptor;
CleanupEndpointDescriptor(CurrentDescriptor, PreviousDescriptor);
//
// use next descriptor
//
CurrentDescriptor = TempDescriptor;
}
if (!CurrentDescriptor)
break;
if (CurrentDescriptor->HeadPhysicalDescriptor)
{
TransferDescriptor = (POHCI_GENERAL_TD)CurrentDescriptor->HeadLogicalDescriptor;
ASSERT(TransferDescriptor);
if ((OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(TransferDescriptor->Flags) == (EndpointDescriptor->bEndpointAddress & 0xF)) &&
(OHCI_ENDPOINT_GET_DEVICE_ADDRESS(TransferDescriptor->Flags) == DeviceAddress))
{
//
// cleanup endpoint
//
TempDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentDescriptor->NextDescriptor;
CleanupEndpointDescriptor(CurrentDescriptor, PreviousDescriptor);
//
// use next descriptor
//
CurrentDescriptor = TempDescriptor;
}
}
if (!CurrentDescriptor)
break;
PreviousDescriptor = CurrentDescriptor;
CurrentDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentDescriptor->NextDescriptor;
}
//
// done
//
return STATUS_SUCCESS;
}
NTSTATUS
CreateUSBQueue(
PUSBQUEUE *OutUsbQueue)

View file

@ -7,6 +7,7 @@
#include <hubbusif.h>
#include <usbbusif.h>
#include <usbioctl.h>
#include <usb100.h>
extern
"C"