}
// 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 OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
- virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp);
+ 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 InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp, IN USB_DEVICE_SPEED DeviceSpeed);
virtual BOOLEAN IsRequestComplete();
virtual ULONG GetTransferType();
virtual NTSTATUS GetEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR ** OutEndpointDescriptor);
NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD *OutDescriptor, ULONG FrameCount);
UCHAR GetEndpointAddress();
USHORT GetMaxPacketSize();
+ VOID CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
+
// constructor / destructor
CUSBRequest(IUnknown *OuterUnknown){}
NTSTATUS m_NtStatusCode;
ULONG m_UrbStatusCode;
+ //
+ // device speed
+ //
+ USB_DEVICE_SPEED m_DeviceSpeed;
+
+ //
+ // store urb
+ //
+ PURB m_Urb;
};
//----------------------------------------------------------------------------------------
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)
{
m_DeviceAddress = DeviceAddress;
m_EndpointDescriptor = EndpointDescriptor;
m_TotalBytesTransferred = 0;
+ m_DeviceSpeed = DeviceSpeed;
//
// Set Length Completed to 0
NTSTATUS
CUSBRequest::InitializeWithIrp(
IN PDMAMEMORYMANAGER DmaManager,
- IN OUT PIRP Irp)
+ IN OUT PIRP Irp,
+ IN USB_DEVICE_SPEED DeviceSpeed)
{
PIO_STACK_LOCATION IoStack;
- PURB Urb;
//
// sanity checks
//
// get urb
//
- Urb = (PURB)IoStack->Parameters.Others.Argument1;
+ m_Urb = (PURB)IoStack->Parameters.Others.Argument1;
//
// store irp
//
m_Irp = Irp;
+ //
+ // store speed
+ //
+ m_DeviceSpeed = DeviceSpeed;
+
//
// check function type
//
- switch (Urb->UrbHeader.Function)
+ switch (m_Urb->UrbHeader.Function)
{
case URB_FUNCTION_ISOCH_TRANSFER:
{
//
// there must be at least one packet
//
- ASSERT(Urb->UrbIsochronousTransfer.NumberOfPackets);
+ ASSERT(m_Urb->UrbIsochronousTransfer.NumberOfPackets);
//
// is there data to be transferred
//
- if (Urb->UrbIsochronousTransfer.TransferBufferLength)
+ if (m_Urb->UrbIsochronousTransfer.TransferBufferLength)
{
//
// Check if there is a MDL
//
- if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
+ if (!m_Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
{
//
// sanity check
//
- PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
+ PC_ASSERT(m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
//
// Create one using TransferBuffer
//
- DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
- m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
- Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
+ DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer, m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
+ m_TransferBufferMDL = IoAllocateMdl(m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
+ m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
FALSE,
FALSE,
NULL);
//
// use provided mdl
//
- m_TransferBufferMDL = Urb->UrbIsochronousTransfer.TransferBufferMDL;
+ m_TransferBufferMDL = m_Urb->UrbIsochronousTransfer.TransferBufferMDL;
}
}
//
// save buffer length
//
- m_TransferBufferLength = Urb->UrbIsochronousTransfer.TransferBufferLength;
+ m_TransferBufferLength = m_Urb->UrbIsochronousTransfer.TransferBufferLength;
//
// Set Length Completed to 0
//
// get endpoint descriptor
//
- m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbIsochronousTransfer.PipeHandle;
+ m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)m_Urb->UrbIsochronousTransfer.PipeHandle;
//
// completed initialization
//
// bulk interrupt transfer
//
- if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
+ if (m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
{
//
// Check if there is a MDL
//
- if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
+ if (!m_Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
{
//
// sanity check
//
- PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
+ PC_ASSERT(m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
//
// Create one using TransferBuffer
//
- DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
- m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
- Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
+ DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer, m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
+ m_TransferBufferMDL = IoAllocateMdl(m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
+ m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
FALSE,
FALSE,
NULL);
}
else
{
- m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
+ m_TransferBufferMDL = m_Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
}
//
// save buffer length
//
- m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
+ m_TransferBufferLength = m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
//
// Set Length Completed to 0
//
// get endpoint descriptor
//
- m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
+ m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)m_Urb->UrbBulkOrInterruptTransfer.PipeHandle;
}
break;
}
default:
- DPRINT1("URB Function: not supported %x\n", Urb->UrbHeader.Function);
+ DPRINT1("URB Function: not supported %x\n", m_Urb->UrbHeader.Function);
PC_ASSERT(FALSE);
}
CUSBRequest::BuildIsochronousEndpoint(
POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
{
- POHCI_ISO_TD FirstDescriptor, PreviousDescriptor = NULL, CurrentDescriptor;
+ POHCI_ISO_TD FirstDescriptor = NULL, PreviousDescriptor = NULL, CurrentDescriptor = NULL;
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor;
ULONG Index = 0, SubIndex, NumberOfPackets, PageOffset, Page;
NTSTATUS Status;
Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
- DPRINT1("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %x\n", Descriptor->Flags, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
+ DPRINT("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %x\n", Descriptor->Flags, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
//
// is there an endpoint descriptor
}
-
//
- // FIXME: detect type
+ // set type
//
- Descriptor->Flags |= OHCI_ENDPOINT_FULL_SPEED;
+ if (m_DeviceSpeed == UsbFullSpeed)
+ {
+ //
+ // device is full speed
+ //
+ Descriptor->Flags |= OHCI_ENDPOINT_FULL_SPEED;
+ }
+ else if (m_DeviceSpeed == UsbLowSpeed)
+ {
+ //
+ // device is full speed
+ //
+ Descriptor->Flags |= OHCI_ENDPOINT_LOW_SPEED;
+ }
+ else
+ {
+ //
+ // error
+ //
+ ASSERT(FALSE);
+ }
Descriptor->HeadPhysicalDescriptor = 0;
Descriptor->NextPhysicalEndpoint = 0;
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)
+ {
+ //
+ // indicate short packet support
+ //
+ CurrentDescriptor->Flags |= OHCI_TD_BUFFER_ROUNDING;
+ }
+ }
+#endif
+
//
// is there a previous descriptor
//
//
// initialize data descriptor
//
- DataDescriptor->Flags = 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 | OHCI_TD_DIRECTION_PID_IN;
+ DataDescriptor->Flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_TOGGLE_CARRY | OHCI_TD_TOGGLE_1;
+
+ if (m_EndpointDescriptor)
+ {
+ if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor->bEndpointAddress))
+ {
+ //
+ // direction out
+ //
+ DataDescriptor->Flags |= OHCI_TD_DIRECTION_PID_OUT;
+ }
+ else
+ {
+ //
+ // direction in
+ //
+ DataDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
+ }
+ }
+ else
+ {
+ //
+ // no end point address provided - assume its an in direction
+ //
+ DataDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
+ }
+
+ //
+ // use short packets
+ //
+ DataDescriptor->Flags |= OHCI_TD_BUFFER_ROUNDING;
//
// store physical address of buffer
//
DataDescriptor->BufferPhysical = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1;
-
}
//
// initialize setup descriptor
//
- SetupDescriptor->Flags = OHCI_TD_DIRECTION_PID_SETUP | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
+ SetupDescriptor->Flags = OHCI_TD_BUFFER_ROUNDING | OHCI_TD_DIRECTION_PID_SETUP | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
if (m_SetupPacket)
{
}
VOID
-CUSBRequest::CompletionCallback(
+CUSBRequest::CheckError(
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
{
- PIO_STACK_LOCATION IoStack;
+ POHCI_GENERAL_TD TransferDescriptor;
+ ULONG ConditionCode;
PURB Urb;
+ PIO_STACK_LOCATION IoStack;
- DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
//
// set status code
m_NtStatusCode = STATUS_SUCCESS;
m_UrbStatusCode = USBD_STATUS_SUCCESS;
+
+ if (OutDescriptor->Flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT)
+ {
+ //
+ // FIXME: handle isochronous support
+ //
+ ASSERT(FALSE);
+ }
+ else
+ {
+ //
+ // get first general transfer descriptor
+ //
+ TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
+
+ while(TransferDescriptor)
+ {
+ //
+ // the descriptor must have been processed
+ //
+ ASSERT(OHCI_TD_GET_CONDITION_CODE(TransferDescriptor->Flags) != OHCI_TD_CONDITION_NOT_ACCESSED);
+
+ //
+ // get condition code
+ //
+ ConditionCode = OHCI_TD_GET_CONDITION_CODE(TransferDescriptor->Flags);
+ if (ConditionCode != OHCI_TD_CONDITION_NO_ERROR)
+ {
+ //
+ // FIXME status code
+ //
+ m_NtStatusCode = STATUS_UNSUCCESSFUL;
+
+ switch(ConditionCode)
+ {
+ case OHCI_TD_CONDITION_CRC_ERROR:
+ DPRINT1("OHCI_TD_CONDITION_CRC_ERROR detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_CRC;
+ break;
+ case OHCI_TD_CONDITION_BIT_STUFFING:
+ DPRINT1("OHCI_TD_CONDITION_BIT_STUFFING detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_BTSTUFF;
+ break;
+ case OHCI_TD_CONDITION_TOGGLE_MISMATCH:
+ DPRINT1("OHCI_TD_CONDITION_TOGGLE_MISMATCH detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_DATA_TOGGLE_MISMATCH;
+ break;
+ case OHCI_TD_CONDITION_STALL:
+ DPRINT1("OHCI_TD_CONDITION_STALL detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_STALL_PID;
+ break;
+ case OHCI_TD_CONDITION_NO_RESPONSE:
+ DPRINT1("OHCI_TD_CONDITION_NO_RESPONSE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_DEV_NOT_RESPONDING;
+ break;
+ case OHCI_TD_CONDITION_PID_CHECK_FAILURE:
+ DPRINT1("OHCI_TD_CONDITION_PID_CHECK_FAILURE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_PID_CHECK_FAILURE;
+ break;
+ case OHCI_TD_CONDITION_UNEXPECTED_PID:
+ DPRINT1("OHCI_TD_CONDITION_UNEXPECTED_PID detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_UNEXPECTED_PID;
+ break;
+ case OHCI_TD_CONDITION_DATA_OVERRUN:
+ DPRINT1("OHCI_TD_CONDITION_DATA_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_DATA_OVERRUN;
+ break;
+ case OHCI_TD_CONDITION_DATA_UNDERRUN:
+ if (m_Irp)
+ {
+ //
+ // get current irp stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
+ //
+ // get urb
+ //
+ Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+ if(Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_SHORT_TRANSFER_OK)
+ {
+ //
+ // short packets are ok
+ //
+ ASSERT(Urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER);
+ m_NtStatusCode = STATUS_SUCCESS;
+ break;
+ }
+ }
+ DPRINT1("OHCI_TD_CONDITION_DATA_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_DATA_UNDERRUN;
+ break;
+ case OHCI_TD_CONDITION_BUFFER_OVERRUN:
+ DPRINT1("OHCI_TD_CONDITION_BUFFER_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_BUFFER_OVERRUN;
+ break;
+ case OHCI_TD_CONDITION_BUFFER_UNDERRUN:
+ DPRINT1("OHCI_TD_CONDITION_BUFFER_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
+ m_UrbStatusCode = USBD_STATUS_BUFFER_UNDERRUN;
+ break;
+ }
+ }
+
+ //
+ // get next
+ //
+ TransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor;
+ }
+ }
+}
+
+VOID
+CUSBRequest::CompletionCallback(
+ struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
+{
+ PIO_STACK_LOCATION IoStack;
+ PURB Urb;
+
+ DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
+
+ //
+ // check for errors
+ //
+ CheckError(OutDescriptor);
+
if (m_Irp)
{
//
// set irp completion status
//
- m_Irp->IoStatus.Status = STATUS_SUCCESS; //FIXME
+ m_Irp->IoStatus.Status = m_NtStatusCode;
//
// get current irp stack location
//
// store urb status
//
- Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; //FIXME
+ Urb->UrbHeader.Status = m_UrbStatusCode;
//
// Check if the MDL was created