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