2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Serial enumerator driver
4 * FILE: drivers/bus/serenum/fdo.c
5 * PURPOSE: IRP_MJ_PNP operations for FDOs
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
15 IN PDRIVER_OBJECT DriverObject
,
16 IN PDEVICE_OBJECT Pdo
)
19 PFDO_DEVICE_EXTENSION DeviceExtension
;
22 DPRINT("Serenum: SerenumAddDevice called. Pdo = %p\n", Pdo
);
24 /* Create new device object */
25 Status
= IoCreateDevice(DriverObject
,
26 sizeof(FDO_DEVICE_EXTENSION
),
28 FILE_DEVICE_BUS_EXTENDER
,
29 FILE_DEVICE_SECURE_OPEN
,
32 if (!NT_SUCCESS(Status
))
34 DPRINT("Serenum: IoCreateDevice() failed with status 0x%08lx\n", Status
);
37 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
38 RtlZeroMemory(DeviceExtension
, sizeof(FDO_DEVICE_EXTENSION
));
40 /* Register device interface */
41 Status
= IoRegisterDeviceInterface(
43 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
,
45 &DeviceExtension
->SerenumInterfaceName
);
46 if (!NT_SUCCESS(Status
))
48 DPRINT("Serenum: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
53 DeviceExtension
->Common
.IsFDO
= TRUE
;
54 DeviceExtension
->Common
.PnpState
= dsStopped
;
55 DeviceExtension
->Pdo
= Pdo
;
56 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
, SERENUM_TAG
, 0, 0);
57 Fdo
->Flags
|= DO_POWER_PAGABLE
;
58 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
59 if (!NT_SUCCESS(Status
))
61 DPRINT("Serenum: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
65 Fdo
->Flags
|= DO_BUFFERED_IO
;
66 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
68 return STATUS_SUCCESS
;
71 static NTSTATUS STDCALL
72 SerenumFdoStartDevice(
73 IN PDEVICE_OBJECT DeviceObject
,
76 PFDO_DEVICE_EXTENSION DeviceExtension
;
79 DPRINT("Serenum: SerenumFdoStartDevice() called\n");
80 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
82 ASSERT(DeviceExtension
->Common
.PnpState
== dsStopped
);
84 Status
= IoSetDeviceInterfaceState(&DeviceExtension
->SerenumInterfaceName
, TRUE
);
85 if (!NT_SUCCESS(Status
))
87 DPRINT("Serenum: IoSetDeviceInterfaceState() failed with status 0x%08lx\n", Status
);
91 DeviceExtension
->Common
.PnpState
= dsStarted
;
93 return STATUS_SUCCESS
;
97 SerenumFdoQueryBusRelations(
98 IN PDEVICE_OBJECT DeviceObject
,
99 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
101 PFDO_DEVICE_EXTENSION DeviceExtension
;
102 PDEVICE_RELATIONS DeviceRelations
;
105 NTSTATUS Status
= STATUS_SUCCESS
;
107 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
108 ASSERT(DeviceExtension
->Common
.IsFDO
);
110 /* Do enumeration if needed */
111 if (!(DeviceExtension
->Flags
& FLAG_ENUMERATION_DONE
))
113 ASSERT(DeviceExtension
->AttachedPdo
== NULL
);
114 /* Detect plug-and-play devices */
115 Status
= SerenumDetectPnpDevice(DeviceObject
, DeviceExtension
->LowerDevice
);
116 if (Status
== STATUS_DEVICE_NOT_CONNECTED
)
118 /* Detect legacy devices */
119 Status
= SerenumDetectLegacyDevice(DeviceObject
, DeviceExtension
->LowerDevice
);
120 if (Status
== STATUS_DEVICE_NOT_CONNECTED
)
121 Status
= STATUS_SUCCESS
;
123 DeviceExtension
->Flags
|= FLAG_ENUMERATION_DONE
;
125 NumPDO
= (DeviceExtension
->AttachedPdo
!= NULL
? 1 : 0);
127 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(
129 sizeof(DEVICE_RELATIONS
) + sizeof(PDEVICE_OBJECT
) * (NumPDO
- 1),
131 if (!DeviceRelations
)
132 return STATUS_INSUFFICIENT_RESOURCES
;
134 /* Fill returned structure */
135 DeviceRelations
->Count
= NumPDO
;
136 for (i
= 0; i
< NumPDO
; i
++)
138 ObReferenceObject(DeviceExtension
->AttachedPdo
);
139 DeviceRelations
->Objects
[i
] = DeviceExtension
->AttachedPdo
;
142 *pDeviceRelations
= DeviceRelations
;
148 IN PDEVICE_OBJECT DeviceObject
,
152 PIO_STACK_LOCATION Stack
;
153 ULONG_PTR Information
= 0;
156 Stack
= IoGetCurrentIrpStackLocation(Irp
);
157 MinorFunction
= Stack
->MinorFunction
;
159 switch (MinorFunction
)
161 /* FIXME: do all these minor functions
162 IRP_MN_QUERY_REMOVE_DEVICE 0x1
163 IRP_MN_REMOVE_DEVICE 0x2
164 IRP_MN_CANCEL_REMOVE_DEVICE 0x3
165 IRP_MN_STOP_DEVICE 0x4
166 IRP_MN_QUERY_STOP_DEVICE 0x5
167 IRP_MN_CANCEL_STOP_DEVICE 0x6
168 IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
169 IRP_MN_QUERY_INTERFACE (optional) 0x8
170 IRP_MN_QUERY_CAPABILITIES (optional) 0x9
171 IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional or required) 0xb
172 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
173 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
174 IRP_MN_SURPRISE_REMOVAL 0x17
176 case IRP_MN_START_DEVICE
: /* 0x0 */
178 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
179 /* Call lower driver */
180 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
181 if (NT_SUCCESS(Status
))
182 Status
= SerenumFdoStartDevice(DeviceObject
, Irp
);
185 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x7 */
187 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
191 PDEVICE_RELATIONS DeviceRelations
= NULL
;
192 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
193 Status
= SerenumFdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
194 Information
= (ULONG_PTR
)DeviceRelations
;
198 DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
199 Stack
->Parameters
.QueryDeviceRelations
.Type
);
200 return ForwardIrpAndForget(DeviceObject
, Irp
);
206 DPRINT1("Serenum: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
207 return ForwardIrpAndForget(DeviceObject
, Irp
);
211 Irp
->IoStatus
.Information
= Information
;
212 Irp
->IoStatus
.Status
= Status
;
213 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);