2 * PROJECT: ReactOS Universal Serial Bus Hub Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbhub/fdo.c
7 * Hervé Poussineau (hpoussin@reactos.org)
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
19 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
21 DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE
,
22 0xA5DCBF10L
, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
27 PDEVICE_OBJECT DeviceObject
,
32 DPRINT("Entered Urb Completion\n");
35 // Get the original Irp
37 OriginalIrp
= (PIRP
)Context
;
40 // Update it to match what was returned for the IRP that was passed to RootHub
42 OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
43 OriginalIrp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
44 DPRINT("Status %x, Information %x\n", Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
47 // Complete the original Irp
49 IoCompleteRequest(OriginalIrp
, IO_NO_INCREMENT
);
52 // Free our allocated IRP
57 // Return this status so the IO Manager doesnt mess with the Irp
59 return STATUS_MORE_PROCESSING_REQUIRED
;
64 PDEVICE_OBJECT RootHubDeviceObject
,
65 IN ULONG IoControlCode
,
67 OUT PVOID OutParameter1
,
68 OUT PVOID OutParameter2
)
71 IO_STATUS_BLOCK IoStatus
;
72 PIO_STACK_LOCATION ForwardStack
, CurrentStack
;
76 // Get the current stack location for the Irp
78 CurrentStack
= IoGetCurrentIrpStackLocation(Irp
);
82 // Pull the Urb from that stack, it will be reused in the Irp sent to RootHub
84 Urb
= (PURB
)CurrentStack
->Parameters
.Others
.Argument1
;
88 // Create the Irp to forward to RootHub
90 ForwardIrp
= IoBuildAsynchronousFsdRequest(IRP_MJ_SHUTDOWN
,
98 DPRINT1("Failed to allocate IRP\n");
99 return STATUS_INSUFFICIENT_RESOURCES
;
103 // Get the new Irps next stack
105 ForwardStack
= IoGetNextIrpStackLocation(ForwardIrp
);
108 // Copy the stack for the current irp into the next stack of new irp
110 RtlCopyMemory(ForwardStack
, CurrentStack
, sizeof(IO_STACK_LOCATION
));
112 IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
113 IoStatus
.Information
= 0;
116 // Mark the Irp from upper driver as pending
118 IoMarkIrpPending(Irp
);
121 // Now set the completion routine for the new Irp.
123 IoSetCompletionRoutine(ForwardIrp
,
130 IoCallDriver(RootHubDeviceObject
, ForwardIrp
);
133 // Always return pending as the completion routine will take care of it
135 return STATUS_PENDING
;
140 IN PDEVICE_OBJECT DeviceObject
)
143 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
144 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
147 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
148 ASSERT(ChildDeviceExtension
->Common
.IsFDO
== FALSE
);
150 // This can happen when parent device was surprise removed.
151 if (ChildDeviceExtension
->ParentDeviceObject
== NULL
)
154 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
156 KeAcquireGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
157 for(Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
159 if (HubDeviceExtension
->ChildDeviceObject
[Index
] == DeviceObject
)
161 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
167 KeReleaseGuardedMutex(&HubDeviceExtension
->HubMutexLock
);
175 USBHUB_PdoHandleInternalDeviceControl(
176 IN PDEVICE_OBJECT DeviceObject
,
180 PIO_STACK_LOCATION Stack
;
181 ULONG_PTR Information
= 0;
182 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
183 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
184 PDEVICE_OBJECT RootHubDeviceObject
;
187 //DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject);
190 // get current stack location
192 Stack
= IoGetCurrentIrpStackLocation(Irp
);
196 // Set default status
198 Status
= Irp
->IoStatus
.Status
;
200 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
201 ASSERT(ChildDeviceExtension
->Common
.IsFDO
== FALSE
);
203 Status
= IoAcquireRemoveLock(&ChildDeviceExtension
->Common
.RemoveLock
, Irp
);
204 if (!NT_SUCCESS(Status
))
206 Irp
->IoStatus
.Status
= Status
;
207 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
211 if (ChildDeviceExtension
->Common
.PnPState
== SurpriseRemovePending
||
212 ChildDeviceExtension
->Common
.PnPState
== RemovePending
||
213 ChildDeviceExtension
->ParentDeviceObject
== NULL
)
215 // Parent or child device was surprise removed.
216 DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject
);
217 Irp
->IoStatus
.Status
= STATUS_DEVICE_NOT_CONNECTED
;
218 Irp
->IoStatus
.Information
= 0;
219 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
220 IoReleaseRemoveLock(&ChildDeviceExtension
->Common
.RemoveLock
, Irp
);
221 return STATUS_DEVICE_NOT_CONNECTED
;
224 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
225 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
227 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
229 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO
:
231 DPRINT("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
232 if (Irp
->AssociatedIrp
.SystemBuffer
== NULL
233 || Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
!= sizeof(PVOID
))
235 Status
= STATUS_INVALID_PARAMETER
;
241 pHubPointer
= (PVOID
*)Irp
->AssociatedIrp
.SystemBuffer
;
244 Information
= sizeof(PVOID
);
245 Status
= STATUS_SUCCESS
;
249 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
251 //DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB\n");
256 Urb
= (PURB
)Stack
->Parameters
.Others
.Argument1
;
260 // Set the real device handle
262 //DPRINT("UsbdDeviceHandle %x, ChildDeviceHandle %x\n", Urb->UrbHeader.UsbdDeviceHandle, ChildDeviceExtension->UsbDeviceHandle);
264 Urb
->UrbHeader
.UsbdDeviceHandle
= ChildDeviceExtension
->UsbDeviceHandle
;
269 switch (Urb
->UrbHeader
.Function
)
274 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
275 DPRINT("URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
277 case URB_FUNCTION_CLASS_DEVICE
:
278 DPRINT("URB_FUNCTION_CLASS_DEVICE\n");
280 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
281 DPRINT("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
283 case URB_FUNCTION_SELECT_CONFIGURATION
:
284 DPRINT("URB_FUNCTION_SELECT_CONFIGURATION\n");
286 case URB_FUNCTION_SELECT_INTERFACE
:
287 DPRINT("URB_FUNCTION_SELECT_INTERFACE\n");
289 case URB_FUNCTION_CLASS_OTHER
:
290 DPRINT("URB_FUNCTION_CLASS_OTHER\n");
292 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
295 DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n");
296 DPRINT1("PipeHandle %x\n", Urb->UrbBulkOrInterruptTransfer.PipeHandle);
297 DPRINT1("TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags);
298 DPRINT1("Buffer %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
299 DPRINT1("BufferMDL %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
300 DPRINT1("Length %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
301 DPRINT1("UrbLink %x\n", Urb->UrbBulkOrInterruptTransfer.UrbLink);
302 DPRINT1("hca %x\n", Urb->UrbBulkOrInterruptTransfer.hca);
303 if (Urb->UrbBulkOrInterruptTransfer.TransferFlags == USBD_SHORT_TRANSFER_OK)
310 case URB_FUNCTION_CLASS_INTERFACE
:
311 DPRINT("URB_FUNCTION_CLASS_INTERFACE\n");
313 case URB_FUNCTION_VENDOR_DEVICE
:
314 DPRINT("URB_FUNCTION_VENDOR_DEVICE\n");
317 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb
->UrbHeader
.Function
);
320 Urb
->UrbHeader
.UsbdDeviceHandle
= ChildDeviceExtension
->UsbDeviceHandle
;
321 //DPRINT1("Stack->CompletionRoutine %x\n", Stack->CompletionRoutine);
323 // Send the request to RootHub
325 Status
= ForwardUrbToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Irp
, Urb
, NULL
);
326 IoReleaseRemoveLock(&ChildDeviceExtension
->Common
.RemoveLock
, Irp
);
330 // FIXME: Can these be sent to RootHub?
332 case IOCTL_INTERNAL_USB_RESET_PORT
:
333 DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
335 case IOCTL_INTERNAL_USB_GET_PORT_STATUS
:
337 PORT_STATUS_CHANGE PortStatus
;
339 PUCHAR PortStatusBits
;
341 PortStatusBits
= (PUCHAR
)Stack
->Parameters
.Others
.Argument1
;
343 // USBD_PORT_ENABLED (bit 0) or USBD_PORT_CONNECTED (bit 1)
345 DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
346 DPRINT("Arg1 %x\n", *PortStatusBits
);
348 if (Stack
->Parameters
.Others
.Argument1
)
350 for (PortId
= 1; PortId
<= HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
; PortId
++)
352 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
353 if (NT_SUCCESS(Status
))
355 DPRINT("Connect %x\n", ((PortStatus
.Status
& USB_PORT_STATUS_CONNECT
) << 1) << ((PortId
- 1) * 2));
356 DPRINT("Enable %x\n", ((PortStatus
.Status
& USB_PORT_STATUS_ENABLE
) >> 1) << ((PortId
- 1) * 2));
358 (((PortStatus
.Status
& USB_PORT_STATUS_CONNECT
) << 1) << ((PortId
- 1) * 2)) +
359 (((PortStatus
.Status
& USB_PORT_STATUS_ENABLE
) >> 1) << ((PortId
- 1) * 2));
365 DPRINT1("Arg1 %x\n", *PortStatusBits
);
366 Status
= STATUS_SUCCESS
;
369 case IOCTL_INTERNAL_USB_ENABLE_PORT
:
370 DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
372 case IOCTL_INTERNAL_USB_CYCLE_PORT
:
373 DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
375 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
377 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
378 if (Stack
->Parameters
.Others
.Argument1
)
380 // store device handle
381 *(PVOID
*)Stack
->Parameters
.Others
.Argument1
= (PVOID
)ChildDeviceExtension
->UsbDeviceHandle
;
382 Status
= STATUS_SUCCESS
;
387 Status
= STATUS_INVALID_PARAMETER
;
391 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
393 if (Stack
->Parameters
.Others
.Argument1
)
395 // inform caller that it is a real usb hub
396 *(PVOID
*)Stack
->Parameters
.Others
.Argument1
= NULL
;
399 if (Stack
->Parameters
.Others
.Argument2
)
401 // output device object
402 *(PVOID
*)Stack
->Parameters
.Others
.Argument2
= DeviceObject
;
406 Status
= STATUS_SUCCESS
;
411 DPRINT1("Unknown IOCTL code 0x%lx\n", Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
412 Information
= Irp
->IoStatus
.Information
;
413 Status
= Irp
->IoStatus
.Status
;
417 if (Status
!= STATUS_PENDING
)
419 Irp
->IoStatus
.Information
= Information
;
420 Irp
->IoStatus
.Status
= Status
;
421 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
423 IoReleaseRemoveLock(&ChildDeviceExtension
->Common
.RemoveLock
, Irp
);
428 USBHUB_PdoStartDevice(
429 IN PDEVICE_OBJECT DeviceObject
,
432 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
434 DPRINT("USBHUB_PdoStartDevice %x\n", DeviceObject
);
435 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
438 // This should be a PDO
440 ASSERT(ChildDeviceExtension
->Common
.IsFDO
== FALSE
);
443 // register device interface
445 IoRegisterDeviceInterface(DeviceObject
, &GUID_DEVINTERFACE_USB_DEVICE
, NULL
, &ChildDeviceExtension
->SymbolicLinkName
);
446 IoSetDeviceInterfaceState(&ChildDeviceExtension
->SymbolicLinkName
, TRUE
);
448 SET_NEW_PNP_STATE(ChildDeviceExtension
->Common
, Started
);
451 return STATUS_SUCCESS
;
456 IN PDEVICE_OBJECT DeviceObject
,
458 OUT ULONG_PTR
* Information
)
460 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
462 PUNICODE_STRING SourceString
= NULL
;
463 PWCHAR ReturnString
= NULL
;
464 NTSTATUS Status
= STATUS_SUCCESS
;
466 IdType
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryId
.IdType
;
467 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
471 case BusQueryDeviceID
:
473 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
474 SourceString
= &ChildDeviceExtension
->usDeviceId
;
477 case BusQueryHardwareIDs
:
479 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
480 SourceString
= &ChildDeviceExtension
->usHardwareIds
;
483 case BusQueryCompatibleIDs
:
485 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
486 SourceString
= &ChildDeviceExtension
->usCompatibleIds
;
489 case BusQueryInstanceID
:
491 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
492 SourceString
= &ChildDeviceExtension
->usInstanceId
;
496 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
497 return STATUS_NOT_SUPPORTED
;
505 ReturnString
= ExAllocatePool(PagedPool
, SourceString
->MaximumLength
);
511 return STATUS_INSUFFICIENT_RESOURCES
;
517 RtlCopyMemory(ReturnString
, SourceString
->Buffer
, SourceString
->MaximumLength
);
520 *Information
= (ULONG_PTR
)ReturnString
;
526 USBHUB_PdoQueryDeviceText(
527 IN PDEVICE_OBJECT DeviceObject
,
529 OUT ULONG_PTR
* Information
)
531 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
532 DEVICE_TEXT_TYPE DeviceTextType
;
533 PUNICODE_STRING SourceString
= NULL
;
534 PWCHAR ReturnString
= NULL
;
535 NTSTATUS Status
= STATUS_SUCCESS
;
537 DeviceTextType
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryDeviceText
.DeviceTextType
;
538 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
544 switch (DeviceTextType
)
546 case DeviceTextDescription
:
547 case DeviceTextLocationInformation
:
549 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
552 // does the device provide a text description
554 if (ChildDeviceExtension
->usTextDescription
.Buffer
&& ChildDeviceExtension
->usTextDescription
.Length
)
559 SourceString
= &ChildDeviceExtension
->usTextDescription
;
565 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType
);
566 Status
= STATUS_NOT_SUPPORTED
;
573 ReturnString
= ExAllocatePool(PagedPool
, SourceString
->MaximumLength
);
574 RtlCopyMemory(ReturnString
, SourceString
->Buffer
, SourceString
->MaximumLength
);
575 DPRINT1("%S\n", ReturnString
);
576 *Information
= (ULONG_PTR
)ReturnString
;
584 IN PDEVICE_OBJECT DeviceObject
,
589 PIO_STACK_LOCATION Stack
;
590 ULONG_PTR Information
= 0;
591 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
592 PDEVICE_RELATIONS DeviceRelation
;
594 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
595 Stack
= IoGetCurrentIrpStackLocation(Irp
);
596 MinorFunction
= Stack
->MinorFunction
;
598 Status
= IoAcquireRemoveLock(&UsbChildExtension
->Common
.RemoveLock
, Irp
);
599 if (!NT_SUCCESS(Status
))
601 Irp
->IoStatus
.Status
= Status
;
602 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
606 switch (MinorFunction
)
608 case IRP_MN_START_DEVICE
:
610 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
611 Status
= USBHUB_PdoStartDevice(DeviceObject
, Irp
);
614 case IRP_MN_QUERY_CAPABILITIES
:
616 PDEVICE_CAPABILITIES DeviceCapabilities
;
618 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
620 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)Stack
->Parameters
.DeviceCapabilities
.Capabilities
;
621 // FIXME: capabilities can change with connected device
622 DeviceCapabilities
->LockSupported
= FALSE
;
623 DeviceCapabilities
->EjectSupported
= FALSE
;
624 DeviceCapabilities
->Removable
= TRUE
;
625 DeviceCapabilities
->DockDevice
= FALSE
;
626 DeviceCapabilities
->UniqueID
= FALSE
;
627 DeviceCapabilities
->SilentInstall
= FALSE
;
628 DeviceCapabilities
->RawDeviceOK
= FALSE
;
629 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
630 DeviceCapabilities
->HardwareDisabled
= FALSE
;
631 //DeviceCapabilities->NoDisplayInUI = FALSE;
632 DeviceCapabilities
->Address
= UsbChildExtension
->PortNumber
;
633 DeviceCapabilities
->UINumber
= 0;
634 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
635 for (i
= 1; i
< PowerSystemMaximum
; i
++)
636 DeviceCapabilities
->DeviceState
[i
] = PowerDeviceD3
;
637 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined;
638 DeviceCapabilities
->D1Latency
= 0;
639 DeviceCapabilities
->D2Latency
= 0;
640 DeviceCapabilities
->D3Latency
= 0;
641 Status
= STATUS_SUCCESS
;
644 case IRP_MN_QUERY_RESOURCES
:
646 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
648 Information
= Irp
->IoStatus
.Information
;
649 Status
= Irp
->IoStatus
.Status
;
652 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
654 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
656 Information
= Irp
->IoStatus
.Information
;
657 Status
= Irp
->IoStatus
.Status
;
660 case IRP_MN_QUERY_DEVICE_TEXT
:
662 DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
663 Status
= USBHUB_PdoQueryDeviceText(DeviceObject
, Irp
, &Information
);
666 case IRP_MN_QUERY_ID
:
668 DPRINT("IRP_MN_QUERY_ID\n");
669 Status
= USBHUB_PdoQueryId(DeviceObject
, Irp
, &Information
);
672 case IRP_MN_QUERY_BUS_INFORMATION
:
674 PPNP_BUS_INFORMATION BusInfo
;
675 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
676 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
677 RtlCopyMemory(&BusInfo
->BusTypeGuid
,
679 sizeof(BusInfo
->BusTypeGuid
));
680 BusInfo
->LegacyBusType
= PNPBus
;
682 BusInfo
->BusNumber
= 0;
683 Information
= (ULONG_PTR
)BusInfo
;
684 Status
= STATUS_SUCCESS
;
687 case IRP_MN_REMOVE_DEVICE
:
689 PHUB_DEVICE_EXTENSION HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)UsbChildExtension
->ParentDeviceObject
->DeviceExtension
;
690 PUSB_BUS_INTERFACE_HUB_V5 HubInterface
= &HubDeviceExtension
->HubInterface
;
692 DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
694 ASSERT((UsbChildExtension
->Common
.PnPState
== RemovePending
) ||
695 (UsbChildExtension
->Common
.PnPState
== SurpriseRemovePending
));
697 SET_NEW_PNP_STATE(UsbChildExtension
->Common
, NotStarted
);
699 if (!IsValidPDO(DeviceObject
))
701 // Parent or child device was surprise removed, freeing resources allocated for child device.
702 SET_NEW_PNP_STATE(UsbChildExtension
->Common
, Deleted
);
704 IoReleaseRemoveLockAndWait(&UsbChildExtension
->Common
.RemoveLock
, Irp
);
706 // Remove the usb device
707 if (UsbChildExtension
->UsbDeviceHandle
)
709 Status
= HubInterface
->RemoveUsbDevice(HubInterface
->BusContext
, UsbChildExtension
->UsbDeviceHandle
, 0);
710 ASSERT(Status
== STATUS_SUCCESS
);
712 // Free full configuration descriptor
713 if (UsbChildExtension
->FullConfigDesc
)
714 ExFreePool(UsbChildExtension
->FullConfigDesc
);
717 if (UsbChildExtension
->usCompatibleIds
.Buffer
)
718 ExFreePool(UsbChildExtension
->usCompatibleIds
.Buffer
);
720 if (UsbChildExtension
->usDeviceId
.Buffer
)
721 ExFreePool(UsbChildExtension
->usDeviceId
.Buffer
);
723 if (UsbChildExtension
->usHardwareIds
.Buffer
)
724 ExFreePool(UsbChildExtension
->usHardwareIds
.Buffer
);
726 if (UsbChildExtension
->usInstanceId
.Buffer
)
727 ExFreePool(UsbChildExtension
->usInstanceId
.Buffer
);
729 DPRINT("Deleting child PDO\n");
730 IoDeleteDevice(DeviceObject
);
734 IoReleaseRemoveLock(&UsbChildExtension
->Common
.RemoveLock
, Irp
);
737 // If device is physically presented, we leave its PDO undeleted.
739 /* Complete the IRP */
740 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
741 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
743 return STATUS_SUCCESS
;
745 case IRP_MN_QUERY_DEVICE_RELATIONS
:
747 /* only target relations are supported */
748 if (Stack
->Parameters
.QueryDeviceRelations
.Type
!= TargetDeviceRelation
)
751 Status
= Irp
->IoStatus
.Status
;
752 Information
= Irp
->IoStatus
.Information
;
756 /* allocate device relations */
757 DeviceRelation
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
));
761 Status
= STATUS_INSUFFICIENT_RESOURCES
;
765 /* init device relation */
766 DeviceRelation
->Count
= 1;
767 DeviceRelation
->Objects
[0] = DeviceObject
;
768 ObReferenceObject(DeviceRelation
->Objects
[0]);
771 Information
= (ULONG_PTR
)DeviceRelation
;
772 Status
= STATUS_SUCCESS
;
775 case IRP_MN_QUERY_STOP_DEVICE
:
778 // We should fail this request, because we're not handling IRP_MN_STOP_DEVICE for now.
779 // We'll receive this IRP ONLY when the PnP manager rebalances resources.
781 Status
= STATUS_NOT_SUPPORTED
;
784 case IRP_MN_QUERY_REMOVE_DEVICE
:
787 // Free interface obtained from bottom, according MSDN we should
788 // check interfaces provided to top, but here we are not checking.
789 // All checking will be performed in roothub driver's
790 // IRP_MN_QUERY_REMOVE_DEVICE handler. This will make problems when
791 // buggy driver is loaded on top of us. But we decided to keep source
792 // simpler, because in any case buggy driver will prevent removing of
795 UsbChildExtension
->DeviceInterface
.InterfaceDereference(UsbChildExtension
->DeviceInterface
.BusContext
);
797 SET_NEW_PNP_STATE(UsbChildExtension
->Common
, RemovePending
);
799 /* Sure, no problem */
800 Status
= STATUS_SUCCESS
;
804 case IRP_MN_CANCEL_REMOVE_DEVICE
:
806 // Check to see have we received query-remove before
807 if (UsbChildExtension
->Common
.PnPState
== RemovePending
)
809 RESTORE_PREVIOUS_PNP_STATE(UsbChildExtension
->Common
);
810 UsbChildExtension
->DeviceInterface
.InterfaceReference(UsbChildExtension
->DeviceInterface
.BusContext
);
813 Status
= STATUS_SUCCESS
;
816 case IRP_MN_QUERY_INTERFACE
:
818 DPRINT1("IRP_MN_QUERY_INTERFACE\n");
819 if (IsEqualGUIDAligned(Stack
->Parameters
.QueryInterface
.InterfaceType
, &USB_BUS_INTERFACE_USBDI_GUID
))
821 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID\n");
822 RtlCopyMemory(Stack
->Parameters
.QueryInterface
.Interface
, &UsbChildExtension
->DeviceInterface
, Stack
->Parameters
.QueryInterface
.Size
);
823 UsbChildExtension
->DeviceInterface
.InterfaceReference(UsbChildExtension
->DeviceInterface
.BusContext
);
824 Status
= STATUS_SUCCESS
;
829 IoSkipCurrentIrpStackLocation(Irp
);
830 Status
= IoCallDriver(UsbChildExtension
->ParentDeviceObject
, Irp
);
831 IoReleaseRemoveLock(&UsbChildExtension
->Common
.RemoveLock
, Irp
);
834 case IRP_MN_SURPRISE_REMOVAL
:
836 DPRINT("[USBHUB] HandlePnp IRP_MN_SURPRISE_REMOVAL\n");
839 // Here we should free all resources and stop all access, lets just set
840 // the flag and do further clean-up in subsequent IRP_MN_REMOVE_DEVICE
841 // We can receive this IRP when device is physically connected (on stop/start fail).
843 SET_NEW_PNP_STATE(UsbChildExtension
->Common
, SurpriseRemovePending
);
845 Status
= STATUS_SUCCESS
;
850 DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
851 Information
= Irp
->IoStatus
.Information
;
852 Status
= Irp
->IoStatus
.Status
;
856 IoReleaseRemoveLock(&UsbChildExtension
->Common
.RemoveLock
, Irp
);
858 Irp
->IoStatus
.Information
= Information
;
859 Irp
->IoStatus
.Status
= Status
;
860 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);