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