Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpin_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
1.7.6.1
|