+++ /dev/null
-/*
- * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: lib/drivers/libusb/hcd_controller.cpp
- * PURPOSE: USB Common Driver Library.
- * PROGRAMMERS:
- * Michael Martin (michael.martin@reactos.org)
- * Johannes Anderwald (johannes.anderwald@reactos.org)
- */
-
-#include "libusb.h"
-
-#define NDEBUG
-#include <debug.h>
-
-class CHCDController : public IHCDController,
- public IDispatchIrp
-{
-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;
- }
-
- // IHCDController interface functions
- NTSTATUS Initialize(IN PROOTHDCCONTROLLER RootHCDController, IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
-
- // IDispatchIrp interface functions
- NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
- NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
- NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
- NTSTATUS HandleSystemControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
-
- // local functions
- NTSTATUS CreateFDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
- NTSTATUS SetSymbolicLink(BOOLEAN Enable);
-
- // constructor / destructor
- CHCDController(IUnknown *OuterUnknown){}
- virtual ~CHCDController(){}
-
-protected:
- LONG m_Ref;
- PROOTHDCCONTROLLER m_RootController;
- PDRIVER_OBJECT m_DriverObject;
- PDEVICE_OBJECT m_PhysicalDeviceObject;
- PDEVICE_OBJECT m_FunctionalDeviceObject;
- PDEVICE_OBJECT m_NextDeviceObject;
- PUSBHARDWAREDEVICE m_Hardware;
- PHUBCONTROLLER m_HubController;
- ULONG m_FDODeviceNumber;
- LPCSTR m_USBType;
-};
-
-//=================================================================================================
-// COM
-//
-NTSTATUS
-STDMETHODCALLTYPE
-CHCDController::QueryInterface(
- IN REFIID refiid,
- OUT PVOID* Output)
-{
- return STATUS_UNSUCCESSFUL;
-}
-
-//-------------------------------------------------------------------------------------------------
-NTSTATUS
-CHCDController::Initialize(
- IN PROOTHDCCONTROLLER RootHCDController,
- IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT PhysicalDeviceObject)
-{
- NTSTATUS Status;
- PCOMMON_DEVICE_EXTENSION DeviceExtension;
-
- //
- // create usb hardware
- //
- Status = CreateUSBHardware(&m_Hardware);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to create hardware object
- //
- DPRINT1("Failed to create hardware object\n");
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // initialize members
- //
- m_DriverObject = DriverObject;
- m_PhysicalDeviceObject = PhysicalDeviceObject;
- m_RootController = RootHCDController;
-
- //
- // create FDO
- //
- Status = CreateFDO(m_DriverObject, &m_FunctionalDeviceObject);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to create PDO
- //
- return Status;
- }
-
- //
- // now attach to device stack
- //
- m_NextDeviceObject = IoAttachDeviceToDeviceStack(m_FunctionalDeviceObject, m_PhysicalDeviceObject);
- if (!m_NextDeviceObject)
- {
- //
- // failed to attach to device stack
- //
- IoDeleteDevice(m_FunctionalDeviceObject);
- m_FunctionalDeviceObject = 0;
-
- return STATUS_NO_SUCH_DEVICE;
- }
-
- //
- // initialize hardware object
- //
- Status = m_Hardware->Initialize(m_DriverObject, m_FunctionalDeviceObject, m_PhysicalDeviceObject, m_NextDeviceObject);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("[%s] Failed to initialize hardware object %x\n", m_Hardware->GetUSBType(), Status);
-
- //
- // failed to initialize hardware object, detach from device stack
- //
- IoDetachDevice(m_NextDeviceObject);
-
- //
- // now delete the device
- //
- IoDeleteDevice(m_FunctionalDeviceObject);
-
- //
- // nullify pointers :)
- //
- m_FunctionalDeviceObject = 0;
- m_NextDeviceObject = 0;
-
- return Status;
- }
-
- //
- // get usb controller type
- //
- m_USBType = m_Hardware->GetUSBType();
-
-
- //
- // set device flags
- //
- m_FunctionalDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
-
-
- //
- // get device extension
- //
- DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_FunctionalDeviceObject->DeviceExtension;
- PC_ASSERT(DeviceExtension);
-
- //
- // initialize device extension
- //
- DeviceExtension->IsFDO = TRUE;
- DeviceExtension->IsHub = FALSE;
- DeviceExtension->Dispatcher = PDISPATCHIRP(this);
-
- //
- // device is initialized
- //
- m_FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
-
-
- //
- // is there a root controller
- //
- if (m_RootController)
- {
- //
- // add reference
- //
- m_RootController->AddRef();
-
- //
- // register with controller
- //
- m_RootController->RegisterHCD(this);
- }
-
-
- //
- // done
- //
- return STATUS_SUCCESS;
-}
-
-//-------------------------------------------------------------------------------------------------
-NTSTATUS
-CHCDController::HandleDeviceControl(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- PIO_STACK_LOCATION IoStack;
- PCOMMON_DEVICE_EXTENSION DeviceExtension;
- NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
- PUSB_HCD_DRIVERKEY_NAME DriverKey;
- ULONG ResultLength;
-
- //
- // get current stack location
- //
- IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- //
- // get device extension
- //
- DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- PC_ASSERT(DeviceExtension->IsFDO);
-
- DPRINT1("[%s] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n", m_USBType,
- IoStack->Parameters.DeviceIoControl.IoControlCode,
- IoStack->Parameters.DeviceIoControl.InputBufferLength,
- IoStack->Parameters.DeviceIoControl.OutputBufferLength);
-
- //
- // perform ioctl for FDO
- //
- if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_HCD_DRIVERKEY_NAME)
- {
- //
- // check if sizee is at least >= USB_HCD_DRIVERKEY_NAME
- //
- if(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(USB_HCD_DRIVERKEY_NAME))
- {
- //
- // get device property size
- //
- Status = IoGetDeviceProperty(m_PhysicalDeviceObject, DevicePropertyDriverKeyName, 0, NULL, &ResultLength);
-
- //
- // get input buffer
- //
- DriverKey = (PUSB_HCD_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer;
-
- //
- // check result
- //
- if (Status == STATUS_BUFFER_TOO_SMALL)
- {
- //
- // does the caller provide enough buffer space
- //
- if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= ResultLength)
- {
- //
- // it does
- //
- Status = IoGetDeviceProperty(m_PhysicalDeviceObject, DevicePropertyDriverKeyName, IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG), DriverKey->DriverKeyName, &ResultLength);
- }
-
- //
- // store result
- //
- DriverKey->ActualLength = ResultLength + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + sizeof(WCHAR);
- Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
- Status = STATUS_SUCCESS;
- }
- }
- else
- {
- //
- // buffer is certainly too small
- //
- Status = STATUS_BUFFER_OVERFLOW;
- Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME);
- }
- }
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_ROOT_HUB_NAME)
- {
- //
- // check if sizee is at least >= USB_HCD_DRIVERKEY_NAME
- //
- if(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(USB_HCD_DRIVERKEY_NAME))
- {
- //
- // sanity check
- //
- PC_ASSERT(m_HubController);
-
- //
- // get input buffer
- //
- DriverKey = (PUSB_HCD_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer;
-
- //
- // get symbolic link
- //
- Status = m_HubController->GetHubControllerSymbolicLink(IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG), DriverKey->DriverKeyName, &ResultLength);
-
-
- if (NT_SUCCESS(Status))
- {
- //
- // null terminate it
- //
- PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG) - sizeof(WCHAR) >= ResultLength);
-
- DriverKey->DriverKeyName[ResultLength / sizeof(WCHAR)] = L'\0';
- }
-
- //
- // store result
- //
- DriverKey->ActualLength = ResultLength + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + sizeof(WCHAR);
- Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
- Status = STATUS_SUCCESS;
- }
- else
- {
- //
- // buffer is certainly too small
- //
- Status = STATUS_BUFFER_OVERFLOW;
- Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME);
- }
- }
-
- //
- // complete the request
- //
- Irp->IoStatus.Status = Status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- //
- // done
- //
- return Status;
-}
-
-NTSTATUS
-CHCDController::HandlePnp(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- PIO_STACK_LOCATION IoStack;
- PCOMMON_DEVICE_EXTENSION DeviceExtension;
- PCM_RESOURCE_LIST RawResourceList;
- PCM_RESOURCE_LIST TranslatedResourceList;
- PDEVICE_RELATIONS DeviceRelations;
- NTSTATUS Status;
-
- //
- // get device extension
- //
- DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- PC_ASSERT(DeviceExtension->IsFDO);
-
- //
- // get current stack location
- //
- IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- switch(IoStack->MinorFunction)
- {
- case IRP_MN_START_DEVICE:
- {
- DPRINT("[%s] HandlePnp IRP_MN_START FDO\n", m_USBType);
-
- //
- // first start lower device object
- //
- Status = SyncForwardIrp(m_NextDeviceObject, Irp);
-
- if (NT_SUCCESS(Status))
- {
- //
- // operation succeeded, lets start the device
- //
- RawResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
- TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
-
- if (m_Hardware)
- {
- //
- // start the hardware
- //
- Status = m_Hardware->PnpStart(RawResourceList, TranslatedResourceList);
- }
-
- //
- // enable symbolic link
- //
- Status = SetSymbolicLink(TRUE);
- }
-
- DPRINT("[%s] HandlePnp IRP_MN_START FDO: Status %x\n", m_USBType ,Status);
- break;
- }
- case IRP_MN_QUERY_DEVICE_RELATIONS:
- {
- DPRINT("[%s] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %lx\n", m_USBType, IoStack->Parameters.QueryDeviceRelations.Type);
-
- if (m_HubController == NULL)
- {
- //
- // create hub controller
- //
- Status = CreateHubController(&m_HubController);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to create hub controller
- //
- break;
- }
-
- //
- // initialize hub controller
- //
- Status = m_HubController->Initialize(m_DriverObject, PHCDCONTROLLER(this), m_Hardware, TRUE, 0 /* FIXME*/);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to initialize hub controller
- //
- break;
- }
-
- //
- // add reference to prevent it from getting deleting while hub driver adds / removes references
- //
- m_HubController->AddRef();
- }
-
- if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
- {
- //
- // allocate device relations
- //
- DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
-
- if (!DeviceRelations)
- {
- //
- // no memory
- //
- Status = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
-
- //
- // init device relations
- //
- DeviceRelations->Count = 1;
- Status = m_HubController->GetHubControllerDeviceObject(&DeviceRelations->Objects [0]);
-
- //
- // sanity check
- //
- PC_ASSERT(Status == STATUS_SUCCESS);
-
- ObReferenceObject(DeviceRelations->Objects [0]);
-
- //
- // store result
- //
- Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
- Status = STATUS_SUCCESS;
- }
- else
- {
- //
- // not supported
- //
- Status = STATUS_NOT_SUPPORTED;
- }
- break;
- }
- case IRP_MN_STOP_DEVICE:
- {
- DPRINT("[%s] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType);
-
- if (m_Hardware)
- {
- //
- // stop the hardware
- //
- Status = m_Hardware->PnpStop();
- }
- else
- {
- //
- // fake success
- //
- Status = STATUS_SUCCESS;
- }
-
- if (NT_SUCCESS(Status))
- {
- //
- // stop lower device
- //
- Status = SyncForwardIrp(m_NextDeviceObject, Irp);
- }
- break;
- }
- case IRP_MN_QUERY_REMOVE_DEVICE:
- case IRP_MN_QUERY_STOP_DEVICE:
- {
-#if 0
- //
- // sure
- //
- Irp->IoStatus.Status = STATUS_SUCCESS;
-
- //
- // forward irp to next device object
- //
- IoSkipCurrentIrpStackLocation(Irp);
- return IoCallDriver(m_NextDeviceObject, Irp);
-#else
- DPRINT1("[%s] Denying controller removal due to reinitialization bugs\n", m_USBType);
- Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_UNSUCCESSFUL;
-#endif
- }
- case IRP_MN_REMOVE_DEVICE:
- {
- DPRINT("[%s] HandlePnp IRP_MN_REMOVE_DEVICE FDO\n", m_USBType);
-
- //
- // delete the symbolic link
- //
- SetSymbolicLink(FALSE);
-
- //
- // forward irp to next device object
- //
- IoSkipCurrentIrpStackLocation(Irp);
- IoCallDriver(m_NextDeviceObject, Irp);
-
- //
- // detach device from device stack
- //
- IoDetachDevice(m_NextDeviceObject);
-
- //
- // delete device
- //
- IoDeleteDevice(m_FunctionalDeviceObject);
-
- return STATUS_SUCCESS;
- }
- default:
- {
- //
- // forward irp to next device object
- //
- IoSkipCurrentIrpStackLocation(Irp);
- return IoCallDriver(m_NextDeviceObject, Irp);
- }
- }
-
- //
- // store result and complete request
- //
- Irp->IoStatus.Status = Status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return Status;
-}
-
-NTSTATUS
-CHCDController::HandlePower(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- PoStartNextPowerIrp(Irp);
- IoSkipCurrentIrpStackLocation(Irp);
- return PoCallDriver(m_NextDeviceObject, Irp);
-}
-
-NTSTATUS
-CHCDController::HandleSystemControl(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- IoSkipCurrentIrpStackLocation(Irp);
- return IoCallDriver(m_NextDeviceObject, Irp);
-}
-
-NTSTATUS
-CHCDController::CreateFDO(
- PDRIVER_OBJECT DriverObject,
- PDEVICE_OBJECT * OutDeviceObject)
-{
- WCHAR CharDeviceName[64];
- NTSTATUS Status;
- ULONG UsbDeviceNumber = 0;
- UNICODE_STRING DeviceName;
-
- while (TRUE)
- {
- //
- // construct device name
- //
- swprintf(CharDeviceName, L"\\Device\\USBFDO-%d", UsbDeviceNumber);
-
- //
- // initialize device name
- //
- RtlInitUnicodeString(&DeviceName, CharDeviceName);
-
- //
- // create device
- //
- Status = IoCreateDevice(DriverObject,
- sizeof(COMMON_DEVICE_EXTENSION),
- &DeviceName,
- FILE_DEVICE_CONTROLLER,
- 0,
- FALSE,
- OutDeviceObject);
-
- //
- // check for success
- //
- if (NT_SUCCESS(Status))
- break;
-
- //
- // is there a device object with that same name
- //
- if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
- {
- //
- // Try the next name
- //
- UsbDeviceNumber++;
- continue;
- }
-
- //
- // bail out on other errors
- //
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("[%s] CreateFDO: Failed to create %wZ, Status %x\n", m_USBType, &DeviceName, Status);
- return Status;
- }
- }
-
- //
- // store FDO number
- //
- m_FDODeviceNumber = UsbDeviceNumber;
-
- DPRINT("[%s] CreateFDO: DeviceName %wZ\n", m_USBType, &DeviceName);
-
- /* done */
- return Status;
-}
-
-NTSTATUS
-CHCDController::SetSymbolicLink(
- BOOLEAN Enable)
-{
- NTSTATUS Status;
- WCHAR LinkName[32];
- WCHAR FDOName[32];
- UNICODE_STRING Link, FDO;
-
- if (Enable)
- {
- //
- // create legacy link
- //
- swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber);
- swprintf(FDOName, L"\\Device\\USBFDO-%d", m_FDODeviceNumber);
- RtlInitUnicodeString(&Link, LinkName);
- RtlInitUnicodeString(&FDO, FDOName);
-
- //
- // create symbolic link
- //
- Status = IoCreateSymbolicLink(&Link, &FDO);
-
- if (!NT_SUCCESS(Status))
- {
- //
- // FIXME: handle me
- //
- ASSERT(0);
- }
- }
- else
- {
- //
- // create legacy link
- //
- swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber);
- RtlInitUnicodeString(&Link, LinkName);
-
- //
- // now delete the symbolic link
- //
- Status = IoDeleteSymbolicLink(&Link);
-
- if (!NT_SUCCESS(Status))
- {
- //
- // FIXME: handle me
- //
- ASSERT(0);
- }
- }
-
- //
- // done
- //
- return Status;
-}
-
-NTSTATUS
-NTAPI
-CreateHCDController(
- PHCDCONTROLLER *OutHcdController)
-{
- PHCDCONTROLLER This;
-
- //
- // allocate controller
- //
- This = new(NonPagedPool, TAG_USBLIB) CHCDController(0);
- if (!This)
- {
- //
- // failed to allocate
- //
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // add reference count
- //
- This->AddRef();
-
- //
- // return result
- //
- *OutHcdController = (PHCDCONTROLLER)This;
-
- //
- // done
- //
- return STATUS_SUCCESS;
-}