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