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

📄 dcampkt.c

📁 a sample WDM stream class video capture driver that supports two IEEE 1394 digital cameras. The sam
💻 C
📖 第 1 页 / 共 5 页
字号:

#ifdef SUPPORT_YUV800
    case FOURCC_Y800:  
         ModeIndex = VMODE5_YUV800;
         break;
#endif

    default:          
         Status = STATUS_NOT_IMPLEMENTED;;
         return Status;;
    }


    DbgMsg1(("\'DCamAllocateIsochResource: ModeIndex=%d, AvgTimePerFrame=%d, FrameRate=%d\n", 
             ModeIndex, dwAvgTimePerFrame, pDevExt->FrameRate));

    //
    // Get an Irp so we can send some allocation commands down
    //

    StackSize = pDevExt->BusDeviceObject->StackSize;
    Irp = IoAllocateIrp(StackSize, FALSE);

    if (!Irp) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // Calculate the index to use to reference the ISOCH table
    //
    pStrmEx->idxIsochTable = ModeIndex * NUM_POSSIBLE_RATES + pDevExt->FrameRate;

    ASSERT(pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage == IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize);
    DbgMsg2(("\'DCamAllocateIsochResource: ModeIndex=%d, idxIsochTable=%d, biSizeImage=%d, CompletePictureSize=%d\n", 
             ModeIndex, pStrmEx->idxIsochTable, pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage, IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize));          

    //
    // 0. Determine the MAX_SPEED and not use the speed defined in the static table.
    //
    Irb->FunctionNumber = REQUEST_GET_SPEED_BETWEEN_DEVICES;
    Irb->Flags = 0;
    Irb->u.GetMaxSpeedBetweenDevices.fulFlags = USE_LOCAL_NODE;
    Irb->u.GetMaxSpeedBetweenDevices.ulNumberOfDestinations = 0;
    Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
    if(Status) {
        ERROR_LOG(("\'DCamAllocateIsochResource: Error %x while trying to get maximun speed between devices.\n", Status));        

        IoFreeIrp(Irp);
        return STATUS_INSUFFICIENT_RESOURCES;
    }     
    
    fulSpeed = Irb->u.GetMaxSpeedBetweenDevices.fulSpeed;

    //
    // The max speed between devices should be within supported speed range, and
    // must be equal or greater than the required speed for the chosen format.
    //
    if(
        (  fulSpeed != SPEED_FLAGS_100 
        && fulSpeed != SPEED_FLAGS_200 
        && fulSpeed != SPEED_FLAGS_400
        )
        || fulSpeed < IsochInfoTable[pStrmEx->idxIsochTable].SpeedRequired
       ) {

        ASSERT(fulSpeed == SPEED_FLAGS_100 || fulSpeed == SPEED_FLAGS_200 ||  fulSpeed == SPEED_FLAGS_400);
        ASSERT(fulSpeed >= IsochInfoTable[pStrmEx->idxIsochTable].SpeedRequired);

        IoFreeIrp(Irp);
        return STATUS_UNSUCCESSFUL;
    }

    pDevExt->SpeedCode = fulSpeed >> 1;  // Safe for S100, 200 and 400 (is checked above).
    DbgMsg2(("\'GetMaxSpeedBetweenDevices.fulSpeed=%x; SpeedCode:%x\n", fulSpeed, pDevExt->SpeedCode));


    //
    // 1. Allocate CHANNEL
    //       First try to re-allocate the same channel
    //       If it is used, try to get any channel.  1394DCam can only be on channel 0..15
    //
    Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_CHANNEL;
    Irb->Flags = 0;

    //
    //      ULONG           nRequestedChannel;      // Need a specific channel
    //      ULONG           Channel;                // Returned channel
    //      LARGE_INTEGER   ChannelsAvailable;      // Channels available
    // Instead of hardcoded '0'; use -1 to ask the bus driver to get the next available channel for us.
    // -1 (any channel) or an existing channel
    Irb->u.IsochAllocateChannel.nRequestedChannel = pDevExt->IsochChannel;  
    Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
    if(Status) {

        //
        // Due to channel change, 
        // all Pending read will be either resubmitted, 
        // or cancelled (if out of resource).
        //
        pDevExt->bStopIsochCallback = TRUE;  // Set back to FALSE after pending buffer are attached.


        //
        // If this is an initial request and no channel available,
        // free all resource and abort.
        //
        if(pDevExt->IsochChannel == ISOCH_ANY_CHANNEL)
            goto NoResource_abort;

        DbgMsg1(("DCamAllocateIsochResource: last allocated channel %d is not available; pending count %d.\n",  
            pDevExt->IsochChannel, pDevExt->PendingReadCount));                      

        // Try gettting any channel.
        Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_CHANNEL;
        Irb->Flags = 0;
        Irb->u.IsochAllocateChannel.nRequestedChannel = ISOCH_ANY_CHANNEL;  
        Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
        if(Status) {
            ERROR_LOG(("DCamAllocateIsochResource: allocate any channel failed, status %x!\n",  Status));
            goto NoResource_abort;           
        }

        //
        // Channel changed, we MUST reallocate resource.
        // The "stale" resrouce will be free later when 
        // pending packet are detached.
        //

        bAllocateResource = TRUE;
    }   
    
    DbgMsg1(("**IsochAlloc: Channel(Old) %d, requested %d, got %d, HiLo(0x%x:%x), PendingRead %d\n", 
         pDevExt->IsochChannel, 
         Irb->u.IsochAllocateChannel.nRequestedChannel, 
         Irb->u.IsochAllocateChannel.Channel, 
         Irb->u.IsochAllocateChannel.ChannelsAvailable.u.HighPart,
         Irb->u.IsochAllocateChannel.ChannelsAvailable.u.LowPart,
         pDevExt->PendingReadCount));

    // New channel
    pDevExt->IsochChannel = Irb->u.IsochAllocateChannel.Channel;  // Used in allocating iso. resource and reallocation


    //
    // 2. Allocate BANDWIDTH
    //
    Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_BANDWIDTH;
    Irb->Flags = 0;
    Irb->u.IsochAllocateBandwidth.nMaxBytesPerFrameRequested = IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2;
    Irb->u.IsochAllocateBandwidth.fulSpeed = fulSpeed;
    Irb->u.IsochAllocateBandwidth.hBandwidth = 0;
    Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
    
    if(Status) {
        ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to allocate Isoch bandwidth\n", Status));                  
        goto NoResource_abort;
    }

    pDevExt->hBandwidth = Irb->u.IsochAllocateBandwidth.hBandwidth;
    DbgMsg2(("**IsochAlloc: nMaxBytesPerFrameRequested %d, fulSpeed %d; hBandWidth 0x%x\n",
         IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2, fulSpeed, pDevExt->hBandwidth));



    //
    // 3. Allocate RESOURCES
    //    Note: after a bus reset, we need not free and re-allocate this resoruce again.
    //
    if(bAllocateResource) {
        Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_RESOURCES;
        Irb->Flags = 0;
        Irb->u.IsochAllocateResources.fulSpeed = fulSpeed;
        Irb->u.IsochAllocateResources.nChannel = pDevExt->IsochChannel;
        Irb->u.IsochAllocateResources.nMaxBytesPerFrame = IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2;
        // For slower frame rate use smaller quadlets
        // smaller frame size will use more packet to fill the same amount of data
        // this is why smaller frame rate actually demand more resource !!
        Irb->u.IsochAllocateResources.nNumberOfBuffers = MAX_BUFFERS_SUPPLIED + 1;  // "+1" as a "safety"
        Irb->u.IsochAllocateResources.nMaxBufferSize = IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize;
        if (pDevExt->HostControllerInfomation.HostCapabilities & HOST_INFO_SUPPORTS_RETURNING_ISO_HDR) {       
            Irb->u.IsochAllocateResources.nQuadletsToStrip = 1;
            Irb->u.IsochAllocateResources.fulFlags = RESOURCE_USED_IN_LISTENING | RESOURCE_STRIP_ADDITIONAL_QUADLETS;

        } else {
            Irb->u.IsochAllocateResources.nQuadletsToStrip = 0;
            Irb->u.IsochAllocateResources.fulFlags = RESOURCE_USED_IN_LISTENING;
        }

        Irb->u.IsochAllocateResources.hResource = 0;
        DbgMsg2(("\'DCamAllocateIsochResource: fullSpeed(%d), nMaxBytesPerFrame(%d), nMaxBufferSize(%d)\n", 
                              Irb->u.IsochAllocateResources.fulSpeed,
                              Irb->u.IsochAllocateResources.nMaxBytesPerFrame,
                              Irb->u.IsochAllocateResources.nMaxBufferSize));
        Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);          

        if(Status) {
            ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to allocate Isoch resources\n", Status));
            goto NoResource_abort;
        }


        pDevExt->hResource = Irb->u.IsochAllocateResources.hResource;

    }

    pDevExt->CurrentModeIndex = ModeIndex;
    DbgMsg2(("**IsochAlloc: hResource = %x\n", pDevExt->hResource));

    IoFreeIrp(Irp);     

    return STATUS_SUCCESS;



NoResource_abort:

    // Free bandwidth
    if(pDevExt->hBandwidth != NULL) {

        Irb->FunctionNumber = REQUEST_ISOCH_FREE_BANDWIDTH;
        Irb->Flags = 0;
        Irb->u.IsochFreeBandwidth.hBandwidth = pDevExt->hBandwidth;
        Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
        pDevExt->hBandwidth = NULL;
        if(Status) {
            ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to free Isoch bandwidth\n", Status));
        }
    }

    // Free channel
    if (pDevExt->IsochChannel != ISOCH_ANY_CHANNEL) {

        Irb->FunctionNumber = REQUEST_ISOCH_FREE_CHANNEL;
        Irb->Flags = 0;
        Irb->u.IsochFreeChannel.nChannel = pDevExt->IsochChannel;
        Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
        pDevExt->IsochChannel = ISOCH_ANY_CHANNEL;  // Reset it.

        if(Status) {
            ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to free Isoch channel\n", Status));
        }
    }


    IoFreeIrp(Irp);
    return STATUS_INSUFFICIENT_RESOURCES;
    
}


NTSTATUS
DCamFreeIsochResource (
    PDCAM_EXTENSION pDevExt,
    PIRB Irb,
    BOOL bFreeResource
    )
/*++

Routine Description:

    Free resource allocated in DCamAllocateIsochResource().

Arguments:

    Srb - Pointer to Stream request block

Return Value:

    Nothing

--*/
{
    PIRP Irp;
    CCHAR StackSize;
    NTSTATUS Status = STATUS_SUCCESS;


    PAGED_CODE();

    DbgMsg2(("\'DCamFreeIsochResource: enter; DevExt=%x, Irb=%x\n", pDevExt, Irb));

    ASSERT(pDevExt);
    ASSERT(Irb);


    if(Irb == 0 ||
       pDevExt == 0) {
       DbgMsg2(("\'DCamFreeIsochResource: ABORTED!\n"));
       return STATUS_SUCCESS;
    }
    //
    // Get an Irp so we can send some free commands down
    //
    StackSize = pDevExt->BusDeviceObject->StackSize;
    Irp = IoAllocateIrp(StackSize, FALSE);

    if (!Irp) {   
        ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to allocate an Irp\n\n", Status));
        return STATUS_INSUFFICIENT_RESOURCES;
    }


    //
    // 1. Free Resource
    //
    if (pDevExt->hResource && bFreeResource) {

        DbgMsg2(("\'DCamFreeIsochResource: Attempt to free ->hResource\n"));

        Irb->FunctionNumber = REQUEST_ISOCH_FREE_RESOURCES;
        Irb->Flags = 0;
        Irb->u.IsochFreeResources.hResource = pDevExt->hResource;
        Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);

        pDevExt->hResource = NULL;
        if (Status) {

            ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to free Isoch resources\n\n", Status));
        }
    }

    //
    // 2. Free Channel
    //
    if (pDevExt->IsochChannel != ISOCH_ANY_CHANNEL) {

        DbgMsg2(("\'DCamFreeIsochResource: Attempt to free ->IsochChannel\n"));

        Irb->FunctionNumber = REQUEST_ISOCH_FREE_CHANNEL;
        Irb->Flags = 0;
        Irb->u.IsochFreeChannel.nChannel = pDevExt->IsochChannel;
        Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);

        pDevExt->IsochChannel = ISOCH_ANY_CHANNEL;

        if(Status) {
            
            ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to free Isoch channel\n\n", Status));
        }
    }

    //
    // 3. Free Bandwidth
    //
    if (pDevExt->hBandwidth) {

        DbgMsg2(("\'DCamFreeIsochResource: Attempt to free ->hBandwidth\n"));

        Irb->FunctionNumber = REQUEST_ISOCH_FREE_BANDWIDTH;
        Irb->Flags = 0;
        Irb->u.IsochFreeBandwidth.hBandwidth = pDevExt->hBandwidth;
        Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);

        pDevExt->hBandwidth = NULL;

        if (Status) {

            ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to free Isoch bandwidth\n", Status));
        }
    }

    DbgMsg2(("\'DCamFreeIsochResource: hResource = %x\n", pDevExt->hResource));


    IoFreeIrp(Irp);

    return STATUS_SUCCESS;

}



