Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / win32ss / drivers / videoprt / child.c
1 /*
2 * VideoPort driver
3 *
4 * Copyright (C) 2012 ReactOS Team
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #include "videoprt.h"
23
24 /* PRIVATE FUNCTIONS **********************************************************/
25
26 BOOLEAN
27 NTAPI
28 IntVideoPortGetMonitorId(
29 IN PVIDEO_PORT_CHILD_EXTENSION ChildExtension,
30 IN OUT PWCHAR Buffer)
31 {
32 USHORT Manufacturer, Model;
33 UNICODE_STRING UnicodeModelStr;
34
35 /* This must be valid to call this function */
36 ASSERT(ChildExtension->EdidValid);
37
38 /* 3 letters 5-bit ANSI manufacturer code (big endian) */
39 Manufacturer = *(PUSHORT)(&ChildExtension->ChildDescriptor[8]);
40
41 /* Letters encoded as A=1 to Z=26 */
42 Buffer[0] = (WCHAR)((Manufacturer & 0x7C00) + 'A' - 1);
43 Buffer[1] = (WCHAR)((Manufacturer & 0x03E0) + 'A' - 1);
44 Buffer[2] = (WCHAR)((Manufacturer & 0x001F) + 'A' - 1);
45
46 /* Model number (16-bit little endian) */
47 Model = *(PUSHORT)(&ChildExtension->ChildDescriptor[10]);
48
49 /* Use Rtl helper for conversion */
50 UnicodeModelStr.Buffer = &Buffer[3];
51 UnicodeModelStr.Length = 0;
52 UnicodeModelStr.MaximumLength = 4 * sizeof(WCHAR);
53 RtlIntegerToUnicodeString(Model, 16, &UnicodeModelStr);
54
55 /* Terminate it */
56 Buffer[7] = UNICODE_NULL;
57
58 /* And we're done */
59 return TRUE;
60 }
61
62 NTSTATUS NTAPI
63 IntVideoPortChildQueryId(
64 IN PVIDEO_PORT_CHILD_EXTENSION ChildExtension,
65 IN PIRP Irp,
66 IN PIO_STACK_LOCATION IrpSp)
67 {
68 PWCHAR Buffer = NULL, StaticBuffer;
69 UNICODE_STRING UnicodeStr;
70
71 switch (IrpSp->Parameters.QueryId.IdType)
72 {
73 case BusQueryDeviceID:
74 switch (ChildExtension->ChildType)
75 {
76 case Monitor:
77 if (ChildExtension->EdidValid)
78 {
79 StaticBuffer = L"DISPLAY\\";
80 Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 8) * sizeof(WCHAR));
81 if (!Buffer) return STATUS_NO_MEMORY;
82
83 /* Write the static portion */
84 RtlCopyMemory(Buffer, StaticBuffer, wcslen(StaticBuffer) * sizeof(WCHAR));
85
86 /* Add the dynamic portion */
87 IntVideoPortGetMonitorId(ChildExtension,
88 &Buffer[wcslen(StaticBuffer)]);
89 }
90 else
91 {
92 StaticBuffer = L"DISPLAY\\Default_Monitor";
93 Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
94 if (!Buffer) return STATUS_NO_MEMORY;
95
96 /* Copy the default id */
97 RtlCopyMemory(Buffer, StaticBuffer, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
98 }
99 break;
100 default:
101 ASSERT(FALSE);
102 break;
103 }
104 break;
105 case BusQueryInstanceID:
106 Buffer = ExAllocatePool(PagedPool, 5 * sizeof(WCHAR));
107 if (!Buffer) return STATUS_NO_MEMORY;
108
109 UnicodeStr.Buffer = Buffer;
110 UnicodeStr.Length = 0;
111 UnicodeStr.MaximumLength = 4 * sizeof(WCHAR);
112 RtlIntegerToUnicodeString(ChildExtension->ChildId, 16, &UnicodeStr);
113 break;
114 case BusQueryHardwareIDs:
115 switch (ChildExtension->ChildType)
116 {
117 case Monitor:
118 if (ChildExtension->EdidValid)
119 {
120 StaticBuffer = L"MONITOR\\";
121 Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 9) * sizeof(WCHAR));
122 if (!Buffer) return STATUS_NO_MEMORY;
123
124 /* Write the static portion */
125 RtlCopyMemory(Buffer, StaticBuffer, wcslen(StaticBuffer) * sizeof(WCHAR));
126
127 /* Add the dynamic portion */
128 IntVideoPortGetMonitorId(ChildExtension,
129 &Buffer[wcslen(StaticBuffer)]);
130
131 /* Add the second null termination char */
132 Buffer[wcslen(StaticBuffer) + 8] = UNICODE_NULL;
133 }
134 else
135 {
136 StaticBuffer = L"MONITOR\\Default_Monitor";
137 Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 2) * sizeof(WCHAR));
138 if (!Buffer) return STATUS_NO_MEMORY;
139
140 /* Copy the default id */
141 RtlCopyMemory(Buffer, StaticBuffer, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
142
143 /* Add the second null terminator */
144 Buffer[wcslen(StaticBuffer) + 1] = UNICODE_NULL;
145 }
146 break;
147 default:
148 ASSERT(FALSE);
149 break;
150 }
151 break;
152 case BusQueryCompatibleIDs:
153 switch (ChildExtension->ChildType)
154 {
155 case Monitor:
156 if (ChildExtension->EdidValid)
157 {
158 StaticBuffer = L"*PNP09FF";
159 Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 2) * sizeof(WCHAR));
160 if (!Buffer) return STATUS_NO_MEMORY;
161
162 RtlCopyMemory(Buffer, StaticBuffer, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
163
164 Buffer[wcslen(StaticBuffer)+1] = UNICODE_NULL;
165 }
166 else
167 {
168 /* No PNP ID for non-PnP monitors */
169 return Irp->IoStatus.Status;
170 }
171 break;
172 default:
173 ASSERT(FALSE);
174 break;
175 }
176 break;
177 default:
178 return Irp->IoStatus.Status;
179 }
180
181 INFO_(VIDEOPRT, "Reporting ID: %S\n", Buffer);
182 Irp->IoStatus.Information = (ULONG_PTR)Buffer;
183
184 return STATUS_SUCCESS;
185 }
186
187 NTSTATUS NTAPI
188 IntVideoPortChildQueryText(
189 IN PVIDEO_PORT_CHILD_EXTENSION ChildExtension,
190 IN PIRP Irp,
191 IN PIO_STACK_LOCATION IrpSp)
192 {
193 PWCHAR Buffer, StaticBuffer;
194
195 if (IrpSp->Parameters.QueryDeviceText.DeviceTextType != DeviceTextDescription)
196 return Irp->IoStatus.Status;
197
198 switch (ChildExtension->ChildType)
199 {
200 case Monitor:
201 /* FIXME: We can return a better description I think */
202 StaticBuffer = L"Monitor";
203 break;
204
205 case VideoChip:
206 /* FIXME: No idea what we return here */
207 StaticBuffer = L"Video chip";
208 break;
209
210 default: /* Other */
211 StaticBuffer = L"Other device";
212 break;
213 }
214
215 Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
216 if (!Buffer) return STATUS_NO_MEMORY;
217
218 RtlCopyMemory(Buffer, StaticBuffer, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
219
220 INFO_(VIDEOPRT, "Reporting description: %S\n", Buffer);
221 Irp->IoStatus.Information = (ULONG_PTR)Buffer;
222
223 return STATUS_SUCCESS;
224 }
225
226 NTSTATUS NTAPI
227 IntVideoPortChildQueryRelations(
228 IN PVIDEO_PORT_CHILD_EXTENSION ChildExtension,
229 IN PIRP Irp,
230 IN PIO_STACK_LOCATION IrpSp)
231 {
232 PDEVICE_RELATIONS DeviceRelations;
233
234 if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
235 {
236 WARN_(VIDEOPRT, "Unsupported device relations type\n");
237 return Irp->IoStatus.Status;
238 }
239
240 DeviceRelations = ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS));
241 if (!DeviceRelations) return STATUS_NO_MEMORY;
242
243 DeviceRelations->Count = 1;
244 DeviceRelations->Objects[0] = ChildExtension->PhysicalDeviceObject;
245
246 ObReferenceObject(DeviceRelations->Objects[0]);
247
248 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
249
250 return STATUS_SUCCESS;
251 }
252
253 NTSTATUS NTAPI
254 IntVideoPortChildQueryCapabilities(
255 IN PVIDEO_PORT_CHILD_EXTENSION ChildExtension,
256 IN PIRP Irp,
257 IN PIO_STACK_LOCATION IrpSp)
258 {
259 PDEVICE_CAPABILITIES DeviceCaps = IrpSp->Parameters.DeviceCapabilities.Capabilities;
260 ULONG i;
261
262 /* Set some values */
263 DeviceCaps->LockSupported = FALSE;
264 DeviceCaps->EjectSupported = FALSE;
265 DeviceCaps->DockDevice = FALSE;
266 DeviceCaps->UniqueID = FALSE;
267 DeviceCaps->RawDeviceOK = FALSE;
268 DeviceCaps->WakeFromD0 = FALSE;
269 DeviceCaps->WakeFromD1 = FALSE;
270 DeviceCaps->WakeFromD2 = FALSE;
271 DeviceCaps->WakeFromD3 = FALSE;
272 DeviceCaps->HardwareDisabled = FALSE;
273 DeviceCaps->NoDisplayInUI = FALSE;
274
275 /* Address and UI number are set by default */
276
277 DeviceCaps->DeviceState[PowerSystemWorking] = PowerDeviceD0;
278 for (i = 1; i < POWER_SYSTEM_MAXIMUM; i++)
279 {
280 DeviceCaps->DeviceState[i] = PowerDeviceD3;
281 }
282
283 DeviceCaps->SystemWake = PowerSystemUnspecified;
284 DeviceCaps->DeviceWake = PowerDeviceUnspecified;
285
286 /* FIXME: Device power states */
287 DeviceCaps->DeviceD1 = FALSE;
288 DeviceCaps->DeviceD2 = FALSE;
289 DeviceCaps->D1Latency = 0;
290 DeviceCaps->D2Latency = 0;
291 DeviceCaps->D3Latency = 0;
292
293 switch (ChildExtension->ChildType)
294 {
295 case VideoChip:
296 /* FIXME: Copy capabilities from parent */
297 ASSERT(FALSE);
298 break;
299
300 case NonPrimaryChip: /* Reserved */
301 ASSERT(FALSE);
302 break;
303
304 case Monitor:
305 DeviceCaps->SilentInstall = TRUE;
306 DeviceCaps->Removable = TRUE;
307 DeviceCaps->SurpriseRemovalOK = TRUE;
308 break;
309
310 default: /* Other */
311 DeviceCaps->SilentInstall = FALSE;
312 DeviceCaps->Removable = FALSE;
313 DeviceCaps->SurpriseRemovalOK = FALSE;
314 break;
315 }
316
317 return STATUS_SUCCESS;
318 }
319
320 NTSTATUS NTAPI
321 IntVideoPortDispatchPdoPnp(
322 IN PDEVICE_OBJECT DeviceObject,
323 IN PIRP Irp)
324 {
325 PIO_STACK_LOCATION IrpSp;
326 NTSTATUS Status = Irp->IoStatus.Status;
327
328 IrpSp = IoGetCurrentIrpStackLocation(Irp);
329
330 switch (IrpSp->MinorFunction)
331 {
332 case IRP_MN_START_DEVICE:
333 case IRP_MN_STOP_DEVICE:
334 /* Nothing to do */
335 Status = STATUS_SUCCESS;
336 break;
337
338 case IRP_MN_QUERY_RESOURCES:
339 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
340 /* None (keep old status) */
341 break;
342
343 case IRP_MN_QUERY_ID:
344 /* Call our helper */
345 Status = IntVideoPortChildQueryId(DeviceObject->DeviceExtension,
346 Irp,
347 IrpSp);
348 break;
349
350 case IRP_MN_QUERY_CAPABILITIES:
351 /* Call our helper */
352 Status = IntVideoPortChildQueryCapabilities(DeviceObject->DeviceExtension,
353 Irp,
354 IrpSp);
355 break;
356
357 case IRP_MN_SURPRISE_REMOVAL:
358 case IRP_MN_QUERY_REMOVE_DEVICE:
359 Status = STATUS_SUCCESS;
360 break;
361
362 case IRP_MN_REMOVE_DEVICE:
363 Irp->IoStatus.Status = STATUS_SUCCESS;
364 IoCompleteRequest(Irp, IO_NO_INCREMENT);
365 IoDeleteDevice(DeviceObject);
366 return STATUS_SUCCESS;
367
368 case IRP_MN_QUERY_DEVICE_RELATIONS:
369 /* Call our helper */
370 Status = IntVideoPortChildQueryRelations(DeviceObject->DeviceExtension,
371 Irp,
372 IrpSp);
373 break;
374
375 case IRP_MN_QUERY_DEVICE_TEXT:
376 /* Call our helper */
377 Status = IntVideoPortChildQueryText(DeviceObject->DeviceExtension,
378 Irp,
379 IrpSp);
380 break;
381
382 default:
383 break;
384 }
385
386 Irp->IoStatus.Status = Status;
387
388 IoCompleteRequest(Irp, IO_NO_INCREMENT);
389
390 return Status;
391 }