3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS Serial enumerator driver
5 * FILE: drivers/bus/serenum/fdo.c
6 * PURPOSE: IRP_MJ_PNP operations for FDOs
8 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
16 IN PDRIVER_OBJECT DriverObject
,
17 IN PDEVICE_OBJECT Pdo
)
20 PFDO_DEVICE_EXTENSION DeviceExtension
;
23 DPRINT("Serenum: SerenumAddDevice called. Pdo = %p\n", Pdo
);
25 /* Create new device object */
26 Status
= IoCreateDevice(DriverObject
,
27 sizeof(FDO_DEVICE_EXTENSION
),
29 FILE_DEVICE_BUS_EXTENDER
,
30 FILE_DEVICE_SECURE_OPEN
,
33 if (!NT_SUCCESS(Status
))
35 DPRINT("Serenum: IoCreateDevice() failed with status 0x%08lx\n", Status
);
38 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
39 RtlZeroMemory(DeviceExtension
, sizeof(FDO_DEVICE_EXTENSION
));
41 /* Register device interface */
42 Status
= IoRegisterDeviceInterface(
44 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
,
46 &DeviceExtension
->SerenumInterfaceName
);
47 if (!NT_SUCCESS(Status
))
49 DPRINT("Serenum: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
54 DeviceExtension
->Common
.IsFDO
= TRUE
;
55 DeviceExtension
->Common
.PnpState
= dsStopped
;
56 DeviceExtension
->Pdo
= Pdo
;
57 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
, SERENUM_TAG
, 0, 0);
58 Fdo
->Flags
|= DO_POWER_PAGABLE
;
59 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
60 if (!NT_SUCCESS(Status
))
62 DPRINT("Serenum: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
66 Fdo
->Flags
|= DO_BUFFERED_IO
;
67 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
69 return STATUS_SUCCESS
;
73 SerenumFdoStartDevice(
74 IN PDEVICE_OBJECT DeviceObject
,
77 PFDO_DEVICE_EXTENSION DeviceExtension
;
80 DPRINT("Serenum: SerenumFdoStartDevice() called\n");
81 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
83 ASSERT(DeviceExtension
->Common
.PnpState
== dsStopped
);
85 Status
= IoSetDeviceInterfaceState(&DeviceExtension
->SerenumInterfaceName
, TRUE
);
86 if (!NT_SUCCESS(Status
))
88 DPRINT("Serenum: IoSetDeviceInterfaceState() failed with status 0x%08lx\n", Status
);
92 DeviceExtension
->Common
.PnpState
= dsStarted
;
94 return STATUS_SUCCESS
;
98 SerenumFdoQueryBusRelations(
99 IN PDEVICE_OBJECT DeviceObject
,
100 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
102 PFDO_DEVICE_EXTENSION DeviceExtension
;
103 PDEVICE_RELATIONS DeviceRelations
;
106 NTSTATUS Status
= STATUS_SUCCESS
;
108 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
109 ASSERT(DeviceExtension
->Common
.IsFDO
);
111 /* Do enumeration if needed */
112 if (!(DeviceExtension
->Flags
& FLAG_ENUMERATION_DONE
))
114 ASSERT(DeviceExtension
->AttachedPdo
== NULL
);
115 /* Detect plug-and-play devices */
116 Status
= SerenumDetectPnpDevice(DeviceObject
, DeviceExtension
->LowerDevice
);
117 if (Status
== STATUS_DEVICE_NOT_CONNECTED
)
119 /* Detect legacy devices */
120 Status
= SerenumDetectLegacyDevice(DeviceObject
, DeviceExtension
->LowerDevice
);
121 if (Status
== STATUS_DEVICE_NOT_CONNECTED
)
122 Status
= STATUS_SUCCESS
;
124 DeviceExtension
->Flags
|= FLAG_ENUMERATION_DONE
;
126 NumPDO
= (DeviceExtension
->AttachedPdo
!= NULL
? 1 : 0);
128 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(
130 sizeof(DEVICE_RELATIONS
) + sizeof(PDEVICE_OBJECT
) * (NumPDO
- 1),
132 if (!DeviceRelations
)
133 return STATUS_INSUFFICIENT_RESOURCES
;
135 /* Fill returned structure */
136 DeviceRelations
->Count
= NumPDO
;
137 for (i
= 0; i
< NumPDO
; i
++)
139 ObReferenceObject(DeviceExtension
->AttachedPdo
);
140 DeviceRelations
->Objects
[i
] = DeviceExtension
->AttachedPdo
;
143 *pDeviceRelations
= DeviceRelations
;
149 IN PDEVICE_OBJECT DeviceObject
,
153 PIO_STACK_LOCATION Stack
;
154 ULONG_PTR Information
= 0;
157 Stack
= IoGetCurrentIrpStackLocation(Irp
);
158 MinorFunction
= Stack
->MinorFunction
;
160 switch (MinorFunction
)
162 /* FIXME: do all these minor functions
163 IRP_MN_QUERY_REMOVE_DEVICE 0x1
164 IRP_MN_REMOVE_DEVICE 0x2
165 IRP_MN_CANCEL_REMOVE_DEVICE 0x3
166 IRP_MN_STOP_DEVICE 0x4
167 IRP_MN_QUERY_STOP_DEVICE 0x5
168 IRP_MN_CANCEL_STOP_DEVICE 0x6
169 IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
170 IRP_MN_QUERY_INTERFACE (optional) 0x8
171 IRP_MN_QUERY_CAPABILITIES (optional) 0x9
172 IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional or required) 0xb
173 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
174 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
175 IRP_MN_SURPRISE_REMOVAL 0x17
177 case IRP_MN_START_DEVICE
: /* 0x0 */
179 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
180 /* Call lower driver */
181 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
182 if (NT_SUCCESS(Status
))
183 Status
= SerenumFdoStartDevice(DeviceObject
, Irp
);
186 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x7 */
188 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
192 PDEVICE_RELATIONS DeviceRelations
;
193 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
194 Status
= SerenumFdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
195 Information
= (ULONG_PTR
)DeviceRelations
;
199 DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
200 Stack
->Parameters
.QueryDeviceRelations
.Type
);
201 return ForwardIrpAndForget(DeviceObject
, Irp
);
207 DPRINT1("Serenum: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
208 return ForwardIrpAndForget(DeviceObject
, Irp
);
212 Irp
->IoStatus
.Information
= Information
;
213 Irp
->IoStatus
.Status
= Status
;
214 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);