⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 callback.c

📁 a sample WDM stream class video capture driver that supports two IEEE 1394 digital cameras. The sam
💻 C
📖 第 1 页 / 共 2 页
字号:
    // 
    //
    // 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 + -