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

📄 datapkt.c

📁 a sample WDM stream class video capture driver that supports two IEEE 1394 digital cameras. The sam
💻 C
📖 第 1 页 / 共 3 页
字号:
            }
            IsochDescriptorReserved->Flags |= STATE_DETACHING_BUFFERS;
            KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);

            IsochDescriptor = (PISOCH_DESCRIPTOR) (((PUCHAR) IsochDescriptorReserved) - FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));

            pIrp = (PIRP) IsochDescriptor->DeviceReserved[5];
            ASSERT(pIrp);
            pIrb = (PIRB) IsochDescriptor->DeviceReserved[6];
            ASSERT(pIrb);


            DbgMsg1(("DCamReSubmitPacket: detaching IsochDescriptor %x IsochDescriptorReserved %x, pSrb %x\n",
                        IsochDescriptor, IsochDescriptorReserved, IsochDescriptorReserved->Srb));

#if DBG
            // Should not have been detached
            ASSERT((IsochDescriptor->DeviceReserved[7] == 0x87654321));
            IsochDescriptor->DeviceReserved[7]++;
#endif
            pIrb->FunctionNumber           = REQUEST_ISOCH_DETACH_BUFFERS;
            pIrb->Flags                    = 0;
            pIrb->u.IsochDetachBuffers.hResource = hStaleResource;
            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,
                DCamReSubmitPacketCR,
                IsochDescriptor,
                TRUE,
                TRUE,
                TRUE
                );

            Status =
                IoCallDriver(
                    pDevExt->BusDeviceObject,
                    pIrp
                    );

            ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING);

        } else {
            ERROR_LOG(("PendingCount %d, but list is empty!!\n", cntPendingRead));
            ASSERT(cntPendingRead == 0);
        }

    }  // for()

    return Status;
}



VOID
DCamReadStreamWorker(
    IN PHW_STREAM_REQUEST_BLOCK pSrb,
    IN PISOCH_DESCRIPTOR IsochDescriptor
    )

/*++

Routine Description:

    Does most of the work for handling reads via Attach buffers

Arguments:

    Srb - Pointer to Stream request block

    IsochDescriptor - Pointer to IsochDescriptor to be used

Return Value:

    Nothing

--*/

{

    PIRB pIrb;
    PIRP pIrp;
    PIO_STACK_LOCATION NextIrpStack;
    PDCAM_EXTENSION pDevExt;
    PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
    NTSTATUS Status;


    pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
    pIrp = (PIRP) IsochDescriptor->DeviceReserved[5];
    ASSERT(pIrp);
    pIrb = (PIRB) IsochDescriptor->DeviceReserved[6];
    ASSERT(pIrb);
#if DBG
    // track number time the same IsochDescriptor are attaching; should only be one.
    IsochDescriptor->DeviceReserved[4]++;
#endif

    //
    // It is pending and will be completed in isoch callback or cancelled.
    //

    pSrb->Status = STATUS_PENDING;

    IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];

    DbgMsg3(("\'DCamReadStreamWorker: enter with pSrb = %x, pDevExt=0x%x\n", pSrb, pDevExt));

    //
    // Attach descriptor onto our pending descriptor list
    //

    ExInterlockedInsertTailList(
       &pDevExt->IsochDescriptorList,
       &IsochDescriptorReserved->DescriptorList,
       &pDevExt->IsochDescriptorLock
       );

    pIrb->FunctionNumber           = REQUEST_ISOCH_ATTACH_BUFFERS;
    pIrb->Flags                    = 0;
    pIrb->u.IsochAttachBuffers.hResource = pDevExt->hResource;
    pIrb->u.IsochAttachBuffers.nNumberOfDescriptors = 1;
    pIrb->u.IsochAttachBuffers.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,
        DCamAttachBufferCR,
        IsochDescriptor,
        TRUE,
        TRUE,
        TRUE
        );

    Status =
        IoCallDriver(
            pDevExt->BusDeviceObject,
            pIrp
            );

    ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING);

    return;  // Complete Asynchronously in IoCompletionRoutine*
}




VOID
DCamReadStream(
    IN PHW_STREAM_REQUEST_BLOCK Srb
    )

/*++

Routine Description:

    Called when an Read Data Srb request is received

Arguments:

    Srb - Pointer to Stream request block

Return Value:

    Nothing

--*/

{

    PIRB pIrb;
    PIRP pIrp;
    KIRQL oldIrql;
    PDCAM_EXTENSION pDevExt;
    PSTREAMEX     pStrmEx;
    PISOCH_DESCRIPTOR IsochDescriptor;
    PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
    NTSTATUS StatusWait;


    pIrb = (PIRB) Srb->SRBExtension;
    pDevExt = (PDCAM_EXTENSION) Srb->HwDeviceExtension;
    ASSERT(pDevExt != NULL);



    pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
    ASSERT(pStrmEx);

    if(pDevExt->bDevRemoved ||
       pStrmEx == NULL) {

        Srb->Status = pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_UNSUCCESSFUL;
        Srb->ActualBytesTransferred = 0;
        Srb->CommandData.DataBufferArray->DataUsed = 0;
        ERROR_LOG(("DCamReadStream: Failed with Status %x or pStrmEx %x\n", Srb->Status, pStrmEx));

        StreamClassStreamNotification(StreamRequestComplete, Srb->StreamObject, Srb);
        return;
    }

    //
    // Mutext for either StreamIo (SRB_READ) ControlIo (SRB_SET_STREAM_STATE)
    //
    // Non-alertable; wait infinite

    StatusWait = KeWaitForSingleObject( &pStrmEx->hMutex, Executive, KernelMode, FALSE, 0 );
    ASSERT(StatusWait == STATUS_SUCCESS);

    DbgMsg3(("\'%d:%s) DCamReadStream: enter with Srb %x, DevExt %x\n",
            pDevExt->idxDev, pDevExt->pchVendorName, Srb, pDevExt));


    // Rule:
    // Only accept read requests when in either the Pause or Run
    // States.  If Stopped, immediately return the SRB.

    if (pStrmEx->KSState == KSSTATE_STOP ||
        pStrmEx->KSState == KSSTATE_ACQUIRE) {

        DbgMsg2(("\'%d:%s)DCamReadStream: Current KSState(%d) < (%d)=KSSTATE_PAUSE; Srb=0x%x; DevExt=0x%x",
                 pDevExt->idxDev, pDevExt->pchVendorName, pStrmEx->KSState,  KSSTATE_PAUSE, Srb, pDevExt));

        DbgMsg2(("\'DCamReadStream: PendingRead=%d, IsochDescriptorList(%s)\n",
              pDevExt->PendingReadCount, IsListEmpty(&pDevExt->IsochDescriptorList)?"Empty":"!Empty"));

        Srb->Status = STATUS_UNSUCCESSFUL;
        Srb->CommandData.DataBufferArray->DataUsed = 0;
        StreamClassStreamNotification(StreamRequestComplete, Srb->StreamObject, Srb);

        KeReleaseMutex(&pStrmEx->hMutex, FALSE);

        return;
    }


    // Buffer need to be big enough
    if (IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize > Srb->CommandData.DataBufferArray->FrameExtent) {

        ASSERT(IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize <= Srb->CommandData.DataBufferArray->FrameExtent);
        Srb->Status = STATUS_INVALID_PARAMETER;
        StreamClassStreamNotification(StreamRequestComplete, Srb->StreamObject, Srb);

        KeReleaseMutex(&pStrmEx->hMutex, FALSE);

        return;
    }


    //
    // Use our own IRP
    //
    pIrp = IoAllocateIrp(pDevExt->BusDeviceObject->StackSize, FALSE);
    if(!pIrp) {
        ASSERT(pIrp);
        Srb->Status = STATUS_INSUFFICIENT_RESOURCES;
        return;
    }

    //
    // This structure (IsochDescriptor) has (ULONG) DeviceReserved[8];
    // Its first 4 ULONGs are used by IsochDescriptorReserved,
    // The 6th (index[5]), is used to keep pIrp
    //     7th (index[6]), is used to keep pIrb
    //

    IsochDescriptor = ExAllocatePoolWithTag(NonPagedPool, sizeof(ISOCH_DESCRIPTOR), 'macd');
    if (!IsochDescriptor) {

        ASSERT(FALSE);
        Srb->Status = STATUS_INSUFFICIENT_RESOURCES;
        StreamClassStreamNotification(StreamRequestComplete, Srb->StreamObject, Srb);

        KeReleaseMutex(&pStrmEx->hMutex, FALSE);

        return;
    }


    DbgMsg3(("\'DCamReadStream: IsochDescriptor = %x\n", IsochDescriptor));
    IsochDescriptor->fulFlags = SYNCH_ON_SY;

    DbgMsg3(("\'DCamReadStream: Incoming Mdl = %x\n", Srb->Irp->MdlAddress));
    IsochDescriptor->Mdl = Srb->Irp->MdlAddress;

    // Use size match what we originally requested in AllocateIsoch
    IsochDescriptor->ulLength = IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize;
    IsochDescriptor->nMaxBytesPerFrame = IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2;

    IsochDescriptor->ulSynch = START_OF_PICTURE;
    IsochDescriptor->ulTag = 0;
    IsochDescriptor->Callback = DCamIsochCallback;
    IsochDescriptor->Context1 = pDevExt;
    IsochDescriptor->Context2 = IsochDescriptor;

    //
    // IsochDescriptorReserved is pointed to the DeviceReserved[0];
    // The entire, except the links, are kept in the DeviceReserved[]
    //

    IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
    IsochDescriptorReserved->Srb = Srb;
    IsochDescriptorReserved->Flags = 0;

    IsochDescriptor->DeviceReserved[5] = (ULONG_PTR) pIrp;
    IsochDescriptor->DeviceReserved[6] = (ULONG_PTR) pIrb;

#if DBG
    //
    // Put signatures and use these count to track if the IsochDescriptor
    // has been attached or detached unexpectely.
    //
    // When attach, [4]++  (DCamReadStreamWorker(), DCamReSumbitPacketCR())
    //      detach, [7]++  (DCamIsochcallback(), DCamCancelPacketCR(), DCamResubmitPacket())
    //

    IsochDescriptor->DeviceReserved[4] = 0x12345678;
    IsochDescriptor->DeviceReserved[7] = 0x87654321;
#endif

    //
    // Checking here to see if we have enuff resources to put this read
    // down right away.  Since we only allocated N amount of resources
    // from the 1394 stack beneath us, we'll have to stay within that
    // limit and do some of the throttling ourself.
    //

    KeAcquireSpinLock(&pDevExt->IsochWaitingLock, &oldIrql);
    if (InterlockedIncrement(&pDevExt->PendingReadCount) > MAX_BUFFERS_SUPPLIED) {

        //
        // don't have enuff resources to do an attach buffers right now.
        // we'll queue this request and pull it off later when another
        // read completes.
        //

        DbgMsg2(("\'DCamReadStream: Queueing request - Read Count = %x\n", pDevExt->PendingReadCount));
        InsertTailList(
           &pDevExt->IsochWaitingList,
           &IsochDescriptorReserved->DescriptorList
           );

        KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);

        KeReleaseMutex(&pStrmEx->hMutex, FALSE);

        return;

    }

    if(pStrmEx->KSState == KSSTATE_PAUSE) {
        DbgMsg2(("\'DCamReadStream: Doing Pre-read in _PAUSE state; Srb %x, pDevExt %x, PendingCount %d\n",
                 Srb, pDevExt, pDevExt->PendingReadCount));
    }

    //
    // Do actual read work here via our Read worker function
    //

    KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
    DCamReadStreamWorker(Srb, IsochDescriptor);

    KeReleaseMutex(&pStrmEx->hMutex, FALSE);

}

VOID
DCamReceiveDataPacket(
    IN PHW_STREAM_REQUEST_BLOCK Srb
    )

/*++

Routine Description:

    Called with video data packet commands

Arguments:

    Srb - Pointer to Stream request block

Return Value:

    Nothing

--*/

{
    PAGED_CODE();

    //
    // determine the type of packet.
    //

    switch (Srb->Command) {

    case SRB_READ_DATA:

         DbgMsg3(("\'DCamReceiveDataPacket: SRB_READ_DATA\n"));
         DCamReadStream(Srb);

         // This request will be completed asynchronously...

         break;

    case SRB_WRITE_DATA:

         DbgMsg3(("\'DCamReceiveDataPacket: SRB_WRITE_DATA, not used for digital camera.\n"));
         ASSERT(FALSE);

    default:

         //
         // invalid / unsupported command. Fail it as such
         //

         Srb->Status = STATUS_NOT_IMPLEMENTED;

         StreamClassStreamNotification(StreamRequestComplete, Srb->StreamObject, Srb);

    }

}


⌨️ 快捷键说明

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