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

📄 usb2com.read.cpp

📁 这是一个关于USB转接串口的驱动程序开发
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//********************************************************************
//	created:	11:7:2008   21:29
//	file:		usb2com.read.cpp
//	author:		tiamo
//	purpose:	read
//********************************************************************

#include "stdafx.h"

//
// read dispatch routine
//
NTSTATUS Usb2ComRead(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp)
{
	PUSB2COM_DEVICE_EXTENSION DevExt					= static_cast<PUSB2COM_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
	PIO_STACK_LOCATION IrpSp							= IoGetCurrentIrpStackLocation(Irp);
	NTSTATUS Status										= STATUS_SUCCESS;

	//
	// check zero-length
	//
	if(!IrpSp->Parameters.Read.Length)
	{
		Irp->IoStatus.Status							= Status = STATUS_SUCCESS;
		Irp->IoStatus.Information						= 0;
		IoCompleteRequest(Irp,IO_NO_INCREMENT);

		return Status;
	}

	//
	// acquire remove lock
	//
	Status												= IoAcquireRemoveLock(&DevExt->RemoveLock,Irp);
	if(!NT_SUCCESS(Status))
	{
		//
		// we are removing
		//
		Irp->IoStatus.Status							= Status;
		Irp->IoStatus.Information						= 0;
		IoCompleteRequest(Irp,IO_NO_INCREMENT);

		return Status;
	}

	
	//
	// set information with zero
	//
	Irp->IoStatus.Information							= 0;

	//
	// protected by read lock
	//
	KIRQL SavedIrql;
	KeAcquireSpinLock(&DevExt->ReadLock,&SavedIrql);

	//
	// current read irp is pending,just queue this one
	//
	if(DevExt->CurrentReadIrp)
	{
		//
		// setup a cancel routine
		//
		PDRIVER_CANCEL OldCancel						= IoSetCancelRoutine(Irp,&Usb2ComQueuedReadIrpCancel);
		ASSERT(!OldCancel);

		//
		// IoCancelIrp called
		//
		if(Irp->Cancel)
		{
			OldCancel									= IoSetCancelRoutine(Irp,0);

			if(OldCancel)
			{
				//
				// our cancel routine has not been called
				//
				ASSERT(OldCancel == &Usb2ComQueuedReadIrpCancel);

				KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);

				Irp->IoStatus.Status					= STATUS_CANCELLED;

				IoCompleteRequest(Irp,IO_NO_INCREMENT);

				IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);

				Status									= STATUS_CANCELLED;
			}
			else
			{
				//
				// our cancel routine will be called as soon as we release read lock
				//
				IoMarkIrpPending(Irp);

				InitializeListHead(&Irp->Tail.Overlay.ListEntry);

				KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);

				Status									= STATUS_PENDING;
			}
		}
		else
		{
			//
			// mark it pending and queue it
			//
			IoMarkIrpPending(Irp);

			InsertTailList(&DevExt->ReadQueueListHead,&Irp->Tail.Overlay.ListEntry);

			KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);

			Status										= STATUS_PENDING;
		}
	}
	else
	{
		//
		// set as the current read irp,and start it
		//
		DevExt->CurrentReadIrp							= Irp;

		LIST_ENTRY CompleteIrpListHead;
		InitializeListHead(&CompleteIrpListHead);

		Status											= Usb2ComProcessPendingReadIrps(DevExt,&CompleteIrpListHead,TRUE);

		KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);

		while(!IsListEmpty(&CompleteIrpListHead))
		{
			PLIST_ENTRY ListEntry							= RemoveHeadList(&CompleteIrpListHead);
			PIRP Irp										= CONTAINING_RECORD(ListEntry,IRP,Tail.Overlay.ListEntry);

			IoCompleteRequest(Irp,IO_NO_INCREMENT);

			IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
		}
	}

	return Status;
}

//
// cancel all read irps
//
VOID Usb2ComCancelAllReadIrps(__in PUSB2COM_DEVICE_EXTENSION DevExt)
{
	KIRQL SavedIrql;
	KeAcquireSpinLock(&DevExt->ReadLock,&SavedIrql);
	
	LIST_ENTRY CompleteIrpListHead;
	InitializeListHead(&CompleteIrpListHead);

	PIRP Irp											= Usb2ComGetNextReadIrp(DevExt);
	while(Irp)
	{
		InsertTailList(&CompleteIrpListHead,&Irp->Tail.Overlay.ListEntry);

		Irp												= Usb2ComGetNextReadIrp(DevExt);
	}

	Irp													= DevExt->CurrentReadIrp;

	if(Irp)
	{
		PDRIVER_CANCEL OldCancel						= IoSetCancelRoutine(Irp,0);
		if(OldCancel)
			InsertTailList(&CompleteIrpListHead,&Irp->Tail.Overlay.ListEntry);

		DevExt->CurrentReadIrp							= 0;
	}

	KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);

	while(!IsListEmpty(&CompleteIrpListHead))
	{
		PLIST_ENTRY ListEntry							= RemoveHeadList(&CompleteIrpListHead);
		PIRP Irp										= CONTAINING_RECORD(ListEntry,IRP,Tail.Overlay.ListEntry);
		Irp->IoStatus.Status							= STATUS_CANCELLED;

		IoCompleteRequest(Irp,IO_NO_INCREMENT);

		IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
	}
}

//
// reset read info
//
VOID Usb2ComResetReadBufferInfo(__in PUSB2COM_DEVICE_EXTENSION DevExt)
{
	KIRQL SavedIrql;
	KeAcquireSpinLock(&DevExt->ReadLock,&SavedIrql);
	
	DevExt->FirstReadCharSlot							= 0;
	DevExt->ReadBufferCharsCount						= 0;

	KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);
}

//
// current read irp cancel routine
//
VOID Usb2ComCurrentReadIrpCancel(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp)
{
	PUSB2COM_DEVICE_EXTENSION DevExt					= static_cast<PUSB2COM_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);

	//
	// release global spin lock
	//
	IoReleaseCancelSpinLock(Irp->CancelIrql);

	//
	// acquire our read queue lock
	//
	KIRQL SavedIrql;
	KeAcquireSpinLock(&DevExt->ReadLock,&SavedIrql);

	Irp->IoStatus.Status							= STATUS_CANCELLED;

	LIST_ENTRY CompleteIrpListHead;
	InitializeListHead(&CompleteIrpListHead);

	InsertTailList(&CompleteIrpListHead,&Irp->Tail.Overlay.ListEntry);

	//
	// if it is the current read irp,complete it and start the next one
	//
	if(Irp == DevExt->CurrentWriteIrp)
	{
		DevExt->CurrentReadIrp							= Usb2ComGetNextReadIrp(DevExt);
		Usb2ComProcessPendingReadIrps(DevExt,&CompleteIrpListHead,TRUE);
	}

	KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);
	
	while(!IsListEmpty(&CompleteIrpListHead))
	{
		PLIST_ENTRY ListEntry							= RemoveHeadList(&CompleteIrpListHead);
		PIRP Irp										= CONTAINING_RECORD(ListEntry,IRP,Tail.Overlay.ListEntry);

		IoCompleteRequest(Irp,IO_NO_INCREMENT);

		IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
	}
}

//
// queued read irp cancel routine
//
VOID Usb2ComQueuedReadIrpCancel(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp)
{
	PUSB2COM_DEVICE_EXTENSION DevExt					= static_cast<PUSB2COM_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);

	//
	// release global spin lock
	//
	IoReleaseCancelSpinLock(Irp->CancelIrql);

	//
	// acquire our read queue lock
	//
	KIRQL SavedIrql;
	KeAcquireSpinLock(&DevExt->ReadLock,&SavedIrql);

	//
	// remove the irp from read queue
	//
	RemoveEntryList(&Irp->Tail.Overlay.ListEntry);

	KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);

	//
	// complete this irp with canceled
	//
	Irp->IoStatus.Status								= STATUS_CANCELLED;
	IoCompleteRequest(Irp,IO_NO_INCREMENT);

	//
	// release remove lock on this irp
	//
	IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
}

//
// get next read irp
//
PIRP Usb2ComGetNextReadIrp(__in PUSB2COM_DEVICE_EXTENSION DevExt)
{
	PIRP Irp											= 0;

	while(!Irp && !IsListEmpty(&DevExt->ReadQueueListHead))
	{
		PLIST_ENTRY ListEntry							= RemoveHeadList(&DevExt->ReadQueueListHead);
		Irp												= CONTAINING_RECORD(ListEntry,IRP,Tail.Overlay.ListEntry);

		//
		// handle irp cancel
		//
		PDRIVER_CANCEL OldCancelRoutine					= IoSetCancelRoutine(Irp,0);

		//
		// IoCancelIrp could just been called on this irp,
		//
		if(OldCancelRoutine)
		{
			//
			// our cancel routine has not been called,return it
			//
			ASSERT(OldCancelRoutine == &Usb2ComQueuedReadIrpCancel);
		}
		else
		{
			//
			// our cancel routine will be called on this irp,reinitialize list entry to make cancel routine happy

⌨️ 快捷键说明

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