mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 10:21:50 +00:00
[USBEHCI_NEW]
- Null terminate buffer from IOCTL_USB_GET_ROOT_HUB_NAME, fixes usbview problems - Implement URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER, IUSBHardware needs more work - Silence debug traces - Start implementing IUSBRequest interfaces - Complete unhandled major irp with status success svn path=/branches/usb-bringup/; revision=51396
This commit is contained in:
parent
d3e13a4ada
commit
3ac2c07f55
7 changed files with 1083 additions and 55 deletions
|
@ -7,6 +7,7 @@ add_definitions(-D_WIN32_WINNT=0x600)
|
||||||
add_library(usbehci SHARED
|
add_library(usbehci SHARED
|
||||||
usbehci.cpp
|
usbehci.cpp
|
||||||
usb_device.cpp
|
usb_device.cpp
|
||||||
|
usb_request.cpp
|
||||||
usb_queue.cpp
|
usb_queue.cpp
|
||||||
hcd_controller.cpp
|
hcd_controller.cpp
|
||||||
hardware.cpp
|
hardware.cpp
|
||||||
|
|
|
@ -327,8 +327,11 @@ CHCDController::HandleDeviceControl(
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// informal debug print
|
// null terminate it
|
||||||
//
|
//
|
||||||
|
PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG) - sizeof(WCHAR) >= ResultLength);
|
||||||
|
|
||||||
|
DriverKey->DriverKeyName[ResultLength / sizeof(WCHAR)] = L'\0';
|
||||||
DPRINT1("Result %S\n", DriverKey->DriverKeyName);
|
DPRINT1("Result %S\n", DriverKey->DriverKeyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,7 +555,6 @@ CHCDController::HandlePnp(
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
DPRINT1("CHCDController::HandlePnp Dispatch to lower device object %lx\n", IoStack->MinorFunction);
|
|
||||||
//
|
//
|
||||||
// forward irp to next device object
|
// forward irp to next device object
|
||||||
//
|
//
|
||||||
|
|
|
@ -61,6 +61,8 @@ public:
|
||||||
NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
|
||||||
NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
|
||||||
NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb);
|
||||||
|
NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
|
||||||
|
|
||||||
|
|
||||||
// constructor / destructor
|
// constructor / destructor
|
||||||
CHubController(IUnknown *OuterUnknown){}
|
CHubController(IUnknown *OuterUnknown){}
|
||||||
|
@ -155,6 +157,20 @@ const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] =
|
||||||
0xFF /* bInterval; (255ms -- usb 2.0 spec) */
|
0xFF /* bInterval; (255ms -- usb 2.0 spec) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// flags for handling USB_REQUEST_SET_FEATURE / USB_REQUEST_GET_FEATURE
|
||||||
|
//
|
||||||
|
#define PORT_ENABLE 1
|
||||||
|
#define PORT_SUSPEND 2
|
||||||
|
#define PORT_OVER_CURRENT 3
|
||||||
|
#define PORT_RESET 4
|
||||||
|
#define PORT_POWER 8
|
||||||
|
#define C_PORT_CONNECTION 16
|
||||||
|
#define C_PORT_ENABLE 17
|
||||||
|
#define C_PORT_SUSPEND 18
|
||||||
|
#define C_PORT_OVER_CURRENT 19
|
||||||
|
#define C_PORT_RESET 20
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDMETHODCALLTYPE
|
STDMETHODCALLTYPE
|
||||||
|
@ -653,7 +669,9 @@ CHubController::HandlePnp(
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
DPRINT1("CHubController::HandlePnp Unhandeled %x\n", IoStack->MinorFunction);
|
//
|
||||||
|
// ignore request with default status
|
||||||
|
//
|
||||||
Status = Irp->IoStatus.Status;
|
Status = Irp->IoStatus.Status;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -682,6 +700,15 @@ CHubController::HandlePower(
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CHubController::HandleBulkOrInterruptTransfer(
|
||||||
|
IN OUT PIRP Irp,
|
||||||
|
PURB Urb)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -689,11 +716,143 @@ CHubController::HandleClassOther(
|
||||||
IN OUT PIRP Irp,
|
IN OUT PIRP Irp,
|
||||||
PURB Urb)
|
PURB Urb)
|
||||||
{
|
{
|
||||||
DPRINT1("CHubController::HandleClassOther> Request %x Value %x not implemented\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
|
NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
USHORT PortStatus = 0, PortChange = 0;
|
||||||
|
PUSHORT Buffer;
|
||||||
|
ULONG NumPort;
|
||||||
|
ULONG PortId;
|
||||||
|
|
||||||
|
//DPRINT1("CHubController::HandleClassOther> Request %x Value %x not implemented\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME implement me
|
// get number of ports available
|
||||||
//
|
//
|
||||||
|
Status = m_Hardware->GetDeviceDetails(NULL, NULL, &NumPort, NULL);
|
||||||
|
PC_ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < NumPort);
|
||||||
|
|
||||||
|
//
|
||||||
|
// port range reported start from 1 -n
|
||||||
|
// convert back port id so it matches the hardware
|
||||||
|
//
|
||||||
|
PortId = Urb->UrbControlVendorClassRequest.Index - 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// check request code
|
||||||
|
//
|
||||||
|
switch(Urb->UrbControlVendorClassRequest.Request)
|
||||||
|
{
|
||||||
|
case USB_REQUEST_GET_STATUS:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength == sizeof(USHORT) * 2);
|
||||||
|
PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get port status
|
||||||
|
//
|
||||||
|
//Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
|
||||||
|
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// request contains buffer of 2 ushort which are used from submitting port status and port change status
|
||||||
|
//
|
||||||
|
Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store status, then port change
|
||||||
|
//
|
||||||
|
*Buffer = PortStatus;
|
||||||
|
Buffer++;
|
||||||
|
*Buffer = PortChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case USB_REQUEST_CLEAR_FEATURE:
|
||||||
|
{
|
||||||
|
switch (Urb->UrbControlVendorClassRequest.Value)
|
||||||
|
{
|
||||||
|
case C_PORT_CONNECTION:
|
||||||
|
//Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION);
|
||||||
|
break;
|
||||||
|
case C_PORT_RESET:
|
||||||
|
//Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
|
||||||
|
PC_ASSERT(FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case USB_REQUEST_SET_FEATURE:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// request set feature
|
||||||
|
//
|
||||||
|
switch(Urb->UrbControlVendorClassRequest.Value)
|
||||||
|
{
|
||||||
|
case PORT_ENABLE:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// port enable is a no-op for EHCI
|
||||||
|
//
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PORT_SUSPEND:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// set suspend port feature
|
||||||
|
//
|
||||||
|
Status = STATUS_SUCCESS; //m_Hardware->SetPortFeature(PortId, PORT_SUSPEND);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PORT_POWER:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// set power feature on port
|
||||||
|
//
|
||||||
|
Status = STATUS_SUCCESS; //m_Hardware->SetPortFeature(PortId, PORT_POWER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PORT_RESET:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// reset port feature
|
||||||
|
//
|
||||||
|
Status = m_Hardware->ResetPort(PortId);
|
||||||
|
PC_ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
DPRINT1("Unsupported request id %x\n", Urb->UrbControlVendorClassRequest.Value);
|
||||||
|
PC_ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
DPRINT1("CHubController::HandleClassOther Unknown request code %x\n", Urb->UrbControlVendorClassRequest.Request);
|
||||||
|
PC_ASSERT(0);
|
||||||
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -862,7 +1021,6 @@ CHubController::HandleGetDescriptor(
|
||||||
|
|
||||||
if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
|
if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
|
||||||
{
|
{
|
||||||
DPRINT1("Root Hub descriptor\n");
|
|
||||||
//
|
//
|
||||||
// copy root hub device descriptor
|
// copy root hub device descriptor
|
||||||
//
|
//
|
||||||
|
@ -960,13 +1118,6 @@ CHubController::HandleDeviceControl(
|
||||||
//
|
//
|
||||||
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
|
||||||
DPRINT1("HandleDeviceControl>Type: FDO %u IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n",
|
|
||||||
DeviceExtension->IsFDO,
|
|
||||||
IoStack->Parameters.DeviceIoControl.IoControlCode,
|
|
||||||
IoStack->Parameters.DeviceIoControl.InputBufferLength,
|
|
||||||
IoStack->Parameters.DeviceIoControl.OutputBufferLength);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// determine which request should be performed
|
// determine which request should be performed
|
||||||
//
|
//
|
||||||
|
@ -980,8 +1131,6 @@ CHubController::HandleDeviceControl(
|
||||||
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
PC_ASSERT(Urb);
|
PC_ASSERT(Urb);
|
||||||
|
|
||||||
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x Length %lu Status %x Handle %p Flags %x UNIMPLEMENTED\n", Urb->UrbHeader.Function, Urb->UrbHeader.Length, Urb->UrbHeader.Status, Urb->UrbHeader.UsbdDeviceHandle, Urb->UrbHeader.UsbdFlags);
|
|
||||||
|
|
||||||
switch (Urb->UrbHeader.Function)
|
switch (Urb->UrbHeader.Function)
|
||||||
{
|
{
|
||||||
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
|
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
|
||||||
|
@ -999,6 +1148,12 @@ CHubController::HandleDeviceControl(
|
||||||
case URB_FUNCTION_CLASS_OTHER:
|
case URB_FUNCTION_CLASS_OTHER:
|
||||||
Status = HandleClassOther(Irp, Urb);
|
Status = HandleClassOther(Irp, Urb);
|
||||||
break;
|
break;
|
||||||
|
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
|
||||||
|
Status = HandleBulkOrInterruptTransfer(Irp, Urb);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// request completed
|
// request completed
|
||||||
|
@ -1007,7 +1162,7 @@ CHubController::HandleDeviceControl(
|
||||||
}
|
}
|
||||||
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
|
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
|
||||||
{
|
{
|
||||||
DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
|
DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
|
||||||
|
|
||||||
if (IoStack->Parameters.Others.Argument1)
|
if (IoStack->Parameters.Others.Argument1)
|
||||||
{
|
{
|
||||||
|
@ -1032,7 +1187,7 @@ CHubController::HandleDeviceControl(
|
||||||
}
|
}
|
||||||
case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
|
case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
|
||||||
{
|
{
|
||||||
DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
|
DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
|
||||||
|
|
||||||
//
|
//
|
||||||
// this is the first request send, it delivers the PDO to the caller
|
// this is the first request send, it delivers the PDO to the caller
|
||||||
|
@ -1061,7 +1216,7 @@ CHubController::HandleDeviceControl(
|
||||||
}
|
}
|
||||||
case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
|
case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
|
||||||
{
|
{
|
||||||
DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
|
DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
|
||||||
|
|
||||||
//
|
//
|
||||||
// after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
|
// after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
|
||||||
|
@ -1082,6 +1237,14 @@ CHubController::HandleDeviceControl(
|
||||||
Irp->IoStatus.Information = sizeof(ULONG);
|
Irp->IoStatus.Information = sizeof(ULONG);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
|
||||||
|
IoStack->Parameters.DeviceIoControl.IoControlCode,
|
||||||
|
IoStack->Parameters.DeviceIoControl.InputBufferLength,
|
||||||
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
|
@ -1921,7 +2084,37 @@ USBHI_GetControllerInformation(
|
||||||
ULONG ControllerInformationBufferLength,
|
ULONG ControllerInformationBufferLength,
|
||||||
PULONG LengthReturned)
|
PULONG LengthReturned)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
|
||||||
|
|
||||||
|
DPRINT1("USBHI_GetControllerInformation\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
PC_ASSERT(ControllerInformationBuffer);
|
||||||
|
PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
|
||||||
|
|
||||||
|
//
|
||||||
|
// get controller info buffer
|
||||||
|
//
|
||||||
|
ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME only version 0 is supported for now
|
||||||
|
//
|
||||||
|
PC_ASSERT(ControllerInfo->InformationLevel == 0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// fill in information
|
||||||
|
//
|
||||||
|
ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
|
||||||
|
ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
|
||||||
|
ControllerInfo->IsHighSpeedController = TRUE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// set length returned
|
||||||
|
//
|
||||||
|
*LengthReturned = ControllerInfo->ActualLength;
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -312,6 +312,8 @@ typedef IDMAMemoryManager *PDMAMEMORYMANAGER;
|
||||||
// CancelCallback routine is invoked.
|
// CancelCallback routine is invoked.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
struct _QUEUE_HEAD;
|
||||||
|
|
||||||
DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
||||||
{
|
{
|
||||||
DEFINE_ABSTRACT_UNKNOWN()
|
DEFINE_ABSTRACT_UNKNOWN()
|
||||||
|
@ -324,44 +326,39 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
||||||
// If there is a TransferBuffer, the TransferBufferLength contains the length of the buffer
|
// If there is a TransferBuffer, the TransferBufferLength contains the length of the buffer
|
||||||
|
|
||||||
|
|
||||||
virtual NTSTATUS InitializeWithSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
|
virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager,
|
||||||
IN ULONG TransferBufferLength,
|
IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
|
||||||
IN PVOID TransferBuffer) = 0;
|
IN OUT ULONG TransferBufferLength,
|
||||||
|
IN OUT PMDL TransferBuffer) = 0;
|
||||||
//
|
|
||||||
//TODO: find required parameters for different packet types
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// SetEndPoint
|
// InitializeWithIrp
|
||||||
//
|
//
|
||||||
// Description: sets the endpoint of the request.
|
// Description: initializes the request with an IRP
|
||||||
|
// The irp contains an URB block which contains all necessary information
|
||||||
|
|
||||||
virtual NTSTATUS SetEndPoint(PUSB_ENDPOINT_DESCRIPTOR EndPoint);
|
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager,
|
||||||
|
IN OUT PIRP Irp);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// SetCompletionDetails
|
// SetCompletionEvent
|
||||||
//
|
//
|
||||||
// Description: sets up how the request should be completed
|
// Description: sets up completion event which is signaled when the
|
||||||
// If an irp is passed, then it is completed with status code of the
|
// request is completed or cancelled
|
||||||
// CompletionCallback or CancelCallback
|
|
||||||
// If an event is passed, then the event is signaled
|
|
||||||
|
|
||||||
virtual NTSTATUS SetCompletionDetails(IN OPTIONAL PIRP Irp,
|
virtual NTSTATUS SetCompletionEvent(IN PKEVENT Event) = 0;
|
||||||
IN OPTIONAL PKEVENT Event) = 0;
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// CompletionCallback
|
// CompletionCallback
|
||||||
//
|
//
|
||||||
// Description: called when request has been completed. It is called when
|
// Description: called when request has been completed. It is called when
|
||||||
// IUSBQueue completes the request
|
// IUSBQueue completes the request
|
||||||
|
|
||||||
virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode,
|
virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode,
|
||||||
IN ULONG UrbStatusCode) = 0;
|
IN ULONG UrbStatusCode) = 0;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -371,6 +368,31 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
||||||
|
|
||||||
virtual VOID CancelCallback(IN NTSTATUS NtStatusCode) = 0;
|
virtual VOID CancelCallback(IN NTSTATUS NtStatusCode) = 0;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// GetQueueHead
|
||||||
|
//
|
||||||
|
// Description: returns an initialized queue head with contains the all transfer descriptors
|
||||||
|
|
||||||
|
virtual NTSTATUS GetQueueHead(struct _QUEUE_HEAD ** OutHead) = 0;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// IsRequestComplete
|
||||||
|
//
|
||||||
|
// Description: returns true when the request has been completed
|
||||||
|
// Should be called after the CompletionCallback has been invoked
|
||||||
|
|
||||||
|
virtual BOOLEAN IsRequestComplete() = 0;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// GetTransferType
|
||||||
|
//
|
||||||
|
// Description: returns the type of the request: control, bulk, iso, interrupt
|
||||||
|
|
||||||
|
virtual ULONG GetTransferType() = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef IUSBRequest *PUSBREQUEST;
|
typedef IUSBRequest *PUSBREQUEST;
|
||||||
|
|
|
@ -68,6 +68,7 @@ protected:
|
||||||
USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
|
USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
|
||||||
ULONG m_PortStatus;
|
ULONG m_PortStatus;
|
||||||
PUSBQUEUE m_Queue;
|
PUSBQUEUE m_Queue;
|
||||||
|
PDMAMEMORYMANAGER m_DmaManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
|
@ -124,6 +125,21 @@ CUSBDevice::Initialize(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: get dma manager
|
||||||
|
//
|
||||||
|
//Status = m_Device->GetDMA(&m_DmaManager);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to get usb queue
|
||||||
|
//
|
||||||
|
DPRINT1("CUSBDevice::Initialize GetUsbQueue failed with %x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// zero descriptor
|
// zero descriptor
|
||||||
//
|
//
|
||||||
|
@ -293,7 +309,7 @@ CUSBDevice::SetDeviceAddress(
|
||||||
// initialize request
|
// initialize request
|
||||||
//
|
//
|
||||||
CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
|
CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
|
||||||
CtrlSetup.wValue.W = DeviceAddress;
|
CtrlSetup.wValue.W = (USHORT)DeviceAddress;
|
||||||
|
|
||||||
//
|
//
|
||||||
// set device address
|
// set device address
|
||||||
|
@ -386,6 +402,8 @@ CUSBDevice::CommitSetupPacket(
|
||||||
PUSBREQUEST Request;
|
PUSBREQUEST Request;
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
BOOLEAN Wait = FALSE;
|
BOOLEAN Wait = FALSE;
|
||||||
|
PMDL Mdl = 0;
|
||||||
|
|
||||||
|
|
||||||
if (!m_Queue)
|
if (!m_Queue)
|
||||||
{
|
{
|
||||||
|
@ -409,10 +427,12 @@ CUSBDevice::CommitSetupPacket(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME build MDL */
|
||||||
|
|
||||||
//
|
//
|
||||||
// initialize request
|
// initialize request
|
||||||
//
|
//
|
||||||
Status = Request->InitializeWithSetupPacket(Packet, BufferLength, Buffer);
|
Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, BufferLength, Mdl);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -439,7 +459,7 @@ CUSBDevice::CommitSetupPacket(
|
||||||
//
|
//
|
||||||
// set completion details
|
// set completion details
|
||||||
//
|
//
|
||||||
Status = Request->SetCompletionDetails(Irp, pEvent);
|
Status = Request->SetCompletionEvent(pEvent);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
|
801
drivers/usb/usbehci_new/usb_request.cpp
Normal file
801
drivers/usb/usbehci_new/usb_request.cpp
Normal file
|
@ -0,0 +1,801 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/usb/usbehci/usb_request.cpp
|
||||||
|
* PURPOSE: USB EHCI device driver.
|
||||||
|
* PROGRAMMERS:
|
||||||
|
* Michael Martin (michael.martin@reactos.org)
|
||||||
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INITGUID
|
||||||
|
|
||||||
|
#include "usbehci.h"
|
||||||
|
#include "hardware.h"
|
||||||
|
|
||||||
|
class CUSBRequest : public IUSBRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
|
||||||
|
|
||||||
|
STDMETHODIMP_(ULONG) AddRef()
|
||||||
|
{
|
||||||
|
InterlockedIncrement(&m_Ref);
|
||||||
|
return m_Ref;
|
||||||
|
}
|
||||||
|
STDMETHODIMP_(ULONG) Release()
|
||||||
|
{
|
||||||
|
InterlockedDecrement(&m_Ref);
|
||||||
|
|
||||||
|
if (!m_Ref)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return m_Ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IUSBRequest interface functions
|
||||||
|
virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
|
||||||
|
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp);
|
||||||
|
virtual NTSTATUS SetCompletionEvent(IN PKEVENT Event);
|
||||||
|
virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode, IN ULONG UrbStatusCode);
|
||||||
|
virtual VOID CancelCallback(IN NTSTATUS NtStatusCode);
|
||||||
|
virtual NTSTATUS GetQueueHead(struct _QUEUE_HEAD ** OutHead);
|
||||||
|
virtual BOOLEAN IsRequestComplete();
|
||||||
|
virtual ULONG GetTransferType();
|
||||||
|
|
||||||
|
// local functions
|
||||||
|
ULONG InternalGetTransferType();
|
||||||
|
NTSTATUS BuildControlTransferQueueHead(PQUEUE_HEAD * OutHead);
|
||||||
|
NTSTATUS BuildBulkTransferQueueHead(PQUEUE_HEAD * OutHead);
|
||||||
|
NTSTATUS CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor);
|
||||||
|
NTSTATUS CreateQueueHead(PQUEUE_HEAD *OutQueueHead);
|
||||||
|
ULONG GetDeviceAddress();
|
||||||
|
NTSTATUS BuildSetupPacket();
|
||||||
|
|
||||||
|
// constructor / destructor
|
||||||
|
CUSBRequest(IUnknown *OuterUnknown){}
|
||||||
|
virtual ~CUSBRequest(){}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
LONG m_Ref;
|
||||||
|
PDMAMEMORYMANAGER m_DmaManager;
|
||||||
|
PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket;
|
||||||
|
ULONG m_TransferBufferLength;
|
||||||
|
PMDL m_TransferBufferMDL;
|
||||||
|
PIRP m_Irp;
|
||||||
|
PKEVENT m_CompletionEvent;
|
||||||
|
|
||||||
|
PQUEUE_HEAD m_QueueHead;
|
||||||
|
PQUEUE_TRANSFER_DESCRIPTOR m_TransferDescriptors[3];
|
||||||
|
PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket;
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
STDMETHODCALLTYPE
|
||||||
|
CUSBRequest::QueryInterface(
|
||||||
|
IN REFIID refiid,
|
||||||
|
OUT PVOID* Output)
|
||||||
|
{
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::InitializeWithSetupPacket(
|
||||||
|
IN PDMAMEMORYMANAGER DmaManager,
|
||||||
|
IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
|
||||||
|
IN OUT ULONG TransferBufferLength,
|
||||||
|
IN OUT PMDL TransferBuffer)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
PC_ASSERT(DmaManager);
|
||||||
|
PC_ASSERT(SetupPacket);
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize packet
|
||||||
|
//
|
||||||
|
m_DmaManager = DmaManager;
|
||||||
|
m_SetupPacket = SetupPacket;
|
||||||
|
m_TransferBufferLength = TransferBufferLength;
|
||||||
|
m_TransferBufferMDL = TransferBuffer;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::InitializeWithIrp(
|
||||||
|
IN PDMAMEMORYMANAGER DmaManager,
|
||||||
|
IN OUT PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PURB Urb;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
PC_ASSERT(DmaManager);
|
||||||
|
PC_ASSERT(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current irp stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
|
||||||
|
PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
|
||||||
|
PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store irp
|
||||||
|
//
|
||||||
|
m_Irp = Irp;
|
||||||
|
|
||||||
|
//
|
||||||
|
// check function type
|
||||||
|
//
|
||||||
|
switch (Urb->UrbHeader.Function)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// luckily those request have the same structure layout
|
||||||
|
//
|
||||||
|
case URB_FUNCTION_CLASS_INTERFACE:
|
||||||
|
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
|
||||||
|
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// bulk / interrupt transfer
|
||||||
|
//
|
||||||
|
if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// it must have an MDL
|
||||||
|
//
|
||||||
|
PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get mdl buffer
|
||||||
|
//
|
||||||
|
m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
|
||||||
|
m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
DPRINT1("URB Function: not supported %x\n", Urb->UrbHeader.Function);
|
||||||
|
PC_ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::SetCompletionEvent(
|
||||||
|
IN PKEVENT Event)
|
||||||
|
{
|
||||||
|
if (m_QueueHead)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// WTF? operation is already in progress
|
||||||
|
//
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// store completion event
|
||||||
|
//
|
||||||
|
m_CompletionEvent = Event;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
VOID
|
||||||
|
CUSBRequest::CompletionCallback(
|
||||||
|
IN NTSTATUS NtStatusCode,
|
||||||
|
IN ULONG UrbStatusCode)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PURB Urb;
|
||||||
|
|
||||||
|
if (m_Irp)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// set irp completion status
|
||||||
|
//
|
||||||
|
m_Irp->IoStatus.Status = NtStatusCode;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current irp stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store urb status
|
||||||
|
//
|
||||||
|
Urb->UrbHeader.Status = UrbStatusCode;
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if the request was successfull
|
||||||
|
//
|
||||||
|
if (!NT_SUCCESS(NtStatusCode))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// set returned length to zero in case of error
|
||||||
|
//
|
||||||
|
Urb->UrbHeader.Length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: check if the transfer was split
|
||||||
|
// if yes dont complete irp yet
|
||||||
|
//
|
||||||
|
IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_CompletionEvent)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME: make sure the request was not split
|
||||||
|
//
|
||||||
|
KeSetEvent(m_CompletionEvent, 0, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
VOID
|
||||||
|
CUSBRequest::CancelCallback(
|
||||||
|
IN NTSTATUS NtStatusCode)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PURB Urb;
|
||||||
|
|
||||||
|
if (m_Irp)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// set irp completion status
|
||||||
|
//
|
||||||
|
m_Irp->IoStatus.Status = NtStatusCode;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current irp stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store urb status
|
||||||
|
//
|
||||||
|
Urb->UrbHeader.Status = USBD_STATUS_CANCELED;
|
||||||
|
Urb->UrbHeader.Length = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: check if the transfer was split
|
||||||
|
// if yes dont complete irp yet
|
||||||
|
//
|
||||||
|
IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_CompletionEvent)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME: make sure the request was not split
|
||||||
|
//
|
||||||
|
KeSetEvent(m_CompletionEvent, 0, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::GetQueueHead(
|
||||||
|
struct _QUEUE_HEAD ** OutHead)
|
||||||
|
{
|
||||||
|
ULONG TransferType;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// first get transfer type
|
||||||
|
//
|
||||||
|
TransferType = InternalGetTransferType();
|
||||||
|
|
||||||
|
//
|
||||||
|
// build request depending on type
|
||||||
|
//
|
||||||
|
switch(TransferType)
|
||||||
|
{
|
||||||
|
case USB_ENDPOINT_TYPE_CONTROL:
|
||||||
|
Status = BuildControlTransferQueueHead(OutHead);
|
||||||
|
break;
|
||||||
|
case USB_ENDPOINT_TYPE_BULK:
|
||||||
|
Status = BuildBulkTransferQueueHead(OutHead);
|
||||||
|
break;
|
||||||
|
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||||
|
DPRINT1("USB_ENDPOINT_TYPE_INTERRUPT not implemented\n");
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
break;
|
||||||
|
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||||
|
DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n");
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// store queue head
|
||||||
|
//
|
||||||
|
m_QueueHead = *OutHead;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
BOOLEAN
|
||||||
|
CUSBRequest::IsRequestComplete()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME: check if request was split
|
||||||
|
//
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
ULONG
|
||||||
|
CUSBRequest::GetTransferType()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// call internal implementation
|
||||||
|
//
|
||||||
|
return InternalGetTransferType();
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
ULONG
|
||||||
|
CUSBRequest::InternalGetTransferType()
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PURB Urb;
|
||||||
|
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||||
|
ULONG TransferType;
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if an irp is provided
|
||||||
|
//
|
||||||
|
if (m_Irp)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if there is a handle
|
||||||
|
//
|
||||||
|
if (Urb->UrbBulkOrInterruptTransfer.PipeHandle)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// cast to end point
|
||||||
|
//
|
||||||
|
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
||||||
|
|
||||||
|
//
|
||||||
|
// end point is defined in the low byte of bmAttributes
|
||||||
|
//
|
||||||
|
TransferType = (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no pipe handle, assume it is a control transfer
|
||||||
|
//
|
||||||
|
TransferType = USB_ENDPOINT_TYPE_CONTROL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// initialized with setup packet, must be a control transfer
|
||||||
|
//
|
||||||
|
TransferType = USB_ENDPOINT_TYPE_CONTROL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return TransferType;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::BuildControlTransferQueueHead(
|
||||||
|
PQUEUE_HEAD * OutHead)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG NumTransferDescriptors, Index;
|
||||||
|
PQUEUE_HEAD QueueHead;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// first allocate the queue head
|
||||||
|
//
|
||||||
|
Status = CreateQueueHead(&QueueHead);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate queue head
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// create setup packet
|
||||||
|
//
|
||||||
|
Status = BuildSetupPacket();
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate setup packet
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// calculate num of transfer descriptors
|
||||||
|
//
|
||||||
|
NumTransferDescriptors = m_TransferBufferMDL != 0 ? 3 : 2;
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate transfer descriptors
|
||||||
|
//
|
||||||
|
for(Index = 0; Index < NumTransferDescriptors; Index++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// allocate transfer descriptor
|
||||||
|
//
|
||||||
|
Status = CreateDescriptor(&m_TransferDescriptors[Index]);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate transfer descriptor
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// now initialize the queue head
|
||||||
|
//
|
||||||
|
QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
|
||||||
|
|
||||||
|
//if (PipeHandle)
|
||||||
|
// QueueHead->EndPointCharacteristics.EndPointNumber = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->bEndpointAddress & 0x0F;
|
||||||
|
|
||||||
|
QueueHead->Token.Bits.DataToggle = TRUE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// setup descriptors
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[0]->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN;
|
||||||
|
m_TransferDescriptors[0]->Token.Bits.TotalBytesToTransfer = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET);
|
||||||
|
m_TransferDescriptors[0]->Token.Bits.DataToggle = FALSE;
|
||||||
|
|
||||||
|
if (m_TransferBufferMDL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// setup in descriptor
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[1]->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
|
||||||
|
m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer = m_TransferBufferLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// setup out descriptor
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[2]->Token.Bits.PIDCode = PID_CODE_OUT_TOKEN;
|
||||||
|
m_TransferDescriptors[2]->Token.Bits.TotalBytesToTransfer = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// link descriptors
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[0]->NextPointer = m_TransferDescriptors[1]->PhysicalAddr;
|
||||||
|
|
||||||
|
//
|
||||||
|
// special case, setup alternative next descriptor in case of error
|
||||||
|
// HAIKU links to dead descriptor
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[0]->AlternateNextPointer = m_TransferDescriptors[2]->PhysicalAddr;
|
||||||
|
m_TransferDescriptors[1]->NextPointer = m_TransferDescriptors[2]->PhysicalAddr;
|
||||||
|
m_TransferDescriptors[1]->AlternateNextPointer = m_TransferDescriptors[2]->PhysicalAddr;
|
||||||
|
|
||||||
|
//
|
||||||
|
// interrupt on completion
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[2]->Token.Bits.InterruptOnComplete = TRUE;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no buffer, setup in descriptor
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[1]->Token.Bits.PIDCode = PID_CODE_IN_TOKEN;
|
||||||
|
m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// link descriptors
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[0]->NextPointer = m_TransferDescriptors[1]->PhysicalAddr;
|
||||||
|
m_TransferDescriptors[0]->AlternateNextPointer = m_TransferDescriptors[1]->PhysicalAddr;
|
||||||
|
|
||||||
|
//
|
||||||
|
// interrupt on completion
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[1]->Token.Bits.InterruptOnComplete = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: where put MDL virtual address?
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// link setup packet into buffer - VIRTUAL Address!!!
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[0]->BufferPointer[0] = (ULONG)PtrToUlong(m_DescriptorPacket);
|
||||||
|
|
||||||
|
//
|
||||||
|
// link transfer descriptors to queue head
|
||||||
|
//
|
||||||
|
QueueHead->NextPointer = m_TransferDescriptors[0]->PhysicalAddr;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
*OutHead = QueueHead;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
|
PQUEUE_HEAD * OutHead)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::CreateDescriptor(
|
||||||
|
PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor)
|
||||||
|
{
|
||||||
|
PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress;
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate descriptor
|
||||||
|
//
|
||||||
|
Status = m_DmaManager->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR), (PVOID*)&Descriptor, &TransferDescriptorPhysicalAddress);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate transfer descriptor
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize transfer descriptor
|
||||||
|
//
|
||||||
|
Descriptor->NextPointer = TERMINATE_POINTER;
|
||||||
|
Descriptor->AlternateNextPointer = TERMINATE_POINTER;
|
||||||
|
Descriptor->Token.Bits.DataToggle = TRUE;
|
||||||
|
Descriptor->Token.Bits.ErrorCounter = 0x03;
|
||||||
|
Descriptor->Token.Bits.Active = TRUE;
|
||||||
|
Descriptor->PhysicalAddr = TransferDescriptorPhysicalAddress.LowPart;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
*OutDescriptor = Descriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::CreateQueueHead(
|
||||||
|
PQUEUE_HEAD *OutQueueHead)
|
||||||
|
{
|
||||||
|
PQUEUE_HEAD QueueHead;
|
||||||
|
PHYSICAL_ADDRESS QueueHeadPhysicalAddress;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate queue head
|
||||||
|
//
|
||||||
|
Status = m_DmaManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysicalAddress);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate queue head
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize queue head
|
||||||
|
//
|
||||||
|
QueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
|
||||||
|
QueueHead->AlternateNextPointer = TERMINATE_POINTER;
|
||||||
|
QueueHead->NextPointer = TERMINATE_POINTER;
|
||||||
|
|
||||||
|
//
|
||||||
|
// 1 for non high speed, 0 for high speed device
|
||||||
|
//
|
||||||
|
QueueHead->EndPointCharacteristics.ControlEndPointFlag = 0;
|
||||||
|
QueueHead->EndPointCharacteristics.HeadOfReclamation = FALSE;
|
||||||
|
QueueHead->EndPointCharacteristics.MaximumPacketLength = 64;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set NakCountReload to max value possible
|
||||||
|
//
|
||||||
|
QueueHead->EndPointCharacteristics.NakCountReload = 0xF;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the Initial Data Toggle from the QEDT
|
||||||
|
//
|
||||||
|
QueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: check if High Speed Device
|
||||||
|
//
|
||||||
|
QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
|
||||||
|
QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x03;
|
||||||
|
QueueHead->Token.DWord = 0;
|
||||||
|
QueueHead->Token.Bits.InterruptOnComplete = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME check if that is really needed
|
||||||
|
//
|
||||||
|
QueueHead->PhysicalAddr = QueueHeadPhysicalAddress.LowPart;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
ULONG
|
||||||
|
CUSBRequest::GetDeviceAddress()
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PURB Urb;
|
||||||
|
PUSBDEVICE UsbDevice;
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if there is an irp provided
|
||||||
|
//
|
||||||
|
if (!m_Irp)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no irp is provided
|
||||||
|
// assume it is for device address 0
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get contained urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if there is a pipe handle provided
|
||||||
|
//
|
||||||
|
if (Urb->UrbHeader.UsbdDeviceHandle)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// there is a device handle provided
|
||||||
|
//
|
||||||
|
UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle;
|
||||||
|
|
||||||
|
//
|
||||||
|
// return device address
|
||||||
|
//
|
||||||
|
return UsbDevice->GetDeviceAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// no device handle provided, it is the host root bus
|
||||||
|
//
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CUSBRequest::BuildSetupPacket()
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PHYSICAL_ADDRESS PhysicalAddress;
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: generate setup packet from urb request
|
||||||
|
//
|
||||||
|
PC_ASSERT(m_SetupPacket);
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate common buffer setup packet
|
||||||
|
//
|
||||||
|
Status = m_DmaManager->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), (PVOID*)&m_DescriptorPacket, &PhysicalAddress);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_SetupPacket)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// copy setup packet
|
||||||
|
//
|
||||||
|
RtlCopyMemory(m_DescriptorPacket, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -64,8 +64,6 @@ EHCI_Dispatch(
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT1("EHCI_Dispatch\n");
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// get common device extension
|
// get common device extension
|
||||||
//
|
//
|
||||||
|
@ -106,19 +104,10 @@ EHCI_Dispatch(
|
||||||
//
|
//
|
||||||
return DeviceExtension->Dispatcher->HandleDeviceControl(DeviceObject, Irp);
|
return DeviceExtension->Dispatcher->HandleDeviceControl(DeviceObject, Irp);
|
||||||
}
|
}
|
||||||
case IRP_MJ_CREATE:
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// dispatch create request
|
|
||||||
//
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
DPRINT1("EHCI_Dispatch> Major %lu Minor %lu not supported\n", IoStack->MajorFunction, IoStack->MinorFunction);
|
DPRINT1("EHCI_Dispatch> Major %lu Minor %lu unhandeled\n", IoStack->MajorFunction, IoStack->MinorFunction);
|
||||||
Status = STATUS_NOT_SUPPORTED;
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue