1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp
5 * PURPOSE: WavePci IRP Audio Pin
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 class CPortPinWavePci : public CUnknownImpl<IPortPinWavePci, IServiceSink, IPortWavePciStream>
15 {
16 public:
17 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
18
19 IMP_IPortPinWavePci;
20 IMP_IServiceSink;
21 IMP_IPortWavePciStream;
CPortPinWavePci(IUnknown * OuterUnknown)22 CPortPinWavePci(IUnknown *OuterUnknown) {}
~CPortPinWavePci()23 virtual ~CPortPinWavePci(){}
24 protected:
25
26 friend NTSTATUS NTAPI PinWavePciState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
27 friend NTSTATUS NTAPI PinWavePciDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
28 friend NTSTATUS NTAPI PinWavePciAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
29 friend NTSTATUS NTAPI PinWavePciAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
30
31 IPortWavePci * m_Port;
32 IPortFilterWavePci * m_Filter;
33 KSPIN_DESCRIPTOR * m_KsPinDescriptor;
34 PMINIPORTWAVEPCI m_Miniport;
35 PSERVICEGROUP m_ServiceGroup;
36 PDMACHANNEL m_DmaChannel;
37 PMINIPORTWAVEPCISTREAM m_Stream;
38 KSSTATE m_State;
39 PKSDATAFORMAT m_Format;
40 KSPIN_CONNECT * m_ConnectDetails;
41
42 BOOL m_Capture;
43 PDEVICE_OBJECT m_DeviceObject;
44 IIrpQueue * m_IrpQueue;
45
46 ULONG m_TotalPackets;
47 KSAUDIO_POSITION m_Position;
48 ULONG m_StopCount;
49
50 BOOL m_bUsePrefetch;
51 ULONG m_PrefetchOffset;
52 SUBDEVICE_DESCRIPTOR m_Descriptor;
53
54 KSALLOCATOR_FRAMING m_AllocatorFraming;
55
56 NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp);
57 NTSTATUS NTAPI HandleKsStream(IN PIRP Irp);
58 };
59
60 typedef struct
61 {
62 CPortPinWavePci *Pin;
63 PIO_WORKITEM WorkItem;
64 KSSTATE State;
65 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
66
67 NTSTATUS NTAPI PinWavePciState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
68 NTSTATUS NTAPI PinWavePciDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
69 NTSTATUS NTAPI PinWavePciAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
70 NTSTATUS NTAPI PinWavePciAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
71
72 DEFINE_KSPROPERTY_CONNECTIONSET(PinWavePciConnectionSet, PinWavePciState, PinWavePciDataFormat, PinWavePciAllocatorFraming);
73 DEFINE_KSPROPERTY_AUDIOSET(PinWavePciAudioSet, PinWavePciAudioPosition);
74
75 KSPROPERTY_SET PinWavePciPropertySet[] =
76 {
77 {
78 &KSPROPSETID_Connection,
79 sizeof(PinWavePciConnectionSet) / sizeof(KSPROPERTY_ITEM),
80 (const KSPROPERTY_ITEM*)&PinWavePciConnectionSet,
81 0,
82 NULL
83 },
84 {
85 &KSPROPSETID_Audio,
86 sizeof(PinWavePciAudioSet) / sizeof(KSPROPERTY_ITEM),
87 (const KSPROPERTY_ITEM*)&PinWavePciAudioSet,
88 0,
89 NULL
90 }
91 };
92
93 NTSTATUS
94 NTAPI
PinWavePciAllocatorFraming(IN PIRP Irp,IN PKSIDENTIFIER Request,IN OUT PVOID Data)95 PinWavePciAllocatorFraming(
96 IN PIRP Irp,
97 IN PKSIDENTIFIER Request,
98 IN OUT PVOID Data)
99 {
100 CPortPinWavePci *Pin;
101 PSUBDEVICE_DESCRIPTOR Descriptor;
102
103 // get sub device descriptor
104 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
105
106 // sanity check
107 PC_ASSERT(Descriptor);
108 PC_ASSERT(Descriptor->PortPin);
109 PC_ASSERT_IRQL(DISPATCH_LEVEL);
110
111 // cast to pin impl
112 Pin = (CPortPinWavePci*)Descriptor->PortPin;
113
114 if (Request->Flags & KSPROPERTY_TYPE_GET)
115 {
116 // copy pin framing
117 RtlMoveMemory(Data, &Pin->m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING));
118
119 Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING);
120 return STATUS_SUCCESS;
121 }
122
123 // not supported
124 return STATUS_NOT_SUPPORTED;
125 }
126
127 NTSTATUS
128 NTAPI
PinWavePciAudioPosition(IN PIRP Irp,IN PKSIDENTIFIER Request,IN OUT PVOID Data)129 PinWavePciAudioPosition(
130 IN PIRP Irp,
131 IN PKSIDENTIFIER Request,
132 IN OUT PVOID Data)
133 {
134 CPortPinWavePci *Pin;
135 PSUBDEVICE_DESCRIPTOR Descriptor;
136
137 // get sub device descriptor
138 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
139
140 // sanity check
141 PC_ASSERT(Descriptor);
142 PC_ASSERT(Descriptor->PortPin);
143 PC_ASSERT_IRQL(DISPATCH_LEVEL);
144
145 // cast to pin impl
146 Pin = (CPortPinWavePci*)Descriptor->PortPin;
147
148 //sanity check
149 PC_ASSERT(Pin->m_Stream);
150
151 if (Request->Flags & KSPROPERTY_TYPE_GET)
152 {
153 // FIXME non multithreading-safe
154 // copy audio position
155 RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
156
157 DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset);
158 Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION);
159 return STATUS_SUCCESS;
160 }
161
162 // not supported
163 return STATUS_NOT_SUPPORTED;
164 }
165
166 NTSTATUS
167 NTAPI
PinWavePciState(IN PIRP Irp,IN PKSIDENTIFIER Request,IN OUT PVOID Data)168 PinWavePciState(
169 IN PIRP Irp,
170 IN PKSIDENTIFIER Request,
171 IN OUT PVOID Data)
172 {
173 NTSTATUS Status = STATUS_UNSUCCESSFUL;
174 CPortPinWavePci *Pin;
175 PSUBDEVICE_DESCRIPTOR Descriptor;
176 PVOID FirstTag, LastTag;
177 ULONG MappingsRevoked;
178 PKSSTATE State = (PKSSTATE)Data;
179
180 // get sub device descriptor
181 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
182
183 // sanity check
184 PC_ASSERT(Descriptor);
185 PC_ASSERT(Descriptor->PortPin);
186 PC_ASSERT_IRQL(DISPATCH_LEVEL);
187
188 // cast to pin impl
189 Pin = (CPortPinWavePci*)Descriptor->PortPin;
190
191 //sanity check
192 PC_ASSERT(Pin->m_Stream);
193
194 if (Request->Flags & KSPROPERTY_TYPE_SET)
195 {
196 // try set stream
197 Status = Pin->m_Stream->SetState(*State);
198
199 DPRINT("Setting state %u %x\n", *State, Status);
200 if (NT_SUCCESS(Status))
201 {
202 // store new state
203 Pin->m_State = *State;
204 if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP)
205 {
206 // FIXME
207 // complete with successful state
208 Pin->m_IrpQueue->CancelBuffers();
209 while(Pin->m_IrpQueue->GetAcquiredTagRange(&FirstTag, &LastTag))
210 {
211 Status = Pin->m_Stream->RevokeMappings(FirstTag, LastTag, &MappingsRevoked);
212 DPRINT("RevokeMappings Status %lx MappingsRevoked: %lu\n", Status, MappingsRevoked);
213 KeStallExecutionProcessor(10);
214 }
215 Pin->m_Position.PlayOffset = 0;
216 Pin->m_Position.WriteOffset = 0;
217 }
218 else if (Pin->m_State == KSSTATE_STOP)
219 {
220 Pin->m_IrpQueue->CancelBuffers();
221 while(Pin->m_IrpQueue->GetAcquiredTagRange(&FirstTag, &LastTag))
222 {
223 Status = Pin->m_Stream->RevokeMappings(FirstTag, LastTag, &MappingsRevoked);
224 DPRINT("RevokeMappings Status %lx MappingsRevoked: %lu\n", Status, MappingsRevoked);
225 KeStallExecutionProcessor(10);
226 }
227 Pin->m_Position.PlayOffset = 0;
228 Pin->m_Position.WriteOffset = 0;
229 }
230 // store result
231 Irp->IoStatus.Information = sizeof(KSSTATE);
232
233 }
234 // store result
235 Irp->IoStatus.Information = sizeof(KSSTATE);
236 return Status;
237 }
238 else if (Request->Flags & KSPROPERTY_TYPE_GET)
239 {
240 // get current stream state
241 *State = Pin->m_State;
242 // store result
243 Irp->IoStatus.Information = sizeof(KSSTATE);
244
245 return STATUS_SUCCESS;
246 }
247
248 // unsupported request
249 return STATUS_NOT_SUPPORTED;
250 }
251
252 NTSTATUS
253 NTAPI
PinWavePciDataFormat(IN PIRP Irp,IN PKSIDENTIFIER Request,IN OUT PVOID Data)254 PinWavePciDataFormat(
255 IN PIRP Irp,
256 IN PKSIDENTIFIER Request,
257 IN OUT PVOID Data)
258 {
259 NTSTATUS Status = STATUS_UNSUCCESSFUL;
260 CPortPinWavePci *Pin;
261 PSUBDEVICE_DESCRIPTOR Descriptor;
262 PIO_STACK_LOCATION IoStack;
263
264 // get current irp stack location
265 IoStack = IoGetCurrentIrpStackLocation(Irp);
266
267 // get sub device descriptor
268 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
269
270 // sanity check
271 PC_ASSERT(Descriptor);
272 PC_ASSERT(Descriptor->PortPin);
273
274 // cast to pin impl
275 Pin = (CPortPinWavePci*)Descriptor->PortPin;
276
277 //sanity check
278 PC_ASSERT(Pin->m_Stream);
279 PC_ASSERT(Pin->m_Format);
280
281 if (Request->Flags & KSPROPERTY_TYPE_SET)
282 {
283 // try to change data format
284 PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
285 ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize);
286
287 if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size)
288 {
289 // format is identical
290 Irp->IoStatus.Information = DataFormat->FormatSize;
291 return STATUS_SUCCESS;
292 }
293
294 // new change request
295 PC_ASSERT(Pin->m_State == KSSTATE_STOP);
296 // FIXME queue a work item when Irql != PASSIVE_LEVEL
297 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
298
299 // allocate new data format
300 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
301 if (!NewDataFormat)
302 {
303 // not enough memory
304 return STATUS_NO_MEMORY;
305 }
306
307 // copy new data format
308 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
309
310 // set new format
311 Status = Pin->m_Stream->SetFormat(NewDataFormat);
312 if (NT_SUCCESS(Status))
313 {
314 // free old format
315 FreeItem(Pin->m_Format, TAG_PORTCLASS);
316
317 // store new format
318 Pin->m_Format = NewDataFormat;
319 Irp->IoStatus.Information = NewDataFormat->FormatSize;
320
321 #if 0
322 PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
323 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO));
324 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM));
325 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
326
327 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
328 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
329 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
330 #endif
331
332 }
333 else
334 {
335 // failed to set format
336 FreeItem(NewDataFormat, TAG_PORTCLASS);
337 }
338
339 // done
340 return Status;
341 }
342 else if (Request->Flags & KSPROPERTY_TYPE_GET)
343 {
344 // get current data format
345 PC_ASSERT(Pin->m_Format);
346
347 if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
348 {
349 // buffer too small
350 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
351 return STATUS_MORE_ENTRIES;
352 }
353 // copy data format
354 RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize);
355 // store result size
356 Irp->IoStatus.Information = Pin->m_Format->FormatSize;
357
358 // done
359 return STATUS_SUCCESS;
360 }
361
362 // unsupported request
363 return STATUS_NOT_SUPPORTED;
364 }
365
366 //==================================================================================================================================
367
368 NTSTATUS
369 NTAPI
QueryInterface(IN REFIID refiid,OUT PVOID * Output)370 CPortPinWavePci::QueryInterface(
371 IN REFIID refiid,
372 OUT PVOID* Output)
373 {
374 //DPRINT("CPortPinWavePci::QueryInterface entered\n");
375
376 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
377 IsEqualGUIDAligned(refiid, IID_IUnknown))
378 {
379 *Output = PVOID(PUNKNOWN((IIrpTarget*)this));
380 PUNKNOWN(*Output)->AddRef();
381 return STATUS_SUCCESS;
382 }
383
384 if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
385 {
386 *Output = PVOID(PSERVICESINK(this));
387 PUNKNOWN(*Output)->AddRef();
388 return STATUS_SUCCESS;
389 }
390
391 if (IsEqualGUIDAligned(refiid, IID_IPortWavePciStream))
392 {
393 *Output = PVOID(PPORTWAVEPCISTREAM(this));
394 PUNKNOWN(*Output)->AddRef();
395 return STATUS_SUCCESS;
396 }
397
398 return STATUS_UNSUCCESSFUL;
399 }
400
401 NTSTATUS
402 NTAPI
GetMapping(IN PVOID Tag,OUT PPHYSICAL_ADDRESS PhysicalAddress,OUT PVOID * VirtualAddress,OUT PULONG ByteCount,OUT PULONG Flags)403 CPortPinWavePci::GetMapping(
404 IN PVOID Tag,
405 OUT PPHYSICAL_ADDRESS PhysicalAddress,
406 OUT PVOID *VirtualAddress,
407 OUT PULONG ByteCount,
408 OUT PULONG Flags)
409 {
410
411 PC_ASSERT_IRQL(DISPATCH_LEVEL);
412 return m_IrpQueue->GetMappingWithTag(Tag, PhysicalAddress, VirtualAddress, ByteCount, Flags);
413 }
414
415 NTSTATUS
416 NTAPI
ReleaseMapping(IN PVOID Tag)417 CPortPinWavePci::ReleaseMapping(
418 IN PVOID Tag)
419 {
420
421 PC_ASSERT_IRQL(DISPATCH_LEVEL);
422 return m_IrpQueue->ReleaseMappingWithTag(Tag);
423 }
424
425 NTSTATUS
426 NTAPI
TerminatePacket()427 CPortPinWavePci::TerminatePacket()
428 {
429 UNIMPLEMENTED;
430 PC_ASSERT_IRQL(DISPATCH_LEVEL);
431 return STATUS_SUCCESS;
432 }
433
434 VOID
435 NTAPI
RequestService()436 CPortPinWavePci::RequestService()
437 {
438 PC_ASSERT_IRQL(DISPATCH_LEVEL);
439
440 if (m_State == KSSTATE_RUN)
441 {
442 m_Stream->Service();
443 //TODO
444 //generate events
445 }
446 }
447
448 //==================================================================================================================================
449
450 NTSTATUS
451 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)452 CPortPinWavePci::NewIrpTarget(
453 OUT struct IIrpTarget **OutTarget,
454 IN PCWSTR Name,
455 IN PUNKNOWN Unknown,
456 IN POOL_TYPE PoolType,
457 IN PDEVICE_OBJECT DeviceObject,
458 IN PIRP Irp,
459 IN KSOBJECT_CREATE *CreateObject)
460 {
461 UNIMPLEMENTED;
462
463 Irp->IoStatus.Information = 0;
464 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
465 IoCompleteRequest(Irp, IO_NO_INCREMENT);
466
467 return STATUS_UNSUCCESSFUL;
468 }
469
470 NTSTATUS
471 NTAPI
HandleKsProperty(IN PIRP Irp)472 CPortPinWavePci::HandleKsProperty(
473 IN PIRP Irp)
474 {
475 //PKSPROPERTY Property;
476 NTSTATUS Status;
477 //UNICODE_STRING GuidString;
478 PIO_STACK_LOCATION IoStack;
479
480 //DPRINT("IPortPinWave_HandleKsProperty entered\n");
481
482 IoStack = IoGetCurrentIrpStackLocation(Irp);
483
484 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
485 {
486 //DPRINT("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
487
488 Irp->IoStatus.Status = STATUS_SUCCESS;
489
490 IoCompleteRequest(Irp, IO_NO_INCREMENT);
491 return STATUS_SUCCESS;
492 }
493
494 Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
495
496 if (Status == STATUS_NOT_FOUND)
497 {
498 //Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
499 #if 0
500 RtlStringFromGUID(Property->Set, &GuidString);
501 //DPRINT("Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
502 RtlFreeUnicodeString(&GuidString);
503 #endif
504 }
505
506 if (Status != STATUS_PENDING)
507 {
508 Irp->IoStatus.Status = Status;
509 IoCompleteRequest(Irp, IO_NO_INCREMENT);
510 }
511
512 return Status;
513 }
514
515 NTSTATUS
516 NTAPI
HandleKsStream(IN PIRP Irp)517 CPortPinWavePci::HandleKsStream(
518 IN PIRP Irp)
519 {
520 NTSTATUS Status;
521 ULONG Data = 0;
522 InterlockedIncrement((PLONG)&m_TotalPackets);
523
524 DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
525
526 Status = m_IrpQueue->AddMapping(Irp, &Data);
527
528 if (NT_SUCCESS(Status))
529 {
530 if (m_Capture)
531 m_Position.WriteOffset += Data;
532 else
533 m_Position.PlayOffset += Data;
534
535 if (m_State == KSSTATE_RUN)
536 {
537 // notify stream of new mapping
538 m_Stream->MappingAvailable();
539 }
540
541 return STATUS_PENDING;
542 }
543
544 return Status;
545 }
546
547 NTSTATUS
548 NTAPI
DeviceIoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)549 CPortPinWavePci::DeviceIoControl(
550 IN PDEVICE_OBJECT DeviceObject,
551 IN PIRP Irp)
552 {
553 PIO_STACK_LOCATION IoStack;
554
555 IoStack = IoGetCurrentIrpStackLocation(Irp);
556
557 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
558 {
559 return HandleKsProperty(Irp);
560 }
561 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
562 {
563 return HandleKsStream(Irp);
564 }
565
566 UNIMPLEMENTED;
567
568 Irp->IoStatus.Information = 0;
569 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
570 IoCompleteRequest(Irp, IO_NO_INCREMENT);
571
572 return STATUS_UNSUCCESSFUL;
573 }
574
575 NTSTATUS
576 NTAPI
Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)577 CPortPinWavePci::Read(
578 IN PDEVICE_OBJECT DeviceObject,
579 IN PIRP Irp)
580 {
581 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
582 }
583
584 NTSTATUS
585 NTAPI
Write(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)586 CPortPinWavePci::Write(
587 IN PDEVICE_OBJECT DeviceObject,
588 IN PIRP Irp)
589 {
590 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
591 }
592
593 NTSTATUS
594 NTAPI
Flush(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)595 CPortPinWavePci::Flush(
596 IN PDEVICE_OBJECT DeviceObject,
597 IN PIRP Irp)
598 {
599 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
600 }
601
602 NTSTATUS
603 NTAPI
Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)604 CPortPinWavePci::Close(
605 IN PDEVICE_OBJECT DeviceObject,
606 IN PIRP Irp)
607 {
608 NTSTATUS Status;
609
610 if (m_Format)
611 {
612 // free format
613 FreeItem(m_Format, TAG_PORTCLASS);
614
615 // format is freed
616 m_Format = NULL;
617 }
618
619 if (m_IrpQueue)
620 {
621 // cancel remaining irps
622 m_IrpQueue->CancelBuffers();
623
624 // release irp queue
625 m_IrpQueue->Release();
626
627 // queue is freed
628 m_IrpQueue = NULL;
629 }
630
631 if (m_ServiceGroup)
632 {
633 // remove member from service group
634 m_ServiceGroup->RemoveMember(PSERVICESINK(this));
635
636 // do not release service group, it is released by the miniport object
637 m_ServiceGroup = NULL;
638 }
639
640 if (m_Stream)
641 {
642 if (m_State != KSSTATE_STOP)
643 {
644 // stop stream
645 Status = m_Stream->SetState(KSSTATE_STOP);
646 if (!NT_SUCCESS(Status))
647 {
648 DPRINT("Warning: failed to stop stream with %x\n", Status);
649 PC_ASSERT(0);
650 }
651 }
652 // set state to stop
653 m_State = KSSTATE_STOP;
654
655 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
656
657 // release stream
658 m_Stream->Release();
659
660 // stream is now freed
661 m_Stream = NULL;
662 }
663
664 if (m_Filter)
665 {
666 // disconnect pin from filter
667 m_Filter->FreePin((PPORTPINWAVEPCI)this);
668
669 // release filter reference
670 m_Filter->Release();
671
672 // pin is done with filter
673 m_Filter = NULL;
674 }
675
676 if (m_Port)
677 {
678 // release reference to port driver
679 m_Port->Release();
680
681 // work is done for port
682 m_Port = NULL;
683 }
684
685 // successfully complete irp
686 Irp->IoStatus.Status = STATUS_SUCCESS;
687 Irp->IoStatus.Information = 0;
688 IoCompleteRequest(Irp, IO_NO_INCREMENT);
689
690 return STATUS_SUCCESS;
691 }
692
693 NTSTATUS
694 NTAPI
QuerySecurity(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)695 CPortPinWavePci::QuerySecurity(
696 IN PDEVICE_OBJECT DeviceObject,
697 IN PIRP Irp)
698 {
699 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
700 }
701
702 NTSTATUS
703 NTAPI
SetSecurity(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)704 CPortPinWavePci::SetSecurity(
705 IN PDEVICE_OBJECT DeviceObject,
706 IN PIRP Irp)
707 {
708 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
709 }
710
711 BOOLEAN
712 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)713 CPortPinWavePci::FastDeviceIoControl(
714 IN PFILE_OBJECT FileObject,
715 IN BOOLEAN Wait,
716 IN PVOID InputBuffer,
717 IN ULONG InputBufferLength,
718 OUT PVOID OutputBuffer,
719 IN ULONG OutputBufferLength,
720 IN ULONG IoControlCode,
721 OUT PIO_STATUS_BLOCK StatusBlock,
722 IN PDEVICE_OBJECT DeviceObject)
723 {
724 return FALSE;
725 }
726
727 BOOLEAN
728 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)729 CPortPinWavePci::FastRead(
730 IN PFILE_OBJECT FileObject,
731 IN PLARGE_INTEGER FileOffset,
732 IN ULONG Length,
733 IN BOOLEAN Wait,
734 IN ULONG LockKey,
735 IN PVOID Buffer,
736 OUT PIO_STATUS_BLOCK StatusBlock,
737 IN PDEVICE_OBJECT DeviceObject)
738 {
739 return FALSE;
740 }
741
742 BOOLEAN
743 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)744 CPortPinWavePci::FastWrite(
745 IN PFILE_OBJECT FileObject,
746 IN PLARGE_INTEGER FileOffset,
747 IN ULONG Length,
748 IN BOOLEAN Wait,
749 IN ULONG LockKey,
750 IN PVOID Buffer,
751 OUT PIO_STATUS_BLOCK StatusBlock,
752 IN PDEVICE_OBJECT DeviceObject)
753 {
754 return FALSE;
755 }
756
757 NTSTATUS
758 NTAPI
Init(IN PPORTWAVEPCI Port,IN PPORTFILTERWAVEPCI Filter,IN KSPIN_CONNECT * ConnectDetails,IN KSPIN_DESCRIPTOR * KsPinDescriptor,IN PDEVICE_OBJECT DeviceObject)759 CPortPinWavePci::Init(
760 IN PPORTWAVEPCI Port,
761 IN PPORTFILTERWAVEPCI Filter,
762 IN KSPIN_CONNECT * ConnectDetails,
763 IN KSPIN_DESCRIPTOR * KsPinDescriptor,
764 IN PDEVICE_OBJECT DeviceObject)
765 {
766 NTSTATUS Status;
767 PKSDATAFORMAT DataFormat;
768 BOOLEAN Capture;
769 ISubdevice * Subdevice = NULL;
770 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
771
772 // check if it is a source / sink pin
773 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
774 {
775 // sink pin
776 Capture = FALSE;
777 }
778 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
779 {
780 // source pin
781 Capture = TRUE;
782 }
783 else
784 {
785 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
786 DbgBreakPoint();
787 while(TRUE);
788 }
789
790 // add port / filter reference
791 Port->AddRef();
792 Filter->AddRef();
793
794 // initialize pin
795 m_Port = Port;
796 m_Filter = Filter;
797 m_KsPinDescriptor = KsPinDescriptor;
798 m_ConnectDetails = ConnectDetails;
799 m_Miniport = GetWavePciMiniport(Port);
800 m_DeviceObject = DeviceObject;
801 m_State = KSSTATE_STOP;
802 m_Capture = Capture;
803
804 DPRINT("IPortPinWavePci_fnInit entered\n");
805
806 // get dataformat
807 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
808
809 // allocate data format
810 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
811 if (!m_Format)
812 {
813 // release references
814 m_Port->Release();
815 m_Filter->Release();
816
817 // no dangling pointers
818 Port = NULL;
819 Filter = NULL;
820
821 // failed to allocate data format
822 return STATUS_INSUFFICIENT_RESOURCES;
823 }
824
825 // copy data format
826 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
827
828 // allocate new stream
829 Status = m_Miniport->NewStream(&m_Stream,
830 NULL,
831 NonPagedPool,
832 PPORTWAVEPCISTREAM(this),
833 ConnectDetails->PinId,
834 Capture,
835 m_Format,
836 &m_DmaChannel,
837 &m_ServiceGroup);
838
839 DPRINT("IPortPinWavePci_fnInit Status %x\n", Status);
840
841 if (!NT_SUCCESS(Status))
842 {
843 // free references
844 Port->Release();
845 Filter->Release();
846
847 // free data format
848 FreeItem(m_Format, TAG_PORTCLASS);
849
850 // no dangling pointers
851 m_Port = NULL;
852 m_Filter = NULL;
853 m_Format = NULL;
854
855 // failed to allocate stream
856 return Status;
857 }
858
859 // get allocator requirements for pin
860 Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming);
861 if (NT_SUCCESS(Status))
862 {
863 DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n",
864 m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
865 }
866
867 // allocate new irp queue
868 Status = NewIrpQueue(&m_IrpQueue);
869 if (!NT_SUCCESS(Status))
870 {
871 // free references
872 Port->Release();
873 Filter->Release();
874 m_Stream->Release();
875
876 // free data format
877 FreeItem(m_Format, TAG_PORTCLASS);
878
879 // no dangling pointers
880 m_Port = NULL;
881 m_Filter = NULL;
882 m_Format = NULL;
883 m_Stream = NULL;
884
885 // failed to allocate irp queue
886 return Status;
887 }
888
889 // initialize irp queue
890 Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, TRUE);
891 if (!NT_SUCCESS(Status))
892 {
893 // this should never happen
894 ASSERT(0);
895 }
896
897 // get subdevice interface
898 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
899
900 if (!NT_SUCCESS(Status))
901 {
902 // this function should never fail
903 ASSERT(0);
904 }
905
906 // get subdevice descriptor
907 Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
908 if (!NT_SUCCESS(Status))
909 {
910 // this function should never fail
911 ASSERT(0);
912 }
913
914 // release subdevice
915 Subdevice->Release();
916
917 /* set up subdevice descriptor */
918 RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
919 m_Descriptor.FilterPropertySet = PinWavePciPropertySet;
920 m_Descriptor.FilterPropertySetCount = sizeof(PinWavePciPropertySet) / sizeof(KSPROPERTY_SET);
921 m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream;
922 m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor;
923 m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
924 m_Descriptor.PortPin = (PVOID)this;
925
926 if (m_ServiceGroup)
927 {
928 Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
929 if (!NT_SUCCESS(Status))
930 {
931 // free references
932 m_Stream->Release();
933 Port->Release();
934 Filter->Release();
935
936 // free data format
937 FreeItem(m_Format, TAG_PORTCLASS);
938
939 // no dangling pointers
940 m_Stream = NULL;
941 m_Port = NULL;
942 m_Filter = NULL;
943 m_Format = NULL;
944
945 // failed to add to service group
946 return Status;
947 }
948 }
949
950 return STATUS_SUCCESS;
951 }
952
953 PVOID
954 NTAPI
GetIrpStream()955 CPortPinWavePci::GetIrpStream()
956 {
957 return (PVOID)m_IrpQueue;
958 }
959
960 PMINIPORT
961 NTAPI
GetMiniport()962 CPortPinWavePci::GetMiniport()
963 {
964 return (PMINIPORT)m_Miniport;
965 }
966
967 NTSTATUS
NewPortPinWavePci(OUT IPortPinWavePci ** OutPin)968 NewPortPinWavePci(
969 OUT IPortPinWavePci ** OutPin)
970 {
971 CPortPinWavePci * This;
972
973 This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWavePci(NULL);
974 if (!This)
975 return STATUS_INSUFFICIENT_RESOURCES;
976
977 This->AddRef();
978
979 // store result
980 *OutPin = (IPortPinWavePci*)This;
981
982 return STATUS_SUCCESS;
983 }
984