[PORTCLS]
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / undoc.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/api.cpp
5 * PURPOSE: Port api functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11
12 KSPIN_INTERFACE PinInterfaces[] =
13 {
14 {
15 {STATIC_KSINTERFACESETID_Standard},
16 KSINTERFACE_STANDARD_STREAMING,
17 0
18 },
19 {
20 {STATIC_KSINTERFACESETID_Standard},
21 KSINTERFACE_STANDARD_LOOPED_STREAMING,
22 0
23 }
24 };
25
26
27 NTSTATUS
28 NTAPI
29 KsoDispatchCreateWithGenericFactory(
30 LONG Unknown,
31 PIRP Irp)
32 {
33 UNIMPLEMENTED;
34 return STATUS_NOT_IMPLEMENTED;
35 }
36
37 IIrpTarget *
38 NTAPI
39 KsoGetIrpTargetFromFileObject(
40 PFILE_OBJECT FileObject)
41 {
42 PC_ASSERT(FileObject);
43
44 // IrpTarget is stored in FsContext
45 return (IIrpTarget*)FileObject->FsContext;
46 }
47
48 IIrpTarget *
49 NTAPI
50 KsoGetIrpTargetFromIrp(
51 PIRP Irp)
52 {
53 PKSOBJECT_CREATE_ITEM CreateItem;
54
55 // access the create item
56 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
57
58 // IIrpTarget is stored in Context member
59 return (IIrpTarget*)CreateItem->Context;
60 }
61
62 NTSTATUS
63 NTAPI
64 PcHandleEnableEventWithTable(
65 IN PIRP Irp,
66 IN PSUBDEVICE_DESCRIPTOR Descriptor)
67 {
68 // store descriptor
69 KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor;
70
71 // FIXME seh probing
72 return KsEnableEvent(Irp, Descriptor->EventSetCount, Descriptor->EventSet, NULL, KSEVENTS_NONE, NULL);
73 }
74
75 NTSTATUS
76 NTAPI
77 PcHandleDisableEventWithTable(
78 IN PIRP Irp,
79 IN PSUBDEVICE_DESCRIPTOR Descriptor)
80 {
81 // store descriptor
82 KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor;
83
84 // FIXME seh probing
85
86 return KsDisableEvent(Irp, Descriptor->EventList, KSEVENTS_SPINLOCK, (PVOID)Descriptor->EventListLock);
87 }
88
89
90 NTSTATUS
91 NTAPI
92 PcHandlePropertyWithTable(
93 IN PIRP Irp,
94 IN ULONG PropertySetCount,
95 IN PKSPROPERTY_SET PropertySet,
96 IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
97 {
98 NTSTATUS Status;
99 PIO_STACK_LOCATION IoStack;
100 PKSP_NODE Property;
101 PPCNODE_DESCRIPTOR Node;
102 PPCPROPERTY_ITEM PropertyItem;
103 ULONG Index;
104 LPGUID Buffer;
105 //PULONG Flags;
106 PPCPROPERTY_REQUEST PropertyRequest;
107
108 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
109
110 /* try first KsPropertyHandler */
111 Status = KsPropertyHandler(Irp, PropertySetCount, PropertySet);
112
113 // get current irp stack location
114 IoStack = IoGetCurrentIrpStackLocation(Irp);
115
116 // access property
117 Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
118
119 // check if this a GUID_NULL request
120 if (Status == STATUS_NOT_FOUND)
121 {
122 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE))
123 return Status;
124
125 // check if its a request for a topology node
126 if (IsEqualGUIDAligned(Property->Property.Set, GUID_NULL) && Property->Property.Id == 0 && Property->Property.Flags == (KSPROPERTY_TYPE_SETSUPPORT | KSPROPERTY_TYPE_TOPOLOGY))
127 {
128 if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
129 {
130 // request is out of bounds
131 Irp->IoStatus.Information = 0;
132 return STATUS_INVALID_PARAMETER;
133 }
134
135 Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
136
137 if (!Node->AutomationTable)
138 {
139 // request is out of bounds
140 Irp->IoStatus.Information = 0;
141 return STATUS_INVALID_PARAMETER;
142 }
143
144 PC_ASSERT(Node->AutomationTable);
145 PC_ASSERT(Node->AutomationTable->PropertyCount);
146 PC_ASSERT(Node->AutomationTable->PropertyItemSize);
147
148 Buffer = (LPGUID)AllocateItem(NonPagedPool, sizeof (GUID) * Node->AutomationTable->PropertyCount, TAG_PORTCLASS);
149 if (!Buffer)
150 return STATUS_INSUFFICIENT_RESOURCES;
151
152
153 ULONG Count = 0, SubIndex;
154 PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
155 for (Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
156 {
157 BOOL Found = FALSE;
158 for (SubIndex = 0; SubIndex < Count; Index++)
159 {
160 if (IsEqualGUIDAligned(Buffer[SubIndex], *PropertyItem->Set))
161 {
162 Found = TRUE;
163 break;
164 }
165 }
166 if (!Found)
167 {
168 RtlMoveMemory(&Buffer[Count], PropertyItem->Set, sizeof (GUID));
169 Count++;
170 }
171 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
172 }
173
174 Irp->IoStatus.Information = sizeof (GUID) * Count;
175 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof (GUID) * Count)
176 {
177 // buffer too small
178 FreeItem(Buffer, TAG_PORTCLASS);
179 return STATUS_MORE_ENTRIES;
180 }
181
182 RtlMoveMemory(Irp->UserBuffer, Buffer, sizeof (GUID) * Count);
183 FreeItem(Buffer, TAG_PORTCLASS);
184 return STATUS_SUCCESS;
185 }
186 else /*if (Property->Property.Flags == (KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY) ||
187 Property->Property.Flags == (KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY) ||
188 Property->Property.Flags == (KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY)) */
189 {
190 //UNICODE_STRING GuidString;
191
192 if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
193 {
194 // request is out of bounds
195 Irp->IoStatus.Information = 0;
196 return STATUS_INVALID_PARAMETER;
197 }
198
199 Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
200
201 if (!Node->AutomationTable)
202 {
203 // request is out of bounds
204 Irp->IoStatus.Information = 0;
205 return STATUS_NOT_FOUND;
206 }
207
208 PC_ASSERT(Node->AutomationTable);
209 PC_ASSERT(Node->AutomationTable->PropertyCount);
210 PC_ASSERT(Node->AutomationTable->PropertyItemSize);
211
212 PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
213
214 for(Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
215 {
216 if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Property.Set) && PropertyItem->Id == Property->Property.Id)
217 {
218 if (Property->Property.Flags & KSPROPERTY_TYPE_BASICSUPPORT)
219 {
220 if (!(PropertyItem->Flags & KSPROPERTY_TYPE_BASICSUPPORT))
221 {
222 PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG));
223 PULONG Flags = (PULONG)Irp->UserBuffer;
224
225 /* reset flags */
226 *Flags = 0;
227
228 if (PropertyItem->Flags & KSPROPERTY_TYPE_SET)
229 *Flags |= KSPROPERTY_TYPE_SET;
230
231 if (PropertyItem->Flags & KSPROPERTY_TYPE_GET)
232 *Flags |= KSPROPERTY_TYPE_GET;
233
234 Irp->IoStatus.Information = sizeof(ULONG);
235
236 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
237 {
238 /* get output buffer */
239 PKSPROPERTY_DESCRIPTION Description = (PKSPROPERTY_DESCRIPTION)Irp->UserBuffer;
240
241 /* store result */
242 Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
243 Description->PropTypeSet.Set = KSPROPTYPESETID_General;
244 Description->PropTypeSet.Id = 0;
245 Description->PropTypeSet.Flags = 0;
246 Description->MembersListCount = 0;
247 Description->Reserved = 0;
248
249 Irp->IoStatus.Information = sizeof(KSPROPERTY_DESCRIPTION);
250 }
251 return STATUS_SUCCESS;
252 }
253 }
254
255
256 PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
257 if (!PropertyRequest)
258 return STATUS_INSUFFICIENT_RESOURCES;
259
260 PC_ASSERT(SubDeviceDescriptor->UnknownMiniport);
261 PropertyRequest->MajorTarget = SubDeviceDescriptor->UnknownMiniport;
262 PropertyRequest->MinorTarget = SubDeviceDescriptor->UnknownStream;
263 PropertyRequest->Irp = Irp;
264 PropertyRequest->Node = Property->NodeId;
265 PropertyRequest->PropertyItem = PropertyItem;
266 PropertyRequest->Verb = Property->Property.Flags;
267 PropertyRequest->InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSNODEPROPERTY);
268 PropertyRequest->Instance = (PVOID)((ULONG_PTR)IoStack->Parameters.DeviceIoControl.Type3InputBuffer + sizeof(KSNODEPROPERTY));
269 PropertyRequest->ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
270 PropertyRequest->Value = Irp->UserBuffer;
271
272 Status = PropertyItem->Handler(PropertyRequest);
273
274 if (Status != STATUS_PENDING)
275 {
276 //DPRINT("Status %x ValueSize %u
277
278 Irp->IoStatus.Information = PropertyRequest->ValueSize;
279 ExFreePool(PropertyRequest);
280 }
281 #if 0
282 RtlStringFromGUID(Property->Property.Set, &GuidString);
283 DPRINT("Id %u Flags %x Set %S FlagsItem %x Status %x\n", Property->Property.Id, Property->Property.Flags, GuidString.Buffer, PropertyItem->Flags, Status);
284 RtlFreeUnicodeString(&GuidString);
285 #endif
286 return Status;
287 }
288 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
289 }
290 #if 0
291 RtlStringFromGUID(Property->Property.Set, &GuidString);
292 DPRINT("Id %u Flags %x Set %S Status %x\n", Property->Property.Id, Property->Property.Flags, GuidString.Buffer, Status);
293 RtlFreeUnicodeString(&GuidString);
294 #endif
295 }
296 }
297 return Status;
298 }
299
300 VOID
301 NTAPI
302 PcAcquireFormatResources(
303 LONG Unknown,
304 LONG Unknown2,
305 LONG Unknown3,
306 LONG Unknown4)
307 {
308 UNIMPLEMENTED;
309 }
310
311 NTSTATUS
312 PcAddToEventTable(
313 PVOID Ptr,
314 LONG Unknown2,
315 ULONG Length,
316 LONG Unknown3,
317 LONG Unknown4,
318 LONG Unknown5,
319 LONG Unknown6,
320 LONG Unknown7)
321 {
322 UNIMPLEMENTED;
323 return STATUS_NOT_IMPLEMENTED;
324 }
325
326 NTSTATUS
327 PcAddToPropertyTable(
328 PVOID Ptr,
329 LONG Unknown,
330 LONG Unknown2,
331 LONG Unknown3,
332 CHAR Unknown4)
333 {
334 UNIMPLEMENTED;
335 return STATUS_NOT_IMPLEMENTED;
336 }
337
338 NTSTATUS
339 PcCaptureFormat(
340 LONG Unknown,
341 LONG Unknown2,
342 LONG Unknown3,
343 LONG Unknown4)
344 {
345 UNIMPLEMENTED;
346 return STATUS_NOT_IMPLEMENTED;
347 }
348
349 VOID
350 DumpFilterDescriptor(
351 IN PPCFILTER_DESCRIPTOR FilterDescription)
352 {
353 ULONG Index;
354 PPCPROPERTY_ITEM PropertyItem;
355 UNICODE_STRING GuidString;
356
357 DPRINT("======================\n");
358 DPRINT("Descriptor Automation Table%p\n",FilterDescription->AutomationTable);
359
360 if (FilterDescription->AutomationTable)
361 {
362 DPRINT("FilterPropertiesCount %u FilterPropertySize %u Expected %u\n", FilterDescription->AutomationTable->PropertyCount, FilterDescription->AutomationTable->PropertyItemSize, sizeof(PCPROPERTY_ITEM));
363 if (FilterDescription->AutomationTable->PropertyCount)
364 {
365 PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
366
367 for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
368 {
369 RtlStringFromGUID(*PropertyItem->Set, &GuidString);
370 DPRINT("Index %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
371
372 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
373 }
374 }
375 }
376
377
378 DPRINT("======================\n");
379 }
380
381 NTSTATUS
382 NTAPI
383 PcCreateSubdeviceDescriptor(
384 OUT SUBDEVICE_DESCRIPTOR ** OutSubdeviceDescriptor,
385 IN ULONG InterfaceCount,
386 IN GUID * InterfaceGuids,
387 IN ULONG IdentifierCount,
388 IN KSIDENTIFIER *Identifier,
389 IN ULONG FilterPropertiesCount,
390 IN KSPROPERTY_SET * FilterProperties,
391 IN ULONG Unknown1,
392 IN ULONG Unknown2,
393 IN ULONG PinPropertiesCount,
394 IN KSPROPERTY_SET * PinProperties,
395 IN ULONG EventSetCount,
396 IN KSEVENT_SET * EventSet,
397 IN PPCFILTER_DESCRIPTOR FilterDescription)
398 {
399 SUBDEVICE_DESCRIPTOR * Descriptor;
400 ULONG Index;
401 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
402 PPCPIN_DESCRIPTOR SrcDescriptor;
403
404 Descriptor = (PSUBDEVICE_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS);
405 if (!Descriptor)
406 return STATUS_INSUFFICIENT_RESOURCES;
407
408 // initialize physical / symbolic link connection list
409 InitializeListHead(&Descriptor->SymbolicLinkList);
410 InitializeListHead(&Descriptor->PhysicalConnectionList);
411
412 Descriptor->Interfaces = (GUID*)AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS);
413 if (!Descriptor->Interfaces)
414 goto cleanup;
415
416 // copy interface guids
417 RtlCopyMemory(Descriptor->Interfaces, InterfaceGuids, sizeof(GUID) * InterfaceCount);
418 Descriptor->InterfaceCount = InterfaceCount;
419
420 if (FilterPropertiesCount)
421 {
422 /// FIXME
423 /// handle driver properties
424
425 //DumpFilterDescriptor(FilterDescription);
426
427 Descriptor->FilterPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
428 if (! Descriptor->FilterPropertySet)
429 goto cleanup;
430
431 Descriptor->FilterPropertySetCount = FilterPropertiesCount;
432 for(Index = 0; Index < FilterPropertiesCount; Index++)
433 {
434 RtlMoveMemory(&Descriptor->FilterPropertySet[Index], &FilterProperties[Index], sizeof(KSPROPERTY_SET));
435 }
436 }
437
438 Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
439 if (!Descriptor->Topology)
440 goto cleanup;
441
442 if (FilterDescription->ConnectionCount)
443 {
444 Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
445 if (!Descriptor->Topology->TopologyConnections)
446 goto cleanup;
447
448 RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR));
449 Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount;
450 }
451
452 if (FilterDescription->NodeCount)
453 {
454 Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
455 if (!Descriptor->Topology->TopologyNodes)
456 goto cleanup;
457
458 Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
459 if (!Descriptor->Topology->TopologyNodesNames)
460 goto cleanup;
461
462 for(Index = 0; Index < FilterDescription->NodeCount; Index++)
463 {
464 if (FilterDescription->Nodes[Index].Type)
465 {
466 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], FilterDescription->Nodes[Index].Type, sizeof(GUID));
467 }
468 if (FilterDescription->Nodes[Index].Name)
469 {
470 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], FilterDescription->Nodes[Index].Name, sizeof(GUID));
471 }
472 }
473 Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
474 }
475
476 if (FilterDescription->PinCount)
477 {
478 Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescription->PinCount, TAG_PORTCLASS);
479 if (!Descriptor->Factory.KsPinDescriptor)
480 goto cleanup;
481
482 Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
483 if (!Descriptor->Factory.Instances)
484 goto cleanup;
485
486 Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount;
487 Descriptor->Factory.PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR);
488
489 SrcDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins;
490 DPRINT("Size %u Expected %u Ex Size %u\n", FilterDescription->PinSize, sizeof(KSPIN_DESCRIPTOR), sizeof(KSPIN_DESCRIPTOR_EX));
491
492 // copy pin factories
493 for(Index = 0; Index < FilterDescription->PinCount; Index++)
494 {
495 RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
496
497 Descriptor->Factory.KsPinDescriptor[Index].Interfaces = PinInterfaces;
498 Descriptor->Factory.KsPinDescriptor[Index].InterfacesCount = sizeof(PinInterfaces) / sizeof(KSPIN_INTERFACE);
499
500 DPRINT("Index %u DataRangeCount %u\n", Index, SrcDescriptor->KsPinDescriptor.DataRangesCount);
501
502 Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;
503 Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = SrcDescriptor->MaxFilterInstanceCount;
504 Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = SrcDescriptor->MaxGlobalInstanceCount;
505 Descriptor->Factory.Instances[Index].MinFilterInstanceCount = SrcDescriptor->MinFilterInstanceCount;
506 SrcDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)SrcDescriptor + FilterDescription->PinSize);
507 }
508 }
509
510 Descriptor->DeviceDescriptor = FilterDescription;
511 *OutSubdeviceDescriptor = Descriptor;
512 return STATUS_SUCCESS;
513
514 cleanup:
515 if (Descriptor)
516 {
517 if (Descriptor->Interfaces)
518 FreeItem(Descriptor->Interfaces, TAG_PORTCLASS);
519
520 if (Descriptor->Factory.KsPinDescriptor)
521 FreeItem(Descriptor->Factory.KsPinDescriptor, TAG_PORTCLASS);
522
523 FreeItem(Descriptor, TAG_PORTCLASS);
524 }
525 return Status;
526 }
527
528 NTSTATUS
529 NTAPI
530 PcValidateConnectRequest(
531 IN PIRP Irp,
532 IN KSPIN_FACTORY * Factory,
533 OUT PKSPIN_CONNECT * Connect)
534 {
535 return KsValidateConnectRequest(Irp, Factory->PinDescriptorCount, Factory->KsPinDescriptor, Connect);
536 }
537