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