virtual ~CIrpQueue(){}
protected:
- ULONG m_CurrentOffset;
+ volatile ULONG m_CurrentOffset;
LONG m_NumMappings;
ULONG m_NumDataAvailable;
BOOL m_StartStream;
- KSPIN_CONNECT * m_ConnectDetails;
+ PKSPIN_CONNECT m_ConnectDetails;
PKSDATAFORMAT_WAVEFORMATEX m_DataFormat;
KSPIN_LOCK m_IrpListLock;
NTSTATUS
NTAPI
CIrpQueue::AddMapping(
- IN PUCHAR Buffer,
- IN ULONG BufferSize,
- IN PIRP Irp)
+ IN PIRP Irp,
+ OUT PULONG Data)
{
PKSSTREAM_HEADER Header;
NTSTATUS Status = STATUS_SUCCESS;
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
- PC_ASSERT(!Buffer);
-
if (!Irp->MdlAddress)
{
// ioctl from KsStudio
}
// get first stream header
- Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
+
+ if (Irp->RequestorMode == UserMode)
+ Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
+ else
+ Header = (PKSSTREAM_HEADER)Irp->UserBuffer;
+
+ // sanity check
+ PC_ASSERT(Header);
// calculate num headers
NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size;
// get first audio buffer
Mdl = Irp->MdlAddress;
-
+ // sanity check
+ PC_ASSERT(Mdl);
// store the current stream header
Irp->Tail.Overlay.DriverContext[OFFSET_STREAMHEADER] = (PVOID)Header;
// store current header index
Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0);
-
NumData = 0;
// prepare all headers
- for(Index = 0; Index < NumHeaders; Index++)
- {
+ for(Index = 0; Index < NumHeaders; Index++)
+ {
// sanity checks
PC_ASSERT(Header);
PC_ASSERT(Mdl);
- Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+ if (Irp->RequestorMode == UserMode)
+ {
+ Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+ }
if (!Header->Data)
- {
+ {
// insufficient resources
ExFreePool(Irp->AssociatedIrp.SystemBuffer);
Irp->AssociatedIrp.SystemBuffer = NULL;
- // complete and forget request
+ // complete and forget request
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
- }
+ }
// increment num mappings
InterlockedIncrement(&m_NumMappings);
// move to next mdl
Mdl = Mdl->Next;
- }
+ }
DPRINT("StreamHeaders %u NumData %u FrameSize %u NumDataAvailable %u\n", NumHeaders, NumData, m_MaxFrameSize, m_NumDataAvailable);
-
+ *Data = NumData;
// mark irp as pending
IoMarkIrpPending(Irp);
if (!Irp)
{
DPRINT("NoIrp\n");
- return STATUS_UNSUCCESSFUL;
// no irp available, use silence buffer
*Buffer = (PUCHAR)m_SilenceBuffer;
*BufferSize = m_MaxFrameSize;
// ASSERT(StreamHeader);
// add to current offset
- m_CurrentOffset += BytesWritten;
+ InterlockedExchangeAdd((volatile PLONG)&m_CurrentOffset, (LONG)BytesWritten);
// decrement available data counter
m_NumDataAvailable -= BytesWritten;
if (m_CurrentOffset >= Size)
{
if (STREAMHEADER_INDEX(m_Irp) + 1 < STREAMHEADER_COUNT(m_Irp))
- {
+ {
// the irp has at least one more stream header
m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(STREAMHEADER_INDEX(m_Irp) + 1);
// done
return;
- }
+ }
- // irp has been processed completly
+ // irp has been processed completly
NumData = 0;
- StreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer;
+ if (m_Irp->RequestorMode == KernelMode)
+ StreamHeader = (PKSSTREAM_HEADER)m_Irp->UserBuffer;
+ else
+ StreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer;
// loop all stream headers
for(Index = 0; Index < STREAMHEADER_COUNT(m_Irp); Index++)
- {
+ {
PC_ASSERT(StreamHeader);
// add size of buffer
// get next stream header
StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
- }
+ }
+
+ if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
+ {
+ // looped streaming repeat the buffers untill
+ // the caller decides to stop the streams
+
+ // reset stream header index
+ m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0);
+ // re-insert irp
+ KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, m_Irp, KsListEntryTail, NULL);
+ // clear current irp
+ m_Irp = NULL;
+ // reset offset
+ m_CurrentOffset = 0;
+ // increment available data
+ InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, NumData);
+ // done
+ return;
+ }
m_Irp->IoStatus.Status = STATUS_SUCCESS;
m_Irp->IoStatus.Information = NumData;
-#if 0
- PC_ASSERT_IRQL(DISPATCH_LEVEL);
- MmUnlockPages(m_Irp->MdlAddress);
- IoFreeMdl(m_Irp->MdlAddress);
- m_Irp->MdlAddress = NULL;
- ExFreePool(m_Irp->AssociatedIrp.SystemBuffer);
- m_Irp->AssociatedIrp.SystemBuffer = NULL;
-#endif
-
// complete the request
IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT);
// remove irp as it is complete
NTAPI
CIrpQueue::CancelBuffers()
{
+ // is there an active irp
+ if (m_Irp)
+ {
+ // re-insert it to cancelable queue
+ KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, m_Irp, KsListEntryTail, NULL);
+ //set it to zero
+ m_Irp = NULL;
+ }
+ // cancel all irps
+ KsCancelIo(&m_IrpList, &m_IrpListLock);
+ // reset stream start flag
m_StartStream = FALSE;
+ // done
return TRUE;
}
return m_OutOfMapping;
}
-VOID
+ULONG
NTAPI
-CIrpQueue::PrintQueueStatus()
+CIrpQueue::GetCurrentIrpOffset()
{
+ return m_CurrentOffset;
}
VOID