- Remove dead code
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / pin_wavecyclic.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
5 * PURPOSE: WaveCyclic IRP Audio Pin
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.h"
10
11 typedef struct
12 {
13 IPortPinWaveCyclicVtbl *lpVtbl;
14 IServiceSinkVtbl *lpVtblServiceSink;
15
16 LONG ref;
17 IPortWaveCyclic * Port;
18 IPortFilterWaveCyclic * Filter;
19 KSPIN_DESCRIPTOR * KsPinDescriptor;
20 PMINIPORTWAVECYCLIC Miniport;
21 PSERVICEGROUP ServiceGroup;
22 PDMACHANNEL DmaChannel;
23 PMINIPORTWAVECYCLICSTREAM Stream;
24 KSSTATE State;
25 PKSDATAFORMAT Format;
26 KSPIN_CONNECT * ConnectDetails;
27
28 PVOID CommonBuffer;
29 ULONG CommonBufferSize;
30 ULONG CommonBufferOffset;
31
32 IIrpQueue * IrpQueue;
33
34 ULONG FrameSize;
35 BOOL Capture;
36
37 ULONG TotalPackets;
38 ULONG StopCount;
39
40 ULONG Delay;
41 }IPortPinWaveCyclicImpl;
42
43
44 typedef struct
45 {
46 IPortPinWaveCyclicImpl *Pin;
47 PIO_WORKITEM WorkItem;
48 KSSTATE State;
49 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
50
51 NTSTATUS
52 NTAPI
53 IPortWaveCyclic_fnProcessNewIrp(
54 IPortPinWaveCyclicImpl * This);
55
56 //==================================================================================================================================
57
58 static
59 NTSTATUS
60 NTAPI
61 IServiceSink_fnQueryInterface(
62 IServiceSink* iface,
63 IN REFIID refiid,
64 OUT PVOID* Output)
65 {
66 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortPinWaveCyclicImpl, lpVtblServiceSink);
67
68 DPRINT("IServiceSink_fnQueryInterface entered\n");
69
70 if (IsEqualGUIDAligned(refiid, &IID_IServiceSink) ||
71 IsEqualGUIDAligned(refiid, &IID_IUnknown))
72 {
73 *Output = &This->lpVtblServiceSink;
74 InterlockedIncrement(&This->ref);
75 return STATUS_SUCCESS;
76 }
77 return STATUS_UNSUCCESSFUL;
78 }
79
80 static
81 ULONG
82 NTAPI
83 IServiceSink_fnAddRef(
84 IServiceSink* iface)
85 {
86 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortPinWaveCyclicImpl, lpVtblServiceSink);
87 DPRINT("IServiceSink_fnAddRef entered\n");
88
89 return InterlockedIncrement(&This->ref);
90 }
91
92 static
93 ULONG
94 NTAPI
95 IServiceSink_fnRelease(
96 IServiceSink* iface)
97 {
98 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortPinWaveCyclicImpl, lpVtblServiceSink);
99
100 InterlockedDecrement(&This->ref);
101
102 DPRINT("IServiceSink_fnRelease entered %u\n", This->ref);
103
104 if (This->ref == 0)
105 {
106 FreeItem(This, TAG_PORTCLASS);
107 return 0;
108 }
109 /* Return new reference count */
110 return This->ref;
111 }
112
113 static
114 VOID
115 UpdateCommonBuffer(
116 IPortPinWaveCyclicImpl * This,
117 ULONG Position,
118 ULONG MaxTransferCount)
119 {
120 ULONG BufferLength;
121 ULONG BytesToCopy;
122 ULONG BufferSize;
123 PUCHAR Buffer;
124 NTSTATUS Status;
125
126 BufferLength = Position - This->CommonBufferOffset;
127 BufferLength = min(BufferLength, MaxTransferCount);
128
129 while(BufferLength)
130 {
131 Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize);
132 if (!NT_SUCCESS(Status))
133 return;
134
135 BytesToCopy = min(BufferLength, BufferSize);
136
137 if (This->Capture)
138 {
139 This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel,
140 Buffer,
141 (PUCHAR)This->CommonBuffer + This->CommonBufferOffset,
142 BytesToCopy);
143 }
144 else
145 {
146 This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel,
147 (PUCHAR)This->CommonBuffer + This->CommonBufferOffset,
148 Buffer,
149 BytesToCopy);
150 }
151
152 This->IrpQueue->lpVtbl->UpdateMapping(This->IrpQueue, BytesToCopy);
153 This->CommonBufferOffset += BytesToCopy;
154
155 BufferLength = Position - This->CommonBufferOffset;
156 }
157 }
158
159 static
160 VOID
161 UpdateCommonBufferOverlap(
162 IPortPinWaveCyclicImpl * This,
163 ULONG Position,
164 ULONG MaxTransferCount)
165 {
166 ULONG BufferLength, Length, Gap;
167 ULONG BytesToCopy;
168 ULONG BufferSize;
169 PUCHAR Buffer;
170 NTSTATUS Status;
171
172
173 BufferLength = Gap = This->CommonBufferSize - This->CommonBufferOffset;
174 BufferLength = Length = min(BufferLength, MaxTransferCount);
175 while(BufferLength)
176 {
177 Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize);
178 if (!NT_SUCCESS(Status))
179 return;
180
181 BytesToCopy = min(BufferLength, BufferSize);
182
183 if (This->Capture)
184 {
185 This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel,
186 Buffer,
187 (PUCHAR)This->CommonBuffer + This->CommonBufferOffset,
188 BytesToCopy);
189 }
190 else
191 {
192 This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel,
193 (PUCHAR)This->CommonBuffer + This->CommonBufferOffset,
194 Buffer,
195 BytesToCopy);
196 }
197
198 This->IrpQueue->lpVtbl->UpdateMapping(This->IrpQueue, BytesToCopy);
199 This->CommonBufferOffset += BytesToCopy;
200
201 BufferLength = This->CommonBufferSize - This->CommonBufferOffset;
202 }
203
204 if (Gap == Length)
205 {
206 This->CommonBufferOffset = 0;
207
208 MaxTransferCount -= Length;
209
210 if (MaxTransferCount)
211 {
212 UpdateCommonBuffer(This, Position, MaxTransferCount);
213 }
214 }
215 }
216
217 VOID
218 NTAPI
219 SetStreamWorkerRoutine(
220 IN PDEVICE_OBJECT DeviceObject,
221 IN PVOID Context)
222 {
223 IPortPinWaveCyclicImpl * This;
224 PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
225 KSSTATE State;
226 ULONG MinimumDataThreshold;
227 ULONG MaximumDataThreshold;
228
229 This = Ctx->Pin;
230 State = Ctx->State;
231
232 IoFreeWorkItem(Ctx->WorkItem);
233 FreeItem(Ctx, TAG_PORTCLASS);
234
235 /* Has the audio stream resumed? */
236 if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) && State == KSSTATE_STOP)
237 return;
238
239 /* Has the audio state already been set? */
240 if (This->State == State)
241 return;
242
243 /* Set the state */
244 if (NT_SUCCESS(This->Stream->lpVtbl->SetState(This->Stream, State)))
245 {
246 /* Set internal state */
247 This->State = State;
248
249 if (This->State == KSSTATE_STOP)
250 {
251 /* reset start stream */
252 This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue); //FIX function name
253
254 /* increase stop counter */
255 This->StopCount++;
256 /* get current data threshold */
257 MinimumDataThreshold = This->IrpQueue->lpVtbl->GetMinimumDataThreshold(This->IrpQueue);
258 /* get maximum data threshold */
259 MaximumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)This->Format)->WaveFormatEx.nAvgBytesPerSec;
260 /* increase minimum data threshold by a third sec */
261 MinimumDataThreshold += This->FrameSize * 10;
262
263 /* assure it has not exceeded */
264 MinimumDataThreshold = min(MinimumDataThreshold, MaximumDataThreshold);
265 /* store minimum data threshold */
266 This->IrpQueue->lpVtbl->SetMinimumDataThreshold(This->IrpQueue, MinimumDataThreshold);
267
268 DPRINT1("Stopping TotalPackets %u StopCount %u\n", This->TotalPackets, This->StopCount);
269 }
270 if (This->State == KSSTATE_RUN)
271 {
272 DPRINT1("State RUN %x MinAvailable %u CommonBufferSize %u Offset %u\n", State, This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue), This->CommonBufferSize, This->CommonBufferOffset);
273 }
274 }
275 }
276
277 VOID
278 NTAPI
279 SetStreamState(
280 IN IPortPinWaveCyclicImpl * This,
281 IN KSSTATE State)
282 {
283 PDEVICE_OBJECT DeviceObject;
284 PIO_WORKITEM WorkItem;
285 PSETSTREAM_CONTEXT Context;
286
287 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
288
289 /* Has the audio stream resumed? */
290 if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) && State == KSSTATE_STOP)
291 return;
292
293 /* Has the audio state already been set? */
294 if (This->State == State)
295 return;
296
297 /* Get device object */
298 DeviceObject = GetDeviceObject(This->Port);
299
300 /* allocate set state context */
301 Context = AllocateItem(NonPagedPool, sizeof(SETSTREAM_CONTEXT), TAG_PORTCLASS);
302
303 if (!Context)
304 return;
305
306 /* allocate work item */
307 WorkItem = IoAllocateWorkItem(DeviceObject);
308
309 if (!WorkItem)
310 {
311 ExFreePool(Context);
312 return;
313 }
314
315 Context->Pin = (PVOID)This;
316 Context->WorkItem = WorkItem;
317 Context->State = State;
318
319 /* queue the work item */
320 IoQueueWorkItem(WorkItem, SetStreamWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
321 }
322
323 static
324 VOID
325 NTAPI
326 IServiceSink_fnRequestService(
327 IServiceSink* iface)
328 {
329 ULONG Position;
330 NTSTATUS Status;
331 PUCHAR Buffer;
332 ULONG BufferSize;
333 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortPinWaveCyclicImpl, lpVtblServiceSink);
334
335 ASSERT_IRQL(DISPATCH_LEVEL);
336
337 Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize);
338 if (!NT_SUCCESS(Status))
339 {
340 //SetStreamState(This, KSSTATE_STOP);
341 return;
342 }
343
344 Status = This->Stream->lpVtbl->GetPosition(This->Stream, &Position);
345 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u\n", Position, Buffer, This->CommonBufferSize, BufferSize);
346
347 if (Position < This->CommonBufferOffset)
348 {
349 UpdateCommonBufferOverlap(This, Position, This->FrameSize);
350 }
351 else if (Position >= This->CommonBufferOffset)
352 {
353 UpdateCommonBuffer(This, Position, This->FrameSize);
354 }
355 }
356
357 static IServiceSinkVtbl vt_IServiceSink =
358 {
359 IServiceSink_fnQueryInterface,
360 IServiceSink_fnAddRef,
361 IServiceSink_fnRelease,
362 IServiceSink_fnRequestService
363 };
364
365 //==================================================================================================================================
366 /*
367 * @implemented
368 */
369 NTSTATUS
370 NTAPI
371 IPortPinWaveCyclic_fnQueryInterface(
372 IPortPinWaveCyclic* iface,
373 IN REFIID refiid,
374 OUT PVOID* Output)
375 {
376 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
377
378 if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
379 IsEqualGUIDAligned(refiid, &IID_IUnknown))
380 {
381 *Output = &This->lpVtbl;
382 InterlockedIncrement(&This->ref);
383 return STATUS_SUCCESS;
384 }
385
386 return STATUS_UNSUCCESSFUL;
387 }
388
389 /*
390 * @implemented
391 */
392 ULONG
393 NTAPI
394 IPortPinWaveCyclic_fnAddRef(
395 IPortPinWaveCyclic* iface)
396 {
397 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
398
399 return InterlockedIncrement(&This->ref);
400 }
401
402 /*
403 * @implemented
404 */
405 ULONG
406 NTAPI
407 IPortPinWaveCyclic_fnRelease(
408 IPortPinWaveCyclic* iface)
409 {
410 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
411
412 InterlockedDecrement(&This->ref);
413
414 if (This->ref == 0)
415 {
416 FreeItem(This, TAG_PORTCLASS);
417 return 0;
418 }
419 return This->ref;
420 }
421
422 /*
423 * @unimplemented
424 */
425 NTSTATUS
426 NTAPI
427 IPortPinWaveCyclic_fnNewIrpTarget(
428 IN IPortPinWaveCyclic* iface,
429 OUT struct IIrpTarget **OutTarget,
430 IN WCHAR * Name,
431 IN PUNKNOWN Unknown,
432 IN POOL_TYPE PoolType,
433 IN PDEVICE_OBJECT DeviceObject,
434 IN PIRP Irp,
435 IN KSOBJECT_CREATE *CreateObject)
436 {
437 UNIMPLEMENTED
438 return STATUS_UNSUCCESSFUL;
439 }
440
441 NTSTATUS
442 NTAPI
443 IPortPinWaveCyclic_HandleKsProperty(
444 IN IPortPinWaveCyclic * iface,
445 IN PIRP Irp)
446 {
447 PKSPROPERTY Property;
448 NTSTATUS Status;
449 UNICODE_STRING GuidString;
450 PIO_STACK_LOCATION IoStack;
451 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
452
453 IoStack = IoGetCurrentIrpStackLocation(Irp);
454
455 DPRINT("IPortPinWave_HandleKsProperty entered\n");
456
457 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
458 {
459 Irp->IoStatus.Information = 0;
460 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
461 IoCompleteRequest(Irp, IO_NO_INCREMENT);
462 return STATUS_INVALID_PARAMETER;
463 }
464
465 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
466
467 if (IsEqualGUIDAligned(&Property->Set, &GUID_NULL))
468 {
469 if (Property->Flags & KSPROPERTY_TYPE_SETSUPPORT)
470 {
471 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GUID))
472 {
473 /* buffer too small */
474 Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
475 Irp->IoStatus.Information = sizeof(GUID);
476 IoCompleteRequest(Irp, IO_NO_INCREMENT);
477
478 return STATUS_BUFFER_OVERFLOW;
479 }
480 /* FIXME copy guids
481 * KSPROPSETID_Audio when available
482 * KSPROPSETID_Sysaudio_Pin
483 */
484 RtlMoveMemory(Irp->UserBuffer, &KSPROPSETID_Connection, sizeof(GUID));
485
486 Irp->IoStatus.Status = STATUS_SUCCESS;
487 Irp->IoStatus.Information = sizeof(GUID);
488 IoCompleteRequest(Irp, IO_NO_INCREMENT);
489
490 return STATUS_SUCCESS;
491 }
492 }
493
494
495 if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Connection))
496 {
497 if (Property->Id == KSPROPERTY_CONNECTION_STATE)
498 {
499 PKSSTATE State = (PKSSTATE)Irp->UserBuffer;
500
501 ASSERT_IRQL(DISPATCH_LEVEL);
502 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSSTATE))
503 {
504 Irp->IoStatus.Information = sizeof(KSSTATE);
505 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
506 IoCompleteRequest(Irp, IO_NO_INCREMENT);
507 return STATUS_BUFFER_TOO_SMALL;
508 }
509
510 if (Property->Flags & KSPROPERTY_TYPE_SET)
511 {
512 Status = STATUS_UNSUCCESSFUL;
513 Irp->IoStatus.Information = 0;
514
515 if (This->Stream)
516 {
517 Status = This->Stream->lpVtbl->SetState(This->Stream, *State);
518
519 DPRINT1("Setting state %u %x\n", *State, Status);
520 if (NT_SUCCESS(Status))
521 {
522 This->State = *State;
523 }
524 }
525 Irp->IoStatus.Status = Status;
526 IoCompleteRequest(Irp, IO_NO_INCREMENT);
527 return Status;
528 }
529 else if (Property->Flags & KSPROPERTY_TYPE_GET)
530 {
531 *State = This->State;
532 Irp->IoStatus.Information = sizeof(KSSTATE);
533 Irp->IoStatus.Status = STATUS_SUCCESS;
534 IoCompleteRequest(Irp, IO_NO_INCREMENT);
535 return STATUS_SUCCESS;
536 }
537 }
538 else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT)
539 {
540 PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
541 if (Property->Flags & KSPROPERTY_TYPE_SET)
542 {
543 PKSDATAFORMAT NewDataFormat;
544 if (!RtlCompareMemory(DataFormat, This->Format, DataFormat->FormatSize))
545 {
546 Irp->IoStatus.Information = DataFormat->FormatSize;
547 Irp->IoStatus.Status = STATUS_SUCCESS;
548 IoCompleteRequest(Irp, IO_NO_INCREMENT);
549 return STATUS_SUCCESS;
550 }
551
552 NewDataFormat = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
553 if (!NewDataFormat)
554 {
555 Irp->IoStatus.Information = 0;
556 Irp->IoStatus.Status = STATUS_NO_MEMORY;
557 IoCompleteRequest(Irp, IO_NO_INCREMENT);
558 return STATUS_NO_MEMORY;
559 }
560 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
561
562 if (This->Stream)
563 {
564 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
565 ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
566 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO));
567 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM));
568 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
569
570 ASSERT(This->State == KSSTATE_STOP);
571 DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
572 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
573 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
574
575 Status = This->Stream->lpVtbl->SetFormat(This->Stream, NewDataFormat);
576 if (NT_SUCCESS(Status))
577 {
578 if (This->Format)
579 ExFreePoolWithTag(This->Format, TAG_PORTCLASS);
580
581 This->IrpQueue->lpVtbl->UpdateFormat(This->IrpQueue, (PKSDATAFORMAT)NewDataFormat);
582 This->Format = NewDataFormat;
583 Irp->IoStatus.Information = DataFormat->FormatSize;
584 Irp->IoStatus.Status = STATUS_SUCCESS;
585 IoCompleteRequest(Irp, IO_NO_INCREMENT);
586 return STATUS_SUCCESS;
587 }
588 }
589 DPRINT1("Failed to set format\n");
590 Irp->IoStatus.Information = 0;
591 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
592 IoCompleteRequest(Irp, IO_NO_INCREMENT);
593 return STATUS_UNSUCCESSFUL;
594 }
595 else if (Property->Flags & KSPROPERTY_TYPE_GET)
596 {
597 if (!This->Format)
598 {
599 DPRINT1("No format\n");
600 Irp->IoStatus.Information = 0;
601 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
602 IoCompleteRequest(Irp, IO_NO_INCREMENT);
603 return STATUS_UNSUCCESSFUL;
604 }
605 if (This->Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
606 {
607 Irp->IoStatus.Information = This->Format->FormatSize;
608 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
609 IoCompleteRequest(Irp, IO_NO_INCREMENT);
610 return STATUS_BUFFER_TOO_SMALL;
611 }
612
613 RtlMoveMemory(DataFormat, This->Format, This->Format->FormatSize);
614 Irp->IoStatus.Information = DataFormat->FormatSize;
615 Irp->IoStatus.Status = STATUS_SUCCESS;
616 IoCompleteRequest(Irp, IO_NO_INCREMENT);
617 return STATUS_SUCCESS;
618 }
619 }
620 else if (Property->Id == KSPROPERTY_CONNECTION_ALLOCATORFRAMING)
621 {
622 PKSALLOCATOR_FRAMING Framing = (PKSALLOCATOR_FRAMING)Irp->UserBuffer;
623
624 ASSERT_IRQL(DISPATCH_LEVEL);
625 /* Validate input buffer */
626 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSALLOCATOR_FRAMING))
627 {
628 Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING);
629 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
630 IoCompleteRequest(Irp, IO_NO_INCREMENT);
631 return STATUS_BUFFER_TOO_SMALL;
632 }
633 /* Clear frame structure */
634 RtlZeroMemory(Framing, sizeof(KSALLOCATOR_FRAMING));
635 /* store requested frame size */
636 Framing->FrameSize = This->FrameSize;
637 /* FIXME fill in struct */
638
639 Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING);
640 Irp->IoStatus.Status = STATUS_SUCCESS;
641 IoCompleteRequest(Irp, IO_NO_INCREMENT);
642 return STATUS_SUCCESS;
643 }
644 }
645
646 RtlStringFromGUID(&Property->Set, &GuidString);
647 DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
648 RtlFreeUnicodeString(&GuidString);
649
650 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
651 Irp->IoStatus.Information = 0;
652 IoCompleteRequest(Irp, IO_NO_INCREMENT);
653 return STATUS_NOT_IMPLEMENTED;
654 }
655
656 NTSTATUS
657 NTAPI
658 IPortPinWaveCyclic_HandleKsStream(
659 IN IPortPinWaveCyclic * iface,
660 IN PIRP Irp)
661 {
662 NTSTATUS Status;
663 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
664
665 InterlockedIncrement((PLONG)&This->TotalPackets);
666
667 DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u Pre %u Post %u State %x MinData %u\n", This->TotalPackets, This->State, This->IrpQueue->lpVtbl->NumData(This->IrpQueue));
668
669 Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, NULL, 0, Irp);
670
671 return STATUS_PENDING;
672 }
673
674 /*
675 * @unimplemented
676 */
677 NTSTATUS
678 NTAPI
679 IPortPinWaveCyclic_fnDeviceIoControl(
680 IN IPortPinWaveCyclic* iface,
681 IN PDEVICE_OBJECT DeviceObject,
682 IN PIRP Irp)
683 {
684 PIO_STACK_LOCATION IoStack;
685
686 IoStack = IoGetCurrentIrpStackLocation(Irp);
687
688
689 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
690 {
691 return IPortPinWaveCyclic_HandleKsProperty(iface, Irp);
692 }
693 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
694 {
695 /// FIXME
696 /// handle enable event
697 }
698 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
699 {
700 /// FIXME
701 /// handle disable event
702 }
703 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
704 {
705 /// FIXME
706 /// handle reset state
707 }
708 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
709 {
710 return IPortPinWaveCyclic_HandleKsStream(iface, Irp);
711 }
712 else
713 {
714 return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
715 }
716
717 UNIMPLEMENTED
718
719 Irp->IoStatus.Information = 0;
720 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
721 IoCompleteRequest(Irp, IO_NO_INCREMENT);
722
723 return STATUS_UNSUCCESSFUL;
724 }
725
726 /*
727 * @implemented
728 */
729 NTSTATUS
730 NTAPI
731 IPortPinWaveCyclic_fnRead(
732 IN IPortPinWaveCyclic* iface,
733 IN PDEVICE_OBJECT DeviceObject,
734 IN PIRP Irp)
735 {
736 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
737 }
738
739 /*
740 * @implemented
741 */
742 NTSTATUS
743 NTAPI
744 IPortPinWaveCyclic_fnWrite(
745 IN IPortPinWaveCyclic* iface,
746 IN PDEVICE_OBJECT DeviceObject,
747 IN PIRP Irp)
748 {
749 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
750 }
751
752 /*
753 * @implemented
754 */
755 NTSTATUS
756 NTAPI
757 IPortPinWaveCyclic_fnFlush(
758 IN IPortPinWaveCyclic* iface,
759 IN PDEVICE_OBJECT DeviceObject,
760 IN PIRP Irp)
761 {
762 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
763 }
764
765 VOID
766 NTAPI
767 CloseStreamRoutine(
768 IN PDEVICE_OBJECT DeviceObject,
769 IN PVOID Context)
770 {
771 PMINIPORTWAVECYCLICSTREAM Stream;
772 IPortPinWaveCyclicImpl * This;
773 NTSTATUS Status;
774 PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
775
776 This = (IPortPinWaveCyclicImpl*)Ctx->Pin;
777
778 if (This->State != KSSTATE_STOP)
779 {
780 /* stop stream in case it hasn't been */
781 Status = This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
782 if (!NT_SUCCESS(Status))
783 DPRINT1("Warning: failed to stop stream with %x\n", Status);
784
785 This->State = KSSTATE_STOP;
786 }
787
788 if (This->Format)
789 {
790 /* free format */
791 ExFreePool(This->Format);
792 This->Format = NULL;
793 }
794
795 if (This->IrpQueue)
796 {
797 This->IrpQueue->lpVtbl->Release(This->IrpQueue);
798 }
799
800 /* complete the irp */
801 Ctx->Irp->IoStatus.Information = 0;
802 Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
803 IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
804
805 /* free the work item */
806 IoFreeWorkItem(Ctx->WorkItem);
807
808 /* free work item ctx */
809 FreeItem(Ctx, TAG_PORTCLASS);
810
811 /* release reference to port driver */
812 This->Port->lpVtbl->Release(This->Port);
813
814 /* release reference to filter instance */
815 This->Filter->lpVtbl->Release(This->Filter);
816
817 if (This->Stream)
818 {
819 Stream = This->Stream;
820 This->Stream = NULL;
821 This->Filter->lpVtbl->FreePin(This->Filter, (IPortPinWaveCyclic*)This);
822 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
823 Stream->lpVtbl->Release(Stream);
824 }
825 }
826
827 /*
828 * @implemented
829 */
830 NTSTATUS
831 NTAPI
832 IPortPinWaveCyclic_fnClose(
833 IN IPortPinWaveCyclic* iface,
834 IN PDEVICE_OBJECT DeviceObject,
835 IN PIRP Irp)
836 {
837 PCLOSESTREAM_CONTEXT Ctx;
838 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
839
840 if (This->Stream)
841 {
842 /* allocate a close context */
843 Ctx = AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
844 if (!Ctx)
845 {
846 DPRINT1("Failed to allocate stream context\n");
847 goto cleanup;
848 }
849 /* allocate work context */
850 Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
851 if (!Ctx->WorkItem)
852 {
853 DPRINT1("Failed to allocate work item\n");
854 goto cleanup;
855 }
856 /* setup the close context */
857 Ctx->Irp = Irp;
858 Ctx->Pin = (PVOID)This;
859
860 IoMarkIrpPending(Irp);
861 Irp->IoStatus.Information = 0;
862 Irp->IoStatus.Status = STATUS_PENDING;
863
864 /* remove member from service group */
865 This->ServiceGroup->lpVtbl->RemoveMember(This->ServiceGroup, (PSERVICESINK)&This->lpVtblServiceSink);
866
867 /* defer work item */
868 IoQueueWorkItem(Ctx->WorkItem, CloseStreamRoutine, DelayedWorkQueue, (PVOID)Ctx);
869 /* Return result */
870 return STATUS_PENDING;
871 }
872
873 Irp->IoStatus.Information = 0;
874 Irp->IoStatus.Status = STATUS_SUCCESS;
875 IoCompleteRequest(Irp, IO_NO_INCREMENT);
876
877 return STATUS_SUCCESS;
878
879 cleanup:
880
881 if (Ctx)
882 FreeItem(Ctx, TAG_PORTCLASS);
883
884 Irp->IoStatus.Information = 0;
885 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
886 IoCompleteRequest(Irp, IO_NO_INCREMENT);
887 return STATUS_UNSUCCESSFUL;
888
889 }
890
891 /*
892 * @implemented
893 */
894 NTSTATUS
895 NTAPI
896 IPortPinWaveCyclic_fnQuerySecurity(
897 IN IPortPinWaveCyclic* iface,
898 IN PDEVICE_OBJECT DeviceObject,
899 IN PIRP Irp)
900 {
901 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
902 }
903
904 /*
905 * @implemented
906 */
907 NTSTATUS
908 NTAPI
909 IPortPinWaveCyclic_fnSetSecurity(
910 IN IPortPinWaveCyclic* iface,
911 IN PDEVICE_OBJECT DeviceObject,
912 IN PIRP Irp)
913 {
914 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
915 }
916
917 /*
918 * @implemented
919 */
920 BOOLEAN
921 NTAPI
922 IPortPinWaveCyclic_fnFastDeviceIoControl(
923 IN IPortPinWaveCyclic* iface,
924 IN PFILE_OBJECT FileObject,
925 IN BOOLEAN Wait,
926 IN PVOID InputBuffer,
927 IN ULONG InputBufferLength,
928 OUT PVOID OutputBuffer,
929 IN ULONG OutputBufferLength,
930 IN ULONG IoControlCode,
931 OUT PIO_STATUS_BLOCK StatusBlock,
932 IN PDEVICE_OBJECT DeviceObject)
933 {
934 return KsDispatchFastIoDeviceControlFailure(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, StatusBlock, DeviceObject);
935 }
936
937 /*
938 * @implemented
939 */
940 BOOLEAN
941 NTAPI
942 IPortPinWaveCyclic_fnFastRead(
943 IN IPortPinWaveCyclic* iface,
944 IN PFILE_OBJECT FileObject,
945 IN PLARGE_INTEGER FileOffset,
946 IN ULONG Length,
947 IN BOOLEAN Wait,
948 IN ULONG LockKey,
949 IN PVOID Buffer,
950 OUT PIO_STATUS_BLOCK StatusBlock,
951 IN PDEVICE_OBJECT DeviceObject)
952 {
953 NTSTATUS Status;
954 PCONTEXT_WRITE Packet;
955 PIRP Irp;
956 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
957
958 /* HACK to be removed */
959
960 DPRINT("IPortPinWaveCyclic_fnFastRead entered\n");
961
962 Packet = (PCONTEXT_WRITE)Buffer;
963
964 Irp = Packet->Irp;
965 StatusBlock->Status = STATUS_PENDING;
966
967 Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
968
969 if (!NT_SUCCESS(Status))
970 return FALSE;
971
972 StatusBlock->Status = STATUS_PENDING;
973
974 return TRUE;
975 }
976
977 /*
978 * @implemented
979 */
980 BOOLEAN
981 NTAPI
982 IPortPinWaveCyclic_fnFastWrite(
983 IN IPortPinWaveCyclic* iface,
984 IN PFILE_OBJECT FileObject,
985 IN PLARGE_INTEGER FileOffset,
986 IN ULONG Length,
987 IN BOOLEAN Wait,
988 IN ULONG LockKey,
989 IN PVOID Buffer,
990 OUT PIO_STATUS_BLOCK StatusBlock,
991 IN PDEVICE_OBJECT DeviceObject)
992 {
993 NTSTATUS Status;
994 PCONTEXT_WRITE Packet;
995 PIRP Irp;
996 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
997
998 /* HACK to be removed */
999
1000 InterlockedIncrement((PLONG)&This->TotalPackets);
1001
1002 DPRINT("IPortPinWaveCyclic_fnFastWrite entered Total %u State %x MinData %u\n", This->TotalPackets, This->State, This->IrpQueue->lpVtbl->NumData(This->IrpQueue));
1003
1004 Packet = (PCONTEXT_WRITE)Buffer;
1005 Irp = Packet->Irp;
1006
1007 Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
1008
1009 if (!NT_SUCCESS(Status))
1010 return FALSE;
1011
1012 StatusBlock->Status = STATUS_PENDING;
1013
1014 return TRUE;
1015 }
1016
1017 /*
1018 * @implemented
1019 */
1020 NTSTATUS
1021 NTAPI
1022 IPortPinWaveCyclic_fnInit(
1023 IN IPortPinWaveCyclic* iface,
1024 IN PPORTWAVECYCLIC Port,
1025 IN PPORTFILTERWAVECYCLIC Filter,
1026 IN KSPIN_CONNECT * ConnectDetails,
1027 IN KSPIN_DESCRIPTOR * KsPinDescriptor)
1028 {
1029 NTSTATUS Status;
1030 PKSDATAFORMAT DataFormat;
1031 PDEVICE_OBJECT DeviceObject;
1032 BOOL Capture;
1033 PVOID SilenceBuffer;
1034 //IDrmAudioStream * DrmAudio = NULL;
1035
1036 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
1037
1038 This->KsPinDescriptor = KsPinDescriptor;
1039 This->ConnectDetails = ConnectDetails;
1040 This->Miniport = GetWaveCyclicMiniport(Port);
1041
1042 DeviceObject = GetDeviceObject(Port);
1043
1044 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
1045
1046 DPRINT("IPortPinWaveCyclic_fnInit entered\n");
1047
1048 This->Format = ExAllocatePoolWithTag(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
1049 if (!This->Format)
1050 return STATUS_INSUFFICIENT_RESOURCES;
1051
1052 RtlMoveMemory(This->Format, DataFormat, DataFormat->FormatSize);
1053
1054 Status = NewIrpQueue(&This->IrpQueue);
1055 if (!NT_SUCCESS(Status))
1056 return Status;
1057
1058 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
1059 {
1060 Capture = FALSE;
1061 }
1062 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
1063 {
1064 Capture = TRUE;
1065 }
1066 else
1067 {
1068 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
1069 KeBugCheck(0);
1070 }
1071
1072
1073 Status = This->Miniport->lpVtbl->NewStream(This->Miniport,
1074 &This->Stream,
1075 NULL,
1076 NonPagedPool,
1077 ConnectDetails->PinId,
1078 Capture,
1079 This->Format,
1080 &This->DmaChannel,
1081 &This->ServiceGroup);
1082 #if 0
1083 Status = This->Stream->lpVtbl->QueryInterface(This->Stream, &IID_IDrmAudioStream, (PVOID*)&DrmAudio);
1084 if (NT_SUCCESS(Status))
1085 {
1086 DRMRIGHTS DrmRights;
1087 DPRINT1("Got IID_IDrmAudioStream interface %p\n", DrmAudio);
1088
1089 DrmRights.CopyProtect = FALSE;
1090 DrmRights.Reserved = 0;
1091 DrmRights.DigitalOutputDisable = FALSE;
1092
1093 Status = DrmAudio->lpVtbl->SetContentId(DrmAudio, 1, &DrmRights);
1094 DPRINT("Status %x\n", Status);
1095 }
1096 #endif
1097
1098 DPRINT("IPortPinWaveCyclic_fnInit Status %x\n", Status);
1099
1100 if (!NT_SUCCESS(Status))
1101 return Status;
1102
1103 Status = This->ServiceGroup->lpVtbl->AddMember(This->ServiceGroup,
1104 (PSERVICESINK)&This->lpVtblServiceSink);
1105 if (!NT_SUCCESS(Status))
1106 {
1107 DPRINT1("Failed to add pin to service group\n");
1108 return Status;
1109 }
1110
1111 This->ServiceGroup->lpVtbl->SupportDelayedService(This->ServiceGroup);
1112 This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
1113 This->State = KSSTATE_STOP;
1114 This->CommonBufferOffset = 0;
1115 This->CommonBufferSize = This->DmaChannel->lpVtbl->AllocatedBufferSize(This->DmaChannel);
1116 This->CommonBuffer = This->DmaChannel->lpVtbl->SystemAddress(This->DmaChannel);
1117 This->Capture = Capture;
1118 /* delay of 10 milisec */
1119 This->Delay = Int32x32To64(10, -10000);
1120
1121 Status = This->Stream->lpVtbl->SetNotificationFreq(This->Stream, 10, &This->FrameSize);
1122
1123 SilenceBuffer = AllocateItem(NonPagedPool, This->FrameSize, TAG_PORTCLASS);
1124 if (!SilenceBuffer)
1125 return STATUS_INSUFFICIENT_RESOURCES;
1126
1127 This->Stream->lpVtbl->Silence(This->Stream, SilenceBuffer, This->FrameSize);
1128
1129 Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DataFormat, DeviceObject, This->FrameSize, 0, SilenceBuffer);
1130 if (!NT_SUCCESS(Status))
1131 {
1132 This->IrpQueue->lpVtbl->Release(This->IrpQueue);
1133 return Status;
1134 }
1135
1136 Port->lpVtbl->AddRef(Port);
1137 Filter->lpVtbl->AddRef(Filter);
1138
1139 This->Port = Port;
1140 This->Filter = Filter;
1141
1142 //This->Stream->lpVtbl->SetFormat(This->Stream, (PKSDATAFORMAT)This->Format);
1143 DPRINT1("Setting state to acquire %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_ACQUIRE));
1144 DPRINT1("Setting state to pause %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE));
1145 This->State = KSSTATE_PAUSE;
1146
1147 //This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay);
1148
1149 return STATUS_SUCCESS;
1150 }
1151
1152 /*
1153 * @unimplemented
1154 */
1155 ULONG
1156 NTAPI
1157 IPortPinWaveCyclic_fnGetCompletedPosition(
1158 IN IPortPinWaveCyclic* iface)
1159 {
1160 UNIMPLEMENTED;
1161 return 0;
1162 }
1163
1164 /*
1165 * @unimplemented
1166 */
1167 ULONG
1168 NTAPI
1169 IPortPinWaveCyclic_fnGetCycleCount(
1170 IN IPortPinWaveCyclic* iface)
1171 {
1172 UNIMPLEMENTED;
1173 return 0;
1174 }
1175
1176 /*
1177 * @implemented
1178 */
1179 ULONG
1180 NTAPI
1181 IPortPinWaveCyclic_fnGetDeviceBufferSize(
1182 IN IPortPinWaveCyclic* iface)
1183 {
1184 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
1185
1186 return This->CommonBufferSize;
1187 }
1188
1189 /*
1190 * @implemented
1191 */
1192 PVOID
1193 NTAPI
1194 IPortPinWaveCyclic_fnGetIrpStream(
1195 IN IPortPinWaveCyclic* iface)
1196 {
1197 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
1198
1199 return (PVOID)This->IrpQueue;
1200 }
1201
1202
1203 /*
1204 * @implemented
1205 */
1206 PMINIPORT
1207 NTAPI
1208 IPortPinWaveCyclic_fnGetMiniport(
1209 IN IPortPinWaveCyclic* iface)
1210 {
1211 IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
1212
1213 return (PMINIPORT)This->Miniport;
1214 }
1215
1216 static IPortPinWaveCyclicVtbl vt_IPortPinWaveCyclic =
1217 {
1218 IPortPinWaveCyclic_fnQueryInterface,
1219 IPortPinWaveCyclic_fnAddRef,
1220 IPortPinWaveCyclic_fnRelease,
1221 IPortPinWaveCyclic_fnNewIrpTarget,
1222 IPortPinWaveCyclic_fnDeviceIoControl,
1223 IPortPinWaveCyclic_fnRead,
1224 IPortPinWaveCyclic_fnWrite,
1225 IPortPinWaveCyclic_fnFlush,
1226 IPortPinWaveCyclic_fnClose,
1227 IPortPinWaveCyclic_fnQuerySecurity,
1228 IPortPinWaveCyclic_fnSetSecurity,
1229 IPortPinWaveCyclic_fnFastDeviceIoControl,
1230 IPortPinWaveCyclic_fnFastRead,
1231 IPortPinWaveCyclic_fnFastWrite,
1232 IPortPinWaveCyclic_fnInit,
1233 IPortPinWaveCyclic_fnGetCompletedPosition,
1234 IPortPinWaveCyclic_fnGetCycleCount,
1235 IPortPinWaveCyclic_fnGetDeviceBufferSize,
1236 IPortPinWaveCyclic_fnGetIrpStream,
1237 IPortPinWaveCyclic_fnGetMiniport
1238 };
1239
1240
1241
1242
1243 NTSTATUS NewPortPinWaveCyclic(
1244 OUT IPortPinWaveCyclic ** OutPin)
1245 {
1246 IPortPinWaveCyclicImpl * This;
1247
1248 This = AllocateItem(NonPagedPool, sizeof(IPortPinWaveCyclicImpl), TAG_PORTCLASS);
1249 if (!This)
1250 return STATUS_INSUFFICIENT_RESOURCES;
1251
1252 /* initialize IPortPinWaveCyclic */
1253 This->ref = 1;
1254 This->lpVtbl = &vt_IPortPinWaveCyclic;
1255 This->lpVtblServiceSink = &vt_IServiceSink;
1256
1257
1258 /* store result */
1259 *OutPin = (IPortPinWaveCyclic*)&This->lpVtbl;
1260
1261 return STATUS_SUCCESS;
1262 }