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

📄 isostrm.c

📁 这是ARM9开发板上自带的USB驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
 	}

	IsoUsb_DecrementIoCount(deviceObject); // also deccrement global pending IRP count

    ISOUSB_KdPrint (DBGLVL_MAXIMUM,(" ENTER IsoUsb_IsoIrp_Complete(), streamObject->PendingIrps = dec %d\n", streamObject->PendingIrps));

	// Check the IRP and URB status in the transferObject
    // Here is where a driver for a real device would collect and/or process data in the buffers
    status = IsoUsb_ProcessTransfer(transferObject);

	ISOUSB_KdPrintCond( DBGLVL_MEDIUM,(!NT_SUCCESS(status)), ("IsoUsb_IsoIrp_Complete() BAD transfer status 0x%x\n", status));

	if( !NT_SUCCESS(status) ) {
	    IsoUsb_ResetParentPort( DeviceObject );
    }

	// See if a stop stream has been requested..
	if( streamObject->IsoStreamStarted ) {// this is set FALSE when we get a stop stream ioctl request

		// Last xfer was OK and no stop has been requested;
		// Resubmit the whole thing again and recycle it..
		ISOUSB_KdPrint (DBGLVL_MAXIMUM,("IsoUsb_IsoIrp_Complete() ABOUT TO RECYCLE IRP AND URB!\n"));
		IsoUsb_InitializeStreamUrb(DeviceObject, transferObject);

		nextStack = IoGetNextIrpStackLocation(Irp);
		ASSERT(nextStack != NULL);

		nextStack->Parameters.Others.Argument1 = transferObject->Urb;
		nextStack->Parameters.DeviceIoControl.IoControlCode =
			IOCTL_INTERNAL_USB_SUBMIT_URB;
		nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;


        IoSetCompletionRoutine(Irp,
                IsoUsb_IsoIrp_Complete,
                transferObject, //pass transfer object as Context
                TRUE,  // Invoke on Success
                TRUE,  // Invoke on Error
                TRUE); // Invoke on Cancel


		// increment this stream object's pending irp count
		streamObject->PendingIrps++;
		// increment this stream object's total times recycled count
		streamObject->TimesRecycled++;
		// also increment global pending IRP count
		IsoUsb_IncrementIoCount(deviceObject);

		//
		// Resubmit the request...
        // Note that if the driver has actually done a  fair amount of data processing
        // or copying from packet buffers, you may want to schedule a dpc
        // to resubmit instead of doing it here
		//
		status = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
							  Irp);
	}
	

    ISOUSB_KdPrint (DBGLVL_MAXIMUM,(" EXIT IsoUsb_IsoIrp_Complete(), streamObject->PendingIrps = dec %d\n", streamObject->PendingIrps));

    return STATUS_MORE_PROCESSING_REQUIRED;
}


VOID
IsoUsb_StreamTimeoutDPC(
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
    )
/*++

Routine Description:

  Check for data capture problems
  Stop stream if problems found

Arguments:

Return Value:

    The function value is the final status from the operation.

--*/
{
    PDEVICE_EXTENSION deviceExtension;
    PDEVICE_OBJECT deviceObject;
    PISOUSB_STREAM_OBJECT streamObject;
    BOOLEAN inQueue;
    LARGE_INTEGER dueTime;

    streamObject = DeferredContext;
    deviceObject = streamObject->DeviceObject;
    deviceExtension = deviceObject->DeviceExtension;

    //



    //
    // schedule next one
    //

    if (streamObject->IsoStreamStarted) {

        KeInitializeTimer(&streamObject->TimeoutTimer);
        KeInitializeDpc(&streamObject->TimeoutDpc,
                        IsoUsb_StreamTimeoutDPC,
                        streamObject);

        dueTime.QuadPart = -10000 * ISOUSB_STREAM_TIMEOUT_INTERVAL;

        inQueue = KeSetTimer(&streamObject->TimeoutTimer,
                             dueTime,
                             &streamObject->TimeoutDpc);

        ASSERT(inQueue == FALSE);  // assert timer not already in system queue

    }
}


NTSTATUS
IsoUsb_StartIsoStream(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

	Handler for IOCTL_ISOUSB_START_ISO_STREAM

Arguments:

    DeviceObject - pointer to the device extension for this instance of the
                     82930 device.

    Irp -

Return Value:

    NT status code

--*/
{
    ULONG i;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PIO_STACK_LOCATION irpStack;
    ULONG inputBufferLength;
    ULONG outputBufferLength;
    PULONG_PTR streamObjectHandle;
    PISOUSB_STREAM_OBJECT streamObject;
    LARGE_INTEGER dueTime;
    BOOLEAN inQueue;
	PUSBD_PIPE_INFORMATION PipeInfo;
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;

    irpStack = IoGetCurrentIrpStackLocation (Irp);

    streamObjectHandle = Irp->AssociatedIrp.SystemBuffer;
    inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    if ( outputBufferLength  < sizeof(*streamObjectHandle) ) {

        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

        return STATUS_INVALID_PARAMETER;
    }

    streamObject = ExAllocatePool(NonPagedPool, sizeof(ISOUSB_STREAM_OBJECT));

    if (streamObject) {


		RtlZeroMemory( streamObject, sizeof(ISOUSB_STREAM_OBJECT));

		// hard code to 5th pipe; this is the iso in pipe on our test board
		PipeInfo = &(deviceExtension->UsbInterface->Pipes[4]);

		ISOUSB_KdPrint (DBGLVL_MEDIUM,(" ENTER IsoUsb_StartIsoStream()  pipe %x\n", PipeInfo));

		deviceExtension->PipeInfo[4].fPipeOpened = TRUE; // set flag for this pipe opened
		deviceExtension->OpenPipeCount++;

		// try to power up device if its not already in D0
		IsoUsb_SelfSuspendOrActivate( DeviceObject, FALSE );

        streamObject->DeviceObject = DeviceObject;
        streamObject->PipeInfo = PipeInfo;
        streamObject->IsoStreamStarted = TRUE;

		// event to be set when PendingIrps == 0; signals stream can be stopped
		KeInitializeEvent(&streamObject->NoPendingIrpEvent, NotificationEvent, FALSE);

        // This initializes the pair of IRP/URBS that we will keep endlessly recycling
		// until the Iso stream is stoppped; at least one of these pairs will always be in
		// use and one will be available so continuous throughput is maintained.
		for (i=0; i< ISOUSB_MAX_IRP; i++) {

            ntStatus = IsoUsb_StartTransfer(DeviceObject,
                                            streamObject,
                                            i);

            if (!NT_SUCCESS(ntStatus)) {
				ISOUSB_Trap(DBGLVL_MAXIMUM);
                break;
            }

        }

		// We are returning the pointer to our stream object as an untyped handle to the user
        *streamObjectHandle = (ULONG_PTR) streamObject;

        //
        // start the timeout DPC
        //

        KeInitializeTimer(&streamObject->TimeoutTimer);
        KeInitializeDpc(&streamObject->TimeoutDpc,
                        IsoUsb_StreamTimeoutDPC,
                        streamObject);

        dueTime.QuadPart = -10000 * ISOUSB_STREAM_TIMEOUT_INTERVAL;

        inQueue = KeSetTimer(&streamObject->TimeoutTimer,
                             dueTime,
                             &streamObject->TimeoutDpc);


    } else {
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

	// We are returning the size of our stream object pointer to the user
    Irp->IoStatus.Information = sizeof(*streamObjectHandle);
    Irp->IoStatus.Status = ntStatus;

    ISOUSB_KdPrint (DBGLVL_MEDIUM,(" EXIT IsoUsb_StartIsoStream() %x\n", ntStatus));

    return ntStatus;
}


NTSTATUS
IsoUsb_StopIsoStream(
    IN PDEVICE_OBJECT DeviceObject,
    IN PISOUSB_STREAM_OBJECT StreamObject,
    IN PIRP Irp
    )
/*++

Routine Description:

	Handler for IOCTL_ISOUSB_STOP_ISO_STREAM

Arguments:

    DeviceObject - pointer to the device extension for this instance of the
                     82930 device.

    StreamObject - pointer to the ISOUSB_STREAM_OBJECT; We returned this pointer to the user
	  in the return data buffer from their IOCTL_ISOUSB_START_ISO_STREAM call

    Irp - The current IRP for this request

Return Value:

    NT status code

--*/
{
	PUSBD_PIPE_INFORMATION pipe;
	int i;
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    ULONG packetSize, numPackets, maxXferSize;


	// validate the input parm; its DeviceObject member should match our DeviceObject
	ISOUSB_KdPrintCond (DBGLVL_MEDIUM,
						(!StreamObject || (StreamObject->DeviceObject != DeviceObject)),
						("ENTER IsoUsb_StopIsoStream() StreamObject parm INVALID!!!!!\n"));	

	// See if we were called with a bogus or NULL StreamObject parm;
	// This could happen if user calls without ever having successfully started a stream
    if (!StreamObject || (StreamObject->DeviceObject != DeviceObject))
		return STATUS_INVALID_PARAMETER;

	maxXferSize = StreamObject->PipeInfo->MaximumTransferSize;  // We set this
    packetSize = StreamObject->PipeInfo->MaximumPacketSize;	    // USBD sets this
    numPackets = maxXferSize / packetSize;

	// Tell IsoUsb_StreamTimeoutDPC() not to reschedule itself on next timeout
	// This also flags IsoUsb_IsoIrp_Complete() to stop recycling the pair of stream IRP/Urbs
	StreamObject->IsoStreamStarted = FALSE;

    // Wait for any io request pending for this stream object to
    // complete before returning success.
	// This  event is set when streamObject->PendingIrpCount goes to 0
    KeWaitForSingleObject(
                &StreamObject->NoPendingIrpEvent,
                Suspended,
                KernelMode,
                FALSE,
                NULL);


    ISOUSB_KdPrint (DBGLVL_DEFAULT, ("IsoUsb_StopIsoStream() StreamObject->TimesRecycled = decimal %d,  0x%x\n",
		StreamObject->TimesRecycled , StreamObject->TimesRecycled));
    ISOUSB_KdPrint (DBGLVL_DEFAULT, ("IsoUsb_StopIsoStream() Total packets processed = decimal %d\n",
		StreamObject->TotalPacketsProcessed ));
    ISOUSB_KdPrint (DBGLVL_DEFAULT, ("IsoUsb_StopIsoStream() Total stream bytes processed  = decimal %d\n",
		StreamObject->TotalBytesProcessed ));
    ISOUSB_KdPrint (DBGLVL_DEFAULT, ("EXIT IsoUsb_StopIsoStream() Error Packet Count  = decimal %d\n",
		StreamObject->ErrorPacketCount ));


    // Free all the buffers, URBS, and Irps associated with our stream object
	for (i=0; i< ISOUSB_MAX_IRP; i++) {
		PISOUSB_TRANSFER_OBJECT transferObject;

		transferObject = StreamObject->TransferObjectList[i];

		ISOUSB_ASSERT( transferObject );

		ISOUSB_ASSERT( transferObject->Irp );
		IoFreeIrp( transferObject->Irp );

		ISOUSB_ASSERT( transferObject->Urb );
		ExFreePool( transferObject->Urb );

		ISOUSB_ASSERT( transferObject->DataBuffer );
		ExFreePool( transferObject->DataBuffer );

		ExFreePool( transferObject );
    }

	ExFreePool( StreamObject ); // also free the stream object itself


	// Close our Iso input pipe;
	// Hard-code to 5th pipe; this is the iso input pipe on our test board
	pipe = &(deviceExtension->UsbInterface->Pipes[4]);

	deviceExtension->PipeInfo[4].fPipeOpened = FALSE; // set flag for this pipe closed
	deviceExtension->OpenPipeCount--;

	// ISSUE? Not sure why this is neccesary, but it is...
	IsoUsb_ResetParentPort( DeviceObject );

	// try to power down device if we just closed the last open pipe
	IsoUsb_SelfSuspendOrActivate( DeviceObject, TRUE );

	return STATUS_SUCCESS;

}







⌨️ 快捷键说明

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