- Fix various bugs such as wrong function definitions, using of uninitialized variables
[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 DPRINT1("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 DPRINT1("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 DPRINT1("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 DPRINT1("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 DPRINT1("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 DPRINT1("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 DbgBreakPoint();
418
419 Irp->IoStatus.Information = 0;
420 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
421 IoCompleteRequest(Irp, IO_NO_INCREMENT);
422
423 return STATUS_UNSUCCESSFUL;
424 }
425
426 NTSTATUS
427 NTAPI
428 CPortPinWaveRT::Read(
429 IN PDEVICE_OBJECT DeviceObject,
430 IN PIRP Irp)
431 {
432 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
433 }
434
435 NTSTATUS
436 NTAPI
437 CPortPinWaveRT::Write(
438 IN PDEVICE_OBJECT DeviceObject,
439 IN PIRP Irp)
440 {
441 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
442 }
443
444 NTSTATUS
445 NTAPI
446 CPortPinWaveRT::Flush(
447 IN PDEVICE_OBJECT DeviceObject,
448 IN PIRP Irp)
449 {
450 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
451 }
452
453 VOID
454 NTAPI
455 CloseStreamRoutine(
456 IN PDEVICE_OBJECT DeviceObject,
457 IN PVOID Context)
458 {
459 PMINIPORTWAVERTSTREAM Stream;
460 NTSTATUS Status;
461 ISubdevice *ISubDevice;
462 PSUBDEVICE_DESCRIPTOR Descriptor;
463 CPortPinWaveRT * This;
464 PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
465
466 This = (CPortPinWaveRT*)Ctx->Pin;
467
468 if (This->m_Stream)
469 {
470 if (This->m_State != KSSTATE_STOP)
471 {
472 This->m_Stream->SetState(KSSTATE_STOP);
473 KeStallExecutionProcessor(10);
474 }
475 }
476
477 Status = This->m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
478 if (NT_SUCCESS(Status))
479 {
480 Status = ISubDevice->GetDescriptor(&Descriptor);
481 if (NT_SUCCESS(Status))
482 {
483 Descriptor->Factory.Instances[This->m_ConnectDetails->PinId].CurrentPinInstanceCount--;
484 }
485 ISubDevice->Release();
486 }
487
488 if (This->m_Format)
489 {
490 ExFreePool(This->m_Format);
491 This->m_Format = NULL;
492 }
493
494 if (This->m_IrpQueue)
495 {
496 This->m_IrpQueue->Release();
497 }
498
499 // complete the irp
500 Ctx->Irp->IoStatus.Information = 0;
501 Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
502 IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
503
504 // free the work item
505 IoFreeWorkItem(Ctx->WorkItem);
506
507 // free work item ctx
508 FreeItem(Ctx, TAG_PORTCLASS);
509
510 if (This->m_Stream)
511 {
512 Stream = This->m_Stream;
513 This->m_Stream = NULL;
514 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
515 Stream->Release();
516 }
517 }
518
519 NTSTATUS
520 NTAPI
521 CPortPinWaveRT::Close(
522 IN PDEVICE_OBJECT DeviceObject,
523 IN PIRP Irp)
524 {
525 PCLOSESTREAM_CONTEXT Ctx;
526
527 if (m_Stream)
528 {
529 Ctx = (PCLOSESTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
530 if (!Ctx)
531 {
532 DPRINT1("Failed to allocate stream context\n");
533 goto cleanup;
534 }
535
536 Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
537 if (!Ctx->WorkItem)
538 {
539 DPRINT1("Failed to allocate work item\n");
540 goto cleanup;
541 }
542
543 Ctx->Irp = Irp;
544 Ctx->Pin = this;
545
546 IoMarkIrpPending(Irp);
547 Irp->IoStatus.Information = 0;
548 Irp->IoStatus.Status = STATUS_PENDING;
549
550 // defer work item
551 IoQueueWorkItem(Ctx->WorkItem, CloseStreamRoutine, DelayedWorkQueue, (PVOID)Ctx);
552 // Return result
553 return STATUS_PENDING;
554 }
555
556 Irp->IoStatus.Information = 0;
557 Irp->IoStatus.Status = STATUS_SUCCESS;
558 IoCompleteRequest(Irp, IO_NO_INCREMENT);
559
560 return STATUS_SUCCESS;
561
562 cleanup:
563
564 if (Ctx)
565 FreeItem(Ctx, TAG_PORTCLASS);
566
567 Irp->IoStatus.Information = 0;
568 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
569 IoCompleteRequest(Irp, IO_NO_INCREMENT);
570 return STATUS_UNSUCCESSFUL;
571
572 }
573
574 NTSTATUS
575 NTAPI
576 CPortPinWaveRT::QuerySecurity(
577 IN PDEVICE_OBJECT DeviceObject,
578 IN PIRP Irp)
579 {
580 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
581 }
582
583 NTSTATUS
584 NTAPI
585 CPortPinWaveRT::SetSecurity(
586 IN PDEVICE_OBJECT DeviceObject,
587 IN PIRP Irp)
588 {
589 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
590 }
591
592 BOOLEAN
593 NTAPI
594 CPortPinWaveRT::FastDeviceIoControl(
595 IN PFILE_OBJECT FileObject,
596 IN BOOLEAN Wait,
597 IN PVOID InputBuffer,
598 IN ULONG InputBufferLength,
599 OUT PVOID OutputBuffer,
600 IN ULONG OutputBufferLength,
601 IN ULONG IoControlCode,
602 OUT PIO_STATUS_BLOCK StatusBlock,
603 IN PDEVICE_OBJECT DeviceObject)
604 {
605 return FALSE;
606 }
607
608 BOOLEAN
609 NTAPI
610 CPortPinWaveRT::FastRead(
611 IN PFILE_OBJECT FileObject,
612 IN PLARGE_INTEGER FileOffset,
613 IN ULONG Length,
614 IN BOOLEAN Wait,
615 IN ULONG LockKey,
616 IN PVOID Buffer,
617 OUT PIO_STATUS_BLOCK StatusBlock,
618 IN PDEVICE_OBJECT DeviceObject)
619 {
620 return FALSE;
621 }
622
623 BOOLEAN
624 NTAPI
625 CPortPinWaveRT::FastWrite(
626 IN PFILE_OBJECT FileObject,
627 IN PLARGE_INTEGER FileOffset,
628 IN ULONG Length,
629 IN BOOLEAN Wait,
630 IN ULONG LockKey,
631 IN PVOID Buffer,
632 OUT PIO_STATUS_BLOCK StatusBlock,
633 IN PDEVICE_OBJECT DeviceObject)
634 {
635 return FALSE;
636 }
637
638 NTSTATUS
639 NTAPI
640 CPortPinWaveRT::Init(
641 IN PPORTWAVERT Port,
642 IN PPORTFILTERWAVERT Filter,
643 IN KSPIN_CONNECT * ConnectDetails,
644 IN KSPIN_DESCRIPTOR * KsPinDescriptor,
645 IN PDEVICE_OBJECT DeviceObject)
646 {
647 NTSTATUS Status;
648 PKSDATAFORMAT DataFormat;
649 BOOLEAN Capture;
650 KSRTAUDIO_HWLATENCY Latency;
651
652 Port->AddRef();
653 Filter->AddRef();
654
655 m_Port = Port;
656 m_Filter = Filter;
657 m_KsPinDescriptor = KsPinDescriptor;
658 m_ConnectDetails = ConnectDetails;
659 m_Miniport = GetWaveRTMiniport(Port);
660
661 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
662
663 DPRINT("CPortPinWaveRT::Init entered\n");
664
665 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
666 if (!m_Format)
667 return STATUS_INSUFFICIENT_RESOURCES;
668
669 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
670
671 Status = NewIrpQueue(&m_IrpQueue);
672 if (!NT_SUCCESS(Status))
673 {
674 goto cleanup;
675 }
676
677 Status = m_IrpQueue->Init(ConnectDetails, DataFormat, DeviceObject, 0, 0, NULL);
678 if (!NT_SUCCESS(Status))
679 {
680 goto cleanup;
681 }
682
683 Status = NewPortWaveRTStream(&m_PortStream);
684 if (!NT_SUCCESS(Status))
685 {
686 goto cleanup;
687 }
688
689 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
690 {
691 Capture = FALSE;
692 }
693 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
694 {
695 Capture = TRUE;
696 }
697 else
698 {
699 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
700 KeBugCheck(0);
701 }
702
703 Status = m_Miniport->NewStream(&m_Stream, m_PortStream, ConnectDetails->PinId, Capture, m_Format);
704 DPRINT("CPortPinWaveRT::Init Status %x\n", Status);
705
706 if (!NT_SUCCESS(Status))
707 goto cleanup;
708
709 m_Stream->GetHWLatency(&Latency);
710 // delay of 10 milisec
711 m_Delay = Int32x32To64(10, -10000);
712
713 Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl, &m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType);
714 if (!NT_SUCCESS(Status))
715 {
716 DPRINT1("AllocateAudioBuffer failed with %x\n", Status);
717 goto cleanup;
718 }
719
720 m_CommonBuffer = MmGetSystemAddressForMdlSafe(m_Mdl, NormalPagePriority);
721 if (!NT_SUCCESS(Status))
722 {
723 DPRINT1("Failed to get system address %x\n", Status);
724 IoFreeMdl(m_Mdl);
725 m_Mdl = NULL;
726 goto cleanup;
727 }
728
729 DPRINT1("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
730 DPRINT1("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
731 m_State = KSSTATE_PAUSE;
732 return STATUS_SUCCESS;
733
734 cleanup:
735 if (m_IrpQueue)
736 {
737 m_IrpQueue->Release();
738 m_IrpQueue = NULL;
739 }
740
741 if (m_Format)
742 {
743 FreeItem(m_Format, TAG_PORTCLASS);
744 m_Format = NULL;
745 }
746
747 if (m_Stream)
748 {
749 m_Stream->Release();
750 m_Stream = NULL;
751 }
752 else
753 {
754 if (m_PortStream)
755 {
756 m_PortStream->Release();
757 m_PortStream = NULL;
758 }
759
760 }
761 return Status;
762 }
763
764
765 NTSTATUS
766 NewPortPinWaveRT(
767 OUT IPortPinWaveRT ** OutPin)
768 {
769 CPortPinWaveRT * This;
770
771 This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWaveRT(NULL);
772 if (!This)
773 return STATUS_INSUFFICIENT_RESOURCES;
774
775 This->AddRef();
776
777 // store result
778 *OutPin = (PPORTPINWAVERT)This;
779
780 return STATUS_SUCCESS;
781 }