From: Johannes Anderwald Date: Fri, 27 May 2011 13:04:55 +0000 (+0000) Subject: [USBOHCI] X-Git-Tag: backups/usb-bringup@55523~54 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=2231c8333a038808328a88b6f23419d122a69d17 [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 --- diff --git a/drivers/usb/usbohci/hardware.cpp b/drivers/usb/usbohci/hardware.cpp index 1d53c8f1cff..e4650c1874e 100644 --- a/drivers/usb/usbohci/hardware.cpp +++ b/drivers/usb/usbohci/hardware.cpp @@ -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( diff --git a/drivers/usb/usbohci/hardware.h b/drivers/usb/usbohci/hardware.h index 864b96d0d97..cf4fb544f9d 100644 --- a/drivers/usb/usbohci/hardware.h +++ b/drivers/usb/usbohci/hardware.h @@ -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 + diff --git a/drivers/usb/usbohci/hub_controller.cpp b/drivers/usb/usbohci/hub_controller.cpp index 1f6bc559ce9..24e08a82c75 100644 --- a/drivers/usb/usbohci/hub_controller.cpp +++ b/drivers/usb/usbohci/hub_controller.cpp @@ -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; + } + + // + // check if this is a valid usb device handle + // + ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))); // - // FIXME need more flags ? + // get device // - *Status = USB_PORT_STATUS_CONNECT; + 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) diff --git a/drivers/usb/usbohci/interfaces.h b/drivers/usb/usbohci/interfaces.h index 582b7fb4740..e7920e2c77e 100644 --- a/drivers/usb/usbohci/interfaces.h +++ b/drivers/usb/usbohci/interfaces.h @@ -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; diff --git a/drivers/usb/usbohci/usb_queue.cpp b/drivers/usb/usbohci/usb_queue.cpp index 5880b61c03e..a9773506922 100644 --- a/drivers/usb/usbohci/usb_queue.cpp +++ b/drivers/usb/usbohci/usb_queue.cpp @@ -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; } diff --git a/drivers/usb/usbohci/usb_request.cpp b/drivers/usb/usbohci/usb_request.cpp index f3db44a87b6..dcb9c19388e 100644 --- a/drivers/usb/usbohci/usb_request.cpp +++ b/drivers/usb/usbohci/usb_request.cpp @@ -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;