Author: janderwald
Date: Tue Apr 19 01:21:10 2011
New Revision: 51396
URL:
http://svn.reactos.org/svn/reactos?rev=51396&view=rev
Log:
[USBEHCI_NEW]
- Null terminate buffer from IOCTL_USB_GET_ROOT_HUB_NAME, fixes usbview problems
- Implement URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER, IUSBHardware needs more work
- Silence debug traces
- Start implementing IUSBRequest interfaces
- Complete unhandled major irp with status success
Added:
branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp (with props)
Modified:
branches/usb-bringup/drivers/usb/usbehci_new/CMakeLists.txt
branches/usb-bringup/drivers/usb/usbehci_new/hcd_controller.cpp
branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp
branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h
branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp
branches/usb-bringup/drivers/usb/usbehci_new/usbehci.cpp
Modified: branches/usb-bringup/drivers/usb/usbehci_new/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/CMakeLists.txt [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/CMakeLists.txt [iso-8859-1] Tue Apr 19
01:21:10 2011
@@ -7,6 +7,7 @@
add_library(usbehci SHARED
usbehci.cpp
usb_device.cpp
+ usb_request.cpp
usb_queue.cpp
hcd_controller.cpp
hardware.cpp
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hcd_controller.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/hcd_controller.cpp [iso-8859-1]
(original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/hcd_controller.cpp [iso-8859-1] Tue Apr
19 01:21:10 2011
@@ -327,8 +327,11 @@
if (NT_SUCCESS(Status))
{
//
- // informal debug print
- //
+ // null terminate it
+ //
+ PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength -
sizeof(ULONG) - sizeof(WCHAR) >= ResultLength);
+
+ DriverKey->DriverKeyName[ResultLength / sizeof(WCHAR)] =
L'\0';
DPRINT1("Result %S\n", DriverKey->DriverKeyName);
}
@@ -552,7 +555,6 @@
}
default:
{
- DPRINT1("CHCDController::HandlePnp Dispatch to lower device object
%lx\n", IoStack->MinorFunction);
//
// forward irp to next device object
//
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp [iso-8859-1]
(original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp [iso-8859-1] Tue Apr
19 01:21:10 2011
@@ -61,6 +61,8 @@
NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb);
+ NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
+
// constructor / destructor
CHubController(IUnknown *OuterUnknown){}
@@ -154,6 +156,20 @@
0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
0xFF /* bInterval; (255ms -- usb 2.0 spec) */
};
+
+//
+// flags for handling USB_REQUEST_SET_FEATURE / USB_REQUEST_GET_FEATURE
+//
+#define PORT_ENABLE 1
+#define PORT_SUSPEND 2
+#define PORT_OVER_CURRENT 3
+#define PORT_RESET 4
+#define PORT_POWER 8
+#define C_PORT_CONNECTION 16
+#define C_PORT_ENABLE 17
+#define C_PORT_SUSPEND 18
+#define C_PORT_OVER_CURRENT 19
+#define C_PORT_RESET 20
//----------------------------------------------------------------------------------------
NTSTATUS
@@ -653,7 +669,9 @@
}
default:
{
- DPRINT1("CHubController::HandlePnp Unhandeled %x\n",
IoStack->MinorFunction);
+ //
+ // ignore request with default status
+ //
Status = Irp->IoStatus.Status;
break;
}
@@ -682,6 +700,15 @@
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleBulkOrInterruptTransfer(
+ IN OUT PIRP Irp,
+ PURB Urb)
+{
+ UNIMPLEMENTED
+ return STATUS_NOT_IMPLEMENTED;
+}
//-----------------------------------------------------------------------------------------
NTSTATUS
@@ -689,11 +716,143 @@
IN OUT PIRP Irp,
PURB Urb)
{
- DPRINT1("CHubController::HandleClassOther> Request %x Value %x not
implemented\n", Urb->UrbControlVendorClassRequest.Request,
Urb->UrbControlVendorClassRequest.Value);
-
- //
- // FIXME implement me
- //
+ NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+ USHORT PortStatus = 0, PortChange = 0;
+ PUSHORT Buffer;
+ ULONG NumPort;
+ ULONG PortId;
+
+ //DPRINT1("CHubController::HandleClassOther> Request %x Value %x not
implemented\n", Urb->UrbControlVendorClassRequest.Request,
Urb->UrbControlVendorClassRequest.Value);
+
+ //
+ // get number of ports available
+ //
+ Status = m_Hardware->GetDeviceDetails(NULL, NULL, &NumPort, NULL);
+ PC_ASSERT(Status == STATUS_SUCCESS);
+
+ //
+ // sanity check
+ //
+ PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < NumPort);
+
+ //
+ // port range reported start from 1 -n
+ // convert back port id so it matches the hardware
+ //
+ PortId = Urb->UrbControlVendorClassRequest.Index - 1;
+
+ //
+ // check request code
+ //
+ switch(Urb->UrbControlVendorClassRequest.Request)
+ {
+ case USB_REQUEST_GET_STATUS:
+ {
+ //
+ // sanity check
+ //
+ PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength ==
sizeof(USHORT) * 2);
+ PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
+
+ //
+ // get port status
+ //
+ //Status = m_Hardware->GetPortStatus(PortId, &PortStatus,
&PortChange);
+
+ Status = STATUS_SUCCESS;
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // request contains buffer of 2 ushort which are used from submitting
port status and port change status
+ //
+ Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer;
+
+ //
+ // store status, then port change
+ //
+ *Buffer = PortStatus;
+ Buffer++;
+ *Buffer = PortChange;
+ }
+
+ //
+ // done
+ //
+ break;
+ }
+ case USB_REQUEST_CLEAR_FEATURE:
+ {
+ switch (Urb->UrbControlVendorClassRequest.Value)
+ {
+ case C_PORT_CONNECTION:
+ //Status = m_Hardware->ClearPortStatus(PortId,
C_PORT_CONNECTION);
+ break;
+ case C_PORT_RESET:
+ //Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
+ break;
+ default:
+ DPRINT("Unknown Value for Clear Feature %x \n",
Urb->UrbControlVendorClassRequest.Value);
+ PC_ASSERT(FALSE);
+ break;
+ }
+
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case USB_REQUEST_SET_FEATURE:
+ {
+ //
+ // request set feature
+ //
+ switch(Urb->UrbControlVendorClassRequest.Value)
+ {
+ case PORT_ENABLE:
+ {
+ //
+ // port enable is a no-op for EHCI
+ //
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ case PORT_SUSPEND:
+ {
+ //
+ // set suspend port feature
+ //
+ Status = STATUS_SUCCESS; //m_Hardware->SetPortFeature(PortId,
PORT_SUSPEND);
+ break;
+ }
+ case PORT_POWER:
+ {
+ //
+ // set power feature on port
+ //
+ Status = STATUS_SUCCESS; //m_Hardware->SetPortFeature(PortId,
PORT_POWER);
+ break;
+ }
+
+ case PORT_RESET:
+ {
+ //
+ // reset port feature
+ //
+ Status = m_Hardware->ResetPort(PortId);
+ PC_ASSERT(Status == STATUS_SUCCESS);
+ break;
+ }
+ default:
+ DPRINT1("Unsupported request id %x\n",
Urb->UrbControlVendorClassRequest.Value);
+ PC_ASSERT(FALSE);
+ }
+ break;
+ }
+ default:
+ DPRINT1("CHubController::HandleClassOther Unknown request code
%x\n", Urb->UrbControlVendorClassRequest.Request);
+ PC_ASSERT(0);
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ }
+
return STATUS_SUCCESS;
}
@@ -862,7 +1021,6 @@
if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
{
- DPRINT1("Root Hub descriptor\n");
//
// copy root hub device descriptor
//
@@ -960,13 +1118,6 @@
//
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- DPRINT1("HandleDeviceControl>Type: FDO %u IoCtl %x InputBufferLength %lu
OutputBufferLength %lu\n",
- DeviceExtension->IsFDO,
- IoStack->Parameters.DeviceIoControl.IoControlCode,
- IoStack->Parameters.DeviceIoControl.InputBufferLength,
- IoStack->Parameters.DeviceIoControl.OutputBufferLength);
-
//
// determine which request should be performed
//
@@ -979,8 +1130,6 @@
//
Urb = (PURB)IoStack->Parameters.Others.Argument1;
PC_ASSERT(Urb);
-
- DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x Length %lu Status %x
Handle %p Flags %x UNIMPLEMENTED\n", Urb->UrbHeader.Function,
Urb->UrbHeader.Length, Urb->UrbHeader.Status, Urb->UrbHeader.UsbdDeviceHandle,
Urb->UrbHeader.UsbdFlags);
switch (Urb->UrbHeader.Function)
{
@@ -999,6 +1148,12 @@
case URB_FUNCTION_CLASS_OTHER:
Status = HandleClassOther(Irp, Urb);
break;
+ case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
+ Status = HandleBulkOrInterruptTransfer(Irp, Urb);
+ break;
+ default:
+ DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT
IMPLEMENTED\n", Urb->UrbHeader.Function);
+ break;
}
//
// request completed
@@ -1007,7 +1162,7 @@
}
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
{
- DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
+ DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
if (IoStack->Parameters.Others.Argument1)
{
@@ -1032,7 +1187,7 @@
}
case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
{
- DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
+ DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
//
// this is the first request send, it delivers the PDO to the caller
@@ -1061,7 +1216,7 @@
}
case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
{
- DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
+ DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
//
// after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
@@ -1080,6 +1235,14 @@
//
Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(ULONG);
+ break;
+ }
+ default:
+ {
+ DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu
OutputBufferLength %lu NOT IMPLEMENTED\n",
+ IoStack->Parameters.DeviceIoControl.IoControlCode,
+ IoStack->Parameters.DeviceIoControl.InputBufferLength,
+ IoStack->Parameters.DeviceIoControl.OutputBufferLength);
break;
}
}
@@ -1921,7 +2084,37 @@
ULONG ControllerInformationBufferLength,
PULONG LengthReturned)
{
- UNIMPLEMENTED
+ PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
+
+ DPRINT1("USBHI_GetControllerInformation\n");
+
+ //
+ // sanity checks
+ //
+ PC_ASSERT(ControllerInformationBuffer);
+ PC_ASSERT(ControllerInformationBufferLength >=
sizeof(USB_CONTROLLER_INFORMATION_0));
+
+ //
+ // get controller info buffer
+ //
+ ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
+
+ //
+ // FIXME only version 0 is supported for now
+ //
+ PC_ASSERT(ControllerInfo->InformationLevel == 0);
+
+ //
+ // fill in information
+ //
+ ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
+ ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
+ ControllerInfo->IsHighSpeedController = TRUE;
+
+ //
+ // set length returned
+ //
+ *LengthReturned = ControllerInfo->ActualLength;
return STATUS_NOT_IMPLEMENTED;
}
Modified: branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] Tue Apr 19
01:21:10 2011
@@ -312,6 +312,8 @@
// CancelCallback routine is invoked.
//
+struct _QUEUE_HEAD;
+
DECLARE_INTERFACE_(IUSBRequest, IUnknown)
{
DEFINE_ABSTRACT_UNKNOWN()
@@ -324,44 +326,39 @@
// If there is a TransferBuffer, the TransferBufferLength contains the length of the
buffer
- virtual NTSTATUS InitializeWithSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET
SetupPacket,
- IN ULONG TransferBufferLength,
- IN PVOID TransferBuffer) = 0;
-
-//
-//TODO: find required parameters for different packet types
-//
-
-
-//-----------------------------------------------------------------------------------------
-//
-// SetEndPoint
-//
-// Description: sets the endpoint of the request.
-
- virtual NTSTATUS SetEndPoint(PUSB_ENDPOINT_DESCRIPTOR EndPoint);
-
-//-----------------------------------------------------------------------------------------
-//
-// SetCompletionDetails
-//
-// Description: sets up how the request should be completed
-// If an irp is passed, then it is completed with status code of the
-// CompletionCallback or CancelCallback
-// If an event is passed, then the event is signaled
-
- virtual NTSTATUS SetCompletionDetails(IN OPTIONAL PIRP Irp,
- IN OPTIONAL PKEVENT Event) = 0;
+ virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager,
+ IN PUSB_DEFAULT_PIPE_SETUP_PACKET
SetupPacket,
+ IN OUT ULONG TransferBufferLength,
+ IN OUT PMDL TransferBuffer) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// InitializeWithIrp
+//
+// Description: initializes the request with an IRP
+// The irp contains an URB block which contains all necessary information
+
+ virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager,
+ IN OUT PIRP Irp);
+
+//-----------------------------------------------------------------------------------------
+//
+// SetCompletionEvent
+//
+// Description: sets up completion event which is signaled when the
+// request is completed or cancelled
+
+ virtual NTSTATUS SetCompletionEvent(IN PKEVENT Event) = 0;
//-----------------------------------------------------------------------------------------
//
// CompletionCallback
//
-// Description: called when request has been completed. It is called when
+// Description: called when request has been completed. It is called when
// IUSBQueue completes the request
virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode,
- IN ULONG UrbStatusCode) = 0;
+ IN ULONG UrbStatusCode) = 0;
//-----------------------------------------------------------------------------------------
//
@@ -370,6 +367,31 @@
// Description: called when request is cancelled. Called by IUSBQueue
virtual VOID CancelCallback(IN NTSTATUS NtStatusCode) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetQueueHead
+//
+// Description: returns an initialized queue head with contains the all transfer
descriptors
+
+ virtual NTSTATUS GetQueueHead(struct _QUEUE_HEAD ** OutHead) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// IsRequestComplete
+//
+// Description: returns true when the request has been completed
+// Should be called after the CompletionCallback has been invoked
+
+ virtual BOOLEAN IsRequestComplete() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetTransferType
+//
+// Description: returns the type of the request: control, bulk, iso, interrupt
+
+ virtual ULONG GetTransferType() = 0;
};
Modified: branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp [iso-8859-1] Tue Apr 19
01:21:10 2011
@@ -68,6 +68,7 @@
USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
ULONG m_PortStatus;
PUSBQUEUE m_Queue;
+ PDMAMEMORYMANAGER m_DmaManager;
};
//----------------------------------------------------------------------------------------
@@ -125,6 +126,21 @@
}
//
+ // FIXME: get dma manager
+ //
+ //Status = m_Device->GetDMA(&m_DmaManager);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get usb queue
+ //
+ DPRINT1("CUSBDevice::Initialize GetUsbQueue failed with %x\n",
Status);
+ return Status;
+ }
+
+
+
+ //
// zero descriptor
//
RtlZeroMemory(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
@@ -293,7 +309,7 @@
// initialize request
//
CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
- CtrlSetup.wValue.W = DeviceAddress;
+ CtrlSetup.wValue.W = (USHORT)DeviceAddress;
//
// set device address
@@ -386,6 +402,8 @@
PUSBREQUEST Request;
KEVENT Event;
BOOLEAN Wait = FALSE;
+ PMDL Mdl = 0;
+
if (!m_Queue)
{
@@ -409,10 +427,12 @@
return Status;
}
+ /* FIXME build MDL */
+
//
// initialize request
//
- Status = Request->InitializeWithSetupPacket(Packet, BufferLength, Buffer);
+ Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, BufferLength,
Mdl);
if (!NT_SUCCESS(Status))
{
//
@@ -439,7 +459,7 @@
//
// set completion details
//
- Status = Request->SetCompletionDetails(Irp, pEvent);
+ Status = Request->SetCompletionEvent(pEvent);
if (!NT_SUCCESS(Status))
{
//
Added: branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp (added)
+++ branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp [iso-8859-1] Tue Apr 19
01:21:10 2011
@@ -1,0 +1,801 @@
+/*
+ * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: drivers/usb/usbehci/usb_request.cpp
+ * PURPOSE: USB EHCI device driver.
+ * PROGRAMMERS:
+ * Michael Martin (michael.martin(a)reactos.org)
+ * Johannes Anderwald (johannes.anderwald(a)reactos.org)
+ */
+
+#define INITGUID
+
+#include "usbehci.h"
+#include "hardware.h"
+
+class CUSBRequest : public IUSBRequest
+{
+public:
+ STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
+
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ InterlockedIncrement(&m_Ref);
+ return m_Ref;
+ }
+ STDMETHODIMP_(ULONG) Release()
+ {
+ InterlockedDecrement(&m_Ref);
+
+ if (!m_Ref)
+ {
+ delete this;
+ return 0;
+ }
+ return m_Ref;
+ }
+
+ // IUSBRequest interface functions
+ virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN
PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN OUT ULONG TransferBufferLength, IN OUT PMDL
TransferBuffer);
+ virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP
Irp);
+ virtual NTSTATUS SetCompletionEvent(IN PKEVENT Event);
+ virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode, IN ULONG UrbStatusCode);
+ virtual VOID CancelCallback(IN NTSTATUS NtStatusCode);
+ virtual NTSTATUS GetQueueHead(struct _QUEUE_HEAD ** OutHead);
+ virtual BOOLEAN IsRequestComplete();
+ virtual ULONG GetTransferType();
+
+ // local functions
+ ULONG InternalGetTransferType();
+ NTSTATUS BuildControlTransferQueueHead(PQUEUE_HEAD * OutHead);
+ NTSTATUS BuildBulkTransferQueueHead(PQUEUE_HEAD * OutHead);
+ NTSTATUS CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor);
+ NTSTATUS CreateQueueHead(PQUEUE_HEAD *OutQueueHead);
+ ULONG GetDeviceAddress();
+ NTSTATUS BuildSetupPacket();
+
+ // constructor / destructor
+ CUSBRequest(IUnknown *OuterUnknown){}
+ virtual ~CUSBRequest(){}
+
+protected:
+ LONG m_Ref;
+ PDMAMEMORYMANAGER m_DmaManager;
+ PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket;
+ ULONG m_TransferBufferLength;
+ PMDL m_TransferBufferMDL;
+ PIRP m_Irp;
+ PKEVENT m_CompletionEvent;
+
+ PQUEUE_HEAD m_QueueHead;
+ PQUEUE_TRANSFER_DESCRIPTOR m_TransferDescriptors[3];
+ PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket;
+};
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+STDMETHODCALLTYPE
+CUSBRequest::QueryInterface(
+ IN REFIID refiid,
+ OUT PVOID* Output)
+{
+ return STATUS_UNSUCCESSFUL;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::InitializeWithSetupPacket(
+ IN PDMAMEMORYMANAGER DmaManager,
+ IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
+ IN OUT ULONG TransferBufferLength,
+ IN OUT PMDL TransferBuffer)
+{
+ //
+ // sanity checks
+ //
+ PC_ASSERT(DmaManager);
+ PC_ASSERT(SetupPacket);
+
+ //
+ // initialize packet
+ //
+ m_DmaManager = DmaManager;
+ m_SetupPacket = SetupPacket;
+ m_TransferBufferLength = TransferBufferLength;
+ m_TransferBufferMDL = TransferBuffer;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::InitializeWithIrp(
+ IN PDMAMEMORYMANAGER DmaManager,
+ IN OUT PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PURB Urb;
+ NTSTATUS Status;
+
+ //
+ // sanity checks
+ //
+ PC_ASSERT(DmaManager);
+ PC_ASSERT(Irp);
+
+ //
+ // get current irp stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // sanity check
+ //
+ PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
+ PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_INTERNAL_USB_SUBMIT_URB);
+ PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
+
+ //
+ // get urb
+ //
+ Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+ //
+ // store irp
+ //
+ m_Irp = Irp;
+
+ //
+ // check function type
+ //
+ switch (Urb->UrbHeader.Function)
+ {
+ //
+ // luckily those request have the same structure layout
+ //
+ case URB_FUNCTION_CLASS_INTERFACE:
+ case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+ case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
+ {
+ //
+ // bulk / interrupt transfer
+ //
+ if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
+ {
+ //
+ // it must have an MDL
+ //
+ PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
+
+ //
+ // get mdl buffer
+ //
+ m_TransferBufferMDL =
Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
+ m_TransferBufferLength =
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
+ }
+ break;
+ }
+ default:
+ DPRINT1("URB Function: not supported %x\n",
Urb->UrbHeader.Function);
+ PC_ASSERT(FALSE);
+ }
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::SetCompletionEvent(
+ IN PKEVENT Event)
+{
+ if (m_QueueHead)
+ {
+ //
+ // WTF? operation is already in progress
+ //
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // store completion event
+ //
+ m_CompletionEvent = Event;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+//----------------------------------------------------------------------------------------
+VOID
+CUSBRequest::CompletionCallback(
+ IN NTSTATUS NtStatusCode,
+ IN ULONG UrbStatusCode)
+{
+ PIO_STACK_LOCATION IoStack;
+ PURB Urb;
+
+ if (m_Irp)
+ {
+ //
+ // set irp completion status
+ //
+ m_Irp->IoStatus.Status = NtStatusCode;
+
+ //
+ // get current irp stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
+ //
+ // get urb
+ //
+ Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+ //
+ // store urb status
+ //
+ Urb->UrbHeader.Status = UrbStatusCode;
+
+ //
+ // check if the request was successfull
+ //
+ if (!NT_SUCCESS(NtStatusCode))
+ {
+ //
+ // set returned length to zero in case of error
+ //
+ Urb->UrbHeader.Length = 0;
+ }
+
+ //
+ // FIXME: check if the transfer was split
+ // if yes dont complete irp yet
+ //
+ IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
+ }
+
+ if (m_CompletionEvent)
+ {
+ //
+ // FIXME: make sure the request was not split
+ //
+ KeSetEvent(m_CompletionEvent, 0, FALSE);
+ }
+}
+//----------------------------------------------------------------------------------------
+VOID
+CUSBRequest::CancelCallback(
+ IN NTSTATUS NtStatusCode)
+{
+ PIO_STACK_LOCATION IoStack;
+ PURB Urb;
+
+ if (m_Irp)
+ {
+ //
+ // set irp completion status
+ //
+ m_Irp->IoStatus.Status = NtStatusCode;
+
+ //
+ // get current irp stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
+ //
+ // get urb
+ //
+ Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+ //
+ // store urb status
+ //
+ Urb->UrbHeader.Status = USBD_STATUS_CANCELED;
+ Urb->UrbHeader.Length = 0;
+
+ //
+ // FIXME: check if the transfer was split
+ // if yes dont complete irp yet
+ //
+ IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
+ }
+
+ if (m_CompletionEvent)
+ {
+ //
+ // FIXME: make sure the request was not split
+ //
+ KeSetEvent(m_CompletionEvent, 0, FALSE);
+ }
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::GetQueueHead(
+ struct _QUEUE_HEAD ** OutHead)
+{
+ ULONG TransferType;
+ NTSTATUS Status;
+
+ //
+ // first get transfer type
+ //
+ TransferType = InternalGetTransferType();
+
+ //
+ // build request depending on type
+ //
+ switch(TransferType)
+ {
+ case USB_ENDPOINT_TYPE_CONTROL:
+ Status = BuildControlTransferQueueHead(OutHead);
+ break;
+ case USB_ENDPOINT_TYPE_BULK:
+ Status = BuildBulkTransferQueueHead(OutHead);
+ break;
+ case USB_ENDPOINT_TYPE_INTERRUPT:
+ DPRINT1("USB_ENDPOINT_TYPE_INTERRUPT not implemented\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ case USB_ENDPOINT_TYPE_ISOCHRONOUS:
+ DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // store queue head
+ //
+ m_QueueHead = *OutHead;
+ }
+
+ //
+ // done
+ //
+ return Status;
+}
+
+//----------------------------------------------------------------------------------------
+BOOLEAN
+CUSBRequest::IsRequestComplete()
+{
+ //
+ // FIXME: check if request was split
+ //
+ return TRUE;
+}
+//----------------------------------------------------------------------------------------
+ULONG
+CUSBRequest::GetTransferType()
+{
+ //
+ // call internal implementation
+ //
+ return InternalGetTransferType();
+}
+
+//----------------------------------------------------------------------------------------
+ULONG
+CUSBRequest::InternalGetTransferType()
+{
+ PIO_STACK_LOCATION IoStack;
+ PURB Urb;
+ PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+ ULONG TransferType;
+
+ //
+ // check if an irp is provided
+ //
+ if (m_Irp)
+ {
+ //
+ // get stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
+ //
+ // get urb
+ //
+ Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+ //
+ // check if there is a handle
+ //
+ if (Urb->UrbBulkOrInterruptTransfer.PipeHandle)
+ {
+ //
+ // cast to end point
+ //
+ EndpointDescriptor =
(PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
+
+ //
+ // end point is defined in the low byte of bmAttributes
+ //
+ TransferType = (EndpointDescriptor->bmAttributes &
USB_ENDPOINT_TYPE_MASK);
+ }
+ else
+ {
+ //
+ // no pipe handle, assume it is a control transfer
+ //
+ TransferType = USB_ENDPOINT_TYPE_CONTROL;
+ }
+ }
+ else
+ {
+ //
+ // initialized with setup packet, must be a control transfer
+ //
+ TransferType = USB_ENDPOINT_TYPE_CONTROL;
+ }
+
+ //
+ // done
+ //
+ return TransferType;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::BuildControlTransferQueueHead(
+ PQUEUE_HEAD * OutHead)
+{
+ NTSTATUS Status;
+ ULONG NumTransferDescriptors, Index;
+ PQUEUE_HEAD QueueHead;
+
+
+ //
+ // first allocate the queue head
+ //
+ Status = CreateQueueHead(&QueueHead);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to allocate queue head
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // create setup packet
+ //
+ Status = BuildSetupPacket();
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to allocate setup packet
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // calculate num of transfer descriptors
+ //
+ NumTransferDescriptors = m_TransferBufferMDL != 0 ? 3 : 2;
+
+ //
+ // allocate transfer descriptors
+ //
+ for(Index = 0; Index < NumTransferDescriptors; Index++)
+ {
+ //
+ // allocate transfer descriptor
+ //
+ Status = CreateDescriptor(&m_TransferDescriptors[Index]);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to allocate transfer descriptor
+ //
+ return Status;
+ }
+ }
+
+ //
+ // now initialize the queue head
+ //
+ QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
+
+ //if (PipeHandle)
+ // QueueHead->EndPointCharacteristics.EndPointNumber =
((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->bEndpointAddress & 0x0F;
+
+ QueueHead->Token.Bits.DataToggle = TRUE;
+
+ //
+ // setup descriptors
+ //
+ m_TransferDescriptors[0]->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN;
+ m_TransferDescriptors[0]->Token.Bits.TotalBytesToTransfer =
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET);
+ m_TransferDescriptors[0]->Token.Bits.DataToggle = FALSE;
+
+ if (m_TransferBufferMDL)
+ {
+ //
+ // setup in descriptor
+ //
+ m_TransferDescriptors[1]->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
+ m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer =
m_TransferBufferLength;
+
+ //
+ // setup out descriptor
+ //
+ m_TransferDescriptors[2]->Token.Bits.PIDCode = PID_CODE_OUT_TOKEN;
+ m_TransferDescriptors[2]->Token.Bits.TotalBytesToTransfer = 0;
+
+ //
+ // link descriptors
+ //
+ m_TransferDescriptors[0]->NextPointer =
m_TransferDescriptors[1]->PhysicalAddr;
+
+ //
+ // special case, setup alternative next descriptor in case of error
+ // HAIKU links to dead descriptor
+ //
+ m_TransferDescriptors[0]->AlternateNextPointer =
m_TransferDescriptors[2]->PhysicalAddr;
+ m_TransferDescriptors[1]->NextPointer =
m_TransferDescriptors[2]->PhysicalAddr;
+ m_TransferDescriptors[1]->AlternateNextPointer =
m_TransferDescriptors[2]->PhysicalAddr;
+
+ //
+ // interrupt on completion
+ //
+ m_TransferDescriptors[2]->Token.Bits.InterruptOnComplete = TRUE;
+
+ }
+ else
+ {
+ //
+ // no buffer, setup in descriptor
+ //
+ m_TransferDescriptors[1]->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
+ m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer = 0;
+
+ //
+ // link descriptors
+ //
+ m_TransferDescriptors[0]->NextPointer =
m_TransferDescriptors[1]->PhysicalAddr;
+ m_TransferDescriptors[0]->AlternateNextPointer =
m_TransferDescriptors[1]->PhysicalAddr;
+
+ //
+ // interrupt on completion
+ //
+ m_TransferDescriptors[1]->Token.Bits.InterruptOnComplete = TRUE;
+ }
+
+ //
+ // FIXME: where put MDL virtual address?
+ //
+
+
+ //
+ // link setup packet into buffer - VIRTUAL Address!!!
+ //
+ m_TransferDescriptors[0]->BufferPointer[0] =
(ULONG)PtrToUlong(m_DescriptorPacket);
+
+ //
+ // link transfer descriptors to queue head
+ //
+ QueueHead->NextPointer = m_TransferDescriptors[0]->PhysicalAddr;
+
+ //
+ // store result
+ //
+ *OutHead = QueueHead;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::BuildBulkTransferQueueHead(
+ PQUEUE_HEAD * OutHead)
+{
+ UNIMPLEMENTED
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::CreateDescriptor(
+ PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor)
+{
+ PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
+ NTSTATUS Status;
+ PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress;
+
+ //
+ // allocate descriptor
+ //
+ Status = m_DmaManager->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR),
(PVOID*)&Descriptor, &TransferDescriptorPhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to allocate transfer descriptor
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize transfer descriptor
+ //
+ Descriptor->NextPointer = TERMINATE_POINTER;
+ Descriptor->AlternateNextPointer = TERMINATE_POINTER;
+ Descriptor->Token.Bits.DataToggle = TRUE;
+ Descriptor->Token.Bits.ErrorCounter = 0x03;
+ Descriptor->Token.Bits.Active = TRUE;
+ Descriptor->PhysicalAddr = TransferDescriptorPhysicalAddress.LowPart;
+
+ //
+ // store result
+ //
+ *OutDescriptor = Descriptor;
+
+ //
+ // done
+ //
+ return Status;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::CreateQueueHead(
+ PQUEUE_HEAD *OutQueueHead)
+{
+ PQUEUE_HEAD QueueHead;
+ PHYSICAL_ADDRESS QueueHeadPhysicalAddress;
+ NTSTATUS Status;
+
+ //
+ // allocate queue head
+ //
+ Status = m_DmaManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead,
&QueueHeadPhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to allocate queue head
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize queue head
+ //
+ QueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
+ QueueHead->AlternateNextPointer = TERMINATE_POINTER;
+ QueueHead->NextPointer = TERMINATE_POINTER;
+
+ //
+ // 1 for non high speed, 0 for high speed device
+ //
+ QueueHead->EndPointCharacteristics.ControlEndPointFlag = 0;
+ QueueHead->EndPointCharacteristics.HeadOfReclamation = FALSE;
+ QueueHead->EndPointCharacteristics.MaximumPacketLength = 64;
+
+ //
+ // Set NakCountReload to max value possible
+ //
+ QueueHead->EndPointCharacteristics.NakCountReload = 0xF;
+
+ //
+ // Get the Initial Data Toggle from the QEDT
+ //
+ QueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
+
+ //
+ // FIXME: check if High Speed Device
+ //
+ QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
+ QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x03;
+ QueueHead->Token.DWord = 0;
+ QueueHead->Token.Bits.InterruptOnComplete = FALSE;
+
+ //
+ // FIXME check if that is really needed
+ //
+ QueueHead->PhysicalAddr = QueueHeadPhysicalAddress.LowPart;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+//----------------------------------------------------------------------------------------
+ULONG
+CUSBRequest::GetDeviceAddress()
+{
+ PIO_STACK_LOCATION IoStack;
+ PURB Urb;
+ PUSBDEVICE UsbDevice;
+
+ //
+ // check if there is an irp provided
+ //
+ if (!m_Irp)
+ {
+ //
+ // no irp is provided
+ // assume it is for device address 0
+ return 0;
+ }
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
+ //
+ // get contained urb
+ //
+ Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+ //
+ // check if there is a pipe handle provided
+ //
+ if (Urb->UrbHeader.UsbdDeviceHandle)
+ {
+ //
+ // there is a device handle provided
+ //
+ UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle;
+
+ //
+ // return device address
+ //
+ return UsbDevice->GetDeviceAddress();
+ }
+
+ //
+ // no device handle provided, it is the host root bus
+ //
+ return 0;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::BuildSetupPacket()
+{
+ NTSTATUS Status;
+ PHYSICAL_ADDRESS PhysicalAddress;
+
+ //
+ // FIXME: generate setup packet from urb request
+ //
+ PC_ASSERT(m_SetupPacket);
+
+ //
+ // allocate common buffer setup packet
+ //
+ Status = m_DmaManager->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET),
(PVOID*)&m_DescriptorPacket, &PhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // no memory
+ //
+ return Status;
+ }
+
+ if (m_SetupPacket)
+ {
+ //
+ // copy setup packet
+ //
+ RtlCopyMemory(m_DescriptorPacket, m_SetupPacket,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+ }
+
+ //
+ // done
+ //
+ return Status;
+}
+
Propchange: branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Modified: branches/usb-bringup/drivers/usb/usbehci_new/usbehci.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/usbehci.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/usbehci.cpp [iso-8859-1] Tue Apr 19
01:21:10 2011
@@ -64,8 +64,6 @@
PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
- DPRINT1("EHCI_Dispatch\n");
-
//
// get common device extension
//
@@ -106,19 +104,10 @@
//
return DeviceExtension->Dispatcher->HandleDeviceControl(DeviceObject,
Irp);
}
- case IRP_MJ_CREATE:
- {
- //
- // dispatch create request
- //
- Status = STATUS_SUCCESS;
-
- break;
- }
default:
{
- DPRINT1("EHCI_Dispatch> Major %lu Minor %lu not supported\n",
IoStack->MajorFunction, IoStack->MinorFunction);
- Status = STATUS_NOT_SUPPORTED;
+ DPRINT1("EHCI_Dispatch> Major %lu Minor %lu unhandeled\n",
IoStack->MajorFunction, IoStack->MinorFunction);
+ Status = STATUS_SUCCESS;
}
}