From 667b425b6c9ac16ffc30f1465c279d482ae82e30 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Thu, 26 May 2011 02:15:11 +0000 Subject: [PATCH] [USBOHCI] - Remove dead code - Silence traces - Pass status & DoneHead as parameters to dpc routine - Move IUSBRequest cleanup code into new function and use it for bulk / control transfer cleanup - Fix bugs in AllocateEndpointDescriptor. It did not take the device address into account. It also did not respect the direction of the descriptor - Implement support for bulk transfer requests - Handle irp completion in CompletionCallback - Tested in Windows XP SP3 + Vbox 4.04 + USB2.0 disabled + ReactOS usbstor + USB mass storage device - OHCI Mass storage support is now also ready - Next interrupt transfers svn path=/branches/usb-bringup/; revision=51917 --- drivers/usb/usbohci/hardware.cpp | 32 +-- drivers/usb/usbohci/hardware.h | 2 + drivers/usb/usbohci/interfaces.h | 8 + drivers/usb/usbohci/usb_queue.cpp | 100 +++++++-- drivers/usb/usbohci/usb_request.cpp | 329 +++++++++++++++++++++++++--- 5 files changed, 392 insertions(+), 79 deletions(-) diff --git a/drivers/usb/usbohci/hardware.cpp b/drivers/usb/usbohci/hardware.cpp index 9f5ea16d277..f64a3323e98 100644 --- a/drivers/usb/usbohci/hardware.cpp +++ b/drivers/usb/usbohci/hardware.cpp @@ -697,8 +697,6 @@ CUSBHardwareDevice::HeadEndpointDescriptorModified( // // notify controller // - //WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_HEAD_ED_OFFSET), m_ControlEndpointDescriptor->NextPhysicalEndpoint); - //WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_CURRENT_ED_OFFSET), m_ControlEndpointDescriptor->NextPhysicalEndpoint); WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), Value | OHCI_CONTROL_LIST_FILLED); } else if (Type == USB_ENDPOINT_TYPE_BULK) @@ -708,12 +706,6 @@ CUSBHardwareDevice::HeadEndpointDescriptorModified( // WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), Value | OHCI_BULK_LIST_FILLED); } - - Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET)); - - - DPRINT1("HeadEndpointDescriptorModified Value %x Type %x\n", Value, Type); - } NTSTATUS @@ -1191,7 +1183,7 @@ InterruptServiceRoutine( // This = (CUSBHardwareDevice*) ServiceContext; - DPRINT1("InterruptServiceRoutine\n"); + DPRINT("InterruptServiceRoutine\n"); // // get done head @@ -1246,6 +1238,7 @@ InterruptServiceRoutine( // head completed // Acknowledge |= OHCI_WRITEBACK_DONE_HEAD; + This->m_HCCA->DoneHead = 0; } if (Status & OHCI_RESUME_DETECTED) @@ -1296,8 +1289,8 @@ InterruptServiceRoutine( // // defer processing // - DPRINT1("Status %x\n", Status); - KeInsertQueueDpc(&This->m_IntDpcObject, This, (PVOID)Status); + DPRINT("Status %x Acknowledge %x\n", Status, Acknowledge); + KeInsertQueueDpc(&This->m_IntDpcObject, (PVOID)Status, (PVOID)(DoneHead & ~1)); // // interrupt handled @@ -1321,23 +1314,14 @@ OhciDefferedRoutine( // // get parameters // - This = (CUSBHardwareDevice*) SystemArgument1; - CStatus = (ULONG) SystemArgument2; + This = (CUSBHardwareDevice*)DeferredContext; + CStatus = (ULONG) SystemArgument1; + DoneHead = (ULONG)SystemArgument2; - DPRINT1("OhciDefferedRoutine Status %x\n", CStatus); + DPRINT("OhciDefferedRoutine Status %x\n", CStatus); if (CStatus & OHCI_WRITEBACK_DONE_HEAD) { - // - // descriptor completion, get done head - // - DoneHead = This->m_HCCA->DoneHead; - - // - // clear out lower bits, ed are 16 byte aligned - // - DoneHead &= ~0xF; - // // notify queue of event // diff --git a/drivers/usb/usbohci/hardware.h b/drivers/usb/usbohci/hardware.h index 08580fcfe4d..c9afa4c63a6 100644 --- a/drivers/usb/usbohci/hardware.h +++ b/drivers/usb/usbohci/hardware.h @@ -216,6 +216,8 @@ typedef struct _OHCI_ENDPOINT_DESCRIPTOR #define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s) ((s) << 16) #define OHCI_ENDPOINT_LOW_SPEED 0x00002000 #define OHCI_ENDPOINT_FULL_SPEED 0x00000000 +#define OHCI_ENDPOINT_DIRECTION_OUT 0x00000800 +#define OHCI_ENDPOINT_DIRECTION_IN 0x00001000 // // Maximum port count set by OHCI diff --git a/drivers/usb/usbohci/interfaces.h b/drivers/usb/usbohci/interfaces.h index 3c3b5e2fc43..311807dbbe1 100644 --- a/drivers/usb/usbohci/interfaces.h +++ b/drivers/usb/usbohci/interfaces.h @@ -443,6 +443,14 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown) // Description: notifies request that the endpoint descriptor is complete virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) = 0; + +//----------------------------------------------------------------------------------------- +// +// FreeEndpointDescriptor +// +// Description: frees the associated endpoint descriptor and its general descriptors + + virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) = 0; }; diff --git a/drivers/usb/usbohci/usb_queue.cpp b/drivers/usb/usbohci/usb_queue.cpp index 783c2935d96..bbb99653066 100644 --- a/drivers/usb/usbohci/usb_queue.cpp +++ b/drivers/usb/usbohci/usb_queue.cpp @@ -44,6 +44,7 @@ public: // local functions BOOLEAN IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress); NTSTATUS FindTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor); + VOID CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor); // constructor / destructor CUSBQueue(IUnknown *OuterUnknown){} @@ -127,7 +128,7 @@ CUSBQueue::AddUSBRequest( POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor; POHCI_ENDPOINT_DESCRIPTOR Descriptor; - DPRINT1("CUSBQueue::AddUSBRequest\n"); + DPRINT("CUSBQueue::AddUSBRequest\n"); // // sanity check @@ -146,11 +147,11 @@ CUSBQueue::AddUSBRequest( { case USB_ENDPOINT_TYPE_ISOCHRONOUS: case USB_ENDPOINT_TYPE_INTERRUPT: - case USB_ENDPOINT_TYPE_BULK: /* NOT IMPLEMENTED IN QUEUE */ Status = STATUS_NOT_SUPPORTED; break; case USB_ENDPOINT_TYPE_CONTROL: + case USB_ENDPOINT_TYPE_BULK: Status = STATUS_SUCCESS; break; default: @@ -228,12 +229,14 @@ CUSBQueue::AddUSBRequest( Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP; //HeadDescriptor->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); + + // // notify hardware of our request // m_Hardware->HeadEndpointDescriptorModified(Type); - DPRINT1("Request %x %x added to queue\n", Descriptor, Descriptor->PhysicalAddress); return STATUS_SUCCESS; @@ -356,6 +359,47 @@ CUSBQueue::IsTransferDescriptorInEndpoint( return FALSE; } +VOID +CUSBQueue::CleanupEndpointDescriptor( + POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, + POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor) +{ + PUSBREQUEST Request; + + // + // FIXME: verify unlinking process + // + PreviousEndpointDescriptor->NextDescriptor = EndpointDescriptor->NextDescriptor; + PreviousEndpointDescriptor->NextPhysicalEndpoint = EndpointDescriptor->NextPhysicalEndpoint; + + // + // get corresponding request + // + Request = PUSBREQUEST(EndpointDescriptor->Request); + ASSERT(Request); + + // + // notify of completion + // + Request->CompletionCallback(EndpointDescriptor); + + // + // free endpoint descriptor + // + Request->FreeEndpointDescriptor(EndpointDescriptor); + + // + // FIXME: check if complete + // + //ASSERT(Request->IsRequestComplete()); + + // + // release request + // + Request->Release(); + +} + VOID CUSBQueue::TransferDescriptorCompletionCallback( @@ -363,7 +407,8 @@ CUSBQueue::TransferDescriptorCompletionCallback( { POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor; NTSTATUS Status; - PUSBREQUEST Request; + + DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress); // // find transfer descriptor in control list @@ -372,32 +417,39 @@ CUSBQueue::TransferDescriptorCompletionCallback( if (NT_SUCCESS(Status)) { // - // FIXME: make sure this is ok - // unlink descriptor + // cleanup endpoint // - PreviousEndpointDescriptor->NextDescriptor = EndpointDescriptor->NextDescriptor; - PreviousEndpointDescriptor->NextPhysicalEndpoint = EndpointDescriptor->NextPhysicalEndpoint; + CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor); // - // get corresponding request + // done // - Request = PUSBREQUEST(EndpointDescriptor->Request); - - // - // notify of completion - // - Request->CompletionCallback(EndpointDescriptor); - - // - // FIXME: check if complete - // - ASSERT(Request->IsRequestComplete()); - // - // release request - // - Request->Release(); + return; } + // + // find transfer descriptor in bulk list + // + Status = FindTransferDescriptorInEndpoint(m_BulkHeadEndpointDescriptor, TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor); + if (NT_SUCCESS(Status)) + { + // + // cleanup endpoint + // + CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor); + + // + // done + // + return; + } + + // + // hardware reported dead endpoint completed + // + DPRINT1("CUSBQueue::TransferDescriptorCompletionCallback invalid transfer descriptor %x\n", TransferDescriptorLogicalAddress); + ASSERT(FALSE); + } diff --git a/drivers/usb/usbohci/usb_request.cpp b/drivers/usb/usbohci/usb_request.cpp index 38fdfd57101..a1442542ad8 100644 --- a/drivers/usb/usbohci/usb_request.cpp +++ b/drivers/usb/usbohci/usb_request.cpp @@ -45,6 +45,7 @@ public: virtual BOOLEAN IsRequestInitialized(); virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead); virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor); + virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor); // local functions ULONG InternalGetTransferType(); @@ -53,6 +54,7 @@ public: NTSTATUS BuildSetupPacket(); NTSTATUS BuildSetupPacketFromURB(); NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor); + NTSTATUS BuildBulkInterruptEndpoint(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); @@ -606,10 +608,36 @@ CUSBRequest::AllocateEndpointDescriptor( // // append device address and endpoint number // - Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(m_DeviceAddress); + Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(GetDeviceAddress()); Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress()); Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize()); + // + // is there an endpoint descriptor + // + if (m_EndpointDescriptor) + { + // + // check direction + // + if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor->bEndpointAddress)) + { + // + // direction out + // + Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_OUT; + } + else + { + // + // direction in + // + Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_IN; + } + + } + + // // FIXME: detect type // @@ -631,6 +659,198 @@ CUSBRequest::AllocateEndpointDescriptor( return STATUS_SUCCESS; } +NTSTATUS +CUSBRequest::BuildBulkInterruptEndpoint( + POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor) +{ + POHCI_GENERAL_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor, LastDescriptor; + POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor; + ULONG BufferSize, CurrentSize, Direction, MaxLengthInPage; + NTSTATUS Status; + PVOID Buffer; + + // + // allocate endpoint descriptor + // + Status = AllocateEndpointDescriptor(&EndpointDescriptor); + if (!NT_SUCCESS(Status)) + { + // + // failed to create setup descriptor + // + return Status; + } + + // + // allocate transfer descriptor for last descriptor + // + Status = CreateGeneralTransferDescriptor(&LastDescriptor, 0); + if (!NT_SUCCESS(Status)) + { + // + // failed to create transfer descriptor + // + m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); + return Status; + } + + // + // get buffer size + // + BufferSize = m_TransferBufferLength; + ASSERT(BufferSize); + ASSERT(m_TransferBufferMDL); + + // + // get buffer + // + Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority); + ASSERT(Buffer); + + if (InternalGetPidDirection()) + { + // + // input direction + // + Direction = OHCI_TD_DIRECTION_PID_IN; + } + else + { + // + // output direction + // + Direction = OHCI_TD_DIRECTION_PID_OUT; + } + + do + { + // + // get current buffersize + // + CurrentSize = min(8192, BufferSize); + + // + // get page offset + // + MaxLengthInPage = PAGE_SIZE - BYTE_OFFSET(Buffer); + + // + // get minimum from current page size + // + CurrentSize = min(CurrentSize, MaxLengthInPage); + ASSERT(CurrentSize); + + // + // allocate transfer descriptor + // + Status = CreateGeneralTransferDescriptor(&CurrentDescriptor, 0); + if (!NT_SUCCESS(Status)) + { + // + // failed to create transfer descriptor + // TODO: cleanup + // + ASSERT(FALSE); + m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); + FreeDescriptor(LastDescriptor); + return Status; + } + + // + // initialize descriptor + // + CurrentDescriptor->Flags = Direction | 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; + + // + // store physical address of buffer + // + CurrentDescriptor->BufferPhysical = MmGetPhysicalAddress(Buffer).LowPart; + CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + CurrentSize - 1; + + // + // is there a previous descriptor + // + if (PreviousDescriptor) + { + // + // link descriptors + // + PreviousDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor; + PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart; + } + else + { + // + // it is the first descriptor + // + FirstDescriptor = CurrentDescriptor; + } + + DPRINT("PreviousDescriptor %p CurrentDescriptor %p Buffer Logical %p Physical %x Last Physical %x CurrentSize %lu\n", PreviousDescriptor, CurrentDescriptor, CurrentDescriptor->BufferLogical, CurrentDescriptor->BufferPhysical, CurrentDescriptor->LastPhysicalByteAddress, CurrentSize); + + // + // set previous descriptor + // + PreviousDescriptor = CurrentDescriptor; + + // + // subtract buffer size + // + BufferSize -= CurrentSize; + + // + // increment buffer offset + // + Buffer = (PVOID)((ULONG_PTR)Buffer + CurrentSize); + + }while(BufferSize); + + // + // first descriptor has no carry bit + // + FirstDescriptor->Flags &= ~OHCI_TD_TOGGLE_CARRY; + + // + // fixme: toggle + // + FirstDescriptor->Flags |= OHCI_TD_TOGGLE_0; + + // + // 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); + + // + // link last data descriptor to last descriptor + // + CurrentDescriptor->NextLogicalDescriptor = LastDescriptor; + CurrentDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart; + + // + // now link descriptor to endpoint + // + EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart; + EndpointDescriptor->TailPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart; + EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor; + + // + // store result + // + *OutEndpointDescriptor = EndpointDescriptor; + + // + // done + // + return STATUS_SUCCESS; + +} + + NTSTATUS CUSBRequest::BuildControlTransferDescriptor( POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor) @@ -639,8 +859,6 @@ CUSBRequest::BuildControlTransferDescriptor( POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor; NTSTATUS Status; - DPRINT1("CUSBRequest::BuildControlTransferDescriptor\n"); - // // allocate endpoint descriptor // @@ -695,7 +913,6 @@ CUSBRequest::BuildControlTransferDescriptor( return Status; } - if (m_TransferBufferLength) { // @@ -729,6 +946,7 @@ CUSBRequest::BuildControlTransferDescriptor( // DataDescriptor->BufferPhysical = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart; DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1; + } // @@ -849,12 +1067,8 @@ CUSBRequest::GetEndpointDescriptor( 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; + Status = BuildBulkInterruptEndpoint(OutDescriptor); break; case USB_ENDPOINT_TYPE_ISOCHRONOUS: DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n"); @@ -919,32 +1133,24 @@ CUSBRequest::GetResultStatus( } - VOID -CUSBRequest::CompletionCallback( +CUSBRequest::FreeEndpointDescriptor( struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) { POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor; - DPRINT1("CUSBRequest::CompletionCallback\n"); - - // - // set status code - // - m_NtStatusCode = STATUS_SUCCESS; - m_UrbStatusCode = USBD_STATUS_SUCCESS; - - ASSERT(!m_Irp); - - // - // FIXME: cleanup descriptors - // + DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart); // // get first general transfer descriptor // TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor; + // + // release endpoint descriptor + // + m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); + while(TransferDescriptor) { // @@ -963,6 +1169,8 @@ CUSBRequest::CompletionCallback( m_DmaManager->Release(TransferDescriptor->BufferLogical, TransferDescriptor->BufferSize); } + DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor, TransferDescriptor->PhysicalAddress.LowPart, TransferDescriptor->BufferPhysical, TransferDescriptor->LastPhysicalByteAddress); + // // release descriptor // @@ -974,16 +1182,75 @@ CUSBRequest::CompletionCallback( TransferDescriptor = NextTransferDescriptor; } - // - // release endpoint descriptor - // - m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); +} + +VOID +CUSBRequest::CompletionCallback( + struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) +{ + POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor; + PIO_STACK_LOCATION IoStack; + PURB Urb; + + DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart); // - // signal completion event + // set status code // - PC_ASSERT(m_CompletionEvent); - KeSetEvent(m_CompletionEvent, 0, FALSE); + m_NtStatusCode = STATUS_SUCCESS; + m_UrbStatusCode = USBD_STATUS_SUCCESS; + + if (m_Irp) + { + // + // set irp completion status + // + m_Irp->IoStatus.Status = STATUS_SUCCESS; //FIXME + + // + // get current irp stack location + // + IoStack = IoGetCurrentIrpStackLocation(m_Irp); + + // + // get urb + // + Urb = (PURB)IoStack->Parameters.Others.Argument1; + + // + // store urb status + // + Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; //FIXME + + // + // Check if the MDL was created + // + if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL) + { + // + // Free Mdl + // + IoFreeMdl(m_TransferBufferMDL); + } + + // + // FIXME: support status and calculate length + // + + // + // FIXME: check if the transfer was split + // if yes dont complete irp yet + // + IoCompleteRequest(m_Irp, IO_NO_INCREMENT); + } + else + { + // + // signal completion event + // + PC_ASSERT(m_CompletionEvent); + KeSetEvent(m_CompletionEvent, 0, FALSE); + } }