0840319d8dad694d83e9bd0bbaf5d02f27efc590
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / pin_wavert.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/pin_wavert.cpp
5 * PURPOSE: WaveRT IRP Audio Pin
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 class CPortPinWaveRT : public IPortPinWaveRT
12 {
13 public:
14 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
15
16 STDMETHODIMP_(ULONG) AddRef()
17 {
18 InterlockedIncrement(&m_Ref);
19 return m_Ref;
20 }
21 STDMETHODIMP_(ULONG) Release()
22 {
23 InterlockedDecrement(&m_Ref);
24
25 if (!m_Ref)
26 {
27 delete this;
28 return 0;
29 }
30 return m_Ref;
31 }
32 IMP_IPortPinWaveRT;
33 CPortPinWaveRT(IUnknown *OuterUnknown){}
34 virtual ~CPortPinWaveRT(){}
35
36 protected:
37
38 IPortWaveRT * m_Port;
39 IPortFilterWaveRT * m_Filter;
40 KSPIN_DESCRIPTOR * m_KsPinDescriptor;
41 PMINIPORTWAVERT m_Miniport;
42 PMINIPORTWAVERTSTREAM m_Stream;
43 PPORTWAVERTSTREAM m_PortStream;
44 KSSTATE m_State;
45 PKSDATAFORMAT m_Format;
46 KSPIN_CONNECT * m_ConnectDetails;
47
48 PVOID m_CommonBuffer;
49 ULONG m_CommonBufferSize;
50 ULONG m_CommonBufferOffset;
51
52 IIrpQueue * m_IrpQueue;
53
54 BOOL m_Capture;
55
56 ULONG m_TotalPackets;
57 ULONG m_PreCompleted;
58 ULONG m_PostCompleted;
59
60 ULONGLONG m_Delay;
61
62 MEMORY_CACHING_TYPE m_CacheType;
63 PMDL m_Mdl;
64
65 LONG m_Ref;
66
67 NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp);
68 NTSTATUS NTAPI HandleKsStream(IN PIRP Irp);
69 VOID NTAPI SetStreamState(IN KSSTATE State);
70 friend VOID NTAPI SetStreamWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
71 friend VOID NTAPI CloseStreamRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
72
73 };
74
75
76 typedef struct
77 {
78 CPortPinWaveRT *Pin;
79 PIO_WORKITEM WorkItem;
80 KSSTATE State;
81 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
82
83
84 //==================================================================================================================================
85 NTSTATUS
86 NTAPI
87 CPortPinWaveRT::QueryInterface(
88 IN REFIID refiid,
89 OUT PVOID* Output)
90 {
91 DPRINT("IServiceSink_fnQueryInterface entered\n");
92
93 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
94 IsEqualGUIDAligned(refiid, IID_IUnknown))
95 {
96 *Output = PVOID(PUNKNOWN((IIrpTarget*)this));
97 PUNKNOWN(*Output)->AddRef();
98 return STATUS_SUCCESS;
99 }
100 return STATUS_UNSUCCESSFUL;
101 }
102
103 VOID
104 NTAPI
105 SetStreamWorkerRoutine(
106 IN PDEVICE_OBJECT DeviceObject,
107 IN PVOID Context)
108 {
109 CPortPinWaveRT * This;
110 PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
111 KSSTATE State;
112
113 This = Ctx->Pin;
114 State = Ctx->State;
115
116 IoFreeWorkItem(Ctx->WorkItem);
117 FreeItem(Ctx, TAG_PORTCLASS);
118
119 // Has the audio stream resumed?
120 if (This->m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
121 return;
122
123 // Set the state
124 if (NT_SUCCESS(This->m_Stream->SetState(State)))
125 {
126 // Set internal state to stop
127 This->m_State = State;
128
129 if (This->m_State == KSSTATE_STOP)
130 {
131 // reset start stream
132 This->m_IrpQueue->CancelBuffers(); //FIX function name
133 DPRINT("Stopping PreCompleted %u PostCompleted %u\n", This->m_PreCompleted, This->m_PostCompleted);
134 }
135
136 if (This->m_State == KSSTATE_RUN)
137 {
138 // start the notification timer
139 }
140 }
141 }
142
143 VOID
144 NTAPI
145 CPortPinWaveRT::SetStreamState(
146 IN KSSTATE State)
147 {
148 PDEVICE_OBJECT DeviceObject;
149 PIO_WORKITEM WorkItem;
150 PSETSTREAM_CONTEXT Context;
151
152 PC_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
153
154 // Has the audio stream resumed?
155 if (m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
156 return;
157
158 // Has the audio state already been set?
159 if (m_State == State)
160 return;
161
162 // Get device object
163 DeviceObject = GetDeviceObjectFromPortWaveRT(m_Port);
164
165 // allocate set state context
166 Context = (PSETSTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(SETSTREAM_CONTEXT), TAG_PORTCLASS);
167
168 if (!Context)
169 return;
170
171 // allocate work item
172 WorkItem = IoAllocateWorkItem(DeviceObject);
173
174 if (!WorkItem)
175 {
176 ExFreePool(Context);
177 return;
178 }
179
180 Context->Pin = this;
181 Context->WorkItem = WorkItem;
182 Context->State = State;
183
184 // queue the work item
185 IoQueueWorkItem(WorkItem, SetStreamWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
186 }
187
188 //==================================================================================================================================
189
190 NTSTATUS
191 NTAPI
192 CPortPinWaveRT::NewIrpTarget(
193 OUT struct IIrpTarget **OutTarget,
194 IN PCWSTR Name,
195 IN PUNKNOWN Unknown,
196 IN POOL_TYPE PoolType,
197 IN PDEVICE_OBJECT DeviceObject,
198 IN PIRP Irp,
199 IN KSOBJECT_CREATE *CreateObject)
200 {
201 UNIMPLEMENTED
202 return STATUS_UNSUCCESSFUL;
203 }
204
205 NTSTATUS
206 NTAPI
207 CPortPinWaveRT::HandleKsProperty(
208 IN PIRP Irp)
209 {
210 PKSPROPERTY Property;
211 NTSTATUS Status;
212 UNICODE_STRING GuidString;
213 PIO_STACK_LOCATION IoStack;
214
215 IoStack = IoGetCurrentIrpStackLocation(Irp);
216
217 DPRINT("IPortPinWave_HandleKsProperty entered\n");
218
219 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
220 {
221 Irp->IoStatus.Information = 0;
222 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
223 IoCompleteRequest(Irp, IO_NO_INCREMENT);
224 return STATUS_INVALID_PARAMETER;
225 }
226
227 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
228
229 if (IsEqualGUIDAligned(Property->Set, KSPROPSETID_Connection))
230 {
231 if (Property->Id == KSPROPERTY_CONNECTION_STATE)
232 {
233 PKSSTATE State = (PKSSTATE)Irp->UserBuffer;
234
235 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSSTATE))
236 {
237 Irp->IoStatus.Information = sizeof(KSSTATE);
238 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
239 IoCompleteRequest(Irp, IO_NO_INCREMENT);
240 return STATUS_BUFFER_TOO_SMALL;
241 }
242
243 if (Property->Flags & KSPROPERTY_TYPE_SET)
244 {
245 Status = STATUS_UNSUCCESSFUL;
246 Irp->IoStatus.Information = 0;
247
248 if (m_Stream)
249 {
250 Status = m_Stream->SetState(*State);
251
252 DPRINT("Setting state %u %x\n", *State, Status);
253 if (NT_SUCCESS(Status))
254 {
255 m_State = *State;
256 }
257 }
258 Irp->IoStatus.Status = Status;
259 IoCompleteRequest(Irp, IO_NO_INCREMENT);
260 return Status;
261 }
262 else if (Property->Flags & KSPROPERTY_TYPE_GET)
263 {
264 *State = m_State;
265 Irp->IoStatus.Information = sizeof(KSSTATE);
266 Irp->IoStatus.Status = STATUS_SUCCESS;
267 IoCompleteRequest(Irp, IO_NO_INCREMENT);
268 return STATUS_SUCCESS;
269 }
270 }
271 else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT)
272 {
273 PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
274 if (Property->Flags & KSPROPERTY_TYPE_SET)
275 {
276 PKSDATAFORMAT NewDataFormat;
277 if (!RtlCompareMemory(DataFormat, m_Format, DataFormat->FormatSize))
278 {
279 Irp->IoStatus.Information = DataFormat->FormatSize;
280 Irp->IoStatus.Status = STATUS_SUCCESS;
281 IoCompleteRequest(Irp, IO_NO_INCREMENT);
282 return STATUS_SUCCESS;
283 }
284
285 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
286 if (!NewDataFormat)
287 {
288 Irp->IoStatus.Information = 0;
289 Irp->IoStatus.Status = STATUS_NO_MEMORY;
290 IoCompleteRequest(Irp, IO_NO_INCREMENT);
291 return STATUS_NO_MEMORY;
292 }
293 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
294
295 if (m_Stream)
296 {
297 #if 0
298 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
299 ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
300 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO));
301 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM));
302 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
303
304 ASSERT(m_State == KSSTATE_STOP);
305 #endif
306 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
307 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
308 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
309
310 Status = m_Stream->SetFormat(NewDataFormat);
311 if (NT_SUCCESS(Status))
312 {
313 if (m_Format)
314 ExFreePoolWithTag(m_Format, TAG_PORTCLASS);
315
316 m_IrpQueue->UpdateFormat((PKSDATAFORMAT)NewDataFormat);
317 m_Format = NewDataFormat;
318 Irp->IoStatus.Information = DataFormat->FormatSize;
319 Irp->IoStatus.Status = STATUS_SUCCESS;
320 IoCompleteRequest(Irp, IO_NO_INCREMENT);
321 return STATUS_SUCCESS;
322 }
323 }
324 DPRINT("Failed to set format\n");
325 Irp->IoStatus.Information = 0;
326 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
327 IoCompleteRequest(Irp, IO_NO_INCREMENT);
328 return STATUS_UNSUCCESSFUL;
329 }
330 else if (Property->Flags & KSPROPERTY_TYPE_GET)
331 {
332 if (!m_Format)
333 {
334 DPRINT("No format\n");
335 Irp->IoStatus.Information = 0;
336 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
337 IoCompleteRequest(Irp, IO_NO_INCREMENT);
338 return STATUS_UNSUCCESSFUL;
339 }
340 if (m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
341 {
342 Irp->IoStatus.Information = m_Format->FormatSize;
343 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
344 IoCompleteRequest(Irp, IO_NO_INCREMENT);
345 return STATUS_BUFFER_TOO_SMALL;
346 }
347
348 RtlMoveMemory(DataFormat, m_Format, m_Format->FormatSize);
349 Irp->IoStatus.Information = DataFormat->FormatSize;
350 Irp->IoStatus.Status = STATUS_SUCCESS;
351 IoCompleteRequest(Irp, IO_NO_INCREMENT);
352 return STATUS_SUCCESS;
353 }
354 }
355
356 }
357 RtlStringFromGUID(Property->Set, &GuidString);
358 DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
359 RtlFreeUnicodeString(&GuidString);
360
361 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
362 Irp->IoStatus.Information = 0;
363 IoCompleteRequest(Irp, IO_NO_INCREMENT);
364 return STATUS_NOT_IMPLEMENTED;
365 }
366
367 NTSTATUS
368 NTAPI
369 CPortPinWaveRT::HandleKsStream(
370 IN PIRP Irp)
371 {
372 DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p\n", m_State, m_Stream);
373
374 return STATUS_PENDING;
375 }
376
377 NTSTATUS
378 NTAPI
379 CPortPinWaveRT::DeviceIoControl(
380 IN PDEVICE_OBJECT DeviceObject,
381 IN PIRP Irp)
382 {
383 PIO_STACK_LOCATION IoStack;
384
385 IoStack = IoGetCurrentIrpStackLocation(Irp);
386
387
388 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
389 {
390 return HandleKsProperty(Irp);
391 }
392 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
393 {
394 /// FIXME
395 /// handle enable event
396 }
397 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
398 {
399 /// FIXME
400 /// handle disable event
401 }
402 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
403 {
404 /// FIXME
405 /// handle reset state
406 }
407 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
408 {
409 return HandleKsStream(Irp);
410 }
411 else
412 {
413 return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
414 }
415
416 UNIMPLEMENTED
417
418 Irp->IoStatus.Information = 0;
419 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
420 IoCompleteRequest(Irp, IO_NO_INCREMENT);
421
422 return STATUS_UNSUCCESSFUL;
423 }
424
425 NTSTATUS
426 NTAPI
427 CPortPinWaveRT::Read(
428 IN PDEVICE_OBJECT DeviceObject,
429 IN PIRP Irp)
430 {
431 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
432 }
433
434 NTSTATUS
435 NTAPI
436 CPortPinWaveRT::Write(
437 IN PDEVICE_OBJECT DeviceObject,
438 IN PIRP Irp)
439 {
440 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
441 }
442
443 NTSTATUS
444 NTAPI
445 CPortPinWaveRT::Flush(
446 IN PDEVICE_OBJECT DeviceObject,
447 IN PIRP Irp)
448 {
449 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
450 }
451
452 VOID
453 NTAPI
454 CloseStreamRoutine(
455 IN PDEVICE_OBJECT DeviceObject,
456 IN PVOID Context)
457 {
458 PMINIPORTWAVERTSTREAM Stream;
459 NTSTATUS Status;
460 ISubdevice *ISubDevice;
461 PSUBDEVICE_DESCRIPTOR Descriptor;
462 CPortPinWaveRT * This;
463 PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
464
465 This = (CPortPinWaveRT*)Ctx->Pin;
466
467 if (This->m_Stream)
468 {
469 if (This->m_State != KSSTATE_STOP)
470 {
471 This->m_Stream->SetState(KSSTATE_STOP);
472 KeStallExecutionProcessor(10);
473 }
474 }
475
476 Status = This->m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
477 if (NT_SUCCESS(Status))
478 {
479 Status = ISubDevice->GetDescriptor(&Descriptor);
480 if (NT_SUCCESS(Status))
481 {
482 Descriptor->Factory.Instances[This->m_ConnectDetails->PinId].CurrentPinInstanceCount--;
483 }
484 ISubDevice->Release();
485 }
486
487 if (This->m_Format)
488 {
489 ExFreePool(This->m_Format);
490 This->m_Format = NULL;
491 }
492
493 if (This->m_IrpQueue)
494 {
495 This->m_IrpQueue->Release();
496 }
497
498 // complete the irp
499 Ctx->Irp->IoStatus.Information = 0;
500 Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
501 IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
502
503 // free the work item
504 IoFreeWorkItem(Ctx->WorkItem);
505
506 // free work item ctx
507 FreeItem(Ctx, TAG_PORTCLASS);
508
509 if (This->m_Stream)
510 {
511 Stream = This->m_Stream;
512 This->m_Stream = NULL;
513 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
514 Stream->Release();
515 }
516 }
517
518 NTSTATUS
519 NTAPI
520 CPortPinWaveRT::Close(
521 IN PDEVICE_OBJECT DeviceObject,
522 IN PIRP Irp)
523 {
524 PCLOSESTREAM_CONTEXT Ctx;
525
526 if (m_Stream)
527 {
528 Ctx = (PCLOSESTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
529 if (!Ctx)
530 {
531 DPRINT("Failed to allocate stream context\n");
532 goto cleanup;
533 }
534
535 Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
536 if (!Ctx->WorkItem)
537 {
538 DPRINT("Failed to allocate work item\n");
539 goto cleanup;
540 }
541
542 Ctx->Irp = Irp;
543 Ctx->Pin = this;
544
545 IoMarkIrpPending(Irp);
546 Irp->IoStatus.Information = 0;
547 Irp->IoStatus.Status = STATUS_PENDING;
548
549 // defer work item
550 IoQueueWorkItem(Ctx->WorkItem, CloseStreamRoutine, DelayedWorkQueue, (PVOID)Ctx);
551 // Return result
552 return STATUS_PENDING;
553 }
554
555 Irp->IoStatus.Information = 0;
556 Irp->IoStatus.Status = STATUS_SUCCESS;
557 IoCompleteRequest(Irp, IO_NO_INCREMENT);
558
559 return STATUS_SUCCESS;
560
561 cleanup:
562
563 if (Ctx)
564 FreeItem(Ctx, TAG_PORTCLASS);
565
566 Irp->IoStatus.Information = 0;
567 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
568 IoCompleteRequest(Irp, IO_NO_INCREMENT);
569 return STATUS_UNSUCCESSFUL;
570
571 }
572
573 NTSTATUS
574 NTAPI
575 CPortPinWaveRT::QuerySecurity(
576 IN PDEVICE_OBJECT DeviceObject,
577 IN PIRP Irp)
578 {
579 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
580 }
581
582 NTSTATUS
583 NTAPI
584 CPortPinWaveRT::SetSecurity(
585 IN PDEVICE_OBJECT DeviceObject,
586 IN PIRP Irp)
587 {
588 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
589 }
590
591 BOOLEAN
592 NTAPI
593 CPortPinWaveRT::FastDeviceIoControl(
594 IN PFILE_OBJECT FileObject,
595 IN BOOLEAN Wait,
596 IN PVOID InputBuffer,
597 IN ULONG InputBufferLength,
598 OUT PVOID OutputBuffer,
599 IN ULONG OutputBufferLength,
600 IN ULONG IoControlCode,
601 OUT PIO_STATUS_BLOCK StatusBlock,
602 IN PDEVICE_OBJECT DeviceObject)
603 {
604 return FALSE;
605 }
606
607 BOOLEAN
608 NTAPI
609 CPortPinWaveRT::FastRead(
610 IN PFILE_OBJECT FileObject,
611 IN PLARGE_INTEGER FileOffset,
612 IN ULONG Length,
613 IN BOOLEAN Wait,
614 IN ULONG LockKey,
615 IN PVOID Buffer,
616 OUT PIO_STATUS_BLOCK StatusBlock,
617 IN PDEVICE_OBJECT DeviceObject)
618 {
619 return FALSE;
620 }
621
622 BOOLEAN
623 NTAPI
624 CPortPinWaveRT::FastWrite(
625 IN PFILE_OBJECT FileObject,
626 IN PLARGE_INTEGER FileOffset,
627 IN ULONG Length,
628 IN BOOLEAN Wait,
629 IN ULONG LockKey,
630 IN PVOID Buffer,
631 OUT PIO_STATUS_BLOCK StatusBlock,
632 IN PDEVICE_OBJECT DeviceObject)
633 {
634 return FALSE;
635 }
636
637 NTSTATUS
638 NTAPI
639 CPortPinWaveRT::Init(
640 IN PPORTWAVERT Port,
641 IN PPORTFILTERWAVERT Filter,
642 IN KSPIN_CONNECT * ConnectDetails,
643 IN KSPIN_DESCRIPTOR * KsPinDescriptor,
644 IN PDEVICE_OBJECT DeviceObject)
645 {
646 NTSTATUS Status;
647 PKSDATAFORMAT DataFormat;
648 BOOLEAN Capture;
649 KSRTAUDIO_HWLATENCY Latency;
650
651 Port->AddRef();
652 Filter->AddRef();
653
654 m_Port = Port;
655 m_Filter = Filter;
656 m_KsPinDescriptor = KsPinDescriptor;
657 m_ConnectDetails = ConnectDetails;
658 m_Miniport = GetWaveRTMiniport(Port);
659
660 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
661
662 DPRINT("CPortPinWaveRT::Init entered\n");
663
664 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
665 if (!m_Format)
666 return STATUS_INSUFFICIENT_RESOURCES;
667
668 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
669
670 Status = NewIrpQueue(&m_IrpQueue);
671 if (!NT_SUCCESS(Status))
672 {
673 goto cleanup;
674 }
675
676 Status = m_IrpQueue->Init(ConnectDetails, DataFormat, DeviceObject, 0, 0, NULL);
677 if (!NT_SUCCESS(Status))
678 {
679 goto cleanup;
680 }
681
682 Status = NewPortWaveRTStream(&m_PortStream);
683 if (!NT_SUCCESS(Status))
684 {
685 goto cleanup;
686 }
687
688 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
689 {
690 Capture = FALSE;
691 }
692 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
693 {
694 Capture = TRUE;
695 }
696 else
697 {
698 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
699 KeBugCheck(0);
700 }
701
702 Status = m_Miniport->NewStream(&m_Stream, m_PortStream, ConnectDetails->PinId, Capture, m_Format);
703 DPRINT("CPortPinWaveRT::Init Status %x\n", Status);
704
705 if (!NT_SUCCESS(Status))
706 goto cleanup;
707
708 m_Stream->GetHWLatency(&Latency);
709 // delay of 10 milisec
710 m_Delay = Int32x32To64(10, -10000);
711
712 Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl, &m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType);
713 if (!NT_SUCCESS(Status))
714 {
715 DPRINT("AllocateAudioBuffer failed with %x\n", Status);
716 goto cleanup;
717 }
718
719 m_CommonBuffer = MmGetSystemAddressForMdlSafe(m_Mdl, NormalPagePriority);
720 if (!NT_SUCCESS(Status))
721 {
722 DPRINT("Failed to get system address %x\n", Status);
723 IoFreeMdl(m_Mdl);
724 m_Mdl = NULL;
725 goto cleanup;
726 }
727
728 DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
729 DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
730 m_State = KSSTATE_PAUSE;
731 return STATUS_SUCCESS;
732
733 cleanup:
734 if (m_IrpQueue)
735 {
736 m_IrpQueue->Release();
737 m_IrpQueue = NULL;
738 }
739
740 if (m_Format)
741 {
742 FreeItem(m_Format, TAG_PORTCLASS);
743 m_Format = NULL;
744 }
745
746 if (m_Stream)
747 {
748 m_Stream->Release();
749 m_Stream = NULL;
750 }
751 else
752 {
753 if (m_PortStream)
754 {
755 m_PortStream->Release();
756 m_PortStream = NULL;
757 }
758
759 }
760 return Status;
761 }
762
763
764 NTSTATUS
765 NewPortPinWaveRT(
766 OUT IPortPinWaveRT ** OutPin)
767 {
768 CPortPinWaveRT * This;
769
770 This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWaveRT(NULL);
771 if (!This)
772 return STATUS_INSUFFICIENT_RESOURCES;
773
774 This->AddRef();
775
776 // store result
777 *OutPin = (PPORTPINWAVERT)This;
778
779 return STATUS_SUCCESS;
780 }