ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pin_dmus.cpp
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Kernel Streaming
00004  * FILE:            drivers/wdm/audio/backpln/portcls/pin_dmus.cpp
00005  * PURPOSE:         DMus IRP Audio Pin
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 #include "private.hpp"
00010 
00011 class CPortPinDMus : public IPortPinDMus
00012 {
00013 public:
00014     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
00015 
00016     STDMETHODIMP_(ULONG) AddRef()
00017     {
00018         InterlockedIncrement(&m_Ref);
00019         return m_Ref;
00020     }
00021     STDMETHODIMP_(ULONG) Release()
00022     {
00023         InterlockedDecrement(&m_Ref);
00024 
00025         if (!m_Ref)
00026         {
00027             delete this;
00028             return 0;
00029         }
00030         return m_Ref;
00031     }
00032     IMP_IPortPinDMus;
00033     IMP_IServiceSink;
00034     IMP_IMasterClock;
00035     IMP_IAllocatorMXF;
00036 
00037      CPortPinDMus(IUnknown * OuterUnknown){}
00038      virtual ~CPortPinDMus(){}
00039 
00040 protected:
00041     VOID TransferMidiDataToDMus();
00042     VOID TransferMidiData();
00043 
00044     IPortDMus * m_Port;
00045     IPortFilterDMus * m_Filter;
00046     KSPIN_DESCRIPTOR * m_KsPinDescriptor;
00047     PMINIPORTDMUS m_Miniport;
00048 
00049     PSERVICEGROUP m_ServiceGroup;
00050 
00051     PMXF m_Mxf;
00052     ULONGLONG m_SchedulePreFetch;
00053     NPAGED_LOOKASIDE_LIST m_LookAsideEvent;
00054     NPAGED_LOOKASIDE_LIST m_LookAsideBuffer;
00055 
00056     PMINIPORTMIDI m_MidiMiniport;
00057     PMINIPORTMIDISTREAM m_MidiStream;
00058 
00059 
00060     KSSTATE m_State;
00061     PKSDATAFORMAT m_Format;
00062     KSPIN_CONNECT * m_ConnectDetails;
00063 
00064     DMUS_STREAM_TYPE m_Capture;
00065     PDEVICE_OBJECT m_DeviceObject;
00066     IIrpQueue * m_IrpQueue;
00067 
00068     ULONG m_TotalPackets;
00069     ULONG m_PreCompleted;
00070     ULONG m_PostCompleted;
00071 
00072     ULONG m_LastTag;
00073 
00074     LONG m_Ref;
00075 };
00076 
00077 typedef struct
00078 {
00079     DMUS_KERNEL_EVENT Event;
00080     PVOID Tag;
00081 }DMUS_KERNEL_EVENT_WITH_TAG, *PDMUS_KERNEL_EVENT_WITH_TAG;
00082 
00083 typedef struct
00084 {
00085     CPortPinDMus *Pin;
00086     PIO_WORKITEM WorkItem;
00087     KSSTATE State;
00088 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
00089 
00090 //==================================================================================================================================
00091 NTSTATUS
00092 NTAPI
00093 CPortPinDMus::GetTime(OUT REFERENCE_TIME  *prtTime)
00094 {
00095     UNIMPLEMENTED
00096     return STATUS_SUCCESS;
00097 }
00098 
00099 //==================================================================================================================================
00100 NTSTATUS
00101 NTAPI
00102 CPortPinDMus::GetMessage(
00103     OUT PDMUS_KERNEL_EVENT * ppDMKEvt)
00104 {
00105     PVOID Buffer;
00106 
00107     Buffer = ExAllocateFromNPagedLookasideList(&m_LookAsideEvent);
00108     if (!Buffer)
00109         return STATUS_INSUFFICIENT_RESOURCES;
00110 
00111     *ppDMKEvt = (PDMUS_KERNEL_EVENT)Buffer;
00112     RtlZeroMemory(Buffer, sizeof(DMUS_KERNEL_EVENT));
00113     return STATUS_SUCCESS;
00114 }
00115 
00116 USHORT
00117 NTAPI
00118 CPortPinDMus::GetBufferSize()
00119 {
00120     return PAGE_SIZE;
00121 }
00122 
00123 NTSTATUS
00124 NTAPI
00125 CPortPinDMus::GetBuffer(
00126     OUT PBYTE * ppBuffer)
00127 {
00128     PVOID Buffer;
00129 
00130     Buffer = ExAllocateFromNPagedLookasideList(&m_LookAsideBuffer);
00131     if (!Buffer)
00132         return STATUS_INSUFFICIENT_RESOURCES;
00133 
00134     *ppBuffer = (PBYTE)Buffer;
00135     RtlZeroMemory(Buffer, PAGE_SIZE);
00136     return STATUS_SUCCESS;
00137 }
00138 
00139 
00140 NTSTATUS
00141 NTAPI
00142 CPortPinDMus::PutBuffer(
00143     IN PBYTE pBuffer)
00144 {
00145     PDMUS_KERNEL_EVENT_WITH_TAG Event = (PDMUS_KERNEL_EVENT_WITH_TAG)pBuffer;
00146 
00147     m_IrpQueue->ReleaseMappingWithTag(Event->Tag);
00148 
00149     ExFreeToNPagedLookasideList(&m_LookAsideBuffer, pBuffer);
00150     return STATUS_SUCCESS;
00151 }
00152 
00153 NTSTATUS
00154 NTAPI
00155 CPortPinDMus::SetState(
00156     IN KSSTATE State)
00157 {
00158     UNIMPLEMENTED
00159     return STATUS_NOT_IMPLEMENTED;
00160 }
00161 
00162 
00163 NTSTATUS
00164 NTAPI
00165 CPortPinDMus::PutMessage(
00166     IN PDMUS_KERNEL_EVENT pDMKEvt)
00167 {
00168     ExFreeToNPagedLookasideList(&m_LookAsideEvent, pDMKEvt);
00169     return STATUS_SUCCESS;
00170 }
00171 
00172 
00173 NTSTATUS
00174 NTAPI
00175 CPortPinDMus::ConnectOutput(
00176     IN PMXF sinkMXF)
00177 {
00178     UNIMPLEMENTED
00179     return STATUS_NOT_IMPLEMENTED;
00180 }
00181 
00182 
00183 NTSTATUS
00184 NTAPI
00185 CPortPinDMus::DisconnectOutput(
00186     IN PMXF sinkMXF)
00187 {
00188     UNIMPLEMENTED
00189     return STATUS_NOT_IMPLEMENTED;
00190 }
00191 
00192 //==================================================================================================================================
00193 
00194 VOID
00195 CPortPinDMus::TransferMidiData()
00196 {
00197     NTSTATUS Status;
00198     PUCHAR Buffer;
00199     ULONG BufferSize;
00200     ULONG BytesWritten;
00201 
00202     do
00203     {
00204         Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
00205         if (!NT_SUCCESS(Status))
00206         {
00207             return;
00208         }
00209 
00210         if (m_Capture)
00211         {
00212             Status = m_MidiStream->Read(Buffer, BufferSize, &BytesWritten);
00213             if (!NT_SUCCESS(Status))
00214             {
00215                 DPRINT("Read failed with %x\n", Status);
00216                 return;
00217             }
00218         }
00219         else
00220         {
00221             Status = m_MidiStream->Write(Buffer, BufferSize, &BytesWritten);
00222             if (!NT_SUCCESS(Status))
00223             {
00224                 DPRINT("Write failed with %x\n", Status);
00225                 return;
00226             }
00227         }
00228 
00229         if (!BytesWritten)
00230         {
00231             DPRINT("Device is busy retry later\n");
00232             return;
00233         }
00234 
00235         m_IrpQueue->UpdateMapping(BytesWritten);
00236 
00237     }while(TRUE);
00238 
00239 }
00240 
00241 VOID
00242 CPortPinDMus::TransferMidiDataToDMus()
00243 {
00244     NTSTATUS Status;
00245     PHYSICAL_ADDRESS  PhysicalAddress;
00246     ULONG BufferSize, Flags;
00247     PVOID Buffer;
00248     PDMUS_KERNEL_EVENT_WITH_TAG Event, LastEvent = NULL, Root = NULL;
00249 
00250     do
00251     {
00252         m_LastTag++;
00253         Status = m_IrpQueue->GetMappingWithTag(UlongToPtr(m_LastTag), &PhysicalAddress, &Buffer, &BufferSize, &Flags);
00254         if (!NT_SUCCESS(Status))
00255         {
00256             break;
00257         }
00258 
00259         Status = GetMessage((PDMUS_KERNEL_EVENT*)&Event);
00260         if (!NT_SUCCESS(Status))
00261             break;
00262 
00263         //FIXME
00264         //set up struct
00265         //Event->Event.usFlags = DMUS_KEF_EVENT_COMPLETE;
00266         Event->Event.cbStruct = sizeof(DMUS_KERNEL_EVENT);
00267         Event->Event.cbEvent = (USHORT)BufferSize;
00268         Event->Event.uData.pbData = (PBYTE)Buffer;
00269 
00270 
00271         if (!Root)
00272             Root = Event;
00273         else
00274             LastEvent->Event.pNextEvt = (struct _DMUS_KERNEL_EVENT *)Event;
00275 
00276         LastEvent = Event;
00277         LastEvent->Event.pNextEvt = NULL;
00278         LastEvent->Tag = UlongToPtr(m_LastTag);
00279 
00280     }while(TRUE);
00281 
00282     if (!Root)
00283     {
00284         return;
00285     }
00286 
00287     Status = m_Mxf->PutMessage((PDMUS_KERNEL_EVENT)Root);
00288     DPRINT("Status %x\n", Status);
00289 }
00290 
00291 
00292 
00293 VOID
00294 NTAPI
00295 CPortPinDMus::RequestService()
00296 {
00297     PC_ASSERT_IRQL(DISPATCH_LEVEL);
00298 
00299     if (m_MidiStream)
00300     {
00301         TransferMidiData();
00302     }
00303     else if (m_Mxf)
00304     {
00305         TransferMidiDataToDMus();
00306     }
00307 }
00308 
00309 //==================================================================================================================================
00310 NTSTATUS
00311 NTAPI
00312 CPortPinDMus::QueryInterface(
00313     IN  REFIID refiid,
00314     OUT PVOID* Output)
00315 {
00316 
00317     if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
00318         IsEqualGUIDAligned(refiid, IID_IUnknown))
00319     {
00320         *Output = PVOID(PUNKNOWN(this));
00321         PUNKNOWN(*Output)->AddRef();
00322         return STATUS_SUCCESS;
00323     }
00324 
00325     return STATUS_UNSUCCESSFUL;
00326 }
00327 
00328 NTSTATUS
00329 NTAPI
00330 CPortPinDMus::NewIrpTarget(
00331     OUT struct IIrpTarget **OutTarget,
00332     IN PCWSTR Name,
00333     IN PUNKNOWN Unknown,
00334     IN POOL_TYPE PoolType,
00335     IN PDEVICE_OBJECT DeviceObject,
00336     IN PIRP Irp,
00337     IN KSOBJECT_CREATE *CreateObject)
00338 {
00339     UNIMPLEMENTED
00340 
00341     Irp->IoStatus.Information = 0;
00342     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
00343     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00344 
00345     return STATUS_UNSUCCESSFUL;
00346 }
00347 
00348 NTSTATUS
00349 NTAPI
00350 CPortPinDMus::DeviceIoControl(
00351     IN PDEVICE_OBJECT DeviceObject,
00352     IN PIRP Irp)
00353 {
00354     UNIMPLEMENTED
00355 
00356     Irp->IoStatus.Information = 0;
00357     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
00358     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00359 
00360     return STATUS_UNSUCCESSFUL;
00361 }
00362 
00363 NTSTATUS
00364 NTAPI
00365 CPortPinDMus::Read(
00366     IN PDEVICE_OBJECT DeviceObject,
00367     IN PIRP Irp)
00368 {
00369     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
00370 }
00371 
00372 NTSTATUS
00373 NTAPI
00374 CPortPinDMus::Write(
00375     IN PDEVICE_OBJECT DeviceObject,
00376     IN PIRP Irp)
00377 {
00378     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
00379 }
00380 
00381 NTSTATUS
00382 NTAPI
00383 CPortPinDMus::Flush(
00384     IN PDEVICE_OBJECT DeviceObject,
00385     IN PIRP Irp)
00386 {
00387     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
00388 }
00389 
00390 NTSTATUS
00391 NTAPI
00392 CPortPinDMus::Close(
00393     IN PDEVICE_OBJECT DeviceObject,
00394     IN PIRP Irp)
00395 {
00396     NTSTATUS Status;
00397     ISubdevice * SubDevice;
00398     PSUBDEVICE_DESCRIPTOR Descriptor;
00399 
00400     if (m_ServiceGroup)
00401     {
00402         m_ServiceGroup->RemoveMember(PSERVICESINK(this));
00403     }
00404 
00405     if (m_MidiStream)
00406     {
00407         if (m_State != KSSTATE_STOP)
00408         {
00409             m_MidiStream->SetState(KSSTATE_STOP);
00410             m_State = KSSTATE_STOP;
00411         }
00412         DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
00413         m_MidiStream->Release();
00414     }
00415 
00416     Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice);
00417     if (NT_SUCCESS(Status))
00418     {
00419         Status = SubDevice->GetDescriptor(&Descriptor);
00420         if (NT_SUCCESS(Status))
00421         {
00422             // release reference count
00423             Descriptor->Factory.Instances[m_ConnectDetails->PinId].CurrentPinInstanceCount--;
00424         }
00425         SubDevice->Release();
00426     }
00427 
00428     if (m_Format)
00429     {
00430         FreeItem(m_Format, TAG_PORTCLASS);
00431         m_Format = NULL;
00432     }
00433 
00434     // complete the irp
00435     Irp->IoStatus.Information = 0;
00436     Irp->IoStatus.Status = STATUS_SUCCESS;
00437     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00438 
00439     // destroy DMus pin
00440     m_Filter->FreePin(PPORTPINDMUS(this));
00441 
00442     return STATUS_SUCCESS;
00443 }
00444 
00445 NTSTATUS
00446 NTAPI
00447 CPortPinDMus::QuerySecurity(
00448     IN PDEVICE_OBJECT DeviceObject,
00449     IN PIRP Irp)
00450 {
00451     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
00452 }
00453 
00454 NTSTATUS
00455 NTAPI
00456 CPortPinDMus::SetSecurity(
00457     IN PDEVICE_OBJECT DeviceObject,
00458     IN PIRP Irp)
00459 {
00460     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
00461 }
00462 
00463 BOOLEAN
00464 NTAPI
00465 CPortPinDMus::FastDeviceIoControl(
00466     IN PFILE_OBJECT FileObject,
00467     IN BOOLEAN Wait,
00468     IN PVOID InputBuffer,
00469     IN ULONG InputBufferLength,
00470     OUT PVOID OutputBuffer,
00471     IN ULONG OutputBufferLength,
00472     IN ULONG IoControlCode,
00473     OUT PIO_STATUS_BLOCK StatusBlock,
00474     IN PDEVICE_OBJECT DeviceObject)
00475 {
00476     return FALSE;
00477 }
00478 
00479 BOOLEAN
00480 NTAPI
00481 CPortPinDMus::FastRead(
00482     IN PFILE_OBJECT FileObject,
00483     IN PLARGE_INTEGER FileOffset,
00484     IN ULONG Length,
00485     IN BOOLEAN Wait,
00486     IN ULONG LockKey,
00487     IN PVOID Buffer,
00488     OUT PIO_STATUS_BLOCK StatusBlock,
00489     IN PDEVICE_OBJECT DeviceObject)
00490 {
00491     return FALSE;
00492 }
00493 
00494 BOOLEAN
00495 NTAPI
00496 CPortPinDMus::FastWrite(
00497     IN PFILE_OBJECT FileObject,
00498     IN PLARGE_INTEGER FileOffset,
00499     IN ULONG Length,
00500     IN BOOLEAN Wait,
00501     IN ULONG LockKey,
00502     IN PVOID Buffer,
00503     OUT PIO_STATUS_BLOCK StatusBlock,
00504     IN PDEVICE_OBJECT DeviceObject)
00505 {
00506     return FALSE;
00507 }
00508 
00509 NTSTATUS
00510 NTAPI
00511 CPortPinDMus::Init(
00512     IN PPORTDMUS Port,
00513     IN PPORTFILTERDMUS Filter,
00514     IN KSPIN_CONNECT * ConnectDetails,
00515     IN KSPIN_DESCRIPTOR * KsPinDescriptor,
00516     IN PDEVICE_OBJECT DeviceObject)
00517 {
00518     NTSTATUS Status;
00519     PKSDATAFORMAT DataFormat;
00520     DMUS_STREAM_TYPE Type;
00521 
00522     Port->AddRef();
00523     Filter->AddRef();
00524 
00525     m_Port = Port;
00526     m_Filter = Filter;
00527     m_KsPinDescriptor = KsPinDescriptor;
00528     m_ConnectDetails = ConnectDetails;
00529     m_DeviceObject = DeviceObject;
00530 
00531     GetDMusMiniport(Port, &m_Miniport, &m_MidiMiniport);
00532 
00533     DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
00534 
00535     DPRINT("CPortPinDMus::Init entered\n");
00536 
00537     m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
00538     if (!m_Format)
00539         return STATUS_INSUFFICIENT_RESOURCES;
00540 
00541     RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
00542 
00543     if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
00544     {
00545         Type = DMUS_STREAM_MIDI_RENDER;
00546     }
00547     else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
00548     {
00549         Type = DMUS_STREAM_MIDI_CAPTURE;
00550     }
00551     else
00552     {
00553         DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
00554         DbgBreakPoint();
00555         while(TRUE);
00556     }
00557 
00558     Status = NewIrpQueue(&m_IrpQueue);
00559     if (!NT_SUCCESS(Status))
00560     {
00561         DPRINT("Failed to allocate IrpQueue with %x\n", Status);
00562         return Status;
00563     }
00564 
00565     if (m_MidiMiniport)
00566     {
00567         Status = m_MidiMiniport->NewStream(&m_MidiStream, NULL, NonPagedPool, ConnectDetails->PinId, Type, m_Format, &m_ServiceGroup);
00568 
00569         DPRINT("CPortPinDMus::Init Status %x\n", Status);
00570 
00571         if (!NT_SUCCESS(Status))
00572             return Status;
00573     }
00574     else
00575     {
00576         Status = m_Miniport->NewStream(&m_Mxf, NULL, NonPagedPool, ConnectDetails->PinId, Type, m_Format, &m_ServiceGroup, PAllocatorMXF(this), PMASTERCLOCK(this),&m_SchedulePreFetch);
00577 
00578         DPRINT("CPortPinDMus::Init Status %x\n", Status);
00579 
00580         if (!NT_SUCCESS(Status))
00581             return Status;
00582 
00583         if (Type == DMUS_STREAM_MIDI_CAPTURE)
00584         {
00585             Status = m_Mxf->ConnectOutput(PMXF(this));
00586             if (!NT_SUCCESS(Status))
00587             {
00588                 DPRINT("IMXF_ConnectOutput failed with Status %x\n", Status);
00589                 return Status;
00590             }
00591         }
00592 
00593         ExInitializeNPagedLookasideList(&m_LookAsideEvent, NULL, NULL, 0, sizeof(DMUS_KERNEL_EVENT_WITH_TAG), TAG_PORTCLASS, 0);
00594         ExInitializeNPagedLookasideList(&m_LookAsideBuffer, NULL, NULL, 0, PAGE_SIZE, TAG_PORTCLASS, 0);
00595     }
00596 
00597     if (m_ServiceGroup)
00598     {
00599         Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
00600         if (!NT_SUCCESS(Status))
00601         {
00602             DPRINT("Failed to add pin to service group\n");
00603             return Status;
00604         }
00605     }
00606 
00607     Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, 0, 0, FALSE);
00608     if (!NT_SUCCESS(Status))
00609     {
00610         DPRINT("IrpQueue_Init failed with %x\n", Status);
00611         return Status;
00612     }
00613 
00614     m_State = KSSTATE_STOP;
00615     m_Capture = Type;
00616 
00617     return STATUS_SUCCESS;
00618 }
00619 
00620 VOID
00621 NTAPI
00622 CPortPinDMus::Notify()
00623 {
00624     m_ServiceGroup->RequestService();
00625 }
00626 
00627 NTSTATUS
00628 NewPortPinDMus(
00629     OUT IPortPinDMus ** OutPin)
00630 {
00631     CPortPinDMus * This;
00632 
00633     This = new (NonPagedPool, TAG_PORTCLASS)CPortPinDMus(NULL);
00634     if (!This)
00635         return STATUS_INSUFFICIENT_RESOURCES;
00636 
00637     This->AddRef();
00638 
00639     // store result
00640     *OutPin = (IPortPinDMus*)This;
00641 
00642     return STATUS_SUCCESS;
00643 }
00644 

Generated on Sat May 26 2012 04:27:09 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.