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
;
21 //UNICODE_STRING SymbolicLinkName;
24 DPRINT("Serenum: SerenumAddDevice called. Pdo = %p\n", Pdo
);
26 /* Create new device object */
27 Status
= IoCreateDevice(DriverObject
,
28 sizeof(FDO_DEVICE_EXTENSION
),
30 FILE_DEVICE_BUS_EXTENDER
,
31 FILE_DEVICE_SECURE_OPEN
,
34 if (!NT_SUCCESS(Status
))
36 DPRINT("Serenum: IoCreateDevice() failed with status 0x%08lx\n", Status
);
40 /* Register device interface */
41 #if 0 /* FIXME: activate */
42 Status
= IoRegisterDeviceInterface(Pdo
, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
, NULL
, &SymbolicLinkName
);
43 if (!NT_SUCCESS(Status
))
45 DPRINT("Serenum: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
48 DPRINT1("Serenum: IoRegisterDeviceInterface() returned '%wZ'\n", &SymbolicLinkName
);
49 Status
= IoSetDeviceInterfaceState(&SymbolicLinkName
, TRUE
);
50 if (!NT_SUCCESS(Status
))
52 DPRINT("Serenum: IoSetDeviceInterfaceState() failed with status 0x%08lx\n", Status
);
55 RtlFreeUnicodeString(&SymbolicLinkName
);
58 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
59 RtlZeroMemory(DeviceExtension
, sizeof(FDO_DEVICE_EXTENSION
));
60 DeviceExtension
->Common
.IsFDO
= TRUE
;
61 DeviceExtension
->Common
.PnpState
= dsStopped
;
62 DeviceExtension
->Pdo
= Pdo
;
63 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
, SERENUM_TAG
, 0, 0);
64 Fdo
->Flags
|= DO_POWER_PAGABLE
;
65 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
66 if (!NT_SUCCESS(Status
))
68 DPRINT("Serenum: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
72 Fdo
->Flags
|= DO_BUFFERED_IO
;
73 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
75 return STATUS_SUCCESS
;
79 SerenumFdoStartDevice(
80 IN PDEVICE_OBJECT DeviceObject
,
83 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
85 DPRINT("Serenum: SerenumFdoStartDevice() called\n");
86 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
88 ASSERT(DeviceExtension
->PnpState
== dsStopped
);
89 DeviceExtension
->PnpState
= dsStarted
;
91 return STATUS_SUCCESS
;
95 SerenumFdoQueryBusRelations(
96 IN PDEVICE_OBJECT DeviceObject
,
97 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
99 PFDO_DEVICE_EXTENSION DeviceExtension
;
100 PDEVICE_RELATIONS DeviceRelations
;
105 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
106 ASSERT(DeviceExtension
->Common
.IsFDO
);
108 /* Do enumeration if needed */
109 if (!(DeviceExtension
->Flags
& FLAG_ENUMERATION_DONE
))
111 ASSERT(DeviceExtension
->AttachedPdo
== NULL
);
112 /* Detect plug-and-play devices */
113 Status
= SerenumDetectPnpDevice(DeviceObject
, DeviceExtension
->LowerDevice
);
114 if (Status
== STATUS_DEVICE_NOT_CONNECTED
)
116 /* Detect legacy devices */
117 Status
= SerenumDetectLegacyDevice(DeviceObject
, DeviceExtension
->LowerDevice
);
118 if (Status
== STATUS_DEVICE_NOT_CONNECTED
)
119 Status
= STATUS_SUCCESS
;
121 DeviceExtension
->Flags
|= FLAG_ENUMERATION_DONE
;
123 NumPDO
= (DeviceExtension
->AttachedPdo
!= NULL
? 1 : 0);
125 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(
127 sizeof(DEVICE_RELATIONS
) + sizeof(PDEVICE_OBJECT
) * (NumPDO
- 1),
129 if (!DeviceRelations
)
130 return STATUS_INSUFFICIENT_RESOURCES
;
132 /* Fill returned structure */
133 DeviceRelations
->Count
= NumPDO
;
134 for (i
= 0; i
< NumPDO
; i
++)
136 ObReferenceObject(DeviceExtension
->AttachedPdo
);
137 DeviceRelations
->Objects
[i
] = DeviceExtension
->AttachedPdo
;
140 *pDeviceRelations
= DeviceRelations
;
146 IN PDEVICE_OBJECT DeviceObject
,
150 PIO_STACK_LOCATION Stack
;
151 ULONG_PTR Information
= 0;
154 Stack
= IoGetCurrentIrpStackLocation(Irp
);
155 MinorFunction
= Stack
->MinorFunction
;
157 switch (MinorFunction
)
159 /* FIXME: do all these minor functions
160 IRP_MN_QUERY_REMOVE_DEVICE 0x1
161 IRP_MN_REMOVE_DEVICE 0x2
162 IRP_MN_CANCEL_REMOVE_DEVICE 0x3
163 IRP_MN_STOP_DEVICE 0x4
164 IRP_MN_QUERY_STOP_DEVICE 0x5
165 IRP_MN_CANCEL_STOP_DEVICE 0x6
166 IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
167 IRP_MN_QUERY_INTERFACE (optional) 0x8
168 IRP_MN_QUERY_CAPABILITIES (optional) 0x9
169 IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional or required) 0xb
170 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
171 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
172 IRP_MN_SURPRISE_REMOVAL 0x17
174 case IRP_MN_START_DEVICE
: /* 0x0 */
176 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
177 /* Call lower driver */
178 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
179 if (NT_SUCCESS(Status
))
180 Status
= SerenumFdoStartDevice(DeviceObject
, Irp
);
183 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x7 */
185 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
189 PDEVICE_RELATIONS DeviceRelations
;
190 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
191 Status
= SerenumFdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
192 Information
= (ULONG_PTR
)DeviceRelations
;
196 DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
197 Stack
->Parameters
.QueryDeviceRelations
.Type
);
198 return ForwardIrpAndForget(DeviceObject
, Irp
);
204 DPRINT1("Serenum: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
205 return ForwardIrpAndForget(DeviceObject
, Irp
);
209 Irp
->IoStatus
.Information
= Information
;
210 Irp
->IoStatus
.Status
= Status
;
211 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);