2 * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/libusb/hcd_controller.cpp
5 * PURPOSE: USB Common Driver Library.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
16 class CHCDController
: public IHCDController
,
20 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
22 STDMETHODIMP_(ULONG
) AddRef()
24 InterlockedIncrement(&m_Ref
);
27 STDMETHODIMP_(ULONG
) Release()
29 InterlockedDecrement(&m_Ref
);
39 // IHCDController interface functions
40 NTSTATUS
Initialize(IN PROOTHDCCONTROLLER RootHCDController
, IN PDRIVER_OBJECT DriverObject
, IN PDEVICE_OBJECT PhysicalDeviceObject
);
42 // IDispatchIrp interface functions
43 NTSTATUS
HandlePnp(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
44 NTSTATUS
HandlePower(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
45 NTSTATUS
HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
46 NTSTATUS
HandleSystemControl(IN PDEVICE_OBJECT DeviceObject
, IN OUT PIRP Irp
);
49 NTSTATUS
CreateFDO(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT
* OutDeviceObject
);
50 NTSTATUS
SetSymbolicLink(BOOLEAN Enable
);
52 // constructor / destructor
53 CHCDController(IUnknown
*OuterUnknown
){}
54 virtual ~CHCDController(){}
58 PROOTHDCCONTROLLER m_RootController
;
59 PDRIVER_OBJECT m_DriverObject
;
60 PDEVICE_OBJECT m_PhysicalDeviceObject
;
61 PDEVICE_OBJECT m_FunctionalDeviceObject
;
62 PDEVICE_OBJECT m_NextDeviceObject
;
63 PUSBHARDWAREDEVICE m_Hardware
;
64 PHUBCONTROLLER m_HubController
;
65 ULONG m_FDODeviceNumber
;
69 //=================================================================================================
74 CHCDController::QueryInterface(
78 return STATUS_UNSUCCESSFUL
;
81 //-------------------------------------------------------------------------------------------------
83 CHCDController::Initialize(
84 IN PROOTHDCCONTROLLER RootHCDController
,
85 IN PDRIVER_OBJECT DriverObject
,
86 IN PDEVICE_OBJECT PhysicalDeviceObject
)
89 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
92 // create usb hardware
94 Status
= CreateUSBHardware(&m_Hardware
);
95 if (!NT_SUCCESS(Status
))
98 // failed to create hardware object
100 DPRINT1("Failed to create hardware object\n");
101 return STATUS_INSUFFICIENT_RESOURCES
;
105 // initialize members
107 m_DriverObject
= DriverObject
;
108 m_PhysicalDeviceObject
= PhysicalDeviceObject
;
109 m_RootController
= RootHCDController
;
114 Status
= CreateFDO(m_DriverObject
, &m_FunctionalDeviceObject
);
115 if (!NT_SUCCESS(Status
))
118 // failed to create PDO
124 // now attach to device stack
126 m_NextDeviceObject
= IoAttachDeviceToDeviceStack(m_FunctionalDeviceObject
, m_PhysicalDeviceObject
);
127 if (!m_NextDeviceObject
)
130 // failed to attach to device stack
132 IoDeleteDevice(m_FunctionalDeviceObject
);
133 m_FunctionalDeviceObject
= 0;
135 return STATUS_NO_SUCH_DEVICE
;
139 // initialize hardware object
141 Status
= m_Hardware
->Initialize(m_DriverObject
, m_FunctionalDeviceObject
, m_PhysicalDeviceObject
, m_NextDeviceObject
);
142 if (!NT_SUCCESS(Status
))
144 DPRINT1("[%s] Failed to initialize hardware object %x\n", m_Hardware
->GetUSBType(), Status
);
147 // failed to initialize hardware object, detach from device stack
149 IoDetachDevice(m_NextDeviceObject
);
152 // now delete the device
154 IoDeleteDevice(m_FunctionalDeviceObject
);
157 // nullify pointers :)
159 m_FunctionalDeviceObject
= 0;
160 m_NextDeviceObject
= 0;
166 // get usb controller type
168 m_USBType
= m_Hardware
->GetUSBType();
174 m_FunctionalDeviceObject
->Flags
|= DO_BUFFERED_IO
| DO_POWER_PAGABLE
;
178 // get device extension
180 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)m_FunctionalDeviceObject
->DeviceExtension
;
181 PC_ASSERT(DeviceExtension
);
184 // initialize device extension
186 DeviceExtension
->IsFDO
= TRUE
;
187 DeviceExtension
->IsHub
= FALSE
;
188 DeviceExtension
->Dispatcher
= PDISPATCHIRP(this);
191 // device is initialized
193 m_FunctionalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
197 // is there a root controller
199 if (m_RootController
)
204 m_RootController
->AddRef();
207 // register with controller
209 m_RootController
->RegisterHCD(this);
216 return STATUS_SUCCESS
;
219 //-------------------------------------------------------------------------------------------------
221 CHCDController::HandleDeviceControl(
222 IN PDEVICE_OBJECT DeviceObject
,
225 PIO_STACK_LOCATION IoStack
;
226 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
227 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
228 PUSB_HCD_DRIVERKEY_NAME DriverKey
;
232 // get current stack location
234 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
237 // get device extension
239 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
244 PC_ASSERT(DeviceExtension
->IsFDO
);
246 DPRINT1("[%s] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n", m_USBType
,
247 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
,
248 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
249 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
252 // perform ioctl for FDO
254 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_GET_HCD_DRIVERKEY_NAME
)
257 // check if sizee is at least >= USB_HCD_DRIVERKEY_NAME
259 if(IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= sizeof(USB_HCD_DRIVERKEY_NAME
))
262 // get device property size
264 Status
= IoGetDeviceProperty(m_PhysicalDeviceObject
, DevicePropertyDriverKeyName
, 0, NULL
, &ResultLength
);
269 DriverKey
= (PUSB_HCD_DRIVERKEY_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
274 if (Status
== STATUS_BUFFER_TOO_SMALL
)
277 // does the caller provide enough buffer space
279 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= ResultLength
)
284 Status
= IoGetDeviceProperty(m_PhysicalDeviceObject
, DevicePropertyDriverKeyName
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(ULONG
), DriverKey
->DriverKeyName
, &ResultLength
);
290 DriverKey
->ActualLength
= ResultLength
+ FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME
, DriverKeyName
) + sizeof(WCHAR
);
291 Irp
->IoStatus
.Information
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
292 Status
= STATUS_SUCCESS
;
298 // buffer is certainly too small
300 Status
= STATUS_BUFFER_OVERFLOW
;
301 Irp
->IoStatus
.Information
= sizeof(USB_HCD_DRIVERKEY_NAME
);
304 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_USB_GET_ROOT_HUB_NAME
)
307 // check if sizee is at least >= USB_HCD_DRIVERKEY_NAME
309 if(IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= sizeof(USB_HCD_DRIVERKEY_NAME
))
314 PC_ASSERT(m_HubController
);
319 DriverKey
= (PUSB_HCD_DRIVERKEY_NAME
)Irp
->AssociatedIrp
.SystemBuffer
;
324 Status
= m_HubController
->GetHubControllerSymbolicLink(IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(ULONG
), DriverKey
->DriverKeyName
, &ResultLength
);
327 if (NT_SUCCESS(Status
))
332 PC_ASSERT(IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(ULONG
) - sizeof(WCHAR
) >= ResultLength
);
334 DriverKey
->DriverKeyName
[ResultLength
/ sizeof(WCHAR
)] = L
'\0';
340 DriverKey
->ActualLength
= ResultLength
+ FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME
, DriverKeyName
) + sizeof(WCHAR
);
341 Irp
->IoStatus
.Information
= IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
342 Status
= STATUS_SUCCESS
;
347 // buffer is certainly too small
349 Status
= STATUS_BUFFER_OVERFLOW
;
350 Irp
->IoStatus
.Information
= sizeof(USB_HCD_DRIVERKEY_NAME
);
355 // complete the request
357 Irp
->IoStatus
.Status
= Status
;
358 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
367 CHCDController::HandlePnp(
368 IN PDEVICE_OBJECT DeviceObject
,
371 PIO_STACK_LOCATION IoStack
;
372 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
373 PCM_RESOURCE_LIST RawResourceList
;
374 PCM_RESOURCE_LIST TranslatedResourceList
;
375 PDEVICE_RELATIONS DeviceRelations
;
379 // get device extension
381 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
386 PC_ASSERT(DeviceExtension
->IsFDO
);
389 // get current stack location
391 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
393 switch(IoStack
->MinorFunction
)
395 case IRP_MN_START_DEVICE
:
397 DPRINT("[%s] HandlePnp IRP_MN_START FDO\n", m_USBType
);
400 // first start lower device object
402 Status
= SyncForwardIrp(m_NextDeviceObject
, Irp
);
404 if (NT_SUCCESS(Status
))
407 // operation succeeded, lets start the device
409 RawResourceList
= IoStack
->Parameters
.StartDevice
.AllocatedResources
;
410 TranslatedResourceList
= IoStack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
;
415 // start the hardware
417 Status
= m_Hardware
->PnpStart(RawResourceList
, TranslatedResourceList
);
420 if (NT_SUCCESS(Status
))
423 // enable symbolic link
425 Status
= SetSymbolicLink(TRUE
);
429 DPRINT("[%s] HandlePnp IRP_MN_START FDO: Status %x\n", m_USBType
,Status
);
432 case IRP_MN_QUERY_DEVICE_RELATIONS
:
434 DPRINT("[%s] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %lx\n", m_USBType
, IoStack
->Parameters
.QueryDeviceRelations
.Type
);
436 if (m_HubController
== NULL
)
439 // create hub controller
441 Status
= CreateHubController(&m_HubController
);
442 if (!NT_SUCCESS(Status
))
445 // failed to create hub controller
451 // initialize hub controller
453 Status
= m_HubController
->Initialize(m_DriverObject
, PHCDCONTROLLER(this), m_Hardware
, TRUE
, 0 /* FIXME*/);
454 if (!NT_SUCCESS(Status
))
457 // failed to initialize hub controller
463 // add reference to prevent it from getting deleting while hub driver adds / removes references
465 m_HubController
->AddRef();
468 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== BusRelations
)
471 // allocate device relations
473 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
));
475 if (!DeviceRelations
)
480 Status
= STATUS_INSUFFICIENT_RESOURCES
;
485 // init device relations
487 DeviceRelations
->Count
= 1;
488 Status
= m_HubController
->GetHubControllerDeviceObject(&DeviceRelations
->Objects
[0]);
493 PC_ASSERT(Status
== STATUS_SUCCESS
);
495 ObReferenceObject(DeviceRelations
->Objects
[0]);
500 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
501 Status
= STATUS_SUCCESS
;
508 Status
= STATUS_NOT_SUPPORTED
;
512 case IRP_MN_STOP_DEVICE
:
514 DPRINT("[%s] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType
);
521 Status
= m_Hardware
->PnpStop();
528 Status
= STATUS_SUCCESS
;
531 if (NT_SUCCESS(Status
))
536 Status
= SyncForwardIrp(m_NextDeviceObject
, Irp
);
540 case IRP_MN_QUERY_REMOVE_DEVICE
:
541 case IRP_MN_QUERY_STOP_DEVICE
:
547 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
550 // forward irp to next device object
552 IoSkipCurrentIrpStackLocation(Irp
);
553 return IoCallDriver(m_NextDeviceObject
, Irp
);
555 DPRINT1("[%s] Denying controller removal due to reinitialization bugs\n", m_USBType
);
556 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
557 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
558 return STATUS_UNSUCCESSFUL
;
561 case IRP_MN_REMOVE_DEVICE
:
563 DPRINT("[%s] HandlePnp IRP_MN_REMOVE_DEVICE FDO\n", m_USBType
);
566 // delete the symbolic link
568 SetSymbolicLink(FALSE
);
571 // forward irp to next device object
573 IoSkipCurrentIrpStackLocation(Irp
);
574 IoCallDriver(m_NextDeviceObject
, Irp
);
577 // detach device from device stack
579 IoDetachDevice(m_NextDeviceObject
);
584 IoDeleteDevice(m_FunctionalDeviceObject
);
586 return STATUS_SUCCESS
;
591 // forward irp to next device object
593 IoSkipCurrentIrpStackLocation(Irp
);
594 return IoCallDriver(m_NextDeviceObject
, Irp
);
599 // store result and complete request
601 Irp
->IoStatus
.Status
= Status
;
602 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
608 CHCDController::HandlePower(
609 IN PDEVICE_OBJECT DeviceObject
,
612 PoStartNextPowerIrp(Irp
);
613 IoSkipCurrentIrpStackLocation(Irp
);
614 return PoCallDriver(m_NextDeviceObject
, Irp
);
618 CHCDController::HandleSystemControl(
619 IN PDEVICE_OBJECT DeviceObject
,
622 IoSkipCurrentIrpStackLocation(Irp
);
623 return IoCallDriver(m_NextDeviceObject
, Irp
);
627 CHCDController::CreateFDO(
628 PDRIVER_OBJECT DriverObject
,
629 PDEVICE_OBJECT
* OutDeviceObject
)
631 WCHAR CharDeviceName
[64];
633 ULONG UsbDeviceNumber
= 0;
634 UNICODE_STRING DeviceName
;
639 // construct device name
641 swprintf(CharDeviceName
, L
"\\Device\\USBFDO-%d", UsbDeviceNumber
);
644 // initialize device name
646 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
651 Status
= IoCreateDevice(DriverObject
,
652 sizeof(COMMON_DEVICE_EXTENSION
),
654 FILE_DEVICE_CONTROLLER
,
662 if (NT_SUCCESS(Status
))
666 // is there a device object with that same name
668 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
678 // bail out on other errors
680 if (!NT_SUCCESS(Status
))
682 DPRINT1("[%s] CreateFDO: Failed to create %wZ, Status %x\n", m_USBType
, &DeviceName
, Status
);
690 m_FDODeviceNumber
= UsbDeviceNumber
;
692 DPRINT("[%s] CreateFDO: DeviceName %wZ\n", m_USBType
, &DeviceName
);
699 CHCDController::SetSymbolicLink(
705 UNICODE_STRING Link
, FDO
;
710 // create legacy link
712 swprintf(LinkName
, L
"\\DosDevices\\HCD%d", m_FDODeviceNumber
);
713 swprintf(FDOName
, L
"\\Device\\USBFDO-%d", m_FDODeviceNumber
);
714 RtlInitUnicodeString(&Link
, LinkName
);
715 RtlInitUnicodeString(&FDO
, FDOName
);
718 // create symbolic link
720 Status
= IoCreateSymbolicLink(&Link
, &FDO
);
722 if (!NT_SUCCESS(Status
))
733 // create legacy link
735 swprintf(LinkName
, L
"\\DosDevices\\HCD%d", m_FDODeviceNumber
);
736 RtlInitUnicodeString(&Link
, LinkName
);
739 // now delete the symbolic link
741 Status
= IoDeleteSymbolicLink(&Link
);
743 if (!NT_SUCCESS(Status
))
761 PHCDCONTROLLER
*OutHcdController
)
766 // allocate controller
768 This
= new(NonPagedPool
, TAG_USBLIB
) CHCDController(0);
772 // failed to allocate
774 return STATUS_INSUFFICIENT_RESOURCES
;
778 // add reference count
785 *OutHcdController
= (PHCDCONTROLLER
)This
;
790 return STATUS_SUCCESS
;