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