diff --git a/drivers/usb/usbohci/hardware.cpp b/drivers/usb/usbohci/hardware.cpp index f64a3323e98..1d53c8f1cff 100644 --- a/drivers/usb/usbohci/hardware.cpp +++ b/drivers/usb/usbohci/hardware.cpp @@ -61,6 +61,7 @@ public: NTSTATUS GetDeviceDetails(PUSHORT VendorId, PUSHORT DeviceId, PULONG NumberOfPorts, PULONG Speed); NTSTATUS GetBulkHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor); NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor); + NTSTATUS GetInterruptEndpointDescriptors(struct _OHCI_ENDPOINT_DESCRIPTOR *** OutDescriptor); VOID HeadEndpointDescriptorModified(ULONG HeadType); NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager); @@ -113,16 +114,16 @@ protected: PHYSICAL_ADDRESS m_HCCAPhysicalAddress; // hcca physical address POHCI_ENDPOINT_DESCRIPTOR m_ControlEndpointDescriptor; // dummy control endpoint descriptor POHCI_ENDPOINT_DESCRIPTOR m_BulkEndpointDescriptor; // dummy control endpoint descriptor - POHCI_ENDPOINT_DESCRIPTOR m_IsoEndpointDescriptor; // iso endpoint descriptor + POHCI_ENDPOINT_DESCRIPTOR m_IsoEndpointDescriptor; // iso endpoint descriptor POHCI_ENDPOINT_DESCRIPTOR m_InterruptEndpoints[OHCI_STATIC_ENDPOINT_COUNT]; // endpoints for interrupt / iso transfers ULONG m_NumberOfPorts; // number of ports OHCI_PORT_STATUS m_PortStatus[OHCI_MAX_PORT_COUNT]; // port change status PDMAMEMORYMANAGER m_MemoryManager; // memory manager HD_INIT_CALLBACK* m_SCECallBack; // status change callback routine PVOID m_SCEContext; // status change callback routine context - BOOLEAN m_DoorBellRingInProgress; // door bell ring in progress WORK_QUEUE_ITEM m_StatusChangeWorkItem; // work item for status change callback ULONG m_SyncFramePhysAddr; // periodic frame list physical address + ULONG m_IntervalValue; // periodic interval value }; //================================================================================================= @@ -489,7 +490,7 @@ CUSBHardwareDevice::GetUSBQueue( NTSTATUS CUSBHardwareDevice::StartController(void) { - ULONG Control, NumberOfPorts, Index, Descriptor, FrameInterval, Periodic, IntervalValue; + ULONG Control, NumberOfPorts, Index, Descriptor, FrameInterval, Periodic; // // first write address of HCCA @@ -545,16 +546,19 @@ CUSBHardwareDevice::StartController(void) // // get frame interval // - //FrameInterval = (READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET)) & OHCI_FRAME_INTERVAL_TOGGLE) ^ OHCI_FRAME_INTERVAL_TOGGLE; - //FrameInterval |= OHCI_FSMPS(IntervalValue) | IntervalValue; + FrameInterval = (READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET)) & OHCI_FRAME_INTERVAL_TOGGLE) ^ OHCI_FRAME_INTERVAL_TOGGLE; + FrameInterval |= OHCI_FSMPS(m_IntervalValue) | m_IntervalValue; // // write frame interval // - //WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET), FrameInterval); - // 90% periodic - //Periodic = OHCI_PERIODIC(intervalValue); - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 0x40 /*OHCI_PERIODIC_START_OFFSET*/), 0x3E67); + WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET), FrameInterval); + + // + // 90 % periodic + // + Periodic = OHCI_PERIODIC(m_IntervalValue); + WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_PERIODIC_START_OFFSET), Periodic); // @@ -686,6 +690,14 @@ CUSBHardwareDevice::GetBulkHeadEndpointDescriptor( return STATUS_SUCCESS; } +NTSTATUS +CUSBHardwareDevice::GetInterruptEndpointDescriptors( + struct _OHCI_ENDPOINT_DESCRIPTOR *** OutDescriptor) +{ + *OutDescriptor = m_InterruptEndpoints; + return STATUS_SUCCESS; +} + VOID CUSBHardwareDevice::HeadEndpointDescriptorModified( ULONG Type) @@ -846,7 +858,7 @@ NTSTATUS CUSBHardwareDevice::StopController(void) { ULONG Control, Reset; - ULONG Index; + ULONG Index, FrameInterval; // // first turn off all interrupts @@ -878,6 +890,16 @@ CUSBHardwareDevice::StopController(void) // KeStallExecutionProcessor(100); + // + // read from interval + // + FrameInterval = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET)); + + // + // store interval value for later + // + m_IntervalValue = OHCI_GET_INTERVAL_VALUE(FrameInterval); + // // now reset controller // diff --git a/drivers/usb/usbohci/hardware.h b/drivers/usb/usbohci/hardware.h index c9afa4c63a6..864b96d0d97 100644 --- a/drivers/usb/usbohci/hardware.h +++ b/drivers/usb/usbohci/hardware.h @@ -90,6 +90,19 @@ #define OHCI_RH_NO_OVER_CURRENT_PROTECTION 0x1000 #define OHCI_RH_GET_POWER_ON_TO_POWER_GOOD_TIME(s) ((s) >> 24) +// +// Frame interval register (section 7.3.1) +// +#define OHCI_FRAME_INTERVAL_OFFSET 0x34 +#define OHCI_GET_INTERVAL_VALUE(s) ((s) & 0x3fff) +#define OHCI_GET_FS_LARGEST_DATA_PACKET(s) (((s) >> 16) & 0x7fff) +#define OHCI_FRAME_INTERVAL_TOGGLE 0x80000000 + +// +// periodic start register +// +#define OHCI_PERIODIC_START_OFFSET 0x40 +#define OHCI_PERIODIC(i) ((i) * 9 / 10) // // Root Hub Descriptor B register (section 7.4.2) diff --git a/drivers/usb/usbohci/hub_controller.cpp b/drivers/usb/usbohci/hub_controller.cpp index 9a4b8447098..1f6bc559ce9 100644 --- a/drivers/usb/usbohci/hub_controller.cpp +++ b/drivers/usb/usbohci/hub_controller.cpp @@ -60,6 +60,7 @@ public: VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine); // internal ioctl routines NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb); + NTSTATUS HandleGetDescriptorFromInterface(IN OUT PIRP Irp, PURB Urb); NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb); NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb); NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb); @@ -1223,6 +1224,55 @@ CHubController::HandleClassDevice( return Status; } + +//----------------------------------------------------------------------------------------- +NTSTATUS +CHubController::HandleGetDescriptorFromInterface( + IN OUT PIRP Irp, + IN OUT PURB Urb) +{ + PUSBDEVICE UsbDevice; + USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; + NTSTATUS Status; + + // + // sanity check + // + ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength); + ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); + + // + // 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_DESCRIPTOR; + CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index; + CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType; + CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId; + CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength; + CtrlSetup.bmRequestType.B = 0x81; + + // + // submit setup packet + // + Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer); + ASSERT(Status == STATUS_SUCCESS); + + // + // done + // + return Status; +} + //----------------------------------------------------------------------------------------- NTSTATUS CHubController::HandleGetDescriptor( @@ -1492,8 +1542,8 @@ CHubController::HandleClassInterface( // // sanity check // - PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer); - PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength); + //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL); + //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength); PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); // @@ -1520,7 +1570,7 @@ CHubController::HandleClassInterface( // // initialize setup packet // - CtrlSetup.bmRequestType.B = 0xa1; //FIXME: Const. + CtrlSetup.bmRequestType.B = 0xa1; CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request; CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value; CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index; @@ -1579,6 +1629,9 @@ CHubController::HandleDeviceControl( switch (Urb->UrbHeader.Function) { + case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE: + Status = HandleGetDescriptorFromInterface(Irp, Urb); + break; case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: Status = HandleGetDescriptor(Irp, Urb); break; diff --git a/drivers/usb/usbohci/interfaces.h b/drivers/usb/usbohci/interfaces.h index 311807dbbe1..582b7fb4740 100644 --- a/drivers/usb/usbohci/interfaces.h +++ b/drivers/usb/usbohci/interfaces.h @@ -188,6 +188,14 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown) virtual NTSTATUS GetControlHeadEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) = 0; +//----------------------------------------------------------------------------------------- +// +// GetInterruptEndpointDescriptors +// +// Description: returns interrupt endpoint descriptors + + virtual NTSTATUS GetInterruptEndpointDescriptors(struct _OHCI_ENDPOINT_DESCRIPTOR *** OutDescriptorArray) = 0; + //----------------------------------------------------------------------------------------- // // HeadEndpointDescriptorModified @@ -451,6 +459,15 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown) // Description: frees the associated endpoint descriptor and its general descriptors virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) = 0; + +//----------------------------------------------------------------------------------------- +// +// GetInterruptInterval +// +// Description: returns interval of the iso / interrupt + + virtual UCHAR GetInterval() = 0; + }; diff --git a/drivers/usb/usbohci/usb_queue.cpp b/drivers/usb/usbohci/usb_queue.cpp index bbb99653066..5880b61c03e 100644 --- a/drivers/usb/usbohci/usb_queue.cpp +++ b/drivers/usb/usbohci/usb_queue.cpp @@ -44,7 +44,12 @@ 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); + NTSTATUS FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor); + VOID CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor); + POHCI_ENDPOINT_DESCRIPTOR FindInterruptEndpointDescriptor(UCHAR InterruptInterval); + VOID PrintEndpointList(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor); + VOID LinkEndpoint(POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor); // constructor / destructor CUSBQueue(IUnknown *OuterUnknown){} @@ -56,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_InterruptEndpoints; }; //================================================================================================= @@ -94,6 +100,11 @@ CUSBQueue::Initialize( // Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor); + // + // get interrupt endpoints + // + Hardware->GetInterruptEndpointDescriptors(&m_InterruptEndpoints); + // // initialize spinlock // @@ -118,6 +129,32 @@ CUSBQueue::GetPendingRequestCount() return 0; } +VOID +CUSBQueue::LinkEndpoint( + POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor, + POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor) +{ + POHCI_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor = HeadEndpointDescriptor; + + // + // get last descriptor in queue + // + while(CurrentEndpointDescriptor->NextDescriptor) + { + // + // move to last descriptor + // + CurrentEndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentEndpointDescriptor->NextDescriptor; + } + + // + // link endpoints + // + CurrentEndpointDescriptor->NextPhysicalEndpoint = EndpointDescriptor->PhysicalAddress.LowPart; + CurrentEndpointDescriptor->NextDescriptor = EndpointDescriptor; + +} + NTSTATUS CUSBQueue::AddUSBRequest( IUSBRequest * Request) @@ -146,10 +183,10 @@ CUSBQueue::AddUSBRequest( switch(Type) { case USB_ENDPOINT_TYPE_ISOCHRONOUS: - case USB_ENDPOINT_TYPE_INTERRUPT: /* 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; @@ -213,31 +250,35 @@ CUSBQueue::AddUSBRequest( // HeadDescriptor = m_ControlHeadEndpointDescriptor; } + else if (Type == USB_ENDPOINT_TYPE_INTERRUPT) + { + // + // get head descriptor + // + HeadDescriptor = FindInterruptEndpointDescriptor(Request->GetInterval()); + ASSERT(HeadDescriptor); + } // - // link endpoints + // insert endpoint at end // - Descriptor->NextPhysicalEndpoint = HeadDescriptor->NextPhysicalEndpoint; - Descriptor->NextDescriptor = HeadDescriptor->NextDescriptor; - - HeadDescriptor->NextPhysicalEndpoint = Descriptor->PhysicalAddress.LowPart; - HeadDescriptor->NextDescriptor = Descriptor; + LinkEndpoint(HeadDescriptor, Descriptor); // // set descriptor active // 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); - - + if (Type == USB_ENDPOINT_TYPE_CONTROL || Type == USB_ENDPOINT_TYPE_BULK) + { + // + // notify hardware of our request + // + m_Hardware->HeadEndpointDescriptorModified(Type); + } return STATUS_SUCCESS; } @@ -318,6 +359,35 @@ CUSBQueue::FindTransferDescriptorInEndpoint( return STATUS_NOT_FOUND; } +NTSTATUS +CUSBQueue::FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor) +{ + ULONG Index; + NTSTATUS Status; + + // + // search descriptor in endpoint list + // + for(Index = 0; Index < OHCI_STATIC_ENDPOINT_COUNT; Index++) + { + // + // is it in current endpoint + // + Status = FindTransferDescriptorInEndpoint(m_InterruptEndpoints[Index], TransferDescriptorLogicalAddress, OutEndpointDescriptor, OutPreviousEndpointDescriptor); + if (NT_SUCCESS(Status)) + { + // + // found transfer descriptor + // + return STATUS_SUCCESS; + } + } + + // + // not found + // + return STATUS_NOT_FOUND; +} BOOLEAN CUSBQueue::IsTransferDescriptorInEndpoint( @@ -399,7 +469,27 @@ CUSBQueue::CleanupEndpointDescriptor( Request->Release(); } +VOID +CUSBQueue::PrintEndpointList( + POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor) +{ + DPRINT1("CUSBQueue::PrintEndpointList HeadEndpoint %p Logical %x\n", EndpointDescriptor, EndpointDescriptor->PhysicalAddress.LowPart); + // + // get first general transfer descriptor + // + EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor; + + while(EndpointDescriptor) + { + DPRINT1(" CUSBQueue::PrintEndpointList Endpoint %p Logical %x\n", EndpointDescriptor, EndpointDescriptor->PhysicalAddress.LowPart); + + // + // move to next + // + EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor; + } +} VOID CUSBQueue::TransferDescriptorCompletionCallback( @@ -444,14 +534,73 @@ CUSBQueue::TransferDescriptorCompletionCallback( return; } + // + // find transfer descriptor in interrupt list + // + Status = FindTransferDescriptorInInterruptHeadEndpoints(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); + DPRINT("CUSBQueue::TransferDescriptorCompletionCallback invalid transfer descriptor %x\n", TransferDescriptorLogicalAddress); ASSERT(FALSE); } +POHCI_ENDPOINT_DESCRIPTOR +CUSBQueue::FindInterruptEndpointDescriptor( + UCHAR InterruptInterval) +{ + ULONG Index = 0; + ULONG Power = 1; + + // + // sanity check + // + ASSERT(InterruptInterval < OHCI_BIGGEST_INTERVAL); + + // + // find interrupt index + // + while (Power <= OHCI_BIGGEST_INTERVAL / 2) + { + // + // is current interval greater + // + if (Power * 2 > InterruptInterval) + break; + + // + // increment power + // + Power *= 2; + + // + // move to next interrupt + // + Index++; + } + + DPRINT("InterruptInterval %lu Selected InterruptIndex %lu Choosen Interval %lu\n", InterruptInterval, Index, Power); + + // + // return endpoint + // + return m_InterruptEndpoints[Index]; +} NTSTATUS CreateUSBQueue( diff --git a/drivers/usb/usbohci/usb_request.cpp b/drivers/usb/usbohci/usb_request.cpp index a1442542ad8..f3db44a87b6 100644 --- a/drivers/usb/usbohci/usb_request.cpp +++ b/drivers/usb/usbohci/usb_request.cpp @@ -46,6 +46,8 @@ public: virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead); virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor); virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor); + virtual UCHAR GetInterval(); + // local functions ULONG InternalGetTransferType(); @@ -377,6 +379,18 @@ CUSBRequest::GetMaxPacketSize() return m_EndpointDescriptor->wMaxPacketSize; } +UCHAR +CUSBRequest::GetInterval() +{ + ASSERT(m_EndpointDescriptor); + ASSERT((m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT); + + // + // return interrupt interval + // + return m_EndpointDescriptor->bInterval; +} + UCHAR CUSBRequest::GetEndpointAddress() { @@ -786,7 +800,7 @@ CUSBRequest::BuildBulkInterruptEndpoint( 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); + DPRINT("PreviousDescriptor %p CurrentDescriptor %p Logical %x Buffer Logical %p Physical %x Last Physical %x CurrentSize %lu\n", PreviousDescriptor, CurrentDescriptor, CurrentDescriptor->PhysicalAddress.LowPart, CurrentDescriptor->BufferLogical, CurrentDescriptor->BufferPhysical, CurrentDescriptor->LastPhysicalByteAddress, CurrentSize); // // set previous descriptor @@ -847,7 +861,6 @@ CUSBRequest::BuildBulkInterruptEndpoint( // done // return STATUS_SUCCESS; - }