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