[CMAKE]
[reactos.git] / drivers / serial / serenum / pdo.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Serial enumerator driver
4 * FILE: drivers/bus/serenum/pdo.c
5 * PURPOSE: IRP_MJ_PNP operations for PDOs
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
8 */
9
10 #include "serenum.h"
11
12 static NTSTATUS
13 SerenumPdoStartDevice(
14 IN PDEVICE_OBJECT DeviceObject)
15 {
16 PPDO_DEVICE_EXTENSION DeviceExtension;
17
18 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
19
20 ASSERT(DeviceExtension->Common.PnpState == dsStopped);
21
22 DeviceExtension->Common.PnpState = dsStarted;
23 return STATUS_SUCCESS;
24 }
25
26 static NTSTATUS
27 SerenumPdoQueryId(
28 IN PDEVICE_OBJECT DeviceObject,
29 IN PIRP Irp,
30 OUT ULONG_PTR* Information)
31 {
32 PPDO_DEVICE_EXTENSION DeviceExtension;
33 ULONG IdType;
34 PUNICODE_STRING SourceString;
35 UNICODE_STRING String;
36 NTSTATUS Status;
37
38 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
39 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
40 RtlInitUnicodeString(&String, NULL);
41
42 switch (IdType)
43 {
44 case BusQueryDeviceID:
45 {
46 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
47 SourceString = &DeviceExtension->DeviceId;
48 break;
49 }
50 case BusQueryHardwareIDs:
51 {
52 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
53 SourceString = &DeviceExtension->HardwareIds;
54 break;
55 }
56 case BusQueryCompatibleIDs:
57 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
58 SourceString = &DeviceExtension->CompatibleIds;
59 break;
60 case BusQueryInstanceID:
61 {
62 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
63 SourceString = &DeviceExtension->InstanceId;
64 break;
65 }
66 default:
67 WARN_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
68 ASSERT(FALSE);
69 return STATUS_NOT_SUPPORTED;
70 }
71
72 Status = DuplicateUnicodeString(
73 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
74 SourceString,
75 &String);
76 *Information = (ULONG_PTR)String.Buffer;
77 return Status;
78 }
79
80 static NTSTATUS
81 SerenumPdoQueryDeviceRelations(
82 IN PDEVICE_OBJECT DeviceObject,
83 OUT PDEVICE_RELATIONS* pDeviceRelations)
84 {
85 PFDO_DEVICE_EXTENSION DeviceExtension;
86 PDEVICE_RELATIONS DeviceRelations;
87
88 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
89 ASSERT(DeviceExtension->Common.IsFDO);
90
91 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(
92 PagedPool,
93 sizeof(DEVICE_RELATIONS),
94 SERENUM_TAG);
95 if (!DeviceRelations)
96 return STATUS_INSUFFICIENT_RESOURCES;
97
98 ObReferenceObject(DeviceObject);
99 DeviceRelations->Count = 1;
100 DeviceRelations->Objects[0] = DeviceObject;
101
102 *pDeviceRelations = DeviceRelations;
103 return STATUS_SUCCESS;
104 }
105
106 NTSTATUS
107 SerenumPdoPnp(
108 IN PDEVICE_OBJECT DeviceObject,
109 IN PIRP Irp)
110 {
111 ULONG MinorFunction;
112 PIO_STACK_LOCATION Stack;
113 ULONG_PTR Information = 0;
114 NTSTATUS Status;
115
116 Stack = IoGetCurrentIrpStackLocation(Irp);
117 MinorFunction = Stack->MinorFunction;
118
119 switch (MinorFunction)
120 {
121 /* FIXME: do all these minor functions
122 IRP_MN_QUERY_REMOVE_DEVICE 0x1
123 IRP_MN_REMOVE_DEVICE 0x2
124 IRP_MN_CANCEL_REMOVE_DEVICE 0x3
125 IRP_MN_STOP_DEVICE 0x4
126 IRP_MN_QUERY_STOP_DEVICE 0x5
127 IRP_MN_CANCEL_STOP_DEVICE 0x6
128 IRP_MN_QUERY_DEVICE_RELATIONS / EjectionRelations (optional) 0x7
129 IRP_MN_QUERY_INTERFACE (required or optional) 0x8
130 IRP_MN_READ_CONFIG (required or optional) 0xf
131 IRP_MN_WRITE_CONFIG (required or optional) 0x10
132 IRP_MN_EJECT (required or optional) 0x11
133 IRP_MN_SET_LOCK (required or optional) 0x12
134 IRP_MN_QUERY_ID / BusQueryDeviceID 0x13
135 IRP_MN_QUERY_ID / BusQueryCompatibleIDs (optional) 0x13
136 IRP_MN_QUERY_ID / BusQueryInstanceID (optional) 0x13
137 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
138 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
139 IRP_MN_SURPRISE_REMOVAL 0x17
140 */
141 case IRP_MN_START_DEVICE: /* 0x0 */
142 {
143 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
144 Status = SerenumPdoStartDevice(DeviceObject);
145 break;
146 }
147 case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x7 */
148 {
149 switch (Stack->Parameters.QueryDeviceRelations.Type)
150 {
151 case RemovalRelations:
152 {
153 return ForwardIrpToAttachedFdoAndForget(DeviceObject, Irp);
154 }
155 case TargetDeviceRelation:
156 {
157 PDEVICE_RELATIONS DeviceRelations = NULL;
158 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
159 Status = SerenumPdoQueryDeviceRelations(DeviceObject, &DeviceRelations);
160 Information = (ULONG_PTR)DeviceRelations;
161 break;
162 }
163 default:
164 {
165 WARN_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
166 Stack->Parameters.QueryDeviceRelations.Type);
167 ASSERT(FALSE);
168 Status = STATUS_NOT_IMPLEMENTED;
169 break;
170 }
171 }
172 break;
173 }
174 case IRP_MN_QUERY_CAPABILITIES: /* 0x9 */
175 {
176 PDEVICE_CAPABILITIES DeviceCapabilities;
177 ULONG i;
178 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
179
180 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
181 /* FIXME: capabilities can change with connected device */
182 DeviceCapabilities->LockSupported = FALSE;
183 DeviceCapabilities->EjectSupported = FALSE;
184 DeviceCapabilities->Removable = TRUE;
185 DeviceCapabilities->DockDevice = FALSE;
186 DeviceCapabilities->UniqueID = FALSE;
187 DeviceCapabilities->SilentInstall = FALSE;
188 DeviceCapabilities->RawDeviceOK = TRUE;
189 DeviceCapabilities->SurpriseRemovalOK = TRUE;
190 DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME */
191 //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
192 DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* FIXME */
193 for (i = 0; i < PowerSystemMaximum; i++)
194 DeviceCapabilities->DeviceState[i] = PowerDeviceD3; /* FIXME */
195 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */
196 DeviceCapabilities->D1Latency = 0; /* FIXME */
197 DeviceCapabilities->D2Latency = 0; /* FIXME */
198 DeviceCapabilities->D3Latency = 0; /* FIXME */
199 Status = STATUS_SUCCESS;
200 break;
201 }
202 case IRP_MN_QUERY_RESOURCES: /* 0xa */
203 {
204 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
205 /* Serial devices don't need resources, except the ones of
206 * the serial port. This PDO is the serial device PDO, so
207 * report no resource by not changing Information and
208 * Status
209 */
210 Information = Irp->IoStatus.Information;
211 Status = Irp->IoStatus.Status;
212 break;
213 }
214 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0xb */
215 {
216 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
217 /* Serial devices don't need resources, except the ones of
218 * the serial port. This PDO is the serial device PDO, so
219 * report no resource by not changing Information and
220 * Status
221 */
222 Information = Irp->IoStatus.Information;
223 Status = Irp->IoStatus.Status;
224 break;
225 }
226 case IRP_MN_QUERY_DEVICE_TEXT: /* 0xc */
227 {
228 switch (Stack->Parameters.QueryDeviceText.DeviceTextType)
229 {
230 case DeviceTextDescription:
231 {
232 PUNICODE_STRING Source;
233 PWSTR Description;
234 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
235
236 Source = &((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceDescription;
237 Description = ExAllocatePoolWithTag(PagedPool, Source->Length + sizeof(WCHAR), SERENUM_TAG);
238 if (!Description)
239 Status = STATUS_INSUFFICIENT_RESOURCES;
240 else
241 {
242 RtlCopyMemory(Description, Source->Buffer, Source->Length);
243 Description[Source->Length / sizeof(WCHAR)] = L'\0';
244 Information = (ULONG_PTR)Description;
245 Status = STATUS_SUCCESS;
246 }
247 break;
248 }
249 case DeviceTextLocationInformation:
250 {
251 /* We don't have any text location to report,
252 * and this query is optional, so ignore it.
253 */
254 Information = Irp->IoStatus.Information;
255 Status = Irp->IoStatus.Status;
256 break;
257 }
258 default:
259 {
260 WARN_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n",
261 Stack->Parameters.QueryDeviceText.DeviceTextType);
262 ASSERT(FALSE);
263 Status = STATUS_NOT_SUPPORTED;
264 }
265 }
266 break;
267 }
268 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0xd */
269 {
270 return ForwardIrpToAttachedFdoAndForget(DeviceObject, Irp);
271 }
272 case IRP_MN_QUERY_ID: /* 0x13 */
273 {
274 Status = SerenumPdoQueryId(DeviceObject, Irp, &Information);
275 break;
276 }
277 case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */
278 {
279 PPNP_BUS_INFORMATION BusInfo;
280 TRACE_(SERENUM, "IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
281
282 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), SERENUM_TAG);
283 if (!BusInfo)
284 Status = STATUS_INSUFFICIENT_RESOURCES;
285 else
286 {
287 memcpy(
288 &BusInfo->BusTypeGuid,
289 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
290 sizeof(BusInfo->BusTypeGuid));
291 BusInfo->LegacyBusType = PNPBus;
292 /* We're the only serial bus enumerator on the computer */
293 BusInfo->BusNumber = 0;
294 Information = (ULONG_PTR)BusInfo;
295 Status = STATUS_SUCCESS;
296 }
297 break;
298 }
299 default:
300 {
301 /* We can't forward request to the lower driver, because
302 * we are a Pdo, so we don't have lower driver... */
303 WARN_(SERENUM, "IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
304 ASSERT(FALSE);
305 Information = Irp->IoStatus.Information;
306 Status = Irp->IoStatus.Status;
307 }
308 }
309
310 Irp->IoStatus.Information = Information;
311 Irp->IoStatus.Status = Status;
312 IoCompleteRequest(Irp, IO_NO_INCREMENT);
313 return Status;
314 }