Sync to trunk (r44371)
[reactos.git] / reactos / 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 // store result
455 Irp->IoStatus.Information = sizeof(KSSTATE);
456 }
457 }
458 else if (Request->Flags & KSPROPERTY_TYPE_GET)
459 {
460 // get current stream state
461 *State = Pin->m_State;
462 // store result
463 Irp->IoStatus.Information = sizeof(KSSTATE);
464
465 return STATUS_SUCCESS;
466 }
467
468 // unsupported request
469 return STATUS_NOT_SUPPORTED;
470 }
471
472 NTSTATUS
473 NTAPI
474 PinWaveCyclicDataFormat(
475 IN PIRP Irp,
476 IN PKSIDENTIFIER Request,
477 IN OUT PVOID Data)
478 {
479 NTSTATUS Status = STATUS_UNSUCCESSFUL;
480 CPortPinWaveCyclic *Pin;
481 PSUBDEVICE_DESCRIPTOR Descriptor;
482 PIO_STACK_LOCATION IoStack;
483
484 // get current irp stack location
485 IoStack = IoGetCurrentIrpStackLocation(Irp);
486
487 // get sub device descriptor
488 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
489
490 // sanity check
491 PC_ASSERT(Descriptor);
492 PC_ASSERT(Descriptor->PortPin);
493
494 // cast to pin impl
495 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
496
497 //sanity check
498 PC_ASSERT(Pin->m_Stream);
499 PC_ASSERT(Pin->m_Format);
500
501 if (Request->Flags & KSPROPERTY_TYPE_SET)
502 {
503 // try to change data format
504 PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
505 ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize);
506
507 if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size)
508 {
509 // format is identical
510 Irp->IoStatus.Information = DataFormat->FormatSize;
511 return STATUS_SUCCESS;
512 }
513
514 // new change request
515 PC_ASSERT(Pin->m_State != KSSTATE_RUN);
516 // FIXME queue a work item when Irql != PASSIVE_LEVEL
517 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
518
519 // allocate new data format
520 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
521 if (!NewDataFormat)
522 {
523 // not enough memory
524 return STATUS_NO_MEMORY;
525 }
526
527 // copy new data format
528 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
529
530 // set new format
531 Status = Pin->m_Stream->SetFormat(NewDataFormat);
532 if (NT_SUCCESS(Status))
533 {
534 // free old format
535 FreeItem(Pin->m_Format, TAG_PORTCLASS);
536
537 // update irp queue with new format
538 Pin->m_IrpQueue->UpdateFormat((PKSDATAFORMAT)NewDataFormat);
539
540 // store new format
541 Pin->m_Format = NewDataFormat;
542 Irp->IoStatus.Information = NewDataFormat->FormatSize;
543
544 #if 0
545 PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
546 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO));
547 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM));
548 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
549
550
551 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
552 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
553 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
554 #endif
555
556 }
557 else
558 {
559 // failed to set format
560 FreeItem(NewDataFormat, TAG_PORTCLASS);
561 }
562
563
564 // done
565 return Status;
566 }
567 else if (Request->Flags & KSPROPERTY_TYPE_GET)
568 {
569 // get current data format
570 PC_ASSERT(Pin->m_Format);
571
572 if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
573 {
574 // buffer too small
575 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
576 return STATUS_MORE_ENTRIES;
577 }
578 // copy data format
579 RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize);
580 // store result size
581 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
582
583 // done
584 return STATUS_SUCCESS;
585 }
586
587 // unsupported request
588 return STATUS_NOT_SUPPORTED;
589 }
590
591 VOID
592 CPortPinWaveCyclic::GeneratePositionEvents(
593 IN ULONGLONG OldOffset,
594 IN ULONGLONG NewOffset)
595 {
596 PLIST_ENTRY Entry;
597 PKSEVENT_ENTRY EventEntry;
598 PLOOPEDSTREAMING_EVENT_CONTEXT Context;
599
600 // acquire event lock
601 KeAcquireSpinLockAtDpcLevel(&m_EventListLock);
602
603 // point to first entry
604 Entry = m_EventList.Flink;
605
606 while(Entry != &m_EventList)
607 {
608 // get event entry
609 EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry);
610
611 // get event entry context
612 Context = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
613
614 if (Context->bLoopedStreaming == TRUE)
615 {
616 if (NewOffset > OldOffset)
617 {
618 /* buffer progress no overlap */
619 if (OldOffset < Context->Position && Context->Position <= NewOffset)
620 {
621 /* when someone eventually fixes sprintf... */
622 DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
623 DPRINT("Context->Position %I64u\n", Context->Position);
624 DPRINT("NewOffset %I64u\n", NewOffset);
625 /* generate event */
626 KsGenerateEvent(EventEntry);
627 }
628 }
629 else
630 {
631 /* buffer wrap-arround */
632 if (OldOffset < Context->Position || NewOffset > Context->Position)
633 {
634 /* when someone eventually fixes sprintf... */
635 DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
636 DPRINT("Context->Position %I64u\n", Context->Position);
637 DPRINT("NewOffset %I64u\n", NewOffset);
638 /* generate event */
639 KsGenerateEvent(EventEntry);
640 }
641 }
642 }
643
644 // move to next entry
645 Entry = Entry->Flink;
646 }
647
648 // release lock
649 KeReleaseSpinLockFromDpcLevel(&m_EventListLock);
650 }
651
652 VOID
653 CPortPinWaveCyclic::UpdateCommonBuffer(
654 ULONG Position,
655 ULONG MaxTransferCount)
656 {
657 ULONG BufferLength;
658 ULONG BytesToCopy;
659 ULONG BufferSize;
660 PUCHAR Buffer;
661 NTSTATUS Status;
662
663 BufferLength = Position - m_CommonBufferOffset;
664 BufferLength = min(BufferLength, MaxTransferCount);
665
666 while(BufferLength)
667 {
668 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
669 if (!NT_SUCCESS(Status))
670 return;
671
672 BytesToCopy = min(BufferLength, BufferSize);
673
674 if (m_Capture)
675 {
676 m_DmaChannel->CopyFrom(Buffer, (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BytesToCopy);
677 }
678 else
679 {
680 m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, Buffer, BytesToCopy);
681 }
682
683 m_IrpQueue->UpdateMapping(BytesToCopy);
684 m_CommonBufferOffset += BytesToCopy;
685
686 BufferLength = Position - m_CommonBufferOffset;
687 m_Position.PlayOffset += BytesToCopy;
688
689 if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
690 {
691 // normalize position
692 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
693 }
694 }
695 }
696
697 VOID
698 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
699 ULONG Position,
700 ULONG MaxTransferCount)
701 {
702 ULONG BufferLength, Length, Gap;
703 ULONG BytesToCopy;
704 ULONG BufferSize;
705 PUCHAR Buffer;
706 NTSTATUS Status;
707
708
709 BufferLength = Gap = m_CommonBufferSize - m_CommonBufferOffset;
710 BufferLength = Length = min(BufferLength, MaxTransferCount);
711 while(BufferLength)
712 {
713 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
714 if (!NT_SUCCESS(Status))
715 return;
716
717 BytesToCopy = min(BufferLength, BufferSize);
718
719 if (m_Capture)
720 {
721 m_DmaChannel->CopyFrom(Buffer,
722 (PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
723 BytesToCopy);
724 }
725 else
726 {
727 m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
728 Buffer,
729 BytesToCopy);
730 }
731
732 m_IrpQueue->UpdateMapping(BytesToCopy);
733 m_CommonBufferOffset += BytesToCopy;
734 m_Position.PlayOffset += BytesToCopy;
735
736 BufferLength = m_CommonBufferSize - m_CommonBufferOffset;
737
738 if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
739 {
740 // normalize position
741 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
742 }
743
744 }
745
746 if (Gap == Length)
747 {
748 m_CommonBufferOffset = 0;
749
750 MaxTransferCount -= Length;
751
752 if (MaxTransferCount)
753 {
754 UpdateCommonBuffer(Position, MaxTransferCount);
755 }
756 }
757 }
758
759 VOID
760 NTAPI
761 CPortPinWaveCyclic::RequestService()
762 {
763 ULONG Position;
764 NTSTATUS Status;
765 PUCHAR Buffer;
766 ULONG BufferSize;
767 ULONGLONG OldOffset, NewOffset;
768
769 PC_ASSERT_IRQL(DISPATCH_LEVEL);
770
771 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
772 if (!NT_SUCCESS(Status))
773 {
774 return;
775 }
776
777 Status = m_Stream->GetPosition(&Position);
778 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position, Buffer, m_CommonBufferSize, BufferSize, m_Capture);
779
780 OldOffset = m_Position.PlayOffset;
781
782 if (Position < m_CommonBufferOffset)
783 {
784 UpdateCommonBufferOverlap(Position, m_FrameSize);
785 }
786 else if (Position >= m_CommonBufferOffset)
787 {
788 UpdateCommonBuffer(Position, m_FrameSize);
789 }
790
791 NewOffset = m_Position.PlayOffset;
792
793 GeneratePositionEvents(OldOffset, NewOffset);
794 }
795
796 NTSTATUS
797 NTAPI
798 CPortPinWaveCyclic::NewIrpTarget(
799 OUT struct IIrpTarget **OutTarget,
800 IN PCWSTR Name,
801 IN PUNKNOWN Unknown,
802 IN POOL_TYPE PoolType,
803 IN PDEVICE_OBJECT DeviceObject,
804 IN PIRP Irp,
805 IN KSOBJECT_CREATE *CreateObject)
806 {
807 UNIMPLEMENTED
808 return STATUS_UNSUCCESSFUL;
809 }
810
811 NTSTATUS
812 NTAPI
813 CPortPinWaveCyclic::DeviceIoControl(
814 IN PDEVICE_OBJECT DeviceObject,
815 IN PIRP Irp)
816 {
817 PIO_STACK_LOCATION IoStack;
818 PKSPROPERTY Property;
819 UNICODE_STRING GuidString;
820 NTSTATUS Status = STATUS_NOT_SUPPORTED;
821 ULONG Data = 0;
822 KSRESET ResetValue;
823
824 /* get current irp stack location */
825 IoStack = IoGetCurrentIrpStackLocation(Irp);
826
827 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
828 {
829 /* handle property with subdevice descriptor */
830 Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
831
832 if (Status == STATUS_NOT_FOUND)
833 {
834 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
835
836 RtlStringFromGUID(Property->Set, &GuidString);
837 DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
838 RtlFreeUnicodeString(&GuidString);
839 }
840 }
841 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
842 {
843 Status = PcHandleEnableEventWithTable(Irp, &m_Descriptor);
844 }
845 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
846 {
847 Status = PcHandleDisableEventWithTable(Irp, &m_Descriptor);
848 }
849 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
850 {
851 /// FIXME
852 Status = KsAcquireResetValue(Irp, &ResetValue);
853 DPRINT("Status %x Value %u\n", Status, ResetValue);
854 /* check for success */
855 if (NT_SUCCESS(Status))
856 {
857 if (ResetValue == KSRESET_BEGIN)
858 {
859 m_IrpQueue->CancelBuffers();
860 m_ResetState = KSRESET_BEGIN;
861 }
862 else if (ResetValue == KSRESET_END)
863 {
864 m_ResetState = KSRESET_END;
865 }
866 }
867 }
868 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
869 {
870 /* increment total number of packets */
871 InterlockedIncrement((PLONG)&m_TotalPackets);
872
873 DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
874
875 /* is the device not currently reset */
876 if (m_ResetState == KSRESET_END)
877 {
878 /* add the mapping */
879 Status = m_IrpQueue->AddMapping(Irp, &Data);
880
881 /* check for success */
882 if (NT_SUCCESS(Status))
883 {
884 m_Position.WriteOffset += Data;
885 Status = STATUS_PENDING;
886 }
887 }
888 else
889 {
890 /* reset request is currently in progress */
891 Status = STATUS_DEVICE_NOT_READY;
892 DPRINT1("NotReady\n");
893 }
894 }
895 else
896 {
897 return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
898 }
899
900 if (Status != STATUS_PENDING)
901 {
902 Irp->IoStatus.Status = Status;
903 IoCompleteRequest(Irp, IO_NO_INCREMENT);
904 }
905
906 return Status;
907 }
908
909 NTSTATUS
910 NTAPI
911 CPortPinWaveCyclic::Read(
912 IN PDEVICE_OBJECT DeviceObject,
913 IN PIRP Irp)
914 {
915 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
916 }
917
918 NTSTATUS
919 NTAPI
920 CPortPinWaveCyclic::Write(
921 IN PDEVICE_OBJECT DeviceObject,
922 IN PIRP Irp)
923 {
924 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
925 }
926
927 NTSTATUS
928 NTAPI
929 CPortPinWaveCyclic::Flush(
930 IN PDEVICE_OBJECT DeviceObject,
931 IN PIRP Irp)
932 {
933 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
934 }
935
936 NTSTATUS
937 NTAPI
938 CPortPinWaveCyclic::Close(
939 IN PDEVICE_OBJECT DeviceObject,
940 IN PIRP Irp)
941 {
942 DPRINT("CPortPinWaveCyclic::Close entered\n");
943
944 PC_ASSERT_IRQL(PASSIVE_LEVEL);
945
946 if (m_Format)
947 {
948 // free format
949 ExFreePool(m_Format);
950 m_Format = NULL;
951 }
952
953 if (m_IrpQueue)
954 {
955 // fixme cancel irps
956 m_IrpQueue->Release();
957 }
958
959
960 if (m_Port)
961 {
962 // release reference to port driver
963 m_Port->Release();
964 m_Port = NULL;
965 }
966
967 if (m_ServiceGroup)
968 {
969 // remove member from service group
970 m_ServiceGroup->RemoveMember(PSERVICESINK(this));
971 m_ServiceGroup = NULL;
972 }
973
974 if (m_Stream)
975 {
976 if (m_State != KSSTATE_STOP)
977 {
978 // stop stream
979 NTSTATUS Status = m_Stream->SetState(KSSTATE_STOP);
980 if (!NT_SUCCESS(Status))
981 {
982 DPRINT("Warning: failed to stop stream with %x\n", Status);
983 PC_ASSERT(0);
984 }
985 }
986 // set state to stop
987 m_State = KSSTATE_STOP;
988
989
990 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
991 // release stream
992 m_Stream->Release();
993
994 }
995
996
997 if (m_Filter)
998 {
999 // release reference to filter instance
1000 m_Filter->FreePin((PPORTPINWAVECYCLIC)this);
1001 m_Filter->Release();
1002 m_Filter = NULL;
1003 }
1004
1005 Irp->IoStatus.Information = 0;
1006 Irp->IoStatus.Status = STATUS_SUCCESS;
1007 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1008
1009 delete this;
1010
1011 return STATUS_SUCCESS;
1012 }
1013
1014 NTSTATUS
1015 NTAPI
1016 CPortPinWaveCyclic::QuerySecurity(
1017 IN PDEVICE_OBJECT DeviceObject,
1018 IN PIRP Irp)
1019 {
1020 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1021 }
1022
1023 NTSTATUS
1024 NTAPI
1025 CPortPinWaveCyclic::SetSecurity(
1026 IN PDEVICE_OBJECT DeviceObject,
1027 IN PIRP Irp)
1028 {
1029 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1030 }
1031
1032 BOOLEAN
1033 NTAPI
1034 CPortPinWaveCyclic::FastDeviceIoControl(
1035 IN PFILE_OBJECT FileObject,
1036 IN BOOLEAN Wait,
1037 IN PVOID InputBuffer,
1038 IN ULONG InputBufferLength,
1039 OUT PVOID OutputBuffer,
1040 IN ULONG OutputBufferLength,
1041 IN ULONG IoControlCode,
1042 OUT PIO_STATUS_BLOCK StatusBlock,
1043 IN PDEVICE_OBJECT DeviceObject)
1044 {
1045 return KsDispatchFastIoDeviceControlFailure(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, StatusBlock, DeviceObject);
1046 }
1047
1048
1049 BOOLEAN
1050 NTAPI
1051 CPortPinWaveCyclic::FastRead(
1052 IN PFILE_OBJECT FileObject,
1053 IN PLARGE_INTEGER FileOffset,
1054 IN ULONG Length,
1055 IN BOOLEAN Wait,
1056 IN ULONG LockKey,
1057 IN PVOID Buffer,
1058 OUT PIO_STATUS_BLOCK StatusBlock,
1059 IN PDEVICE_OBJECT DeviceObject)
1060 {
1061 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
1062 }
1063
1064
1065 BOOLEAN
1066 NTAPI
1067 CPortPinWaveCyclic::FastWrite(
1068 IN PFILE_OBJECT FileObject,
1069 IN PLARGE_INTEGER FileOffset,
1070 IN ULONG Length,
1071 IN BOOLEAN Wait,
1072 IN ULONG LockKey,
1073 IN PVOID Buffer,
1074 OUT PIO_STATUS_BLOCK StatusBlock,
1075 IN PDEVICE_OBJECT DeviceObject)
1076 {
1077 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
1078 }
1079
1080
1081 NTSTATUS
1082 NTAPI
1083 CPortPinWaveCyclic::Init(
1084 IN PPORTWAVECYCLIC Port,
1085 IN PPORTFILTERWAVECYCLIC Filter,
1086 IN KSPIN_CONNECT * ConnectDetails,
1087 IN KSPIN_DESCRIPTOR * KsPinDescriptor)
1088 {
1089 NTSTATUS Status;
1090 PKSDATAFORMAT DataFormat;
1091 PDEVICE_OBJECT DeviceObject;
1092 BOOLEAN Capture;
1093 PVOID SilenceBuffer;
1094 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
1095 //IDrmAudioStream * DrmAudio = NULL;
1096
1097 m_KsPinDescriptor = KsPinDescriptor;
1098 m_ConnectDetails = ConnectDetails;
1099 m_Miniport = GetWaveCyclicMiniport(Port);
1100
1101 DeviceObject = GetDeviceObject(Port);
1102
1103 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
1104
1105 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat->FormatSize);
1106
1107 Status = NewIrpQueue(&m_IrpQueue);
1108 if (!NT_SUCCESS(Status))
1109 return Status;
1110
1111 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
1112 {
1113 Capture = FALSE;
1114 }
1115 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
1116 {
1117 Capture = TRUE;
1118 }
1119 else
1120 {
1121 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
1122 DbgBreakPoint();
1123 while(TRUE);
1124 }
1125
1126
1127 Status = m_Miniport->NewStream(&m_Stream,
1128 NULL,
1129 NonPagedPool,
1130 ConnectDetails->PinId,
1131 Capture,
1132 DataFormat,
1133 &m_DmaChannel,
1134 &m_ServiceGroup);
1135 #if 0
1136 Status = m_Stream->QueryInterface(IID_IDrmAudioStream, (PVOID*)&DrmAudio);
1137 if (NT_SUCCESS(Status))
1138 {
1139 DRMRIGHTS DrmRights;
1140 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio);
1141
1142 DrmRights.CopyProtect = FALSE;
1143 DrmRights.Reserved = 0;
1144 DrmRights.DigitalOutputDisable = FALSE;
1145
1146 Status = DrmAudio->SetContentId(1, &DrmRights);
1147 DPRINT("Status %x\n", Status);
1148 }
1149 #endif
1150
1151 DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture);
1152 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);
1153
1154 if (!NT_SUCCESS(Status))
1155 return Status;
1156
1157 ISubdevice * Subdevice = NULL;
1158 // get subdevice interface
1159 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
1160
1161 if (!NT_SUCCESS(Status))
1162 return Status;
1163
1164 Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
1165 if (!NT_SUCCESS(Status))
1166 {
1167 // failed to get descriptor
1168 Subdevice->Release();
1169 return Status;
1170 }
1171
1172 /* initialize event management */
1173 InitializeListHead(&m_EventList);
1174 KeInitializeSpinLock(&m_EventListLock);
1175
1176 /* set up subdevice descriptor */
1177 RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
1178 m_Descriptor.FilterPropertySet = PinWaveCyclicPropertySet;
1179 m_Descriptor.FilterPropertySetCount = sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET);
1180 m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream;
1181 m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor;
1182 m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
1183 m_Descriptor.PortPin = (PVOID)this;
1184 m_Descriptor.EventSetCount = sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET);
1185 m_Descriptor.EventSet = PinWaveCyclicEventSet;
1186 m_Descriptor.EventList = &m_EventList;
1187 m_Descriptor.EventListLock = &m_EventListLock;
1188
1189 // initialize reset state
1190 m_ResetState = KSRESET_END;
1191
1192 // release subdevice descriptor
1193 Subdevice->Release();
1194
1195 // add ourselves to service group
1196 Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
1197 if (!NT_SUCCESS(Status))
1198 {
1199 DPRINT("Failed to add pin to service group\n");
1200 return Status;
1201 }
1202
1203 m_ServiceGroup->SupportDelayedService();
1204 m_Stream->SetState(KSSTATE_STOP);
1205 m_State = KSSTATE_STOP;
1206 m_CommonBufferOffset = 0;
1207 m_CommonBufferSize = m_DmaChannel->AllocatedBufferSize();
1208 m_CommonBuffer = m_DmaChannel->SystemAddress();
1209 m_Capture = Capture;
1210 // delay of 10 milisec
1211 m_Delay = Int32x32To64(10, -10000);
1212
1213 Status = m_Stream->SetNotificationFreq(10, &m_FrameSize);
1214
1215 SilenceBuffer = AllocateItem(NonPagedPool, m_FrameSize, TAG_PORTCLASS);
1216 if (!SilenceBuffer)
1217 return STATUS_INSUFFICIENT_RESOURCES;
1218
1219
1220 /* set up allocator framing */
1221 m_AllocatorFraming.RequirementsFlags = KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
1222 m_AllocatorFraming.PoolType = NonPagedPool;
1223 m_AllocatorFraming.Frames = 8;
1224 m_AllocatorFraming.FileAlignment = FILE_64_BYTE_ALIGNMENT;
1225 m_AllocatorFraming.Reserved = 0;
1226 m_AllocatorFraming.FrameSize = m_FrameSize;
1227
1228 m_Stream->Silence(SilenceBuffer, m_FrameSize);
1229 m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize);
1230
1231 Status = m_IrpQueue->Init(ConnectDetails, DataFormat, DeviceObject, m_FrameSize, 0, SilenceBuffer);
1232 if (!NT_SUCCESS(Status))
1233 {
1234 m_IrpQueue->Release();
1235 return Status;
1236 }
1237
1238 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
1239 if (!m_Format)
1240 return STATUS_INSUFFICIENT_RESOURCES;
1241
1242 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
1243
1244 Port->AddRef();
1245 Filter->AddRef();
1246
1247 m_Port = Port;
1248 m_Filter = Filter;
1249
1250 //DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
1251 //DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
1252
1253 return STATUS_SUCCESS;
1254 }
1255
1256
1257 ULONG
1258 NTAPI
1259 CPortPinWaveCyclic::GetCompletedPosition()
1260 {
1261 UNIMPLEMENTED;
1262 return 0;
1263 }
1264
1265
1266 ULONG
1267 NTAPI
1268 CPortPinWaveCyclic::GetCycleCount()
1269 {
1270 UNIMPLEMENTED;
1271 return 0;
1272 }
1273
1274
1275 ULONG
1276 NTAPI
1277 CPortPinWaveCyclic::GetDeviceBufferSize()
1278 {
1279 return m_CommonBufferSize;
1280 }
1281
1282
1283 PVOID
1284 NTAPI
1285 CPortPinWaveCyclic::GetIrpStream()
1286 {
1287 return (PVOID)m_IrpQueue;
1288 }
1289
1290
1291 PMINIPORT
1292 NTAPI
1293 CPortPinWaveCyclic::GetMiniport()
1294 {
1295 return (PMINIPORT)m_Miniport;
1296 }
1297
1298
1299 NTSTATUS
1300 NewPortPinWaveCyclic(
1301 OUT IPortPinWaveCyclic ** OutPin)
1302 {
1303 CPortPinWaveCyclic * This;
1304
1305 This = new(NonPagedPool, TAG_PORTCLASS)CPortPinWaveCyclic(NULL);
1306 if (!This)
1307 return STATUS_INSUFFICIENT_RESOURCES;
1308
1309 This->AddRef();
1310
1311 // store result
1312 *OutPin = (IPortPinWaveCyclic*)This;
1313
1314 return STATUS_SUCCESS;
1315 }
1316