mirror of
https://github.com/reactos/reactos.git
synced 2024-07-11 15:15:27 +00:00
[USBOHCI]
- Don't preserve command status values when notifying controller of a new bulk / control endpoint - Abort pipe & reset data toggle in the sync reset routine - Allocate interface descriptors and endpoint handles when creating the configuration descriptor - Implement routine for allocating chained descriptors - Implement data toggle for bulk&interrupt transfers - Mass storage devices should now work in real hardware with OHCI controller - Tested in real hardware with NEC Corporation USB [1033:0035] (rev 43) svn path=/trunk/; revision=55687
This commit is contained in:
parent
87a7ba545c
commit
656f87b67c
|
@ -732,21 +732,19 @@ VOID
|
||||||
CUSBHardwareDevice::HeadEndpointDescriptorModified(
|
CUSBHardwareDevice::HeadEndpointDescriptorModified(
|
||||||
ULONG Type)
|
ULONG Type)
|
||||||
{
|
{
|
||||||
ULONG Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET));
|
|
||||||
|
|
||||||
if (Type == USB_ENDPOINT_TYPE_CONTROL)
|
if (Type == USB_ENDPOINT_TYPE_CONTROL)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// notify controller
|
// notify controller
|
||||||
//
|
//
|
||||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), Value | OHCI_CONTROL_LIST_FILLED);
|
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), OHCI_CONTROL_LIST_FILLED);
|
||||||
}
|
}
|
||||||
else if (Type == USB_ENDPOINT_TYPE_BULK)
|
else if (Type == USB_ENDPOINT_TYPE_BULK)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// notify controller
|
// notify controller
|
||||||
//
|
//
|
||||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), Value | OHCI_BULK_LIST_FILLED);
|
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), OHCI_BULK_LIST_FILLED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1579,7 +1577,7 @@ OhciDefferedRoutine(
|
||||||
CStatus = (ULONG) SystemArgument1;
|
CStatus = (ULONG) SystemArgument1;
|
||||||
DoneHead = (ULONG)SystemArgument2;
|
DoneHead = (ULONG)SystemArgument2;
|
||||||
|
|
||||||
DPRINT("OhciDefferedRoutine Status %x\n", CStatus);
|
DPRINT("OhciDefferedRoutine Status %x DoneHead %x\n", CStatus, DoneHead);
|
||||||
|
|
||||||
if (CStatus & OHCI_WRITEBACK_DONE_HEAD)
|
if (CStatus & OHCI_WRITEBACK_DONE_HEAD)
|
||||||
{
|
{
|
||||||
|
|
|
@ -224,6 +224,7 @@ typedef struct _OHCI_ENDPOINT_DESCRIPTOR
|
||||||
PVOID HeadLogicalDescriptor;
|
PVOID HeadLogicalDescriptor;
|
||||||
PVOID NextDescriptor;
|
PVOID NextDescriptor;
|
||||||
PVOID Request;
|
PVOID Request;
|
||||||
|
LIST_ENTRY DescriptorListEntry;
|
||||||
}OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR;
|
}OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR;
|
||||||
|
|
||||||
|
|
||||||
|
@ -242,7 +243,9 @@ typedef struct _OHCI_ENDPOINT_DESCRIPTOR
|
||||||
#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000
|
#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000
|
||||||
#define OHCI_ENDPOINT_HEAD_MASK 0xfffffffc
|
#define OHCI_ENDPOINT_HEAD_MASK 0xfffffffc
|
||||||
#define OHCI_ENDPOINT_HALTED 0x00000001
|
#define OHCI_ENDPOINT_HALTED 0x00000001
|
||||||
|
#define OHCI_ENDPOINT_TOGGLE_CARRY 0x00000002
|
||||||
#define OHCI_ENDPOINT_DIRECTION_DESCRIPTOR 0x00000000
|
#define OHCI_ENDPOINT_DIRECTION_DESCRIPTOR 0x00000000
|
||||||
|
|
||||||
//
|
//
|
||||||
// Maximum port count set by OHCI
|
// Maximum port count set by OHCI
|
||||||
//
|
//
|
||||||
|
|
|
@ -1710,7 +1710,7 @@ CHubController::HandleSyncResetAndClearStall(
|
||||||
IN OUT PURB Urb)
|
IN OUT PURB Urb)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
PUSB_ENDPOINT EndpointDescriptor;
|
||||||
ULONG Type;
|
ULONG Type;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1736,12 +1736,24 @@ CHubController::HandleSyncResetAndClearStall(
|
||||||
//
|
//
|
||||||
// get endpoint descriptor
|
// get endpoint descriptor
|
||||||
//
|
//
|
||||||
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
|
EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbPipeRequest.PipeHandle;
|
||||||
|
|
||||||
|
//
|
||||||
|
// abort pipe
|
||||||
|
//
|
||||||
|
Status = HandleAbortPipe(Irp, Urb);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// abort pipe failed
|
||||||
|
//
|
||||||
|
DPRINT1("[USBOHCI] AbortPipe failed with %x\n", Status);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// get type
|
// get type
|
||||||
//
|
//
|
||||||
Type = (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
|
Type = (EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK);
|
||||||
if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS)
|
if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -1752,8 +1764,9 @@ CHubController::HandleSyncResetAndClearStall(
|
||||||
DPRINT1("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status);
|
DPRINT1("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status);
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME reset data toggle
|
// reset data toggle
|
||||||
//
|
//
|
||||||
|
EndpointDescriptor->DataToggle = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// done
|
// done
|
||||||
|
|
|
@ -372,6 +372,8 @@ DECLARE_INTERFACE_(IDMAMemoryManager, IUnknown)
|
||||||
|
|
||||||
typedef IDMAMemoryManager *PDMAMEMORYMANAGER;
|
typedef IDMAMemoryManager *PDMAMEMORYMANAGER;
|
||||||
|
|
||||||
|
struct _USB_ENDPOINT;
|
||||||
|
|
||||||
|
|
||||||
//=========================================================================================
|
//=========================================================================================
|
||||||
//
|
//
|
||||||
|
@ -401,7 +403,7 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
||||||
virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager,
|
virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager,
|
||||||
IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
|
IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
|
||||||
IN UCHAR DeviceAddress,
|
IN UCHAR DeviceAddress,
|
||||||
IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
|
IN OPTIONAL struct _USB_ENDPOINT* EndpointDescriptor,
|
||||||
IN USB_DEVICE_SPEED DeviceSpeed,
|
IN USB_DEVICE_SPEED DeviceSpeed,
|
||||||
IN OUT ULONG TransferBufferLength,
|
IN OUT ULONG TransferBufferLength,
|
||||||
IN OUT PMDL TransferBuffer) = 0;
|
IN OUT PMDL TransferBuffer) = 0;
|
||||||
|
@ -470,7 +472,7 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
||||||
//
|
//
|
||||||
// Description: notifies request that the endpoint descriptor is complete
|
// Description: notifies request that the endpoint descriptor is complete
|
||||||
|
|
||||||
virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) = 0;
|
virtual VOID CompletionCallback() = 0;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
|
|
@ -54,10 +54,11 @@ public:
|
||||||
virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, IN OUT PUSBD_INTERFACE_INFORMATION Interface);
|
virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, IN OUT PUSBD_INTERFACE_INFORMATION Interface);
|
||||||
virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor);
|
virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor);
|
||||||
|
|
||||||
|
|
||||||
// local function
|
// local function
|
||||||
virtual NTSTATUS CommitIrp(PIRP Irp);
|
virtual NTSTATUS CommitIrp(PIRP Irp);
|
||||||
virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl);
|
virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl);
|
||||||
virtual NTSTATUS CreateConfigurationDescriptor(ULONG ConfigurationIndex);
|
virtual NTSTATUS CreateConfigurationDescriptor(UCHAR ConfigurationIndex);
|
||||||
virtual NTSTATUS CreateDeviceDescriptor();
|
virtual NTSTATUS CreateDeviceDescriptor();
|
||||||
virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
|
virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
|
||||||
virtual VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
|
virtual VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
|
||||||
|
@ -80,9 +81,8 @@ protected:
|
||||||
ULONG m_PortStatus;
|
ULONG m_PortStatus;
|
||||||
PUSBQUEUE m_Queue;
|
PUSBQUEUE m_Queue;
|
||||||
PDMAMEMORYMANAGER m_DmaManager;
|
PDMAMEMORYMANAGER m_DmaManager;
|
||||||
PUSB_CONFIGURATION_DESCRIPTOR *m_ConfigurationDescriptors;
|
|
||||||
LIST_ENTRY m_IrpListHead;
|
|
||||||
|
|
||||||
|
PUSB_CONFIGURATION m_ConfigurationDescriptors;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
|
@ -120,11 +120,6 @@ CUSBDevice::Initialize(
|
||||||
//
|
//
|
||||||
KeInitializeSpinLock(&m_Lock);
|
KeInitializeSpinLock(&m_Lock);
|
||||||
|
|
||||||
//
|
|
||||||
// initialize irp list
|
|
||||||
//
|
|
||||||
InitializeListHead(&m_IrpListHead);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// no device address has been set yet
|
// no device address has been set yet
|
||||||
//
|
//
|
||||||
|
@ -276,6 +271,7 @@ CUSBDevice::GetType()
|
||||||
|
|
||||||
DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n", m_DeviceDescriptor.bcdUSB);
|
DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n", m_DeviceDescriptor.bcdUSB);
|
||||||
//PC_ASSERT(FALSE);
|
//PC_ASSERT(FALSE);
|
||||||
|
|
||||||
return Usb11Device;
|
return Usb11Device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +302,7 @@ CUSBDevice::SetDeviceAddress(
|
||||||
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
UCHAR OldAddress;
|
UCHAR OldAddress;
|
||||||
ULONG Index;
|
UCHAR Index;
|
||||||
|
|
||||||
DPRINT1("CUSBDevice::SetDeviceAddress Address %d\n", DeviceAddress);
|
DPRINT1("CUSBDevice::SetDeviceAddress Address %d\n", DeviceAddress);
|
||||||
|
|
||||||
|
@ -388,12 +384,12 @@ CUSBDevice::SetDeviceAddress(
|
||||||
//
|
//
|
||||||
// allocate configuration descriptor
|
// allocate configuration descriptor
|
||||||
//
|
//
|
||||||
m_ConfigurationDescriptors = (PUSB_CONFIGURATION_DESCRIPTOR*) ExAllocatePoolWithTag(NonPagedPool, sizeof(PUSB_CONFIGURATION_DESCRIPTOR) * m_DeviceDescriptor.bNumConfigurations, TAG_USBOHCI);
|
m_ConfigurationDescriptors = (PUSB_CONFIGURATION) ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_CONFIGURATION) * m_DeviceDescriptor.bNumConfigurations, TAG_USBOHCI);
|
||||||
|
|
||||||
//
|
//
|
||||||
// zero configuration descriptor
|
// zero configuration descriptor
|
||||||
//
|
//
|
||||||
RtlZeroMemory(m_ConfigurationDescriptors, sizeof(PUSB_CONFIGURATION_DESCRIPTOR) * m_DeviceDescriptor.bNumConfigurations);
|
RtlZeroMemory(m_ConfigurationDescriptors, sizeof(USB_CONFIGURATION) * m_DeviceDescriptor.bNumConfigurations);
|
||||||
|
|
||||||
//
|
//
|
||||||
// retrieve the configuration descriptors
|
// retrieve the configuration descriptors
|
||||||
|
@ -525,7 +521,7 @@ CUSBDevice::SubmitIrp(
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CUSBDevice::CommitSetupPacket(
|
CUSBDevice::CommitSetupPacket(
|
||||||
IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet,
|
IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet,
|
||||||
IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
|
IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor,
|
||||||
IN ULONG BufferLength,
|
IN ULONG BufferLength,
|
||||||
IN OUT PMDL Mdl)
|
IN OUT PMDL Mdl)
|
||||||
{
|
{
|
||||||
|
@ -662,19 +658,15 @@ CUSBDevice::CreateDeviceDescriptor()
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// copy back device descriptor
|
|
||||||
//
|
|
||||||
RtlCopyMemory(&m_DeviceDescriptor, DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// informal dbg print
|
// informal dbg print
|
||||||
//
|
//
|
||||||
|
RtlCopyMemory(&m_DeviceDescriptor, DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
||||||
DumpDeviceDescriptor(&m_DeviceDescriptor);
|
DumpDeviceDescriptor(&m_DeviceDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// free item
|
// free buffer
|
||||||
//
|
//
|
||||||
ExFreePool(DeviceDescriptor);
|
ExFreePool(DeviceDescriptor);
|
||||||
|
|
||||||
|
@ -688,13 +680,16 @@ CUSBDevice::CreateDeviceDescriptor()
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CUSBDevice::CreateConfigurationDescriptor(
|
CUSBDevice::CreateConfigurationDescriptor(
|
||||||
ULONG Index)
|
UCHAR Index)
|
||||||
{
|
{
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
|
ULONG InterfaceIndex, EndPointIndex;
|
||||||
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
|
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
|
||||||
|
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||||
|
PUSB_ENDPOINT_DESCRIPTOR EndPointDescriptor;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -714,11 +709,6 @@ CUSBDevice::CreateConfigurationDescriptor(
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// zero buffer
|
|
||||||
//
|
|
||||||
RtlZeroMemory(Buffer, PAGE_SIZE);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// build setup packet
|
// build setup packet
|
||||||
//
|
//
|
||||||
|
@ -727,15 +717,11 @@ CUSBDevice::CreateConfigurationDescriptor(
|
||||||
CtrlSetup.bmRequestType._BM.Reserved = 0;
|
CtrlSetup.bmRequestType._BM.Reserved = 0;
|
||||||
CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
|
CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
|
||||||
CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||||
CtrlSetup.wValue.LowByte = 0;
|
CtrlSetup.wValue.LowByte = Index;
|
||||||
CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
|
CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
|
||||||
CtrlSetup.wIndex.W = 0;
|
CtrlSetup.wIndex.W = 0;
|
||||||
CtrlSetup.wLength = PAGE_SIZE;
|
CtrlSetup.wLength = PAGE_SIZE;
|
||||||
|
|
||||||
//
|
|
||||||
// FIXME: where put configuration index?
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// now build MDL describing the buffer
|
// now build MDL describing the buffer
|
||||||
//
|
//
|
||||||
|
@ -791,9 +777,124 @@ CUSBDevice::CreateConfigurationDescriptor(
|
||||||
PC_ASSERT(ConfigurationDescriptor->bNumInterfaces);
|
PC_ASSERT(ConfigurationDescriptor->bNumInterfaces);
|
||||||
|
|
||||||
//
|
//
|
||||||
// store configuration descriptor
|
// request is complete, initialize configuration descriptor
|
||||||
//
|
//
|
||||||
m_ConfigurationDescriptors[Index] = ConfigurationDescriptor;
|
m_ConfigurationDescriptors[Index].ConfigurationDescriptor = ConfigurationDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// now allocate interface descriptors
|
||||||
|
//
|
||||||
|
m_ConfigurationDescriptors[Index].Interfaces = (PUSB_INTERFACE)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_INTERFACE) * ConfigurationDescriptor->bNumInterfaces, TAG_USBOHCI);
|
||||||
|
if (!m_ConfigurationDescriptors[Index].Interfaces)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate interface descriptors
|
||||||
|
//
|
||||||
|
ExFreePool(Buffer);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// zero interface descriptor
|
||||||
|
//
|
||||||
|
RtlZeroMemory(m_ConfigurationDescriptors[Index].Interfaces, sizeof(USB_INTERFACE) * ConfigurationDescriptor->bNumInterfaces);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get first interface descriptor
|
||||||
|
//
|
||||||
|
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)(ConfigurationDescriptor + 1);
|
||||||
|
|
||||||
|
//
|
||||||
|
// setup interface descriptors
|
||||||
|
//
|
||||||
|
for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++)
|
||||||
|
{
|
||||||
|
while(InterfaceDescriptor->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE && InterfaceDescriptor->bLength != sizeof(USB_INTERFACE_DESCRIPTOR))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// move to next descriptor
|
||||||
|
//
|
||||||
|
ASSERT(InterfaceDescriptor->bLength);
|
||||||
|
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
ASSERT(InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
|
||||||
|
ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
|
||||||
|
ASSERT(InterfaceDescriptor->bNumEndpoints);
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy current interface descriptor
|
||||||
|
//
|
||||||
|
RtlCopyMemory(&m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].InterfaceDescriptor, InterfaceDescriptor, InterfaceDescriptor->bLength);
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate end point descriptors
|
||||||
|
//
|
||||||
|
m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints = (PUSB_ENDPOINT)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_ENDPOINT) * InterfaceDescriptor->bNumEndpoints, TAG_USBOHCI);
|
||||||
|
if (!m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate endpoint
|
||||||
|
//
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// zero memory
|
||||||
|
//
|
||||||
|
RtlZeroMemory(m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints, sizeof(USB_ENDPOINT) * InterfaceDescriptor->bNumEndpoints);
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize end point descriptors
|
||||||
|
//
|
||||||
|
EndPointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)(InterfaceDescriptor + 1);
|
||||||
|
|
||||||
|
for(EndPointIndex = 0; EndPointIndex < InterfaceDescriptor->bNumEndpoints; EndPointIndex++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// skip other descriptors
|
||||||
|
//
|
||||||
|
while(EndPointDescriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE && EndPointDescriptor->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// assert when next interface descriptor is reached before the next endpoint
|
||||||
|
//
|
||||||
|
ASSERT(EndPointDescriptor->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE);
|
||||||
|
ASSERT(EndPointDescriptor->bLength);
|
||||||
|
|
||||||
|
DPRINT1("InterfaceDescriptor bNumEndpoints %x EndpointIndex %x Skipping Descriptor Type %x\n", InterfaceDescriptor->bNumEndpoints, EndPointIndex, EndPointDescriptor->bDescriptorType);
|
||||||
|
//
|
||||||
|
// move to next descriptor
|
||||||
|
//
|
||||||
|
EndPointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndPointDescriptor + EndPointDescriptor->bLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(EndPointDescriptor->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE);
|
||||||
|
ASSERT(EndPointDescriptor->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR));
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy endpoint descriptor
|
||||||
|
//
|
||||||
|
RtlCopyMemory(&m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints[EndPointIndex].EndPointDescriptor, EndPointDescriptor, EndPointDescriptor->bLength);
|
||||||
|
|
||||||
|
//
|
||||||
|
// move to next offset
|
||||||
|
//
|
||||||
|
EndPointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndPointDescriptor + EndPointDescriptor->bLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// update interface descriptor offset
|
||||||
|
//
|
||||||
|
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)EndPointDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// done
|
// done
|
||||||
|
@ -827,8 +928,8 @@ CUSBDevice::GetConfigurationDescriptors(
|
||||||
//
|
//
|
||||||
// copy configuration descriptor
|
// copy configuration descriptor
|
||||||
//
|
//
|
||||||
RtlCopyMemory(ConfigDescriptorBuffer, m_ConfigurationDescriptors[0], min(m_ConfigurationDescriptors[0]->wTotalLength, BufferLength));
|
RtlCopyMemory(ConfigDescriptorBuffer, m_ConfigurationDescriptors[0].ConfigurationDescriptor, min(m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength, BufferLength));
|
||||||
*OutBufferLength = m_ConfigurationDescriptors[0]->wTotalLength;
|
*OutBufferLength = m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
|
@ -839,11 +940,7 @@ CUSBDevice::GetConfigurationDescriptorsLength()
|
||||||
// FIXME: support multiple configurations
|
// FIXME: support multiple configurations
|
||||||
//
|
//
|
||||||
PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
|
PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
|
||||||
|
return m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength;
|
||||||
ASSERT(m_ConfigurationDescriptors[0]);
|
|
||||||
ASSERT(m_ConfigurationDescriptors[0]->wTotalLength);
|
|
||||||
|
|
||||||
return m_ConfigurationDescriptors[0]->wTotalLength;
|
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
VOID
|
VOID
|
||||||
|
@ -897,7 +994,12 @@ CUSBDevice::SubmitSetupPacket(
|
||||||
//
|
//
|
||||||
Mdl = IoAllocateMdl(Buffer, BufferLength, FALSE, FALSE, 0);
|
Mdl = IoAllocateMdl(Buffer, BufferLength, FALSE, FALSE, 0);
|
||||||
if (!Mdl)
|
if (!Mdl)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// HACK HACK HACK: assume the buffer is build from non paged pool
|
// HACK HACK HACK: assume the buffer is build from non paged pool
|
||||||
|
@ -934,95 +1036,17 @@ CUSBDevice::SelectConfiguration(
|
||||||
ULONG InterfaceIndex, PipeIndex;
|
ULONG InterfaceIndex, PipeIndex;
|
||||||
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PUSB_CONFIGURATION_DESCRIPTOR CurrentConfigurationDescriptor;
|
|
||||||
PUSB_INTERFACE_DESCRIPTOR CurrentInterfaceDescriptor;
|
|
||||||
PUSB_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor;
|
|
||||||
PVOID StartPosition;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME: support multiple configurations
|
// sanity checks
|
||||||
//
|
//
|
||||||
ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
|
ASSERT(ConfigurationDescriptor->iConfiguration < m_DeviceDescriptor.bNumConfigurations);
|
||||||
ASSERT(m_ConfigurationDescriptors[0]);
|
ASSERT(ConfigurationDescriptor->iConfiguration == m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].ConfigurationDescriptor->iConfiguration);
|
||||||
CurrentConfigurationDescriptor = m_ConfigurationDescriptors[0];
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// sanity check
|
// sanity check
|
||||||
//
|
//
|
||||||
PC_ASSERT(ConfigurationDescriptor->iConfiguration == CurrentConfigurationDescriptor->iConfiguration);
|
ASSERT(ConfigurationDescriptor->bNumInterfaces <= m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].ConfigurationDescriptor->bNumInterfaces);
|
||||||
PC_ASSERT(ConfigurationDescriptor->bNumInterfaces <= CurrentConfigurationDescriptor->bNumInterfaces);
|
|
||||||
DPRINT1("CUSBDevice::SelectConfiguration NumInterfaces %lu\n", ConfigurationDescriptor->bNumInterfaces);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// copy interface info and pipe info
|
|
||||||
//
|
|
||||||
for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// find interface descriptor
|
|
||||||
//
|
|
||||||
CurrentInterfaceDescriptor = USBD_ParseConfigurationDescriptor(CurrentConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting);
|
|
||||||
|
|
||||||
//
|
|
||||||
// sanity check
|
|
||||||
//
|
|
||||||
ASSERT(CurrentInterfaceDescriptor);
|
|
||||||
ASSERT(CurrentInterfaceDescriptor->bLength != 0);
|
|
||||||
ASSERT(InterfaceInfo->NumberOfPipes == CurrentInterfaceDescriptor->bNumEndpoints);
|
|
||||||
ASSERT(InterfaceInfo->Length != 0);
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DPRINT1("CUSBDevice::SelectConfiguration InterfaceNumber %lu AlternativeSetting %lu bNumEndpoints %lu\n", InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting, CurrentInterfaceDescriptor->bNumEndpoints);
|
|
||||||
|
|
||||||
//
|
|
||||||
// copy interface info
|
|
||||||
//
|
|
||||||
InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)CurrentInterfaceDescriptor;
|
|
||||||
InterfaceInfo->Class = CurrentInterfaceDescriptor->bInterfaceClass;
|
|
||||||
InterfaceInfo->SubClass = CurrentInterfaceDescriptor->bInterfaceSubClass;
|
|
||||||
InterfaceInfo->Protocol = CurrentInterfaceDescriptor->bInterfaceProtocol;
|
|
||||||
InterfaceInfo->Reserved = 0;
|
|
||||||
|
|
||||||
//
|
|
||||||
// copy endpoint info
|
|
||||||
//
|
|
||||||
StartPosition = CurrentInterfaceDescriptor;
|
|
||||||
for(PipeIndex = 0; PipeIndex < InterfaceInfo->NumberOfPipes; PipeIndex++)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// find corresponding endpoint descriptor
|
|
||||||
//
|
|
||||||
CurrentEndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)USBD_ParseDescriptors(CurrentConfigurationDescriptor, CurrentConfigurationDescriptor->wTotalLength, StartPosition, USB_ENDPOINT_DESCRIPTOR_TYPE);
|
|
||||||
|
|
||||||
//
|
|
||||||
// sanity checks
|
|
||||||
//
|
|
||||||
ASSERT(CurrentEndpointDescriptor);
|
|
||||||
ASSERT(CurrentEndpointDescriptor->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE);
|
|
||||||
|
|
||||||
//
|
|
||||||
// copy pipe info
|
|
||||||
//
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = CurrentEndpointDescriptor->wMaxPacketSize;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].EndpointAddress = CurrentEndpointDescriptor->bEndpointAddress;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].Interval = CurrentEndpointDescriptor->bInterval;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)CurrentEndpointDescriptor->bmAttributes;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)CurrentEndpointDescriptor;
|
|
||||||
|
|
||||||
//
|
|
||||||
// move start position beyond the current endpoint descriptor
|
|
||||||
//
|
|
||||||
StartPosition = (PVOID)(CurrentEndpointDescriptor + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// move offset
|
|
||||||
//
|
|
||||||
InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)PtrToUlong(InterfaceInfo) + InterfaceInfo->Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// now build setup packet
|
// now build setup packet
|
||||||
|
@ -1040,18 +1064,71 @@ CUSBDevice::SelectConfiguration(
|
||||||
// informal debug print
|
// informal debug print
|
||||||
//
|
//
|
||||||
DPRINT1("CUsbDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationDescriptor->iConfiguration, m_ConfigurationIndex, Status);
|
DPRINT1("CUsbDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationDescriptor->iConfiguration, m_ConfigurationIndex, Status);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// store configuration device index
|
// failed
|
||||||
//
|
//
|
||||||
m_ConfigurationIndex = ConfigurationDescriptor->iConfiguration;
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// store configuration device index
|
||||||
|
//
|
||||||
|
m_ConfigurationIndex = ConfigurationDescriptor->iConfiguration;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store configuration handle
|
||||||
|
//
|
||||||
|
*ConfigurationHandle = &m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration];
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy interface info and pipe info
|
||||||
|
//
|
||||||
|
for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// sanity check: is the info pre-layed out
|
||||||
|
//
|
||||||
|
PC_ASSERT(InterfaceInfo->NumberOfPipes == m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints);
|
||||||
|
PC_ASSERT(InterfaceInfo->Length != 0);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// store configuration handle
|
// copy interface info
|
||||||
//
|
//
|
||||||
*ConfigurationHandle = m_ConfigurationDescriptors[0];
|
InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)&m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex];
|
||||||
|
InterfaceInfo->Class = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].InterfaceDescriptor.bInterfaceClass;
|
||||||
|
InterfaceInfo->SubClass = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].InterfaceDescriptor.bInterfaceSubClass;
|
||||||
|
InterfaceInfo->Protocol = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].InterfaceDescriptor.bInterfaceProtocol;
|
||||||
|
InterfaceInfo->Reserved = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy endpoint info
|
||||||
|
//
|
||||||
|
for(PipeIndex = 0; PipeIndex < InterfaceInfo->NumberOfPipes; PipeIndex++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// copy pipe info
|
||||||
|
//
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.wMaxPacketSize;
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].EndpointAddress = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress;
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].Interval = m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.bInterval;
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.bmAttributes;
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)&m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// data toggle is reset on configuration requests
|
||||||
|
//
|
||||||
|
m_ConfigurationDescriptors[ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceIndex].EndPoints[PipeIndex].DataToggle = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// move offset
|
||||||
|
//
|
||||||
|
InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)PtrToUlong(InterfaceInfo) + InterfaceInfo->Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1066,49 +1143,31 @@ CUSBDevice::SelectInterface(
|
||||||
IN USBD_CONFIGURATION_HANDLE ConfigurationHandle,
|
IN USBD_CONFIGURATION_HANDLE ConfigurationHandle,
|
||||||
IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo)
|
IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo)
|
||||||
{
|
{
|
||||||
PUSB_CONFIGURATION_DESCRIPTOR Configuration;
|
PUSB_CONFIGURATION Configuration;
|
||||||
ULONG PipeIndex;
|
ULONG PipeIndex;
|
||||||
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
|
||||||
PUSB_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor;
|
|
||||||
PVOID StartPosition;
|
|
||||||
|
|
||||||
//
|
|
||||||
// FIXME support multiple configurations
|
|
||||||
//
|
|
||||||
PC_ASSERT(m_ConfigurationDescriptors[0] == (PUSB_CONFIGURATION_DESCRIPTOR)ConfigurationHandle);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// get configuration struct
|
// get configuration struct
|
||||||
//
|
//
|
||||||
Configuration = (PUSB_CONFIGURATION_DESCRIPTOR)ConfigurationHandle;
|
Configuration = (PUSB_CONFIGURATION)ConfigurationHandle;
|
||||||
|
|
||||||
//
|
//
|
||||||
// sanity checks
|
// sanity check
|
||||||
//
|
//
|
||||||
PC_ASSERT(Configuration->bNumInterfaces > InterfaceInfo->InterfaceNumber);
|
ASSERT(Configuration->ConfigurationDescriptor->bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE);
|
||||||
#ifdef _MSC_VER
|
ASSERT(Configuration->ConfigurationDescriptor->bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR));
|
||||||
//PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
|
ASSERT(Configuration->ConfigurationDescriptor->iConfiguration < m_DeviceDescriptor.bNumConfigurations);
|
||||||
#endif
|
ASSERT(&m_ConfigurationDescriptors[Configuration->ConfigurationDescriptor->iConfiguration] == Configuration);
|
||||||
|
|
||||||
//
|
|
||||||
// FIXME: check bandwidth
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// find interface number
|
|
||||||
//
|
|
||||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptor(Configuration, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting);
|
|
||||||
ASSERT(InterfaceDescriptor);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// initialize setup packet
|
// initialize setup packet
|
||||||
//
|
//
|
||||||
RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
|
RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
|
||||||
CtrlSetup.bRequest = USB_REQUEST_SET_INTERFACE;
|
CtrlSetup.bRequest = USB_REQUEST_SET_INTERFACE;
|
||||||
CtrlSetup.wValue.W = InterfaceDescriptor->bAlternateSetting;
|
CtrlSetup.wValue.W = Configuration->Interfaces[InterfaceInfo->InterfaceNumber].InterfaceDescriptor.bAlternateSetting;
|
||||||
CtrlSetup.wIndex.W = InterfaceDescriptor->bInterfaceNumber;
|
CtrlSetup.wIndex.W = Configuration->Interfaces[InterfaceInfo->InterfaceNumber].InterfaceDescriptor.bInterfaceNumber;
|
||||||
CtrlSetup.bmRequestType.B = 0x01;
|
CtrlSetup.bmRequestType.B = 0x01;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1120,55 +1179,58 @@ CUSBDevice::SelectInterface(
|
||||||
// informal debug print
|
// informal debug print
|
||||||
//
|
//
|
||||||
DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status);
|
DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status);
|
||||||
DPRINT1("CUSBDevice::SelectInterface bInterfaceNumber %u bAlternateSetting %u NumberOfPipes %u Length %lu\n",
|
if (!NT_SUCCESS(Status))
|
||||||
InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, InterfaceInfo->NumberOfPipes, InterfaceInfo->Length);
|
|
||||||
InterfaceInfo->InterfaceHandle = InterfaceDescriptor;
|
|
||||||
InterfaceInfo->NumberOfPipes = InterfaceDescriptor->bNumEndpoints;
|
|
||||||
|
|
||||||
//
|
|
||||||
// are there end points
|
|
||||||
//
|
|
||||||
if (InterfaceDescriptor->bNumEndpoints)
|
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// sanity check
|
// failed to select interface
|
||||||
//
|
//
|
||||||
ASSERT(InterfaceInfo->Length == sizeof(USBD_INTERFACE_INFORMATION) + (InterfaceDescriptor->bNumEndpoints > 1 ? sizeof(USBD_PIPE_INFORMATION) * (InterfaceDescriptor->bNumEndpoints - 1) : 0));
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
PC_ASSERT(Configuration->ConfigurationDescriptor->bNumInterfaces > InterfaceInfo->InterfaceNumber);
|
||||||
|
PC_ASSERT(Configuration->Interfaces[InterfaceInfo->InterfaceNumber].InterfaceDescriptor.bNumEndpoints == InterfaceInfo->NumberOfPipes);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy pipe handles
|
||||||
|
//
|
||||||
|
for(PipeIndex = 0; PipeIndex < InterfaceInfo->NumberOfPipes; PipeIndex++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// copy pipe handle
|
||||||
|
//
|
||||||
|
DPRINT1("PipeIndex %lu\n", PipeIndex);
|
||||||
|
DPRINT1("EndpointAddress %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
|
||||||
|
DPRINT1("Interval %d\n", InterfaceInfo->Pipes[PipeIndex].Interval);
|
||||||
|
DPRINT1("MaximumPacketSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize);
|
||||||
|
DPRINT1("MaximumTransferSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumTransferSize);
|
||||||
|
DPRINT1("PipeFlags %d\n", InterfaceInfo->Pipes[PipeIndex].PipeFlags);
|
||||||
|
DPRINT1("PipeType %dd\n", InterfaceInfo->Pipes[PipeIndex].PipeType);
|
||||||
|
DPRINT1("UsbEndPoint %x\n", Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress);
|
||||||
|
PC_ASSERT(Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress == InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
|
||||||
|
|
||||||
|
InterfaceInfo->Pipes[PipeIndex].PipeHandle = &Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor;
|
||||||
|
|
||||||
//
|
//
|
||||||
// store number of pipes
|
// data toggle is reset on select interface requests
|
||||||
//
|
//
|
||||||
InterfaceInfo->NumberOfPipes = InterfaceDescriptor->bNumEndpoints;
|
m_ConfigurationDescriptors[Configuration->ConfigurationDescriptor->iConfiguration].Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].DataToggle = FALSE;
|
||||||
|
|
||||||
StartPosition = InterfaceDescriptor;
|
if (Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bmAttributes & (USB_ENDPOINT_TYPE_ISOCHRONOUS | USB_ENDPOINT_TYPE_INTERRUPT))
|
||||||
for(PipeIndex = 0; PipeIndex < InterfaceInfo->NumberOfPipes; PipeIndex++)
|
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// find corresponding endpoint descriptor
|
// FIXME: check if enough bandwidth is available
|
||||||
//
|
//
|
||||||
CurrentEndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)USBD_ParseDescriptors(Configuration, Configuration->wTotalLength, StartPosition, USB_ENDPOINT_DESCRIPTOR_TYPE);
|
|
||||||
|
|
||||||
//
|
|
||||||
// sanity checks
|
|
||||||
//
|
|
||||||
ASSERT(CurrentEndpointDescriptor);
|
|
||||||
ASSERT(CurrentEndpointDescriptor->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE);
|
|
||||||
|
|
||||||
//
|
|
||||||
// copy pipe info
|
|
||||||
//
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = CurrentEndpointDescriptor->wMaxPacketSize;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].EndpointAddress = CurrentEndpointDescriptor->bEndpointAddress;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].Interval = CurrentEndpointDescriptor->bInterval;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)CurrentEndpointDescriptor->bmAttributes;
|
|
||||||
InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)CurrentEndpointDescriptor;
|
|
||||||
|
|
||||||
//
|
|
||||||
// move start position beyond the current endpoint descriptor
|
|
||||||
//
|
|
||||||
StartPosition = (PVOID)(CurrentEndpointDescriptor + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// done
|
// done
|
||||||
//
|
//
|
||||||
|
@ -1191,6 +1253,7 @@ CUSBDevice::AbortPipe(
|
||||||
return m_Queue->AbortDevicePipe(m_DeviceAddress, EndpointDescriptor);
|
return m_Queue->AbortDevicePipe(m_DeviceAddress, EndpointDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CreateUSBDevice(
|
CreateUSBDevice(
|
||||||
|
|
|
@ -53,6 +53,8 @@ public:
|
||||||
POHCI_ENDPOINT_DESCRIPTOR FindInterruptEndpointDescriptor(UCHAR InterruptInterval);
|
POHCI_ENDPOINT_DESCRIPTOR FindInterruptEndpointDescriptor(UCHAR InterruptInterval);
|
||||||
VOID PrintEndpointList(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor);
|
VOID PrintEndpointList(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor);
|
||||||
VOID LinkEndpoint(POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor);
|
VOID LinkEndpoint(POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor);
|
||||||
|
VOID AddEndpointDescriptor(IN POHCI_ENDPOINT_DESCRIPTOR Descriptor);
|
||||||
|
|
||||||
|
|
||||||
// constructor / destructor
|
// constructor / destructor
|
||||||
CUSBQueue(IUnknown *OuterUnknown){}
|
CUSBQueue(IUnknown *OuterUnknown){}
|
||||||
|
@ -66,6 +68,7 @@ protected:
|
||||||
POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor; // control head descriptor
|
POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor; // control head descriptor
|
||||||
POHCI_ENDPOINT_DESCRIPTOR m_IsoHeadEndpointDescriptor; // isochronous head descriptor
|
POHCI_ENDPOINT_DESCRIPTOR m_IsoHeadEndpointDescriptor; // isochronous head descriptor
|
||||||
POHCI_ENDPOINT_DESCRIPTOR * m_InterruptEndpoints;
|
POHCI_ENDPOINT_DESCRIPTOR * m_InterruptEndpoints;
|
||||||
|
LIST_ENTRY m_PendingRequestList; // pending request list
|
||||||
};
|
};
|
||||||
|
|
||||||
//=================================================================================================
|
//=================================================================================================
|
||||||
|
@ -119,6 +122,12 @@ CUSBQueue::Initialize(
|
||||||
//
|
//
|
||||||
KeInitializeSpinLock(&m_Lock);
|
KeInitializeSpinLock(&m_Lock);
|
||||||
|
|
||||||
|
//
|
||||||
|
// init list
|
||||||
|
//
|
||||||
|
InitializeListHead(&m_PendingRequestList);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// store hardware
|
// store hardware
|
||||||
//
|
//
|
||||||
|
@ -164,53 +173,29 @@ CUSBQueue::LinkEndpoint(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
VOID
|
||||||
CUSBQueue::AddUSBRequest(
|
CUSBQueue::AddEndpointDescriptor(
|
||||||
IUSBRequest * Request)
|
IN POHCI_ENDPOINT_DESCRIPTOR Descriptor)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
IUSBRequest *Request;
|
||||||
ULONG Type;
|
ULONG Type;
|
||||||
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
|
POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor;
|
||||||
POHCI_ENDPOINT_DESCRIPTOR Descriptor;
|
|
||||||
POHCI_ISO_TD CurrentDescriptor;
|
POHCI_ISO_TD CurrentDescriptor;
|
||||||
ULONG FrameNumber;
|
ULONG FrameNumber;
|
||||||
USHORT Frame;
|
USHORT Frame;
|
||||||
|
|
||||||
DPRINT("CUSBQueue::AddUSBRequest\n");
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// sanity check
|
// sanity check
|
||||||
//
|
//
|
||||||
ASSERT(Request != NULL);
|
ASSERT(Descriptor->Request);
|
||||||
|
Request = (IUSBRequest*)Descriptor->Request;
|
||||||
|
|
||||||
//
|
//
|
||||||
// get request type
|
// get request type
|
||||||
//
|
//
|
||||||
Type = Request->GetTransferType();
|
Type = Request->GetTransferType();
|
||||||
|
|
||||||
//
|
|
||||||
// add extra reference which is released when the request is completed
|
|
||||||
//
|
|
||||||
Request->AddRef();
|
|
||||||
|
|
||||||
//
|
|
||||||
// get transfer descriptors
|
|
||||||
//
|
|
||||||
Status = Request->GetEndpointDescriptor(&Descriptor);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// failed to get transfer descriptor
|
|
||||||
//
|
|
||||||
DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with %x\n", Status);
|
|
||||||
|
|
||||||
//
|
|
||||||
// release reference
|
|
||||||
//
|
|
||||||
Request->Release();
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// check type
|
// check type
|
||||||
//
|
//
|
||||||
|
@ -294,8 +279,8 @@ CUSBQueue::AddUSBRequest(
|
||||||
//
|
//
|
||||||
// bad request type
|
// bad request type
|
||||||
//
|
//
|
||||||
Request->Release();
|
ASSERT(FALSE);
|
||||||
return STATUS_INVALID_PARAMETER;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -315,7 +300,50 @@ CUSBQueue::AddUSBRequest(
|
||||||
//
|
//
|
||||||
m_Hardware->HeadEndpointDescriptorModified(Type);
|
m_Hardware->HeadEndpointDescriptorModified(Type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CUSBQueue::AddUSBRequest(
|
||||||
|
IUSBRequest * Request)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
IN POHCI_ENDPOINT_DESCRIPTOR Descriptor;
|
||||||
|
|
||||||
|
DPRINT("CUSBQueue::AddUSBRequest\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(Request != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// add extra reference which is released when the request is completed
|
||||||
|
//
|
||||||
|
Request->AddRef();
|
||||||
|
|
||||||
|
//
|
||||||
|
// get transfer descriptors
|
||||||
|
//
|
||||||
|
Status = Request->GetEndpointDescriptor(&Descriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to get transfer descriptor
|
||||||
|
//
|
||||||
|
DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with %x\n", Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// release reference
|
||||||
|
//
|
||||||
|
Request->Release();
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// add the request
|
||||||
|
//
|
||||||
|
AddEndpointDescriptor(Descriptor);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,6 +590,9 @@ CUSBQueue::CleanupEndpointDescriptor(
|
||||||
POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor)
|
POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor)
|
||||||
{
|
{
|
||||||
PUSBREQUEST Request;
|
PUSBREQUEST Request;
|
||||||
|
POHCI_ENDPOINT_DESCRIPTOR NewEndpointDescriptor;
|
||||||
|
USBD_STATUS UrbStatus;
|
||||||
|
KIRQL OldLevel;
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME: verify unlinking process
|
// FIXME: verify unlinking process
|
||||||
|
@ -576,21 +607,90 @@ CUSBQueue::CleanupEndpointDescriptor(
|
||||||
ASSERT(Request);
|
ASSERT(Request);
|
||||||
|
|
||||||
//
|
//
|
||||||
// notify of completion
|
// check for errors
|
||||||
//
|
//
|
||||||
Request->CompletionCallback(EndpointDescriptor);
|
if (EndpointDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HALTED)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// the real error will processed by IUSBRequest
|
||||||
|
//
|
||||||
|
UrbStatus = USBD_STATUS_STALL_PID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// well done ;)
|
||||||
|
//
|
||||||
|
UrbStatus = USBD_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check if the transfer was completed and if UrbStatus is ok
|
||||||
|
//
|
||||||
|
if ((Request->IsRequestComplete() == FALSE) && (UrbStatus == USBD_STATUS_SUCCESS))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// request is incomplete, get new queue head
|
||||||
|
//
|
||||||
|
if (Request->GetEndpointDescriptor(&NewEndpointDescriptor) == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// notify of completion
|
||||||
|
//
|
||||||
|
Request->FreeEndpointDescriptor(EndpointDescriptor);
|
||||||
|
|
||||||
|
//
|
||||||
|
// first acquire request lock
|
||||||
|
//
|
||||||
|
KeAcquireSpinLock(&m_Lock, &OldLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// add to pending list
|
||||||
|
//
|
||||||
|
InsertTailList(&m_PendingRequestList, &NewEndpointDescriptor->DescriptorListEntry);
|
||||||
|
|
||||||
|
//
|
||||||
|
// release queue head
|
||||||
|
//
|
||||||
|
KeReleaseSpinLock(&m_Lock, OldLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Done for now
|
||||||
|
//
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DPRINT1("Unable to create a new QueueHead\n");
|
||||||
|
//ASSERT(FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Else there was a problem
|
||||||
|
// FIXME: Find better return
|
||||||
|
UrbStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UrbStatus != USBD_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("URB failed with status 0x%x\n", UrbStatus);
|
||||||
|
//PC_ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// free endpoint descriptor
|
// free endpoint descriptor
|
||||||
//
|
//
|
||||||
Request->FreeEndpointDescriptor(EndpointDescriptor);
|
Request->FreeEndpointDescriptor(EndpointDescriptor);
|
||||||
|
|
||||||
|
//
|
||||||
|
// notify of completion
|
||||||
|
//
|
||||||
|
Request->CompletionCallback();
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// release request
|
// release request
|
||||||
//
|
//
|
||||||
Request->Release();
|
Request->Release();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CUSBQueue::PrintEndpointList(
|
CUSBQueue::PrintEndpointList(
|
||||||
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor)
|
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor)
|
||||||
|
@ -618,6 +718,7 @@ CUSBQueue::TransferDescriptorCompletionCallback(
|
||||||
ULONG TransferDescriptorLogicalAddress)
|
ULONG TransferDescriptorLogicalAddress)
|
||||||
{
|
{
|
||||||
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
|
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress);
|
DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress);
|
||||||
|
@ -697,15 +798,41 @@ CUSBQueue::TransferDescriptorCompletionCallback(
|
||||||
//
|
//
|
||||||
// no more completed descriptors found
|
// no more completed descriptors found
|
||||||
//
|
//
|
||||||
return;
|
break;
|
||||||
|
|
||||||
}while(TRUE);
|
}while(TRUE);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// hardware reported dead endpoint completed
|
// acquire spin lock
|
||||||
//
|
//
|
||||||
DPRINT1("CUSBQueue::TransferDescriptorCompletionCallback invalid transfer descriptor %x\n", TransferDescriptorLogicalAddress);
|
KeAcquireSpinLockAtDpcLevel(&m_Lock);
|
||||||
ASSERT(FALSE);
|
|
||||||
|
//
|
||||||
|
// is there a pending list item
|
||||||
|
//
|
||||||
|
if (!IsListEmpty(&m_PendingRequestList))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get list entry
|
||||||
|
//
|
||||||
|
Entry = RemoveHeadList(&m_PendingRequestList);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get entry
|
||||||
|
//
|
||||||
|
EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CONTAINING_RECORD(Entry, OHCI_ENDPOINT_DESCRIPTOR, DescriptorListEntry);
|
||||||
|
|
||||||
|
//
|
||||||
|
// add entry
|
||||||
|
//
|
||||||
|
AddEndpointDescriptor(EndpointDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// release lock
|
||||||
|
//
|
||||||
|
KeReleaseSpinLockFromDpcLevel(&m_Lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
POHCI_ENDPOINT_DESCRIPTOR
|
POHCI_ENDPOINT_DESCRIPTOR
|
||||||
|
@ -789,8 +916,12 @@ CUSBQueue::AbortDevicePipe(
|
||||||
HeadDescriptor = FindInterruptEndpointDescriptor(EndpointDescriptor->bInterval);
|
HeadDescriptor = FindInterruptEndpointDescriptor(EndpointDescriptor->bInterval);
|
||||||
ASSERT(HeadDescriptor);
|
ASSERT(HeadDescriptor);
|
||||||
}
|
}
|
||||||
else if (Type == USB_ENDPOINT_TYPE_ISOCHRONOUS)
|
else
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// IMPLEMENT me
|
||||||
|
//
|
||||||
|
ASSERT(Type == USB_ENDPOINT_TYPE_ISOCHRONOUS);
|
||||||
UNIMPLEMENTED
|
UNIMPLEMENTED
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// IUSBRequest interface functions
|
// IUSBRequest interface functions
|
||||||
virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN USB_DEVICE_SPEED DeviceSpeed, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
|
virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN OPTIONAL struct _USB_ENDPOINT* EndpointDescriptor, IN USB_DEVICE_SPEED DeviceSpeed, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
|
||||||
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp, IN USB_DEVICE_SPEED DeviceSpeed);
|
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp, IN USB_DEVICE_SPEED DeviceSpeed);
|
||||||
virtual BOOLEAN IsRequestComplete();
|
virtual BOOLEAN IsRequestComplete();
|
||||||
virtual ULONG GetTransferType();
|
virtual ULONG GetTransferType();
|
||||||
|
@ -44,7 +44,7 @@ public:
|
||||||
virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode);
|
virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode);
|
||||||
virtual BOOLEAN IsRequestInitialized();
|
virtual BOOLEAN IsRequestInitialized();
|
||||||
virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
|
virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
|
||||||
virtual VOID CompletionCallback(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
|
virtual VOID CompletionCallback();
|
||||||
virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
|
virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
|
||||||
virtual UCHAR GetInterval();
|
virtual UCHAR GetInterval();
|
||||||
|
|
||||||
|
@ -65,6 +65,8 @@ public:
|
||||||
USHORT GetMaxPacketSize();
|
USHORT GetMaxPacketSize();
|
||||||
VOID CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
|
VOID CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
|
||||||
VOID DumpEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR *Descriptor);
|
VOID DumpEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR *Descriptor);
|
||||||
|
NTSTATUS BuildTransferDescriptorChain(IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, OUT POHCI_GENERAL_TD * OutFirstDescriptor, OUT POHCI_GENERAL_TD * OutLastDescriptor, OUT PULONG OutTransferBufferOffset);
|
||||||
|
VOID InitDescriptor(IN POHCI_GENERAL_TD CurrentDescriptor, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode);
|
||||||
|
|
||||||
|
|
||||||
// constructor / destructor
|
// constructor / destructor
|
||||||
|
@ -120,9 +122,9 @@ protected:
|
||||||
UCHAR m_DeviceAddress;
|
UCHAR m_DeviceAddress;
|
||||||
|
|
||||||
//
|
//
|
||||||
// store end point address
|
// store endpoint descriptor
|
||||||
//
|
//
|
||||||
PUSB_ENDPOINT_DESCRIPTOR m_EndpointDescriptor;
|
PUSB_ENDPOINT m_EndpointDescriptor;
|
||||||
|
|
||||||
//
|
//
|
||||||
// allocated setup packet from the DMA pool
|
// allocated setup packet from the DMA pool
|
||||||
|
@ -145,6 +147,11 @@ protected:
|
||||||
// store urb
|
// store urb
|
||||||
//
|
//
|
||||||
PURB m_Urb;
|
PURB m_Urb;
|
||||||
|
|
||||||
|
//
|
||||||
|
// base buffer
|
||||||
|
//
|
||||||
|
PVOID m_Base;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
|
@ -163,7 +170,7 @@ CUSBRequest::InitializeWithSetupPacket(
|
||||||
IN PDMAMEMORYMANAGER DmaManager,
|
IN PDMAMEMORYMANAGER DmaManager,
|
||||||
IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
|
IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
|
||||||
IN UCHAR DeviceAddress,
|
IN UCHAR DeviceAddress,
|
||||||
IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
|
IN OPTIONAL struct _USB_ENDPOINT* EndpointDescriptor,
|
||||||
IN USB_DEVICE_SPEED DeviceSpeed,
|
IN USB_DEVICE_SPEED DeviceSpeed,
|
||||||
IN OUT ULONG TransferBufferLength,
|
IN OUT ULONG TransferBufferLength,
|
||||||
IN OUT PMDL TransferBuffer)
|
IN OUT PMDL TransferBuffer)
|
||||||
|
@ -331,7 +338,7 @@ CUSBRequest::InitializeWithIrp(
|
||||||
//
|
//
|
||||||
// get endpoint descriptor
|
// get endpoint descriptor
|
||||||
//
|
//
|
||||||
m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)m_Urb->UrbIsochronousTransfer.PipeHandle;
|
m_EndpointDescriptor = (PUSB_ENDPOINT)m_Urb->UrbIsochronousTransfer.PipeHandle;
|
||||||
|
|
||||||
//
|
//
|
||||||
// completed initialization
|
// completed initialization
|
||||||
|
@ -406,7 +413,7 @@ CUSBRequest::InitializeWithIrp(
|
||||||
//
|
//
|
||||||
// get endpoint descriptor
|
// get endpoint descriptor
|
||||||
//
|
//
|
||||||
m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)m_Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
m_EndpointDescriptor = (PUSB_ENDPOINT)m_Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -459,11 +466,21 @@ CUSBRequest::GetMaxPacketSize()
|
||||||
{
|
{
|
||||||
if (!m_EndpointDescriptor)
|
if (!m_EndpointDescriptor)
|
||||||
{
|
{
|
||||||
//
|
if (m_DeviceSpeed == UsbLowSpeed)
|
||||||
// FIXME: use DeviceDescriptor.bMaxPacketSize0
|
{
|
||||||
// control pipe request
|
//
|
||||||
//
|
// control pipes use 8 bytes packets
|
||||||
return 8;
|
//
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// must be full speed
|
||||||
|
//
|
||||||
|
ASSERT(m_DeviceSpeed == UsbFullSpeed);
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(m_Irp);
|
ASSERT(m_Irp);
|
||||||
|
@ -472,19 +489,19 @@ CUSBRequest::GetMaxPacketSize()
|
||||||
//
|
//
|
||||||
// return max packet size
|
// return max packet size
|
||||||
//
|
//
|
||||||
return m_EndpointDescriptor->wMaxPacketSize;
|
return m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
UCHAR
|
UCHAR
|
||||||
CUSBRequest::GetInterval()
|
CUSBRequest::GetInterval()
|
||||||
{
|
{
|
||||||
ASSERT(m_EndpointDescriptor);
|
ASSERT(m_EndpointDescriptor);
|
||||||
ASSERT((m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT);
|
ASSERT((m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT);
|
||||||
|
|
||||||
//
|
//
|
||||||
// return interrupt interval
|
// return interrupt interval
|
||||||
//
|
//
|
||||||
return m_EndpointDescriptor->bInterval;
|
return m_EndpointDescriptor->EndPointDescriptor.bInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
UCHAR
|
UCHAR
|
||||||
|
@ -504,7 +521,7 @@ CUSBRequest::GetEndpointAddress()
|
||||||
//
|
//
|
||||||
// endpoint number is between 1-15
|
// endpoint number is between 1-15
|
||||||
//
|
//
|
||||||
return (m_EndpointDescriptor->bEndpointAddress & 0xF);
|
return (m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
|
@ -523,7 +540,7 @@ CUSBRequest::InternalGetTransferType()
|
||||||
//
|
//
|
||||||
// end point is defined in the low byte of bmAttributes
|
// end point is defined in the low byte of bmAttributes
|
||||||
//
|
//
|
||||||
TransferType = (m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
|
TransferType = (m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -547,7 +564,7 @@ CUSBRequest::InternalGetPidDirection()
|
||||||
//
|
//
|
||||||
// end point direction is highest bit in bEndpointAddress
|
// end point direction is highest bit in bEndpointAddress
|
||||||
//
|
//
|
||||||
return (m_EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
|
return (m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -967,7 +984,7 @@ CUSBRequest::AllocateEndpointDescriptor(
|
||||||
Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
|
Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
|
||||||
Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
|
Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
|
||||||
|
|
||||||
DPRINT("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %x\n", Descriptor->Flags, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
|
DPRINT("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %lu\n", Descriptor->Flags, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
|
||||||
|
|
||||||
//
|
//
|
||||||
// is there an endpoint descriptor
|
// is there an endpoint descriptor
|
||||||
|
@ -977,7 +994,7 @@ CUSBRequest::AllocateEndpointDescriptor(
|
||||||
//
|
//
|
||||||
// check direction
|
// check direction
|
||||||
//
|
//
|
||||||
if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor->bEndpointAddress))
|
if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// direction out
|
// direction out
|
||||||
|
@ -1041,55 +1058,16 @@ CUSBRequest::AllocateEndpointDescriptor(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
VOID
|
||||||
CUSBRequest::BuildBulkInterruptEndpoint(
|
CUSBRequest::InitDescriptor(
|
||||||
POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
|
IN POHCI_GENERAL_TD CurrentDescriptor,
|
||||||
|
IN PVOID TransferBuffer,
|
||||||
|
IN ULONG TransferBufferLength,
|
||||||
|
IN UCHAR PidDirection)
|
||||||
{
|
{
|
||||||
POHCI_GENERAL_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor, LastDescriptor;
|
ULONG Direction;
|
||||||
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
|
||||||
ULONG BufferSize, CurrentSize, Direction, MaxLengthInPage;
|
|
||||||
NTSTATUS Status;
|
|
||||||
PVOID Buffer;
|
|
||||||
|
|
||||||
//
|
if (PidDirection)
|
||||||
// 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
|
// input direction
|
||||||
|
@ -1104,24 +1082,42 @@ CUSBRequest::BuildBulkInterruptEndpoint(
|
||||||
Direction = OHCI_TD_DIRECTION_PID_OUT;
|
Direction = OHCI_TD_DIRECTION_PID_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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(TransferBuffer).LowPart;
|
||||||
|
CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + TransferBufferLength - 1;
|
||||||
|
|
||||||
|
DPRINT("CurrentDescriptor %p Addr %x TransferBufferLength %lu\n", CurrentDescriptor, CurrentDescriptor->PhysicalAddress.LowPart, TransferBufferLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::BuildTransferDescriptorChain(
|
||||||
|
IN PVOID TransferBuffer,
|
||||||
|
IN ULONG TransferBufferLength,
|
||||||
|
IN UCHAR PidDirection,
|
||||||
|
OUT POHCI_GENERAL_TD * OutFirstDescriptor,
|
||||||
|
OUT POHCI_GENERAL_TD * OutLastDescriptor,
|
||||||
|
OUT PULONG OutTransferBufferOffset)
|
||||||
|
{
|
||||||
|
POHCI_GENERAL_TD FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG MaxLengthInPage, TransferBufferOffset = 0;
|
||||||
|
ULONG MaxPacketSize = 0, TransferSize, CurrentSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// for now use one page as maximum size
|
||||||
|
//
|
||||||
|
MaxPacketSize = PAGE_SIZE;
|
||||||
|
|
||||||
do
|
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
|
// allocate transfer descriptor
|
||||||
//
|
//
|
||||||
|
@ -1129,49 +1125,60 @@ CUSBRequest::BuildBulkInterruptEndpoint(
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// failed to create transfer descriptor
|
// failed to allocate transfer descriptor
|
||||||
// TODO: cleanup
|
|
||||||
//
|
//
|
||||||
ASSERT(FALSE);
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
|
|
||||||
FreeDescriptor(LastDescriptor);
|
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
if (MaxPacketSize)
|
||||||
// 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;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (m_Urb != NULL)
|
|
||||||
{
|
{
|
||||||
if (m_Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_SHORT_TRANSFER_OK)
|
//
|
||||||
{
|
// transfer size is minimum available buffer or endpoint size
|
||||||
//
|
//
|
||||||
// indicate short packet support
|
TransferSize = min(TransferBufferLength - TransferBufferOffset, MaxPacketSize);
|
||||||
//
|
|
||||||
CurrentDescriptor->Flags |= OHCI_TD_BUFFER_ROUNDING;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// use available buffer
|
||||||
|
//
|
||||||
|
TransferSize = TransferBufferLength - TransferBufferOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get page offset
|
||||||
|
//
|
||||||
|
MaxLengthInPage = PAGE_SIZE - BYTE_OFFSET(TransferBuffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get minimum from current page size
|
||||||
|
//
|
||||||
|
CurrentSize = min(TransferSize, MaxLengthInPage);
|
||||||
|
ASSERT(CurrentSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// now init the descriptor
|
||||||
|
//
|
||||||
|
InitDescriptor(CurrentDescriptor,
|
||||||
|
(PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset),
|
||||||
|
CurrentSize,
|
||||||
|
PidDirection);
|
||||||
|
|
||||||
|
//
|
||||||
|
// adjust offset
|
||||||
|
//
|
||||||
|
TransferBufferOffset += CurrentSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// is there a previous descriptor
|
// is there a previous descriptor
|
||||||
//
|
//
|
||||||
if (PreviousDescriptor)
|
if (LastDescriptor)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// link descriptors
|
// link descriptors
|
||||||
//
|
//
|
||||||
PreviousDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor;
|
LastDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor;
|
||||||
PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
|
LastDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1181,24 +1188,115 @@ CUSBRequest::BuildBulkInterruptEndpoint(
|
||||||
FirstDescriptor = CurrentDescriptor;
|
FirstDescriptor = CurrentDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
if(TransferBufferLength == TransferBufferOffset)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// end reached
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
}while(TRUE);
|
||||||
// set previous descriptor
|
|
||||||
//
|
|
||||||
PreviousDescriptor = CurrentDescriptor;
|
|
||||||
|
|
||||||
|
if (OutFirstDescriptor)
|
||||||
|
{
|
||||||
//
|
//
|
||||||
// subtract buffer size
|
// store first descriptor
|
||||||
//
|
//
|
||||||
BufferSize -= CurrentSize;
|
*OutFirstDescriptor = FirstDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OutLastDescriptor)
|
||||||
|
{
|
||||||
//
|
//
|
||||||
// increment buffer offset
|
// store last descriptor
|
||||||
//
|
//
|
||||||
Buffer = (PVOID)((ULONG_PTR)Buffer + CurrentSize);
|
*OutLastDescriptor = CurrentDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
}while(BufferSize);
|
if (OutTransferBufferOffset)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// store offset
|
||||||
|
//
|
||||||
|
*OutTransferBufferOffset = TransferBufferOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::BuildBulkInterruptEndpoint(
|
||||||
|
POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
|
||||||
|
{
|
||||||
|
POHCI_GENERAL_TD FirstDescriptor, LastDescriptor;
|
||||||
|
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PVOID Base;
|
||||||
|
ULONG ChainDescriptorLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(m_EndpointDescriptor);
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate endpoint descriptor
|
||||||
|
//
|
||||||
|
Status = AllocateEndpointDescriptor(&EndpointDescriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to create setup descriptor
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(m_TransferBufferMDL);
|
||||||
|
|
||||||
|
if (m_Base == NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get buffer
|
||||||
|
//
|
||||||
|
m_Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Increase the size of last transfer, 0 in case this is the first
|
||||||
|
//
|
||||||
|
Base = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted);
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
ASSERT(m_EndpointDescriptor);
|
||||||
|
ASSERT(Base);
|
||||||
|
|
||||||
|
//
|
||||||
|
// use 2 * PAGE_SIZE at max for each new request
|
||||||
|
//
|
||||||
|
ULONG MaxTransferLength = min(1 * PAGE_SIZE, m_TransferBufferLength - m_TransferBufferLengthCompleted);
|
||||||
|
DPRINT("m_TransferBufferLength %lu m_TransferBufferLengthCompleted %lu DataToggle %x\n", m_TransferBufferLength, m_TransferBufferLengthCompleted, m_EndpointDescriptor->DataToggle);
|
||||||
|
|
||||||
|
//
|
||||||
|
// build bulk transfer descriptor chain
|
||||||
|
//
|
||||||
|
Status = BuildTransferDescriptorChain(Base,
|
||||||
|
MaxTransferLength,
|
||||||
|
InternalGetPidDirection(),
|
||||||
|
&FirstDescriptor,
|
||||||
|
&LastDescriptor,
|
||||||
|
&ChainDescriptorLength);
|
||||||
|
|
||||||
|
//
|
||||||
|
// move to next offset
|
||||||
|
//
|
||||||
|
m_TransferBufferLengthCompleted += ChainDescriptorLength;
|
||||||
|
|
||||||
//
|
//
|
||||||
// first descriptor has no carry bit
|
// first descriptor has no carry bit
|
||||||
|
@ -1206,33 +1304,33 @@ CUSBRequest::BuildBulkInterruptEndpoint(
|
||||||
FirstDescriptor->Flags &= ~OHCI_TD_TOGGLE_CARRY;
|
FirstDescriptor->Flags &= ~OHCI_TD_TOGGLE_CARRY;
|
||||||
|
|
||||||
//
|
//
|
||||||
// fixme: toggle
|
// apply data toggle
|
||||||
//
|
//
|
||||||
FirstDescriptor->Flags |= OHCI_TD_TOGGLE_0;
|
FirstDescriptor->Flags |= (m_EndpointDescriptor->DataToggle ? OHCI_TD_TOGGLE_1 : OHCI_TD_TOGGLE_0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// clear interrupt mask for last transfer descriptor
|
// clear interrupt mask for last transfer descriptor
|
||||||
//
|
//
|
||||||
CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
|
LastDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// fire interrupt as soon transfer is finished
|
// fire interrupt as soon transfer is finished
|
||||||
//
|
//
|
||||||
CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
|
LastDescriptor->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
|
// now link descriptor to endpoint
|
||||||
//
|
//
|
||||||
EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
|
EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart;
|
||||||
EndpointDescriptor->TailPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart;
|
EndpointDescriptor->TailPhysicalDescriptor = (FirstDescriptor == LastDescriptor ? 0 : LastDescriptor->PhysicalAddress.LowPart);
|
||||||
EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
|
EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// dump descriptor list
|
||||||
|
//
|
||||||
|
//DumpEndpointDescriptor(EndpointDescriptor);
|
||||||
|
|
||||||
//
|
//
|
||||||
// store result
|
// store result
|
||||||
//
|
//
|
||||||
|
@ -1567,6 +1665,12 @@ CUSBRequest::FreeEndpointDescriptor(
|
||||||
|
|
||||||
DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
|
DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check for errors
|
||||||
|
//
|
||||||
|
CheckError(OutDescriptor);
|
||||||
|
|
||||||
|
|
||||||
if (OutDescriptor->Flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT)
|
if (OutDescriptor->Flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -1686,6 +1790,14 @@ CUSBRequest::CheckError(
|
||||||
//
|
//
|
||||||
TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
|
TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
|
||||||
|
|
||||||
|
if (m_EndpointDescriptor != NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// update data toggle
|
||||||
|
//
|
||||||
|
m_EndpointDescriptor->DataToggle = (OutDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_TOGGLE_CARRY);
|
||||||
|
}
|
||||||
|
|
||||||
while(TransferDescriptor)
|
while(TransferDescriptor)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -1776,21 +1888,18 @@ CUSBRequest::CheckError(
|
||||||
TransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor;
|
TransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CUSBRequest::CompletionCallback(
|
CUSBRequest::CompletionCallback()
|
||||||
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
|
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PURB Urb;
|
PURB Urb;
|
||||||
|
|
||||||
DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
|
DPRINT("CUSBRequest::CompletionCallback\n");
|
||||||
|
|
||||||
//
|
|
||||||
// check for errors
|
|
||||||
//
|
|
||||||
CheckError(OutDescriptor);
|
|
||||||
|
|
||||||
if (m_Irp)
|
if (m_Irp)
|
||||||
{
|
{
|
||||||
|
@ -1826,12 +1935,11 @@ CUSBRequest::CompletionCallback(
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME: support status and calculate length
|
// FIXME calculate length
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME: check if the transfer was split
|
// complete request
|
||||||
// if yes dont complete irp yet
|
|
||||||
//
|
//
|
||||||
IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,4 +108,26 @@ NTSTATUS CreateUSBQueue(PUSBQUEUE *OutUsbQueue);
|
||||||
//
|
//
|
||||||
NTSTATUS InternalCreateUSBRequest(PUSBREQUEST *OutRequest);
|
NTSTATUS InternalCreateUSBRequest(PUSBREQUEST *OutRequest);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _USB_ENDPOINT
|
||||||
|
{
|
||||||
|
USB_ENDPOINT_DESCRIPTOR EndPointDescriptor;
|
||||||
|
UCHAR HubAddress;
|
||||||
|
UCHAR HubPort;
|
||||||
|
UCHAR DataToggle;
|
||||||
|
} USB_ENDPOINT, *PUSB_ENDPOINT;
|
||||||
|
|
||||||
|
typedef struct _USB_INTERFACE
|
||||||
|
{
|
||||||
|
USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||||
|
USB_ENDPOINT *EndPoints;
|
||||||
|
} USB_INTERFACE, *PUSB_INTERFACE;
|
||||||
|
|
||||||
|
typedef struct _USB_CONFIGURATION
|
||||||
|
{
|
||||||
|
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
|
||||||
|
USB_INTERFACE *Interfaces;
|
||||||
|
} USB_CONFIGURATION, *PUSB_CONFIGURATION;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue