mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
[USBOHCI]
- 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
This commit is contained in:
parent
667b425b6c
commit
9aff3e967c
6 changed files with 297 additions and 30 deletions
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue