Author: janderwald Date: Tue Apr 19 18:35:40 2011 New Revision: 51406
URL: http://svn.reactos.org/svn/reactos?rev=51406&view=rev Log: [USBEHCI_NEW] - Fix warning because comparing signed vs unsigned - Implement function for retrieving the device descriptor - Implement function for retrieving a configuration descriptor (including contained interface descriptor and endpoint descriptor) - Cleanup interface for IUSBRequest: - When caller initializes IUSBRequest with an IRP, then the operation mode is asynchronously. Therefore when the request is completed, IUSBRequest::ShouldReleaseRequestAfterCompletion will return true, which makes IUSBQueue call Release on IUSBRequest - When the caller initializes IUSBRequest with an setup packet, the operation mode is synchronously. After submitting the IUSBRequest to queue, the caller should call IUSBRequest::GetResultStatus. This function will then block untill the operation has been completed. However, the caller needs to call Release() as those requests are not cleaned up by the IUSBQueue
Modified: 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/usb_request.cpp
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 18:35:40 2011 @@ -288,7 +288,7 @@ return STATUS_UNSUCCESSFUL; }
- if (BufferLength < m_HubDeviceInterfaceString.Length - 8) + if (BufferLength < (ULONG)m_HubDeviceInterfaceString.Length - 8) { // // buffer too small @@ -774,7 +774,7 @@ // // sanity check // - PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < NumPort); + PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < (USHORT)NumPort);
// // port range reported start from 1 -n @@ -1882,7 +1882,8 @@ // // submit urb // - Status = UsbDevice->SubmitUrb(Urb); + //Status = UsbDevice->SubmitUrb(Urb); + UNIMPLEMENTED
if (NT_SUCCESS(Status)) {
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 18:35:40 2011 @@ -171,6 +171,15 @@ // Do not call Initialize on IUSBQueue, the object is already initialized
virtual NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue) = 0; + +//----------------------------------------------------------------------------------------- +// +// GetDMA +// +// Description: returns the DMA object which can be used to allocate memory from the common buffer + + virtual NTSTATUS GetDMA(OUT struct IDMAMemoryManager **OutDMAMemoryManager) = 0; +
//----------------------------------------------------------------------------------------- // @@ -363,40 +372,33 @@ // 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; + IN OUT PIRP Irp) = 0;
//----------------------------------------------------------------------------------------- // // CompletionCallback // // Description: called when request has been completed. It is called when -// IUSBQueue completes the request +// IUSBQueue completes a queue head
virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode, - IN ULONG UrbStatusCode) = 0; + IN ULONG UrbStatusCode, + IN struct _QUEUE_HEAD *QueueHead) = 0;
//----------------------------------------------------------------------------------------- // // CancelCallback // -// Description: called when request is cancelled. Called by IUSBQueue - - virtual VOID CancelCallback(IN NTSTATUS NtStatusCode) = 0; +// Description: called when the queue head is cancelled + + virtual VOID CancelCallback(IN NTSTATUS NtStatusCode, + IN struct _QUEUE_HEAD *QueueHead) = 0;
//----------------------------------------------------------------------------------------- // // GetQueueHead // -// Description: returns an initialized queue head with contains the all transfer descriptors +// Description: returns an initialized queue head which contains all transfer descriptors
virtual NTSTATUS GetQueueHead(struct _QUEUE_HEAD ** OutHead) = 0;
@@ -406,6 +408,9 @@ // // Description: returns true when the request has been completed // Should be called after the CompletionCallback has been invoked +// This function is called by IUSBQueue after queue head has been completed +// If the function returns true, IUSBQueue will then call ShouldReleaseRequestAfterCompletion +// If that function returns also true, it calls Release() to delete the IUSBRequest
virtual BOOLEAN IsRequestComplete() = 0;
@@ -417,6 +422,34 @@
virtual ULONG GetTransferType() = 0;
+//----------------------------------------------------------------------------------------- +// +// GetResultStatus +// +// Description: returns the status code of the result +// Note: this function will block the caller untill the request has been completed + + virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS * NtStatusCode, + OUT OPTIONAL PULONG UrbStatusCode) = 0; + +//----------------------------------------------------------------------------------------- +// +// IsRequestInitialized +// +// Description: returns true when the request has been successfully initialized using InitializeXXX methods + + virtual BOOLEAN IsRequestInitialized() = 0; + +//----------------------------------------------------------------------------------------- +// +// ShouldReleaseRequestAfterCompletion +// +// Description: this function gets called when the request returns +// IUSBQueue will then call Release() on the object to release all associated memory +// This function will typically return true when the request has been initialized with an irp +// If the request was initialized with an setup packet, it will return false + + virtual BOOLEAN ShouldReleaseRequestAfterCompletion() = 0; };
typedef IUSBRequest *PUSBREQUEST; @@ -446,7 +479,7 @@ // // GetPendingRequestCount // -// Description: returns the number of pending requests +// Description: returns the number of pending requests true from IsRequestComplete
virtual ULONG GetPendingRequestCount() = 0;
@@ -608,7 +641,7 @@ // // Description: gets the device address of the this device
- virtual ULONG GetDeviceAddress() = 0; + virtual UCHAR GetDeviceAddress() = 0;
//----------------------------------------------------------------------------------------- @@ -657,7 +690,7 @@ // // Description: sets device handle data
- virtual NTSTATUS SetDeviceAddress(ULONG DeviceAddress) = 0; + virtual NTSTATUS SetDeviceAddress(UCHAR DeviceAddress) = 0;
//----------------------------------------------------------------------------------------- // @@ -677,11 +710,11 @@
//----------------------------------------------------------------------------------------- // -// SubmitUrb -// -// Description: submits an urb - - virtual NTSTATUS SubmitUrb(PURB Urb) = 0; +// SubmitIrp +// +// Description: submits an irp containing an urb + + virtual NTSTATUS SubmitIrp(PIRP Urb) = 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 18:35:40 2011 @@ -11,6 +11,24 @@ #define INITGUID #include "usbehci.h"
+typedef struct _USB_ENDPOINT +{ + USB_ENDPOINT_DESCRIPTOR EndPointDescriptor; +} USB_ENDPOINT, *PUSB_ENDPOINT; + +typedef struct _USB_INTERFACE +{ + USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + USB_ENDPOINT *EndPoints; +} USB_INTERFACE, *PUSB_INTERFACE; + +typedef struct _USB_CONFIGURATION +{ + USB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; + USB_INTERFACE *Interfaces; +} USB_CONFIGURATION, *PUSB_CONFIGURATION; + + class CUSBDevice : public IUSBDevice { public: @@ -37,20 +55,22 @@ virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController, IN PUSBHARDWAREDEVICE Device, IN PVOID Parent, IN ULONG Port, IN ULONG PortStatus); virtual BOOLEAN IsHub(); virtual NTSTATUS GetParent(PVOID * Parent); - virtual ULONG GetDeviceAddress(); + virtual UCHAR GetDeviceAddress(); virtual ULONG GetPort(); virtual USB_DEVICE_SPEED GetSpeed(); virtual USB_DEVICE_TYPE GetType(); virtual ULONG GetState(); virtual void SetDeviceHandleData(PVOID Data); - virtual NTSTATUS SetDeviceAddress(ULONG DeviceAddress); + virtual NTSTATUS SetDeviceAddress(UCHAR DeviceAddress); virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor); virtual UCHAR GetConfigurationValue(); - virtual NTSTATUS SubmitUrb(PURB Urb); + virtual NTSTATUS SubmitIrp(PIRP Irp);
// local function - virtual NTSTATUS CommitUrb(PURB Urb); - virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN ULONG BufferLength, IN OUT PVOID Buffer, IN OPTIONAL PIRP Irp, IN OPTIONAL PKEVENT pEvent); + virtual NTSTATUS CommitIrp(PIRP Irp); + virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN ULONG BufferLength, IN OUT PMDL Mdl); + virtual NTSTATUS CreateConfigurationDescriptor(ULONG ConfigurationIndex); + virtual NTSTATUS CreateDeviceDescriptor();
// constructor / destructor CUSBDevice(IUnknown *OuterUnknown){} @@ -62,13 +82,15 @@ PUSBHARDWAREDEVICE m_Device; PVOID m_Parent; ULONG m_Port; - ULONG m_DeviceAddress; + UCHAR m_DeviceAddress; PVOID m_Data; KSPIN_LOCK m_Lock; USB_DEVICE_DESCRIPTOR m_DeviceDescriptor; ULONG m_PortStatus; PUSBQUEUE m_Queue; PDMAMEMORYMANAGER m_DmaManager; + + PUSB_CONFIGURATION m_ConfigurationDescriptors; };
//---------------------------------------------------------------------------------------- @@ -126,19 +148,445 @@ }
// - // 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; - } - - + // get dma manager + // + Status = m_Device->GetDMA(&m_DmaManager); + if (!NT_SUCCESS(Status)) + { + // + // failed to get dma manager + // + DPRINT1("CUSBDevice::Initialize GetDMA failed with %x\n", Status); + return Status; + } + + // + // sanity check + // + PC_ASSERT(m_DmaManager); + + // + // get device descriptor + // + Status = CreateDeviceDescriptor(); + if (!NT_SUCCESS(Status)) + { + // + // failed to get device descriptor + // + DPRINT1("CUSBDevice::Initialize Failed to get device descriptor with %x\n", Status); + return Status; + } + + // + // done + // + return Status; +} + +//---------------------------------------------------------------------------------------- +BOOLEAN +CUSBDevice::IsHub() +{ + // + // USB Standard Device Class see http://www.usb.org/developers/defined_class/#BaseClass09h + // for details + // + return (m_DeviceDescriptor.bDeviceClass == 0x09 && m_DeviceDescriptor.bDeviceSubClass == 0x00); +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::GetParent( + PVOID * Parent) +{ + // + // returns parent + // + *Parent = m_Parent; + + // + // done + // + return STATUS_SUCCESS; +} + +//---------------------------------------------------------------------------------------- +UCHAR +CUSBDevice::GetDeviceAddress() +{ + // + // get device address + // + return m_DeviceAddress; +} + +//---------------------------------------------------------------------------------------- +ULONG +CUSBDevice::GetPort() +{ + // + // get port to which this device is connected to + // + return m_Port; +} + +//---------------------------------------------------------------------------------------- +USB_DEVICE_SPEED +CUSBDevice::GetSpeed() +{ + if (m_PortStatus & USB_PORT_STATUS_LOW_SPEED) + { + // + // low speed device + // + return UsbLowSpeed; + } + else if (m_PortStatus & USB_PORT_STATUS_HIGH_SPEED) + { + // + // high speed device + // + return UsbHighSpeed; + } + + // + // default to full speed + // + return UsbFullSpeed; +} + +//---------------------------------------------------------------------------------------- +USB_DEVICE_TYPE +CUSBDevice::GetType() +{ + // + // device is encoded into bcdUSB + // + if (m_DeviceDescriptor.bcdUSB == 0x110) + { + // + // USB 1.1 device + // + return Usb11Device; + } + else if (m_DeviceDescriptor.bcdUSB == 0x200) + { + // + // USB 2.0 device + // + return Usb20Device; + } + + DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n", m_DeviceDescriptor.bcdUSB); + PC_ASSERT(FALSE); + + return Usb11Device; +} + +//---------------------------------------------------------------------------------------- +ULONG +CUSBDevice::GetState() +{ + UNIMPLEMENTED + return FALSE; +} + +//---------------------------------------------------------------------------------------- +void +CUSBDevice::SetDeviceHandleData( + PVOID Data) +{ + // + // set device data, for debugging issues + // + m_Data = Data; +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::SetDeviceAddress( + UCHAR DeviceAddress) +{ + USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; + NTSTATUS Status; + UCHAR OldAddress; + ULONG Index; + + // + // zero request + // + RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); + + // + // initialize request + // + CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS; + CtrlSetup.wValue.W = (USHORT)DeviceAddress; + + // + // set device address + // + Status = CommitSetupPacket(&CtrlSetup, 0, 0); + + // + // check for success + // + if (!NT_SUCCESS(Status)) + { + // + // failed to set device address + // + DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with %x Address %x\n", Status, DeviceAddress); + return Status; + } + + // + // back up old address + // + OldAddress = m_DeviceAddress; + + // + // store new device address + // + m_DeviceAddress = DeviceAddress; + + // + // check that setting device address succeeded by retrieving the device descriptor + // + Status = CreateDeviceDescriptor(); + if (!NT_SUCCESS(Status)) + { + // + // failed to retrieve device descriptor + // + DPRINT1("CUSBbDevice::SetDeviceAddress> failed to set new device address %d, falling back to %d Error %x\n", DeviceAddress, OldAddress, Status); + m_DeviceAddress = OldAddress; + + // + // return error status + // + return Status; + } + + // + // sanity checks + // + PC_ASSERT(m_DeviceDescriptor.bNumConfigurations); + + // + // allocate configuration descriptor + // + m_ConfigurationDescriptors = (PUSB_CONFIGURATION) ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_CONFIGURATION) * m_DeviceDescriptor.bNumConfigurations, TAG_USBEHCI); + + // + // zero configuration descriptor + // + RtlZeroMemory(m_ConfigurationDescriptors, sizeof(USB_CONFIGURATION) * m_DeviceDescriptor.bNumConfigurations); + + // + // retrieve the configuration descriptors + // + for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++) + { + // + // retrieve configuration descriptors from device + // + Status = CreateConfigurationDescriptor(Index); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CUSBDevice::SetDeviceAddress> failed to retrieve configuration %lu\n", Index); + break; + } + } + + // + // done + // + return Status; + +} + +//---------------------------------------------------------------------------------------- +void +CUSBDevice::GetDeviceDescriptor( + PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) +{ + RtlMoveMemory(DeviceDescriptor, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); +} + +//---------------------------------------------------------------------------------------- +UCHAR +CUSBDevice::GetConfigurationValue() +{ + UNIMPLEMENTED + return 0x1; +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::CommitIrp( + PIRP Irp) +{ + NTSTATUS Status; + PUSBREQUEST Request; + + if (!m_Queue || m_DmaManager) + { + // + // no queue, wtf? + // + DPRINT1("CUSBDevice::CommitUrb> no queue / dma !!!\n"); + return STATUS_UNSUCCESSFUL; + } + + // + // build usb request + // + Status = m_Queue->CreateUSBRequest(&Request); + if (!NT_SUCCESS(Status)) + { + // + // failed to build request + // + DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status); + return Status; + } + + // + // initialize request + // + Status = Request->InitializeWithIrp(m_DmaManager, Irp); + + // + // now add the request + // + Status = m_Queue->AddUSBRequest(Request); + if (!NT_SUCCESS(Status)) + { + // + // failed to add request + // + DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status); + Request->Release(); + return Status; + } + + // + // done + // + return Status; +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::SubmitIrp( + PIRP Irp) +{ + KIRQL OldLevel; + NTSTATUS Status; + + // + // acquire device lock + // + KeAcquireSpinLock(&m_Lock, &OldLevel); + + // + // commit urb + // + Status = CommitIrp(Irp); + + // + // release lock + // + KeReleaseSpinLock(&m_Lock, OldLevel); + + return Status; +} +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::CommitSetupPacket( + PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, + IN ULONG BufferLength, + IN OUT PMDL Mdl) +{ + NTSTATUS Status; + PUSBREQUEST Request; + + if (!m_Queue) + { + // + // no queue, wtf? + // + DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n"); + return STATUS_UNSUCCESSFUL; + } + + // + // build usb request + // + Status = m_Queue->CreateUSBRequest(&Request); + if (!NT_SUCCESS(Status)) + { + // + // failed to build request + // + DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status); + return Status; + } + + // + // initialize request + // + Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, BufferLength, Mdl); + if (!NT_SUCCESS(Status)) + { + // + // failed to initialize request + // + DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request with %x\n", Status); + Request->Release(); + return Status; + } + + + // + // now add the request + // + Status = m_Queue->AddUSBRequest(Request); + if (!NT_SUCCESS(Status)) + { + // + // failed to add request + // + DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status); + Request->Release(); + return Status; + } + + // + // get the result code when the operation has been finished + // + Request->GetResultStatus(&Status, NULL); + + // + // release request + // + Request->Release(); + + // + // done + // + return Status; +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::CreateDeviceDescriptor() +{ + USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; + PMDL Mdl; + NTSTATUS Status;
// // zero descriptor @@ -155,362 +603,239 @@ CtrlSetup.bmRequestType.B = 0x80;
// + // allocate mdl describing the device descriptor + // + Mdl = IoAllocateMdl(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR), FALSE, FALSE, 0); + if (!Mdl) + { + // + // failed to allocate mdl + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // build mdl for non paged pool + // + MmBuildMdlForNonPagedPool(Mdl); + + // // commit setup packet // - Status = CommitSetupPacket(&CtrlSetup, sizeof(USB_DEVICE_DESCRIPTOR), &m_DeviceDescriptor, 0, 0); - - // - // check for success - // - if (!NT_SUCCESS(Status)) - { - DPRINT1("CUSBDevice::Initialize CommitSetupPacket failed with %x\n", Status); - } + Status = CommitSetupPacket(&CtrlSetup, sizeof(USB_DEVICE_DESCRIPTOR), Mdl); + + // + // now free the mdl + // + IoFreeMdl(Mdl);
// // done // return Status; -} - -//---------------------------------------------------------------------------------------- -BOOLEAN -CUSBDevice::IsHub() -{ - // - // USB Standard Device Class see http://www.usb.org/developers/defined_class/#BaseClass09h - // for details - // - return (m_DeviceDescriptor.bDeviceClass == 0x09 && m_DeviceDescriptor.bDeviceSubClass == 0x00); -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::GetParent( - PVOID * Parent) -{ - // - // returns parent - // - *Parent = m_Parent; - - // - // done - // - return STATUS_SUCCESS; -} - -//---------------------------------------------------------------------------------------- -ULONG -CUSBDevice::GetDeviceAddress() -{ - // - // get device address - // - return m_DeviceAddress; -} - -//---------------------------------------------------------------------------------------- -ULONG -CUSBDevice::GetPort() -{ - // - // get port to which this device is connected to - // - return m_Port; -} - -//---------------------------------------------------------------------------------------- -USB_DEVICE_SPEED -CUSBDevice::GetSpeed() -{ - if (m_PortStatus & USB_PORT_STATUS_LOW_SPEED) - { - // - // low speed device - // - return UsbLowSpeed; - } - else if (m_PortStatus & USB_PORT_STATUS_HIGH_SPEED) - { - // - // high speed device - // - return UsbHighSpeed; - } - - // - // default to full speed - // - return UsbFullSpeed; -} - -//---------------------------------------------------------------------------------------- -USB_DEVICE_TYPE -CUSBDevice::GetType() -{ - // - // device is encoded into bcdUSB - // - if (m_DeviceDescriptor.bcdUSB == 0x110) - { - // - // USB 1.1 device - // - return Usb11Device; - } - else if (m_DeviceDescriptor.bcdUSB == 0x200) - { - // - // USB 2.0 device - // - return Usb20Device; - } - - DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n", m_DeviceDescriptor.bcdUSB); - PC_ASSERT(FALSE); - - return Usb11Device; -} - -//---------------------------------------------------------------------------------------- -ULONG -CUSBDevice::GetState() -{ - UNIMPLEMENTED - return FALSE; -} - -//---------------------------------------------------------------------------------------- -void -CUSBDevice::SetDeviceHandleData( - PVOID Data) -{ - // - // set device data, for debugging issues - // - m_Data = Data; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::SetDeviceAddress( - ULONG DeviceAddress) -{ + +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::CreateConfigurationDescriptor( + ULONG Index) +{ + PVOID Buffer; USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; NTSTATUS Status; - - // - // zero request - // - RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - - // - // initialize request - // - CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS; - CtrlSetup.wValue.W = (USHORT)DeviceAddress; - - // - // set device address - // - Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0, 0); - - // - // check for success - // - if (!NT_SUCCESS(Status)) - { - // - // failed to set device address - // - DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with %x Address %x\n", Status, DeviceAddress); - return Status; - } - - // - // store device address - // - m_DeviceAddress = DeviceAddress; + PMDL Mdl; + ULONG InterfaceIndex, EndPointIndex; + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + PUSB_ENDPOINT_DESCRIPTOR EndPointDescriptor; + + + // + // sanity checks + // + PC_ASSERT(m_ConfigurationDescriptors); + + // + // first allocate a buffer which should be enough to store all different interfaces and endpoints + // + Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_USBEHCI); + if (!Buffer) + { + // + // failed to allocate buffer + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // build setup packet + // + 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 = 0; + CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE; + CtrlSetup.wIndex.W = 0; + CtrlSetup.wLength = PAGE_SIZE; + + // + // FIXME: where put configuration index? + // + + // + // now build MDL describing the buffer + // + Mdl = IoAllocateMdl(Buffer, PAGE_SIZE, FALSE, FALSE, 0); + if (!Mdl) + { + // + // failed to allocate mdl + // + ExFreePoolWithTag(Buffer, TAG_USBEHCI); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // build mdl for non paged pool + // + MmBuildMdlForNonPagedPool(Mdl); + + // + // commit packet + // + Status = CommitSetupPacket(&CtrlSetup, PAGE_SIZE, Mdl); + if (!NT_SUCCESS(Status)) + { + // + // failed to issue request, cleanup + // + IoFreeMdl(Mdl); + ExFreePool(Buffer); + return Status; + } + + // + // now free the mdl + // + IoFreeMdl(Mdl); + + // + // get configuration descriptor + // + ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Buffer; + + // + // sanity check + // + PC_ASSERT(ConfigurationDescriptor->bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR)); + PC_ASSERT(ConfigurationDescriptor->wTotalLength <= PAGE_SIZE); + PC_ASSERT(ConfigurationDescriptor->bNumInterfaces); + + // + // request is complete, initialize configuration descriptor + // + RtlCopyMemory(&m_ConfigurationDescriptors[Index].ConfigurationDescriptor, ConfigurationDescriptor, ConfigurationDescriptor->bLength); + + // + // now allocate interface descriptors + // + m_ConfigurationDescriptors[Index].Interfaces = (PUSB_INTERFACE)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_INTERFACE) * ConfigurationDescriptor->bNumInterfaces, TAG_USBEHCI); + if (!m_ConfigurationDescriptors[Index].Interfaces) + { + // + // failed to allocate interface descriptors + // + ExFreePool(Buffer); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // zero interface descriptor + // + RtlZeroMemory(m_ConfigurationDescriptors[Index].Interfaces, sizeof(USB_INTERFACE) * ConfigurationDescriptor->bNumInterfaces); + + // + // get first interface descriptor + // + InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)(ConfigurationDescriptor + 1); + + // + // setup interface descriptors + // + for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++) + { + // + // sanity check + // + PC_ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR)); + PC_ASSERT(InterfaceDescriptor->bNumEndpoints); + + // + // copy current interface descriptor + // + RtlCopyMemory(&m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].InterfaceDescriptor, InterfaceDescriptor, InterfaceDescriptor->bLength); + + // + // allocate end point descriptors + // + m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints = (PUSB_ENDPOINT)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_ENDPOINT) * InterfaceDescriptor->bNumEndpoints, TAG_USBEHCI); + if (!m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints) + { + // + // failed to allocate endpoint + // + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + // + // zero memory + // + RtlZeroMemory(m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints, sizeof(USB_ENDPOINT) * InterfaceDescriptor->bNumEndpoints); + + // + // initialize end point descriptors + // + EndPointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)(InterfaceDescriptor + 1); + + for(EndPointIndex = 0; EndPointIndex < InterfaceDescriptor->bNumEndpoints; EndPointIndex++) + { + // + // sanity check + // + PC_ASSERT(EndPointDescriptor->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)); + + // + // copy endpoint descriptor + // + RtlCopyMemory(&m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints[EndPointIndex].EndPointDescriptor, EndPointDescriptor, EndPointDescriptor->bLength); + + // + // move to next offset + // + EndPointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndPointDescriptor + EndPointDescriptor->bLength); + } + + // + // update interface descriptor offset + // + InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)EndPointDescriptor; + } + + // + // free buffer + // + ExFreePoolWithTag(Buffer, TAG_USBEHCI);
// // done // - return STATUS_SUCCESS; -} - -//---------------------------------------------------------------------------------------- -void -CUSBDevice::GetDeviceDescriptor( - PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) -{ - RtlMoveMemory(DeviceDescriptor, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); -} - -//---------------------------------------------------------------------------------------- -UCHAR -CUSBDevice::GetConfigurationValue() -{ - UNIMPLEMENTED - return 0x1; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::CommitUrb( - PURB Urb) -{ - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::SubmitUrb( - PURB Urb) -{ - KIRQL OldLevel; - NTSTATUS Status; - - // - // acquire device lock - // - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // - // commit urb - // - Status = CommitUrb(Urb); - - // - // release lock - // - KeReleaseSpinLock(&m_Lock, OldLevel); - return Status; } -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::CommitSetupPacket( - PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, - IN ULONG BufferLength, - IN OUT PVOID Buffer, - IN PIRP Irp, - IN PKEVENT pEvent) -{ - NTSTATUS Status; - PUSBREQUEST Request; - KEVENT Event; - BOOLEAN Wait = FALSE; - PMDL Mdl = 0; - - - if (!m_Queue) - { - // - // no queue, wtf? - // - DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n"); - return STATUS_UNSUCCESSFUL; - } - - // - // build usb request - // - Status = m_Queue->CreateUSBRequest(&Request); - if (!NT_SUCCESS(Status)) - { - // - // failed to build request - // - DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status); - return Status; - } - - /* FIXME build MDL */ - - // - // initialize request - // - Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, BufferLength, Mdl); - if (!NT_SUCCESS(Status)) - { - // - // failed to initialize request - // - DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request with %x\n", Status); - Request->Release(); - return Status; - } - - // - // is a irp or event provided ? - // - if (Irp == NULL && pEvent == NULL) - { - // - // no completion details provided, requestor wants synchronized - // - KeInitializeEvent(&Event, NotificationEvent, FALSE); - pEvent = &Event; - Wait = TRUE; - } - - // - // set completion details - // - Status = Request->SetCompletionEvent(pEvent); - if (!NT_SUCCESS(Status)) - { - // - // failed to set completion details - // - DPRINT1("CUSBDevice::CommitSetupPacket> failed to set completion details with %x\n", Status); - Request->Release(); - return Status; - } - - // - // now add the request - // - Status = m_Queue->AddUSBRequest(Request); - if (!NT_SUCCESS(Status)) - { - // - // failed to add request - // - DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status); - Request->Release(); - return Status; - } - - if (Wait) - { - // - // wait for the operation to complete - // - KeWaitForSingleObject(pEvent, Executive, KernelMode, FALSE, NULL); - } - - //TODO: - // Get result code from operation - // - - // - // returns the result code when the operation has been finished - // - //Status = Request->GetResultCode(); - - // - // release request - // - Request->Release(); - - // - // done - // - return Status; -} + //---------------------------------------------------------------------------------------- NTSTATUS CreateUSBDevice(
Modified: 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 [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp [iso-8859-1] Tue Apr 19 18:35:40 2011 @@ -38,12 +38,14 @@ // 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 VOID CompletionCallback(IN NTSTATUS NtStatusCode, IN ULONG UrbStatusCode, IN struct _QUEUE_HEAD *QueueHead); + virtual VOID CancelCallback(IN NTSTATUS NtStatusCode, IN struct _QUEUE_HEAD *QueueHead); virtual NTSTATUS GetQueueHead(struct _QUEUE_HEAD ** OutHead); virtual BOOLEAN IsRequestComplete(); virtual ULONG GetTransferType(); + virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode); + virtual BOOLEAN IsRequestInitialized(); + virtual BOOLEAN ShouldReleaseRequestAfterCompletion();
// local functions ULONG InternalGetTransferType(); @@ -60,17 +62,60 @@
protected: LONG m_Ref; + + // + // memory manager for allocating setup packet / queue head / transfer descriptors + // PDMAMEMORYMANAGER m_DmaManager; + + // + // caller provided irp packet containing URB request + // + PIRP m_Irp; + + // + // transfer buffer length + // + ULONG m_TransferBufferLength; + + // + // transfer buffer MDL + // + PMDL m_TransferBufferMDL; + + + // + // caller provided setup packet + // PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket; - ULONG m_TransferBufferLength; - PMDL m_TransferBufferMDL; - PIRP m_Irp; + + // + // completion event for callers who initialized request with setup packet + // PKEVENT m_CompletionEvent;
+ // + // DMA queue head + // PQUEUE_HEAD m_QueueHead; + + // + // DMA transfer descriptors linked to the queue head + // PQUEUE_TRANSFER_DESCRIPTOR m_TransferDescriptors[3]; + + // + // allocated setup packet from the DMA pool + // PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket; PHYSICAL_ADDRESS m_DescriptorSetupPacket; + + // + // stores the result of the operation + // + NTSTATUS m_NtStatusCode; + ULONG m_UrbStatusCode; + };
//---------------------------------------------------------------------------------------- @@ -106,6 +151,23 @@ m_TransferBufferMDL = TransferBuffer;
// + // allocate completion event + // + m_CompletionEvent = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_USBEHCI); + if (!m_CompletionEvent) + { + // + // failed to allocate completion event + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // initialize completion event + // + KeInitializeEvent(m_CompletionEvent, NotificationEvent, FALSE); + + // // done // return STATUS_SUCCESS; @@ -166,7 +228,7 @@ if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength) { // - // it must have an MDL + // FIXME: it must have an MDL // PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
@@ -189,38 +251,27 @@ 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) + IN ULONG UrbStatusCode, + IN struct _QUEUE_HEAD *QueueHead) { PIO_STACK_LOCATION IoStack; PURB Urb;
+ // + // FIXME: support linked queue heads + // + + // + // store completion code + // + m_NtStatusCode = NtStatusCode; + m_UrbStatusCode = UrbStatusCode; + if (m_Irp) { // @@ -260,23 +311,33 @@ // IoCompleteRequest(m_Irp, IO_NO_INCREMENT); } - - if (m_CompletionEvent) - { - // - // FIXME: make sure the request was not split - // + else + { + // + // signal completion event + // + PC_ASSERT(m_CompletionEvent); KeSetEvent(m_CompletionEvent, 0, FALSE); } } //---------------------------------------------------------------------------------------- VOID CUSBRequest::CancelCallback( - IN NTSTATUS NtStatusCode) + IN NTSTATUS NtStatusCode, + IN struct _QUEUE_HEAD *QueueHead) { PIO_STACK_LOCATION IoStack; PURB Urb;
+ // + // FIXME: support linked queue heads + // + + // + // store cancelleation code + // + m_NtStatusCode = NtStatusCode; + if (m_Irp) { // @@ -306,12 +367,12 @@ // IoCompleteRequest(m_Irp, IO_NO_INCREMENT); } - - if (m_CompletionEvent) - { - // - // FIXME: make sure the request was not split - // + else + { + // + // signal completion event + // + PC_ASSERT(m_CompletionEvent); KeSetEvent(m_CompletionEvent, 0, FALSE); } } @@ -370,6 +431,7 @@ // // FIXME: check if request was split // + UNIMPLEMENTED return TRUE; } //---------------------------------------------------------------------------------------- @@ -451,7 +513,6 @@ NTSTATUS Status; ULONG NumTransferDescriptors, Index; PQUEUE_HEAD QueueHead; -
// // first allocate the queue head @@ -802,3 +863,75 @@ return Status; }
+//---------------------------------------------------------------------------------------- +VOID +CUSBRequest::GetResultStatus( + OUT OPTIONAL NTSTATUS * NtStatusCode, + OUT OPTIONAL PULONG UrbStatusCode) +{ + // + // sanity check + // + PC_ASSERT(m_CompletionEvent); + + // + // wait for the operation to complete + // + KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL); + + // + // copy status + // + if (NtStatusCode) + { + *NtStatusCode = m_NtStatusCode; + } + + // + // copy urb status + // + if (UrbStatusCode) + { + *UrbStatusCode = m_UrbStatusCode; + } + +} + + +//----------------------------------------------------------------------------------------- +BOOLEAN +CUSBRequest::IsRequestInitialized() +{ + if (m_Irp || m_SetupPacket) + { + // + // request is initialized + // + return TRUE; + } + + // + // request is not initialized + // + return FALSE; +} + +//----------------------------------------------------------------------------------------- +BOOLEAN +CUSBRequest::ShouldReleaseRequestAfterCompletion() +{ + if (m_Irp) + { + // + // the request is completed, release it + // + return TRUE; + } + else + { + // + // created with an setup packet, don't release + // + return FALSE; + } +}