?? callback.c
字號:
//
//
// CAUTION:
// maybe need to do this only if we are recovered from power loss state.
// We can move this to power management function in the future.
// In the completion routine, it will invoke other function to restore its streaming state.
//
DCamSetKSStateInitialize(pDevExt);
DbgMsg2(("\'DCamBusResetNotification: Leaving...; Task complete in the CompletionRoutine.\n"));
return;
}
NTSTATUS
DCamDetachBufferCR(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
IN PIRB pIrb
)
/*++
Routine Description:
Detaching a buffer has completed. Attach next buffer.
Returns more processing required so the IO Manager will leave us alone
Arguments:
DriverObject - Pointer to driver object created by system.
pIrp - Irp that just completed
pIrb - Context set in DCamIsochCallback()
Return Value:
None.
--*/
{
IN PISOCH_DESCRIPTOR IsochDescriptor;
PDCAM_EXTENSION pDevExt;
PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
KIRQL oldIrql;
if(!pIrb) {
ERROR_LOG(("\'DCamDetachBufferCR: pIrb is NULL\n"));
ASSERT(pIrb);
IoFreeIrp(pIrp);
return (STATUS_MORE_PROCESSING_REQUIRED);
}
// Get IsochDescriptor from the context (pIrb)
IsochDescriptor = pIrb->u.IsochDetachBuffers.pIsochDescriptor;
if(!IsochDescriptor) {
ERROR_LOG(("\'DCamDetachBufferCR: IsochDescriptor is NULL\n"));
ASSERT(IsochDescriptor);
IoFreeIrp(pIrp);
return (STATUS_MORE_PROCESSING_REQUIRED);
}
if(pIrp->IoStatus.Status != STATUS_SUCCESS) {
ERROR_LOG(("\'DCamDetachBufferCR: pIrp->IoStatus.Status(%x) != STATUS_SUCCESS\n", pIrp->IoStatus.Status));
ASSERT(pIrp->IoStatus.Status == STATUS_SUCCESS);
IoFreeIrp(pIrp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
// IsochDescriptorReserved->Srb->Irp->IoStatus = pIrp->IoStatus.Status;
IoFreeIrp(pIrp);
// Freed and should not be referenced again!
IsochDescriptor->DeviceReserved[5] = 0;
IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
pDevExt = (PDCAM_EXTENSION) IsochDescriptor->Context1;
DbgMsg3(("\'DCamDetachBufferCR: IsochDescriptorReserved=%x; DevExt=%x\n", IsochDescriptorReserved, pDevExt));
ASSERT(IsochDescriptorReserved);
ASSERT(pDevExt);
if(pDevExt &&
IsochDescriptorReserved) {
//
// Indicate that the Srb should be complete
//
IsochDescriptorReserved->Flags |= STATE_SRB_IS_COMPLETE;
IsochDescriptorReserved->Srb->Status = STATUS_SUCCESS;
IsochDescriptorReserved->Srb->CommandData.DataBufferArray->DataUsed = IsochDescriptor->ulLength;
IsochDescriptorReserved->Srb->ActualBytesTransferred = IsochDescriptor->ulLength;
DbgMsg3(("\'DCamDetachBufferCR: Completing Srb %x\n", IsochDescriptorReserved->Srb));
KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
RemoveEntryList(&IsochDescriptorReserved->DescriptorList); InterlockedDecrement(&pDevExt->PendingReadCount);
KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
ASSERT(IsochDescriptorReserved->Srb->StreamObject);
ASSERT(IsochDescriptorReserved->Srb->Flags & SRB_HW_FLAGS_STREAM_REQUEST);
StreamClassStreamNotification(
StreamRequestComplete,
IsochDescriptorReserved->Srb->StreamObject,
IsochDescriptorReserved->Srb);
// Free it here instead of in DCamCompletionRoutine.
ExFreePool(IsochDescriptor);
KeAcquireSpinLock(&pDevExt->IsochWaitingLock, &oldIrql);
if (!IsListEmpty(&pDevExt->IsochWaitingList) && pDevExt->PendingReadCount >= MAX_BUFFERS_SUPPLIED) {
//
// We had someone blocked waiting for us to complete. Pull
// them off the waiting list and get them running
//
DbgMsg3(("DCamDetachBufferCR: Dequeueing request - Read Count = %x\n", pDevExt->PendingReadCount));
IsochDescriptorReserved = \
(PISOCH_DESCRIPTOR_RESERVED) RemoveHeadList(
&pDevExt->IsochWaitingList
);
KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
IsochDescriptor = \
(PISOCH_DESCRIPTOR) (((PUCHAR) IsochDescriptorReserved) -
FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));
DCamReadStreamWorker(IsochDescriptorReserved->Srb, IsochDescriptor);
} else {
KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
}
}
return (STATUS_MORE_PROCESSING_REQUIRED);
}
VOID
DCamIsochCallback(
IN PDCAM_EXTENSION pDevExt,
IN PISOCH_DESCRIPTOR IsochDescriptor
)
/*++
Routine Description:
Called when an Isoch Descriptor completes
Arguments:
pDevExt - Pointer to our DeviceExtension
IsochDescriptor - IsochDescriptor that completed
Return Value:
Nothing
--*/
{
PIRB pIrb;
PIRP pIrp;
PSTREAMEX pStrmEx;
PIO_STACK_LOCATION NextIrpStack;
PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
PKSSTREAM_HEADER pDataPacket;
PKS_FRAME_INFO pFrameInfo;
KIRQL oldIrql;
//
// Debug check to make sure we're dealing with a real IsochDescriptor
//
ASSERT ( IsochDescriptor );
IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
//
// All Pending read will be either resubmitted, or cancelled (if out of resource).
//
if(pDevExt->bStopIsochCallback) {
ERROR_LOG(("DCamIsochCallback: bStopCallback is set. IsochDescriptor %x (and Reserved %x) is returned and not processed.\n",
IsochDescriptor, IsochDescriptorReserved));
return;
}
//
// Synchronization note:
//
// We are competing with cancel packet routine in the
// event of device removal or setting to STOP state.
// which ever got the spin lock to set DEATCH_BUFFER
// flag take ownership completing the Irp/IsochDescriptor.
//
KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
if(pDevExt->bDevRemoved ||
(IsochDescriptorReserved->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS)) ) {
ERROR_LOG(("DCamIsochCallback: bDevRemoved || STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS %x %x\n",
IsochDescriptorReserved,IsochDescriptorReserved->Flags));
ASSERT((!pDevExt->bDevRemoved && !(IsochDescriptorReserved->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS))));
KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
return;
}
IsochDescriptorReserved->Flags |= STATE_DETACHING_BUFFERS;
KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
ASSERT(pStrmEx == (PSTREAMEX)IsochDescriptorReserved->Srb->StreamObject->HwStreamExtension);
pStrmEx->FrameCaptured++;
pStrmEx->FrameInfo.PictureNumber = pStrmEx->FrameCaptured + pStrmEx->FrameInfo.DropCount;
//
// Return the timestamp for the frame
//
pDataPacket = IsochDescriptorReserved->Srb->CommandData.DataBufferArray;
pFrameInfo = (PKS_FRAME_INFO) (pDataPacket + 1);
ASSERT ( pDataPacket );
ASSERT ( pFrameInfo );
//
// Return the timestamp for the frame
//
pDataPacket->PresentationTime.Numerator = 1;
pDataPacket->PresentationTime.Denominator = 1;
pDataPacket->Duration = pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
//
// if we have a master clock
//
if (pStrmEx->hMasterClock) {
ULONGLONG tmStream;
tmGetStreamTime(IsochDescriptorReserved->Srb, pStrmEx, &tmStream);
pDataPacket->PresentationTime.Time = tmStream;
pDataPacket->OptionsFlags = 0;
pDataPacket->OptionsFlags |=
KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
KSSTREAM_HEADER_OPTIONSF_DURATIONVALID |
KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT; // Every frame we generate is a key frame (aka SplicePoint)
DbgMsg3(("\'IsochCallback: Time(%dms); P#(%d)=Cap(%d)+Drp(%d); Pend%d\n",
(ULONG) tmStream/10000,
(ULONG) pStrmEx->FrameInfo.PictureNumber,
(ULONG) pStrmEx->FrameCaptured,
(ULONG) pStrmEx->FrameInfo.DropCount,
pDevExt->PendingReadCount));
} else {
pDataPacket->PresentationTime.Time = 0;
pDataPacket->OptionsFlags &=
~(KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
KSSTREAM_HEADER_OPTIONSF_DURATIONVALID);
}
// Set additional info fields about the data captured such as:
// Frames Captured
// Frames Dropped
// Field Polarity
pStrmEx->FrameInfo.ExtendedHeaderSize = pFrameInfo->ExtendedHeaderSize;
*pFrameInfo = pStrmEx->FrameInfo;
#ifdef SUPPORT_RGB24
// Swaps B and R or BRG24 to RGB24.
// There are 640x480 pixels so 307200 swaps are needed.
if(pDevExt->CurrentModeIndex == VMODE4_RGB24 && pStrmEx->pVideoInfoHeader) {
PBYTE pbFrameBuffer;
BYTE bTemp;
ULONG i, ulLen;
#ifdef USE_WDM110 // Win2000
// Driver verifier flag to use this but if this is used, this driver will not load for any Win9x OS.
pbFrameBuffer = (PBYTE) MmGetSystemAddressForMdlSafe(IsochDescriptorReserved->Srb->Irp->MdlAddress, NormalPagePriority);
#else // Win9x
pbFrameBuffer = (PBYTE) MmGetSystemAddressForMdl (IsochDescriptorReserved->Srb->Irp->MdlAddress);
#endif
if(pbFrameBuffer) {
// calculate number of pixels
ulLen = abs(pStrmEx->pVideoInfoHeader->bmiHeader.biWidth) * abs(pStrmEx->pVideoInfoHeader->bmiHeader.biHeight);
ASSERT(ulLen == pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage/3);
if(ulLen > pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage)
ulLen = pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage/3;
for (i=0; i < ulLen; i++) {
// swap R and B
bTemp = pbFrameBuffer[0];
pbFrameBuffer[0] = pbFrameBuffer[2];
pbFrameBuffer[2] = bTemp;
pbFrameBuffer += 3; // next RGB24 pixel
}
}
}
#endif
// Reuse the Irp and Irb
pIrp = (PIRP) IsochDescriptor->DeviceReserved[5];
ASSERT(pIrp);
pIrb = (PIRB) IsochDescriptor->DeviceReserved[6];
ASSERT(pIrb);
#if DBG
// Same isochdescriptor should only be callback once.
ASSERT((IsochDescriptor->DeviceReserved[7] == 0x87654321));
IsochDescriptor->DeviceReserved[7]++;
#endif
pIrb->FunctionNumber = REQUEST_ISOCH_DETACH_BUFFERS;
pIrb->u.IsochDetachBuffers.hResource = pDevExt->hResource;
pIrb->u.IsochDetachBuffers.nNumberOfDescriptors = 1;
pIrb->u.IsochDetachBuffers.pIsochDescriptor = IsochDescriptor;
NextIrpStack = IoGetNextIrpStackLocation(pIrp);
NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
NextIrpStack->Parameters.Others.Argument1 = pIrb;
IoSetCompletionRoutine(
pIrp,
DCamDetachBufferCR, // Detach complete and will attach queued buffer.
pIrb,
TRUE,
TRUE,
TRUE
);
IoCallDriver(pDevExt->BusDeviceObject, pIrp);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -