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