Hopefully create a branch and not destroy the svn repository.
[reactos.git] / drivers / wdm / audio / backpln / portcls / pin_wavecyclic.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
5 * PURPOSE: WaveCyclic IRP Audio Pin
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 class CPortPinWaveCyclic : public IPortPinWaveCyclic,
12 public IServiceSink
13 {
14 public:
15 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
16
17 STDMETHODIMP_(ULONG) AddRef()
18 {
19 InterlockedIncrement(&m_Ref);
20 return m_Ref;
21 }
22 STDMETHODIMP_(ULONG) Release()
23 {
24 InterlockedDecrement(&m_Ref);
25
26 if (!m_Ref)
27 {
28 delete this;
29 return 0;
30 }
31 return m_Ref;
32 }
33 IMP_IPortPinWaveCyclic;
34 IMP_IServiceSink;
35 CPortPinWaveCyclic(IUnknown *OuterUnknown){}
36 virtual ~CPortPinWaveCyclic(){}
37
38 protected:
39
40 VOID UpdateCommonBuffer(ULONG Position, ULONG MaxTransferCount);
41 VOID UpdateCommonBufferOverlap(ULONG Position, ULONG MaxTransferCount);
42 VOID GeneratePositionEvents(IN ULONGLONG OldOffset, IN ULONGLONG NewOffset);
43
44 friend NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
45 friend NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
46 friend NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
47 friend NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
48 friend NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
49 friend NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
50 friend VOID CALLBACK PinSetStateWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
51
52 IPortWaveCyclic * m_Port;
53 IPortFilterWaveCyclic * m_Filter;
54 KSPIN_DESCRIPTOR * m_KsPinDescriptor;
55 PMINIPORTWAVECYCLIC m_Miniport;
56 PSERVICEGROUP m_ServiceGroup;
57 PDMACHANNEL m_DmaChannel;
58 PMINIPORTWAVECYCLICSTREAM m_Stream;
59 KSSTATE m_State;
60 PKSDATAFORMAT m_Format;
61 PKSPIN_CONNECT m_ConnectDetails;
62
63 PVOID m_CommonBuffer;
64 ULONG m_CommonBufferSize;
65 ULONG m_CommonBufferOffset;
66
67 IIrpQueue * m_IrpQueue;
68
69 ULONG m_FrameSize;
70 BOOL m_Capture;
71
72 ULONG m_TotalPackets;
73 ULONG m_StopCount;
74 KSAUDIO_POSITION m_Position;
75 KSALLOCATOR_FRAMING m_AllocatorFraming;
76 SUBDEVICE_DESCRIPTOR m_Descriptor;
77
78 KSPIN_LOCK m_EventListLock;
79 LIST_ENTRY m_EventList;
80
81 KSRESET m_ResetState;
82
83 ULONG m_Delay;
84
85 LONG m_Ref;
86 };
87
88
89 typedef struct
90 {
91 ULONG bLoopedStreaming;
92 ULONGLONG Position;
93 }LOOPEDSTREAMING_EVENT_CONTEXT, *PLOOPEDSTREAMING_EVENT_CONTEXT;
94
95 typedef struct
96 {
97 ULONG bLoopedStreaming;
98 }ENDOFSTREAM_EVENT_CONTEXT, *PENDOFSTREAM_EVENT_CONTEXT;
99
100
101
102 NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
103 NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
104 NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
105 NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
106 NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
107 NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
108
109
110 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet, PinWaveCyclicState, PinWaveCyclicDataFormat, PinWaveCyclicAllocatorFraming);
111 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet, PinWaveCyclicAudioPosition);
112
113 KSEVENT_ITEM PinWaveCyclicConnectionEventSet =
114 {
115 KSEVENT_CONNECTION_ENDOFSTREAM,
116 sizeof(KSEVENTDATA),
117 sizeof(ENDOFSTREAM_EVENT_CONTEXT),
118 PinWaveCyclicAddEndOfStreamEvent,
119 0,
120 0
121 };
122
123 KSEVENT_ITEM PinWaveCyclicStreamingEventSet =
124 {
125 KSEVENT_LOOPEDSTREAMING_POSITION,
126 sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA),
127 sizeof(LOOPEDSTREAMING_EVENT_CONTEXT),
128 PinWaveCyclicAddLoopedStreamEvent,
129 0,
130 0
131 };
132
133
134 KSPROPERTY_SET PinWaveCyclicPropertySet[] =
135 {
136 {
137 &KSPROPSETID_Connection,
138 sizeof(PinWaveCyclicConnectionSet) / sizeof(KSPROPERTY_ITEM),
139 (const KSPROPERTY_ITEM*)&PinWaveCyclicConnectionSet,
140 0,
141 NULL
142 },
143 {
144 &KSPROPSETID_Audio,
145 sizeof(PinWaveCyclicAudioSet) / sizeof(KSPROPERTY_ITEM),
146 (const KSPROPERTY_ITEM*)&PinWaveCyclicAudioSet,
147 0,
148 NULL
149 }
150 };
151
152 KSEVENT_SET PinWaveCyclicEventSet[] =
153 {
154 {
155 &KSEVENTSETID_LoopedStreaming,
156 sizeof(PinWaveCyclicStreamingEventSet) / sizeof(KSEVENT_ITEM),
157 (const KSEVENT_ITEM*)&PinWaveCyclicStreamingEventSet
158 },
159 {
160 &KSEVENTSETID_Connection,
161 sizeof(PinWaveCyclicConnectionEventSet) / sizeof(KSEVENT_ITEM),
162 (const KSEVENT_ITEM*)&PinWaveCyclicConnectionEventSet
163 }
164 };
165
166
167 //==================================================================================================================================
168
169 NTSTATUS
170 NTAPI
171 CPortPinWaveCyclic::QueryInterface(
172 IN REFIID refiid,
173 OUT PVOID* Output)
174 {
175 DPRINT("IServiceSink_fnQueryInterface entered\n");
176
177 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
178 IsEqualGUIDAligned(refiid, IID_IUnknown))
179 {
180 *Output = PVOID(PUNKNOWN((IIrpTarget*)this));
181 PUNKNOWN(*Output)->AddRef();
182 return STATUS_SUCCESS;
183 }
184
185 if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
186 {
187 *Output = PVOID(PUNKNOWN(PSERVICESINK(this)));
188 PUNKNOWN(*Output)->AddRef();
189 return STATUS_SUCCESS;
190 }
191
192 return STATUS_UNSUCCESSFUL;
193 }
194
195 NTSTATUS
196 NTAPI
197 PinWaveCyclicAddEndOfStreamEvent(
198 IN PIRP Irp,
199 IN PKSEVENTDATA EventData,
200 IN PKSEVENT_ENTRY EventEntry)
201 {
202 PENDOFSTREAM_EVENT_CONTEXT Entry;
203 PSUBDEVICE_DESCRIPTOR Descriptor;
204 CPortPinWaveCyclic *Pin;
205
206 // get sub device descriptor
207 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
208
209 // sanity check
210 PC_ASSERT(Descriptor);
211 PC_ASSERT(Descriptor->PortPin);
212 PC_ASSERT_IRQL(DISPATCH_LEVEL);
213
214 // cast to pin impl
215 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
216
217 // get extra size
218 Entry = (PENDOFSTREAM_EVENT_CONTEXT)(EventEntry + 1);
219
220 // not a looped event
221 Entry->bLoopedStreaming = FALSE;
222
223 // insert item
224 (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
225
226 // done
227 return STATUS_SUCCESS;
228 }
229
230 NTSTATUS
231 NTAPI
232 PinWaveCyclicAddLoopedStreamEvent(
233 IN PIRP Irp,
234 IN PKSEVENTDATA EventData,
235 IN PKSEVENT_ENTRY EventEntry)
236 {
237 PLOOPEDSTREAMING_POSITION_EVENT_DATA Data;
238 PLOOPEDSTREAMING_EVENT_CONTEXT Entry;
239 PSUBDEVICE_DESCRIPTOR Descriptor;
240 CPortPinWaveCyclic *Pin;
241
242 // get sub device descriptor
243 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp);
244
245 // sanity check
246 PC_ASSERT(Descriptor);
247 PC_ASSERT(Descriptor->PortPin);
248 PC_ASSERT_IRQL(DISPATCH_LEVEL);
249
250 // cast to pin impl
251 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
252
253 // cast to looped event
254 Data = (PLOOPEDSTREAMING_POSITION_EVENT_DATA)EventData;
255
256 // get extra size
257 Entry = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
258
259 Entry->bLoopedStreaming = TRUE;
260 Entry->Position = Data->Position;
261
262 DPRINT1("Added event\n");
263
264 // insert item
265 (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
266
267 // done
268 return STATUS_SUCCESS;
269 }
270
271 NTSTATUS
272 NTAPI
273 PinWaveCyclicAllocatorFraming(
274 IN PIRP Irp,
275 IN PKSIDENTIFIER Request,
276 IN OUT PVOID Data)
277 {
278 CPortPinWaveCyclic *Pin;
279 PSUBDEVICE_DESCRIPTOR Descriptor;
280
281 // get sub device descriptor
282 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp);
283
284 // sanity check
285 PC_ASSERT(Descriptor);
286 PC_ASSERT(Descriptor->PortPin);
287 PC_ASSERT_IRQL(DISPATCH_LEVEL);
288
289 // cast to pin impl
290 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
291
292
293 if (Request->Flags & KSPROPERTY_TYPE_GET)
294 {
295 // copy pin framing
296 RtlMoveMemory(Data, &Pin->m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING));
297
298 Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING);
299 return STATUS_SUCCESS;
300 }
301
302 // not supported
303 return STATUS_NOT_SUPPORTED;
304 }
305
306 NTSTATUS
307 NTAPI
308 PinWaveCyclicAudioPosition(
309 IN PIRP Irp,
310 IN PKSIDENTIFIER Request,
311 IN OUT PVOID Data)
312 {
313 CPortPinWaveCyclic *Pin;
314 PSUBDEVICE_DESCRIPTOR Descriptor;
315 PKSAUDIO_POSITION Position;
316
317 // get sub device descriptor
318 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
319
320 // sanity check
321 PC_ASSERT(Descriptor);
322 PC_ASSERT(Descriptor->PortPin);
323 PC_ASSERT_IRQL(DISPATCH_LEVEL);
324
325 // cast to pin impl
326 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
327
328 //sanity check
329 PC_ASSERT(Pin->m_Stream);
330
331 if (Request->Flags & KSPROPERTY_TYPE_GET)
332 {
333 // FIXME non multithreading-safe
334 // copy audio position
335
336 Position = (PKSAUDIO_POSITION)Data;
337
338 if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING)
339 {
340 RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
341 DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset);
342 }
343 else if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
344 {
345 Position->PlayOffset = Pin->m_Position.PlayOffset;
346 Position->WriteOffset = (ULONGLONG)Pin->m_IrpQueue->GetCurrentIrpOffset();
347 DPRINT("Play %lu Write %lu\n", Position->PlayOffset, Position->WriteOffset);
348 }
349
350
351 Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION);
352 return STATUS_SUCCESS;
353 }
354
355 // not supported
356 return STATUS_NOT_SUPPORTED;
357 }
358
359 typedef struct
360 {
361 CPortPinWaveCyclic *Pin;
362 KSSTATE NewState;
363 PIO_WORKITEM WorkItem;
364 PIRP Irp;
365
366 }SETPIN_CONTEXT, *PSETPIN_CONTEXT;
367
368 VOID
369 CALLBACK
370 PinSetStateWorkerRoutine(
371 IN PDEVICE_OBJECT DeviceObject,
372 IN PVOID Context)
373 {
374 PSETPIN_CONTEXT PinWorkContext = (PSETPIN_CONTEXT)Context;
375 NTSTATUS Status;
376
377 // try set stream
378 Status = PinWorkContext->Pin->m_Stream->SetState(PinWorkContext->NewState);
379
380 DPRINT1("Setting state %u %x\n", PinWorkContext->NewState, Status);
381 if (NT_SUCCESS(Status))
382 {
383 // store new state
384 PinWorkContext->Pin->m_State = PinWorkContext->NewState;
385
386 if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP)
387 {
388 /* FIXME complete pending irps with successfull state */
389 PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
390 }
391 //HACK
392 //PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
393 }
394
395 // store result
396 PinWorkContext->Irp->IoStatus.Information = sizeof(KSSTATE);
397 PinWorkContext->Irp->IoStatus.Status = Status;
398
399 // complete irp
400 IoCompleteRequest(PinWorkContext->Irp, IO_NO_INCREMENT);
401
402 // free work item
403 IoFreeWorkItem(PinWorkContext->WorkItem);
404
405 // free work context
406 FreeItem(PinWorkContext, TAG_PORTCLASS);
407
408 }
409
410
411 NTSTATUS
412 NTAPI
413 PinWaveCyclicState(
414 IN PIRP Irp,
415 IN PKSIDENTIFIER Request,
416 IN OUT PVOID Data)
417 {
418 NTSTATUS Status = STATUS_UNSUCCESSFUL;
419 CPortPinWaveCyclic *Pin;
420 PSUBDEVICE_DESCRIPTOR Descriptor;
421 PKSSTATE State = (PKSSTATE)Data;
422
423 // get sub device descriptor
424 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
425
426 // sanity check
427 PC_ASSERT(Descriptor);
428 PC_ASSERT(Descriptor->PortPin);
429 PC_ASSERT_IRQL(DISPATCH_LEVEL);
430
431 // cast to pin impl
432 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
433
434 //sanity check
435 PC_ASSERT(Pin->m_Stream);
436
437 if (Request->Flags & KSPROPERTY_TYPE_SET)
438 {
439 // try set stream
440 Status = Pin->m_Stream->SetState(*State);
441
442 DPRINT("Setting state %u %x\n", *State, Status);
443 if (NT_SUCCESS(Status))
444 {
445 // store new state
446 Pin->m_State = *State;
447
448 if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP)
449 {
450 // FIXME
451 // complete with successful state
452 Pin->m_IrpQueue->CancelBuffers();
453 }
454 else if (Pin->m_State == KSSTATE_STOP)
455 {
456 Pin->m_IrpQueue->CancelBuffers();
457 }
458 // store result
459 Irp->IoStatus.Information = sizeof(KSSTATE);
460 }
461 return Status;
462 }
463 else if (Request->Flags & KSPROPERTY_TYPE_GET)
464 {
465 // get current stream state
466 *State = Pin->m_State;
467 // store result
468 Irp->IoStatus.Information = sizeof(KSSTATE);
469
470 return STATUS_SUCCESS;
471 }
472
473 // unsupported request
474 return STATUS_NOT_SUPPORTED;
475 }
476
477 NTSTATUS
478 NTAPI
479 PinWaveCyclicDataFormat(
480 IN PIRP Irp,
481 IN PKSIDENTIFIER Request,
482 IN OUT PVOID Data)
483 {
484 NTSTATUS Status = STATUS_UNSUCCESSFUL;
485 CPortPinWaveCyclic *Pin;
486 PSUBDEVICE_DESCRIPTOR Descriptor;
487 PIO_STACK_LOCATION IoStack;
488
489 // get current irp stack location
490 IoStack = IoGetCurrentIrpStackLocation(Irp);
491
492 // get sub device descriptor
493 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
494
495 // sanity check
496 PC_ASSERT(Descriptor);
497 PC_ASSERT(Descriptor->PortPin);
498
499 // cast to pin impl
500 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
501
502 //sanity check
503 PC_ASSERT(Pin->m_Stream);
504 PC_ASSERT(Pin->m_Format);
505
506 if (Request->Flags & KSPROPERTY_TYPE_SET)
507 {
508 // try to change data format
509 PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
510 ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize);
511
512 if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size)
513 {
514 // format is identical
515 Irp->IoStatus.Information = DataFormat->FormatSize;
516 return STATUS_SUCCESS;
517 }
518
519 // new change request
520 PC_ASSERT(Pin->m_State != KSSTATE_RUN);
521 // FIXME queue a work item when Irql != PASSIVE_LEVEL
522 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
523
524 // allocate new data format
525 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
526 if (!NewDataFormat)
527 {
528 // not enough memory
529 return STATUS_NO_MEMORY;
530 }
531
532 // copy new data format
533 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
534
535 // set new format
536 Status = Pin->m_Stream->SetFormat(NewDataFormat);
537 if (NT_SUCCESS(Status))
538 {
539 // free old format
540 FreeItem(Pin->m_Format, TAG_PORTCLASS);
541
542 // update irp queue with new format
543 Pin->m_IrpQueue->UpdateFormat((PKSDATAFORMAT)NewDataFormat);
544
545 // store new format
546 Pin->m_Format = NewDataFormat;
547 Irp->IoStatus.Information = NewDataFormat->FormatSize;
548
549 #if 0
550 PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
551 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO));
552 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM));
553 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
554
555
556 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
557 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
558 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
559 #endif
560
561 }
562 else
563 {
564 // failed to set format
565 FreeItem(NewDataFormat, TAG_PORTCLASS);
566 }
567
568
569 // done
570 return Status;
571 }
572 else if (Request->Flags & KSPROPERTY_TYPE_GET)
573 {
574 // get current data format
575 PC_ASSERT(Pin->m_Format);
576
577 if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
578 {
579 // buffer too small
580 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
581 return STATUS_MORE_ENTRIES;
582 }
583 // copy data format
584 RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize);
585 // store result size
586 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
587
588 // done
589 return STATUS_SUCCESS;
590 }
591
592 // unsupported request
593 return STATUS_NOT_SUPPORTED;
594 }
595
596 VOID
597 CPortPinWaveCyclic::GeneratePositionEvents(
598 IN ULONGLONG OldOffset,
599 IN ULONGLONG NewOffset)
600 {
601 PLIST_ENTRY Entry;
602 PKSEVENT_ENTRY EventEntry;
603 PLOOPEDSTREAMING_EVENT_CONTEXT Context;
604
605 // acquire event lock
606 KeAcquireSpinLockAtDpcLevel(&m_EventListLock);
607
608 // point to first entry
609 Entry = m_EventList.Flink;
610
611 while(Entry != &m_EventList)
612 {
613 // get event entry
614 EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry);
615
616 // get event entry context
617 Context = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
618
619 if (Context->bLoopedStreaming == TRUE)
620 {
621 if (NewOffset > OldOffset)
622 {
623 /* buffer progress no overlap */
624 if (OldOffset < Context->Position && Context->Position <= NewOffset)
625 {
626 /* when someone eventually fixes sprintf... */
627 DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
628 DPRINT("Context->Position %I64u\n", Context->Position);
629 DPRINT("NewOffset %I64u\n", NewOffset);
630 /* generate event */
631 KsGenerateEvent(EventEntry);
632 }
633 }
634 else
635 {
636 /* buffer wrap-arround */
637 if (OldOffset < Context->Position || NewOffset > Context->Position)
638 {
639 /* when someone eventually fixes sprintf... */
640 DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
641 DPRINT("Context->Position %I64u\n", Context->Position);
642 DPRINT("NewOffset %I64u\n", NewOffset);
643 /* generate event */
644 KsGenerateEvent(EventEntry);
645 }
646 }
647 }
648
649 // move to next entry
650 Entry = Entry->Flink;
651 }
652
653 // release lock
654 KeReleaseSpinLockFromDpcLevel(&m_EventListLock);
655 }
656
657 VOID
658 CPortPinWaveCyclic::UpdateCommonBuffer(
659 ULONG Position,
660 ULONG MaxTransferCount)
661 {
662 ULONG BufferLength;
663 ULONG BytesToCopy;
664 ULONG BufferSize;
665 PUCHAR Buffer;
666 NTSTATUS Status;
667
668 BufferLength = Position - m_CommonBufferOffset;
669 BufferLength = min(BufferLength, MaxTransferCount);
670
671 while(BufferLength)
672 {
673 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
674 if (!NT_SUCCESS(Status))
675 return;
676
677 BytesToCopy = min(BufferLength, BufferSize);
678
679 if (m_Capture)
680 {
681 m_DmaChannel->CopyFrom(Buffer, (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BytesToCopy);
682 }
683 else
684 {
685 m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, Buffer, BytesToCopy);
686 }
687
688 m_IrpQueue->UpdateMapping(BytesToCopy);
689 m_CommonBufferOffset += BytesToCopy;
690
691 BufferLength = Position - m_CommonBufferOffset;
692 m_Position.PlayOffset += BytesToCopy;
693
694 if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
695 {
696 // normalize position
697 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
698 }
699 }
700 }
701
702 VOID
703 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
704 ULONG Position,
705 ULONG MaxTransferCount)
706 {
707 ULONG BufferLength, Length, Gap;
708 ULONG BytesToCopy;
709 ULONG BufferSize;
710 PUCHAR Buffer;
711 NTSTATUS Status;
712
713
714 BufferLength = Gap = m_CommonBufferSize - m_CommonBufferOffset;
715 BufferLength = Length = min(BufferLength, MaxTransferCount);
716 while(BufferLength)
717 {
718 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
719 if (!NT_SUCCESS(Status))
720 return;
721
722 BytesToCopy = min(BufferLength, BufferSize);
723
724 if (m_Capture)
725 {
726 m_DmaChannel->CopyFrom(Buffer,
727 (PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
728 BytesToCopy);
729 }
730 else
731 {
732 m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
733 Buffer,
734 BytesToCopy);
735 }
736
737 m_IrpQueue->UpdateMapping(BytesToCopy);
738 m_CommonBufferOffset += BytesToCopy;
739 m_Position.PlayOffset += BytesToCopy;
740
741 BufferLength = m_CommonBufferSize - m_CommonBufferOffset;
742
743 if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
744 {
745 // normalize position
746 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
747 }
748
749 }
750
751 if (Gap == Length)
752 {
753 m_CommonBufferOffset = 0;
754
755 MaxTransferCount -= Length;
756
757 if (MaxTransferCount)
758 {
759 UpdateCommonBuffer(Position, MaxTransferCount);
760 }
761 }
762 }
763
764 VOID
765 NTAPI
766 CPortPinWaveCyclic::RequestService()
767 {
768 ULONG Position;
769 NTSTATUS Status;
770 PUCHAR Buffer;
771 ULONG BufferSize;
772 ULONGLONG OldOffset, NewOffset;
773
774 PC_ASSERT_IRQL(DISPATCH_LEVEL);
775
776 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
777 if (!NT_SUCCESS(Status))
778 {
779 return;
780 }
781
782 Status = m_Stream->GetPosition(&Position);
783 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position, Buffer, m_CommonBufferSize, BufferSize, m_Capture);
784
785 OldOffset = m_Position.PlayOffset;
786
787 if (Position < m_CommonBufferOffset)
788 {
789 UpdateCommonBufferOverlap(Position, m_FrameSize);
790 }
791 else if (Position >= m_CommonBufferOffset)
792 {
793 UpdateCommonBuffer(Position, m_FrameSize);
794 }
795
796 NewOffset = m_Position.PlayOffset;
797
798 GeneratePositionEvents(OldOffset, NewOffset);
799 }
800
801 NTSTATUS
802 NTAPI
803 CPortPinWaveCyclic::NewIrpTarget(
804 OUT struct IIrpTarget **OutTarget,
805 IN PCWSTR Name,
806 IN PUNKNOWN Unknown,
807 IN POOL_TYPE PoolType,
808 IN PDEVICE_OBJECT DeviceObject,
809 IN PIRP Irp,
810 IN KSOBJECT_CREATE *CreateObject)
811 {
812 UNIMPLEMENTED
813 return STATUS_UNSUCCESSFUL;
814 }
815
816 NTSTATUS
817 NTAPI
818 CPortPinWaveCyclic::DeviceIoControl(
819 IN PDEVICE_OBJECT DeviceObject,
820 IN PIRP Irp)
821 {
822 PIO_STACK_LOCATION IoStack;
823 PKSPROPERTY Property;
824 UNICODE_STRING GuidString;
825 NTSTATUS Status = STATUS_NOT_SUPPORTED;
826 ULONG Data = 0;
827 KSRESET ResetValue;
828
829 /* get current irp stack location */
830 IoStack = IoGetCurrentIrpStackLocation(Irp);
831
832 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
833 {
834 /* handle property with subdevice descriptor */
835 Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
836
837 if (Status == STATUS_NOT_FOUND)
838 {
839 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
840
841 RtlStringFromGUID(Property->Set, &GuidString);
842 DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
843 RtlFreeUnicodeString(&GuidString);
844 }
845 }
846 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
847 {
848 Status = PcHandleEnableEventWithTable(Irp, &m_Descriptor);
849 }
850 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
851 {
852 Status = PcHandleDisableEventWithTable(Irp, &m_Descriptor);
853 }
854 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
855 {
856 Status = KsAcquireResetValue(Irp, &ResetValue);
857 DPRINT("Status %x Value %u\n", Status, ResetValue);
858 /* check for success */
859 if (NT_SUCCESS(Status))
860 {
861 if (ResetValue == KSRESET_BEGIN)
862 {
863 m_IrpQueue->CancelBuffers();
864 m_ResetState = KSRESET_BEGIN;
865 }
866 else if (ResetValue == KSRESET_END)
867 {
868 m_ResetState = KSRESET_END;
869 }
870 }
871 }
872 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
873 {
874 /* increment total number of packets */
875 InterlockedIncrement((PLONG)&m_TotalPackets);
876
877 DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
878
879 /* is the device not currently reset */
880 if (m_ResetState == KSRESET_END)
881 {
882 /* add the mapping */
883 Status = m_IrpQueue->AddMapping(Irp, &Data);
884
885 /* check for success */
886 if (NT_SUCCESS(Status))
887 {
888 m_Position.WriteOffset += Data;
889 Status = STATUS_PENDING;
890 }
891 }
892 else
893 {
894 /* reset request is currently in progress */
895 Status = STATUS_DEVICE_NOT_READY;
896 DPRINT1("NotReady\n");
897 }
898 }
899 else
900 {
901 return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
902 }
903
904 if (Status != STATUS_PENDING)
905 {
906 Irp->IoStatus.Status = Status;
907 IoCompleteRequest(Irp, IO_NO_INCREMENT);
908 }
909
910 return Status;
911 }
912
913 NTSTATUS
914 NTAPI
915 CPortPinWaveCyclic::Read(
916 IN PDEVICE_OBJECT DeviceObject,
917 IN PIRP Irp)
918 {
919 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
920 }
921
922 NTSTATUS
923 NTAPI
924 CPortPinWaveCyclic::Write(
925 IN PDEVICE_OBJECT DeviceObject,
926 IN PIRP Irp)
927 {
928 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
929 }
930
931 NTSTATUS
932 NTAPI
933 CPortPinWaveCyclic::Flush(
934 IN PDEVICE_OBJECT DeviceObject,
935 IN PIRP Irp)
936 {
937 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
938 }
939
940 NTSTATUS
941 NTAPI
942 CPortPinWaveCyclic::Close(
943 IN PDEVICE_OBJECT DeviceObject,
944 IN PIRP Irp)
945 {
946 DPRINT("CPortPinWaveCyclic::Close entered\n");
947
948 PC_ASSERT_IRQL(PASSIVE_LEVEL);
949
950 if (m_Format)
951 {
952 // free format
953 ExFreePool(m_Format);
954 m_Format = NULL;
955 }
956
957 if (m_IrpQueue)
958 {
959 // fixme cancel irps
960 m_IrpQueue->Release();
961 }
962
963
964 if (m_Port)
965 {
966 // release reference to port driver
967 m_Port->Release();
968 m_Port = NULL;
969 }
970
971 if (m_ServiceGroup)
972 {
973 // remove member from service group
974 m_ServiceGroup->RemoveMember(PSERVICESINK(this));
975 m_ServiceGroup = NULL;
976 }
977
978 if (m_Stream)
979 {
980 if (m_State != KSSTATE_STOP)
981 {
982 // stop stream
983 NTSTATUS Status = m_Stream->SetState(KSSTATE_STOP);
984 if (!NT_SUCCESS(Status))
985 {
986 DPRINT("Warning: failed to stop stream with %x\n", Status);
987 PC_ASSERT(0);
988 }
989 }
990 // set state to stop
991 m_State = KSSTATE_STOP;
992
993
994 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
995 // release stream
996 m_Stream->Release();
997
998 }
999
1000
1001 if (m_Filter)
1002 {
1003 // release reference to filter instance
1004 m_Filter->FreePin((PPORTPINWAVECYCLIC)this);
1005 m_Filter->Release();
1006 m_Filter = NULL;
1007 }
1008
1009 Irp->IoStatus.Information = 0;
1010 Irp->IoStatus.Status = STATUS_SUCCESS;
1011 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1012
1013 delete this;
1014
1015 return STATUS_SUCCESS;
1016 }
1017
1018 NTSTATUS
1019 NTAPI
1020 CPortPinWaveCyclic::QuerySecurity(
1021 IN PDEVICE_OBJECT DeviceObject,
1022 IN PIRP Irp)
1023 {
1024 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1025 }
1026
1027 NTSTATUS
1028 NTAPI
1029 CPortPinWaveCyclic::SetSecurity(
1030 IN PDEVICE_OBJECT DeviceObject,
1031 IN PIRP Irp)
1032 {
1033 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1034 }
1035
1036 BOOLEAN
1037 NTAPI
1038 CPortPinWaveCyclic::FastDeviceIoControl(
1039 IN PFILE_OBJECT FileObject,
1040 IN BOOLEAN Wait,
1041 IN PVOID InputBuffer,
1042 IN ULONG InputBufferLength,
1043 OUT PVOID OutputBuffer,
1044 IN ULONG OutputBufferLength,
1045 IN ULONG IoControlCode,
1046 OUT PIO_STATUS_BLOCK StatusBlock,
1047 IN PDEVICE_OBJECT DeviceObject)
1048 {
1049 return KsDispatchFastIoDeviceControlFailure(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, StatusBlock, DeviceObject);
1050 }
1051
1052
1053 BOOLEAN
1054 NTAPI
1055 CPortPinWaveCyclic::FastRead(
1056 IN PFILE_OBJECT FileObject,
1057 IN PLARGE_INTEGER FileOffset,
1058 IN ULONG Length,
1059 IN BOOLEAN Wait,
1060 IN ULONG LockKey,
1061 IN PVOID Buffer,
1062 OUT PIO_STATUS_BLOCK StatusBlock,
1063 IN PDEVICE_OBJECT DeviceObject)
1064 {
1065 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
1066 }
1067
1068
1069 BOOLEAN
1070 NTAPI
1071 CPortPinWaveCyclic::FastWrite(
1072 IN PFILE_OBJECT FileObject,
1073 IN PLARGE_INTEGER FileOffset,
1074 IN ULONG Length,
1075 IN BOOLEAN Wait,
1076 IN ULONG LockKey,
1077 IN PVOID Buffer,
1078 OUT PIO_STATUS_BLOCK StatusBlock,
1079 IN PDEVICE_OBJECT DeviceObject)
1080 {
1081 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
1082 }
1083
1084
1085 NTSTATUS
1086 NTAPI
1087 CPortPinWaveCyclic::Init(
1088 IN PPORTWAVECYCLIC Port,
1089 IN PPORTFILTERWAVECYCLIC Filter,
1090 IN KSPIN_CONNECT * ConnectDetails,
1091 IN KSPIN_DESCRIPTOR * KsPinDescriptor)
1092 {
1093 NTSTATUS Status;
1094 PKSDATAFORMAT DataFormat;
1095 PDEVICE_OBJECT DeviceObject;
1096 BOOLEAN Capture;
1097 PVOID SilenceBuffer;
1098 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
1099 //IDrmAudioStream * DrmAudio = NULL;
1100
1101 m_KsPinDescriptor = KsPinDescriptor;
1102 m_ConnectDetails = ConnectDetails;
1103 m_Miniport = GetWaveCyclicMiniport(Port);
1104
1105 DeviceObject = GetDeviceObject(Port);
1106
1107 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
1108
1109 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat->FormatSize);
1110
1111 Status = NewIrpQueue(&m_IrpQueue);
1112 if (!NT_SUCCESS(Status))
1113 return Status;
1114
1115 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
1116 {
1117 Capture = FALSE;
1118 }
1119 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
1120 {
1121 Capture = TRUE;
1122 }
1123 else
1124 {
1125 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
1126 DbgBreakPoint();
1127 while(TRUE);
1128 }
1129
1130
1131 Status = m_Miniport->NewStream(&m_Stream,
1132 NULL,
1133 NonPagedPool,
1134 ConnectDetails->PinId,
1135 Capture,
1136 DataFormat,
1137 &m_DmaChannel,
1138 &m_ServiceGroup);
1139 #if 0
1140 Status = m_Stream->QueryInterface(IID_IDrmAudioStream, (PVOID*)&DrmAudio);
1141 if (NT_SUCCESS(Status))
1142 {
1143 DRMRIGHTS DrmRights;
1144 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio);
1145
1146 DrmRights.CopyProtect = FALSE;
1147 DrmRights.Reserved = 0;
1148 DrmRights.DigitalOutputDisable = FALSE;
1149
1150 Status = DrmAudio->SetContentId(1, &DrmRights);
1151 DPRINT("Status %x\n", Status);
1152 }
1153 #endif
1154
1155 DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture);
1156 DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize);
1157
1158 if (!NT_SUCCESS(Status))
1159 return Status;
1160
1161 ISubdevice * Subdevice = NULL;
1162 // get subdevice interface
1163 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
1164
1165 if (!NT_SUCCESS(Status))
1166 return Status;
1167
1168 Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
1169 if (!NT_SUCCESS(Status))
1170 {
1171 // failed to get descriptor
1172 Subdevice->Release();
1173 return Status;
1174 }
1175
1176 /* initialize event management */
1177 InitializeListHead(&m_EventList);
1178 KeInitializeSpinLock(&m_EventListLock);
1179
1180 /* set up subdevice descriptor */
1181 RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
1182 m_Descriptor.FilterPropertySet = PinWaveCyclicPropertySet;
1183 m_Descriptor.FilterPropertySetCount = sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET);
1184 m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream;
1185 m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor;
1186 m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
1187 m_Descriptor.PortPin = (PVOID)this;
1188 m_Descriptor.EventSetCount = sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET);
1189 m_Descriptor.EventSet = PinWaveCyclicEventSet;
1190 m_Descriptor.EventList = &m_EventList;
1191 m_Descriptor.EventListLock = &m_EventListLock;
1192
1193 // initialize reset state
1194 m_ResetState = KSRESET_END;
1195
1196 // release subdevice descriptor
1197 Subdevice->Release();
1198
1199 // add ourselves to service group
1200 Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
1201 if (!NT_SUCCESS(Status))
1202 {
1203 DPRINT("Failed to add pin to service group\n");
1204 return Status;
1205 }
1206
1207 m_ServiceGroup->SupportDelayedService();
1208 m_Stream->SetState(KSSTATE_STOP);
1209 m_State = KSSTATE_STOP;
1210 m_CommonBufferOffset = 0;
1211 m_CommonBufferSize = m_DmaChannel->AllocatedBufferSize();
1212 m_CommonBuffer = m_DmaChannel->SystemAddress();
1213 m_Capture = Capture;
1214 // delay of 10 milisec
1215 m_Delay = Int32x32To64(10, -10000);
1216
1217 Status = m_Stream->SetNotificationFreq(10, &m_FrameSize);
1218
1219 SilenceBuffer = AllocateItem(NonPagedPool, m_FrameSize, TAG_PORTCLASS);
1220 if (!SilenceBuffer)
1221 return STATUS_INSUFFICIENT_RESOURCES;
1222
1223
1224 /* set up allocator framing */
1225 m_AllocatorFraming.RequirementsFlags = KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
1226 m_AllocatorFraming.PoolType = NonPagedPool;
1227 m_AllocatorFraming.Frames = 8;
1228 m_AllocatorFraming.FileAlignment = FILE_64_BYTE_ALIGNMENT;
1229 m_AllocatorFraming.Reserved = 0;
1230 m_AllocatorFraming.FrameSize = m_FrameSize;
1231
1232 m_Stream->Silence(SilenceBuffer, m_FrameSize);
1233 m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize);
1234
1235 Status = m_IrpQueue->Init(ConnectDetails, DataFormat, DeviceObject, m_FrameSize, 0, SilenceBuffer);
1236 if (!NT_SUCCESS(Status))
1237 {
1238 m_IrpQueue->Release();
1239 return Status;
1240 }
1241
1242 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
1243 if (!m_Format)
1244 return STATUS_INSUFFICIENT_RESOURCES;
1245
1246 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
1247
1248 Port->AddRef();
1249 Filter->AddRef();
1250
1251 m_Port = Port;
1252 m_Filter = Filter;
1253
1254 //DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
1255 //DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
1256
1257 return STATUS_SUCCESS;
1258 }
1259
1260
1261 ULONG
1262 NTAPI
1263 CPortPinWaveCyclic::GetCompletedPosition()
1264 {
1265 UNIMPLEMENTED;
1266 return 0;
1267 }
1268
1269
1270 ULONG
1271 NTAPI
1272 CPortPinWaveCyclic::GetCycleCount()
1273 {
1274 UNIMPLEMENTED;
1275 return 0;
1276 }
1277
1278
1279 ULONG
1280 NTAPI
1281 CPortPinWaveCyclic::GetDeviceBufferSize()
1282 {
1283 return m_CommonBufferSize;
1284 }
1285
1286
1287 PVOID
1288 NTAPI
1289 CPortPinWaveCyclic::GetIrpStream()
1290 {
1291 return (PVOID)m_IrpQueue;
1292 }
1293
1294
1295 PMINIPORT
1296 NTAPI
1297 CPortPinWaveCyclic::GetMiniport()
1298 {
1299 return (PMINIPORT)m_Miniport;
1300 }
1301
1302
1303 NTSTATUS
1304 NewPortPinWaveCyclic(
1305 OUT IPortPinWaveCyclic ** OutPin)
1306 {
1307 CPortPinWaveCyclic * This;
1308
1309 This = new(NonPagedPool, TAG_PORTCLASS)CPortPinWaveCyclic(NULL);
1310 if (!This)
1311 return STATUS_INSUFFICIENT_RESOURCES;
1312
1313 This->AddRef();
1314
1315 // store result
1316 *OutPin = (IPortPinWaveCyclic*)This;
1317
1318 return STATUS_SUCCESS;
1319 }
1320