[USBOHCI]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Thu, 26 May 2011 12:37:18 +0000 (12:37 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Thu, 26 May 2011 12:37:18 +0000 (12:37 +0000)
- Set up periodic threshold (90 %)
- Add function to retrieve interrupt endpoints
- Add function to retrieve specific descriptors from interface. These are used by HID devices such as mice / keyboards
- Add function to retrieve interrupt interval
- Enqueue all endpoint descriptors at the end of the associated queue
- Only notify hardware of insertion when it is an bulk / control request
- Scan interrupt endpoint list to find the completed transfer descriptor
- Add debugging function to print out linked endpoint descriptors
- Interrupt transfers are now implemented.
- Tested in Windows XP SP3 + Vbox 4.04 + Microsoft 5-Button Mouse. The HID mouse installs, initializes and starts up. Unfortunately the mouse does not work as expected yet

svn path=/branches/usb-bringup/; revision=51922

drivers/usb/usbohci/hardware.cpp
drivers/usb/usbohci/hardware.h
drivers/usb/usbohci/hub_controller.cpp
drivers/usb/usbohci/interfaces.h
drivers/usb/usbohci/usb_queue.cpp
drivers/usb/usbohci/usb_request.cpp

index f64a332..1d53c8f 100644 (file)
@@ -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
     //
index c9afa4c..864b96d 100644 (file)
 #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)
index 9a4b844..1f6bc55 100644 (file)
@@ -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;
index 311807d..582b7fb 100644 (file)
@@ -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;
+
 };
 
 
index bbb9965..5880b61 100644 (file)
@@ -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(
index a144254..f3db44a 100644 (file)
@@ -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;
-
 }