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
);
421 // enable symbolic link
423 Status
= SetSymbolicLink(TRUE
);
426 DPRINT("[%s] HandlePnp IRP_MN_START FDO: Status %x\n", m_USBType
,Status
);
429 case IRP_MN_QUERY_DEVICE_RELATIONS
:
431 DPRINT("[%s] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %lx\n", m_USBType
, IoStack
->Parameters
.QueryDeviceRelations
.Type
);
433 if (m_HubController
== NULL
)
436 // create hub controller
438 Status
= CreateHubController(&m_HubController
);
439 if (!NT_SUCCESS(Status
))
442 // failed to create hub controller
448 // initialize hub controller
450 Status
= m_HubController
->Initialize(m_DriverObject
, PHCDCONTROLLER(this), m_Hardware
, TRUE
, 0 /* FIXME*/);
451 if (!NT_SUCCESS(Status
))
454 // failed to initialize hub controller
460 // add reference to prevent it from getting deleting while hub driver adds / removes references
462 m_HubController
->AddRef();
465 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== BusRelations
)
468 // allocate device relations
470 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
));
472 if (!DeviceRelations
)
477 Status
= STATUS_INSUFFICIENT_RESOURCES
;
482 // init device relations
484 DeviceRelations
->Count
= 1;
485 Status
= m_HubController
->GetHubControllerDeviceObject(&DeviceRelations
->Objects
[0]);
490 PC_ASSERT(Status
== STATUS_SUCCESS
);
492 ObReferenceObject(DeviceRelations
->Objects
[0]);
497 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
498 Status
= STATUS_SUCCESS
;
505 Status
= STATUS_NOT_SUPPORTED
;
509 case IRP_MN_STOP_DEVICE
:
511 DPRINT("[%s] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType
);
518 Status
= m_Hardware
->PnpStop();
525 Status
= STATUS_SUCCESS
;
528 if (NT_SUCCESS(Status
))
533 Status
= SyncForwardIrp(m_NextDeviceObject
, Irp
);
537 case IRP_MN_QUERY_REMOVE_DEVICE
:
538 case IRP_MN_QUERY_STOP_DEVICE
:
544 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
547 // forward irp to next device object
549 IoSkipCurrentIrpStackLocation(Irp
);
550 return IoCallDriver(m_NextDeviceObject
, Irp
);
552 DPRINT1("[%s] Denying controller removal due to reinitialization bugs\n", m_USBType
);
553 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
554 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
555 return STATUS_UNSUCCESSFUL
;
558 case IRP_MN_REMOVE_DEVICE
:
560 DPRINT("[%s] HandlePnp IRP_MN_REMOVE_DEVICE FDO\n", m_USBType
);
563 // delete the symbolic link
565 SetSymbolicLink(FALSE
);
568 // forward irp to next device object
570 IoSkipCurrentIrpStackLocation(Irp
);
571 IoCallDriver(m_NextDeviceObject
, Irp
);
574 // detach device from device stack
576 IoDetachDevice(m_NextDeviceObject
);
581 IoDeleteDevice(m_FunctionalDeviceObject
);
583 return STATUS_SUCCESS
;
588 // forward irp to next device object
590 IoSkipCurrentIrpStackLocation(Irp
);
591 return IoCallDriver(m_NextDeviceObject
, Irp
);
596 // store result and complete request
598 Irp
->IoStatus
.Status
= Status
;
599 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
605 CHCDController::HandlePower(
606 IN PDEVICE_OBJECT DeviceObject
,
609 PoStartNextPowerIrp(Irp
);
610 IoSkipCurrentIrpStackLocation(Irp
);
611 return PoCallDriver(m_NextDeviceObject
, Irp
);
615 CHCDController::HandleSystemControl(
616 IN PDEVICE_OBJECT DeviceObject
,
619 IoSkipCurrentIrpStackLocation(Irp
);
620 return IoCallDriver(m_NextDeviceObject
, Irp
);
624 CHCDController::CreateFDO(
625 PDRIVER_OBJECT DriverObject
,
626 PDEVICE_OBJECT
* OutDeviceObject
)
628 WCHAR CharDeviceName
[64];
630 ULONG UsbDeviceNumber
= 0;
631 UNICODE_STRING DeviceName
;
636 // construct device name
638 swprintf(CharDeviceName
, L
"\\Device\\USBFDO-%d", UsbDeviceNumber
);
641 // initialize device name
643 RtlInitUnicodeString(&DeviceName
, CharDeviceName
);
648 Status
= IoCreateDevice(DriverObject
,
649 sizeof(COMMON_DEVICE_EXTENSION
),
651 FILE_DEVICE_CONTROLLER
,
659 if (NT_SUCCESS(Status
))
663 // is there a device object with that same name
665 if ((Status
== STATUS_OBJECT_NAME_EXISTS
) || (Status
== STATUS_OBJECT_NAME_COLLISION
))
675 // bail out on other errors
677 if (!NT_SUCCESS(Status
))
679 DPRINT1("[%s] CreateFDO: Failed to create %wZ, Status %x\n", m_USBType
, &DeviceName
, Status
);
687 m_FDODeviceNumber
= UsbDeviceNumber
;
689 DPRINT("[%s] CreateFDO: DeviceName %wZ\n", m_USBType
, &DeviceName
);
696 CHCDController::SetSymbolicLink(
702 UNICODE_STRING Link
, FDO
;
707 // create legacy link
709 swprintf(LinkName
, L
"\\DosDevices\\HCD%d", m_FDODeviceNumber
);
710 swprintf(FDOName
, L
"\\Device\\USBFDO-%d", m_FDODeviceNumber
);
711 RtlInitUnicodeString(&Link
, LinkName
);
712 RtlInitUnicodeString(&FDO
, FDOName
);
715 // create symbolic link
717 Status
= IoCreateSymbolicLink(&Link
, &FDO
);
719 if (!NT_SUCCESS(Status
))
730 // create legacy link
732 swprintf(LinkName
, L
"\\DosDevices\\HCD%d", m_FDODeviceNumber
);
733 RtlInitUnicodeString(&Link
, LinkName
);
736 // now delete the symbolic link
738 Status
= IoDeleteSymbolicLink(&Link
);
740 if (!NT_SUCCESS(Status
))
758 PHCDCONTROLLER
*OutHcdController
)
763 // allocate controller
765 This
= new(NonPagedPool
, TAG_USBLIB
) CHCDController(0);
769 // failed to allocate
771 return STATUS_INSUFFICIENT_RESOURCES
;
775 // add reference count
782 *OutHcdController
= (PHCDCONTROLLER
)This
;
787 return STATUS_SUCCESS
;