[USBOHCI]

- Start implementing control transfers
- Move initialization of usb queue after the bulk / control head endpoints have been created
- Add interface functions to retrieve bulk / control head endpoint descriptors
- Add macros for setting transfer descriptors field (taken from Haiku)
- Partly implement IUSBQueue::AddUSBRequest for control / bulk transfers
- Create endpoint descriptor for control request and link setup descriptor to it 
- Link setup descriptors to data descriptor / status descriptor
- WIP (needs fixes)

svn path=/branches/usb-bringup/; revision=51864
This commit is contained in:
Johannes Anderwald 2011-05-23 17:42:52 +00:00
parent c5acda628c
commit f75cb3d51d
5 changed files with 633 additions and 26 deletions

View file

@ -59,6 +59,10 @@ public:
NTSTATUS PnpStop(void);
NTSTATUS HandlePower(PIRP Irp);
NTSTATUS GetDeviceDetails(PUSHORT VendorId, PUSHORT DeviceId, PULONG NumberOfPorts, PULONG Speed);
NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
VOID HeadEndpointDescriptorModified(ULONG HeadType);
NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager);
NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue);
@ -359,16 +363,6 @@ CUSBHardwareDevice::PnpStart(
return Status;
}
//
// Initialize the UsbQueue now that we have an AdapterObject.
//
Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, m_MemoryManager, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to Initialize the UsbQueue\n");
return Status;
}
//
// initializes the controller
//
@ -380,6 +374,16 @@ CUSBHardwareDevice::PnpStart(
return Status;
}
//
// Initialize the UsbQueue now that we have an AdapterObject.
//
Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, m_MemoryManager, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to Initialize the UsbQueue\n");
return Status;
}
//
// Stop the controller before modifying schedules
@ -631,6 +635,42 @@ CUSBHardwareDevice::AllocateEndpointDescriptor(
return STATUS_SUCCESS;
}
NTSTATUS
CUSBHardwareDevice::GetBulkHeadEndpointDescriptor(
struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
{
*OutDescriptor = m_BulkEndpointDescriptor;
return STATUS_SUCCESS;
}
VOID
CUSBHardwareDevice::HeadEndpointDescriptorModified(
ULONG Type)
{
if (Type == USB_ENDPOINT_TYPE_CONTROL)
{
//
// notify controller
//
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), OHCI_CONTROL_LIST_FILLED);
}
else if (Type == USB_ENDPOINT_TYPE_BULK)
{
//
// notify controller
//
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), OHCI_BULK_LIST_FILLED);
}
}
NTSTATUS
CUSBHardwareDevice::GetControlHeadEndpointDescriptor(
struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
{
*OutDescriptor = m_ControlEndpointDescriptor;
return STATUS_SUCCESS;
}
NTSTATUS
CUSBHardwareDevice::InitializeController()
{
@ -1128,7 +1168,7 @@ InterruptServiceRoutine(
// head completed
//
DPRINT1("InterruptServiceRoutine> Done Head completion\n");
ASSERT(FALSE);
//
// FIXME: handle event
//
@ -1148,9 +1188,11 @@ InterruptServiceRoutine(
if (Status & OHCI_UNRECOVERABLE_ERROR)
{
DPRINT1("InterruptServiceRoutine> Controller error\n");
//
// halt controller
//
ASSERT(FALSE);
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_CONTROL_OFFSET), OHCI_HC_FUNCTIONAL_STATE_RESET);
}

View file

@ -192,7 +192,7 @@ typedef struct
#define OHCI_PAGE_OFFSET(x) ((x) & 0xfff)
typedef struct
typedef struct _OHCI_ENDPOINT_DESCRIPTOR
{
// Hardware part
ULONG Flags;
@ -202,10 +202,19 @@ typedef struct
// Software part
PHYSICAL_ADDRESS PhysicalAddress;
PVOID Request;
PVOID NextDescriptor;
}OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR;
#define OHCI_ENDPOINT_SKIP 0x00004000
#define OHCI_ENDPOINT_SET_DEVICE_ADDRESS(s) (s)
#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)
#define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s) ((s) << 16)
#define OHCI_ENDPOINT_LOW_SPEED 0x00002000
#define OHCI_ENDPOINT_FULL_SPEED 0x00000000
//
// Maximum port count set by OHCI
@ -220,15 +229,51 @@ typedef struct
}OHCI_PORT_STATUS;
typedef struct {
typedef struct
{
// Hardware part 16 bytes
uint32 flags; // Flags field
uint32 buffer_physical; // Physical buffer pointer
uint32 next_physical_descriptor; // Physical pointer next descriptor
uint32 last_physical_byte_address; // Physical pointer to buffer end
ULONG Flags; // Flags field
ULONG BufferPhysical; // Physical buffer pointer
ULONG NextPhysicalDescriptor; // Physical pointer next descriptor
ULONG LastPhysicalByteAddress; // Physical pointer to buffer end
// Software part
addr_t physical_address; // Physical address of this descriptor
size_t buffer_size; // Size of the buffer
void *buffer_logical; // Logical pointer to the buffer
void *next_logical_descriptor; // Logical pointer next descriptor
} ohci_general_td;
PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this descriptor
ULONG BufferSize; // Size of the buffer
PVOID BufferLogical; // Logical pointer to the buffer
PVOID Request; // pointer to IUSBRequest
}OHCI_GENERAL_TD, *POHCI_GENERAL_TD;
#define OHCI_TD_BUFFER_ROUNDING 0x00040000
#define OHCI_TD_DIRECTION_PID_MASK 0x00180000
#define OHCI_TD_DIRECTION_PID_SETUP 0x00000000
#define OHCI_TD_DIRECTION_PID_OUT 0x00080000
#define OHCI_TD_DIRECTION_PID_IN 0x00100000
#define OHCI_TD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7)
#define OHCI_TD_SET_DELAY_INTERRUPT(x) ((x) << 21)
#define OHCI_TD_INTERRUPT_MASK 0x00e00000
#define OHCI_TD_TOGGLE_CARRY 0x00000000
#define OHCI_TD_TOGGLE_0 0x02000000
#define OHCI_TD_TOGGLE_1 0x03000000
#define OHCI_TD_TOGGLE_MASK 0x03000000
#define OHCI_TD_GET_ERROR_COUNT(x) (((x) >> 26) & 3)
#define OHCI_TD_GET_CONDITION_CODE(x) ((x) >> 28)
#define OHCI_TD_SET_CONDITION_CODE(x) ((x) << 28)
#define OHCI_TD_CONDITION_CODE_MASK 0xf0000000
#define OHCI_TD_INTERRUPT_IMMEDIATE 0x00
#define OHCI_TD_INTERRUPT_NONE 0x07
#define OHCI_TD_CONDITION_NO_ERROR 0x00
#define OHCI_TD_CONDITION_CRC_ERROR 0x01
#define OHCI_TD_CONDITION_BIT_STUFFING 0x02
#define OHCI_TD_CONDITION_TOGGLE_MISMATCH 0x03
#define OHCI_TD_CONDITION_STALL 0x04
#define OHCI_TD_CONDITION_NO_RESPONSE 0x05
#define OHCI_TD_CONDITION_PID_CHECK_FAILURE 0x06
#define OHCI_TD_CONDITION_UNEXPECTED_PID 0x07
#define OHCI_TD_CONDITION_DATA_OVERRUN 0x08
#define OHCI_TD_CONDITION_DATA_UNDERRUN 0x09
#define OHCI_TD_CONDITION_BUFFER_OVERRUN 0x0c
#define OHCI_TD_CONDITION_BUFFER_UNDERRUN 0x0d
#define OHCI_TD_CONDITION_NOT_ACCESSED 0x0f

View file

@ -107,7 +107,7 @@ DECLARE_INTERFACE_(IHCDController, IUnknown)
typedef IHCDController *PHCDCONTROLLER;
struct _OHCI_ENDPOINT_DESCRIPTOR;
//=========================================================================================
//
// class IUSBHardwareDevice
@ -172,6 +172,33 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown)
virtual NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue) = 0;
//-----------------------------------------------------------------------------------------
//
// GetBulkHeadEndpointDescriptor
//
// Description: returns the bulk head endpoint descriptor
virtual NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
//-----------------------------------------------------------------------------------------
//
// GetControlHeadEndpointDescriptor
//
// Description: returns the control head endpoint descriptor
virtual NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
//-----------------------------------------------------------------------------------------
//
// HeadEndpointDescriptorModified
//
// Description: notifies the hardware that an endpoint descriptor was added to head endpoint descriptor
virtual VOID HeadEndpointDescriptorModified(ULONG HeadType) = 0;
//-----------------------------------------------------------------------------------------
//
// GetDMA
@ -334,8 +361,6 @@ typedef IDMAMemoryManager *PDMAMEMORYMANAGER;
// CancelCallback routine is invoked.
//
struct _QUEUE_HEAD;
DECLARE_INTERFACE_(IUSBRequest, IUnknown)
{
DEFINE_ABSTRACT_UNKNOWN()
@ -385,6 +410,14 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
virtual ULONG GetTransferType() = 0;
//-----------------------------------------------------------------------------------------
//
// GetEndpointDescriptor
//
// Description: returns the general transfer descriptor
virtual NTSTATUS GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
//-----------------------------------------------------------------------------------------
//
// GetResultStatus

View file

@ -46,6 +46,9 @@ public:
protected:
LONG m_Ref; // reference count
KSPIN_LOCK m_Lock; // list lock
PUSBHARDWAREDEVICE m_Hardware; // hardware
POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor; // bulk head descriptor
POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor; // control head descriptor
};
//=================================================================================================
@ -74,7 +77,26 @@ CUSBQueue::Initialize(
IN PDMAMEMORYMANAGER MemManager,
IN OPTIONAL PKSPIN_LOCK Lock)
{
UNIMPLEMENTED
//
// get bulk endpoint descriptor
//
Hardware->GetBulkHeadEndpointDescriptor(&m_BulkHeadEndpointDescriptor);
//
// get control endpoint descriptor
//
Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor);
//
// initialize spinlock
//
KeInitializeSpinLock(&m_Lock);
//
// store hardware
//
m_Hardware = Hardware;
return STATUS_SUCCESS;
}
@ -96,6 +118,10 @@ CUSBQueue::AddUSBRequest(
NTSTATUS Status;
ULONG Type;
KIRQL OldLevel;
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
POHCI_ENDPOINT_DESCRIPTOR Descriptor;
DPRINT1("CUSBQueue::AddUSBRequest\n");
//
// sanity check
@ -143,6 +169,63 @@ CUSBQueue::AddUSBRequest(
//
Request->AddRef();
//
// get transfer descriptors
//
Status = Request->GetEndpointDescriptor(&Descriptor);
if (!NT_SUCCESS(Status))
{
//
// failed to get transfer descriptor
//
DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with %x\n", Status);
//
// release reference
//
Request->Release();
return Status;
}
//
// 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;
}
//
// link endpoints
//
Descriptor->NextPhysicalEndpoint = HeadDescriptor->NextPhysicalEndpoint;
Descriptor->NextDescriptor = HeadDescriptor->NextDescriptor;
HeadDescriptor->NextPhysicalEndpoint = Descriptor->PhysicalAddress.LowPart;
HeadDescriptor->NextDescriptor = Descriptor;
//
// set descriptor active
//
Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
//
// notify hardware of our request
//
m_Hardware->HeadEndpointDescriptorModified(Type);
DPRINT1("Request added to queue\n");
return STATUS_SUCCESS;
}

