Skip to content

Commit c2c6b0f

Browse files
committed
usb: HUB: Add PnP state tracking
Added PDO/FDO PnP state tracking, which is done according MSDN's "State Transitions for PnP Devices" topic. svn path=/branches/GSoC_2016/USB/; revision=72388
1 parent b1c1381 commit c2c6b0f

File tree

4 files changed

+68
-9
lines changed

4 files changed

+68
-9
lines changed

drivers/usb/usbhub/fdo.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,7 @@ CreateUsbChildDeviceObject(
13221322
RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->UsbDInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2));
13231323
UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext);
13241324

1325-
UsbChildExtension->IsRemovePending = FALSE;
1325+
INITIALIZE_PNP_STATE(UsbChildExtension->Common);
13261326

13271327
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
13281328

@@ -2053,6 +2053,8 @@ USBHUB_FdoHandlePnp(
20532053
Status = USBHUB_ParentFDOStartDevice(DeviceObject, Irp);
20542054
}
20552055

2056+
SET_NEW_PNP_STATE(HubDeviceExtension->Common, Started);
2057+
20562058
Irp->IoStatus.Status = Status;
20572059
IoCompleteRequest(Irp, IO_NO_INCREMENT);
20582060
return Status;
@@ -2116,6 +2118,18 @@ USBHUB_FdoHandlePnp(
21162118
// No action is required from FDO because it have nothing to free.
21172119
DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n");
21182120

2121+
SET_NEW_PNP_STATE(HubDeviceExtension->Common, RemovePending);
2122+
2123+
Irp->IoStatus.Status = STATUS_SUCCESS;
2124+
break;
2125+
}
2126+
case IRP_MN_CANCEL_REMOVE_DEVICE:
2127+
{
2128+
DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
2129+
2130+
if (HubDeviceExtension->Common.PnPState == RemovePending)
2131+
RESTORE_PREVIOUS_PNP_STATE(HubDeviceExtension->Common);
2132+
21192133
Irp->IoStatus.Status = STATUS_SUCCESS;
21202134
break;
21212135
}
@@ -2127,6 +2141,7 @@ USBHUB_FdoHandlePnp(
21272141
// our children that their parent is removed and on next removal
21282142
// they also can be removed.
21292143
//
2144+
SET_NEW_PNP_STATE(HubDeviceExtension->Common, SurpriseRemovePending);
21302145

21312146
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
21322147

drivers/usb/usbhub/pdo.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,9 @@ USBHUB_PdoHandleInternalDeviceControl(
200200
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
201201
ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
202202

203-
if (ChildDeviceExtension->IsRemovePending || !IsValidPDO(DeviceObject))
203+
if (ChildDeviceExtension->Common.PnPState == SurpriseRemovePending ||
204+
ChildDeviceExtension->Common.PnPState == RemovePending ||
205+
!IsValidPDO(DeviceObject))
204206
{
205207
// Parent or child device was surprise removed.
206208
DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject);
@@ -432,6 +434,8 @@ USBHUB_PdoStartDevice(
432434
IoRegisterDeviceInterface(DeviceObject, &GUID_DEVINTERFACE_USB_DEVICE, NULL, &ChildDeviceExtension->SymbolicLinkName);
433435
IoSetDeviceInterfaceState(&ChildDeviceExtension->SymbolicLinkName, TRUE);
434436

437+
SET_NEW_PNP_STATE(ChildDeviceExtension->Common, Started);
438+
435439
UNIMPLEMENTED
436440
return STATUS_SUCCESS;
437441
}
@@ -668,9 +672,15 @@ USBHUB_PdoHandlePnp(
668672

669673
DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
670674

675+
ASSERT((UsbChildExtension->Common.PnPState == RemovePending) ||
676+
(UsbChildExtension->Common.PnPState == SurpriseRemovePending));
677+
678+
SET_NEW_PNP_STATE(UsbChildExtension->Common, NotStarted);
679+
671680
if (!IsValidPDO(DeviceObject))
672681
{
673682
// Parent or child device was surprise removed, freeing resources allocated for child device.
683+
SET_NEW_PNP_STATE(UsbChildExtension->Common, Deleted);
674684

675685
// Remove the usb device
676686
if (UsbChildExtension->UsbDeviceHandle)
@@ -699,8 +709,7 @@ USBHUB_PdoHandlePnp(
699709
IoDeleteDevice(DeviceObject);
700710
}
701711

702-
// Device is physically presented, so we leave its PDO undeleted.
703-
ASSERT(UsbChildExtension->IsRemovePending == TRUE);
712+
// If device is physically presented, we leave its PDO undeleted.
704713

705714
/* Complete the IRP */
706715
Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -760,7 +769,7 @@ USBHUB_PdoHandlePnp(
760769
//
761770
UsbChildExtension->DeviceInterface.InterfaceDereference(UsbChildExtension->DeviceInterface.BusContext);
762771

763-
UsbChildExtension->IsRemovePending = TRUE;
772+
SET_NEW_PNP_STATE(UsbChildExtension->Common, RemovePending);
764773

765774
/* Sure, no problem */
766775
Status = STATUS_SUCCESS;
@@ -770,9 +779,9 @@ USBHUB_PdoHandlePnp(
770779
case IRP_MN_CANCEL_REMOVE_DEVICE:
771780
{
772781
// Check to see have we received query-remove before
773-
if (UsbChildExtension->IsRemovePending == TRUE)
782+
if (UsbChildExtension->Common.PnPState == RemovePending)
774783
{
775-
UsbChildExtension->IsRemovePending = FALSE;
784+
RESTORE_PREVIOUS_PNP_STATE(UsbChildExtension->Common);
776785
UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext);
777786
}
778787

@@ -804,7 +813,7 @@ USBHUB_PdoHandlePnp(
804813
// the flag and do further clean-up in subsequent IRP_MN_REMOVE_DEVICE
805814
// We can receive this IRP when device is physically connected (on stop/start fail).
806815
//
807-
UsbChildExtension->IsRemovePending = TRUE;
816+
SET_NEW_PNP_STATE(UsbChildExtension->Common, SurpriseRemovePending);
808817

809818
Status = STATUS_SUCCESS;
810819
break;

drivers/usb/usbhub/usbhub.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ USBHUB_AddDevice(
8686
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
8787
RtlZeroMemory(HubDeviceExtension, sizeof(HUB_DEVICE_EXTENSION));
8888

89+
INITIALIZE_PNP_STATE(HubDeviceExtension->Common);
90+
8991
//
9092
// Set this to Fdo
9193
//

drivers/usb/usbhub/usbhub.h

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,43 @@ typedef struct _WORK_ITEM_DATA
3939
PVOID Context;
4040
} WORK_ITEM_DATA, *PWORK_ITEM_DATA;
4141

42+
43+
//
44+
// Definitions for device's PnP state tracking, all this states are described
45+
// in PnP Device States diagram of DDK documentation.
46+
//
47+
typedef enum _DEVICE_PNP_STATE {
48+
49+
NotStarted = 0, // Not started
50+
Started, // After handling of START_DEVICE IRP
51+
StopPending, // After handling of QUERY_STOP IRP
52+
Stopped, // After handling of STOP_DEVICE IRP
53+
RemovePending, // After handling of QUERY_REMOVE IRP
54+
SurpriseRemovePending, // After handling of SURPRISE_REMOVE IRP
55+
Deleted, // After handling of REMOVE_DEVICE IRP
56+
UnKnown // Unknown state
57+
58+
} DEVICE_PNP_STATE;
59+
60+
#define INITIALIZE_PNP_STATE(Data) \
61+
(Data).PnPState = NotStarted;\
62+
(Data).PreviousPnPState = NotStarted;
63+
64+
#define SET_NEW_PNP_STATE(Data, state) \
65+
(Data).PnPState = (Data).PnPState;\
66+
(Data).PnPState = (state);
67+
68+
#define RESTORE_PREVIOUS_PNP_STATE(Data) \
69+
(Data).PnPState = (Data).PreviousPnPState;
70+
4271
typedef struct
4372
{
4473
BOOLEAN IsFDO;
74+
// We'll track device PnP state via this variables
75+
DEVICE_PNP_STATE PnPState;
76+
DEVICE_PNP_STATE PreviousPnPState;
77+
// Remove lock
78+
IO_REMOVE_LOCK RemoveLock;
4579
} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
4680

4781
typedef struct _HUB_CHILDDEVICE_EXTENSION
@@ -61,7 +95,6 @@ typedef struct _HUB_CHILDDEVICE_EXTENSION
6195
UNICODE_STRING SymbolicLinkName;
6296
USB_BUS_INTERFACE_USBDI_V2 DeviceInterface;
6397
USB_DEVICE_INFORMATION_0 DeviceInformation;
64-
BOOLEAN IsRemovePending;
6598
} HUB_CHILDDEVICE_EXTENSION, *PHUB_CHILDDEVICE_EXTENSION;
6699

67100
typedef struct _HUB_DEVICE_EXTENSION

0 commit comments

Comments
 (0)