mirror of
https://github.com/reactos/reactos.git
synced 2024-10-05 00:43:21 +00:00
[USBOHCI]
- Implement reseting pipe and clear pipe stall svn path=/branches/usb-bringup-trunk/; revision=55394
This commit is contained in:
parent
690f71f605
commit
c2d96ce7ff
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <hubbusif.h>
|
||||
#include <usbbusif.h>
|
||||
#include <usbioctl.h>
|
||||
#include <usb100.h>
|
||||
|
||||
extern
|
||||
"C"
|
||||
|
|
Loading…
Reference in a new issue