View file

@ -40,6 +40,7 @@ public:
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp);
virtual BOOLEAN IsRequestComplete();
virtual ULONG GetTransferType();
virtual NTSTATUS GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutEndpointDescriptor);
virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode);
virtual BOOLEAN IsRequestInitialized();
virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
@ -51,6 +52,12 @@ public:
UCHAR GetDeviceAddress();
NTSTATUS BuildSetupPacket();
NTSTATUS BuildSetupPacketFromURB();
NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, ULONG BufferSize);
VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor);
NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor);
UCHAR GetEndpointAddress();
USHORT GetMaxPacketSize();
// constructor / destructor
CUSBRequest(IUnknown *OuterUnknown){}
@ -348,6 +355,46 @@ CUSBRequest::GetTransferType()
return InternalGetTransferType();
}
USHORT
CUSBRequest::GetMaxPacketSize()
{
if (!m_EndpointDescriptor)
{
//
// control request
//
return 0;
}
ASSERT(m_Irp);
ASSERT(m_EndpointDescriptor);
//
// return max packet size
//
return m_EndpointDescriptor->wMaxPacketSize;
}
UCHAR
CUSBRequest::GetEndpointAddress()
{
if (!m_EndpointDescriptor)
{
//
// control request
//
return 0;
}
ASSERT(m_Irp);
ASSERT(m_EndpointDescriptor);
//
// endpoint number is between 1-15
//
return (m_EndpointDescriptor->bEndpointAddress & 0xF);
}
//----------------------------------------------------------------------------------------
ULONG
CUSBRequest::InternalGetTransferType()
@ -444,9 +491,366 @@ CUSBRequest::GetDeviceAddress()
return 0;
}
VOID
CUSBRequest::FreeDescriptor(
POHCI_GENERAL_TD Descriptor)
{
if (Descriptor->BufferSize)
{
//
// free buffer
//
m_DmaManager->Release(Descriptor->BufferLogical, Descriptor->BufferSize);
}
//
// release descriptor
//
m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
}
//----------------------------------------------------------------------------------------
NTSTATUS
CUSBRequest::CreateGeneralTransferDescriptor(
POHCI_GENERAL_TD* OutDescriptor,
ULONG BufferSize)
{
POHCI_GENERAL_TD Descriptor;
PHYSICAL_ADDRESS DescriptorAddress;
NTSTATUS Status;
//
// allocate transfer descriptor
//
Status = m_DmaManager->Allocate(sizeof(OHCI_GENERAL_TD), (PVOID*)&Descriptor, &DescriptorAddress);
if (!NT_SUCCESS(Status))
{
//
// no memory
//
return Status;
}
//
// initialize descriptor, hardware part
//
Descriptor->Flags = 0;
Descriptor->BufferPhysical = 0;
Descriptor->NextPhysicalDescriptor = 0;
Descriptor->LastPhysicalByteAddress = 0;
//
// software part
//
Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
Descriptor->BufferSize = BufferSize;
if (BufferSize > 0)
{
//
// allocate buffer from dma
//
Status = m_DmaManager->Allocate(BufferSize, &Descriptor->BufferLogical, &DescriptorAddress);
if (!NT_SUCCESS(Status))
{
//
// no memory
//
m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
return Status;
}
//
// set physical address of buffer
//
Descriptor->BufferPhysical = DescriptorAddress.LowPart;
Descriptor->LastPhysicalByteAddress = Descriptor->BufferPhysical + BufferSize - 1;
}
//
// store result
//
*OutDescriptor = Descriptor;
//
// done
//
return STATUS_SUCCESS;
}
NTSTATUS
CUSBRequest::AllocateEndpointDescriptor(
OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor)
{
POHCI_ENDPOINT_DESCRIPTOR Descriptor;
PHYSICAL_ADDRESS DescriptorAddress;
NTSTATUS Status;
//
// allocate descriptor
//
Status = m_DmaManager->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR), (PVOID*)&Descriptor, &DescriptorAddress);
if (!NT_SUCCESS(Status))
{
//
// failed to allocate descriptor
//
return Status;
}
//
// intialize descriptor
//
Descriptor->Flags = OHCI_ENDPOINT_SKIP;
//
// append device address and endpoint number
//
Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(m_DeviceAddress);
Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
//
// FIXME: detect type
//
Descriptor->Flags |= OHCI_ENDPOINT_FULL_SPEED;
Descriptor->HeadPhysicalDescriptor = 0;
Descriptor->NextPhysicalEndpoint = 0;
Descriptor->TailPhysicalDescriptor = 0;
Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
//
// store result
//
*OutDescriptor = Descriptor;
//
// done
//
return STATUS_SUCCESS;
}
NTSTATUS
CUSBRequest::BuildControlTransferDescriptor(
POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
{
POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL;
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
NTSTATUS Status;
DPRINT1("CUSBRequest::BuildControlTransferDescriptor\n");
//
// allocate endpoint descriptor
//
Status = AllocateEndpointDescriptor(&EndpointDescriptor);
if (!NT_SUCCESS(Status))
{
//
// failed to create setup descriptor
//
return Status;
}
//
// first allocate setup descriptor
//
Status = CreateGeneralTransferDescriptor(&SetupDescriptor, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
if (!NT_SUCCESS(Status))
{
//
// failed to create setup descriptor
//
m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
return Status;
}
//
// now create the status descriptor
//
Status = CreateGeneralTransferDescriptor(&StatusDescriptor, 0);
if (!NT_SUCCESS(Status))
{
//
// failed to create status descriptor
//
FreeDescriptor(SetupDescriptor);
m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
return Status;
}
if (m_TransferBufferLength)
{
//
// FIXME: support more than one data descriptor
//
ASSERT(m_TransferBufferLength < 8192);
//
// now create the data descriptor
//
Status = CreateGeneralTransferDescriptor(&DataDescriptor, 0);
if (!NT_SUCCESS(Status))
{
//
// failed to create status descriptor
//
m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
FreeDescriptor(SetupDescriptor);
FreeDescriptor(StatusDescriptor);
return Status;
}
//
// initialize data descriptor
//
DataDescriptor->Flags = OHCI_TD_BUFFER_ROUNDING| OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_TOGGLE_CARRY | OHCI_TD_DIRECTION_PID_IN;
//
// store physical address of buffer
//
DataDescriptor->BufferPhysical = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1;
}
//
// initialize setup descriptor
//
SetupDescriptor->Flags = OHCI_TD_DIRECTION_PID_SETUP | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
if (m_SetupPacket)
{
//
// copy setup packet
//
RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
}
else
{
//
// generate setup packet from urb
//
ASSERT(FALSE);
}
//
// initialize status descriptor
//
StatusDescriptor->Flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
if (m_TransferBufferLength == 0)
{
//
// input direction is flipped for the status descriptor
//
StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
}
else
{
//
// output direction is flipped for the status descriptor
//
StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_OUT;
}
//
// now link the descriptors
//
if (m_TransferBufferLength)
{
//
// link setup descriptor to data descriptor
//
SetupDescriptor->NextPhysicalDescriptor = DataDescriptor->PhysicalAddress.LowPart;
//
// FIXME: should link to last data descriptor to status descriptor
//
DataDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
}
else
{
//
// link setup descriptor to status descriptor
//
SetupDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
}
//
// now link descriptor to endpoint
//
EndpointDescriptor->HeadPhysicalDescriptor = SetupDescriptor->PhysicalAddress.LowPart;
EndpointDescriptor->TailPhysicalDescriptor = SetupDescriptor->PhysicalAddress.LowPart;
DPRINT1("CUSBRequest::BuildControlTransferDescriptor done\n");
//
// store result
//
*OutEndpointDescriptor = EndpointDescriptor;
//
// done
//
return STATUS_SUCCESS;
}
//----------------------------------------------------------------------------------------
NTSTATUS
CUSBRequest::GetEndpointDescriptor(
struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
{
ULONG TransferType;
NTSTATUS Status;
//
// get transfer type
//
TransferType = InternalGetTransferType();
//
// build request depending on type
//
switch(TransferType)
{
case USB_ENDPOINT_TYPE_CONTROL:
Status = BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
break;
case USB_ENDPOINT_TYPE_BULK:
DPRINT1("USB_ENDPOINT_TYPE_BULK not implemented\n");
Status = STATUS_NOT_IMPLEMENTED; //BuildBulkTransferQueueHead(OutDescriptor);
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;
default:
PC_ASSERT(FALSE);
Status = STATUS_NOT_IMPLEMENTED;
break;
}
if (NT_SUCCESS(Status))
{
//
// store queue head
//
//m_QueueHead = *OutDescriptor;
//
// store request object
//
(*OutDescriptor)->Request = PVOID(this);
}
//
// done
//
return Status;
}
//----------------------------------------------------------------------------------------
VOID