[USBOHCI]

- Implement function to retrieve isochronous head endpoint descriptor
- Implement function to retrieve current frame number
- Set isochronous descriptor flag for head endpoint
- Implement retrieve device status for devices
- Implement retrieve class status from device
- Partly implement isochronous descriptor handling in usb queue
- Start implementing isochronous transfers in ISUBRequest
- Code currently not tested as the Virtual Machine with XP + ReactOS usbohci driver brings down the host system when starting the iso transfers. Ironically it crashes in MS usbohci driver


svn path=/branches/usb-bringup/; revision=51957
This commit is contained in:
Johannes Anderwald 2011-05-27 13:04:55 +00:00
parent 9aff3e967c
commit 2231c8333a
6 changed files with 503 additions and 45 deletions

View file

@ -62,8 +62,10 @@ public:
NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
NTSTATUS GetInterruptEndpointDescriptors(struct _OHCI_ENDPOINT_DESCRIPTOR *** OutDescriptor);
NTSTATUS GetIsochronousHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor);
VOID HeadEndpointDescriptorModified(ULONG HeadType);
NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager);
NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue);
@ -80,6 +82,7 @@ public:
KIRQL AcquireDeviceLock(void);
VOID ReleaseDeviceLock(KIRQL OldLevel);
virtual VOID GetCurrentFrameNumber(PULONG FrameNumber);
// local
BOOLEAN InterruptService();
NTSTATUS InitializeController();
@ -698,6 +701,17 @@ CUSBHardwareDevice::GetInterruptEndpointDescriptors(
return STATUS_SUCCESS;
}
NTSTATUS
CUSBHardwareDevice::GetIsochronousHeadEndpointDescriptor(
struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor)
{
//
// get descriptor
//
*OutDescriptor = m_IsoEndpointDescriptor;
return STATUS_SUCCESS;
}
VOID
CUSBHardwareDevice::HeadEndpointDescriptorModified(
ULONG Type)
@ -848,6 +862,11 @@ CUSBHardwareDevice::InitializeController()
//
m_InterruptEndpoints[0]->NextPhysicalEndpoint = m_IsoEndpointDescriptor->PhysicalAddress.LowPart;
//
// set iso endpoint type
//
m_IsoEndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
//
// done
//
@ -1183,6 +1202,15 @@ CUSBHardwareDevice::AcquireDeviceLock(void)
return OldLevel;
}
VOID
CUSBHardwareDevice::GetCurrentFrameNumber(
PULONG FrameNumber)
{
//
// store frame number
//
*FrameNumber = m_HCCA->CurrentFrameNumber;
}
VOID
CUSBHardwareDevice::ReleaseDeviceLock(

View file

@ -231,6 +231,8 @@ typedef struct _OHCI_ENDPOINT_DESCRIPTOR
#define OHCI_ENDPOINT_FULL_SPEED 0x00000000
#define OHCI_ENDPOINT_DIRECTION_OUT 0x00000800
#define OHCI_ENDPOINT_DIRECTION_IN 0x00001000
#define OHCI_ENDPOINT_GENERAL_FORMAT 0x00000000
#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000
//
// Maximum port count set by OHCI
@ -293,3 +295,35 @@ typedef struct
#define OHCI_TD_CONDITION_BUFFER_OVERRUN 0x0c
#define OHCI_TD_CONDITION_BUFFER_UNDERRUN 0x0d
#define OHCI_TD_CONDITION_NOT_ACCESSED 0x0f
// --------------------------------
// Isochronous transfer descriptor structure (section 4.3.2)
// --------------------------------
#define OHCI_ITD_NOFFSET 8
typedef struct _OHCI_ISO_TD_
{
// Hardware part 32 byte
ULONG Flags;
ULONG BufferPhysical; // Physical page number of byte 0
ULONG NextPhysicalDescriptor; // Next isochronous transfer descriptor
ULONG LastPhysicalByteAddress; // Physical buffer end
ULONG Offset[OHCI_ITD_NOFFSET]; // Buffer offsets
// Software part
PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this descriptor
struct _OHCI_ISO_TD_ * NextLogicalDescriptor; // Logical pointer next descriptor
}OHCI_ISO_TD, *POHCI_ISO_TD;
#define OHCI_ITD_GET_STARTING_FRAME(x) ((x) & 0x0000ffff)
#define OHCI_ITD_SET_STARTING_FRAME(x) ((x) & 0xffff)
#define OHCI_ITD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7)
#define OHCI_ITD_SET_DELAY_INTERRUPT(x) ((x) << 21)
#define OHCI_ITD_NO_INTERRUPT 0x00e00000
#define OHCI_ITD_GET_FRAME_COUNT(x) ((((x) >> 24) & 7) + 1)
#define OHCI_ITD_SET_FRAME_COUNT(x) (((x) - 1) << 24)
#define OHCI_ITD_GET_CONDITION_CODE(x) ((x) >> 28)
#define OHCI_ITD_NO_CONDITION_CODE 0xf0000000

View file

@ -1119,7 +1119,10 @@ CHubController::HandleGetStatusFromDevice(
IN OUT PIRP Irp,
PURB Urb)
{
PUSHORT Status;
PUSHORT DeviceStatus;
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
NTSTATUS Status;
PUSBDEVICE UsbDevice;
//
// sanity checks
@ -1127,22 +1130,54 @@ CHubController::HandleGetStatusFromDevice(
PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL);
//
// get status buffer
//
Status = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
{
//
// FIXME need more flags ?
//
*DeviceStatus = USB_PORT_STATUS_CONNECT;
return STATUS_SUCCESS;
}
//
// FIXME need more flags ?
// check if this is a valid usb device handle
//
*Status = USB_PORT_STATUS_CONNECT;
ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
//
// get device
//
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
//
// generate setup packet
//
CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
CtrlSetup.wValue.LowByte = 0;
CtrlSetup.wValue.HiByte = 0;
CtrlSetup.wIndex.W = Urb->UrbControlGetStatusRequest.Index;
CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
CtrlSetup.bmRequestType.B = 0x80;
//
// submit setup packet
//
Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
ASSERT(Status == STATUS_SUCCESS);
DPRINT1("CHubController::HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus);
//
// done
//
return STATUS_SUCCESS;
return Status;
}
//-----------------------------------------------------------------------------------------
@ -1155,6 +1190,8 @@ CHubController::HandleClassDevice(
PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
ULONG PortCount, Dummy2;
USHORT Dummy1;
PUSBDEVICE UsbDevice;
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
@ -1163,6 +1200,36 @@ CHubController::HandleClassDevice(
//
switch(Urb->UrbControlVendorClassRequest.Request)
{
case USB_REQUEST_GET_STATUS:
{
//
// check if this is a valid usb device handle
//
ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
//
// get device
//
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
//
// generate setup packet
//
CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
CtrlSetup.wValue.LowByte = Urb->UrbControlVendorClassRequest.Index;
CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
CtrlSetup.bmRequestType.B = 0xA0;
//
// submit setup packet
//
Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
ASSERT(Status == STATUS_SUCCESS);
break;
}
case USB_REQUEST_GET_DESCRIPTOR:
{
switch (Urb->UrbControlVendorClassRequest.Value >> 8)

View file

@ -188,6 +188,15 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown)
virtual NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
//-----------------------------------------------------------------------------------------
//
// GetIsochronousHeadEndpointDescriptor
//
// Description: returns the control head endpoint descriptor
virtual NTSTATUS GetIsochronousHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0;
//-----------------------------------------------------------------------------------------
//
// GetInterruptEndpointDescriptors
@ -301,6 +310,14 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown)
// Description: releases the device lock
virtual void ReleaseDeviceLock(KIRQL OldLevel) = 0;
//----------------------------------------------------------------------------------------
//
// GetCurrentFrameNumber
//
// Description: returns the current frame number
virtual VOID GetCurrentFrameNumber(PULONG FrameNumber) = 0;
};
typedef IUSBHardwareDevice *PUSBHARDWAREDEVICE;

View file

@ -61,6 +61,7 @@ protected:
PUSBHARDWAREDEVICE m_Hardware; // hardware
POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor; // bulk head descriptor
POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor; // control head descriptor
POHCI_ENDPOINT_DESCRIPTOR m_IsoHeadEndpointDescriptor; // isochronous head descriptor
POHCI_ENDPOINT_DESCRIPTOR * m_InterruptEndpoints;
};
@ -100,6 +101,9 @@ CUSBQueue::Initialize(
//
Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor);
//
Hardware->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor);
//
// get interrupt endpoints
//
@ -164,6 +168,8 @@ CUSBQueue::AddUSBRequest(
KIRQL OldLevel;
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
POHCI_ENDPOINT_DESCRIPTOR Descriptor;
POHCI_ISO_TD CurrentDescriptor;
ULONG FrameNumber;
DPRINT("CUSBQueue::AddUSBRequest\n");
@ -177,39 +183,6 @@ CUSBQueue::AddUSBRequest(
//
Type = Request->GetTransferType();
//
// check if supported
//
switch(Type)
{
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
/* NOT IMPLEMENTED IN QUEUE */
Status = STATUS_NOT_SUPPORTED;
break;
case USB_ENDPOINT_TYPE_INTERRUPT:
case USB_ENDPOINT_TYPE_CONTROL:
case USB_ENDPOINT_TYPE_BULK:
Status = STATUS_SUCCESS;
break;
default:
/* BUG */
PC_ASSERT(FALSE);
Status = STATUS_NOT_SUPPORTED;
}
//
// check for success
//
if (!NT_SUCCESS(Status))
{
//
// request not supported, please try later
//
DPRINT1("Request Type %x not supported\n", Type);
ASSERT(FALSE);
return Status;
}
//
// add extra reference which is released when the request is completed
//
@ -258,6 +231,48 @@ CUSBQueue::AddUSBRequest(
HeadDescriptor = FindInterruptEndpointDescriptor(Request->GetInterval());
ASSERT(HeadDescriptor);
}
else if (Type == USB_ENDPOINT_TYPE_ISOCHRONOUS)
{
//
// get head descriptor
//
HeadDescriptor = m_IsoHeadEndpointDescriptor;
//
// get current frame number
//
m_Hardware->GetCurrentFrameNumber(&FrameNumber);
//
// increment frame number
//
FrameNumber++;
//
// apply frame number to iso transfer descriptors
//
CurrentDescriptor = (POHCI_ISO_TD)Descriptor->HeadLogicalDescriptor;
DPRINT1("ISO: NextFrameNumber %x\n", FrameNumber);
while(CurrentDescriptor)
{
//
// set current frame number
//
CurrentDescriptor->Flags |= OHCI_ITD_SET_STARTING_FRAME(FrameNumber);
//
// move to next frame number
//
FrameNumber++;
//
// move to next descriptor
//
CurrentDescriptor = CurrentDescriptor->NextLogicalDescriptor;
}
}
//
// insert endpoint at end
@ -269,9 +284,6 @@ CUSBQueue::AddUSBRequest(
//
Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP;
DPRINT("Request %x Logical %x added to queue Queue %p Logical %x\n", Descriptor, Descriptor->PhysicalAddress.LowPart, HeadDescriptor, HeadDescriptor->PhysicalAddress.LowPart);
if (Type == USB_ENDPOINT_TYPE_CONTROL || Type == USB_ENDPOINT_TYPE_BULK)
{
//
@ -280,6 +292,7 @@ CUSBQueue::AddUSBRequest(
m_Hardware->HeadEndpointDescriptorModified(Type);
}
return STATUS_SUCCESS;
}

View file

@ -57,9 +57,11 @@ public:
NTSTATUS BuildSetupPacketFromURB();
NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
NTSTATUS BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor);
NTSTATUS BuildIsochronousEndpoint(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);
NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD *OutDescriptor, ULONG FrameCount);
UCHAR GetEndpointAddress();
USHORT GetMaxPacketSize();
@ -243,6 +245,81 @@ CUSBRequest::InitializeWithIrp(
//
switch (Urb->UrbHeader.Function)
{
case URB_FUNCTION_ISOCH_TRANSFER:
{
//
// there must be at least one packet
//
ASSERT(Urb->UrbIsochronousTransfer.NumberOfPackets);
//
// is there data to be transferred
//
if (Urb->UrbIsochronousTransfer.TransferBufferLength)
{
//
// Check if there is a MDL
//
if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
{
//
// sanity check
//
PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
//
// Create one using TransferBuffer
//
DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
FALSE,
FALSE,
NULL);
if (!m_TransferBufferMDL)
{
//
// failed to allocate mdl
//
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// build mdl for non paged pool
// FIXME: Does hub driver already do this when passing MDL?
//
MmBuildMdlForNonPagedPool(m_TransferBufferMDL);
}
else
{
//
// use provided mdl
//
m_TransferBufferMDL = Urb->UrbIsochronousTransfer.TransferBufferMDL;
}
}
//
// save buffer length
//
m_TransferBufferLength = Urb->UrbIsochronousTransfer.TransferBufferLength;
//
// Set Length Completed to 0
//
m_TransferBufferLengthCompleted = 0;
//
// get endpoint descriptor
//
m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbIsochronousTransfer.PipeHandle;
//
// completed initialization
//
break;
}
//
// luckily those request have the same structure layout
//
@ -525,6 +602,230 @@ CUSBRequest::FreeDescriptor(
m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD));
}
//----------------------------------------------------------------------------------------
NTSTATUS
CUSBRequest::CreateIsochronousTransferDescriptor(
POHCI_ISO_TD* OutDescriptor,
ULONG FrameCount)
{
POHCI_ISO_TD Descriptor;
PHYSICAL_ADDRESS DescriptorAddress;
NTSTATUS Status;
//
// allocate transfer descriptor
//
Status = m_DmaManager->Allocate(sizeof(OHCI_ISO_TD), (PVOID*)&Descriptor, &DescriptorAddress);
if (!NT_SUCCESS(Status))
{
//
// no memory
//
return Status;
}
//
// initialize descriptor, hardware part
//
Descriptor->Flags = OHCI_ITD_SET_FRAME_COUNT(FrameCount) | OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED);
Descriptor->BufferPhysical = 0;
Descriptor->NextPhysicalDescriptor = 0;
Descriptor->LastPhysicalByteAddress = 0;
//
// software part
//
Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart;
Descriptor->NextLogicalDescriptor = 0;
//
// store result
//
*OutDescriptor = Descriptor;
//
// done
//
return STATUS_SUCCESS;
}
NTSTATUS
CUSBRequest::BuildIsochronousEndpoint(
POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
{
POHCI_ISO_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor;
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
ULONG Index = 0, SubIndex, NumberOfPackets, PageOffset;
NTSTATUS Status;
PVOID Buffer;
PIO_STACK_LOCATION IoStack;
PURB Urb;
DPRINT1("cp\n");
//
// get current irp stack location
//
IoStack = IoGetCurrentIrpStackLocation(m_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;
ASSERT(Urb);
//
// allocate endpoint descriptor
//
Status = AllocateEndpointDescriptor(&EndpointDescriptor);
if (!NT_SUCCESS(Status))
{
//
// failed to create setup descriptor
//
return Status;
}
DPRINT1("cp\n");
//
// get buffer
//
Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
ASSERT(Buffer);
DPRINT1("cp\n");
while(Index < Urb->UrbIsochronousTransfer.NumberOfPackets)
{
//
// get number of packets remaining
//
NumberOfPackets = min(Urb->UrbIsochronousTransfer.NumberOfPackets - Index, OHCI_ITD_NOFFSET);
DPRINT1("cp Number Packets %lu\n", NumberOfPackets);
//
// allocate iso descriptor
//
Status = CreateIsochronousTransferDescriptor(&CurrentDescriptor, NumberOfPackets);
if (!NT_SUCCESS(Status))
{
//
// FIXME: cleanup
// failed to allocate descriptor
//
ASSERT(FALSE);
return Status;
}
DPRINT1("cp\n");
//
// initialize descriptor
//
CurrentDescriptor->BufferPhysical = (MmGetPhysicalAddress(Buffer).LowPart & ~ (PAGE_SIZE - 1));
//
// get page offset
//
PageOffset = BYTE_OFFSET(MmGetPhysicalAddress(Buffer).LowPart);
DPRINT1("cp\n");
for(SubIndex = 0; SubIndex < NumberOfPackets; SubIndex++)
{
//
// store buffer offset
//
CurrentDescriptor->Offset[SubIndex] = Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset + PageOffset;
}
//
// increment packet offset
//
Index += NumberOfPackets;
//
// check if this is the last descriptor
//
if (Index == Urb->UrbIsochronousTransfer.NumberOfPackets)
{
//
// end of transfer
//
CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + m_TransferBufferLength - 1;
}
else
{
//
// use start address of next packet - 1
//
CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + Urb->UrbIsochronousTransfer.IsoPacket[Index + 1].Offset - 1;
//
// move buffer to next address
//
Buffer = (PVOID)((ULONG_PTR)Buffer + Urb->UrbIsochronousTransfer.IsoPacket[Index + 1].Offset);
}
//
// is there a previous descriptor
//
if (PreviousDescriptor)
{
//
// link descriptors
//
PreviousDescriptor->NextLogicalDescriptor = CurrentDescriptor;
PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
}
else
{
//
// first descriptor
//
FirstDescriptor = CurrentDescriptor;
}
//
// store as previous descriptor
//
PreviousDescriptor = CurrentDescriptor;
}
DPRINT1("cp\n");
//
// clear interrupt mask for last transfer descriptor
//
CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
//
// fire interrupt as soon transfer is finished
//
CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
//
// set isochronous type
//
EndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
//
// now link descriptor to endpoint
//
EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
EndpointDescriptor->TailPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
DPRINT1("cp\n");
//
// store result
//
*OutEndpointDescriptor = EndpointDescriptor;
//
// done
//
return STATUS_SUCCESS;
}
//----------------------------------------------------------------------------------------
NTSTATUS
CUSBRequest::CreateGeneralTransferDescriptor(
@ -1084,8 +1385,7 @@ CUSBRequest::GetEndpointDescriptor(
Status = BuildBulkInterruptEndpoint(OutDescriptor);
break;
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
Status = STATUS_NOT_IMPLEMENTED;
Status = BuildIsochronousEndpoint((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor);
break;
default:
PC_ASSERT(FALSE);
@ -1201,7 +1501,6 @@ VOID
CUSBRequest::CompletionCallback(
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
{
POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor;
PIO_STACK_LOCATION IoStack;
PURB Urb;