VOID 
InitializeStreamExtension(
    PDCAM_EXTENSION pDevExt,
    PHW_STREAM_OBJECT   pStreamObject,
    PSTREAMEX           pStrmEx
    )
{
    PAGED_CODE();

    pStrmEx->hMasterClock = 0;
    pStrmEx->FrameInfo.ExtendedHeaderSize = sizeof(KS_FRAME_INFO);
    pStrmEx->FrameInfo.PictureNumber = 0;
    pStrmEx->FrameInfo.DropCount     = 0;
    pStrmEx->FrameInfo.dwFrameFlags  = 0;     
    pStrmEx->FirstFrameTime    = 0;
    pStrmEx->pVideoInfoHeader  = 0;
    pStrmEx->KSState           = KSSTATE_STOP;
    pStrmEx->KSSavedState      = KSSTATE_STOP;


    KeInitializeMutex( &pStrmEx->hMutex, 0);  // Level 0 and in Signal state

}

BOOL
DCamDeviceInUse(
    PIRB pIrb,
    PDCAM_EXTENSION pDevExt
)
/*++

Routine Description:

    See if this device is in used.  
    We check ISO_ENABLE since this is the only register
    in a 1394DCam that we can set/get and 99%+ of time
    this bit is set by its owner.

Arguments:

    pIrb - Pointer to IEEE 1394 Request Block definition (IRB)
    pDevExt - this device extension

Return Value:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -